summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore17
-rw-r--r--Makefile.am31
-rwxr-xr-xautogen.sh16
-rw-r--r--configure.ac62
-rw-r--r--free.191
-rw-r--r--free.c77
-rw-r--r--include/Makefile.am4
-rw-r--r--include/c.h159
-rw-r--r--include/nls.h114
-rw-r--r--include/strutils.h11
-rw-r--r--include/xalloc.h60
-rw-r--r--kill.1137
-rw-r--r--lib/.gitignore1
-rw-r--r--lib/Makefile.am7
-rw-r--r--lib/strutils.c62
-rw-r--r--pgrep.1271
-rw-r--r--pgrep.c202
-rw-r--r--pmap.168
-rw-r--r--pmap.c854
-rw-r--r--po/.gitignore18
-rw-r--r--po/Makevars41
-rwxr-xr-xpo/update-potfiles11
-rw-r--r--proc/alloc.c1
-rw-r--r--proc/devname.c2
-rw-r--r--proc/devname.h1
-rw-r--r--proc/escape.c4
-rw-r--r--proc/escape.h2
-rw-r--r--proc/ksym.c10
-rw-r--r--proc/libprocps.sym1
-rw-r--r--proc/procps.h6
-rw-r--r--proc/readproc.h1
-rw-r--r--proc/sig.c43
-rw-r--r--proc/sig.h2
-rw-r--r--proc/slab.c6
-rw-r--r--ps/Makefile.am6
-rw-r--r--ps/TRANSLATION39
-rw-r--r--ps/common.h14
-rw-r--r--ps/display.c27
-rw-r--r--ps/global.c26
-rw-r--r--ps/help.c124
-rw-r--r--ps/it35
-rw-r--r--ps/output.c13
-rw-r--r--ps/parser.c358
-rw-r--r--ps/ps.11915
-rw-r--r--ps/select.c4
-rw-r--r--ps/sortformat.c80
-rw-r--r--ps/stacktrace.c22
-rw-r--r--pwdx.145
-rw-r--r--pwdx.c193
-rw-r--r--skill.1185
-rw-r--r--skill.c1102
-rw-r--r--slabtop.145
-rw-r--r--slabtop.c222
-rw-r--r--sysctl.8126
-rw-r--r--sysctl.c413
-rw-r--r--tload.157
-rw-r--r--tload.c274
-rw-r--r--top/Makefile.am26
-rw-r--r--top/README.top (renamed from README.top)49
-rw-r--r--top/top.1 (renamed from top.1)7
-rw-r--r--top/top.c (renamed from top.c)391
-rw-r--r--top/top.h (renamed from top.h)133
-rw-r--r--top/top_nls.c497
-rw-r--r--top/top_nls.h82
-rw-r--r--uptime.159
-rw-r--r--uptime.c57
-rw-r--r--vmstat.8201
-rw-r--r--vmstat.c1368
-rw-r--r--w.1107
-rw-r--r--w.c665
-rw-r--r--watch.1160
-rw-r--r--watch.c704
72 files changed, 7286 insertions, 4938 deletions
diff --git a/.gitignore b/.gitignore
index 4338705..09d2345 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,9 @@
+*.lo
+*.o
+*.so
+.deps
+.libs
+ABOUT-NLS
aclocal.m4
autom4te.cache
compile
@@ -5,24 +11,22 @@ config.guess
config.h
config.h.in
config.log
+config.rpath
config.status
config.sub
configure
depcomp
-.deps
-.libs
free
INSTALL
install-sh
kill
libtool
-*.lo
ltmain.sh
m4/
Makefile
Makefile.in
missing
-*.o
+mkinstalldirs
pgrep
pkill
pmap
@@ -39,11 +43,12 @@ pwdx
skill
slabtop
snice
-*.so
stamp-h1
sysctl
tload
-top
+top/Makefile
+top/Makefile.in
+top/top
uptime
vmstat
w
diff --git a/Makefile.am b/Makefile.am
index e246d02..8fb59cf 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,7 +1,14 @@
-AM_CPPFLAGS = -include $(top_builddir)/config.h
+AM_CPPFLAGS = -include $(top_builddir)/config.h -I$(top_srcdir)/include
ACLOCAL_AMFLAGS = -I m4
-SUBDIRS = proc ps testsuite
+SUBDIRS = \
+ include \
+ lib \
+ po \
+ proc \
+ ps \
+ testsuite \
+ top
AM_CFLAGS = -Iproc
AM_LDFLAGS = ./proc/libprocps.la
@@ -45,33 +52,33 @@ endif
if WITH_NCURSES
usrbin_exec_PROGRAMS += \
slabtop \
- top \
watch
-top_SOURCES = top.c top.h
dist_man_MANS += \
slabtop.1 \
- top.1 \
watch.1
+slabtop_SOURCES = slabtop.c $(top_srcdir)/lib/strutils.c
slabtop_LDADD = @NCURSES_LIBS@
-top_LDADD = @NCURSES_LIBS@
-watch_LDADD = @WATCH_NCURSES_LIBS@
+watch_SOURCES = watch.c $(top_srcdir)/lib/strutils.c
+watch_LDADD = @NCURSES_LIBS@
endif
-kill_SOURCES = skill.c
-snice_SOURCES = skill.c
+kill_SOURCES = skill.c $(top_srcdir)/lib/strutils.c
+skill_SOURCES = skill.c $(top_srcdir)/lib/strutils.c
+snice_SOURCES = skill.c $(top_srcdir)/lib/strutils.c
+tload_SOURCES = tload.c $(top_srcdir)/lib/strutils.c
pkill_SOURCES = pgrep.c
+vmstat_SOURCES = vmstat.c $(top_srcdir)/lib/strutils.c
sysconf_DATA = sysctl.conf
EXTRA_DIST = \
autogen.sh \
CodingStyle \
- contrib/ \
+ contrib \
COPYING.LIB \
$(sysconf_DATA)
procpsngdir = $(docdir)
dist_procpsng_DATA = \
BUGS \
- FAQ \
- README.top
+ FAQ
diff --git a/autogen.sh b/autogen.sh
index b42f57b..d707245 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -10,11 +10,17 @@ THEDIR=$(pwd)
cd ${SRCDIR}
DIE=0
-test -f top.c || {
+test -f free.c || {
echo "You must run this script in the top-level procps-ng directory"
DIE=1
}
+(autopoint --version) < /dev/null > /dev/null 2>&1 || {
+ echo "You must have autopoint installed to generate util-linux build system."
+ echo "The autopoint command is part of the GNU gettext package."
+ DIE=1
+}
+
(autoconf --version) < /dev/null > /dev/null || {
echo "You must have autoconf installed to generate procps-ng build system."
DIE=1
@@ -45,6 +51,7 @@ if test ${DIE} -ne 0; then
fi
echo "Generate build-system by:"
+echo " autopoint: $(autopoint --version | head -1)"
echo " aclocal: $(aclocal --version | head -1)"
echo " autoconf: $(autoconf --version | head -1)"
echo " autoheader: $(autoheader --version | head -1)"
@@ -54,6 +61,13 @@ echo " libtoolize: $(libtoolize --version | head -1)"
rm -rf autom4te.cache
set -e
+po/update-potfiles
+autopoint --force $AP_OPTS
+if ! grep -q datarootdir po/Makefile.in.in; then
+ echo autopoint does not honor dataroot variable, patching.
+ sed -i -e 's/^datadir *=\(.*\)/datarootdir = @datarootdir@\
+datadir = @datadir@/g' po/Makefile.in.in
+fi
libtoolize --force ${LT_OPTS}
aclocal -I m4 ${AL_OPTS}
autoconf ${AC_OPTS}
diff --git a/configure.ac b/configure.ac
index 85afd0e..7c99fb3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@ AC_INIT([procps-ng],
[3.3.2],
[procps@freelists.org],,[http://gitorious.org/procps])
AM_INIT_AUTOMAKE
-AC_CONFIG_SRCDIR([top.c])
+AC_CONFIG_SRCDIR([free.c])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
@@ -31,9 +31,11 @@ AC_HEADER_MAJOR
AC_CHECK_HEADERS([\
fcntl.h \
langinfo.h \
+ libintl.h \
limits.h \
locale.h \
netinet/in.h \
+ stdint.h \
stdlib.h \
string.h \
sys/file.h \
@@ -71,6 +73,7 @@ AC_FUNC_REALLOC
AC_FUNC_STRTOD
AC_CHECK_FUNCS([\
alarm \
+ getline \
getpagesize \
gettimeofday \
iswprint \
@@ -81,10 +84,10 @@ AC_CHECK_FUNCS([\
nl_langinfo \
putenv \
regcomp \
+ rpmatch \
select \
setlocale \
strcasecmp \
- strverscmp \
strchr \
strcspn \
strdup \
@@ -96,11 +99,32 @@ AC_CHECK_FUNCS([\
strstr \
strtol \
strtoul \
+ strverscmp \
uname \
utmpname \
wcwidth
])
+usrbin_execdir='${exec_prefix}/usr/bin'
+AC_SUBST([usrbin_execdir])
+
+AM_GNU_GETTEXT_VERSION([0.14.1])
+AM_GNU_GETTEXT([external])
+dnl if test -d "$srcdir/po"
+dnl then
+dnl ALL_LINGUAS=`cd $srcdir/po > /dev/null && echo *.po | sed 's/\.po//g'`
+dnl else
+dnl ALL_LINGUAS="af am ar as be bg bn_IN bn ca cs cy da de el en_GB es et eu_ES fa fi fr gl gu he hi hr hu hy id is it ja ka kn ko ku lo lt lv mk ml mr ms my nb nl nn no nso or pa pl pt_BR pt ro ru si sk sl sq sr@Latn sr sv ta te th tr uk ur vi zh_CN zh_TW zu"
+dnl fi
+
+AC_MSG_CHECKING(whether program_invocation_short_name is defined)
+AC_TRY_COMPILE([#include <argp.h>],
+ [program_invocation_short_name = "test";],
+ AC_DEFINE(HAVE_PROGRAM_INVOCATION_SHORT_NAME, 1,
+ [Define if program_invocation_short_name is defined])
+ AC_MSG_RESULT(yes),
+ AC_MSG_RESULT(no))
+
AC_ARG_WITH([ncurses],
AS_HELP_STRING([--without-ncurses], [build only applications not needing ncurses]),
[with_ncurses=no], [with_ncurses=yes]
@@ -109,15 +133,15 @@ AC_ARG_WITH([ncurses],
if test "x$with_ncurses" = xno; then
AM_CONDITIONAL(WITH_NCURSES, false)
else
- AC_CHECK_LIB(ncurses, initscr, [have_ncurses=yes], [have_ncurses=no])
- AC_CHECK_HEADERS(curses.h ncurses.h, [], [have_ncurses=no], AC_INCLUDES_DEFAULT)
+ AC_CHECK_LIB(ncursesw, initscr, [have_ncurses=yes], [have_ncurses=no])
+ AC_CHECK_HEADERS(curses.h ncurses.h term.h, [], [have_ncurses=no], AC_INCLUDES_DEFAULT)
if test "x$have_ncurses" = xno; then
AC_MSG_ERROR([ncurses support missing/incomplete (for partial build use --without-ncurses)])
fi
AM_CONDITIONAL(WITH_NCURSES, true)
if test "$enable_watch8bit" = yes; then
AC_CHECK_LIB([ncursesw], [addwstr], [WATCH_NCURSES_LIBS=-lncursesw],
- [AC_MSG_ERROR([Cannot find ncurses wide library ncursesw with --enable-watch8bit])])
+ [AC_MSG_ERROR([Cannot find ncurses wide library ncursesw with --enable-watch8bit])])
else
WATCH_NCURSES_LIBS="-lncurses"
fi
@@ -126,9 +150,6 @@ fi
AC_SUBST([NCURSES_LIBS])
AC_SUBST([WATCH_NCURSES_LIBS])
-usrbin_execdir='${exec_prefix}/usr/bin'
-AC_SUBST([usrbin_execdir])
-
AC_ARG_ENABLE([kill],
AS_HELP_STRING([--disable-kill], [do not build kill]),
[], enable_kill=yes
@@ -160,17 +181,22 @@ if test "x$enable_whining" = xyes; then
AC_DEFINE(BUILD_WITH_WHINE, 1, [should extra warnings be printed (slackware-ism)])
fi
-if test x"$DEJAGNU" = x
-then
- DEJAGNU="\$(top_srcdir)/testsuite/global-conf.exp"
-fi
-AC_SUBST(DEJAGNU)
+if test x"$DEJAGNU" = x
+then
+ DEJAGNU="\$(top_srcdir)/testsuite/global-conf.exp"
+fi
+AC_SUBST(DEJAGNU)
AC_CONFIG_FILES([
-Makefile
-proc/Makefile
-proc/libprocps.pc
-ps/Makefile
-testsuite/Makefile
+ Makefile
+ include/Makefile
+ lib/Makefile
+ po/Makefile.in
+ proc/Makefile
+ proc/libprocps.pc
+ ps/Makefile
+ testsuite/Makefile
+ top/Makefile
])
+
AC_OUTPUT
diff --git a/free.1 b/free.1
index 5884751..1722f69 100644
--- a/free.1
+++ b/free.1
@@ -2,38 +2,38 @@
.\" This page Copyright (C) 1993 Matt Welsh, mdw@sunsite.unc.edu.
.\" Long options where added at April 15th, 2011.
.\" Freely distributable under the terms of the GPL
-.TH FREE 1 "15 Apr 2011 " "Cohesive Systems" "Linux User's Manual"
+.TH FREE 1 "September 2011" "procps-ng" "User Commands"
.SH NAME
free \- Display amount of free and used memory in the system
.SH SYNOPSIS
.B free
-.RB [ options ]
+.RI [ options ]
.SH DESCRIPTION
-\fBfree\fP displays the total amount of free and used physical and swap
-memory in the system, as well as the buffers used by the kernel.
-The shared memory column should be ignored; it is obsolete.
-.SS OPTIONS
+.B free
+displays the total amount of free and used physical and swap memory in the
+system, as well as the buffers used by the kernel. The shared memory column
+should be ignored; it is obsolete.
+.SH OPTIONS
.TP
-\fB\-b, \-\-bytes\fR
+\fB\-b\fR, \fB\-\-bytes\fR
Display the amount of memory in bytes.
.TP
-\fB\-k, \-\-kilo\fR
-Display the amount of memory in kilobytes. This is the default.
+\fB\-k\fR, \fB\-\-kilo\fR
+Display the amount of memory in kilobytes. This is the default.
.TP
-\fB\-m, \-\-mega\fR
+\fB\-m\fR, \fB\-\-mega\fR
Display the amount of memory in megabytes.
.TP
-\fB\-g, \-\-giga\fR
+\fB\-g\fR, \fB\-\-giga\fR
Display the amount of memory in gigabytes.
.TP
-\fB\-\-tera
+\fB\-\-tera\fR
Display the amount of memory in terabytes.
.TP
-\fB\-h, \-\-human\fP
-Show all output fields automatically scaled to shortest three
-digit unit and display the units of print out. Following units
-are used.
-
+\fB\-h\fR, \fB\-\-human\fP
+Show all output fields automatically scaled to shortest three digit unit and
+display the units of print out. Following units are used.
+.sp
.nf
B = bytes
K = kilos
@@ -41,46 +41,57 @@ are used.
G = gigas
T = teras
.fi
-
-If unit is missing, and you have petabyte of RAM or swap, the
-number is in terabytes and columns might not be aligned with
-header.
+.sp
+If unit is missing, and you have petabyte of RAM or swap, the number is in
+terabytes and columns might not be aligned with header.
.TP
-\fB\-c, \-\-count\fR \fICOUNT\fR
-Display the result \fIcount\fR times. Requires the \fB\-s\fR option.
+\fB\-c\fR, \fB\-\-count\fR \fIcount\fR
+Display the result
+.I count
+times. Requires the
+.B \-s
+option.
.TP
-\fB\-l, \-\-lohi\fR
+\fB\-l\fR, \fB\-\-lohi\fR
Show detailed low and high memory statistics.
.TP
-\fB\-o, \-\-old\fR
+\fB\-o\fR, \fB\-\-old\fR
Display the output in old format, the only difference being this option
will disable the display of the "buffer adjusted" line.
.TP
-\fB\-s, \-\-seconds\fR \fISECONDS\fR
-Continuously display the result \fIdelay\fP seconds apart. You
-may actually specify any floating point number for \fIdelay\fP,
+\fB\-s\fR, \fB\-\-seconds\fR \fIseconds\fR
+Continuously display the result delay
+.I seconds
+apart. You may actually specify any floating point number for
+.IR delay ,
.BR usleep (3)
is used for microsecond resolution delay times.
.TP
-\fB\-\-si\fP
+\fB\-\-si\fR
Use power of 1000 not 1024.
.TP
-\fB\-t, \-\-total\fR
+\fB\-t\fR, \fB\-\-total\fR
Display a line showing the column totals.
.TP
-\fB\-\-help\fP
+\fB\-\-help\fR
Print help.
.TP
-\fB\-V, \-\-version\fR
+\fB\-V\fR, \fB\-\-version\fR
Display version information.
+.PD
.SH FILES
-.nf
-/proc/meminfo memory information
-.fi
+.TP
+/proc/meminfo
+memory information
+.PD
+.SH "SEE ALSO"
+.BR ps (1),
+.BR slabtop (1),
+.BR top "(1),
+.BR vmstat (8).
.SH AUTHORS
Written by Brian Edmonds.
-
-Send bug reports to <procps@freelists.org>
-.SH "SEE ALSO"
-.BR ps "(1), " slabtop "(1), " top "(1), " vmstat (8).
-.\"{{{}}}
+.SH "REPORTING BUGS"
+Please send bug reports to
+.UR procps\@freelists.org
+.UE
diff --git a/free.c b/free.c
index d281c95..0667b41 100644
--- a/free.c
+++ b/free.c
@@ -11,10 +11,14 @@
* Copyright 2003 Robert Love
* Copyright 2004 Albert Cahalan
*/
+
#include "proc/sysinfo.h"
#include "proc/version.h"
+#include "c.h"
+#include "nls.h"
+
+#include <locale.h>
#include <errno.h>
-#include <err.h>
#include <limits.h>
#include <ctype.h>
#include <getopt.h>
@@ -48,24 +52,26 @@ static const char *scale_size(unsigned long size, int flags, struct commandline_
static void __attribute__ ((__noreturn__))
usage(FILE * out)
{
- fprintf(out, "\nUsage: %s [options]\n" "\nOptions:\n", program_invocation_short_name);
+ fputs(USAGE_HEADER, out);
fprintf(out,
- " -b, --bytes show output in bytes\n"
- " -k, --kilo show output in kilobytes\n"
- " -m, --mega show output in megabytes\n"
- " -g, --giga show output in gigabytes\n"
- " --tera show output in terabytes\n"
- " -h, --human show human readable output\n"
- " --si use powers of 1000 not 1024\n"
- " -l, --lohi show detailed low and high memory statistics\n"
- " -o, --old use old format (no -/+buffers/cache line)\n"
- " -t, --total show total for RAM + swap\n"
- " -s N, --seconds N repeat printing every N seconds\n"
- " -c N, --count N repeat printing N times\n");
- fprintf(out,
- " --help display this help text\n"
- " -V, --version display version information and exit\n");
- fprintf(out, "\nFor more information see free(1).\n");
+ _(" %s [options]\n"), program_invocation_short_name);
+ fputs(USAGE_OPTIONS, out);
+ fputs(_(" -b, --bytes show output in bytes\n"), out);
+ fputs(_(" -k, --kilo show output in kilobytes\n"), out);
+ fputs(_(" -m, --mega show output in megabytes\n"), out);
+ fputs(_(" -g, --giga show output in gigabytes\n"), out);
+ fputs(_(" --tera show output in terabytes\n"), out);
+ fputs(_(" -h, --human show human readable output\n"), out);
+ fputs(_(" --si use powers of 1000 not 1024\n"), out);
+ fputs(_(" -l, --lohi show detailed low and high memory statistics\n"), out);
+ fputs(_(" -o, --old use old format (no -/+buffers/cache line)\n"), out);
+ fputs(_(" -t, --total show total for RAM + swap\n"), out);
+ fputs(_(" -s N, --seconds N repeat printing every N seconds\n"), out);
+ fputs(_(" -c N, --count N repeat printing N times\n"), out);
+ fputs(USAGE_SEPARATOR, out);
+ fputs(_(" --help display this help text\n"), out);
+ fputs(USAGE_VERSION, out);
+ fprintf(out, USAGE_MAN_TAIL("free(1)"));
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
@@ -79,7 +85,7 @@ double power(unsigned int base, unsigned int expo)
static const char *scale_size(unsigned long size, int flags, struct commandline_arguments args)
{
static char nextup[] = { 'B', 'K', 'M', 'G', 'T', 0 };
- static char buf[SIZE_MAX];
+ static char buf[BUFSIZ];
int i;
char *up;
float base;
@@ -166,7 +172,6 @@ int main(int argc, char **argv)
int c, flags = 0;
char *endptr;
struct commandline_arguments args;
- args.repeat_counter = 0;
/*
* For long options that have no equivalent short option, use a
@@ -199,6 +204,11 @@ int main(int argc, char **argv)
/* defaults to old format */
args.exponent = 0;
args.repeat_interval = 1000000;
+ args.repeat_counter = 0;
+
+ setlocale (LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
while ((c = getopt_long(argc, argv, "bkmghlotc:s:V", longopts, NULL)) != -1)
switch (c) {
@@ -236,23 +246,23 @@ int main(int argc, char **argv)
flags |= FREE_REPEAT;
args.repeat_interval = (1000000 * strtof(optarg, &endptr));
if (errno || optarg == endptr || (endptr && *endptr))
- errx(EXIT_FAILURE, "seconds argument `%s' failed", optarg);
+ errx(EXIT_FAILURE, _("seconds argument `%s' failed"), optarg);
if (args.repeat_interval < 1)
errx(EXIT_FAILURE,
- "seconds argument `%s' is not positive number", optarg);
+ _("seconds argument `%s' is not positive number"), optarg);
break;
case 'c':
flags |= FREE_REPEAT;
flags |= FREE_REPEATCOUNT;
args.repeat_counter = strtoul(optarg, &endptr, 10);
if (errno || optarg == endptr || (endptr && *endptr))
- errx(EXIT_FAILURE, "count argument `%s' failed", optarg);
+ errx(EXIT_FAILURE, _("count argument `%s' failed"), optarg);
break;
case HELP_OPTION:
usage(stdout);
case 'V':
- display_version();
+ printf(PROCPS_NG_VERSION);
exit(EXIT_SUCCESS);
default:
usage(stderr);
@@ -261,10 +271,11 @@ int main(int argc, char **argv)
do {
meminfo();
-
- printf
- (" total used free shared buffers cached\n");
- printf("%-7s", "Mem:");
+ /* Translation Hint: You can use 9 character words in
+ * the header, and the words need to be right align to
+ * beginning of a number. */
+ printf("%s\n", _(" total used free shared buffers cached"));
+ printf("%-7s", _("Mem:"));
printf(" %10s", scale_size(kb_main_total, flags, args));
printf(" %10s", scale_size(kb_main_used, flags, args));
printf(" %10s", scale_size(kb_main_free, flags, args));
@@ -279,13 +290,13 @@ int main(int argc, char **argv)
* to print the high info, even if it is zero.
*/
if (flags & FREE_LOHI) {
- printf("%-7s", "Low:");
+ printf("%-7s", _("Low:"));
printf(" %10s", scale_size(kb_low_total, flags, args));
printf(" %10s", scale_size(kb_low_total - kb_low_free, flags, args));
printf(" %10s", scale_size(kb_low_free, flags, args));
printf("\n");
- printf("%-7s", "High:");
+ printf("%-7s", _("High:"));
printf(" %10s", scale_size(kb_high_total, flags, args));
printf(" %10s", scale_size(kb_high_total - kb_high_free, flags, args));
printf(" %10s", scale_size(kb_high_free, flags, args));
@@ -294,21 +305,21 @@ int main(int argc, char **argv)
if (!(flags & FREE_OLDFMT)) {
unsigned KLONG buffers_plus_cached = kb_main_buffers + kb_main_cached;
- printf("-/+ buffers/cache:");
+ printf(_("-/+ buffers/cache:"));
printf(" %10s",
scale_size(kb_main_used - buffers_plus_cached, flags, args));
printf(" %10s",
scale_size(kb_main_free + buffers_plus_cached, flags, args));
printf("\n");
}
- printf("%-7s", "Swap:");
+ printf("%-7s", _("Swap:"));
printf(" %10s", scale_size(kb_swap_total, flags, args));
printf(" %10s", scale_size(kb_swap_used, flags, args));
printf(" %10s", scale_size(kb_swap_free, flags, args));
printf("\n");
if (flags & FREE_TOTAL) {
- printf("%-7s", "Total:");
+ printf("%-7s", _("Total:"));
printf(" %10s", scale_size(kb_main_total + kb_swap_total, flags, args));
printf(" %10s", scale_size(kb_main_used + kb_swap_used, flags, args));
printf(" %10s", scale_size(kb_main_free + kb_swap_free, flags, args));
diff --git a/include/Makefile.am b/include/Makefile.am
new file mode 100644
index 0000000..560eb77
--- /dev/null
+++ b/include/Makefile.am
@@ -0,0 +1,4 @@
+dist_noinst_HEADERS = \
+ c.h \
+ nls.h \
+ xalloc.h
diff --git a/include/c.h b/include/c.h
new file mode 100644
index 0000000..950bca2
--- /dev/null
+++ b/include/c.h
@@ -0,0 +1,159 @@
+/*
+ * This header was copied from util-linux at fall 2011.
+ */
+
+/*
+ * Fundamental C definitions.
+ */
+
+#ifndef PROCPS_NG_C_H
+#define PROCPS_NG_C_H
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef HAVE_ERR_H
+# include <err.h>
+#endif
+
+/*
+ * Compiler specific stuff
+ */
+#ifndef __GNUC_PREREQ
+# if defined __GNUC__ && defined __GNUC_MINOR__
+# define __GNUC_PREREQ(maj, min) \
+ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+# else
+# define __GNUC_PREREQ(maj, min) 0
+# endif
+#endif
+
+/*
+ * Function attributes
+ */
+#ifndef __ul_alloc_size
+# if __GNUC_PREREQ (4, 3)
+# define __ul_alloc_size(s) __attribute__((alloc_size(s)))
+# else
+# define __ul_alloc_size(s)
+# endif
+#endif
+
+#ifndef __ul_calloc_size
+# if __GNUC_PREREQ (4, 3)
+# define __ul_calloc_size(n, s) __attribute__((alloc_size(n, s)))
+# else
+# define __ul_calloc_size(n, s)
+# endif
+#endif
+
+/*
+ * Misc
+ */
+#ifndef PATH_MAX
+# define PATH_MAX 4096
+#endif
+
+#ifndef TRUE
+# define TRUE 1
+#endif
+
+#ifndef FALSE
+# define FALSE 0
+#endif
+
+/*
+ * Program name.
+ */
+#ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME
+# ifdef HAVE___PROGNAME
+extern char *__progname;
+# define program_invocation_short_name __progname
+# else
+# ifdef HAVE_GETEXECNAME
+# define program_invocation_short_name \
+ prog_inv_sh_nm_from_file(getexecname(), 0)
+# else
+# define program_invocation_short_name \
+ prog_inv_sh_nm_from_file(__FILE__, 1)
+# endif
+static char prog_inv_sh_nm_buf[256];
+static inline char *prog_inv_sh_nm_from_file(char *f, char stripext)
+{
+ char *t;
+
+ if ((t = strrchr(f, '/')) != NULL)
+ t++;
+ else
+ t = f;
+
+ strncpy(prog_inv_sh_nm_buf, t, sizeof(prog_inv_sh_nm_buf) - 1);
+ prog_inv_sh_nm_buf[sizeof(prog_inv_sh_nm_buf) - 1] = '\0';
+
+ if (stripext && (t = strrchr(prog_inv_sh_nm_buf, '.')) != NULL)
+ *t = '\0';
+
+ return prog_inv_sh_nm_buf;
+}
+# endif
+#endif
+
+/*
+ * Error printing.
+ */
+#ifndef HAVE_ERR_H
+static inline void
+errmsg(char doexit, int excode, char adderr, const char *fmt, ...)
+{
+ fprintf(stderr, "%s: ", program_invocation_short_name);
+ if (fmt != NULL) {
+ va_list argp;
+ va_start(argp, fmt);
+ vfprintf(stderr, fmt, argp);
+ va_end(argp);
+ if (adderr)
+ fprintf(stderr, ": ");
+ }
+ if (adderr)
+ fprintf(stderr, "%m");
+ fprintf(stderr, "\n");
+ if (doexit)
+ exit(excode);
+}
+
+# ifndef HAVE_ERR
+# define err(E, FMT...) errmsg(1, E, 1, FMT)
+# endif
+
+# ifndef HAVE_ERRX
+# define errx(E, FMT...) errmsg(1, E, 0, FMT)
+# endif
+
+# ifndef HAVE_WARN
+# define warn(FMT...) errmsg(0, 0, 1, FMT)
+# endif
+
+# ifndef HAVE_WARNX
+# define warnx(FMT...) errmsg(0, 0, 0, FMT)
+# endif
+#endif /* !HAVE_ERR_H */
+
+
+/*
+ * Constant strings for usage() functions.
+ */
+#define USAGE_HEADER _("\nUsage:\n")
+#define USAGE_OPTIONS _("\nOptions:\n")
+#define USAGE_SEPARATOR _("\n")
+#define USAGE_HELP _(" -h, --help display this help and exit\n")
+#define USAGE_VERSION _(" -V, --version output version information and exit\n")
+#define USAGE_MAN_TAIL(_man) _("\nFor more details see %s.\n"), _man
+
+#define PROCPS_NG_VERSION _("%s from %s\n"), program_invocation_short_name, PACKAGE_STRING
+
+#endif /* PROCPS_NG_C_H */
diff --git a/include/nls.h b/include/nls.h
new file mode 100644
index 0000000..fee89b2
--- /dev/null
+++ b/include/nls.h
@@ -0,0 +1,114 @@
+/*
+ * This header was copied from util-linux at fall 2011.
+ */
+
+#ifndef PROCPS_NG_NLS_H
+#define PROCPS_NG_NLS_H
+
+/* programs issuing textdomain() need PACKAGE string */
+#include "../config.h"
+
+/* programs issuing bindtextdomain() also need LOCALEDIR string */
+#ifndef LOCALEDIR
+#define LOCALEDIR "/usr/share/locale"
+#endif
+
+#ifdef HAVE_LOCALE_H
+# include <locale.h>
+#else
+# undef setlocale
+# define setlocale(Category, Locale) /* empty */
+#endif
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# define _(Text) gettext (Text)
+# ifdef gettext_noop
+# define N_(String) gettext_noop (String)
+# else
+# define N_(String) (String)
+# endif
+# define P_(Singular, Plural, n) ngettext (Singular, Plural, n)
+#else
+# undef bindtextdomain
+# define bindtextdomain(Domain, Directory) /* empty */
+# undef textdomain
+# define textdomain(Domain) /* empty */
+# define _(Text) (Text)
+# define N_(Text) (Text)
+# define P_(Singular, Plural, n) ((n) == 1 ? (Singular) : (Plural))
+#endif /* ENABLE_NLS */
+
+#ifdef HAVE_LANGINFO_H
+# include <langinfo.h>
+#else
+
+typedef int nl_item;
+extern char *langinfo_fallback(nl_item item);
+
+# define nl_langinfo langinfo_fallback
+
+enum {
+ CODESET = 1,
+ RADIXCHAR,
+ THOUSEP,
+ D_T_FMT,
+ D_FMT,
+ T_FMT,
+ T_FMT_AMPM,
+ AM_STR,
+ PM_STR,
+
+ DAY_1,
+ DAY_2,
+ DAY_3,
+ DAY_4,
+ DAY_5,
+ DAY_6,
+ DAY_7,
+
+ ABDAY_1,
+ ABDAY_2,
+ ABDAY_3,
+ ABDAY_4,
+ ABDAY_5,
+ ABDAY_6,
+ ABDAY_7,
+
+ MON_1,
+ MON_2,
+ MON_3,
+ MON_4,
+ MON_5,
+ MON_6,
+ MON_7,
+ MON_8,
+ MON_9,
+ MON_10,
+ MON_11,
+ MON_12,
+
+ ABMON_1,
+ ABMON_2,
+ ABMON_3,
+ ABMON_4,
+ ABMON_5,
+ ABMON_6,
+ ABMON_7,
+ ABMON_8,
+ ABMON_9,
+ ABMON_10,
+ ABMON_11,
+ ABMON_12,
+
+ ERA_D_FMT,
+ ERA_D_T_FMT,
+ ERA_T_FMT,
+ ALT_DIGITS,
+ CRNCYSTR,
+ YESEXPR,
+ NOEXPR
+};
+
+#endif /* !HAVE_LANGINFO_H */
+#endif /* PROCPS_NG_NLS_H */
diff --git a/include/strutils.h b/include/strutils.h
new file mode 100644
index 0000000..e36048d
--- /dev/null
+++ b/include/strutils.h
@@ -0,0 +1,11 @@
+/*
+ * This header was copied from util-linux at fall 2011.
+ */
+
+#ifndef PROCPS_NG_STRUTILS
+#define PROCPS_NG_STRUTILS
+
+extern long strtol_or_err(const char *str, const char *errmesg);
+extern double strtod_or_err(const char *str, const char *errmesg);
+
+#endif
diff --git a/include/xalloc.h b/include/xalloc.h
new file mode 100644
index 0000000..bd02c75
--- /dev/null
+++ b/include/xalloc.h
@@ -0,0 +1,60 @@
+/*
+ * This header was copied from util-linux at fall 2011.
+ */
+
+/*
+ * General memory allocation wrappers for malloc, realloc, calloc
+ * and strdup.
+ */
+
+#ifndef PROCPS_NG_XALLOC_H
+#define PROCPS_NG_XALLOC_H
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "c.h"
+
+#ifndef XALLOC_EXIT_CODE
+# define XALLOC_EXIT_CODE EXIT_FAILURE
+#endif
+
+static inline __ul_alloc_size(1)
+void *xmalloc(const size_t size)
+{
+ void *ret = malloc(size);
+ if (!ret && size)
+ err(XALLOC_EXIT_CODE, "cannot allocate %zu bytes", size);
+ return ret;
+}
+
+static inline __ul_alloc_size(2)
+void *xrealloc(void *ptr, const size_t size)
+{
+ void *ret = realloc(ptr, size);
+ if (!ret && size)
+ err(XALLOC_EXIT_CODE, "cannot allocate %zu bytes", size);
+ return ret;
+}
+
+static inline __ul_calloc_size(1, 2)
+void *xcalloc(const size_t nelems, const size_t size)
+{
+ void *ret = calloc(nelems, size);
+ if (!ret && size && nelems)
+ err(XALLOC_EXIT_CODE, "cannot allocate %zu bytes", size);
+ return ret;
+}
+
+static inline char *xstrdup(const char *str)
+{
+ char *ret;
+ if (!str)
+ return NULL;
+ ret = strdup(str);
+ if (!ret)
+ err(XALLOC_EXIT_CODE, "cannot duplicate string");
+ return ret;
+}
+
+#endif /* PROCPS_NG_XALLOC_H */
diff --git a/kill.1 b/kill.1
index 5df66a1..e9af8ee 100644
--- a/kill.1
+++ b/kill.1
@@ -5,73 +5,57 @@
.\" Licensed under version 2 of the GNU General Public License.
.\" Written by Albert Cahalan; converted to a man page by
.\" Michael K. Johnson
-.TH KILL 1 "November 21, 1999" "Linux" "Linux User's Manual"
+.TH KILL 1 "October 2011" "procps-ng" "User Commands"
.SH NAME
kill \- send a signal to a process
-
.SH SYNOPSIS
-\fBkill\fR [ \-\fBsignal\fR | \-s \fBsignal\fR ] \fBpid\fR ...
-.br
-\fBkill\fR [ \-L | -V, \-\-version ]
-.br
-\fBkill\fR \-l [ \fBsignal\fR ]
-
+.B kill
+[options] <pid> [...]
.SH DESCRIPTION
-The default signal for kill is TERM. Use \-l or \-L to list available signals.
-Particularly useful signals include HUP, INT, KILL, STOP, CONT, and 0.
-Alternate signals may be specified in three ways: \-9 \-SIGKILL \-KILL.
-Negative PID values may be used to choose whole process groups; see the
-PGID column in ps command output. A PID of \-1 is special; it indicates
-all processes except the kill process itself and init.
-
-.SH SIGNALS
-The signals listed below may be available for use with kill.
-When known constant, numbers and default behavior are shown.
-
-.TS
-lB rB lB lB
-lfCW r l l.
-Name Num Action Description
-0 0 n/a exit code indicates if a signal may be sent
-ALRM 14 exit
-HUP 1 exit
-INT 2 exit
-KILL 9 exit cannot be blocked
-PIPE 13 exit
-POLL exit
-PROF exit
-TERM 15 exit
-USR1 exit
-USR2 exit
-VTALRM exit
-STKFLT exit might not be implemented
-PWR ignore might exit on some systems
-WINCH ignore
-CHLD ignore
-URG ignore
-TSTP stop might interact with the shell
-TTIN stop might interact with the shell
-TTOU stop might interact with the shell
-STOP stop cannot be blocked
-CONT restart continue if stopped, otherwise ignore
-ABRT 6 core
-FPE 8 core
-ILL 4 core
-QUIT 3 core
-SEGV 11 core
-TRAP 5 core
-SYS core might not be implemented
-EMT core might not be implemented
-BUS core core dump might fail
-XCPU core core dump might fail
-XFSZ core core dump might fail
-.TE
-
+The default signal for kill is TERM. Use
+.B \-l
+or
+.B \-L
+to list available signals. Particularly useful signals include HUP,
+INT, KILL, STOP, CONT, and 0. Alternate signals may be specified in
+three ways:
+.BR \-9 ", " \-SIGKILL
+or
+.BR \-KILL .
+Negative PID values may be used to choose whole process groups; see
+the PGID column in ps command output. A PID of
+.B \-1
+is special; it indicates all processes except the kill process itself
+and init.
+.SH OPTIONS
+.TP
+.B <pid> [...]
+Send signal to every <pid> listed.
+.TP
+.B \-<signal>
+.TQ
+.B \-s <signal>
+.TQ
+.B \-\-signal <signal>
+Specify the
+.B signal
+to be sent. The signal can be specified by using name or number.
+The behavior of signals is explained in
+.BR signal (7)
+manual page.
+.TP
+\fB\-l\fR, \fB\-\-list\fR [\fIsignal\fR]
+List signal names. This option has optional argument, which
+will convert signal number to signal name, or other way round.
+.TP
+.BR \-L , \ \-\-table
+List signal names in a nice table.
+.TP
+.PD
.SH NOTES
-Your shell (command line interpreter) may have a built-in kill command.
-You may need to run the command described here as /bin/kill to solve
-the conflict.
-
+Your shell (command line interpreter) may have a built-in kill
+command. You may need to run the command described here as /bin/kill
+to solve the conflict.
.SH EXAMPLES
.TP
.B kill \-9 \-1
@@ -85,22 +69,25 @@ List the available signal choices in a nice table.
.TP
.B kill 123 543 2341 3453
Send the default signal, SIGTERM, to all those processes.
-
.SH "SEE ALSO"
-.BR pkill (1),
-.BR skill (1),
.BR kill (2),
-.BR renice (1),
+.BR killall (1),
.BR nice (1),
+.BR pkill (1),
+.BR renice (1),
.BR signal (7),
-.BR killall (1).
-
+.BR skill (1)
.SH STANDARDS
-This command meets appropriate standards. The \-L flag is Linux-specific.
-
+This command meets appropriate standards. The
+.B \-L
+flag is Linux-specific.
.SH AUTHOR
-Albert Cahalan <albert@users.sf.net> wrote kill in 1999 to replace a
-bsdutils one that was not standards compliant. The util-linux one might
-also work correctly.
-
-Please send bug reports to <procps@freelists.org>
+.UR albert\@users.sf.net
+Albert Cahalan
+.UE
+wrote kill in 1999 to replace a bsdutils one that was not standards
+compliant. The util-linux one might also work correctly.
+.SH "REPORTING BUGS"
+Please send bug reports to
+.UR procps\@freelists.org
+.UE
diff --git a/lib/.gitignore b/lib/.gitignore
new file mode 100644
index 0000000..88ee4c9
--- /dev/null
+++ b/lib/.gitignore
@@ -0,0 +1 @@
+test_strutils
diff --git a/lib/Makefile.am b/lib/Makefile.am
new file mode 100644
index 0000000..4216a25
--- /dev/null
+++ b/lib/Makefile.am
@@ -0,0 +1,7 @@
+AM_CPPFLAGS = -include $(top_builddir)/config.h -I$(top_srcdir)/include
+
+AM_CPPFLAGS += -DTEST_PROGRAM
+
+noinst_PROGRAMS = test_strutils
+
+test_strutils_SOURCES = strutils.c
diff --git a/lib/strutils.c b/lib/strutils.c
new file mode 100644
index 0000000..65ef998
--- /dev/null
+++ b/lib/strutils.c
@@ -0,0 +1,62 @@
+/*
+ * This file was copied from util-linux at fall 2011.
+ */
+
+#include <stdlib.h>
+
+#include "c.h"
+#include "strutils.h"
+
+/*
+ * same as strtol(3) but exit on failure instead of returning crap
+ */
+long strtol_or_err(const char *str, const char *errmesg)
+{
+ long num;
+ char *end = NULL;
+
+ if (str == NULL || *str == '\0')
+ goto err;
+ errno = 0;
+ num = strtol(str, &end, 10);
+ if (errno || str == end || (end && *end))
+ goto err;
+
+ return num;
+ err:
+ if (errno)
+ err(EXIT_FAILURE, "%s: '%s'", errmesg, str);
+ else
+ errx(EXIT_FAILURE, "%s: '%s'", errmesg, str);
+}
+/*
+ * same as strtod(3) but exit on failure instead of returning crap
+ */
+double strtod_or_err(const char *str, const char *errmesg)
+{
+ double num;
+ char *end = NULL;
+
+ if (str == NULL || *str == '\0')
+ goto err;
+ errno = 0;
+ num = strtod(str, &end);
+
+ if (errno || str == end || (end && *end))
+ goto err;
+
+ return num;
+ err:
+ if (errno)
+ err(EXIT_FAILURE, "%s: '%s'", errmesg, str);
+ else
+ errx(EXIT_FAILURE, "%s: '%s'", errmesg, str);
+ return 0;
+}
+
+#ifdef TEST_PROGRAM
+int main(int argc, char *argv[])
+{
+ return EXIT_FAILURE;
+}
+#endif /* TEST_PROGRAM */
diff --git a/pgrep.1 b/pgrep.1
index c933b8f..06e1e7f 100644
--- a/pgrep.1
+++ b/pgrep.1
@@ -2,162 +2,203 @@
.\" Licensed under version 2 of the GNU General Public License.
.\" Copyright 2000 Kjetil Torgrim Homme
.\"
-.TH PGREP 1 "October 5, 2007" "Linux" "Linux User's Manual"
+.TH PGREP "1" "September 2011" "procps-ng" "User Commands"
.SH NAME
pgrep, pkill \- look up or signal processes based on name and other attributes
-
.SH SYNOPSIS
-.na
-\fBpgrep\fR [\fB\-cflvx\fR] [\fB\-d\ \fIdelimiter\fR] [\fB\-n\fR|\fB\-o\fR] \
-[\fB\-P\ \fIppid\fR,...] [\fB\-g\ \fIpgrp\fR,...] [\fB\-s\ \fIsid\fR,...] \
-[\fB\-u\ \fIeuid\fR,...] [\fB\-U\ \fIuid\fR,...] [\fB\-G\ \fIgid\fR,...] \
-[\fB\-t\ \fIterm\fR,...] [\fIpattern\fR]
-
-.HP
-\fBpkill\fR [\fB\-\fIsignal\fR] [\fB\-fvx\fR] [\fB\-n\fR|\fB\-o\fR] \
-[\fB\-P\ \fIppid\fR,...] [\fB\-g\ \fIpgrp\fR,...] [\fB\-s\ \fIsid\fR,...] \
-[\fB\-u\ \fIeuid\fR,...] [\fB\-U\ \fIuid\fR,...] [\fB\-G\ \fIgid\fR,...] \
-[\fB\-t\ \fIterm\fR,...] [\fIpattern\fR]
-
+.B pgrep
+[options] pattern
+.br
+.B pkill
+[options] pattern
.SH DESCRIPTION
-\fBpgrep\fP looks through the currently running processes and lists the
-process IDs which matches the selection criteria to stdout. All
-the criteria have to match. For example,
-
+.B pgrep
+looks through the currently running processes and lists the process IDs which
+matches the selection criteria to stdout. All the criteria have to match.
+For example,
.IP
$ pgrep \-u root sshd
-
.PP
-will only list the processes called \fBsshd\fP AND owned by \fBroot\fP.
+will only list the processes called
+.B sshd
+AND owned by
+.BR root .
On the other hand,
-
.IP
$ pgrep \-u root,daemon
-
.PP
-will list the processes owned by \fBroot\fP OR \fBdaemon\fP.
-
-\fBpkill\fP will send the specified signal (by default \fBSIGTERM\fP)
+will list the processes owned by
+.B root
+OR
+.BR daemon .
+.PP
+.B pkill
+will send the specified signal (by default
+.BR SIGTERM )
to each process instead of listing them on stdout.
-
.SH OPTIONS
-\-c
-Suppress normal output; instead print a count of matching processes.
-.TP
-\fB\-d \fIdelimiter\fP
-Sets the string used to delimit each process ID in the output (by
-default a newline). (\fBpgrep\fP only.)
-.TP
-\fB\-f\fR
-The \fIpattern\fP is normally only matched against the process name.
-When \fB\-f\fR is set, the full command line is used.
-.TP
-\fB\-g \fIpgrp\fP,...
-Only match processes in the process group IDs listed. Process group 0
-is translated into \fBpgrep\fP's or \fBpkill\fP's own process group.
-.TP
-\-G \fIgid\fP,...
-Only match processes whose real group ID is listed. Either the
-numerical or symbolical value may be used.
.TP
-\fB\-l\fR
-List the process name as well as the process ID. (\fBpgrep\fP only.)
+\fB\-\fR\fIsignal\fP
+.TQ
+\fB\-\-signal\fR \fIsignal\fR
+Defines the signal to send to each matched process. Either the numeric or
+the symbolic signal name can be used.
+.RB ( pkill
+only.)
.TP
-\fB\-n\fR
-Select only the newest (most recently started) of the matching
-processes.
-.TP
-\fB\-o\fR
-Select only the oldest (least recently started) of the matching
-processes.
-.TP
-\fB\-P \fIppid\fP,...
+\fB\-c\fR, \fB\-\-count\fR
+Suppress normal output; instead print a count of matching processes.
+(\fBpgrep\fP only.)
+.TP
+\fB\-d\fR, \fB\-\-delimeter\fR \fIdelimiter\fP
+Sets the string used to delimit each process ID in the output (by default a
+newline).
+.RB ( pgrep
+only.)
+.TP
+\fB\-f\fR, \fB\-\-full\fR
+The
+.I pattern
+is normally only matched against the process name. When
+.B \-f
+is set, the full command line is used.
+.TP
+\fB\-g\fR, \fB\-\-pgroup\fR \fIpgrp\fP,...
+Only match processes in the process group IDs listed. Process group 0 is
+translated into
+.BR pgrep 's
+or
+.BR pkill 's
+own process group.
+.TP
+\fB\-G\fR, \fB\-\-group\fR \fIgid\fP,...
+Only match processes whose real group ID is listed. Either the numerical or
+symbolical value may be used.
+.TP
+\fB\-l\fR, \fB\-\-\fRlist\-name\fR
+List the process name as well as the process ID.
+.RB ( pgrep
+only.)
+\fB\-n\fR, \fB\-\-newest\fR
+Select only the newest (most recently started) of the matching processes.
+.TP
+\fB\-o\fR, \fB\-\-oldest\fR
+Select only the oldest (least recently started) of the matching processes.
+.TP
+\fB\-P\fR, \fB\-\-parent\fR \fIppid\fP,...
Only match processes whose parent process ID is listed.
.TP
-\fB\-s \fIsid\fP,...
+\fB\-s\fR, \fB\-\-session\fR \fIsid\fP,...
Only match processes whose process session ID is listed. Session ID 0
-is translated into \fBpgrep\fP's or \fBpkill\fP's own session ID.
+is translated into
+.BR pgrep 's
+or
+.BR pkill 's
+own session ID.
.TP
-\fB\-t \fIterm\fP,...
-Only match processes whose controlling terminal is listed. The
-terminal name should be specified without the "/dev/" prefix.
+\fB\-t\fR, \fB\-\-terminal\fR \fIterm\fP,...
+Only match processes whose controlling terminal is listed. The terminal name
+should be specified without the "/dev/" prefix.
.TP
-\fB\-u \fIeuid\fP,...
-Only match processes whose effective user ID is listed. Either the
-numerical or symbolical value may be used.
+\fB\-u\fR, \fB\-\-euid\fR \fIeuid\fP,...
+Only match processes whose effective user ID is listed. Either the numerical
+or symbolical value may be used.
.TP
-\fB\-U \fIuid\fP,...
-Only match processes whose real user ID is listed. Either the
-numerical or symbolical value may be used.
+\fB\-U\fR, \fB\-\-uid\fR \fIuid\fP,...
+Only match processes whose real user ID is listed. Either the numerical or
+symbolical value may be used.
.TP
-\fB\-v\fR
+\fB\-v\fR, \fB\-\-inverse\fR\fR
Negates the matching.
.TP
-\fB\-x\fR
+\fB\-x\fR, \fB\-\-exact\fR\fR
Only match processes whose name (or command line if \-f is specified)
-\fBexactly\fP match the \fIpattern\fP.
-.TP
-\-\fIsignal\fP
-Defines the signal to send to each matched process. Either the
-numeric or the symbolic signal name can be used. (\fBpkill\fP only.)
-
+.B exactly
+match the
+.IR pattern .
+.TP
+\fB\-F\fR, \fB\-\-pidfile\fR \fIfile\fR
+Read
+.IR PID 's
+from file. This option is perhaps more useful for
+.B pkill
+than
+.BR pgrep .
+.TP
+\fB\-L\fR, \fB\-\-logpidfile\fR
+Fail if pidfile (see -F) not locked.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Display version information and exit.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Display help and exit.
+.PD
.SH OPERANDS
.TP
-\fIpattern\fP
-Specifies an Extended Regular Expression for matching against the
-process names or command lines.
-
+.I pattern
+Specifies an Extended Regular Expression for matching against the process
+names or command lines.
.SH EXAMPLES
-Example 1: Find the process ID of the \fBnamed\fP daemon:
-
+Example 1: Find the process ID of the
+.B named
+daemon:
.IP
$ pgrep \-u root named
-
.PP
-Example 2: Make \fBsyslog\fP reread its configuration file:
-
+Example 2: Make
+.B syslog
+reread its configuration file:
.IP
$ pkill \-HUP syslogd
-
.PP
-Example 3: Give detailed information on all \fBxterm\fP processes:
-
+Example 3: Give detailed information on all
+.B xterm
+processes:
.IP
$ ps \-fp $(pgrep \-d, \-x xterm)
-
.PP
-Example 4: Make all \fBnetscape\fP processes run nicer:
-
+Example 4: Make all
+.B netscape
+processes run nicer:
.IP
-$ renice +4 `pgrep netscape`
-
+$ renice +4 $(pgrep netscape)
.SH "EXIT STATUS"
.PD 0
.TP
-.I 0
+0
One or more processes matched the criteria.
.TP
-.I 1
+1
No processes matched.
.TP
-.I 2
+2
Syntax error in the command line.
.TP
-.I 3
+3
Fatal error: out of memory etc.
-
+.PD
.SH NOTES
-The process name used for matching is limited to the 15 characters
-present in the output of /proc/\fIpid\fP/stat. Use the \-f option to
-match against the complete command line, /proc/\fIpid\fP/cmdline.
-
-The running \fBpgrep\fP or \fBpkill\fP process will never report
-itself as a match.
-
+The process name used for matching is limited to the 15 characters present in
+the output of /proc/\fIpid\fP/stat. Use the \-f option to match against the
+complete command line, /proc/\fIpid\fP/cmdline.
+.PP
+The running
+.B pgrep
+or
+.B pkill
+process will never report itself as a
+match.
.SH BUGS
-The options \fB\-n\fP and \fB\-o\fP and \fB\-v\fP can not be combined.
-Let me know if you need to do this.
-
+The options
+.B \-n
+and
+.B \-o
+and
+.B \-v
+can not be combined. Let
+me know if you need to do this.
+.PP
Defunct processes are reported.
.SH "SEE ALSO"
@@ -168,12 +209,16 @@ Defunct processes are reported.
.BR skill (1),
.BR kill (1),
.BR kill (2)
-
.SH STANDARDS
-\fBpkill\fP and \fBpgrep\fP were introduced in Sun's Solaris 7. This
-implementation is fully compatible.
-
+.B pkill
+and
+.B pgrep
+were introduced in Sun's Solaris 7. This implementation is fully compatible.
.SH AUTHOR
-Kjetil Torgrim Homme <kjetilho@ifi.uio.no>
-
-Please send bug reports to <procps@freelists.org>
+.UR kjetilho\@ifi.uio.no
+Kjetil Torgrim Homme
+.UE
+.SH "REPORTING BUGS"
+Please send bug reports to
+.UR procps\@freelists.org
+.UE
diff --git a/pgrep.c b/pgrep.c
index c8cd0ca..9d8d825 100644
--- a/pgrep.c
+++ b/pgrep.c
@@ -26,20 +26,24 @@
#include <grp.h>
#include <regex.h>
#include <errno.h>
+#include <getopt.h>
+// EXIT_SUCCESS is 0
+// EXIT_FAILURE is 1
+#define EXIT_USAGE 2
+#define EXIT_FATAL 3
+#define XALLOC_EXIT_CODE EXIT_FATAL
+
+#include "c.h"
+#include "nls.h"
+#include "xalloc.h"
#include "proc/readproc.h"
#include "proc/sig.h"
#include "proc/devname.h"
#include "proc/sysinfo.h"
#include "proc/version.h" /* procps_version */
-// EXIT_SUCCESS is 0
-// EXIT_FAILURE is 1
-#define EXIT_USAGE 2
-#define EXIT_FATAL 3
-
static int i_am_pkill = 0;
-static const char *progname = "pgrep";
union el {
long num;
@@ -71,27 +75,47 @@ static union el *opt_ruid = NULL;
static char *opt_pattern = NULL;
static char *opt_pidfile = NULL;
-static int usage (int opt) NORETURN;
-static int usage (int opt)
+static int __attribute__ ((__noreturn__)) usage(int opt)
{
- int err = (opt=='?'); /* getopt() uses '?' to mark an error */
+ int err = (opt == '?');
FILE *fp = err ? stderr : stdout;
- if (i_am_pkill)
- fprintf (fp, "Usage: pkill [-SIGNAL] [-fvx] ");
- else
- fprintf (fp, "Usage: pgrep [-cflvx] [-d DELIM] ");
- fprintf (fp, "[-n|-o] [-P PPIDLIST] [-g PGRPLIST] [-s SIDLIST]\n"
- "\t[-u EUIDLIST] [-U UIDLIST] [-G GIDLIST] [-t TERMLIST] "
- "[PATTERN]\n");
-
- exit(err ? EXIT_USAGE : EXIT_SUCCESS);
+ fputs(USAGE_HEADER, fp);
+ fprintf(fp, _(" %s [options] <pattern>\n"), program_invocation_short_name);
+ fputs(USAGE_OPTIONS, fp);
+ if (i_am_pkill == 0) {
+ fputs(_(" -c, --count count of matching processes\n"), fp);
+ fputs(_(" -d, --delimeter <string> update delay in seconds\n"), fp);
+ fputs(_(" -l, --list-name list PID and process name\n"), fp);
+ }
+ if (i_am_pkill == 1) {
+ fputs(_(" -<sig>, --signal <sig> signal to send (either number or name)\n"), fp);
+ }
+ fputs(_(" -f, --full use full process name to match\n"), fp);
+ fputs(_(" -g, --pgroup <id,...> match listed process group IDs\n"), fp);
+ fputs(_(" -G, --group <gid,...> match real group IDs\n"), fp);
+ fputs(_(" -n, --newest select most recently started\n"), fp);
+ fputs(_(" -o, --oldest select least recently started\n"), fp);
+ fputs(_(" -P, --parent <ppid,...> match only childs of given parent\n"), fp);
+ fputs(_(" -s, --session <sid,...> match session IDs\n"), fp);
+ fputs(_(" -t, --terminal <tty,...> match by controlling terminal\n"), fp);
+ fputs(_(" -u, --euid <id,...> match by effective IDs\n"), fp);
+ fputs(_(" -U, --uid <id,...> match by real IDs\n"), fp);
+ fputs(_(" -v, --inverse negates the matching\n"), fp);
+ fputs(_(" -x, --exact match exectly with command name\n"), fp);
+ fputs(_(" -F, --pidfile <file> read PIDs from file\n"), fp);
+ fputs(_(" -L, --logpidfile fail if PID file is not locked\n"), fp);
+ fputs(USAGE_SEPARATOR, fp);
+ fputs(USAGE_HELP, fp);
+ fputs(USAGE_VERSION, fp);
+ fprintf(fp, USAGE_MAN_TAIL("pgrep(1)"));
+
+ exit(fp == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
-
static union el *split_list (const char *restrict str, int (*convert)(const char *, union el *))
{
- char *copy = strdup (str);
+ char *copy = xstrdup (str);
char *ptr = copy;
char *sep_pos;
int i = 0;
@@ -102,9 +126,7 @@ static union el *split_list (const char *restrict str, int (*convert)(const char
if (i == size) {
size = size * 5 / 4 + 4;
// add 1 because slot zero is a count
- list = realloc (list, 1 + size * sizeof *list);
- if (list == NULL)
- exit (EXIT_FATAL);
+ list = xrealloc (list, 1 + size * sizeof *list);
}
sep_pos = strchr (ptr, ',');
if (sep_pos)
@@ -215,7 +237,7 @@ static union el *read_pidfile(void)
goto out;
if(*endp && !isspace(*endp))
goto out;
- list = malloc(2 * sizeof *list);
+ list = xmalloc(2 * sizeof *list);
list[0].num = 1;
list[1].num = pid;
out:
@@ -233,8 +255,7 @@ static int conv_uid (const char *restrict name, union el *restrict e)
pwd = getpwnam (name);
if (pwd == NULL) {
- fprintf (stderr, "%s: invalid user name: %s\n",
- progname, name);
+ warnx(_("invalid user name: %s"), name);
return 0;
}
e->num = pwd->pw_uid;
@@ -251,8 +272,7 @@ static int conv_gid (const char *restrict name, union el *restrict e)
grp = getgrnam (name);
if (grp == NULL) {
- fprintf (stderr, "%s: invalid group name: %s\n",
- progname, name);
+ warnx(_("invalid group name: %s"), name);
return 0;
}
e->num = grp->gr_gid;
@@ -263,8 +283,7 @@ static int conv_gid (const char *restrict name, union el *restrict e)
static int conv_pgrp (const char *restrict name, union el *restrict e)
{
if (! strict_atol (name, &e->num)) {
- fprintf (stderr, "%s: invalid process group: %s\n",
- progname, name);
+ warnx(_("invalid process group: %s"), name);
return 0;
}
if (e->num == 0)
@@ -276,8 +295,7 @@ static int conv_pgrp (const char *restrict name, union el *restrict e)
static int conv_sid (const char *restrict name, union el *restrict e)
{
if (! strict_atol (name, &e->num)) {
- fprintf (stderr, "%s: invalid session id: %s\n",
- progname, name);
+ warnx(_("invalid session id: %s"), name);
return 0;
}
if (e->num == 0)
@@ -289,8 +307,7 @@ static int conv_sid (const char *restrict name, union el *restrict e)
static int conv_num (const char *restrict name, union el *restrict e)
{
if (! strict_atol (name, &e->num)) {
- fprintf (stderr, "%s: not a number: %s\n",
- progname, name);
+ warnx(_("not a number: %s"), name);
return 0;
}
return 1;
@@ -299,7 +316,7 @@ static int conv_num (const char *restrict name, union el *restrict e)
static int conv_str (const char *restrict name, union el *restrict e)
{
- e->str = strdup (name);
+ e->str = xstrdup (name);
return 1;
}
@@ -373,9 +390,7 @@ static PROCTAB *do_openproc (void)
if (opt_euid && !opt_negate) {
int num = opt_euid[0].num;
int i = num;
- uid_t *uids = malloc (num * sizeof (uid_t));
- if (uids == NULL)
- exit (EXIT_FATAL);
+ uid_t *uids = xmalloc (num * sizeof (uid_t));
while (i-- > 0) {
uids[i] = opt_euid[i+1].num;
}
@@ -396,13 +411,9 @@ static regex_t * do_regcomp (void)
char errbuf[256];
int re_err;
- preg = malloc (sizeof (regex_t));
- if (preg == NULL)
- exit (EXIT_FATAL);
+ preg = xmalloc (sizeof (regex_t));
if (opt_exact) {
- re = malloc (strlen (opt_pattern) + 5);
- if (re == NULL)
- exit (EXIT_FATAL);
+ re = xmalloc (strlen (opt_pattern) + 5);
sprintf (re, "^(%s)$", opt_pattern);
} else {
re = opt_pattern;
@@ -520,14 +531,12 @@ static union el * select_procs (int *num)
}
if (matches == size) {
size = size * 5 / 4 + 4;
- list = realloc(list, size * sizeof *list);
- if (list == NULL)
- exit (EXIT_FATAL);
+ list = xrealloc(list, size * sizeof *list);
}
if (opt_long) {
char buff[5096]; // FIXME
sprintf (buff, "%d %s", task.XXXID, cmd);
- list[matches++].str = strdup (buff);
+ list[matches++].str = xstrdup (buff);
} else {
list[matches++].num = task.XXXID;
}
@@ -547,9 +556,35 @@ static void parse_opts (int argc, char **argv)
int opt;
int criteria_count = 0;
- if (strstr (argv[0], "pkill")) {
- i_am_pkill = 1;
- progname = "pkill";
+ enum {
+ SIGNAL_OPTION = CHAR_MAX + 1
+ };
+ static const struct option longopts[] = {
+ {"signal", required_argument, NULL, SIGNAL_OPTION},
+ {"count", no_argument, NULL, 'c'},
+ {"delimeter", required_argument, NULL, 'd'},
+ {"list-name", no_argument, NULL, 'l'},
+ {"full", no_argument, NULL, 'f'},
+ {"pgroup", required_argument, NULL, 'g'},
+ {"group", required_argument, NULL, 'G'},
+ {"newest", no_argument, NULL, 'n'},
+ {"oldest", no_argument, NULL, 'o'},
+ {"parent", required_argument, NULL, 'P'},
+ {"session", required_argument, NULL, 's'},
+ {"terminal", required_argument, NULL, 't'},
+ {"euid", required_argument, NULL, 'u'},
+ {"uid", required_argument, NULL, 'U'},
+ {"inverse", no_argument, NULL, 'v'},
+ {"exact", no_argument, NULL, 'x'},
+ {"pidfile", required_argument, NULL, 'F'},
+ {"logpidfile", no_argument, NULL, 'L'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'V'},
+ {NULL, 0, NULL, 0}
+ };
+
+ if (strstr (program_invocation_short_name, "pkill")) {
+ i_am_pkill = 1;
/* Look for a signal name or number as first argument */
if (argc > 1 && argv[1][0] == '-') {
int sig;
@@ -566,17 +601,22 @@ static void parse_opts (int argc, char **argv)
}
} else {
/* These options are for pgrep only */
- strcat (opts, "ld:");
+ strcat (opts, "cld:");
}
- strcat (opts, "LF:cfnovxP:g:s:u:U:G:t:?V");
+ strcat (opts, "LF:fnovxP:g:s:u:U:G:t:?Vh");
- while ((opt = getopt (argc, argv, opts)) != -1) {
+ while ((opt = getopt_long (argc, argv, opts, longopts, NULL)) != -1) {
switch (opt) {
+ case SIGNAL_OPTION:
+ opt_signal = signal_name_to_number (optarg);
+ if (opt_signal == -1 && isdigit (optarg[0]))
+ opt_signal = atoi (optarg);
+ break;
// case 'D': // FreeBSD: print info about non-matches for debugging
// break;
case 'F': // FreeBSD: the arg is a file containing a PID to match
- opt_pidfile = strdup (optarg);
+ opt_pidfile = xstrdup (optarg);
++criteria_count;
break;
case 'G': // Solaris: match rgid/rgroup
@@ -613,7 +653,7 @@ static void parse_opts (int argc, char **argv)
++criteria_count;
break;
case 'V':
- fprintf(stdout, "%s (%s)\n", progname, procps_version);
+ printf(PROCPS_NG_VERSION);
exit(EXIT_SUCCESS);
// case 'c': // Solaris: match by contract ID
// break;
@@ -621,7 +661,7 @@ static void parse_opts (int argc, char **argv)
opt_count = 1;
break;
case 'd': // Solaris: change the delimiter
- opt_delim = strdup (optarg);
+ opt_delim = xstrdup (optarg);
break;
case 'f': // Solaris: match full process name (as in "ps -f")
opt_full = 1;
@@ -683,52 +723,62 @@ static void parse_opts (int argc, char **argv)
break;
// case 'z': // Solaris: match by zone ID
// break;
+ case 'h':
+ usage (opt);
+ break;
case '?':
usage (optopt ? optopt : opt);
break;
}
}
- if(opt_lock && !opt_pidfile){
- fprintf(stderr, "%s: -L without -F makes no sense\n",progname);
- usage(0);
- }
+ if(opt_lock && !opt_pidfile)
+ errx(EXIT_FAILURE, _("-L without -F makes no sense\n"
+ "Try `%s --help' for more information."),
+ program_invocation_short_name);
if(opt_pidfile){
opt_pid = read_pidfile();
- if(!opt_pid){
- fprintf(stderr, "%s: pidfile not valid\n",progname);
- usage(0);
- }
+ if(!opt_pid)
+ errx(EXIT_FAILURE, _("pidfile not valid\n"
+ "Try `%s --help' for more information."),
+ program_invocation_short_name);
}
if (argc - optind == 1)
opt_pattern = argv[optind];
else if (argc - optind > 1)
- usage (0);
- else if (criteria_count == 0) {
- fprintf (stderr, "%s: No matching criteria specified\n",
- progname);
- usage (0);
- }
+ errx(EXIT_FAILURE, _("only one pattern can be provided\n"
+ "Try `%s --help' for more information."),
+ program_invocation_short_name);
+ else if (criteria_count == 0)
+ errx(EXIT_FAILURE, _("no matching criteria specified\n"
+ "Try `%s --help' for more information."),
+ program_invocation_short_name);
}
-int main (int argc, char *argv[])
+int main (int argc, char **argv)
{
union el *procs;
int num;
+ setlocale (LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
parse_opts (argc, argv);
procs = select_procs (&num);
if (i_am_pkill) {
int i;
for (i = 0; i < num; i++) {
- if (kill (procs[i].num, opt_signal) != -1) continue;
- if (errno==ESRCH) continue; // gone now, which is OK
- fprintf (stderr, "pkill: %ld - %s\n",
- procs[i].num, strerror (errno));
+ if (kill (procs[i].num, opt_signal) != -1)
+ continue;
+ if (errno==ESRCH)
+ // gone now, which is OK
+ continue;
+ warn(_("killing pid %ld failed"));
}
} else {
if (opt_count) {
diff --git a/pmap.1 b/pmap.1
index 9327c6b..4d8fde5 100644
--- a/pmap.1
+++ b/pmap.1
@@ -5,37 +5,59 @@
.\" Licensed under version 2 of the GNU General Public License.
.\" Written by Albert Cahalan.
.\"
-.TH PMAP 1 "October 26, 2002" "Linux" "Linux User's Manual"
+.TH PMAP "1" "June 2011" "procps-ng" "User Commands"
.SH NAME
pmap \- report memory map of a process
-
.SH SYNOPSIS
.B pmap
-.RB [ \-x | \-d ]
-.RB [ \-q ]
-.I pid
-\& ...
-.br
-.B pmap \-V
-
+[\fIoptions\fR] \fIpid\fR [...]
.SH DESCRIPTION
The pmap command reports the memory map of a process or processes.
-
-.SH "GENERAL OPTIONS"
-.TS
-lB l l.
-\-x extended Show the extended format.
-\-d device Show the device format.
-\-q quiet Do not display some header/footer lines.
-\-V show version Displays version of program.
-.TE
-
+.SH OPTIONS
+.TP
+\fB\-x\fR, \fB\-\-extended\fR
+Show the extended format.
+.TP
+\fB\-d\fR, \fB\-\-device\fR
+Show the device format.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Do not display some header or footer lines.
+.TP
+\fB\-A\fR, \fB\-\-range\fR \fIlow\fR,\fIhigh\fR
+Limit results to the given range to
+.I low
+and
+.I high
+address range. Notice that the low and high arguments are single string
+separated with comma.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Display help text and exit.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Display version information and exit.
+.SH "EXIT STATUS"
+.PP
+.RS
+.PD 0
+.TP
+.B 0
+Success.
+.TP
+.B 1
+Failure.
+.TP
+.B 42
+Did not find all processes asked for.
+.PD
+.RE
.SH "SEE ALSO"
.BR ps (1),
.BR pgrep (1)
-
.SH STANDARDS
No standards apply, but pmap looks an awful lot like a SunOS command.
-
-.SH BUG REPORTS
-Please send bug reports to <procps@freelists.org>
+.SH "REPORTING BUGS"
+Please send bug reports to
+.UR procps\@freelists.org
+.UE
diff --git a/pmap.c b/pmap.c
index 6555b84..998080e 100644
--- a/pmap.c
+++ b/pmap.c
@@ -9,417 +9,495 @@
* GNU Library General Public License for more details.
*/
-#include <stdio.h>
-#include <stdlib.h>
#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+#include <err.h>
+#include <errno.h>
#include <fcntl.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
-
#include <sys/ipc.h>
#include <sys/shm.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "c.h"
+#include "nls.h"
+#include "proc/escape.h"
+#include "xalloc.h"
#include "proc/readproc.h"
#include "proc/version.h"
-#include "proc/escape.h"
-static void usage(void) NORETURN;
-static void usage(void){
- fprintf(stderr,
- "Usage: pmap [-x | -d] [-q] [-A low,high] pid...\n"
- "-x show details\n"
- "-d show offset and device number\n"
- "-q quiet; less header/footer info\n"
- "-V show the version number\n"
- "-A limit results to the given range\n"
- );
- exit(1);
+static void __attribute__ ((__noreturn__))
+ usage(FILE * out)
+{
+ fputs(USAGE_HEADER, out);
+ fprintf(out,
+ _(" %s [options] pid [pid ...]\n"), program_invocation_short_name);
+ fputs(USAGE_OPTIONS, out);
+ fputs(_(" -x, --extended show details\n"), out);
+ fputs(_(" -d, --device show the device format\n"), out);
+ fputs(_(" -q, --quiet do not display header and footer\n"), out);
+ fputs(_(" -A, --range=<low>[,<high>] limit results to the given range\n"), out);
+ fputs(USAGE_SEPARATOR, out);
+ fputs(USAGE_HELP, out);
+ fputs(USAGE_VERSION, out);
+ fprintf(out, USAGE_MAN_TAIL("pmap(1)"));
+ exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
-
static unsigned KLONG range_low;
static unsigned KLONG range_high = ~0ull;
-static int V_option;
-static int r_option; // ignored -- for SunOS compatibility
-static int x_option;
static int d_option;
static int q_option;
+static int x_option;
static unsigned shm_minor = ~0u;
-static void discover_shm_minor(void){
- void *addr;
- int shmid;
- char mapbuf[256];
-
- if(!freopen("/proc/self/maps", "r", stdin)) return;
-
- // create
- shmid = shmget(IPC_PRIVATE, 42, IPC_CREAT | 0666);
- if(shmid==-1) return; // failed; oh well
- // attach
- addr = shmat(shmid, NULL, SHM_RDONLY);
- if(addr==(void*)-1) goto out_destroy;
-
- while(fgets(mapbuf, sizeof mapbuf, stdin)){
- char flags[32];
- char *tmp; // to clean up unprintables
- unsigned KLONG start, end;
- unsigned long long file_offset, inode;
- unsigned dev_major, dev_minor;
- sscanf(mapbuf,"%"KLF"x-%"KLF"x %31s %Lx %x:%x %Lu", &start, &end, flags, &file_offset, &dev_major, &dev_minor, &inode);
- tmp = strchr(mapbuf,'\n');
- if(tmp) *tmp='\0';
- tmp = mapbuf;
- while(*tmp){
- if(!isprint(*tmp)) *tmp='?';
- tmp++;
- }
- if(start > (unsigned long)addr) continue;
- if(dev_major) continue;
- if(flags[3] != 's') continue;
- if(strstr(mapbuf,"/SYSV")){
- shm_minor = dev_minor;
- break;
- }
- }
-
- if(shmdt(addr)) perror("shmdt");
-
-out_destroy:
- if(shmctl(shmid, IPC_RMID, NULL)) perror("IPC_RMID");
-
- return;
+static void discover_shm_minor(void)
+{
+ void *addr;
+ int shmid;
+ char mapbuf[256];
+
+ if (!freopen("/proc/self/maps", "r", stdin))
+ return;
+
+ /* create */
+ shmid = shmget(IPC_PRIVATE, 42, IPC_CREAT | 0666);
+ if (shmid == -1)
+ /* failed; oh well */
+ return;
+ /* attach */
+ addr = shmat(shmid, NULL, SHM_RDONLY);
+ if (addr == (void *)-1)
+ goto out_destroy;
+
+ while (fgets(mapbuf, sizeof mapbuf, stdin)) {
+ char flags[32];
+ /* to clean up unprintables */
+ char *tmp;
+ unsigned KLONG start, end;
+ unsigned long long file_offset, inode;
+ unsigned dev_major, dev_minor;
+ sscanf(mapbuf, "%" KLF "x-%" KLF "x %31s %Lx %x:%x %Lu", &start,
+ &end, flags, &file_offset, &dev_major, &dev_minor,
+ &inode);
+ tmp = strchr(mapbuf, '\n');
+ if (tmp)
+ *tmp = '\0';
+ tmp = mapbuf;
+ while (*tmp) {
+ if (!isprint(*tmp))
+ *tmp = '?';
+ tmp++;
+ }
+ if (start > (unsigned long)addr)
+ continue;
+ if (dev_major)
+ continue;
+ if (flags[3] != 's')
+ continue;
+ if (strstr(mapbuf, "/SYSV")) {
+ shm_minor = dev_minor;
+ break;
+ }
+ }
+
+ if (shmdt(addr))
+ perror(_("shared memory detach"));
+
+ out_destroy:
+ if (shmctl(shmid, IPC_RMID, NULL))
+ perror(_("shared memory remove"));
+
+ return;
}
-
-static const char *mapping_name(proc_t *p, unsigned KLONG addr, unsigned KLONG len, const char *mapbuf, unsigned showpath, unsigned dev_major, unsigned dev_minor, unsigned long long inode){
- const char *cp;
-
- if(!dev_major && dev_minor==shm_minor && strstr(mapbuf,"/SYSV")){
- static char shmbuf[64];
- snprintf(shmbuf, sizeof shmbuf, " [ shmid=0x%Lx ]", inode);
- return shmbuf;
- }
-
- cp = strrchr(mapbuf,'/');
- if(cp){
- if(showpath) return strchr(mapbuf,'/');
- return cp[1] ? cp+1 : cp;
- }
-
- cp = strchr(mapbuf,'/');
- if(cp){
- if(showpath) return cp;
- return strrchr(cp,'/') + 1; // it WILL succeed
- }
-
- cp = " [ anon ]";
- if( (p->start_stack >= addr) && (p->start_stack <= addr+len) ) cp = " [ stack ]";
- return cp;
+static const char *mapping_name(proc_t * p, unsigned KLONG addr,
+ unsigned KLONG len, const char *mapbuf,
+ unsigned showpath, unsigned dev_major,
+ unsigned dev_minor, unsigned long long inode)
+{
+ const char *cp;
+
+ if (!dev_major && dev_minor == shm_minor && strstr(mapbuf, "/SYSV")) {
+ static char shmbuf[64];
+ snprintf(shmbuf, sizeof shmbuf, " [ shmid=0x%Lx ]", inode);
+ return shmbuf;
+ }
+
+ cp = strrchr(mapbuf, '/');
+ if (cp) {
+ if (showpath)
+ return strchr(mapbuf, '/');
+ return cp[1] ? cp + 1 : cp;
+ }
+
+ cp = strchr(mapbuf, '/');
+ if (cp) {
+ if (showpath)
+ return cp;
+ /* it WILL succeed */
+ return strrchr(cp, '/') + 1;
+ }
+
+ cp = _(" [ anon ]");
+ if ((p->start_stack >= addr) && (p->start_stack <= addr + len))
+ cp = _(" [ stack ]");
+ return cp;
}
-static int one_proc(proc_t *p){
- char buf[32];
- char mapbuf[9600];
- char cmdbuf[512];
- FILE *fp;
- unsigned long total_shared = 0ul;
- unsigned long total_private_readonly = 0ul;
- unsigned long total_private_writeable = 0ul;
-
- char *cp2=NULL;
- unsigned long long rss = 0ull;
- unsigned long long private_dirty = 0ull;
- unsigned long long shared_dirty = 0ull;
- unsigned long long total_rss = 0ull;
- unsigned long long total_private_dirty = 0ull;
- unsigned long long total_shared_dirty = 0ull;
- unsigned KLONG diff=0;
-
- // Overkill, but who knows what is proper? The "w" prog
- // uses the tty width to determine this.
- int maxcmd = 0xfffff;
-
- sprintf(buf,"/proc/%u/maps",p->tgid);
- if ( (fp = fopen(buf, "r")) == NULL) return 1;
- if (x_option) {
- sprintf(buf,"/proc/%u/smaps",p->tgid);
- if ( (fp = freopen(buf, "r", fp)) == NULL) return 1;
- }
-
- escape_command(cmdbuf, p, sizeof cmdbuf, &maxcmd, ESC_ARGS|ESC_BRACKETS);
- printf("%u: %s\n", p->tgid, cmdbuf);
-
- if(!q_option && (x_option|d_option)){
- if(x_option){
- if(sizeof(KLONG)==4) printf("Address Kbytes RSS Dirty Mode Mapping\n");
- else printf("Address Kbytes RSS Dirty Mode Mapping\n");
- }
- if(d_option){
- if(sizeof(KLONG)==4) printf("Address Kbytes Mode Offset Device Mapping\n");
- else printf("Address Kbytes Mode Offset Device Mapping\n");
- }
- }
-
- while(fgets(mapbuf,sizeof mapbuf,fp)){
- char flags[32];
- char *tmp; // to clean up unprintables
- unsigned KLONG start, end;
- unsigned long long file_offset, inode;
- unsigned dev_major, dev_minor;
- unsigned long long smap_value;
- char smap_key[20];
-
- /* hex values are lower case or numeric, keys are upper */
- if (mapbuf[0] >= 'A' && mapbuf[0] <= 'Z') {
- /* Its a key */
- if (sscanf(mapbuf,"%20[^:]: %llu", smap_key, &smap_value) == 2) {
- if (strncmp("Rss", smap_key, 3) == 0) {
- rss = smap_value;
- total_rss += smap_value;
- continue;
- }
- if (strncmp("Shared_Dirty", smap_key, 12) == 0) {
- shared_dirty = smap_value;
- total_shared_dirty += smap_value;
- continue;
- }
- if (strncmp("Private_Dirty", smap_key, 13) == 0) {
- private_dirty = smap_value;
- total_private_dirty += smap_value;
- continue;
- }
- if (strncmp("Swap", smap_key, 4) == 0) { /*doesnt matter as long as last*/
- printf(
- (sizeof(KLONG)==8)
- ? "%016"KLF"x %7lu %7llu %7llu %s %s\n"
- : "%08lx %7lu %7llu %7llu %s %s\n",
- start,
- (unsigned long)(diff>>10),
- rss,
- (private_dirty + shared_dirty),
- flags,
- cp2
- );
- /* reset some counters */
- rss = shared_dirty = private_dirty = 0ull;
- diff=0;
- continue;
- }
- /* Other keys */
- continue;
- }
- }
- sscanf(mapbuf,"%"KLF"x-%"KLF"x %31s %Lx %x:%x %Lu", &start, &end, flags, &file_offset, &dev_major, &dev_minor, &inode);
-
- if(start > range_high)
- break;
- if(end < range_low)
- continue;
-
- tmp = strchr(mapbuf,'\n');
- if(tmp) *tmp='\0';
- tmp = mapbuf;
- while(*tmp){
- if(!isprint(*tmp)) *tmp='?';
- tmp++;
- }
-
- diff = end-start;
- if(flags[3]=='s') total_shared += diff;
- if(flags[3]=='p'){
- flags[3] = '-';
- if(flags[1]=='w') total_private_writeable += diff;
- else total_private_readonly += diff;
- }
-
- // format used by Solaris 9 and procps-3.2.0+
- // an 'R' if swap not reserved (MAP_NORESERVE, SysV ISM shared mem, etc.)
- flags[4] = '-';
- flags[5] = '\0';
-
- if(x_option){
- cp2 = mapping_name(p, start, diff, mapbuf, 0, dev_major, dev_minor, inode);
- /* printed with the keys */
- continue;
- }
- if(d_option){
- const char *cp = mapping_name(p, start, diff, mapbuf, 0, dev_major, dev_minor, inode);
- printf(
- (sizeof(KLONG)==8)
- ? "%016"KLF"x %7lu %s %016Lx %03x:%05x %s\n"
- : "%08lx %7lu %s %016Lx %03x:%05x %s\n",
- start,
- (unsigned long)(diff>>10),
- flags,
- file_offset,
- dev_major, dev_minor,
- cp
- );
- }
- if(!x_option && !d_option){
- const char *cp = mapping_name(p, start, diff, mapbuf, 1, dev_major, dev_minor, inode);
- printf(
- (sizeof(KLONG)==8)
- ? "%016"KLF"x %6luK %s %s\n"
- : "%08lx %6luK %s %s\n",
- start,
- (unsigned long)(diff>>10),
- flags,
- cp
- );
- }
-
- }
-
-
-
-
- if(!q_option){
- if(x_option){
- if(sizeof(KLONG)==8){
- printf("---------------- ------ ------ ------\n");
- printf(
- "total kB %15ld %7llu %7llu\n",
- (total_shared + total_private_writeable + total_private_readonly) >> 10,
- total_rss, (total_shared_dirty+total_private_dirty)
-
- );
- }else{
- printf("-------- ------- ------- ------- -------\n");
- printf(
- "total kB %7ld - - -\n",
- (total_shared + total_private_writeable + total_private_readonly) >> 10
- );
- }
- }
- if(d_option){
- printf(
- "mapped: %ldK writeable/private: %ldK shared: %ldK\n",
- (total_shared + total_private_writeable + total_private_readonly) >> 10,
- total_private_writeable >> 10,
- total_shared >> 10
- );
- }
- if(!x_option && !d_option){
- if(sizeof(KLONG)==8) printf(" total %16ldK\n", (total_shared + total_private_writeable + total_private_readonly) >> 10);
- else printf(" total %8ldK\n", (total_shared + total_private_writeable + total_private_readonly) >> 10);
- }
- }
-
- return 0;
+static int one_proc(proc_t * p)
+{
+ char buf[32];
+ char mapbuf[9600];
+ char cmdbuf[512];
+ FILE *fp;
+ unsigned long total_shared = 0ul;
+ unsigned long total_private_readonly = 0ul;
+ unsigned long total_private_writeable = 0ul;
+ KLONG diff = 0;
+
+ char *cp2 = NULL;
+ unsigned long long rss = 0ull;
+ unsigned long long private_dirty = 0ull;
+ unsigned long long shared_dirty = 0ull;
+ unsigned long long total_rss = 0ull;
+ unsigned long long total_private_dirty = 0ull;
+ unsigned long long total_shared_dirty = 0ull;
+
+ /* Overkill, but who knows what is proper? The "w" prog uses
+ * the tty width to determine this.
+ */
+ int maxcmd = 0xfffff;
+
+ sprintf(buf, "/proc/%u/maps", p->tgid);
+ if ((fp = fopen(buf, "r")) == NULL)
+ return 1;
+ if (x_option) {
+ sprintf(buf, "/proc/%u/smaps", p->tgid);
+ if ((fp = freopen(buf, "r", fp)) == NULL)
+ return 1;
+ }
+
+ escape_command(cmdbuf, p, sizeof cmdbuf, &maxcmd,
+ ESC_ARGS | ESC_BRACKETS);
+ printf("%u: %s\n", p->tgid, cmdbuf);
+
+ if (!q_option && (x_option | d_option)) {
+ if (x_option) {
+ if (sizeof(KLONG) == 4)
+ /* Translation Hint: Please keep
+ * alignment of the following four
+ * headers intact. */
+ printf
+ (_("Address Kbytes RSS Dirty Mode Mapping\n"));
+ else
+ printf
+ (_("Address Kbytes RSS Dirty Mode Mapping\n"));
+ }
+ if (d_option) {
+ if (sizeof(KLONG) == 4)
+ printf
+ (_("Address Kbytes Mode Offset Device Mapping\n"));
+ else
+ printf
+ (_("Address Kbytes Mode Offset Device Mapping\n"));
+ }
+ }
+
+ while (fgets(mapbuf, sizeof mapbuf, fp)) {
+ char flags[32];
+ /* to clean up unprintables */
+ char *tmp;
+ unsigned KLONG start, end;
+ unsigned long long file_offset, inode;
+ unsigned dev_major, dev_minor;
+ unsigned long long smap_value;
+ char smap_key[20];
+
+ /* hex values are lower case or numeric, keys are upper */
+ if (mapbuf[0] >= 'A' && mapbuf[0] <= 'Z') {
+ /* Its a key */
+ if (sscanf
+ (mapbuf, "%20[^:]: %llu", smap_key,
+ &smap_value) == 2) {
+ if (strncmp("Rss", smap_key, 3) == 0) {
+ rss = smap_value;
+ total_rss += smap_value;
+ continue;
+ }
+ if (strncmp("Shared_Dirty", smap_key, 12) == 0) {
+ shared_dirty = smap_value;
+ total_shared_dirty += smap_value;
+ continue;
+ }
+ if (strncmp("Private_Dirty", smap_key, 13) == 0) {
+ private_dirty = smap_value;
+ total_private_dirty += smap_value;
+ continue;
+ }
+ if (strncmp("Swap", smap_key, 4) == 0) {
+ /*doesnt matter as long as last */
+ printf((sizeof(KLONG) == 8)
+ ? "%016" KLF
+ "x %7lu %7llu %7llu %s %s\n" :
+ "%08lx %7lu %7llu %7llu %s %s\n",
+ start,
+ (unsigned long)(diff >> 10), rss,
+ (private_dirty + shared_dirty),
+ flags, cp2);
+ /* reset some counters */
+ rss = shared_dirty = private_dirty =
+ 0ull;
+ diff = 0;
+ continue;
+ }
+ /* Other keys */
+ continue;
+ }
+ }
+ sscanf(mapbuf, "%" KLF "x-%" KLF "x %31s %Lx %x:%x %Lu", &start,
+ &end, flags, &file_offset, &dev_major, &dev_minor,
+ &inode);
+
+ if (start > range_high)
+ break;
+ if (end < range_low)
+ continue;
+
+ tmp = strchr(mapbuf, '\n');
+ if (tmp)
+ *tmp = '\0';
+ tmp = mapbuf;
+ while (*tmp) {
+ if (!isprint(*tmp))
+ *tmp = '?';
+ tmp++;
+ }
+
+ diff = end - start;
+ if (flags[3] == 's')
+ total_shared += diff;
+ if (flags[3] == 'p') {
+ flags[3] = '-';
+ if (flags[1] == 'w')
+ total_private_writeable += diff;
+ else
+ total_private_readonly += diff;
+ }
+ /* format used by Solaris 9 and procps-3.2.0+ an 'R'
+ * if swap not reserved (MAP_NORESERVE, SysV ISM
+ * shared mem, etc.)
+ */
+ flags[4] = '-';
+ flags[5] = '\0';
+
+ if (x_option) {
+ cp2 =
+ mapping_name(p, start, diff, mapbuf, 0, dev_major,
+ dev_minor, inode);
+ /* printed with the keys */
+ continue;
+ }
+ if (d_option) {
+ const char *cp =
+ mapping_name(p, start, diff, mapbuf, 0, dev_major,
+ dev_minor, inode);
+ printf((sizeof(KLONG) == 8)
+ ? "%016" KLF "x %7lu %s %016Lx %03x:%05x %s\n"
+ : "%08lx %7lu %s %016Lx %03x:%05x %s\n",
+ start,
+ (unsigned long)(diff >> 10),
+ flags, file_offset, dev_major, dev_minor, cp);
+ }
+ if (!x_option && !d_option) {
+ const char *cp =
+ mapping_name(p, start, diff, mapbuf, 1, dev_major,
+ dev_minor, inode);
+ printf((sizeof(KLONG) == 8)
+ ? "%016" KLF "x %6luK %s %s\n"
+ : "%08lx %6luK %s %s\n",
+ start, (unsigned long)(diff >> 10), flags, cp);
+ }
+
+ }
+
+ if (!q_option) {
+ if (x_option) {
+ if (sizeof(KLONG) == 8) {
+ printf
+ ("---------------- ------ ------ ------\n");
+ printf(_("total kB %15ld %7llu %7llu\n"),
+ (total_shared + total_private_writeable +
+ total_private_readonly) >> 10,
+ total_rss,
+ (total_shared_dirty +
+ total_private_dirty)
+
+ );
+ } else {
+ printf
+ ("-------- ------- ------- ------- -------\n");
+ printf
+ (_("total kB %7ld - - -\n"),
+ (total_shared + total_private_writeable +
+ total_private_readonly) >> 10);
+ }
+ }
+ if (d_option) {
+ printf
+ (_("mapped: %ldK writeable/private: %ldK shared: %ldK\n"),
+ (total_shared + total_private_writeable +
+ total_private_readonly) >> 10,
+ total_private_writeable >> 10, total_shared >> 10);
+ }
+ if (!x_option && !d_option) {
+ if (sizeof(KLONG) == 8)
+ /* Translation Hint: keep total string length
+ * as 24 characters. Adjust %16 if needed*/
+ printf(_(" total %16ldK\n"),
+ (total_shared + total_private_writeable +
+ total_private_readonly) >> 10);
+ else
+ /* Translation Hint: keep total string length
+ * as 16 characters. Adjust %8 if needed*/
+ printf(_(" total %8ldK\n"),
+ (total_shared + total_private_writeable +
+ total_private_readonly) >> 10);
+ }
+ }
+
+ return 0;
}
-
-int main(int argc, char *argv[]){
- unsigned *pidlist;
- unsigned count = 0;
- PROCTAB* PT;
- proc_t p;
- int ret = 0;
-
- if(argc<2) usage();
- pidlist = malloc(sizeof(unsigned)*argc); // a bit more than needed perhaps
-
- while(*++argv){
- if(!strcmp("--version",*argv)){
- V_option++;
- continue;
- }
- if(**argv=='-'){
- char *walk = *argv;
- if(!walk[1]) usage();
- while(*++walk){
- switch(*walk){
- case 'V':
- V_option++;
- break;
- case 'x':
- x_option++;
- break;
- case 'r':
- r_option++;
- break;
- case 'd':
- d_option++;
- break;
- case 'q':
- q_option++;
- break;
- case 'A':{
- char *arg1;
- if(walk[1]){
- arg1 = walk+1;
- walk += strlen(walk)-1;
- }else{
- arg1 = *++argv;
- if(!arg1)
- usage();
- }
- char *arg2 = strchr(arg1,',');
- if(arg2)
- *arg2 = '\0';
- if(arg2) ++arg2;
- else arg2 = arg1;
-
- if(*arg1)
- range_low = STRTOUKL(arg1,&arg1,16);
- if(*arg2)
- range_high = STRTOUKL(arg2,&arg2,16);
- if(*arg1 || *arg2)
- usage();
- }
- break;
- case 'a': // Sun prints anon/swap reservations
- case 'F': // Sun forces hostile ptrace-like grab
- case 'l': // Sun shows unresolved dynamic names
- case 'L': // Sun shows lgroup info
- case 's': // Sun shows page sizes
- case 'S': // Sun shows swap reservations
- default:
- usage();
- }
- }
- }else{
- char *walk = *argv;
- char *endp;
- unsigned long pid;
- if(!strncmp("/proc/",walk,6)){
- walk += 6;
- // user allowed to do: pmap /proc/*
- if(*walk<'0' || *walk>'9') continue;
- }
- if(*walk<'0' || *walk>'9') usage();
- pid = strtoul(walk, &endp, 0);
- if(pid<1ul || pid>0x7ffffffful || *endp) usage();
- pidlist[count++] = pid;
- }
- }
-
- if( (x_option|V_option|r_option|d_option|q_option) >> 1 ) usage(); // dupes
- if(V_option){
- if(count|x_option|r_option|d_option|q_option) usage();
- fprintf(stdout, "pmap (%s)\n", procps_version);
- return 0;
- }
- if(count<1) usage(); // no processes
- if(d_option && x_option) usage();
-
- discover_shm_minor();
-
- memset(&p, '\0', sizeof(p));
- pidlist[count] = 0; // old libproc interface is zero-terminated
- PT = openproc(PROC_FILLSTAT|PROC_FILLARG|PROC_PID, pidlist);
- while(readproc(PT, &p)){
- ret |= one_proc(&p);
- count--;
- }
- closeproc(PT);
-
- if(count) ret |= 42; // didn't find all processes asked for
- return ret;
+int main(int argc, char **argv)
+{
+ unsigned *pidlist;
+ unsigned count = 0;
+ PROCTAB *PT;
+ proc_t p;
+ int ret = 0, c;
+
+ static const struct option longopts[] = {
+ {"extended", no_argument, NULL, 'x'},
+ {"device", no_argument, NULL, 'd'},
+ {"quiet", no_argument, NULL, 'q'},
+ {"range", required_argument, NULL, 'A'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'V'},
+ {NULL, 0, NULL, 0}
+ };
+
+ setlocale (LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ x_option = d_option = q_option = 0;
+
+ while ((c = getopt_long(argc, argv, "xrdqA:hV", longopts, NULL)) != -1)
+ switch (c) {
+ case 'x':
+ x_option = 1;
+ break;
+ case 'r':
+ warnx(_("option -r is ignored as SunOS compatibility"));
+ break;
+ case 'd':
+ d_option = 1;
+ break;
+ case 'q':
+ q_option = 1;
+ break;
+ case 'A':
+ {
+ /* FIXME: this should be a function. */
+ char *walk = optarg;
+ char *arg1;
+ char *arg2;
+ if (walk[1]) {
+ arg1 = walk + 1;
+ walk += strlen(walk) - 1;
+ } else {
+ arg1 = *++argv;
+ if (!arg1)
+ usage(stderr);
+ }
+ arg2 = strchr(arg1, ',');
+ if (arg2)
+ *arg2 = '\0';
+ if(arg2) ++arg2;
+ else arg2 = arg1;
+
+ if (*arg1)
+ range_low = STRTOUKL(arg1, &arg1, 16);
+ if (*arg2)
+ range_high = STRTOUKL(arg2, &arg2, 16);
+ if (*arg1 || *arg2)
+ usage(stderr);
+ }
+ break;
+ case 'h':
+ usage(stdout);
+ case 'V':
+ printf(PROCPS_NG_VERSION);
+ return EXIT_SUCCESS;
+ case 'a': /* Sun prints anon/swap reservations */
+ case 'F': /* Sun forces hostile ptrace-like grab */
+ case 'l': /* Sun shows unresolved dynamic names */
+ case 'L': /* Sun shows lgroup info */
+ case 's': /* Sun shows page sizes */
+ case 'S': /* Sun shows swap reservations */
+ default:
+ usage(stderr);
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1)
+ errx(EXIT_FAILURE, _("argument missing"));
+ if (d_option && x_option)
+ errx(EXIT_FAILURE, _("options -d and -x cannot coexist"));
+
+ pidlist = xmalloc(sizeof(unsigned) * argc);
+
+ while (*argv) {
+ char *walk = *argv++;
+ char *endp;
+ unsigned long pid;
+ if (!strncmp("/proc/", walk, 6)) {
+ walk += 6;
+ /* user allowed to do: pmap /proc/PID */
+ if (*walk < '0' || *walk > '9')
+ continue;
+ }
+ if (*walk < '0' || *walk > '9')
+ usage(stderr);
+ pid = strtoul(walk, &endp, 0);
+ if (pid < 1ul || pid > 0x7ffffffful || *endp)
+ usage(stderr);
+ pidlist[count++] = pid;
+ }
+
+ discover_shm_minor();
+
+ memset(&p, '\0', sizeof(p));
+ /* old libproc interface is zero-terminated */
+ pidlist[count] = 0;
+ PT = openproc(PROC_FILLSTAT | PROC_FILLARG | PROC_PID, pidlist);
+ while (readproc(PT, &p)) {
+ ret |= one_proc(&p);
+ count--;
+ }
+ closeproc(PT);
+
+ if (count)
+ /* didn't find all processes asked for */
+ ret |= 42;
+ return ret;
}
diff --git a/po/.gitignore b/po/.gitignore
new file mode 100644
index 0000000..7e029c5
--- /dev/null
+++ b/po/.gitignore
@@ -0,0 +1,18 @@
+*.gmo
+boldquot.sed
+en@boldquot.header
+en@quot.header
+insert-header.sin
+Makefile
+Makefile.in
+Makefile.in.in
+Makefile.in.in~
+Makevars.template
+POTFILES
+POTFILES.in
+procps-ng.pot
+quot.sed
+remove-potcdate.sed
+remove-potcdate.sin
+Rules-quot
+stamp-po
diff --git a/po/Makevars b/po/Makevars
new file mode 100644
index 0000000..88a7408
--- /dev/null
+++ b/po/Makevars
@@ -0,0 +1,41 @@
+# Makefile variables for PO directory in any package using GNU gettext.
+
+# Usually the message domain is the same as the package name.
+DOMAIN = $(PACKAGE)
+
+# These two variables depend on the location of this directory.
+subdir = po
+top_builddir = ..
+
+# These options get passed to xgettext.
+XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ --keyword=P_:1,2 --no-wrap --escape --add-comments=Translation
+
+# This is the copyright holder that gets inserted into the header of the
+# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding
+# package. (Note that the msgstr strings, extracted from the package's
+# sources, belong to the copyright holder of the package.) Translators are
+# expected to transfer the copyright for their translations to this person
+# or entity, or to disclaim their copyright. The empty string stands for
+# the public domain; in this case the translators are expected to disclaim
+# their copyright.
+COPYRIGHT_HOLDER = Free Software Foundation, Inc.
+
+# This is the email address or URL to which the translators shall report
+# bugs in the untranslated strings:
+# - Strings which are not entire sentences, see the maintainer guidelines
+# in the GNU gettext documentation, section 'Preparing Strings'.
+# - Strings which use unclear terms or require additional context to be
+# understood.
+# - Strings which make invalid assumptions about notation of date, time or
+# money.
+# - Pluralisation problems.
+# - Incorrect English spelling.
+# - Incorrect formatting.
+# It can be your email address, or a mailing list address where translators
+# can write to without being subscribed, or the URL of a web page through
+# which the translators can contact you.
+MSGID_BUGS_ADDRESS = procps@freelists.org
+
+# This is the list of locale categories, beyond LC_MESSAGES, for which the
+# message catalogs shall be used. It is usually empty.
+EXTRA_LOCALE_CATEGORIES =
diff --git a/po/update-potfiles b/po/update-potfiles
new file mode 100755
index 0000000..70af4ec
--- /dev/null
+++ b/po/update-potfiles
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+if [ ! -f "po/Makevars" ]; then
+ echo "You must run this script in the top-level directory"
+ exit 1
+fi
+
+find . -name '*.c' |
+ sort |
+ sed 's|^./||
+/^contrib/d' > po/POTFILES.in
diff --git a/proc/alloc.c b/proc/alloc.c
index 0bc71a5..21185cc 100644
--- a/proc/alloc.c
+++ b/proc/alloc.c
@@ -12,7 +12,6 @@
#include "alloc.h"
-
static void xdefault_error(const char *restrict fmts, ...) __attribute__((format(printf,1,2)));
static void xdefault_error(const char *restrict fmts, ...) {
va_list va;
diff --git a/proc/devname.c b/proc/devname.c
index 6e8d286..4be24e9 100644
--- a/proc/devname.c
+++ b/proc/devname.c
@@ -70,7 +70,7 @@ static void load_drivers(void){
p = buf;
while(( p = strstr(p, " /dev/") )){ // " /dev/" is the second column
tty_map_node *tmn;
- int len;
+ size_t len;
char *end;
p += 6;
end = strchr(p, ' ');
diff --git a/proc/devname.h b/proc/devname.h
index 10c2cb6..d54de1c 100644
--- a/proc/devname.h
+++ b/proc/devname.h
@@ -2,6 +2,7 @@
#define PROC_DEVNAME_H
#include "procps.h"
+#include "readproc.h"
EXTERN_C_BEGIN
diff --git a/proc/escape.c b/proc/escape.c
index 1fd4e74..ca73198 100644
--- a/proc/escape.c
+++ b/proc/escape.c
@@ -153,7 +153,7 @@ int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *m
// escape an argv or environment string array
//
// bytes arg means sizeof(buf)
-int escape_strlist(char *restrict dst, const char *restrict const *restrict src, size_t bytes, int *cells){
+int escape_strlist(char *restrict dst, char *restrict const *restrict src, size_t bytes, int *cells){
size_t i = 0;
for(;;){
@@ -175,7 +175,7 @@ int escape_command(char *restrict const outbuf, const proc_t *restrict const pp,
int end = 0;
if(flags & ESC_ARGS){
- const char **lc = (const char**)pp->cmdline;
+ char **lc = (char**)pp->cmdline;
if(lc && *lc) return escape_strlist(outbuf, lc, bytes, cells);
}
if(flags & ESC_BRACKETS){
diff --git a/proc/escape.h b/proc/escape.h
index aa9f6d6..8ef7b2f 100644
--- a/proc/escape.h
+++ b/proc/escape.h
@@ -14,7 +14,7 @@ EXTERN_C_BEGIN
#define ESC_BRACKETS 0x2 // if using cmd, put '[' and ']' around it
#define ESC_DEFUNCT 0x4 // mark zombies with " <defunct>"
-extern int escape_strlist(char *restrict dst, const char *restrict const *restrict src, size_t n, int *cells);
+extern int escape_strlist(char *restrict dst, char *restrict const *restrict src, size_t n, int *cells);
extern int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *maxcells);
extern int escape_command(char *restrict const outbuf, const proc_t *restrict const pp, int bytes, int *cells, unsigned flags);
extern int escaped_copy(char *restrict dst, const char *restrict src, int bufsize, int *maxroom);
diff --git a/proc/ksym.c b/proc/ksym.c
index ceddba1..b99a8a6 100644
--- a/proc/ksym.c
+++ b/proc/ksym.c
@@ -275,7 +275,7 @@ open_again:
close(fd);
return;
hell:
- if(buf) free(buf);
+ free(buf);
*bufp = NULL;
*roomp = 0; /* this function will never work again */
total = 0;
@@ -321,9 +321,11 @@ bad_parse:
}
quiet_goodbye:
idx_room = 0;
- if(ksyms_data) free(ksyms_data) , ksyms_data = NULL;
+ free(ksyms_data);
+ ksyms_data = NULL;
ksyms_room = 0;
- if(ksyms_index) free(ksyms_index) , ksyms_index = NULL;
+ free(ksyms_index);
+ ksyms_index = NULL;
ksyms_count = 0;
return 0;
}
@@ -445,7 +447,7 @@ bad_open:
sysmap_room=0;
sysmap_count=0;
- if(sysmap_index) free(sysmap_index);
+ free(sysmap_index);
sysmap_index = NULL;
if(fd>=0) close(fd);
if(sysmap_data) munmap(sysmap_data, sbuf.st_size + 1);
diff --git a/proc/libprocps.sym b/proc/libprocps.sym
index 3e4f9a2..ec66312 100644
--- a/proc/libprocps.sym
+++ b/proc/libprocps.sym
@@ -62,6 +62,7 @@ global:
signal_number_to_name;
smp_num_cpus;
sprint_uptime;
+ strtosig;
tty_to_dev;
unix_print_signals;
uptime;
diff --git a/proc/procps.h b/proc/procps.h
index 4c6866e..abbab98 100644
--- a/proc/procps.h
+++ b/proc/procps.h
@@ -71,8 +71,10 @@
#define expected(x,y) (x)
#endif
-#if SHARED==1 && (__GNUC__ > 2 || __GNUC_MINOR__ >= 96)
-#define LABEL_OFFSET
+#ifdef SHARED
+# if SHARED==1 && (__GNUC__ > 2 || __GNUC_MINOR__ >= 96)
+# define LABEL_OFFSET
+# endif
#endif
#define STRINGIFY_ARG(a) #a
diff --git a/proc/readproc.h b/proc/readproc.h
index b9d93d9..9d78140 100644
--- a/proc/readproc.h
+++ b/proc/readproc.h
@@ -141,6 +141,7 @@ typedef struct proc_t {
nlwp, // stat,status number of threads, or 0 if no clue
tgid, // (special) thread group ID, the POSIX PID (see also: tid)
tty, // stat full device number of controlling terminal
+ /* FIXME: int uids & gids should be uid_t or gid_t from pwd.h */
euid, egid, // stat(),status effective
ruid, rgid, // status real
suid, sgid, // status saved
diff --git a/proc/sig.c b/proc/sig.c
index 3d6e058..1137fef 100644
--- a/proc/sig.c
+++ b/proc/sig.c
@@ -209,6 +209,49 @@ end:
return ret;
}
+/* strtosig is similar to print_given_signals() with exception, that
+ * this function takes a string, and converts it to a signal name or
+ * a number string depending on which way a round conversion is
+ * queried. Non-existing signals return NULL. Notice that the
+ * returned string should be freed after use.
+ */
+char *strtosig(const char *restrict s){
+ char *converted = NULL, *copy, *p, *endp;
+ int i, numsignal = 0;
+
+ copy = strdup(s);
+ if (!copy)
+ err(EXIT_FAILURE, "cannot duplicate string");
+ for (p = copy; *p != '\0'; p++)
+ *p = toupper(*p);
+ p = copy;
+ if (p[0] == 'S' && p[1] == 'I' && p[2] == 'G')
+ p += 3;
+ if (isdigit(*p)){
+ numsignal = strtol(s,&endp,10);
+ if(*endp || endp==s) return NULL; /* not valid */
+ }
+ if (numsignal){
+ for (i = 0; i < number_of_signals; i++){
+ if (numsignal == sigtable[i].num){
+ converted = strdup(sigtable[i].name);
+ break;
+ }
+ }
+ } else {
+ for (i = 0; i < number_of_signals; i++){
+ if (strcmp(p, sigtable[i].name) == 0){
+ converted = malloc(sizeof(char) * 8);
+ if (converted)
+ snprintf(converted, sizeof(converted) - 1, "%d", sigtable[i].num);
+ break;
+ }
+ }
+ }
+ free(p);
+ return converted;
+}
+
void pretty_print_signals(void){
int i = 0;
while(++i <= number_of_signals){
diff --git a/proc/sig.h b/proc/sig.h
index ee850a2..0c842ab 100644
--- a/proc/sig.h
+++ b/proc/sig.h
@@ -22,6 +22,8 @@ extern const char *signal_number_to_name(int signo);
extern int print_given_signals(int argc, const char *restrict const *restrict argv, int max_line);
+extern char *strtosig(const char *restrict s);
+
extern void pretty_print_signals(void);
extern void unix_print_signals(void);
diff --git a/proc/slab.c b/proc/slab.c
index ca41bf9..66b0d4b 100644
--- a/proc/slab.c
+++ b/proc/slab.c
@@ -141,7 +141,8 @@ static int parse_slabinfo20(struct slab_info **list, struct slab_stat *stats,
if (entries++ == 0)
*list = curr;
else
- prev->next = curr;
+ if (prev)
+ prev->next = curr;
assigned = sscanf(buffer, "%" STRINGIFY(SLAB_INFO_NAME_LEN)
"s %d %d %d %d %d : tunables %*d %*d %*d : \
@@ -218,7 +219,8 @@ static int parse_slabinfo11(struct slab_info **list, struct slab_stat *stats,
if (entries++ == 0)
*list = curr;
else
- prev->next = curr;
+ if (prev)
+ prev->next = curr;
assigned = sscanf(buffer, "%" STRINGIFY(SLAB_INFO_NAME_LEN)
"s %d %d %d %d %d %d",
diff --git a/ps/Makefile.am b/ps/Makefile.am
index b3bd987..8634fe2 100644
--- a/ps/Makefile.am
+++ b/ps/Makefile.am
@@ -1,6 +1,6 @@
AM_CPPFLAGS = -include $(top_builddir)/config.h
-AM_CFLAGS = -I../proc
+AM_CFLAGS = -I../proc -I../include
AM_LDFLAGS = ../proc/libprocps.la
dist_man_MANS = ps.1
@@ -23,6 +23,4 @@ pscommand_SOURCES = \
EXTRA_DIST = \
HACKING \
- it \
- regression \
- TRANSLATION
+ regression
diff --git a/ps/TRANSLATION b/ps/TRANSLATION
deleted file mode 100644
index ff8df84..0000000
--- a/ps/TRANSLATION
+++ /dev/null
@@ -1,39 +0,0 @@
-Initially I only want to translate the --help output and man page.
-Common error messages would be next on the list. I want to avoid
-run-time overhead and bloat.
-
-Translations of the --help output should not be longer than 22 lines long.
-Feel free to leave out the less useful options to save space. (not even
-the English help text has all the options)
-
-I think these are the most important options:
-
-*** selection ***
--C by command name list
--G by real group ID list (supports names)
--U by real user ID list (supports names)
--u by effective user ID list (supports names)
--e all processes
--p by process ID list
-
-*** output ***
---no-heading No header line.
--o,o user-defined output
--j,j job control format
--l,l long format
--f full format
-s signal format
-u user-oriented format
---forest ASCII art forest (process hierarchy)
-c show true command name
-
-List of man page translators:
-
-de Wed Jan 10 19:09:15 2001 by Martin Schulze <joey@infodrom.ffis.de>
-es 19 Jan 1999 by Diego Sevilla Ruiz (dsevilla@ditec.um.es)
-fr 09/06/1997 par Christophe Blaess (ccb@club-internet.fr)
-hu Horv#th Andr#s (the '#' is 'a' w/ '/') <horvatha@rs1.szif.hu>
-it Traduzione in italiano di Giovanni Bortolozzo <borto@dei.unipd.it>
-it Revisione parziale di Daniele Giacomini <daniele@evo.it> 30/03/1999
-ja Tue Nov 14 2000 by NAKANO Takeo <nakano@apm.seikei.ac.jp>
-nl <manpages-nl@nl.linux.org>
diff --git a/ps/common.h b/ps/common.h
index d7208a7..e1b6fd5 100644
--- a/ps/common.h
+++ b/ps/common.h
@@ -12,6 +12,8 @@
#ifndef PROCPS_PS_H
#define PROCPS_PS_H
+#include "c.h"
+#include "nls.h"
#include "../proc/procps.h"
#include "../proc/escape.h"
#include "../proc/readproc.h"
@@ -25,6 +27,16 @@
/***************** GENERAL DEFINE ********************/
+/* usage output sections */
+enum {
+ USAGE_DEFAULT,
+ USAGE_ALL,
+ USAGE_SELECTION,
+ USAGE_LIST,
+ USAGE_OUTPUT,
+ USAGE_THREADS,
+ USAGE_MISC
+};
/* selection list */
#define SEL_RUID 1
@@ -326,7 +338,7 @@ extern int want_this_proc(proc_t *buf);
extern const char *select_bits_setup(void);
/* help.c */
-extern const char *help_message;
+extern void __attribute__ ((__noreturn__)) usage(FILE * out, int section);
/* global.c */
extern void self_info(void);
diff --git a/ps/display.c b/ps/display.c
index dfd4e24..2917edb 100644
--- a/ps/display.c
+++ b/ps/display.c
@@ -45,11 +45,12 @@ static void signal_handler(int signo){
if(signo==SIGPIPE) _exit(0); /* "ps | head" will cause this */
/* fprintf() is not reentrant, but we _exit() anyway */
fprintf(stderr,
- "\n\n"
- "Signal %d (%s) caught by ps (%s).\n"
- "Please send bug reports to <procps@freelists.org>\n",
+ _("\n\n"
+ "Signal %d (%s) caught by %s (%s).\n"
+ "Please send bug reports to <procps@freelists.org>\n"),
signo,
signal_number_to_name(signo),
+ program_invocation_short_name,
procps_version
);
_exit(signo+128);
@@ -154,7 +155,7 @@ static void arg_show(void){
case SEL_TTY : show_tty("TTY ", walk->n, walk->u); break;
case SEL_SESS: show_pid("SESS", walk->n, walk->u); break;
case SEL_COMM: show_cmd("COMM", walk->n, walk->u); break;
- default: printf("Garbage typecode value!\n");
+ default: printf(_("Garbage typecode value!\n"));
}
walk = walk->next;
}
@@ -253,7 +254,7 @@ static void lists_and_needs(void){
t_end->need = 0;
break;
default:
- fprintf(stderr, "please report this bug\n");
+ fprintf(stderr, _("please report this bug\n"));
// FALL THROUGH
case CF_PRINT_AS_NEEDED:
case CF_PRINT_EVERY_TIME:
@@ -332,7 +333,7 @@ static void simple_spew(void){
ptp = openproc(needs_for_format | needs_for_sort | needs_for_select | needs_for_threads);
if(!ptp) {
- fprintf(stderr, "Error: can not access /proc.\n");
+ fprintf(stderr, _("Error: can not access /proc.\n"));
exit(1);
}
switch(thread_flags & (TF_show_proc|TF_loose_tasks|TF_show_task)){
@@ -380,7 +381,7 @@ static void prep_forest_sort(void){
if(!sort_list) { /* assume start time order */
incoming = search_format_array("start_time");
- if(!incoming) { fprintf(stderr, "Could not find start_time!\n"); exit(1); }
+ if(!incoming) { fprintf(stderr, _("Could not find start_time!\n")); exit(1); }
tmp_list = malloc(sizeof(sort_node));
tmp_list->reverse = 0;
tmp_list->typecode = '?'; /* what was this for? */
@@ -391,7 +392,7 @@ static void prep_forest_sort(void){
}
/* this is required for the forest option */
incoming = search_format_array("ppid");
- if(!incoming) { fprintf(stderr, "Could not find ppid!\n"); exit(1); }
+ if(!incoming) { fprintf(stderr, _("Could not find ppid!\n")); exit(1); }
tmp_list = malloc(sizeof(sort_node));
tmp_list->reverse = 0;
tmp_list->typecode = '?'; /* what was this for? */
@@ -505,7 +506,7 @@ static void fancy_spew(void){
ptp = openproc(needs_for_format | needs_for_sort | needs_for_select | needs_for_threads);
if(!ptp) {
- fprintf(stderr, "Error: can not access /proc.\n");
+ fprintf(stderr, _("Error: can not access /proc.\n"));
exit(1);
}
@@ -529,7 +530,9 @@ static void fancy_spew(void){
/***** no comment */
int main(int argc, char *argv[]){
#if (__GNU_LIBRARY__ >= 6)
- setlocale (LC_CTYPE, "");
+ setlocale (LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
#endif
#ifdef DEBUG
@@ -562,9 +565,9 @@ int main(int argc, char *argv[]){
arg_parse(argc,argv);
/* arg_show(); */
- trace("screen is %ux%u\n",screen_cols,screen_rows);
+ trace(_("screen is %ux%u\n"),screen_cols,screen_rows);
/* printf("sizeof(proc_t) is %d.\n", sizeof(proc_t)); */
- trace("======= ps output follows =======\n");
+ trace(_("======= ps output follows =======\n"));
init_output(); /* must be between parser and output */
diff --git a/ps/global.c b/ps/global.c
index 2563f80..4a88525 100644
--- a/ps/global.c
+++ b/ps/global.c
@@ -157,7 +157,7 @@ static void set_screen_size(void){
}
if((screen_cols<9) || (screen_rows<2))
- fprintf(stderr,"Your %dx%d screen size is bogus. Expect trouble.\n",
+ fprintf(stderr,_("Your %dx%d screen size is bogus. Expect trouble.\n"),
screen_cols, screen_rows
);
}
@@ -230,7 +230,7 @@ static const char *set_personality(void){
if(!s || !*s) s="unknown"; /* "Do The Right Thing[tm]" */
if(getenv("I_WANT_A_BROKEN_PS")) s="old";
sl = strlen(s);
- if(sl > 15) return "Environment specified an unknown personality.";
+ if(sl > 15) return _("Environment specified an unknown personality.");
strncpy(buf, s, sl);
buf[sl] = '\0';
if ((saved_personality_text = strdup(buf))==NULL) {
@@ -242,7 +242,7 @@ static const char *set_personality(void){
sizeof(personality_table_struct), compare_personality_table_structs
);
- if(!found) return "Environment specified an unknown personality.";
+ if(!found) return _("Environment specified an unknown personality.");
goto *(found->jump); /* See gcc extension info. :-) */
@@ -462,39 +462,39 @@ void self_info(void){
);
display_version();
- fprintf(stderr, "Linux version %d.%d.%d\n",
+ fprintf(stderr, _("Linux version %d.%d.%d\n"),
LINUX_VERSION_MAJOR(linux_version_code),
LINUX_VERSION_MINOR(linux_version_code),
LINUX_VERSION_PATCH(linux_version_code)
);
/* __libc_print_version(); */ /* how can we get the run-time version? */
- fprintf(stderr, "Compiled with: glibc %d.%d, gcc %d.%d\n\n",
+ fprintf(stderr, _("Compiled with: glibc %d.%d, gcc %d.%d\n\n"),
__GLIBC__, __GLIBC_MINOR__, __GNUC__, __GNUC_MINOR__
);
fprintf(stderr,
- "header_gap=%d lines_to_next_header=%d\n"
- "screen_cols=%d screen_rows=%d\n"
- "\n",
+ _("header_gap=%d lines_to_next_header=%d\n"
+ "screen_cols=%d screen_rows=%d\n"
+ "\n"),
header_gap, lines_to_next_header,
screen_cols, screen_rows
);
fprintf(stderr,
- "personality=0x%08x (from \"%s\")\n"
- "EUID=%d TTY=%d,%d Hertz=%Ld page_size=%d\n",
+ _("personality=0x%08x (from \"%s\")\n"
+ "EUID=%d TTY=%d,%d Hertz=%Ld page_size=%d\n"),
personality, saved_personality_text,
cached_euid, (int)major(cached_tty), (int)minor(cached_tty), Hertz,
(int)(page_size)
);
fprintf(stderr,
- "sizeof(proc_t)=%d sizeof(long)=%d sizeof(KLONG)=%d\n",
+ _("sizeof(proc_t)=%d sizeof(long)=%d sizeof(KLONG)=%d\n"),
(int)sizeof(proc_t), (int)sizeof(long), (int)sizeof(KLONG)
);
- fprintf(stderr, "archdefs:%s\n", archdefs);
+ fprintf(stderr, _("archdefs:%s\n"), archdefs);
open_psdb(namelist_file);
- fprintf(stderr,"namelist_file=\"%s\"\n",namelist_file?namelist_file:"<no System.map file>");
+ fprintf(stderr,_("namelist_file=\"%s\"\n"),namelist_file?namelist_file:_("<no System.map file>"));
}
diff --git a/ps/help.c b/ps/help.c
index 2f39a9d..a103c79 100644
--- a/ps/help.c
+++ b/ps/help.c
@@ -9,37 +9,105 @@
* GNU Library General Public License for more details.
*/
-/*
- * The help message must not become longer, because it must fit
- * on an 80x24 screen _with_ the error message and command prompt.
- */
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
-const char *help_message =
-"********* simple selection ********* ********* selection by list *********\n"
-"-A all processes -C by command name\n"
-"-N negate selection -G by real group ID (supports names)\n"
-"-a all w/ tty except session leaders -U by real user ID (supports names)\n"
-"-d all except session leaders -g by session OR by effective group name\n"
-"-e all processes -p by process ID\n"
-"T all processes on this terminal -s processes in the sessions given\n"
-"a all w/ tty, including other users -t by tty\n"
-"g OBSOLETE -- DO NOT USE -u by effective user ID (supports names)\n"
-"r only running processes U processes for specified users\n"
-"x processes w/o controlling ttys t by tty\n"
-"*********** output format ********** *********** long options ***********\n"
-"-o,o user-defined -f full --Group --User --pid --cols --ppid\n"
-"-j,j job control s signal --group --user --sid --rows --info\n"
-"-O,O preloaded -o v virtual memory --cumulative --format --deselect\n"
-"-l,l long u user-oriented --sort --tty --forest --version\n"
-"-F extra full X registers --heading --no-heading --context\n"
-" ********* misc options *********\n"
-"-V,V show version L list format codes f ASCII art forest\n"
-"-m,m,-L,-T,H threads S children in sum -y change -l format\n"
-"-M,Z security data c true command name -c scheduling class\n"
-"-w,w wide output n numeric WCHAN,UID -H process hierarchy\n"
-;
+#include "common.h"
+void __attribute__ ((__noreturn__)) usage(FILE * out, int section)
+{
+ fputs(USAGE_HEADER, out);
+ fprintf(out,
+ _(" %s [options]\n"), program_invocation_short_name);
+ if (section == USAGE_SELECTION || section == USAGE_ALL) {
+ fputs(_("\nSimple options:\n"), out);
+ fputs(_(" -A all processes\n"), out);
+ fputs(_(" -N, --deselect negate selection\n"), out);
+ fputs(_(" -a all without tty and session leader\n"), out);
+ fputs(_(" -d all except session leader\n"), out);
+ fputs(_(" -e all processes\n"), out);
+ fputs(_(" T all processes on this terminal\n"), out);
+ fputs(_(" a all without tty, including other users\n"), out);
+ fputs(_(" g obsolete, do not use\n"), out);
+ fputs(_(" r only running processes\n"), out);
+ fputs(_(" x processes without controlling ttys\n"), out);
+ }
+ if (section == USAGE_LIST || section == USAGE_ALL) {
+ fputs(_("\nSelection by list:\n"), out);
+ fputs(_(" -C <command> command name\n"), out);
+ fputs(_(" U, -u, --user <uid> effective user id or name\n"), out);
+ fputs(_(" -U, --User <uid> real user id or name\n"), out);
+ fputs(_(" -G, --Group <gid> real group id or name\n"), out);
+ fputs(_(" -g, --group <group> session or effective group name\n"), out);
+ fputs(_(" -p, --pid <pid> process id\n"), out);
+ fputs(_(" --ppid <pid> select by parent process id\n"), out);
+ fputs(_(" -s, --sid <session> session id\n"), out);
+ fputs(_(" t, -t, --tty <tty> terminal\n"), out);
+ fputs(_("\n selection <arguments> take csv list e.g. `-u root,nobody'\n"), out);
+ }
+ if (section == USAGE_OUTPUT || section == USAGE_ALL) {
+ fputs(_("\nOutput formats:\n"), out);
+ fputs(_(" o, -o, --format <format>"), out);
+ fputs(_(" user defined format\n"), out);
+ fputs(_(" O <format> preloaded -o allowing sorting\n"), out);
+ fputs(_(" -O <format> preloaded, with default columns, allowing sorting\n"), out);
+ fputs(_(" -j jobs format\n"), out);
+ fputs(_(" j BSD job control format\n"), out);
+ fputs(_(" -l long format\n"), out);
+ fputs(_(" l BSD long format\n"), out);
+ fputs(_(" y do not show flags, show rrs in place addr (used with -l)\n"), out);
+ fputs(_(" -f full-format\n"), out);
+ fputs(_(" -F extra full\n"), out);
+ fputs(_(" s signal format\n"), out);
+ fputs(_(" v virtual memory\n"), out);
+ fputs(_(" u user-oriented format\n"), out);
+ fputs(_(" X register format\n"), out);
+ fputs(_(" Z, -M security data (for SE Linux)\n"), out);
+ fputs(_(" f, --forest ascii art process tree\n"), out);
+ fputs(_(" -H show process hierarchy\n"), out);
+ fputs(_(" --context display security context (for SE Linux)\n"), out);
+ fputs(_(" --heading repeat header lines\n"), out);
+ fputs(_(" --no-headers do not print header at all\n"), out);
+ fputs(_(" --cols <num> set screen width\n"), out);
+ fputs(_(" --rows <num> set screen height\n"), out);
+ }
+ if (section == USAGE_THREADS || section == USAGE_ALL) {
+ fputs(_("\nShow threads:\n"), out);
+ fputs(_(" H as if they where processes\n"), out);
+ fputs(_(" -L possibly with LWP and NLWP columns\n"), out);
+ fputs(_(" -T possibly with SPID column\n"), out);
+ fputs(_(" m, -m after processes\n"), out);
+ }
+ if (section == USAGE_MISC || section == USAGE_ALL) {
+ fputs(_("\nMisc options:\n"), out);
+ fputs(_(" w, -w unlimited output width\n"), out);
+ fputs(_(" L list format codes\n"), out);
+ fputs(_(" c true command name\n"), out);
+ fputs(_(" n display numeric uid and wchan\n"), out);
+ fputs(_(" -y do not show flags, show rss (only with -l)\n"), out);
+ fputs(_(" -c show scheduling class\n"), out);
+ fputs(_(" --sort <spec> specify sort order, can be a csv list\n"), out);
+ fputs(_(" S, --cumulative include some dead child process data\n"), out);
+ fputs(_(" --info print debuggin information\n"), out);
+ fputs(_(" V,-V, --version display version information and exit\n"), out);
+ fputs(_(" --help <selection|list|output|threads|misc|all>\n"), out);
+ fputs(_(" display help\n"), out);
+ }
+ if (section == USAGE_DEFAULT)
+ /* Translation Hint: do not translate arguments, that breaks
+ * string comparison. Outputting something like following
+ * might work.
+ *
+ * Zry `%s --help <selection|list|output|threads|misc|all>
+ * (zlekzio|lizt|czreen vrites|threadz|mizc|trezt)
+ */
+ fprintf(out, _("\n Try `%s --help <selection|list|output|threads|misc|all>'\n"
+ " for more information.\n"), program_invocation_short_name);
+ fprintf(out, USAGE_MAN_TAIL("ps(1)"));
+ exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
+}
/* Missing:
*
diff --git a/ps/it b/ps/it
deleted file mode 100644
index 07fd6dc..0000000
--- a/ps/it
+++ /dev/null
@@ -1,35 +0,0 @@
-From ddainese@dsi.unive.it Sun Apr 18 14:12:27 1999
-
-here is a first translation of the text:
----------------------------------------------------------------------
-const char *help_message =
-"****** seleziona i processi ******* * seleziona una lista specificando: *\n"
-"-A tutti -C il nome del comando\n"
-"-N nega la selezione -G il real group ID (supporta i nomi)\n"
-"-a con tty, tranne i session leader -U il real user ID (supporta i nomi)\n"
-"-d tutti, tranne i session leader -g il session leader OPPURE il gruppo\n"
-"-e tutti -p l'ID del processo\n"
-"T su questo terminale -s la sessione\n"
-"a con tty, di tutti gli utenti -t il tty\n"
-"g tutti, anche i leader di gruppo -u l'effective user ID (supporta i nomi)\n"
-"r in stato running U una lista di utenti\n"
-"x senza tty t il tty\n"
-"******** formato dell'output ****** ********** opzioni lunghe **********\n"
-"-o,o definito dall'utente --Group --User --pid --cols\n"
-"-j,j job s segnali --group --user --sid --rows\n"
-"-O,O -o preimpostato v memoria virtuale --cumulative --format --deselect\n"
-"-l,l lungo u utenti --sort --tty --forest --version\n"
-"-f completo X registri --heading --no-heading\n"
-" ******** opzioni varie *********\n"
-"-V,V versione L codici di formato f foresta di ASCII\n"
-"-m,m vista ad albero S figli in sum -y cambia il formato -l\n"
-"-n,N namelist file c nome reale del comando n WCHAN,UID numerici\n"
-"-w,w output ampio e mostra l'environment -H gerarchia dei processi\n"
-;
----------------------------------------------------------------------
-
-Unfortunately it isn't really understandable for a newbie, because
-there is too little space for a good translation; to make it more
-meaningful, I would need about an entire line for every option, thus
-if you really want the help text stays under 22 lines, it must
-contains only 22 options. What do you think about it?
diff --git a/ps/output.c b/ps/output.c
index f496ec9..5dbae86 100644
--- a/ps/output.c
+++ b/ps/output.c
@@ -77,7 +77,6 @@ static unsigned max_leftward = 0x12345678; /* space for LEFT stuff */
static int wide_signals; /* true if we have room */
static time_t seconds_since_1970;
-static time_t time_of_boot;
static unsigned long page_shift;
@@ -625,7 +624,7 @@ static int pr_pri_api(char *restrict const outbuf, const proc_t *restrict const
}
static int pr_nice(char *restrict const outbuf, const proc_t *restrict const pp){
- if(pp->sched!=0 && pp->sched!=-1) return snprintf(outbuf, COLWID, "-");
+ if(pp->sched!=0 && pp->sched!=(unsigned long)-1) return snprintf(outbuf, COLWID, "-");
return snprintf(outbuf, COLWID, "%ld", pp->nice);
}
@@ -662,11 +661,11 @@ static int pr_class(char *restrict const outbuf, const proc_t *restrict const pp
// default "%u:%u", type, prio
// We just print the priority, and have other keywords for type.
static int pr_rtprio(char *restrict const outbuf, const proc_t *restrict const pp){
- if(pp->sched==0 || pp->sched==-1) return snprintf(outbuf, COLWID, "-");
+ if(pp->sched==0 || pp->sched==(unsigned long)-1) return snprintf(outbuf, COLWID, "-");
return snprintf(outbuf, COLWID, "%ld", pp->rtprio);
}
static int pr_sched(char *restrict const outbuf, const proc_t *restrict const pp){
- if(pp->sched==-1) return snprintf(outbuf, COLWID, "-");
+ if(pp->sched==(unsigned long)-1) return snprintf(outbuf, COLWID, "-");
return snprintf(outbuf, COLWID, "%ld", pp->sched);
}
@@ -1848,7 +1847,7 @@ void show_one_proc(const proc_t *restrict const p, const format_node *restrict f
}
}
did_stuff = 1;
- if(unlikely(active_cols>(int)OUTBUF_SIZE)) fprintf(stderr,"Fix bigness error.\n");
+ if(unlikely(active_cols>(int)OUTBUF_SIZE)) fprintf(stderr,_("Fix bigness error.\n"));
/* print row start sequence */
for(;;){
@@ -1923,7 +1922,7 @@ void show_one_proc(const proc_t *restrict const p, const format_node *restrict f
break;
}
default:
- fprintf(stderr, "bad alignment code\n");
+ fprintf(stderr, _("bad alignment code\n"));
break;
}
/* At this point:
@@ -1996,7 +1995,7 @@ void init_output(void){
case 32768: page_shift = 15; break;
case 16384: page_shift = 14; break;
case 8192: page_shift = 13; break;
- default: fprintf(stderr, "Unknown page size! (assume 4096)\n");
+ default: fprintf(stderr, _("Unknown page size! (assume 4096)\n"));
case 4096: page_shift = 12; break;
case 2048: page_shift = 11; break;
case 1024: page_shift = 10; break;
diff --git a/ps/parser.c b/ps/parser.c
index 01233b7..552face 100644
--- a/ps/parser.c
+++ b/ps/parser.c
@@ -48,7 +48,7 @@ static int not_pure_unix = 0; /* set by BSD and GNU options */
static int force_bsd = 0; /* set when normal parsing fails */
#define exclusive(x) if((ps_argc != 2) || strcmp(ps_argv[1],x))\
- return "The " x " option is exclusive."
+ return _("The " x " option is exclusive.")
/********** utility functions **********/
@@ -74,12 +74,10 @@ static const char *get_opt_arg(void){
static const char *parse_pid(char *str, sel_union *ret){
char *endp;
unsigned long num;
- static const char pidrange[] = "Process ID out of range.";
- static const char pidsyntax[] = "Process ID list syntax error.";
num = strtoul(str, &endp, 0);
- if(*endp != '\0') return pidsyntax;
- if(num<1) return pidrange;
- if(num > 0x7fffffffUL) return pidrange;
+ if(*endp != '\0') return _("Process ID list syntax error.");
+ if(num<1) return _("Process ID out of range.");
+ if(num > 0x7fffffffUL) return _("Process ID out of range.");
ret->pid = num;
return 0;
}
@@ -88,15 +86,13 @@ static const char *parse_uid(char *str, sel_union *ret){
struct passwd *passwd_data;
char *endp;
unsigned long num;
- static const char uidrange[] = "User ID out of range.";
- static const char uidexist[] = "User name does not exist.";
num = strtoul(str, &endp, 0);
if(*endp != '\0'){ /* hmmm, try as login name */
passwd_data = getpwnam(str);
- if(!passwd_data) return uidexist;
+ if(!passwd_data) return _("User name does not exist.");
num = passwd_data->pw_uid;
}
- if(num > 0xfffffffeUL) return uidrange;
+ if(num > 0xfffffffeUL) return _("User ID out of range.");
ret->uid = num;
return 0;
}
@@ -105,15 +101,13 @@ static const char *parse_gid(char *str, sel_union *ret){
struct group *group_data;
char *endp;
unsigned long num;
- static const char gidrange[] = "Group ID out of range.";
- static const char gidexist[] = "Group name does not exist.";
num = strtoul(str, &endp, 0);
if(*endp != '\0'){ /* hmmm, try as login name */
group_data = getgrnam(str);
- if(!group_data) return gidexist;
+ if(!group_data) return _("Group name does not exist.");
num = group_data->gr_gid;
}
- if(num > 0xfffffffeUL) return gidrange;
+ if(num > 0xfffffffeUL) return _("Group ID out of range.");
ret->gid = num;
return 0;
}
@@ -126,12 +120,10 @@ static const char *parse_cmd(char *str, sel_union *ret){
static const char *parse_tty(char *str, sel_union *ret){
struct stat sbuf;
- static const char missing[] = "TTY could not be found.";
- static const char not_tty[] = "List member was not a TTY.";
char path[4096];
if(str[0]=='/'){
if(stat(str, &sbuf) >= 0) goto found_it;
- return missing;
+ return _("TTY could not be found.");;
}
#define lookup(p) \
snprintf(path,4096,p,str); \
@@ -155,13 +147,30 @@ static const char *parse_tty(char *str, sel_union *ret){
return 0;
}
#undef lookup
- return missing;
+ return _("TTY could not be found.");;
found_it:
- if(!S_ISCHR(sbuf.st_mode)) return not_tty;
+ if(!S_ISCHR(sbuf.st_mode)) return _("List member was not a TTY.");
ret->tty = sbuf.st_rdev;
return 0;
}
+static int parse_usage_section(const char *opt)
+{
+ if (!strcmp(opt, "s") || !strcmp(opt, "selection"))
+ return USAGE_SELECTION;
+ if (!strcmp(opt, "l") || !strcmp(opt, "list"))
+ return USAGE_LIST;
+ if (!strcmp(opt, "o") || !strcmp(opt, "output"))
+ return USAGE_OUTPUT;
+ if (!strcmp(opt, "t") || !strcmp(opt, "threads"))
+ return USAGE_THREADS;
+ if (!strcmp(opt, "m") || !strcmp(opt, "misc"))
+ return USAGE_MISC;
+ if (!strcmp(opt, "a") || !strcmp(opt, "all"))
+ return USAGE_ALL;
+ return USAGE_DEFAULT;
+}
+
/*
* Used to parse lists in a generic way. (function pointers)
*/
@@ -182,7 +191,7 @@ static const char *parse_list(const char *arg, const char *(*parse_fn)(char *, s
need_item = 1; /* true */
items = 0;
walk = buf;
- err = "Improper list.";
+ err = _("Improper list.");
do{
switch(*walk){
case ' ': case ',': case '\t': case '\0':
@@ -236,40 +245,40 @@ static const char *parse_sysv_option(void){
switch(*flagptr){
case 'A':
- trace("-A selects all processes.\n");
+ trace(_("-A selects all processes.\n"));
all_processes = 1;
break;
case 'C': /* end */
- trace("-C select by process name.\n"); /* Why only HP/UX and us? */
+ trace(_("-C select by process name.\n")); /* Why only HP/UX and us? */
arg=get_opt_arg();
- if(!arg) return "List of command names must follow -C.";
+ if(!arg) return _("List of command names must follow -C.");
err=parse_list(arg, parse_cmd);
if(err) return err;
selection_list->typecode = SEL_COMM;
return NULL; /* can't have any more options */
case 'F': /* DYNIX/ptx -f plus sz,rss,psr=ENG between c and stime */
- trace("-F does fuller listing\n");
+ trace(_("-F does fuller listing\n"));
format_modifiers |= FM_F;
format_flags |= FF_Uf;
unix_f_option = 1; /* does this matter? */
break;
case 'G': /* end */
- trace("-G select by RGID (supports names)\n");
+ trace(_("-G select by RGID (supports names)\n"));
arg=get_opt_arg();
- if(!arg) return "List of real groups must follow -G.";
+ if(!arg) return _("List of real groups must follow -G.");
err=parse_list(arg, parse_gid);
if(err) return err;
selection_list->typecode = SEL_RGID;
return NULL; /* can't have any more options */
case 'H': /* another nice HP/UX feature */
- trace("-H Process hierarchy (like ASCII art forest option)\n");
+ trace(_("-H Process hierarchy (like ASCII art forest option)\n"));
forest_type = 'u';
break;
#if 0
case 'J': // specify list of job IDs in hex (IRIX) -- like HP "-R" maybe?
- trace("-J select by job ID\n"); // want a JID ("jid") for "-j" too
+ trace(_("-J select by job ID\n")); // want a JID ("jid") for "-j" too
arg=get_opt_arg();
- if(!arg) return "List of jobs must follow -J.";
+ if(!arg) return _("List of jobs must follow -J.");
err=parse_list(arg, parse_jid);
if(err) return err;
selection_list->typecode = SEL_JID;
@@ -282,33 +291,33 @@ static const char *parse_sysv_option(void){
* Zombies are the only exception, with NLWP==0 and 1 output line.
* SCO UnixWare uses -L too.
*/
- trace("-L Print LWP (thread) info.\n");
+ trace(_("-L Print LWP (thread) info.\n"));
thread_flags |= TF_U_L;
// format_modifiers |= FM_L;
break;
case 'M': // typically the SE Linux context
- trace("-M Print security label for Mandatory Access Control.\n");
+ trace(_("-M Print security label for Mandatory Access Control.\n"));
format_modifiers |= FM_M;
break;
case 'N':
- trace("-N negates.\n");
+ trace(_("-N negates.\n"));
negate_selection = 1;
break;
case 'O': /* end */
- trace("-O is preloaded -o.\n");
+ trace(_("-O is preloaded -o.\n"));
arg=get_opt_arg();
- if(!arg) return "Format or sort specification must follow -O.";
+ if(!arg) return _("Format or sort specification must follow -O.");
defer_sf_option(arg, SF_U_O);
return NULL; /* can't have any more options */
case 'P': /* SunOS 5 "psr" or unknown HP/UX feature */
- trace("-P adds columns of PRM info (HP-UX), PSR (SunOS), or capabilities (IRIX)\n");
+ trace(_("-P adds columns of PRM info (HP-UX), PSR (SunOS), or capabilities (IRIX)\n"));
format_modifiers |= FM_P;
break;
#if 0
case 'R': // unknown HP/UX feature, like IRIX "-J" maybe?
- trace("-R select by PRM group\n");
+ trace(_("-R select by PRM group\n"));
arg=get_opt_arg();
- if(!arg) return "List of PRM groups must follow -R.";
+ if(!arg) return _("List of PRM groups must follow -R.");
err=parse_list(arg, parse_prm);
if(err) return err;
selection_list->typecode = SEL_PRM;
@@ -320,55 +329,55 @@ static const char *parse_sysv_option(void){
* Testing (w/ normal processes) shows 1 line/process, not 2.
* Also, testing shows PID==SPID for all normal processes.
*/
- trace("-T adds strange SPID column (old sproc() threads?)\n");
+ trace(_("-T adds strange SPID column (old sproc() threads?)\n"));
thread_flags |= TF_U_T;
// format_modifiers |= FM_T;
break;
case 'U': /* end */
- trace("-U select by RUID (supports names).\n");
+ trace(_("-U select by RUID (supports names).\n"));
arg=get_opt_arg();
- if(!arg) return "List of real groups must follow -U.";
+ if(!arg) return _("List of real groups must follow -U.");
err=parse_list(arg, parse_uid);
if(err) return err;
selection_list->typecode = SEL_RUID;
return NULL; /* can't have any more options */
case 'V': /* single */
- trace("-V prints version.\n");
+ trace(_("-V prints version.\n"));
exclusive("-V");
display_version();
exit(0);
// This must be verified against SVR4-MP. (UnixWare or Powermax)
// Leave it undocumented until that problem is solved.
case 'Z': /* full Mandatory Access Control level info */
- trace("-Z shows full MAC info\n");
+ trace(_("-Z shows full MAC info\n"));
format_modifiers |= FM_M;
break;
case 'a':
- trace("-a select all with a tty, but omit session leaders.\n");
+ trace(_("-a select all with a tty, but omit session leaders.\n"));
simple_select |= SS_U_a;
break;
case 'c':
/* HP-UX and SunOS 5 scheduling info modifier */
- trace("-c changes scheduling info.\n");
+ trace(_("-c changes scheduling info.\n"));
format_modifiers |= FM_c;
break;
case 'd':
- trace("-d select all, but omit session leaders.\n");
+ trace(_("-d select all, but omit session leaders.\n"));
simple_select |= SS_U_d;
break;
case 'e':
- trace("-e selects all processes.\n");
+ trace(_("-e selects all processes.\n"));
all_processes = 1;
break;
case 'f':
- trace("-f does full listing\n");
+ trace(_("-f does full listing\n"));
format_flags |= FF_Uf;
unix_f_option = 1; /* does this matter? */
break;
case 'g': /* end */
- trace("-g selects by session leader OR by group name\n");
+ trace(_("-g selects by session leader OR by group name\n"));
arg=get_opt_arg();
- if(!arg) return "List of session leaders OR effective group names must follow -g.";
+ if(!arg) return _("List of session leaders OR effective group names must follow -g.");
err=parse_list(arg, parse_pid);
if(!err){
selection_list->typecode = SEL_SESS;
@@ -379,26 +388,26 @@ static const char *parse_sysv_option(void){
selection_list->typecode = SEL_EGID;
return NULL; /* can't have any more options */
}
- return "List of session leaders OR effective group IDs was invalid.";
+ return _("List of session leaders OR effective group IDs was invalid.");
case 'j':
- trace("-j jobs format.\n");
+ trace(_("-j jobs format.\n"));
/* old Debian used RD_j and Digital uses JFMT */
if(sysv_j_format) format_flags |= FF_Uj;
else format_modifiers |= FM_j;
break;
case 'l':
- trace("-l long format.\n");
+ trace(_("-l long format.\n"));
format_flags |= FF_Ul;
break;
case 'm':
- trace("-m shows threads.\n");
+ trace(_("-m shows threads.\n"));
/* note that AIX shows 2 lines for a normal process */
thread_flags |= TF_U_m;
break;
case 'n': /* end */
- trace("-n sets namelist file.\n");
+ trace(_("-n sets namelist file.\n"));
arg=get_opt_arg();
- if(!arg) return "Alternate System.map file must follow -n.";
+ if(!arg) return _("Alternate System.map file must follow -n.");
namelist_file = arg;
return NULL; /* can't have any more options */
case 'o': /* end */
@@ -407,96 +416,96 @@ static const char *parse_sysv_option(void){
/* The result must be 2 columns: "PID NICE,tty=TERMINAL,comm" */
/* Yes, the second column has the name "NICE,tty=TERMINAL,comm" */
/* This parser looks for any excuse to ignore that braindamage. */
- trace("-o user-defined format.\n");
+ trace(_("-o user-defined format.\n"));
arg=get_opt_arg();
- if(!arg) return "Format specification must follow -o.";
+ if(!arg) return _("Format specification must follow -o.");
not_pure_unix |= defer_sf_option(arg, SF_U_o);
return NULL; /* can't have any more options */
case 'p': /* end */
- trace("-p select by PID.\n");
+ trace(_("-p select by PID.\n"));
arg=get_opt_arg();
- if(!arg) return "List of process IDs must follow -p.";
+ if(!arg) return _("List of process IDs must follow -p.");
err=parse_list(arg, parse_pid);
if(err) return err;
selection_list->typecode = SEL_PID;
return NULL; /* can't have any more options */
#if 0
case 'r':
- trace("-r some Digital Unix thing about warnings...\n");
- trace(" or SCO's option to chroot() for new /proc and /dev.\n");
- return "The -r option is reserved.";
+ trace(_("-r some Digital Unix thing about warnings...\n"));
+ trace(_(" or SCO's option to chroot() for new /proc and /dev.\n"));
+ return _("The -r option is reserved.");
break;
#endif
case 's': /* end */
- trace("-s Select processes belonging to the sessions given.\n");
+ trace(_("-s Select processes belonging to the sessions given.\n"));
arg=get_opt_arg();
- if(!arg) return "List of session IDs must follow -s.";
+ if(!arg) return _("List of session IDs must follow -s.");
err=parse_list(arg, parse_pid);
if(err) return err;
selection_list->typecode = SEL_SESS;
return NULL; /* can't have any more options */
case 't': /* end */
- trace("-t select by tty.\n");
+ trace(_("-t select by tty.\n"));
arg=get_opt_arg();
- if(!arg) return "List of terminals (pty, tty...) must follow -t.";
+ if(!arg) return _("List of terminals (pty, tty...) must follow -t.");
err=parse_list(arg, parse_tty);
if(err) return err;
selection_list->typecode = SEL_TTY;
return NULL; /* can't have any more options */
case 'u': /* end */
- trace("-u select by user ID (the EUID?) (supports names).\n");
+ trace(_("-u select by user ID (the EUID?) (supports names).\n"));
arg=get_opt_arg();
- if(!arg) return "List of users must follow -u.";
+ if(!arg) return _("List of users must follow -u.");
err=parse_list(arg, parse_uid);
if(err) return err;
selection_list->typecode = SEL_EUID;
return NULL; /* can't have any more options */
case 'w':
- trace("-w wide output.\n");
+ trace(_("-w wide output.\n"));
w_count++;
break;
case 'x': /* behind personality until "ps -ax" habit is uncommon */
if(personality & PER_SVR4_x){
// Same as -y, but for System V Release 4 MP
- trace("-x works like Sun Solaris & SCO Unixware -y option\n");
+ trace(_("-x works like Sun Solaris & SCO Unixware -y option\n"));
format_modifiers |= FM_y;
break;
}
if(personality & PER_HPUX_x){
- trace("-x extends the command line\n");
+ trace(_("-x extends the command line\n"));
w_count += 2;
unix_f_option = 1;
break;
}
- return "Must set personality to get -x option.";
+ return _("Must set personality to get -x option.");
case 'y': /* Sun's -l hack (also: Irix "lnode" resource control info) */
- trace("-y Print lnone info in UID/USER column or do Sun -l hack.\n");
+ trace(_("-y Print lnone info in UID/USER column or do Sun -l hack.\n"));
format_modifiers |= FM_y;
break;
#if 0
// This must be verified against SVR4-MP (UnixWare or Powermax)
case 'z': /* alias of Mandatory Access Control level info */
- trace("-z shows aliased MAC info\n");
+ trace(_("-z shows aliased MAC info\n"));
format_modifiers |= FM_M;
break;
// Solaris 10 does this
case 'z': /* select by zone */
- trace("-z secects by zone\n");
+ trace(_("-z secects by zone\n"));
arg=get_opt_arg();
- if(!arg) return "List of zones (contexts, labels, whatever?) must follow -z.";
+ if(!arg) return _("List of zones (contexts, labels, whatever?) must follow -z.");
err=parse_list(arg, parse_zone);
if(err) return err;
selection_list->typecode = SEL_ZONE;
return NULL; /* can't have any more options */
#endif
case '-':
- return "Embedded '-' among SysV options makes no sense.";
+ return _("Embedded '-' among SysV options makes no sense.");
break;
case '\0':
- return "Please report the \"SysV \\0 can't happen\" bug.";
+ return _("Please report the \"SysV \\0 can't happen\" bug.");
break;
default:
- return "Unsupported SysV option.";
+ return _("Unsupported SysV option.");
} /* switch */
} /* while */
return NULL;
@@ -509,20 +518,20 @@ static const char *parse_bsd_option(void){
flagptr = ps_argv[thisarg]; /* assume we _have_ a '-' */
if(flagptr[0]=='-'){
- if(!force_bsd) return "Can't happen! Problem #1.";
+ if(!force_bsd) return _("Can't happen! Problem #1.");
}else{
flagptr--; /* off beginning, will increment before use */
if(personality & PER_FORCE_BSD){
- if(!force_bsd) return "Can't happen! Problem #2.";
+ if(!force_bsd) return _("Can't happen! Problem #2.");
}else{
- if(force_bsd) return "2nd chance parse failed, not BSD or SysV.";
+ if(force_bsd) return _("2nd chance parse failed, not BSD or SysV.");
}
}
while(*++flagptr){
switch(*flagptr){
case '0' ... '9': /* end */
- trace("0..9 Old BSD-style select by process ID\n");
+ trace(_("0..9 Old BSD-style select by process ID\n"));
arg=flagptr;
err=parse_list(arg, parse_pid);
if(err) return err;
@@ -531,48 +540,48 @@ static const char *parse_bsd_option(void){
#if 0
case 'A':
/* maybe this just does a larger malloc() ? */
- trace("A Increases the argument space (Digital Unix)\n");
- return "Option A is reserved.";
+ trace(_("A Increases the argument space (Digital Unix)\n"));
+ return _("Option A is reserved.");
break;
case 'C':
/* should divide result by 1-(e**(foo*log(bar))) */
- trace("C Use raw CPU time for %%CPU instead of decaying ave\n");
- return "Option C is reserved.";
+ trace(_("C Use raw CPU time for %%CPU instead of decaying ave\n"));
+ return _("Option C is reserved.");
break;
#endif
case 'H': // The FreeBSD way (NetBSD:s OpenBSD:k FreeBSD:H -- NIH???)
- trace("H Print LWP (thread) info.\n"); // was: Use /vmcore as c-dumpfile\n");
+ trace(_("H Print LWP (thread) info.\n")); // was: Use /vmcore as c-dumpfile\n");
thread_flags |= TF_B_H;
//format_modifiers |= FM_L; // FIXME: determine if we need something like this
break;
case 'L': /* single */
- trace("L List all format specifiers\n");
+ trace(_("L List all format specifiers\n"));
exclusive("L");
print_format_specifiers();
exit(0);
case 'M': // undocumented for now: these are proliferating!
- trace("M MacOS X thread display, like AIX/Tru64\n");
+ trace(_("M MacOS X thread display, like AIX/Tru64\n"));
thread_flags |= TF_B_m;
break;
case 'N': /* end */
- trace("N Specify namelist file\n");
+ trace(_("N Specify namelist file\n"));
arg=get_opt_arg();
- if(!arg) return "Alternate System.map file must follow N.";
+ if(!arg) return _("Alternate System.map file must follow N.");
namelist_file = arg;
return NULL; /* can't have any more options */
case 'O': /* end */
- trace("O Like o + defaults, add new columns after PID. Also sort.\n");
+ trace(_("O Like o + defaults, add new columns after PID. Also sort.\n"));
arg=get_opt_arg();
- if(!arg) return "Format or sort specification must follow O.";
+ if(!arg) return _("Format or sort specification must follow O.");
defer_sf_option(arg, SF_B_O);
return NULL; /* can't have any more options */
break;
case 'S':
- trace("S include dead kids in sum\n");
+ trace(_("S include dead kids in sum\n"));
include_dead_children = 1;
break;
case 'T':
- trace("T Select all processes on this terminal\n");
+ trace(_("T Select all processes on this terminal\n"));
/* put our tty on a tiny list */
{
selection_node *node;
@@ -586,62 +595,62 @@ static const char *parse_bsd_option(void){
}
break;
case 'U': /* end */
- trace("U Select processes for specified users.\n");
+ trace(_("U Select processes for specified users.\n"));
arg=get_opt_arg();
- if(!arg) return "List of users must follow U.";
+ if(!arg) return _("List of users must follow U.");
err=parse_list(arg, parse_uid);
if(err) return err;
selection_list->typecode = SEL_EUID;
return NULL; /* can't have any more options */
case 'V': /* single */
- trace("V show version info\n");
+ trace(_("V show version info\n"));
exclusive("V");
display_version();
exit(0);
case 'W':
- trace("W N/A get swap info from ... not /dev/drum.\n");
- return "Obsolete W option not supported. (You have a /dev/drum?)";
+ trace(_("W N/A get swap info from ... not /dev/drum.\n"));
+ return _("Obsolete W option not supported. (You have a /dev/drum?)");
break;
case 'X':
- trace("X Old Linux i386 register format\n");
+ trace(_("X Old Linux i386 register format\n"));
format_flags |= FF_LX;
break;
case 'Z': /* FreeBSD does MAC like SGI's Irix does it */
- trace("Z Print security label for Mandatory Access Control.\n");
+ trace(_("Z Print security label for Mandatory Access Control.\n"));
format_modifiers |= FM_M;
break;
case 'a':
- trace("a Select all w/tty, including other users\n");
+ trace(_("a Select all w/tty, including other users\n"));
simple_select |= SS_B_a;
break;
case 'c':
- trace("c true command name\n");
+ trace(_("c true command name\n"));
bsd_c_option = 1;
break;
// case 'd':
-// trace("d FreeBSD-style tree\n");
+// trace(_("d FreeBSD-style tree\n"));
// forest_type = 'f';
// break;
case 'e':
- trace("e environment\n");
+ trace(_("e environment\n"));
bsd_e_option = 1;
break;
case 'f':
- trace("f ASCII art forest\n");
+ trace(_("f ASCII art forest\n"));
forest_type = 'b';
break;
case 'g':
- trace("g _all_, even group leaders!.\n");
+ trace(_("g _all_, even group leaders!.\n"));
simple_select |= SS_B_g;
break;
case 'h':
- trace("h Repeat header... yow.\n");
- if(header_type) return "Only one heading option may be specified.";
+ trace(_("h Repeat header... yow.\n"));
+ if(header_type) return _("Only one heading option may be specified.");
if(personality & PER_BSD_h) header_type = HEAD_MULTI;
else header_type = HEAD_NONE;
break;
case 'j':
- trace("j job control format\n");
+ trace(_("j job control format\n"));
format_flags |= FF_Bj;
break;
case 'k':
@@ -649,17 +658,17 @@ static const char *parse_bsd_option(void){
// trace("k Print LWP (thread) info.\n"); // was: Use /vmcore as c-dumpfile\n");
// NetBSD, and soon (?) FreeBSD: sort-by-keyword
- trace("k Specify sorting keywords.\n");
+ trace(_("k Specify sorting keywords.\n"));
arg=get_opt_arg();
- if(!arg) return "Long sort specification must follow 'k'.";
+ if(!arg) return _("Long sort specification must follow 'k'.");
defer_sf_option(arg, SF_G_sort);
return NULL; /* can't have any more options */
case 'l':
- trace("l Display long format\n");
+ trace(_("l Display long format\n"));
format_flags |= FF_Bl;
break;
case 'm':
- trace("m all threads, sort on mem use, show mem info\n");
+ trace(_("m all threads, sort on mem use, show mem info\n"));
if(personality & PER_OLD_m){
format_flags |= FF_Lm;
break;
@@ -671,35 +680,35 @@ static const char *parse_bsd_option(void){
thread_flags |= TF_B_m;
break;
case 'n':
- trace("n Numeric output for WCHAN, and USER replaced by UID\n");
+ trace(_("n Numeric output for WCHAN, and USER replaced by UID\n"));
wchan_is_number = 1;
user_is_number = 1;
/* TODO add tty_is_number too? */
break;
case 'o': /* end */
- trace("o Specify user-defined format\n");
+ trace(_("o Specify user-defined format\n"));
arg=get_opt_arg();
- if(!arg) return "Format specification must follow o.";
+ if(!arg) return _("Format specification must follow o.");
defer_sf_option(arg, SF_B_o);
return NULL; /* can't have any more options */
case 'p': /* end */
- trace("p Select by process ID\n");
+ trace(_("p Select by process ID\n"));
arg=get_opt_arg();
- if(!arg) return "List of process IDs must follow p.";
+ if(!arg) return _("List of process IDs must follow p.");
err=parse_list(arg, parse_pid);
if(err) return err;
selection_list->typecode = SEL_PID;
return NULL; /* can't have any more options */
case 'r':
- trace("r Select running processes\n");
+ trace(_("r Select running processes\n"));
running_only = 1;
break;
case 's':
- trace("s Display signal format\n");
+ trace(_("s Display signal format\n"));
format_flags |= FF_Bs;
break;
case 't': /* end */
- trace("t Select by tty.\n");
+ trace(_("t Select by tty.\n"));
/* List of terminals (tty, pty...) _should_ follow t. */
arg=get_opt_arg();
if(!arg){
@@ -719,29 +728,29 @@ static const char *parse_bsd_option(void){
selection_list->typecode = SEL_TTY;
return NULL; /* can't have any more options */
case 'u':
- trace("u Display user-oriented\n");
+ trace(_("u Display user-oriented\n"));
format_flags |= FF_Bu;
break;
case 'v':
- trace("v Display virtual memory\n");
+ trace(_("v Display virtual memory\n"));
format_flags |= FF_Bv;
break;
case 'w':
- trace("w wide output\n");
+ trace(_("w wide output\n"));
w_count++;
break;
case 'x':
- trace("x Select processes without controlling ttys\n");
+ trace(_("x Select processes without controlling ttys\n"));
simple_select |= SS_B_x;
break;
case '-':
- return "Embedded '-' among BSD options makes no sense.";
+ return _("Embedded '-' among BSD options makes no sense.");
break;
case '\0':
- return "Please report the \"BSD \\0 can't happen\" bug.";
+ return _("Please report the \"BSD \\0 can't happen\" bug.");
break;
default:
- return "Unsupported option (BSD syntax)";
+ return _("Unsupported option (BSD syntax)");
} /* switch */
} /* while */
return NULL;
@@ -786,6 +795,7 @@ static const char *parse_gnu_option(void){
char buf[16];
gnu_table_struct findme = { buf, NULL};
gnu_table_struct *found;
+ int usage_section;
static const gnu_table_struct gnu_table[] = {
{"Group", &&case_Group}, /* rgid */
{"User", &&case_User}, /* ruid */
@@ -826,7 +836,7 @@ static const char *parse_gnu_option(void){
s = ps_argv[thisarg]+2;
sl = strcspn(s,":=");
- if(sl > 15) return "Unknown gnu long option.";
+ if(sl > 15) return _("Unknown gnu long option.");
strncpy(buf, s, sl);
buf[sl] = '\0';
flagptr = s+sl;
@@ -835,14 +845,14 @@ static const char *parse_gnu_option(void){
sizeof(gnu_table_struct), compare_gnu_table_structs
);
- if(!found) return "Unknown gnu long option.";
+ if(!found) return _("Unknown gnu long option.");
goto *(found->jump); /* See gcc extension info. :-) */
case_Group:
trace("--Group\n");
arg = grab_gnu_arg();
- if(!arg) return "List of real groups must follow --Group.";
+ if(!arg) return _("List of real groups must follow --Group.");
err=parse_list(arg, parse_gid);
if(err) return err;
selection_list->typecode = SEL_RGID;
@@ -850,7 +860,7 @@ static const char *parse_gnu_option(void){
case_User:
trace("--User\n");
arg = grab_gnu_arg();
- if(!arg) return "List of real users must follow --User.";
+ if(!arg) return _("List of real users must follow --User.");
err=parse_list(arg, parse_uid);
if(err) return err;
selection_list->typecode = SEL_RUID;
@@ -869,15 +879,15 @@ static const char *parse_gnu_option(void){
return NULL;
}
}
- return "Number of columns must follow --cols, --width, or --columns.";
+ return _("Number of columns must follow --cols, --width, or --columns.");
case_cumulative:
trace("--cumulative\n");
- if(s[sl]) return "Option --cumulative does not take an argument.";
+ if(s[sl]) return _("Option --cumulative does not take an argument.");
include_dead_children = 1;
return NULL;
case_deselect:
trace("--deselect\n");
- if(s[sl]) return "Option --deselect does not take an argument.";
+ if(s[sl]) return _("Option --deselect does not take an argument.");
negate_selection = 1;
return NULL;
case_no_header:
@@ -889,8 +899,8 @@ static const char *parse_gnu_option(void){
case_noheading:
case_noheadings:
trace("--noheaders\n");
- if(s[sl]) return "Option --no-heading does not take an argument.";
- if(header_type) return "Only one heading option may be specified.";
+ if(s[sl]) return _("Option --no-heading does not take an argument.");
+ if(header_type) return _("Only one heading option may be specified.");
header_type = HEAD_NONE;
return NULL;
case_header:
@@ -898,35 +908,37 @@ static const char *parse_gnu_option(void){
case_heading:
case_headings:
trace("--headers\n");
- if(s[sl]) return "Option --heading does not take an argument.";
- if(header_type) return "Only one heading option may be specified.";
+ if(s[sl]) return _("Option --heading does not take an argument.");
+ if(header_type) return _("Only one heading option may be specified.");
header_type = HEAD_MULTI;
return NULL;
case_forest:
trace("--forest\n");
- if(s[sl]) return "Option --forest does not take an argument.";
+ if(s[sl]) return _("Option --forest does not take an argument.");
forest_type = 'g';
return NULL;
case_format:
trace("--format\n");
arg=grab_gnu_arg();
- if(!arg) return "Format specification must follow --format.";
+ if(!arg) return _("Format specification must follow --format.");
defer_sf_option(arg, SF_G_format);
return NULL;
case_group:
trace("--group\n");
arg = grab_gnu_arg();
- if(!arg) return "List of effective groups must follow --group.";
+ if(!arg) return _("List of effective groups must follow --group.");
err=parse_list(arg, parse_gid);
if(err) return err;
selection_list->typecode = SEL_EGID;
return NULL;
case_help:
trace("--help\n");
- exclusive("--help");
- fwrite(help_message,1,strlen(help_message),stdout);
- exit(0);
- return NULL;
+ arg = grab_gnu_arg();
+ if(!arg)
+ usage_section = USAGE_DEFAULT;
+ else
+ usage_section = parse_usage_section(arg);
+ usage(stdout, usage_section);
case_info:
trace("--info\n");
exclusive("--info");
@@ -936,7 +948,7 @@ static const char *parse_gnu_option(void){
case_pid:
trace("--pid\n");
arg = grab_gnu_arg();
- if(!arg) return "List of process IDs must follow --pid.";
+ if(!arg) return _("List of process IDs must follow --pid.");
err=parse_list(arg, parse_pid);
if(err) return err;
selection_list->typecode = SEL_PID;
@@ -944,7 +956,7 @@ static const char *parse_gnu_option(void){
case_ppid:
trace("--ppid\n");
arg = grab_gnu_arg();
- if(!arg) return "List of process IDs must follow --ppid.";
+ if(!arg) return _("List of process IDs must follow --ppid.");
err=parse_list(arg, parse_pid);
if(err) return err;
selection_list->typecode = SEL_PPID;
@@ -962,11 +974,11 @@ static const char *parse_gnu_option(void){
return NULL;
}
}
- return "Number of rows must follow --rows or --lines.";
+ return _("Number of rows must follow --rows or --lines.");
case_sid:
trace("--sid\n");
arg = grab_gnu_arg();
- if(!arg) return "Some sid thing(s) must follow --sid.";
+ if(!arg) return _("Some sid thing(s) must follow --sid.");
err=parse_list(arg, parse_pid);
if(err) return err;
selection_list->typecode = SEL_SESS;
@@ -974,13 +986,13 @@ static const char *parse_gnu_option(void){
case_sort:
trace("--sort\n");
arg=grab_gnu_arg();
- if(!arg) return "Long sort specification must follow --sort.";
+ if(!arg) return _("Long sort specification must follow --sort.");
defer_sf_option(arg, SF_G_sort);
return NULL;
case_tty:
trace("--tty\n");
arg = grab_gnu_arg();
- if(!arg) return "List of ttys must follow --tty.";
+ if(!arg) return _("List of ttys must follow --tty.");
err=parse_list(arg, parse_tty);
if(err) return err;
selection_list->typecode = SEL_TTY;
@@ -988,7 +1000,7 @@ static const char *parse_gnu_option(void){
case_user:
trace("--user\n");
arg = grab_gnu_arg();
- if(!arg) return "List of effective users must follow --user.";
+ if(!arg) return _("List of effective users must follow --user.");
err=parse_list(arg, parse_uid);
if(err) return err;
selection_list->typecode = SEL_EUID;
@@ -1092,9 +1104,9 @@ static const char *parse_all_options(void){
const char *err = NULL;
int at;
while(++thisarg < ps_argc){
- trace("parse_all_options calling arg_type for \"%s\"\n", ps_argv[thisarg]);
+ trace(_("parse_all_options calling arg_type for \"%s\"\n"), ps_argv[thisarg]);
at = arg_type(ps_argv[thisarg]);
- trace("ps_argv[thisarg] is %s\n", ps_argv[thisarg]);
+ trace(_("ps_argv[thisarg] is %s\n"), ps_argv[thisarg]);
if(at != ARG_SYSV) not_pure_unix = 1;
switch(at){
case ARG_GNU:
@@ -1105,7 +1117,7 @@ static const char *parse_all_options(void){
err = parse_sysv_option();
break;
case ARG_BSD:
- if(force_bsd && !(personality & PER_FORCE_BSD)) return "way bad";
+ if(force_bsd && !(personality & PER_FORCE_BSD)) return _("way bad");
}
prefer_bsd_defaults = 1;
err = parse_bsd_option();
@@ -1118,12 +1130,12 @@ static const char *parse_all_options(void){
break;
case ARG_END:
case ARG_FAIL:
- trace(" FAIL/END on [%s]\n",ps_argv[thisarg]);
- return "Garbage option.";
+ trace(_(" FAIL/END on [%s]\n"),ps_argv[thisarg]);
+ return _("Garbage option.");
break;
default:
printf(" ? %s\n",ps_argv[thisarg]);
- return "Something broke.";
+ return _("Something broke.");
} /* switch */
if(err) return err;
} /* while */
@@ -1143,16 +1155,16 @@ static const char *thread_option_check(void){
}
if(forest_type){
- return "Thread display conflicts with forest display.";
+ return _("Thread display conflicts with forest display.");
}
//thread_flags |= TF_no_forest;
if((thread_flags&TF_B_H) && (thread_flags&(TF_B_m|TF_U_m)))
- return "Thread flags conflict; can't use H with m or -m.";
+ return _("Thread flags conflict; can't use H with m or -m.");
if((thread_flags&TF_B_m) && (thread_flags&TF_U_m))
- return "Thread flags conflict; can't use both m and -m.";
+ return _("Thread flags conflict; can't use both m and -m.");
if((thread_flags&TF_U_L) && (thread_flags&TF_U_T))
- return "Thread flags conflict; can't use both -L and -T.";
+ return _("Thread flags conflict; can't use both -L and -T.");
if(thread_flags&TF_B_H) thread_flags |= (TF_show_proc|TF_loose_tasks);
if(thread_flags&(TF_B_m|TF_U_m)) thread_flags |= (TF_show_proc|TF_show_task|TF_show_both);
@@ -1161,7 +1173,7 @@ static const char *thread_option_check(void){
if(thread_flags&(TF_B_m|TF_U_m|TF_B_H)){
// Got a thread style, so format modification is a requirement?
// Maybe -T/-L has H thread style though. (sorting interaction?)
- //return "Huh? Tell procps@freelists.org what you expected.";
+ //return _("Huh? Tell procps@freelists.org what you expected.");
thread_flags |= TF_must_use;
}else{
// using -L/-T thread style, so format from elsewhere is OK
@@ -1195,7 +1207,7 @@ int arg_parse(int argc, char *argv[]){
return 0;
try_bsd:
- trace("--------- now try BSD ------\n");
+ trace(_("--------- now try BSD ------\n"));
reset_global();
reset_parser();
@@ -1242,7 +1254,7 @@ try_bsd:
// changing the actual behavior of ps in any way. I know of no
// other 'ps' that produces this message.
if(!(personality & PER_FORCE_BSD))
- fprintf(stderr, "Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html\n");
+ fprintf(stderr, _("Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html\n"));
#endif
// Remember: contact procps@freelists.org
// if you should feel tempted. Be damn sure you understand all
@@ -1254,9 +1266,7 @@ try_bsd:
total_failure:
reset_parser();
- if(personality & PER_FORCE_BSD) fprintf(stderr, "ERROR: %s\n", err2);
- else fprintf(stderr, "ERROR: %s\n", err);
- fwrite(help_message,1,strlen(help_message),stderr);
- exit(1);
- /* return 1; */ /* useless */
+ if(personality & PER_FORCE_BSD) fprintf(stderr, _("ERROR: %s\n"), err2);
+ else fprintf(stderr, _("ERROR: %s\n"), err);
+ usage(stderr, USAGE_DEFAULT);
}
diff --git a/ps/ps.1 b/ps/ps.1
index b84447b..a2fa18c 100644
--- a/ps/ps.1
+++ b/ps/ps.1
@@ -4,7 +4,7 @@
.\" Quick hack conversion by Albert Cahalan, 1998.
.\" Licensed under version 2 of the Gnu General Public License.
.\"
-.TH PS 1 "February 25, 2010" "Linux" "Linux User's Manual"
+.TH PS 1 "December 2011" "procps-ng" "User Commands"
.\"
.\" To render this page:
.\" groff -t -b -man -X -P-resolution -P100 -Tps ps.1 &
@@ -12,12 +12,10 @@
.\" tbl ps.1 | troff -Ww -man -z
.\" groff -t -man -Tps ps.1 | ps2pdf - - > ps.pdf
.\"
-.\" The '70s called. They want their perfect justification,
-.\" hyphenation, and double-spaced sentences back.
+.\" Ragged-right text.
.na
+.\" Disable hyphenation.
.nh
-.if n .ss 12 0
-.\"
.\"
.\" ColSize is used for the format spec table.
.\" It's the left margin, minus the right, minus
@@ -26,22 +24,6 @@
.\"
.nr ColSize ((\n[.l] - \n[.i]) / 1n - 29)
.\"
-.\" This is for command options
-.nr OptSize (16u)
-.\"
-.\" l=\n(.l
-.\" i=\n(.i
-.\" o=\n(.o
-.\" H=\n(.H
-.\" s=\n(.s
-.\" ColSize=\n[ColSize]
-.\"
-.\" Macro for easy option formatting: .opt \-x
-.de opt
-. TP \\n[OptSize]
-. BI \\$*
-..
-.\"
.SH NAME
ps \- report a snapshot of the current processes.
.SH SYNOPSIS
@@ -50,11 +32,15 @@ ps \- report a snapshot of the current processes.
.PP
.SH DESCRIPTION
.B ps
-displays information about a selection of the active processes.
-If you want a repetitive update of the selection and the
-displayed information, use\ \fItop\fR(1) instead.
+displays information about a selection of the active processes. If you want
+a repetitive update of the selection and the displayed information, use
+.IR top (1)
+instead.
.P
-This version of \fBps\fR accepts several kinds of options:
+This version of
+.B ps
+accepts several kinds of options:
+.IP
.PD 0
.IP 1 4
UNIX options, which may be grouped and must be preceded by a dash.
@@ -65,45 +51,49 @@ GNU long options, which are preceded by two dashes.
.PD
.PP
Options of different types may be freely mixed, but conflicts can appear.
-There are some synonymous options, which are functionally identical, due
-to the many standards and \fBps\fR implementations that this \fBps\fR is
-compatible with.
+There are some synonymous options, which are functionally identical, due to
+the many standards and
+.B ps
+implementations that this
+.B ps
+is compatible with.
.P
-Note that "\fBps\ \-aux\fR" is distinct from "\fBps\ aux\fR".
-The POSIX and UNIX standards require that "\fBps\ \-aux\fR" print all
-processes owned by a user named "x", as well as printing all processes
-that would be selected by the \fB\-a\fR option. If the user named "x" does
-not exist, this \fBps\fR may interpret the command as "\fBps\ aux\fR"
-instead and print a warning. This behavior is intended to aid in
-transitioning old scripts and habits. It is fragile, subject to change,
-and thus should not be relied upon.
+Note that "\fBps \-aux\fR" is distinct from "\fBps\ aux\fR". The POSIX and
+UNIX standards require that "\fBps\ \-aux\fR" print all processes owned by a
+user named "x", as well as printing all processes that would be selected by
+the
+.B \-a
+option. If the user named "x" does not exist, this
+.B ps
+may interpret the command as "\fBps\ aux\fR" instead and print a warning.
+This behavior is intended to aid in transitioning old scripts and habits. It
+is fragile, subject to change, and thus should not be relied upon.
.P
-By default, \fBps\fR selects all processes
-with the same effective user ID (euid=EUID) as the current user
-and
-associated with the same terminal as the invoker.
-It displays the process ID (pid=PID),
-the terminal associated with the process (tname=TTY),
-the cumulated CPU time in [DD\-]hh:mm:ss format (time=TIME),
-and the executable name (ucmd=CMD).
-Output is unsorted by default.
+By default,
+.B ps
+selects all processes with the same effective user ID (euid=EUID) as the
+current user and associated with the same terminal as the invoker. It
+displays the process ID (pid=PID), the terminal associated with the process
+(tname=TTY), the cumulated CPU time in [DD\-]hh:mm:ss format (time=TIME), and
+the executable name (ucmd=CMD). Output is unsorted by default.
.P
The use of BSD\-style options will add process state (stat=STAT) to the
default display and show the command args (args=COMMAND) instead of the
-executable name. You can override this with the \fBPS_FORMAT\fR
+executable name. You can override this with the
+.B PS_FORMAT
environment variable. The use of BSD\-style options will also change the
-process selection to include processes on other terminals (TTYs) that
-are owned by you; alternately, this may be described as setting the
-selection to be the set of all processes filtered to exclude
-processes owned by other users or not on a terminal. These effects
-are not considered when options are described as being "identical" below,
-so \fB\-M\fR will be considered identical to \fBZ\fR and so on.
+process selection to include processes on other terminals (TTYs) that are
+owned by you; alternately, this may be described as setting the selection to
+be the set of all processes filtered to exclude processes owned by other
+users or not on a terminal. These effects are not considered when options
+are described as being "identical" below, so
+.B \-M
+will be considered identical to \fBZ\fR and so on.
.P
-Except as described below, process selection options are additive.
-The default selection is discarded, and then the selected processes
-are added to the set of processes to be displayed.
-A\ process will thus be shown if it meets any of the given
-selection criteria.
+Except as described below, process selection options are additive. The
+default selection is discarded, and then the selected processes are added to
+the set of processes to be displayed. A process will thus be shown if it
+meets any of the given selection criteria.
.PP
.\" """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.SH "EXAMPLES"
@@ -158,531 +148,668 @@ Print only the name of PID 42:
.PP
.\" """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.SH "SIMPLE PROCESS SELECTION"
-
-.opt a
-Lift the BSD\-style "only yourself" restriction, which is imposed upon
-the set of all processes when some BSD\-style (without\ "\-") options
-are used or when the \fBps\fR personality setting is BSD\-like.
-The set of processes selected in this manner is
-in addition to the set of processes selected by other means.
-An alternate description is that this option causes \fBps\fR to
-list all processes with a terminal (tty),
-or to list all processes when used together with the \fBx\fR option.
-
-.opt \-A
-Select all processes. Identical to \fB\-e\fR.
-
-.opt \-a
-Select all processes except both session leaders (see \fIgetsid\fR(2)) and
-processes not associated with a terminal.
-
-.opt \-d
+.TP
+.BR a
+Lift the BSD\-style "only yourself" restriction, which is imposed upon the
+set of all processes when some BSD\-style (without "\-") options are used or
+when the
+.B ps
+personality setting is BSD\-like. The set of processes selected in this
+manner is in addition to the set of processes selected by other means. An
+alternate description is that this option causes
+.B ps
+to list all processes with a terminal (tty), or to list all processes when
+used together with the
+.B x
+option.
+.TP
+.B \-A
+Select all processes. Identical to
+.BR \-e .
+.TP
+.B \-a
+Select all processes except both session leaders (see
+.IR getsid (2))
+and processes not associated with a terminal.
+.TP
+.B \-d
Select all processes except session leaders.
-
-.opt \-\-deselect
+.TP
+.B \-\-deselect
Select all processes except those that fulfill the specified conditions
-(negates the selection). Identical to \fB\-N\fR.
-
-
-.opt \-e
-Select all processes. Identical to \fB\-A\fR.
-
+(negates the selection). Identical to
+.BR \-N .
+.TP
+.B \-e
+Select all processes. Identical to
+.BR \-A .
.\" Current "g" behavior: add in the session leaders, which would
.\" be excluded in the sunos4 personality. Supposed "g" behavior:
.\" add in the group leaders -- at least according to the SunOS 4
.\" man page on the FreeBSD site. Uh oh. I think I had tested SunOS
.\" though, so maybe the code is correct.
-
-.opt g
+.TP
+.B g
Really all, even session leaders. This flag is obsolete and may be
-discontinued in a future release. It is normally implied by the \fBa\fR flag,
-and is only useful when operating in the sunos4 personality.
-
-.opt \-N
+discontinued in a future release. It is normally implied by the
+.B a
+flag, and is only useful when operating in the sunos4 personality.
+.TP
+.B \-N
Select all processes except those that fulfill the specified conditions
-(negates the selection). Identical to \fB\-\-deselect\fR.
-
-.opt T
+(negates the selection). Identical to
+.BR \-\-deselect .
+.TP
+.B T
Select all processes associated with this terminal. Identical to the
-\fBt\fR option without any argument.
-
-.opt r
+.B t
+option without any argument.
+.TP
+.B r
Restrict the selection to only running processes.
-
-.opt x
-Lift the BSD\-style "must have a tty" restriction, which is imposed upon
-the set of all processes when some BSD\-style (without\ "\-") options
-are used or when the \fBps\fR personality setting is BSD\-like.
-The set of processes selected in this manner is
-in addition to the set of processes selected by other means.
-An alternate description is that this option causes \fBps\fR to
-list all processes owned by you (same EUID as \fBps\fR),
-or to list all processes when used together with the \fBa\fR option.
-
+.TP
+.B x
+Lift the BSD\-style "must have a tty" restriction, which is imposed upon the
+set of all processes when some BSD\-style (without "\-") options are used or
+when the
+.B ps
+personality setting is BSD\-like. The set of processes selected in this
+manner is in addition to the set of processes selected by other means. An
+alternate description is that this option causes
+.B ps
+to list all processes owned by you (same EUID as
+.BR ps ),
+or to list all processes when used together with the
+.B a
+option.
.\" """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.PD
.PP
.SH "PROCESS SELECTION BY LIST"
-These options accept a single argument in the form of a blank\-separated
-or comma\-separated list. They can be used multiple times.
-For\ example:\ \fBps\ \-p\ "1\ 2"\ \-p\ 3,4\fR
-.P
-
-.opt \-\fI123\fR
-Identical to \fB\-\-sid\ \fI123\fR.
-
-.opt \fI123\fR
+These options accept a single argument in the form of a blank\-separated or
+comma\-separated list. They can be used multiple times. For example:
+\fBps\ \-p\ "1\ 2"\ \-p\ 3,4\fR
+.TP
+.RI \- 123
Identical to \fB\-\-pid\ \fI123\fR.
-
-.opt \-C \ cmdlist
-Select by command name.
-.br
-This selects the processes whose executable name is given in
-\fIcmdlist\fR.
-
-.opt \-G \ grplist
-Select by real group ID (RGID) or name.
-.br
-This selects the processes whose real group name or ID is in the
-\fIgrplist\fR list. The real group ID identifies the group of the user
-who created the process, see \fIgetgid\fR(2).
-
-.opt \-g \ grplist
-Select by session OR by effective group name.
-.br
-Selection by session is specified by many standards,
-but selection by effective group is the logical behavior that
-several other operating systems use.
-This \fBps\fR will select by session when the list
-is completely numeric (as\ sessions\ are).
-Group ID numbers will work only when some group names are also specified.
-See the \fB\-s\fR and \fB\-\-group\fR options.
-
-.opt \-\-Group \ grplist
-Select by real group ID (RGID) or name. Identical to \fB\-G\fR.
-
-.opt \-\-group \ grplist
-Select by effective group ID (EGID) or name.
-.br
-This selects the processes whose effective group name or ID is in
-\fIgrouplist\fR. The effective group ID describes the group whose file
-access permissions are used by the process (see\ \fIgetegid\fR(2)).
-The \fB\-g\fR option is often an alternative to\ \fB\-\-group\fR.
-
-.opt p \ pidlist
-Select by process ID. Identical to \fB\-p\fR and\ \fB\-\-pid\fR.
-
-.opt \-p \ pidlist
-Select by PID.
-.br
-This selects the processes whose process ID numbers appear in
-\fIpidlist\fR. Identical to \fBp\fR and\ \fB\-\-pid\fR.
-
-.opt \-\-pid \ pidlist
-Select by process\ ID. Identical to \fB\-p\fR\ and\ \fBp\fR.
-
-.opt \-\-ppid \ pidlist
-Select by parent process\ ID.
-This selects the processes
-with a parent\ process\ ID in \fIpidlist\fR.
-That\ is, it selects processes that are children
-of those listed in \fIpidlist\fR.
-
-.opt \-s \ sesslist
-Select by session ID.
-.br
-This selects the processes
-with a session ID specified in\ \fIsesslist\fR.
-
-.opt \-\-sid \ sesslist
-Select by session\ ID. Identical to\ \fB\-s\fR.
-
-.opt t \ ttylist
-Select by tty. Nearly identical to \fB\-t\fR and \fB\-\-tty\fR,
-but can also be used with an empty \fIttylist\fR to indicate
-the terminal associated with \fBps\fR.
-Using the \fBT\fR option is considered cleaner than using \fBt\fR with
-an\ empty\ \fIttylist\fR.
-
-.opt \-t \ ttylist
-Select by tty.
-.br
-This selects the processes associated with the terminals
-given in \fIttylist\fR.
+.TP
+.I 123
+Identical to \fB\-\-pid\ \fI123\fR.
+.TP
+.BI \-C \ cmdlist
+Select by command name. This selects the processes whose executable name is
+given in
+.IR cmdlist .
+.TP
+.BI \-G \ grplist
+Select by real group ID (RGID) or name. This selects the processes whose
+real group name or ID is in the
+.I grplist
+list. The real group ID identifies the group of the user who created the
+process, see
+.IR getgid (2).
+.TP
+.BI \-g \ grplist
+Select by session OR by effective group name. Selection by session is
+specified by many standards, but selection by effective group is the logical
+behavior that several other operating systems use. This
+.B ps
+will select by session when the list is completely numeric (as\ sessions\
+are). Group ID numbers will work only when some group names are also
+specified. See the
+.B \-s
+and
+.B \-\-group
+options.
+.TP
+.BI \-\-Group \ grplist
+Select by real group ID (RGID) or name. Identical to
+.BR \-G .
+.TP
+.BI \-\-group \ grplist
+Select by effective group ID (EGID) or name. This selects the processes
+whose effective group name or ID is in
+.IR grouplist .
+The effective group ID describes the group whose file access permissions are
+used by the process (see
+.IR getegid (2)).
+The
+.B \-g
+option is often an alternative to
+.BR \-\-group .
+.TP
+.BI p \ pidlist
+Select by process ID. Identical to
+.B \-p
+and
+.BR \-\-pid .
+.TP
+.BI \-p \ pidlist
+Select by PID. This selects the processes whose process ID numbers appear in
+.IR pidlist .
+Identical to
+.B p
+and
+.BR \-\-pid .
+.TP
+.BI \-\-pid \ pidlist
+Select by process\ ID. Identical to
+.B \-p
+and
+.BR p .
+.TP
+.BI \-\-ppid \ pidlist
+Select by parent process ID. This selects the processes with a parent
+process\ ID in
+.IR pidlist .
+That is, it selects processes that are children of those listed in
+.IR pidlist .
+.TP
+.BI \-s \ sesslist
+Select by session ID. This selects the processes with a session ID specified
+in
+.IR sesslist .
+.TP
+.BI \-\-sid \ sesslist
+Select by session\ ID. Identical to
+.BR \-s .
+.TP
+.BI t \ ttylist
+Select by tty. Nearly identical to
+.B \-t
+and
+.BR \-\-tty ,
+but can also
+be used with an empty
+.I ttylist
+to indicate the terminal associated with
+.BR ps .
+Using the
+.B T
+option is considered cleaner than using
+.B t
+with an empty
+.IR ttylist .
+.TP
+.BI \-t \ ttylist
+Select by tty. This selects the processes associated with the terminals
+given in
+.IR ttylist .
Terminals (ttys, or screens for text output) can be specified in several
-forms: /dev/ttyS1, ttyS1, S1.
-A\ plain "\-" may be used to select processes not attached to any terminal.
-
-.opt \-\-tty \ ttylist
-Select by terminal. Identical to \fB\-t\fR and\ \fBt\fR.
-
-.opt U \ userlist
-Select by effective user ID (EUID) or name.
-.br
-This selects the processes whose effective user name
-or ID is in \fIuserlist\fR.
-The effective user\ ID describes the user whose file
-access permissions are used by the process
-(see\ \fIgeteuid\fR(2)).
-Identical to \fB\-u\fR and\ \fB\-\-user\fR.
-
-.opt \-U \ userlist
-Select by real user ID (RUID) or name.
-.br
-It selects the processes whose real user name or ID is in the
-\fIuserlist\fR list.
-The real user ID identifies the user who created the process,
-see\ \fIgetuid\fR(2).
-
-.opt \-u \ userlist
-Select by effective user ID (EUID) or name.
-.br
-This selects the processes whose effective user name or ID is in
-\fIuserlist\fR. The effective user ID describes the user whose file
-access permissions are used by the process (see\ \fIgeteuid\fR(2)).
-Identical to \fBU\fR and \fB\-\-user\fR.
-
-.opt \-\-User \ userlist
-Select by real user ID (RUID) or name. Identical to \fB\-U\fR.
-
-.opt \-\-user \ userlist
-Select by effective user ID (EUID) or name.
-Identical to \fB\-u\fR and\ \fBU\fR.
-
+forms: /dev/ttyS1, ttyS1, S1. A plain "\-" may be used to select processes
+not attached to any terminal.
+.TP
+.BI \-\-tty \ ttylist
+Select by terminal. Identical to
+.B \-t
+and
+.BR t .
+.TP
+.BI U \ userlist
+Select by effective user ID (EUID) or name. This selects the processes whose
+effective user name or ID is in
+.IR userlist .
+The effective user ID describes the user whose file access permissions are
+used by the process (see
+.IR geteuid (2)).
+Identical to
+.B \-u
+and
+.BR \-\-user .
+.TP
+.BI \-U \ userlist
+Select by real user ID (RUID) or name. It selects the processes whose real
+user name or ID is in the
+.I userlist
+list. The real user ID identifies the user who created the process, see
+.IR getuid (2).
+.TP
+.BI \-u \ userlist
+Select by effective user ID (EUID) or name. This selects the processes whose
+effective user name or ID is in
+.IR userlist .
+
+The effective user ID describes the user whose file
+access permissions are used by the process (see
+.IR geteuid (2)).
+Identical to
+.B U
+and
+.BR \-\-user .
+.TP
+.BI \-\-User \ userlist
+Select by real user ID (RUID) or name. Identical to
+.BR \-U .
+.TP
+.BI \-\-user \ userlist
+Select by effective user ID (EUID) or name. Identical to
+.B \-u
+and
+.BR U .
.\" """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.PD
.PP
.SH "OUTPUT FORMAT CONTROL"
-These options are used to choose the information displayed by \fBps\fR.
+These options are used to choose the information displayed by
+.BR ps .
The output may differ by personality.
.PP
-
-.opt \-c
-Show different scheduler information for the \fB\-l\fR option.
-
-.opt \-\-context
-Display security context format (for\ SE\ Linux).
-
-.opt \-f
-Do full\-format listing. This option can be combined with many
-other UNIX\-style options to add additional columns. It also causes
-the command arguments to be printed. When used with \fB\-L\fR, the
-NLWP (number of threads) and LWP (thread ID) columns will be added.
-See the \fBc\fR option, the format keyword \fBargs\fR, and the
-format keyword \fBcomm\fR.
-
-.opt \-F
-Extra full format. See the \fB\-f\fR option, which \fB\-F\fR implies.
-
-.opt \-\-format \ format
-user\-defined format. Identical to \fB\-o\fR and \fBo\fR.
-
-.opt j
+.TP
+.B \-c
+Show different scheduler information for the
+.B \-l
+option.
+.TP
+.B \-\-context
+Display security context format (for SE Linux).
+.TP
+.B \-f
+Do full\-format listing. This option can be combined with many other
+UNIX\-style options to add additional columns. It also causes the command
+arguments to be printed. When used with
+.BR \-L ,
+the NLWP (number of threads) and LWP (thread ID) columns will be added. See
+the
+.B c
+option, the format keyword
+.BR args ,
+and the format keyword
+.BR comm .
+.TP
+.B \-F
+Extra full format. See the
+.B \-f
+option, which
+.B \-F
+implies.
+.TP
+.BI \-\-format \ format
+user\-defined format. Identical to
+.B \-o
+and
+.BR o .
+.TP
+.B j
BSD job control format.
-
-.opt \-j
-Jobs format
-
-.opt l
+.TP
+.B \-j
+Jobs format.
+.TP
+.B l
Display BSD long format.
-
-.opt \-l
-Long format. The \fB\-y\fR option is often useful with this.
-
-.opt \-M
-Add a column of security data. Identical to \fBZ\fR (for\ SE\ Linux).
-
-.opt O \ format
-is preloaded \fBo\fR (overloaded).
-.br
-The BSD \fBO\fR option can act like \fB\-O\fR (user\-defined output
-format with some common fields predefined) or can be used to specify
-sort order. Heuristics are used to determine the behavior of this
-option. To ensure that the desired behavior is obtained (sorting or
-formatting), specify the option in some other way
-(e.g. with \fB\-O\fR or \fB\-\-sort\fR).
-When used as a formatting option, it is identical to \fB\-O\fR, with the
-BSD\ personality.
-
-.opt \-O \ format
-Like \fB\-o\fR, but preloaded with some default columns.
-Identical to \fB\-o\ pid,\fIformat\fB,state,tname,time,command\fR
-or \fB\-o\ pid,\fIformat\fB,tname,time,cmd\fR, see\ \fB\-o\fR\ below.
-
-.opt o \ format
-Specify user\-defined format. Identical to \fB\-o\fR and
-\fB\-\-format\fR.
-
-.opt \-o \ format
+.TP
+.B \-l
+Long format. The
+.B \-y
+option is often useful with this.
+.TP
+.B \-M
+Add a column of security data. Identical to
+.B Z
+(for SE Linux).
+.TP
+.BI O \ format
+is preloaded
+.B o
+(overloaded). The BSD
+.B O
+option can act like
+.B \-O
+(user\-defined output format with some common fields predefined) or can be
+used to specify sort order. Heuristics are used to determine the behavior of
+this option. To ensure that the desired behavior is obtained (sorting or
+formatting), specify the option in some other way (e.g. with
+.B \-O
+or
+.BR \-\-sort ).
+When used as a formatting option, it is identical to
+.BR \-O ,
+with the BSD personality.
+.TP
+.BI \-O \ format
+Like
+.BR \-o ,
+but preloaded with some default columns. Identical to
+\fB\-o\ pid,\:\fIformat\fB,\:state,\:tname,\:time,\:command\fR or
+\fB\-o\ pid,\:\fIformat\fB,\:tname,\:time,\:cmd\fR,
+see
+.B \-o
+below.
+.TP
+.BI o \ format
+Specify user\-defined format. Identical to
+.B \-o
+and
+.BR \-\-format .
+.TP
+.BI \-o \ format
User\-defined format.
-.br
-\fIformat\fR is a single argument in the form of a
-blank\-separated or comma\-separated list, which offers
-a way to specify individual output columns.
-The recognized keywords are described in the \fBSTANDARD FORMAT
-SPECIFIERS\fR section below.
-Headers may be
-renamed (\fBps\ \-o\ pid,ruser=RealUser\ \-o\ comm=Command\fR) as desired.
-If all column headers are empty (\fBps\ \-o\ pid=\ \-o\ comm=\fR) then the
-header line will not be output. Column width will increase as
-needed for wide headers; this may be used to widen up columns
-such as WCHAN (\fBps\ \-o\ pid,wchan=WIDE\-WCHAN\-COLUMN\ \-o\ comm\fR).
-Explicit width control (\fBps\ opid,wchan:42,cmd\fR) is offered too.
-The behavior of \fBps\ \-o\ pid=X,comm=Y\fR varies with personality;
-output may be one column named "X,comm=Y" or two columns
-named "X" and "Y". Use multiple \fB\-o\fR options when in doubt.
-Use the \fBPS_FORMAT\fR environment variable to specify a default
-as desired; DefSysV and DefBSD are macros that may be used to
-choose the default UNIX or BSD columns.
-
-.opt s
-Display signal format
-
-.opt u
-Display user\-oriented format
-
-.opt v
-Display virtual memory format
-
-.opt X
+.I format
+is a single argument in the form of a blank\-separated or comma\-separated
+list, which offers a way to specify individual output columns. The
+recognized keywords are described in the
+.B STANDARD FORMAT SPECIFIERS
+section below. Headers may be renamed
+.RB ( "ps \-o pid,\:ruser=RealUser \-o comm=Command" )
+as desired.
+If all column headers are empty
+.RB ( "ps \-o pid= \-o comm=" )
+then the header line will not be output. Column width will increase as
+needed for wide headers; this may be used to widen up columns such as WCHAN
+.RB ( "ps \-o pid,\:wchan=\:WIDE\-\:WCHAN\-\:COLUMN \-o comm" ).
+Explicit width
+control
+.RB ( "ps opid,\:wchan:42,\:cmd" )
+is offered too. The behavior of
+.B ps -o pid=X,\:comm=Y
+varies with personality; output may be one column named "X,\:comm=Y" or two
+columns named "X" and "Y". Use multiple
+.B \-o
+options when in doubt. Use the
+.B PS_FORMAT
+environment variable to specify a default as desired; DefSysV and DefBSD are
+macros that may be used to choose the default UNIX or BSD columns.
+.TP
+.B s
+Display signal format.
+.TP
+.B u
+Display user\-oriented format.
+.TP
+.B v
+Display virtual memory format.
+.TP
+.B X
Register format.
-
-.opt \-y
-Do not show flags; show rss in place of addr.
-This option can only be used with \fB\-l\fR.
-
-.opt Z
-Add a column of security data. Identical to \fB\-M\fR (for\ SE\ Linux).
-
+.TP
+.B \-y
+Do not show flags; show rss in place of addr. This option can only be used
+with
+.BR \-l .
+.TP
+.B Z
+Add a column of security data. Identical to
+.B \-M
+(for SE Linux).
.\" """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.PD
.PP
.SH "OUTPUT MODIFIERS"
-
.\" .TP
.\" .B C
.\" use raw CPU time for %CPU instead of decaying average
-
-.opt c
-Show the true command name. This is derived from the name of the
-executable file, rather than from the argv value. Command arguments
-and any modifications to them are
-thus not shown. This option
-effectively turns the \fBargs\fR format keyword into the \fBcomm\fR
-format keyword; it is useful with the \fB\-f\fR format option and with
-the various BSD\-style format options, which all normally
-display the command arguments.
-See the \fB\-f\fR option, the format keyword \fBargs\fR, and the
-format keyword \fBcomm\fR.
-
-.opt \-\-cols \ n
-Set screen width
-
-.opt \-\-columns \ n
-Set screen width
-
-.opt \-\-cumulative
-Include some dead child process data (as a sum with the parent)
-
-.opt e
+.TP
+.B c
+Show the true command name. This is derived from the name of the executable
+file, rather than from the argv value. Command arguments and any
+modifications to them are thus not shown. This option effectively turns the
+.B args
+format keyword into the
+.B comm
+format keyword; it is useful with the
+.B \-f
+format option and with the various BSD\-style format options, which all
+normally display the command arguments. See the
+.B \-f
+option, the format
+keyword
+.BR args ,
+and the format keyword
+.BR comm .
+.TP
+.BI \-\-cols \ n
+Set screen width.
+.TP
+.BI \-\-columns \ n
+Set screen width.
+.TP
+.B \-\-cumulative
+Include some dead child process data (as a sum with the parent).
+.TP
+.B e
Show the environment after the command.
-
-.opt f
+.TP
+.B f
ASCII art process hierarchy (forest).
-
-.opt \-\-forest
+.TP
+.B \-\-forest
ASCII art process tree.
-
-.opt h
-No header. (or, one header per screen in the BSD personality)
-.br
-The \fBh\fR option is problematic. Standard BSD \fBps\fR uses
-this option to print a header on each page of output, but older
-Linux \fBps\fR uses this option to totally disable the header.
-This version of \fBps\fR follows the Linux usage of not printing
-the header unless the BSD personality has been selected, in which
-case it prints a header on each page of output. Regardless of the
-current personality, you can use the long options \fB\-\-headers\fR
-and \fB\-\-no\-headers\fR to enable printing headers each page or
-disable headers entirely, respectively.
-
-.opt \-H
+.TP
+.B h
+No header. (or, one header per screen in the BSD personality). The
+.B h
+option is problematic. Standard BSD
+.B ps
+uses this option to print a header on each page of output, but older Linux
+.B ps
+uses this option to totally disable the header. This version of
+.B ps
+follows the Linux usage of not printing the header unless the BSD personality
+has been selected, in which case it prints a header on each page of output.
+Regardless of the current personality, you can use the long options
+.B \-\-headers
+and
+.B \-\-no\-headers
+to enable printing headers each page or disable headers entirely,
+respectively.
+.TP
+.B \-H
Show process hierarchy (forest).
-
-.opt \-\-headers
+.TP
+.B \-\-headers
Repeat header lines, one per page of output.
-
-.opt k \ spec
-Specify sorting order. Sorting syntax is
+.TP
+.BI k \ spec
+Specify sorting order. Sorting syntax is
[\fB+\fR|\fB\-\fR]\fIkey\fR[,[\fB+\fR|\fB\-\fR]\fIkey\fR[,...]].
-Choose a multi\-letter key from the \fBSTANDARD FORMAT SPECIFIERS\fR section.
-The\ "+" is optional since default direction is increasing numerical or
-lexicographic order. Identical to \fB\-\-sort\fR. Examples:
+Choose a multi\-letter key from the
+.B STANDARD FORMAT SPECIFIERS
+section. The "+" is optional since default direction is increasing
+numerical or lexicographic order. Identical to
+.BR \-\-sort .
+.RS 8
+.IP
+Examples:
.br
-\fBps\ jaxkuid,\-ppid,+pid\fR
+.B ps jaxkuid,\-ppid,+pid
.br
-\fBps\ axk\ comm\ o\ comm,args\fR
+.B ps axk comm o comm,args
.br
-\fBps\ kstart_time\ \-ef\fR
-
-.opt \-\-lines \ n
+.B ps kstart_time \-ef
+.RE
+.TP
+.BI \-\-lines \ n
Set screen height.
-
-.opt \-n \ namelist
-Set namelist file. Identical to \fBN\fR.
-.br
-The namelist file is needed for a proper WCHAN display, and must match
-the current Linux kernel exactly for correct output.
-Without this option, the default search path for the namelist is:
-
- $PS_SYSMAP
+.TP
+.BI \-n \ namelist
+Set namelist file. Identical to
+.BR N .
+The namelist file is needed for a proper WCHAN display, and must match the
+current Linux kernel exactly for correct output. Without this option, the
+default search path for the namelist is:
+.RS 8
+.IP
+$PS_SYSMAP
.br
- $PS_SYSTEM_MAP
+$PS_SYSTEM_MAP
.br
- /proc/*/wchan
+/proc/*/wchan
.br
- /boot/System.map\-\`uname\ \-r\`
+/boot/System.map\-$(uname\ \-r)
.br
- /boot/System.map
+/boot/System.map
.br
- /lib/modules/\`uname\ \-r\`/System.map
+/lib/modules/$(uname\ \-r)/System.map
.br
- /usr/src/linux/System.map
+/usr/src/linux/System.map
.br
- /System.map
-
-.opt n
+/System.map
+.RE
+.TP
+.B n
Numeric output for WCHAN and USER (including all types of UID and GID).
-
-.opt N \ namelist
-Specify namelist file. Identical to \fB\-n\fR, see \fB\-n\fR above.
-
-.opt \-\-no\-headers
-Print no header line at all. \fB\-\-no\-heading\fR is an alias for this
-option.
-
-.opt O \ order
+.TP
+.BI N \ namelist
+Specify namelist file. Identical to
+.BR \-n ,
+see
+.B \-n
+above.
+.TP
+.B \-\-no\-headers
+Print no header line at all.
+.B \-\-no\-heading
+is an alias for this option.
+.TP
+.BI O \ order
Sorting order (overloaded).
-.br
-The BSD \fBO\fR option can act like \fB\-O\fR (user\-defined output
-format with some common fields predefined) or can be used to specify
-sort order. Heuristics are used to determine the behavior of this
-option. To ensure that the desired behavior is obtained (sorting or
-formatting), specify the option in some other way (e.g. with \fB\-O\fR
-or \fB\-\-sort\fR).
-
-For sorting, obsolete BSD \fBO\fR option syntax is
+The BSD
+.B O
+option can act like
+.B \-O
+(user\-defined output format with some common fields predefined) or can be
+used to specify sort order. Heuristics are used to determine the behavior of
+this option. To ensure that the desired behavior is obtained (sorting or
+formatting), specify the option in some other way (e.g. with
+.B \-O
+or
+.BR \-\-sort ).
+.IP
+For sorting, obsolete BSD
+.B O
+option syntax is
\fBO\fR[\fB+\fR|\fB\-\fR]\fIk1\fR[,[\fB+\fR|\fB\-\fR]\fIk2\fR[,...]].
It orders the processes listing according to the multilevel sort specified by
-the sequence of one\-letter short keys \fIk1\fR, \fIk2\fR, ... described
-in the \fBOBSOLETE SORT KEYS\fR section below.
-The\ "+" is currently optional,
-merely re\-iterating the default direction on a key,
-but may help to distinguish an \fBO\fR sort from an \fBO\fR format.
-The\ "\-" reverses direction only on the key it precedes.
-
-.opt \-\-rows \ n
+the sequence of one\-letter short keys
+.IR k1 , k2 ", ..."
+described in the
+.B OBSOLETE SORT KEYS
+section below. The\ "+" is currently optional, merely re\-iterating the
+default direction on a key, but may help to distinguish an
+.B O
+sort from an
+.B O
+format. The "\-" reverses direction only on the key it precedes.
+.TP
+.BI \-\-rows \ n
Set screen height.
-
-.opt S
-Sum up some information, such as CPU usage, from dead child processes
-into their parent. This is useful for examining a system where a
-parent process repeatedly forks off short\-lived children to do work.
-
-.opt \-\-sort \ spec
-Specify sorting order. Sorting syntax is
-[\fB+\fR|\fB\-\fR]\fIkey\fR[,[\fB+\fR|\fB\-\fR]\fIkey\fR[,...]].
-Choose a multi\-letter key from the \fBSTANDARD FORMAT SPECIFIERS\fR section.
-The\ "+" is optional since default direction is increasing numerical or
-lexicographic order. Identical to\ \fBk\fR.
-For example: \fBps\ jax\ \-\-sort=uid,\-ppid,+pid\fR
-
-.opt w
-Wide output. Use this option twice for unlimited width.
-
-.opt \-w
-Wide output. Use this option twice for unlimited width.
-
-.opt \-\-width \ n
-set screen width
-
+.TP
+.B S
+Sum up some information, such as CPU usage, from dead child processes into
+their parent. This is useful for examining a system where a parent process
+repeatedly forks off short\-lived children to do work.
+.TP
+.BI \-\-sort \ spec
+Specify sorting order. Sorting syntax is
+[\fB+\fR|\fB\-\fR]\fIkey\fR[,[\fB+\fR|\fB\-\fR]\fIkey\fR[,...]]. Choose a
+multi\-letter key from the
+.B STANDARD FORMAT SPECIFIERS
+section. The "+" is optional since default direction is increasing numerical
+or lexicographic order. Identical to
+.BR k .
+For example:
+.B ps jax \-\-sort=\:uid,\:\-ppid,\:+pid
+.TP
+.B w
+Wide output. Use this option twice for unlimited width.
+.TP
+.B \-w
+Wide output. Use this option twice for unlimited width.
+.TP
+.BI \-\-width \ n
+Set screen width.
.\" """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.PD
.PP
.SH "THREAD DISPLAY"
-.PD 0
-
-.opt H
+.TP
+.B H
Show threads as if they were processes.
-
-.opt \-L
+.TP
+.B \-L
Show threads, possibly with LWP and NLWP columns.
-
-.opt m
+.TP
+.B m
Show threads after processes.
-
-.opt \-m
+.TP
+.B \-m
Show threads after processes.
-
-.opt \-T
+.TP
+.B \-T
Show threads, possibly with SPID column.
-
.\" """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.PD
.PP
.SH "OTHER INFORMATION"
-.PD 0
-
-.opt \-\-help
-Print a help message.
-
-.opt \-\-info
+.TP
+.BI \-\-help \ section
+Print a help message. The section argument can be
+\fBs\fIelection\fR,
+\fBl\fIist\fR,
+\fBo\fIutput\fR,
+\fBt\fIhreads\fR,
+\fBm\fIisc\fR or
+\fBa\fIll\fR.
+Arguments can be shorthanded to first letter.
+.TP
+.B \-\-info
Print debugging info.
-
-.opt L
+.TP
+.B L
List all format specifiers.
-
-.opt V
+.TP
+.B V
Print the procps-ng version.
-
-.opt \-V
+.TP
+.B \-V
Print the procps-ng version.
-
-.opt \-\-version
+.TP
+.B \-\-version
Print the procps-ng version.
-
.\" """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.PD
.PP
.SH NOTES
-This \fBps\fR works by reading the virtual files in\ /proc.
-This \fBps\fR does not need to be setuid kmem or have any privileges to run.
-Do not give this \fBps\fR any special permissions.
-
-This \fBps\fR needs access to namelist data for proper WCHAN display.
-For kernels prior to 2.6, the System.map file must be installed.
-
-CPU usage is currently expressed as the percentage of time spent
-running during the entire lifetime of a process.
-This is not ideal, and\ it does not conform to the
-standards that \fBps\fR otherwise conforms\ to.
-CPU\ usage is unlikely to add up to exactly\ 100%.
-
+This
+.B ps
+works by reading the virtual files in /proc. This
+.B ps
+does not need to be setuid kmem or have any privileges to run. Do not give
+this
+.B ps
+any special permissions.
+.PP
+This
+.B ps
+needs access to namelist data for proper WCHAN display. For kernels prior to
+2.6, the System.map file must be installed.
+.PP
+CPU usage is currently expressed as the percentage of time spent running
+during the entire lifetime of a process. This is not ideal, and\ it does not
+conform to the standards that
+.B ps
+otherwise conforms to. CPU usage is unlikely to add up to exactly 100%.
+.PP
The SIZE and RSS fields don't count some parts of a process including the
-page tables, kernel stack, struct thread_info, and struct task_struct.
-This is usually at least 20\ KiB of memory that is always resident.
-SIZE is the virtual size of the process (code+data+stack).
-
-Processes marked <defunct> are dead processes (so\-called\ "zombies") that
-remain because their parent has not destroyed them properly. These processes
-will be destroyed by \fIinit\fR(8) if the parent process exits.
-
-If the length of the username is greater than the length of
-the display column, the numeric user ID is displayed instead.
-
+page tables, kernel stack, struct thread_info, and struct task_struct. This
+is usually at least 20 KiB of memory that is always resident. SIZE is the
+virtual size of the process (code+\:data+\:stack).
+.PP
+Processes marked <defunct> are dead processes (so\-called "zombies") that
+remain because their parent has not destroyed them properly. These processes
+will be destroyed by
+.IR init (8)
+if the parent process exits.
+.PP
+If the length of the username is greater than the length of the display
+column, the numeric user ID is displayed instead.
.SH "PROCESS FLAGS"
The sum of these values is displayed in the "F" column,
-which is provided by the \fBflags\fR output specifier:
+which is provided by the
+.B flags
+output specifier:
+.IP
+.RS 8
.PD 0
.TP 5
1
@@ -691,24 +818,28 @@ forked but didn't exec
4
used super\-user privileges
.PD
+.RE
.PP
.SH "PROCESS STATE CODES"
-Here are the different values that the \fBs\fR, \fBstat\fR and
-\fBstate\fR output specifiers (header\ "STAT"\ or\ "S") will display to
-describe the state of a process:
+Here are the different values that the
+.BR s , \ stat \ and \ state
+output specifiers (header "STAT" or "S") will display to describe the state
+of a process:
+.IP
+.RS 8
.PD 0
.TP 5
D
-uninterruptible sleep (usually\ IO)
+uninterruptible sleep (usually IO)
.TP
R
-running or runnable (on\ run\ queue)
+running or runnable (on run queue)
.TP
S
interruptible sleep (waiting for an event to complete)
.TP
T
-stopped, either by a job control signal or because it is being traced.
+stopped, either by a job control signal or because it is being traced
.TP
W
paging (not valid since the 2.6.xx kernel)
@@ -717,11 +848,15 @@ X
dead (should never be seen)
.TP
Z
-defunct ("zombie") process, terminated but not reaped by its parent.
+defunct ("zombie") process, terminated but not reaped by its parent
.PD
+.RE
.PP
-For BSD formats and when the \fBstat\fR keyword is used, additional
-characters may be displayed:
+For BSD formats and when the
+.B stat
+keyword is used, additional characters may be displayed:
+.IP
+.RS 8
.PD 0
.TP 5
<
@@ -731,30 +866,35 @@ N
low\-priority (nice to other users)
.TP
L
-has pages locked into memory (for real\-time and custom\ IO)
+has pages locked into memory (for real\-time and custom IO)
.TP
s
is a session leader
.TP
l
-is multi-threaded (using CLONE_THREAD, like NPTL pthreads\ do)
+is multi-threaded (using CLONE_THREAD, like NPTL pthreads do)
.TP
+
-is in the foreground process group.
+is in the foreground process group
.PD
-.PP
+.RE
.PP
.SH "OBSOLETE SORT KEYS"
-These keys are used by the BSD \fBO\fR option (when it is used for
-sorting). The GNU \fB\-\-sort\fR option doesn't use these keys, but the
-specifiers described below in the \fBSTANDARD FORMAT SPECIFIERS\fR
-section. Note that the values used in sorting are the internal
-values \fBps\fR uses and not the "cooked" values used in some of
-the output format fields (e.g. sorting on tty will sort into
-device number, not according to the terminal name displayed).
-Pipe \fBps\fR output into the \fIsort\fR(1) command if you want
-to sort the cooked values.
-
+These keys are used by the BSD
+.B O
+option (when it is used for sorting). The GNU
+.B \-\-sort
+option doesn't use these keys, but the specifiers described below in the
+.B STANDARD FORMAT SPECIFIERS
+section. Note that the values used in sorting are the internal values
+.B ps
+uses and not the "cooked" values used in some of the output format fields
+(e.g. sorting on tty will sort into device number, not according to the
+terminal name displayed). Pipe
+.B ps
+output into the
+.BR sort (1)
+command if you want to sort the cooked values.
.TS
l l lw(3i).
\fBKEY LONG DESCRIPTION\fR
@@ -788,10 +928,18 @@ y priority kernel scheduling priority
.PP
.PP
.SH "AIX FORMAT DESCRIPTORS"
-This \fBps\fR supports AIX format descriptors, which work somewhat like the
-formatting codes of \fIprintf\fR(1) and \fIprintf\fR(3). For example, the normal
-default output can be produced with this: \fBps\ \-eo\ "%p\ %y\ %x\ %c"\fR.
-The\ \fBNORMAL\fR codes are described in the next section.
+This
+.B ps
+supports AIX format descriptors, which work somewhat like the
+formatting codes of
+.IR printf (1)
+and
+.IR printf (3).
+For example, the normal default output can be produced with this:
+\fBps \-eo "%p %y %x %c"\fR.
+The
+.B NORMAL
+codes are described in the next section.
.TS
l l l.
\fBCODE NORMAL HEADER\fR
@@ -811,22 +959,27 @@ l l l.
%y tty TTY
%z vsz VSZ
.TE
-
.SH "STANDARD FORMAT SPECIFIERS"
Here are the different keywords that may be used to control the output
-format (e.g. with option \fB\-o\fR) or to sort the selected processes
-with the GNU\-style \fB\-\-sort\fR option.
-
-For example: \fBps\ \-eo\ pid,user,args\ \-\-sort\ user\fR
-
-This version of \fBps\fR tries to recognize most of the keywords used in
-other implementations of \fBps\fR.
-
+format (e.g. with option
+.BR \-o )
+or to sort the selected processes with the GNU\-style
+.B \-\-sort
+option.
+.PP
+For example:
+.B ps \-eo pid,\:user,\:args \-\-sort user
+.PP
+This version of
+.B ps
+tries to recognize most of the keywords used in other implementations of
+.BR ps .
+.PP
The following user\-defined format specifiers may contain
-spaces: \fBargs\fR, \fBcmd\fR, \fBcomm\fR, \fBcommand\fR, \fBfname\fR,
-\fBucmd\fR, \fBucomm\fR,
-\fBlstart\fR, \fBbsdstart\fR, \fBstart\fR.
-
+spaces:
+.BR args , \ cmd , \ comm , \ command , \ fname , \ ucmd , \ ucomm ,
+.BR lstart , \ bsdstart , \ start .
+.PP
Some keywords may not be available for sorting.
.\" #######################################################################
@@ -843,66 +996,85 @@ lB1 l1 l.
CODE HEADER DESCRIPTION
%cpu %CPU T{
-cpu utilization of the process in "##.#" format. Currently, it is the CPU time
-used divided by the time the process has been running (cputime/realtime
-ratio), expressed as a percentage. It will not add up to 100% unless you
-are lucky. (alias\ \fBpcpu\fR).
+cpu utilization of the process in "##.#" format. Currently, it is the CPU
+time used divided by the time the process has been running (cputime/realtime
+ratio), expressed as a percentage. It will not add up to 100% unless you are
+lucky. (alias
+.BR pcpu ).
T}
%mem %MEM T{
-ratio of the process's resident set size to the physical memory on
-the machine, expressed as a percentage. (alias\ \fBpmem\fR).
+ratio of the process's resident set size to the physical memory on the
+machine, expressed as a percentage. (alias
+.BR pmem ).
T}
args COMMAND T{
command with all its arguments as a string. Modifications to the arguments
-may be shown. The output in this column may contain spaces.
-A\ process marked <defunct> is partly dead, waiting
-to be fully destroyed by its parent. Sometimes the process args
-will be unavailable; when this happens, \fBps\fR will instead
-print the executable name in brackets.
-(alias\ \fBcmd\fR,\ \fBcommand\fR). See also the \fBcomm\fR format
-keyword, the \fB\-f\fR option, and the \fBc\fR option.
+may be shown. The output in this column may contain spaces. A process
+marked <defunct> is partly dead, waiting to be fully destroyed by its parent.
+Sometimes the process args will be unavailable; when this happens,
+.B ps
+will instead print the executable name in brackets. (alias
+.BR cmd , \ command ).
+See also the
+.B comm
+format keyword, the
+.B \-f
+option, and the
+.B c
+option.
.br
-When specified last, this column will extend to the edge of the display.
-If \fBps\fR can not determine display width, as when output is redirected
-(piped) into a file or another command, the output width is undefined
-(it may be 80, unlimited, determined by the \fBTERM\fR variable, and so on).
-The \fBCOLUMNS\fR environment variable or \fB\-\-cols\fR option may
-be used to exactly determine the width in this case.
-The \fBw\fR or \fB\-w\fR option may be also be used to adjust width.
+When specified last, this column will extend to the edge of the display. If
+.B ps
+can not determine display width, as when output is redirected (piped) into a
+file or another command, the output width is undefined (it may be 80,
+unlimited, determined by the
+.B TERM
+variable, and so on). The
+.B COLUMNS
+environment variable or
+.B \-\-cols
+option may be used to exactly determine the width in this case. The
+.B w
+or
+.B \-w
+option may be also be used to adjust width.
T}
blocked BLOCKED T{
-mask of the blocked signals, see \fIsignal\fR(7).
-According to the width of the field,
-a\ 32 or 64\-bit mask in hexadecimal format is displayed.
-(alias\ \fBsig_block\fR,\ \fBsigmask\fR).
+mask of the blocked signals, see
+.IR signal (7).
+According to the width of the field, a 32 or 64\-bit mask in hexadecimal
+format is displayed. (alias
+.BR sig_block , \ sigmask ).
T}
bsdstart START T{
-time the command started. If the process was started less
-than 24 hours ago, the output format is "\ HH:MM",
-else it is "Mmm\ dd"
-(where Mmm is the three letters of the month).
-See also \fBlstart\fR, \fBstart\fR, \fBstart_time\fR, and \fBstime\fR.
+time the command started. If the process was started less than 24 hours ago,
+the output format is "\ HH:MM", else it is " Mmm:SS" (where Mmm is the three
+letters of the month). See also
+.BR lstart , \ start , \ start_time ", and" \ stime .
T}
bsdtime TIME T{
-accumulated cpu time, user\ +\ system. The display format is usually
+accumulated cpu time, user + system. The display format is usually
"MMM:SS", but can be shifted to the right if the process used more than 999
minutes of cpu time.
T}
c C T{
-processor utilization. Currently, this is the integer value of
-the percent usage over the lifetime of the process. (see\ \fB%cpu\fR).
+processor utilization. Currently, this is the integer value of the percent
+usage over the lifetime of the process. (see
+.BR %cpu ).
T}
caught CAUGHT T{
-mask of the caught signals, see \fIsignal\fR(7). According to the
-width of the field, a 32 or 64 bits mask in hexadecimal format is
-displayed. (alias\ \fBsig_catch\fR,\ \fBsigcatch\fR).
+mask of the caught signals, see
+.IR signal (7).
+According to the width of the field, a 32 or 64 bits mask in hexadecimal
+format is displayed. (alias
+.BR sig_catch , \ sigcatch ).
T}
cgroup CGROUP T{
@@ -910,9 +1082,10 @@ display control groups to which the process belongs.
T}
class CLS T{
-scheduling class of the process. (alias\ \fBpolicy\fR,\ \fBcls\fR).
+scheduling class of the process. (alias
+.BR policy , \ cls ).
Field's possible values are:
-.br
+.IP "" 2
\- not reported
.br
TS SCHED_OTHER
@@ -931,9 +1104,10 @@ IDL SCHED_IDLE
T}
cls CLS T{
-scheduling class of the process. (alias\ \fBpolicy\fR,\ \fBclass\fR).
+scheduling class of the process. (alias
+.BR policy , \ cls ).
Field's possible values are:
-.br
+.IP "" 2
\- not reported
.br
TS SCHED_OTHER
@@ -952,47 +1126,68 @@ IDL SCHED_IDLE
T}
cmd CMD T{
-see \fBargs\fR. (alias\ \fBargs\fR,\ \fBcommand\fR).
+see
+.BR args .
+(alias
+.BR args , \ command ).
T}
comm COMMAND T{
-command name (only\ the executable\ name). Modifications to the command
-name will not be shown. A\ process marked <defunct> is partly dead, waiting
-to be fully destroyed by its parent. The output in this
-column may contain spaces. (alias\ \fBucmd\fR,\ \fBucomm\fR).
-See also the \fBargs\fR format
-keyword, the \fB\-f\fR option, and the \fBc\fR option.
+command name (only the executable name). Modifications to the command name
+will not be shown. A process marked <defunct> is partly dead, waiting to be
+fully destroyed by its parent. The output in this column may contain spaces.
+(alias
+.BR ucmd , \ ucomm ).
+See also the
+.B args format keyword,
+the
+.B \-f
+option, and the
+.B c
+option.
.br
-When specified last, this column will extend to the edge of the display.
-If \fBps\fR can not determine display width, as when output is redirected
-(piped) into a file or another command, the output width is undefined
-(it may be 80, unlimited, determined by the \fBTERM\fR variable, and so on).
-The \fBCOLUMNS\fR environment variable or \fB\-\-cols\fR option may
-be used to exactly determine the width in this case.
-The \fBw\fR or \fB\-w\fR option may be also be used to adjust width.
+When specified last, this column will extend to the edge of the display. If
+.B ps
+can not determine display width, as when output is redirected (piped) into a
+file or another command, the output width is undefined (it may be 80,
+unlimited, determined by the
+.B TERM
+variable, and so on). The
+.B COLUMNS
+environment variable or
+.B \-\-cols
+option may be used to exactly determine the width in this case. The
+.BR w \ or \ \-w
+option may be also be used to adjust width.
T}
command COMMAND T{
-see \fBargs\fR. (alias\ \fBargs\fR,\ \fBcmd\fR).
+See
+.BR args .
+(alias
+.BR args , \ command ).
T}
cp CP T{
-per\-mill (tenths of a percent) CPU usage. (see\ \fB%cpu\fR).
+per\-mill (tenths of a percent) CPU usage. (see
+.BR %cpu ).
T}
cputime TIME T{
-cumulative CPU time, "[DD\-]hh:mm:ss" format. (alias\ \fBtime\fR).
+cumulative CPU time, "[DD\-]hh:mm:ss" format. (alias
+.BR time ).
T}
egid EGID T{
-effective group ID number of the process as a decimal integer.
-(alias\ \fBgid\fR).
+effective group ID number of the process as a decimal integer. (alias
+.BR gid ).
T}
egroup EGROUP T{
-effective group ID of the process. This will be the textual group ID,
-if it can be obtained and the field width permits, or a decimal
-representation otherwise. (alias\ \fBgroup\fR).
+effective group ID of the process. This will be the textual group ID, if it
+can be obtained and the field width permits, or a decimal representation
+otherwise. (alias
+.BR group ).
T}
eip EIP T{
@@ -1004,97 +1199,114 @@ stack pointer.
T}
etime ELAPSED T{
-elapsed time since the process was started,
-in\ the form\ [[DD\-]hh:]mm:ss.
+elapsed time since the process was started, in the form [[DD\-]hh:]mm:ss.
T}
etimes ELAPSED T{
-elapsed time since the process was started,
-in\ seconds.
+elapsed time since the process was started, in seconds.
T}
euid EUID T{
-effective user\ ID (alias\ \fBuid\fR).
+effective user ID (alias
+.BR uid ).
T}
euser EUSER T{
-effective user\ name. This will be the textual
-user\ ID, if\ it can be obtained and the field width permits,
-or\ a\ decimal representation otherwise.
-The\ \fBn\fR\ option can be used
-to force the decimal representation.
-(alias\ \fBuname\fR,\ \fBuser\fR).
+effective user name. This will be the textual user ID, if it can be obtained
+and the field width permits, or a decimal representation otherwise. The
+.B n
+option can be used to force the decimal representation. (alias
+.BR uname , \ user ).
T}
f F T{
-flags associated with the process, see the \fBPROCESS FLAGS\fR section.
-(alias\ \fBflag\fR,\ \fBflags\fR).
+flags associated with the process, see the
+.B PROCESS FLAGS
+section. (alias
+.BR flag , \ flags ).
T}
fgid FGID T{
-filesystem access group\ ID. (alias\ \fBfsgid\fR).
+filesystem access group\ ID. (alias
+.BR fsgid ).
T}
fgroup FGROUP T{
-filesystem access group\ ID.
-This will be the textual group\ ID, if\ it can be obtained
-and the field width permits,
-or\ a\ decimal representation otherwise.
-(alias\ \fBfsgroup\fR).
+filesystem access group ID. This will be the textual group ID, if it can
+be obtained and the field width permits, or a decimal representation
+otherwise. (alias
+.BR fsgroup ).
T}
flag F T{
-see\ \fBf\fR. (alias\ \fBf\fR,\ \fBflags\fR).
+see
+.BR f .
+(alias
+.BR f , \ flags ).
T}
flags F T{
-see\ \fBf\fR. (alias\ \fBf\fR,\ \fBflag\fR).
+see
+.BR f .
+(alias
+.BR f , \ flag ).
T}
fname COMMAND T{
-first 8 bytes of the base name of the process's executable file.
-The output in this column may contain spaces.
+first 8 bytes of the base name of the process's executable file. The output
+in this column may contain spaces.
T}
fuid FUID T{
-filesystem access user\ ID. (alias\ \fBfsuid\fR).
+filesystem access user ID. (alias
+.BR fsuid ).
T}
fuser FUSER T{
-filesystem access user\ ID. This will be the textual user\ ID,
-if\ it can be obtained and the field width permits,
-or\ a\ decimal representation otherwise.
+filesystem access user ID. This will be the textual user ID, if it can be
+obtained and the field width permits, or a decimal representation otherwise.
T}
gid GID T{
-see\ \fBegid\fR. (alias\ \fBegid\fR).
+see
+.BR egid .
+(alias
+.BR egid ).
T}
group GROUP T{
-see\ \fBegroup\fR. (alias\ \fBegroup\fR).
+see
+.BR egroup .
+(alias
+.BR egroup ).
T}
ignored IGNORED T{
-mask of the ignored signals, see \fIsignal\fR(7). According to the
-width of the field, a\ 32 or 64\ bits mask in hexadecimal format
-is displayed. (alias \fBsig_ignore\fR, \fBsigignore\fR).
+mask of the ignored signals, see
+.IR signal (7).
+According to the width of the field, a 32 or 64 bits mask in hexadecimal
+format is displayed. (alias
+.BR sig_ignore , \ sigignore ).
T}
label LABEL T{
-security label, most commonly used for SE\ Linux context data.
-This is for the \fIMandatory Access Control\fR ("MAC") found on
-high\-security systems.
+security label, most commonly used for SE Linux context data. This is for
+the
+.I Mandatory Access Control
+("MAC") found on high\-security systems.
T}
lstart STARTED T{
-time the command started.
-See also \fBbsdstart\fR, \fBstart\fR, \fBstart_time\fR, and \fBstime\fR.
+time the command started. See also
+.BR bsdstart , \ start , \ start_time ", and" \ stime .
T}
lwp LWP T{
-light weight process (thread) ID of the dispatchable entity
-(alias\ \fBspid\fR,\ \fBtid\fR).
-See \fBtid\fR for additional information.
+light weight process (thread) ID of the dispatchable entity (alias
+.BR spid , \ tid ).
+See
+.B tid
+for additional information.
T}
maj_flt MAJFLT T{
@@ -1106,58 +1318,81 @@ The number of minor page faults that have occured with this process.
T}
ni NI T{
-nice value. This ranges from 19 (nicest) to \-20 (not\ nice to\ others),
-see\ \fInice\fR(1). (alias\ \fBnice\fR).
+nice value. This ranges from 19 (nicest) to \-20 (not nice to others),
+see
+.IR nice (1).
+(alias
+.BR nice ).
T}
nice NI T{
-see\ \fBni\fR. (alias\ \fBni\fR).
+see
+.BR ni . (alias
+.BR ni ).
T}
nlwp NLWP T{
-number of lwps (threads) in the process. (alias\ \fBthcount\fR).
+number of lwps (threads) in the process. (alias
+.BR thcount ).
T}
nwchan WCHAN T{
-address of the kernel function where the process is sleeping
-(use \fBwchan\fR if you want the kernel function name).
-Running tasks will display a dash ('\-') in this column.
+address of the kernel function where the process is sleeping (use
+.B wchan
+if you want the kernel function name). Running tasks will display a dash
+('\-') in this column.
T}
pcpu %CPU T{
-see\ \fB%cpu\fR. (alias\ \fB%cpu\fR).
+see
+.BR %cpu .
+(alias
+.BR %cpu ).
T}
pending PENDING T{
-mask of the pending signals. See\ \fIsignal\fR(7). Signals pending on
-the process are distinct from signals pending on individual threads.
-Use the \fBm\fR option or the \fB\-m\fR option to see both.
-According to the width of the field, a\ 32 or 64\ bits mask in
-hexadecimal format is displayed. (alias\ \fBsig\fR).
+mask of the pending signals. See
+.IR signal (7).
+Signals pending on the process are distinct from signals pending on
+individual threads. Use the
+.B m
+option or the
+.B \-m
+option to see both. According to the width of the field, a 32 or 64 bits
+mask in hexadecimal format is displayed. (alias
+.BR sig ).
T}
pgid PGID T{
-process group\ ID or, equivalently, the process\ ID of the
-process group leader. (alias\ \fBpgrp\fR).
+process group ID or, equivalently, the process ID of the process group
+leader. (alias
+.BR pgrp ).
T}
pgrp PGRP T{
-see\ \fBpgid\fR. (alias\ \fBpgid\fR).
+see
+.BR pgid .
+(alias
+.BR pgid ).
T}
pid PID T{
-a number representing the process ID
-(alias\ \fBtgid\fR).
+a number representing the process ID (alias
+.BR tgid ).
T}
pmem %MEM T{
-see\ \fB%mem\fR. (alias\ \fB%mem\fR).
+see
+.BR %mem .
+(alias
+.BR %mem ).
T}
policy POL T{
-scheduling class of the process. (alias\ \fBclass\fR,\ \fBcls\fR).
+scheduling class of the process. (alias
+.BR class , \ cls ).
Possible values are:
-.br
+.IP "" 2
\- not reported
.br
TS SCHED_OTHER
@@ -1180,7 +1415,7 @@ parent process ID.
T}
pri PRI T{
-priority of the process. Higher number means lower priority.
+priority of the process. Higher number means lower priority.
T}
psr PSR T{
@@ -1192,23 +1427,28 @@ real group ID.
T}
rgroup RGROUP T{
-real group name. This will be the textual group\ ID, if\ it can be
-obtained and the field width permits,
-or\ a\ decimal representation otherwise.
+real group name. This will be the textual group ID, if it can be obtained
+and the field width permits, or a decimal representation otherwise.
T}
rss RSS T{
-resident set size, the non\-swapped physical memory that
-a task has used (in\ kiloBytes).
-(alias\ \fBrssize\fR,\ \fBrsz\fR).
+resident set size, the non\-swapped physical memory that a task has used (in\
+kiloBytes). (alias
+.BR rssize , \ rsz ).
T}
rssize RSS T{
-see\ \fBrss\fR. (alias\ \fBrss\fR,\ \fBrsz\fR).
+see
+.BR rss .
+(alias
+.BR rss , \ rsz ).
T}
rsz RSZ T{
-see\ \fBrss\fR. (alias\ \fBrss\fR,\ \fBrssize\fR).
+see
+.BR rss .
+(alias
+.BR rss , \ rssize ).
T}
rtprio RTPRIO T{
@@ -1216,78 +1456,95 @@ realtime priority.
T}
ruid RUID T{
-real user\ ID.
+real user ID.
T}
ruser RUSER T{
-real user\ ID. This will be the textual user\ ID,
-if\ it can be obtained and the field width permits,
-or\ a\ decimal representation otherwise.
+real user ID. This will be the textual user ID, if it can be obtained and
+the field width permits, or a decimal representation otherwise.
T}
s S T{
-minimal state display (one\ character).
-See\ section \fBPROCESS STATE CODES\fR for the different values.
-See\ also \fBstat\fR if you want additional
-information displayed. (alias\ \fBstate\fR).
+minimal state display (one character). See section
+.B PROCESS STATE CODES
+for the different values. See also
+.B stat
+if you want additional information displayed. (alias
+.BR state ).
T}
sched SCH T{
scheduling policy of the process. The policies SCHED_OTHER (SCHED_NORMAL),
SCHED_FIFO, SCHED_RR, SCHED_BATCH, SCHED_ISO, and SCHED_IDLE are respectively
-displayed as 0,\ 1,\ 2,\ 3,\ 4,\ and\ 5.
+displayed as 0, 1, 2, 3, 4, and 5.
T}
sess SESS T{
-session\ ID or, equivalently, the process\ ID of the session\ leader.
-(alias\ \fBsession\fR,\ \fBsid\fR).
+session ID or, equivalently, the process ID of the session leader. (alias
+.BR session , \ sid ).
T}
sgi_p P T{
-processor that the process is currently executing on.
-Displays "*" if the process is not currently running or runnable.
+processor that the process is currently executing on. Displays "*" if the
+process is not currently running or runnable.
T}
sgid SGID T{
-saved group\ ID.
-(alias\ \fBsvgid\fR).
+saved group ID. (alias
+.BR svgid ).
T}
sgroup SGROUP T{
-saved group\ name. This will be the textual group\ ID,
-if\ it can be obtained and the field width permits,
-or\ a\ decimal representation otherwise.
+saved group name. This will be the textual group ID, if it can be obtained
+and the field width permits, or a decimal representation otherwise.
T}
sid SID T{
-see\ \fBsess\fR. (alias\ \fBsess\fR,\ \fBsession\fR).
+see
+.BR sess .
+(alias
+.BR sess , \ session ).
T}
sig PENDING T{
-see\ \fBpending\fR. (alias\ \fBpending\fR,\ \fBsig_pend\fR).
+see
+.BR pending .
+(alias
+.BR pending , \ sig_pend ).
T}
sigcatch CAUGHT T{
-see\ \fBcaught\fR. (alias\ \fBcaught\fR,\ \fBsig_catch\fR).
+see
+.BR caught .
+(alias
+.BR caught , \ sig_catch ).
T}
sigignore IGNORED T{
-see\ \fBignored\fR. (alias\ \fBignored\fR,\ \fBsig_ignore\fR).
+see
+.BR ignored .
+(alias
+.BR ignored , \ sig_ignore ).
T}
sigmask BLOCKED T{
-see\ \fBblocked\fR. (alias\ \fBblocked\fR,\ \fBsig_block\fR).
+see
+.BR blocked .
+(alias
+.BR blocked , \ sig_block ).
T}
size SIZE T{
-approximate amount of swap space that would be required
-if the process were to dirty all writable pages and then
-be swapped out.
-This number is very\ rough!
+approximate amount of swap space that would be required if the process were
+to dirty all writable pages and then be swapped out. This number is very
+rough!
T}
spid SPID T{
-see \fBlwp\fR. (alias\ \fBlwp\fR,\ \fBtid\fR).
+see
+.BR lwp .
+(alias
+.BR lwp , \ tid ).
T}
stackp STACKP T{
@@ -1295,159 +1552,186 @@ address of the bottom (start) of stack for the process.
T}
start STARTED T{
-time the command started.
-If the process was started less than 24 hours ago,
-the output format is "HH:MM:SS",
-else it is "\ \ <mm\ dd"
-(where Mmm is a three\-letter month\ name).
-See also \fBlstart\fR, \fBbsdstart\fR, \fBstart_time\fR, and \fBstime\fR.
+time the command started. If the process was started less than 24 hours ago,
+the output format is "HH:MM:SS", else it is "\ \ Mmm\ dd" (where Mmm is a
+three\-letter month name). See also
+.BR lstart , \ bsdstart , \ start_time ", and" \ stime .
T}
start_time START T{
-starting time or date of the process.
-Only the year will be displayed if the process was not
-started the same year \fBps\fR was invoked,
-or\ "MmmDD" if\ it was not started the same day,
-or\ "HH:MM" otherwise.
-See also \fBbsdstart\fR, \fBstart\fR, \fBlstart\fR, and \fBstime\fR.
+starting time or date of the process. Only the year will be displayed if the
+process was not started the same year
+.B ps
+was invoked, or "MmmDD" if it was not started the same day, or "HH:MM"
+otherwise. See also
+.BR bsdstart , \ start , \ lstart ", and" \ stime .
T}
stat STAT T{
-multi\-character process state.
-See\ section \fBPROCESS STATE CODES\fR
-for the different values meaning.
-See also \fBs\fR and \fBstate\fR if you just want
-the first character displayed.
+multi\-character process state. See section
+.B PROCESS STATE CODES
+for the different values meaning. See also
+.BR s \ and \ state
+if you just want the first character displayed.
T}
state S T{
-see\ \fBs\fR. (alias\ \fBs\fR).
+see
+.BR s ". (alias" \ s ).
T}
suid SUID T{
-saved user\ ID. (alias\ \fBsvuid\fR).
+saved user ID. (alias
+.BR svuid ).
T}
supgid SUPGID T{
-group ids of supplementary groups, if any.
-See
+group ids of supplementary groups, if any. See
.BR getgroups (2).
T}
supgrp SUPGRP T{
-group names of supplementary groups, if any.
-See
+group names of supplementary groups, if any. See
.BR getgroups (2).
T}
suser SUSER T{
-saved user name. This will be the textual user\ ID,
-if\ it can be obtained and the field width permits,
-or\ a\ decimal representation otherwise.
-(alias\ \fBsvuser\fR).
+saved user name. This will be the textual user ID, if it can be obtained and
+the field width permits, or a decimal representation otherwise. (alias
+.BR svuser ).
T}
svgid SVGID T{
-see\ \fBsgid\fR. (alias\ \fBsgid\fR).
+see
+.BR sgid .
+(alias
+.BR sgid ).
T}
svuid SVUID T{
-see\ \fBsuid\fR. (alias\ \fBsuid\fR).
+see
+.BR suid .
+(alias
+.BR suid ).
T}
sz SZ T{
-size in physical pages of the core image of the process.
-This includes text, data, and stack space.
-Device mappings are currently excluded; this is subject to change.
-See \fBvsz\fR and \fBrss\fR.
+size in physical pages of the core image of the process. This includes text,
+data, and stack space. Device mappings are currently excluded; this is
+subject to change. See
+.BR vsz \ and \ rss .
T}
tgid TGID T{
-a number representing the thread group to which a task
-belongs (alias\ \fBpid\fR).
+a number representing the thread group to which a task belongs (alias
+.BR pid ).
It is the process ID of the thread group leader.
T}
thcount THCNT T{
-see \fBnlwp\fR. (alias\ \fBnlwp\fR).
+see
+.BR nlwp .
+(alias
+.BR nlwp ).
number of kernel threads owned by the process.
T}
tid TID T{
-the unique number representing a dispatacable entity
-(alias\ \fBlwp\fR,\ \fBspid\fR).
-This value may also appear as: a process ID (pid);
-a process group ID (pgrp);
-a session ID for the session leader (sid);
-a thread group ID for the thread group leader (tgid);
-and a tty process group ID for the process group leader (tpgid).
+the unique number representing a dispatacable entity (alias
+.BR lwp , \ spid ).
+This value may also appear as: a process ID (pid); a process group ID (pgrp);
+a session ID for the session leader (sid); a thread group ID for the thread
+group leader (tgid); and a tty process group ID for the process group leader
+(tpgid).
T}
time TIME T{
-cumulative CPU\ time, "[DD\-]HH:MM:SS" format. (alias\ \fBcputime\fR).
+cumulative CPU\ time, "[DD\-]HH:MM:SS" format. (alias
+.BR cputime ).
T}
tname TTY T{
-controlling tty (terminal).
-(alias\ \fBtt\fR,\ \fBtty\fR).
+controlling tty (terminal). (alias
+.BR tt , \ tty ).
T}
tpgid TPGID T{
-ID of the foreground process group on the tty (terminal) that
-the process is connected to, or \-1 if the process is not connected
-to a tty.
+ID of the foreground process group on the tty (terminal) that the process is
+connected to, or \-1 if the process is not connected to a tty.
T}
tt TT T{
-controlling tty (terminal). (alias\ \fBtname\fR,\ \fBtty\fR).
+controlling tty (terminal). (alias
+.BR tname , \ tty ).
T}
tty TT T{
-controlling tty (terminal). (alias\ \fBtname\fR,\ \fBtt\fR).
+controlling tty (terminal). (alias
+.BR tname , \ tt ).
T}
ucmd CMD T{
-see \fBcomm\fR. (alias\ \fBcomm\fR,\ \fBucomm\fR).
+see
+.BR comm .
+(alias
+.BR comm , \ ucomm ).
T}
ucomm COMMAND T{
-see \fBcomm\fR. (alias\ \fBcomm\fR,\ \fBucmd\fR).
+see
+.BR comm .
+(alias
+.BR comm , \ ucmd ).
T}
uid UID T{
-see \fBeuid\fR. (alias\ \fBeuid\fR).
+see
+.BR euid .
+(alias
+.BR euid ).
T}
uname USER T{
-see \fBeuser\fR. (alias\ \fBeuser\fR,\ \fBuser\fR).
+see
+.BR euser .
+(alias
+.BR euser , \ user ).
T}
user USER T{
-see \fBeuser\fR. (alias\ \fBeuser\fR,\ \fBuname\fR).
+see
+.BR euser .
+(alias
+.BR euser , \ uname ).
T}
vsize VSZ T{
-see \fBvsz\fR. (alias\ \fBvsz\fR).
+see
+.BR vsz .
+(alias
+.BR vsz ).
T}
vsz VSZ T{
-virtual memory size of the process in KiB (1024\-byte\ units).
-Device mappings are currently excluded; this is subject to change.
-(alias\ \fBvsize\fR).
+virtual memory size of the process in KiB (1024\-byte units). Device
+mappings are currently excluded; this is subject to change. (alias
+.BR vsize ).
T}
wchan WCHAN T{
-name of the kernel function in which the process is sleeping,
-a\ "\-"\ if the process is running,
-or a "*"\ if the process is multi\-threaded and
-\fBps\fR is not displaying threads.
+name of the kernel function in which the process is sleeping, a "\-" if the
+process is running, or a "*" if the process is multi\-threaded and
+.B ps
+is not displaying threads.
T}
+
.TE
.\" #######################################################################
.PP
.PP
.SH "ENVIRONMENT VARIABLES"
-The following environment variables could affect \fBps\fR:
+The following environment variables could affect
+.BR ps :
.TP 3
.B COLUMNS
Override default display width.
@@ -1456,12 +1740,14 @@ Override default display width.
Override default display height.
.TP
.B PS_PERSONALITY
-Set to one of posix, old, linux, bsd, sun, digital...
-(see\ section\ \fBPERSONALITY\fR\ below).
+Set to one of posix, old, linux, bsd, sun, digital... (see section
+.B PERSONALITY
+below).
.TP
.B CMD_ENV
-Set to one of posix, old, linux, bsd, sun, digital...
-(see\ section\ \fBPERSONALITY\fR\ below).
+Set to one of posix, old, linux, bsd, sun, digital... (see section
+.B PERSONALITY
+below).
.TP
.B I_WANT_A_BROKEN_PS
Force obsolete command line interpretation.
@@ -1474,8 +1760,14 @@ Not currently supported.
.TP
.B PS_FORMAT
Default output format override. You may set this to a format
-string of the type used for the \fB\-o\fR option.
-The \fBDefSysV\fR and \fBDefBSD\fR values are particularly useful.
+string of the type used for the
+.B \-o
+option.
+The
+.B DefSysV
+and
+.B DefBSD
+values are particularly useful.
.TP
.B PS_SYSMAP
Default namelist (System.map) location.
@@ -1487,27 +1779,29 @@ Default namelist (System.map) location.
Don't find excuses to ignore bad "features".
.TP
.B POSIX2
-When set to "on", acts as \fBPOSIXLY_CORRECT\fR.
+When set to "on", acts as
+.BR POSIXLY_CORRECT .
.TP
.B UNIX95
Don't find excuses to ignore bad "features".
.TP
.B _XPG
-Cancel \fBCMD_ENV\fI=irix\fR non\-standard behavior.
-.PP
-In general, it\ is a bad idea to set these variables.
-The one exception is \fBCMD_ENV\fR or \fBPS_PERSONALITY\fR,
-which could be set to Linux for normal systems.
-Without that setting,
-\fBps\fR follows the useless and bad parts of the Unix98 standard.
+Cancel \fBCMD_ENV\fR=\fIirix\fR non\-standard behavior.
.PP
+In general, it is a bad idea to set these variables. The one exception is
+.B CMD_ENV
+or
+.BR PS_PERSONALITY ,
+which could be set to Linux for normal systems. Without that setting,
+.B ps
+follows the useless and bad parts of the Unix98 standard.
.PP
.SH "PERSONALITY"
.TS
l l.
390 like the OS/390 OpenEdition \fBps\fR
aix like AIX \fBps\fR
-bsd like FreeBSD \fBps\fR (totally\ non\-standard)
+bsd like FreeBSD \fBps\fR (totally non\-standard)
compaq like Digital Unix \fBps\fR
debian like the old Debian \fBps\fR
digital like Tru64 (was Digital\ Unix, was OSF/1) \fBps\fR
@@ -1515,18 +1809,18 @@ gnu like the old Debian \fBps\fR
hp like HP\-UX \fBps\fR
hpux like HP\-UX \fBps\fR
irix like Irix \fBps\fR
-linux ***** RECOMMENDED *****
-old like the original Linux \fBps\fR (totally\ non\-standard)
+linux ***** \fBrecommended\fR *****
+old like the original Linux \fBps\fR (totally non\-standard)
os390 like OS/390 Open Edition \fBps\fR
posix standard
s390 like OS/390 Open Edition \fBps\fR
sco like SCO \fBps\fR
sgi like Irix \fBps\fR
solaris2 like Solaris 2+ (SunOS 5) \fBps\fR
-sunos4 like SunOS 4 (Solaris 1) \fBps\fR (totally\ non\-standard)
+sunos4 like SunOS 4 (Solaris 1) \fBps\fR (totally non\-standard)
svr4 standard
sysv standard
-tru64 like Tru64 (was Digital\ Unix, was OSF/1) \fBps\fR
+tru64 like Tru64 (was Digital Unix, was OSF/1) \fBps\fR
unix standard
unix95 standard
unix98 standard
@@ -1534,11 +1828,16 @@ unix98 standard
.PP
.PP
.SH "SEE ALSO"
-\fBtop\fR(1), \fBpgrep\fR(1), \fBpstree\fR(1), \fBproc\fR(5).
+.BR pgrep (1),
+.BR pstree (1),
+.BR top (1),
+.BR proc (5).
.PP
.PP
.SH STANDARDS
-This \fBps\fR conforms to:
+This
+.B ps
+conforms to:
.PP
.PD 0
.IP 1 4
@@ -1554,16 +1853,34 @@ ISO/IEC 9945:2003
.PD
.PP
.SH AUTHOR
-\fBps\fR was originally written by Branko Lankester <lankeste@fwi.uva.nl>. Michael
-K. Johnson <johnsonm@redhat.com> re\-wrote it significantly to use the proc
-filesystem, changing a few things in the process. Michael Shields
-<mjshield@nyx.cs.du.edu> added the pid\-list feature. Charles Blake
-<cblake@bbn.com> added multi\-level sorting, the dirent\-style library, the
-device name\-to\-number mmaped database, the approximate binary search
-directly on System.map, and many code and documentation cleanups. David
-Mossberger\-Tang wrote the generic BFD support for psupdate. Albert Cahalan
-<albert@users.sf.net> rewrote ps for full Unix98 and BSD support, along with
-some ugly hacks for obsolete and foreign syntax.
-
-Please send bug reports to <procps@freelists.org>.
-No\ subscription is required or suggested.
+.B ps
+was originally written by
+.UR lankeste\@\:fwi.\:uva.\:nl
+Branko Lankester
+.UE .
+.UR johnsonm\@\:redhat.\:com
+Michael K. Johnson
+.UE
+re\-wrote it significantly to use the proc filesystem, changing a few things
+in the process.
+.UR mjshield\@\:nyx.\:cs.\:du.\:edu
+Michael Shields
+.UE
+added the pid\-list feature.
+.UR cblake\@\:bbn.\:com
+Charles Blake
+.UE
+added multi\-level sorting, the dirent\-style library, the device
+name\-to\-number mmaped database, the approximate binary search directly on
+System.map, and many code and documentation cleanups. David Mossberger\-Tang
+wrote the generic BFD support for psupdate.
+.URalbert\@\:users.\:sf.\:net
+Albert Cahalan
+.UE
+rewrote ps for full Unix98 and BSD support, along with some ugly hacks for
+obsolete and foreign syntax.
+.PP
+Please send bug reports to
+.UR procps\@\:freelists.\:org
+.UE .
+No subscription is required or suggested.
diff --git a/ps/select.c b/ps/select.c
index 2c52d02..6b8220d 100644
--- a/ps/select.c
+++ b/ps/select.c
@@ -59,7 +59,7 @@ const char *select_bits_setup(void){
simple_select = 0;
break;
default:
- return "Process selection options conflict.";
+ return _("Process selection options conflict.");
break;
}
return NULL;
@@ -83,7 +83,7 @@ static int proc_was_listed(proc_t *buf){
while(sn){
switch(sn->typecode){
default:
- printf("Internal error in ps! Please report this bug.\n");
+ printf(_("Internal error in ps! Please report this bug.\n"));
#define return_if_match(foo,bar) \
i=sn->n; while(i--) \
diff --git a/ps/sortformat.c b/ps/sortformat.c
index 82ee27c..663ffee 100644
--- a/ps/sortformat.c
+++ b/ps/sortformat.c
@@ -96,12 +96,12 @@ static void O_wrap(sf_node *sfn, int otype){
trailer = (otype=='b') ? "END_BSD" : "END_SYS5" ;
fnode = do_one_spec("pid",NULL);
- if(!fnode)fprintf(stderr,"Seriously crashing. Goodbye cruel world.\n");
+ if(!fnode)fprintf(stderr,_("Seriously crashing. Goodbye cruel world.\n"));
endp = sfn->f_cooked; while(endp->next) endp = endp->next; /* find end */
endp->next = fnode;
fnode = do_one_spec(trailer,NULL);
- if(!fnode) { fprintf(stderr,"Seriously crashing. Goodbye cruel world.\n"); exit(1); }
+ if(!fnode) { fprintf(stderr,_("Seriously crashing. Goodbye cruel world.\n")); exit(1); }
endp = fnode; while(endp->next) endp = endp->next; /* find end */
endp->next = sfn->f_cooked;
sfn->f_cooked = fnode;
@@ -136,7 +136,7 @@ static const char *aix_format_parse(sf_node *sfn){
items++;
c = *walk++;
if(c) goto initial;
- return "Improper AIX field descriptor.";
+ return _("Improper AIX field descriptor.");
looks_ok:
;
}
@@ -157,12 +157,12 @@ static const char *aix_format_parse(sf_node *sfn){
walk++;
if(!aix){
free(buf);
- return "Unknown AIX field descriptor.";
+ return _("Unknown AIX field descriptor.");
}
fnode = do_one_spec(aix->spec, aix->head);
if(!fnode){
free(buf);
- return "AIX field descriptor processing bug.";
+ return _("AIX field descriptor processing bug.");
}
} else {
int len;
@@ -279,7 +279,7 @@ out:
snprintf(
errbuf,
sizeof(errbuf),
- "Unknown user-defined format specifier \"%s\".",
+ _("Unknown user-defined format specifier \"%s\"."),
walk
);
}
@@ -305,10 +305,10 @@ out:
/* errors may cause a retry looking for AIX format codes */
if(0) unknown: err=errbuf;
- if(0) empty: err="Empty format list.";
- if(0) improper: err="Improper format list.";
- if(0) badwidth: err="Column widths must be unsigned decimal numbers.";
- if(0) notmacro: err="Can't set width for a macro (multi-column) format specifier.";
+ if(0) empty: err=_("Empty format list.");
+ if(0) improper: err=_("Improper format list.");
+ if(0) badwidth: err=_("Column widths must be unsigned decimal numbers.");
+ if(0) notmacro: err=_("Can't set width for a macro (multi-column) format specifier.");
if(strchr(sfn->sf,'%')) err = aix_format_parse(sfn);
return err;
}
@@ -361,7 +361,7 @@ static const char *long_sort_parse(sf_node *sfn){
case ' ': case ',': case '\t': case '\n': case '\0':
if(need_item){
free(buf);
- return "Improper sort list";
+ return _("Improper sort list");
}
need_item=1;
break;
@@ -372,12 +372,12 @@ static const char *long_sort_parse(sf_node *sfn){
} while (*++walk);
if(!items){
free(buf);
- return "Empty sort list.";
+ return _("Empty sort list.");
}
#ifdef STRICT_LIST
if(need_item){ /* can't have trailing deliminator */
free(buf);
- return "Improper sort list.";
+ return _("Improper sort list.");
}
#else
if(need_item){ /* allow 1 trailing deliminator */
@@ -393,7 +393,7 @@ static const char *long_sort_parse(sf_node *sfn){
snode = do_one_sort_spec(walk);
if(!snode){
free(buf);
- return "Unknown sort specifier.";
+ return _("Unknown sort specifier.");
}
endp = snode; while(endp->next) endp = endp->next; /* find end */
endp->next = sfn->s_cooked;
@@ -420,7 +420,7 @@ static const char *verify_short_sort(const char *arg){
int i;
const char *walk;
int tmp;
- if(strspn(arg,all) != strlen(arg)) return "Bad sorting code.";
+ if(strspn(arg,all) != strlen(arg)) return _("Bad sorting code.");
for(i=256; i--;) checkoff[i] = 0;
walk = arg;
for(;;){
@@ -431,13 +431,13 @@ static const char *verify_short_sort(const char *arg){
case '+':
case '-':
tmp = *(walk+1);
- if(!tmp || tmp=='+' || tmp=='-') return "Bad sorting code.";
+ if(!tmp || tmp=='+' || tmp=='-') return _("Bad sorting code.");
break;
case 'P':
- if(forest_type) return "PPID sort and forest output conflict.";
+ if(forest_type) return _("PPID sort and forest output conflict.");
/* fall through */
default:
- if(checkoff[tmp]) return "Bad sorting code."; /* repeated */
+ if(checkoff[tmp]) return _("Bad sorting code."); /* repeated */
/* ought to check against already accepted sort options */
checkoff[tmp] = 1;
break;
@@ -471,9 +471,9 @@ static const char *short_sort_parse(sf_node *sfn){
break;
default:
ss = search_shortsort_array(tmp);
- if(!ss) return "Unknown sort specifier.";
+ if(!ss) return _("Unknown sort specifier.");
snode = do_one_sort_spec(ss->spec);
- if(!snode) return "Unknown sort specifier.";
+ if(!snode) return _("Unknown sort specifier.");
snode->reverse = direction;
endp = snode; while(endp->next) endp = endp->next; /* find end */
endp->next = sfn->s_cooked;
@@ -509,14 +509,14 @@ static const char *parse_O_option(sf_node *sfn){
break;
case SF_U_O: /*** format ***/
/* Can have -l -f f u... set already_parsed_format like DEC does */
- if(already_parsed_format) return "option -O can not follow other format options.";
+ if(already_parsed_format) return _("option -O can not follow other format options.");
err = format_parse(sfn);
if(err) return err;
already_parsed_format = 1;
O_wrap(sfn,'u'); /* must wrap user format in default */
break;
case SF_B_O: /*** both ***/
- if(have_gnu_sort || already_parsed_sort) err = "Multiple sort options.";
+ if(have_gnu_sort || already_parsed_sort) err = _("Multiple sort options.");
else err = verify_short_sort(sfn->sf);
if(!err){ /* success as sorting code */
short_sort_parse(sfn);
@@ -524,7 +524,7 @@ static const char *parse_O_option(sf_node *sfn){
return NULL;
}
if(already_parsed_format){
- err = "option O is neither first format nor sort order.";
+ err = _("option O is neither first format nor sort order.");
break;
}
if(!format_parse(sfn)){ /* if success as format code */
@@ -534,12 +534,12 @@ static const char *parse_O_option(sf_node *sfn){
}
break;
case SF_G_sort: case SF_B_m: /*** sort ***/
- if(already_parsed_sort) err = "Multiple sort options.";
+ if(already_parsed_sort) err = _("Multiple sort options.");
else err = long_sort_parse(sfn);
already_parsed_sort = 1;
break;
default: /*** junk ***/
- return "Bug: parse_O_option got weirdness!";
+ return _("Bug: parse_O_option got weirdness!");
}
return err; /* could be NULL */
}
@@ -651,7 +651,7 @@ static int fmt_delete(const char *findme){
static const char *generate_sysv_list(void){
format_node *fn;
if((format_modifiers & FM_y) && !(format_flags & FF_Ul))
- return "Modifier -y without format -l makes no sense.";
+ return _("Modifier -y without format -l makes no sense.");
if(prefer_bsd_defaults){
if(format_flags) PUSH("cmd");
else PUSH("args");
@@ -754,7 +754,7 @@ const char *process_sf_options(int localbroken){
if(err) return err;
}
- if(format_list) printf("Bug: must reset the list first!\n");
+ if(format_list) printf(_("Bug: must reset the list first!\n"));
/* merge formatting info of sf_list into format_list here */
sf_walk = sf_list;
@@ -792,7 +792,7 @@ const char *process_sf_options(int localbroken){
// with sorting. Do the threads remain grouped, with sorting
// by process, or do the threads get sorted by themselves?
if(sort_list && (thread_flags&TF_no_sort)){
- return "Tell procps@freelists.org what you expected.";
+ return _("Tell PACKAGE_BUGREPORT what you expected.");
}
// If nothing else, try to use $PS_FORMAT before the default.
@@ -802,7 +802,7 @@ const char *process_sf_options(int localbroken){
if(tmp && *tmp){
const char *err;
sf_node sfn;
- if(thread_flags&TF_must_use) return "Tell procps@freelists.org what you want. (-L/-T, -m/m/H, and $PS_FORMAT)";
+ if(thread_flags&TF_must_use) return _("Tell PACKAGE_BUGREPORT what you want. (-L/-T, -m/m/H, and $PS_FORMAT)");
sfn.sf = tmp;
sfn.f_cooked = NULL;
err = format_parse(&sfn);
@@ -819,14 +819,14 @@ const char *process_sf_options(int localbroken){
return NULL;
}
// FIXME: prove that this won't be hit on valid bogus-BSD options
- fprintf(stderr, "Warning: $PS_FORMAT ignored. (%s)\n", err);
+ fprintf(stderr, _("Warning: $PS_FORMAT ignored. (%s)\n"), err);
}
}
if(format_list){
- if(format_flags) return "Conflicting format options.";
- if(format_modifiers) return "Can't use output modifiers with user-defined output";
- if(thread_flags&TF_must_use) return "-L/-T with H/m/-m and -o/-O/o/O is nonsense";
+ if(format_flags) return _("Conflicting format options.");
+ if(format_modifiers) return _("Can't use output modifiers with user-defined output");
+ if(thread_flags&TF_must_use) return _("-L/-T with H/m/-m and -o/-O/o/O is nonsense");
return NULL;
}
@@ -834,7 +834,7 @@ const char *process_sf_options(int localbroken){
const char *spec;
switch(format_flags){
- default: return "Conflicting format options.";
+ default: return _("Conflicting format options.");
/* These can be NULL, which enables SysV list generation code. */
case 0: spec=NULL; break;
@@ -884,9 +884,9 @@ const char *process_sf_options(int localbroken){
if(format_modifiers & FM_j){
fn = do_one_spec("pgid", NULL);
if(!fmt_add_after("PPID", fn)) if(!fmt_add_after("PID", fn))
- return "Internal error, no PID or PPID for -j option.";
+ return _("Internal error, no PID or PPID for -j option.");
fn = do_one_spec("sid", NULL);
- if(!fmt_add_after("PGID", fn)) return "Lost my PGID!";
+ if(!fmt_add_after("PGID", fn)) return _("Lost my PGID!");
}
if(format_modifiers & FM_y){
/* TODO: check for failure to do something, and complain if so */
@@ -899,15 +899,15 @@ const char *process_sf_options(int localbroken){
fmt_delete("NI");
fn = do_one_spec("class", NULL);
if(!fmt_add_after("PRI", fn))
- return "Internal error, no PRI for -c option.";
+ return _("Internal error, no PRI for -c option.");
fmt_delete("PRI"); /* we want a different one */
fn = do_one_spec("pri", NULL);
- if(!fmt_add_after("CLS", fn)) return "Lost my CLS!";
+ if(!fmt_add_after("CLS", fn)) return _("Lost my CLS!");
}
if(thread_flags & TF_U_T){
fn = do_one_spec("spid", NULL);
if(!fmt_add_after("PID", fn) && (thread_flags&TF_must_use))
- return "-T with H/-m/m but no PID for SPID to follow";
+ return _("-T with H/-m/m but no PID for SPID to follow");
}
if(thread_flags & TF_U_L){
fn = do_one_spec("lwp", NULL);
@@ -918,7 +918,7 @@ const char *process_sf_options(int localbroken){
if(fmt_add_after("PPID", fn)) goto did_lwp;
if(fmt_add_after("PID", fn)) goto did_lwp;
if(thread_flags&TF_must_use)
- return "-L with H/-m/m but no PID/PGID/SID/SESS for NLWP to follow";
+ return _("-L with H/-m/m but no PID/PGID/SID/SESS for NLWP to follow");
did_lwp:
fn = do_one_spec("nlwp", NULL);
fmt_add_after("%CPU", fn);
diff --git a/ps/stacktrace.c b/ps/stacktrace.c
index 79814bb..60b89f4 100644
--- a/ps/stacktrace.c
+++ b/ps/stacktrace.c
@@ -14,6 +14,8 @@
#include <sys/wait.h>
#include <sys/time.h>
+#include "common.h"
+
#define INTERACTIVE 0
#define STACK_TRACE 1
@@ -23,12 +25,12 @@ static int stack_trace_done;
/***********/
static void debug_stop(char **args){
execvp (args[0], args);
- perror ("exec failed");
+ perror (_("exec failed"));
_exit (0);
}
/***********/
-static void stack_trace_sigchld(int signum){
+static void stack_trace_sigchld(int signum __attribute__ ((__unused__))){
stack_trace_done = 1;
}
@@ -48,7 +50,7 @@ static void stack_trace(char **args){
signal(SIGCHLD, stack_trace_sigchld);
if((pipe (in_fd) == -1) || (pipe (out_fd) == -1)){
- perror ("could open pipe");
+ perror (_("could open pipe"));
_exit (0);
}
@@ -58,11 +60,11 @@ static void stack_trace(char **args){
close (1); dup (out_fd[1]); /* set the stdout to the out pipe */
close (2); dup (out_fd[1]); /* set the stderr to the out pipe */
execvp (args[0], args); /* exec gdb */
- perror ("exec failed");
+ perror (_("exec failed"));
_exit (0);
} else {
if(pid == (pid_t) -1){
- perror ("could not fork");
+ perror (_("could not fork"));
_exit (0);
}
}
@@ -126,7 +128,7 @@ void debug(int method, char *prog_name){
char *args[4] = { "gdb", NULL, NULL, NULL };
int x;
- snprintf (buf, 99, "%d", getpid ());
+ snprintf (buf, 16, "%d", getpid ());
args[1] = prog_name;
args[2] = buf;
@@ -135,17 +137,17 @@ void debug(int method, char *prog_name){
if(pid == 0){
switch (method){
case INTERACTIVE:
- fprintf (stderr, "debug_stop\n");
+ fprintf (stderr, _("debug_stop\n"));
debug_stop(args);
break;
case STACK_TRACE:
- fprintf (stderr, "stack_trace\n");
+ fprintf (stderr, _("stack_trace\n"));
stack_trace(args);
break;
}
_exit(0);
} else if(pid == (pid_t) -1){
- perror ("could not fork");
+ perror (_("could not fork"));
return;
}
@@ -154,7 +156,7 @@ void debug(int method, char *prog_name){
}
/************/
-static void stack_trace_sigsegv(int signum){
+static void stack_trace_sigsegv(int signum __attribute__ ((__unused__))){
debug(STACK_TRACE, stored_prog_name);
}
diff --git a/pwdx.1 b/pwdx.1
index 8491fef..0caec42 100644
--- a/pwdx.1
+++ b/pwdx.1
@@ -1,37 +1,32 @@
-'\" t
-.\" (The preceding line is a note to broken versions of man to tell
-.\" them to pre-process this man page with tbl)
.\" Man page for pwdx
.\" Licensed under version 2 of the GNU General Public License.
.\" Copyright 2004 Nicholas Miell.
.\" Based on the pmap(1) man page by Albert Cahalan.
.\"
-.TH PWDX 1 "September 8, 2004" "Linux" "Linux User's Manual"
+.TH PWDX "1" "June 2011" "procps-ng" "User Commands"
.SH NAME
pwdx \- report current working directory of a process
-
.SH SYNOPSIS
-.nf
-pwdx pids...
-pwdx -V
-.fi
-
-.SH DESCRIPTION
-The pwdx command reports the current working directory of a process or
-processes.
-
-.SH "GENERAL OPTIONS"
-.TS
-l l l.
--V show version Displays version of program.
-.TE
-
+.B pwdx
+[\fIoptions\fR] \fIpid\fR [...]
+.SH OPTIONS
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Output version information and exit.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Output help screen and exit.
.SH "SEE ALSO"
-ps(1) pgrep(1)
-
+.BR ps (1),
+.BR pgrep (1)
.SH STANDARDS
No standards apply, but pwdx looks an awful lot like a SunOS command.
-
.SH AUTHOR
-Nicholas Miell <nmiell@gmail.com> wrote pwdx in 2004. Please send bug
-reports to <procps@freelists.org>
+.UR nmiell\@gmail.com
+Nicholas Miell
+.UE
+wrote pwdx in 2004.
+.SH "REPORTING BUGS"
+Please send bug reports to
+.UR procps\@freelists.org
+.UE
diff --git a/pwdx.c b/pwdx.c
index 755c178..e4fcdd0 100644
--- a/pwdx.c
+++ b/pwdx.c
@@ -1,108 +1,113 @@
-// Copyright 2004 Nicholas Miell
-//
-// This file may be used subject to the terms and conditions of the
-// GNU Library General Public License Version 2 as published by the
-// Free Software Foundation.This program is distributed in the hope
-// that it will be useful, but WITHOUT ANY WARRANTY; without even the
-// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-// PURPOSE. See the GNU Library General Public License for more
-// details.
+/*
+ * Copyright 2004 Nicholas Miell
+ *
+ * This file may be used subject to the terms and conditions of the
+ * GNU Library General Public License Version 2 as published by the
+ * Free Software Foundation.This program is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU Library General Public License for more
+ * details.
+ */
+#include <errno.h>
+#include <getopt.h>
+#include <limits.h>
#include <stdio.h>
-#include <string.h>
#include <stdlib.h>
+#include <string.h>
#include <sys/types.h>
-#include <regex.h>
-#include <limits.h>
#include <unistd.h>
-#include <errno.h>
#include "proc/version.h"
+#include "c.h"
+#include "nls.h"
-static void die(const char *msg) NORETURN;
-static void die(const char *msg)
+static void __attribute__ ((__noreturn__)) usage(FILE * out)
{
- fputs(msg, stderr);
- exit(1);
-}
+ fputs(USAGE_HEADER, out);
+ fprintf(out, _(" %s [options] pid...\n"), program_invocation_short_name);
+ fputs(USAGE_OPTIONS, out);
+ fputs(USAGE_HELP, out);
+ fputs(USAGE_VERSION, out);
+ fprintf(out, USAGE_MAN_TAIL("pwdx(1)"));
-static void version(void) NORETURN;
-static void version(void)
-{
- printf("pwdx (%s)\n", procps_version);
- exit(0);
+ exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
-int main(int argc, char* argv[])
+int main(int argc, char *argv[])
{
- regex_t re;
- int i;
-
- if (argc < 2)
- die("Usage: pwdx pid...\n");
-
- // Allowed on the command line:
- //
- // --version
- // -V
- // /proc/nnnn
- // nnnn
- //
- // where nnnn is any number that doesn't begin with 0.
- //
- // If --version or -V are present, further arguments are ignored
- // completely.
-
- regcomp(&re, "^((/proc/+)?[1-9][0-9]*|-V|--version)$",
- REG_EXTENDED|REG_NOSUB);
-
- for (i = 1; i < argc; i++) {
- if (regexec(&re, argv[i], 0, NULL, 0) != 0) {
- /* Constant 27 is the length of the error string "pwdx: ... " */
- char buf[27 + strlen (argv[i]) + 1];
- snprintf(buf, sizeof buf, "pwdx: invalid process id: %s\n", argv[i]);
- buf[sizeof(buf)-1] = '\0';
- die(buf);
- }
- if (!strcmp("-V", argv[i]) || !strcmp("--version", argv[i]))
- version();
- }
-
- regfree(&re);
-
- int alloclen = 128;
- char *pathbuf = malloc(alloclen);
-
- for (i = 1; i < argc; i++) {
- char * s;
- int len;
- /* Constant 10 is the length of strings "/proc/" + "/cwd" + 1 */
- char buf[10 + strlen(argv[i]) + 1];
-
- // At this point, all arguments are in the form /proc/nnnn
- // or nnnn, so a simple check based on the first char is
- // possible
- if (argv[i][0] != '/')
- snprintf(buf, sizeof buf, "/proc/%s/cwd", argv[i]);
- else
- snprintf(buf, sizeof buf, "%s/cwd", argv[i]);
-
- // buf contains /proc/nnnn/cwd symlink name on entry, the
- // target of that symlink on return
- while ((len = readlink(buf, pathbuf, alloclen)) == alloclen) {
- alloclen *= 2;
- pathbuf = realloc(pathbuf, alloclen);
- }
-
- if (len < 0) {
- s = strerror(errno == ENOENT ? ESRCH : errno);
- } else {
- pathbuf[len] = 0;
- s = pathbuf;
- }
-
- printf("%s: %s\n", argv[i], s);
- }
-
- return 0;
+ char ch;
+ int retval = 0, i;
+ int alloclen = 128;
+ char *pathbuf;
+
+ static const struct option longopts[] = {
+ {"version", no_argument, 0, 'V'},
+ {"help", no_argument, 0, 'h'},
+ {NULL, 0, 0, 0}
+ };
+
+ setlocale (LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ while ((ch = getopt_long(argc, argv, "Vh", longopts, NULL)) != -1)
+ switch (ch) {
+ case 'V':
+ printf(PROCPS_NG_VERSION);
+ return EXIT_SUCCESS;
+ case 'h':
+ usage(stdout);
+ default:
+ usage(stderr);
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0)
+ usage(stderr);
+
+ pathbuf = malloc(alloclen);
+
+ for (i = 0; i < argc; i++) {
+ char *s;
+ ssize_t len;
+ /* Constant 10 is the length of strings "/proc/" + "/cwd" + 1 */
+ char buf[10 + strlen(argv[i]) + 1];
+
+ /*
+ * At this point, all arguments are in the form
+ * /proc/NNNN or NNNN, so a simple check based on
+ * the first char is possible
+ */
+ if (argv[i][0] != '/')
+ snprintf(buf, sizeof buf, "/proc/%s/cwd", argv[i]);
+ else
+ snprintf(buf, sizeof buf, "%s/cwd", argv[i]);
+
+ /*
+ * buf contains /proc/NNNN/cwd symlink name
+ * on entry, the target of that symlink on return
+ */
+ while ((len = readlink(buf, pathbuf, alloclen)) == alloclen) {
+ alloclen *= 2;
+ pathbuf = realloc(pathbuf, alloclen);
+ }
+
+ if (len < 0) {
+ s = strerror(errno == ENOENT ? ESRCH : errno);
+ retval = EXIT_FAILURE;
+ fprintf(stderr, "%s: %s\n", argv[i], s);
+ continue;
+ } else {
+ pathbuf[len] = 0;
+ s = pathbuf;
+ }
+
+ printf("%s: %s\n", argv[i], s);
+ }
+
+ return retval;
}
diff --git a/skill.1 b/skill.1
index 9289cc1..df1b5be 100644
--- a/skill.1
+++ b/skill.1
@@ -6,124 +6,109 @@
.\" Written by Albert Cahalan, converted to a man page by
.\" Michael K. Johnson
.\"
-.TH SKILL 1 "March 12, 1999" "Linux" "Linux User's Manual"
+.TH SKILL 1 "October 2011" "procps-ng" "User Commands"
.SH NAME
skill, snice \- send a signal or report process status
-
.SH SYNOPSIS
.B skill
-.RI [ "signal to send" ]
+.RI [ signal ]
.RI [ options ]
-.I process selection criteria
+.I expression
.br
.B snice
.RI [ "new priority" ]
.RI [ options ]
-.I process selection criteria
-
+.I expression
.SH DESCRIPTION
-These tools are probably obsolete and unportable. The command
-syntax is poorly defined. Consider using the killall, pkill,
-and pgrep commands instead.
-
-The default signal for skill is TERM. Use \-l or \-L to list available signals.
-Particularly useful signals include HUP, INT, KILL, STOP, CONT, and 0.
-Alternate signals may be specified in three ways: \-9 \-SIGKILL \-KILL.
-
-The default priority for snice is +4. (snice +4 ...)
-Priority numbers range from +20 (slowest) to \-20 (fastest).
-Negative priority numbers are restricted to administrative users.
-
-.SH "GENERAL OPTIONS"
-.TS
-lB l l.
-\-f fast mode This is not currently useful.
-\-i interactive use You will be asked to approve each action.
-\-v verbose output Display information about selected processes.
-\-w warnings enabled This is not currently useful.
-\-n no action This only displays the process ID.
-\-V show version Displays version of program.
-.TE
-
+These tools are obsolete and unportable. The command syntax is
+poorly defined. Consider using the killall, pkill, and pgrep
+commands instead.
+.PP
+The default signal for skill is TERM. Use \-l or \-L to list
+available signals. Particularly useful signals include HUP, INT,
+KILL, STOP, CONT, and 0. Alternate signals may be specified in three
+ways: \-9 \-SIGKILL \-KILL.
+.PP
+The default priority for snice is +4. Priority numbers range from
++20 (slowest) to \-20 (fastest). Negative priority numbers are
+restricted to administrative users.
+.SH OPTIONS
+.TP
+.BR \-f , \ \-\-fast
+Fast mode. This option has not been implemented.
+.TP
+.BR \-i , \ \-\-interactive
+Interactive use. You will be asked to approve each action.
+.TP
+.BR \-l , \ \-\-list
+List all signal names.
+.TP
+.BR \-L , \ \-\-table
+List all signal names in a nice table.
+.TP
+.BR \-n , \ \-\-no\-action
+No action; perform a simulation of events that would occur but do not
+actually change the system.
+.TP
+.BR \-v , \ \-\-verbose
+Verbose; explain what is being done.
+.TP
+.BR \-w , \ \-\-warnings
+Enable warnings. This option has not been implemented.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Display help text and exit.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Display version information.
+.PD
.SH "PROCESS SELECTION OPTIONS"
-Selection criteria can be: terminal, user, pid, command.
-The options below may be used to ensure correct interpretation.
-Do not blame Albert for this interesting interface.
-.TS
-lB l.
-\-t The next argument is a terminal (tty or pty).
-\-u The next argument is a username.
-\-p The next argument is a process ID number.
-\-c The next argument is a command name.
-.TE
-
+Selection criteria can be: terminal, user, pid, command. The options
+below may be used to ensure correct interpretation.
+.TP
+\fB\-t\fR, \fB\-\-tty\fR \fItty\fR
+The next expression is a terminal (tty or pty).
+.TP
+\fB\-u\fR, \fB\-\-user\fR \fIuser\fR
+The next expression is a username.
+.TP
+\fB\-p\fR, \fB\-\-pid\fR \fIpid\fR
+The next expression is a process ID number.
+.TP
+\fB\-c\fR, \fB\-\-command\fR \fIcommand\fR
+The next expression is a command name.
+.PD
.SH SIGNALS
-The signals listed below may be available for use with skill.
-When known, numbers and default behavior are shown.
-.TS
-lB rB lB lB
-lfCW r l l.
-Name Num Action Description
-0 0 n/a exit code indicates if a signal may be sent
-ALRM 14 exit
-HUP 1 exit
-INT 2 exit
-KILL 9 exit this signal may not be blocked
-PIPE 13 exit
-POLL exit
-PROF exit
-TERM 15 exit
-USR1 exit
-USR2 exit
-VTALRM exit
-STKFLT exit may not be implemented
-PWR ignore may exit on some systems
-WINCH ignore
-CHLD ignore
-URG ignore
-TSTP stop may interact with the shell
-TTIN stop may interact with the shell
-TTOU stop may interact with the shell
-STOP stop this signal may not be blocked
-CONT restart continue if stopped, otherwise ignore
-ABRT 6 core
-FPE 8 core
-ILL 4 core
-QUIT 3 core
-SEGV 11 core
-TRAP 5 core
-SYS core may not be implemented
-EMT core may not be implemented
-BUS core core dump may fail
-XCPU core core dump may fail
-XFSZ core core dump may fail
-.TE
-
+The behavior of signals is explained in
+.BR signal (7)
+manual page.
.SH EXAMPLES
-.TS
-lB lB
-lfCW l.
-Command Description
-snice seti crack +7 Slow down seti and crack
-skill \-KILL \-v /dev/pts/* Kill users on new-style PTY devices
-skill \-STOP viro lm davem Stop 3 users
-snice \-17 root bash Give priority to root's shell
-.TE
-
+.TP
+.B snice -c seti -c crack +7
+Slow down seti and crack commands.
+.TP
+.B skill \-KILL \-t /dev/pts/*
+Kill users on PTY devices.
+.TP
+.B skill \-STOP \-u viro \-u lm \-u davem
+Stop three users.
.SH "SEE ALSO"
+.BR kill (1),
+.BR kill (2),
.BR killall (1),
+.BR nice (1),
.BR pkill (1),
-.BR kill (1),
.BR renice (1),
-.BR nice (1),
-.BR kill (2),
.BR signal (7)
-
.SH STANDARDS
No standards apply.
-
.SH AUTHOR
-Albert Cahalan <albert@users.sf.net> wrote skill and snice in 1999 as a
-replacement for a non-free version.
-
-Please send bug reports to <procps@freelists.org>.
+.UR albert\@users.sf.net
+Albert Cahalan
+.UE
+wrote skill and snice in 1999 as a replacement for a non-free
+version.
+.SH "REPORTING BUGS"
+Please send bug reports to
+.UR procps\@freelists.org
+.UE
diff --git a/skill.c b/skill.c
index a618667..798497d 100644
--- a/skill.c
+++ b/skill.c
@@ -8,10 +8,13 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*/
-#include <fcntl.h>
-#include <pwd.h>
+#include <ctype.h>
#include <dirent.h>
#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <limits.h>
+#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -21,14 +24,27 @@
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
+
+#include "c.h"
+#include "strutils.h"
+#include "nls.h"
+#include "xalloc.h"
#include "proc/pwcache.h"
#include "proc/sig.h"
#include "proc/devname.h"
-#include "proc/procps.h" /* char *user_from_uid(uid_t uid) */
-#include "proc/version.h" /* procps_version */
+#include "proc/procps.h" /* char *user_from_uid(uid_t uid) */
+#include "proc/version.h" /* procps_version */
-static int f_flag, i_flag, v_flag, w_flag, n_flag;
+#define DEFAULT_NICE 4
+struct run_time_conf_t {
+ int fast;
+ int interactive;
+ int verbose;
+ int warnings;
+ int noaction;
+ int debugging;
+};
static int tty_count, uid_count, cmd_count, pid_count;
static int *ttys;
static uid_t *uids;
@@ -36,8 +52,7 @@ static const char **cmds;
static int *pids;
#define ENLIST(thing,addme) do{ \
-if(!thing##s) thing##s = malloc(sizeof(*thing##s)*saved_argc); \
-if(!thing##s) fprintf(stderr,"No memory.\n"),exit(2); \
+if(!thing##s) thing##s = xmalloc(sizeof(*thing##s)*saved_argc); \
thing##s[thing##_count++] = addme; \
}while(0)
@@ -46,538 +61,603 @@ static int saved_argc;
static int sig_or_pri;
-static int program = -1;
-#define PROG_KILL 1
-#define PROG_SKILL 2
-/* #define PROG_NICE 3 */ /* easy, but the old one isn't broken */
-#define PROG_SNICE 4
-
-
-/********************************************************************/
-
-static void display_kill_version(void){
- switch(program) {
- case PROG_KILL:
- fprintf(stdout, "kill (%s)\n",procps_version);
- return;
- case PROG_SKILL:
- fprintf(stdout, "skill (%s)\n",procps_version);
- return;
- case PROG_SNICE:
- fprintf(stdout, "snice (%s)\n",procps_version);
- return;
- default:
- fprintf(stdout, "unknown (%s)\n",procps_version);
- return;
- }
-}
+enum {
+ PROG_UNKNOWN,
+ PROG_KILL,
+ PROG_SKILL,
+ PROG_SNICE
+};
+static int program = PROG_UNKNOWN;
-/***** kill or nice a process */
-static void hurt_proc(int tty, int uid, int pid, const char *restrict const cmd){
- int failed;
- int saved_errno;
- char dn_buf[1000];
- dev_to_tty(dn_buf, 999, tty, pid, ABBREV_DEV);
- if(i_flag){
- char buf[8];
- fprintf(stderr, "%-8s %-8s %5d %-16.16s ? ",
- (char*)dn_buf,user_from_uid(uid),pid,cmd
- );
- if(!fgets(buf,7,stdin)){
- printf("\n");
- exit(0);
- }
- if(*buf!='y' && *buf!='Y') return;
- }
- /* do the actual work */
- if(program==PROG_SKILL) failed=kill(pid,sig_or_pri);
- else failed=setpriority(PRIO_PROCESS,pid,sig_or_pri);
- saved_errno = errno;
- if(w_flag && failed){
- fprintf(stderr, "%-8s %-8s %5d %-16.16s ",
- (char*)dn_buf,user_from_uid(uid),pid,cmd
- );
- errno = saved_errno;
- perror("");
- return;
- }
- if(i_flag) return;
- if(v_flag){
- printf("%-8s %-8s %5d %-16.16s\n",
- (char*)dn_buf,user_from_uid(uid),pid,cmd
- );
- return;
- }
- if(n_flag){
- printf("%d\n",pid);
- return;
- }
+static void display_kill_version(void)
+{
+ fprintf(stdout, PROCPS_NG_VERSION);
}
+/* kill or nice a process */
+static void hurt_proc(int tty, int uid, int pid, const char *restrict const cmd,
+ struct run_time_conf_t *run_time)
+{
+ int failed;
+ char dn_buf[1000];
+ dev_to_tty(dn_buf, 999, tty, pid, ABBREV_DEV);
+ if (run_time->interactive) {
+ char *buf;
+ size_t len = 0;
+ fprintf(stderr, "%-8s %-8s %5d %-16.16s ? ",
+ (char *)dn_buf, user_from_uid(uid), pid, cmd);
+ fflush (stdout);
+ getline(&buf, &len, stdin);
+ if (rpmatch(buf) < 1) {
+ free(buf);
+ return;
+ }
+ free(buf);
+ }
+ /* do the actual work */
+ errno = 0;
+ if (program == PROG_SKILL)
+ failed = kill(pid, sig_or_pri);
+ else
+ failed = setpriority(PRIO_PROCESS, pid, sig_or_pri);
+ if ((run_time->warnings && failed) || run_time->debugging || run_time->verbose) {
+ fprintf(stderr, "%-8s %-8s %5d %-16.16s ",
+ (char *)dn_buf, user_from_uid(uid), pid, cmd);
+ perror("");
+ return;
+ }
+ if (run_time->interactive)
+ return;
+ if (run_time->noaction) {
+ printf("%d\n", pid);
+ return;
+ }
+}
-/***** check one process */
-static void check_proc(int pid){
- char buf[128];
- struct stat statbuf;
- char *tmp;
- int tty;
- int fd;
- int i;
- if(pid==my_pid) return;
- sprintf(buf, "/proc/%d/stat", pid); /* pid (cmd) state ppid pgrp session tty */
- fd = open(buf,O_RDONLY);
- if(fd==-1){ /* process exited maybe */
- if(pids && w_flag) printf("WARNING: process %d could not be found.\n",pid);
- return;
- }
- fstat(fd, &statbuf);
- if(uids){ /* check the EUID */
- i=uid_count;
- while(i--) if(uids[i]==statbuf.st_uid) break;
- if(i==-1) goto closure;
- }
- read(fd,buf,128);
- buf[127] = '\0';
- tmp = strrchr(buf, ')');
- *tmp++ = '\0';
- i = 5; while(i--) while(*tmp++!=' '); /* scan to find tty */
- tty = atoi(tmp);
- if(ttys){
- i=tty_count;
- while(i--) if(ttys[i]==tty) break;
- if(i==-1) goto closure;
- }
- tmp = strchr(buf, '(') + 1;
- if(cmds){
- i=cmd_count;
- /* fast comparison trick -- useful? */
- while(i--) if(cmds[i][0]==*tmp && !strcmp(cmds[i],tmp)) break;
- if(i==-1) goto closure;
- }
- /* This is where we kill/nice something. */
-/* fprintf(stderr, "PID %d, UID %d, TTY %d,%d, COMM %s\n",
- pid, statbuf.st_uid, tty>>8, tty&0xf, tmp
- );
-*/
- hurt_proc(tty, statbuf.st_uid, pid, tmp);
-closure:
- close(fd); /* kill/nice _first_ to avoid PID reuse */
+/* check one process */
+static void check_proc(int pid, struct run_time_conf_t *run_time)
+{
+ char buf[128];
+ struct stat statbuf;
+ char *tmp;
+ int tty;
+ int fd;
+ int i;
+ if (pid == my_pid || pid == 0)
+ return;
+ /* pid (cmd) state ppid pgrp session tty */
+ sprintf(buf, "/proc/%d/stat", pid);
+ fd = open(buf, O_RDONLY);
+ if (fd == -1) {
+ /* process exited maybe */
+ if (run_time->warnings)
+ warn(_("cannot open file %s"), buf);
+ return;
+ }
+ fstat(fd, &statbuf);
+ if (uids) {
+ /* check the EUID */
+ i = uid_count;
+ while (i--)
+ if (uids[i] == statbuf.st_uid)
+ break;
+ if (i == -1)
+ goto closure;
+ }
+ read(fd, buf, 128);
+ buf[127] = '\0';
+ tmp = strrchr(buf, ')');
+ *tmp++ = '\0';
+ i = 5;
+ while (i--)
+ while (*tmp++ != ' ')
+ /* scan to find tty */ ;
+ tty = atoi(tmp);
+ if (ttys) {
+ i = tty_count;
+ while (i--)
+ if (ttys[i] == tty)
+ break;
+ if (i == -1)
+ goto closure;
+ }
+ tmp = strchr(buf, '(') + 1;
+ if (cmds) {
+ i = cmd_count;
+ /* fast comparison trick -- useful? */
+ while (i--)
+ if (cmds[i][0] == *tmp && !strcmp(cmds[i], tmp))
+ break;
+ if (i == -1)
+ goto closure;
+ }
+ /* This is where we kill/nice something. */
+ /* for debugging purposes?
+ fprintf(stderr, "PID %d, UID %d, TTY %d,%d, COMM %s\n",
+ pid, statbuf.st_uid, tty >> 8, tty & 0xf, tmp);
+ */
+ hurt_proc(tty, statbuf.st_uid, pid, tmp, run_time);
+ closure:
+ /* kill/nice _first_ to avoid PID reuse */
+ close(fd);
}
+/* debug function */
+static void show_lists(void)
+{
+ int i;
-/***** debug function */
-#if 0
-static void show_lists(void){
- int i;
-
- fprintf(stderr, "%d TTY: ", tty_count);
- if(ttys){
- i=tty_count;
- while(i--){
- fprintf(stderr, "%d,%d%c", (ttys[i]>>8)&0xff, ttys[i]&0xff, i?' ':'\n');
- }
- }else fprintf(stderr, "\n");
-
- fprintf(stderr, "%d UID: ", uid_count);
- if(uids){
- i=uid_count;
- while(i--) fprintf(stderr, "%d%c", uids[i], i?' ':'\n');
- }else fprintf(stderr, "\n");
-
- fprintf(stderr, "%d PID: ", pid_count);
- if(pids){
- i=pid_count;
- while(i--) fprintf(stderr, "%d%c", pids[i], i?' ':'\n');
- }else fprintf(stderr, "\n");
-
- fprintf(stderr, "%d CMD: ", cmd_count);
- if(cmds){
- i=cmd_count;
- while(i--) fprintf(stderr, "%s%c", cmds[i], i?' ':'\n');
- }else fprintf(stderr, "\n");
-}
-#endif
+ /* Translation Hint: the following few messages to "CMD" are
+ * for debugging, and does not have to be translated. */
+ fprintf(stderr, _("signal: %d\n"), sig_or_pri);
+ fprintf(stderr, _("%d TTY: "), tty_count);
+ if (ttys) {
+ i = tty_count;
+ while (i--) {
+ fprintf(stderr, "%d,%d%c", (ttys[i] >> 8) & 0xff,
+ ttys[i] & 0xff, i ? ' ' : '\n');
+ }
+ } else
+ fprintf(stderr, "\n");
-/***** iterate over all PIDs */
-static void iterate(void){
- int pid;
- DIR *d;
- struct dirent *de;
- if(pids){
- pid = pid_count;
- while(pid--) check_proc(pids[pid]);
- return;
- }
+ fprintf(stderr, _("%d UID: "), uid_count);
+ if (uids) {
+ i = uid_count;
+ while (i--)
+ fprintf(stderr, "%d%c", uids[i], i ? ' ' : '\n');
+ } else
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, _("%d PID: "), pid_count);
+ if (pids) {
+ i = pid_count;
+ while (i--)
+ fprintf(stderr, "%d%c", pids[i], i ? ' ' : '\n');
+ } else
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, _("%d CMD: "), cmd_count);
+ if (cmds) {
+ i = cmd_count;
+ while (i--)
+ fprintf(stderr, "%s%c", cmds[i], i ? ' ' : '\n');
+ } else
+ fprintf(stderr, "\n");
+}
+
+/* iterate over all PIDs */
+static void iterate(struct run_time_conf_t *run_time)
+{
+ int pid;
+ DIR *d;
+ struct dirent *de;
+ if (pids) {
+ pid = pid_count;
+ while (pid--)
+ check_proc(pids[pid], run_time);
+ return;
+ }
#if 0
- /* could setuid() and kill -1 to have the kernel wipe out a user */
- if(!ttys && !cmds && !pids && !i_flag){
- }
+ /* could setuid() and kill -1 to have the kernel wipe out a user */
+ if (!ttys && !cmds && !pids && !run_time->interactive) {
+ }
#endif
- d = opendir("/proc");
- if(!d){
- perror("/proc");
- exit(1);
- }
- while(( de = readdir(d) )){
- if(de->d_name[0] > '9') continue;
- if(de->d_name[0] < '1') continue;
- pid = atoi(de->d_name);
- if(pid) check_proc(pid);
- }
- closedir (d);
+ d = opendir("/proc");
+ if (!d)
+ err(EXIT_FAILURE, "/proc");
+ while ((de = readdir(d))) {
+ if (de->d_name[0] > '9')
+ continue;
+ if (de->d_name[0] < '1')
+ continue;
+ pid = atoi(de->d_name);
+ if (pid)
+ check_proc(pid, run_time);
+ }
+ closedir(d);
}
-/***** kill help */
-static void kill_usage(void) NORETURN;
-static void kill_usage(void){
- fprintf(stderr,
- "Usage:\n"
- " kill pid ... Send SIGTERM to every process listed.\n"
- " kill signal pid ... Send a signal to every process listed.\n"
- " kill -s signal pid ... Send a signal to every process listed.\n"
- " kill -l List all signal names.\n"
- " kill -L List all signal names in a nice table.\n"
- " kill -l signal Convert between signal numbers and names.\n"
- );
- exit(1);
+/* kill help */
+static void __attribute__ ((__noreturn__)) kill_usage(FILE * out)
+{
+ fputs(USAGE_HEADER, out);
+ fprintf(out,
+ _(" %s [options] <pid> [...]\n"), program_invocation_short_name);
+ fputs(USAGE_OPTIONS, out);
+ fputs(_(" <pid> [...] send signal to every <pid> listed\n"), out);
+ fputs(_(" -<signal>, -s, --signal <signal>\n"), out);
+ fputs(_(" specify the <signal> to be sent\n"), out);
+ fputs(_(" -l, --list=[<signal>] list all signal names, or convert one to a name\n"), out);
+ fputs(_(" -L, --table list all signal names in a nice table\n"), out);
+ fputs(USAGE_SEPARATOR, out);
+ fputs(USAGE_HELP, out);
+ fputs(USAGE_VERSION, out);
+ fprintf(out, USAGE_MAN_TAIL("kill(1)"));
+ exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
-/***** kill */
-static void kill_main(int argc, const char *restrict const *restrict argv) NORETURN;
-static void kill_main(int argc, const char *restrict const *restrict argv){
- const char *sigptr;
- int signo = SIGTERM;
- int exitvalue = 0;
- if(argc<2) kill_usage();
- if(!strcmp(argv[1],"-V")|| !strcmp(argv[1],"--version")){
- display_kill_version();
- exit(0);
- }
- if(argv[1][0]!='-'){
- argv++;
- argc--;
- goto no_more_args;
- }
-
- /* The -l option prints out signal names. */
- if(argv[1][1]=='l' && argv[1][2]=='\0'){
- if(argc==2){
- unix_print_signals();
- exit(0);
- }
- /* at this point, argc must be 3 or more */
- if(argc>128 || argv[2][0] == '-') kill_usage();
- exit(print_given_signals(argc-2, argv+2, 80));
- }
-
- /* The -L option prints out signal names in a nice table. */
- if(argv[1][1]=='L' && argv[1][2]=='\0'){
- if(argc==2){
- pretty_print_signals();
- exit(0);
- }
- kill_usage();
- }
- if(argv[1][1]=='-' && argv[1][2]=='\0'){
- argv+=2;
- argc-=2;
- goto no_more_args;
- }
- if(argv[1][1]=='-') kill_usage(); /* likely --help */
- // FIXME: "kill -sWINCH $$" not handled
- if(argv[1][2]=='\0' && (argv[1][1]=='s' || argv[1][1]=='n')){
- sigptr = argv[2];
- argv+=3;
- argc-=3;
- }else{
- sigptr = argv[1]+1;
- argv+=2;
- argc-=2;
- }
- signo = signal_name_to_number(sigptr);
- if(signo<0){
- fprintf(stderr, "ERROR: unknown signal name \"%s\".\n", sigptr);
- kill_usage();
- }
-no_more_args:
- if(!argc) kill_usage(); /* nothing to kill? */
- while(argc--){
- long pid;
- char *endp;
- pid = strtol(argv[argc],&endp,10);
- if(!*endp && (endp != argv[argc])){
- if(!kill((pid_t)pid,signo)) continue;
- // The UNIX standard contradicts itself. If at least one process
- // is matched for each PID (as if processes could share PID!) and
- // "the specified signal was successfully processed" (the systcall
- // returned zero?) for at least one of those processes, then we must
- // exit with zero. Note that an error might have also occured.
- // The standard says we return non-zero if an error occurs. Thus if
- // killing two processes gives 0 for one and EPERM for the other,
- // we are required to return both zero and non-zero. Quantum kill???
- perror("kill");
- exitvalue = 1;
- continue;
- }
- fprintf(stderr, "ERROR: garbage process ID \"%s\".\n", argv[argc]);
- kill_usage();
- }
- exit(exitvalue);
+/* skill and snice help */
+static void __attribute__ ((__noreturn__)) skillsnice_usage(FILE * out)
+{
+ fputs(USAGE_HEADER, out);
+
+ if (program == PROG_SKILL) {
+ fprintf(out,
+ _(" %s [signal] [options] <expression>\n"),
+ program_invocation_short_name);
+ } else {
+ fprintf(out,
+ _(" %s [new priority] [options] <expression>\n"),
+ program_invocation_short_name);
+ }
+ fputs(USAGE_OPTIONS, out);
+ fputs(_(" -f, --fast fast mode (not implemented)\n"), out);
+ fputs(_(" -i, --interactive interactive\n"), out);
+ fputs(_(" -l, --list list all signal names\n"), out);
+ fputs(_(" -L, --table list all signal names in a nice table\n"), out);
+ fputs(_(" -n, --no-action no action\n"), out);
+ fputs(_(" -v, --verbose explain what is being done\n"), out);
+ fputs(_(" -w, --warnings enable warnings (not implemented)\n"), out);
+ fputs(USAGE_SEPARATOR, out);
+ fputs(_("Expression can be: terminal, user, pid, command.\n"), out);
+ fputs(_("The options below may be used to ensure correct interpretation.\n"), out);
+ fputs(_(" -c, --command <command> expression is a command name\n"), out);
+ fputs(_(" -p, --pid <pid> expression is a process id number\n"), out);
+ fputs(_(" -t, --tty <tty> expression is a terminal\n"), out);
+ fputs(_(" -u, --user <username> expression is a username\n"), out);
+ fputs(USAGE_SEPARATOR, out);
+ fputs(USAGE_HELP, out);
+ fputs(USAGE_VERSION, out);
+ if (program == PROG_SKILL) {
+ fprintf(out,
+ _("\n"
+ "The default signal is TERM. Use -l or -L to list available signals.\n"
+ "Particularly useful signals include HUP, INT, KILL, STOP, CONT, and 0.\n"
+ "Alternate signals may be specified in three ways: -SIGKILL -KILL -9\n"));
+ fprintf(out, USAGE_MAN_TAIL("skill(1)"));
+ } else {
+ fprintf(out,
+ _("\n"
+ "The default priority is +4. (snice +4 ...)\n"
+ "Priority numbers range from +20 (slowest) to -20 (fastest).\n"
+ "Negative priority numbers are restricted to administrative users.\n"));
+ fprintf(out, USAGE_MAN_TAIL("snice(1)"));
+ }
+ exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
-/***** skill/snice help */
-static void skillsnice_usage(void) NORETURN;
-static void skillsnice_usage(void){
- if(program==PROG_SKILL){
- fprintf(stderr,
- "Usage: skill [signal to send] [options] process selection criteria\n"
- "Example: skill -KILL -v pts/*\n"
- "\n"
- "The default signal is TERM. Use -l or -L to list available signals.\n"
- "Particularly useful signals include HUP, INT, KILL, STOP, CONT, and 0.\n"
- "Alternate signals may be specified in three ways: -SIGKILL -KILL -9\n"
- );
- }else{
- fprintf(stderr,
- "Usage: snice [new priority] [options] process selection criteria\n"
- "Example: snice +7 netscape crack\n"
- "\n"
- "The default priority is +4. (snice +4 ...)\n"
- "Priority numbers range from +20 (slowest) to -20 (fastest).\n"
- "Negative priority numbers are restricted to administrative users.\n"
- );
- }
- fprintf(stderr,
- "\n"
- "General options:\n"
- "-f fast mode This is not currently useful.\n"
- "-i interactive use You will be asked to approve each action.\n"
- "-v verbose output Display information about selected processes.\n"
- "-w warnings enabled This is not currently useful.\n"
- "-n no action This only displays the process ID.\n"
- "\n"
- "Selection criteria can be: terminal, user, pid, command.\n"
- "The options below may be used to ensure correct interpretation.\n"
- "-t The next argument is a terminal (tty or pty).\n"
- "-u The next argument is a username.\n"
- "-p The next argument is a process ID number.\n"
- "-c The next argument is a command name.\n"
- );
- exit(1);
+int skill_sig_option(int *argc, char **argv)
+{
+ int i, nargs = *argc;
+ int signo = -1;
+ for (i = 1; i < nargs; i++) {
+ if (argv[i][0] == '-') {
+ signo = signal_name_to_number(argv[i] + 1);
+ if (-1 < signo) {
+ if (nargs - i) {
+ nargs--;
+ memmove(argv + i, argv + i + 1,
+ sizeof(char *) * (nargs - i));
+ }
+ return signo;
+ }
+ }
+ }
+ return signo;
+}
+
+/* kill */
+static void __attribute__ ((__noreturn__))
+ kill_main(int argc, char **argv)
+{
+ int signo, i;
+ int sigopt = 0;
+ long pid;
+ int exitvalue = EXIT_SUCCESS;
+
+ static const struct option longopts[] = {
+ {"list", optional_argument, NULL, 'l'},
+ {"table", no_argument, NULL, 'L'},
+ {"signal", required_argument, NULL, 's'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'V'},
+ {NULL, 0, NULL, 0}
+ };
+
+ setlocale (LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ if (argc < 2)
+ kill_usage(stderr);
+
+ signo = skill_sig_option(&argc, argv);
+ if (signo < 0)
+ signo = SIGTERM;
+ else
+ sigopt++;
+
+ while ((i = getopt_long(argc, argv, "l::Ls:hV", longopts, NULL)) != -1)
+ switch (i) {
+ case 'l':
+ if (optarg) {
+ char *s;
+ s = strtosig(optarg);
+ if (s)
+ printf("%s\n", s);
+ else
+ warnx(_("unknown signal name %s"),
+ optarg);
+ free(s);
+ } else {
+ unix_print_signals();
+ }
+ exit(EXIT_SUCCESS);
+ case 'L':
+ pretty_print_signals();
+ exit(EXIT_SUCCESS);
+ case 's':
+ signo = signal_name_to_number(optarg);
+ break;
+ case 'h':
+ kill_usage(stdout);
+ case 'V':
+ display_kill_version();
+ exit(EXIT_SUCCESS);
+ default:
+ kill_usage(stderr);
+ }
+
+ argc -= optind + sigopt;
+ argv += optind;
+
+ for (i = 0; i < argc; i++) {
+ pid = strtol_or_err(argv[i], _("failed to parse argument"));
+ if (!kill((pid_t) pid, signo))
+ continue;
+ exitvalue = EXIT_FAILURE;
+ continue;
+ }
+
+ exit(exitvalue);
}
#if 0
-static void _skillsnice_usage(int line){
- fprintf(stderr,"Something at line %d.\n", line);
- skillsnice_usage();
+static void _skillsnice_usage(int line)
+{
+ fprintf(stderr, _("Something at line %d.\n"), line);
+ skillsnice_usage(stderr);
}
+
#define skillsnice_usage() _skillsnice_usage(__LINE__)
#endif
#define NEXTARG (argc?( argc--, ((argptr=*++argv)) ):NULL)
-/***** common skill/snice argument parsing code */
-#define NO_PRI_VAL ((int)0xdeafbeef)
-static void skillsnice_parse(int argc, const char *restrict const *restrict argv){
- int signo = -1;
- int prino = NO_PRI_VAL;
- int force = 0;
- int num_found = 0;
- const char *restrict argptr;
- if(argc<2) skillsnice_usage();
- if(argc==2 && argv[1][0]=='-'){
- if(!strcmp(argv[1],"-L")){
- pretty_print_signals();
- exit(0);
- }
- if(!strcmp(argv[1],"-l")){
- unix_print_signals();
- exit(0);
- }
- if(!strcmp(argv[1],"-V")|| !strcmp(argv[1],"--version")){
- display_kill_version();
- exit(0);
- }
- skillsnice_usage();
- }
- NEXTARG;
- /* Time for serious parsing. What does "skill -int 123 456" mean? */
- while(argc){
- if(force && !num_found){ /* if forced, _must_ find something */
- fprintf(stderr,"ERROR: -%c used with bad data.\n", force);
- skillsnice_usage();
- }
- force = 0;
- if(program==PROG_SKILL && signo<0 && *argptr=='-'){
- signo = signal_name_to_number(argptr+1);
- if(signo>=0){ /* found a signal */
- if(!NEXTARG) break;
- continue;
- }
- }
- if(program==PROG_SNICE && prino==NO_PRI_VAL
- && (*argptr=='+' || *argptr=='-') && argptr[1]){
- long val;
- char *endp;
- val = strtol(argptr,&endp,10);
- if(!*endp && val<=999 && val>=-999){
- prino=val;
- if(!NEXTARG) break;
- continue;
- }
- }
- /* If '-' found, collect any flags. (but lone "-" is a tty) */
- if(*argptr=='-' && argptr[1]){
- argptr++;
- do{
- switch(( force = *argptr++ )){
- default: skillsnice_usage();
- case 't':
- case 'u':
- case 'p':
- case 'c':
- if(!*argptr){ /* nothing left here, *argptr is '\0' */
- if(!NEXTARG){
- fprintf(stderr,"ERROR: -%c with nothing after it.\n", force);
- skillsnice_usage();
- }
- }
- goto selection_collection;
- case 'f': f_flag++; break;
- case 'i': i_flag++; break;
- case 'v': v_flag++; break;
- case 'w': w_flag++; break;
- case 'n': n_flag++; break;
- case 0:
- NEXTARG;
- /*
- * If no more arguments, all the "if(argc)..." tests will fail
- * and the big loop will exit.
- */
- } /* END OF SWITCH */
- }while(force);
- } /* END OF IF */
-selection_collection:
- num_found = 0; /* we should find at least one thing */
- switch(force){ /* fall through each data type */
- default: skillsnice_usage();
- case 0: /* not forced */
- if (argptr && argptr[0] == '-') /* its the next argument not a parameter */
- continue;
- case 't':
- if(argc){
- struct stat sbuf;
- char path[32];
- if(!argptr) skillsnice_usage(); /* Huh? Maybe "skill -t ''". */
- snprintf(path,32,"/dev/%s",argptr);
- if(stat(path, &sbuf)>=0 && S_ISCHR(sbuf.st_mode)){
- num_found++;
- ENLIST(tty,sbuf.st_rdev);
- if(!NEXTARG) break;
- }else if(!(argptr[1])){ /* if only 1 character */
- switch(*argptr){
- default:
- if(stat(argptr,&sbuf)<0) break; /* the shell eats '?' */
- case '-':
- case '?':
- num_found++;
- ENLIST(tty,0);
- if(!NEXTARG) break;
- }
- }
- }
- if(force) continue;
- case 'u':
- if(argc){
- struct passwd *passwd_data;
- passwd_data = getpwnam(argptr);
- if(passwd_data){
- num_found++;
- ENLIST(uid,passwd_data->pw_uid);
- if(!NEXTARG) break;
- }
- }
- if(force) continue;
- case 'p':
- if(argc && *argptr>='0' && *argptr<='9'){
- char *endp;
- int num;
- num = strtol(argptr, &endp, 0);
- if(*endp == '\0'){
- num_found++;
- ENLIST(pid,num);
- if(!NEXTARG) break;
- }
- }
- if(force) continue;
- if(num_found) continue; /* could still be an option */
- case 'c':
- if(argc){
- num_found++;
- ENLIST(cmd,argptr);
- if(!NEXTARG) break;
- }
- } /* END OF SWITCH */
- } /* END OF WHILE */
- /* No more arguments to process. Must sanity check. */
- if(!tty_count && !uid_count && !cmd_count && !pid_count){
- fprintf(stderr,"ERROR: no process selection criteria.\n");
- skillsnice_usage();
- }
- if((f_flag|i_flag|v_flag|w_flag|n_flag) & ~1){
- fprintf(stderr,"ERROR: general flags may not be repeated.\n");
- skillsnice_usage();
- }
- if(i_flag && (v_flag|f_flag|n_flag)){
- fprintf(stderr,"ERROR: -i makes no sense with -v, -f, and -n.\n");
- skillsnice_usage();
- }
- if(v_flag && (i_flag|f_flag)){
- fprintf(stderr,"ERROR: -v makes no sense with -i and -f.\n");
- skillsnice_usage();
- }
- /* OK, set up defaults */
- if(prino==NO_PRI_VAL) prino=4;
- if(signo<0) signo=SIGTERM;
- if(n_flag){
- program=PROG_SKILL;
- signo=0; /* harmless */
- }
- if(program==PROG_SKILL) sig_or_pri = signo;
- else sig_or_pri = prino;
+/* common skill/snice argument parsing code */
+
+int snice_prio_option(int *argc, char **argv)
+{
+ int i = 1, nargs = *argc;
+ long prio = DEFAULT_NICE;
+
+ while (i < nargs) {
+ if ((argv[i][0] == '-' || argv[i][0] == '+')
+ && isdigit(argv[i][1])) {
+ prio = strtol_or_err(argv[i],
+ _("failed to parse argument"));
+ if (prio < INT_MIN || INT_MAX < prio)
+ errx(EXIT_FAILURE,
+ _("priority %lu out of range"), prio);
+ nargs--;
+ if (nargs - i)
+ memmove(argv + i, argv + i + 1,
+ sizeof(char *) * (nargs - i));
+ } else
+ i++;
+ }
+ *argc = nargs;
+ return (int)prio;
}
-/***** main body */
-int main(int argc, const char *argv[]){
- const char *tmpstr;
- my_pid = getpid();
- saved_argc = argc;
- if(!argc){
- fprintf(stderr,"ERROR: could not determine own name.\n");
- exit(1);
- }
- tmpstr=strrchr(*argv,'/');
- if(tmpstr) tmpstr++;
- if(!tmpstr) tmpstr=*argv;
- if(strstr(tmpstr,"kill")) program = PROG_KILL;
- if(strstr(tmpstr,"skill")) program = PROG_SKILL;
- if(strstr(tmpstr,"snice")) program = PROG_SNICE;
- switch(program){
- case PROG_SNICE:
- case PROG_SKILL:
- setpriority(PRIO_PROCESS,my_pid,-20);
- skillsnice_parse(argc, argv);
-/* show_lists(); */
- iterate(); /* this is it, go get them */
- break;
- case PROG_KILL:
- kill_main(argc, argv);
- break;
- default:
- fprintf(stderr,"ERROR: no \"%s\" support.\n",tmpstr);
- }
- return 0;
+static void skillsnice_parse(int argc,
+ char **argv, struct run_time_conf_t *run_time)
+{
+ int signo = -1;
+ int prino = DEFAULT_NICE;
+ int num_found = 0;
+ int ch, i;
+ const char *restrict argptr;
+
+ static const struct option longopts[] = {
+ {"command", required_argument, NULL, 'c'},
+ {"debug", no_argument, NULL, 'd'},
+ {"fast", no_argument, NULL, 'f'},
+ {"interactive", no_argument, NULL, 'i'},
+ {"list", no_argument, NULL, 'l'},
+ {"no-action", no_argument, NULL, 'n'},
+ {"pid", required_argument, NULL, 'p'},
+ {"table", no_argument, NULL, 'L'},
+ {"tty", required_argument, NULL, 't'},
+ {"user", required_argument, NULL, 'u'},
+ {"verbose", no_argument, NULL, 'v'},
+ {"warnings", no_argument, NULL, 'w'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'V'},
+ {NULL, 0, NULL, 0}
+ };
+
+ if (argc < 2)
+ skillsnice_usage(stderr);
+
+ sig_or_pri = -1;
+
+ if (program == PROG_SNICE)
+ prino = snice_prio_option(&argc, argv);
+ else if (program == PROG_SKILL) {
+ signo = skill_sig_option(&argc, argv);
+ if (-1 < signo)
+ sig_or_pri = signo;
+ }
+
+ pid_count = 0;
+
+ while ((ch =
+ getopt_long(argc, argv, "c:dfilnp:Lt:u:vwhV", longopts,
+ NULL)) != -1)
+ switch (ch) {
+ case 'c':
+ ENLIST(cmd, optarg);
+ break;
+ case 'd':
+ run_time->debugging = 1;
+ break;
+ case 'f':
+ run_time->fast = 1;
+ break;
+ case 'i':
+ run_time->interactive = 1;
+ break;
+ case 'l':
+ unix_print_signals();
+ exit(EXIT_SUCCESS);
+ case 'n':
+ run_time->noaction = 1;
+ break;
+ case 'p':
+ ENLIST(pid,
+ strtol_or_err(optarg,
+ _("failed to parse argument")));
+ pid_count++;
+ break;
+ case 'L':
+ pretty_print_signals();
+ exit(EXIT_SUCCESS);
+ case 't':
+ {
+ struct stat sbuf;
+ char path[32];
+ if (!optarg)
+ /* Huh? Maybe "skill -t ''". */
+ skillsnice_usage(stderr);
+ snprintf(path, 32, "/dev/%s", optarg);
+ if (stat(path, &sbuf) >= 0
+ && S_ISCHR(sbuf.st_mode)) {
+ num_found++;
+ ENLIST(tty, sbuf.st_rdev);
+ if (!NEXTARG)
+ break;
+ } else if (!(optarg[1])) {
+ /* if only 1 character */
+ switch (*optarg) {
+ default:
+ if (stat(optarg, &sbuf) < 0)
+ /* the shell eats '?' */
+ break;
+ case '-':
+ case '?':
+ num_found++;
+ ENLIST(tty, 0);
+ if (!NEXTARG)
+ break;
+ }
+ }
+ }
+ break;
+ case 'u':
+ {
+ struct passwd *passwd_data;
+ passwd_data = getpwnam(optarg);
+ if (passwd_data) {
+ num_found++;
+ ENLIST(uid, passwd_data->pw_uid);
+ if (!NEXTARG)
+ break;
+ }
+ }
+ break;
+ case 'v':
+ run_time->verbose = 1;
+ break;
+ case 'w':
+ run_time->warnings = 1;
+ break;
+ case 'h':
+ skillsnice_usage(stdout);
+ case 'V':
+ display_kill_version();
+ exit(EXIT_SUCCESS);
+ default:
+ skillsnice_usage(stderr);
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ for (i = 0; i < argc; i++) {
+ ENLIST(pid, strtol_or_err(argv[0],
+ _("failed to parse argument")));
+ pid_count++;
+ argv++;
+ }
+
+ /* No more arguments to process. Must sanity check. */
+ if (!tty_count && !uid_count && !cmd_count && !pid_count)
+ errx(EXIT_FAILURE, _("no process selection criteria"));
+ if ((run_time->fast | run_time->interactive | run_time->
+ verbose | run_time->warnings | run_time->noaction) & ~1)
+ errx(EXIT_FAILURE, _("general flags may not be repeated"));
+ if (run_time->interactive
+ && (run_time->verbose | run_time->fast | run_time->noaction))
+ errx(EXIT_FAILURE, _("-i makes no sense with -v, -f, and -n"));
+ if (run_time->verbose && (run_time->interactive | run_time->fast))
+ errx(EXIT_FAILURE, _("-v makes no sense with -i and -f"));
+ if (run_time->noaction) {
+ program = PROG_SKILL;
+ /* harmless */
+ sig_or_pri = 0;
+ }
+ if (program == PROG_SNICE)
+ sig_or_pri = prino;
+ else if (sig_or_pri < 0)
+ sig_or_pri = SIGTERM;
}
+/* main body */
+int main(int argc, char ** argv)
+{
+ struct run_time_conf_t run_time;
+ memset(&run_time, 0, sizeof(struct run_time_conf_t));
+ my_pid = getpid();
+ if (strcmp(program_invocation_short_name, "kill") == 0 ||
+ strcmp(program_invocation_short_name, "lt-kill") == 0)
+ program = PROG_KILL;
+ else if (strcmp(program_invocation_short_name, "skill") == 0 ||
+ strcmp(program_invocation_short_name, "lt-skill") == 0)
+ program = PROG_SKILL;
+ else if (strcmp(program_invocation_short_name, "snice") == 0 ||
+ strcmp(program_invocation_short_name, "lt-snice") == 0)
+ program = PROG_SNICE;
+
+ switch (program) {
+ case PROG_SNICE:
+ case PROG_SKILL:
+ setpriority(PRIO_PROCESS, my_pid, -20);
+ skillsnice_parse(argc, argv, &run_time);
+ if (run_time.debugging)
+ show_lists();
+ iterate(&run_time);
+ break;
+ case PROG_KILL:
+ kill_main(argc, argv);
+ break;
+ default:
+ fprintf(stderr, _("skill: \"%s\" is not support\n"),
+ program_invocation_short_name);
+ fprintf(stderr, USAGE_MAN_TAIL("skill(1)"));
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
diff --git a/slabtop.1 b/slabtop.1
index 08d8ec5..6af551d 100644
--- a/slabtop.1
+++ b/slabtop.1
@@ -2,27 +2,24 @@
.\"
.\" Copyright (C) 2003 Chris Rivera
.\" Licensed under the terms of the GNU Library General Public License, v2
-.TH SLABTOP 1 "13 Sep 2003" "Linux" "Linux User's Manual"
+.TH SLABTOP "1" "June 2011" "procps-ng" "User Commands"
.SH NAME
slabtop \- display kernel slab cache information in real time
-
.SH SYNOPSIS
.B slabtop
-.RI [ options ]
-
+[\fIoptions\fR]
.SH DESCRIPTION
.B slabtop
displays detailed kernel slab cache information in real time. It displays a
listing of the top caches sorted by one of the listed sort criteria. It also
displays a statistics header filled with slab layer information.
-
.SH OPTIONS
Normal invocation of
.B slabtop
does not require any options. The behavior, however, can be fine-tuned by
specifying one or more of the following flags:
.TP
-.B \-\-delay=\fIn\fR, \fB\-d \fIn
+\fB\-d\fR, \fB\-\-delay\fR=\fIN\fR
Refresh the display every
.I n
in seconds. By default,
@@ -30,23 +27,22 @@ in seconds. By default,
refreshes the display every three seconds. To exit the program, hit
.BR q.
.TP
-.B \-\-sort=\fIS\fR, \fB\-s\fR \fIS
+\fB\-s\fR, \fB\-\-sort\fR=\fIS\fR
Sort by \fIS\fR, where \fIS\fR is one of the sort criteria.
.TP
-.B \-\-once\fR, \fB\-o
+\fB\-o\fR, \fB\-\-once\fR
Display the output once and then exit.
.TP
-.B \-\-version\fR, \fB\-V
+\fB\-V\fR, \fB\-\-version\fR
Display version information and exit.
.TP
-.B \-\-help
+\fB\-h\fR, \fB\-\-help\fR
Display usage information and exit.
-
.SH SORT CRITERIA
The following are valid sort criteria used to sort the individual slab caches
and thereby determine what are the "top" slab caches to display. The default
sort criteria is to sort by the number of objects ("o").
-
+.PP
The sort criteria can also be changed while slabtop is running by pressing
the associated character.
.TP
@@ -79,49 +75,46 @@ sort by object size
.TP
.BR u:
sort by cache utilization
-
.SH COMMANDS
.B slabtop
accepts keyboard commands from the user during use. The following are
supported. In the case of letters, both cases are accepted.
-
+.PP
Each of the valid sort characters are also accepted, to change the sort
routine. See the section
-.IR "SORT CRITERIA" .
-
+.BR "SORT CRITERIA" .
.TP
.BR <SPACEBAR>
Refresh the screen.
.TP
.BR Q
Quit the program.
-
.SH FILES
.TP
.I /proc/slabinfo
slab information
-
.SH "SEE ALSO"
.BR free (1),
.BR ps (1),
.BR top (1),
.BR vmstat (8)
-
.SH NOTES
Currently,
.B slabtop
requires a 2.4 or later kernel (specifically, a version 1.1 or later
.IR /proc/slabinfo ).
Kernel 2.2 should be supported in the future.
-
-The slabtop statistic header is tracking how many bytes of slabs are being used
-and it not a measure of physical memory. The 'Slab' field in the /proc/meminfo
-file is tracking information about used slab physical memory.
-
+.PP
+The slabtop statistic header is tracking how many bytes of slabs are being
+used and it not a measure of physical memory. The 'Slab' field in the
+/proc/meminfo file is tracking information about used slab physical memory.
.SH AUTHORS
Written by Chris Rivera and Robert Love.
-
+.PP
.B slabtop
was inspired by Martin Bligh's perl script,
.BR vmtop .
-Please send bug reports to <procps@freelists.org>.
+.SH "REPORTING BUGS"
+Please send bug reports to
+.UR procps\@freelists.org
+.UE
diff --git a/slabtop.c b/slabtop.c
index 5c9d31e..df3b6cf 100644
--- a/slabtop.c
+++ b/slabtop.c
@@ -1,4 +1,4 @@
-/*
+/*
* slabtop.c - utility to display kernel slab information.
*
* Chris Rivera <cmrivera@ufl.edu>
@@ -9,6 +9,7 @@
* Copyright (C) 2003 Chris Rivera
*/
+#include <locale.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -25,11 +26,13 @@
#include <sys/types.h>
#include <unistd.h>
+#include "c.h"
+#include "nls.h"
+#include "strutils.h"
#include "proc/slab.h"
#include "proc/version.h"
#define DEF_SORT_FUNC sort_nr_objs
-#define SLAB_STAT_ZERO { nr_objs: 0 }
static unsigned short cols, rows;
static struct termios saved_tty;
@@ -57,7 +60,7 @@ static struct slab_info *merge_objs(struct slab_info *a, struct slab_info *b)
return sorted_list.next;
}
-/*
+/*
* slabsort - merge sort the slab_info linked list based on sort_func
*/
static struct slab_info *slabsort(struct slab_info *list)
@@ -149,12 +152,11 @@ static int sort_cache_size(const struct slab_info *a, const struct slab_info *b)
/*
* term_size - set the globals 'cols' and 'rows' to the current terminal size
*/
-static void term_size(int unused)
+static void term_size(int unusused __attribute__ ((__unused__)))
{
struct winsize ws;
- (void) unused;
- if ((ioctl(1, TIOCGWINSZ, &ws) != -1) && ws.ws_row > 10) {
+ if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) && ws.ws_row > 10) {
cols = ws.ws_col;
rows = ws.ws_row;
} else {
@@ -163,37 +165,37 @@ static void term_size(int unused)
}
}
-static void sigint_handler(int unused)
+static void sigint_handler(int unused __attribute__ ((__unused__)))
{
- (void) unused;
-
delay = 0;
}
-static void usage(const char *cmd)
+static void __attribute__((__noreturn__)) usage(FILE *out)
{
- fprintf(stderr, "usage: %s [options]\n\n", cmd);
- fprintf(stderr, "options:\n");
- fprintf(stderr, " --delay=n, -d n "
- "delay n seconds between updates\n");
- fprintf(stderr, " --once, -o "
- "only display once, then exit\n");
- fprintf(stderr, " --sort=S, -s S "
- "specify sort criteria S (see below)\n");
- fprintf(stderr, " --version, -V "
- "display version information and exit\n");
- fprintf(stderr, " --help display this help and exit\n\n");
- fprintf(stderr, "The following are valid sort criteria:\n");
- fprintf(stderr, " a: sort by number of active objects\n");
- fprintf(stderr, " b: sort by objects per slab\n");
- fprintf(stderr, " c: sort by cache size\n");
- fprintf(stderr, " l: sort by number of slabs\n");
- fprintf(stderr, " v: sort by number of active slabs\n");
- fprintf(stderr, " n: sort by name\n");
- fprintf(stderr, " o: sort by number of objects\n");
- fprintf(stderr, " p: sort by pages per slab\n");
- fprintf(stderr, " s: sort by object size\n");
- fprintf(stderr, " u: sort by cache utilization\n");
+ fputs(USAGE_HEADER, out);
+ fprintf(out, _(" %s [options]\n"), program_invocation_short_name);
+ fputs(USAGE_OPTIONS, out);
+ fprintf(out, _(" -d, --delay <secs> delay updates\n"));
+ fprintf(out, _(" -o, --once only display once, then exit\n"));
+ fprintf(out, _(" -s, --sort <char> specify sort criteria by character (see below)\n"));
+ fputs(USAGE_SEPARATOR, out);
+ fputs(USAGE_HELP, out);
+ fputs(USAGE_VERSION, out);
+
+ fprintf(out, _("\nThe following are valid sort criteria:\n"));
+ fprintf(out, _(" a: sort by number of active objects\n"));
+ fprintf(out, _(" b: sort by objects per slab\n"));
+ fprintf(out, _(" c: sort by cache size\n"));
+ fprintf(out, _(" l: sort by number of slabs\n"));
+ fprintf(out, _(" v: sort by number of active slabs\n"));
+ fprintf(out, _(" n: sort by name\n"));
+ fprintf(out, _(" o: sort by number of objects (the default)\n"));
+ fprintf(out, _(" p: sort by pages per slab\n"));
+ fprintf(out, _(" s: sort by object size\n"));
+ fprintf(out, _(" u: sort by cache utilization\n"));
+ fprintf(out, USAGE_MAN_TAIL("slabtop(1)"));
+
+ exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
/*
@@ -204,27 +206,27 @@ static void * set_sort_func(char key)
{
switch (key) {
case 'n':
- return sort_name;
+ return (void *) sort_name;
case 'o':
- return sort_nr_objs;
+ return (void *) sort_nr_objs;
case 'a':
- return sort_nr_active_objs;
+ return (void *) sort_nr_active_objs;
case 's':
- return sort_obj_size;
+ return (void *) sort_obj_size;
case 'b':
- return sort_objs_per_slab;
+ return (void *) sort_objs_per_slab;
case 'p':
- return sort_pages_per_slab;
+ return (void *) sort_pages_per_slab;
case 'l':
- return sort_nr_slabs;
+ return (void *) sort_nr_slabs;
case 'v':
- return sort_nr_active_slabs;
+ return (void *) sort_nr_active_slabs;
case 'c':
- return sort_cache_size;
+ return (void *) sort_cache_size;
case 'u':
- return sort_use;
+ return (void *) sort_use;
default:
- return DEF_SORT_FUNC;
+ return (void *) DEF_SORT_FUNC;
}
}
@@ -276,71 +278,69 @@ int main(int argc, char *argv[])
struct slab_info *slab_list = NULL;
int run_once=0;
- struct option longopts[] = {
- { "delay", 1, NULL, 'd' },
- { "sort", 1, NULL, 's' },
- { "once", 0, NULL, 'o' },
- { "help", 0, NULL, 'h' },
- { "version", 0, NULL, 'V' },
- { NULL, 0, NULL, 0 }
+ static const struct option longopts[] = {
+ { "delay", required_argument, NULL, 'd' },
+ { "sort", required_argument, NULL, 's' },
+ { "once", no_argument, NULL, 'o' },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'V' },
+ { NULL, 0, NULL, 0 }
};
+ setlocale (LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
sort_func = DEF_SORT_FUNC;
while ((o = getopt_long(argc, argv, "d:s:ohV", longopts, NULL)) != -1) {
- int ret = 1;
-
switch (o) {
+ char *end;
case 'd':
errno = 0;
- delay = strtol(optarg, NULL, 10);
- if (errno) {
- perror("strtoul");
- return 1;
- }
- if (delay < 0) {
- fprintf(stderr, "error: can't have a "\
- "negative delay\n");
- exit(1);
- }
+ delay = strtol_or_err(optarg, _("illegal delay"));
+ if (delay < 1)
+ errx(EXIT_FAILURE,
+ _("delay must be positive integer"));
break;
case 's':
- sort_func = set_sort_func(optarg[0]);
+ sort_func = (int (*)(const struct slab_info*,
+ const struct slab_info *)) set_sort_func(optarg[0]);
break;
case 'o':
- run_once=1;
+ run_once=1;
delay = 0;
break;
case 'V':
- display_version();
- return 0;
+ printf(PROCPS_NG_VERSION);
+ return EXIT_SUCCESS;
case 'h':
- ret = 0;
+ usage(stdout);
default:
- usage(argv[0]);
- return ret;
+ usage(stderr);
}
}
- if (tcgetattr(0, &saved_tty) == -1)
- perror("tcgetattr");
+ if (tcgetattr(STDIN_FILENO, &saved_tty) == -1)
+ warn(_("terminal setting retrieval"));
old_rows = rows;
term_size(0);
- if (!run_once) {
- initscr();
- resizeterm(rows, cols);
- signal(SIGWINCH, term_size);
- }
+ if (!run_once) {
+ initscr();
+ resizeterm(rows, cols);
+ signal(SIGWINCH, term_size);
+ }
signal(SIGINT, sigint_handler);
do {
struct slab_info *curr;
- struct slab_stat stats = SLAB_STAT_ZERO;
+ struct slab_stat stats;
struct timeval tv;
fd_set readfds;
char c;
int i;
+ memset(&stats, 0, sizeof(struct slab_stat));
if (get_slabinfo(&slab_list, &stats))
break;
@@ -350,25 +350,36 @@ int main(int argc, char *argv[])
old_rows = rows;
}
- move(0,0);
- print_line( " Active / Total Objects (%% used) : %d / %d (%.1f%%)\n"
- " Active / Total Slabs (%% used) : %d / %d (%.1f%%)\n"
- " Active / Total Caches (%% used) : %d / %d (%.1f%%)\n"
- " Active / Total Size (%% used) : %.2fK / %.2fK (%.1f%%)\n"
- " Minimum / Average / Maximum Object : %.2fK / %.2fK / %.2fK\n\n",
- stats.nr_active_objs, stats.nr_objs, 100.0 * stats.nr_active_objs / stats.nr_objs,
- stats.nr_active_slabs, stats.nr_slabs, 100.0 * stats.nr_active_slabs / stats.nr_slabs,
- stats.nr_active_caches, stats.nr_caches, 100.0 * stats.nr_active_caches / stats.nr_caches,
- stats.active_size / 1024.0, stats.total_size / 1024.0, 100.0 * stats.active_size / stats.total_size,
- stats.min_obj_size / 1024.0, stats.avg_obj_size / 1024.0, stats.max_obj_size / 1024.0
- );
+ move(0, 0);
+ print_line(" %-35s: %d / %d (%.1f%%)\n"
+ " %-35s: %d / %d (%.1f%%)\n"
+ " %-35s: %d / %d (%.1f%%)\n"
+ " %-35s: %.2fK / %.2fK (%.1f%%)\n"
+ " %-35s: %.2fK / %.2fK / %.2fK\n\n",
+ /* Translation Hint: Next five strings must not
+ * exceed 35 length in characters. */
+ _("Active / Total Objects (% used)"),
+ stats.nr_active_objs, stats.nr_objs,
+ 100.0 * stats.nr_active_objs / stats.nr_objs,
+ _("Active / Total Slabs (% used)"),
+ stats.nr_active_caches, stats.nr_caches,
+ 100.0 * stats.nr_active_caches / stats.nr_caches,
+ _("Active / Total Caches (% used)"),
+ stats.nr_active_slabs, stats.nr_slabs,
+ 100.0 * stats.nr_active_slabs / stats.nr_slabs,
+ _("Active / Total Size (% used)"),
+ stats.active_size / 1024.0, stats.total_size / 1024.0,
+ 100.0 * stats.active_size / stats.total_size,
+ _("Minimum / Average / Maximum Object"),
+ stats.min_obj_size / 1024.0, stats.avg_obj_size / 1024.0,
+ stats.max_obj_size / 1024.0);
slab_list = slabsort(slab_list);
attron(A_REVERSE);
- print_line( "%6s %6s %4s %8s %6s %8s %10s %-23s\n",
- "OBJS", "ACTIVE", "USE", "OBJ SIZE", "SLABS",
- "OBJ/SLAB", "CACHE SIZE", "NAME");
+ /* Translation Hint: Please keep alignment of the
+ * following intact. */
+ print_line("%-78s\n", _(" OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME"));
attroff(A_REVERSE);
curr = slab_list;
@@ -382,23 +393,22 @@ int main(int argc, char *argv[])
}
put_slabinfo(slab_list);
-
if (!run_once) {
- refresh();
- FD_ZERO(&readfds);
- FD_SET(0, &readfds);
- tv.tv_sec = delay;
- tv.tv_usec = 0;
- if (select(1, &readfds, NULL, NULL, &tv) > 0) {
- if (read(0, &c, 1) != 1)
- break;
- parse_input(c);
- }
- }
+ refresh();
+ FD_ZERO(&readfds);
+ FD_SET(STDIN_FILENO, &readfds);
+ tv.tv_sec = delay;
+ tv.tv_usec = 0;
+ if (select(STDOUT_FILENO, &readfds, NULL, NULL, &tv) > 0) {
+ if (read(0, &c, 1) != 1)
+ break;
+ parse_input(c);
+ }
+ }
} while (delay);
- tcsetattr(0, TCSAFLUSH, &saved_tty);
+ tcsetattr(STDIN_FILENO, TCSAFLUSH, &saved_tty);
free_slabinfo(slab_list);
if (!run_once) endwin();
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/sysctl.8 b/sysctl.8
index 3bb46d7..9e4b9b7 100644
--- a/sysctl.8
+++ b/sysctl.8
@@ -6,40 +6,12 @@
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
.\" GNU General Public License for more details."
-.TH SYSCTL 8 "21 Sep 1999" "" ""
+.TH SYSCTL "8" "June 2011" "procps-ng" "System Administration"
.SH NAME
sysctl \- configure kernel parameters at runtime
.SH SYNOPSIS
.B sysctl
-.RB [ \-n ]
-.RB [ \-e ]
-.I variable
-\&...
-.br
-.B sysctl
-.RB [ \-n ]
-.RB [ \-e ]
-.RB [ \-q ]
-.B \-w
-.IR variable = value
-\&...
-.br
-.B sysctl
-.RB [ \-n ]
-.RB [ \-e ]
-.RB [ \-q ]
-.B \-p
-.RI [ filename ]
-.br
-.B sysctl
-.RB [ \-n ]
-.RB [ \-e ]
-.B \-a
-.br
-.B sysctl
-.RB [ \-n ]
-.RB [ \-e ]
-.B \-A
+[\fIoptions\fR] [\fIvariable\fR[\fI=value\fR]] [...]
.SH DESCRIPTION
.B sysctl
is used to modify kernel parameters at runtime. The parameters available
@@ -67,31 +39,77 @@ quotes. This requires the
.B \-w
parameter to use.
.TP
-.B \-n
+\fB\-n\fR, \fB\-\-values\fR
Use this option to disable printing of the key name when printing values.
.TP
-.B \-e
+\fB\-e\fR, \fB\-\-ignore\fR
Use this option to ignore errors about unknown keys.
.TP
-.B \-N
-Use this option to only print the names. It may be useful with shells that
+\fB\-N\fR, \fB\-\-names\fR
+Use this option to only print the names. It may be useful with shells that
have programmable completion.
.TP
-.B \-q
+\fB\-q\fR, \fB\-\-quiet\fR
Use this option to not display the values set to stdout.
.TP
-.B \-w
+\fB\-w\fR, \fB\-\-write\fR
Use this option when you want to change a sysctl setting.
.TP
-.B \-p
-Load in sysctl settings from the file specified or /etc/sysctl.conf if none given.
-Specifying \- as filename means reading data from standard input.
+\fB\-p\fR, \fB\-\-load\fR[=\fIFILE\fR]
+Load in sysctl settings from the file specified or /etc/sysctl.conf if none
+given. Specifying \- as filename means reading data from standard input.
.TP
-.B \-a
+\fB\-a\fR, \fB\-\-all\fR
Display all values currently available.
.TP
-.B \-A
-Display all values currently available in table form.
+\fB\-b\fR, \fB\-\-binary\fR
+Print value without new line.
+.TP
+\fB\-\-system\fR
+Load settings from all system configuration files.
+.br
+/run/sysctl.d/*.conf
+.br
+/etc/sysctl.d/*.conf
+.br
+/usr/local/lib/sysctl.d/*.conf
+.br
+/usr/lib/sysctl.d/*.conf
+.br
+/lib/sysctl.d/*.conf
+.br
+/etc/sysctl.conf
+.TP
+\fB\-\-pattern\fR \fIpattern\fR
+Only apply settings that match
+.IR pattern .
+The
+.I pattern
+uses extended regular expression syntax.
+.TP
+\fB\-A\fR
+Alias of \fB\-a\fR
+.TP
+\fB\-d\fR
+Alias of \fB\-h\fR
+.TP
+\fB\-f\fR
+Alias of \fB\-p\fR
+.TP
+\fB\-X\fR
+Alias of \fB\-a\fR
+.TP
+\fB\-o\fR
+Does nothing in favour of BSD compatibility.
+.TP
+\fB\-x\fR
+Does nothing in favour of BSD compatibility.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Display help text and exit.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Display version information and exit.
.SH EXAMPLES
/sbin/sysctl \-a
.br
@@ -100,18 +118,26 @@ Display all values currently available in table form.
/sbin/sysctl \-w kernel.domainname="example.com"
.br
/sbin/sysctl \-p /etc/sysctl.conf
+.br
+/sbin/sysctl \-a \-\-pattern forward
+.br
+/sbin/sysctl \-a \-\-pattern forward$
+.br
+/sbin/sysctl \-a \-\-pattern 'net.ipv4.conf.(eth|wlan)0.arp'
+.br
+/sbin/sysctl \-\-system \-\-pattern '^net.ipv6'
.SH FILES
.I /proc/sys
.br
.I /etc/sysctl.conf
.SH SEE ALSO
.BR sysctl.conf (5)
-.SH BUGS
-The
-.B \-A
-parameter behaves just as
-.B \-a
-does.
+.BR regex (7)
.SH AUTHOR
-George Staikos, <staikos@0wned.org>
-
+.UR staikos\@0wned.org
+George Staikos
+.UE
+.SH "REPORTING BUGS"
+Please send bug reports to
+.UR procps\@freelists.org
+.UE
diff --git a/sysctl.c b/sysctl.c
index 6738e6d..b4e0dea 100644
--- a/sysctl.c
+++ b/sysctl.c
@@ -22,20 +22,27 @@
*/
+#include <dirent.h>
+#include <errno.h>
+#include <getopt.h>
+#include <libgen.h>
+#include <limits.h>
+#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
+#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <dirent.h>
-#include <string.h>
-#include <errno.h>
-#include <libgen.h>
+#include <unistd.h>
+
+#include "c.h"
+#include "nls.h"
+#include "xalloc.h"
#include "proc/procps.h"
#include "proc/version.h"
-// Proof that C++ causes brain damage:
+/* Proof that C++ causes brain damage: */
typedef int bool;
static bool true = 1;
static bool false = 0;
@@ -51,26 +58,21 @@ static bool PrintName;
static bool PrintNewline;
static bool IgnoreError;
static bool Quiet;
+static char *pattern;
-/* error messages */
-static const char ERR_UNKNOWN_PARAMETER[] = "error: Unknown parameter \"%s\"\n";
-static const char ERR_MALFORMED_SETTING[] = "error: Malformed setting \"%s\"\n";
-static const char ERR_NO_EQUALS[] = "error: \"%s\" must be of the form name=value\n";
-static const char ERR_INVALID_KEY[] = "error: \"%s\" is an unknown key\n";
-static const char ERR_UNKNOWN_WRITING[] = "error: \"%s\" setting key \"%s\"\n";
-static const char ERR_UNKNOWN_READING[] = "error: \"%s\" reading key \"%s\"\n";
-static const char ERR_PERMISSION_DENIED[] = "error: permission denied on key '%s'\n";
-static const char ERR_OPENING_DIR[] = "error: unable to open directory \"%s\"\n";
-static const char ERR_PRELOAD_FILE[] = "error: unable to open preload file \"%s\"\n";
-static const char WARN_BAD_LINE[] = "warning: %s(%d): invalid syntax, continuing...\n";
-
+static int pattern_match(const char *string, const char *pattern);
static void slashdot(char *restrict p, char old, char new){
+ int warned = 1;
p = strpbrk(p,"/.");
if(!p) return; /* nothing -- can't be, but oh well */
if(*p==new) return; /* already in desired format */
while(p){
char c = *p;
+ if((*(p+1) == '/' || *(p+1) == '.') && warned) {
+ warnx(_("separators should not be repeated: %s"), p);
+ warned = 0;
+ }
if(c==old) *p=new;
if(c==new) *p=old;
p = strpbrk(p+1,"/.");
@@ -83,16 +85,38 @@ static void slashdot(char *restrict p, char old, char new){
* Display the usage format
*
*/
-static int Usage(const char *restrict const name) {
- printf("usage: %s [-n] [-e] variable ... \n"
- " %s [-n] [-e] [-q] -w variable=value ... \n"
- " %s [-n] [-e] -a \n"
- " %s [-n] [-e] [-q] -p <file> (default /etc/sysctl.conf) \n"
- " %s [-n] [-e] -A\n", name, name, name, name, name);
- return -1;
+static void __attribute__ ((__noreturn__))
+ Usage(FILE * out)
+{
+ fputs(USAGE_HEADER, out);
+ fprintf(out,
+ _(" %s [options] [variable[=value] ...]\n"), program_invocation_short_name);
+ fputs(USAGE_OPTIONS, out);
+ fputs(_(" -a, --all display all variables\n"), out);
+ fputs(_(" -A alias of -a\n"), out);
+ fputs(_(" -X alias of -a\n"), out);
+ fputs(_(" -b, --binary print value without new line\n"), out);
+ fputs(_(" -e, --ignore ignore unknown variables errors\n"), out);
+ fputs(_(" -N, --names print variable names without values\n"), out);
+ fputs(_(" -n, --values print only values of a variables\n"), out);
+ fputs(_(" -p, --load[=<file>] read values from file\n"), out);
+ fputs(_(" -f alias of -p\n"), out);
+ fputs(_(" --system read values from all system directories\n"), out);
+ fputs(_(" -r, --pattern <expression>\n"), out);
+ fputs(_(" select setting that match expression\n"), out);
+ fputs(_(" -q, --quiet do not echo variable set\n"), out);
+ fputs(_(" -w, --write enable writing a value to variable\n"), out);
+ fputs(_(" -o does nothing\n"), out);
+ fputs(_(" -x does nothing\n"), out);
+ fputs(_(" -d alias of -h\n"), out);
+ fputs(USAGE_SEPARATOR, out);
+ fputs(USAGE_HELP, out);
+ fputs(USAGE_VERSION, out);
+ fprintf(out, USAGE_MAN_TAIL("sysctl(8)"));
+
+ exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
-
/*
* Strip the leading and trailing spaces from a string
*
@@ -132,23 +156,27 @@ static int ReadSetting(const char *restrict const name) {
struct stat ts;
if (!name || !*name) {
- fprintf(stderr, ERR_INVALID_KEY, name);
+ warnx(_("\"%s\" is an unknown key"), name);
return -1;
}
+ /* used to display the output */
+ outname = xstrdup(name);
+ slashdot(outname,'/','.'); /* change / to . */
+
/* used to open the file */
- tmpname = malloc(strlen(name)+strlen(PROC_PATH)+2);
+ tmpname = xmalloc(strlen(name)+strlen(PROC_PATH)+2);
strcpy(tmpname, PROC_PATH);
strcat(tmpname, name);
slashdot(tmpname+strlen(PROC_PATH),'.','/'); /* change . to / */
/* used to display the output */
- outname = strdup(name);
+ outname = xstrdup(name);
slashdot(outname,'/','.'); /* change / to . */
if (stat(tmpname, &ts) < 0) {
if (!IgnoreError) {
- perror(tmpname);
+ warn(_("cannot stat %s"), tmpname);
rc = -1;
}
goto out;
@@ -165,22 +193,27 @@ static int ReadSetting(const char *restrict const name) {
goto out;
}
+ if (pattern && !pattern_match(outname, pattern)){
+ free(outname);
+ return 0;
+ }
+
fp = fopen(tmpname, "r");
if (!fp) {
switch(errno) {
case ENOENT:
if (!IgnoreError) {
- fprintf(stderr, ERR_INVALID_KEY, outname);
+ warnx(_("\"%s\" is an unknown key"), outname);
rc = -1;
}
break;
case EACCES:
- fprintf(stderr, ERR_PERMISSION_DENIED, outname);
+ warnx(_("permission denied on key '%s'"), outname);
rc = -1;
break;
default:
- fprintf(stderr, ERR_UNKNOWN_READING, strerror(errno), outname);
+ warn(_("reading key \"%s\""), outname);
rc = -1;
break;
}
@@ -208,7 +241,7 @@ static int ReadSetting(const char *restrict const name) {
} else {
switch(errno) {
case EACCES:
- fprintf(stderr, ERR_PERMISSION_DENIED, outname);
+ warnx(_("permission denied on key '%s'"), outname);
rc = -1;
break;
case EISDIR:{
@@ -221,7 +254,7 @@ static int ReadSetting(const char *restrict const name) {
goto out;
}
default:
- fprintf(stderr, ERR_UNKNOWN_READING, strerror(errno), outname);
+ warnx(_("reading key \"%s\""), outname);
rc = -1;
case 0:
break;
@@ -251,18 +284,18 @@ static int DisplayAll(const char *restrict const path) {
dp = opendir(path);
if (!dp) {
- fprintf(stderr, ERR_OPENING_DIR, path);
+ warnx(_("unable to open directory \"%s\""), path);
rc = -1;
} else {
readdir(dp); // skip .
readdir(dp); // skip ..
while (( de = readdir(dp) )) {
char *restrict tmpdir;
- tmpdir = (char *restrict)malloc(strlen(path)+strlen(de->d_name)+2);
+ tmpdir = (char *restrict)xmalloc(strlen(path)+strlen(de->d_name)+2);
sprintf(tmpdir, "%s%s", path, de->d_name);
rc2 = stat(tmpdir, &ts);
if (rc2 != 0) {
- perror(tmpdir);
+ warn(_("cannot stat %s"), tmpdir);
} else {
if (S_ISDIR(ts.st_mode)) {
strcat(tmpdir, "/");
@@ -300,45 +333,45 @@ static int WriteSetting(const char *setting) {
equals = strchr(setting, '=');
if (!equals) {
- fprintf(stderr, ERR_NO_EQUALS, setting);
+ warnx(_("\"%s\" must be of the form name=value"), setting);
return -1;
}
value = equals + 1; /* point to the value in name=value */
if (!*name || !*value || name == equals) {
- fprintf(stderr, ERR_MALFORMED_SETTING, setting);
+ warnx(_("Malformed setting \"%s\""), setting);
return -2;
}
/* used to open the file */
- tmpname = malloc(equals-name+1+strlen(PROC_PATH));
+ tmpname = xmalloc(equals-name+1+strlen(PROC_PATH));
strcpy(tmpname, PROC_PATH);
strncat(tmpname, name, (int)(equals-name));
tmpname[equals-name+strlen(PROC_PATH)] = 0;
slashdot(tmpname+strlen(PROC_PATH),'.','/'); /* change . to / */
/* used to display the output */
- outname = malloc(equals-name+1);
+ outname = xmalloc(equals-name+1);
strncpy(outname, name, (int)(equals-name));
outname[equals-name] = 0;
slashdot(outname,'/','.'); /* change / to . */
if (stat(tmpname, &ts) < 0) {
if (!IgnoreError) {
- perror(tmpname);
+ warn(_("cannot stat %s"), tmpname);
rc = -1;
}
goto out;
}
if ((ts.st_mode & S_IWUSR) == 0) {
- fprintf(stderr, ERR_UNKNOWN_WRITING, strerror(EACCES), outname);
+ warn(_("setting key \"%s\""), outname);
goto out;
}
if (S_ISDIR(ts.st_mode)) {
- fprintf(stderr, ERR_UNKNOWN_WRITING, strerror(EACCES), outname);
+ warn(_("setting key \"%s\""), outname);
goto out;
}
@@ -348,28 +381,28 @@ static int WriteSetting(const char *setting) {
switch(errno) {
case ENOENT:
if (!IgnoreError) {
- fprintf(stderr, ERR_INVALID_KEY, outname);
+ warnx(_("\"%s\" is an unknown key"), outname);
rc = -1;
}
break;
case EACCES:
- fprintf(stderr, ERR_PERMISSION_DENIED, outname);
+ warnx(_("permission denied on key '%s'"), outname);
rc = -1;
break;
default:
- fprintf(stderr, ERR_UNKNOWN_WRITING, strerror(errno), outname);
+ warn(_("setting key \"%s\""), outname);
rc = -1;
break;
}
} else {
rc = fprintf(fp, "%s\n", value);
if (rc < 0) {
- fprintf(stderr, ERR_UNKNOWN_WRITING, strerror(errno), outname);
+ warn(_("setting key \"%s\""), outname);
fclose(fp);
} else {
rc=fclose(fp);
if (rc != 0)
- fprintf(stderr, ERR_UNKNOWN_WRITING, strerror(errno), outname);
+ warn(_("setting key \"%s\""), outname);
}
if (rc==0 && !Quiet) {
if (NameOnly) {
@@ -392,7 +425,21 @@ out:
return rc;
}
-
+static int pattern_match(const char *string, const char *pattern)
+{
+ int status;
+ regex_t re;
+
+ if (regcomp(&re, pattern, REG_EXTENDED | REG_NOSUB) != 0) {
+ return (0); /* Report error. */
+ }
+ status = regexec(&re, string, (size_t) 0, NULL, 0);
+ regfree(&re);
+ if (status != 0) {
+ return (0); /* Report error. */
+ }
+ return (1);
+}
/*
* Preload the sysctl's from the conf file
@@ -414,7 +461,7 @@ static int Preload(const char *restrict const filename) {
;
if (!fp) {
- fprintf(stderr, ERR_PRELOAD_FILE, filename);
+ warn(_("cannot open \"%s\""), filename);
return -1;
}
@@ -430,15 +477,19 @@ static int Preload(const char *restrict const filename) {
name = strtok(t, "=");
if (!name || !*name) {
- fprintf(stderr, WARN_BAD_LINE, filename, n);
+ warnx(_("%s(%d): invalid syntax, continuing..."), filename, n);
continue;
}
StripLeadingAndTrailingSpaces(name);
+ if (pattern && !pattern_match(name, pattern)){
+ continue;
+ }
+
value = strtok(NULL, "\n\r");
if (!value || !*value) {
- fprintf(stderr, WARN_BAD_LINE, filename, n);
+ warnx(_("%s(%d): invalid syntax, continuing..."), filename, n);
continue;
}
@@ -454,112 +505,204 @@ static int Preload(const char *restrict const filename) {
return rc;
}
+struct pair {
+ char* name;
+ char* value;
+};
+
+static int sortpairs(const void* A, const void* B)
+{
+ const struct pair* a = *(struct pair* const*)A;
+ const struct pair* b = *(struct pair* const*)B;
+ return strcmp(a->name, b->name);
+}
+
+static int PreloadSystem(void) {
+ unsigned di, i;
+ const char* dirs[] = {
+ "/run/sysctl.d",
+ "/etc/sysctl.d",
+ "/usr/local/lib/sysctl.d",
+ "/usr/lib/sysctl.d",
+ "/lib/sysctl.d",
+ };
+ struct pair** cfgs = NULL;
+ unsigned ncfgs = 0;
+ enum { nprealloc = 16 };
+
+ for (di=0; di < sizeof(dirs)/sizeof(dirs[0]); ++di) {
+ struct dirent* de;
+ DIR* dp = opendir(dirs[di]);
+ if (!dp)
+ continue;
+ while (( de = readdir(dp) )) {
+ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
+ continue;
+ }
+ if (strlen(de->d_name) < 6 || !strcmp(de->d_name+strlen(de->d_name)-6, ".conf"))
+ continue;
+ /* check if config already known */
+ for (i = 0; i < ncfgs; ++i) {
+ if (!strcmp(cfgs[i]->name, de->d_name))
+ break;
+ }
+ if (i < ncfgs) // already in
+ continue;
+
+ if (ncfgs % nprealloc == 0) {
+ cfgs = xrealloc(cfgs, sizeof(struct pair*)*(ncfgs+nprealloc));
+ }
+ cfgs[ncfgs] = xmalloc(sizeof(struct pair) + strlen(de->d_name)*2+2 + strlen(dirs[di])+1);
+ cfgs[ncfgs]->name = (char*)cfgs[ncfgs]+sizeof(struct pair);
+ strcpy(cfgs[ncfgs]->name, de->d_name);
+ cfgs[ncfgs]->value = (char*)cfgs[ncfgs]+sizeof(struct pair) + strlen(cfgs[ncfgs]->name)+1;
+ sprintf(cfgs[ncfgs]->value, "%s/%s", dirs[di], de->d_name);
+ ncfgs++;
+
+ }
+ closedir(dp);
+ }
+
+ qsort(cfgs, ncfgs, sizeof(struct cfg*), sortpairs);
+
+ for (i = 0; i < ncfgs; ++i) {
+ if (!Quiet)
+ printf(_("* Applying %s ...\n"), cfgs[i]->value);
+ Preload(cfgs[i]->value);
+ }
+
+ if (!Quiet)
+ printf(_("* Applying %s ...\n"), DEFAULT_PRELOAD);
+ return Preload(DEFAULT_PRELOAD);
+}
/*
* Main...
*
*/
-int main(int argc, char *argv[]) {
- const char *me = (const char *)basename(argv[0]);
+int main(int argc, char *argv[])
+{
bool SwitchesAllowed = true;
bool WriteMode = false;
bool DisplayAllOpt = false;
+ bool preloadfileOpt = false;
int ReturnCode = 0;
+ int c;
const char *preloadfile = DEFAULT_PRELOAD;
+ enum {
+ SYSTEM_OPTION = CHAR_MAX + 1
+ };
+ static const struct option longopts[] = {
+ {"all", no_argument, NULL, 'a'},
+ {"binary", no_argument, NULL, 'b'},
+ {"ignore", no_argument, NULL, 'e'},
+ {"names", no_argument, NULL, 'N'},
+ {"values", no_argument, NULL, 'n'},
+ {"load", optional_argument, NULL, 'p'},
+ {"quiet", no_argument, NULL, 'q'},
+ {"write", no_argument, NULL, 'w'},
+ {"system", no_argument, NULL, SYSTEM_OPTION},
+ {"pattern", required_argument, NULL, 'r'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'V'},
+ {NULL, 0, NULL, 0}
+ };
+
+ setlocale (LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
PrintName = true;
PrintNewline = true;
IgnoreError = false;
Quiet = false;
if (argc < 2) {
- return Usage(me);
+ Usage(stderr);
}
- argv++;
-
- for (; argv && *argv && **argv; argv++) {
- if (SwitchesAllowed && **argv == '-') { /* we have a switch */
- if ((*argv)[1] && (*argv)[2]){ // don't yet handle "sysctl -ew"
- if (!strcmp("--help",*argv)) {
- Usage(me);
- exit(0);
- }
- if (!strcmp("--version",*argv)) {
- fprintf(stdout, "sysctl (%s)\n",procps_version);
- exit(0);
- }
- fprintf(stderr, ERR_UNKNOWN_PARAMETER, *argv);
- return Usage(me);
- }
- switch((*argv)[1]) {
- case 'b':
- /* This is "binary" format, which means more for BSD. */
- PrintNewline = false;
- /* FALL THROUGH */
- case 'n':
- PrintName = false;
+ while ((c =
+ getopt_long(argc, argv, "bneNwfp::qoxaAXr:Vdh", longopts,
+ NULL)) != -1)
+ switch (c) {
+ case 'b':
+ /* This is "binary" format, which means more for BSD. */
+ PrintNewline = false;
+ /* FALL THROUGH */
+ case 'n':
+ PrintName = false;
+ break;
+ case 'e':
+ /*
+ * For FreeBSD, -e means a "%s=%s\n" format. ("%s: %s\n" default)
+ * We (and NetBSD) use "%s = %s\n" always, and -e to ignore errors.
+ */
+ IgnoreError = true;
+ break;
+ case 'N':
+ NameOnly = true;
+ break;
+ case 'w':
+ SwitchesAllowed = false;
+ WriteMode = true;
+ break;
+ case 'f': /* the NetBSD way */
+ case 'p':
+ preloadfileOpt = true;
+ if (optarg)
+ preloadfile = optarg;
break;
- case 'e':
- // For FreeBSD, -e means a "%s=%s\n" format. ("%s: %s\n" default)
- // We (and NetBSD) use "%s = %s\n" always, and -e to ignore errors.
- IgnoreError = true;
+ case 'q':
+ Quiet = true;
+ break;
+ case 'o': /* BSD: binary values too, 1st 16 bytes in hex */
+ case 'x': /* BSD: binary values too, whole thing in hex */
+ /* does nothing */ ;
+ break;
+ case 'a': /* string and integer values (for Linux, all of them) */
+ case 'A': /* same as -a -o */
+ case 'X': /* same as -a -x */
+ DisplayAllOpt = true;
break;
- case 'N':
- NameOnly = true;
+ case SYSTEM_OPTION:
+ IgnoreError = true;
+ return PreloadSystem();
+ case 'r':
+ pattern = xstrdup(optarg);
break;
- case 'w':
- SwitchesAllowed = false;
- WriteMode = true;
- break;
- case 'f': // the NetBSD way
- case 'p':
- argv++;
- if (argv && *argv && **argv) {
- preloadfile = *argv;
- }
- return Preload(preloadfile);
- case 'q':
- Quiet = true;
- break;
- case 'o': // BSD: binary values too, 1st 16 bytes in hex
- case 'x': // BSD: binary values too, whole thing in hex
- /* does nothing */ ;
- break;
- case 'a': // string and integer values (for Linux, all of them)
- case 'A': // same as -a -o
- case 'X': // same as -a -x
- DisplayAllOpt = true;
- break;
- case 'V':
- fprintf(stdout, "sysctl (%s)\n",procps_version);
- exit(0);
- case 'd': // BSD: print description ("vm.kvm_size: Size of KVM")
- case 'h': // BSD: human-readable (did FreeBSD 5 make -e default?)
- case '?':
- return Usage(me);
- default:
- fprintf(stderr, ERR_UNKNOWN_PARAMETER, *argv);
- return Usage(me);
- }
- } else {
- if (NameOnly && Quiet) // nonsense
- return Usage(me);
- if (DisplayAllOpt) // We cannot have values with -a
- return Usage(me);
- SwitchesAllowed = false;
- if (WriteMode || strchr(*argv, '='))
- ReturnCode = WriteSetting(*argv);
- else
- ReturnCode = ReadSetting(*argv);
+ case 'V':
+ printf(PROCPS_NG_VERSION);
+ exit(0);
+ case 'd': /* BSD: print description ("vm.kvm_size: Size of KVM") */
+ case 'h': /* BSD: human-readable (did FreeBSD 5 make -e default?) */
+ case '?':
+ Usage(stdout);
+ default:
+ Usage(stderr);
}
- }
- if (DisplayAllOpt) {
- if (Quiet)
- return Usage(me);
+ if (DisplayAllOpt)
return DisplayAll(PROC_PATH);
- }
+ if (preloadfileOpt)
+ return Preload(preloadfile);
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1)
+ errx(EXIT_FAILURE, _("no variables specified\n"
+ "Try `%s --help' for more information."),
+ program_invocation_short_name);
+ if (NameOnly && Quiet)
+ errx(EXIT_FAILURE, _("options -N and -q cannot coexist\n"
+ "Try `%s --help' for more information."),
+ program_invocation_short_name);
+
+ if (WriteMode || index(*argv, '='))
+ ReturnCode = WriteSetting(*argv);
+ else
+ ReturnCode = ReadSetting(*argv);
return ReturnCode;
}
diff --git a/tload.1 b/tload.1
index 8ec8c43..7f9fa48 100644
--- a/tload.1
+++ b/tload.1
@@ -1,39 +1,42 @@
.\" -*-Nroff-*-
.\" This page Copyright (C) 1993 Matt Welsh, mdw@tc.cornell.edu.
.\" Freely distributable under the terms of the GPL
-.TH TLOAD 1 "20 Mar 1993 " "Cohesive Systems" "Linux User's Manual"
+.TH TLOAD "1" "June 2011" "procps-ng" "User Commands"
.SH NAME
tload \- graphic representation of system load average
.SH SYNOPSIS
.B tload
-.RB [ "\-V" "] [" "\-s"
-.IR scale "] ["
-.BI "\-d" " delay"
-.RI "] [" tty ]
+[\fIoptions\fR] [\fItty\fR]
.SH DESCRIPTION
-\fBtload\fP prints a graph of the current system load average to the
-specified \fItty\fP (or the tty of the tload process if none is specified).
-.SS Options
-The
-.BI "\-s" " scale"
-option allows a vertical scale to be specified for the
-display (in characters between graph ticks); thus, a smaller value
-represents a larger scale, and vice versa.
-
-The
-.BI "\-d" " delay"
-sets the delay between graph updates in seconds.
+.B tload
+prints a graph of the current system load average to the specified
+.I tty
+(or the tty of the tload process if none is specified).
+.SH OPTIONS
+.TP
+\fB\-s\fR, \fB\-\-scale\fR \fInumber\fR
+The scale option allows a vertical scale to be specified for the display (in
+characters between graph ticks); thus, a smaller value represents a larger
+scale, and vice versa.
+.TP
+\fB\-d\fR, \fB\-\-delay\fR \fIseconds\fR
+The delay sets the delay between graph updates in
+.IR seconds .
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Display this help text.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Display version information and exit.
.PP
.SH FILES
.I /proc/loadavg
load average information
-
.SH "SEE ALSO"
.BR ps (1),
.BR top (1),
.BR uptime (1),
.BR w (1)
-
.SH BUGS
The
.BI "\-d" " delay"
@@ -42,9 +45,15 @@ option sets the time argument for an
if \-d 0 is specified, the alarm is set to 0, which will never send the
.B SIGALRM
and update the display.
-
.SH AUTHORS
-Branko Lankester, David Engel <david@ods.com>, and
-Michael K. Johnson <johnsonm@redhat.com>.
-
-Please send bug reports to <albert@users.sf.net>
+Branko Lankester,
+.UR david\@\:ods.\:com
+David Engel
+.UE , and
+.UR johnsonm\@\:redhat.\:com
+Michael K. Johnson
+.UE .
+.SH "REPORTING BUGS"
+Please send bug reports to
+.UR procps\@freelists.org
+.UE
diff --git a/tload.c b/tload.c
index f846ecb..4fe57ad 100644
--- a/tload.c
+++ b/tload.c
@@ -11,143 +11,183 @@
*/
#include "proc/version.h"
#include "proc/sysinfo.h"
-#include <stdio.h>
-#include <stdlib.h>
+#include "c.h"
+#include "nls.h"
+#include "strutils.h"
+#include "xalloc.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
#include <setjmp.h>
#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
-#include <termios.h>
-#include <fcntl.h>
#include <sys/ioctl.h>
+#include <termios.h>
+#include <unistd.h>
static char *screen;
static int nrows = 25;
static int ncols = 80;
static int scr_size;
-static int fd=1;
-static int dly=5;
+static int fd = 1;
+static unsigned int dly = 5;
static jmp_buf jb;
-static void alrm(int signo)
+static void alrm(int signo __attribute__ ((__unused__)))
{
- (void)signo;
- signal(SIGALRM, alrm);
- alarm(dly);
+ signal(SIGALRM, alrm);
+ alarm(dly);
}
static void setsize(int i)
{
- struct winsize win;
-
- signal(SIGWINCH, setsize);
- if (ioctl(fd, TIOCGWINSZ, &win) != -1) {
- if (win.ws_col > 0)
- ncols = win.ws_col;
- if (win.ws_row > 0)
- nrows = win.ws_row;
- }
- scr_size = nrows * ncols;
- if (screen == NULL)
- screen = (char *) malloc(scr_size);
- else
- screen = (char *) realloc(screen, scr_size);
-
- if (screen == NULL) {
- perror("");
- exit(1);
- }
- memset(screen, ' ', scr_size-1);
- *(screen + scr_size - 2) = '\0';
- if (i)
- longjmp(jb, 0);
+ struct winsize win;
+
+ signal(SIGWINCH, setsize);
+ if (ioctl(fd, TIOCGWINSZ, &win) != -1) {
+ if (win.ws_col > 0)
+ ncols = win.ws_col;
+ if (win.ws_row > 0)
+ nrows = win.ws_row;
+ }
+ scr_size = nrows * ncols;
+ if (screen == NULL)
+ screen = (char *)xmalloc(scr_size);
+ else
+ screen = (char *)xrealloc(screen, scr_size);
+
+ memset(screen, ' ', scr_size - 1);
+ *(screen + scr_size - 2) = '\0';
+ if (i)
+ longjmp(jb, 0);
}
-int main(int argc, char **argv)
+static void __attribute__ ((__noreturn__)) usage(FILE * out)
{
- int lines, row, col=0;
- int i, opt;
- double av[3];
- static double max_scale, scale_fact;
- char *scale_arg = NULL;
-
- while ((opt = getopt(argc, argv, "s:d:V")) != -1)
- switch (opt) {
- case 's': scale_arg = optarg; break;
- case 'd': dly = atoi(optarg); break;
- case 'V': display_version(); exit(0); break;
- default:
- printf("usage: tload [-V] [-d delay] [-s scale] [tty]\n");
- exit(1);
- }
-
- if (argc > optind) {
- if ((fd = open(argv[optind], 1)) == -1) {
- perror("tty");
- exit(1);
- }
- }
-
- setsize(0);
-
- if (scale_arg)
- max_scale = atof(scale_arg);
- else
- max_scale = nrows;
-
- scale_fact = max_scale;
-
- setjmp(jb);
- col = 0;
- alrm(0);
-
- while (1) {
-
- if (scale_fact < max_scale)
- scale_fact *= 2.0; /* help it drift back up. */
-
- loadavg(&av[0], &av[1], &av[2]);
-
- repeat:
- lines = av[0] * scale_fact;
- row = nrows-1;
-
- while (--lines >= 0) {
- *(screen + row * ncols + col) = '*';
- if (--row < 0) {
- scale_fact /= 2.0;
- goto repeat;
- }
- }
- while (row >= 0)
- *(screen + row-- * ncols + col) = ' ';
-
- for (i = 1; ; ++i) {
- char *p;
- row = nrows - (i * scale_fact);
- if (row < 0)
- break;
- if (*(p = screen + row * ncols + col) == ' ')
- *p = '-';
- else
- *p = '=';
- }
-
- if (++col == ncols) {
- --col;
- memmove(screen, screen + 1, scr_size-1);
+ fputs(USAGE_HEADER, out);
+ fprintf(out,
+ _(" %s [options] [tty]\n"), program_invocation_short_name);
+ fputs(USAGE_OPTIONS, out);
+ fputs(_(" -d, --delay <secs> update delay in seconds\n"), out);
+ fputs(_(" -s, --scale <num> vertical scale\n"), out);
+ fputs(USAGE_SEPARATOR, out);
+ fputs(USAGE_HELP, out);
+ fputs(USAGE_VERSION, out);
+ fprintf(out, USAGE_MAN_TAIL("tload(1)"));
+
+ exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
+}
- for(row = nrows-2; row >= 0; --row)
- *(screen + row * ncols + col) = ' ';
+int main(int argc, char **argv)
+{
+ int lines, row, col = 0;
+ int i, opt;
+ double av[3];
+ static double max_scale = 0, scale_fact;
+ long tmpdly;
+
+ static const struct option longopts[] = {
+ {"scale", required_argument, NULL, 's'},
+ {"delay", required_argument, NULL, 'd'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'V'},
+ {NULL, 0, NULL, 0}
+ };
+
+ setlocale (LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ while ((opt =
+ getopt_long(argc, argv, "s:d:Vh", longopts, NULL)) != -1)
+ switch (opt) {
+ case 's':
+ max_scale = strtod_or_err(optarg, _("failed to parse argument"));
+ if (max_scale < 0)
+ errx(EXIT_FAILURE, _("scale cannot be negative"));
+ break;
+ case 'd':
+ tmpdly = strtol_or_err(optarg, _("failed to parse argument"));
+ if (tmpdly < 1)
+ errx(EXIT_FAILURE, _("delay must be positive integer"));
+ else if (UINT_MAX < tmpdly)
+ errx(EXIT_FAILURE, _("too large delay value"));
+ dly = tmpdly;
+ break;
+ case 'V':
+ printf(PROCPS_NG_VERSION);
+ return EXIT_SUCCESS;
+ break;
+ case 'h':
+ usage(stdout);
+ default:
+ usage(stderr);
+ }
+
+ if (argc > optind)
+ if ((fd = open(argv[optind], 1)) == -1)
+ err(EXIT_FAILURE, _("can not open tty"));
+
+ setsize(0);
+
+ if (max_scale == 0)
+ max_scale = nrows;
+
+ scale_fact = max_scale;
+
+ setjmp(jb);
+ col = 0;
+ alrm(0);
+
+ while (1) {
+
+ if (scale_fact < max_scale)
+ scale_fact *= 2.0; /* help it drift back up. */
+
+ loadavg(&av[0], &av[1], &av[2]);
+
+ repeat:
+ lines = av[0] * scale_fact;
+ row = nrows - 1;
+
+ while (--lines >= 0) {
+ *(screen + row * ncols + col) = '*';
+ if (--row < 0) {
+ scale_fact /= 2.0;
+ goto repeat;
+ }
+ }
+ while (row >= 0)
+ *(screen + row-- * ncols + col) = ' ';
+
+ for (i = 1;; ++i) {
+ char *p;
+ row = nrows - (i * scale_fact);
+ if (row < 0)
+ break;
+ if (*(p = screen + row * ncols + col) == ' ')
+ *p = '-';
+ else
+ *p = '=';
+ }
+
+ if (++col == ncols) {
+ --col;
+ memmove(screen, screen + 1, scr_size - 1);
+
+ for (row = nrows - 2; row >= 0; --row)
+ *(screen + row * ncols + col) = ' ';
+ }
+ i = sprintf(screen, " %.2f, %.2f, %.2f", av[0], av[1], av[2]);
+ if (i > 0)
+ screen[i] = ' ';
+
+ write(fd, "\033[H", 3);
+ write(fd, screen, scr_size - 1);
+ pause();
}
- i = sprintf(screen, " %.2f, %.2f, %.2f",
- av[0], av[1], av[2]);
- if (i>0)
- screen[i] = ' ';
-
- write(fd, "\033[H", 3);
- write(fd, screen, scr_size - 1);
- pause();
- }
}
diff --git a/top/Makefile.am b/top/Makefile.am
new file mode 100644
index 0000000..714a04e
--- /dev/null
+++ b/top/Makefile.am
@@ -0,0 +1,26 @@
+AM_CPPFLAGS = -include $(top_builddir)/config.h
+
+AM_CFLAGS = -I../proc -I../include
+AM_LDFLAGS = ../proc/libprocps.la
+
+if WITH_NCURSES
+usrbin_exec_PROGRAMS = \
+ top
+
+top_SOURCES = \
+ top.h \
+ top.c \
+ top_nls.h \
+ top_nls.c
+
+dist_man_MANS = \
+ top.1
+
+top_LDADD = @NCURSES_LIBS@
+endif
+
+EXTRA_DIST =
+
+procpsngdir = $(docdir)
+dist_procpsng_DATA = \
+ README.top
diff --git a/README.top b/top/README.top
index b6c9142..78fee02 100644
--- a/README.top
+++ b/top/README.top
@@ -326,3 +326,52 @@ notes:
c only in a full screen xterm window could all common fields
actually be displayed
+
+BENCHMARKS, Redux (for NLS) ==============================================
+ December, 2011 benchmarks produced on a much more modern
+ platform containing:
+ Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz
+ SMP with 4 cpus
+ reflected in the substantially reduced elapsed times.
+
+ Tested as root with nice -10 and using only common fields
+ but rcfiles specified identical sort fields and identical
+ settings for the 'B', 'b', 'x' and 'y' toggles (even though
+ the defaults are not necessarily identical).
+
+ Each test was run outside of X-windows at a linux console
+ offering 48 rows and 170 columns. This was done to reduce
+ contention which sometimes made comparisions problematic.
+
+ old-top = procps-3.2.8 (debian patched and memory leaking)
+ new-top = procps-ng-3.3.2 with NLS support
+
+ ----------------------------------------------------------
+ The following comparisons were run with
+ -d0 -n5000
+ 140 tasks & 275 threads
+
+ linux console (48x170) new-top old-top
+ d 1 win, lflgs_none 2.6 secs 15.0 secs + 577.0%
+ 1 win, default 16.1 secs 19.3 secs
+ 1 win, colors w/ x+y 16.6 secs 35.0 secs + 210.8%
+ e 1 win, show cpus 16.2 secs 20.1 secs + 124.1%
+ 1 win, thread mode 31.8 secs 34.1 secs
+ f 1 win, every field on 30.5 secs 34.0 secs
+ 1 win, cmdline 19.9 secs 23.1 secs
+ 4 wins, default 31.9 secs 35.2 secs
+ 4 wins, colors w/ x+y 29.2 secs 47.4 secs + 162.3%
+ g 1 win, b&w w/ bold x 30.0 secs 33.2 secs
+ h 1 win, scroll msg on 31.1 secs 33.9 secs
+
+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+notes:
+ d these represent the same anamoly as the original 'a' footnote
+ e these represent the '1' toggle, where each of 4 cpus was shown
+ (not possible on the original uniprocessor)
+ f every common field was turned on and all fields were visible
+ g on a black and white display, sort column was shown in bold
+ (further proof of column highlighting improvements)
+ h similar to 'g', but new top was showing scroll msg
+ (old top has no such provision)
diff --git a/top.1 b/top/top.1
index 355aef4..16af3d1 100644
--- a/top.1
+++ b/top/top.1
@@ -1421,12 +1421,15 @@ b. Scrolling a window vertically and/or horizontally,
.TP 3
c. The state of the command/command-line toggle,
\*(Xc 'c' \*(CI.
+.TP 3
+d. The stability of the chosen sort column,
+for example PID is good but %CPU bad.
.RS -3
.PP
If a search fails, restoring the \*(CW home (unscrolled) position, scrolling
-horizontally or displaying command-lines could yet produce a successful '&'
-search.
+horizontally, displaying command-lines or choosing a more stable sort field
+could yet produce a successful '&' search.
The above \*(CIs are\fB always\fR available in \*(FM but\fB never\fR
available in \*(AM if the \*(CW's \*(TD has been toggled \*F.
diff --git a/top.c b/top/top.c
index 1ccb7a1..1d9ee5e 100644
--- a/top.c
+++ b/top/top.c
@@ -15,7 +15,9 @@
/* For contributions to this program, the author wishes to thank:
* Craig Small, <csmall@small.dropbear.id.au>
* Albert D. Cahalan, <albert@users.sf.net>
+ * Sami Kerola, <kerolasa@iki.fi>
*/
+
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/time.h>
@@ -39,16 +41,19 @@
#include <unistd.h>
#include <values.h>
-#include "proc/devname.h"
-#include "proc/procps.h"
-#include "proc/readproc.h"
-#include "proc/sig.h"
-#include "proc/sysinfo.h"
-#include "proc/version.h"
-#include "proc/wchan.h"
-#include "proc/whattime.h"
+#include "../include/nls.h"
+
+#include "../proc/devname.h"
+#include "../proc/procps.h"
+#include "../proc/readproc.h"
+#include "../proc/sig.h"
+#include "../proc/sysinfo.h"
+#include "../proc/version.h"
+#include "../proc/wchan.h"
+#include "../proc/whattime.h"
#include "top.h"
+#include "top_nls.h"
/*###### Miscellaneous global stuff ####################################*/
@@ -76,7 +81,7 @@ static unsigned Pg2K_shft = 0;
/* (assume no IO-wait stats, overridden if linux 2.5.41) */
static int Cpu_tot;
static float Cpu_pmax;
-static const char *Cpu_States_fmts = STATES_line2x4;
+static const char *Cpu_States_fmts;
/* Specific process id monitoring support */
static pid_t Monpids [MONPIDMAX] = { 0 };
@@ -358,8 +363,8 @@ static void bye_bye (const char *str) {
, LINUX_VERSION_PATCH(linux_version_code)
, procps_version
, (unsigned)Hertz, (unsigned)sizeof(Hertz), (unsigned)sizeof(Hertz) * 8
- , Page_size, Cpu_tot
- , (unsigned) sizeof(CPU_t), (unsigned)sizeof(HST_t), Page_size / (unsigned)sizeof(HST_t), HHist_siz
+ , Page_size, Cpu_tot , (unsigned) sizeof(CPU_t)
+ , (unsigned)sizeof(HST_t), Page_size / (unsigned)sizeof(HST_t), HHist_siz
, (unsigned)sizeof(proc_t), (unsigned)sizeof(p->cmd), (unsigned)sizeof(proc_t*)
, (long)Frames_libflags
, (unsigned)SCREENMAX, (unsigned)ROWMINSIZ, (unsigned)ROWMAXSIZ
@@ -487,7 +492,7 @@ static void error_exit (const char *str) {
/*
- * Handle library memory errors ourselves rather than accept a default
+ * Handle library errors ourselves rather than accept a default
* fprintf to stderr (since we've mucked with the termios struct) */
static void library_err (const char *fmts, ...) NORETURN;
static void library_err (const char *fmts, ...) {
@@ -526,14 +531,11 @@ static void pause_pgm (void) {
* Catches all remaining signals not otherwise handled */
static void sig_abexit (int sig) NORETURN;
static void sig_abexit (int sig) {
- static const char *ab_msg =
- "\n\tsignal %d (%s) was caught by %s, please"
- "\n\tsee http://www.debian.org/Bugs/Reporting\n";
sigset_t ss;
sigfillset(&ss);
sigprocmask(SIG_BLOCK, &ss, NULL);
- bye_bye(fmtmk(ab_msg, sig, signal_number_to_name(sig), Myname));
+ bye_bye(fmtmk(N_fmt(EXIT_signals_fmt), sig, signal_number_to_name(sig), Myname));
} // end: sig_abexit
@@ -693,7 +695,7 @@ static inline void show_scroll (void) {
if (1 > totpflgs) totpflgs = 1;
if (1 > begpflgs) begpflgs = 1;
snprintf(tmp, sizeof(tmp)
- , "scroll coordinates: y = %d/%d (tasks), x = %d/%d (fields)"
+ , N_fmt(SCROLL_coord_fmt)
, Curwin->begtask + 1, Frame_maxtask
, begpflgs, totpflgs);
PUTT("%s%s %.*s%s", tg2(0, Msg_row), Caps_off, Screen_cols - 2, tmp, Cap_clr_eol);
@@ -789,7 +791,33 @@ static void show_special (int interact, const char *glob) {
if (*glob) PUTT("%.*s", Screen_cols -1, glob);
} // end: show_special
-/*###### Low Level Keyboard support ####################################*/
+/*###### Low Level Memory/Keyboard support #############################*/
+
+ /*
+ * Handle our own memory stuff without the risk of leaving the
+ * user's terminal in an ugly state should things go sour. */
+
+static void *alloc_c (size_t num) MALLOC;
+static void *alloc_c (size_t num) {
+ void *pv;
+
+ if (!num) ++num;
+ if (!(pv = calloc(1, num)))
+ error_exit(N_txt(FAIL_alloc_c_txt));
+ return pv;
+} // end: alloc_c
+
+
+static void *alloc_r (void *ptr, size_t num) MALLOC;
+static void *alloc_r (void *ptr, size_t num) {
+ void *pv;
+
+ if (!num) ++num;
+ if (!(pv = realloc(ptr, num)))
+ error_exit(N_txt(FAIL_alloc_r_txt));
+ return pv;
+} // end: alloc_r
+
/*
* This routine isolates ALL user INPUT and ensures that we
@@ -996,7 +1024,7 @@ static float get_float (const char *prompt) {
if (!(*(line = linein(prompt)))) return -1.0;
// note: we're not allowing negative floats
if (strcspn(line, "+,.0123456789")) {
- show_msg("Unacceptable floating point");
+ show_msg(N_txt(BAD_numfloat_txt));
return -1.0;
}
sscanf(line, "%f", &f);
@@ -1013,7 +1041,7 @@ static int get_int (const char *prompt) {
if (!(*(line = linein(prompt)))) return INT_MIN;
// note: we've got to allow negative ints (renice)
if (strcspn(line, "-+0123456789")) {
- show_msg("Unacceptable integer");
+ show_msg(N_txt(BAD_integers_txt));
return INT_MIN;
}
sscanf(line, "%d", &n);
@@ -1065,11 +1093,11 @@ static const char *scale_num (unsigned long num, const int width, const int type
* format 'tics' to fit 'width'. */
static const char *scale_tics (TIC_t tics, const int width) {
#ifdef CASEUP_SUFIX
- #define HH "%uH"
+ #define HH "%uH" // nls_maybe
#define DD "%uD"
#define WW "%uW"
#else
- #define HH "%uh"
+ #define HH "%uh" // nls_maybe
#define DD "%ud"
#define WW "%uw"
#endif
@@ -1124,7 +1152,7 @@ static const char *user_certify (WIN_t *q, const char *str, char typ) {
pwd = getpwuid(num);
else
pwd = getpwnam(str);
- if (!pwd) return "Invalid user";
+ if (!pwd) return N_txt(BAD_username_txt);
q->usrseluid = pwd->pw_uid;
q->usrseltyp = typ;
}
@@ -1186,63 +1214,65 @@ static FLD_t Fieldstab[] = {
/* .head + .fmts anomolies:
entries shown with NULL are either valued at runtime (see zap_fieldstab)
or, in the case of .fmts, may represent variable width fields
+ .desc anomolies:
+ the .desc field is always null initially, under nls support
.lflg anomolies:
P_UED, L_NONE - natural outgrowth of 'stat()' in readproc (euid)
P_CPU, L_stat - never filled by libproc, but requires times (pcpu)
P_CMD, L_stat - may yet require L_CMDLINE in calibrate_fields (cmd/cmdline)
L_EITHER - must L_status, else L_stat == 64-bit math (__udivdi3) on 32-bit !
.head .fmts .width .scale .sort .lflg .desc
- ------------ -------- ------ ------ -------- -------- ---------------------- */
- { NULL, NULL, -1, -1, SF(PID), L_NONE, "Process Id" },
- { NULL, NULL, -1, -1, SF(PPD), L_EITHER, "Parent Process pid" },
- { " UID ", "%5d ", -1, -1, SF(UED), L_NONE, "Effective User Id" },
- { "USER ", "%-8.8s ", -1, -1, SF(UEN), L_EUSER, "Effective User Name" },
- { " RUID ", "%5d ", -1, -1, SF(URD), L_status, "Real User Id" },
- { "RUSER ", "%-8.8s ", -1, -1, SF(URN), L_OUSER, "Real User Name" },
- { " SUID ", "%5d ", -1, -1, SF(USD), L_status, "Saved User Id" },
- { "SUSER ", "%-8.8s ", -1, -1, SF(USN), L_OUSER, "Saved User Name" },
- { " GID ", "%5d ", -1, -1, SF(GID), L_NONE, "Group Id" },
- { "GROUP ", "%-8.8s ", -1, -1, SF(GRP), L_EGROUP, "Group Name" },
- { NULL, NULL, -1, -1, SF(PGD), L_stat, "Process Group Id" },
- { "TTY ", "%-8.8s ", 8, -1, SF(TTY), L_stat, "Controlling Tty" },
- { NULL, NULL, -1, -1, SF(TPG), L_stat, "Tty Process Grp Id" },
- { NULL, NULL, -1, -1, SF(SID), L_stat, "Session Id" },
- { " PR ", "%3d ", -1, -1, SF(PRI), L_stat, "Priority" },
- { " NI ", "%3d ", -1, -1, SF(NCE), L_stat, "Nice Value" },
- { "nTH ", "%3d ", -1, -1, SF(THD), L_EITHER, "Number of Threads" },
- { NULL, NULL, -1, -1, SF(CPN), L_stat, "Last Used Cpu (SMP)" },
- { " %CPU ", NULL, -1, -1, SF(CPU), L_stat, "CPU Usage" },
- { " TIME ", "%6.6s ", 6, -1, SF(TME), L_stat, "CPU Time" },
- { " TIME+ ", "%9.9s ", 9, -1, SF(TME), L_stat, "CPU Time, hundredths" },
- { "%MEM ", "%#4.1f ", -1, -1, SF(RES), L_statm, "Memory Usage (RES)" },
- { " VIRT ", "%5.5s ", 5, SK_Kb, SF(VRT), L_statm, "Virtual Image (kb)" },
- { "SWAP ", "%4.4s ", 4, SK_Kb, SF(SWP), L_status, "Swapped Size (kb)" },
- { " RES ", "%4.4s ", 4, SK_Kb, SF(RES), L_statm, "Resident Size (kb)" },
- { "CODE ", "%4.4s ", 4, SK_Kb, SF(COD), L_statm, "Code Size (kb)" },
- { "DATA ", "%4.4s ", 4, SK_Kb, SF(DAT), L_statm, "Data+Stack Size (kb)" },
- { " SHR ", "%4.4s ", 4, SK_Kb, SF(SHR), L_statm, "Shared Mem Size (kb)" },
- { "nMaj ", "%4.4s ", 4, SK_no, SF(FL1), L_stat, "Major Page Faults" },
- { "nMin ", "%4.4s ", 4, SK_no, SF(FL2), L_stat, "Minor Page Faults" },
- { "nDRT ", "%4.4s ", 4, SK_no, SF(DRT), L_statm, "Dirty Pages Count" },
- { "S ", "%c ", -1, -1, SF(STA), L_EITHER, "Process Status" },
+ ------------ -------- ------ ------ -------- -------- ------ */
+ { NULL, NULL, -1, -1, SF(PID), L_NONE, NULL },
+ { NULL, NULL, -1, -1, SF(PPD), L_EITHER, NULL },
+ { " UID ", "%5d ", -1, -1, SF(UED), L_NONE, NULL },
+ { "USER ", "%-8.8s ", -1, -1, SF(UEN), L_EUSER, NULL },
+ { " RUID ", "%5d ", -1, -1, SF(URD), L_status, NULL },
+ { "RUSER ", "%-8.8s ", -1, -1, SF(URN), L_OUSER, NULL },
+ { " SUID ", "%5d ", -1, -1, SF(USD), L_status, NULL },
+ { "SUSER ", "%-8.8s ", -1, -1, SF(USN), L_OUSER, NULL },
+ { " GID ", "%5d ", -1, -1, SF(GID), L_NONE, NULL },
+ { "GROUP ", "%-8.8s ", -1, -1, SF(GRP), L_EGROUP, NULL },
+ { NULL, NULL, -1, -1, SF(PGD), L_stat, NULL },
+ { "TTY ", "%-8.8s ", 8, -1, SF(TTY), L_stat, NULL },
+ { NULL, NULL, -1, -1, SF(TPG), L_stat, NULL },
+ { NULL, NULL, -1, -1, SF(SID), L_stat, NULL },
+ { " PR ", "%3d ", -1, -1, SF(PRI), L_stat, NULL },
+ { " NI ", "%3d ", -1, -1, SF(NCE), L_stat, NULL },
+ { "nTH ", "%3d ", -1, -1, SF(THD), L_EITHER, NULL },
+ { NULL, NULL, -1, -1, SF(CPN), L_stat, NULL },
+ { " %CPU ", NULL, -1, -1, SF(CPU), L_stat, NULL },
+ { " TIME ", "%6.6s ", 6, -1, SF(TME), L_stat, NULL },
+ { " TIME+ ", "%9.9s ", 9, -1, SF(TME), L_stat, NULL },
+ { "%MEM ", "%#4.1f ", -1, -1, SF(RES), L_statm, NULL },
+ { " VIRT ", "%5.5s ", 5, SK_Kb, SF(VRT), L_statm, NULL },
+ { "SWAP ", "%4.4s ", 4, SK_Kb, SF(SWP), L_status, NULL },
+ { " RES ", "%4.4s ", 4, SK_Kb, SF(RES), L_statm, NULL },
+ { "CODE ", "%4.4s ", 4, SK_Kb, SF(COD), L_statm, NULL },
+ { "DATA ", "%4.4s ", 4, SK_Kb, SF(DAT), L_statm, NULL },
+ { " SHR ", "%4.4s ", 4, SK_Kb, SF(SHR), L_statm, NULL },
+ { "nMaj ", "%4.4s ", 4, SK_no, SF(FL1), L_stat, NULL },
+ { "nMin ", "%4.4s ", 4, SK_no, SF(FL2), L_stat, NULL },
+ { "nDRT ", "%4.4s ", 4, SK_no, SF(DRT), L_statm, NULL },
+ { "S ", "%c ", -1, -1, SF(STA), L_EITHER, NULL },
// next 2 entries are special: '.head' is variable width (see calibrate_fields)
- { "COMMAND ", NULL, -1, -1, SF(CMD), L_EITHER, "Command Name/Line" },
- { "WCHAN ", NULL, -1, -1, SF(WCH), L_stat, "Sleeping in Function" },
+ { "COMMAND ", NULL, -1, -1, SF(CMD), L_EITHER, NULL },
+ { "WCHAN ", NULL, -1, -1, SF(WCH), L_stat, NULL },
// next entry's special: the 0's will be replaced with '.'!
#ifdef CASEUP_HEXES
- { "Flags ", "%08lX ", -1, -1, SF(FLG), L_stat, "Task Flags <sched.h>" },
+ { "Flags ", "%08lX ", -1, -1, SF(FLG), L_stat, NULL },
#else
- { "Flags ", "%08lx ", -1, -1, SF(FLG), L_stat, "Task Flags <sched.h>" },
+ { "Flags ", "%08lx ", -1, -1, SF(FLG), L_stat, NULL },
#endif
// next 3 entries as P_CMD/P_WCH: '.head' must be same length -- they share varcolsz
- { "CGROUPS ", NULL, -1, -1, SF(CGR), L_CGROUP, "Control Groups" },
- { "SUPGIDS ", NULL, -1, -1, SF(SGD), L_status, "Supp Groups IDs" },
- { "SUPGRPS ", NULL, -1, -1, SF(SGN), L_SUPGRP, "Supp Groups Names" },
- { NULL, NULL, -1, -1, SF(TGD), L_status, "Thread Group Id" }
+ { "CGROUPS ", NULL, -1, -1, SF(CGR), L_CGROUP, NULL },
+ { "SUPGIDS ", NULL, -1, -1, SF(SGD), L_status, NULL },
+ { "SUPGRPS ", NULL, -1, -1, SF(SGN), L_SUPGRP, NULL },
+ { NULL, NULL, -1, -1, SF(TGD), L_status, NULL }
#ifdef OOMEM_ENABLE
#define L_oom PROC_FILLOOM
- ,{ "Adj ", "%3d ", -1, -1, SF(OOA), L_oom, "oom_adjustment (2^X)" }
- ,{ " Badness ", "%8d ", -1, -1, SF(OOM), L_oom, "oom_score (badness)" }
+ ,{ "Adj ", "%3d ", -1, -1, SF(OOA), L_oom, NULL }
+ ,{ " Badness ", "%8d ", -1, -1, SF(OOM), L_oom, NULL }
#undef L_oom
#endif
#undef SF
@@ -1318,7 +1348,7 @@ static void adj_geometry (void) {
// we'll only grow our Pseudo_screen, never shrink it
if (pseudo_max < Pseudo_size) {
pseudo_max = Pseudo_size;
- Pseudo_screen = realloc(Pseudo_screen, pseudo_max);
+ Pseudo_screen = alloc_r(Pseudo_screen, pseudo_max);
}
PSU_CLREOS(0);
if (Frames_resize) putp(Cap_clr_scr);
@@ -1348,7 +1378,7 @@ static void calibrate_fields (void) {
sigemptyset(&newss);
sigaddset(&newss, SIGWINCH);
if (-1 == sigprocmask(SIG_BLOCK, &newss, &oldss))
- error_exit(fmtmk("failed sigprocmask, SIG_BLOCK: %s", strerror(errno)));
+ error_exit(fmtmk(N_fmt(FAIL_sigstop_fmt), strerror(errno)));
adj_geometry();
Frames_libflags = 0;
@@ -1501,7 +1531,7 @@ static void calibrate_fields (void) {
Frames_resize = 0;
if (-1 == sigprocmask(SIG_SETMASK, &oldss, NULL))
- error_exit(fmtmk("failed sigprocmask, SIG_SETMASK: %s", strerror(errno)));
+ error_exit(fmtmk(N_fmt(FAIL_sigmask_fmt), strerror(errno)));
} // end: calibrate_fields
@@ -1549,13 +1579,13 @@ static void display_fields (int focus, int extend) {
fflush(stdout);
i = (P_MAXPFLGS % mxCOL) ? 1 : 0;
- if (rmax < i + (P_MAXPFLGS / mxCOL)) error_exit("++rows");
+ if (rmax < i + (P_MAXPFLGS / mxCOL)) error_exit("++rows"); // nls_maybe
i = P_MAXPFLGS / rmax;
if (P_MAXPFLGS % rmax) ++i;
if (i > 1) { cmax /= i; xadd = 1; }
if (cmax > xTOTL) cmax = xTOTL;
smax = cmax - xPRFX;
- if (smax < 0) error_exit("++cols");
+ if (smax < 0) error_exit("++cols"); // nls_maybe
for (i = 0; i < P_MAXPFLGS; ++i) {
char sbuf[xSUFX+1];
@@ -1614,7 +1644,8 @@ static void fields_utility (void) {
if (!h) for (h = Fieldstab[f].head; ' ' == *h; ++h) ;
display_fields(i, (p != NULL));
putp(Cap_home);
- show_special(1, fmtmk(FIELDS_heading, w->grpname, CHKw(w, Show_FOREST) ? "forest view" : h));
+ show_special(1, fmtmk(N_unq(FIELD_header_fmt)
+ , w->grpname, CHKw(w, Show_FOREST) ? N_txt(FOREST_views_txt) : h));
switch (key = keyin(0)) {
case kbd_UP:
@@ -1674,7 +1705,7 @@ static void zap_fieldstab (void) {
static char fmts_pid[8];
static char fmts_cpu[8];
static int once;
- unsigned digits;
+ unsigned i, digits;
char buf[8];
if (once) goto always;
@@ -1692,7 +1723,7 @@ static void zap_fieldstab (void) {
Fieldstab[P_TPG].head = "TPGID ";
Fieldstab[P_TPG].fmts = "%5d ";
if (5 < (digits = get_pid_digits())) {
- if (10 < digits) error_exit("failed pid size test");
+ if (10 < digits) error_exit(N_txt(FAIL_widepid_txt));
snprintf(fmts_pid, sizeof(fmts_pid), "%%%uu ", digits);
Fieldstab[P_PID].head = " PID " + 10 - digits;
Fieldstab[P_PID].fmts = fmts_pid;
@@ -1707,6 +1738,10 @@ static void zap_fieldstab (void) {
Fieldstab[P_TPG].head = " TPGID " + 10 - digits;
Fieldstab[P_TPG].fmts = fmts_pid;
}
+
+ for (i = 0; i < P_MAXPFLGS; i++)
+ Fieldstab[i].desc = N_fld(i);
+
once = 1;
/*** hotplug_acclimated ***/
@@ -1714,7 +1749,7 @@ always:
Fieldstab[P_CPN].head = "P ";
Fieldstab[P_CPN].fmts = "%1d ";
if (1 < (digits = (unsigned)snprintf(buf, sizeof(buf), "%u", (unsigned)Cpu_tot))) {
- if (5 < digits) error_exit("failed num cpus test");
+ if (5 < digits) error_exit(N_txt(FAIL_widecpu_txt));
snprintf(fmts_cpu, sizeof(fmts_cpu), "%%%ud ", digits);
Fieldstab[P_CPN].head = " P " + 5 - digits;
Fieldstab[P_CPN].fmts = fmts_cpu;
@@ -1746,7 +1781,6 @@ always:
* cpus[0] thru cpus[n] == tics for each separate cpu
* cpus[Cpu_tot] == tics from the 1st /proc/stat line */
static CPU_t *cpus_refresh (CPU_t *cpus) {
- static const char err_read[] = "failed /proc/stat read";
static FILE *fp = NULL;
static int sav_cpus = -1;
char buf[MEDBUFSIZ]; // enough for /proc/stat CPU line (not the intr line)
@@ -1764,12 +1798,11 @@ static CPU_t *cpus_refresh (CPU_t *cpus) {
(sorry Linux, but you'll have to close it for us) */
if (!fp) {
if (!(fp = fopen("/proc/stat", "r")))
- error_exit(fmtmk("failed /proc/stat open: %s", strerror(errno)));
+ error_exit(fmtmk(N_fmt(FAIL_statopn_fmt), strerror(errno)));
/* note: we allocate one more CPU_t than Cpu_tot so that the last slot
can hold tics representing the /proc/stat cpu summary (the first
line read) -- that slot supports our View_CPUSUM toggle */
- if ((cpus = calloc((1 + Cpu_tot),sizeof(CPU_t)))==NULL)
- error_exit(fmtmk("failed to allocate memory for CPU_t"));
+ cpus = alloc_c((1 + Cpu_tot) * sizeof(CPU_t));
}
rewind(fp);
fflush(fp);
@@ -1777,11 +1810,11 @@ static CPU_t *cpus_refresh (CPU_t *cpus) {
// first value the last slot with the cpu summary line
cpus[Cpu_tot].x = cpus[Cpu_tot].y = cpus[Cpu_tot].z = 0;
// FIXME: can't tell above by kernel version number
- if (!fgets(buf, sizeof(buf), fp)) error_exit(err_read);
+ if (!fgets(buf, sizeof(buf), fp)) error_exit(N_txt(FAIL_statget_txt));
if (4 > sscanf(buf, "cpu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu"
, &cpus[Cpu_tot].u, &cpus[Cpu_tot].n, &cpus[Cpu_tot].s, &cpus[Cpu_tot].i
, &cpus[Cpu_tot].w, &cpus[Cpu_tot].x, &cpus[Cpu_tot].y, &cpus[Cpu_tot].z))
- error_exit(err_read);
+ error_exit(N_txt(FAIL_statget_txt));
// and just in case we're 2.2.xx compiled without SMP support...
if (1 == Cpu_tot)
memcpy(cpus, &cpus[1], sizeof(CPU_t));
@@ -1791,13 +1824,13 @@ static CPU_t *cpus_refresh (CPU_t *cpus) {
rewind(fp);
fgets(buf, sizeof(buf), fp);
#endif
- if (!fgets(buf, sizeof(buf), fp)) error_exit(err_read);
+ if (!fgets(buf, sizeof(buf), fp)) error_exit(N_txt(FAIL_statget_txt));
cpus[i].x = cpus[i].y = cpus[i].z = 0;
// FIXME: can't tell above by kernel version number
if (4 > sscanf(buf, "cpu%u %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu", &cpus[i].id
, &cpus[i].u, &cpus[i].n, &cpus[i].s, &cpus[i].i
, &cpus[i].w, &cpus[i].x, &cpus[i].y, &cpus[i].z)) {
- error_exit(err_read);
+ error_exit(N_txt(FAIL_statget_txt));
}
#ifdef PRETEND4CPUS
cpus[i].id = i;
@@ -1920,8 +1953,8 @@ static void prochlp (proc_t *this) {
if (Frame_maxtask+1 >= HHist_siz) {
HHist_siz = HHist_siz * 5 / 4 + 100;
- PHist_sav = realloc(PHist_sav, sizeof(HST_t) * HHist_siz);
- PHist_new = realloc(PHist_new, sizeof(HST_t) * HHist_siz);
+ PHist_sav = alloc_r(PHist_sav, sizeof(HST_t) * HHist_siz);
+ PHist_new = alloc_r(PHist_new, sizeof(HST_t) * HHist_siz);
}
/* calculate time in this process; the sum of user time (utime) and
@@ -1965,13 +1998,13 @@ static void procs_refresh (void) {
prochlp(NULL); // prep for a new frame
if (NULL == (PT = openproc(Frames_libflags, Monpids)))
- error_exit(fmtmk("failed openproc: %s", strerror(errno)));
+ error_exit(fmtmk(N_fmt(FAIL_openlib_fmt), strerror(errno)));
read_something = Thread_mode ? readeither : readproc;
for (;;) {
if (n_used == n_alloc) {
n_alloc = 10 + ((n_alloc * 5) / 4); // grow by over 25%
- private_ppt = realloc(private_ppt, sizeof(proc_t*) * n_alloc);
+ private_ppt = alloc_r(private_ppt, sizeof(proc_t*) * n_alloc);
// ensure NULL pointers for the additional memory just acquired
memset(private_ppt + n_used, 0, sizeof(proc_t*) * (n_alloc - n_used));
}
@@ -1990,7 +2023,7 @@ static void procs_refresh (void) {
else {
n_saved = n_alloc;
for (i = 0; i < GROUPSMAX; i++) {
- Winstk[i].ppt = realloc(Winstk[i].ppt, sizeof(proc_t*) * n_alloc);
+ Winstk[i].ppt = alloc_r(Winstk[i].ppt, sizeof(proc_t*) * n_alloc);
memcpy(Winstk[i].ppt, private_ppt, sizeof(proc_t*) * n_used);
}
}
@@ -2035,23 +2068,27 @@ static void before (char *me) {
struct sigaction sa;
int i;
- // setup our program name and library error message handler -- big!
+ // setup our program name
Myname = strrchr(me, '/');
if (Myname) ++Myname; else Myname = me;
- // establish cpu particulars -- even bigger!
+ // accommodate nls/gettext potential translations
+ initialize_nls();
+
+ // establish cpu particulars
#ifdef PRETEND4CPUS
smp_num_cpus = 4;
#endif
Cpu_tot = smp_num_cpus;
+ Cpu_States_fmts = N_unq(STATE_lin2x4_fmt);
if (linux_version_code > LINUX_VERSION(2, 5, 41))
- Cpu_States_fmts = STATES_line2x5;
+ Cpu_States_fmts = N_unq(STATE_lin2x5_fmt);
if (linux_version_code >= LINUX_VERSION(2, 6, 0))
- Cpu_States_fmts = STATES_line2x6;
+ Cpu_States_fmts = N_unq(STATE_lin2x6_fmt);
if (linux_version_code >= LINUX_VERSION(2, 6, 11))
- Cpu_States_fmts = STATES_line2x7;
+ Cpu_States_fmts = N_unq(STATE_lin2x7_fmt);
- // get virtual page stuff -- nearing huge!
+ // get virtual page stuff
Page_size = getpagesize();
i = Page_size;
while(i > 1024) { i >>= 1; Pg2K_shft++; }
@@ -2105,10 +2142,7 @@ static void before (char *me) {
* line b: contains w->winflags, sortindx, maxtasks
* line c: contains w->summclr, msgsclr, headclr, taskclr */
static void configs_read (void) {
-#ifndef RCFILE_NOERR
- static const char err_rcid[] = "incompatible rcfile, you should delete '%s'";
- static const char err_flds[] = "window entry #%d corrupt, please delete '%s'";
-#else
+#ifdef RCFILE_NOERR
RCF_t rcdef = DEF_RCFILE;
#endif
float tmp_delay = DEF_DELAY;
@@ -2140,7 +2174,7 @@ static void configs_read (void) {
, &id, &Rc.mode_altscr, &Rc.mode_irixps, &tmp_delay, &i))
|| RCF_VERSION_ID != id)
#ifndef RCFILE_NOERR
- error_exit(fmtmk(err_rcid, Rc_name));
+ error_exit(fmtmk(N_fmt(RC_bad_files_fmt), Rc_name));
#else
goto just_default_em;
#endif
@@ -2157,7 +2191,7 @@ static void configs_read (void) {
#endif
if (strlen(Winstk[i].rc.fieldscur) != sizeof(DEF_FIELDS) - 1)
#ifndef RCFILE_NOERR
- error_exit(fmtmk(err_flds, i+1, Rc_name));
+ error_exit(fmtmk(N_fmt(RC_bad_entry_fmt), i+1, Rc_name));
#else
goto just_default_em;
#endif
@@ -2165,7 +2199,7 @@ static void configs_read (void) {
int f = FLDget(&Winstk[i], x);
if (P_MAXPFLGS <= f)
#ifndef RCFILE_NOERR
- error_exit(fmtmk(err_flds, i+1, Rc_name));
+ error_exit(fmtmk(N_fmt(RC_bad_entry_fmt), i+1, Rc_name));
#else
goto just_default_em;
#endif
@@ -2211,9 +2245,6 @@ static void parse_args (char **args) {
. no deprecated/illegal use of 'breakargv:' with goto
. bunched args are actually handled properly and none are ignored
. we tolerate NO whitespace and NO switches -- maybe too tolerant? */
- static const char usage_str[] =
- " -hv | -bcHiSs -d delay -n limit -u|U user | -p pid[,pid] -w [cols]";
- static const char sel_error[] = "conflicting process selections (U/p/u)";
static const char numbs_str[] = "+,-.0123456789";
float tmp_delay = MAXFLOAT;
char *p;
@@ -2230,7 +2261,8 @@ static void parse_args (char **args) {
if (cp[1]) ++cp;
else if (*args) cp = *args++;
if (strspn(cp, numbs_str))
- error_exit(fmtmk("inappropriate '%s'\nusage:\t%s%s", cp, Myname, usage_str));
+ error_exit(fmtmk(N_fmt(WRONG_switch_fmt)
+ , cp, Myname, N_txt(USAGE_abbrev_txt)));
continue;
case 'b':
Batch = 1;
@@ -2241,17 +2273,18 @@ static void parse_args (char **args) {
case 'd':
if (cp[1]) ++cp;
else if (*args) cp = *args++;
- else error_exit("-d requires argument");
+ else error_exit(fmtmk(N_fmt(MISSING_args_fmt), ch));
/* a negative delay will be dealt with shortly... */
if (1 != sscanf(cp, "%f", &tmp_delay))
- error_exit(fmtmk("bad delay '%s'", cp));
+ error_exit(fmtmk(N_fmt(BAD_delayint_fmt), cp));
break;
case 'H':
Thread_mode = 1;
break;
case 'h':
case 'v': case 'V':
- fprintf(stdout, "\t%s\nusage:\t%s%s", procps_version, Myname, usage_str);
+ fprintf(stdout, N_fmt(HELP_cmdline_fmt)
+ , procps_version, Myname, N_txt(USAGE_abbrev_txt));
bye_bye(NULL);
case 'i':
TOGw(Curwin, Show_IDLEPS);
@@ -2260,21 +2293,21 @@ static void parse_args (char **args) {
case 'n':
if (cp[1]) cp++;
else if (*args) cp = *args++;
- else error_exit("-n requires argument");
+ else error_exit(fmtmk(N_fmt(MISSING_args_fmt), ch));
if (1 != sscanf(cp, "%d", &Loops) || 1 > Loops)
- error_exit(fmtmk("bad iterations arg '%s'", cp));
+ error_exit(fmtmk(N_fmt(BAD_niterate_fmt), cp));
break;
case 'p':
- if (Curwin->usrseltyp) error_exit(sel_error);
+ if (Curwin->usrseltyp) error_exit(N_txt(SELECT_clash_txt));
do {
if (cp[1]) cp++;
else if (*args) cp = *args++;
- else error_exit("-p argument missing");
+ else error_exit(fmtmk(N_fmt(MISSING_args_fmt), ch));
if (Monpidsidx >= MONPIDMAX)
- error_exit(fmtmk("pid limit (%d) exceeded", MONPIDMAX));
+ error_exit(fmtmk(N_fmt(LIMIT_exceed_fmt), MONPIDMAX));
if (1 != sscanf(cp, "%d", &Monpids[Monpidsidx])
|| 0 > Monpids[Monpidsidx])
- error_exit(fmtmk("bad pid '%s'", cp));
+ error_exit(fmtmk(N_fmt(BAD_mon_pids_fmt), cp));
if (!Monpids[Monpidsidx])
Monpids[Monpidsidx] = getpid();
Monpidsidx++;
@@ -2292,10 +2325,10 @@ static void parse_args (char **args) {
case 'u':
case 'U':
{ const char *errmsg;
- if (Monpidsidx || Curwin->usrseltyp) error_exit(sel_error);
+ if (Monpidsidx || Curwin->usrseltyp) error_exit(N_txt(SELECT_clash_txt));
if (cp[1]) cp++;
else if (*args) cp = *args++;
- else error_exit(fmtmk("-%c missing name", ch));
+ else error_exit(fmtmk(N_fmt(MISSING_args_fmt), ch));
if ((errmsg = user_certify(Curwin, cp, ch))) error_exit(errmsg);
cp += strlen(cp);
break;
@@ -2309,14 +2342,15 @@ static void parse_args (char **args) {
if (pn && !(ci = strspn(pn, "0123456789"))) { ai = 0; pn = NULL; }
if (pn && (1 != sscanf(pn, "%d", &Width_mode)
|| Width_mode < W_MIN_COL))
- error_exit(fmtmk("bad width arg '%s', must > %d", pn, W_MIN_COL-1));
+ error_exit(fmtmk(N_fmt(BAD_widtharg_fmt), pn, W_MIN_COL-1));
cp++;
args += ai;
if (pn) cp = pn + ci;
continue;
}
default :
- error_exit(fmtmk("unknown option '%c'\nusage:\t%s%s", *cp, Myname, usage_str));
+ error_exit(fmtmk(N_fmt(UNKNOWN_opts_fmt)
+ , *cp, Myname, N_txt(USAGE_abbrev_txt)));
} // end: switch (*cp)
@@ -2329,9 +2363,9 @@ static void parse_args (char **args) {
// fixup delay time, maybe...
if (MAXFLOAT > tmp_delay) {
if (Secure_mode)
- error_exit("-d disallowed in \"secure\" mode");
+ error_exit(N_txt(DELAY_secure_txt));
if (0 > tmp_delay)
- error_exit("-d requires positive argument");
+ error_exit(N_txt(DELAY_badarg_txt));
Rc.delay_time = tmp_delay;
}
} // end: parse_args
@@ -2355,7 +2389,7 @@ static void whack_terminal (void) {
#endif
// our part...
if (-1 == tcgetattr(STDIN_FILENO, &Tty_original))
- error_exit("failed tty get");
+ error_exit(N_txt(FAIL_tty_get_txt));
// ok, haven't really changed anything but we do have our snapshot
Ttychanged = 1;
@@ -2370,7 +2404,7 @@ static void whack_terminal (void) {
tmptty.c_cc[VERASE] = *key_backspace;
#ifdef TERMIOS_ONLY
if (-1 == tcsetattr(STDIN_FILENO, TCSAFLUSH, &tmptty))
- error_exit(fmtmk("failed Tty_tweaked set: %s", strerror(errno)));
+ error_exit(fmtmk(N_fmt(FAIL_tty_mod_fmt), strerror(errno)));
tcgetattr(STDIN_FILENO, &Tty_tweaked);
#endif
// lastly, a nearly raw mode for unsolicited single keystrokes
@@ -2378,7 +2412,7 @@ static void whack_terminal (void) {
tmptty.c_cc[VMIN] = 1;
tmptty.c_cc[VTIME] = 0;
if (-1 == tcsetattr(STDIN_FILENO, TCSAFLUSH, &tmptty))
- error_exit(fmtmk("failed Tty_raw set: %s", strerror(errno)));
+ error_exit(fmtmk(N_fmt(FAIL_tty_raw_fmt), strerror(errno)));
tcgetattr(STDIN_FILENO, &Tty_raw);
#ifndef OFF_STDIOLBF
@@ -2406,13 +2440,12 @@ static void win_names (WIN_t *q, const char *name) {
/*
* Display a window/field group (ie. make it "current"). */
static WIN_t *win_select (char ch) {
- static const char prompt[] = "Choose field group (1 - 4)";
WIN_t *w = Curwin; // avoid gcc bloat with a local copy
/* if there's no ch, it means we're supporting the external interface,
so we must try to get our own darn ch by begging the user... */
if (!ch) {
- show_pmt(prompt);
+ show_pmt(N_txt(CHOOSE_group_txt));
if (1 > chin(0, (char *)&ch, 1)) return Curwin;
}
switch (ch) {
@@ -2437,11 +2470,10 @@ static WIN_t *win_select (char ch) {
static int win_warn (int what) {
switch (what) {
case Warn_ALT:
- show_msg("Command disabled, 'A' mode required");
+ show_msg(N_txt(DISABLED_cmd_txt));
break;
case Warn_VIZ:
- show_msg(fmtmk("Command disabled, activate %s with '-' or '_'"
- , Curwin->grpname));
+ show_msg(fmtmk(N_fmt(DISABLED_win_fmt), Curwin->grpname));
break;
default: // keep gcc happy
break;
@@ -2480,7 +2512,7 @@ static void wins_colors (void) {
char ch, tgt = 'T';
if (0 >= max_colors) {
- show_msg("No colors to map!");
+ show_msg(N_txt(COLORS_nomap_txt));
return;
}
winsclrhlp(w, 1);
@@ -2490,11 +2522,11 @@ static void wins_colors (void) {
do {
putp(Cap_home);
// this string is well above ISO C89's minimum requirements!
- show_special(1, fmtmk(COLOR_help
+ show_special(1, fmtmk(N_unq(COLOR_custom_fmt)
, procps_version, w->grpname
- , CHKw(w, View_NOBOLD) ? "On" : "Off"
- , CHKw(w, Show_COLORS) ? "On" : "Off"
- , CHKw(w, Show_HIBOLD) ? "On" : "Off"
+ , CHKw(w, View_NOBOLD) ? N_txt(ON_word_only_txt) : N_txt(OFF_one_word_txt)
+ , CHKw(w, Show_COLORS) ? N_txt(ON_word_only_txt) : N_txt(OFF_one_word_txt)
+ , CHKw(w, Show_HIBOLD) ? N_txt(ON_word_only_txt) : N_txt(OFF_one_word_txt)
, tgt, clr, w->grpname));
if (1 > chin(0, &ch, 1)) break;
switch (ch) {
@@ -2642,7 +2674,7 @@ static void file_writerc (void) {
int i;
if (!(fp = fopen(Rc_name, "w"))) {
- show_msg(fmtmk("Failed '%s' open: %s", Rc_name, strerror(errno)));
+ show_msg(fmtmk(N_fmt(FAIL_rc_open_fmt), Rc_name, strerror(errno)));
return;
}
fprintf(fp, "%s's " RCF_EYECATCHER, Myname);
@@ -2661,23 +2693,23 @@ static void file_writerc (void) {
, Winstk[i].rc.headclr, Winstk[i].rc.taskclr);
}
fclose(fp);
- show_msg(fmtmk("Wrote configuration to '%s'", Rc_name));
+ show_msg(fmtmk(N_fmt(WRITE_rcfile_fmt), Rc_name));
} // end: file_writerc
static void find_string (int ch) {
- #define reDUX (found) ? "another " : ""
+ #define reDUX (found) ? N_txt(WORD_another_txt) : ""
static char str[SCREENMAX];
static int found;
char buf[ROWMINSIZ];
int i;
if ('&' == ch && !str[0]) {
- show_msg("Locate next inactive, use \"L\"");
+ show_msg(N_txt(FIND_no_next_txt));
return;
}
if ('L' == ch) {
- strcpy(str, linein("Locate string"));
+ strcpy(str, linein(N_txt(GET_find_str_txt)));
found = 0;
}
if (str[0]) {
@@ -2690,7 +2722,7 @@ static void find_string (int ch) {
return;
}
}
- show_msg(fmtmk("%s\"%s\" not found", reDUX, str));
+ show_msg(fmtmk(N_fmt(FIND_no_find_fmt), reDUX, str));
}
#undef reDUX
} // end: find_string
@@ -2703,20 +2735,19 @@ static void help_view (void) {
putp(Cap_clr_scr);
putp(Cap_curs_huge);
- // this string is well above ISO C89's minimum requirements!
- show_special(1, fmtmk(KEYS_help
+ show_special(1, fmtmk(N_unq(KEYS_helpbas_fmt)
, procps_version
, w->grpname
- , CHKw(w, Show_CTIMES) ? "On" : "Off"
+ , CHKw(w, Show_CTIMES) ? N_txt(ON_word_only_txt) : N_txt(OFF_one_word_txt)
, Rc.delay_time
- , Secure_mode ? "On" : "Off"
- , Secure_mode ? "" : KEYS_help_unsecured));
+ , Secure_mode ? N_txt(ON_word_only_txt) : N_txt(OFF_one_word_txt)
+ , Secure_mode ? "" : N_unq(KEYS_helpext_fmt)));
if (0 < chin(0, &ch, 1)
&& ('?' == ch || 'h' == ch || 'H' == ch)) {
do {
putp(Cap_clr_scr);
- show_special(1, fmtmk(WINDOWS_help
+ show_special(1, fmtmk(N_unq(WINDOWS_help_fmt)
, w->grpname
, Winstk[0].rc.winname, Winstk[1].rc.winname
, Winstk[2].rc.winname, Winstk[3].rc.winname));
@@ -2731,8 +2762,6 @@ static void help_view (void) {
static void keys_global (int ch) {
// standardized error message(s)
- static const char err_secure[] = "Unavailable in secure mode";
- static const char err_notsmp[] = "Only 1 cpu detected";
WIN_t *w = Curwin; // avoid gcc bloat with a local copy
switch (ch) {
@@ -2743,10 +2772,10 @@ static void keys_global (int ch) {
case 'd':
case 's':
if (Secure_mode)
- show_msg(err_secure);
+ show_msg(N_txt(NOT_onsecure_txt));
else {
float tmp =
- get_float(fmtmk("Change delay from %.1f to", Rc.delay_time));
+ get_float(fmtmk(N_fmt(DELAY_change_fmt), Rc.delay_time));
if (-1 < tmp) Rc.delay_time = tmp;
}
break;
@@ -2760,40 +2789,42 @@ static void keys_global (int ch) {
case 'H':
Thread_mode = !Thread_mode;
if (!CHKw(w, View_STATES))
- show_msg(fmtmk("Show threads %s", Thread_mode ? "On" : "Off"));
+ show_msg(fmtmk(N_fmt(THREADS_show_fmt)
+ , Thread_mode ? N_txt(ON_word_only_txt) : N_txt(OFF_one_word_txt)));
break;
case 'I':
if (Cpu_tot > 1) {
Rc.mode_irixps = !Rc.mode_irixps;
- show_msg(fmtmk("Irix mode %s", Rc.mode_irixps ? "On" : "Off"));
+ show_msg(fmtmk(N_fmt(IRIX_curmode_fmt)
+ , Rc.mode_irixps ? N_txt(ON_word_only_txt) : N_txt(OFF_one_word_txt)));
} else
- show_msg(err_notsmp);
+ show_msg(N_txt(NOT_smp_cpus_txt));
break;
case 'k':
if (Secure_mode) {
- show_msg(err_secure);
+ show_msg(N_txt(NOT_onsecure_txt));
} else {
int pid, sig = SIGTERM;
char *str;
- if (-1 < (pid = get_int("pid to signal/kill"))) {
- str = linein(fmtmk("Send pid %d signal [%d/sigterm]", pid, SIGTERM));
+ if (-1 < (pid = get_int(N_txt(GET_pid2kill_txt)))) {
+ str = linein(fmtmk(N_fmt(GET_sigs_num_fmt), pid, SIGTERM));
if (*str) sig = signal_name_to_number(str);
if (0 < sig && kill(pid, sig))
- show_msg(fmtmk("Failed signal pid '%d' with '%d': %s"
+ show_msg(fmtmk(N_fmt(FAIL_signals_fmt)
, pid, sig, strerror(errno)));
- else if (0 > sig) show_msg("Invalid signal");
+ else if (0 > sig) show_msg(N_txt(BAD_signalid_txt));
}
}
break;
case 'r':
if (Secure_mode)
- show_msg(err_secure);
+ show_msg(N_txt(NOT_onsecure_txt));
else {
int val, pid;
- if (-1 < (pid = get_int("PID to renice"))
- && INT_MIN < (val = get_int(fmtmk("Renice PID %d to value", pid))))
+ if (-1 < (pid = get_int(N_txt(GET_pid2nice_txt)))
+ && INT_MIN < (val = get_int(fmtmk(N_fmt(GET_nice_num_fmt), pid))))
if (setpriority(PRIO_PROCESS, (unsigned)pid, val))
- show_msg(fmtmk("Failed renice of PID %d to %d: %s"
+ show_msg(fmtmk(N_fmt(FAIL_re_nice_fmt)
, pid, val, strerror(errno)));
}
break;
@@ -2838,10 +2869,10 @@ static void keys_task (int ch) {
case '#':
case 'n':
if (VIZCHKw(w)) {
- int num = get_int(fmtmk("Maximum tasks = %d, change to (0 is unlimited)", w->rc.maxtasks));
+ int num = get_int(fmtmk(N_fmt(GET_max_task_fmt), w->rc.maxtasks));
if (INT_MIN < num) {
if (-1 < num ) w->rc.maxtasks = num;
- else show_msg("Invalid maximum");
+ else show_msg(N_txt(BAD_max_task_txt));
}
}
break;
@@ -2894,7 +2925,7 @@ static void keys_task (int ch) {
#else
if (!CHKw(w, Show_HICOLS | Show_HIROWS))
#endif
- show_msg("Nothing to highlight!");
+ show_msg(N_txt(HILIGHT_cant_txt));
else {
TOGw(w, Show_HIBOLD);
capsmk(w);
@@ -2920,14 +2951,15 @@ static void keys_task (int ch) {
case 'S':
if (VIZCHKw(w)) {
TOGw(w, Show_CTIMES);
- show_msg(fmtmk("Cumulative time %s", CHKw(w, Show_CTIMES) ? "On" : "Off"));
+ show_msg(fmtmk(N_fmt(TIME_accumed_fmt) , CHKw(w, Show_CTIMES)
+ ? N_txt(ON_word_only_txt) : N_txt(OFF_one_word_txt)));
}
break;
case 'U':
case 'u':
if (VIZCHKw(w)) {
const char *errmsg;
- if ((errmsg = user_certify(w, linein("Which user (blank for all)"), ch)))
+ if ((errmsg = user_certify(w, linein(N_txt(GET_user_ids_txt)), ch)))
show_msg(errmsg);
}
break;
@@ -2935,7 +2967,8 @@ static void keys_task (int ch) {
if (VIZCHKw(w)) {
TOGw(w, Show_FOREST);
if (!ENUviz(w, P_CMD))
- show_msg(fmtmk("Forest mode %s", CHKw(w, Show_FOREST) ? "On" : "Off"));
+ show_msg(fmtmk(N_fmt(FOREST_modes_fmt) , CHKw(w, Show_FOREST)
+ ? N_txt(ON_word_only_txt) : N_txt(OFF_one_word_txt)));
}
break;
case 'x':
@@ -3010,7 +3043,7 @@ static void keys_window (int ch) {
case 'G':
if (ALTCHKw) {
char tmp[SMLBUFSIZ];
- STRLCPY(tmp, linein(fmtmk("Rename window '%s' to (1-3 chars)", w->rc.winname)))
+ STRLCPY(tmp, linein(fmtmk(N_fmt(NAME_windows_fmt), w->rc.winname)));
if (tmp[0]) win_names(w, tmp);
}
break;
@@ -3152,7 +3185,7 @@ static void forest_create (WIN_t *q) {
qsort(Seed_ppt, Frame_maxtask, sizeof(proc_t*), Fieldstab[P_PPD].sort);
if (hwmsav < Frame_maxtask) { // grow, but never shrink
hwmsav = Frame_maxtask;
- Tree_ppt = realloc(Tree_ppt, sizeof(proc_t*) * hwmsav);
+ Tree_ppt = alloc_r(Tree_ppt, sizeof(proc_t*) * hwmsav);
}
while (0 == Seed_ppt[i]->ppid) // identify trees (expect 2)
forest_add(i++, 1); // add parent plus children
@@ -3228,7 +3261,7 @@ static void do_key (int ch) {
}
if (!(i < MAXTBL(key_tab))) {
- show_msg("Unknown command - try 'h' for help");
+ show_msg(N_txt(UNKNOWN_cmds_txt));
return;
}
};
@@ -3328,8 +3361,8 @@ static void summary_show (void) {
// Display Task and Cpu(s) States
if (isROOM(View_STATES, 2)) {
- show_special(0, fmtmk(STATES_line1
- , Thread_mode ? "Threads" : "Tasks"
+ show_special(0, fmtmk(N_unq(STATE_line_1_fmt)
+ , Thread_mode ? N_txt(WORD_threads_txt) : N_txt(WORD_process_txt)
, Frame_maxtask, Frame_running, Frame_sleepin
, Frame_stopped, Frame_zombied));
Msg_row += 1;
@@ -3338,14 +3371,14 @@ static void summary_show (void) {
if (CHKw(w, View_CPUSUM)) {
// display just the 1st /proc/stat line
- summaryhlp(&smpcpu[Cpu_tot], "Cpu(s):");
+ summaryhlp(&smpcpu[Cpu_tot], N_txt(WORD_allcpus_txt));
Msg_row += 1;
} else {
int i;
char tmp[MEDBUFSIZ];
// display each cpu's states separately, screen height permitting...
for (i = 0; i < Cpu_tot; i++) {
- snprintf(tmp, sizeof(tmp), "Cpu%-3d:", smpcpu[i].id);
+ snprintf(tmp, sizeof(tmp), N_fmt(WORD_eachcpu_fmt), smpcpu[i].id);
summaryhlp(&smpcpu[i], tmp);
Msg_row += 1;
if (!isROOM(anyFLG, 1)) break;
@@ -3357,14 +3390,16 @@ static void summary_show (void) {
if (isROOM(View_MEMORY, 2)) {
#define mkM(x) (unsigned long)(kb_main_ ## x >> shift)
#define mkS(x) (unsigned long)(kb_swap_ ## x >> shift)
- const char *which = "Kb";
+ const char *which = N_txt(AMT_kilobyte_txt);
int shift = 0;
/*** hotplug_acclimated ***/
- if (kb_main_total > 9999999) { which = "Mb"; shift = 10; }
- if (kb_main_total > 9999999999ull) { which = "Gb"; shift = 20; }
+ if (kb_main_total > 9999999)
+ { which = N_txt(AMT_megabyte_txt); shift = 10; }
+ if (kb_main_total > 9999999999ull)
+ { which = N_txt(AMT_gigabyte_txt); shift = 20; }
- show_special(0, fmtmk(MEMORY_twolines
+ show_special(0, fmtmk(N_unq(MEMORY_lines_fmt)
, which, mkM(total), mkM(used), mkM(free), mkM(buffers)
, which, mkS(total), mkS(used), mkS(free), mkM(cached)));
Msg_row += 2;
diff --git a/top.h b/top/top.h
index a79286c..7f76b77 100644
--- a/top.h
+++ b/top/top.h
@@ -15,11 +15,12 @@
/* For contributions to this program, the author wishes to thank:
* Craig Small, <csmall@small.dropbear.id.au>
* Albert D. Cahalan, <albert@users.sf.net>
+ * Sami Kerola, <kerolasa@iki.fi>
*/
#ifndef _Itop
#define _Itop
-#include "proc/readproc.h"
+#include "../proc/readproc.h"
/* Development/Debugging defines ----------------------------------- */
//#define ATEOJ_RPTHSH /* report on hash specifics, at end-of-job */
@@ -40,6 +41,7 @@
//#define TREE_NORESET /* sort keys do NOT force forest view OFF */
//#define TREE_ONEPASS /* for speed, tolerate dangling children */
//#define USE_X_COLHDR /* emphasize header vs. whole col, for 'x' */
+//#define VALIDATE_NLS /* validate integrity of all 3 nls tables */
/*###### Notes, etc. ###################################################*/
@@ -55,6 +57,12 @@
/* For introducing inaugural cgroup support, thanks to:
Jan Gorig <jgorig@redhat.com> - April, 2011 */
+ /* For the motivation and path to nls support, thanks to:
+ Sami Kerola, <kerolasa@iki.fi> */
+
+ /* There are still some short strings that may yet be candidates
+ for nls support inclusion. They're identified with:
+ // nls_maybe */
#ifdef PRETEND2_5_X
#define linux_version_code LINUX_VERSION(2,5,43)
@@ -436,6 +444,8 @@ typedef struct WIN_t {
/*###### Display Support *Data* ########################################*/
+/*###### Some Display Support *Data* ###################################*/
+/* ( see module top_nls.c for the nls translatable data ) */
/* Configuration files support */
#define SYS_RCFILESPEC "/etc/toprc"
@@ -482,123 +492,6 @@ typedef struct WIN_t {
see 'show_special' for syntax details + other cautions. */
#define LOADAV_line "%s -%s\n"
#define LOADAV_line_alt "%s~6 -%s\n"
-#define STATES_line1 "%s:~3" \
- " %3u ~2total,~3 %3u ~2running,~3 %3u ~2sleeping,~3 %3u ~2stopped,~3 %3u ~2zombie~3\n"
-#define STATES_line2x4 "%%%s~3" \
- " %#5.1f ~2user,~3 %#5.1f ~2system,~3 %#5.1f ~2nice,~3 %#5.1f ~2idle~3\n"
- /* These are the STATES_line evolutions
- lnx 2.5.x, procps-3.0.5 : IO-wait = i/o wait time
- lnx 2.6.x, procps-3.1.12 : IO-wait now wa, hi = hard irq, si = soft irq
- lnx 2.7.x, procps-3.2.7 : st = steal time */
-#define STATES_line2x5 "%%%s~3" \
- " %#5.1f ~2user,~3 %#5.1f ~2system,~3 %#5.1f ~2nice,~3 %#5.1f ~2idle,~3 %#5.1f ~2IO-wait~3\n"
-#define STATES_line2x6 "%%%s~3" \
- " %#5.1f ~2us,~3 %#5.1f ~2sy,~3 %#5.1f ~2ni,~3 %#5.1f ~2id,~3 %#5.1f ~2wa,~3 %#5.1f ~2hi,~3 %#5.1f ~2si~3\n"
-#define STATES_line2x7 "%%%s~3" \
- "%#5.1f ~2us,~3%#5.1f ~2sy,~3%#5.1f ~2ni,~3%#5.1f ~2id,~3%#5.1f ~2wa,~3%#5.1f ~2hi,~3%#5.1f ~2si,~3%#5.1f ~2st~3\n"
-#define MEMORY_twolines \
- "%s Mem: ~3 %8lu ~2total,~3 %8lu ~2used,~3 %8lu ~2free,~3 %8lu ~2buffers~3\n" \
- "%s Swap:~3 %8lu ~2total,~3 %8lu ~2used,~3 %8lu ~2free,~3 %8lu ~2cached~3\n"
-
- /* Keyboard Help specially formatted string(s) --
- see 'show_special' for syntax details + other cautions. */
-#define KEYS_help \
- "Help for Interactive Commands~2 - %s\n" \
- "Window ~1%s~6: ~1Cumulative mode ~3%s~2. ~1System~6: ~1Delay ~3%.1f secs~2; ~1Secure mode ~3%s~2.\n" \
- "\n" \
- " Z~5,~1B~5 Global: '~1Z~2' change color mappings; '~1B~2' disable/enable bold\n" \
- " l,t,m Toggle Summaries: '~1l~2' load avg; '~1t~2' task/cpu stats; '~1m~2' mem info\n" \
- " 1,I Toggle SMP view: '~11~2' single/separate states; '~1I~2' Irix/Solaris mode\n" \
- " f,F Manage Fields: add/remove; change order; select sort field\n" \
- "\n" \
- " L,&,<,> . Locate: '~1L~2'/'~1&~2' find/again; Move sort column: '~1<~2'/'~1>~2' left/right\n" \
- " R,H,V . Toggle: '~1R~2' norm/rev sort; '~1H~2' show threads; '~1V~2' forest view\n" \
- " c,i,S . Toggle: '~1c~2' cmd name/line; '~1i~2' idle tasks; '~1S~2' cumulative time\n" \
- " x~5,~1y~5 . Toggle highlights: '~1x~2' sort field; '~1y~2' running tasks\n" \
- " z~5,~1b~5 . Toggle: '~1z~2' color/mono; '~1b~2' bold/reverse (only if 'x' or 'y')\n" \
- " u,U . Show: '~1u~2' effective user; '~1U~2' real, saved, file or effective user\n" \
- " n or # . Set maximum tasks displayed\n" \
- " C,... . Toggle scroll coordinates msg for: ~1up~2,~1down~2,~1left~2,right~2,~1home~2,~1end~2\n" \
- "\n" \
- "%s" \
- " W Write configuration file\n" \
- " q Quit\n" \
- " ( commands shown with '.' require a ~1visible~2 task display ~1window~2 ) \n" \
- "Press '~1h~2' or '~1?~2' for help with ~1Windows~2,\n" \
- "any other key to continue " \
- ""
-
- /* This guy goes into the help text (maybe) */
-#define KEYS_help_unsecured \
- " k,r Manipulate tasks: '~1k~2' kill; '~1r~2' renice\n" \
- " d or s Set update interval\n" \
- ""
-
- /* Fields Management specially formatted string(s) --
- see 'show_special' for syntax details + other cautions */
-#define FIELDS_heading \
- "Fields Management~2 for window ~1%s~6, whose current sort field is ~1%s~2\n" \
- " Navigate with Up/Dn, Right selects for move then <Enter> or Left commits,\n" \
- " 'd' or <Space> toggles display, 's' sets sort. Use 'q' or <Esc> to end! " \
- ""
-
- /* Colors Help specially formatted string(s) --
- see 'show_special' for syntax details + other cautions. */
-#define COLOR_help \
- "Help for color mapping~2 - %s\n" \
- "current window: ~1%s~6\n" \
- "\n" \
- " color - 04:25:44 up 8 days, 50 min, 7 users, load average:\n" \
- " Tasks:~3 64 ~2total,~3 2 ~3running,~3 62 ~2sleeping,~3 0 ~2stopped,~3\n" \
- " %%Cpu(s):~3 76.5 ~2user,~3 11.2 ~2system,~3 0.0 ~2nice,~3 12.3 ~2idle~3\n" \
- " ~1 Nasty Message! ~4 -or- ~1Input Prompt~5\n" \
- " ~1 PID TTY PR NI %%CPU TIME+ VIRT SWAP S COMMAND ~6\n" \
- " 17284 ~8pts/2 ~7 8 0 0.0 0:00.75 1380 0 S /bin/bash ~8\n" \
- " ~1 8601 pts/1 7 -10 0.4 0:00.03 916 0 R color -b -z~7\n" \
- " 11005 ~8? ~7 9 0 0.0 0:02.50 2852 1008 S amor -sessi~8\n" \
- " available toggles: ~1B~2 =disable bold globally (~1%s~2),\n" \
- " ~1z~2 =color/mono (~1%s~2), ~1b~2 =tasks \"bold\"/reverse (~1%s~2)\n" \
- "\n" \
- "Select ~1target~2 as upper case letter:\n" \
- " S~2 = Summary Data,~1 M~2 = Messages/Prompts,\n" \
- " H~2 = Column Heads,~1 T~2 = Task Information\n" \
- "Select ~1color~2 as number:\n" \
- " 0~2 = black,~1 1~2 = red, ~1 2~2 = green,~1 3~2 = yellow,\n" \
- " 4~2 = blue, ~1 5~2 = magenta,~1 6~2 = cyan, ~1 7~2 = white\n" \
- "\n" \
- "Selected: ~1target~2 ~1 %c ~4; ~1color~2 ~1 %d ~4\n" \
- " press 'q' to abort changes to window '~1%s~2'\n" \
- " press 'a' or 'w' to commit & change another, <Enter> to commit and end " \
- ""
-
- /* Windows/Field Group Help specially formatted string(s) --
- see 'show_special' for syntax details + other cautions. */
-#define WINDOWS_help \
- "Help for Windows / Field Groups~2 - \"Current Window\" = ~1 %s ~6\n" \
- "\n" \
- ". Use multiple ~1windows~2, each with separate config opts (color,fields,sort,etc)\n" \
- ". The 'current' window controls the ~1Summary Area~2 and responds to your ~1Commands~2\n" \
- " . that window's ~1task display~2 can be turned ~1Off~2 & ~1On~2, growing/shrinking others\n" \
- " . with ~1NO~2 task display, some commands will be ~1disabled~2 ('i','R','n','c', etc)\n" \
- " until a ~1different window~2 has been activated, making it the 'current' window\n" \
- ". You ~1change~2 the 'current' window by: ~1 1~2) cycling forward/backward;~1 2~2) choosing\n" \
- " a specific field group; or~1 3~2) exiting the color mapping or fields screens\n" \
- ". Commands ~1available anytime -------------~2\n" \
- " A . Alternate display mode toggle, show ~1Single~2 / ~1Multiple~2 windows\n" \
- " g . Choose another field group and make it 'current', or change now\n" \
- " by selecting a number from: ~1 1~2 =%s;~1 2~2 =%s;~1 3~2 =%s; or~1 4~2 =%s\n" \
- ". Commands ~1requiring~2 '~1A~2' mode~1 -------------~2\n" \
- " G . Change the ~1Name~5 of the 'current' window/field group\n" \
- " ~1*~4 a , w . Cycle through all four windows: '~1a~5' Forward; '~1w~5' Backward\n" \
- " ~1*~4 - , _ . Show/Hide: '~1-~5' ~1Current~2 window; '~1_~5' all ~1Visible~2/~1Invisible~2\n" \
- " The screen will be divided evenly between task displays. But you can make\n" \
- " some ~1larger~2 or ~1smaller~2, using '~1n~2' and '~1i~2' commands. Then later you could:\n" \
- " ~1*~4 = , + . Rebalance tasks: '~1=~5' ~1Current~2 window; '~1+~5' ~1Every~2 window\n" \
- " (this also forces the ~1current~2 or ~1every~2 window to become visible)\n" \
- "\n" \
- "In '~1A~2' mode, '~1*~4' keys are your ~1essential~2 commands. Please try the '~1a~2' and '~1w~2'\n" \
- "commands plus the 'g' sub-commands NOW. Press <Enter> to make 'Current' " \
- ""
/*###### For Piece of mind #############################################*/
@@ -641,7 +534,9 @@ typedef struct WIN_t {
//atic int show_pmt (const char *str);
//atic inline void show_scroll (void);
//atic void show_special (int interact, const char *glob);
-/*------ Low Level Keyboard support ------------------------------------*/
+/*------ Low Level Memory/Keyboard support -----------------------------*/
+//atic void *alloc_c (size_t num);
+//atic void *alloc_r (void *ptr, size_t num);
//atic int chin (int ech, char *buf, unsigned cnt);
//atic int keyin (int init);
//atic char *linein (const char *prompt);
diff --git a/top/top_nls.c b/top/top_nls.c
new file mode 100644
index 0000000..43c76fa
--- /dev/null
+++ b/top/top_nls.c
@@ -0,0 +1,497 @@
+/* top_nls.c - provide the basis for future nls translations */
+/*
+ * Copyright (c) 2011, by: James C. Warner
+ * All rights reserved. 8921 Hilloway Road
+ * Eden Prairie, Minnesota 55347 USA
+ *
+ * This file may be used subject to the terms and conditions of the
+ * GNU Library General Public License Version 2, or any later version
+ * at your option, as published by the Free Software Foundation.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ */
+/* For contributions to this program, the author wishes to thank:
+ * Craig Small, <csmall@small.dropbear.id.au>
+ * Sami Kerola, <kerolasa@iki.fi>
+ */
+
+#include <locale.h>
+#include <stdio.h>
+#ifdef VALIDATE_NLS
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+#include "../include/nls.h"
+
+#include "top.h"
+#include "top_nls.h"
+
+ // Programmer Note(s):
+ // Preparation ---------------------------------------------
+ // Unless you have *something* following the gettext macro,
+ // xgettext will refuse to see any TRANSLATORS comments.
+ // Thus empty strings have been added for potential future
+ // comment additions.
+ //
+ // Also, by omitting the argument for the --add-comments
+ // XGETTEXT_OPTION in po/Makevars, *any* preceeding c style
+ // comment will be propagated to the .pot file, providing
+ // that the gettext macro isn't empty as discussed above.
+ // However, this is far too aggressive so we have chosen
+ // the word 'Translation' to denote xgettext comments.
+ //
+ // /* Need Not Say 'TRANSLATORS': ...
+ // snprintf(buf, sizeof(buf), "%s", _( // unseen comment
+ //
+ // /* Translation Hint: ...
+ // snprintf(buf, sizeof(buf), "%s", _("" // now it's seen!
+ //
+ // Translation, from po/ directory after make --------------
+ // ( this is the procedure used before any translations were )
+ // ( available in the po/ directory, which contained only the )
+ // ( procps-ng.pot, this domain's template file. )
+ //
+ // ( below: ll_CC = language/country as in 'zh_CN' or 'en_AU' )
+ //
+ // msginit --locale=ll_CC --no-wrap
+ // . creates a ll_CC.po file from the template procps-ng.pot
+ // . may also duplicate msgid as msgstr if languages similar
+ // msgen --no-wrap ll_CC.po --output-file=ll_CC.po
+ // . duplicates every msgid literal as msgstr value
+ // . this is the file that's edited
+ // . replace "Content-Type: ... charset=ASCII\n"
+ // with "... charset=UTF-8\n"
+ // . translate msgstr values, leaving msgid unchanged
+ // msgfmt ll_CC.po --strict --output-file=procps-ng.mo
+ // . after which chmod 644
+ // . move to /usr/share/local/ll_CC/LC_MESSAGES/ directory
+ //
+ // Testing -------------------------------------------------
+ // export LC_ALL= && export LANGUAGE=ll_CC
+ // run some capable program like top
+ //
+
+ /*
+ * These are our three string tables with the following contents:
+ * Desc : fields descriptions not to exceed 20 screen positions
+ * Norm : regular text possibly also containing c-format specifiers
+ * Uniq : show_special specially formatted strings
+ *
+ * The latter table presents the greatest translation challenge !
+ */
+const char *Desc_nlstab[P_MAXPFLGS];
+const char *Norm_nlstab[norm_MAX];
+const char *Uniq_nlstab[uniq_MAX];
+
+
+ /*
+ * This routine builds the nls table containing plain text only
+ * used as the field descriptions. Each translated line MUST be
+ * kept to a maximum of 20 characters or less! */
+static void build_desc_nlstab (void) {
+
+/* Translation Notes ------------------------------------------------
+ . It is strongly recommend that the --no-wrap command line option
+ . be used with all supporting translation tools, when available.
+ .
+ . The following single lines contain only plain text used as the
+ . descriptions under Field Management when the 'f' key is typed.
+ .
+ . To avoid truncation, each translated line MUST be kept to a
+ . length of 20 characters or less.
+ . */
+
+ Desc_nlstab[P_PID] = _("Process Id");
+ Desc_nlstab[P_PPD] = _("Parent Process pid");
+ Desc_nlstab[P_UED] = _("Effective User Id");
+ Desc_nlstab[P_UEN] = _("Effective User Name");
+ Desc_nlstab[P_URD] = _("Real User Id");
+ Desc_nlstab[P_URN] = _("Real User Name");
+ Desc_nlstab[P_USD] = _("Saved User Id");
+ Desc_nlstab[P_USN] = _("Saved User Name");
+ Desc_nlstab[P_GID] = _("Group Id");
+ Desc_nlstab[P_GRP] = _("Group Name");
+ Desc_nlstab[P_PGD] = _("Process Group Id");
+ Desc_nlstab[P_TTY] = _("Controlling Tty");
+ Desc_nlstab[P_TPG] = _("Tty Process Grp Id");
+ Desc_nlstab[P_SID] = _("Session Id");
+ Desc_nlstab[P_PRI] = _("Priority");
+ Desc_nlstab[P_NCE] = _("Nice Value");
+ Desc_nlstab[P_THD] = _("Number of Threads");
+ Desc_nlstab[P_CPN] = _("Last Used Cpu (SMP)");
+ Desc_nlstab[P_CPU] = _("CPU Usage");
+ Desc_nlstab[P_TME] = _("CPU Time");
+ Desc_nlstab[P_TM2] = _("CPU Time, hundredths");
+ Desc_nlstab[P_MEM] = _("Memory Usage (RES)");
+ Desc_nlstab[P_VRT] = _("Virtual Image (kb)");
+ Desc_nlstab[P_SWP] = _("Swapped Size (kb)");
+ Desc_nlstab[P_RES] = _("Resident Size (kb)");
+ Desc_nlstab[P_COD] = _("Code Size (kb)");
+ Desc_nlstab[P_DAT] = _("Data+Stack Size (kb)");
+ Desc_nlstab[P_SHR] = _("Shared Mem Size (kb)");
+ Desc_nlstab[P_FL1] = _("Major Page Faults");
+ Desc_nlstab[P_FL2] = _("Minor Page Faults");
+ Desc_nlstab[P_DRT] = _("Dirty Pages Count");
+ Desc_nlstab[P_STA] = _("Process Status");
+ Desc_nlstab[P_CMD] = _("Command Name/Line");
+ Desc_nlstab[P_WCH] = _("Sleeping in Function");
+ Desc_nlstab[P_FLG] = _("Task Flags <sched.h>");
+ Desc_nlstab[P_CGR] = _("Control Groups");
+ Desc_nlstab[P_SGD] = _("Supp Groups IDs");
+ Desc_nlstab[P_SGN] = _("Supp Groups Names");
+ Desc_nlstab[P_TGD] = _("Thread Group Id");
+#ifdef OOMEM_ENABLE
+ Desc_nlstab[P_OOA] = _("oom_adjustment (2^X)");
+ Desc_nlstab[P_OOM] = _("oom_score (badness)");
+#endif
+}
+
+
+ /*
+ * This routine builds the nls table containing both plain text
+ * and regular c-format strings. */
+static void build_norm_nlstab (void) {
+
+/* Translation Notes ------------------------------------------------
+ . It is strongly recommend that the --no-wrap command line option
+ . be used with all supporting translation tools, when available.
+ .
+ . This group of lines contains both plain text and c-format strings.
+ .
+ . Some strings reflect switches used to affect the running program
+ . and should not be translated without also making corresponding
+ . c-code logic changes.
+ . */
+
+ Norm_nlstab[EXIT_signals_fmt] = _(""
+ "\tsignal %d (%s) was caught by %s, please\n"
+ "\tsee http://www.debian.org/Bugs/Reporting\n");
+ Norm_nlstab[WRONG_switch_fmt] = _(""
+ "inappropriate '%s'\n"
+ "usage:\t%s%s");
+ Norm_nlstab[HELP_cmdline_fmt] = _(""
+ "\t%s\n"
+ "usage:\t%s%s");
+ Norm_nlstab[FAIL_statopn_fmt] = _("failed /proc/stat open: %s");
+ Norm_nlstab[FAIL_openlib_fmt] = _("failed openproc: %s");
+ Norm_nlstab[BAD_delayint_fmt] = _("bad delay interval '%s'");
+ Norm_nlstab[BAD_niterate_fmt] = _("bad iterations argument '%s'");
+ Norm_nlstab[LIMIT_exceed_fmt] = _("pid limit (%d) exceeded");
+ Norm_nlstab[BAD_mon_pids_fmt] = _("bad pid '%s'");
+ Norm_nlstab[MISSING_args_fmt] = _("-%c requires argument");
+ Norm_nlstab[BAD_widtharg_fmt] = _("bad width arg '%s', must > %d");
+ Norm_nlstab[UNKNOWN_opts_fmt] = _(""
+ "unknown option '%c'\n"
+ "usage:\t%s%s");
+ Norm_nlstab[DELAY_secure_txt] = _("-d disallowed in \"secure\" mode");
+ Norm_nlstab[DELAY_badarg_txt] = _("-d requires positive argument");
+ Norm_nlstab[ON_word_only_txt] = _("On");
+ Norm_nlstab[OFF_one_word_txt] = _("Off");
+/* Translation Hint: Only the following words should be translated
+ . delay, limit, user, cols (abbreviation for columns)*/
+ Norm_nlstab[USAGE_abbrev_txt] = _(" -hv | -bcHiSs -d delay -n limit -u|U user | -p pid[,pid] -w [cols]");
+ Norm_nlstab[FAIL_statget_txt] = _("failed /proc/stat read");
+ Norm_nlstab[FOREST_modes_fmt] = _("Forest mode %s");
+ Norm_nlstab[FAIL_tty_get_txt] = _("failed tty get");
+ Norm_nlstab[FAIL_tty_mod_fmt] = _("failed Tty_tweaked set: %s");
+ Norm_nlstab[FAIL_tty_raw_fmt] = _("failed Tty_raw set: %s");
+ Norm_nlstab[CHOOSE_group_txt] = _("Choose field group (1 - 4)");
+ Norm_nlstab[DISABLED_cmd_txt] = _("Command disabled, 'A' mode required");
+ Norm_nlstab[DISABLED_win_fmt] = _("Command disabled, activate %s with '-' or '_'");
+ Norm_nlstab[COLORS_nomap_txt] = _("No colors to map!");
+ Norm_nlstab[FAIL_rc_open_fmt] = _("Failed '%s' open: %s");
+ Norm_nlstab[WRITE_rcfile_fmt] = _("Wrote configuration to '%s'");
+ Norm_nlstab[DELAY_change_fmt] = _("Change delay from %.1f to");
+ Norm_nlstab[THREADS_show_fmt] = _("Show threads %s");
+ Norm_nlstab[IRIX_curmode_fmt] = _("Irix mode %s");
+ Norm_nlstab[GET_pid2kill_txt] = _("pid to signal/kill");
+ Norm_nlstab[GET_sigs_num_fmt] = _("Send pid %d signal [%d/sigterm]");
+ Norm_nlstab[FAIL_signals_fmt] = _("Failed signal pid '%d' with '%d': %s");
+ Norm_nlstab[BAD_signalid_txt] = _("Invalid signal");
+ Norm_nlstab[GET_pid2nice_txt] = _("PID to renice");
+ Norm_nlstab[GET_nice_num_fmt] = _("Renice PID %d to value");
+ Norm_nlstab[FAIL_re_nice_fmt] = _("Failed renice of PID %d to %d: %s");
+ Norm_nlstab[NAME_windows_fmt] = _("Rename window '%s' to (1-3 chars)");
+ Norm_nlstab[TIME_accumed_fmt] = _("Cumulative time %s");
+ Norm_nlstab[GET_max_task_fmt] = _("Maximum tasks = %d, change to (0 is unlimited)");
+ Norm_nlstab[BAD_max_task_txt] = _("Invalid maximum");
+ Norm_nlstab[HILIGHT_cant_txt] = _("Nothing to highlight!");
+ Norm_nlstab[GET_user_ids_txt] = _("Which user (blank for all)");
+ Norm_nlstab[UNKNOWN_cmds_txt] = _("Unknown command - try 'h' for help");
+ Norm_nlstab[SCROLL_coord_fmt] = _("scroll coordinates: y = %d/%d (tasks), x = %d/%d (fields)");
+ Norm_nlstab[FAIL_alloc_c_txt] = _("failed memory allocate");
+ Norm_nlstab[FAIL_alloc_r_txt] = _("failed memory re-allocate");
+ Norm_nlstab[BAD_numfloat_txt] = _("Unacceptable floating point");
+ Norm_nlstab[BAD_username_txt] = _("Invalid user");
+ Norm_nlstab[FAIL_sigstop_fmt] = _("failed sigprocmask, SIG_BLOCK: %s");
+ Norm_nlstab[FAIL_sigmask_fmt] = _("failed sigprocmask, SIG_SETMASK: %s");
+ Norm_nlstab[FOREST_views_txt] = _("forest view");
+ Norm_nlstab[FAIL_widepid_txt] = _("failed pid maximum size test");
+ Norm_nlstab[FAIL_widecpu_txt] = _("failed number of cpus test");
+ Norm_nlstab[RC_bad_files_fmt] = _("incompatible rcfile, you should delete '%s'");
+ Norm_nlstab[RC_bad_entry_fmt] = _("window entry #%d corrupt, please delete '%s'");
+ Norm_nlstab[NOT_onsecure_txt] = _("Unavailable in secure mode");
+ Norm_nlstab[NOT_smp_cpus_txt] = _("Only 1 cpu detected");
+ Norm_nlstab[BAD_integers_txt] = _("Unacceptable integer");
+ Norm_nlstab[SELECT_clash_txt] = _("conflicting process selections (U/p/u)");
+/* Translation Hint: This is an abbreviation (limit 2 characters) for:
+ . kilobytes (1000 bytes) */
+ Norm_nlstab[AMT_kilobyte_txt] = _("Kb");
+/* Translation Hint: This is an abbreviation (limit 2 characters) for:
+ . megabytes (1,000,000 bytes) */
+ Norm_nlstab[AMT_megabyte_txt] = _("Mb");
+/* Translation Hint: This is an abbreviation (limit 2 characters) for:
+ . gigabytes (1,000,000,000 bytes) */
+ Norm_nlstab[AMT_gigabyte_txt] = _("Gb");
+ Norm_nlstab[WORD_threads_txt] = _("Threads");
+ Norm_nlstab[WORD_process_txt] = _("Tasks");
+/* Translation Hint: The following "word" is meant to represent either a single
+ . cpu or all of the processors in a multi-processor computer
+ . (should be exactly 6 characters, not counting the colon)*/
+ Norm_nlstab[WORD_allcpus_txt] = _("Cpu(s):");
+/* Translation Hint: The following "word" is meant to represent a single processor
+ . (should be exactly 3 characters) */
+ Norm_nlstab[WORD_eachcpu_fmt] = _("Cpu%-3d:");
+/* Translation Hint: The following word "another" must have 1 trailing space */
+ Norm_nlstab[WORD_another_txt] = _("another ");
+ Norm_nlstab[FIND_no_next_txt] = _("Locate next inactive, use \"L\"");
+ Norm_nlstab[GET_find_str_txt] = _("Locate string");
+ Norm_nlstab[FIND_no_find_fmt] = _("%s\"%s\" not found");
+}
+
+
+ /*
+ * This routine builds the nls table containing specially
+ * formatted strings designed to fit within an 80x24 terminal. */
+static void build_uniq_nlstab (void) {
+
+/* Translation Notes ------------------------------------------------
+ . It is strongly recommend that the --no-wrap command line option
+ . be used with all supporting translation tools, when available.
+ .
+ . The next several text groups contain special escape sequences
+ . representing values used to index a table at run-time.
+ .
+ . Each such sequence consists of a tilde (~) followed by an ascii
+ . number in the range of '1' - '8'. Examples are '~2', '~8', etc.
+ . These escape sequences must never themselves be translated but
+ . could be deleted.
+ .
+ . If you remove these escape sequences (both tilde and number) it
+ . would make translation easier. However, the ability to display
+ . colors and bold text at run-time will have been lost.
+ .
+ . Additionally, each of these text groups was designed to display
+ . in a 80x24 terminal window. Hopefully, any translations will
+ . adhere to that goal lest the translated text be truncated.
+ .
+ . If you would like additional information regarding these strings,
+ . please see the prolog to the show_special function in the top.c
+ . source file.
+ . */
+
+ Uniq_nlstab[KEYS_helpbas_fmt] = _(""
+ "Help for Interactive Commands~2 - %s\n"
+ "Window ~1%s~6: ~1Cumulative mode ~3%s~2. ~1System~6: ~1Delay ~3%.1f secs~2; ~1Secure mode ~3%s~2.\n"
+ "\n"
+ " Z~5,~1B~5 Global: '~1Z~2' change color mappings; '~1B~2' disable/enable bold\n"
+ " l,t,m Toggle Summaries: '~1l~2' load avg; '~1t~2' task/cpu stats; '~1m~2' mem info\n"
+ " 1,I Toggle SMP view: '~11~2' single/separate states; '~1I~2' Irix/Solaris mode\n"
+ " f,F Manage Fields: add/remove; change order; select sort field\n"
+ "\n"
+ " L,&,<,> . Locate: '~1L~2'/'~1&~2' find/again; Move sort column: '~1<~2'/'~1>~2' left/right\n" \
+ " R,H,V . Toggle: '~1R~2' norm/rev sort; '~1H~2' show threads; '~1V~2' forest view\n"
+ " c,i,S . Toggle: '~1c~2' cmd name/line; '~1i~2' idle tasks; '~1S~2' cumulative time\n"
+ " x~5,~1y~5 . Toggle highlights: '~1x~2' sort field; '~1y~2' running tasks\n"
+ " z~5,~1b~5 . Toggle: '~1z~2' color/mono; '~1b~2' bold/reverse (only if 'x' or 'y')\n"
+ " u,U . Show: '~1u~2' effective user; '~1U~2' real, saved, file or effective user\n"
+ " n or # . Set maximum tasks displayed\n"
+ " C,... . Toggle scroll coordinates msg for: ~1up~2,~1down~2,~1left~2,right~2,~1home~2,~1end~2\n"
+ "\n"
+ "%s"
+ " W Write configuration file\n"
+ " q Quit\n"
+ " ( commands shown with '.' require a ~1visible~2 task display ~1window~2 ) \n"
+ "Press '~1h~2' or '~1?~2' for help with ~1Windows~2,\n"
+ "any other key to continue ");
+
+/* Translation Hint: As is true for the text above, the "keys" shown to the left and
+ . also imbedded in the translatable text (along with escape seqs)
+ . should never themselves be translated. */
+ Uniq_nlstab[KEYS_helpext_fmt] = _(""
+ " k,r Manipulate tasks: '~1k~2' kill; '~1r~2' renice\n"
+ " d or s Set update interval\n");
+
+ Uniq_nlstab[WINDOWS_help_fmt] = _(""
+ "Help for Windows / Field Groups~2 - \"Current Window\" = ~1 %s ~6\n"
+ "\n"
+ ". Use multiple ~1windows~2, each with separate config opts (color,fields,sort,etc)\n"
+ ". The 'current' window controls the ~1Summary Area~2 and responds to your ~1Commands~2\n"
+ " . that window's ~1task display~2 can be turned ~1Off~2 & ~1On~2, growing/shrinking others\n"
+ " . with ~1NO~2 task display, some commands will be ~1disabled~2 ('i','R','n','c', etc)\n"
+ " until a ~1different window~2 has been activated, making it the 'current' window\n"
+ ". You ~1change~2 the 'current' window by: ~1 1~2) cycling forward/backward;~1 2~2) choosing\n"
+ " a specific field group; or~1 3~2) exiting the color mapping or fields screens\n"
+ ". Commands ~1available anytime -------------~2\n"
+ " A . Alternate display mode toggle, show ~1Single~2 / ~1Multiple~2 windows\n"
+ " g . Choose another field group and make it 'current', or change now\n"
+ " by selecting a number from: ~1 1~2 =%s;~1 2~2 =%s;~1 3~2 =%s; or~1 4~2 =%s\n"
+ ". Commands ~1requiring~2 '~1A~2' mode~1 -------------~2\n"
+ " G . Change the ~1Name~5 of the 'current' window/field group\n"
+ " ~1*~4 a , w . Cycle through all four windows: '~1a~5' Forward; '~1w~5' Backward\n"
+ " ~1*~4 - , _ . Show/Hide: '~1-~5' ~1Current~2 window; '~1_~5' all ~1Visible~2/~1Invisible~2\n"
+ " The screen will be divided evenly between task displays. But you can make\n"
+ " some ~1larger~2 or ~1smaller~2, using '~1n~2' and '~1i~2' commands. Then later you could:\n"
+ " ~1*~4 = , + . Rebalance tasks: '~1=~5' ~1Current~2 window; '~1+~5' ~1Every~2 window\n"
+ " (this also forces the ~1current~2 or ~1every~2 window to become visible)\n"
+ "\n"
+ "In '~1A~2' mode, '~1*~4' keys are your ~1essential~2 commands. Please try the '~1a~2' and '~1w~2'\n"
+ "commands plus the 'g' sub-commands NOW. Press <Enter> to make 'Current' ");
+
+/* Translation Notes ------------------------------------------------
+ . The following 'Help for color mapping' simulated screen should
+ . probably NOT be translated. It is terribly hard to follow in
+ . this form and any translation could produce unpleasing results
+ . that are unlikely to parallel the running top program.
+ .
+ . If you decide to proceed with translation, do the following
+ . lines only, taking care not to disturbe the tilde + number.
+ .
+ . Simulated screen excerpt:
+ . --> " Tasks:~3 64 ~2total,~3 2 ~3running,~3 62
+ . --> " %%Cpu(s):~3 76.5 ~2user,~3 11.2 ~2system,~
+ . --> " ~1 Nasty Message! ~4 -or- ~1Input Prompt~5
+ .
+ . --> " available toggles: ~1B~2 =disable bold globa
+ . --> " ~1z~2 =color/mono (~1%s~2), ~1b~2 =tasks
+ .
+ . --> "Select ~1target~2 as upper case letter:\n"
+ . --> " S~2 = Summary Data,~1 M~2 = Messages/Prompt
+ . --> " H~2 = Column Heads,~1 T~2 = Task Informatio
+ . --> "Select ~1color~2 as number:\n"
+ . --> " 0~2 = black,~1 1~2 = red, ~1 2~2 = gree
+ . --> " 4~2 = blue, ~1 5~2 = magenta,~1 6~2 = cyan
+ . */
+ Uniq_nlstab[COLOR_custom_fmt] = _(""
+ "Help for color mapping~2 - %s\n"
+ "current window: ~1%s~6\n"
+ "\n"
+ " color - 04:25:44 up 8 days, 50 min, 7 users, load average:\n"
+ " Tasks:~3 64 ~2total,~3 2 ~3running,~3 62 ~2sleeping,~3 0 ~2stopped,~3\n"
+ " %%Cpu(s):~3 76.5 ~2user,~3 11.2 ~2system,~3 0.0 ~2nice,~3 12.3 ~2idle~3\n"
+ " ~1 Nasty Message! ~4 -or- ~1Input Prompt~5\n"
+ " ~1 PID TTY PR NI %%CPU TIME+ VIRT SWAP S COMMAND ~6\n"
+ " 17284 ~8pts/2 ~7 8 0 0.0 0:00.75 1380 0 S /bin/bash ~8\n"
+ " ~1 8601 pts/1 7 -10 0.4 0:00.03 916 0 R color -b -z~7\n"
+ " 11005 ~8? ~7 9 0 0.0 0:02.50 2852 1008 S amor -sessi~8\n"
+ " available toggles: ~1B~2 =disable bold globally (~1%s~2),\n"
+ " ~1z~2 =color/mono (~1%s~2), ~1b~2 =tasks \"bold\"/reverse (~1%s~2)\n"
+ "\n"
+ "Select ~1target~2 as upper case letter:\n"
+ " S~2 = Summary Data,~1 M~2 = Messages/Prompts,\n"
+ " H~2 = Column Heads,~1 T~2 = Task Information\n"
+ "Select ~1color~2 as number:\n"
+ " 0~2 = black,~1 1~2 = red, ~1 2~2 = green,~1 3~2 = yellow,\n"
+ " 4~2 = blue, ~1 5~2 = magenta,~1 6~2 = cyan, ~1 7~2 = white\n"
+ "\n"
+ "Selected: ~1target~2 ~1 %c ~4; ~1color~2 ~1 %d ~4\n"
+ " press 'q' to abort changes to window '~1%s~2'\n"
+ " press 'a' or 'w' to commit & change another, <Enter> to commit and end ");
+
+ Uniq_nlstab[FIELD_header_fmt] = _(""
+ "Fields Management~2 for window ~1%s~6, whose current sort field is ~1%s~2\n"
+ " Navigate with Up/Dn, Right selects for move then <Enter> or Left commits,\n"
+ " 'd' or <Space> toggles display, 's' sets sort. Use 'q' or <Esc> to end! ");
+
+ Uniq_nlstab[STATE_line_1_fmt] = _("%s:~3"
+ " %3u ~2total,~3 %3u ~2running,~3 %3u ~2sleeping,~3 %3u ~2stopped,~3 %3u ~2zombie~3\n");
+
+ Uniq_nlstab[STATE_lin2x4_fmt] = _("%%%s~3"
+ " %#5.1f ~2user,~3 %#5.1f ~2system,~3 %#5.1f ~2nice,~3 %#5.1f ~2idle~3\n");
+
+ Uniq_nlstab[STATE_lin2x5_fmt] = _("%%%s~3"
+ " %#5.1f ~2user,~3 %#5.1f ~2system,~3 %#5.1f ~2nice,~3 %#5.1f ~2idle,~3 %#5.1f ~2IO-wait~3\n");
+
+/* Translation Hint: Only the following abbreviations need be translated
+ . us = user, sy = system, ni = nice, id = idle, wa = wait,
+ . hi hardware interrupt, si = software interrupt */
+ Uniq_nlstab[STATE_lin2x6_fmt] = _("%%%s~3"
+ " %#5.1f ~2us,~3 %#5.1f ~2sy,~3 %#5.1f ~2ni,~3 %#5.1f ~2id,~3 %#5.1f ~2wa,~3 %#5.1f ~2hi,~3 %#5.1f ~2si~3\n");
+
+/* Translation Hint: Only the following abbreviations need be translated
+ . us = user, sy = system, ni = nice, id = idle, wa = wait,
+ . hi hardware interrupt, si = software interrupt, st = steal time */
+ Uniq_nlstab[STATE_lin2x7_fmt] = _("%%%s~3"
+ "%#5.1f ~2us,~3%#5.1f ~2sy,~3%#5.1f ~2ni,~3%#5.1f ~2id,~3%#5.1f ~2wa,~3%#5.1f ~2hi,~3%#5.1f ~2si,~3%#5.1f ~2st~3\n");
+
+/* Translation Hint: Only the following need be translated
+ . abbreviations: Mem = physical memory/ram, Swap = the linux swap file
+ . words: total, used, free, buffers, cached */
+ Uniq_nlstab[MEMORY_lines_fmt] = _(""
+ "%s Mem: ~3 %8lu ~2total,~3 %8lu ~2used,~3 %8lu ~2free,~3 %8lu ~2buffers~3\n"
+ "%s Swap:~3 %8lu ~2total,~3 %8lu ~2used,~3 %8lu ~2free,~3 %8lu ~2cached~3\n");
+}
+
+
+ /*
+ * This function must be called very early at startup, before
+ * any other function call, and especially before any changes
+ * have been made to the terminal if VALIDATE_NLS is defined!
+ *
+ * The gettext documentation suggests that alone among locale
+ * variables LANGUAGE=ll_CC may be abbreviated as LANGUAGE=ll
+ * to denote the language's main dialect. Unfortunately this
+ * does not appear to be true. One must specify the complete
+ * ll_CC. Optionally, a '.UTF-8' or '.uft8' suffix, as shown
+ * in the following examples, may also be included:
+ * export LANGUAGE=ll_CC # minimal requirement
+ * export LANGUAGE=ll_CC.UTF-8 # optional convention
+ * export LANGUAGE=ll_CC.utf8 # ok, too
+ *
+ * Additionally, as suggested in the gettext documentation, a
+ * user will also have to export an empty LC_ALL= to actually
+ * enable any translations.
+ */
+void initialize_nls (void) {
+#ifdef VALIDATE_NLS
+ static const char *nls_err ="\t%s_nlstab[%d] == NULL\n";
+ int i;
+
+ setlocale (LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ memset(Desc_nlstab, 0, sizeof(Desc_nlstab));
+ build_desc_nlstab();
+ for (i = 0; i < P_MAXPFLGS; i++)
+ if (!Desc_nlstab[i]) {
+ fprintf(stderr, nls_err, "Desc", i);
+ exit(1);
+ }
+ memset(Norm_nlstab, 0, sizeof(Norm_nlstab));
+ build_norm_nlstab();
+ for (i = 0; i < norm_MAX; i++)
+ if (!Norm_nlstab[i]) {
+ fprintf(stderr, nls_err, "Norm", i);
+ exit(1);
+ }
+ memset(Uniq_nlstab, 0, sizeof(Uniq_nlstab));
+ build_uniq_nlstab();
+ for (i = 0; i < uniq_MAX; i++)
+ if (!Uniq_nlstab[i]) {
+ fprintf(stderr, nls_err, "Uniq", i);
+ exit(1);
+ }
+#else
+ setlocale (LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ build_desc_nlstab();
+ build_norm_nlstab();
+ build_uniq_nlstab();
+#endif
+}
diff --git a/top/top_nls.h b/top/top_nls.h
new file mode 100644
index 0000000..3f554e6
--- /dev/null
+++ b/top/top_nls.h
@@ -0,0 +1,82 @@
+/* top_nls.h - provide the basis for future nls translations */
+/*
+ * Copyright (c) 2011 by: James C. Warner
+ * All rights reserved. 8921 Hilloway Road
+ * Eden Prairie, Minnesota 55347 USA
+ *
+ * This file may be used subject to the terms and conditions of the
+ * GNU Library General Public License Version 2, or any later version
+ * at your option, as published by the Free Software Foundation.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ */
+/* For contributions to this program, the author wishes to thank:
+ * Craig Small, <csmall@small.dropbear.id.au>
+ * Sami Kerola, <kerolasa@iki.fi>
+ */
+#ifndef _Itop_nls
+#define _Itop_nls
+
+ /*
+ * These are our three string tables with the following contents:
+ * Desc : field descriptions not to exceed 20 screen positions
+ * Norm : regular text possibly also containing c-format specifiers
+ * Uniq : show_special specially formatted strings
+ * The latter table presents the greatest translation challenge !
+ */
+extern const char *Desc_nlstab[];
+extern const char *Norm_nlstab[];
+extern const char *Uniq_nlstab[];
+
+ /*
+ * Simple optional macros to ease table access.
+ * The N_txt and N_fmt macros are interchangeable but
+ * highlight the two types of strings found in Norm_nlstable.
+ */
+#define N_fld(e) Desc_nlstab[e]
+#define N_txt(e) Norm_nlstab[e]
+#define N_fmt(e) Norm_nlstab[e]
+#define N_unq(e) Uniq_nlstab[e]
+
+ /*
+ * These enums are the means to access two of our three tables.
+ * The Desc_nlstab is accessed with standard top pflag enums.
+ *
+ * The norm_nls enums carry a suffix distinguishing plain text
+ * from any text also containiing c-format specifiers.
+ */
+enum norm_nls {
+ AMT_kilobyte_txt, AMT_megabyte_txt, AMT_gigabyte_txt, BAD_delayint_fmt,
+ BAD_integers_txt, BAD_max_task_txt, BAD_mon_pids_fmt, BAD_niterate_fmt,
+ BAD_numfloat_txt, BAD_signalid_txt, BAD_username_txt, BAD_widtharg_fmt,
+ CHOOSE_group_txt, COLORS_nomap_txt, DELAY_badarg_txt, DELAY_change_fmt,
+ DELAY_secure_txt, DISABLED_cmd_txt, DISABLED_win_fmt, EXIT_signals_fmt,
+ FAIL_alloc_c_txt, FAIL_alloc_r_txt, FAIL_openlib_fmt, FAIL_rc_open_fmt,
+ FAIL_re_nice_fmt, FAIL_sigmask_fmt, FAIL_signals_fmt, FAIL_sigstop_fmt,
+ FAIL_statget_txt, FAIL_statopn_fmt, FAIL_tty_get_txt, FAIL_tty_mod_fmt,
+ FAIL_tty_raw_fmt, FAIL_widecpu_txt, FAIL_widepid_txt, FIND_no_find_fmt,
+ FIND_no_next_txt, FOREST_modes_fmt, FOREST_views_txt, GET_find_str_txt,
+ GET_max_task_fmt, GET_nice_num_fmt, GET_pid2kill_txt, GET_pid2nice_txt,
+ GET_sigs_num_fmt, GET_user_ids_txt, HELP_cmdline_fmt, HILIGHT_cant_txt,
+ IRIX_curmode_fmt, LIMIT_exceed_fmt, MISSING_args_fmt, NAME_windows_fmt,
+ NOT_onsecure_txt, NOT_smp_cpus_txt, OFF_one_word_txt, ON_word_only_txt,
+ RC_bad_entry_fmt, RC_bad_files_fmt, SCROLL_coord_fmt, SELECT_clash_txt,
+ THREADS_show_fmt, TIME_accumed_fmt, UNKNOWN_cmds_txt, UNKNOWN_opts_fmt,
+ USAGE_abbrev_txt, WORD_allcpus_txt, WORD_another_txt, WORD_eachcpu_fmt,
+ WORD_process_txt, WORD_threads_txt, WRITE_rcfile_fmt, WRONG_switch_fmt,
+ norm_MAX
+};
+
+enum uniq_nls {
+ KEYS_helpbas_fmt, KEYS_helpext_fmt, WINDOWS_help_fmt, COLOR_custom_fmt,
+ FIELD_header_fmt, MEMORY_lines_fmt, STATE_line_1_fmt, STATE_lin2x4_fmt,
+ STATE_lin2x5_fmt, STATE_lin2x6_fmt, STATE_lin2x7_fmt,
+ uniq_MAX
+};
+
+void initialize_nls (void);
+
+#endif /* _Itop_nls */
+
diff --git a/uptime.1 b/uptime.1
index c635f95..e5fac2e 100644
--- a/uptime.1
+++ b/uptime.1
@@ -1,32 +1,35 @@
.\" -*-Nroff-*-
.\"
-.TH UPTIME 1 "26 Jan 1993" "Cohesive Systems" "Linux User's Manual"
+.TH UPTIME "1" "June 2011" "procps-ng" "User Commands"
.SH NAME
uptime \- Tell how long the system has been running.
.SH SYNOPSIS
.B uptime
-.br
-.B uptime
-.RB [ \-V ]
+[\fIoptions\fR]
.SH DESCRIPTION
.B uptime
-gives a one line display of the following information.
-The current time,
-how long the system has been running,
-how many users are currently logged on,
-and the system load averages for the past 1, 5, and 15 minutes.
-
-This is the same information contained in the header line displayed by
+gives a one line display of the following information. The current time, how
+long the system has been running, how many users are currently logged on, and
+the system load averages for the past 1, 5, and 15 minutes.
+.PP
+This is the same information contained in the header line displayed by
.BR w (1).
-.sp
-System load averages is the average number of processes that are either
-in a runnable or uninterruptable state. A process in a runnable state is
-either using the CPU or waiting to use the CPU. A process in
-uninterruptable state is waiting for some I/O access, eg waiting for
-disk. The averages are taken over the three time intervals.
-Load averages are not normalized for the number of CPUs in a system, so
-a load average of 1 means a single CPU system is loaded all the time
-while on a 4 CPU system it means it was idle 75% of the time.
+.PP
+System load averages is the average number of processes that are either in a
+runnable or uninterruptable state. A process in a runnable state is either
+using the CPU or waiting to use the CPU. A process in uninterruptable state
+is waiting for some I/O access, eg waiting for disk. The averages are taken
+over the three time intervals. Load averages are not normalized for the
+number of CPUs in a system, so a load average of 1 means a single CPU system
+is loaded all the time while on a 4 CPU system it means it was idle 75% of
+the time.
+.SH OPTIONS
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+display this help text
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+display version information and exit
.SH FILES
.TP
.I /var/run/utmp
@@ -36,12 +39,20 @@ information about who is currently logged on
process information
.SH AUTHORS
.B uptime
-was written by Larry Greenfield <greenfie@gauss.rutgers.edu> and
-Michael K. Johnson <johnsonm@sunsite.unc.edu>.
-
-Please send bug reports to <procps@freelists.org>
+was written by
+.UR greenfie\@gauss.\:rutgers.\:edu
+Larry Greenfield
+.UE
+and
+.UR johnsonm\@sunsite.\:unc.\:edu
+Michael K. Johnson
+.UE
.SH "SEE ALSO"
.BR ps (1),
.BR top (1),
.BR utmp (5),
.BR w (1)
+.SH "REPORTING BUGS"
+Please send bug reports to
+.UR procps\@freelists.org
+.UE
diff --git a/uptime.c b/uptime.c
index 6a4d8bd..6ad5d1f 100644
--- a/uptime.c
+++ b/uptime.c
@@ -1,17 +1,50 @@
+#include <errno.h>
+#include <getopt.h>
+#include <stdlib.h>
#include <stdio.h>
-#include <string.h>
+
+#include "c.h"
+#include "nls.h"
#include "proc/whattime.h"
#include "proc/version.h"
-int main(int argc, char *argv[]) {
- if(argc == 1) {
- print_uptime();
- return 0;
- }
- if((argc == 2) && (!strcmp(argv[1], "-V"))) {
- display_version();
- return 0;
- }
- fprintf(stderr, "usage: uptime [-V]\n -V display version\n");
- return 1;
+static void __attribute__ ((__noreturn__)) usage(FILE * out)
+{
+ fputs(USAGE_HEADER, out);
+ fprintf(out, _(" %s [options]\n"), program_invocation_short_name);
+ fputs(USAGE_OPTIONS, out);
+ fputs(USAGE_HELP, out);
+ fputs(USAGE_VERSION, out);
+ fprintf(out, USAGE_MAN_TAIL("uptime(1)"));
+
+ exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
+int main(int argc, char **argv)
+{
+ int c;
+
+ static const struct option longopts[] = {
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'V'},
+ {NULL, 0, NULL, 0}
+ };
+
+ setlocale (LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ while ((c = getopt_long(argc, argv, "hV", longopts, NULL)) != -1)
+ switch (c) {
+ case 'h':
+ usage(stdout);
+ case 'V':
+ printf(PROCPS_NG_VERSION);
+ return EXIT_SUCCESS;
+ default:
+ usage(stderr);
+ }
+
+ print_uptime();
+ return EXIT_SUCCESS;
}
diff --git a/vmstat.8 b/vmstat.8
index 499cf4e..11e9917 100644
--- a/vmstat.8
+++ b/vmstat.8
@@ -1,83 +1,90 @@
.\" This page Copyright (C) 1994 Henry Ware <al172@yfn.ysu.edu>
.\" Distributed under the GPL, Copyleft 1994.
-.TH VMSTAT 8 "2009 Jan 9" "Throatwobbler Ginkgo Labs" "Linux Administrator's Manual"
+.TH VMSTAT 8 "September 2011" "procps-ng" "System Administration"
.SH NAME
vmstat \- Report virtual memory statistics
.SH SYNOPSIS
-.ft B
.B vmstat
-.RB [ "\-a" ]
-.RB [ "\-n" ]
-.RI [ delay " [ " count ]]
-.br
-.B vmstat
-.RB [ "\-f" ]
-.RB [ "\-s" ]
-.RB [ "\-m" ]
-.br
-.B vmstat
-.RB [ "\-S unit"]
-.br
-.B vmstat
-.RB [ "\-d"]
-.br
-.B vmstat
-.RB [ "\-D"]
-.br
-.B vmstat
-.RB [ "\-p disk partition"]
-.br
-.B vmstat
-.RB [ "\-V" ]
+[options]
+.RI [ delay " [" count ]]
.SH DESCRIPTION
-\fBvmstat\fP reports information about processes, memory, paging,
-block IO, traps, disks and cpu activity.
-
+.B vmstat
+reports information about processes, memory, paging, block IO, traps, disks
+and cpu activity.
+.PP
The first report produced gives averages since the last reboot. Additional
-reports give information on a sampling period of length \fIdelay\fP.
+reports give information on a sampling period of length
+.IR delay .
The process and memory reports are instantaneous in either case.
-
-.SS Options
-The \fB\-a\fP switch displays active/inactive memory, given a 2.5.41 kernel or better.
-.PP
-The \fB\-f\fP switch displays the number of forks since boot.
-This includes the fork, vfork, and clone system calls, and is
-equivalent to the total number of tasks created. Each process
-is represented by one or more tasks, depending on thread usage.
-This display does not repeat.
-.PP
-The \fB\-m\fP displays slabinfo.
-.PP
-The \fB\-n\fP switch causes the header to be displayed only once rather than periodically.
-.PP
-The \fB\-s\fP switch displays a table of various event counters
-and memory statistics. This display does not repeat.
-.PP
+.SH OPTIONS
+.TP
.I delay
-is the delay between updates in seconds. If no delay is specified,
-only one report is printed with the average values since boot.
-.PP
+The
+.I delay
+between updates in seconds. If no
+.I delay
+is specified, only one report is printed with the average values since boot.
+.TP
.I count
-is the number of updates. If no count is specified and delay is
-defined, \fIcount\fP defaults to infinity.
-.PP
-The \fB\-d\fP reports disk statistics (2.5.70 or above required)
-.PP
-The \fB-D\fP reports some summary statistics about disk activity.
-.PP
-The \fB\-p\fP followed by some partition name for detailed statistics (2.5.70 or above required)
-.PP
-The \fB\-S\fP followed by k or K or m or M switches outputs between
-1000, 1024, 1000000, or 1048576 bytes. Note this does not change the
-swap (si/so) or block (bi/bo) fields.
-.PP
-The \fB\-V\fP switch results in displaying version information.
-.PP
-.SH FIELD DESCRIPTION FOR VM MODE
+Number of updates. In absense of
+.IR count ,
+when
+.I delay
+is defined, default is infinite.
+.TP
+\fB\-a\fR, \fB\-\-active\fR
+Display active and inactive memory, given a 2.5.41 kernel or better.
+.TP
+\fB\-f\fR, \fB\-\-forks\fR
+The
+.B \-f
+switch displays the number of forks since boot. This includes the fork,
+vfork, and clone system calls, and is equivalent to the total number of tasks
+created. Each process is represented by one or more tasks, depending on
+thread usage. This display does not repeat.
+.TP
+\fB\-m\fR, \fB\-\-slabs\fR
+Displays slabinfo.
+.TP
+\fB\-n\fR, \fB\-\-one-header\fR
+Display the header only once rather than periodically.
+.TP
+\fB\-s\fR, \fB\-\-stats\fR
+Displays a table of various event counters and memory statistics. This
+display does not repeat.
+.TP
+\fB\-d\fR, \fB\-\-disk\fR
+Report disk statistics (2.5.70 or above required).
+.TP
+\fB\-D\fR, \fB\-\-disk-sum\fR
+Report some summary statistics about disk activity.
+.TP
+\fB\-p\fR, \fB\-\-partition\fR \fIdevice\fR
+Detailed statistics about partition (2.5.70 or above required).
+.TP
+\fB\-S\fR, \fB\-\-unit\fR \fIcharacter\fR
+Switches outputs between 1000
+.RI ( k ),
+1024
+.RI ( K ),
+1000000
+.RI ( m ),
+or 1048576
+.RI ( M )
+bytes. Note this does not change the swap (si/so) or block (bi/bo)
+fields.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Display version information and exit.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Display help and exit.
+.PD
+.SH "FIELD DESCRIPTION FOR VM MODE"
.SS
.B "Procs"
.nf
-r: The number of processes waiting for run time.
+r: The number of processes waiting for run time.
b: The number of processes in uninterruptible sleep.
.fi
.PP
@@ -88,8 +95,8 @@ swpd: the amount of virtual memory used.
free: the amount of idle memory.
buff: the amount of memory used as buffers.
cache: the amount of memory used as cache.
-inact: the amount of inactive memory. (\-a option)
-active: the amount of active memory. (\-a option)
+inact: the amount of inactive memory. (\-a option)
+active: the amount of active memory. (\-a option)
.fi
.PP
.SS
@@ -114,21 +121,21 @@ cs: The number of context switches per second.
.fi
.PP
.SS
-.B "CPU "
+.B "CPU"
These are percentages of total CPU time.
.nf
-us: Time spent running non\-kernel code. (user time, including nice time)
-sy: Time spent running kernel code. (system time)
-id: Time spent idle. Prior to Linux 2.5.41, this includes IO\-wait time.
-wa: Time spent waiting for IO. Prior to Linux 2.5.41, included in idle.
-st: Time stolen from a virtual machine. Prior to Linux 2.6.11, unknown.
+us: Time spent running non\-kernel code. (user time, including nice time)
+sy: Time spent running kernel code. (system time)
+id: Time spent idle. Prior to Linux 2.5.41, this includes IO\-wait time.
+wa: Time spent waiting for IO. Prior to Linux 2.5.41, included in idle.
+st: Time stolen from a virtual machine. Prior to Linux 2.6.11, unknown.
.fi
.PP
-.SH FIELD DESCRIPTION FOR DISK MODE
+.SH "FIELD DESCRIPTION FOR DISK MODE"
.SS
.B "Reads"
.nf
-total: Total reads completed successfully
+total: Total reads completed successfully
merged: grouped reads (resulting in one I/O)
sectors: Sectors read successfully
ms: milliseconds spent reading
@@ -149,19 +156,16 @@ ms: milliseconds spent writing
cur: I/O in progress
s: seconds spent for I/O
.fi
-
.PP
-.SH FIELD DESCRIPTION FOR DISK PARTITION MODE
+.SH "FIELD DESCRIPTION FOR DISK PARTITION MODE"
.nf
reads: Total number of reads issued to this partition
read sectors: Total read sectors for partition
writes : Total number of writes issued to this partition
requested writes: Total number of write requests made for partition
-
.fi
-
.PP
-.SH FIELD DESCRIPTION FOR SLAB MODE
+.SH "FIELD DESCRIPTION FOR SLAB MODE"
.nf
cache: Cache name
num: Number of currently active objects
@@ -169,21 +173,21 @@ total: Total number of available objects
size: Size of each object
pages: Number of pages with at least one active object
.fi
-
.SH NOTES
.B "vmstat "
does not require special permissions.
.PP
These reports are intended to help identify system bottlenecks. Linux
-.B "vmstat "
+.B vmstat
does not count itself as a running process.
.PP
-All linux blocks are currently 1024 bytes. Old kernels may report
-blocks as 512 bytes, 2048 bytes, or 4096 bytes.
+All linux blocks are currently 1024 bytes. Old kernels may report blocks as
+512 bytes, 2048 bytes, or 4096 bytes.
.PP
-Since procps 3.1.9, vmstat lets you choose units (k, K, m, M) default is K (1024 bytes) in the default mode
+Since procps 3.1.9, vmstat lets you choose units (k, K, m, M). Default is K
+(1024 bytes) in the default mode.
.PP
-vmstat uses slabinfo 1.1 FIXME
+vmstat uses slabinfo 1.1
.SH FILES
.ta
.nf
@@ -191,18 +195,27 @@ vmstat uses slabinfo 1.1 FIXME
/proc/stat
/proc/*/stat
.fi
-
.SH "SEE ALSO"
+.BR free (1),
.BR iostat (1),
-.BR sar (1),
.BR mpstat (1),
.BR ps (1),
-.BR top (1),
-.BR free (1)
+.BR sar (1),
+.BR top (1)
.PP
.SH BUGS
Does not tabulate the block io per device or count the number of system calls.
.SH AUTHORS
-.nf
-Written by Henry Ware <al172@yfn.ysu.edu>.
-Fabian Fr\('ed\('erick <ffrederick@users.sourceforge.net> (diskstat, slab, partitions...)
+Written by
+.UR al172\@yfn.\:ysu.\:edu
+Henry Ware
+.UE .
+.br
+.UR ffrederick\@users.\:sourceforge.\:net
+Fabian Fr\('ed\('erick
+.UE
+(diskstat, slab, partitions...)
+.SH "REPORTING BUGS"
+Please send bug reports to
+.UR procps\@freelists.org
+.UE
diff --git a/vmstat.c b/vmstat.c
index e7a28d7..fddffbc 100644
--- a/vmstat.c
+++ b/vmstat.c
@@ -1,31 +1,37 @@
-// old: "Copyright 1994 by Henry Ware <al172@yfn.ysu.edu>. Copyleft same year."
-// most code copyright 2002 Albert Cahalan
-//
-// 27/05/2003 (Fabian Frederick) : Add unit conversion + interface
-// Export proc/stat access to libproc
-// Adapt vmstat helpfile
-// 31/05/2003 (Fabian) : Add diskstat support (/libproc)
-// June 2003 (Fabian) : -S <x> -s & -s -S <x> patch
-// June 2003 (Fabian) : -Adding diskstat against 3.1.9, slabinfo
-// -patching 'header' in disk & slab
-// July 2003 (Fabian) : -Adding disk partition output
-// -Adding disk table
-// -Syncing help / usage
+/* old: "Copyright 1994 by Henry Ware <al172@yfn.ysu.edu>. Copyleft same year."
+ * most code copyright 2002 Albert Cahalan
+ *
+ * 27/05/2003 (Fabian Frederick) : Add unit conversion + interface
+ * Export proc/stat access to libproc
+ * Adapt vmstat helpfile
+ * 31/05/2003 (Fabian) : Add diskstat support (/libproc)
+ * June 2003 (Fabian) : -S <x> -s & -s -S <x> patch
+ * June 2003 (Fabian) : Adding diskstat against 3.1.9, slabinfo
+ * patching 'header' in disk & slab
+ * July 2003 (Fabian) : Adding disk partition output
+ * Adding disk table
+ * Syncing help / usage
+ */
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
#include <assert.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
#include <fcntl.h>
+#include <getopt.h>
#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/dir.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
#include <termios.h>
#include <unistd.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/dir.h>
-#include <dirent.h>
+#include "c.h"
+#include "nls.h"
+#include "strutils.h"
#include "proc/sysinfo.h"
#include "proc/version.h"
@@ -35,7 +41,7 @@
#define UNIT_m 1000000
#define UNIT_M 1048576
-static unsigned long dataUnit=UNIT_K;
+static unsigned long dataUnit = UNIT_K;
static char szDataUnit[3] = "K";
#define VMSTAT 0
@@ -45,638 +51,778 @@ static char szDataUnit[3] = "K";
#define PARTITIONSTAT 0x00000008
#define DISKSUMSTAT 0x00000010
-static int statMode=VMSTAT;
+static int statMode = VMSTAT;
-#define FALSE 0
-#define TRUE 1
-
-static int a_option; /* "-a" means "show active/inactive" */
+/* "-a" means "show active/inactive" */
+static int a_option;
static unsigned sleep_time = 1;
+static int infinite_updates = 0;
static unsigned long num_updates;
-
-static unsigned int height; // window height
-static unsigned int moreheaders=TRUE;
-
-
-/////////////////////////////////////////////////////////////////////////
-
-static void usage(void) NORETURN;
-static void usage(void) {
- fprintf(stderr,"usage: vmstat [-V] [-n] [delay [count]]\n");
- fprintf(stderr," -V prints version.\n");
- fprintf(stderr," -n causes the headers not to be reprinted regularly.\n");
- fprintf(stderr," -a print inactive/active page stats.\n");
- fprintf(stderr," -d prints disk statistics\n");
- fprintf(stderr," -D prints disk table\n");
- fprintf(stderr," -p prints disk partition statistics\n");
- fprintf(stderr," -s prints vm table\n");
- fprintf(stderr," -m prints slabinfo\n");
- fprintf(stderr," -S unit size\n");
- fprintf(stderr," delay is the delay between updates in seconds. \n");
- fprintf(stderr," unit size k:1000 K:1024 m:1000000 M:1048576 (default is K)\n");
- fprintf(stderr," count is the number of updates.\n");
- exit(EXIT_FAILURE);
+/* window height */
+static unsigned int height;
+static unsigned int moreheaders = TRUE;
+
+static void __attribute__ ((__noreturn__))
+ usage(FILE * out)
+{
+ fputs(USAGE_HEADER, out);
+ fprintf(out,
+ _(" %s [options] [delay [count]]\n"),
+ program_invocation_short_name);
+ fputs(USAGE_OPTIONS, out);
+ fputs(_(" -a, --active active/inactive memory\n"), out);
+ fputs(_(" -f, --forks number of forks since boot\n"), out);
+ fputs(_(" -m, --slabs slabinfo\n"), out);
+ fputs(_(" -n, --one-header do not redisplay header\n"), out);
+ fputs(_(" -s, --stats event counter statistics\n"), out);
+ fputs(_(" -d, --disk disk statistics\n"), out);
+ fputs(_(" -D, --disk-sum summarize disk statistics\n"), out);
+ fputs(_(" -p, --partition <dev> partition specific statistics\n"), out);
+ fputs(_(" -S, --unit <char> define display unit\n"), out);
+ fputs(USAGE_SEPARATOR, out);
+ fputs(USAGE_HELP, out);
+ fputs(USAGE_VERSION, out);
+ fprintf(out, USAGE_MAN_TAIL("vmstat(8)"));
+
+ exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
-/////////////////////////////////////////////////////////////////////////////
-
#if 0
-// produce: " 6 ", "123 ", "123k ", etc.
-static int format_1024(unsigned long long val64, char *restrict dst){
- unsigned oldval;
- const char suffix[] = " kmgtpe";
- unsigned level = 0;
- unsigned val32;
-
- if(val64 < 1000){ // special case to avoid "6.0 " when plain " 6 " would do
- val32 = val64;
- return sprintf(dst,"%3u ",val32);
- }
-
- while(val64 > 0xffffffffull){
- level++;
- val64 /= 1024;
- }
-
- val32 = val64;
-
- while(val32 > 999){
- level++;
- oldval = val32;
- val32 /= 1024;
- }
-
- if(val32 < 10){
- unsigned fract = (oldval % 1024) * 10 / 1024;
- return sprintf(dst, "%u.%u%c ", val32, fract, suffix[level]);
- }
- return sprintf(dst, "%3u%c ", val32, suffix[level]);
-}
+/* produce: " 6 ", "123 ", "123k ", etc. */
+static int format_1024(unsigned long long val64, char *restrict dst)
+{
+ unsigned oldval;
+ const char suffix[] = " kmgtpe";
+ unsigned level = 0;
+ unsigned val32;
+
+ if (val64 < 1000) {
+ /* special case to avoid "6.0 " when plain " 6 " would do */
+ val32 = val64;
+ return sprintf(dst, "%3u ", val32);
+ }
+ while (val64 > 0xffffffffull) {
+ level++;
+ val64 /= 1024;
+ }
-// produce: " 6 ", "123 ", "123k ", etc.
-static int format_1000(unsigned long long val64, char *restrict dst){
- unsigned oldval;
- const char suffix[] = " kmgtpe";
- unsigned level = 0;
- unsigned val32;
-
- if(val64 < 1000){ // special case to avoid "6.0 " when plain " 6 " would do
- val32 = val64;
- return sprintf(dst,"%3u ",val32);
- }
-
- while(val64 > 0xffffffffull){
- level++;
- val64 /= 1000;
- }
-
- val32 = val64;
-
- while(val32 > 999){
- level++;
- oldval = val32;
- val32 /= 1000;
- }
-
- if(val32 < 10){
- unsigned fract = (oldval % 1000) / 100;
- return sprintf(dst, "%u.%u%c ", val32, fract, suffix[level]);
- }
- return sprintf(dst, "%3u%c ", val32, suffix[level]);
-}
-#endif
+ val32 = val64;
-////////////////////////////////////////////////////////////////////////////
-
-static void new_header(void){
- printf("procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----\n");
- printf(
- "%2s %2s %6s %6s %6s %6s %4s %4s %5s %5s %4s %4s %2s %2s %2s %2s\n",
- "r","b",
- "swpd", "free", a_option?"inact":"buff", a_option?"active":"cache",
- "si","so",
- "bi","bo",
- "in","cs",
- "us","sy","id","wa"
- );
+ while (val32 > 999) {
+ level++;
+ oldval = val32;
+ val32 /= 1024;
+ }
+
+ if (val32 < 10) {
+ unsigned fract = (oldval % 1024) * 10 / 1024;
+ return sprintf(dst, "%u.%u%c ", val32, fract, suffix[level]);
+ }
+ return sprintf(dst, "%3u%c ", val32, suffix[level]);
}
-////////////////////////////////////////////////////////////////////////////
+/* produce: " 6 ", "123 ", "123k ", etc. */
+static int format_1000(unsigned long long val64, char *restrict dst)
+{
+ unsigned oldval;
+ const char suffix[] = " kmgtpe";
+ unsigned level = 0;
+ unsigned val32;
+
+ if (val64 < 1000) {
+ /* special case to avoid "6.0 " when plain " 6 " would do */
+ val32 = val64;
+ return sprintf(dst, "%3u ", val32);
+ }
-static unsigned long unitConvert(unsigned int size){
- float cvSize;
- cvSize=(float)size/dataUnit*((statMode==SLABSTAT)?1:1024);
- return ((unsigned long) cvSize);
-}
+ while (val64 > 0xffffffffull) {
+ level++;
+ val64 /= 1000;
+ }
-////////////////////////////////////////////////////////////////////////////
-
-static void new_format(void) {
- const char format[]="%2u %2u %6lu %6lu %6lu %6lu %4u %4u %5u %5u %4u %4u %2u %2u %2u %2u\n";
- unsigned int tog=0; /* toggle switch for cleaner code */
- unsigned int i;
- unsigned int hz = Hertz;
- unsigned int running,blocked,dummy_1,dummy_2;
- jiff cpu_use[2], cpu_nic[2], cpu_sys[2], cpu_idl[2], cpu_iow[2], cpu_xxx[2], cpu_yyy[2], cpu_zzz[2];
- jiff duse, dsys, didl, diow, dstl, Div, divo2;
- unsigned long pgpgin[2], pgpgout[2], pswpin[2], pswpout[2];
- unsigned int intr[2], ctxt[2];
- unsigned int sleep_half;
- unsigned long kb_per_page = sysconf(_SC_PAGESIZE) / 1024ul;
- int debt = 0; // handle idle ticks running backwards
-
- sleep_half=(sleep_time/2);
- new_header();
- meminfo();
-
- getstat(cpu_use,cpu_nic,cpu_sys,cpu_idl,cpu_iow,cpu_xxx,cpu_yyy,cpu_zzz,
- pgpgin,pgpgout,pswpin,pswpout,
- intr,ctxt,
- &running,&blocked,
- &dummy_1, &dummy_2);
-
- duse= *cpu_use + *cpu_nic;
- dsys= *cpu_sys + *cpu_xxx + *cpu_yyy;
- didl= *cpu_idl;
- diow= *cpu_iow;
- dstl= *cpu_zzz;
- Div= duse+dsys+didl+diow+dstl;
- divo2= Div/2UL;
- printf(format,
- running, blocked,
- unitConvert(kb_swap_used), unitConvert(kb_main_free),
- unitConvert(a_option?kb_inactive:kb_main_buffers),
- unitConvert(a_option?kb_active:kb_main_cached),
- (unsigned)( (*pswpin * unitConvert(kb_per_page) * hz + divo2) / Div ),
- (unsigned)( (*pswpout * unitConvert(kb_per_page) * hz + divo2) / Div ),
- (unsigned)( (*pgpgin * hz + divo2) / Div ),
- (unsigned)( (*pgpgout * hz + divo2) / Div ),
- (unsigned)( (*intr * hz + divo2) / Div ),
- (unsigned)( (*ctxt * hz + divo2) / Div ),
- (unsigned)( (100*duse + divo2) / Div ),
- (unsigned)( (100*dsys + divo2) / Div ),
- (unsigned)( (100*didl + divo2) / Div ),
- (unsigned)( (100*diow + divo2) / Div ) /* ,
- (unsigned)( (100*dstl + divo2) / Div ) */
- );
-
- for(i=1;i<num_updates;i++) { /* \\\\\\\\\\\\\\\\\\\\ main loop ////////////////// */
- sleep(sleep_time);
- if (moreheaders && ((i%height)==0)) new_header();
- tog= !tog;
-
- meminfo();
-
- getstat(cpu_use+tog,cpu_nic+tog,cpu_sys+tog,cpu_idl+tog,cpu_iow+tog,cpu_xxx+tog,cpu_yyy+tog,cpu_zzz+tog,
- pgpgin+tog,pgpgout+tog,pswpin+tog,pswpout+tog,
- intr+tog,ctxt+tog,
- &running,&blocked,
- &dummy_1,&dummy_2);
-
- duse= cpu_use[tog]-cpu_use[!tog] + cpu_nic[tog]-cpu_nic[!tog];
- dsys= cpu_sys[tog]-cpu_sys[!tog] + cpu_xxx[tog]-cpu_xxx[!tog] + cpu_yyy[tog]-cpu_yyy[!tog];
- didl= cpu_idl[tog]-cpu_idl[!tog];
- diow= cpu_iow[tog]-cpu_iow[!tog];
- dstl= cpu_zzz[tog]-cpu_zzz[!tog];
-
- /* idle can run backwards for a moment -- kernel "feature" */
- if(debt){
- didl = (int)didl + debt;
- debt = 0;
- }
- if( (int)didl < 0 ){
- debt = (int)didl;
- didl = 0;
- }
-
- Div= duse+dsys+didl+diow+dstl;
- divo2= Div/2UL;
- printf(format,
- running, blocked,
- unitConvert(kb_swap_used),unitConvert(kb_main_free),
- unitConvert(a_option?kb_inactive:kb_main_buffers),
- unitConvert(a_option?kb_active:kb_main_cached),
- (unsigned)( ( (pswpin [tog] - pswpin [!tog])*unitConvert(kb_per_page)+sleep_half )/sleep_time ), /*si*/
- (unsigned)( ( (pswpout[tog] - pswpout[!tog])*unitConvert(kb_per_page)+sleep_half )/sleep_time ), /*so*/
- (unsigned)( ( pgpgin [tog] - pgpgin [!tog] +sleep_half )/sleep_time ), /*bi*/
- (unsigned)( ( pgpgout[tog] - pgpgout[!tog] +sleep_half )/sleep_time ), /*bo*/
- (unsigned)( ( intr [tog] - intr [!tog] +sleep_half )/sleep_time ), /*in*/
- (unsigned)( ( ctxt [tog] - ctxt [!tog] +sleep_half )/sleep_time ), /*cs*/
- (unsigned)( (100*duse+divo2)/Div ), /*us*/
- (unsigned)( (100*dsys+divo2)/Div ), /*sy*/
- (unsigned)( (100*didl+divo2)/Div ), /*id*/
- (unsigned)( (100*diow+divo2)/Div )/*, //wa
- (unsigned)( (100*dstl+divo2)/Div ) //st */
- );
- }
-}
+ val32 = val64;
-////////////////////////////////////////////////////////////////////////////
+ while (val32 > 999) {
+ level++;
+ oldval = val32;
+ val32 /= 1000;
+ }
-static void diskpartition_header(const char *partition_name){
- printf("%-10s %10s %10s %10s %10s\n",partition_name, "reads ", "read sectors", "writes ", "requested writes");
+ if (val32 < 10) {
+ unsigned fract = (oldval % 1000) / 100;
+ return sprintf(dst, "%u.%u%c ", val32, fract, suffix[level]);
+ }
+ return sprintf(dst, "%3u%c ", val32, suffix[level]);
}
+#endif
-////////////////////////////////////////////////////////////////////////////
-
-static int diskpartition_format(const char* partition_name){
- FILE *fDiskstat;
- struct disk_stat *disks;
- struct partition_stat *partitions, *current_partition=NULL;
- unsigned long ndisks, j, k, npartitions;
- const char format[] = "%20u %10llu %10u %10llu\n";
-
- fDiskstat=fopen("/proc/diskstats","rb");
- if(!fDiskstat){
- fprintf(stderr, "Your kernel doesn't support diskstat. (2.5.70 or above required)\n");
- exit(EXIT_FAILURE);
- }
-
- fclose(fDiskstat);
- ndisks=getdiskstat(&disks,&partitions);
- npartitions=getpartitions_num(disks, ndisks);
- for(k=0; k<npartitions; k++){
- if(!strcmp(partition_name, partitions[k].partition_name)){
- current_partition=&(partitions[k]);
- }
- }
- if(!current_partition){
- free(disks);
- free(partitions);
- return -1;
- }
- diskpartition_header(partition_name);
- printf (format,
- current_partition->reads,current_partition->reads_sectors,current_partition->writes,current_partition->requested_writes);
- fflush(stdout);
- free(disks);
- free(partitions);
- for(j=1; j<num_updates; j++){
- if (moreheaders && ((j%height)==0)) diskpartition_header(partition_name);
- sleep(sleep_time);
- ndisks=getdiskstat(&disks,&partitions);
- npartitions=getpartitions_num(disks, ndisks);
- current_partition=NULL;
- for(k=0; k<npartitions; k++){
- if(!strcmp(partition_name, partitions[k].partition_name)){
- current_partition=&(partitions[k]);
- }
- }
- if(!current_partition){
- free(disks);
- free(partitions);
- return -1;
- }
- printf (format,
- current_partition->reads,current_partition->reads_sectors,current_partition->writes,current_partition->requested_writes);
- fflush(stdout);
- free(disks);
- free(partitions);
- }
- return 0;
+static void new_header(void)
+{
+ /* Translation Hint: Translating folloging header & fields
+ * that follow (marked with max x chars) might not work,
+ * unless manual page is translated as well. */
+ printf(_("procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----\n"));
+ printf
+ ("%2s %2s %6s %6s %6s %6s %4s %4s %5s %5s %4s %4s %2s %2s %2s %2s\n",
+ /* Translation Hint: max 2 chars */
+ _("r"),
+ /* Translation Hint: max 2 chars */
+ _("b"),
+ /* Translation Hint: max 6 chars */
+ _("swpd"),
+ /* Translation Hint: max 6 chars */
+ _("free"),
+ /* Translation Hint: max 6 chars */
+ a_option ? _("inact") :
+ /* Translation Hint: max 6 chars */
+ _("buff"),
+ /* Translation Hint: max 6 chars */
+ a_option ? _("active") :
+ /* Translation Hint: max 6 chars */
+ _("cache"),
+ /* Translation Hint: max 4 chars */
+ _("si"),
+ /* Translation Hint: max 4 chars */
+ _("so"),
+ /* Translation Hint: max 5 chars */
+ _("bi"),
+ /* Translation Hint: max 5 chars */
+ _("bo"),
+ /* Translation Hint: max 4 chars */
+ _("in"),
+ /* Translation Hint: max 4 chars */
+ _("cs"),
+ /* Translation Hint: max 2 chars */
+ _("us"),
+ /* Translation Hint: max 2 chars */
+ _("sy"),
+ /* Translation Hint: max 2 chars */
+ _("id"),
+ /* Translation Hint: max 2 chars */
+ _("wa"));
}
-////////////////////////////////////////////////////////////////////////////
-
-static void diskheader(void){
- printf("disk- ------------reads------------ ------------writes----------- -----IO------\n");
+static unsigned long unitConvert(unsigned int size)
+{
+ float cvSize;
+ cvSize = (float)size / dataUnit * ((statMode == SLABSTAT) ? 1 : 1024);
+ return ((unsigned long)cvSize);
+}
- printf("%5s %6s %6s %7s %7s %6s %6s %7s %7s %6s %6s\n",
- " ", "total", "merged","sectors","ms","total","merged","sectors","ms","cur","sec");
+static void new_format(void)
+{
+ const char format[] =
+ "%2u %2u %6lu %6lu %6lu %6lu %4u %4u %5u %5u %4u %4u %2u %2u %2u %2u\n";
+ unsigned int tog = 0; /* toggle switch for cleaner code */
+ unsigned int i;
+ unsigned int hz = Hertz;
+ unsigned int running, blocked, dummy_1, dummy_2;
+ jiff cpu_use[2], cpu_nic[2], cpu_sys[2], cpu_idl[2], cpu_iow[2],
+ cpu_xxx[2], cpu_yyy[2], cpu_zzz[2];
+ jiff duse, dsys, didl, diow, dstl, Div, divo2;
+ unsigned long pgpgin[2], pgpgout[2], pswpin[2], pswpout[2];
+ unsigned int intr[2], ctxt[2];
+ unsigned int sleep_half;
+ unsigned long kb_per_page = sysconf(_SC_PAGESIZE) / 1024ul;
+ int debt = 0; /* handle idle ticks running backwards */
+
+ sleep_half = (sleep_time / 2);
+ new_header();
+ meminfo();
+
+ getstat(cpu_use, cpu_nic, cpu_sys, cpu_idl, cpu_iow, cpu_xxx, cpu_yyy,
+ cpu_zzz, pgpgin, pgpgout, pswpin, pswpout, intr, ctxt, &running,
+ &blocked, &dummy_1, &dummy_2);
+
+ duse = *cpu_use + *cpu_nic;
+ dsys = *cpu_sys + *cpu_xxx + *cpu_yyy;
+ didl = *cpu_idl;
+ diow = *cpu_iow;
+ dstl = *cpu_zzz;
+ Div = duse + dsys + didl + diow + dstl;
+ divo2 = Div / 2UL;
+ printf(format,
+ running, blocked,
+ unitConvert(kb_swap_used), unitConvert(kb_main_free),
+ unitConvert(a_option?kb_inactive:kb_main_buffers),
+ unitConvert(a_option?kb_active:kb_main_cached),
+ (unsigned)( (*pswpin * unitConvert(kb_per_page) * hz + divo2) / Div ),
+ (unsigned)( (*pswpout * unitConvert(kb_per_page) * hz + divo2) / Div ),
+ (unsigned)( (*pgpgin * hz + divo2) / Div ),
+ (unsigned)( (*pgpgout * hz + divo2) / Div ),
+ (unsigned)( (*intr * hz + divo2) / Div ),
+ (unsigned)( (*ctxt * hz + divo2) / Div ),
+ (unsigned)( (100*duse + divo2) / Div ),
+ (unsigned)( (100*dsys + divo2) / Div ),
+ (unsigned)( (100*didl + divo2) / Div ),
+ (unsigned)( (100*diow + divo2) / Div )/*,
+ (unsigned)( (100*dstl + divo2) / Div ) */
+ );
+
+ /* main loop */
+ for (i = 1; infinite_updates || i < num_updates; i++) {
+ sleep(sleep_time);
+ if (moreheaders && ((i % height) == 0))
+ new_header();
+ tog = !tog;
+
+ meminfo();
+
+ getstat(cpu_use + tog, cpu_nic + tog, cpu_sys + tog,
+ cpu_idl + tog, cpu_iow + tog, cpu_xxx + tog,
+ cpu_yyy + tog, cpu_zzz + tog, pgpgin + tog,
+ pgpgout + tog, pswpin + tog, pswpout + tog, intr + tog,
+ ctxt + tog, &running, &blocked, &dummy_1, &dummy_2);
+
+ duse =
+ cpu_use[tog] - cpu_use[!tog] + cpu_nic[tog] - cpu_nic[!tog];
+ dsys =
+ cpu_sys[tog] - cpu_sys[!tog] + cpu_xxx[tog] -
+ cpu_xxx[!tog] + cpu_yyy[tog] - cpu_yyy[!tog];
+ didl = cpu_idl[tog] - cpu_idl[!tog];
+ diow = cpu_iow[tog] - cpu_iow[!tog];
+ dstl = cpu_zzz[tog] - cpu_zzz[!tog];
+
+ /* idle can run backwards for a moment -- kernel "feature" */
+ if (debt) {
+ didl = (int)didl + debt;
+ debt = 0;
+ }
+ if ((int)didl < 0) {
+ debt = (int)didl;
+ didl = 0;
+ }
+
+ Div = duse + dsys + didl + diow + dstl;
+ divo2 = Div / 2UL;
+ printf(format,
+ running,
+ blocked,
+ unitConvert(kb_swap_used),unitConvert(kb_main_free),
+ unitConvert(a_option?kb_inactive:kb_main_buffers),
+ unitConvert(a_option?kb_active:kb_main_cached),
+ /*si */
+ (unsigned)( ( (pswpin [tog] - pswpin [!tog])*unitConvert(kb_per_page)+sleep_half )/sleep_time ),
+ /* so */
+ (unsigned)( ( (pswpout[tog] - pswpout[!tog])*unitConvert(kb_per_page)+sleep_half )/sleep_time ),
+ /* bi */
+ (unsigned)( ( pgpgin [tog] - pgpgin [!tog] +sleep_half )/sleep_time ),
+ /* bo */
+ (unsigned)( ( pgpgout[tog] - pgpgout[!tog] +sleep_half )/sleep_time ),
+ /* in */
+ (unsigned)( ( intr [tog] - intr [!tog] +sleep_half )/sleep_time ),
+ /* cs */
+ (unsigned)( ( ctxt [tog] - ctxt [!tog] +sleep_half )/sleep_time ),
+ /* us */
+ (unsigned)( (100*duse+divo2)/Div ),
+ /* sy */
+ (unsigned)( (100*dsys+divo2)/Div ),
+ /* id */
+ (unsigned)( (100*didl+divo2)/Div ),
+ /* wa */
+ (unsigned)( (100*diow+divo2)/Div )/*,
+ / * st * /
+ (unsigned)( (100*dstl+divo2)/Div ) */
+ );
+ }
+}
+static void diskpartition_header(const char *partition_name)
+{
+ printf("%-10s %10s %10s %10s %10s\n",
+ partition_name,
+ /* Translation Hint: Translating folloging disk partition
+ * header fields that follow (marked with max x chars) might
+ * not work, unless manual page is translated as well. */
+ /* Translation Hint: max 10 chars. The word is
+ * expected to be centralized, use spaces at the end
+ * to do that. */
+ _("reads "),
+ /* Translation Hint: max 10 chars */
+ _("read sectors"),
+ /* Translation Hint: max 10 chars. The word is
+ * expected to be centralized, use spaces at the end
+ * to do that. */
+ _("writes "),
+ /* Translation Hint: max 10 chars */
+ _("requested writes"));
}
-////////////////////////////////////////////////////////////////////////////
-
-static void diskformat(void){
- FILE *fDiskstat;
- struct disk_stat *disks;
- struct partition_stat *partitions;
- unsigned long ndisks,i,j,k;
- const char format[]="%-5s %6u %6u %7llu %7u %6u %6u %7llu %7u %6u %6u\n";
- if ((fDiskstat=fopen("/proc/diskstats", "rb"))){
- fclose(fDiskstat);
- ndisks=getdiskstat(&disks,&partitions);
- if (!moreheaders) diskheader();
- for(k=0; k<ndisks; k++){
- if (moreheaders && ((k%height)==0)) diskheader();
- printf(format,
- disks[k].disk_name,
- disks[k].reads,
- disks[k].merged_reads,
- disks[k].reads_sectors,
- disks[k].milli_reading,
- disks[k].writes,
- disks[k].merged_writes,
- disks[k].written_sectors,
- disks[k].milli_writing,
- disks[k].inprogress_IO?disks[k].inprogress_IO/1000:0,
- disks[k].milli_spent_IO?disks[k].milli_spent_IO/1000:0/*,
- disks[i].weighted_milli_spent_IO/1000*/
- );
- fflush(stdout);
- }
- free(disks);
- free(partitions);
- for(j=1; j<num_updates; j++){
- sleep(sleep_time);
- ndisks=getdiskstat(&disks,&partitions);
- for(i=0; i<ndisks; i++,k++){
- if (moreheaders && ((k%height)==0)) diskheader();
- printf(format,
- disks[i].disk_name,
- disks[i].reads,
- disks[i].merged_reads,
- disks[i].reads_sectors,
- disks[i].milli_reading,
- disks[i].writes,
- disks[i].merged_writes,
- disks[i].written_sectors,
- disks[i].milli_writing,
- disks[i].inprogress_IO?disks[i].inprogress_IO/1000:0,
- disks[i].milli_spent_IO?disks[i].milli_spent_IO/1000:0/*,
- disks[i].weighted_milli_spent_IO/1000*/
- );
- fflush(stdout);
- }
- free(disks);
- free(partitions);
- }
- }else{
- fprintf(stderr, "Your kernel doesn't support diskstat (2.5.70 or above required)\n");
- exit(EXIT_FAILURE);
- }
+static int diskpartition_format(const char *partition_name)
+{
+ FILE *fDiskstat;
+ struct disk_stat *disks;
+ struct partition_stat *partitions, *current_partition = NULL;
+ unsigned long ndisks, j, k, npartitions;
+ const char format[] = "%20u %10llu %10u %10u\n";
+
+ fDiskstat = fopen("/proc/diskstats", "rb");
+ if (!fDiskstat)
+ errx(EXIT_FAILURE,
+ _("Your kernel doesn't support diskstat. (2.5.70 or above required)"));
+
+ fclose(fDiskstat);
+ ndisks = getdiskstat(&disks, &partitions);
+ npartitions = getpartitions_num(disks, ndisks);
+ for (k = 0; k < npartitions; k++) {
+ if (!strcmp(partition_name, partitions[k].partition_name)) {
+ current_partition = &(partitions[k]);
+ }
+ }
+ if (!current_partition) {
+ free(disks);
+ free(partitions);
+ return -1;
+ }
+ diskpartition_header(partition_name);
+ printf(format,
+ current_partition->reads, current_partition->reads_sectors,
+ current_partition->writes, current_partition->requested_writes);
+ fflush(stdout);
+ free(disks);
+ free(partitions);
+ for (j = 1; infinite_updates || j < num_updates; j++) {
+ if (moreheaders && ((j % height) == 0))
+ diskpartition_header(partition_name);
+ sleep(sleep_time);
+ ndisks = getdiskstat(&disks, &partitions);
+ npartitions = getpartitions_num(disks, ndisks);
+ current_partition = NULL;
+ for (k = 0; k < npartitions; k++) {
+ if (!strcmp
+ (partition_name, partitions[k].partition_name)) {
+ current_partition = &(partitions[k]);
+ }
+ }
+ if (!current_partition) {
+ free(disks);
+ free(partitions);
+ return -1;
+ }
+ printf(format,
+ current_partition->reads,
+ current_partition->reads_sectors,
+ current_partition->writes,
+ current_partition->requested_writes);
+ fflush(stdout);
+ free(disks);
+ free(partitions);
+ }
+ return 0;
}
-////////////////////////////////////////////////////////////////////////////
+static void diskheader(void)
+{
+ /* Translation Hint: Translating folloging header & fields
+ * that follow (marked with max x chars) might not work,
+ * unless manual page is translated as well. */
+ printf(_("disk- ------------reads------------ ------------writes----------- -----IO------\n"));
+ printf("%5s %6s %6s %7s %7s %6s %6s %7s %7s %6s %6s\n",
+ " ",
+ /* Translation Hint: max 6 chars */
+ _("total"),
+ /* Translation Hint: max 6 chars */
+ _("merged"),
+ /* Translation Hint: max 7 chars */
+ _("sectors"),
+ /* Translation Hint: max 7 chars */
+ _("ms"),
+ /* Translation Hint: max 6 chars */
+ _("total"),
+ /* Translation Hint: max 6 chars */
+ _("merged"),
+ /* Translation Hint: max 7 chars */
+ _("sectors"),
+ /* Translation Hint: max 7 chars */
+ _("ms"),
+ /* Translation Hint: max 6 chars */
+ _("cur"),
+ /* Translation Hint: max 6 chars */
+ _("sec"));
+}
-static void slabheader(void){
- printf("%-24s %6s %6s %6s %6s\n","Cache","Num", "Total", "Size", "Pages");
+static void diskformat(void)
+{
+ FILE *fDiskstat;
+ struct disk_stat *disks;
+ struct partition_stat *partitions;
+ unsigned long ndisks, i, j, k;
+ const char format[] = "%-5s %6u %6u %7llu %7u %6u %6u %7llu %7u %6u %6u\n";
+
+ if ((fDiskstat = fopen("/proc/diskstats", "rb"))) {
+ fclose(fDiskstat);
+ ndisks = getdiskstat(&disks, &partitions);
+ if (!moreheaders)
+ diskheader();
+ for (k = 0; k < ndisks; k++) {
+ if (moreheaders && ((k % height) == 0))
+ diskheader();
+ printf(format,
+ disks[k].disk_name,
+ disks[k].reads,
+ disks[k].merged_reads,
+ disks[k].reads_sectors,
+ disks[k].milli_reading,
+ disks[k].writes,
+ disks[k].merged_writes,
+ disks[k].written_sectors,
+ disks[k].milli_writing,
+ disks[k].inprogress_IO ? disks[k].inprogress_IO / 1000 : 0,
+ disks[k].milli_spent_IO ? disks[k].
+ milli_spent_IO / 1000 : 0);
+ fflush(stdout);
+ }
+ free(disks);
+ free(partitions);
+ for (j = 1; infinite_updates || j < num_updates; j++) {
+ sleep(sleep_time);
+ ndisks = getdiskstat(&disks, &partitions);
+ for (i = 0; i < ndisks; i++, k++) {
+ if (moreheaders && ((k % height) == 0))
+ diskheader();
+ printf(format,
+ disks[i].disk_name,
+ disks[i].reads,
+ disks[i].merged_reads,
+ disks[i].reads_sectors,
+ disks[i].milli_reading,
+ disks[i].writes,
+ disks[i].merged_writes,
+ disks[i].written_sectors,
+ disks[i].milli_writing,
+ disks[i].inprogress_IO ? disks[i].inprogress_IO / 1000 : 0,
+ disks[i].milli_spent_IO ? disks[i].
+ milli_spent_IO / 1000 : 0);
+ fflush(stdout);
+ }
+ free(disks);
+ free(partitions);
+ }
+ } else
+ errx(EXIT_FAILURE,
+ _("Your kernel doesn't support diskstat (2.5.70 or above required)"));
}
-////////////////////////////////////////////////////////////////////////////
-
-static void slabformat (void){
- FILE *fSlab;
- struct slab_cache *slabs;
- unsigned long nSlab,i,j,k;
- const char format[]="%-24s %6u %6u %6u %6u\n";
-
- fSlab=fopen("/proc/slabinfo", "rb");
- if(!fSlab){
- fprintf(stderr, "Your kernel doesn't support slabinfo or your permissions are insufficient.\n");
- return;
- }
-
- if (!moreheaders) slabheader();
- nSlab = getslabinfo(&slabs);
- for(k=0; k<nSlab; k++){
- if (moreheaders && ((k%height)==0)) slabheader();
- printf(format,
- slabs[k].name,
- slabs[k].active_objs,
- slabs[k].num_objs,
- slabs[k].objsize,
- slabs[k].objperslab
- );
- }
- free(slabs);
- for(j=1,k=1; j<num_updates; j++) {
- sleep(sleep_time);
- nSlab = getslabinfo(&slabs);
- for(i=0; i<nSlab; i++,k++){
- if (moreheaders && ((k%height)==0)) slabheader();
- printf(format,
- slabs[i].name,
- slabs[i].active_objs,
- slabs[i].num_objs,
- slabs[i].objsize,
- slabs[i].objperslab
- );
- }
- free(slabs);
- }
- free(fSlab);
+static void slabheader(void)
+{
+ printf("%-24s %6s %6s %6s %6s\n",
+ /* Translation Hint: Translating folloging slab fields that
+ * follow (marked with max x chars) might not work, unless
+ * manual page is translated as well. */
+ /* Translation Hint: max 24 chars */
+ _("Cache"),
+ /* Translation Hint: max 6 chars */
+ _("Num"),
+ /* Translation Hint: max 6 chars */
+ _("Total"),
+ /* Translation Hint: max 6 chars */
+ _("Size"),
+ /* Translation Hint: max 6 chars */
+ _("Pages"));
}
-////////////////////////////////////////////////////////////////////////////
-
-static void disksum_format(void) {
-
- FILE *fDiskstat;
- struct disk_stat *disks;
- struct partition_stat *partitions;
- int ndisks, i;
- unsigned long reads, merged_reads, read_sectors, milli_reading, writes,
- merged_writes, written_sectors, milli_writing, inprogress_IO,
- milli_spent_IO, weighted_milli_spent_IO;
-
- reads=merged_reads=read_sectors=milli_reading=writes=merged_writes= \
- written_sectors=milli_writing=inprogress_IO=milli_spent_IO= \
- weighted_milli_spent_IO=0;
-
- if ((fDiskstat=fopen("/proc/diskstats", "rb"))){
- fclose(fDiskstat);
- ndisks=getdiskstat(&disks, &partitions);
- printf("%13d disks \n", ndisks);
- printf("%13d partitions \n", getpartitions_num(disks, ndisks));
-
- for(i=0; i<ndisks; i++){
- reads+=disks[i].reads;
- merged_reads+=disks[i].merged_reads;
- read_sectors+=disks[i].reads_sectors;
- milli_reading+=disks[i].milli_reading;
- writes+=disks[i].writes;
- merged_writes+=disks[i].merged_writes;
- written_sectors+=disks[i].written_sectors;
- milli_writing+=disks[i].milli_writing;
- inprogress_IO+=disks[i].inprogress_IO?disks[i].inprogress_IO/1000:0;
- milli_spent_IO+=disks[i].milli_spent_IO?disks[i].milli_spent_IO/1000:0;
- }
-
- printf("%13lu total reads\n",reads);
- printf("%13lu merged reads\n",merged_reads);
- printf("%13lu read sectors\n",read_sectors);
- printf("%13lu milli reading\n",milli_reading);
- printf("%13lu writes\n",writes);
- printf("%13lu merged writes\n",merged_writes);
- printf("%13lu written sectors\n",written_sectors);
- printf("%13lu milli writing\n",milli_writing);
- printf("%13lu inprogress IO\n",inprogress_IO);
- printf("%13lu milli spent IO\n",milli_spent_IO);
-
- free(disks);
- free(partitions);
- }
+static void slabformat(void)
+{
+ FILE *fSlab;
+ struct slab_cache *slabs;
+ unsigned long nSlab, i, j, k;
+ const char format[] = "%-24s %6u %6u %6u %6u\n";
+
+ fSlab = fopen("/proc/slabinfo", "rb");
+ if (!fSlab) {
+ warnx(_("Your kernel doesn't support slabinfo or your permissions are insufficient."));
+ return;
+ }
+
+ if (!moreheaders)
+ slabheader();
+ nSlab = getslabinfo(&slabs);
+ for (k = 0; k < nSlab; k++) {
+ if (moreheaders && ((k % height) == 0))
+ slabheader();
+ printf(format,
+ slabs[k].name,
+ slabs[k].active_objs,
+ slabs[k].num_objs,
+ slabs[k].objsize, slabs[k].objperslab);
+ }
+ free(slabs);
+ for (j = 1, k = 1; infinite_updates || j < num_updates; j++) {
+ sleep(sleep_time);
+ nSlab = getslabinfo(&slabs);
+ for (i = 0; i < nSlab; i++, k++) {
+ if (moreheaders && ((k % height) == 0))
+ slabheader();
+ printf(format,
+ slabs[i].name,
+ slabs[i].active_objs,
+ slabs[i].num_objs,
+ slabs[i].objsize, slabs[i].objperslab);
+ }
+ free(slabs);
+ }
+ free(fSlab);
}
-////////////////////////////////////////////////////////////////////////////
-
-static void sum_format(void) {
- unsigned int running, blocked, btime, processes;
- jiff cpu_use, cpu_nic, cpu_sys, cpu_idl, cpu_iow, cpu_xxx, cpu_yyy, cpu_zzz;
- unsigned long pgpgin, pgpgout, pswpin, pswpout;
- unsigned int intr, ctxt;
-
- meminfo();
-
- getstat(&cpu_use, &cpu_nic, &cpu_sys, &cpu_idl,
- &cpu_iow, &cpu_xxx, &cpu_yyy, &cpu_zzz,
- &pgpgin, &pgpgout, &pswpin, &pswpout,
- &intr, &ctxt,
- &running, &blocked,
- &btime, &processes);
-
- printf("%13lu %s total memory\n", unitConvert(kb_main_total),szDataUnit);
- printf("%13lu %s used memory\n", unitConvert(kb_main_used),szDataUnit);
- printf("%13lu %s active memory\n", unitConvert(kb_active),szDataUnit);
- printf("%13lu %s inactive memory\n", unitConvert(kb_inactive),szDataUnit);
- printf("%13lu %s free memory\n", unitConvert(kb_main_free),szDataUnit);
- printf("%13lu %s buffer memory\n", unitConvert(kb_main_buffers),szDataUnit);
- printf("%13lu %s swap cache\n", unitConvert(kb_main_cached),szDataUnit);
- printf("%13lu %s total swap\n", unitConvert(kb_swap_total),szDataUnit);
- printf("%13lu %s used swap\n", unitConvert(kb_swap_used),szDataUnit);
- printf("%13lu %s free swap\n", unitConvert(kb_swap_free),szDataUnit);
- printf("%13Lu non-nice user cpu ticks\n", cpu_use);
- printf("%13Lu nice user cpu ticks\n", cpu_nic);
- printf("%13Lu system cpu ticks\n", cpu_sys);
- printf("%13Lu idle cpu ticks\n", cpu_idl);
- printf("%13Lu IO-wait cpu ticks\n", cpu_iow);
- printf("%13Lu IRQ cpu ticks\n", cpu_xxx);
- printf("%13Lu softirq cpu ticks\n", cpu_yyy);
- printf("%13Lu stolen cpu ticks\n", cpu_zzz);
- printf("%13lu pages paged in\n", pgpgin);
- printf("%13lu pages paged out\n", pgpgout);
- printf("%13lu pages swapped in\n", pswpin);
- printf("%13lu pages swapped out\n", pswpout);
- printf("%13u interrupts\n", intr);
- printf("%13u CPU context switches\n", ctxt);
- printf("%13u boot time\n", btime);
- printf("%13u forks\n", processes);
+static void disksum_format(void)
+{
+
+ FILE *fDiskstat;
+ struct disk_stat *disks;
+ struct partition_stat *partitions;
+ int ndisks, i;
+ unsigned long reads, merged_reads, read_sectors, milli_reading, writes,
+ merged_writes, written_sectors, milli_writing, inprogress_IO,
+ milli_spent_IO, weighted_milli_spent_IO;
+
+ reads = merged_reads = read_sectors = milli_reading = writes =
+ merged_writes = written_sectors = milli_writing = inprogress_IO =
+ milli_spent_IO = weighted_milli_spent_IO = 0;
+
+ if ((fDiskstat = fopen("/proc/diskstats", "rb"))) {
+ fclose(fDiskstat);
+ ndisks = getdiskstat(&disks, &partitions);
+ printf(_("%13d disks \n"), ndisks);
+ printf(_("%13d partitions \n"),
+ getpartitions_num(disks, ndisks));
+
+ for (i = 0; i < ndisks; i++) {
+ reads += disks[i].reads;
+ merged_reads += disks[i].merged_reads;
+ read_sectors += disks[i].reads_sectors;
+ milli_reading += disks[i].milli_reading;
+ writes += disks[i].writes;
+ merged_writes += disks[i].merged_writes;
+ written_sectors += disks[i].written_sectors;
+ milli_writing += disks[i].milli_writing;
+ inprogress_IO += disks[i].inprogress_IO ? disks[i].inprogress_IO / 1000 : 0;
+ milli_spent_IO += disks[i].milli_spent_IO ? disks[i].milli_spent_IO / 1000 : 0;
+ }
+
+ printf(_("%13lu total reads\n"), reads);
+ printf(_("%13lu merged reads\n"), merged_reads);
+ printf(_("%13lu read sectors\n"), read_sectors);
+ printf(_("%13lu milli reading\n"), milli_reading);
+ printf(_("%13lu writes\n"), writes);
+ printf(_("%13lu merged writes\n"), merged_writes);
+ printf(_("%13lu written sectors\n"), written_sectors);
+ printf(_("%13lu milli writing\n"), milli_writing);
+ printf(_("%13lu inprogress IO\n"), inprogress_IO);
+ printf(_("%13lu milli spent IO\n"), milli_spent_IO);
+
+ free(disks);
+ free(partitions);
+ }
}
-////////////////////////////////////////////////////////////////////////////
+static void sum_format(void)
+{
+ unsigned int running, blocked, btime, processes;
+ jiff cpu_use, cpu_nic, cpu_sys, cpu_idl, cpu_iow, cpu_xxx, cpu_yyy, cpu_zzz;
+ unsigned long pgpgin, pgpgout, pswpin, pswpout;
+ unsigned int intr, ctxt;
+
+ meminfo();
+
+ getstat(&cpu_use, &cpu_nic, &cpu_sys, &cpu_idl,
+ &cpu_iow, &cpu_xxx, &cpu_yyy, &cpu_zzz,
+ &pgpgin, &pgpgout, &pswpin, &pswpout,
+ &intr, &ctxt, &running, &blocked, &btime, &processes);
+
+ printf(_("%13lu %s total memory\n"), unitConvert(kb_main_total), szDataUnit);
+ printf(_("%13lu %s used memory\n"), unitConvert(kb_main_used), szDataUnit);
+ printf(_("%13lu %s active memory\n"), unitConvert(kb_active), szDataUnit);
+ printf(_("%13lu %s inactive memory\n"), unitConvert(kb_inactive), szDataUnit);
+ printf(_("%13lu %s free memory\n"), unitConvert(kb_main_free), szDataUnit);
+ printf(_("%13lu %s buffer memory\n"), unitConvert(kb_main_buffers), szDataUnit);
+ printf(_("%13lu %s swap cache\n"), unitConvert(kb_main_cached), szDataUnit);
+ printf(_("%13lu %s total swap\n"), unitConvert(kb_swap_total), szDataUnit);
+ printf(_("%13lu %s used swap\n"), unitConvert(kb_swap_used), szDataUnit);
+ printf(_("%13lu %s free swap\n"), unitConvert(kb_swap_free), szDataUnit);
+ printf(_("%13Lu non-nice user cpu ticks\n"), cpu_use);
+ printf(_("%13Lu nice user cpu ticks\n"), cpu_nic);
+ printf(_("%13Lu system cpu ticks\n"), cpu_sys);
+ printf(_("%13Lu idle cpu ticks\n"), cpu_idl);
+ printf(_("%13Lu IO-wait cpu ticks\n"), cpu_iow);
+ printf(_("%13Lu IRQ cpu ticks\n"), cpu_xxx);
+ printf(_("%13Lu softirq cpu ticks\n"), cpu_yyy);
+ printf(_("%13Lu stolen cpu ticks\n"), cpu_zzz);
+ printf(_("%13lu pages paged in\n"), pgpgin);
+ printf(_("%13lu pages paged out\n"), pgpgout);
+ printf(_("%13lu pages swapped in\n"), pswpin);
+ printf(_("%13lu pages swapped out\n"), pswpout);
+ printf(_("%13u interrupts\n"), intr);
+ printf(_("%13u CPU context switches\n"), ctxt);
+ printf(_("%13u boot time\n"), btime);
+ printf(_("%13u forks\n"), processes);
+}
-static void fork_format(void) {
- unsigned int running, blocked, btime, processes;
- jiff cpu_use, cpu_nic, cpu_sys, cpu_idl, cpu_iow, cpu_xxx, cpu_yyy, cpu_zzz;
- unsigned long pgpgin, pgpgout, pswpin, pswpout;
- unsigned int intr, ctxt;
+static void fork_format(void)
+{
+ unsigned int running, blocked, btime, processes;
+ jiff cpu_use, cpu_nic, cpu_sys, cpu_idl, cpu_iow, cpu_xxx, cpu_yyy, cpu_zzz;
+ unsigned long pgpgin, pgpgout, pswpin, pswpout;
+ unsigned int intr, ctxt;
- getstat(&cpu_use, &cpu_nic, &cpu_sys, &cpu_idl,
- &cpu_iow, &cpu_xxx, &cpu_yyy, &cpu_zzz,
- &pgpgin, &pgpgout, &pswpin, &pswpout,
- &intr, &ctxt,
- &running, &blocked,
- &btime, &processes);
+ getstat(&cpu_use, &cpu_nic, &cpu_sys, &cpu_idl,
+ &cpu_iow, &cpu_xxx, &cpu_yyy, &cpu_zzz,
+ &pgpgin, &pgpgout, &pswpin, &pswpout,
+ &intr, &ctxt, &running, &blocked, &btime, &processes);
- printf("%13u forks\n", processes);
+ printf(_("%13u forks\n"), processes);
}
-////////////////////////////////////////////////////////////////////////////
+static int winhi(void)
+{
+ struct winsize win;
+ int rows = 24;
+
+ if (ioctl(1, TIOCGWINSZ, &win) != -1 && win.ws_row > 0)
+ rows = win.ws_row;
-static int winhi(void) {
- struct winsize win;
- int rows = 24;
-
- if (ioctl(1, TIOCGWINSZ, &win) != -1 && win.ws_row > 0)
- rows = win.ws_row;
-
- return rows;
+ return rows;
}
-////////////////////////////////////////////////////////////////////////////
-
-int main(int argc, char *argv[]) {
- char *partition = NULL;
- int c;
-
- while((c = getopt(argc, argv, "VdafmDnp:S:s")) != EOF) switch(c) {
- case 'V':
- display_version();
- exit(0);
- case 'd':
- statMode |= DISKSTAT;
- break;
- case 'a':
- /* active/inactive mode */
- a_option=1;
- break;
- case 'f':
- // FIXME: check for conflicting args
- fork_format();
- exit(0);
- case 'm':
- statMode |= SLABSTAT;
- break;
- case 'D':
- statMode |= DISKSUMSTAT;
- break;
- case 'n':
- /* print only one header */
- moreheaders=FALSE;
- break;
- case 'p':
- statMode |= PARTITIONSTAT;
- partition = optarg;
- if (memcmp(partition, "/dev/", 5) == 0) partition += 5;
- break;
- case 'S':
- switch(optarg[0]) {
- case 'b': case 'B': dataUnit = UNIT_B; break;
- case 'k': dataUnit = UNIT_k; break;
- case 'K': dataUnit = UNIT_K; break;
- case 'm': dataUnit = UNIT_m; break;
- case 'M': dataUnit = UNIT_M; break;
+int main(int argc, char *argv[])
+{
+ char *partition = NULL;
+ int c;
+ long tmp;
+
+ static const struct option longopts[] = {
+ {"active", no_argument, NULL, 'a'},
+ {"forks", no_argument, NULL, 'f'},
+ {"slabs", no_argument, NULL, 'm'},
+ {"one-header", no_argument, NULL, 'n'},
+ {"stats", no_argument, NULL, 's'},
+ {"disk", no_argument, NULL, 'd'},
+ {"disk-sum", no_argument, NULL, 'D'},
+ {"partition", required_argument, NULL, 'p'},
+ {"unit", required_argument, NULL, 'S'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'V'},
+ {NULL, 0, NULL, 0}
+ };
+
+ setlocale (LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ while ((c =
+ getopt_long(argc, argv, "afmnsdDp:S:hV", longopts,
+ NULL)) != EOF)
+ switch (c) {
+ case 'V':
+ printf(PROCPS_NG_VERSION);
+ return EXIT_SUCCESS;
+ case 'h':
+ usage(stdout);
+ case 'd':
+ statMode |= DISKSTAT;
+ break;
+ case 'a':
+ /* active/inactive mode */
+ a_option = 1;
+ break;
+ case 'f':
+ /* FIXME: check for conflicting args */
+ fork_format();
+ exit(0);
+ case 'm':
+ statMode |= SLABSTAT;
+ break;
+ case 'D':
+ statMode |= DISKSUMSTAT;
+ break;
+ case 'n':
+ /* print only one header */
+ moreheaders = FALSE;
+ break;
+ case 'p':
+ statMode |= PARTITIONSTAT;
+ partition = optarg;
+ if (memcmp(partition, "/dev/", 5) == 0)
+ partition += 5;
+ break;
+ case 'S':
+ switch (optarg[0]) {
+ case 'b':
+ case 'B':
+ dataUnit = UNIT_B;
+ break;
+ case 'k':
+ dataUnit = UNIT_k;
+ break;
+ case 'K':
+ dataUnit = UNIT_K;
+ break;
+ case 'm':
+ dataUnit = UNIT_m;
+ break;
+ case 'M':
+ dataUnit = UNIT_M;
+ break;
+ default:
+ errx(EXIT_FAILURE,
+ /* Translation Hint: do not change argument characters */
+ _("-S requires k, K, m or M (default is kb)"));
+ }
+ szDataUnit[0] = optarg[0];
+ break;
+ case 's':
+ statMode |= VMSUMSTAT;
+ break;
+ default:
+ /* no other aguments defined yet. */
+ usage(stderr);
+ }
+
+ if (optind < argc) {
+ tmp = strtol_or_err(argv[optind++], _("failed to parse argument"));
+ if (tmp < 1)
+ errx(EXIT_FAILURE, _("delay must be positive integer"));
+ else if (UINT_MAX < tmp)
+ errx(EXIT_FAILURE, _("too large delay value"));
+ sleep_time = tmp;
+ infinite_updates = 1;
+ }
+ if (optind < argc) {
+ num_updates = strtol_or_err(argv[optind++], _("failed to parse argument"));
+ infinite_updates = 0;
+ }
+ if (optind < argc)
+ usage(stderr);
+
+ if (moreheaders) {
+ int tmp = winhi() - 3;
+ height = ((tmp > 0) ? tmp : 22);
+ }
+ setlinebuf(stdout);
+ switch (statMode) {
+ case (VMSTAT):
+ new_format();
+ break;
+ case (VMSUMSTAT):
+ sum_format();
+ break;
+ case (DISKSTAT):
+ diskformat();
+ break;
+ case (PARTITIONSTAT):
+ if (diskpartition_format(partition) == -1)
+ printf(_("Partition was not found\n"));
+ break;
+ case (SLABSTAT):
+ slabformat();
+ break;
+ case (DISKSUMSTAT):
+ disksum_format();
+ break;
default:
- fprintf(stderr, "-S requires k, K, m or M (default is kb)\n");
- exit(EXIT_FAILURE);
+ usage(stderr);
+ break;
}
- szDataUnit[0] = optarg[0];
- break;
- case 's':
- statMode |= VMSUMSTAT;
- break;
- default:
- /* no other aguments defined yet. */
- usage();
- }
-
- if (optind < argc) {
- if ((sleep_time = atoi(argv[optind++])) == 0)
- usage();
- num_updates = ULONG_MAX;
- }
- if (optind < argc)
- num_updates = atol(argv[optind++]);
- if (optind < argc)
- usage();
-
- if (moreheaders) {
- int tmp=winhi()-3;
- height=((tmp>0)?tmp:22);
- }
- setlinebuf(stdout);
- switch(statMode){
- case(VMSTAT): new_format();
- break;
- case(VMSUMSTAT): sum_format();
- break;
- case(DISKSTAT): diskformat();
- break;
- case(PARTITIONSTAT): if(diskpartition_format(partition)==-1)
- printf("Partition was not found\n");
- break;
- case(SLABSTAT): slabformat();
- break;
- case(DISKSUMSTAT): disksum_format();
- break;
- default: usage();
- break;
- }
- return 0;
+ return 0;
}
-
-
diff --git a/w.1 b/w.1
index 4dca9b7..baeaf6c 100644
--- a/w.1
+++ b/w.1
@@ -1,74 +1,69 @@
.\" -*-Nroff-*-
.\"
-.TH W 1 "5 October 2009 " " " "Linux User's Manual"
+.TH W "1" "June 2011" "procps-ng" "User Commands"
.SH NAME
w \- Show who is logged on and what they are doing.
.SH SYNOPSIS
.B w
-.RB [ \-husfV- ]
-.RI [ user ]
+[\fIoptions\fR] \fIuser\fR [...]
.SH DESCRIPTION
.B w
-displays information about the users currently on the machine,
-and their processes.
-The header shows, in this order, the current time,
-how long the system has been running,
-how many users are currently logged on,
-and the system load averages for the past 1, 5, and 15 minutes.
-
-The following entries are displayed for each user:
-login name, the tty name, the remote host, login time, idle time, JCPU, PCPU,
-and the command line of their current process.
-
-The JCPU time is the time used by all processes attached to the tty. It
-does not include past background jobs, but does include currently
-running background jobs.
-
+displays information about the users currently on the machine, and their
+processes. The header shows, in this order, the current time, how long the
+system has been running, how many users are currently logged on, and the
+system load averages for the past 1, 5, and 15 minutes.
+.PP
+The following entries are displayed for each user: login name, the tty name,
+the remote host, login time, idle time, JCPU, PCPU, and the command line of
+their current process.
+.PP
+The JCPU time is the time used by all processes attached to the tty. It does
+not include past background jobs, but does include currently running
+background jobs.
+.PP
The PCPU time is the time used by the current process, named in the "what"
field.
-
-.PP
.SH "COMMAND\-LINE OPTIONS"
-.TP 0.5i
-.B "\-h "
+.TP
+\fB\-h\fR, \fB\-\-no\-header\fR
Don't print the header.
-.TP 0.5i
-.B "\-u "
-Ignores the username while figuring out the current process and cpu
-times. To demonstrate this, do a "su" and do a "w" and a "w \-u".
-.TP 0.5i
-.B "\-s "
-Use the short format.
-Don't print the login time, JCPU or PCPU times.
-.TP 0.5i
-.B "\-f "
+.TP
+\fB\-u\fR, \fB\-\-no\-current\fR
+Ignores the username while figuring out the
+current process and cpu times. To demonstrate this, do a "su" and do a "w"
+and a "w \-u".
+.TP
+\fB\-s\fR, \fB\-\-short\fR
+Use the short format. Don't print the login time, JCPU or PCPU times.
+.TP
+\fB\-f\fR, \fB\-\-from\fR
Toggle printing the
.B from
-(remote hostname) field. The default as
-released is for the
+(remote hostname) field. The default as released is for the
.B from
-field to not be printed, although your system administrator or
-distribution maintainer may have compiled a version in which the
+field to not be printed, although your system administrator or distribution
+maintainer may have compiled a version in which the
.B from
field is shown by default.
-.TP 0.5i
-.B "\-V "
+.TP
+\fB\-\-help\fR
+Display help text and exit.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
Display version information.
-.TP 0.5i
-.B "\-o "
-Old style output. Prints blank space for idle times less than one minute.
-.TP 0.5i
+.TP
+\fB\-o\fR, \fB\-\-old\-style\fR
+Old style output. Prints blank space for idle times less than one minute.
+.TP
.B "user "
Show information about the specified user only.
-
.SH ENVIRONMENT
.TP
PROCPS_USERLEN
-Override the default width of the username column. Defaults to 8.
+Override the default width of the username column. Defaults to 8.
.TP
PROCPS_FROMLEN
-Override the default width of the from column. Defaults to 16.
-
+Override the default width of the from column. Defaults to 16.
.SH FILES
.TP
.I /var/run/utmp
@@ -76,8 +71,6 @@ information about who is currently logged on
.TP
.I /proc
process information
-.PP
-
.SH "SEE ALSO"
.BR free (1),
.BR ps (1),
@@ -85,11 +78,17 @@ process information
.BR uptime (1),
.BR utmp (5),
.BR who (1)
-
.SH AUTHORS
.B w
-was re-written almost entirely by Charles Blake, based on the version by Larry
-Greenfield <greenfie@gauss.rutgers.edu> and Michael K. Johnson
-<johnsonm@redhat.com>.
-
-Please send bug reports to <procps@freelists.org>
+was re-written almost entirely by Charles Blake, based on the version by
+.UR greenfie\@\:gauss.\:rutgers.\:edu
+Larry Greenfield
+.UE
+and
+.UR johnsonm\@\:redhat.\:com
+Michael K. Johnson
+.UE
+.SH "REPORTING BUGS"
+Please send bug reports to
+.UR procps\@freelists.org
+.UE
diff --git a/w.c b/w.c
index c2fc466..9a1a2f4 100644
--- a/w.c
+++ b/w.c
@@ -1,20 +1,33 @@
-/* w - show what logged in users are doing. Almost entirely rewritten from
- * scratch by Charles Blake circa June 1996. Some vestigal traces of the
- * original may exist. That was done in 1993 by Larry Greenfield with some
- * fixes by Michael K. Johnson.
+/*
+ * w - show what logged in users are doing.
+ *
+ * Almost entirely rewritten from scratch by Charles Blake circa
+ * June 1996. Some vestigal traces of the original may exist.
+ * That was done in 1993 by Larry Greenfield with some fixes by
+ * Michael K. Johnson.
*
* Changes by Albert Cahalan, 2002.
*/
-#include "proc/version.h"
-#include "proc/whattime.h"
-#include "proc/readproc.h"
+
+#include "c.h"
+#include "nls.h"
#include "proc/devname.h"
+#include "proc/escape.h"
#include "proc/procps.h"
+#include "proc/readproc.h"
#include "proc/sysinfo.h"
-#include "proc/escape.h"
+#include "proc/version.h"
+#include "proc/whattime.h"
+
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
+#include <getopt.h>
+#include <limits.h>
+#include <locale.h>
+#include <locale.h>
+#include <pwd.h>
+#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -23,12 +36,10 @@
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <pwd.h>
+#include <termios.h>
#include <time.h>
#include <unistd.h>
#include <utmp.h>
-#include <locale.h>
-#include <termios.h>
static int ignoreuser = 0; /* for '-u' */
static int oldstyle = 0; /* for '-o' */
@@ -37,9 +48,9 @@ static proc_t **procs; /* our snapshot of the process table */
typedef struct utmp utmp_t;
#ifdef W_SHOWFROM
-# define FROM_STRING "on"
+# define FROM_STRING "on"
#else
-# define FROM_STRING "off"
+# define FROM_STRING "off"
#endif
/* Uh... same thing as UT_NAMESIZE */
@@ -49,297 +60,405 @@ typedef struct utmp utmp_t;
#define HOSTSZ 40
-/* This routine is careful since some programs leave utmp strings
- * unprintable. Always outputs at least fromlen chars padded with spaces
- * on the right if necessary.
+/*
+ * This routine is careful since some programs leave utmp strings
+ * unprintable. Always outputs at least 16 chars padded with
+ * spaces on the right if necessary.
*/
-static void print_host(const char *restrict host, int len, const int fromlen) {
- const char *last;
- int width = 0;
-
- if (len > fromlen) len = fromlen;
- last = host + len;
- for ( ; host < last ; host++){
- if (isprint(*host) && *host != ' ') {
- fputc(*host, stdout);
- ++width;
- } else {
- break;
+static void print_host(const char *restrict host, int len, const int fromlen)
+{
+ const char *last;
+ int width = 0;
+
+ if (len > fromlen)
+ len = fromlen;
+ last = host + len;
+ for (; host < last; host++) {
+ if (isprint(*host) && *host != ' ') {
+ fputc(*host, stdout);
+ ++width;
+ } else {
+ break;
+ }
}
- }
- // space-fill, and a '-' too if needed to ensure the column exists
- while(width++ < fromlen)
- fputc(' ',stdout);
-}
-/***** compact 7 char format for time intervals (belongs in libproc?) */
-static void print_time_ival7(time_t t, int centi_sec, FILE* fout) {
- if((long)t < (long)0){ /* system clock changed? */
- printf(" ? ");
- return;
- }
- if (oldstyle) {
- if (t >= 48*60*60) /* > 2 days */
- fprintf(fout, " %2ludays", t/(24*60*60));
- else if (t >= 60*60) /* > 1 hour */
- fprintf(fout, " %2lu:%02u ", t/(60*60), (unsigned) ((t/60)%60));
- else if (t > 60) /* > 1 minute */
- fprintf(fout, " %2lu:%02um", t/60, (unsigned) t%60);
- else
- fprintf(fout, " ");
- } else {
- if (t >= 48*60*60) /* > 2 days */
- fprintf(fout, " %2ludays", t/(24*60*60));
- else if (t >= 60*60) /* > 1 hour */
- fprintf(fout, " %2lu:%02um", t/(60*60), (unsigned) ((t/60)%60));
- else if (t > 60) /* > 1 minute */
- fprintf(fout, " %2lu:%02u ", t/60, (unsigned) t%60);
- else
- fprintf(fout, " %2lu.%02us", t, centi_sec);
- }
+ /*
+ * space-fill, and a '-' too if needed to ensure the
+ * column exists
+ */
+ while (width++ < fromlen)
+ fputc(' ', stdout);
}
-/**** stat the device file to get an idle time */
-static time_t idletime(const char *restrict const tty) {
- struct stat sbuf;
- if (stat(tty, &sbuf) != 0)
- return 0;
- return time(NULL) - sbuf.st_atime;
+/* compact 7 char format for time intervals (belongs in libproc?) */
+static void print_time_ival7(time_t t, int centi_sec, FILE * fout)
+{
+ if ((long)t < (long)0) {
+ /* system clock changed? */
+ printf(" ? ");
+ return;
+ }
+ if (oldstyle) {
+ if (t >= 48 * 60 * 60)
+ /* > 2 days */
+ fprintf(fout, _(" %2ludays"), t / (24 * 60 * 60));
+ else if (t >= 60 * 60)
+ /* > 1 hour */
+ fprintf(fout, " %2lu:%02u ", t / (60 * 60),
+ (unsigned)((t / 60) % 60));
+ else if (t > 60)
+ /* > 1 minute */
+ fprintf(fout, _(" %2lu:%02um"), t / 60, (unsigned)t % 60);
+ else
+ fprintf(fout, " ");
+ } else {
+ if (t >= 48 * 60 * 60)
+ /* 2 days or more */
+ fprintf(fout, _(" %2ludays"), t / (24 * 60 * 60));
+ else if (t >= 60 * 60)
+ /* 1 hour or more */
+ fprintf(fout, _(" %2lu:%02um"), t / (60 * 60),
+ (unsigned)((t / 60) % 60));
+ else if (t > 60)
+ /* 1 minute or more */
+ fprintf(fout, " %2lu:%02u ", t / 60, (unsigned)t % 60);
+ else
+ fprintf(fout, _(" %2lu.%02us"), t, centi_sec);
+ }
}
-/***** 7 character formatted login time */
-static void print_logintime(time_t logt, FILE* fout) {
- char weekday[][4] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" },
- month [][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
- "Aug", "Sep", "Oct", "Nov", "Dec" };
- time_t curt;
- struct tm *logtm, *curtm;
- int today;
-
- curt = time(NULL);
- curtm = localtime(&curt);
- /* localtime returns a pointer to static memory */
- today = curtm->tm_yday;
- logtm = localtime(&logt);
- if (curt - logt > 12*60*60 && logtm->tm_yday != today) {
- if (curt - logt > 6*24*60*60)
- fprintf(fout, " %02d%3s%02d", logtm->tm_mday, month[logtm->tm_mon],
- logtm->tm_year % 100);
- else
- fprintf(fout, " %3s%02d ", weekday[logtm->tm_wday], logtm->tm_hour);
- } else {
- fprintf(fout, " %02d:%02d ", logtm->tm_hour, logtm->tm_min);
- }
+/* stat the device file to get an idle time */
+static time_t idletime(const char *restrict const tty)
+{
+ struct stat sbuf;
+ if (stat(tty, &sbuf) != 0)
+ return 0;
+ return time(NULL) - sbuf.st_atime;
}
+/* 7 character formatted login time */
+
+static void print_logintime(time_t logt, FILE * fout)
+{
+ /* FIXME: make use of locale, remember strftime() */
+ char weekday[][4] = {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+ };
+ char month[][4] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
+ "Sep", "Oct", "Nov", "Dec"
+ };
+ time_t curt;
+ struct tm *logtm, *curtm;
+ int today;
-/* This function scans the process table accumulating total cpu times for
- * any processes "associated" with this login session. It also searches
- * for the "best" process to report as "(w)hat" the user for that login
- * session is doing currently. This the essential core of 'w'.
+ curt = time(NULL);
+ curtm = localtime(&curt);
+ /* localtime returns a pointer to static memory */
+ today = curtm->tm_yday;
+ logtm = localtime(&logt);
+ if (curt - logt > 12 * 60 * 60 && logtm->tm_yday != today) {
+ if (curt - logt > 6 * 24 * 60 * 60)
+ fprintf(fout, " %02d%3s%02d", logtm->tm_mday,
+ month[logtm->tm_mon], logtm->tm_year % 100);
+ else
+ fprintf(fout, " %3s%02d ", weekday[logtm->tm_wday],
+ logtm->tm_hour);
+ } else {
+ fprintf(fout, " %02d:%02d ", logtm->tm_hour, logtm->tm_min);
+ }
+}
+
+/*
+ * This function scans the process table accumulating total cpu
+ * times for any processes "associated" with this login session.
+ * It also searches for the "best" process to report as "(w)hat"
+ * the user for that login session is doing currently. This the
+ * essential core of 'w'.
*/
-static const proc_t *getproc(const utmp_t *restrict const u, const char *restrict const tty, unsigned long long *restrict const jcpu, int *restrict const found_utpid) {
- int line;
- proc_t **pptr = procs;
- const proc_t *best = NULL;
- const proc_t *secondbest = NULL;
- unsigned uid = ~0U;
-
- *found_utpid = 0;
- if(!ignoreuser){
- char buf[UT_NAMESIZE+1];
- struct passwd *passwd_data; /* pointer to static data */
- strncpy(buf,u->ut_user,UT_NAMESIZE);
- buf[UT_NAMESIZE] = '\0';
- passwd_data = getpwnam(buf);
- if(!passwd_data) return NULL;
- uid = passwd_data->pw_uid;
- /* OK to have passwd_data go out of scope here */
- }
- line = tty_to_dev(tty);
- *jcpu = 0;
- for(; *pptr; pptr++) {
- const proc_t *restrict const tmp = *pptr;
- if(unlikely(tmp->tgid == u->ut_pid)) {
- *found_utpid = 1;
- best = tmp;
+static const proc_t *getproc(const utmp_t * restrict const u,
+ const char *restrict const tty,
+ unsigned long long *restrict const jcpu,
+ int *restrict const found_utpid)
+{
+ int line;
+ proc_t **pptr = procs;
+ const proc_t *best = NULL;
+ const proc_t *secondbest = NULL;
+ unsigned uid = ~0U;
+
+ *found_utpid = 0;
+ if (!ignoreuser) {
+ char buf[UT_NAMESIZE + 1];
+ /* pointer to static data */
+ struct passwd *passwd_data;
+ strncpy(buf, u->ut_user, UT_NAMESIZE);
+ buf[UT_NAMESIZE] = '\0';
+ passwd_data = getpwnam(buf);
+ if (!passwd_data)
+ return NULL;
+ uid = passwd_data->pw_uid;
+ /* OK to have passwd_data go out of scope here */
}
- if(tmp->tty != line) continue;
- (*jcpu) += tmp->utime + tmp->stime;
- secondbest = tmp;
- /* same time-logic here as for "best" below */
- if(! (secondbest && tmp->start_time <= secondbest->start_time) ){
- secondbest = tmp;
+ line = tty_to_dev(tty);
+ *jcpu = 0;
+ for (; *pptr; pptr++) {
+ const proc_t *restrict const tmp = *pptr;
+ if (unlikely(tmp->tgid == u->ut_pid)) {
+ *found_utpid = 1;
+ best = tmp;
+ }
+ if (tmp->tty != line)
+ continue;
+ (*jcpu) += tmp->utime + tmp->stime;
+ secondbest = tmp;
+ /* same time-logic here as for "best" below */
+ if (!(secondbest && tmp->start_time <= secondbest->start_time)) {
+ secondbest = tmp;
+ }
+ if (!ignoreuser && uid != tmp->euid && uid != tmp->ruid)
+ continue;
+ if (tmp->pgrp != tmp->tpgid)
+ continue;
+ if (best && tmp->start_time <= best->start_time)
+ continue;
+ best = tmp;
}
- if(!ignoreuser && uid != tmp->euid && uid != tmp->ruid) continue;
- if(tmp->pgrp != tmp->tpgid) continue;
- if(best && tmp->start_time <= best->start_time) continue;
- best = tmp;
- }
- return best ? best : secondbest;
+ return best ? best : secondbest;
}
+static void showinfo(utmp_t * u, int formtype, int maxcmd, int from,
+ const int userlen, const int fromlen)
+{
+ unsigned long long jcpu;
+ int ut_pid_found;
+ unsigned i;
+ char uname[USERSZ + 1] = "", tty[5 + sizeof u->ut_line + 1] = "/dev/";
+ const proc_t *best;
-/***** showinfo */
-static void showinfo(utmp_t *u, int formtype, int maxcmd, int from, const int userlen, const int fromlen) {
- unsigned long long jcpu;
- int ut_pid_found;
- unsigned i;
- char uname[USERSZ + 1] = "",
- tty[5 + sizeof u->ut_line + 1] = "/dev/";
- const proc_t *best;
+ for (i = 0; i < sizeof(u->ut_line); i++)
+ /* clean up tty if garbled */
+ if (isalnum(u->ut_line[i]) || (u->ut_line[i] == '/'))
+ tty[i + 5] = u->ut_line[i];
+ else
+ tty[i + 5] = '\0';
- for (i=0; i < sizeof(u->ut_line); i++) /* clean up tty if garbled */
- if (isalnum(u->ut_line[i]) || (u->ut_line[i]=='/'))
- tty[i+5] = u->ut_line[i];
- else
- tty[i+5] = '\0';
-
- best = getproc(u, tty + 5, &jcpu, &ut_pid_found);
-
- /* just skip if stale utmp entry (i.e. login proc doesn't exist). If there
- * is a desire a cmdline flag could be added to optionally show it with a
- * prefix of (stale) in front of cmd or something like that.
- */
- if (!ut_pid_found)
- return;
-
- strncpy(uname, u->ut_user, USERSZ); /* force NUL term for printf */
- if (formtype) {
- printf("%-*.*s%-9.8s", userlen+1, userlen, uname, u->ut_line);
- if (from)
- print_host(u->ut_host, sizeof u->ut_host, fromlen);
- print_logintime(u->ut_time, stdout);
- if (*u->ut_line == ':') /* idle unknown for xdm logins */
- printf(" ?xdm? ");
- else
- print_time_ival7(idletime(tty), 0, stdout);
- print_time_ival7(jcpu/Hertz, (jcpu%Hertz)*(100./Hertz), stdout);
- if (best) {
- unsigned long long pcpu = best->utime + best->stime;
- print_time_ival7(pcpu/Hertz, (pcpu%Hertz)*(100./Hertz), stdout);
- } else
- printf(" ? ");
- } else {
- printf("%-*.*s%-9.8s", userlen+1, userlen, u->ut_user, u->ut_line);
- if (from)
- print_host(u->ut_host, sizeof u->ut_host, fromlen);
- if (*u->ut_line == ':') /* idle unknown for xdm logins */
- printf(" ?xdm? ");
- else
- print_time_ival7(idletime(tty), 0, stdout);
- }
- fputs(" ", stdout);
- if (likely(best)) {
- char cmdbuf[512];
- escape_command(cmdbuf, best, sizeof cmdbuf, &maxcmd, ESC_ARGS);
- fputs(cmdbuf,stdout);
- } else {
- printf("-");
- }
- fputc('\n', stdout);
+ best = getproc(u, tty + 5, &jcpu, &ut_pid_found);
+
+ /*
+ * just skip if stale utmp entry (i.e. login proc doesn't
+ * exist). If there is a desire a cmdline flag could be
+ * added to optionally show it with a prefix of (stale)
+ * in front of cmd or something like that.
+ */
+ if (!ut_pid_found)
+ return;
+
+ /* force NUL term for printf */
+ strncpy(uname, u->ut_user, USERSZ);
+
+ if (formtype) {
+ printf("%-*.*s%-9.8s", userlen + 1, userlen, uname, u->ut_line);
+ if (from)
+ print_host(u->ut_host, sizeof u->ut_host, fromlen);
+ print_logintime(u->ut_time, stdout);
+ if (*u->ut_line == ':')
+ /* idle unknown for xdm logins */
+ printf(" ?xdm? ");
+ else
+ print_time_ival7(idletime(tty), 0, stdout);
+ print_time_ival7(jcpu / Hertz, (jcpu % Hertz) * (100. / Hertz),
+ stdout);
+ if (best) {
+ unsigned long long pcpu = best->utime + best->stime;
+ print_time_ival7(pcpu / Hertz,
+ (pcpu % Hertz) * (100. / Hertz),
+ stdout);
+ } else
+ printf(" ? ");
+ } else {
+ printf("%-*.*s%-9.8s", userlen + 1, userlen, u->ut_user,
+ u->ut_line);
+ if (from)
+ print_host(u->ut_host, sizeof u->ut_host, fromlen);
+ if (*u->ut_line == ':')
+ /* idle unknown for xdm logins */
+ printf(" ?xdm? ");
+ else
+ print_time_ival7(idletime(tty), 0, stdout);
+ }
+ fputs(" ", stdout);
+ if (likely(best)) {
+ char cmdbuf[512];
+ escape_command(cmdbuf, best, sizeof cmdbuf, &maxcmd, ESC_ARGS);
+ fputs(cmdbuf, stdout);
+ } else {
+ printf("-");
+ }
+ fputc('\n', stdout);
+}
+
+static void __attribute__ ((__noreturn__))
+ usage(FILE * out)
+{
+ fputs(USAGE_HEADER, out);
+ fprintf(out,
+ _(" %s [options]\n"), program_invocation_short_name);
+ fputs(USAGE_OPTIONS, out);
+ fputs(_(" -h, --no-header do not print header\n"), out);
+ fputs(_(" -u, --no-current ignore current process username\n"), out);
+ fputs(_(" -s, --short short format\n"), out);
+ fputs(_(" -f, --from show remote hostname field\n"), out);
+ fputs(_(" -o, --old-style old style output\n"), out);
+ fputs(USAGE_SEPARATOR, out);
+ fputs(_(" --help display this help and exit\n"), out);
+ fputs(USAGE_VERSION, out);
+ fprintf(out, USAGE_MAN_TAIL("w(1)"));
+
+ exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
-/***** main */
-int main(int argc, char **argv) {
- char *user = NULL, *p;
- utmp_t *u;
- struct winsize win;
- int header=1, longform=1, from=1, args, maxcmd=80, ch;
- int userlen = 8;
- int fromlen = 16;
- char *env_var;
+int main(int argc, char **argv)
+{
+ char *user = NULL, *p;
+ utmp_t *u;
+ struct winsize win;
+ int header = 1, longform = 1, from = 1, args, maxcmd = 80, ch;
+ int userlen = 8;
+ int fromlen = 16;
+ char *env_var;
+
+ enum {
+ HELP_OPTION = CHAR_MAX + 1
+ };
+
+ static const struct option longopts[] = {
+ {"no-header", no_argument, NULL, 'h'},
+ {"no-current", no_argument, NULL, 'u'},
+ {"sort", no_argument, NULL, 's'},
+ {"from", no_argument, NULL, 'f'},
+ {"old-style", no_argument, NULL, 'o'},
+ {"help", no_argument, NULL, HELP_OPTION},
+ {"version", no_argument, NULL, 'V'},
+ {NULL, 0, NULL, 0}
+ };
+
+ setlocale (LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
#ifndef W_SHOWFROM
- from = 0;
+ from = 0;
#endif
- setlocale(LC_ALL, "");
- for (args=0; (ch = getopt(argc, argv, "hlusfVo")) != EOF; args++)
- switch (ch) {
- case 'h': header = 0; break;
- case 'l': longform = 1; break;
- case 's': longform = 0; break;
- case 'f': from = !from; break;
- case 'V': display_version(); exit(0);
- case 'u': ignoreuser = 1; break;
- case 'o': oldstyle = 1; break;
- default:
- printf("usage: w -hlsufV [user]\n"
- " -h skip header\n"
- " -l long listing (default)\n"
- " -s short listing\n"
- " -u ignore uid of processes\n"
- " -f toggle FROM field (default %s)\n"
- " -o old-style output\n"
- " -V display version\n", FROM_STRING);
- exit(1);
- }
+ while ((ch =
+ getopt_long(argc, argv, "hlusfV", longopts, NULL)) != -1)
+ switch (ch) {
+ case 'h':
+ header = 0;
+ break;
+ case 'l':
+ longform = 1;
+ break;
+ case 's':
+ longform = 0;
+ break;
+ case 'f':
+ from = !from;
+ break;
+ case 'V':
+ printf(PROCPS_NG_VERSION);
+ exit(0);
+ case 'u':
+ ignoreuser = 1;
+ break;
+ case 'o':
+ oldstyle = 1;
+ break;
+ case HELP_OPTION:
+ usage(stdout);
+ default:
+ usage(stderr);
+ }
- if ((argv[optind]))
- user = (argv[optind]);
+ if ((argv[optind]))
+ user = (argv[optind]);
/* Get user field length from environment */
- if ( (env_var = getenv("PROCPS_USERLEN")) != NULL) {
- userlen = atoi(env_var);
- if (userlen < 8 || userlen > USERSZ) {
- fprintf(stderr, "User length environment PROCPS_USERLEN must be between 8 and %d, ignoring.\n", USERSZ);
- userlen=8;
- }
+ if ((env_var = getenv("PROCPS_USERLEN")) != NULL) {
+ userlen = atoi(env_var);
+ if (userlen < 8 || userlen > USERSZ) {
+ warnx
+ (_("User length environment PROCPS_USERLEN must be between 8 and %d, ignoring.\n"),
+ USERSZ);
+ userlen = 8;
+ }
}
/* Get from field length from environment */
- if ( (env_var = getenv("PROCPS_FROMLEN")) != NULL) {
- fromlen = atoi(env_var);
- if (fromlen < 8 || fromlen > HOSTSZ) {
- fprintf(stderr, "From length environment PROCPS_FROMLEN must be between 8 and %d, ignoring.\n", HOSTSZ);
- fromlen=16;
- }
+ if ((env_var = getenv("PROCPS_FROMLEN")) != NULL) {
+ fromlen = atoi(env_var);
+ if (fromlen < 8 || fromlen > HOSTSZ) {
+ warnx
+ (_("From length environment PROCPS_FROMLEN must be between 8 and %d, ignoring.\n"),
+ HOSTSZ);
+ fromlen = 16;
+ }
}
- if (ioctl(1, TIOCGWINSZ, &win) != -1 && win.ws_col > 0)
- maxcmd = win.ws_col;
- else if (p = getenv("COLUMNS"))
- maxcmd = atoi(p);
- else
- maxcmd = 80;
- if (maxcmd < 71) {
- fprintf(stderr, "%d column window is too narrow\n", maxcmd);
- exit(1);
- }
- maxcmd -= 21 + userlen + (from ? fromlen : 0) + (longform ? 20 : 0);
- if (maxcmd < 3)
- fprintf(stderr, "warning: screen width %d suboptimal.\n", win.ws_col);
-
- procs = readproctab(PROC_FILLCOM | PROC_FILLUSR | PROC_FILLSTAT);
-
- if (header) { /* print uptime and headers */
- print_uptime();
- printf("%-*s TTY ",userlen,"USER");
- if (from)
- printf("FROM ");
- if (longform)
- printf(" LOGIN@ IDLE JCPU PCPU WHAT\n");
+ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) != -1 && win.ws_col > 0)
+ maxcmd = win.ws_col;
+ else if (p = getenv("COLUMNS"))
+ maxcmd = atoi(p);
else
- printf(" IDLE WHAT\n");
- }
-
- utmpname(UTMP_FILE);
- setutent();
- if (user) {
- for (;;) {
- u = getutent();
- if (unlikely(!u)) break;
- if (u->ut_type != USER_PROCESS) continue;
- if (!strncmp(u->ut_user, user, USERSZ)) showinfo(u, longform, maxcmd, from, userlen, fromlen);
+ maxcmd = 80;
+ if (maxcmd < 71)
+ errx(EXIT_FAILURE, _("%d column window is too narrow"), maxcmd);
+
+ maxcmd -= 21 + userlen + (from ? fromlen : 0) + (longform ? 20 : 0);
+ if (maxcmd < 3)
+ warnx(_("warning: screen width %d suboptimal"), win.ws_col);
+
+ procs = readproctab(PROC_FILLCOM | PROC_FILLUSR | PROC_FILLSTAT);
+
+ if (header) {
+ /* print uptime and headers */
+ print_uptime();
+ /* Translation Hint: Following five uppercase messages are
+ * headers. Try to keep alignment intact. */
+ printf(_("%-*s TTY "), userlen, _("USER"));
+ if (from)
+ printf(_("FROM "));
+ if (longform)
+ printf(_(" LOGIN@ IDLE JCPU PCPU WHAT\n"));
+ else
+ printf(_(" IDLE WHAT\n"));
}
- } else {
- for (;;) {
- u = getutent();
- if (unlikely(!u)) break;
- if (u->ut_type != USER_PROCESS) continue;
- if (*u->ut_user) showinfo(u, longform, maxcmd, from, userlen, fromlen);
+
+ utmpname(UTMP_FILE);
+ setutent();
+ if (user) {
+ for (;;) {
+ u = getutent();
+ if (unlikely(!u))
+ break;
+ if (u->ut_type != USER_PROCESS)
+ continue;
+ if (!strncmp(u->ut_user, user, USERSZ))
+ showinfo(u, longform, maxcmd, from, userlen,
+ fromlen);
+ }
+ } else {
+ for (;;) {
+ u = getutent();
+ if (unlikely(!u))
+ break;
+ if (u->ut_type != USER_PROCESS)
+ continue;
+ if (*u->ut_user)
+ showinfo(u, longform, maxcmd, from, userlen,
+ fromlen);
+ }
}
- }
- endutent();
+ endutent();
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/watch.1 b/watch.1
index aecbfeb..ac81f46 100644
--- a/watch.1
+++ b/watch.1
@@ -1,42 +1,29 @@
-.TH WATCH 1 "2010 Mar 01" " " "Linux User's Manual"
+.TH WATCH "1" "June 2011" "procps-ng" "User Commands"
.SH NAME
watch \- execute a program periodically, showing output fullscreen
.SH SYNOPSIS
-.na
.B watch
-.RB [ \-bdehpvtx ]
-.RB [ \-n
-.IR seconds ]
-.RB [ \-\-beep ]
-.RB [ \-\-color ]
-.RB [ \-\-differences[=\fIcumulative\fP]]
-.RB [ \-\-errexit ]
-.RB [ \-\-exec ]
-.RB [ \-\-help ]
-.RB [ \-\-interval=\fIseconds\fP]
-.RB [ \-\-no\-title ]
-.RB [ \-\-precise ]
-.RB [ \-\-version ]
-.I command
+[\fIoptions\fR] \fIcommand\fR
.SH DESCRIPTION
.B watch
runs
.I command
repeatedly, displaying its output and errors (the first screenfull). This
-allows you to
-watch the program output change over time. By default, the program is run
-every 2 seconds; use
-.B \-n
-or
-.B \-\-interval
-to specify a different interval. Normally, this interval is interpreted
-as the amout of time between the completion of one run of
-.I command
-and the beginning of the next run. However, with the
-.I \-p
-or
-.I \-\-precise
-option, you can make
+allows you to watch the program output change over time. By default, the
+program is run every 2 seconds.
+.B watch
+will run until interrupted.
+.SH OPTIONS
+.TP
+\fB\-f\fR, \fB\-\-differences\fR
+Highlight the differences between successive updates.
+.TP
+\fB\-n\fR, \fB\-\-interval\fR \fIseconds\fR
+Specify update interval. The command will not allow quicker than 0.1 second
+interval, in which the smaller values are converted.
+.TP
+\fB\-p\fR, \fB\-\-precise\fR
+Make
.BR watch
attempt to run
.I command
@@ -44,54 +31,37 @@ every
.I interval
seconds. Try it with
.B ntptime
-and notice how the fractional seconds stays
-(nearly) the same, as opposed to normal mode where they continuously
-increase.
-.PP
-The
-.B \-d
-or
-.B \-\-differences
-flag will highlight the differences between successive updates. Using
-.B \-\-differences=\fIcumulative\fP
-makes highlighting "sticky", presenting a running display of all
-positions that have ever changed. The
-.B \-t
-or
-.B \-\-no\-title
-option turns off the header showing the interval, command, and current
-time at the top of the display, as well as the following blank line. The
-.I \-b
-or
-.I \-\-beep
-option causes the command to beep if it has a non-zero exit.
-.PP
-.B watch
-will normally run until interrupted. If you want
-.B watch
-to exit on an error from the program running use the
-.I \-e
-or
-.I \-\-errexit
-options, which will cause
-.B watch
-to exit if the return value from the program is non-zero.
-.PP
-By default \fBwatch\fR will normally not pass escape characters, however
-if you use the \fI\-\-c\fR or \fI\-\-color\fR option, then
-\fBwatch\fR will interpret ANSI color sequences for the foreground.
-
-.SH NOTE
-Note that
+and notice how the fractional seconds stays (nearly) the same, as opposed to
+normal mode where they continuously increase.
+.TP
+\fB\-t\fR, \fB\-\-no\-title\fR
+Turn off the header showing the interval, command, and current time at the
+top of the display, as well as the following blank line.
+.TP
+\fB\-b\fR, \fB\-\-beep\fR
+Beep if command has a non-zero exit.
+.TP
+\fB\-e\fR, \fB\-\-errexit\fR
+Exit on a command error.
+.TP
+\fB\-c\fR, \fB\-\-color\fR
+Interpret ANSI color sequences.
+.TP
+\fB\-x\fR, \fB\-\-exec\fR
.I command
-is given to "sh \-c"
+is given to
+.B sh \-c
which means that you may need to use extra quoting to get the desired effect.
-You can disable this with the
-.I -x
-or
-.I --exec
-option, which passes the command to exec(2) instead.
-.PP
+This with the \-\-exec option, which passes the command to
+.BR exec (2)
+instead.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Display help text and exit.
+.TP
+\fB\-v\fR, \fB\-\-version\fR
+Display version information and exit.
+.SH NOTE
Note that POSIX option processing is used (i.e., option processing stops at
the first non\-option argument). This means that flags after
.I command
@@ -108,7 +78,7 @@ To watch the contents of a directory change, you could use
.IP
watch \-d ls \-l
.PP
-If you're only interested in files owned by user joe, you might use
+If you're only interested in files owned by user joe, you might use
.IP
watch \-d 'ls \-l | fgrep joe'
.PP
@@ -150,14 +120,14 @@ display at all.
.PP
Combining Characters never count as different in
.I \-\-differences
-mode. Only the base character counts.
+mode. Only the base character counts.
.PP
Blank lines directly after a line which ends in the last column do not
display.
.PP
.I \-\-precise
-mode doesn't yet have advanced temporal distortion technology to
-compensate for a
+mode doesn't yet have advanced temporal distortion technology to compensate
+for a
.I command
that takes more than
.I interval
@@ -173,12 +143,26 @@ taking ages on a DNS lookup).
.SH AUTHORS
The original
.B watch
-was written by Tony Rems <rembo@unisoft.com> in 1991, with mods and
+was written by
+.UR rembo\@\:unisoft.\:com
+Tony Rems
+.UE
+in 1991, with mods and
corrections by Francois Pinard. It was reworked and new features added by
-Mike Coleman <mkc@acm.org> in 1999. The beep, exec, and error handling
-features were added by Morty Abzug <morty@frakir.org> in 2008.
-On a not so dark and stormy morning
-in March of 2003, Anthony DeRobertis <asd@suespammers.org> got sick of
-his watches that should update every minute eventually updating many
-seconds after the minute started, and added microsecond precision.
-Unicode support was added in 2009 by Jarrod Lowe <procps@rrod.net>.
+.UR mkc\@\:acm.\:org
+Mike Coleman
+.UE
+in 1999. The beep, exec, and error handling features were added by
+.UR morty\@\:frakir.\:org
+Morty Abzug
+.UE
+in 2008. On a not so dark and stormy morning in March of 2003,
+.UR asd\@\:suespammers.\:org
+Anthony DeRobertis
+.UE
+got sick of his watches that should update every minute eventually updating
+many seconds after the minute started, and added microsecond precision.
+Unicode support was added in 2009 by
+.UR procps\@\:rrod.\:net
+Jarrod Lowe
+.UE
diff --git a/watch.c b/watch.c
index a20ea4c..8fb05b1 100644
--- a/watch.c
+++ b/watch.c
@@ -1,149 +1,151 @@
-/* watch -- execute a program repeatedly, displaying output fullscreen
+/*
+ * watch -- execute a program repeatedly, displaying output fullscreen
*
* Based on the original 1991 'watch' by Tony Rems <rembo@unisoft.com>
* (with mods and corrections by Francois Pinard).
*
* Substantially reworked, new features (differences option, SIGWINCH
- * handling, unlimited command length, long line handling) added Apr 1999 by
- * Mike Coleman <mkc@acm.org>.
+ * handling, unlimited command length, long line handling) added Apr
+ * 1999 by Mike Coleman <mkc@acm.org>.
*
* Changes by Albert Cahalan, 2002-2003.
* stderr handling, exec, and beep option added by Morty Abzug, 2008
* Unicode Support added by Jarrod Lowe <procps@rrod.net> in 2009.
*/
+#include "c.h"
#include "config.h"
+#include "nls.h"
+#include "proc/procps.h"
+#include "xalloc.h"
#include <ctype.h>
+#include <errno.h>
+#include <errno.h>
#include <getopt.h>
+#include <locale.h>
+#include <locale.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/time.h>
+#include <termios.h>
+#include <termios.h>
#include <time.h>
#include <unistd.h>
-#include <termios.h>
-#include <locale.h>
-#include "proc/procps.h"
-#include <errno.h>
#ifdef WITH_WATCH8BIT
-#include <wchar.h>
-#include <ncursesw/ncurses.h>
-#else
-#include <ncurses.h>
-#endif /* WITH_WATCH8BIT */
+# include <wchar.h>
+# include <ncursesw/ncurses.h>
+#else
+# include <ncurses.h>
+#endif /* WITH_WATCH8BIT */
#ifdef FORCE_8BIT
-#undef isprint
-#define isprint(x) ( (x>=' '&&x<='~') || (x>=0xa0) )
+# undef isprint
+# define isprint(x) ( (x>=' '&&x<='~') || (x>=0xa0) )
#endif
-static struct option longopts[] = {
- {"color", no_argument, 0, 'c' },
- {"differences", optional_argument, 0, 'd'},
- {"help", no_argument, 0, 'h'},
- {"interval", required_argument, 0, 'n'},
- {"beep", no_argument, 0, 'b'},
- {"errexit", no_argument, 0, 'e'},
- {"exec", no_argument, 0, 'x'},
- {"precise", no_argument, 0, 'p'},
- {"no-title", no_argument, 0, 't'},
- {"version", no_argument, 0, 'v'},
- {0, 0, 0, 0}
-};
-
-static char usage[] =
- "Usage: %s [-bdhnptvx] [--beep] [--color] [--differences[=cumulative]] [--exec] [--help] [--interval=<n>] [--no-title] [--version] <command>\n";
-
-static char *progname;
-
static int curses_started = 0;
static int height = 24, width = 80;
static int screen_size_changed = 0;
static int first_screen = 1;
-static int show_title = 2; // number of lines used, 2 or 0
+static int show_title = 2; /* number of lines used, 2 or 0 */
static int precise_timekeeping = 0;
#define min(x,y) ((x) > (y) ? (y) : (x))
#define MAX_ANSIBUF 10
-static void init_ansi_colors(void)
+static void __attribute__ ((__noreturn__))
+ usage(FILE * out)
{
- int i;
- short ncurses_colors[] = {
- COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE,
- COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE };
-
- for (i=0; i< 8; i++)
- init_pair(i+1, ncurses_colors[i], -1);
+ fputs(USAGE_HEADER, out);
+ fprintf(out,
+ _(" %s [options] command\n"), program_invocation_short_name);
+ fputs(USAGE_OPTIONS, out);
+ fputs(_(" -b, --beep beep if command has a non-zero exit\n"), out);
+ fputs(_(" -c, --color interpret ANSI color sequences\n"), out);
+ fputs(_(" -e, --errexit exit if command has a non-zero exit\n"), out);
+ fputs(_(" -f, --differences highlight changes between updates\n"), out);
+ fputs(_(" -n, --interval <secs> seconds to wait between updates\n"), out);
+ fputs(_(" -p, --precise attempt run command in precise intervals\n"), out);
+ fputs(_(" -t, --no-title turn off header\n"), out);
+ fputs(_(" -x, --exec pass command to exec instead of \"sh -c\"\n"), out);
+ fputs(_(" -h, --help display this help text\n"), out);
+ fputs(_(" -v, --version display version information and exit\n"), out);
+ fputs(USAGE_SEPARATOR, out);
+ fputs(USAGE_HELP, out);
+ fputs(_(" -v, --version output version information and exit\n"), out);
+ fprintf(out, USAGE_MAN_TAIL("watch(1)"));
+
+ exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
-static void set_ansi_attribute(const int attrib)
+static void init_ansi_colors(void)
{
- switch (attrib)
- {
- case -1:
- return;
- case 0:
- standend();
- return;
- case 1:
- attrset(A_BOLD);
- return;
- }
- if (attrib >= 30 && attrib <= 37) {
- color_set(attrib-29,NULL);
- return;
- }
+ int i;
+ short ncurses_colors[] = {
+ COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE,
+ COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE
+ };
+
+ for (i = 0; i < 8; i++)
+ init_pair(i + 1, ncurses_colors[i], -1);
}
-static void process_ansi(FILE *fp)
+static void set_ansi_attribute(const int attrib)
{
- int i,c, num1, num2;
- char buf[MAX_ANSIBUF];
- char *nextnum;
-
-
- c= getc(fp);
- if (c != '[') {
- ungetc(c, fp);
- return;
- }
- for(i=0; i<MAX_ANSIBUF; i++)
- {
- c = getc(fp);
- if (c == 'm') //COLOUR SEQUENCE ENDS in 'm'
- {
- buf[i] = '\0';
- break;
- }
- if (c < '0' && c > '9' && c != ';')
- {
- while(--i >= 0)
- ungetc(buf[i],fp);
- return;
- }
- buf[i] = (char)c;
- }
- num1 = strtol(buf, &nextnum, 10);
- if (nextnum != buf && nextnum[0] != '\0')
- num2 = strtol(nextnum+1, NULL, 10);
- else
- num2 = -1;
- set_ansi_attribute(num1);
- set_ansi_attribute(num2);
+ switch (attrib) {
+ case -1:
+ return;
+ case 0:
+ standend();
+ return;
+ case 1:
+ attrset(A_BOLD);
+ return;
+ }
+ if (attrib >= 30 && attrib <= 37) {
+ color_set(attrib - 29, NULL);
+ return;
+ }
}
-static void do_usage(void) NORETURN;
-static void do_usage(void)
+static void process_ansi(FILE * fp)
{
- fprintf(stderr, usage, progname);
- exit(1);
+ int i, c, num1, num2;
+ char buf[MAX_ANSIBUF];
+ char *nextnum;
+
+ c = getc(fp);
+ if (c != '[') {
+ ungetc(c, fp);
+ return;
+ }
+ for (i = 0; i < MAX_ANSIBUF; i++) {
+ c = getc(fp);
+ /* COLOUR SEQUENCE ENDS in 'm' */
+ if (c == 'm') {
+ buf[i] = '\0';
+ break;
+ }
+ if (c < '0' && c > '9' && c != ';') {
+ while (--i >= 0)
+ ungetc(buf[i], fp);
+ return;
+ }
+ buf[i] = (char)c;
+ }
+ num1 = strtol(buf, &nextnum, 10);
+ if (nextnum != buf && nextnum[0] != '\0')
+ num2 = strtol(nextnum + 1, NULL, 10);
+ else
+ num2 = -1;
+ set_ansi_attribute(num1);
+ set_ansi_attribute(num2);
}
-static void do_exit(int status) NORETURN;
-static void do_exit(int status)
+static void __attribute__ ((__noreturn__)) do_exit(int status)
{
if (curses_started)
endwin();
@@ -151,17 +153,13 @@ static void do_exit(int status)
}
/* signal handler */
-static void die(int notused) NORETURN;
-static void die(int notused)
+static void die(int notused __attribute__ ((__unused__)))
{
- (void) notused;
- do_exit(0);
+ do_exit(EXIT_SUCCESS);
}
-static void
-winch_handler(int notused)
+static void winch_handler(int notused __attribute__ ((__unused__)))
{
- (void) notused;
screen_size_changed = 1;
}
@@ -170,46 +168,53 @@ static char env_row_buf[24];
static int incoming_cols;
static int incoming_rows;
-static void
-get_terminal_size(void)
+static void get_terminal_size(void)
{
struct winsize w;
- if(!incoming_cols){ // have we checked COLUMNS?
+ if (!incoming_cols) {
+ /* have we checked COLUMNS? */
const char *s = getenv("COLUMNS");
incoming_cols = -1;
- if(s && *s){
+ if (s && *s) {
long t;
char *endptr;
t = strtol(s, &endptr, 0);
- if(!*endptr && (t>0) && (t<(long)666)) incoming_cols = (int)t;
+ if (!*endptr && (t > 0) && (t < (long)666))
+ incoming_cols = (int)t;
width = incoming_cols;
- snprintf(env_col_buf, sizeof env_col_buf, "COLUMNS=%d", width);
+ snprintf(env_col_buf, sizeof env_col_buf, "COLUMNS=%d",
+ width);
putenv(env_col_buf);
}
}
- if(!incoming_rows){ // have we checked LINES?
+ if (!incoming_rows) {
+ /* have we checked LINES? */
const char *s = getenv("LINES");
incoming_rows = -1;
- if(s && *s){
+ if (s && *s) {
long t;
char *endptr;
t = strtol(s, &endptr, 0);
- if(!*endptr && (t>0) && (t<(long)666)) incoming_rows = (int)t;
+ if (!*endptr && (t > 0) && (t < (long)666))
+ incoming_rows = (int)t;
height = incoming_rows;
- snprintf(env_row_buf, sizeof env_row_buf, "LINES=%d", height);
+ snprintf(env_row_buf, sizeof env_row_buf, "LINES=%d",
+ height);
putenv(env_row_buf);
}
}
- if (incoming_cols<0 || incoming_rows<0){
+ if (incoming_cols < 0 || incoming_rows < 0) {
if (ioctl(2, TIOCGWINSZ, &w) == 0) {
- if (incoming_rows<0 && w.ws_row > 0){
+ if (incoming_rows < 0 && w.ws_row > 0) {
height = w.ws_row;
- snprintf(env_row_buf, sizeof env_row_buf, "LINES=%d", height);
+ snprintf(env_row_buf, sizeof env_row_buf,
+ "LINES=%d", height);
putenv(env_row_buf);
}
- if (incoming_cols<0 && w.ws_col > 0){
+ if (incoming_cols < 0 && w.ws_col > 0) {
width = w.ws_col;
- snprintf(env_col_buf, sizeof env_col_buf, "COLUMNS=%d", width);
+ snprintf(env_col_buf, sizeof env_col_buf,
+ "COLUMNS=%d", width);
putenv(env_col_buf);
}
}
@@ -219,180 +224,183 @@ get_terminal_size(void)
/* get current time in usec */
typedef unsigned long long watch_usec_t;
#define USECS_PER_SEC (1000000ull)
-watch_usec_t get_time_usec() {
+watch_usec_t get_time_usec()
+{
struct timeval now;
gettimeofday(&now, NULL);
- return USECS_PER_SEC*now.tv_sec + now.tv_usec;
+ return USECS_PER_SEC * now.tv_sec + now.tv_usec;
}
#ifdef WITH_WATCH8BIT
-// read a wide character from a popen'd stream
+/* read a wide character from a popen'd stream */
#define MAX_ENC_BYTES 16
-wint_t my_getwc(FILE *s);
-wint_t my_getwc(FILE *s) {
- char i[MAX_ENC_BYTES]; //assuming no encoding ever consumes more than 16 bytes
+wint_t my_getwc(FILE * s);
+wint_t my_getwc(FILE * s)
+{
+ /* assuming no encoding ever consumes more than 16 bytes */
+ char i[MAX_ENC_BYTES];
int byte = 0;
int convert;
int x;
wchar_t rval;
- while(1) {
+ while (1) {
i[byte] = getc(s);
- if (i[byte]==EOF) { return WEOF; }
+ if (i[byte] == EOF) {
+ return WEOF;
+ }
byte++;
errno = 0;
mbtowc(NULL, NULL, 0);
convert = mbtowc(&rval, i, byte);
x = errno;
- if(convert > 0) { return rval; } //legal conversion
- if(byte == MAX_ENC_BYTES) {
- while(byte > 1) { ungetc(i[--byte], s); } //at least *try* to fix up
- errno = -EILSEQ;
- return WEOF;
+ if (convert > 0) {
+ /* legal conversion */
+ return rval;
+ }
+ if (byte == MAX_ENC_BYTES) {
+ while (byte > 1) {
+ /* at least *try* to fix up */
+ ungetc(i[--byte], s);
+ }
+ errno = -EILSEQ;
+ return WEOF;
}
}
}
-#endif /* WITH_WATCH8BIT */
+#endif /* WITH_WATCH8BIT */
-int
-main(int argc, char *argv[])
+int main(int argc, char *argv[])
{
int optc;
int option_differences = 0,
option_differences_cumulative = 0,
- option_exec = 0,
- option_beep = 0,
- option_color = 0,
- option_errexit = 0,
- option_help = 0, option_version = 0;
+ option_exec = 0,
+ option_beep = 0,
+ option_color = 0,
+ option_errexit = 0, option_help = 0, option_version = 0;
double interval = 2;
char *command;
char **command_argv;
int command_length = 0; /* not including final \0 */
- watch_usec_t next_loop; /* next loop time in us, used for precise time
- keeping only */
+ watch_usec_t next_loop; /* next loop time in us, used for precise time
+ * keeping only */
#ifdef WITH_WATCH8BIT
wchar_t *wcommand = NULL;
int wcommand_columns = 0; /* not including final \0 */
- int wcommand_characters = 0; /* not including final \0 */
-#endif /* WITH_WATCH8BIT */
+ int wcommand_characters = 0; /* not including final \0 */
+#endif /* WITH_WATCH8BIT */
int pipefd[2];
int status;
pid_t child;
+ static struct option longopts[] = {
+ {"color", no_argument, 0, 'c'},
+ {"differences", optional_argument, 0, 'd'},
+ {"help", no_argument, 0, 'h'},
+ {"interval", required_argument, 0, 'n'},
+ {"beep", no_argument, 0, 'b'},
+ {"errexit", no_argument, 0, 'e'},
+ {"exec", no_argument, 0, 'x'},
+ {"precise", no_argument, 0, 'p'},
+ {"no-title", no_argument, 0, 't'},
+ {"version", no_argument, 0, 'v'},
+ {0, 0, 0, 0}
+ };
+
setlocale(LC_ALL, "");
- progname = argv[0];
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
- while ((optc = getopt_long(argc, argv, "+bced::hn:pvtx", longopts, (int *) 0))
+ while ((optc =
+ getopt_long(argc, argv, "+bced::hn:pvtx", longopts, (int *)0))
!= EOF) {
switch (optc) {
case 'b':
option_beep = 1;
break;
- case 'c':
- option_color = 1;
- break;
+ case 'c':
+ option_color = 1;
+ break;
case 'd':
option_differences = 1;
if (optarg)
option_differences_cumulative = 1;
break;
- case 'e':
- option_errexit = 1;
- break;
- case 'h':
- option_help = 1;
+ case 'e':
+ option_errexit = 1;
break;
case 't':
show_title = 0;
break;
case 'x':
- option_exec = 1;
+ option_exec = 1;
break;
case 'n':
- {
- char *str;
- interval = strtod(optarg, &str);
- if (!*optarg || *str)
- do_usage();
- if(interval < 0.1)
- interval = 0.1;
- if(interval > ~0u/1000000)
- interval = ~0u/1000000;
- }
+ interval = strtod_or_err(optarg, _("failed to parse argument"));
+ if (interval < 0.1)
+ interval = 0.1;
+ if (interval > ~0u / 1000000)
+ interval = ~0u / 1000000;
break;
case 'p':
precise_timekeeping = 1;
break;
- case 'v':
- option_version = 1;
+ case 'h':
+ usage(stdout);
break;
+ case 'v':
+ printf(PROCPS_NG_VERSION);
+ return EXIT_SUCCESS;
default:
- do_usage();
+ usage(stderr);
break;
}
}
- if (option_version) {
- fprintf(stderr, "%s\n", PACKAGE_NAME " version " PACKAGE_VERSION);
- if (!option_help)
- exit(0);
- }
-
- if (option_help) {
- fprintf(stderr, usage, progname);
- fputs(" -b, --beep\t\t\t\tbeep if the command has a non-zero exit\n", stderr);
- fputs(" -d, --differences[=cumulative]\thighlight changes between updates\n", stderr);
- fputs("\t\t(cumulative means highlighting is cumulative)\n", stderr);
- fputs(" -e, --errexit\t\t\t\texit watch if the command has a non-zero exit\n", stderr);
- fputs(" -h, --help\t\t\t\tprint a summary of the options\n", stderr);
- fputs(" -n, --interval=<seconds>\t\tseconds to wait between updates\n", stderr);
- fputs(" -p, --precise\t\t\t\tprecise timing, ignore command run time\n", stderr);
- fputs(" -v, --version\t\t\t\tprint the version number\n", stderr);
- fputs(" -t, --no-title\t\t\tturns off showing the header\n", stderr);
- fputs(" -x, --exec\t\t\t\tpass command to exec instead of sh\n", stderr);
- exit(0);
- }
-
if (optind >= argc)
- do_usage();
+ usage(stderr);
- command_argv=&(argv[optind]); /* save for later */
+ /* save for later */
+ command_argv = &(argv[optind]);
- command = strdup(argv[optind++]);
+ command = xstrdup(argv[optind++]);
command_length = strlen(command);
for (; optind < argc; optind++) {
char *endp;
int s = strlen(argv[optind]);
- command = realloc(command, command_length + s + 2); /* space and \0 */
+ /* space and \0 */
+ command = xrealloc(command, command_length + s + 2);
endp = command + command_length;
*endp = ' ';
memcpy(endp + 1, argv[optind], s);
- command_length += 1 + s; /* space then string length */
+ /* space then string length */
+ command_length += 1 + s;
command[command_length] = '\0';
}
#ifdef WITH_WATCH8BIT
- // convert to wide for printing purposes
- //mbstowcs(NULL, NULL, 0);
+ /* convert to wide for printing purposes */
+ /*mbstowcs(NULL, NULL, 0); */
wcommand_characters = mbstowcs(NULL, command, 0);
- if(wcommand_characters < 0) {
- fprintf(stderr, "Unicode Handling Error\n");
- exit(1);
+ if (wcommand_characters < 0) {
+ fprintf(stderr, _("Unicode Handling Error\n"));
+ exit(EXIT_FAILURE);
}
- wcommand = (wchar_t*)malloc((wcommand_characters+1) * sizeof(wcommand));
- if(wcommand == NULL) {
- fprintf(stderr, "Unicode Handling Error (malloc)\n");
- exit(1);
+ wcommand =
+ (wchar_t *) malloc((wcommand_characters + 1) * sizeof(wcommand));
+ if (wcommand == NULL) {
+ fprintf(stderr, _("Unicode Handling Error (malloc)\n"));
+ exit(EXIT_FAILURE);
}
- mbstowcs(wcommand, command, wcommand_characters+1);
+ mbstowcs(wcommand, command, wcommand_characters + 1);
wcommand_columns = wcswidth(wcommand, -1);
-#endif /* WITH_WATCH8BIT */
-
+#endif /* WITH_WATCH8BIT */
get_terminal_size();
- /* Catch keyboard interrupts so we can put tty back in a sane state. */
+ /* Catch keyboard interrupts so we can put tty back in a sane
+ * state. */
signal(SIGINT, die);
signal(SIGTERM, die);
signal(SIGHUP, die);
@@ -401,14 +409,14 @@ main(int argc, char *argv[])
/* Set up tty for curses use. */
curses_started = 1;
initscr();
- if (option_color) {
- if (has_colors()) {
- start_color();
- use_default_colors();
- init_ansi_colors();
- } else
- option_color = 0;
- }
+ if (option_color) {
+ if (has_colors()) {
+ start_color();
+ use_default_colors();
+ init_ansi_colors();
+ } else
+ option_color = 0;
+ }
nonl();
noecho();
cbreak();
@@ -435,44 +443,70 @@ main(int argc, char *argv[])
}
if (show_title) {
- // left justify interval and command,
- // right justify time, clipping all to fit window width
-
- int hlen = asprintf(&header, "Every %.1fs: ", interval);
-
- // the rules:
- // width < tsl : print nothing
- // width < tsl + hlen + 1: print ts
- // width = tsl + hlen + 1: print header, ts
- // width < tsl + hlen + 4: print header, ..., ts
- // width < tsl + hlen + wcommand_columns: print header, truncated wcommand, ..., ts
- // width > "": print header, wcomand, ts
- // this is slightly different from how it used to be
- if(width >= tsl) {
- if(width >= tsl + hlen + 1) {
+ /*
+ * left justify interval and command, right
+ * justify time, clipping all to fit window
+ * width
+ */
+ int hlen = asprintf(&header, _("Every %.1fs: "), interval);
+
+ /*
+ * the rules:
+ * width < tsl : print nothing
+ * width < tsl + hlen + 1: print ts
+ * width = tsl + hlen + 1: print header, ts
+ * width < tsl + hlen + 4: print header, ..., ts
+ * width < tsl + hlen + wcommand_columns: print
+ * header, truncated wcommand,
+ * ..., ts
+ * width > "": print header, wcomand, ts
+ * this is slightly different from how it used to be
+ */
+ if (width >= tsl) {
+ if (width >= tsl + hlen + 1) {
mvaddstr(0, 0, header);
- if(width >= tsl + hlen + 2) {
- if(width < tsl + hlen + 4) {
- mvaddstr(0, width - tsl - 4, "... ");
- }else{
+ if (width >= tsl + hlen + 2) {
+ if (width < tsl + hlen + 4) {
+ mvaddstr(0,
+ width - tsl -
+ 4, "... ");
+ } else {
#ifdef WITH_WATCH8BIT
- if(width < tsl + hlen + wcommand_columns) {
- // print truncated
+ if (width <
+ tsl + hlen +
+ wcommand_columns) {
+ /* print truncated */
int avail_columns = width - tsl - hlen;
int using_columns = wcommand_columns;
int using_characters = wcommand_characters;
- while(using_columns > avail_columns - 4) {
+ while (using_columns > avail_columns - 4) {
using_characters--;
- using_columns = wcswidth(wcommand, using_characters);
+ using_columns
+ =
+ wcswidth
+ (wcommand,
+ using_characters);
}
- mvaddnwstr(0, hlen, wcommand, using_characters);
- mvaddstr(0, width - tsl - 4, "... ");
- }else{
- mvaddwstr(0, hlen, wcommand);
+ mvaddnwstr(0,
+ hlen,
+ wcommand,
+ using_characters);
+ mvaddstr(0,
+ width -
+ tsl -
+ 4,
+ "... ");
+ } else {
+ mvaddwstr(0,
+ hlen,
+ wcommand);
}
#else
- mvaddnstr(0, hlen, command, width - tsl - hlen);
-#endif /* WITH_WATCH8BIT */
+ mvaddnstr(0, hlen,
+ command,
+ width - tsl -
+ hlen);
+#endif /* WITH_WATCH8BIT */
}
}
}
@@ -483,101 +517,99 @@ main(int argc, char *argv[])
}
/* allocate pipes */
- if (pipe(pipefd)<0) {
- perror("pipe");
- do_exit(7);
- }
+ if (pipe(pipefd) < 0)
+ err(7, _("pipe"));
/* flush stdout and stderr, since we're about to do fd stuff */
fflush(stdout);
fflush(stderr);
/* fork to prepare to run command */
- child=fork();
-
- if (child<0) { /* fork error */
- perror("fork");
- do_exit(2);
- } else if (child==0) { /* in child */
- close (pipefd[0]); /* child doesn't need read side of pipe */
- close (1); /* prepare to replace stdout with pipe */
- if (dup2 (pipefd[1], 1)<0) { /* replace stdout with write side of pipe */
- perror("dup2");
- exit(3);
+ child = fork();
+
+ if (child < 0) { /* fork error */
+ err(2, _("fork"));
+ } else if (child == 0) { /* in child */
+ close(pipefd[0]); /* child doesn't need read side of pipe */
+ close(1); /* prepare to replace stdout with pipe */
+ if (dup2(pipefd[1], 1) < 0) { /* replace stdout with write side of pipe */
+ err(3, _("dup2"));
}
- dup2(1, 2); /* stderr should default to stdout */
+ dup2(1, 2); /* stderr should default to stdout */
- if (option_exec) { /* pass command to exec instead of system */
- if (execvp(command_argv[0], command_argv)==-1) {
- perror("exec");
- exit(4);
+ if (option_exec) { /* pass command to exec instead of system */
+ if (execvp(command_argv[0], command_argv) == -1) {
+ err(4, _("exec"));
}
} else {
- status=system(command); /* watch manpage promises sh quoting */
-
- /* propagate command exit status as child exit status */
- if (!WIFEXITED(status)) { /* child exits nonzero if command does */
- exit(1);
- } else {
- exit(WEXITSTATUS(status));
- }
+ status = system(command); /* watch manpage promises sh quoting */
+
+ /* propagate command exit status as child exit status */
+ if (!WIFEXITED(status)) { /* child exits nonzero if command does */
+ exit(EXIT_FAILURE);
+ } else {
+ exit(WEXITSTATUS(status));
+ }
}
}
/* otherwise, we're in parent */
- close(pipefd[1]); /* close write side of pipe */
- if ((p=fdopen(pipefd[0], "r"))==NULL) {
- perror("fdopen");
- do_exit(5);
- }
-
+ close(pipefd[1]); /* close write side of pipe */
+ if ((p = fdopen(pipefd[0], "r")) == NULL)
+ err(5, _("fdopen"));
for (y = show_title; y < height; y++) {
int eolseen = 0, tabpending = 0;
#ifdef WITH_WATCH8BIT
wint_t carry = WEOF;
-#endif /* WITH_WATCH8BIT */
+#endif /* WITH_WATCH8BIT */
for (x = 0; x < width; x++) {
#ifdef WITH_WATCH8BIT
wint_t c = ' ';
#else
int c = ' ';
-#endif /* WITH_WATCH8BIT */
+#endif /* WITH_WATCH8BIT */
int attr = 0;
if (!eolseen) {
- /* if there is a tab pending, just spit spaces until the
- next stop instead of reading characters */
- if (!tabpending)
+ /* if there is a tab pending, just
+ * spit spaces until the next stop
+ * instead of reading characters */
+ if (!tabpending)
#ifdef WITH_WATCH8BIT
- do {
- if(carry == WEOF) {
- c = my_getwc(p);
- }else{
- c = carry;
- carry = WEOF;
- }
- }while (c != WEOF && !isprint(c) && c<12
- && wcwidth(c) == 0
- && c != L'\n'
- && c != L'\t'
- && (c != L'\033' || option_color != 1));
+ do {
+ if (carry == WEOF) {
+ c = my_getwc(p);
+ } else {
+ c = carry;
+ carry = WEOF;
+ }
+ } while (c != WEOF
+ && !isprint(c)
+ && c < 12
+ && wcwidth(c) == 0
+ && c != L'\n'
+ && c != L'\t'
+ && (c != L'\033'
+ || option_color !=
+ 1));
#else
do
c = getc(p);
while (c != EOF && !isprint(c)
&& c != '\n'
&& c != '\t'
- && (c != L'\033' || option_color != 1));
-#endif /* WITH_WATCH8BIT */
- if (c == L'\033' && option_color == 1) {
- x--;
- process_ansi(p);
- continue;
- }
- if (c == L'\n')
-
+ && (c != L'\033'
+ || option_color !=
+ 1));
+#endif /* WITH_WATCH8BIT */
+ if (c == L'\033' && option_color == 1) {
+ x--;
+ process_ansi(p);
+ continue;
+ }
+ if (c == L'\n')
if (!oldeolseen && x == 0) {
x = -1;
continue;
@@ -586,31 +618,33 @@ main(int argc, char *argv[])
else if (c == L'\t')
tabpending = 1;
#ifdef WITH_WATCH8BIT
- if (x==width-1 && wcwidth(c)==2) {
- y++;
- x = -1; //process this double-width
- carry = c; //character on the next line
- continue; //because it won't fit here
- }
- if (c == WEOF || c == L'\n' || c == L'\t')
- c = L' ';
+ if (x == width - 1 && wcwidth(c) == 2) {
+ y++;
+ x = -1; /* process this double-width */
+ carry = c; /* character on the next line */
+ continue; /* because it won't fit here */
+ }
+ if (c == WEOF || c == L'\n'
+ || c == L'\t')
+ c = L' ';
#else
if (c == EOF || c == '\n' || c == '\t')
c = ' ';
-#endif /* WITH_WATCH8BIT */
+#endif /* WITH_WATCH8BIT */
if (tabpending && (((x + 1) % 8) == 0))
tabpending = 0;
}
move(y, x);
if (option_differences) {
#ifdef WITH_WATCH8BIT
- cchar_t oldc;
- in_wch(&oldc);
+ cchar_t oldc;
+ in_wch(&oldc);
attr = !first_screen
- && ((wchar_t)c != oldc.chars[0]
+ && ((wchar_t) c != oldc.chars[0]
||
(option_differences_cumulative
- && (oldc.attr & A_ATTRIBUTES)));
+ && (oldc.
+ attr & A_ATTRIBUTES)));
#else
chtype oldch = inch();
unsigned char oldc = oldch & A_CHARTEXT;
@@ -619,21 +653,25 @@ main(int argc, char *argv[])
||
(option_differences_cumulative
&& (oldch & A_ATTRIBUTES)));
-#endif /* WITH_WATCH8BIT */
+#endif /* WITH_WATCH8BIT */
}
if (attr)
standout();
#ifdef WITH_WATCH8BIT
- addnwstr((wchar_t*)&c,1);
+ addnwstr((wchar_t *) & c, 1);
#else
addch(c);
-#endif /* WITH_WATCH8BIT */
+#endif /* WITH_WATCH8BIT */
if (attr)
standend();
#ifdef WITH_WATCH8BIT
- if(wcwidth(c) == 0) { x--; }
- if(wcwidth(c) == 2) { x++; }
-#endif /* WITH_WATCH8BIT */
+ if (wcwidth(c) == 0) {
+ x--;
+ }
+ if (wcwidth(c) == 2) {
+ x++;
+ }
+#endif /* WITH_WATCH8BIT */
}
oldeolseen = eolseen;
}
@@ -641,29 +679,29 @@ main(int argc, char *argv[])
fclose(p);
/* harvest child process and get status, propagated from command */
- if (waitpid(child, &status, 0)<0) {
- perror("waitpid");
- do_exit(8);
- };
+ if (waitpid(child, &status, 0) < 0)
+ err(8, _("waitpid"));
/* if child process exited in error, beep if option_beep is set */
if ((!WIFEXITED(status) || WEXITSTATUS(status))) {
- if (option_beep) beep();
- if (option_errexit) do_exit(8);
+ if (option_beep)
+ beep();
+ if (option_errexit)
+ exit(8);
}
first_screen = 0;
refresh();
if (precise_timekeeping) {
watch_usec_t cur_time = get_time_usec();
- next_loop += USECS_PER_SEC*interval;
+ next_loop += USECS_PER_SEC * interval;
if (cur_time < next_loop)
usleep(next_loop - cur_time);
} else
- usleep(interval * 1000000);
+ usleep(interval * 1000000);
}
endwin();
- return 0;
+ return EXIT_SUCCESS;
}