From b13154de3eca5ba28fbb4854d916cd0be5febeed Mon Sep 17 00:00:00 2001 From: Igor Pashev Date: Fri, 2 Nov 2012 20:15:39 +0400 Subject: Imported Upstream version 2.22 --- sys-utils/Makemodule.am | 302 +++++ sys-utils/arch.1 | 40 + sys-utils/arch.c | 84 ++ sys-utils/chcpu.8 | 96 ++ sys-utils/chcpu.c | 335 ++++++ sys-utils/ctrlaltdel.8 | 51 + sys-utils/ctrlaltdel.c | 69 ++ sys-utils/cyclades.h | 16 + sys-utils/cytune.8 | 194 +++ sys-utils/cytune.c | 461 +++++++ sys-utils/dmesg.1 | 162 +++ sys-utils/dmesg.c | 1214 +++++++++++++++++++ sys-utils/eject.1 | 165 +++ sys-utils/eject.c | 1132 +++++++++++++++++ sys-utils/fallocate.1 | 62 + sys-utils/fallocate.c | 173 +++ sys-utils/flock.1 | 166 +++ sys-utils/flock.c | 343 ++++++ sys-utils/fsfreeze.8 | 73 ++ sys-utils/fsfreeze.c | 134 +++ sys-utils/fstab.5 | 271 +++++ sys-utils/fstrim.8 | 85 ++ sys-utils/fstrim.c | 153 +++ sys-utils/hwclock-cmos.c | 677 +++++++++++ sys-utils/hwclock-kd.c | 182 +++ sys-utils/hwclock-rtc.c | 509 ++++++++ sys-utils/hwclock.8 | 661 ++++++++++ sys-utils/hwclock.c | 1870 +++++++++++++++++++++++++++++ sys-utils/hwclock.h | 47 + sys-utils/ipcmk.1 | 51 + sys-utils/ipcmk.c | 160 +++ sys-utils/ipcrm.1 | 111 ++ sys-utils/ipcrm.c | 410 +++++++ sys-utils/ipcs.1 | 103 ++ sys-utils/ipcs.c | 714 +++++++++++ sys-utils/ldattach.8 | 144 +++ sys-utils/ldattach.c | 373 ++++++ sys-utils/losetup.8 | 174 +++ sys-utils/losetup.c | 465 +++++++ sys-utils/lp.h | 83 ++ sys-utils/lscpu.1 | 149 +++ sys-utils/lscpu.c | 1400 +++++++++++++++++++++ sys-utils/mount.8 | 2935 +++++++++++++++++++++++++++++++++++++++++++++ sys-utils/mount.c | 995 +++++++++++++++ sys-utils/mountpoint.1 | 43 + sys-utils/mountpoint.c | 212 ++++ sys-utils/pivot_root.8 | 75 ++ sys-utils/pivot_root.c | 75 ++ sys-utils/prlimit.1 | 124 ++ sys-utils/prlimit.c | 643 ++++++++++ sys-utils/readprofile.8 | 152 +++ sys-utils/readprofile.c | 405 +++++++ sys-utils/renice.1 | 128 ++ sys-utils/renice.c | 185 +++ sys-utils/rtcwake.8 | 146 +++ sys-utils/rtcwake.c | 624 ++++++++++ sys-utils/setarch.8 | 85 ++ sys-utils/setarch.c | 351 ++++++ sys-utils/setsid.1 | 24 + sys-utils/setsid.c | 98 ++ sys-utils/swapoff.8 | 1 + sys-utils/swapoff.c | 196 +++ sys-utils/swapon-common.c | 106 ++ sys-utils/swapon-common.h | 26 + sys-utils/swapon.8 | 241 ++++ sys-utils/swapon.c | 823 +++++++++++++ sys-utils/switch_root.8 | 61 + sys-utils/switch_root.c | 225 ++++ sys-utils/tunelp.8 | 147 +++ sys-utils/tunelp.c | 335 ++++++ sys-utils/umount.8 | 175 +++ sys-utils/umount.c | 399 ++++++ sys-utils/unshare.1 | 62 + sys-utils/unshare.c | 137 +++ sys-utils/wdctl.8 | 61 + sys-utils/wdctl.c | 577 +++++++++ 76 files changed, 24936 insertions(+) create mode 100644 sys-utils/Makemodule.am create mode 100644 sys-utils/arch.1 create mode 100644 sys-utils/arch.c create mode 100644 sys-utils/chcpu.8 create mode 100644 sys-utils/chcpu.c create mode 100644 sys-utils/ctrlaltdel.8 create mode 100644 sys-utils/ctrlaltdel.c create mode 100644 sys-utils/cyclades.h create mode 100644 sys-utils/cytune.8 create mode 100644 sys-utils/cytune.c create mode 100644 sys-utils/dmesg.1 create mode 100644 sys-utils/dmesg.c create mode 100644 sys-utils/eject.1 create mode 100644 sys-utils/eject.c create mode 100644 sys-utils/fallocate.1 create mode 100644 sys-utils/fallocate.c create mode 100644 sys-utils/flock.1 create mode 100644 sys-utils/flock.c create mode 100644 sys-utils/fsfreeze.8 create mode 100644 sys-utils/fsfreeze.c create mode 100644 sys-utils/fstab.5 create mode 100644 sys-utils/fstrim.8 create mode 100644 sys-utils/fstrim.c create mode 100644 sys-utils/hwclock-cmos.c create mode 100644 sys-utils/hwclock-kd.c create mode 100644 sys-utils/hwclock-rtc.c create mode 100644 sys-utils/hwclock.8 create mode 100644 sys-utils/hwclock.c create mode 100644 sys-utils/hwclock.h create mode 100644 sys-utils/ipcmk.1 create mode 100644 sys-utils/ipcmk.c create mode 100644 sys-utils/ipcrm.1 create mode 100644 sys-utils/ipcrm.c create mode 100644 sys-utils/ipcs.1 create mode 100644 sys-utils/ipcs.c create mode 100644 sys-utils/ldattach.8 create mode 100644 sys-utils/ldattach.c create mode 100644 sys-utils/losetup.8 create mode 100644 sys-utils/losetup.c create mode 100644 sys-utils/lp.h create mode 100644 sys-utils/lscpu.1 create mode 100644 sys-utils/lscpu.c create mode 100644 sys-utils/mount.8 create mode 100644 sys-utils/mount.c create mode 100644 sys-utils/mountpoint.1 create mode 100644 sys-utils/mountpoint.c create mode 100644 sys-utils/pivot_root.8 create mode 100644 sys-utils/pivot_root.c create mode 100644 sys-utils/prlimit.1 create mode 100644 sys-utils/prlimit.c create mode 100644 sys-utils/readprofile.8 create mode 100644 sys-utils/readprofile.c create mode 100644 sys-utils/renice.1 create mode 100644 sys-utils/renice.c create mode 100644 sys-utils/rtcwake.8 create mode 100644 sys-utils/rtcwake.c create mode 100644 sys-utils/setarch.8 create mode 100644 sys-utils/setarch.c create mode 100644 sys-utils/setsid.1 create mode 100644 sys-utils/setsid.c create mode 100644 sys-utils/swapoff.8 create mode 100644 sys-utils/swapoff.c create mode 100644 sys-utils/swapon-common.c create mode 100644 sys-utils/swapon-common.h create mode 100644 sys-utils/swapon.8 create mode 100644 sys-utils/swapon.c create mode 100644 sys-utils/switch_root.8 create mode 100644 sys-utils/switch_root.c create mode 100644 sys-utils/tunelp.8 create mode 100644 sys-utils/tunelp.c create mode 100644 sys-utils/umount.8 create mode 100644 sys-utils/umount.c create mode 100644 sys-utils/unshare.1 create mode 100644 sys-utils/unshare.c create mode 100644 sys-utils/wdctl.8 create mode 100644 sys-utils/wdctl.c (limited to 'sys-utils') diff --git a/sys-utils/Makemodule.am b/sys-utils/Makemodule.am new file mode 100644 index 0000000..d376f04 --- /dev/null +++ b/sys-utils/Makemodule.am @@ -0,0 +1,302 @@ + +usrbin_exec_PROGRAMS += flock +dist_man_MANS += sys-utils/flock.1 +flock_SOURCES = sys-utils/flock.c +flock_LDADD = $(LDADD) libcommon.la + +usrbin_exec_PROGRAMS += ipcmk +dist_man_MANS += sys-utils/ipcmk.1 +ipcmk_SOURCES = sys-utils/ipcmk.c +ipcmk_LDADD = $(LDADD) libcommon.la + +usrbin_exec_PROGRAMS += ipcrm +dist_man_MANS += sys-utils/ipcrm.1 +ipcrm_SOURCES = sys-utils/ipcrm.c +ipcrm_LDADD = $(LDADD) libcommon.la + +usrbin_exec_PROGRAMS += ipcs +dist_man_MANS += sys-utils/ipcs.1 +ipcs_SOURCES = sys-utils/ipcs.c + +usrbin_exec_PROGRAMS += renice +dist_man_MANS += sys-utils/renice.1 +renice_SOURCES = sys-utils/renice.c + +usrbin_exec_PROGRAMS += setsid +dist_man_MANS += sys-utils/setsid.1 +setsid_SOURCES = sys-utils/setsid.c + +usrsbin_exec_PROGRAMS += readprofile +dist_man_MANS += sys-utils/readprofile.8 +readprofile_SOURCES = sys-utils/readprofile.c + + +if LINUX +# +# Linux-only utils with no another dependencies. All another dependencies have +# to be resolved in configure.ac end exported to makefiles by BUILD_*. +# +bin_PROGRAMS += dmesg +dist_man_MANS += sys-utils/dmesg.1 +dmesg_SOURCES = sys-utils/dmesg.c +dmesg_LDADD = $(LDADD) libcommon.la + +sbin_PROGRAMS += ctrlaltdel +dist_man_MANS += sys-utils/ctrlaltdel.8 +ctrlaltdel_SOURCES = sys-utils/ctrlaltdel.c + +sbin_PROGRAMS += fsfreeze +dist_man_MANS += sys-utils/fsfreeze.8 +fsfreeze_SOURCES = sys-utils/fsfreeze.c + +sbin_PROGRAMS += fstrim +dist_man_MANS += sys-utils/fstrim.8 +fstrim_SOURCES = sys-utils/fstrim.c +fstrim_LDADD = $(LDADD) libcommon.la + +usrbin_exec_PROGRAMS += cytune +dist_man_MANS += sys-utils/cytune.8 +cytune_SOURCES = sys-utils/cytune.c sys-utils/cyclades.h +cytune_LDADD = $(LDADD) libcommon.la + +usrsbin_exec_PROGRAMS += ldattach +dist_man_MANS += sys-utils/ldattach.8 +ldattach_SOURCES = sys-utils/ldattach.c +ldattach_LDADD = $(LDADD) libcommon.la + +usrsbin_exec_PROGRAMS += tunelp +dist_man_MANS += sys-utils/tunelp.8 +tunelp_SOURCES = sys-utils/tunelp.c sys-utils/lp.h + +usrsbin_exec_PROGRAMS += rtcwake +dist_man_MANS += sys-utils/rtcwake.8 +rtcwake_SOURCES = sys-utils/rtcwake.c +rtcwake_LDADD = $(LDADD) libcommon.la + +usrbin_exec_PROGRAMS += setarch +dist_man_MANS += sys-utils/setarch.8 +setarch_SOURCES = sys-utils/setarch.c + +SETARCH_LINKS = linux32 linux64 + +if ARCH_S390 +SETARCH_LINKS += s390 s390x +endif +if ARCH_I86 +SETARCH_LINKS += i386 +endif +if ARCH_86_64 +SETARCH_LINKS += i386 x86_64 +endif +if ARCH_PPC +SETARCH_LINKS += ppc ppc64 ppc32 +endif +if ARCH_SPARC +SETARCH_LINKS += sparc sparc64 sparc32 sparc32bash +endif +if ARCH_MIPS +SETARCH_LINKS += mips mips64 mips32 +endif +if ARCH_IA64 +SETARCH_LINKS += i386 ia64 +endif +if ARCH_HPPA +SETARCH_LINKS += parisc parisc64 parisc32 +endif + +SETARCH_MAN_LINKS = $(addprefix sys-utils/,$(SETARCH_LINKS:=.8)) +man_MANS += $(SETARCH_MAN_LINKS) +CLEANFILES += $(SETARCH_MAN_LINKS) + +$(SETARCH_MAN_LINKS): + $(AM_V_GEN)echo ".so man8/setarch.8" > $@ + +install-exec-hook-setarch: + for I in $(SETARCH_LINKS); do \ + cd $(DESTDIR)$(usrbin_execdir) && ln -sf setarch $$I ; \ + done + +uninstall-hook-setarch: + for I in $(SETARCH_LINKS); do \ + rm -f $(DESTDIR)$(usrbin_execdir)/$$I ; \ + done + +INSTALL_EXEC_HOOKS += install-exec-hook-setarch +UNINSTALL_HOOKS += uninstall-hook-setarch + +endif # LINUX + + +if BUILD_EJECT +usrbin_exec_PROGRAMS += eject +eject_SOURCES = sys-utils/eject.c +eject_LDADD = $(LDADD) libmount.la libcommon.la +eject_CFLAGS = $(AM_CFLAGS) -I$(ul_libmount_incdir) +dist_man_MANS += sys-utils/eject.1 +endif + + +if BUILD_LOSETUP +sbin_PROGRAMS += losetup +dist_man_MANS += sys-utils/losetup.8 +losetup_SOURCES = sys-utils/losetup.c +losetup_LDADD = $(LDADD) libcommon.la + +if HAVE_STATIC_LOSETUP +bin_PROGRAMS += losetup.static +losetup_static_SOURCES = $(losetup_SOURCES) +losetup_static_LDFLAGS = -all-static +losetup_static_LDADD = $(losetup_LDADD) +endif +endif # BUILD_LOSETUP + + +if BUILD_PRLIMIT +usrbin_exec_PROGRAMS += prlimit +dist_man_MANS += sys-utils/prlimit.1 +prlimit_SOURCES = sys-utils/prlimit.c +prlimit_LDADD = $(LDADD) libcommon.la +endif + + +if BUILD_MOUNT +# +# The original mount is in mount/ directory +# -- temporary we share some man pages +# +bin_PROGRAMS += mount umount +dist_man_MANS += \ + sys-utils/mount.8 \ + sys-utils/fstab.5 \ + sys-utils/umount.8 +mount_SOURCES = sys-utils/mount.c +mount_LDADD = $(LDADD) libcommon.la libmount.la $(SELINUX_LIBS) +mount_CFLAGS = $(SUID_CFLAGS) $(AM_CFLAGS) -I$(ul_libmount_incdir) +mount_LDFLAGS = $(SUID_LDFLAGS) $(AM_LDFLAGS) + +umount_SOURCES = sys-utils/umount.c +umount_LDADD = $(LDADD) libcommon.la libmount.la +umount_CFLAGS = $(AM_CFLAGS) $(SUID_CFLAGS) -I$(ul_libmount_incdir) +umount_LDFLAGS = $(SUID_LDFLAGS) $(AM_LDFLAGS) + +if HAVE_STATIC_MOUNT +bin_PROGRAMS += mount.static +mount_static_SOURCES = $(mount_SOURCES) +mount_static_CFLAGS = $(mount_CFLAGS) +mount_static_LDFLAGS = $(mount_LDFLAGS) -all-static +mount_static_LDADD = $(mount_LDADD) $(SELINUX_LIBS_STATIC) +endif + +if HAVE_STATIC_UMOUNT +bin_PROGRAMS += umount.static +umount_static_SOURCES = $(umount_SOURCES) +umount_static_CFLAGS = $(umount_CFLAGS) +umount_static_LDFLAGS = $(umount_LDFLAGS) -all-static +umount_static_LDADD = $(umount_LDADD) +endif + +if MAKEINSTALL_DO_SETUID +install-exec-hook-mount: + chmod 4755 $(DESTDIR)$(bindir)/mount + chmod 4755 $(DESTDIR)$(bindir)/umount + +INSTALL_EXEC_HOOKS += install-exec-hook-mount +endif +endif # BUILD_MOUNT + + +if BUILD_SWAPON +sbin_PROGRAMS += swapon swapoff +dist_man_MANS += \ + sys-utils/swapoff.8 \ + sys-utils/swapon.8 + +swapon_SOURCES = \ + sys-utils/swapon.c \ + sys-utils/swapon-common.c \ + sys-utils/swapon-common.h + +swapon_CFLAGS = $(AM_CFLAGS) -I$(ul_libmount_incdir) +swapon_LDADD = $(LDADD) libcommon.la libmount.la + +swapoff_SOURCES = sys-utils/swapoff.c sys-utils/swapon-common.c +swapoff_CFLAGS = $(AM_CFLAGS) -I$(ul_libmount_incdir) +swapoff_LDADD = $(LDADD) libmount.la +endif + +if BUILD_LSCPU +usrbin_exec_PROGRAMS += lscpu +lscpu_SOURCES = sys-utils/lscpu.c +lscpu_LDADD = $(LDADD) libcommon.la +dist_man_MANS += sys-utils/lscpu.1 +endif + +if BUILD_CHCPU +sbin_PROGRAMS += chcpu +chcpu_SOURCES = sys-utils/chcpu.c +chcpu_LDADD = $(LDADD) libcommon.la +dist_man_MANS += sys-utils/chcpu.8 +endif + +if BUILD_WDCTL +bin_PROGRAMS += wdctl +dist_man_MANS += sys-utils/wdctl.8 +wdctl_SOURCES = sys-utils/wdctl.c +wdctl_LDADD = $(LDADD) libcommon.la +endif + +if BUILD_MOUNTPOINT +bin_PROGRAMS += mountpoint +mountpoint_LDADD = $(LDADD) libmount.la +mountpoint_CFLAGS = $(AM_CFLAGS) -I$(ul_libmount_incdir) +dist_man_MANS += sys-utils/mountpoint.1 +mountpoint_SOURCES = sys-utils/mountpoint.c +endif + +if BUILD_FALLOCATE +usrbin_exec_PROGRAMS += fallocate +fallocate_SOURCES = sys-utils/fallocate.c +fallocate_LDADD = $(LDADD) libcommon.la +dist_man_MANS += sys-utils/fallocate.1 +endif + +if BUILD_PIVOT_ROOT +sbin_PROGRAMS += pivot_root +dist_man_MANS += sys-utils/pivot_root.8 +pivot_root_SOURCES = sys-utils/pivot_root.c +endif + +if BUILD_SWITCH_ROOT +sbin_PROGRAMS += switch_root +dist_man_MANS += sys-utils/switch_root.8 +switch_root_SOURCES = sys-utils/switch_root.c +endif + +if BUILD_UNSHARE +usrbin_exec_PROGRAMS += unshare +dist_man_MANS += sys-utils/unshare.1 +unshare_SOURCES = sys-utils/unshare.c +endif + +if BUILD_ARCH +bin_PROGRAMS += arch +dist_man_MANS += sys-utils/arch.1 +arch_SOURCES = sys-utils/arch.c +endif + +if BUILD_HWCLOCK +sbin_PROGRAMS += hwclock +dist_man_MANS += sys-utils/hwclock.8 +hwclock_SOURCES = \ + sys-utils/hwclock.c \ + sys-utils/hwclock.h \ + sys-utils/hwclock-cmos.c \ + sys-utils/hwclock-kd.c +if LINUX +hwclock_SOURCES += sys-utils/hwclock-rtc.c +endif +hwclock_LDADD = $(LDADD) libcommon.la +if HAVE_AUDIT +hwclock_LDADD += -laudit +endif +endif # BUILD_HWCLOCK diff --git a/sys-utils/arch.1 b/sys-utils/arch.1 new file mode 100644 index 0000000..96cbc0a --- /dev/null +++ b/sys-utils/arch.1 @@ -0,0 +1,40 @@ +.\" arch.1 -- +.\" Copyright 1993 Rickard E. Faith (faith@cs.unc.edu) +.\" Public domain: may be freely distributed. +.TH ARCH 1 "July 1997" "util-linux" "User Commands" +.SH NAME +arch \- print machine architecture +.SH SYNOPSIS +.B arch +.SH DESCRIPTION +.B arch +is a deprecated command since util-linux 2.13. Use +.B "uname -m" +or use +.B arch +from the GNU coreutils package. + +On current Linux systems, +.B arch +prints things such as "i386", "i486", "i586", "alpha", "sparc", +"arm", "m68k", "mips", "ppc". +.SH SEE ALSO +.BR uname (1), +.BR uname (2) +.SH AVAILABILITY +The arch command is part of the util-linux package and is available from +ftp://ftp.kernel.org/pub/linux/utils/util-linux/. +.\" +.\" Details: +.\" arch prints the machine part of the system_utsname struct +.\" This struct is defined in version.c, and this field is +.\" initialized with UTS_MACHINE, which is defined as $ARCH +.\" in the main Makefile. +.\" That gives the possibilities +.\" alpha arm i386 m68k mips ppc sparc sparc64 +.\" +.\" If Makefile is not edited, ARCH is guessed by +.\" ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/) +.\" Then how come we get these i586 values? +.\" Well, the routine check_bugs() does system_utsname.machine[1] = '0' + x86; +.\" (called in init/main.c, defined in ./include/asm-i386/bugs.h) diff --git a/sys-utils/arch.c b/sys-utils/arch.c new file mode 100644 index 0000000..a730589 --- /dev/null +++ b/sys-utils/arch.c @@ -0,0 +1,84 @@ +/* arch -- print machine architecture information + * Created: Mon Dec 20 12:27:15 1993 by faith@cs.unc.edu + * Revised: Mon Dec 20 12:29:23 1993 by faith@cs.unc.edu + * Copyright 1993 Rickard E. Faith (faith@cs.unc.edu) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * This command is deprecated. The utility is in maintenance mode, + * meaning we keep them in source tree for backward compatibility + * only. Do not waste time making this command better, unless the + * fix is about security or other very critical issue. + * + * See Documentation/deprecated.txt for more information. + */ + +#include +#include +#include +#include +#include + +#include "c.h" +#include "closestream.h" +#include "nls.h" + +static void __attribute__ ((__noreturn__)) usage(FILE * out) +{ + fprintf(out, USAGE_HEADER); + /* Synopsis */ + fprintf(out, _(" %s [options]\n"), program_invocation_short_name); + fprintf(out, USAGE_OPTIONS); + fprintf(out, USAGE_HELP); + fprintf(out, USAGE_VERSION); + fprintf(out, USAGE_MAN_TAIL("arch(1)")); + exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); +} + +int main(int argc, char **argv) +{ + struct utsname utsbuf; + int ch; + static const struct option longopts[] = { + {"version", no_argument, NULL, 'V'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + atexit(close_stdout); + + while ((ch = getopt_long(argc, argv, "Vh", longopts, NULL)) != -1) + switch (ch) { + case 'V': + printf(UTIL_LINUX_VERSION); + return EXIT_SUCCESS; + case 'h': + usage(stdout); + default: + usage(stderr); + } + + if (uname(&utsbuf)) + err(EXIT_FAILURE, _("uname failed")); + + printf("%s\n", utsbuf.machine); + + return EXIT_SUCCESS; +} diff --git a/sys-utils/chcpu.8 b/sys-utils/chcpu.8 new file mode 100644 index 0000000..d016b86 --- /dev/null +++ b/sys-utils/chcpu.8 @@ -0,0 +1,96 @@ +.TH CHCPU "8" "June 2012" Linux "User Manuals" +.SH NAME +chcpu \- configure CPUs +.SH SYNOPSIS +chcpu +[\-e] [\-d] [\-c] [\-g] +cpu-list +.br +chcpu [\-p] mode +.br +chcpu +\-r +.br +chcpu [\-h] [\-V] +.br +.SH DESCRIPTION +.B chcpu +can modify the state of CPUs. It can enable or disable CPUs, scan for new +CPUs, change the CPU dispatching +.I mode +of the underlying hypervisor, and request CPUs from the hypervisor +(configure) or return CPUs to the hypervisor (deconfigure). +.PP +Some options have a +.I cpu-list +argument. Use this argument to specify a comma-separated list of CPUs. The +list can contain individual CPU addresses or ranges of addresses. For +example, +.B 0,5,7,9-11 +makes the command applicable to the CPUs with the addresses 0, 5, 7, 9, 10, +and 11. +.SH OPTIONS +.TP +.BR \-r , " \-\-rescan" +Trigger a rescan of CPUs. Use this option on systems that do not +automatically detect newly attached CPUs. The Linux kernel then recognizes +the new CPUs. +.TP +.BR \-c , " \-\-configure " \fIcpu-list\fP +Configure all specified CPUs. Configuring a CPU means that the hypervisor +takes a CPU from the CPU pool and assigns it to the virtual hardware on which +your kernel runs. +.TP +.BR \-e , " \-\-enable " \fIcpu-list\fP +Enable all specified CPUs. Enabling a CPU means that the kernel sets it +online. A CPU must be configured, see +.BR -c , +before it can be enabled. +.TP +.BR \-p , " \-\-dispatch " \fImode\fP +Set the CPU dispatching +.I mode +(polarization). This option has an effect only if your hardware architecture +and hypervisor support CPU polarization. Available +.I modes +are: +.RS 14 +.TP 12 +.PD 0 +.B horizontal +The workload is spread across all available CPUs. +.TP 12 +.B vertical +The workload is concentrated on few CPUs. +.RE +.PD 1 +.TP +.BR \-d , " \-\-disable " \fIcpu-list\fP +Disable all specified CPUs. Disabling a CPU means that the kernel sets it +offline. +.TP +.BR \-g , " \-\-deconfigure " \fIcpu-list\fP +Deconfigure all specified CPUs. Deconfiguring a CPU means that the +hypervisor removes the CPU from the virtual hardware on which the Linux +instance runs and returns it to the CPU pool. A CPU must be offline, see +\-d, before it can be deconfigured. +.TP +.BR \-h , " \-\-help" +Display help information and exit. +.TP +.BR \-V , " \-\-version" +Display version information and exit. +.SH AUTHOR +.MT heiko.carstens@de.ibm.com +Heiko Carstens +.ME +.SH COPYRIGHT +Copyright IBM Corp. 2011 +.br +.SH "SEE ALSO" +.BR lscpu (1) +.SH AVAILABILITY +The chcpu command is part of the util-linux package and is available from +.UR ftp://\:ftp.kernel.org\:/pub\:/linux\:/utils\:/util-linux/ +Linux Kernel Archive +.UE . diff --git a/sys-utils/chcpu.c b/sys-utils/chcpu.c new file mode 100644 index 0000000..0209fe9 --- /dev/null +++ b/sys-utils/chcpu.c @@ -0,0 +1,335 @@ +/* + * chcpu - CPU configuration tool + * + * Copyright IBM Corp. 2011 + * Author(s): Heiko Carstens , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cpuset.h" +#include "nls.h" +#include "xalloc.h" +#include "c.h" +#include "strutils.h" +#include "bitops.h" +#include "path.h" +#include "closestream.h" +#include "optutils.h" + +#define EXCL_ERROR "--{configure,deconfigure,disable,dispatch,enable}" + +#define _PATH_SYS_CPU "/sys/devices/system/cpu" +#define _PATH_SYS_CPU_ONLINE _PATH_SYS_CPU "/online" +#define _PATH_SYS_CPU_RESCAN _PATH_SYS_CPU "/rescan" +#define _PATH_SYS_CPU_DISPATCH _PATH_SYS_CPU "/dispatching" + +static cpu_set_t *onlinecpus; +static int maxcpus; + +#define is_cpu_online(cpu) (CPU_ISSET_S((cpu), CPU_ALLOC_SIZE(maxcpus), onlinecpus)) +#define num_online_cpus() (CPU_COUNT_S(CPU_ALLOC_SIZE(maxcpus), onlinecpus)) + +enum { + CMD_CPU_ENABLE = 0, + CMD_CPU_DISABLE, + CMD_CPU_CONFIGURE, + CMD_CPU_DECONFIGURE, + CMD_CPU_RESCAN, + CMD_CPU_DISPATCH_HORIZONTAL, + CMD_CPU_DISPATCH_VERTICAL, +}; + +static int cpu_enable(cpu_set_t *cpu_set, size_t setsize, int enable) +{ + unsigned int cpu; + int online, rc; + int configured = -1; + + for (cpu = 0; cpu < setsize; cpu++) { + if (!CPU_ISSET(cpu, cpu_set)) + continue; + if (!path_exist(_PATH_SYS_CPU "/cpu%d", cpu)) { + printf(_("CPU %d does not exist\n"), cpu); + continue; + } + if (!path_exist(_PATH_SYS_CPU "/cpu%d/online", cpu)) { + printf(_("CPU %d is not hot pluggable\n"), cpu); + continue; + } + online = path_getnum(_PATH_SYS_CPU "/cpu%d/online", cpu); + if ((online == 1) && (enable == 1)) { + printf(_("CPU %d is already enabled\n"), cpu); + continue; + } + if ((online == 0) && (enable == 0)) { + printf(_("CPU %d is already disabled\n"), cpu); + continue; + } + if (path_exist(_PATH_SYS_CPU "/cpu%d/configure", cpu)) + configured = path_getnum(_PATH_SYS_CPU "/cpu%d/configure", cpu); + if (enable) { + rc = path_writestr("1", _PATH_SYS_CPU "/cpu%d/online", cpu); + if ((rc == -1) && (configured == 0)) + printf(_("CPU %d enable failed " + "(CPU is deconfigured)\n"), cpu); + else if (rc == -1) + printf(_("CPU %d enable failed (%m)\n"), cpu); + else + printf(_("CPU %d enabled\n"), cpu); + } else { + if (onlinecpus && num_online_cpus() == 1) { + printf(_("CPU %d disable failed " + "(last enabled CPU)\n"), cpu); + continue; + } + rc = path_writestr("0", _PATH_SYS_CPU "/cpu%d/online", cpu); + if (rc == -1) + printf(_("CPU %d disable failed (%m)\n"), cpu); + else { + printf(_("CPU %d disabled\n"), cpu); + if (onlinecpus) + CPU_CLR(cpu, onlinecpus); + } + } + } + return EXIT_SUCCESS; +} + +static int cpu_rescan(void) +{ + if (!path_exist(_PATH_SYS_CPU_RESCAN)) + errx(EXIT_FAILURE, _("This system does not support rescanning of CPUs")); + if (path_writestr("1", _PATH_SYS_CPU_RESCAN) == -1) + err(EXIT_FAILURE, _("Failed to trigger rescan of CPUs")); + printf(_("Triggered rescan of CPUs\n")); + return EXIT_SUCCESS; +} + +static int cpu_set_dispatch(int mode) +{ + if (!path_exist(_PATH_SYS_CPU_DISPATCH)) + errx(EXIT_FAILURE, _("This system does not support setting " + "the dispatching mode of CPUs")); + if (mode == 0) { + if (path_writestr("0", _PATH_SYS_CPU_DISPATCH) == -1) + err(EXIT_FAILURE, _("Failed to set horizontal dispatch mode")); + printf(_("Successfully set horizontal dispatching mode\n")); + } else { + if (path_writestr("1", _PATH_SYS_CPU_DISPATCH) == -1) + err(EXIT_FAILURE, _("Failed to set vertical dispatch mode")); + printf(_("Successfully set vertical dispatching mode\n")); + } + return EXIT_SUCCESS; +} + +static int cpu_configure(cpu_set_t *cpu_set, size_t setsize, int configure) +{ + unsigned int cpu; + int rc, current; + + for (cpu = 0; cpu < setsize; cpu++) { + if (!CPU_ISSET(cpu, cpu_set)) + continue; + if (!path_exist(_PATH_SYS_CPU "/cpu%d", cpu)) { + printf(_("CPU %d does not exist\n"), cpu); + continue; + } + if (!path_exist(_PATH_SYS_CPU "/cpu%d/configure", cpu)) { + printf(_("CPU %d is not configurable\n"), cpu); + continue; + } + current = path_getnum(_PATH_SYS_CPU "/cpu%d/configure", cpu); + if ((current == 1) && (configure == 1)) { + printf(_("CPU %d is already configured\n"), cpu); + continue; + } + if ((current == 0) && (configure == 0)) { + printf(_("CPU %d is already deconfigured\n"), cpu); + continue; + } + if ((current == 1) && (configure == 0) && onlinecpus && + is_cpu_online(cpu)) { + printf(_("CPU %d deconfigure failed " + "(CPU is enabled)\n"), cpu); + continue; + } + if (configure) { + rc = path_writestr("1", _PATH_SYS_CPU "/cpu%d/configure", cpu); + if (rc == -1) + printf(_("CPU %d configure failed (%m)\n"), cpu); + else + printf(_("CPU %d configured\n"), cpu); + } else { + rc = path_writestr("0", _PATH_SYS_CPU "/cpu%d/configure", cpu); + if (rc == -1) + printf(_("CPU %d deconfigure failed (%m)\n"), cpu); + else + printf(_("CPU %d deconfigured\n"), cpu); + } + } + return EXIT_SUCCESS; +} + +static void cpu_parse(char *cpu_string, cpu_set_t *cpu_set, size_t setsize) +{ + int rc; + + rc = cpulist_parse(cpu_string, cpu_set, setsize, 1); + if (rc == 0) + return; + if (rc == 2) + errx(EXIT_FAILURE, _("invalid CPU number in CPU list: %s"), cpu_string); + errx(EXIT_FAILURE, _("failed to parse CPU list: %s"), cpu_string); +} + +static void __attribute__((__noreturn__)) usage(FILE *out) +{ + fprintf(out, _( + "\nUsage:\n" + " %s [options]\n"), program_invocation_short_name); + + puts(_( "\nOptions:\n" + " -h, --help print this help\n" + " -e, --enable enable cpus\n" + " -d, --disable disable cpus\n" + " -c, --configure configure cpus\n" + " -g, --deconfigure deconfigure cpus\n" + " -p, --dispatch set dispatching mode\n" + " -r, --rescan trigger rescan of cpus\n" + " -V, --version output version information and exit\n")); + + exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); +} + +int main(int argc, char *argv[]) +{ + cpu_set_t *cpu_set; + size_t setsize; + int cmd = -1; + int c; + + static const struct option longopts[] = { + { "configure", required_argument, 0, 'c' }, + { "deconfigure",required_argument, 0, 'g' }, + { "disable", required_argument, 0, 'd' }, + { "dispatch", required_argument, 0, 'p' }, + { "enable", required_argument, 0, 'e' }, + { "help", no_argument, 0, 'h' }, + { "rescan", no_argument, 0, 'r' }, + { "version", no_argument, 0, 'V' }, + { NULL, 0, 0, 0 } + }; + + static const ul_excl_t excl[] = { /* rows and cols in in ASCII order */ + { 'c','d','e','g','p' }, + { 0 } + }; + int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + atexit(close_stdout); + + maxcpus = get_max_number_of_cpus(); + if (maxcpus < 1) + errx(EXIT_FAILURE, _("cannot determine NR_CPUS; aborting")); + if (path_exist(_PATH_SYS_CPU_ONLINE)) + onlinecpus = path_cpulist(maxcpus, _PATH_SYS_CPU_ONLINE); + setsize = CPU_ALLOC_SIZE(maxcpus); + cpu_set = CPU_ALLOC(maxcpus); + if (!cpu_set) + err(EXIT_FAILURE, _("cpuset_alloc failed")); + + while ((c = getopt_long(argc, argv, "c:d:e:g:hp:rV", longopts, NULL)) != -1) { + + err_exclusive_options(c, longopts, excl, excl_st); + + switch (c) { + case 'c': + cmd = CMD_CPU_CONFIGURE; + cpu_parse(argv[optind - 1], cpu_set, setsize); + break; + case 'd': + cmd = CMD_CPU_DISABLE; + cpu_parse(argv[optind - 1], cpu_set, setsize); + break; + case 'e': + cmd = CMD_CPU_ENABLE; + cpu_parse(argv[optind - 1], cpu_set, setsize); + break; + case 'g': + cmd = CMD_CPU_DECONFIGURE; + cpu_parse(argv[optind - 1], cpu_set, setsize); + break; + case 'h': + usage(stdout); + case 'p': + if (strcmp("horizontal", argv[optind - 1]) == 0) + cmd = CMD_CPU_DISPATCH_HORIZONTAL; + else if (strcmp("vertical", argv[optind - 1]) == 0) + cmd = CMD_CPU_DISPATCH_VERTICAL; + else + errx(EXIT_FAILURE, _("unsupported argument: %s"), + argv[optind -1 ]); + break; + case 'r': + cmd = CMD_CPU_RESCAN; + break; + case 'V': + printf(_("%s from %s\n"), program_invocation_short_name, + PACKAGE_STRING); + return EXIT_SUCCESS; + default: + usage(stderr); + } + } + + if ((argc == 1) || (argc != optind)) + usage(stderr); + + switch (cmd) { + case CMD_CPU_ENABLE: + return cpu_enable(cpu_set, maxcpus, 1); + case CMD_CPU_DISABLE: + return cpu_enable(cpu_set, maxcpus, 0); + case CMD_CPU_CONFIGURE: + return cpu_configure(cpu_set, maxcpus, 1); + case CMD_CPU_DECONFIGURE: + return cpu_configure(cpu_set, maxcpus, 0); + case CMD_CPU_RESCAN: + return cpu_rescan(); + case CMD_CPU_DISPATCH_HORIZONTAL: + return cpu_set_dispatch(0); + case CMD_CPU_DISPATCH_VERTICAL: + return cpu_set_dispatch(1); + } + return EXIT_SUCCESS; +} diff --git a/sys-utils/ctrlaltdel.8 b/sys-utils/ctrlaltdel.8 new file mode 100644 index 0000000..14cf3dd --- /dev/null +++ b/sys-utils/ctrlaltdel.8 @@ -0,0 +1,51 @@ +.\" Copyright 1992, 1993 Rickard E. Faith (faith@cs.unc.edu) +.\" May be distributed under the GNU General Public License +.TH CTRLALTDEL 8 "August 2011" "util-linux" "System Administration" +.SH NAME +ctrlaltdel \- set the function of the Ctrl-Alt-Del combination +.SH SYNOPSIS +.BR "ctrlaltdel hard" | soft +.SH DESCRIPTION +Based on examination of the +.I linux/kernel/sys.c +code, it is clear that there are two supported functions that the +Ctrl-Alt-Del sequence can perform: a +.I hard +reset, which immediately reboots the computer without calling +.BR sync (2) +and without any other preparation; and a +.I soft +reset, which sends the SIGINT (interrupt) signal to the +.B init +process (this is always the process with PID 1). If this option is used, +the +.BR init (8) +program must support this feature. Since there are now several +.BR init (8) +programs in the Linux community, please consult the documentation for the +version that you are currently using. +.PP +.B ctrlaltdel +is usually used in the +.I /etc/rc.local +file. +.SH OPTIONS +.TP +\fB\-V\fR, \fB\-\-version\fR +Output version information and exit. +.TP +\fB\-h\fR, \fB\-\-help\fR +Display help and exit. +.SH FILES +.I /etc/rc.local +.SH "SEE ALSO" +.BR init (8) +.SH AUTHOR +.UR poe@daimi.aau.dk +Peter Orbaek +.UE +.SH AVAILABILITY +The ctrlaltdel command is part of the util-linux package and is available from +.UR ftp://\:ftp.kernel.org\:/pub\:/linux\:/utils\:/util-linux/ +Linux Kernel Archive +.UE . diff --git a/sys-utils/ctrlaltdel.c b/sys-utils/ctrlaltdel.c new file mode 100644 index 0000000..2ad56a1 --- /dev/null +++ b/sys-utils/ctrlaltdel.c @@ -0,0 +1,69 @@ +/* + * ctrlaltdel.c - Set the function of the Ctrl-Alt-Del combination + * Created 4-Jul-92 by Peter Orbaek + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + */ + +#include +#include +#include +#include +#include +#include "linux_reboot.h" +#include "nls.h" +#include "c.h" +#include "closestream.h" + +static void __attribute__ ((__noreturn__)) usage(FILE * out) +{ + fprintf(out, USAGE_HEADER); + fprintf(out, _(" %s \n"), program_invocation_short_name); + fprintf(out, USAGE_OPTIONS); + fprintf(out, USAGE_HELP); + fprintf(out, USAGE_VERSION); + fprintf(out, USAGE_MAN_TAIL("ctrlaltdel(8)")); + exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); +} + +int main(int argc, char **argv) +{ + int ch; + static const struct option longopts[] = { + {"version", no_argument, NULL, 'V'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + atexit(close_stdout); + + while ((ch = getopt_long(argc, argv, "Vh", longopts, NULL)) != -1) + switch (ch) { + case 'V': + printf(UTIL_LINUX_VERSION); + return EXIT_SUCCESS; + case 'h': + usage(stdout); + default: + usage(stderr); + } + + if (geteuid()) + errx(EXIT_FAILURE, + _("You must be root to set the Ctrl-Alt-Del behaviour")); + + if (argc == 2 && !strcmp("hard", argv[1])) { + if (my_reboot(LINUX_REBOOT_CMD_CAD_ON) < 0) + err(EXIT_FAILURE, "reboot"); + } else if (argc == 2 && !strcmp("soft", argv[1])) { + if (my_reboot(LINUX_REBOOT_CMD_CAD_OFF) < 0) + err(EXIT_FAILURE, "reboot"); + } else { + usage(stderr); + } + + return EXIT_SUCCESS; +} diff --git a/sys-utils/cyclades.h b/sys-utils/cyclades.h new file mode 100644 index 0000000..afcf600 --- /dev/null +++ b/sys-utils/cyclades.h @@ -0,0 +1,16 @@ +struct cyclades_monitor { + unsigned long int_count; + unsigned long char_count; + unsigned long char_max; + unsigned long char_last; +}; + +#define CYGETMON 0x435901 +#define CYGETTHRESH 0x435902 +#define CYSETTHRESH 0x435903 +#define CYGETDEFTHRESH 0x435904 +#define CYSETDEFTHRESH 0x435905 +#define CYGETTIMEOUT 0x435906 +#define CYSETTIMEOUT 0x435907 +#define CYGETDEFTIMEOUT 0x435908 +#define CYSETDEFTIMEOUT 0x435909 diff --git a/sys-utils/cytune.8 b/sys-utils/cytune.8 new file mode 100644 index 0000000..fd82391 --- /dev/null +++ b/sys-utils/cytune.8 @@ -0,0 +1,194 @@ +.\" cytune.8 -- +.\" Created: Sat Mar 4 17:44:53 1995 by faith@cs.unc.edu +.\" Update: Sat Mar 4 18:22:24 1995 by faith@cs.unc.edu +.\" Update: Sun Mar 5 06:40:12 1995 by njs@scifi.emi.net +.\" Copyright 1995 Rickard E. Faith (faith@cs.unc.edu) +.\" +.\" Permission is granted to make and distribute verbatim copies of this +.\" manual provided the copyright notice and this permission notice are +.\" preserved on all copies. +.\" +.\" Permission is granted to copy and distribute modified versions of this +.\" manual under the conditions for verbatim copying, provided that the +.\" entire resulting derived work is distributed under the terms of a +.\" permission notice identical to this one +.\" +.\" Since the Linux kernel and libraries are constantly changing, this +.\" manual page may be incorrect or out-of-date. The author(s) assume no +.\" responsibility for errors or omissions, or for damages resulting from +.\" the use of the information contained herein. The author(s) may not +.\" have taken the same level of care in the production of this manual, +.\" which is licensed free of charge, as they might when working +.\" professionally. +.\" +.\" Formatted or processed versions of this manual, if unaccompanied by +.\" the source, must acknowledge the copyright and authors of this work. +.\" " +.TH CYTUNE 8 "September 2011" "util-linux" "System Administration" +.SH NAME +cytune \- tune driver parameters for Cyclades-Z multiport serial card +.SH SYNOPSIS +.B cytune +[options] tty [...] +.SH DESCRIPTION +.B cytune +queries and modifies the interruption threshold for the Cyclades driver. +Each serial line on a Cyclades card has a 12-byte FIFO for input (and another +12-byte FIFO for output). The "threshold" specifies how many input +characters must be present in the FIFO before an interruption is raised. +When a Cyclades tty is opened, this threshold is set to a default value based +on baud rate: +.sp +.RS +Baud Threshold +.sp +50-4800 10 +.br +9600 8 +.br +19200 4 +.br +38400 2 +.br +57600-150000 1 +.RE +.PP +If the threshold is set too low, the large number of interruptions can load +the machine and decrease overall system throughput. If the threshold is set +too high, the FIFO buffer can overflow, and characters will be lost. Slower +machines, however, may not be able to deal with the interrupt load, and will +require that the threshold be adjusted upwards. +.PP +If the cyclades driver was compiled with +.B ENABLE_MONITORING +defined, the cytune command can be used with the +.B \-q +option to report interrupts over the monitoring interval and characters +transferred over the monitoring interval. It will also report the state of +the FIFO. The maximum number of characters in the FIFO when an interrupt +occurred, the instantaneous count of characters in the FIFO, and how many +characters are now in the FIFO are reported. This output might look like +this: +.sp +.RS +/dev/cubC0: 830 ints, 9130 chars; fifo: 11 threshold, 11 max, 11 now +.br + 166.259866 interrupts/second, 1828.858521 characters/second +.RE +.PP +This output indicates that for this monitoring period, the interrupts were +always being handled within one character time, because +.B max +never rose above +.BR threshold . +This is good, and you can probably run this way, provided that a large number +of samples come out this way. You will lose characters if you overrun the +FIFO, as the Cyclades hardware does not seem to support the RTS RS-232 signal +line for hardware flow control from the DCE to the DTE. +.PP +In query mode +.B cytune +will produce a summary report when ended with a SIGINT or when the threshold +or timeout is changed. +.PP +There may be a responsiveness vs. throughput tradeoff. The Cyclades card, at +the higher speeds, is capable of putting a very high interrupt load on the +system. This will reduce the amount of CPU time available for other tasks on +your system. However, the time it takes to respond to a single character may +be increased if you increase the threshold. This might be noticed by +monitoring +.BR ping (8) +times on a SLIP link controlled by a Cyclades card. If your SLIP link is +generally used for interactive work such as +.BR telnet (1), +you may want to leave the threshold low, so that characters are responded to +as quickly as possible. If your SLIP link is generally used for file +transfer, WWW, and the like, setting the FIFO to a high value is likely to +reduce the load on your system while not significantly affecting throughput. +Alternatively, see the +.B \-t +or +.B \-T +options to adjust the time that the cyclades waits before flushing its +buffer. Units are 5ms. +.PP +If you are running a mouse on a Cyclades port, it is likely that you would +want to maintain the threshold and timeout at a low value. +.PP +.SH OPTIONS +.TP +\fB\-s\fR, \fB\-\-set\-threshold\fR \fIvalue\fR +Set the current threshold to +.I value +characters. Note that if the +.I tty +is not being held open by another process, the threshold will be reset on the +next open. Only values between 1 and 12, inclusive, are permitted. +.TP +\fB\-t\fR, \fB\-\-set\-flush\fR \fIvalue\fR +Set the current flush timeout to +.I value +units. Note that if the +.I tty +is not being held open by another process, the threshold will be reset on the +next open. Only values between 0 and 255, inclusive, are permitted. Setting +.I value +to zero forces the default, currently 0x20 (160ms), but soon to be 0x02 +(10ms). Units are 5 ms. +.TP +\fB\-g\fR, \fB\-\-get\-threshold\fR +Get the current threshold and timeout. +.TP +\fB\-S\fR, \fB\-\-set\-default\-threshold\fR \fIvalue\fR +Set the default threshold to +.I value +characters. When the +.I tty +is next opened, this value will be used instead of the default. Only values +between 1 and 12, inclusive, are permitted. +.TP +\fB\-T\fR, \fB\-\-set\-default\-flush\fR \fIvalue\fR +Set the default flush timeout to +.I value +units. When the +.I tty +is next opened, this value will be used instead of the default. If +.I value +is zero, then the the value will default to 0x20 (160ms), soon to be 0x02 +(10ms). +.TP +\fB\-G\fR, \fB\-\-get\-glush\fR +Get the default threshold and flush timeout values. +.TP +\fB\-q\fR, \fB\-\-stats\fR +Gather statistics about the +.IR tty . +The results are only valid if the Cyclades driver has been compiled with +.B ENABLE_MONITORING +defined. This is probably not the default. +.TP +\fB\-i\fR, \fB\-\-interval\fR \fIinterval\fR +Statistics will be gathered every +.I interval +seconds. +.SH BUGS +If you run two copies of +.B cytune +at the same time to report statistics about the same port, the 'ints', 'chars', +and 'max' value will be reset and not reported correctly. +.B cytune +should prevent this, but does not. +.\" .SH AUTHOR +.\" Nick Simicich (njs@scifi.emi.net), with modifications by +.\" Rik Faith (faith@cs.unc.edu) +.SH FILES +.I /dev/ttyC[0-8] +.br +.I /dev/cubC[0-8] +.SH "SEE ALSO" +.BR setserial (8) +.SH AVAILABILITY +The cytune command is part of the util-linux package and is available from +.UR ftp://\:ftp.kernel.org\:/pub\:/linux\:/utils\:/util-linux/ +Linux Kernel Archive +.UE . diff --git a/sys-utils/cytune.c b/sys-utils/cytune.c new file mode 100644 index 0000000..9b39726 --- /dev/null +++ b/sys-utils/cytune.c @@ -0,0 +1,461 @@ +/* cytune.c -- Tune Cyclades driver + * + * Copyright 1995 Nick Simicich (njs@scifi.emi.net) + * Modifications by Rik Faith (faith@cs.unc.edu) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Nick Simicich + * 4. Neither the name of the Nick Simicich nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY NICK SIMICICH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL NICK SIMICICH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + /* + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * Sun Mar 21 1999 - Arnaldo Carvalho de Melo + * - fixed strerr(errno) in gettext calls + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "c.h" +#include "cyclades.h" +#include "closestream.h" +#include "strutils.h" + +#if 0 +# ifndef XMIT +# include +# if LINUX_VERSION_CODE > 66056 +# define XMIT +# endif +# endif +#endif + +#include "xalloc.h" +#include "nls.h" +/* Until it gets put in the kernel, toggle by hand. */ +#undef XMIT + +struct cyclades_control { + struct cyclades_monitor c; + int cfile; + int maxmax; + double maxtran; + double maxxmit; + unsigned long threshold_value; + unsigned long timeout_value; +}; +struct cyclades_control *cmon; +int cmon_index; + +static int global_argc, global_optind; +static char ***global_argv; + +#define mvtime(tvpto, tvpfrom) (((tvpto)->tv_sec = (tvpfrom)->tv_sec),(tvpto)->tv_usec = (tvpfrom)->tv_usec) + +static void __attribute__ ((__noreturn__)) usage(FILE * out) +{ + fprintf(out, USAGE_HEADER); + fprintf(out, _(" %s [options] [...]\n"), program_invocation_short_name); + fprintf(out, USAGE_OPTIONS); + fprintf(out, _(" -s, --set-threshold set interruption threshold value\n")); + fprintf(out, _(" -g, --get-threshold display current threshold value\n")); + fprintf(out, _(" -S, --set-default-threshold set default threshold value\n")); + fprintf(out, _(" -t, --set-flush set flush timeout to value\n")); + fprintf(out, _(" -G, --get-glush display default flush timeout value\n")); + fprintf(out, _(" -T, --set-default-flush set the default flush timeout to value\n")); + fprintf(out, _(" -q, --stats display statistics about the tty\n")); + fprintf(out, _(" -i, --interval gather statistics every interval\n")); + fprintf(out, USAGE_SEPARATOR); + fprintf(out, USAGE_HELP); + fprintf(out, USAGE_VERSION); + fprintf(out, USAGE_MAN_TAIL("cytune(8)")); + + exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); +} + +static inline double dtime(struct timeval *tvpnew, struct timeval *tvpold) +{ + double diff; + diff = (double)tvpnew->tv_sec - (double)tvpold->tv_sec; + diff += ((double)tvpnew->tv_usec - (double)tvpold->tv_usec) / 1000000; + return diff; +} + +static void summary(int sig) +{ + struct cyclades_control *cc; + int argc, local_optind; + char **argv; + int i; + + argc = global_argc; + argv = *global_argv; + local_optind = global_optind; + + if (sig > 0) { + for (i = local_optind; i < argc; i++) { + cc = &cmon[cmon_index]; + warnx(_("File %s, For threshold value %lu, Maximum characters in fifo were %d,\n" + "and the maximum transfer rate in characters/second was %f"), + argv[i], cc->threshold_value, cc->maxmax, + cc->maxtran); + } + exit(EXIT_SUCCESS); + } + cc = &cmon[cmon_index]; + if (cc->threshold_value > 0 && sig != -1) { + warnx(_("File %s, For threshold value %lu and timeout value %lu, Maximum characters in fifo were %d,\n" + "and the maximum transfer rate in characters/second was %f"), + argv[cmon_index + local_optind], cc->threshold_value, + cc->timeout_value, cc->maxmax, cc->maxtran); + } + cc->maxmax = 0; + cc->maxtran = 0.0; + cc->threshold_value = 0; + cc->timeout_value = 0; +} + +static void query_tty_stats(int argc, char **argv, int interval, int numfiles, + unsigned long *threshold_value, + unsigned long *timeout_value) +{ + struct cyclades_monitor cywork; + struct timeval lasttime, thistime; + struct timezone tz = { 0, 0 }; + int i; + double diff; + double xfer_rate; +#ifdef XMIT + double xmit_rate; +#endif + + cmon = xmalloc(sizeof(struct cyclades_control) * numfiles); + + if (signal(SIGINT, summary) || + signal(SIGQUIT, summary) || signal(SIGTERM, summary)) + err(EXIT_FAILURE, _("cannot set signal handler")); + if (gettimeofday(&lasttime, &tz)) + err(EXIT_FAILURE, _("gettimeofday failed")); + + for (i = optind; i < argc; i++) { + cmon_index = i - optind; + cmon[cmon_index].cfile = open(argv[i], O_RDONLY); + if (cmon[cmon_index].cfile == -1) + err(EXIT_FAILURE, _("cannot open %s"), argv[i]); + if (ioctl + (cmon[cmon_index].cfile, CYGETMON, &cmon[cmon_index].c)) + err(EXIT_FAILURE, _("cannot issue CYGETMON on %s"), + argv[i]); + summary(-1); + if (ioctl + (cmon[cmon_index].cfile, CYGETTHRESH, &threshold_value)) + err(EXIT_FAILURE, _("cannot get threshold for %s"), + argv[i]); + if (ioctl(cmon[cmon_index].cfile, CYGETTIMEOUT, &timeout_value)) + err(EXIT_FAILURE, _("cannot get timeout for %s"), + argv[i]); + } + while (1) { + sleep(interval); + + if (gettimeofday(&thistime, &tz)) + err(EXIT_FAILURE, _("gettimeofday failed")); + diff = dtime(&thistime, &lasttime); + mvtime(&lasttime, &thistime); + + for (i = optind; i < argc; i++) { + cmon_index = i - optind; + if (ioctl(cmon[cmon_index].cfile, CYGETMON, &cywork)) + err(EXIT_FAILURE, + _("cannot issue CYGETMON on %s"), argv[i]); + if (ioctl + (cmon[cmon_index].cfile, CYGETTHRESH, + &threshold_value)) + err(EXIT_FAILURE, + _("cannot get threshold for %s"), argv[i]); + if (ioctl + (cmon[cmon_index].cfile, CYGETTIMEOUT, + &timeout_value)) + err(EXIT_FAILURE, + _("cannot get timeout for %s"), argv[i]); + + xfer_rate = cywork.char_count / diff; +#ifdef XMIT + xmit_rate = cywork.send_count / diff; +#endif + if ((*threshold_value) != + cmon[cmon_index].threshold_value + || (*timeout_value) != + cmon[cmon_index].timeout_value) { + summary(-2); + /* Note that the summary must come before the + * setting of threshold_value */ + cmon[cmon_index].threshold_value = + (*threshold_value); + cmon[cmon_index].timeout_value = + (*timeout_value); + } else { + /* Don't record this first cycle after change */ + if (xfer_rate > cmon[cmon_index].maxtran) + cmon[cmon_index].maxtran = xfer_rate; +#ifdef XMIT + if (xmit_rate > cmon[cmon_index].maxxmit) + cmon[cmon_index].maxxmit = xmit_rate; +#endif + if (cmon[cmon_index].maxmax < 0 || + cywork.char_max > + (unsigned long)cmon[cmon_index].maxmax) + cmon[cmon_index].maxmax = + cywork.char_max; + } + +#ifdef XMIT + printf(_("%s: %lu ints, %lu/%lu chars; fifo: %lu thresh, %lu tmout, " + "%lu max, %lu now\n"), argv[i], + cywork.int_count, cywork.char_count, + cywork.send_count, *threshold_value, + *timeout_value, cywork.char_max, + cywork.char_last); + printf(_(" %f int/sec; %f rec, %f send (char/sec)\n"), + cywork.int_count / diff, xfer_rate, xmit_rate); +#else + printf(_("%s: %lu ints, %lu chars; fifo: %lu thresh, %lu tmout, " + "%lu max, %lu now\n"), argv[i], + cywork.int_count, cywork.char_count, + *threshold_value, *timeout_value, cywork.char_max, + cywork.char_last); + printf(_(" %f int/sec; %f rec (char/sec)\n"), + cywork.int_count / diff, xfer_rate); +#endif + memcpy(&cmon[cmon_index].c, &cywork, + sizeof(struct cyclades_monitor)); + } + } + + free(cmon); + return; +} + +int main(int argc, char **argv) +{ + int query = 0; + int interval = 1; + int set = 0; + int set_val = -1; + int get = 0; + int set_def = 0; + int set_def_val = -1; + int get_def = 0; + int set_time = 0; + int set_time_val = -1; + int set_def_time = 0; + int set_def_time_val = -1; + int errflg = 0; + int file; + int numfiles; + int i; + unsigned long threshold_value; + unsigned long timeout_value; + + static const struct option longopts[] = { + {"set-threshold", required_argument, NULL, 's'}, + {"get-threshold", no_argument, NULL, 'g'}, + {"set-default-threshold", required_argument, NULL, 'S'}, + {"set-flush", required_argument, NULL, 't'}, + {"get-flush", no_argument, NULL, 'G'}, + {"set-default-flush", required_argument, NULL, 'T'}, + {"stats", no_argument, NULL, 'q'}, + {"interval", required_argument, NULL, 'i'}, + {"version", no_argument, NULL, 'V'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + /* For signal routine. */ + global_argc = argc; + global_argv = &argv; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + atexit(close_stdout); + + while ((i = + getopt_long(argc, argv, "qs:S:t:T:gGi:Vh", longopts, + NULL)) != -1) { + switch (i) { + case 'q': + query = 1; + break; + case 'i': + interval = strtou32_or_err(optarg, + _("Invalid interval value")); + if (interval < 1) { + warnx(_("Invalid interval value: %d"), + interval); + errflg++; + } + break; + case 's': + ++set; + set_val = strtou32_or_err(optarg, _("Invalid set value")); + if (set_val < 1 || 12 < set_val) { + warnx(_("Invalid set value: %d"), set_val); + errflg++; + } + break; + case 'S': + ++set_def; + set_def_val = strtou32_or_err(optarg, + _("Invalid default value")); + if (set_def_val < 0 || 12 < set_def_val) { + warnx(_("Invalid default value: %d"), + set_def_val); + errflg++; + } + break; + case 't': + ++set_time; + set_time_val = strtou32_or_err(optarg, + _("Invalid set time value")); + if (set_time_val < 1 || 255 < set_time_val) { + warnx(_("Invalid set time value: %d"), + set_time_val); + errflg++; + } + break; + case 'T': + ++set_def_time; + set_def_time_val = strtou32_or_err(optarg, + _("Invalid default time value")); + if (set_def_time_val < 0 || 255 < set_def_time_val) { + warnx(_("Invalid default time value: %d"), + set_def_time_val); + errflg++; + } + break; + case 'g': + ++get; + break; + case 'G': + ++get_def; + break; + case 'V': + printf(_("%s from %s\n"), program_invocation_short_name, + PACKAGE_STRING); + return EXIT_SUCCESS; + case 'h': + usage(stdout); + default: + usage(stderr); + } + } + numfiles = argc - optind; + + if (errflg + || (numfiles == 0) + || (!query && !set && !set_def && !get && !get_def && !set_time && !set_def_time) + || (set && set_def) + || (set_time && set_def_time) + || (get && get_def)) + usage(stderr); + + /* For signal routine. */ + global_optind = optind; + + if (set || set_def) { + for (i = optind; i < argc; i++) { + file = open(argv[i], O_RDONLY); + if (file == -1) + err(EXIT_FAILURE, _("cannot open %s"), argv[i]); + if (ioctl(file, + set ? CYSETTHRESH : CYSETDEFTHRESH, + set ? set_val : set_def_val)) + err(EXIT_FAILURE, + _("cannot set %s to threshold %d"), argv[i], + set ? set_val : set_def_val); + close(file); + } + } + if (set_time || set_def_time) { + for (i = optind; i < argc; i++) { + file = open(argv[i], O_RDONLY); + if (file == -1) + err(EXIT_FAILURE, _("cannot open %s"), argv[i]); + if (ioctl(file, + set_time ? CYSETTIMEOUT : CYSETDEFTIMEOUT, + set_time ? set_time_val : set_def_time_val)) + err(EXIT_FAILURE, + _("cannot set %s to time threshold %d"), + argv[i], + set_time ? set_time_val : set_def_time_val); + close(file); + } + } + + if (get || get_def) { + for (i = optind; i < argc; i++) { + file = open(argv[i], O_RDONLY); + if (file == -1) + err(EXIT_FAILURE, _("cannot open %s"), argv[i]); + if (ioctl + (file, get ? CYGETTHRESH : CYGETDEFTHRESH, + &threshold_value)) + err(EXIT_FAILURE, + _("cannot get threshold for %s"), argv[i]); + if (ioctl + (file, get ? CYGETTIMEOUT : CYGETDEFTIMEOUT, + &timeout_value)) + err(EXIT_FAILURE, + _("cannot get timeout for %s"), argv[i]); + close(file); + if (get) + printf(_("%s: %ld current threshold and %ld current timeout\n"), + argv[i], threshold_value, timeout_value); + else + printf(_("%s: %ld default threshold and %ld default timeout\n"), + argv[i], threshold_value, timeout_value); + } + } + + if (!query) + return EXIT_SUCCESS; + + query_tty_stats(argc, argv, interval, numfiles, &threshold_value, &timeout_value); + + return EXIT_SUCCESS; +} diff --git a/sys-utils/dmesg.1 b/sys-utils/dmesg.1 new file mode 100644 index 0000000..6a8374a --- /dev/null +++ b/sys-utils/dmesg.1 @@ -0,0 +1,162 @@ +.\" Copyright 1993 Rickard E. Faith (faith@cs.unc.edu) +.\" May be distributed under the GNU General Public License +.TH DMESG "1" "July 2012" "util-linux" "User Commands" +.SH NAME +dmesg \- print or control the kernel ring buffer +.SH SYNOPSIS +.B dmesg +.RB [ options ] +.sp +dmesg \-\-clear +.br +dmesg \-\-read-clear [options] +.br +dmesg \-\-console-level level +.br +dmesg \-\-console-on +.br +dmesg \-\-console-off +.SH DESCRIPTION +.B dmesg +is used to examine or control the kernel ring buffer. +.PP +The default action is to read all messages from kernel ring buffer. +.SH OPTIONS +The \-\-clear, \-\-read-clear, \-\-console-on, \-\-console-off and +\-\-console-level options are mutually exclusive. +.PP +.IP "\fB\-C\fR, \fB\-\-clear\fR" +Clear the ring buffer. +.IP "\fB\-c\fR, \fB\-\-read-clear\fR" +Clear the ring buffer contents after printing. +.IP "\fB\-D\fR, \fB\-\-console-off\fR" +Disable printing messages to the console. +.IP "\fB\-d\fR, \fB\-\-show-delta\fR" +Display the timestamp and time delta spent between messages. If used +together with +.B \-\-notime +then only the time delta without the timestamp is printed. +.IP "\fB\-e\fR, \fB\-\-reltime\fR" +Display the local time and delta in human readable format. +.IP "\fB\-E\fR, \fB\-\-console-on\fR" +Enable printing messages to the console. +.IP "\fB\-F\fR, \fB\-\-file \fIfile\fR" +Read log from +.IR file . +.IP "\fB\-f\fR, \fB\-\-facility \fIlist\fR" +Restrict output to defined (comma separated) +.I list +of facilities. For example +.PP +.RS 14 +dmesg \-\-facility=daemon +.RE +.IP +will print messages from system daemons only. For all supported facilities +see +.B dmesg \-\-help +output. +.IP "\fB\-h\fR, \fB\-\-help\fR" +Print a help text and exit. +.IP "\fB\-k\fR, \fB\-\-kernel\fR" +Print kernel messages. +.IP "\fB\-l\fR, \fB\-\-level \fIlist\fR" +Restrict output to defined (comma separated) +.I list +of levels. For example +.PP +.RS 14 +dmesg \-\-level=err,warn +.RE +.IP +will print error and warning messages only. For all supported levels see +.B dmesg \-\-help +output. +.IP "\fB\-n\fR, \fB\-\-console-level \fIlevel\fR +Set the +.I level +at which logging of messages is done to the console. The +.I level +is a level number or abbreviation of the level name. For all supported +levels see +.B dmesg \-\-help +output. +.sp +For example, +.B \-n 1 +or +.B \-n alert +prevents all messages, except emergency (panic) messages, from appearing on +the console. All levels of messages are still written to +.IR /proc/kmsg , +so +.BR syslogd (8) +can still be used to control exactly where kernel messages appear. When the +.B \-n +option is used, +.B dmesg +will +.I not +print or clear the kernel ring buffer. +.IP "\fB\-r\fR, \fB\-\-raw\fR" +Print the raw message buffer, i.e., do not strip the log level prefixes. + +Note that the real raw format depends on method how +.BR dmesg (1) +reads kernel messages. The /dev/kmsg uses different format than +.BR syslog (2) . +For backward compatibility +.BR dmesg (1) +returns data always in +.BR syslog (2) +format. The real raw data from /dev/kmsg is possible to read for example by +command 'dd if=/dev/kmsg iflag=nonblock'. +.IP "\fB\-S\fR, \fB\-\-syslog\fR" +Force to use +.BR syslog (2) +kernel interface to read kernel messages. The default is to use /dev/kmsg rather +than +.BR syslog (2) +since kernel 3.5.0. +.IP "\fB\-s\fR, \fB\-\-buffer-size \fIsize\fR +Use a buffer of +.I size +to query the kernel ring buffer. This is 16392 by default. (The default +kernel syslog buffer size was 4096 at first, 8192 since 1.3.54, 16384 since +2.1.113.) If you have set the kernel buffer to be larger than the default +then this option can be used to view the entire buffer. +.IP "\fB\-T\fR, \fB\-\-ctime\fR" +Print human readable timestamps. The timestamp could be inaccurate! +.IP +The +.B time +source used for the logs is +.B not updated after +system +.BR SUSPEND / RESUME . +.IP "\fB\-t\fR, \fB\-\-notime\fR" +Do not print kernel's timestamps. +.IP "\fB\-u\fR, \fB\-\-userspace\fR" +Print userspace messages. +.IP "\fB\-V\fR, \fB\-\-version\fR" +Output version information and exit. +.IP "\fB\-w\fR, \fB\-\-follow\fR" +Wait for new messages. This feature is supported on systems with readable +/dev/kmsg only (since kernel 3.5.0). +.IP "\fB\-x\fR, \fB\-\-decode\fR" +Decode facility and level (priority) number to human readable prefixes. +.SH SEE ALSO +.BR syslogd (8) +.SH AUTHORS +.MT kzak@redhat.com +Karel Zak +.ME +.br +.MT tytso@athena.mit.edu +Theodore Ts'o +.ME +.SH AVAILABILITY +The dmesg command is part of the util-linux package and is available from +.UR ftp://\:ftp.kernel.org\:/pub\:/linux\:/utils\:/util-linux/ +Linux Kernel Archive +.UE . diff --git a/sys-utils/dmesg.c b/sys-utils/dmesg.c new file mode 100644 index 0000000..0ee03ee --- /dev/null +++ b/sys-utils/dmesg.c @@ -0,0 +1,1214 @@ +/* + * dmesg.c -- Print out the contents of the kernel ring buffer + * + * Copyright (C) 1993 Theodore Ts'o + * Copyright (C) 2011 Karel Zak + * + * This program comes with ABSOLUTELY NO WARRANTY. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "c.h" +#include "nls.h" +#include "strutils.h" +#include "xalloc.h" +#include "widechar.h" +#include "all-io.h" +#include "bitops.h" +#include "closestream.h" +#include "optutils.h" +#include "mangle.h" + +/* Close the log. Currently a NOP. */ +#define SYSLOG_ACTION_CLOSE 0 +/* Open the log. Currently a NOP. */ +#define SYSLOG_ACTION_OPEN 1 +/* Read from the log. */ +#define SYSLOG_ACTION_READ 2 +/* Read all messages remaining in the ring buffer. (allowed for non-root) */ +#define SYSLOG_ACTION_READ_ALL 3 +/* Read and clear all messages remaining in the ring buffer */ +#define SYSLOG_ACTION_READ_CLEAR 4 +/* Clear ring buffer. */ +#define SYSLOG_ACTION_CLEAR 5 +/* Disable printk's to console */ +#define SYSLOG_ACTION_CONSOLE_OFF 6 +/* Enable printk's to console */ +#define SYSLOG_ACTION_CONSOLE_ON 7 +/* Set level of messages printed to console */ +#define SYSLOG_ACTION_CONSOLE_LEVEL 8 +/* Return number of unread characters in the log buffer */ +#define SYSLOG_ACTION_SIZE_UNREAD 9 +/* Return size of the log buffer */ +#define SYSLOG_ACTION_SIZE_BUFFER 10 + +/* + * Priority and facility names + */ +struct dmesg_name { + const char *name; + const char *help; +}; + +/* + * Priority names -- based on sys/syslog.h + */ +static const struct dmesg_name level_names[] = +{ + [LOG_EMERG] = { "emerg", N_("system is unusable") }, + [LOG_ALERT] = { "alert", N_("action must be taken immediately") }, + [LOG_CRIT] = { "crit", N_("critical conditions") }, + [LOG_ERR] = { "err", N_("error conditions") }, + [LOG_WARNING] = { "warn", N_("warning conditions") }, + [LOG_NOTICE] = { "notice",N_("normal but significant condition") }, + [LOG_INFO] = { "info", N_("informational") }, + [LOG_DEBUG] = { "debug", N_("debug-level messages") } +}; + +/* + * sys/syslog.h uses (f << 3) for all facility codes. + * We want to use the codes as array idexes, so shift back... + * + * Note that libc LOG_FAC() macro returns the base codes, not the + * shifted code :-) + */ +#define FAC_BASE(f) ((f) >> 3) + +static const struct dmesg_name facility_names[] = +{ + [FAC_BASE(LOG_KERN)] = { "kern", N_("kernel messages") }, + [FAC_BASE(LOG_USER)] = { "user", N_("random user-level messages") }, + [FAC_BASE(LOG_MAIL)] = { "mail", N_("mail system") }, + [FAC_BASE(LOG_DAEMON)] = { "daemon", N_("system daemons") }, + [FAC_BASE(LOG_AUTH)] = { "auth", N_("security/authorization messages") }, + [FAC_BASE(LOG_SYSLOG)] = { "syslog", N_("messages generated internally by syslogd") }, + [FAC_BASE(LOG_LPR)] = { "lpr", N_("line printer subsystem") }, + [FAC_BASE(LOG_NEWS)] = { "news", N_("network news subsystem") }, + [FAC_BASE(LOG_UUCP)] = { "uucp", N_("UUCP subsystem") }, + [FAC_BASE(LOG_CRON)] = { "cron", N_("clock daemon") }, + [FAC_BASE(LOG_AUTHPRIV)] = { "authpriv", N_("security/authorization messages (private)") }, + [FAC_BASE(LOG_FTP)] = { "ftp", N_("ftp daemon") }, +}; + +/* supported methods to read message buffer + */ +enum { + DMESG_METHOD_KMSG, /* read messages from /dev/kmsg (default) */ + DMESG_METHOD_SYSLOG, /* klogctl() buffer */ + DMESG_METHOD_MMAP /* mmap file with records (see --file) */ +}; + +struct dmesg_control { + /* bit arrays -- see include/bitops.h */ + char levels[ARRAY_SIZE(level_names) / NBBY + 1]; + char facilities[ARRAY_SIZE(facility_names) / NBBY + 1]; + + struct timeval lasttime; /* last printed timestamp */ + struct tm lasttm; /* last localtime */ + time_t boot_time; /* system boot time */ + + int action; /* SYSLOG_ACTION_* */ + int method; /* DMESG_METHOD_* */ + + size_t bufsize; /* size of syslog buffer */ + + int kmsg; /* /dev/kmsg file descriptor */ + ssize_t kmsg_first_read;/* initial read() return code */ + char kmsg_buf[BUFSIZ];/* buffer to read kmsg data */ + + /* + * For the --file option we mmap whole file. The unnecessary (already + * printed) pages are always unmapped. The result is that we have in + * memory only the currently used page(s). + */ + char *filename; + char *mmap_buff; + size_t pagesize; + + unsigned int follow:1, /* wait for new messages */ + raw:1, /* raw mode */ + fltr_lev:1, /* filter out by levels[] */ + fltr_fac:1, /* filter out by facilities[] */ + decode:1, /* use "facility: level: " prefix */ + notime:1, /* don't print timestamp */ + delta:1, /* show time deltas */ + reltime:1, /* show human readable relative times */ + ctime:1; /* show human readable time */ +}; + +struct dmesg_record { + const char *mesg; + size_t mesg_size; + + int level; + int facility; + struct timeval tv; + + const char *next; /* buffer with next unparsed record */ + size_t next_size; /* size of the next buffer */ +}; + +#define INIT_DMESG_RECORD(_r) do { \ + (_r)->mesg = NULL; \ + (_r)->mesg_size = 0; \ + (_r)->facility = -1; \ + (_r)->level = -1; \ + (_r)->tv.tv_sec = 0; \ + (_r)->tv.tv_usec = 0; \ + } while (0) + +static int read_kmsg(struct dmesg_control *ctl); + + +static void __attribute__((__noreturn__)) usage(FILE *out) +{ + size_t i; + + fputs(_("\nUsage:\n"), out); + fprintf(out, + _(" %s [options]\n"), program_invocation_short_name); + + fputs(_("\nOptions:\n"), out); + fputs(_(" -C, --clear clear the kernel ring buffer\n" + " -c, --read-clear read and clear all messages\n" + " -D, --console-off disable printing messages to console\n" + " -d, --show-delta show time delta between printed messages\n" + " -e, --reltime show local time and time delta in readable format\n" + " -E, --console-on enable printing messages to console\n" + " -F, --file use the file instead of the kernel log buffer\n" + " -f, --facility restrict output to defined facilities\n" + " -h, --help display this help and exit\n" + " -k, --kernel display kernel messages\n" + " -l, --level restrict output to defined levels\n" + " -n, --console-level set level of messages printed to console\n" + " -r, --raw print the raw message buffer\n" + " -S, --syslog force to use syslog(2) rather than /dev/kmsg\n" + " -s, --buffer-size buffer size to query the kernel ring buffer\n" + " -T, --ctime show human readable timestamp (could be \n" + " inaccurate if you have used SUSPEND/RESUME)\n" + " -t, --notime don't print messages timestamp\n" + " -u, --userspace display userspace messages\n" + " -V, --version output version information and exit\n" + " -w, --follow wait for new messages\n" + " -x, --decode decode facility and level to readable string\n"), out); + + fputs(_("\nSupported log facilities:\n"), out); + for (i = 0; i < ARRAY_SIZE(level_names); i++) { + fprintf(stderr, " %7s - %s\n", + facility_names[i].name, + _(facility_names[i].help)); + } + + fputs(_("\nSupported log levels (priorities):\n"), out); + for (i = 0; i < ARRAY_SIZE(level_names); i++) { + fprintf(stderr, " %7s - %s\n", + level_names[i].name, + _(level_names[i].help)); + } + + fputc('\n', out); + + exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); +} + +/* + * LEVEL ::= | + * ::= number in range <0..N>, where N < ARRAY_SIZE(level_names) + * ::= case-insensitive text + */ +static int parse_level(const char *str, size_t len) +{ + if (!str) + return -1; + if (!len) + len = strlen(str); + errno = 0; + + if (isdigit(*str)) { + char *end = NULL; + long x = strtol(str, &end, 10); + + if (!errno && end && end > str && (size_t) (end - str) == len && + x >= 0 && (size_t) x < ARRAY_SIZE(level_names)) + return x; + } else { + size_t i; + + for (i = 0; i < ARRAY_SIZE(level_names); i++) { + const char *n = level_names[i].name; + + if (strncasecmp(str, n, len) == 0 && *(n + len) == '\0') + return i; + } + } + + if (errno) + err(EXIT_FAILURE, _("failed to parse level '%s'"), str); + + errx(EXIT_FAILURE, _("unknown level '%s'"), str); + return -1; +} + +/* + * FACILITY ::= | + * ::= number in range <0..N>, where N < ARRAY_SIZE(facility_names) + * ::= case-insensitive text + */ +static int parse_facility(const char *str, size_t len) +{ + if (!str) + return -1; + if (!len) + len = strlen(str); + errno = 0; + + if (isdigit(*str)) { + char *end = NULL; + long x = strtol(str, &end, 10); + + if (!errno && end && end > str && (size_t) (end - str) == len && + x >= 0 && (size_t) x < ARRAY_SIZE(facility_names)) + return x; + } else { + size_t i; + + for (i = 0; i < ARRAY_SIZE(facility_names); i++) { + const char *n = facility_names[i].name; + + if (strncasecmp(str, n, len) == 0 && *(n + len) == '\0') + return i; + } + } + + if (errno) + err(EXIT_FAILURE, _("failed to parse facility '%s'"), str); + + errx(EXIT_FAILURE, _("unknown facility '%s'"), str); + return -1; +} + +/* + * Parses numerical prefix used for all messages in kernel ring buffer. + * + * Priorities/facilities are encoded into a single 32-bit quantity, where the + * bottom 3 bits are the priority (0-7) and the top 28 bits are the facility + * (0-big number). + * + * Note that the number has to end with '>' or ',' char. + */ +static const char *parse_faclev(const char *str, int *fac, int *lev) +{ + long num; + char *end = NULL; + + if (!str) + return str; + + errno = 0; + num = strtol(str, &end, 10); + + if (!errno && end && end > str) { + *fac = LOG_FAC(num); + *lev = LOG_PRI(num); + + if (*lev < 0 || (size_t) *lev > ARRAY_SIZE(level_names)) + *lev = -1; + if (*fac < 0 || (size_t) *fac > ARRAY_SIZE(facility_names)) + *fac = -1; + return end + 1; /* skip '<' or ',' */ + } + + return str; +} + +/* + * Parses timestamp from syslog message prefix, expected format: + * + * seconds.microseconds] + * + * the ']' is the timestamp field terminator. + */ +static const char *parse_syslog_timestamp(const char *str0, struct timeval *tv) +{ + const char *str = str0; + char *end = NULL; + + if (!str0) + return str0; + + errno = 0; + tv->tv_sec = strtol(str, &end, 10); + + if (!errno && end && *end == '.' && *(end + 1)) { + str = end + 1; + end = NULL; + tv->tv_usec = strtol(str, &end, 10); + } + if (errno || !end || end == str || *end != ']') + return str0; + + return end + 1; /* skip ']' */ +} + +/* + * Parses timestamp from /dev/kmsg, expected formats: + * + * microseconds, + * microseconds; + * + * the ',' is fields separators and ';' items terminator (for the last item) + */ +static const char *parse_kmsg_timestamp(const char *str0, struct timeval *tv) +{ + const char *str = str0; + char *end = NULL; + uint64_t usec; + + if (!str0) + return str0; + + errno = 0; + usec = strtoumax(str, &end, 10); + + if (!errno && end && (*end == ';' || *end == ',')) { + tv->tv_usec = usec % 1000000; + tv->tv_sec = usec / 1000000; + } else + return str0; + + return end + 1; /* skip separator */ +} + + +static double time_diff(struct timeval *a, struct timeval *b) +{ + return (a->tv_sec - b->tv_sec) + (a->tv_usec - b->tv_usec) / 1E6; +} + +static int get_syslog_buffer_size(void) +{ + int n = klogctl(SYSLOG_ACTION_SIZE_BUFFER, NULL, 0); + + return n > 0 ? n : 0; +} + +static time_t get_boot_time(void) +{ + struct sysinfo info; + struct timeval tv; + + if (sysinfo(&info) != 0) + warn(_("sysinfo failed")); + else if (gettimeofday(&tv, NULL) != 0) + warn(_("gettimeofday failed")); + else + return tv.tv_sec -= info.uptime; + return 0; +} + +/* + * Reads messages from regular file by mmap + */ +static ssize_t mmap_file_buffer(struct dmesg_control *ctl, char **buf) +{ + struct stat st; + int fd; + + if (!ctl->filename) + return -1; + + fd = open(ctl->filename, O_RDONLY); + if (fd < 0) + err(EXIT_FAILURE, _("cannot open %s"), ctl->filename); + if (fstat(fd, &st)) + err(EXIT_FAILURE, _("stat failed %s"), ctl->filename); + + *buf = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); + if (*buf == MAP_FAILED) + err(EXIT_FAILURE, _("cannot mmap: %s"), ctl->filename); + ctl->mmap_buff = *buf; + ctl->pagesize = getpagesize(); + close(fd); + + return st.st_size; +} + +/* + * Reads messages from kernel ring buffer by klogctl() + */ +static ssize_t read_syslog_buffer(struct dmesg_control *ctl, char **buf) +{ + size_t sz; + int rc = -1; + + if (ctl->bufsize) { + sz = ctl->bufsize + 8; + *buf = xmalloc(sz * sizeof(char)); + rc = klogctl(ctl->action, *buf, sz); + } else { + sz = 16392; + while (1) { + *buf = xmalloc(sz * sizeof(char)); + rc = klogctl(SYSLOG_ACTION_READ_ALL, *buf, sz); + if (rc < 0) + break; + if ((size_t) rc != sz || sz > (1 << 28)) + break; + free(*buf); + *buf = NULL; + sz *= 4; + } + + if (rc > 0 && ctl->action == SYSLOG_ACTION_READ_CLEAR) + rc = klogctl(SYSLOG_ACTION_READ_CLEAR, *buf, sz); + } + + return rc; +} + +/* + * Top level function to read messages + */ +static ssize_t read_buffer(struct dmesg_control *ctl, char **buf) +{ + ssize_t n = -1; + + switch (ctl->method) { + case DMESG_METHOD_MMAP: + n = mmap_file_buffer(ctl, buf); + break; + case DMESG_METHOD_SYSLOG: + if (!ctl->bufsize) + ctl->bufsize = get_syslog_buffer_size(); + + n = read_syslog_buffer(ctl, buf); + break; + case DMESG_METHOD_KMSG: + /* + * Since kernel 3.5.0 + */ + n = read_kmsg(ctl); + if (n == 0 && ctl->action == SYSLOG_ACTION_READ_CLEAR) + n = klogctl(SYSLOG_ACTION_CLEAR, NULL, 0); + break; + } + + return n; +} + +static int fwrite_hex(const char *buf, size_t size, FILE *out) +{ + size_t i; + + for (i = 0; i < size; i++) { + int rc = fprintf(out, "\\x%02x", buf[i]); + if (rc < 0) + return rc; + } + return 0; +} + +/* + * Prints to 'out' and non-printable chars are replaced with \x sequences. + */ +static void safe_fwrite(const char *buf, size_t size, FILE *out) +{ + size_t i; +#ifdef HAVE_WIDECHAR + mbstate_t s; + memset(&s, 0, sizeof (s)); +#endif + for (i = 0; i < size; i++) { + const char *p = buf + i; + int rc, hex = 0; + size_t len = 1; + +#ifdef HAVE_WIDECHAR + wchar_t wc; + len = mbrtowc(&wc, p, size - i, &s); + + if (len == 0) /* L'\0' */ + return; + + if (len == (size_t)-1 || len == (size_t)-2) { /* invalid sequence */ + memset(&s, 0, sizeof (s)); + len = hex = 1; + } else if (len > 1 && !iswprint(wc)) { /* non-printable multibyte */ + hex = 1; + } + i += len - 1; +#else + if (!isprint((unsigned int) *p) && + !isspace((unsigned int) *p)) /* non-printable */ + hex = 1; +#endif + if (hex) + rc = fwrite_hex(p, len, out); + else + rc = fwrite(p, 1, len, out) != len; + if (rc != 0) + err(EXIT_FAILURE, _("write failed")); + } +} + +static const char *skip_item(const char *begin, const char *end, const char *sep) +{ + while (begin < end) { + int c = *begin++; + + if (c == '\0' || strchr(sep, c)) + break; + } + + return begin; +} + +/* + * Parses one record from syslog(2) buffer + */ +static int get_next_syslog_record(struct dmesg_control *ctl, + struct dmesg_record *rec) +{ + size_t i; + const char *begin = NULL; + + if (ctl->method != DMESG_METHOD_MMAP && + ctl->method != DMESG_METHOD_SYSLOG) + return -1; + + if (!rec->next || !rec->next_size) + return 1; + + INIT_DMESG_RECORD(rec); + + /* + * Unmap already printed file data from memory + */ + if (ctl->mmap_buff && (size_t) (rec->next - ctl->mmap_buff) > ctl->pagesize) { + void *x = ctl->mmap_buff; + + ctl->mmap_buff += ctl->pagesize; + munmap(x, ctl->pagesize); + } + + for (i = 0; i < rec->next_size; i++) { + const char *p = rec->next + i; + const char *end = NULL; + + if (!begin) + begin = p; + if (i + 1 == rec->next_size) { + end = p + 1; + i++; + } else if (*p == '\n' && *(p + 1) == '<') + end = p; + + if (begin && !*begin) + begin = NULL; /* zero(s) at the end of the buffer? */ + if (!begin || !end) + continue; + if (end <= begin) + continue; /* error or empty line? */ + + if (*begin == '<') { + if (ctl->fltr_lev || ctl->fltr_fac || ctl->decode) + begin = parse_faclev(begin + 1, &rec->facility, + &rec->level); + else + begin = skip_item(begin, end, ">"); + } + + if (*begin == '[' && (*(begin + 1) == ' ' || + isdigit(*(begin + 1)))) { + if (ctl->delta || ctl->ctime || ctl->reltime) + begin = parse_syslog_timestamp(begin + 1, &rec->tv); + else if (ctl->notime) + begin = skip_item(begin, end, "]"); + + if (begin < end && *begin == ' ') + begin++; + } + + rec->mesg = begin; + rec->mesg_size = end - begin; + + rec->next_size -= end - rec->next; + rec->next = rec->next_size > 0 ? end + 1 : NULL; + if (rec->next_size > 0) + rec->next_size--; + + return 0; + } + + return 1; +} + +static int accept_record(struct dmesg_control *ctl, struct dmesg_record *rec) +{ + if (ctl->fltr_lev && (rec->facility < 0 || + !isset(ctl->levels, rec->level))) + return 0; + + if (ctl->fltr_fac && (rec->facility < 0 || + !isset(ctl->facilities, rec->facility))) + return 0; + + return 1; +} + +static void raw_print(struct dmesg_control *ctl, const char *buf, size_t size) +{ + int lastc = '\n'; + + if (!ctl->mmap_buff) { + /* + * Print whole ring buffer + */ + safe_fwrite(buf, size, stdout); + lastc = buf[size - 1]; + } else { + /* + * Print file in small chunks to save memory + */ + while (size) { + size_t sz = size > ctl->pagesize ? ctl->pagesize : size; + char *x = ctl->mmap_buff; + + safe_fwrite(x, sz, stdout); + lastc = x[sz - 1]; + size -= sz; + ctl->mmap_buff += sz; + munmap(x, sz); + } + } + + if (lastc != '\n') + putchar('\n'); +} + +static struct tm *record_localtime(struct dmesg_control *ctl, + struct dmesg_record *rec, + struct tm *tm) +{ + time_t t = ctl->boot_time + rec->tv.tv_sec; + return localtime_r(&t, tm); +} + +static char *record_ctime(struct dmesg_control *ctl, + struct dmesg_record *rec, + char *buf, size_t bufsiz) +{ + struct tm tm; + + record_localtime(ctl, rec, &tm); + + if (strftime(buf, bufsiz, "%a %b %e %H:%M:%S %Y", &tm) == 0) + *buf = '\0'; + return buf; +} + +static char *short_ctime(struct tm *tm, char *buf, size_t bufsiz) +{ + if (strftime(buf, bufsiz, "%b%e %H:%M", tm) == 0) + *buf = '\0'; + return buf; +} + +static double record_count_delta(struct dmesg_control *ctl, + struct dmesg_record *rec) +{ + double delta = 0; + + if (timerisset(&ctl->lasttime)) + delta = time_diff(&rec->tv, &ctl->lasttime); + + ctl->lasttime = rec->tv; + return delta; +} + +static void print_record(struct dmesg_control *ctl, + struct dmesg_record *rec) +{ + char buf[256]; + + if (!accept_record(ctl, rec)) + return; + + if (!rec->mesg_size) { + putchar('\n'); + return; + } + + /* + * compose syslog(2) compatible raw output -- used for /dev/kmsg for + * backward compatibility with syslog(2) buffers only + */ + if (ctl->raw) { + printf("<%d>[%5d.%06d] ", + LOG_MAKEPRI(rec->facility, rec->level), + (int) rec->tv.tv_sec, + (int) rec->tv.tv_usec); + + goto mesg; + } + + /* + * facility : priority : + */ + if (ctl->decode && rec->level >= 0 && rec->facility >= 0) + printf("%-6s:%-6s: ", facility_names[rec->facility].name, + level_names[rec->level].name); + + /* + * [sec.usec ] or [ctime ] + */ + if (ctl->delta) { + if (ctl->ctime) + printf("[%s ", record_ctime(ctl, rec, buf, sizeof(buf))); + else if (ctl->notime) + putchar('['); + else + printf("[%5d.%06d ", (int) rec->tv.tv_sec, + (int) rec->tv.tv_usec); + printf("<%12.06f>] ", record_count_delta(ctl, rec)); + + /* + * [ctime] + */ + } else if (ctl->ctime) + printf("[%s] ", record_ctime(ctl, rec, buf, sizeof(buf))); + + /* + * [reltime] + */ + else if (ctl->reltime) { + double delta; + struct tm cur; + + record_localtime(ctl, rec, &cur); + delta = record_count_delta(ctl, rec); + + if (cur.tm_min != ctl->lasttm.tm_min || + cur.tm_hour != ctl->lasttm.tm_hour || + cur.tm_yday != ctl->lasttm.tm_yday) + printf("[%s] ", short_ctime(&cur, buf, sizeof(buf))); + else if (delta < 10) + printf("[ %+8.06f] ", delta); + else + printf("[ %+9.06f] ", delta); + + ctl->lasttm = cur; + } + + /* + * In syslog output the timestamp is part of the message and we don't + * parse the timestamp by default. We parse the timestamp only if + * --show-delta or --ctime is specified. + * + * In kmsg output we always parse the timesptamp, so we have to compose + * the [sec.usec] string. + */ + if (ctl->method == DMESG_METHOD_KMSG && + !ctl->notime && !ctl->delta && !ctl->ctime && !ctl->reltime) + printf("[%5d.%06d] ", (int) rec->tv.tv_sec, (int) rec->tv.tv_usec); + +mesg: + safe_fwrite(rec->mesg, rec->mesg_size, stdout); + + if (*(rec->mesg + rec->mesg_size - 1) != '\n') + putchar('\n'); +} + +/* + * Prints the 'buf' kernel ring buffer; the messages are filtered out according + * to 'levels' and 'facilities' bitarrays. + */ +static void print_buffer(struct dmesg_control *ctl, + const char *buf, size_t size) +{ + struct dmesg_record rec = { .next = buf, .next_size = size }; + + if (ctl->raw) { + raw_print(ctl, buf, size); + return; + } + + while (get_next_syslog_record(ctl, &rec) == 0) + print_record(ctl, &rec); +} + +static ssize_t read_kmsg_one(struct dmesg_control *ctl) +{ + ssize_t size; + + /* kmsg returns EPIPE if record was modified while reading */ + do { + size = read(ctl->kmsg, ctl->kmsg_buf, + sizeof(ctl->kmsg_buf) - 1); + } while (size < 0 && errno == EPIPE); + + return size; +} + +static int init_kmsg(struct dmesg_control *ctl) +{ + int mode = O_RDONLY; + + if (!ctl->follow) + mode |= O_NONBLOCK; + + ctl->kmsg = open("/dev/kmsg", mode); + if (ctl->kmsg < 0) + return -1; + + /* + * Seek after the last record available at the time + * the last SYSLOG_ACTION_CLEAR was issued. + * + * ... otherwise SYSLOG_ACTION_CLEAR will have no effect for kmsg. + */ + lseek(ctl->kmsg, 0, SEEK_DATA); + + /* + * Old kernels (<3.5) allow to successfully open /dev/kmsg for + * read-only, but read() returns -EINVAL :-((( + * + * Let's try to read the first record. The record is later processed in + * read_kmsg(). + */ + ctl->kmsg_first_read = read_kmsg_one(ctl); + if (ctl->kmsg_first_read < 0) { + close(ctl->kmsg); + ctl->kmsg = -1; + return -1; + } + + return 0; +} + +/* + * /dev/kmsg record format: + * + * faclev,seqnum,timestamp[optional, ...];messgage\n + * TAGNAME=value + * ... + * + * - fields are separated by ',' + * - last field is terminated by ';' + * + */ +#define LAST_KMSG_FIELD(s) (!s || !*s || *(s - 1) == ';') + +static int parse_kmsg_record(struct dmesg_control *ctl, + struct dmesg_record *rec, + char *buf, + size_t sz) +{ + const char *p = buf, *end; + + if (sz == 0 || !buf || !*buf) + return -1; + + end = buf + (sz - 1); + INIT_DMESG_RECORD(rec); + + while (p < end && isspace(*p)) + p++; + + /* A) priority and facility */ + if (ctl->fltr_lev || ctl->fltr_fac || ctl->decode || ctl->raw) + p = parse_faclev(p, &rec->facility, &rec->level); + else + p = skip_item(p, end, ","); + if (LAST_KMSG_FIELD(p)) + goto mesg; + + /* B) sequence number */ + p = skip_item(p, end, ",;"); + if (LAST_KMSG_FIELD(p)) + goto mesg; + + /* C) timestamp */ + if (ctl->notime) + p = skip_item(p, end, ",;"); + else + p = parse_kmsg_timestamp(p, &rec->tv); + if (LAST_KMSG_FIELD(p)) + goto mesg; + + /* D) optional fields (ignore) */ + p = skip_item(p, end, ";"); + if (LAST_KMSG_FIELD(p)) + goto mesg; + +mesg: + /* E) message text */ + rec->mesg = p; + p = skip_item(p, end, "\n"); + + if (!p) + return -1; + + rec->mesg_size = p - rec->mesg; + + /* + * Kernel escapes non-printable characters, unfortuately kernel + * definition of "non-printable" is too strict. On UTF8 console we can + * print many chars, so let's decode from kernel. + */ + unhexmangle_to_buffer(rec->mesg, (char *) rec->mesg, rec->mesg_size + 1); + + /* F) message tags (ignore) */ + + return 0; +} + +/* + * Note that each read() call for /dev/kmsg returns always one record. It means + * that we don't have to read whole message buffer before the records parsing. + * + * So this function does not compose one huge buffer (like read_syslog_buffer()) + * and print_buffer() is unnecessary. All is done in this function. + * + * Returns 0 on success, -1 on error. + */ +static int read_kmsg(struct dmesg_control *ctl) +{ + struct dmesg_record rec; + ssize_t sz; + + if (ctl->method != DMESG_METHOD_KMSG || ctl->kmsg < 0) + return -1; + + /* + * The very first read() call is done in kmsg_init() where we test + * /dev/kmsg usability. The return code from the initial read() is + * stored in ctl->kmsg_first_read; + */ + sz = ctl->kmsg_first_read; + + while (sz > 0) { + *(ctl->kmsg_buf + sz) = '\0'; /* for debug messages */ + + if (parse_kmsg_record(ctl, &rec, + ctl->kmsg_buf, (size_t) sz) == 0) + print_record(ctl, &rec); + + sz = read_kmsg_one(ctl); + } + + return 0; +} + +#define EXCL_ACT_ERR "--{clear,read-clear,console-level,console-on,console-off}" +#define EXCL_SYS_ERR "--{syslog,follow}" + +int main(int argc, char *argv[]) +{ + char *buf = NULL; + int c; + int console_level = 0; + int klog_rc = 0; + ssize_t n; + static struct dmesg_control ctl = { + .filename = NULL, + .action = SYSLOG_ACTION_READ_ALL, + .method = DMESG_METHOD_KMSG, + .kmsg = -1, + }; + + static const struct option longopts[] = { + { "buffer-size", required_argument, NULL, 's' }, + { "clear", no_argument, NULL, 'C' }, + { "console-level", required_argument, NULL, 'n' }, + { "console-off", no_argument, NULL, 'D' }, + { "console-on", no_argument, NULL, 'E' }, + { "decode", no_argument, NULL, 'x' }, + { "file", required_argument, NULL, 'F' }, + { "facility", required_argument, NULL, 'f' }, + { "follow", no_argument, NULL, 'w' }, + { "help", no_argument, NULL, 'h' }, + { "kernel", no_argument, NULL, 'k' }, + { "level", required_argument, NULL, 'l' }, + { "syslog", no_argument, NULL, 'S' }, + { "raw", no_argument, NULL, 'r' }, + { "read-clear", no_argument, NULL, 'c' }, + { "reltime", no_argument, NULL, 'e' }, + { "show-delta", no_argument, NULL, 'd' }, + { "ctime", no_argument, NULL, 'T' }, + { "notime", no_argument, NULL, 't' }, + { "userspace", no_argument, NULL, 'u' }, + { "version", no_argument, NULL, 'V' }, + { NULL, 0, NULL, 0 } + }; + + static const ul_excl_t excl[] = { /* rows and cols in in ASCII order */ + { 'C','D','E','c','n' }, /* clear,off,on,read-clear,level*/ + { 'S','w' }, /* syslog,follow */ + { 0 } + }; + int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + atexit(close_stdout); + + while ((c = getopt_long(argc, argv, "CcDdEeF:f:hkl:n:rSs:TtuVwx", + longopts, NULL)) != -1) { + + err_exclusive_options(c, longopts, excl, excl_st); + + switch (c) { + case 'C': + ctl.action = SYSLOG_ACTION_CLEAR; + break; + case 'c': + ctl.action = SYSLOG_ACTION_READ_CLEAR; + break; + case 'D': + ctl.action = SYSLOG_ACTION_CONSOLE_OFF; + break; + case 'd': + ctl.delta = 1; + break; + case 'E': + ctl.action = SYSLOG_ACTION_CONSOLE_ON; + break; + case 'e': + ctl.boot_time = get_boot_time(); + if (ctl.boot_time) + ctl.reltime = 1; + break; + case 'F': + ctl.filename = optarg; + ctl.method = DMESG_METHOD_MMAP; + break; + case 'f': + ctl.fltr_fac = 1; + if (string_to_bitarray(optarg, + ctl.facilities, parse_facility) < 0) + return EXIT_FAILURE; + break; + case 'h': + usage(stdout); + break; + case 'k': + ctl.fltr_fac = 1; + setbit(ctl.facilities, FAC_BASE(LOG_KERN)); + break; + case 'l': + ctl.fltr_lev= 1; + if (string_to_bitarray(optarg, + ctl.levels, parse_level) < 0) + return EXIT_FAILURE; + break; + case 'n': + ctl.action = SYSLOG_ACTION_CONSOLE_LEVEL; + console_level = parse_level(optarg, 0); + break; + case 'r': + ctl.raw = 1; + break; + case 'S': + ctl.method = DMESG_METHOD_SYSLOG; + break; + case 's': + ctl.bufsize = strtou32_or_err(optarg, + _("invalid buffer size argument")); + if (ctl.bufsize < 4096) + ctl.bufsize = 4096; + break; + case 'T': + ctl.boot_time = get_boot_time(); + if (ctl.boot_time) + ctl.ctime = 1; + break; + case 't': + ctl.notime = 1; + break; + case 'u': + ctl.fltr_fac = 1; + for (n = 1; (size_t) n < ARRAY_SIZE(facility_names); n++) + setbit(ctl.facilities, n); + break; + case 'V': + printf(_("%s from %s\n"), program_invocation_short_name, + PACKAGE_STRING); + return EXIT_SUCCESS; + case 'w': + ctl.follow = 1; + break; + case 'x': + ctl.decode = 1; + break; + case '?': + default: + usage(stderr); + } + } + argc -= optind; + argv += optind; + + if (argc > 1) + usage(stderr); + + if (ctl.raw && (ctl.fltr_lev || ctl.fltr_fac || ctl.delta || + ctl.notime || ctl.ctime || ctl.decode)) + errx(EXIT_FAILURE, _("--raw can't be used together with level, " + "facility, decode, delta, ctime or notime options")); + + if (ctl.notime && (ctl.ctime || ctl.reltime)) + errx(EXIT_FAILURE, _("--notime can't be used together with --ctime or --reltime")); + if (ctl.reltime && ctl.ctime) + errx(EXIT_FAILURE, _("--reltime can't be used together with --ctime ")); + + switch (ctl.action) { + case SYSLOG_ACTION_READ_ALL: + case SYSLOG_ACTION_READ_CLEAR: + if (ctl.method == DMESG_METHOD_KMSG && init_kmsg(&ctl) != 0) + ctl.method = DMESG_METHOD_SYSLOG; + + n = read_buffer(&ctl, &buf); + if (n > 0) + print_buffer(&ctl, buf, n); + if (!ctl.mmap_buff) + free(buf); + if (n < 0) + err(EXIT_FAILURE, _("read kernel buffer failed")); + if (ctl.kmsg >= 0) + close(ctl.kmsg); + break; + case SYSLOG_ACTION_CLEAR: + case SYSLOG_ACTION_CONSOLE_OFF: + case SYSLOG_ACTION_CONSOLE_ON: + klog_rc = klogctl(ctl.action, NULL, 0); + break; + case SYSLOG_ACTION_CONSOLE_LEVEL: + klog_rc = klogctl(ctl.action, NULL, console_level); + break; + default: + errx(EXIT_FAILURE, _("unsupported command")); + break; + } + + + if (klog_rc) + err(EXIT_FAILURE, _("klogctl failed")); + + return EXIT_SUCCESS; +} diff --git a/sys-utils/eject.1 b/sys-utils/eject.1 new file mode 100644 index 0000000..1a23229 --- /dev/null +++ b/sys-utils/eject.1 @@ -0,0 +1,165 @@ +.\" Copyright (C) 1994-2005 Jeff Tranter (tranter@pobox.com) +.\" Copyright (C) 2012 Karel Zak +.\" +.\" It may be distributed under the GNU Public License, version 2, or +.\" any higher version. See section COPYING of the GNU Public license +.\" for conditions under which this file may be redistributed. +.TH EJECT 1 "April 2012" "Linux" "User Commands" +.SH NAME +eject \- eject removable media +.SH SYNOPSIS +.B eject +.RB [ options ] +.IR device | mountpoint +.SH DESCRIPTION +.B Eject +allows removable media (typically a CD-ROM, floppy disk, tape, JAZ, ZIP or USB +disk) to be ejected under software control. The command can also control some +multi-disc CD-ROM changers, the auto-eject feature supported by some devices, +and close the disc tray of some CD-ROM drives. +.PP +The device corresponding to \fIdevice\fP or \fImountpoint\fP is ejected. If no +name is specified, the default name /dev/cdrom is used. The device may be +addressed by device name (e.g. 'sda'), device path (e.g. '/dev/sda'), +UUID= or LABEL=