From 2f8984613e17f9e5971ec338240b0bb6d2dd1cc6 Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Sat, 11 Feb 2023 08:13:14 +0000 Subject: Code refactor; only s6-ps has remaining globals now Signed-off-by: Laurent Bercot --- .gitignore | 5 +- package/deps.mak | 67 ++-- package/targets.mak | 1 - src/include-local/mount-constants.h | 78 ++++ src/include-local/s6-ps.h | 159 ++++++++ src/libps/deps-lib/s6ps | 7 + src/libps/s6ps_grcache.c | 67 ++++ src/libps/s6ps_otree.c | 100 +++++ src/libps/s6ps_pfield.c | 561 +++++++++++++++++++++++++++++ src/libps/s6ps_pwcache.c | 67 ++++ src/libps/s6ps_statparse.c | 186 ++++++++++ src/libps/s6ps_ttycache.c | 138 +++++++ src/libps/s6ps_wchan.c | 96 +++++ src/minutils/deps-exe/rngseed | 2 - src/minutils/deps-exe/s6-chroot | 1 - src/minutils/deps-exe/s6-freeramdisk | 1 - src/minutils/deps-exe/s6-hostname | 1 - src/minutils/deps-exe/s6-logwatch | 1 - src/minutils/deps-exe/s6-mount | 1 - src/minutils/deps-exe/s6-pivotchroot | 1 - src/minutils/deps-exe/s6-ps | 10 - src/minutils/deps-exe/s6-swapoff | 1 - src/minutils/deps-exe/s6-swapon | 1 - src/minutils/deps-exe/s6-umount | 1 - src/minutils/mount-constants.h | 81 ----- src/minutils/rngseed.c | 279 -------------- src/minutils/s6-chroot.c | 18 - src/minutils/s6-freeramdisk.c | 21 -- src/minutils/s6-hostname.c | 37 -- src/minutils/s6-logwatch.c | 172 --------- src/minutils/s6-mount.c | 149 -------- src/minutils/s6-pivotchroot.c | 21 -- src/minutils/s6-ps.c | 387 -------------------- src/minutils/s6-ps.h | 163 --------- src/minutils/s6-swapoff.c | 54 --- src/minutils/s6-swapon.c | 37 -- src/minutils/s6-umount.c | 66 ---- src/minutils/s6ps_grcache.c | 65 ---- src/minutils/s6ps_otree.c | 98 ----- src/minutils/s6ps_pfield.c | 560 ---------------------------- src/minutils/s6ps_pwcache.c | 66 ---- src/minutils/s6ps_statparse.c | 184 ---------- src/minutils/s6ps_ttycache.c | 136 ------- src/minutils/s6ps_wchan.c | 94 ----- src/multicall/deps-exe/s6-linux-utils | 5 + src/s6-linux-utils/deps-exe/rngseed | 2 + src/s6-linux-utils/deps-exe/s6-chroot | 1 + src/s6-linux-utils/deps-exe/s6-freeramdisk | 1 + src/s6-linux-utils/deps-exe/s6-hostname | 1 + src/s6-linux-utils/deps-exe/s6-logwatch | 1 + src/s6-linux-utils/deps-exe/s6-mount | 1 + src/s6-linux-utils/deps-exe/s6-pivotchroot | 1 + src/s6-linux-utils/deps-exe/s6-ps | 4 + src/s6-linux-utils/deps-exe/s6-swapoff | 1 + src/s6-linux-utils/deps-exe/s6-swapon | 1 + src/s6-linux-utils/deps-exe/s6-umount | 1 + src/s6-linux-utils/rngseed.c | 277 ++++++++++++++ src/s6-linux-utils/s6-chroot.c | 18 + src/s6-linux-utils/s6-freeramdisk.c | 22 ++ src/s6-linux-utils/s6-hostname.c | 36 ++ src/s6-linux-utils/s6-logwatch.c | 173 +++++++++ src/s6-linux-utils/s6-mount.c | 166 +++++++++ src/s6-linux-utils/s6-pivotchroot.c | 21 ++ src/s6-linux-utils/s6-ps.c | 388 ++++++++++++++++++++ src/s6-linux-utils/s6-swapoff.c | 53 +++ src/s6-linux-utils/s6-swapon.c | 38 ++ src/s6-linux-utils/s6-umount.c | 67 ++++ 67 files changed, 2778 insertions(+), 2742 deletions(-) create mode 100644 src/include-local/mount-constants.h create mode 100644 src/include-local/s6-ps.h create mode 100644 src/libps/deps-lib/s6ps create mode 100644 src/libps/s6ps_grcache.c create mode 100644 src/libps/s6ps_otree.c create mode 100644 src/libps/s6ps_pfield.c create mode 100644 src/libps/s6ps_pwcache.c create mode 100644 src/libps/s6ps_statparse.c create mode 100644 src/libps/s6ps_ttycache.c create mode 100644 src/libps/s6ps_wchan.c delete mode 100644 src/minutils/deps-exe/rngseed delete mode 100644 src/minutils/deps-exe/s6-chroot delete mode 100644 src/minutils/deps-exe/s6-freeramdisk delete mode 100644 src/minutils/deps-exe/s6-hostname delete mode 100644 src/minutils/deps-exe/s6-logwatch delete mode 100644 src/minutils/deps-exe/s6-mount delete mode 100644 src/minutils/deps-exe/s6-pivotchroot delete mode 100644 src/minutils/deps-exe/s6-ps delete mode 100644 src/minutils/deps-exe/s6-swapoff delete mode 100644 src/minutils/deps-exe/s6-swapon delete mode 100644 src/minutils/deps-exe/s6-umount delete mode 100644 src/minutils/mount-constants.h delete mode 100644 src/minutils/rngseed.c delete mode 100644 src/minutils/s6-chroot.c delete mode 100644 src/minutils/s6-freeramdisk.c delete mode 100644 src/minutils/s6-hostname.c delete mode 100644 src/minutils/s6-logwatch.c delete mode 100644 src/minutils/s6-mount.c delete mode 100644 src/minutils/s6-pivotchroot.c delete mode 100644 src/minutils/s6-ps.c delete mode 100644 src/minutils/s6-ps.h delete mode 100644 src/minutils/s6-swapoff.c delete mode 100644 src/minutils/s6-swapon.c delete mode 100644 src/minutils/s6-umount.c delete mode 100644 src/minutils/s6ps_grcache.c delete mode 100644 src/minutils/s6ps_otree.c delete mode 100644 src/minutils/s6ps_pfield.c delete mode 100644 src/minutils/s6ps_pwcache.c delete mode 100644 src/minutils/s6ps_statparse.c delete mode 100644 src/minutils/s6ps_ttycache.c delete mode 100644 src/minutils/s6ps_wchan.c create mode 100644 src/multicall/deps-exe/s6-linux-utils create mode 100644 src/s6-linux-utils/deps-exe/rngseed create mode 100644 src/s6-linux-utils/deps-exe/s6-chroot create mode 100644 src/s6-linux-utils/deps-exe/s6-freeramdisk create mode 100644 src/s6-linux-utils/deps-exe/s6-hostname create mode 100644 src/s6-linux-utils/deps-exe/s6-logwatch create mode 100644 src/s6-linux-utils/deps-exe/s6-mount create mode 100644 src/s6-linux-utils/deps-exe/s6-pivotchroot create mode 100644 src/s6-linux-utils/deps-exe/s6-ps create mode 100644 src/s6-linux-utils/deps-exe/s6-swapoff create mode 100644 src/s6-linux-utils/deps-exe/s6-swapon create mode 100644 src/s6-linux-utils/deps-exe/s6-umount create mode 100644 src/s6-linux-utils/rngseed.c create mode 100644 src/s6-linux-utils/s6-chroot.c create mode 100644 src/s6-linux-utils/s6-freeramdisk.c create mode 100644 src/s6-linux-utils/s6-hostname.c create mode 100644 src/s6-linux-utils/s6-logwatch.c create mode 100644 src/s6-linux-utils/s6-mount.c create mode 100644 src/s6-linux-utils/s6-pivotchroot.c create mode 100644 src/s6-linux-utils/s6-ps.c create mode 100644 src/s6-linux-utils/s6-swapoff.c create mode 100644 src/s6-linux-utils/s6-swapon.c create mode 100644 src/s6-linux-utils/s6-umount.c diff --git a/.gitignore b/.gitignore index 43ea92b..4ca416f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,7 @@ *.o -*.a +*.a.xyzzy *.lo -*.so -*.so.* +*.so.xyzzy /config.mak /src/include/s6-linux-utils/config.h /rngseed diff --git a/package/deps.mak b/package/deps.mak index 3150147..0dac63f 100644 --- a/package/deps.mak +++ b/package/deps.mak @@ -2,44 +2,53 @@ # This file has been generated by tools/gen-deps.sh # -src/minutils/rngseed.o src/minutils/rngseed.lo: src/minutils/rngseed.c src/include/s6-linux-utils/config.h -src/minutils/s6-chroot.o src/minutils/s6-chroot.lo: src/minutils/s6-chroot.c -src/minutils/s6-freeramdisk.o src/minutils/s6-freeramdisk.lo: src/minutils/s6-freeramdisk.c -src/minutils/s6-hostname.o src/minutils/s6-hostname.lo: src/minutils/s6-hostname.c -src/minutils/s6-logwatch.o src/minutils/s6-logwatch.lo: src/minutils/s6-logwatch.c -src/minutils/s6-mount.o src/minutils/s6-mount.lo: src/minutils/s6-mount.c src/minutils/mount-constants.h -src/minutils/s6-pivotchroot.o src/minutils/s6-pivotchroot.lo: src/minutils/s6-pivotchroot.c -src/minutils/s6-ps.o src/minutils/s6-ps.lo: src/minutils/s6-ps.c src/minutils/s6-ps.h -src/minutils/s6-swapoff.o src/minutils/s6-swapoff.lo: src/minutils/s6-swapoff.c -src/minutils/s6-swapon.o src/minutils/s6-swapon.lo: src/minutils/s6-swapon.c -src/minutils/s6-umount.o src/minutils/s6-umount.lo: src/minutils/s6-umount.c -src/minutils/s6ps_grcache.o src/minutils/s6ps_grcache.lo: src/minutils/s6ps_grcache.c src/minutils/s6-ps.h -src/minutils/s6ps_otree.o src/minutils/s6ps_otree.lo: src/minutils/s6ps_otree.c src/minutils/s6-ps.h -src/minutils/s6ps_pfield.o src/minutils/s6ps_pfield.lo: src/minutils/s6ps_pfield.c src/minutils/s6-ps.h -src/minutils/s6ps_pwcache.o src/minutils/s6ps_pwcache.lo: src/minutils/s6ps_pwcache.c src/minutils/s6-ps.h -src/minutils/s6ps_statparse.o src/minutils/s6ps_statparse.lo: src/minutils/s6ps_statparse.c src/minutils/s6-ps.h -src/minutils/s6ps_ttycache.o src/minutils/s6ps_ttycache.lo: src/minutils/s6ps_ttycache.c src/minutils/s6-ps.h -src/minutils/s6ps_wchan.o src/minutils/s6ps_wchan.lo: src/minutils/s6ps_wchan.c src/minutils/s6-ps.h +src/libps/s6ps_grcache.o src/libps/s6ps_grcache.lo: src/libps/s6ps_grcache.c src/include-local/s6-ps.h +src/libps/s6ps_otree.o src/libps/s6ps_otree.lo: src/libps/s6ps_otree.c src/include-local/s6-ps.h +src/libps/s6ps_pfield.o src/libps/s6ps_pfield.lo: src/libps/s6ps_pfield.c src/include-local/s6-ps.h +src/libps/s6ps_pwcache.o src/libps/s6ps_pwcache.lo: src/libps/s6ps_pwcache.c src/include-local/s6-ps.h +src/libps/s6ps_statparse.o src/libps/s6ps_statparse.lo: src/libps/s6ps_statparse.c src/include-local/s6-ps.h +src/libps/s6ps_ttycache.o src/libps/s6ps_ttycache.lo: src/libps/s6ps_ttycache.c src/include-local/s6-ps.h +src/libps/s6ps_wchan.o src/libps/s6ps_wchan.lo: src/libps/s6ps_wchan.c src/include-local/s6-ps.h +src/s6-linux-utils/rngseed.o src/s6-linux-utils/rngseed.lo: src/s6-linux-utils/rngseed.c src/include/s6-linux-utils/config.h +src/s6-linux-utils/s6-chroot.o src/s6-linux-utils/s6-chroot.lo: src/s6-linux-utils/s6-chroot.c +src/s6-linux-utils/s6-freeramdisk.o src/s6-linux-utils/s6-freeramdisk.lo: src/s6-linux-utils/s6-freeramdisk.c +src/s6-linux-utils/s6-hostname.o src/s6-linux-utils/s6-hostname.lo: src/s6-linux-utils/s6-hostname.c +src/s6-linux-utils/s6-logwatch.o src/s6-linux-utils/s6-logwatch.lo: src/s6-linux-utils/s6-logwatch.c +src/s6-linux-utils/s6-mount.o src/s6-linux-utils/s6-mount.lo: src/s6-linux-utils/s6-mount.c src/include-local/mount-constants.h +src/s6-linux-utils/s6-pivotchroot.o src/s6-linux-utils/s6-pivotchroot.lo: src/s6-linux-utils/s6-pivotchroot.c +src/s6-linux-utils/s6-ps.o src/s6-linux-utils/s6-ps.lo: src/s6-linux-utils/s6-ps.c src/include-local/s6-ps.h +src/s6-linux-utils/s6-swapoff.o src/s6-linux-utils/s6-swapoff.lo: src/s6-linux-utils/s6-swapoff.c +src/s6-linux-utils/s6-swapon.o src/s6-linux-utils/s6-swapon.lo: src/s6-linux-utils/s6-swapon.c +src/s6-linux-utils/s6-umount.o src/s6-linux-utils/s6-umount.lo: src/s6-linux-utils/s6-umount.c +ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),) +libs6ps.a.xyzzy: src/libps/s6ps_grcache.o src/libps/s6ps_otree.o src/libps/s6ps_pfield.o src/libps/s6ps_pwcache.o src/libps/s6ps_statparse.o src/libps/s6ps_ttycache.o src/libps/s6ps_wchan.o +else +libs6ps.a.xyzzy: src/libps/s6ps_grcache.lo src/libps/s6ps_otree.lo src/libps/s6ps_pfield.lo src/libps/s6ps_pwcache.lo src/libps/s6ps_statparse.lo src/libps/s6ps_ttycache.lo src/libps/s6ps_wchan.lo +endif +libs6ps.so.xyzzy: EXTRA_LIBS := +libs6ps.so.xyzzy: src/libps/s6ps_grcache.lo src/libps/s6ps_otree.lo src/libps/s6ps_pfield.lo src/libps/s6ps_pwcache.lo src/libps/s6ps_statparse.lo src/libps/s6ps_ttycache.lo src/libps/s6ps_wchan.lo +s6-linux-utils: EXTRA_LIBS := -lskarnet ${SYSCLOCK_LIB} ${MAYBEPTHREAD_LIB} +s6-linux-utils: src/multicall/s6-linux-utils.o libs6ps.a.xyzzy ${LIBNSSS} rngseed: EXTRA_LIBS := -lskarnet ${SYSCLOCK_LIB} -rngseed: src/minutils/rngseed.o +rngseed: src/s6-linux-utils/rngseed.o s6-chroot: EXTRA_LIBS := -lskarnet -s6-chroot: src/minutils/s6-chroot.o +s6-chroot: src/s6-linux-utils/s6-chroot.o s6-freeramdisk: EXTRA_LIBS := -lskarnet -s6-freeramdisk: src/minutils/s6-freeramdisk.o +s6-freeramdisk: src/s6-linux-utils/s6-freeramdisk.o s6-hostname: EXTRA_LIBS := -lskarnet -s6-hostname: src/minutils/s6-hostname.o +s6-hostname: src/s6-linux-utils/s6-hostname.o s6-logwatch: EXTRA_LIBS := -lskarnet -s6-logwatch: src/minutils/s6-logwatch.o +s6-logwatch: src/s6-linux-utils/s6-logwatch.o s6-mount: EXTRA_LIBS := -lskarnet -s6-mount: src/minutils/s6-mount.o +s6-mount: src/s6-linux-utils/s6-mount.o s6-pivotchroot: EXTRA_LIBS := -lskarnet -s6-pivotchroot: src/minutils/s6-pivotchroot.o +s6-pivotchroot: src/s6-linux-utils/s6-pivotchroot.o s6-ps: EXTRA_LIBS := -lskarnet ${MAYBEPTHREAD_LIB} -s6-ps: src/minutils/s6-ps.o src/minutils/s6ps_statparse.o src/minutils/s6ps_otree.o src/minutils/s6ps_pfield.o src/minutils/s6ps_pwcache.o src/minutils/s6ps_grcache.o src/minutils/s6ps_ttycache.o src/minutils/s6ps_wchan.o ${LIBNSSS} +s6-ps: src/s6-linux-utils/s6-ps.o libs6ps.a.xyzzy ${LIBNSSS} s6-swapoff: EXTRA_LIBS := -lskarnet -s6-swapoff: src/minutils/s6-swapoff.o +s6-swapoff: src/s6-linux-utils/s6-swapoff.o s6-swapon: EXTRA_LIBS := -lskarnet -s6-swapon: src/minutils/s6-swapon.o +s6-swapon: src/s6-linux-utils/s6-swapon.o s6-umount: EXTRA_LIBS := -lskarnet -s6-umount: src/minutils/s6-umount.o +s6-umount: src/s6-linux-utils/s6-umount.o diff --git a/package/targets.mak b/package/targets.mak index f42cb5a..fb7af4c 100644 --- a/package/targets.mak +++ b/package/targets.mak @@ -12,4 +12,3 @@ s6-swapon \ s6-umount LIBEXEC_TARGETS := - diff --git a/src/include-local/mount-constants.h b/src/include-local/mount-constants.h new file mode 100644 index 0000000..3b30035 --- /dev/null +++ b/src/include-local/mount-constants.h @@ -0,0 +1,78 @@ +/* ISC license. */ + +#ifndef MOUNT_CONSTANTS_H +#define MOUNT_CONSTANTS_H + +/* taken from util-linux */ + +#ifndef MS_RDONLY +#define MS_RDONLY 1 /* Mount read-only */ +#endif +#ifndef MS_NOSUID +#define MS_NOSUID 2 /* Ignore suid and sgid bits */ +#endif +#ifndef MS_NODEV +#define MS_NODEV 4 /* Disallow access to device special files */ +#endif +#ifndef MS_NOEXEC +#define MS_NOEXEC 8 /* Disallow program execution */ +#endif +#ifndef MS_SYNCHRONOUS +#define MS_SYNCHRONOUS 16 /* Writes are synced at once */ +#endif +#ifndef MS_REMOUNT +#define MS_REMOUNT 32 /* Alter flags of a mounted FS */ +#endif +#ifndef MS_MANDLOCK +#define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */ +#endif +#ifndef MS_DIRSYNC +#define MS_DIRSYNC 128 /* Directory modifications are synchronous */ +#endif +#ifndef MS_NOSYMFOLLOW +#define MS_NOSYMFOLLOW 256 /* Don't follow symlinks */ +#endif +#ifndef MS_NOATIME +#define MS_NOATIME 0x400 /* 1024: Do not update access times. */ +#endif +#ifndef MS_NODIRATIME +#define MS_NODIRATIME 0x800 /* 2048: Don't update directory access times */ +#endif +#ifndef MS_BIND +#define MS_BIND 0x1000 /* 4096: Mount existing tree also elsewhere */ +#endif +#ifndef MS_MOVE +#define MS_MOVE 0x2000 /* 8192: Atomically move tree */ +#endif +#ifndef MS_REC +#define MS_REC 0x4000 /* 16384: Recursive loopback */ +#endif +#ifndef MS_SILENT +#define MS_SILENT 0x8000 /* 32768: Don't emit certain kernel messages */ +#endif +#ifndef MS_UNBINDABLE +#define MS_UNBINDABLE (1<<17) /* 131072: Make unbindable */ +#endif +#ifndef MS_PRIVATE +#define MS_PRIVATE (1<<18) /* 262144: Make private */ +#endif +#ifndef MS_SLAVE +#define MS_SLAVE (1<<19) /* 524288: Make slave */ +#endif +#ifndef MS_SHARED +#define MS_SHARED (1<<20) /* 1048576: Make shared */ +#endif +#ifndef MS_RELATIME +#define MS_RELATIME (1<<21) /* 2097152: Update atime relative to mtime/ctime */ +#endif +#ifndef MS_I_VERSION +#define MS_I_VERSION (1<<23) /* Update the inode I_version field */ +#endif +#ifndef MS_STRICTATIME +#define MS_STRICTATIME (1<<24) /* Always perform atime updates */ +#endif +#ifndef MS_LAZYTIME +#define MS_LAZYTIME (1<<25) /* Update the on-disk [acm]times lazily */ +#endif + +#endif diff --git a/src/include-local/s6-ps.h b/src/include-local/s6-ps.h new file mode 100644 index 0000000..7c963f1 --- /dev/null +++ b/src/include-local/s6-ps.h @@ -0,0 +1,159 @@ +/* ISC license. */ + +#ifndef S6PS_H +#define S6PS_H + +#include +#include + +#include +#include +#include +#include + + +typedef struct dius_s dius_t, *dius_t_ref ; +struct dius_s +{ + uint32_t left ; + size_t right ; +} ; +#define DIUS_ZERO { .left = 0, .right = 0 } + +typedef enum pfield_e pfield_t, *pfield_t_ref ; +enum pfield_e +{ + PFIELD_PID, + PFIELD_COMM, + PFIELD_STATE, + PFIELD_PPID, + PFIELD_PGRP, + PFIELD_SESSION, + PFIELD_TTY, + PFIELD_TPGID, + PFIELD_UTIME, + PFIELD_STIME, + PFIELD_CUTIME, + PFIELD_CSTIME, + PFIELD_PRIO, + PFIELD_NICE, + PFIELD_THREADS, + PFIELD_START, + PFIELD_VSIZE, + PFIELD_RSS, + PFIELD_RSSLIM, + PFIELD_CPUNO, + PFIELD_RTPRIO, + PFIELD_RTPOLICY, + PFIELD_USER, + PFIELD_GROUP, + PFIELD_PMEM, + PFIELD_WCHAN, + PFIELD_ARGS, + PFIELD_ENV, + PFIELD_PCPU, + PFIELD_TTIME, + PFIELD_CTTIME, + PFIELD_TSTART, + PFIELD_CPCPU, + PFIELD_PHAIL +} ; + +extern char const *const *s6ps_opttable ; +extern char const *const *s6ps_fieldheaders ; + +typedef struct pscan_s pscan_t, *pscan_t_ref ; +struct pscan_s +{ + stralloc data ; + pid_t pid ; + signed int height ; + size_t statlen ; + size_t commlen ; + size_t cmdlen ; + size_t envlen ; + uid_t uid ; + gid_t gid ; + pid_t ppid ; + unsigned int state ; + pid_t pgrp ; + pid_t session ; + dev_t ttynr ; + pid_t tpgid ; + uint64_t utime ; + uint64_t stime ; + uint64_t cutime ; + uint64_t cstime ; + int prio ; + int nice ; + uint64_t threads ; + uint64_t start ; + uint64_t vsize ; + uint64_t rss ; + uint64_t rsslim ; + uint64_t wchan ; + uint64_t cpuno ; + uint64_t rtprio ; + uint64_t policy ; +} ; + +#define PSCAN_ZERO \ +{ \ + .data = STRALLOC_ZERO, \ + .pid = 0, \ + .height = 0, \ + .statlen = 0, \ + .commlen = 0, \ + .cmdlen = 0, \ + .envlen = 0, \ + .uid = 0, \ + .gid = 0, \ + .ppid = 0, \ + .state = 0, \ + .pgrp = 0, \ + .session = 0, \ + .ttynr = 0, \ + .tpgid = -1, \ + .utime = 0, \ + .stime = 0, \ + .cutime = 0, \ + .cstime = 0, \ + .prio = 0, \ + .nice = 0, \ + .threads = 0, \ + .start = 0, \ + .vsize = 0, \ + .rss = 0, \ + .rsslim = 0, \ + .wchan = 0, \ + .cpuno = 0, \ + .rtprio = 0, \ + .policy = 0 \ +} + +extern int s6ps_statparse (pscan_t *) ; +extern void s6ps_otree (pscan_t *, unsigned int, avltreen *, unsigned int *) ; + +extern int s6ps_compute_boottime (pscan_t *, unsigned int) ; + +typedef int pfieldfmt_func (pscan_t *, size_t *, size_t *) ; +typedef pfieldfmt_func *pfieldfmt_func_ref ; + +extern pfieldfmt_func_ref *s6ps_pfield_fmt ; + +extern void *left_dtok (unsigned int, void *) ; +extern int uint32_cmp (void const *, void const *, void *) ; +extern int s6ps_pwcache_init (void) ; +extern void s6ps_pwcache_finish (void) ; +extern int s6ps_pwcache_lookup (stralloc *, uid_t) ; +extern int s6ps_grcache_init (void) ; +extern void s6ps_grcache_finish (void) ; +extern int s6ps_grcache_lookup (stralloc *, gid_t) ; +extern int s6ps_ttycache_init (void) ; +extern void s6ps_ttycache_finish (void) ; +extern int s6ps_ttycache_lookup (stralloc *, dev_t) ; +extern int s6ps_wchan_init (char const *) ; +extern void s6ps_wchan_finish (void) ; +extern int s6ps_wchan_lookup (stralloc *, uint64_t) ; + +#endif diff --git a/src/libps/deps-lib/s6ps b/src/libps/deps-lib/s6ps new file mode 100644 index 0000000..0f078a6 --- /dev/null +++ b/src/libps/deps-lib/s6ps @@ -0,0 +1,7 @@ +s6ps_grcache.o +s6ps_otree.o +s6ps_pfield.o +s6ps_pwcache.o +s6ps_statparse.o +s6ps_ttycache.o +s6ps_wchan.o diff --git a/src/libps/s6ps_grcache.c b/src/libps/s6ps_grcache.c new file mode 100644 index 0000000..189f5ae --- /dev/null +++ b/src/libps/s6ps_grcache.c @@ -0,0 +1,67 @@ +/* ISC license. */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "s6-ps.h" + +static avltree grcache_tree = AVLTREE_ZERO ; +static genalloc grcache_index = GENALLOC_ZERO ; + +int s6ps_grcache_init (void) +{ + avltree_init(&grcache_tree, 5, 3, 8, &left_dtok, &uint32_cmp, &grcache_index) ; + return 1 ; +} + +void s6ps_grcache_finish (void) +{ + avltree_free(&grcache_tree) ; + genalloc_free(dius_t, &grcache_index) ; +} + +int s6ps_grcache_lookup (stralloc *sa, gid_t gid) +{ + int wasnull = !satmp.s ; + dius_t d = { .left = (uint32_t)gid, .right = satmp.len } ; + uint32_t i ; + if (!avltree_search(&grcache_tree, &d.left, &i)) + { + struct group *gr ; + unsigned int n = genalloc_len(dius_t, &grcache_index) ; + errno = 0 ; + gr = getgrgid(gid) ; + if (!gr) + { + if (errno) return 0 ; + if (!stralloc_readyplus(&satmp, UINT_FMT + 2)) return 0 ; + stralloc_catb(&satmp, "(", 1) ; + satmp.len += uint_fmt(satmp.s + satmp.len, gid) ; + stralloc_catb(&satmp, ")", 2) ; + } + else if (!stralloc_cats(&satmp, gr->gr_name) || !stralloc_0(&satmp)) return 0 ; + if (!genalloc_append(dius_t, &grcache_index, &d)) goto err ; + if (!avltree_insert(&grcache_tree, n)) + { + genalloc_setlen(dius_t, &grcache_index, n) ; + goto err ; + } + i = n ; + } + return stralloc_cats(sa, satmp.s + genalloc_s(dius_t, &grcache_index)[i].right) ; + err: + { + int e = errno ; + if (wasnull) stralloc_free(&satmp) ; + else satmp.len = d.right ; + errno = e ; + } + return 0 ; +} diff --git a/src/libps/s6ps_otree.c b/src/libps/s6ps_otree.c new file mode 100644 index 0000000..6ba8589 --- /dev/null +++ b/src/libps/s6ps_otree.c @@ -0,0 +1,100 @@ +/* ISC license. */ + +#include + +#include + +#include "s6-ps.h" + +typedef struct ptreeiter_s ptreeiter_t, *ptreeiter_t_ref ; +struct ptreeiter_s +{ + unsigned int *childlist ; + unsigned int const *childindex ; + unsigned int const *ppindex ; + unsigned int *cpos ; +} ; + +typedef struct pstuff_s pstuff_t, *pstuff_t_ref ; +struct pstuff_s +{ + unsigned int *orderedlist ; + pscan_t *p ; + unsigned int const *childlist ; + unsigned int const *childindex ; + unsigned int const *nchild ; +} ; + +static int fillchildlist (unsigned int i, unsigned int h, void *x) +{ + ptreeiter_t *pt = x ; + unsigned int j = pt->ppindex[i] ; + pt->childlist[pt->childindex[j] + pt->cpos[j]++] = i ; + (void)h ; + return 1 ; +} + +static void fillo_tree_rec (pstuff_t *blah, unsigned int root, signed int h) +{ + static unsigned int j = 0 ; + unsigned int i = !blah->p[root].pid ; + if (blah->p[root].pid == 1) h = -1 ; + blah->p[root].height = (h > 0) ? h : 0 ; + blah->orderedlist[j++] = root ; + for (; i < blah->nchild[root] ; i++) + fillo_tree_rec(blah, blah->childlist[blah->childindex[root] + i], h+1) ; +} + + /* + Fills up orderedlist with the right indices to print a process tree. + O(n log n) time, O(n) space, all in the stack. + */ + +void s6ps_otree (pscan_t *p, unsigned int n, avltreen *pidtree, unsigned int *orderedlist) +{ + unsigned int childlist[n] ; + unsigned int childindex[n] ; + unsigned int nchild[n] ; + unsigned int i = 0 ; + for (; i < n ; i++) nchild[i] = 0 ; + + /* Compute the ppid tree */ + for (i = 0 ; i < n ; i++) + { + uint32_t k ; + if (!avltreen_search(pidtree, &p[i].ppid, &k)) k = n-1 ; + orderedlist[i] = k ; /* using orderedlist as ppindex */ + nchild[k]++ ; + } + { + unsigned int j = 0 ; + for (i = 0 ; i < n ; i++) + { + childindex[i] = j ; + j += nchild[i] ; + } + } + + /* Fill the childlist by increasing pids so it is sorted */ + { + unsigned int cpos[n] ; + ptreeiter_t blah = { .childlist = childlist, .childindex = childindex, .ppindex = orderedlist, .cpos = cpos } ; + for (i = 0 ; i < n ; i++) cpos[i] = 0 ; + avltreen_iter_nocancel(pidtree, avltreen_totalsize(pidtree), &fillchildlist, &blah) ; + } + + /* If we have init, make it the last in the orphan list */ + if (n > 1 && p[childlist[childindex[n-1]+1]].pid == 1) + { + unsigned int pos1 = childlist[childindex[n-1] + 1] ; + for (i = 2 ; i < nchild[n-1] ; i++) + childlist[childindex[n-1]+i-1] = childlist[childindex[n-1]+i] ; + childlist[childindex[n-1]+nchild[n-1]-1] = pos1 ; + } + + /* Finally, fill orderedlist by walking the childindex tree. */ + { + pstuff_t blah = { .orderedlist = orderedlist, .p = p, .childlist = childlist, .childindex = childindex, .nchild = nchild } ; + fillo_tree_rec(&blah, n-1, -1) ; + } +} diff --git a/src/libps/s6ps_pfield.c b/src/libps/s6ps_pfield.c new file mode 100644 index 0000000..9e53e50 --- /dev/null +++ b/src/libps/s6ps_pfield.c @@ -0,0 +1,561 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "s6-ps.h" + +static char const *const fieldheaders[PFIELD_PHAIL] = +{ + "PID", + "COMM", + "STAT", + "PPID", + "PGRP", + "SESSION", + "TTY", + "TPGID", + "UTIME", + "STIME", + "CUTIME", + "CSTIME", + "PRIO", + "NICE", + "THREADS", + "START", + "VSZ", + "RSS", + "RSSLIM", + "CPU", + "RTPRIO", + "RTPOLICY", + "USER", + "GROUP", + "%MEM", + "WCHAN", + "COMMAND", + "ENVIRONMENT", + "%CPU", + "TTIME", + "CTTIME", + "TSTART", + "C%CPU" +} ; + +char const *const *s6ps_fieldheaders = fieldheaders ; + +static char const *const opttable[PFIELD_PHAIL] = +{ + "pid", + "comm", + "s", + "ppid", + "pgrp", + "sess", + "tty", + "tpgid", + "utime", + "stime", + "cutime", + "cstime", + "prio", + "nice", + "thcount", + "start", + "vsize", + "rss", + "rsslimit", + "psr", + "rtprio", + "policy", + "user", + "group", + "pmem", + "wchan", + "args", + "env", + "pcpu", + "ttime", + "cttime", + "tstart", + "cpcpu" +} ; + +char const *const *s6ps_opttable = opttable ; + +static tain boottime = TAIN_EPOCH ; + +static int fmt_64 (pscan_t *p, size_t *pos, size_t *len, uint64_t u) +{ + if (!stralloc_readyplus(&p->data, UINT64_FMT)) return 0 ; + *pos = p->data.len ; + *len = uint64_fmt(p->data.s + *pos, u) ; + p->data.len += *len ; + return 1 ; +} + +static int fmt_i (pscan_t *p, size_t *pos, size_t *len, int d) +{ + if (!stralloc_readyplus(&p->data, UINT32_FMT+1)) return 0 ; + *pos = p->data.len ; + *len = int_fmt(p->data.s + *pos, d) ; + p->data.len += *len ; + return 1 ; +} + +static int fmt_pid (pscan_t *p, size_t *pos, size_t *len) +{ + return fmt_64(p, pos, len, p->pid) ; +} + +static int fmt_comm (pscan_t *p, size_t *pos, size_t *len) +{ + *pos = p->statlen ; + *len = p->commlen ; + return 1 ; +} + +static int fmt_s (pscan_t *p, size_t *pos, size_t *len) +{ + if (!stralloc_readyplus(&p->data, 4)) return 0 ; + *pos = p->data.len ; + p->data.s[p->data.len++] = p->data.s[p->state] ; + if (p->pid == p->session) p->data.s[p->data.len++] = 's' ; + if (p->threads > 1) p->data.s[p->data.len++] = 'l' ; + if ((p->tpgid > 0) && ((unsigned int)p->tpgid == p->pgrp)) + p->data.s[p->data.len++] = '+' ; + if (p->nice) p->data.s[p->data.len++] = (p->nice < 0) ? '<' : 'N' ; + + *len = p->data.len - *pos ; + return 1 ; +} + +static int fmt_ppid (pscan_t *p, size_t *pos, size_t *len) +{ + return fmt_64(p, pos, len, p->ppid) ; +} + +static int fmt_pgrp (pscan_t *p, size_t *pos, size_t *len) +{ + return fmt_64(p, pos, len, p->pgrp) ; +} + +static int fmt_session (pscan_t *p, size_t *pos, size_t *len) +{ + return fmt_64(p, pos, len, p->session) ; +} + +static int fmt_ttynr(pscan_t *p, size_t *pos, size_t *len) +{ + if (p->ttynr) + { + size_t tmppos = p->data.len ; + if (!s6ps_ttycache_lookup(&p->data, p->ttynr)) return 0 ; + *pos = tmppos ; + *len = p->data.len - tmppos ; + } + else + { + if (!stralloc_catb(&p->data, "-", 1)) return 0 ; + *pos = p->data.len - 1 ; + *len = 1 ; + } + return 1 ; +} + +static int fmt_tpgid (pscan_t *p, size_t *pos, size_t *len) +{ + return p->tpgid < 0 ? fmt_i(p, pos, len, -1) : fmt_64(p, pos, len, p->tpgid) ; +} + +static unsigned int gethz (void) +{ + static unsigned int hz = 0 ; + if (!hz) + { + long jiffies = sysconf(_SC_CLK_TCK) ; + if (jiffies < 1) + { + char fmt[ULONG_FMT + 1] ; + fmt[long_fmt(fmt, jiffies)] = 0 ; + strerr_warnw3x("invalid _SC_CLK_TCK value (", fmt, "), using 100") ; + hz = 100 ; + } + else hz = (unsigned int)jiffies ; + } + return hz ; +} + +int s6ps_compute_boottime (pscan_t *p, unsigned int mypos) +{ + if (!mypos--) + { + strerr_warnwu1x("compute boot time - using epoch") ; + return 0 ; + } + else + { + unsigned int hz = gethz() ; + tain offset = { .sec = { .x = p[mypos].start / hz }, .nano = (p[mypos].start % hz) * (1000000000 / hz) } ; + tain_sub(&boottime, &STAMP, &offset) ; + return 1 ; + } +} + +static int fmt_jiffies (pscan_t *p, size_t *pos, size_t *len, uint64_t j) +{ + unsigned int hz = gethz() ; + uint32_t hrs, mins, secs, hfrac ; + if (!stralloc_readyplus(&p->data, UINT64_FMT + 13)) return 0 ; + hfrac = (j % hz) * 100 / hz ; + *pos = p->data.len ; + j /= hz ; + secs = j % 60 ; j /= 60 ; + mins = j % 60 ; j /= 60 ; + hrs = j % 24 ; j /= 24 ; + if (j) + { + p->data.len += uint64_fmt(p->data.s + p->data.len, j) ; + p->data.s[p->data.len++] = 'd' ; + } + if (j || hrs) + { + uint320_fmt(p->data.s + p->data.len, hrs, 2) ; + p->data.len += 2 ; + p->data.s[p->data.len++] = 'h' ; + } + if (j || hrs || mins) + { + uint320_fmt(p->data.s + p->data.len, mins, 2) ; + p->data.len += 2 ; + p->data.s[p->data.len++] = 'm' ; + } + uint320_fmt(p->data.s + p->data.len, secs, 2) ; + p->data.len += 2 ; + if (!j && !hrs && !mins) + { + p->data.s[p->data.len++] = '.' ; + uint320_fmt(p->data.s + p->data.len, hfrac, 2) ; + p->data.len += 2 ; + } + p->data.s[p->data.len++] = 's' ; + *len = p->data.len - *pos ; + return 1 ; +} + +static int fmt_utime (pscan_t *p, size_t *pos, size_t *len) +{ + return fmt_jiffies(p, pos, len, p->utime) ; +} + +static int fmt_stime (pscan_t *p, size_t *pos, size_t *len) +{ + return fmt_jiffies(p, pos, len, p->stime) ; +} + +static int fmt_cutime (pscan_t *p, size_t *pos, size_t *len) +{ + return fmt_jiffies(p, pos, len, p->utime + p->cutime) ; +} + +static int fmt_cstime (pscan_t *p, size_t *pos, size_t *len) +{ + return fmt_jiffies(p, pos, len, p->stime + p->cstime) ; +} + +static int fmt_prio (pscan_t *p, size_t *pos, size_t *len) +{ + return fmt_i(p, pos, len, p->prio) ; +} + +static int fmt_nice (pscan_t *p, size_t *pos, size_t *len) +{ + return fmt_i(p, pos, len, p->nice) ; +} + +static int fmt_threads (pscan_t *p, size_t *pos, size_t *len) +{ + return fmt_64(p, pos, len, p->threads) ; +} + +static int fmt_timedate (pscan_t *p, size_t *pos, size_t *len, struct tm const *tm) +{ + static struct tm nowtm = { .tm_year = 0 } ; + size_t tmplen ; + char *tmpstrf = "%F" ; + if (!nowtm.tm_year && !localtm_from_tai(&nowtm, tain_secp(&STAMP), 1)) return 0 ; + if (!stralloc_readyplus(&p->data, 20)) return 0 ; + if (tm->tm_year == nowtm.tm_year && tm->tm_yday == nowtm.tm_yday) + tmpstrf = "%T" ; + else if (tm->tm_year == nowtm.tm_year || (tm->tm_year+1 == nowtm.tm_year && (nowtm.tm_mon + 12 - tm->tm_mon) % 12 < 9)) + tmpstrf = "%b%d %R" ; + tmplen = strftime(p->data.s + p->data.len, 20, tmpstrf, tm) ; + if (!tmplen) return 0 ; + *len = tmplen ; + *pos = p->data.len ; + p->data.len += tmplen ; + return 1 ; +} + +static int fmt_start (pscan_t *p, size_t *pos, size_t *len) +{ + struct tm starttm ; + unsigned int hz = gethz() ; + tain blah = { .sec = { .x = p->start / hz }, .nano = (p->start % hz) * (1000000000 / hz) } ; + tain_add(&blah, &boottime, &blah) ; + if (!localtm_from_tai(&starttm, tain_secp(&blah), 1)) return 0 ; + return fmt_timedate(p, pos, len, &starttm) ; +} + +static unsigned int getpgsz (void) +{ + static unsigned int pgsz = 0 ; + if (!pgsz) + { + long sz = sysconf(_SC_PAGESIZE) ; + if (sz < 1) + { + char fmt[ULONG_FMT + 1] ; + fmt[long_fmt(fmt, sz)] = 0 ; + strerr_warnw3x("invalid _SC_PAGESIZE value (", fmt, "), using 4096") ; + pgsz = 4096 ; + } + else pgsz = sz ; + } + return pgsz ; +} + +static int fmt_vsize (pscan_t *p, size_t *pos, size_t *len) +{ + return fmt_64(p, pos, len, p->vsize / 1024) ; +} + +static int fmt_rss (pscan_t *p, size_t *pos, size_t *len) +{ + return fmt_64(p, pos, len, p->rss * (getpgsz() / 1024)) ; +} + +static int fmt_rsslim (pscan_t *p, size_t *pos, size_t *len) +{ + return fmt_64(p, pos, len, p->rsslim / 1024) ; +} + +static int fmt_cpuno (pscan_t *p, size_t *pos, size_t *len) +{ + return fmt_64(p, pos, len, p->cpuno) ; +} + +static int fmt_rtprio (pscan_t *p, size_t *pos, size_t *len) +{ + return fmt_64(p, pos, len, p->rtprio) ; +} + +static int fmt_policy (pscan_t *p, size_t *pos, size_t *len) +{ + static char const *const policies[8] = { "NORMAL", "FIFO", "RR", "BATCH", "ISO", "IDLE", "UNKNOWN", "UNKNOWN" } ; + size_t tmppos = p->data.len ; + if (!stralloc_cats(&p->data, policies[p->policy & 7])) return 0 ; + *pos = tmppos ; + *len = p->data.len - tmppos ; + return 1 ; +} + +static int fmt_user (pscan_t *p, size_t *pos, size_t *len) +{ + size_t tmppos = p->data.len ; + if (!s6ps_pwcache_lookup(&p->data, p->uid)) return 0 ; + *pos = tmppos ; + *len = p->data.len - tmppos ; + return 1 ; +} + +static int fmt_group (pscan_t *p, size_t *pos, size_t *len) +{ + size_t tmppos = p->data.len ; + if (!s6ps_grcache_lookup(&p->data, p->gid)) return 0 ; + *pos = tmppos ; + *len = p->data.len - tmppos ; + return 1 ; +} + +static struct sysinfo si = { .totalram = 0, .loads = { 0, 0, 0 } } ; + +static uint64_t gettotalmem (void) +{ + uint64_t totalmem = 0 ; + if (!si.totalram && (sysinfo(&si) < 0)) return 0 ; + totalmem = si.totalram ; + totalmem *= si.mem_unit ; + return totalmem ; +} + +static int percent (stralloc *sa, unsigned int n, size_t *pos, size_t *len) +{ + if (!stralloc_readyplus(sa, UINT64_FMT+1)) return 0 ; + *pos = sa->len ; + sa->len += uint_fmt(sa->s + sa->len, n / 100) ; + sa->s[sa->len++] = '.' ; + uint0_fmt(sa->s + sa->len, n % 100, 2) ; + sa->len += 2 ; + *len = sa->len - *pos ; + return 1 ; +} + +static int fmt_pmem (pscan_t *p, size_t *pos, size_t *len) +{ + uint64 l = gettotalmem() ; + return l ? percent(&p->data, p->rss * getpgsz() * 10000 / l, pos, len) : 0 ; +} + +static int fmt_wchan (pscan_t *p, size_t *pos, size_t *len) +{ + size_t tmppos = p->data.len ; + if (!s6ps_wchan_lookup(&p->data, p->wchan)) return 0 ; + *len = p->data.len - tmppos ; + *pos = tmppos ; + return 1 ; +} + +static int fmt_args (pscan_t *p, size_t *pos, size_t *len) +{ + if (!stralloc_readyplus(&p->data, (p->height << 2) + (p->cmdlen ? p->cmdlen : p->commlen + (p->data.s[p->state] == 'Z' ? 11 : 3)))) + return 0 ; + *pos = p->data.len ; + if (p->height) + { + unsigned int i = 0 ; + for (; i < 4 * (unsigned int)p->height - 3 ; i++) + p->data.s[p->data.len + i] = ' ' ; + memcpy(p->data.s + p->data.len + 4 * p->height - 3, "\\_ ", 3) ; + p->data.len += p->height << 2 ; + } + if (p->cmdlen) + { + char const *r = p->data.s + p->statlen + p->commlen ; + char *w = p->data.s + p->data.len ; + size_t i = p->cmdlen ; + while (i--) + { + char c = *r++ ; + *w++ = c ? c : ' ' ; + } + p->data.len += p->cmdlen ; + } + else if (p->data.s[p->state] == 'Z') + { + stralloc_catb(&p->data, p->data.s + uint32_fmt(0, p->pid) + 2, p->commlen) ; + stralloc_catb(&p->data, " ", 10) ; + } + else + stralloc_catb(&p->data, p->data.s + uint32_fmt(0, p->pid) + 1, p->commlen+2) ; + *len = p->data.len - *pos ; + return 1 ; +} + +static int fmt_env (pscan_t *p, size_t *pos, size_t *len) +{ + size_t i = 0 ; + if (!p->envlen) + { + if (!stralloc_catb(&p->data, "*", 1)) return 0 ; + *pos = p->data.len - 1 ; + *len = 1 ; + return 1 ; + } + *pos = p->statlen + p->commlen + p->cmdlen ; + *len = p->envlen ; + for (; i < *len ; i++) + if (!p->data.s[*pos + i]) p->data.s[*pos + i] = ' ' ; + return 1 ; +} + +static uint64_t gettotalj (uint64_t j) +{ + tain totaltime ; + unsigned int hz = gethz() ; + tain_sub(&totaltime, &STAMP, &boottime) ; + j = totaltime.sec.x * hz + totaltime.nano / (1000000000 / hz) - j ; + if (!j) j = 1 ; + return j ; +} + +static int fmt_pcpu (pscan_t *p, size_t *pos, size_t *len) +{ + return percent(&p->data, 10000 * (p->utime + p->stime) / gettotalj(p->start), pos, len) ; +} + +static int fmt_ttime (pscan_t *p, size_t *pos, size_t *len) +{ + return fmt_jiffies(p, pos, len, p->utime + p->stime) ; +} + +static int fmt_cttime (pscan_t *p, size_t *pos, size_t *len) +{ + return fmt_jiffies(p, pos, len, p->utime + p->stime + p->cutime + p->cstime) ; +} + +static int fmt_tstart (pscan_t *p, size_t *pos, size_t *len) +{ + unsigned int hz = gethz() ; + tain blah = { .sec = { .x = p->start / hz }, .nano = (p->start % hz) * (1000000000 / hz) } ; + if (!stralloc_readyplus(&p->data, TIMESTAMP)) return 0 ; + tain_add(&blah, &boottime, &blah) ; + *pos = p->data.len ; + *len = timestamp_fmt(p->data.s + p->data.len, &blah) ; + p->data.len += *len ; + return 1 ; +} + +static int fmt_cpcpu (pscan_t *p, size_t *pos, size_t *len) +{ + return percent(&p->data, 10000 * (p->utime + p->stime + p->cutime + p->cstime) / gettotalj(p->start), pos, len) ; +} + +static pfieldfmt_func_ref pfieldfmt_table[PFIELD_PHAIL] = +{ + &fmt_pid, + &fmt_comm, + &fmt_s, + &fmt_ppid, + &fmt_pgrp, + &fmt_session, + &fmt_ttynr, + &fmt_tpgid, + &fmt_utime, + &fmt_stime, + &fmt_cutime, + &fmt_cstime, + &fmt_prio, + &fmt_nice, + &fmt_threads, + &fmt_start, + &fmt_vsize, + &fmt_rss, + &fmt_rsslim, + &fmt_cpuno, + &fmt_rtprio, + &fmt_policy, + &fmt_user, + &fmt_group, + &fmt_pmem, + &fmt_wchan, + &fmt_args, + &fmt_env, + &fmt_pcpu, + &fmt_ttime, + &fmt_cttime, + &fmt_tstart, + &fmt_cpcpu +} ; + +pfieldfmt_func_ref *s6ps_pfield_fmt = pfieldfmt_table ; diff --git a/src/libps/s6ps_pwcache.c b/src/libps/s6ps_pwcache.c new file mode 100644 index 0000000..ce4caa8 --- /dev/null +++ b/src/libps/s6ps_pwcache.c @@ -0,0 +1,67 @@ +/* ISC license. */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "s6-ps.h" + +static avltree pwcache_tree = AVLTREE_ZERO ; +static genalloc pwcache_index = GENALLOC_ZERO ; + +int s6ps_pwcache_init (void) +{ + avltree_init(&pwcache_tree, 5, 3, 8, &left_dtok, &uint32_cmp, &pwcache_index) ; + return 1 ; +} + +void s6ps_pwcache_finish (void) +{ + avltree_free(&pwcache_tree) ; + genalloc_free(dius_t, &pwcache_index) ; +} + +int s6ps_pwcache_lookup (stralloc *sa, uid_t uid) +{ + int wasnull = !satmp.s ; + dius_t d = { .left = (uint32_t)uid, .right = satmp.len } ; + uint32_t i ; + if (!avltree_search(&pwcache_tree, &d.left, &i)) + { + struct passwd *pw ; + unsigned int n = genalloc_len(dius_t, &pwcache_index) ; + errno = 0 ; + pw = getpwuid(uid) ; + if (!pw) + { + if (errno) return 0 ; + if (!stralloc_readyplus(&satmp, UINT_FMT + 2)) return 0 ; + stralloc_catb(&satmp, "(", 1) ; + satmp.len += uint_fmt(satmp.s + satmp.len, uid) ; + stralloc_catb(&satmp, ")", 2) ; + } + else if (!stralloc_cats(&satmp, pw->pw_name) || !stralloc_0(&satmp)) return 0 ; + if (!genalloc_append(dius_t, &pwcache_index, &d)) goto err ; + if (!avltree_insert(&pwcache_tree, n)) + { + genalloc_setlen(dius_t, &pwcache_index, n) ; + goto err ; + } + i = n ; + } + return stralloc_cats(sa, satmp.s + genalloc_s(dius_t, &pwcache_index)[i].right) ; + err: + { + int e = errno ; + if (wasnull) stralloc_free(&satmp) ; + else satmp.len = d.right ; + errno = e ; + } + return 0 ; +} diff --git a/src/libps/s6ps_statparse.c b/src/libps/s6ps_statparse.c new file mode 100644 index 0000000..ea46d70 --- /dev/null +++ b/src/libps/s6ps_statparse.c @@ -0,0 +1,186 @@ +/* ISC license. */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "s6-ps.h" + + + /* + going to great lengths to avoid scanf(), but all this code + is still smaller than scanf (no floating point parsing etc.) + */ + +#define STATVARS 49 + +typedef size_t pscan_func (char const *, void *) ; +typedef pscan_func *pscan_func_ref ; + +static size_t f64 (char const *s, void *u64) +{ + uint64_t *u = u64 ; + return uint64_scan(s, u) ; +} + +#define DEFUNU(name, type) \ +static size_t name (char const *s, void *p) \ +{ \ + uint64_t u ; \ + size_t len = uint64_scan(s, &u) ; \ + *(type *)p = u ; \ + return len ; \ +} \ + +#define DEFUNS(name, type) \ +static size_t name (char const *s, void *p) \ +{ \ + int64_t d ; \ + size_t len = int64_scan(s, &d) ; \ + *(type *)p = d ; \ + return len ; \ +} \ + +DEFUNS(fint, int) +DEFUNS(fpid, pid_t) +DEFUNU(fdev, dev_t) + +static pscan_func_ref scanfuncs[STATVARS] = +{ + &fpid, /* ppid */ + &fpid, /* pgrp */ + &fpid, /* session */ + &fdev, /* tty_nr */ + &fpid, /* tpgid */ + &f64, /* flags */ + &f64, /* minflt */ + &f64, /* cminflt */ + &f64, /* majflt */ + &f64, /* cmajflt */ + &f64, /* utime */ + &f64, /* stime */ + &f64, /* cutime */ + &f64, /* cstime */ + &fint, /* priority */ + &fint, /* nice */ + &f64, /* num_threads */ + &f64, /* itrealvalue */ + &f64, /* starttime */ + &f64, /* vsize */ + &f64, /* rss */ + &f64, /* rsslim */ + &f64, /* startcode */ + &f64, /* endcode */ + &f64, /* startstack */ + &f64, /* kstkesp */ + &f64, /* kstkeip */ + &f64, /* signal */ + &f64, /* blocked */ + &f64, /* sigignore */ + &f64, /* sigcatch */ + &f64, /* wchan */ + &f64, /* nswap */ + &f64, /* cnswap */ + &fint, /* exit_signal */ + &f64, /* processor */ + &f64, /* rt_priority */ + &f64, /* policy */ + &f64, /* delayacct_blkio_ticks */ + &f64, /* guest_time */ + &f64, /* cguest_time */ + &f64, /* start_data */ + &f64, /* end_data */ + &f64, /* start_brk */ + &f64, /* arg_start */ + &f64, /* arg_end */ + &f64, /* env_start */ + &f64, /* env_end */ + &fint /* exit_code */ +} ; + +int s6ps_statparse (pscan_t *p) +{ + uint64_t dummy64 ; + int dummyint ; + size_t pos = 0 ; + void *scanresults[STATVARS] = + { + &p->ppid, + &p->pgrp, + &p->session, + &p->ttynr, + &p->tpgid, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &p->utime, + &p->stime, + &p->cutime, + &p->cstime, + &p->prio, + &p->nice, + &p->threads, + &dummy64, + &p->start, + &p->vsize, + &p->rss, + &p->rsslim, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &p->wchan, + &dummy64, + &dummy64, + &dummy64, + &p->cpuno, + &p->rtprio, + &p->policy, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummy64, + &dummyint + } ; + unsigned int i = 0 ; + + if (!p->statlen) return 0 ; + pos = uint64_scan(p->data.s, &dummy64) ; + if (!pos) return 0 ; + if (dummy64 != p->pid) return 0 ; + if (pos + 5 + p->commlen > p->statlen) return 0 ; + if (p->data.s[pos++] != ' ') return 0 ; + if (p->data.s[pos++] != '(') return 0 ; + pos += p->commlen ; + if (p->data.s[pos++] != ')') return 0 ; + if (p->data.s[pos++] != ' ') return 0 ; + p->state = pos++ ; + for (; i < STATVARS ; i++) + { + size_t w ; + if (pos + 1 > p->statlen) return 0 ; + if (p->data.s[pos++] != ' ') return 0 ; + w = (*scanfuncs[i])(p->data.s + pos, scanresults[i]) ; + if (!w) return 0 ; + pos += w ; + } + return 1 ; +} diff --git a/src/libps/s6ps_ttycache.c b/src/libps/s6ps_ttycache.c new file mode 100644 index 0000000..27282e7 --- /dev/null +++ b/src/libps/s6ps_ttycache.c @@ -0,0 +1,138 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "s6-ps.h" + +static avltree ttycache_tree = AVLTREE_ZERO ; +static genalloc ttycache_index = GENALLOC_ZERO ; + +int s6ps_ttycache_init (void) +{ + avltree_init(&ttycache_tree, 5, 3, 8, &left_dtok, &uint32_cmp, &ttycache_index) ; + return 1 ; +} + +void s6ps_ttycache_finish (void) +{ + avltree_free(&ttycache_tree) ; + genalloc_free(dius_t, &ttycache_index) ; +} + +static int check (char const *s, dev_t ttynr) +{ + struct stat st ; + if (stat(s, &st) < 0) return 0 ; + return S_ISCHR(st.st_mode) && (st.st_rdev == ttynr) ; +} + + + /* No blind scanning of all /dev or /sys/devices, kthx */ + +static int ttyguess (stralloc *sa, dev_t ttynr) +{ + unsigned int maj = major(ttynr), min = minor(ttynr) ; + + /* Try /dev/tty? and /dev/pts/? */ + if (maj == 4 && min < 64) + { + char tmp[11] = "/dev/tty" ; + tmp[uint_fmt(tmp+8, min)] = 0 ; + if (check(tmp, ttynr)) return stralloc_cats(sa, tmp+5) && stralloc_0(sa) ; + } + else if (maj >= 136 && maj < 144) + { + unsigned int n = ((maj - 136) << 20) | min ; + char tmp[9 + UINT_FMT] = "/dev/pts/" ; + tmp[9 + uint_fmt(tmp+9, n)] = 0 ; + if (check(tmp, ttynr)) return stralloc_cats(sa, tmp+5) && stralloc_0(sa) ; + } + + /* Use /sys/dev/char/maj:min if it exists */ + { + int fd ; + size_t pos = 14 ; + char path[23 + 2 * UINT_FMT] = "/sys/dev/char/" ; + pos += uint_fmt(path + pos, maj) ; + path[pos++] = ':' ; + pos += uint_fmt(path + pos, min) ; + memcpy(path + pos, "/uevent", 8) ; + fd = open_read(path) ; + if (fd >= 0) + { + char buf[4097] ; + buffer b = BUFFER_INIT(&fd_readv, fd, buf, 4097) ; + size_t start = satmp.len ; + int r ; + for (;;) + { + satmp.len = start ; + r = skagetln(&b, &satmp, '\n') ; + if (r <= 0) break ; + if ((satmp.len - start) > 8 && !memcmp(satmp.s + start, "DEVNAME=", 8)) break ; + } + fd_close(fd) ; + if (r > 0) + { + satmp.s[satmp.len - 1] = 0 ; + satmp.len = start ; + memcpy(satmp.s + start + 3, "/dev/", 5) ; + if (check(satmp.s + start + 3, ttynr)) + return stralloc_cats(sa, satmp.s + start + 8) && stralloc_0(sa) ; + } + } + } + + /* Fallback: print explicit maj:min */ + { + size_t pos = 1 ; + char tmp[3 + 2 * UINT_FMT] = "(" ; + pos += uint_fmt(tmp + pos, maj) ; + tmp[pos++] = ':' ; + pos += uint_fmt(tmp + pos, min) ; + tmp[pos++] = ')' ; + tmp[pos++] = 0 ; + return stralloc_catb(sa, tmp, pos) ; + } +} + +int s6ps_ttycache_lookup (stralloc *sa, dev_t ttynr) +{ + int wasnull = !satmp.s ; + dius_t d = { .left = (uint32_t)ttynr, .right = satmp.len } ; + uint32_t i ; + if (!avltree_search(&ttycache_tree, &d.left, &i)) + { + unsigned int n = genalloc_len(dius_t, &ttycache_index) ; + if (!ttyguess(&satmp, ttynr)) return 0 ; + if (!genalloc_append(dius_t, &ttycache_index, &d)) goto err ; + if (!avltree_insert(&ttycache_tree, n)) + { + genalloc_setlen(dius_t, &ttycache_index, n) ; + goto err ; + } + i = n ; + } + return stralloc_cats(sa, satmp.s + genalloc_s(dius_t, &ttycache_index)[i].right) ; + err: + { + int e = errno ; + if (wasnull) stralloc_free(&satmp) ; + else satmp.len = d.right ; + errno = e ; + } + return 0 ; +} diff --git a/src/libps/s6ps_wchan.c b/src/libps/s6ps_wchan.c new file mode 100644 index 0000000..9261693 --- /dev/null +++ b/src/libps/s6ps_wchan.c @@ -0,0 +1,96 @@ +/* ISC license. */ + +#include +#include + +#include +#include +#include +#include + +#include "s6-ps.h" + +static stralloc sysmap = STRALLOC_ZERO ; +static genalloc ind = GENALLOC_ZERO ; + +int s6ps_wchan_init (char const *file) +{ + if (file) + { + if (!openslurpclose(&sysmap, file)) return 0 ; + } + else + { + char *files[3] = { "/proc/kallsyms", 0, "/boot/System.map" } ; + struct utsname uts ; + size_t n ; + if (uname(&uts) < 0) return 0 ; + n = strlen(uts.release) ; + { + char buf[18 + n] ; + unsigned int i = 0 ; + memcpy(buf, "/boot/System.map", 16) ; + buf[16] = '-' ; + memcpy(buf + 17, uts.release, n + 1) ; + files[1] = buf ; + for (; i < 3 ; i++) + if (openslurpclose(&sysmap, files[i])) break ; + if (i >= 3) return 0 ; + } + } + { + size_t i = 0 ; + if (!genalloc_append(size_t, &ind, &i)) goto err2 ; + for (i = 1 ; i <= sysmap.len ; i++) + if (sysmap.s[i-1] == '\n') + if (!genalloc_append(size_t, &ind, &i)) goto err ; + } + return 1 ; + err: + genalloc_free(size_t, &ind) ; + err2: + stralloc_free(&sysmap) ; + return 0 ; +} + +void s6ps_wchan_finish (void) +{ + genalloc_free(size_t, &ind) ; + stralloc_free(&sysmap) ; +} + +static inline size_t lookup (uint64_t addr, size_t *i) +{ + size_t low = 0, mid, high = genalloc_len(size_t, &ind), len ; + for (;;) + { + uint64_t cur ; + mid = (low + high) >> 1 ; + len = uint64_xscan(sysmap.s + genalloc_s(size_t, &ind)[mid], &cur) ; + if (!len) return 0 ; + if (cur == addr) break ; + if (mid == low) return 0 ; + if (addr < cur) high = mid ; else low = mid ; + } + *i = mid ; + return len ; +} + +int s6ps_wchan_lookup (stralloc *sa, uint64_t addr) +{ + if (addr == (sizeof(void *) == 8 ? 0xffffffffffffffffULL : 0xffffffffUL)) + return stralloc_catb(sa, "*", 1) ; + if (!addr) return stralloc_catb(sa, "-", 1) ; + if (sysmap.len) + { + size_t i, pos, len = lookup(addr, &i) ; + if (!len) return stralloc_catb(sa, "?", 1) ; + pos = genalloc_s(size_t, &ind)[i] + len + 3 ; + return stralloc_catb(sa, sysmap.s + pos, genalloc_s(size_t, &ind)[i+1] - 1 - pos) ; + } + if (!stralloc_readyplus(sa, UINT64_FMT + 3)) return 0 ; + stralloc_catb(sa, "(0x", 3) ; + sa->len += uint64_fmt(sa->s + sa->len, addr) ; + stralloc_catb(sa, ")", 1) ; + return 1 ; +} diff --git a/src/minutils/deps-exe/rngseed b/src/minutils/deps-exe/rngseed deleted file mode 100644 index a11a5f4..0000000 --- a/src/minutils/deps-exe/rngseed +++ /dev/null @@ -1,2 +0,0 @@ --lskarnet -${SYSCLOCK_LIB} diff --git a/src/minutils/deps-exe/s6-chroot b/src/minutils/deps-exe/s6-chroot deleted file mode 100644 index e7187fe..0000000 --- a/src/minutils/deps-exe/s6-chroot +++ /dev/null @@ -1 +0,0 @@ --lskarnet diff --git a/src/minutils/deps-exe/s6-freeramdisk b/src/minutils/deps-exe/s6-freeramdisk deleted file mode 100644 index e7187fe..0000000 --- a/src/minutils/deps-exe/s6-freeramdisk +++ /dev/null @@ -1 +0,0 @@ --lskarnet diff --git a/src/minutils/deps-exe/s6-hostname b/src/minutils/deps-exe/s6-hostname deleted file mode 100644 index e7187fe..0000000 --- a/src/minutils/deps-exe/s6-hostname +++ /dev/null @@ -1 +0,0 @@ --lskarnet diff --git a/src/minutils/deps-exe/s6-logwatch b/src/minutils/deps-exe/s6-logwatch deleted file mode 100644 index e7187fe..0000000 --- a/src/minutils/deps-exe/s6-logwatch +++ /dev/null @@ -1 +0,0 @@ --lskarnet diff --git a/src/minutils/deps-exe/s6-mount b/src/minutils/deps-exe/s6-mount deleted file mode 100644 index e7187fe..0000000 --- a/src/minutils/deps-exe/s6-mount +++ /dev/null @@ -1 +0,0 @@ --lskarnet diff --git a/src/minutils/deps-exe/s6-pivotchroot b/src/minutils/deps-exe/s6-pivotchroot deleted file mode 100644 index e7187fe..0000000 --- a/src/minutils/deps-exe/s6-pivotchroot +++ /dev/null @@ -1 +0,0 @@ --lskarnet diff --git a/src/minutils/deps-exe/s6-ps b/src/minutils/deps-exe/s6-ps deleted file mode 100644 index 1f0adc5..0000000 --- a/src/minutils/deps-exe/s6-ps +++ /dev/null @@ -1,10 +0,0 @@ -s6ps_statparse.o -s6ps_otree.o -s6ps_pfield.o -s6ps_pwcache.o -s6ps_grcache.o -s6ps_ttycache.o -s6ps_wchan.o -${LIBNSSS} --lskarnet -${MAYBEPTHREAD_LIB} diff --git a/src/minutils/deps-exe/s6-swapoff b/src/minutils/deps-exe/s6-swapoff deleted file mode 100644 index e7187fe..0000000 --- a/src/minutils/deps-exe/s6-swapoff +++ /dev/null @@ -1 +0,0 @@ --lskarnet diff --git a/src/minutils/deps-exe/s6-swapon b/src/minutils/deps-exe/s6-swapon deleted file mode 100644 index e7187fe..0000000 --- a/src/minutils/deps-exe/s6-swapon +++ /dev/null @@ -1 +0,0 @@ --lskarnet diff --git a/src/minutils/deps-exe/s6-umount b/src/minutils/deps-exe/s6-umount deleted file mode 100644 index e7187fe..0000000 --- a/src/minutils/deps-exe/s6-umount +++ /dev/null @@ -1 +0,0 @@ --lskarnet diff --git a/src/minutils/mount-constants.h b/src/minutils/mount-constants.h deleted file mode 100644 index 1e6f3c0..0000000 --- a/src/minutils/mount-constants.h +++ /dev/null @@ -1,81 +0,0 @@ -/* ISC license. */ - -#ifndef MOUNT_CONSTANTS_H -#define MOUNT_CONSTANTS_H - -/* taken from util-linux-ng */ - -#ifndef MS_RDONLY -#define MS_RDONLY 1 /* Mount read-only */ -#endif -#ifndef MS_NOSUID -#define MS_NOSUID 2 /* Ignore suid and sgid bits */ -#endif -#ifndef MS_NODEV -#define MS_NODEV 4 /* Disallow access to device special files */ -#endif -#ifndef MS_NOEXEC -#define MS_NOEXEC 8 /* Disallow program execution */ -#endif -#ifndef MS_SYNCHRONOUS -#define MS_SYNCHRONOUS 16 /* Writes are synced at once */ -#endif -#ifndef MS_REMOUNT -#define MS_REMOUNT 32 /* Alter flags of a mounted FS */ -#endif -#ifndef MS_MANDLOCK -#define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */ -#endif -#ifndef MS_DIRSYNC -#define MS_DIRSYNC 128 /* Directory modifications are synchronous */ -#endif -#ifndef MS_NOATIME -#define MS_NOATIME 0x400 /* 1024: Do not update access times. */ -#endif -#ifndef MS_NODIRATIME -#define MS_NODIRATIME 0x800 /* 2048: Don't update directory access times */ -#endif -#ifndef MS_BIND -#define MS_BIND 0x1000 /* 4096: Mount existing tree also elsewhere */ -#endif -#ifndef MS_MOVE -#define MS_MOVE 0x2000 /* 8192: Atomically move tree */ -#endif -#ifndef MS_REC -#define MS_REC 0x4000 /* 16384: Recursive loopback */ -#endif -#ifndef MS_VERBOSE -#define MS_VERBOSE 0x8000 /* 32768 */ -#endif -#ifndef MS_RELATIME -#define MS_RELATIME 0x200000 /* 200000: Update access times relative to mtime/ctime */ -#endif -#ifndef MS_UNBINDABLE -#define MS_UNBINDABLE (1<<17) /* 131072 unbindable */ -#endif -#ifndef MS_PRIVATE -#define MS_PRIVATE (1<<18) /* 262144 Private */ -#endif -#ifndef MS_SLAVE -#define MS_SLAVE (1<<19) /* 524288 Slave */ -#endif -#ifndef MS_SHARED -#define MS_SHARED (1<<20) /* 1048576 Shared */ -#endif -#ifndef MS_I_VERSION -#define MS_I_VERSION (1<<23) /* update inode I_version field */ -#endif -#ifndef MS_STRICTATIME -#define MS_STRICTATIME (1<<24) /* strict atime semantics */ -#endif -/* - * Magic mount flag number. Had to be or-ed to the flag values. - */ -#ifndef MS_MGC_VAL -#define MS_MGC_VAL 0xC0ED0000 /* magic flag number to indicate "new" flags */ -#endif -#ifndef MS_MGC_MSK -#define MS_MGC_MSK 0xffff0000 /* magic flag number mask */ -#endif - -#endif diff --git a/src/minutils/rngseed.c b/src/minutils/rngseed.c deleted file mode 100644 index bc16bbb..0000000 --- a/src/minutils/rngseed.c +++ /dev/null @@ -1,279 +0,0 @@ -/* ISC license. */ - -#include - -#ifndef SKALIBS_HASCLOCKBOOT -# error "CLOCK_BOOTTIME required" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define USAGE "rngseed [ -d seeddir ] [ -v verbosity ] [ -r | -R ] [ -n | -N ] [ -w | -W ]" -#define dieusage() strerr_dieusage(100, USAGE) - -#define HASH_PREFIX "SeedRNG v1 Old+New Prefix" -#define HASH_FALLBACK "SeedRNG v1 No New Seed Failure" - -struct flags_s -{ - unsigned int read: 1 ; - unsigned int rcred: 1 ; - unsigned int block: 1 ; - unsigned int write: 1 ; - unsigned int wcred: 1 ; -} ; -#define FLAGS_ZERO { .read = 0, .rcred = 1, .block = 1, .write = 0, .wcred = 1 } - -struct randpoolinfo_s -{ - int entropy_count ; - int buf_size ; - char buffer[512] ; -} ; - -static unsigned int verbosity = 1 ; - -static inline void mkdirp (char *s, size_t len) -{ - mode_t m = umask(0) ; - size_t i = 1 ; - for (; i < len ; i++) if (s[i] == '/') - { - s[i] = 0 ; - if (mkdir(s, 02755) < 0 && errno != EEXIST) - strerr_diefu2sys(111, "mkdir ", s) ; - s[i] = '/' ; - } - umask(m) ; -} - -static inline int read_seed_nb (char *s, size_t len) -{ - int wcred ; - size_t w = 0 ; -#ifdef SKALIBS_HASGETRANDOM - while (w < len) - { - ssize_t r = getrandom(s + w, len - w, GRND_NONBLOCK) ; - if (r == -1) - { - if (errno == EINTR) continue ; - if (error_isagain(errno)) break ; - strerr_diefu1sys(111, "getrandom") ; - } - else w += r ; - } - wcred = w >= len ; - if (!wcred) -#else - tain dummy = TAIN_EPOCH ; - iopause_fd x = { .events = IOPAUSE_READ } ; - x.fd = openbc_read("/dev/random") ; - if (x.fd == -1) strerr_diefu2sys(111, "open ", "/dev/random") ; - wcred = iopause(&x, 1, &dummy, &dummy) ; - if (wcred == -1) strerr_diefu1sys(111, "iopause") ; - fd_close(x.fd) ; -#endif - random_devurandom(s + w, len - w) ; - return wcred ; -} - -int main (int argc, char const *const *argv) -{ - blake2s_ctx ctx = BLAKE2S_INIT(32) ; - char const *seeddir = RNGSEED_DIR ; - struct flags_s flags = FLAGS_ZERO ; - PROG = "rngseed" ; - { - subgetopt l = SUBGETOPT_ZERO ; - for (;;) - { - int opt = subgetopt_r(argc, argv, "d:v:rRnNwW", &l) ; - if (opt == -1) break ; - switch (opt) - { - case 'd' : seeddir = l.arg ; break ; - case 'v' : if (!uint0_scan(l.arg, &verbosity)) dieusage() ; break ; - case 'r' : flags.read = 1 ; flags.rcred = 1 ; break ; - case 'R' : flags.read = 1 ; flags.rcred = 0 ; break ; - case 'n' : flags.block = 0 ; break ; - case 'N' : flags.block = 1 ; break ; - case 'w' : flags.write = 1 ; flags.wcred = 1 ; break ; - case 'W' : flags.write = 1 ; flags.wcred = 0 ; break ; - default : dieusage() ; - } - } - argc -= l.ind ; argv += l.ind ; - } - - { - size_t dirlen = strlen(seeddir) ; - char file[dirlen + 6] ; - memcpy(file, seeddir, dirlen) ; - while (dirlen && file[dirlen-1] == '/') dirlen-- ; - memcpy(file + dirlen, "/seed", 6) ; - - if (flags.write) - { - struct timespec ts ; - if (dirlen) - { - file[dirlen] = 0 ; - mkdirp(file, dirlen) ; - if (mkdir(file, 0700) == -1) - { - struct stat st ; - if (errno != EEXIST) strerr_diefu2sys(111, "mkdir ", file) ; - if (stat(file, &st) == -1) - strerr_diefu2sys(111, "stat ", file) ; - if (st.st_mode & 0077) - { - if (verbosity) - strerr_warnw2sys(file, "has permissive modes, changing it to 0700") ; - if (chmod(file, 0700) == -1) - strerr_diefu2sys(111, "chmod ", file) ; - } - } - file[dirlen] = '/' ; - } - blake2s_update(&ctx, HASH_PREFIX, sizeof(HASH_PREFIX) - 1) ; - clock_gettime(CLOCK_REALTIME, &ts) ; - blake2s_update(&ctx, (char *)&ts, sizeof ts) ; - clock_gettime(CLOCK_BOOTTIME, &ts) ; - blake2s_update(&ctx, (char *)&ts, sizeof ts) ; - } - - if (flags.read) - { - struct randpoolinfo_s req ; - struct stat st ; - size_t seedlen ; - int fd ; - if (verbosity >= 2) strerr_warni2x("reading seed from ", file) ; - fd = openbc_read(file) ; - if (fd == -1) strerr_diefu2sys(111, "open ", file) ; - errno = 0 ; - seedlen = allread(fd, req.buffer, 512) ; - if (errno) strerr_diefu2sys(111, "read from ", file) ; - if (!seedlen) strerr_dief2x(100, "empty ", file) ; - if (fstat(fd, &st) == -1) strerr_diefu2sys(111, "stat ", file) ; - if (unlink(file) == -1) strerr_diefu2sys(111, "unlink ", file) ; - fd_close(fd) ; - if (flags.write) - { - blake2s_update(&ctx, (char *)&seedlen, sizeof(seedlen)) ; - blake2s_update(&ctx, req.buffer, seedlen) ; - } - if (flags.rcred && st.st_mode & S_IWUSR && verbosity) - strerr_warnw2x(file, " was not marked as creditable") ; - req.entropy_count = flags.rcred && !(st.st_mode & S_IWUSR) ? (seedlen << 3) : 0 ; - req.buf_size = seedlen ; - fd = openbc_read("/dev/urandom") ; - if (fd == -1) strerr_diefu2sys(111, "open ", "/dev/urandom") ; - if (verbosity >= 2) - { - char fmt[SIZE_FMT] ; - fmt[size_fmt(fmt, seedlen << 3)] = 0 ; - strerr_warni4x("seeding with ", fmt, " bits", req.entropy_count ? "" : " without crediting") ; - } - if (ioctl(fd, RNDADDENTROPY, &req) == -1) - strerr_diefu1sys(111, "seed") ; - fd_close(fd) ; - } - - if (flags.block) - { - if (verbosity >= 2) - strerr_warni1x("waiting for the entropy pool to initialize") ; -#ifdef SKALIBS_HASGETRANDOM - char c ; - ssize_t r = getrandom(&c, 1, 0) ; - if (r == -1) strerr_diefu1sys(111, "getrandom") ; -#else - iopause_fd x = { .events = IOPAUSE_READ } ; - x.fd = openbc_read("/dev/random") ; - if (x.fd == -1) strerr_diefu2sys(111, "open ", "/dev/random") ; - if (iopause(&x, 1, 0, 0) == -1) strerr_diefu1sys(111, "iopause") ; - fd_close(x.fd) ; -#endif - } - - if (flags.write) - { - char seed[512] ; - size_t len = 512 ; - int wcred = 1 ; - char s[SIZE_FMT] = "" ; - int fd = openbc_read("/proc/sys/kernel/random/poolsize") ; - if (fd < 0) - { - if (verbosity) strerr_warnwu2sys("open ", "/proc/sys/kernel/random/poolsize") ; - } - else - { - size_t r ; - errno = 0 ; - r = allread(fd, s, SIZE_FMT - 1) ; - if (errno) - { - if (verbosity) strerr_warnwu2sys("read from ", "/proc/sys/kernel/random/poolsize") ; - } - else - { - s[r] = 0 ; - if (!size_scan(s, &r)) - { - if (verbosity) strerr_warnwu2sys("understand ", "/proc/sys/kernel/random/poolsize") ; - } - else len = (r + 7) >> 3 ; - } - fd_close(fd) ; - } - if (len < 32) len = 32 ; - if (len > 512) len = 512 ; - - if (verbosity >= 2) - { - s[size_fmt(s, len << 3)] = 0 ; - strerr_warni3x("reading ", s, " bits of random to make the seed") ; - } - if (flags.block) random_buf(seed, len) ; - else wcred = read_seed_nb(seed, len) ; - if (!wcred && verbosity) strerr_warnwu1x("make the seed creditable") ; - blake2s_update(&ctx, (char *)&len, sizeof(len)) ; - blake2s_update(&ctx, seed, len) ; - blake2s_final(&ctx, seed + len - 32) ; - if (verbosity >= 2) strerr_warni2x("writing seed to ", file) ; - umask(0077) ; - if (!openwritenclose_unsafe_sync(file, seed, len)) - strerr_diefu2sys(111, "write to ", file) ; - if (flags.wcred && wcred) - { - if (chmod(file, 0400) == -1 && verbosity) - strerr_warnwu3sys("mark ", file, "as creditable") ; - } - } - } - - return 0 ; -} diff --git a/src/minutils/s6-chroot.c b/src/minutils/s6-chroot.c deleted file mode 100644 index ae1fb7b..0000000 --- a/src/minutils/s6-chroot.c +++ /dev/null @@ -1,18 +0,0 @@ -/* ISC license. */ - -#include -#include - -#include -#include - -#define USAGE "s6-chroot dir prog..." - -int main (int argc, char const *const *argv) -{ - PROG = "s6-chroot" ; - if (argc < 3) strerr_dieusage(100, USAGE) ; - if (chdir(argv[1]) == -1) strerr_diefu2sys(111, "chdir to ", argv[1]) ; - if (chroot(".") == -1) strerr_diefu2sys(111, "chroot in ", argv[1]) ; - xexec(argv+2) ; -} diff --git a/src/minutils/s6-freeramdisk.c b/src/minutils/s6-freeramdisk.c deleted file mode 100644 index adfb07c..0000000 --- a/src/minutils/s6-freeramdisk.c +++ /dev/null @@ -1,21 +0,0 @@ -/* ISC license. */ - -#include -#include -#include -#include -#include -#include - -#define USAGE "s6-freeramdisk ramdisk_device" - -int main (int argc, char const *const *argv) -{ - int fd ; - PROG = "s6-freeramdisk" ; - if (argc < 2) strerr_dieusage(100, USAGE) ; - fd = open(argv[1], O_RDWR) ; - if (fd < 0) strerr_diefu3sys(111, "open ", argv[1], " in read-write mode") ; - if (ioctl(fd, BLKFLSBUF) < 0) strerr_diefu2sys(111, "ioctl ", argv[1]) ; - return 0 ; -} diff --git a/src/minutils/s6-hostname.c b/src/minutils/s6-hostname.c deleted file mode 100644 index d673e81..0000000 --- a/src/minutils/s6-hostname.c +++ /dev/null @@ -1,37 +0,0 @@ -/* ISC license. */ - -#ifndef _BSD_SOURCE -#define _BSD_SOURCE -#endif - -#include -#include -#include -#include -#include -#include - -#define USAGE "s6-hostname [ hostname ]" - -static int getit (void) -{ - stralloc sa = STRALLOC_ZERO ; - if (sagethostname(&sa) < 0) strerr_diefu1sys(111, "get hostname") ; - sa.s[sa.len++] = '\n' ; - if (allwrite(1, sa.s, sa.len) < sa.len) - strerr_diefu1sys(111, "write to stdout") ; - return 0 ; -} - -static int setit (char const *h) -{ - if (sethostname(h, strlen(h)) < 0) - strerr_diefu1sys(111, "set hostname") ; - return 0 ; -} - -int main (int argc, char const *const *argv) -{ - PROG = "s6-hostname" ; - return (argc < 2) ? getit() : setit(argv[1]) ; -} diff --git a/src/minutils/s6-logwatch.c b/src/minutils/s6-logwatch.c deleted file mode 100644 index e815f81..0000000 --- a/src/minutils/s6-logwatch.c +++ /dev/null @@ -1,172 +0,0 @@ -/* ISC license. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define USAGE "s6-logwatch [ logdir ]" -#define dieusage() strerr_dieusage(100, USAGE) - -#define B_READING 0 -#define B_BLOCKING 1 -#define B_WAITING 2 -static unsigned int state ; -static int fd ; -static int newcurrent = 0 ; - -union inotify_event_u -{ - struct inotify_event event ; - char buf[sizeof(struct inotify_event) + NAME_MAX + 1] ; -} ; - -static void goteof (void) -{ - if (newcurrent) - { - fd_close(fd) ; - fd = open_read("current") ; - if (fd < 0) strerr_diefu1sys(111, "current") ; - newcurrent = 0 ; - state = B_READING ; - } - else state = B_BLOCKING ; -} - -static int readit (int fd) -{ - struct iovec v[2] ; - ssize_t r ; - buffer_wpeek(buffer_1, v) ; - r = fd_readv(fd, v, 2) ; - switch (r) - { - case -1 : return 0 ; - case 0 : goteof() ; break ; - default : buffer_wseek(buffer_1, r) ; - } - return 1 ; -} - -static void maketransition (unsigned int transition) -{ - static unsigned char const table[3][3] = { - { 0x10, 0x00, 0x00 }, - { 0x60, 0x22, 0x00 }, - { 0x40, 0x03, 0x02 } - } ; - unsigned char c = table[state][transition] ; - state = c & 0x0f ; - if (state == 3) strerr_dief1x(101, "current moved twice without being recreated") ; - if (c & 0x10) newcurrent = 1 ; - if (c & 0x20) { fd_close(fd) ; fd = -1 ; } - if (c & 0x40) - { - fd = open_read("current") ; - if (fd < 0) strerr_diefu1sys(111, "current") ; - } -} - -static void handle_event (int ifd, int watch) -{ - ssize_t r ; - size_t offset = 0 ; - union inotify_event_u u ; - r = read(ifd, u.buf, sizeof(u.buf)) ; - while (r > 0) - { - struct inotify_event *event = (struct inotify_event *)(u.buf + offset) ; - offset += sizeof(struct inotify_event) + event->len ; - r -= sizeof(struct inotify_event) + event->len ; - if (event->wd == watch && !strcmp(event->name, "current")) - { - int transition = -1 ; - if (event->mask & IN_CREATE) transition = 0 ; - else if (event->mask & IN_MOVED_FROM) transition = 1 ; - else if (event->mask & IN_MODIFY) transition = 2 ; - if (transition >= 0) maketransition(transition) ; - } - } -} - -int main (int argc, char const *const *argv) -{ - iopause_fd x[2] = { { .events = IOPAUSE_READ }, { .fd = 1 } } ; - char const *dir = "." ; - int watch ; - unsigned int maxlen = 4096 ; - PROG = "s6-logwatch" ; - { - subgetopt l = SUBGETOPT_ZERO ; - for (;;) - { - int opt = subgetopt_r(argc, argv, "m:", &l) ; - if (opt == -1) break ; - switch (opt) - { - case 'm' : - if (!uint0_scan(l.arg, &maxlen)) dieusage() ; - strerr_warnw1x("the -m option is deprecated") ; - break ; - default : dieusage() ; - } - } - argc -= l.ind ; argv += l.ind ; - } - - if (argc) dir = *argv ; - if (chdir(dir) < 0) strerr_diefu2sys(111, "chdir to ", dir) ; - if (!fd_sanitize()) strerr_diefu1sys(111, "sanitize standard fds") ; - - x[0].fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC) ; - if (x[0].fd < 0) strerr_diefu1sys(111, "inotify_init") ; - watch = inotify_add_watch(x[0].fd, ".", IN_CREATE | IN_MOVED_FROM | IN_MODIFY) ; - if (watch < 0) strerr_diefu1sys(111, "inotify_add_watch") ; - fd = open_readb("current") ; - if (fd < 0) - { - if (errno != ENOENT) strerr_diefu3sys(111, "open ", dir, "/current") ; - state = B_WAITING ; - } - else state = B_READING ; - if (!sig_ignore(SIGPIPE)) strerr_diefu1sys(111, "sig_ignore(SIGPIPE)") ; - if (state == B_READING) - { - if (!readit(fd)) strerr_diefu3sys(111, "read from ", dir, "/current") ; - } - - for (;;) - { - int r ; - x[1].events = buffer_len(buffer_1) ? IOPAUSE_WRITE : 0 ; - r = iopause(x, 2, 0, 0) ; - if (r < 0) strerr_diefu1sys(111, "iopause") ; - if (x[0].revents & IOPAUSE_EXCEPT) x[0].revents |= IOPAUSE_READ ; - if (x[1].revents & IOPAUSE_EXCEPT) x[1].revents |= IOPAUSE_WRITE ; - if (x[1].revents & IOPAUSE_WRITE) - { - if (!buffer_flush(buffer_1) && !error_isagain(errno)) - strerr_diefu1sys(111, "write to stdout") ; - if (x[1].revents & IOPAUSE_EXCEPT) break ; - } - if (state == B_READING && buffer_available(buffer_1)) - { - if (!readit(fd)) strerr_diefu3sys(111, "read from ", dir, "/current") ; - } - if (x[0].revents & IOPAUSE_READ) handle_event(x[0].fd, watch) ; - } - return 0 ; -} diff --git a/src/minutils/s6-mount.c b/src/minutils/s6-mount.c deleted file mode 100644 index 428bda4..0000000 --- a/src/minutils/s6-mount.c +++ /dev/null @@ -1,149 +0,0 @@ -/* ISC license. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "mount-constants.h" - -#define USAGE "s6-mount -a [ -z fstab ] | s6-mount [ -n ] [ -t type ] [ -o option[,option...] ]... device mountpoint" -#define BUFSIZE 4096 - -#define SWITCH(opt) do -#define HCTIWS(opt) while(0) ; -#define CASE(s) if (n == sizeof(s) - 1 && !strncmp(opt, (s), n)) - -static void scanopt (stralloc *data, unsigned long *flags, char const *opt) -{ - for (;;) - { - unsigned int n = str_chr(opt, ',') ; - SWITCH(opt) - { - CASE("defaults") { *flags = MS_MGC_VAL ; break ; } - CASE("ro") { *flags |= MS_RDONLY ; break ; } - CASE("rw") { *flags &= ~MS_RDONLY ; break ; } - CASE("remount") { *flags |= MS_REMOUNT ; break ; } - CASE("sync") { *flags |= MS_SYNCHRONOUS ; break ; } - CASE("async") { *flags &= ~MS_SYNCHRONOUS ; break ; } - CASE("nodev") { *flags |= MS_NODEV ; break ; } - CASE("dev") { *flags &= ~MS_NODEV ; break ; } - CASE("noexec") { *flags |= MS_NOEXEC ; break ; } - CASE("exec") { *flags &= ~MS_NOEXEC ; break ; } - CASE("nosuid") { *flags |= MS_NOSUID ; break ; } - CASE("suid") { *flags &= ~MS_NOSUID ; break ; } - CASE("noatime") { *flags |= MS_NOATIME ; break ; } - CASE("atime") { *flags &= ~MS_NOATIME ; break ; } - CASE("nodiratime") { *flags |= MS_NODIRATIME ; break ; } - CASE("diratime") { *flags &= ~MS_NODIRATIME ; break ; } - CASE("strictatime") { *flags |= MS_STRICTATIME ; break ; } - CASE("nostrictatime") { *flags &= ~MS_STRICTATIME ; break ; } - CASE("relatime") { *flags |= MS_RELATIME ; break ; } - CASE("norelatime") { *flags &= ~MS_RELATIME ; break ; } - CASE("bind") { *flags |= MS_BIND ; break ; } - CASE("nobind") { *flags &= ~MS_BIND ; break ; } - CASE("move") { *flags |= MS_MOVE ; break ; } - CASE("nomove") { *flags &= ~MS_MOVE ; break ; } - CASE("dirsync") { *flags |= MS_DIRSYNC ; break ; } - CASE("nodirsync") { *flags &= ~MS_DIRSYNC ; break ; } - CASE("mandlock") { *flags |= MS_MANDLOCK ; break ; } - CASE("nomandlock") { *flags &= ~MS_MANDLOCK ; break ; } - CASE("silent") { *flags |= MS_SILENT ; break ; } - CASE("nosilent") { *flags &= ~MS_SILENT ; break ; } -#ifdef MS_LAZYTIME - CASE("lazytime") { *flags |= MS_LAZYTIME ; break ; } - CASE("nolazytime") { *flags &= ~MS_LAZYTIME ; break ; } -#endif - - CASE("shared") { *flags &= ~(MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE) ; *flags |= MS_SHARED ; break ; } - CASE("private") { *flags &= ~(MS_SHARED | MS_SLAVE | MS_UNBINDABLE) ; *flags |= MS_PRIVATE ; break ; } - CASE("slave") { *flags &= ~(MS_SHARED | MS_PRIVATE | MS_UNBINDABLE) ; *flags |= MS_SLAVE ; break ; } - CASE("unbindable") { *flags &= ~(MS_SHARED | MS_PRIVATE | MS_SLAVE) ; *flags |= MS_UNBINDABLE ; break ; } - - if ((data->s && data->len && !stralloc_catb(data, ",", 1)) || !stralloc_catb(data, opt, n)) - strerr_diefu1sys(111, "build data string") ; - } - HCTIWS(opt) - - opt += n ; - if (!*opt) break ; - if (*opt != ',') strerr_dief1x(100, "unrecognized option") ; - opt++ ; - } -} - -static int mountall (char const *fstab) -{ - struct mntent *d ; - int e = 0 ; - FILE *yuck = setmntent(fstab, "r") ; - if (!yuck) strerr_diefu2sys(111, "open ", fstab) ; - while ((d = getmntent(yuck))) - { - unsigned long flags = MS_MGC_VAL ; - stralloc data = STRALLOC_ZERO ; - scanopt(&data, &flags, d->mnt_opts) ; - if (!stralloc_0(&data)) - strerr_diefu1sys(111, "build data string") ; -#ifdef DEBUG - strerr_warni4x("mounting ", d->mnt_fsname, " on ", d->mnt_dir) ; -#endif - if (mount(d->mnt_fsname, d->mnt_dir, d->mnt_type, flags, data.s) == -1) - { - e++ ; - strerr_warnwu4sys("mount ", d->mnt_fsname, " on ", d->mnt_dir) ; - } - stralloc_free(&data) ; - } - endmntent(yuck) ; - return e ; -} - -int main (int argc, char const *const *argv) -{ - stralloc data = STRALLOC_ZERO ; - unsigned long flags = MS_MGC_VAL ; - char const *fstype = "none" ; - char const *fstab = "/etc/fstab" ; - PROG = "s6-mount" ; - { - int doall = 0 ; - subgetopt l = SUBGETOPT_ZERO ; - for (;;) - { - int opt = subgetopt_r(argc, argv, "nz:arwt:o:", &l) ; - if (opt == -1) break ; - switch (opt) - { - case 'n' : break ; - case 'z' : fstab = l.arg ; break ; - case 'a' : doall = 1 ; break ; - case 't' : fstype = l.arg ; break ; - case 'w' : scanopt(&data, &flags, "rw") ; break ; - case 'r' : scanopt(&data, &flags, "ro") ; break ; - case 'o' : scanopt(&data, &flags, l.arg) ; break ; - default : strerr_dieusage(100, USAGE) ; - } - } - argc -= l.ind ; argv += l.ind ; - if (doall) return mountall(fstab) ; - } - if (!argc) - { - int fd = open_readb("/proc/mounts") ; - if (fd < 0) strerr_diefu2sys(111, "read ", "/proc/mounts") ; - if (fd_cat(fd, 1) < 0) strerr_diefu2sys(111, "fd_cat ", "/proc/mounts") ; - fd_close(fd) ; - } - else if (argc == 1) strerr_dieusage(100, USAGE) ; - else if (!stralloc_0(&data)) strerr_diefu1sys(111, "build data string") ; - else if (mount(argv[0], argv[1], fstype, flags, data.s) == -1) - strerr_diefu4sys(errno == EBUSY ? 1 : 111, "mount ", argv[0], " on ", argv[1]) ; - return 0 ; -} diff --git a/src/minutils/s6-pivotchroot.c b/src/minutils/s6-pivotchroot.c deleted file mode 100644 index b35a00b..0000000 --- a/src/minutils/s6-pivotchroot.c +++ /dev/null @@ -1,21 +0,0 @@ -/* ISC license. */ - -#include -#include - -#include -#include - -#define USAGE "s6-pivotchroot old-place-for-new-root new-place-for-old-root prog..." - -extern int pivot_root (char const *, char const *) ; - -int main (int argc, char const *const *argv) -{ - PROG = "s6-pivotchroot" ; - if (argc < 4) strerr_dieusage(100, USAGE) ; - if (chdir(argv[1]) < 0) strerr_diefu2sys(111, "chdir to ", argv[1]) ; - if (pivot_root(".", argv[2]) < 0) strerr_diefu1sys(111, "pivot_root") ; - if (chroot(".") < 0) strerr_diefu1sys(111, "chroot") ; - xexec(argv+3) ; -} diff --git a/src/minutils/s6-ps.c b/src/minutils/s6-ps.c deleted file mode 100644 index 3363f24..0000000 --- a/src/minutils/s6-ps.c +++ /dev/null @@ -1,387 +0,0 @@ -/* ISC license. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "s6-ps.h" - -#define USAGE "s6-ps [ -H ] [ -w spacing ] [ -W wchanfile ] [ -l | -o field,field... ]" - -#define RIGHTFORMATTED ( \ - (1 << PFIELD_PID) | \ - (1 << PFIELD_PPID) | \ - (1 << PFIELD_PGRP) | \ - (1 << PFIELD_SESSION) | \ - (1 << PFIELD_TPGID) | \ - (1 << PFIELD_PRIO) | \ - (1 << PFIELD_NICE) | \ - (1 << PFIELD_THREADS) | \ - (1 << PFIELD_VSIZE) | \ - (1 << PFIELD_RSS) | \ - (1 << PFIELD_RSSLIM) | \ - (1 << PFIELD_CPUNO) | \ - (1 << PFIELD_RTPRIO) | \ - (1 << PFIELD_PMEM) | \ - (1 << PFIELD_PCPU) | \ - ((uint64_t)1 << PFIELD_CPCPU)) - -void *left_dtok (unsigned int d, void *x) -{ - return (void *)&genalloc_s(dius_t, (genalloc *)x)[d].left ; -} - -int uint32_cmp (void const *a, void const *b, void *x) -{ - uint32_t aa = *(uint32_t *)a ; - uint32_t bb = *(uint32_t *)b ; - (void)x ; - return (aa < bb) ? -1 : (aa > bb) ; -} - -static void *pid_dtok (unsigned int d, void *x) -{ - return &((pscan_t *)x)[d].pid ; -} - -static int fillo_notree (unsigned int i, unsigned int h, void *x) -{ - static unsigned int j = 0 ; - unsigned int *list = x ; - list[j++] = i ; - (void)h ; - return 1 ; -} - -static inline unsigned int fieldscan (char const *s, pfield_t *list, uint64_t *fbf) -{ - uint64_t bits = 0 ; - unsigned int n = 0 ; - int cont = 1 ; - for (; cont ; n++) - { - size_t len = str_chr(s, ',') ; - pfield_t i = 0 ; - if (!len) strerr_dief3x(100, "invalid", " (empty)", " field for -o option") ; - if (!s[len]) cont = 0 ; - { - char tmp[len+1] ; - memcpy(tmp, s, len) ; - tmp[len] = 0 ; - for (; i < PFIELD_PHAIL ; i++) if (!strcmp(tmp, s6ps_opttable[i])) break ; - if (i >= PFIELD_PHAIL) - strerr_dief4x(100, "invalid", " field for -o option", ": ", tmp) ; - if (bits & ((uint64_t)1 << i)) - strerr_dief4x(100, "duplicate", " field for -o option", ": ", tmp) ; - } - s += len + 1 ; - list[n] = i ; - bits |= ((uint64_t)1 << i) ; - } - *fbf = bits ; - return n ; -} - -static int slurpit (unsigned int dirfd, stralloc *data, char const *buf, char const *what, size_t *len) -{ - size_t start = data->len ; - int fd = open_readat(dirfd, what) ; - if (fd < 0) return 0 ; - if (!slurp(data, fd)) strerr_diefu4sys(111, "slurp ", buf, "/", what) ; - fd_close(fd) ; - *len = data->len - start ; - return 1 ; -} - -int main (int argc, char const *const *argv) -{ - genalloc pscans = GENALLOC_ZERO ; /* array of pscan_t */ - pfield_t fieldlist[PFIELD_PHAIL] = { PFIELD_USER, PFIELD_PID, PFIELD_TTY, PFIELD_STATE, PFIELD_START, PFIELD_ARGS } ; - uint64_t fbf = (1 << PFIELD_USER) | (1 << PFIELD_PID) | (1 << PFIELD_TTY) | (1 << PFIELD_STATE) | (1 << PFIELD_START) | (1 << PFIELD_ARGS) ; - size_t mypos = 0 ; - unsigned int nfields = 6 ; - pscan_t *p ; - size_t n ; - unsigned int spacing = 2 ; - int flagtree = 0 ; - char const *wchanfile = 0 ; - int needstat ; - PROG = "s6-ps" ; - - { - subgetopt l = SUBGETOPT_ZERO ; - for (;;) - { - int opt = subgetopt_r(argc, argv, "Hlw:W:o:", &l) ; - if (opt == -1) break ; - switch (opt) - { - case 'H' : flagtree = 1 ; break ; - case 'l' : - { - nfields = 11 ; - fbf = (1 << PFIELD_USER) | (1 << PFIELD_PID) | ((uint64_t)1 << PFIELD_CPCPU) | (1 << PFIELD_PMEM) | (1 << PFIELD_VSIZE) | (1 << PFIELD_RSS) | (1 << PFIELD_TTY) | (1 << PFIELD_STATE) | (1 << PFIELD_START) | (1 << PFIELD_CTTIME) | (1 << PFIELD_ARGS) ; - fieldlist[0] = PFIELD_USER ; - fieldlist[1] = PFIELD_PID ; - fieldlist[2] = PFIELD_CPCPU ; - fieldlist[3] = PFIELD_PMEM ; - fieldlist[4] = PFIELD_VSIZE ; - fieldlist[5] = PFIELD_RSS ; - fieldlist[6] = PFIELD_TTY ; - fieldlist[7] = PFIELD_STATE ; - fieldlist[8] = PFIELD_START ; - fieldlist[9] = PFIELD_CTTIME ; - fieldlist[10] = PFIELD_ARGS ; - break ; - } - case 'w' : - { - if (!uint0_scan(l.arg, &spacing)) strerr_dieusage(100, USAGE) ; - break ; - } - case 'W' : wchanfile = l.arg ; break ; - case 'o' : - { - nfields = fieldscan(l.arg, fieldlist, &fbf) ; - break ; - } - default : strerr_dieusage(100, USAGE) ; - } - } - argc -= l.ind ; argv += l.ind ; - } - - if (!spacing) spacing = 1 ; - if (spacing > 256) spacing = 256 ; - - needstat = flagtree || !!(fbf & ( - (1 << PFIELD_PID) | - (1 << PFIELD_COMM) | - (1 << PFIELD_STATE) | - (1 << PFIELD_PPID) | - (1 << PFIELD_PGRP) | - (1 << PFIELD_SESSION) | - (1 << PFIELD_TTY) | - (1 << PFIELD_TPGID) | - (1 << PFIELD_UTIME) | - (1 << PFIELD_STIME) | - (1 << PFIELD_CUTIME) | - (1 << PFIELD_CSTIME) | - (1 << PFIELD_PRIO) | - (1 << PFIELD_NICE) | - (1 << PFIELD_THREADS) | - (1 << PFIELD_START) | - (1 << PFIELD_VSIZE) | - (1 << PFIELD_RSS) | - (1 << PFIELD_RSSLIM) | - (1 << PFIELD_CPUNO) | - (1 << PFIELD_RTPRIO) | - (1 << PFIELD_RTPOLICY) | - (1 << PFIELD_PMEM) | - (1 << PFIELD_WCHAN) | - (1 << PFIELD_PCPU) | - (1 << PFIELD_TTIME) | - (1 << PFIELD_CTTIME) | - ((uint64_t)1 << PFIELD_TSTART) | - ((uint64_t)1 << PFIELD_CPCPU))) ; - - - /* Scan /proc */ - - { - int needstatdir = !!(fbf & ((1 << PFIELD_USER) | (1 << PFIELD_GROUP))) ; - pid_t mypid = getpid() ; - DIR *dir = opendir("/proc") ; - direntry *d ; - char buf[25] = "/proc/" ; - - if (!dir) strerr_diefu1sys(111, "open /proc") ; - for (;;) - { - pscan_t pscan = PSCAN_ZERO ; - uint64_t u ; - int dirfd ; - errno = 0 ; - d = readdir(dir) ; - if (!d) break ; - if (!uint640_scan(d->d_name, &u)) continue ; - pscan.pid = u ; - strcpy(buf+6, d->d_name) ; - dirfd = open_read(buf) ; - if (dirfd < 0) continue ; - - if (needstatdir) - { - struct stat st ; - if (fstat(dirfd, &st) < 0) goto errindir ; - pscan.uid = st.st_uid ; - pscan.gid = st.st_gid ; - } - if (needstat) - { - if (!slurpit(dirfd, &pscan.data, buf, "stat", &pscan.statlen)) - goto errindir ; - if (!slurpit(dirfd, &pscan.data, buf, "comm", &pscan.commlen)) - goto errindir ; - if (pscan.commlen) { pscan.commlen-- ; pscan.data.len-- ; } - } - if (fbf & (1 << PFIELD_ARGS)) - { - if (!slurpit(dirfd, &pscan.data, buf, "cmdline", &pscan.cmdlen)) goto errindir ; - while (!pscan.data.s[pscan.data.len-1]) - { - pscan.cmdlen-- ; - pscan.data.len-- ; - } - } - if (fbf & (1 << PFIELD_ENV)) slurpit(dirfd, &pscan.data, buf, "environ", &pscan.envlen) ; - fd_close(dirfd) ; - if (!genalloc_append(pscan_t, &pscans, &pscan)) - strerr_diefu1sys(111, "genalloc_append") ; - if (pscan.pid == mypid) mypos = genalloc_len(pscan_t, &pscans) ; - continue ; - errindir: - fd_close(dirfd) ; - stralloc_free(&pscan.data) ; - } - if (errno) strerr_diefu1sys(111, "readdir /proc") ; - dir_close(dir) ; - } - - /* Add a process 0 as a root and sentinel */ - { - pscan_t pscan = { .pid = 0, .ppid = 0 } ; - if (!genalloc_append(pscan_t, &pscans, &pscan)) strerr_diefu1sys(111, "genalloc_append") ; - } - - p = genalloc_s(pscan_t, &pscans) ; - n = genalloc_len(pscan_t, &pscans) - 1 ; - - { - unsigned int orderedlist[n+1] ; /* 1st element will be 0, ignored */ - unsigned int i = 0 ; - - /* Order the processes for display */ - - { - AVLTREEN_DECLARE_AND_INIT(pidtree, n+1, &pid_dtok, &uint32_cmp, p) ; - for (i = 0 ; i < n ; i++) - { - if (needstat && !s6ps_statparse(p+i)) - strerr_diefu1sys(111, "parse process stats") ; - if (!avltreen_insert(&pidtree, i)) - strerr_diefu1sys(111, "avltreen_insert") ; - } - if (!avltreen_insert(&pidtree, n)) - strerr_diefu1sys(111, "avltreen_insert") ; - - if (flagtree) s6ps_otree(p, n+1, &pidtree, orderedlist) ; - else avltreen_iter_nocancel(&pidtree, avltreen_totalsize(&pidtree), &fillo_notree, orderedlist) ; - } - - - /* Format, compute length, output */ - - if (fbf & ((1 << PFIELD_START) | ((uint64_t)1 << PFIELD_TSTART) | (1 << PFIELD_PCPU) | ((uint64_t)1 << PFIELD_CPCPU))) - { - tain_wallclock_read_g() ; - s6ps_compute_boottime(p, mypos) ; - } - if (fbf & (1 << PFIELD_USER) && !s6ps_pwcache_init()) - strerr_diefu1sys(111, "init user name cache") ; - if (fbf & (1 << PFIELD_GROUP) && !s6ps_grcache_init()) - strerr_diefu1sys(111, "init group name cache") ; - if (fbf & (1 << PFIELD_TTY) && !s6ps_ttycache_init()) - strerr_diefu1sys(111, "init tty name cache") ; - if (fbf & (1 << PFIELD_WCHAN) && !s6ps_wchan_init(wchanfile)) - { - if (wchanfile) strerr_warnwu2sys("init wchan file ", wchanfile) ; - else strerr_warnwu1sys("init wchan") ; - } - - { - size_t fmtpos[n][nfields] ; - size_t fmtlen[n][nfields] ; - size_t maxlen[nfields] ; - unsigned int maxspaces = 0 ; - for (i = 0 ; i < nfields ; i++) maxlen[i] = strlen(s6ps_fieldheaders[fieldlist[i]]) ; - for (i = 0 ; i < n ; i++) - { - unsigned int j = 0 ; - for (; j < nfields ; j++) - { - if (!(*s6ps_pfield_fmt[fieldlist[j]])(p+i, &fmtpos[i][j], &fmtlen[i][j])) - strerr_diefu1sys(111, "format fields") ; - if (fmtlen[i][j] > maxlen[j]) maxlen[j] = fmtlen[i][j] ; - } - } - for (i = 0 ; i < nfields ; i++) - if (maxlen[i] > maxspaces) maxspaces = maxlen[i] ; - maxspaces += spacing ; - if (fbf & (1 << PFIELD_USER)) s6ps_pwcache_finish() ; - if (fbf & (1 << PFIELD_GROUP)) s6ps_grcache_finish() ; - if (fbf & (1 << PFIELD_TTY)) s6ps_ttycache_finish() ; - if (fbf & (1 << PFIELD_WCHAN)) s6ps_wchan_finish() ; - stralloc_free(&satmp) ; - { - char spaces[maxspaces] ; - for (i = 0 ; i < maxspaces ; i++) spaces[i] = ' ' ; - for (i = 0 ; i < nfields ; i++) - { - unsigned int rightformatted = !!(((uint64_t)1 << fieldlist[i]) & RIGHTFORMATTED) ; - size_t len = strlen(s6ps_fieldheaders[fieldlist[i]]) ; - if (rightformatted && (buffer_put(buffer_1, spaces, maxlen[i] - len) < (ssize_t)(maxlen[i] - len))) - goto nowrite ; - if (buffer_put(buffer_1, s6ps_fieldheaders[fieldlist[i]], len) < (ssize_t)len) - goto nowrite ; - if ((i < nfields-1) && (buffer_put(buffer_1, spaces, !rightformatted * (maxlen[i] - len) + spacing) < (ssize_t)(!rightformatted * (maxlen[i] - len) + spacing))) - goto nowrite ; - } - if (buffer_put(buffer_1, "\n", 1) < 1) goto nowrite ; - for (i = 0 ; i < n ; i++) - { - unsigned int oi = orderedlist[i+1] ; - unsigned int j = 0 ; - for (; j < nfields ; j++) - { - unsigned int rightformatted = !!(((uint64_t)1 << fieldlist[j]) & RIGHTFORMATTED) ; - if (rightformatted && (buffer_put(buffer_1, spaces, maxlen[j] - fmtlen[oi][j]) < (ssize_t)(maxlen[j] - fmtlen[oi][j]))) - goto nowrite ; - if (buffer_put(buffer_1, p[oi].data.s + fmtpos[oi][j], fmtlen[oi][j]) < (ssize_t)fmtlen[oi][j]) - goto nowrite ; - if ((j < nfields-1) && (buffer_put(buffer_1, spaces, !rightformatted * (maxlen[j] - fmtlen[oi][j]) + spacing) < (ssize_t)(!rightformatted * (maxlen[j] - fmtlen[oi][j]) + spacing))) - goto nowrite ; - } - if (buffer_put(buffer_1, "\n", 1) < 1) goto nowrite ; - } - } - } - } - buffer_flush(buffer_1) ; - return 0 ; - - nowrite: - strerr_diefu1sys(111, "write to stdout") ; -} diff --git a/src/minutils/s6-ps.h b/src/minutils/s6-ps.h deleted file mode 100644 index eb56dc1..0000000 --- a/src/minutils/s6-ps.h +++ /dev/null @@ -1,163 +0,0 @@ -/* ISC license. */ - -#ifndef _S6PS_H_ -#define _S6PS_H_ - -#include -#include -#include -#include -#include -#include - - -typedef struct dius_s dius_t, *dius_t_ref ; -struct dius_s -{ - uint32_t left ; - size_t right ; -} ; -#define DIUS_ZERO { .left = 0, .right = 0 } - - - /* pfield: the output fields */ - -typedef enum pfield_e pfield_t, *pfield_t_ref ; -enum pfield_e -{ - PFIELD_PID, - PFIELD_COMM, - PFIELD_STATE, - PFIELD_PPID, - PFIELD_PGRP, - PFIELD_SESSION, - PFIELD_TTY, - PFIELD_TPGID, - PFIELD_UTIME, - PFIELD_STIME, - PFIELD_CUTIME, - PFIELD_CSTIME, - PFIELD_PRIO, - PFIELD_NICE, - PFIELD_THREADS, - PFIELD_START, - PFIELD_VSIZE, - PFIELD_RSS, - PFIELD_RSSLIM, - PFIELD_CPUNO, - PFIELD_RTPRIO, - PFIELD_RTPOLICY, - PFIELD_USER, - PFIELD_GROUP, - PFIELD_PMEM, - PFIELD_WCHAN, - PFIELD_ARGS, - PFIELD_ENV, - PFIELD_PCPU, - PFIELD_TTIME, - PFIELD_CTTIME, - PFIELD_TSTART, - PFIELD_CPCPU, - PFIELD_PHAIL -} ; - -extern char const *const *s6ps_opttable ; -extern char const *const *s6ps_fieldheaders ; - - /* pscan: the main structure */ - -typedef struct pscan_s pscan_t, *pscan_t_ref ; -struct pscan_s -{ - stralloc data ; - pid_t pid ; - signed int height ; - size_t statlen ; - size_t commlen ; - size_t cmdlen ; - size_t envlen ; - uid_t uid ; - gid_t gid ; - pid_t ppid ; - unsigned int state ; - pid_t pgrp ; - pid_t session ; - dev_t ttynr ; - pid_t tpgid ; - uint64_t utime ; - uint64_t stime ; - uint64_t cutime ; - uint64_t cstime ; - int prio ; - int nice ; - uint64_t threads ; - uint64_t start ; - uint64_t vsize ; - uint64_t rss ; - uint64_t rsslim ; - uint64_t wchan ; - uint64_t cpuno ; - uint64_t rtprio ; - uint64_t policy ; -} ; - -#define PSCAN_ZERO \ -{ \ - .data = STRALLOC_ZERO, \ - .pid = 0, \ - .height = 0, \ - .statlen = 0, \ - .commlen = 0, \ - .cmdlen = 0, \ - .envlen = 0, \ - .uid = 0, \ - .gid = 0, \ - .ppid = 0, \ - .state = 0, \ - .pgrp = 0, \ - .session = 0, \ - .ttynr = 0, \ - .tpgid = -1, \ - .utime = 0, \ - .stime = 0, \ - .cutime = 0, \ - .cstime = 0, \ - .prio = 0, \ - .nice = 0, \ - .threads = 0, \ - .start = 0, \ - .vsize = 0, \ - .rss = 0, \ - .rsslim = 0, \ - .wchan = 0, \ - .cpuno = 0, \ - .rtprio = 0, \ - .policy = 0 \ -} - -extern int s6ps_statparse (pscan_t *) ; -extern void s6ps_otree (pscan_t *, unsigned int, avltreen *, unsigned int *) ; - -extern int s6ps_compute_boottime (pscan_t *, unsigned int) ; - -typedef int pfieldfmt_func (pscan_t *, size_t *, size_t *) ; -typedef pfieldfmt_func *pfieldfmt_func_ref ; - -extern pfieldfmt_func_ref *s6ps_pfield_fmt ; - -extern void *left_dtok (unsigned int, void *) ; -extern int uint32_cmp (void const *, void const *, void *) ; -extern int s6ps_pwcache_init (void) ; -extern void s6ps_pwcache_finish (void) ; -extern int s6ps_pwcache_lookup (stralloc *, uid_t) ; -extern int s6ps_grcache_init (void) ; -extern void s6ps_grcache_finish (void) ; -extern int s6ps_grcache_lookup (stralloc *, gid_t) ; -extern int s6ps_ttycache_init (void) ; -extern void s6ps_ttycache_finish (void) ; -extern int s6ps_ttycache_lookup (stralloc *, dev_t) ; -extern int s6ps_wchan_init (char const *) ; -extern void s6ps_wchan_finish (void) ; -extern int s6ps_wchan_lookup (stralloc *, uint64_t) ; - -#endif diff --git a/src/minutils/s6-swapoff.c b/src/minutils/s6-swapoff.c deleted file mode 100644 index 00df142..0000000 --- a/src/minutils/s6-swapoff.c +++ /dev/null @@ -1,54 +0,0 @@ -/* ISC license. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define USAGE "s6-swapoff device s6-swapoff -a" - -#define BUFSIZE 4095 - -static int swapoffall ( ) -{ - char buf[BUFSIZE+1] ; - buffer b ; - stralloc sa = STRALLOC_ZERO ; - int e = 0 ; - int r ; - int fd = open_readb("/proc/swaps") ; - if (fd < 0) strerr_diefu1sys(111, "open_readb /proc/swaps") ; - buffer_init(&b, &buffer_read, fd, buf, BUFSIZE+1) ; - if (skagetln(&b, &sa, '\n') < 0) strerr_diefu1sys(111, "skagetln") ; - for (;;) - { - size_t n ; - sa.len = 0 ; - r = skagetln(&b, &sa, '\n') ; - if (r < 0) strerr_diefu1sys(111, "skagetln") ; - if (!r) break ; - n = byte_chr(sa.s, sa.len, ' ') ; - if (n >= sa.len) strerr_dief1x(111, "invalid line in /proc/swaps") ; - sa.s[n] = 0 ; - if (swapoff(sa.s) < 0) { e++ ; strerr_warnwu2sys("swapoff ", sa.s) ; } - } - fd_close(fd) ; - stralloc_free(&sa) ; - return e ; -} - -int main (int argc, char const *const *argv) -{ - PROG = "s6-swapoff" ; - if (argc < 2) strerr_dieusage(100, USAGE) ; - if ((argv[1][0] == '-') && (argv[1][1] == 'a') && !argv[1][2]) - return swapoffall() ; - if (swapoff(argv[1]) == -1) strerr_diefu2sys(111, "swapoff ", argv[1]) ; - return 0 ; -} diff --git a/src/minutils/s6-swapon.c b/src/minutils/s6-swapon.c deleted file mode 100644 index 41aabef..0000000 --- a/src/minutils/s6-swapon.c +++ /dev/null @@ -1,37 +0,0 @@ -/* ISC license. */ - -#include -#include -#include -#include -#include -#include - -#define USAGE "s6-swapon device s6-swapon -a" - -static int swaponall () -{ - struct mntent *d ; - int e = 0 ; - FILE *yuck = setmntent("/etc/fstab", "r") ; - if (!yuck) strerr_diefu1sys(111, "setmntent /etc/fstab") ; - while ((d = getmntent(yuck))) - if (!strcmp(d->mnt_type, "swap") && (swapon(d->mnt_fsname, 0) == -1)) - { - e++ ; - strerr_warnwu2sys("swapon ", d->mnt_fsname) ; - } - endmntent(yuck) ; - return e ; -} - -int main (int argc, char const *const *argv) -{ - PROG = "s6-swapon" ; - if (argc < 2) strerr_dieusage(100, USAGE) ; - if ((argv[1][0] == '-') && (argv[1][1] == 'a') && !argv[1][2]) - return swaponall() ; - if (swapon(argv[1], 0) == -1) - strerr_diefu2sys(111, "swapon ", argv[1]) ; - return 0 ; -} diff --git a/src/minutils/s6-umount.c b/src/minutils/s6-umount.c deleted file mode 100644 index 3ac1091..0000000 --- a/src/minutils/s6-umount.c +++ /dev/null @@ -1,66 +0,0 @@ -/* ISC license. */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define USAGE "s6-umount mountpoint s6-umount -a" - -#define BUFSIZE 4096 -#define MAXLINES 512 - -static int umountall ( ) -{ - stralloc mountpoints[MAXLINES] ; - char buf[BUFSIZE+1] ; - buffer b ; - stralloc sa = STRALLOC_ZERO ; - unsigned int line = 0 ; - int e = 0 ; - int r ; - int fd = open_readb("/proc/mounts") ; - if (fd < 0) strerr_diefu1sys(111, "open /proc/mounts") ; - memset(mountpoints, 0, sizeof(mountpoints)) ; - buffer_init(&b, &buffer_read, fd, buf, BUFSIZE+1) ; - for (;;) - { - size_t n, p ; - if (line >= MAXLINES) strerr_dief1x(111, "/proc/mounts too big") ; - sa.len = 0 ; - r = skagetln(&b, &sa, '\n') ; - if (r <= 0) break ; - p = byte_chr(sa.s, sa.len, ' ') ; - if (p >= sa.len) strerr_dief1x(111, "bad /proc/mounts format") ; - p++ ; - n = byte_chr(sa.s + p, sa.len - p, ' ') ; - if (n == sa.len - p) strerr_dief1x(111, "bad /proc/mounts format") ; - if (!stralloc_catb(&mountpoints[line], sa.s + p, n) || !stralloc_0(&mountpoints[line])) - strerr_diefu1sys(111, "store mount point") ; - line++ ; - } - fd_close(fd) ; - stralloc_free(&sa) ; - if (r < 0) strerr_diefu1sys(111, "read /proc/mounts") ; - while (line--) - if (umount(mountpoints[line].s) == -1) - { - e++ ; - strerr_warnwu2sys("umount ", mountpoints[line].s) ; - } - return e ; -} - -int main (int argc, char const *const *argv) -{ - PROG = "s6-umount" ; - if (argc < 2) strerr_dieusage(100, USAGE) ; - if ((argv[1][0] == '-') && (argv[1][1] == 'a') && !argv[1][2]) - return umountall() ; - if (umount(argv[1]) == -1) strerr_diefu2sys(111, "umount ", argv[1]) ; - return 0 ; -} diff --git a/src/minutils/s6ps_grcache.c b/src/minutils/s6ps_grcache.c deleted file mode 100644 index ba62098..0000000 --- a/src/minutils/s6ps_grcache.c +++ /dev/null @@ -1,65 +0,0 @@ -/* ISC license. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "s6-ps.h" - -static avltree grcache_tree = AVLTREE_ZERO ; -static genalloc grcache_index = GENALLOC_ZERO ; - -int s6ps_grcache_init (void) -{ - avltree_init(&grcache_tree, 5, 3, 8, &left_dtok, &uint32_cmp, &grcache_index) ; - return 1 ; -} - -void s6ps_grcache_finish (void) -{ - avltree_free(&grcache_tree) ; - genalloc_free(dius_t, &grcache_index) ; -} - -int s6ps_grcache_lookup (stralloc *sa, gid_t gid) -{ - int wasnull = !satmp.s ; - dius_t d = { .left = (uint32_t)gid, .right = satmp.len } ; - uint32_t i ; - if (!avltree_search(&grcache_tree, &d.left, &i)) - { - struct group *gr ; - unsigned int n = genalloc_len(dius_t, &grcache_index) ; - errno = 0 ; - gr = getgrgid(gid) ; - if (!gr) - { - if (errno) return 0 ; - if (!stralloc_readyplus(&satmp, UINT_FMT + 2)) return 0 ; - stralloc_catb(&satmp, "(", 1) ; - satmp.len += uint_fmt(satmp.s + satmp.len, gid) ; - stralloc_catb(&satmp, ")", 2) ; - } - else if (!stralloc_cats(&satmp, gr->gr_name) || !stralloc_0(&satmp)) return 0 ; - if (!genalloc_append(dius_t, &grcache_index, &d)) goto err ; - if (!avltree_insert(&grcache_tree, n)) - { - genalloc_setlen(dius_t, &grcache_index, n) ; - goto err ; - } - i = n ; - } - return stralloc_cats(sa, satmp.s + genalloc_s(dius_t, &grcache_index)[i].right) ; - err: - { - int e = errno ; - if (wasnull) stralloc_free(&satmp) ; - else satmp.len = d.right ; - errno = e ; - } - return 0 ; -} diff --git a/src/minutils/s6ps_otree.c b/src/minutils/s6ps_otree.c deleted file mode 100644 index f7952ab..0000000 --- a/src/minutils/s6ps_otree.c +++ /dev/null @@ -1,98 +0,0 @@ -/* ISC license. */ - -#include -#include -#include "s6-ps.h" - -typedef struct ptreeiter_s ptreeiter_t, *ptreeiter_t_ref ; -struct ptreeiter_s -{ - unsigned int *childlist ; - unsigned int const *childindex ; - unsigned int const *ppindex ; - unsigned int *cpos ; -} ; - -typedef struct pstuff_s pstuff_t, *pstuff_t_ref ; -struct pstuff_s -{ - unsigned int *orderedlist ; - pscan_t *p ; - unsigned int const *childlist ; - unsigned int const *childindex ; - unsigned int const *nchild ; -} ; - -static int fillchildlist (unsigned int i, unsigned int h, void *x) -{ - ptreeiter_t *pt = x ; - unsigned int j = pt->ppindex[i] ; - pt->childlist[pt->childindex[j] + pt->cpos[j]++] = i ; - (void)h ; - return 1 ; -} - -static void fillo_tree_rec (pstuff_t *blah, unsigned int root, signed int h) -{ - static unsigned int j = 0 ; - unsigned int i = !blah->p[root].pid ; - if (blah->p[root].pid == 1) h = -1 ; - blah->p[root].height = (h > 0) ? h : 0 ; - blah->orderedlist[j++] = root ; - for (; i < blah->nchild[root] ; i++) - fillo_tree_rec(blah, blah->childlist[blah->childindex[root] + i], h+1) ; -} - - /* - Fills up orderedlist with the right indices to print a process tree. - O(n log n) time, O(n) space, all in the stack. - */ - -void s6ps_otree (pscan_t *p, unsigned int n, avltreen *pidtree, unsigned int *orderedlist) -{ - unsigned int childlist[n] ; - unsigned int childindex[n] ; - unsigned int nchild[n] ; - unsigned int i = 0 ; - for (; i < n ; i++) nchild[i] = 0 ; - - /* Compute the ppid tree */ - for (i = 0 ; i < n ; i++) - { - uint32_t k ; - if (!avltreen_search(pidtree, &p[i].ppid, &k)) k = n-1 ; - orderedlist[i] = k ; /* using orderedlist as ppindex */ - nchild[k]++ ; - } - { - unsigned int j = 0 ; - for (i = 0 ; i < n ; i++) - { - childindex[i] = j ; - j += nchild[i] ; - } - } - - /* Fill the childlist by increasing pids so it is sorted */ - { - unsigned int cpos[n] ; - ptreeiter_t blah = { .childlist = childlist, .childindex = childindex, .ppindex = orderedlist, .cpos = cpos } ; - for (i = 0 ; i < n ; i++) cpos[i] = 0 ; - avltreen_iter_nocancel(pidtree, avltreen_totalsize(pidtree), &fillchildlist, &blah) ; - } - - /* If we have init, make it the last in the orphan list */ - if (n > 1 && p[childlist[childindex[n-1]+1]].pid == 1) - { - unsigned int pos1 = childlist[childindex[n-1] + 1] ; - for (i = 2 ; i < nchild[n-1] ; i++) - childlist[childindex[n-1]+i-1] = childlist[childindex[n-1]+i] ; - childlist[childindex[n-1]+nchild[n-1]-1] = pos1 ; - } - - /* Finally, fill orderedlist by walking the childindex tree. */ - { - pstuff_t blah = { .orderedlist = orderedlist, .p = p, .childlist = childlist, .childindex = childindex, .nchild = nchild } ; - fillo_tree_rec(&blah, n-1, -1) ; - } -} diff --git a/src/minutils/s6ps_pfield.c b/src/minutils/s6ps_pfield.c deleted file mode 100644 index 0280186..0000000 --- a/src/minutils/s6ps_pfield.c +++ /dev/null @@ -1,560 +0,0 @@ -/* ISC license. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "s6-ps.h" - -static char const *const fieldheaders[PFIELD_PHAIL] = -{ - "PID", - "COMM", - "STAT", - "PPID", - "PGRP", - "SESSION", - "TTY", - "TPGID", - "UTIME", - "STIME", - "CUTIME", - "CSTIME", - "PRIO", - "NICE", - "THREADS", - "START", - "VSZ", - "RSS", - "RSSLIM", - "CPU", - "RTPRIO", - "RTPOLICY", - "USER", - "GROUP", - "%MEM", - "WCHAN", - "COMMAND", - "ENVIRONMENT", - "%CPU", - "TTIME", - "CTTIME", - "TSTART", - "C%CPU" -} ; - -char const *const *s6ps_fieldheaders = fieldheaders ; - -static char const *const opttable[PFIELD_PHAIL] = -{ - "pid", - "comm", - "s", - "ppid", - "pgrp", - "sess", - "tty", - "tpgid", - "utime", - "stime", - "cutime", - "cstime", - "prio", - "nice", - "thcount", - "start", - "vsize", - "rss", - "rsslimit", - "psr", - "rtprio", - "policy", - "user", - "group", - "pmem", - "wchan", - "args", - "env", - "pcpu", - "ttime", - "cttime", - "tstart", - "cpcpu" -} ; - -char const *const *s6ps_opttable = opttable ; - -static tain boottime = TAIN_EPOCH ; - -static int fmt_64 (pscan_t *p, size_t *pos, size_t *len, uint64_t u) -{ - if (!stralloc_readyplus(&p->data, UINT64_FMT)) return 0 ; - *pos = p->data.len ; - *len = uint64_fmt(p->data.s + *pos, u) ; - p->data.len += *len ; - return 1 ; -} - -static int fmt_i (pscan_t *p, size_t *pos, size_t *len, int d) -{ - if (!stralloc_readyplus(&p->data, UINT32_FMT+1)) return 0 ; - *pos = p->data.len ; - *len = int_fmt(p->data.s + *pos, d) ; - p->data.len += *len ; - return 1 ; -} - -static int fmt_pid (pscan_t *p, size_t *pos, size_t *len) -{ - return fmt_64(p, pos, len, p->pid) ; -} - -static int fmt_comm (pscan_t *p, size_t *pos, size_t *len) -{ - *pos = p->statlen ; - *len = p->commlen ; - return 1 ; -} - -static int fmt_s (pscan_t *p, size_t *pos, size_t *len) -{ - if (!stralloc_readyplus(&p->data, 4)) return 0 ; - *pos = p->data.len ; - p->data.s[p->data.len++] = p->data.s[p->state] ; - if (p->pid == p->session) p->data.s[p->data.len++] = 's' ; - if (p->threads > 1) p->data.s[p->data.len++] = 'l' ; - if ((p->tpgid > 0) && ((unsigned int)p->tpgid == p->pgrp)) - p->data.s[p->data.len++] = '+' ; - if (p->nice) p->data.s[p->data.len++] = (p->nice < 0) ? '<' : 'N' ; - - *len = p->data.len - *pos ; - return 1 ; -} - -static int fmt_ppid (pscan_t *p, size_t *pos, size_t *len) -{ - return fmt_64(p, pos, len, p->ppid) ; -} - -static int fmt_pgrp (pscan_t *p, size_t *pos, size_t *len) -{ - return fmt_64(p, pos, len, p->pgrp) ; -} - -static int fmt_session (pscan_t *p, size_t *pos, size_t *len) -{ - return fmt_64(p, pos, len, p->session) ; -} - -static int fmt_ttynr(pscan_t *p, size_t *pos, size_t *len) -{ - if (p->ttynr) - { - size_t tmppos = p->data.len ; - if (!s6ps_ttycache_lookup(&p->data, p->ttynr)) return 0 ; - *pos = tmppos ; - *len = p->data.len - tmppos ; - } - else - { - if (!stralloc_catb(&p->data, "-", 1)) return 0 ; - *pos = p->data.len - 1 ; - *len = 1 ; - } - return 1 ; -} - -static int fmt_tpgid (pscan_t *p, size_t *pos, size_t *len) -{ - return p->tpgid < 0 ? fmt_i(p, pos, len, -1) : fmt_64(p, pos, len, p->tpgid) ; -} - -static unsigned int gethz (void) -{ - static unsigned int hz = 0 ; - if (!hz) - { - long jiffies = sysconf(_SC_CLK_TCK) ; - if (jiffies < 1) - { - char fmt[ULONG_FMT + 1] ; - fmt[long_fmt(fmt, jiffies)] = 0 ; - strerr_warnw3x("invalid _SC_CLK_TCK value (", fmt, "), using 100") ; - hz = 100 ; - } - else hz = (unsigned int)jiffies ; - } - return hz ; -} - -int s6ps_compute_boottime (pscan_t *p, unsigned int mypos) -{ - if (!mypos--) - { - strerr_warnwu1x("compute boot time - using epoch") ; - return 0 ; - } - else - { - unsigned int hz = gethz() ; - tain offset = { .sec = { .x = p[mypos].start / hz }, .nano = (p[mypos].start % hz) * (1000000000 / hz) } ; - tain_sub(&boottime, &STAMP, &offset) ; - return 1 ; - } -} - -static int fmt_jiffies (pscan_t *p, size_t *pos, size_t *len, uint64_t j) -{ - unsigned int hz = gethz() ; - uint32_t hrs, mins, secs, hfrac ; - if (!stralloc_readyplus(&p->data, UINT64_FMT + 13)) return 0 ; - hfrac = (j % hz) * 100 / hz ; - *pos = p->data.len ; - j /= hz ; - secs = j % 60 ; j /= 60 ; - mins = j % 60 ; j /= 60 ; - hrs = j % 24 ; j /= 24 ; - if (j) - { - p->data.len += uint64_fmt(p->data.s + p->data.len, j) ; - p->data.s[p->data.len++] = 'd' ; - } - if (j || hrs) - { - uint320_fmt(p->data.s + p->data.len, hrs, 2) ; - p->data.len += 2 ; - p->data.s[p->data.len++] = 'h' ; - } - if (j || hrs || mins) - { - uint320_fmt(p->data.s + p->data.len, mins, 2) ; - p->data.len += 2 ; - p->data.s[p->data.len++] = 'm' ; - } - uint320_fmt(p->data.s + p->data.len, secs, 2) ; - p->data.len += 2 ; - if (!j && !hrs && !mins) - { - p->data.s[p->data.len++] = '.' ; - uint320_fmt(p->data.s + p->data.len, hfrac, 2) ; - p->data.len += 2 ; - } - p->data.s[p->data.len++] = 's' ; - *len = p->data.len - *pos ; - return 1 ; -} - -static int fmt_utime (pscan_t *p, size_t *pos, size_t *len) -{ - return fmt_jiffies(p, pos, len, p->utime) ; -} - -static int fmt_stime (pscan_t *p, size_t *pos, size_t *len) -{ - return fmt_jiffies(p, pos, len, p->stime) ; -} - -static int fmt_cutime (pscan_t *p, size_t *pos, size_t *len) -{ - return fmt_jiffies(p, pos, len, p->utime + p->cutime) ; -} - -static int fmt_cstime (pscan_t *p, size_t *pos, size_t *len) -{ - return fmt_jiffies(p, pos, len, p->stime + p->cstime) ; -} - -static int fmt_prio (pscan_t *p, size_t *pos, size_t *len) -{ - return fmt_i(p, pos, len, p->prio) ; -} - -static int fmt_nice (pscan_t *p, size_t *pos, size_t *len) -{ - return fmt_i(p, pos, len, p->nice) ; -} - -static int fmt_threads (pscan_t *p, size_t *pos, size_t *len) -{ - return fmt_64(p, pos, len, p->threads) ; -} - -static int fmt_timedate (pscan_t *p, size_t *pos, size_t *len, struct tm const *tm) -{ - static struct tm nowtm = { .tm_year = 0 } ; - size_t tmplen ; - char *tmpstrf = "%F" ; - if (!nowtm.tm_year && !localtm_from_tai(&nowtm, tain_secp(&STAMP), 1)) return 0 ; - if (!stralloc_readyplus(&p->data, 20)) return 0 ; - if (tm->tm_year == nowtm.tm_year && tm->tm_yday == nowtm.tm_yday) - tmpstrf = "%T" ; - else if (tm->tm_year == nowtm.tm_year || (tm->tm_year+1 == nowtm.tm_year && (nowtm.tm_mon + 12 - tm->tm_mon) % 12 < 9)) - tmpstrf = "%b%d %R" ; - tmplen = strftime(p->data.s + p->data.len, 20, tmpstrf, tm) ; - if (!tmplen) return 0 ; - *len = tmplen ; - *pos = p->data.len ; - p->data.len += tmplen ; - return 1 ; -} - -static int fmt_start (pscan_t *p, size_t *pos, size_t *len) -{ - struct tm starttm ; - unsigned int hz = gethz() ; - tain blah = { .sec = { .x = p->start / hz }, .nano = (p->start % hz) * (1000000000 / hz) } ; - tain_add(&blah, &boottime, &blah) ; - if (!localtm_from_tai(&starttm, tain_secp(&blah), 1)) return 0 ; - return fmt_timedate(p, pos, len, &starttm) ; -} - -static unsigned int getpgsz (void) -{ - static unsigned int pgsz = 0 ; - if (!pgsz) - { - long sz = sysconf(_SC_PAGESIZE) ; - if (sz < 1) - { - char fmt[ULONG_FMT + 1] ; - fmt[long_fmt(fmt, sz)] = 0 ; - strerr_warnw3x("invalid _SC_PAGESIZE value (", fmt, "), using 4096") ; - pgsz = 4096 ; - } - else pgsz = sz ; - } - return pgsz ; -} - -static int fmt_vsize (pscan_t *p, size_t *pos, size_t *len) -{ - return fmt_64(p, pos, len, p->vsize / 1024) ; -} - -static int fmt_rss (pscan_t *p, size_t *pos, size_t *len) -{ - return fmt_64(p, pos, len, p->rss * (getpgsz() / 1024)) ; -} - -static int fmt_rsslim (pscan_t *p, size_t *pos, size_t *len) -{ - return fmt_64(p, pos, len, p->rsslim / 1024) ; -} - -static int fmt_cpuno (pscan_t *p, size_t *pos, size_t *len) -{ - return fmt_64(p, pos, len, p->cpuno) ; -} - -static int fmt_rtprio (pscan_t *p, size_t *pos, size_t *len) -{ - return fmt_64(p, pos, len, p->rtprio) ; -} - -static int fmt_policy (pscan_t *p, size_t *pos, size_t *len) -{ - static char const *const policies[8] = { "NORMAL", "FIFO", "RR", "BATCH", "ISO", "IDLE", "UNKNOWN", "UNKNOWN" } ; - size_t tmppos = p->data.len ; - if (!stralloc_cats(&p->data, policies[p->policy & 7])) return 0 ; - *pos = tmppos ; - *len = p->data.len - tmppos ; - return 1 ; -} - -static int fmt_user (pscan_t *p, size_t *pos, size_t *len) -{ - size_t tmppos = p->data.len ; - if (!s6ps_pwcache_lookup(&p->data, p->uid)) return 0 ; - *pos = tmppos ; - *len = p->data.len - tmppos ; - return 1 ; -} - -static int fmt_group (pscan_t *p, size_t *pos, size_t *len) -{ - size_t tmppos = p->data.len ; - if (!s6ps_grcache_lookup(&p->data, p->gid)) return 0 ; - *pos = tmppos ; - *len = p->data.len - tmppos ; - return 1 ; -} - -static struct sysinfo si = { .totalram = 0, .loads = { 0, 0, 0 } } ; - -static uint64_t gettotalmem (void) -{ - uint64_t totalmem = 0 ; - if (!si.totalram && (sysinfo(&si) < 0)) return 0 ; - totalmem = si.totalram ; - totalmem *= si.mem_unit ; - return totalmem ; -} - -static int percent (stralloc *sa, unsigned int n, size_t *pos, size_t *len) -{ - if (!stralloc_readyplus(sa, UINT64_FMT+1)) return 0 ; - *pos = sa->len ; - sa->len += uint_fmt(sa->s + sa->len, n / 100) ; - sa->s[sa->len++] = '.' ; - uint0_fmt(sa->s + sa->len, n % 100, 2) ; - sa->len += 2 ; - *len = sa->len - *pos ; - return 1 ; -} - -static int fmt_pmem (pscan_t *p, size_t *pos, size_t *len) -{ - uint64 l = gettotalmem() ; - return l ? percent(&p->data, p->rss * getpgsz() * 10000 / l, pos, len) : 0 ; -} - -static int fmt_wchan (pscan_t *p, size_t *pos, size_t *len) -{ - size_t tmppos = p->data.len ; - if (!s6ps_wchan_lookup(&p->data, p->wchan)) return 0 ; - *len = p->data.len - tmppos ; - *pos = tmppos ; - return 1 ; -} - -static int fmt_args (pscan_t *p, size_t *pos, size_t *len) -{ - if (!stralloc_readyplus(&p->data, (p->height << 2) + (p->cmdlen ? p->cmdlen : p->commlen + (p->data.s[p->state] == 'Z' ? 11 : 3)))) - return 0 ; - *pos = p->data.len ; - if (p->height) - { - unsigned int i = 0 ; - for (; i < 4 * (unsigned int)p->height - 3 ; i++) - p->data.s[p->data.len + i] = ' ' ; - memcpy(p->data.s + p->data.len + 4 * p->height - 3, "\\_ ", 3) ; - p->data.len += p->height << 2 ; - } - if (p->cmdlen) - { - char const *r = p->data.s + p->statlen + p->commlen ; - char *w = p->data.s + p->data.len ; - size_t i = p->cmdlen ; - while (i--) - { - char c = *r++ ; - *w++ = c ? c : ' ' ; - } - p->data.len += p->cmdlen ; - } - else if (p->data.s[p->state] == 'Z') - { - stralloc_catb(&p->data, p->data.s + uint32_fmt(0, p->pid) + 2, p->commlen) ; - stralloc_catb(&p->data, " ", 10) ; - } - else - stralloc_catb(&p->data, p->data.s + uint32_fmt(0, p->pid) + 1, p->commlen+2) ; - *len = p->data.len - *pos ; - return 1 ; -} - -static int fmt_env (pscan_t *p, size_t *pos, size_t *len) -{ - size_t i = 0 ; - if (!p->envlen) - { - if (!stralloc_catb(&p->data, "*", 1)) return 0 ; - *pos = p->data.len - 1 ; - *len = 1 ; - return 1 ; - } - *pos = p->statlen + p->commlen + p->cmdlen ; - *len = p->envlen ; - for (; i < *len ; i++) - if (!p->data.s[*pos + i]) p->data.s[*pos + i] = ' ' ; - return 1 ; -} - -static uint64_t gettotalj (uint64_t j) -{ - tain totaltime ; - unsigned int hz = gethz() ; - tain_sub(&totaltime, &STAMP, &boottime) ; - j = totaltime.sec.x * hz + totaltime.nano / (1000000000 / hz) - j ; - if (!j) j = 1 ; - return j ; -} - -static int fmt_pcpu (pscan_t *p, size_t *pos, size_t *len) -{ - return percent(&p->data, 10000 * (p->utime + p->stime) / gettotalj(p->start), pos, len) ; -} - - -static int fmt_ttime (pscan_t *p, size_t *pos, size_t *len) -{ - return fmt_jiffies(p, pos, len, p->utime + p->stime) ; -} - -static int fmt_cttime (pscan_t *p, size_t *pos, size_t *len) -{ - return fmt_jiffies(p, pos, len, p->utime + p->stime + p->cutime + p->cstime) ; -} - -static int fmt_tstart (pscan_t *p, size_t *pos, size_t *len) -{ - unsigned int hz = gethz() ; - tain blah = { .sec = { .x = p->start / hz }, .nano = (p->start % hz) * (1000000000 / hz) } ; - if (!stralloc_readyplus(&p->data, TIMESTAMP)) return 0 ; - tain_add(&blah, &boottime, &blah) ; - *pos = p->data.len ; - *len = timestamp_fmt(p->data.s + p->data.len, &blah) ; - p->data.len += *len ; - return 1 ; -} - -static int fmt_cpcpu (pscan_t *p, size_t *pos, size_t *len) -{ - return percent(&p->data, 10000 * (p->utime + p->stime + p->cutime + p->cstime) / gettotalj(p->start), pos, len) ; -} - -static pfieldfmt_func_ref pfieldfmt_table[PFIELD_PHAIL] = -{ - &fmt_pid, - &fmt_comm, - &fmt_s, - &fmt_ppid, - &fmt_pgrp, - &fmt_session, - &fmt_ttynr, - &fmt_tpgid, - &fmt_utime, - &fmt_stime, - &fmt_cutime, - &fmt_cstime, - &fmt_prio, - &fmt_nice, - &fmt_threads, - &fmt_start, - &fmt_vsize, - &fmt_rss, - &fmt_rsslim, - &fmt_cpuno, - &fmt_rtprio, - &fmt_policy, - &fmt_user, - &fmt_group, - &fmt_pmem, - &fmt_wchan, - &fmt_args, - &fmt_env, - &fmt_pcpu, - &fmt_ttime, - &fmt_cttime, - &fmt_tstart, - &fmt_cpcpu -} ; - -pfieldfmt_func_ref *s6ps_pfield_fmt = pfieldfmt_table ; diff --git a/src/minutils/s6ps_pwcache.c b/src/minutils/s6ps_pwcache.c deleted file mode 100644 index 283a393..0000000 --- a/src/minutils/s6ps_pwcache.c +++ /dev/null @@ -1,66 +0,0 @@ -/* ISC license. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "s6-ps.h" - -static avltree pwcache_tree = AVLTREE_ZERO ; -static genalloc pwcache_index = GENALLOC_ZERO ; - -int s6ps_pwcache_init (void) -{ - avltree_init(&pwcache_tree, 5, 3, 8, &left_dtok, &uint32_cmp, &pwcache_index) ; - return 1 ; -} - -void s6ps_pwcache_finish (void) -{ - avltree_free(&pwcache_tree) ; - genalloc_free(dius_t, &pwcache_index) ; -} - -int s6ps_pwcache_lookup (stralloc *sa, uid_t uid) -{ - int wasnull = !satmp.s ; - dius_t d = { .left = (uint32_t)uid, .right = satmp.len } ; - uint32_t i ; - if (!avltree_search(&pwcache_tree, &d.left, &i)) - { - struct passwd *pw ; - unsigned int n = genalloc_len(dius_t, &pwcache_index) ; - errno = 0 ; - pw = getpwuid(uid) ; - if (!pw) - { - if (errno) return 0 ; - if (!stralloc_readyplus(&satmp, UINT_FMT + 2)) return 0 ; - stralloc_catb(&satmp, "(", 1) ; - satmp.len += uint_fmt(satmp.s + satmp.len, uid) ; - stralloc_catb(&satmp, ")", 2) ; - } - else if (!stralloc_cats(&satmp, pw->pw_name) || !stralloc_0(&satmp)) return 0 ; - if (!genalloc_append(dius_t, &pwcache_index, &d)) goto err ; - if (!avltree_insert(&pwcache_tree, n)) - { - genalloc_setlen(dius_t, &pwcache_index, n) ; - goto err ; - } - i = n ; - } - return stralloc_cats(sa, satmp.s + genalloc_s(dius_t, &pwcache_index)[i].right) ; - err: - { - int e = errno ; - if (wasnull) stralloc_free(&satmp) ; - else satmp.len = d.right ; - errno = e ; - } - return 0 ; -} diff --git a/src/minutils/s6ps_statparse.c b/src/minutils/s6ps_statparse.c deleted file mode 100644 index fe4c355..0000000 --- a/src/minutils/s6ps_statparse.c +++ /dev/null @@ -1,184 +0,0 @@ -/* ISC license. */ - -#include -#include -#include -#include -#include -#include -#include -#include "s6-ps.h" - - - /* - going to great lengths to avoid scanf(), but all this code - is still smaller than scanf (no floating point parsing etc.) - */ - -#define STATVARS 49 - -typedef size_t sca$1_func (char const *, void *) ; -typedef sca$1_func *sca$1_func_ref ; - -static size_t f64 (char const *s, void *u64) -{ - uint64_t *u = u64 ; - return uint64_scan(s, u) ; -} - -#define DEFUNU(name, type) \ -static size_t name (char const *s, void *p) \ -{ \ - uint64_t u ; \ - size_t len = uint64_scan(s, &u) ; \ - *(type *)p = u ; \ - return len ; \ -} \ - -#define DEFUNS(name, type) \ -static size_t name (char const *s, void *p) \ -{ \ - int64_t d ; \ - size_t len = int64_scan(s, &d) ; \ - *(type *)p = d ; \ - return len ; \ -} \ - -DEFUNS(fint, int) -DEFUNS(fpid, pid_t) -DEFUNU(fdev, dev_t) - -static sca$1_func_ref scanfuncs[STATVARS] = -{ - &fpid, /* ppid */ - &fpid, /* pgrp */ - &fpid, /* session */ - &fdev, /* tty_nr */ - &fpid, /* tpgid */ - &f64, /* flags */ - &f64, /* minflt */ - &f64, /* cminflt */ - &f64, /* majflt */ - &f64, /* cmajflt */ - &f64, /* utime */ - &f64, /* stime */ - &f64, /* cutime */ - &f64, /* cstime */ - &fint, /* priority */ - &fint, /* nice */ - &f64, /* num_threads */ - &f64, /* itrealvalue */ - &f64, /* starttime */ - &f64, /* vsize */ - &f64, /* rss */ - &f64, /* rsslim */ - &f64, /* startcode */ - &f64, /* endcode */ - &f64, /* startstack */ - &f64, /* kstkesp */ - &f64, /* kstkeip */ - &f64, /* signal */ - &f64, /* blocked */ - &f64, /* sigignore */ - &f64, /* sigcatch */ - &f64, /* wchan */ - &f64, /* nswap */ - &f64, /* cnswap */ - &fint, /* exit_signal */ - &f64, /* processor */ - &f64, /* rt_priority */ - &f64, /* policy */ - &f64, /* delayacct_blkio_ticks */ - &f64, /* guest_time */ - &f64, /* cguest_time */ - &f64, /* start_data */ - &f64, /* end_data */ - &f64, /* start_brk */ - &f64, /* arg_start */ - &f64, /* arg_end */ - &f64, /* env_start */ - &f64, /* env_end */ - &fint /* exit_code */ -} ; - -int s6ps_statparse (pscan_t *p) -{ - uint64_t dummy64 ; - int dummyint ; - size_t pos = 0 ; - void *scanresults[STATVARS] = - { - &p->ppid, - &p->pgrp, - &p->session, - &p->ttynr, - &p->tpgid, - &dummy64, - &dummy64, - &dummy64, - &dummy64, - &dummy64, - &p->utime, - &p->stime, - &p->cutime, - &p->cstime, - &p->prio, - &p->nice, - &p->threads, - &dummy64, - &p->start, - &p->vsize, - &p->rss, - &p->rsslim, - &dummy64, - &dummy64, - &dummy64, - &dummy64, - &dummy64, - &dummy64, - &dummy64, - &dummy64, - &dummy64, - &p->wchan, - &dummy64, - &dummy64, - &dummy64, - &p->cpuno, - &p->rtprio, - &p->policy, - &dummy64, - &dummy64, - &dummy64, - &dummy64, - &dummy64, - &dummy64, - &dummy64, - &dummy64, - &dummy64, - &dummy64, - &dummyint - } ; - unsigned int i = 0 ; - - if (!p->statlen) return 0 ; - pos = uint64_scan(p->data.s, &dummy64) ; - if (!pos) return 0 ; - if (dummy64 != p->pid) return 0 ; - if (pos + 5 + p->commlen > p->statlen) return 0 ; - if (p->data.s[pos++] != ' ') return 0 ; - if (p->data.s[pos++] != '(') return 0 ; - pos += p->commlen ; - if (p->data.s[pos++] != ')') return 0 ; - if (p->data.s[pos++] != ' ') return 0 ; - p->state = pos++ ; - for (; i < STATVARS ; i++) - { - size_t w ; - if (pos + 1 > p->statlen) return 0 ; - if (p->data.s[pos++] != ' ') return 0 ; - w = (*scanfuncs[i])(p->data.s + pos, scanresults[i]) ; - if (!w) return 0 ; - pos += w ; - } - return 1 ; -} diff --git a/src/minutils/s6ps_ttycache.c b/src/minutils/s6ps_ttycache.c deleted file mode 100644 index 0608967..0000000 --- a/src/minutils/s6ps_ttycache.c +++ /dev/null @@ -1,136 +0,0 @@ -/* ISC license. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "s6-ps.h" - -static avltree ttycache_tree = AVLTREE_ZERO ; -static genalloc ttycache_index = GENALLOC_ZERO ; - -int s6ps_ttycache_init (void) -{ - avltree_init(&ttycache_tree, 5, 3, 8, &left_dtok, &uint32_cmp, &ttycache_index) ; - return 1 ; -} - -void s6ps_ttycache_finish (void) -{ - avltree_free(&ttycache_tree) ; - genalloc_free(dius_t, &ttycache_index) ; -} - -static int check (char const *s, dev_t ttynr) -{ - struct stat st ; - if (stat(s, &st) < 0) return 0 ; - return S_ISCHR(st.st_mode) && (st.st_rdev == ttynr) ; -} - - - /* No blind scanning of all /dev or /sys/devices, kthx */ - -static int ttyguess (stralloc *sa, dev_t ttynr) -{ - unsigned int maj = major(ttynr), min = minor(ttynr) ; - - /* Try /dev/tty? and /dev/pts/? */ - if (maj == 4 && min < 64) - { - char tmp[11] = "/dev/tty" ; - tmp[uint_fmt(tmp+8, min)] = 0 ; - if (check(tmp, ttynr)) return stralloc_cats(sa, tmp+5) && stralloc_0(sa) ; - } - else if (maj >= 136 && maj < 144) - { - unsigned int n = ((maj - 136) << 20) | min ; - char tmp[9 + UINT_FMT] = "/dev/pts/" ; - tmp[9 + uint_fmt(tmp+9, n)] = 0 ; - if (check(tmp, ttynr)) return stralloc_cats(sa, tmp+5) && stralloc_0(sa) ; - } - - /* Use /sys/dev/char/maj:min if it exists */ - { - int fd ; - size_t pos = 14 ; - char path[23 + 2 * UINT_FMT] = "/sys/dev/char/" ; - pos += uint_fmt(path + pos, maj) ; - path[pos++] = ':' ; - pos += uint_fmt(path + pos, min) ; - memcpy(path + pos, "/uevent", 8) ; - fd = open_read(path) ; - if (fd >= 0) - { - char buf[4097] ; - buffer b = BUFFER_INIT(&fd_readv, fd, buf, 4097) ; - size_t start = satmp.len ; - int r ; - for (;;) - { - satmp.len = start ; - r = skagetln(&b, &satmp, '\n') ; - if (r <= 0) break ; - if ((satmp.len - start) > 8 && !memcmp(satmp.s + start, "DEVNAME=", 8)) break ; - } - fd_close(fd) ; - if (r > 0) - { - satmp.s[satmp.len - 1] = 0 ; - satmp.len = start ; - memcpy(satmp.s + start + 3, "/dev/", 5) ; - if (check(satmp.s + start + 3, ttynr)) - return stralloc_cats(sa, satmp.s + start + 8) && stralloc_0(sa) ; - } - } - } - - /* Fallback: print explicit maj:min */ - { - size_t pos = 1 ; - char tmp[3 + 2 * UINT_FMT] = "(" ; - pos += uint_fmt(tmp + pos, maj) ; - tmp[pos++] = ':' ; - pos += uint_fmt(tmp + pos, min) ; - tmp[pos++] = ')' ; - tmp[pos++] = 0 ; - return stralloc_catb(sa, tmp, pos) ; - } -} - -int s6ps_ttycache_lookup (stralloc *sa, dev_t ttynr) -{ - int wasnull = !satmp.s ; - dius_t d = { .left = (uint32_t)ttynr, .right = satmp.len } ; - uint32_t i ; - if (!avltree_search(&ttycache_tree, &d.left, &i)) - { - unsigned int n = genalloc_len(dius_t, &ttycache_index) ; - if (!ttyguess(&satmp, ttynr)) return 0 ; - if (!genalloc_append(dius_t, &ttycache_index, &d)) goto err ; - if (!avltree_insert(&ttycache_tree, n)) - { - genalloc_setlen(dius_t, &ttycache_index, n) ; - goto err ; - } - i = n ; - } - return stralloc_cats(sa, satmp.s + genalloc_s(dius_t, &ttycache_index)[i].right) ; - err: - { - int e = errno ; - if (wasnull) stralloc_free(&satmp) ; - else satmp.len = d.right ; - errno = e ; - } - return 0 ; -} diff --git a/src/minutils/s6ps_wchan.c b/src/minutils/s6ps_wchan.c deleted file mode 100644 index 209e1ef..0000000 --- a/src/minutils/s6ps_wchan.c +++ /dev/null @@ -1,94 +0,0 @@ -/* ISC license. */ - -#include -#include -#include -#include -#include -#include -#include "s6-ps.h" - -static stralloc sysmap = STRALLOC_ZERO ; -static genalloc ind = GENALLOC_ZERO ; - -int s6ps_wchan_init (char const *file) -{ - if (file) - { - if (!openslurpclose(&sysmap, file)) return 0 ; - } - else - { - char *files[3] = { "/proc/kallsyms", 0, "/boot/System.map" } ; - struct utsname uts ; - size_t n ; - if (uname(&uts) < 0) return 0 ; - n = strlen(uts.release) ; - { - char buf[18 + n] ; - unsigned int i = 0 ; - memcpy(buf, "/boot/System.map", 16) ; - buf[16] = '-' ; - memcpy(buf + 17, uts.release, n + 1) ; - files[1] = buf ; - for (; i < 3 ; i++) - if (openslurpclose(&sysmap, files[i])) break ; - if (i >= 3) return 0 ; - } - } - { - size_t i = 0 ; - if (!genalloc_append(size_t, &ind, &i)) goto err2 ; - for (i = 1 ; i <= sysmap.len ; i++) - if (sysmap.s[i-1] == '\n') - if (!genalloc_append(size_t, &ind, &i)) goto err ; - } - return 1 ; - err: - genalloc_free(size_t, &ind) ; - err2: - stralloc_free(&sysmap) ; - return 0 ; -} - -void s6ps_wchan_finish (void) -{ - genalloc_free(size_t, &ind) ; - stralloc_free(&sysmap) ; -} - -static inline size_t lookup (uint64_t addr, size_t *i) -{ - size_t low = 0, mid, high = genalloc_len(size_t, &ind), len ; - for (;;) - { - uint64_t cur ; - mid = (low + high) >> 1 ; - len = uint64_xscan(sysmap.s + genalloc_s(size_t, &ind)[mid], &cur) ; - if (!len) return 0 ; - if (cur == addr) break ; - if (mid == low) return 0 ; - if (addr < cur) high = mid ; else low = mid ; - } - *i = mid ; - return len ; -} - -int s6ps_wchan_lookup (stralloc *sa, uint64_t addr) -{ - if (addr == (sizeof(void *) == 8 ? 0xffffffffffffffffULL : 0xffffffffUL)) - return stralloc_catb(sa, "*", 1) ; - if (!addr) return stralloc_catb(sa, "-", 1) ; - if (sysmap.len) - { - size_t i, pos, len = lookup(addr, &i) ; - if (!len) return stralloc_catb(sa, "?", 1) ; - pos = genalloc_s(size_t, &ind)[i] + len + 3 ; - return stralloc_catb(sa, sysmap.s + pos, genalloc_s(size_t, &ind)[i+1] - 1 - pos) ; - } - if (!stralloc_readyplus(sa, UINT64_FMT + 3)) return 0 ; - stralloc_catb(sa, "(0x", 3) ; - sa->len += uint64_fmt(sa->s + sa->len, addr) ; - stralloc_catb(sa, ")", 1) ; - return 1 ; -} diff --git a/src/multicall/deps-exe/s6-linux-utils b/src/multicall/deps-exe/s6-linux-utils new file mode 100644 index 0000000..730b277 --- /dev/null +++ b/src/multicall/deps-exe/s6-linux-utils @@ -0,0 +1,5 @@ +libs6ps.a.xyzzy +${LIBNSSS} +-lskarnet +${SYSCLOCK_LIB} +${MAYBEPTHREAD_LIB} diff --git a/src/s6-linux-utils/deps-exe/rngseed b/src/s6-linux-utils/deps-exe/rngseed new file mode 100644 index 0000000..a11a5f4 --- /dev/null +++ b/src/s6-linux-utils/deps-exe/rngseed @@ -0,0 +1,2 @@ +-lskarnet +${SYSCLOCK_LIB} diff --git a/src/s6-linux-utils/deps-exe/s6-chroot b/src/s6-linux-utils/deps-exe/s6-chroot new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/s6-linux-utils/deps-exe/s6-chroot @@ -0,0 +1 @@ +-lskarnet diff --git a/src/s6-linux-utils/deps-exe/s6-freeramdisk b/src/s6-linux-utils/deps-exe/s6-freeramdisk new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/s6-linux-utils/deps-exe/s6-freeramdisk @@ -0,0 +1 @@ +-lskarnet diff --git a/src/s6-linux-utils/deps-exe/s6-hostname b/src/s6-linux-utils/deps-exe/s6-hostname new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/s6-linux-utils/deps-exe/s6-hostname @@ -0,0 +1 @@ +-lskarnet diff --git a/src/s6-linux-utils/deps-exe/s6-logwatch b/src/s6-linux-utils/deps-exe/s6-logwatch new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/s6-linux-utils/deps-exe/s6-logwatch @@ -0,0 +1 @@ +-lskarnet diff --git a/src/s6-linux-utils/deps-exe/s6-mount b/src/s6-linux-utils/deps-exe/s6-mount new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/s6-linux-utils/deps-exe/s6-mount @@ -0,0 +1 @@ +-lskarnet diff --git a/src/s6-linux-utils/deps-exe/s6-pivotchroot b/src/s6-linux-utils/deps-exe/s6-pivotchroot new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/s6-linux-utils/deps-exe/s6-pivotchroot @@ -0,0 +1 @@ +-lskarnet diff --git a/src/s6-linux-utils/deps-exe/s6-ps b/src/s6-linux-utils/deps-exe/s6-ps new file mode 100644 index 0000000..ee390f1 --- /dev/null +++ b/src/s6-linux-utils/deps-exe/s6-ps @@ -0,0 +1,4 @@ +libs6ps.a.xyzzy +${LIBNSSS} +-lskarnet +${MAYBEPTHREAD_LIB} diff --git a/src/s6-linux-utils/deps-exe/s6-swapoff b/src/s6-linux-utils/deps-exe/s6-swapoff new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/s6-linux-utils/deps-exe/s6-swapoff @@ -0,0 +1 @@ +-lskarnet diff --git a/src/s6-linux-utils/deps-exe/s6-swapon b/src/s6-linux-utils/deps-exe/s6-swapon new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/s6-linux-utils/deps-exe/s6-swapon @@ -0,0 +1 @@ +-lskarnet diff --git a/src/s6-linux-utils/deps-exe/s6-umount b/src/s6-linux-utils/deps-exe/s6-umount new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/s6-linux-utils/deps-exe/s6-umount @@ -0,0 +1 @@ +-lskarnet diff --git a/src/s6-linux-utils/rngseed.c b/src/s6-linux-utils/rngseed.c new file mode 100644 index 0000000..2b1772c --- /dev/null +++ b/src/s6-linux-utils/rngseed.c @@ -0,0 +1,277 @@ +/* ISC license. */ + +#include + +#ifndef SKALIBS_HASCLOCKBOOT +# error "CLOCK_BOOTTIME required" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define USAGE "rngseed [ -d seeddir ] [ -v verbosity ] [ -r | -R ] [ -n | -N ] [ -w | -W ]" +#define dieusage() strerr_dieusage(100, USAGE) + +#define RNGSEED_HASH_PREFIX "SeedRNG v1 Old+New Prefix" + +struct rngseed_flags_s +{ + unsigned int read: 1 ; + unsigned int rcred: 1 ; + unsigned int block: 1 ; + unsigned int write: 1 ; + unsigned int wcred: 1 ; +} ; +#define RNGSEED_FLAGS_ZERO { .read = 0, .rcred = 1, .block = 1, .write = 0, .wcred = 1 } + +struct randpoolinfo_s +{ + int entropy_count ; + int buf_size ; + char buffer[512] ; +} ; + +static inline void rngseed_mkdirp (char *s, size_t len) +{ + mode_t m = umask(0) ; + size_t i = 1 ; + for (; i < len ; i++) if (s[i] == '/') + { + s[i] = 0 ; + if (mkdir(s, 02755) < 0 && errno != EEXIST) + strerr_diefu2sys(111, "mkdir ", s) ; + s[i] = '/' ; + } + umask(m) ; +} + +static inline int rngseed_read_seed_nb (char *s, size_t len) +{ + int wcred ; + size_t w = 0 ; +#ifdef SKALIBS_HASGETRANDOM + while (w < len) + { + ssize_t r = getrandom(s + w, len - w, GRND_NONBLOCK) ; + if (r == -1) + { + if (errno == EINTR) continue ; + if (error_isagain(errno)) break ; + strerr_diefu1sys(111, "getrandom") ; + } + else w += r ; + } + wcred = w >= len ; + if (!wcred) +#else + tain dummy = TAIN_EPOCH ; + iopause_fd x = { .events = IOPAUSE_READ } ; + x.fd = openbc_read("/dev/random") ; + if (x.fd == -1) strerr_diefu2sys(111, "open ", "/dev/random") ; + wcred = iopause(&x, 1, &dummy, &dummy) ; + if (wcred == -1) strerr_diefu1sys(111, "iopause") ; + fd_close(x.fd) ; +#endif + random_devurandom(s + w, len - w) ; + return wcred ; +} + +int main (int argc, char const *const *argv) +{ + blake2s_ctx ctx = BLAKE2S_INIT(32) ; + char const *seeddir = RNGSEED_DIR ; + struct rngseed_flags_s flags = RNGSEED_FLAGS_ZERO ; + unsigned int verbosity = 1 ; + PROG = "rngseed" ; + { + subgetopt l = SUBGETOPT_ZERO ; + for (;;) + { + int opt = subgetopt_r(argc, argv, "d:v:rRnNwW", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'd' : seeddir = l.arg ; break ; + case 'v' : if (!uint0_scan(l.arg, &verbosity)) dieusage() ; break ; + case 'r' : flags.read = 1 ; flags.rcred = 1 ; break ; + case 'R' : flags.read = 1 ; flags.rcred = 0 ; break ; + case 'n' : flags.block = 0 ; break ; + case 'N' : flags.block = 1 ; break ; + case 'w' : flags.write = 1 ; flags.wcred = 1 ; break ; + case 'W' : flags.write = 1 ; flags.wcred = 0 ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + } + + { + size_t dirlen = strlen(seeddir) ; + char file[dirlen + 6] ; + memcpy(file, seeddir, dirlen) ; + while (dirlen && file[dirlen-1] == '/') dirlen-- ; + memcpy(file + dirlen, "/seed", 6) ; + + if (flags.write) + { + struct timespec ts ; + if (dirlen) + { + file[dirlen] = 0 ; + rngseed_mkdirp(file, dirlen) ; + if (mkdir(file, 0700) == -1) + { + struct stat st ; + if (errno != EEXIST) strerr_diefu2sys(111, "mkdir ", file) ; + if (stat(file, &st) == -1) + strerr_diefu2sys(111, "stat ", file) ; + if (st.st_mode & 0077) + { + if (verbosity) + strerr_warnw2sys(file, "has permissive modes, changing it to 0700") ; + if (chmod(file, 0700) == -1) + strerr_diefu2sys(111, "chmod ", file) ; + } + } + file[dirlen] = '/' ; + } + blake2s_update(&ctx, RNGSEED_HASH_PREFIX, sizeof(RNGSEED_HASH_PREFIX) - 1) ; + clock_gettime(CLOCK_REALTIME, &ts) ; + blake2s_update(&ctx, (char *)&ts, sizeof ts) ; + clock_gettime(CLOCK_BOOTTIME, &ts) ; + blake2s_update(&ctx, (char *)&ts, sizeof ts) ; + } + + if (flags.read) + { + struct randpoolinfo_s req ; + struct stat st ; + size_t seedlen ; + int fd ; + if (verbosity >= 2) strerr_warni2x("reading seed from ", file) ; + fd = openbc_read(file) ; + if (fd == -1) strerr_diefu2sys(111, "open ", file) ; + errno = 0 ; + seedlen = allread(fd, req.buffer, 512) ; + if (errno) strerr_diefu2sys(111, "read from ", file) ; + if (!seedlen) strerr_dief2x(100, "empty ", file) ; + if (fstat(fd, &st) == -1) strerr_diefu2sys(111, "stat ", file) ; + if (unlink(file) == -1) strerr_diefu2sys(111, "unlink ", file) ; + fd_close(fd) ; + if (flags.write) + { + blake2s_update(&ctx, (char *)&seedlen, sizeof(seedlen)) ; + blake2s_update(&ctx, req.buffer, seedlen) ; + } + if (flags.rcred && st.st_mode & S_IWUSR && verbosity) + strerr_warnw2x(file, " was not marked as creditable") ; + req.entropy_count = flags.rcred && !(st.st_mode & S_IWUSR) ? (seedlen << 3) : 0 ; + req.buf_size = seedlen ; + fd = openbc_read("/dev/urandom") ; + if (fd == -1) strerr_diefu2sys(111, "open ", "/dev/urandom") ; + if (verbosity >= 2) + { + char fmt[SIZE_FMT] ; + fmt[size_fmt(fmt, seedlen << 3)] = 0 ; + strerr_warni4x("seeding with ", fmt, " bits", req.entropy_count ? "" : " without crediting") ; + } + if (ioctl(fd, RNDADDENTROPY, &req) == -1) + strerr_diefu1sys(111, "seed") ; + fd_close(fd) ; + } + + if (flags.block) + { + if (verbosity >= 2) + strerr_warni1x("waiting for the entropy pool to initialize") ; +#ifdef SKALIBS_HASGETRANDOM + char c ; + ssize_t r = getrandom(&c, 1, 0) ; + if (r == -1) strerr_diefu1sys(111, "getrandom") ; +#else + iopause_fd x = { .events = IOPAUSE_READ } ; + x.fd = openbc_read("/dev/random") ; + if (x.fd == -1) strerr_diefu2sys(111, "open ", "/dev/random") ; + if (iopause(&x, 1, 0, 0) == -1) strerr_diefu1sys(111, "iopause") ; + fd_close(x.fd) ; +#endif + } + + if (flags.write) + { + char seed[512] ; + size_t len = 512 ; + int wcred = 1 ; + char s[SIZE_FMT] = "" ; + int fd = openbc_read("/proc/sys/kernel/random/poolsize") ; + if (fd < 0) + { + if (verbosity) strerr_warnwu2sys("open ", "/proc/sys/kernel/random/poolsize") ; + } + else + { + size_t r ; + errno = 0 ; + r = allread(fd, s, SIZE_FMT - 1) ; + if (errno) + { + if (verbosity) strerr_warnwu2sys("read from ", "/proc/sys/kernel/random/poolsize") ; + } + else + { + s[r] = 0 ; + if (!size_scan(s, &r)) + { + if (verbosity) strerr_warnwu2sys("understand ", "/proc/sys/kernel/random/poolsize") ; + } + else len = (r + 7) >> 3 ; + } + fd_close(fd) ; + } + if (len < 32) len = 32 ; + if (len > 512) len = 512 ; + + if (verbosity >= 2) + { + s[size_fmt(s, len << 3)] = 0 ; + strerr_warni3x("reading ", s, " bits of random to make the seed") ; + } + if (flags.block) random_buf(seed, len) ; + else wcred = rngseed_read_seed_nb(seed, len) ; + if (!wcred && verbosity) strerr_warnwu1x("make the seed creditable") ; + blake2s_update(&ctx, (char *)&len, sizeof(len)) ; + blake2s_update(&ctx, seed, len) ; + blake2s_final(&ctx, seed + len - 32) ; + if (verbosity >= 2) strerr_warni2x("writing seed to ", file) ; + umask(0077) ; + if (!openwritenclose_unsafe_sync(file, seed, len)) + strerr_diefu2sys(111, "write to ", file) ; + if (flags.wcred && wcred) + { + if (chmod(file, 0400) == -1 && verbosity) + strerr_warnwu3sys("mark ", file, "as creditable") ; + } + } + } + + return 0 ; +} diff --git a/src/s6-linux-utils/s6-chroot.c b/src/s6-linux-utils/s6-chroot.c new file mode 100644 index 0000000..ae1fb7b --- /dev/null +++ b/src/s6-linux-utils/s6-chroot.c @@ -0,0 +1,18 @@ +/* ISC license. */ + +#include +#include + +#include +#include + +#define USAGE "s6-chroot dir prog..." + +int main (int argc, char const *const *argv) +{ + PROG = "s6-chroot" ; + if (argc < 3) strerr_dieusage(100, USAGE) ; + if (chdir(argv[1]) == -1) strerr_diefu2sys(111, "chdir to ", argv[1]) ; + if (chroot(".") == -1) strerr_diefu2sys(111, "chroot in ", argv[1]) ; + xexec(argv+2) ; +} diff --git a/src/s6-linux-utils/s6-freeramdisk.c b/src/s6-linux-utils/s6-freeramdisk.c new file mode 100644 index 0000000..b965527 --- /dev/null +++ b/src/s6-linux-utils/s6-freeramdisk.c @@ -0,0 +1,22 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include + +#include + +#define USAGE "s6-freeramdisk ramdisk_device" + +int main (int argc, char const *const *argv) +{ + int fd ; + PROG = "s6-freeramdisk" ; + if (argc < 2) strerr_dieusage(100, USAGE) ; + fd = open(argv[1], O_RDWR) ; + if (fd < 0) strerr_diefu3sys(111, "open ", argv[1], " in read-write mode") ; + if (ioctl(fd, BLKFLSBUF) < 0) strerr_diefu2sys(111, "ioctl ", argv[1]) ; + return 0 ; +} diff --git a/src/s6-linux-utils/s6-hostname.c b/src/s6-linux-utils/s6-hostname.c new file mode 100644 index 0000000..f2138cf --- /dev/null +++ b/src/s6-linux-utils/s6-hostname.c @@ -0,0 +1,36 @@ +/* ISC license. */ + +#include + +#include +#include + +#include +#include +#include +#include + +#define USAGE "s6-hostname [ hostname ]" + +static int hostname_getit (void) +{ + stralloc sa = STRALLOC_ZERO ; + if (sagethostname(&sa) < 0) strerr_diefu1sys(111, "get hostname") ; + sa.s[sa.len++] = '\n' ; + if (allwrite(1, sa.s, sa.len) < sa.len) + strerr_diefu1sys(111, "write to stdout") ; + return 0 ; +} + +static int hostname_setit (char const *h) +{ + if (sethostname(h, strlen(h)) < 0) + strerr_diefu1sys(111, "set hostname") ; + return 0 ; +} + +int main (int argc, char const *const *argv) +{ + PROG = "s6-hostname" ; + return (argc < 2) ? hostname_getit() : hostname_setit(argv[1]) ; +} diff --git a/src/s6-linux-utils/s6-logwatch.c b/src/s6-linux-utils/s6-logwatch.c new file mode 100644 index 0000000..7240c5e --- /dev/null +++ b/src/s6-linux-utils/s6-logwatch.c @@ -0,0 +1,173 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-logwatch [ logdir ]" +#define dieusage() strerr_dieusage(100, USAGE) + +#define LOGWATCH_READING 0 +#define LOGWATCH_BLOCKING 1 +#define LOGWATCH_WAITING 2 + +union inotify_event_u +{ + struct inotify_event event ; + char buf[sizeof(struct inotify_event) + NAME_MAX + 1] ; +} ; + +static inline void logwatch_goteof (int *fd, unsigned int *state, int *newcurrent) +{ + if (*newcurrent) + { + fd_close(*fd) ; + *fd = open_read("current") ; + if (*fd < 0) strerr_diefu1sys(111, "current") ; + *newcurrent = 0 ; + *state = LOGWATCH_READING ; + } + else *state = LOGWATCH_BLOCKING ; +} + +static int logwatch_readit (int *fd, unsigned int *state, int *newcurrent) +{ + struct iovec v[2] ; + ssize_t r ; + buffer_wpeek(buffer_1, v) ; + r = fd_readv(*fd, v, 2) ; + switch (r) + { + case -1 : return 0 ; + case 0 : logwatch_goteof(fd, state, newcurrent) ; break ; + default : buffer_wseek(buffer_1, r) ; + } + return 1 ; +} + +static inline void logwatch_maketransition (unsigned int transition, int *fd, unsigned int *state, int *newcurrent) +{ + static unsigned char const table[3][3] = { + { 0x10, 0x00, 0x00 }, + { 0x60, 0x22, 0x00 }, + { 0x40, 0x03, 0x02 } + } ; + unsigned char c = table[*state][transition] ; + *state = c & 0x0f ; + if (*state == 3) strerr_dief1x(101, "current moved twice without being recreated") ; + if (c & 0x10) *newcurrent = 1 ; + if (c & 0x20) { fd_close(*fd) ; *fd = -1 ; } + if (c & 0x40) + { + *fd = open_read("current") ; + if (*fd < 0) strerr_diefu1sys(111, "current") ; + } +} + +static void logwatch_handle_event (int ifd, int watch, int *fd, unsigned int *state, int *newcurrent) +{ + ssize_t r ; + size_t offset = 0 ; + union inotify_event_u u ; + r = read(ifd, u.buf, sizeof(u.buf)) ; + while (r > 0) + { + struct inotify_event *event = (struct inotify_event *)(u.buf + offset) ; + offset += sizeof(struct inotify_event) + event->len ; + r -= sizeof(struct inotify_event) + event->len ; + if (event->wd == watch && !strcmp(event->name, "current")) + { + int transition = -1 ; + if (event->mask & IN_CREATE) transition = 0 ; + else if (event->mask & IN_MOVED_FROM) transition = 1 ; + else if (event->mask & IN_MODIFY) transition = 2 ; + if (transition >= 0) logwatch_maketransition(transition, fd, state, newcurrent) ; + } + } +} + +int main (int argc, char const *const *argv) +{ + iopause_fd x[2] = { { .events = IOPAUSE_READ }, { .fd = 1 } } ; + char const *dir = "." ; + int watch ; + int fd ; + unsigned int state ; + int newcurrent = 0 ; + unsigned int maxlen = 4096 ; + PROG = "s6-logwatch" ; + { + subgetopt l = SUBGETOPT_ZERO ; + for (;;) + { + int opt = subgetopt_r(argc, argv, "m:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'm' : + if (!uint0_scan(l.arg, &maxlen)) dieusage() ; + strerr_warnw1x("the -m option is deprecated") ; + break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + } + + if (argc) dir = *argv ; + if (chdir(dir) < 0) strerr_diefu2sys(111, "chdir to ", dir) ; + if (!fd_sanitize()) strerr_diefu1sys(111, "sanitize standard fds") ; + + x[0].fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC) ; + if (x[0].fd < 0) strerr_diefu1sys(111, "inotify_init") ; + watch = inotify_add_watch(x[0].fd, ".", IN_CREATE | IN_MOVED_FROM | IN_MODIFY) ; + if (watch < 0) strerr_diefu1sys(111, "inotify_add_watch") ; + fd = open_readb("current") ; + if (fd < 0) + { + if (errno != ENOENT) strerr_diefu3sys(111, "open ", dir, "/current") ; + state = LOGWATCH_WAITING ; + } + else state = LOGWATCH_READING ; + if (!sig_ignore(SIGPIPE)) strerr_diefu1sys(111, "sig_ignore(SIGPIPE)") ; + if (state == LOGWATCH_READING) + { + if (!logwatch_readit(&fd, &state, &newcurrent)) strerr_diefu3sys(111, "read from ", dir, "/current") ; + } + + for (;;) + { + int r ; + x[1].events = buffer_len(buffer_1) ? IOPAUSE_WRITE : 0 ; + r = iopause(x, 2, 0, 0) ; + if (r < 0) strerr_diefu1sys(111, "iopause") ; + if (x[0].revents & IOPAUSE_EXCEPT) x[0].revents |= IOPAUSE_READ ; + if (x[1].revents & IOPAUSE_EXCEPT) x[1].revents |= IOPAUSE_WRITE ; + if (x[1].revents & IOPAUSE_WRITE) + { + if (!buffer_flush(buffer_1) && !error_isagain(errno)) + strerr_diefu1sys(111, "write to stdout") ; + if (x[1].revents & IOPAUSE_EXCEPT) break ; + } + if (state == LOGWATCH_READING && buffer_available(buffer_1)) + { + if (!logwatch_readit(&fd, &state, &newcurrent)) strerr_diefu3sys(111, "read from ", dir, "/current") ; + } + if (x[0].revents & IOPAUSE_READ) logwatch_handle_event(x[0].fd, watch, &fd, &state, &newcurrent) ; + } + return 0 ; +} diff --git a/src/s6-linux-utils/s6-mount.c b/src/s6-linux-utils/s6-mount.c new file mode 100644 index 0000000..58fc2ff --- /dev/null +++ b/src/s6-linux-utils/s6-mount.c @@ -0,0 +1,166 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "mount-constants.h" + +#define USAGE "s6-mount -a [ -z fstab ] | s6-mount [ -n ] [ -t type ] [ -o option[,option...] ]... device mountpoint" +#define dienomem() strerr_diefu1sys(111, "stralloc_catb") + +struct mount_flag_modif_s +{ + char const *name ; + unsigned long add ; + unsigned long del ; +} ; + +static int mount_flag_cmp (void const *a, void const *b) +{ + char const *key = a ; + struct mount_flag_modif_s const *p = b ; + return strcmp(key, p->name) ; +} + +static void mount_scanopt (stralloc *data, unsigned long *flags, char const *s) +{ + static struct mount_flag_modif_s const mount_flag_modifs[] = + { + { .name = "async", .add = 0, .del = MS_SYNCHRONOUS }, + { .name = "atime", .add = 0, .del = MS_NOATIME }, + { .name = "bind", .add = MS_BIND, .del = 0 }, + { .name = "defaults", .add = 0, .del = MS_RDONLY | MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_SYNCHRONOUS }, + { .name = "dev", .add = 0, .del = MS_NODEV }, + { .name = "diratime", .add = 0, .del = MS_NODIRATIME }, + { .name = "dirsync", .add = MS_DIRSYNC, .del = 0 }, + { .name = "exec", .add = 0, .del = MS_NOEXEC }, + { .name = "lazytime", .add = MS_LAZYTIME, .del = 0 }, + { .name = "loud", .add = 0, .del = MS_SILENT }, + { .name = "mandlock", .add = MS_MANDLOCK, .del = 0 }, + { .name = "move", .add = MS_MOVE, .del = 0 }, + { .name = "noatime", .add = MS_NOATIME, .del = 0 }, + { .name = "nobind", .add = 0, .del = MS_BIND }, + { .name = "nodev", .add = MS_NODEV, .del = 0 }, + { .name = "nodiratime", .add = MS_NODIRATIME, .del = 0 }, + { .name = "nodirsync", .add = 0, .del = MS_DIRSYNC }, + { .name = "nolazytime", .add = 0, .del = MS_LAZYTIME }, + { .name = "noexec", .add = MS_NOEXEC, .del = 0 }, + { .name = "nomandlock", .add = 0, .del = MS_MANDLOCK }, + { .name = "nomove", .add = 0, .del = MS_MOVE }, + { .name = "norelatime", .add = 0, .del = MS_RELATIME }, + { .name = "nostrictatime", .add = 0, .del = MS_STRICTATIME }, + { .name = "nosymfollow", .add = MS_NOSYMFOLLOW, .del = 0 }, + { .name = "nosuid", .add = MS_NOSUID, .del = 0 }, + { .name = "private", .add = MS_PRIVATE, .del = MS_SHARED | MS_SLAVE | MS_UNBINDABLE }, + { .name = "relatime", .add = MS_RELATIME, .del = 0 }, + { .name = "remount", .add = MS_REMOUNT, .del = 0 }, + { .name = "ro", .add = MS_RDONLY, .del = 0 }, + { .name = "rw", .add = 0, .del = MS_RDONLY }, + { .name = "shared", .add = MS_SHARED, .del = MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE }, + { .name = "silent", .add = MS_SILENT, .del = 0 }, + { .name = "slave", .add = MS_SLAVE, .del = MS_SHARED | MS_PRIVATE | MS_UNBINDABLE }, + { .name = "strictatime", .add = MS_STRICTATIME, .del = 0 }, + { .name = "suid", .add = 0, .del = MS_NOSUID }, + { .name = "symfollow", .add = 0, .del = MS_NOSYMFOLLOW }, + { .name = "sync", .add = MS_SYNCHRONOUS, .del = 0 }, + { .name = "unbindable", .add = MS_UNBINDABLE, .del = MS_SHARED | MS_PRIVATE | MS_SLAVE }, + } ; + + while (*s) + { + struct mount_flag_modif_s const *p ; + size_t n = str_chr(s, ',') ; + char opt[n+1] ; + memcpy(opt, s, n) ; + opt[n] = 0 ; + p = bsearch(opt, mount_flag_modifs, sizeof(mount_flag_modifs) / sizeof(struct mount_flag_modif_s), sizeof(struct mount_flag_modif_s), &mount_flag_cmp) ; + if (p) + { + *flags &= ~p->del ; + *flags |= p->add ; + } + else + { + if (data->s && data->len && !stralloc_catb(data, ",", 1)) dienomem() ; + if (!stralloc_catb(data, s, n)) dienomem() ; + } + s += n + (s[n] == ',') ; + } +} + +static int mountall (char const *fstab) +{ + struct mntent *d ; + int e = 0 ; + FILE *yuck = setmntent(fstab, "r") ; + if (!yuck) strerr_diefu2sys(111, "open ", fstab) ; + while ((d = getmntent(yuck))) + { + unsigned long flags = 0 ; + stralloc data = STRALLOC_ZERO ; + mount_scanopt(&data, &flags, d->mnt_opts) ; + if (!stralloc_0(&data)) + strerr_diefu1sys(111, "build data string") ; + if (mount(d->mnt_fsname, d->mnt_dir, d->mnt_type, flags, data.s) == -1) + { + e++ ; + strerr_warnwu4sys("mount ", d->mnt_fsname, " on ", d->mnt_dir) ; + } + stralloc_free(&data) ; + } + endmntent(yuck) ; + return e ; +} + +int main (int argc, char const *const *argv) +{ + stralloc data = STRALLOC_ZERO ; + unsigned long flags = 0 ; + char const *fstype = "none" ; + char const *fstab = "/etc/fstab" ; + PROG = "s6-mount" ; + { + int doall = 0 ; + subgetopt l = SUBGETOPT_ZERO ; + for (;;) + { + int opt = subgetopt_r(argc, argv, "nz:arwt:o:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'n' : break ; + case 'z' : fstab = l.arg ; break ; + case 'a' : doall = 1 ; break ; + case 't' : fstype = l.arg ; break ; + case 'w' : mount_scanopt(&data, &flags, "rw") ; break ; + case 'r' : mount_scanopt(&data, &flags, "ro") ; break ; + case 'o' : mount_scanopt(&data, &flags, l.arg) ; break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + if (doall) return mountall(fstab) ; + } + if (!argc) + { + int fd = open_readb("/proc/mounts") ; + if (fd < 0) strerr_diefu2sys(111, "read ", "/proc/mounts") ; + if (fd_cat(fd, 1) < 0) strerr_diefu2sys(111, "fd_cat ", "/proc/mounts") ; + fd_close(fd) ; + } + else if (argc == 1) strerr_dieusage(100, USAGE) ; + else if (!stralloc_0(&data)) strerr_diefu1sys(111, "build data string") ; + else if (mount(argv[0], argv[1], fstype, flags, data.s) == -1) + strerr_diefu4sys(errno == EBUSY ? 1 : 111, "mount ", argv[0], " on ", argv[1]) ; + return 0 ; +} diff --git a/src/s6-linux-utils/s6-pivotchroot.c b/src/s6-linux-utils/s6-pivotchroot.c new file mode 100644 index 0000000..b35a00b --- /dev/null +++ b/src/s6-linux-utils/s6-pivotchroot.c @@ -0,0 +1,21 @@ +/* ISC license. */ + +#include +#include + +#include +#include + +#define USAGE "s6-pivotchroot old-place-for-new-root new-place-for-old-root prog..." + +extern int pivot_root (char const *, char const *) ; + +int main (int argc, char const *const *argv) +{ + PROG = "s6-pivotchroot" ; + if (argc < 4) strerr_dieusage(100, USAGE) ; + if (chdir(argv[1]) < 0) strerr_diefu2sys(111, "chdir to ", argv[1]) ; + if (pivot_root(".", argv[2]) < 0) strerr_diefu1sys(111, "pivot_root") ; + if (chroot(".") < 0) strerr_diefu1sys(111, "chroot") ; + xexec(argv+3) ; +} diff --git a/src/s6-linux-utils/s6-ps.c b/src/s6-linux-utils/s6-ps.c new file mode 100644 index 0000000..fe4b433 --- /dev/null +++ b/src/s6-linux-utils/s6-ps.c @@ -0,0 +1,388 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "s6-ps.h" + +#define USAGE "s6-ps [ -H ] [ -w spacing ] [ -W wchanfile ] [ -l | -o field,field... ]" + +#define RIGHTFORMATTED ( \ + (1 << PFIELD_PID) | \ + (1 << PFIELD_PPID) | \ + (1 << PFIELD_PGRP) | \ + (1 << PFIELD_SESSION) | \ + (1 << PFIELD_TPGID) | \ + (1 << PFIELD_PRIO) | \ + (1 << PFIELD_NICE) | \ + (1 << PFIELD_THREADS) | \ + (1 << PFIELD_VSIZE) | \ + (1 << PFIELD_RSS) | \ + (1 << PFIELD_RSSLIM) | \ + (1 << PFIELD_CPUNO) | \ + (1 << PFIELD_RTPRIO) | \ + (1 << PFIELD_PMEM) | \ + (1 << PFIELD_PCPU) | \ + ((uint64_t)1 << PFIELD_CPCPU)) + +void *left_dtok (unsigned int d, void *x) +{ + return (void *)&genalloc_s(dius_t, (genalloc *)x)[d].left ; +} + +int uint32_cmp (void const *a, void const *b, void *x) +{ + uint32_t aa = *(uint32_t *)a ; + uint32_t bb = *(uint32_t *)b ; + (void)x ; + return (aa < bb) ? -1 : (aa > bb) ; +} + +static void *pid_dtok (unsigned int d, void *x) +{ + return &((pscan_t *)x)[d].pid ; +} + +static int fillo_notree (unsigned int i, unsigned int h, void *x) +{ + static unsigned int j = 0 ; + unsigned int *list = x ; + list[j++] = i ; + (void)h ; + return 1 ; +} + +static inline unsigned int fieldscan (char const *s, pfield_t *list, uint64_t *fbf) +{ + uint64_t bits = 0 ; + unsigned int n = 0 ; + int cont = 1 ; + for (; cont ; n++) + { + size_t len = str_chr(s, ',') ; + pfield_t i = 0 ; + if (!len) strerr_dief3x(100, "invalid", " (empty)", " field for -o option") ; + if (!s[len]) cont = 0 ; + { + char tmp[len+1] ; + memcpy(tmp, s, len) ; + tmp[len] = 0 ; + for (; i < PFIELD_PHAIL ; i++) if (!strcmp(tmp, s6ps_opttable[i])) break ; + if (i >= PFIELD_PHAIL) + strerr_dief4x(100, "invalid", " field for -o option", ": ", tmp) ; + if (bits & ((uint64_t)1 << i)) + strerr_dief4x(100, "duplicate", " field for -o option", ": ", tmp) ; + } + s += len + 1 ; + list[n] = i ; + bits |= ((uint64_t)1 << i) ; + } + *fbf = bits ; + return n ; +} + +static int slurpit (unsigned int dirfd, stralloc *data, char const *buf, char const *what, size_t *len) +{ + size_t start = data->len ; + int fd = open_readat(dirfd, what) ; + if (fd < 0) return 0 ; + if (!slurp(data, fd)) strerr_diefu4sys(111, "slurp ", buf, "/", what) ; + fd_close(fd) ; + *len = data->len - start ; + return 1 ; +} + +int main (int argc, char const *const *argv) +{ + genalloc pscans = GENALLOC_ZERO ; /* array of pscan_t */ + pfield_t fieldlist[PFIELD_PHAIL] = { PFIELD_USER, PFIELD_PID, PFIELD_TTY, PFIELD_STATE, PFIELD_START, PFIELD_ARGS } ; + uint64_t fbf = (1 << PFIELD_USER) | (1 << PFIELD_PID) | (1 << PFIELD_TTY) | (1 << PFIELD_STATE) | (1 << PFIELD_START) | (1 << PFIELD_ARGS) ; + size_t mypos = 0 ; + unsigned int nfields = 6 ; + pscan_t *p ; + size_t n ; + unsigned int spacing = 2 ; + int flagtree = 0 ; + char const *wchanfile = 0 ; + int needstat ; + PROG = "s6-ps" ; + + { + subgetopt l = SUBGETOPT_ZERO ; + for (;;) + { + int opt = subgetopt_r(argc, argv, "Hlw:W:o:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'H' : flagtree = 1 ; break ; + case 'l' : + { + nfields = 11 ; + fbf = (1 << PFIELD_USER) | (1 << PFIELD_PID) | ((uint64_t)1 << PFIELD_CPCPU) | (1 << PFIELD_PMEM) | (1 << PFIELD_VSIZE) | (1 << PFIELD_RSS) | (1 << PFIELD_TTY) | (1 << PFIELD_STATE) | (1 << PFIELD_START) | (1 << PFIELD_CTTIME) | (1 << PFIELD_ARGS) ; + fieldlist[0] = PFIELD_USER ; + fieldlist[1] = PFIELD_PID ; + fieldlist[2] = PFIELD_CPCPU ; + fieldlist[3] = PFIELD_PMEM ; + fieldlist[4] = PFIELD_VSIZE ; + fieldlist[5] = PFIELD_RSS ; + fieldlist[6] = PFIELD_TTY ; + fieldlist[7] = PFIELD_STATE ; + fieldlist[8] = PFIELD_START ; + fieldlist[9] = PFIELD_CTTIME ; + fieldlist[10] = PFIELD_ARGS ; + break ; + } + case 'w' : + { + if (!uint0_scan(l.arg, &spacing)) strerr_dieusage(100, USAGE) ; + break ; + } + case 'W' : wchanfile = l.arg ; break ; + case 'o' : + { + nfields = fieldscan(l.arg, fieldlist, &fbf) ; + break ; + } + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + + if (!spacing) spacing = 1 ; + if (spacing > 256) spacing = 256 ; + + needstat = flagtree || !!(fbf & ( + (1 << PFIELD_PID) | + (1 << PFIELD_COMM) | + (1 << PFIELD_STATE) | + (1 << PFIELD_PPID) | + (1 << PFIELD_PGRP) | + (1 << PFIELD_SESSION) | + (1 << PFIELD_TTY) | + (1 << PFIELD_TPGID) | + (1 << PFIELD_UTIME) | + (1 << PFIELD_STIME) | + (1 << PFIELD_CUTIME) | + (1 << PFIELD_CSTIME) | + (1 << PFIELD_PRIO) | + (1 << PFIELD_NICE) | + (1 << PFIELD_THREADS) | + (1 << PFIELD_START) | + (1 << PFIELD_VSIZE) | + (1 << PFIELD_RSS) | + (1 << PFIELD_RSSLIM) | + (1 << PFIELD_CPUNO) | + (1 << PFIELD_RTPRIO) | + (1 << PFIELD_RTPOLICY) | + (1 << PFIELD_PMEM) | + (1 << PFIELD_WCHAN) | + (1 << PFIELD_PCPU) | + (1 << PFIELD_TTIME) | + (1 << PFIELD_CTTIME) | + ((uint64_t)1 << PFIELD_TSTART) | + ((uint64_t)1 << PFIELD_CPCPU))) ; + + + /* Scan /proc */ + + { + int needstatdir = !!(fbf & ((1 << PFIELD_USER) | (1 << PFIELD_GROUP))) ; + pid_t mypid = getpid() ; + DIR *dir = opendir("/proc") ; + direntry *d ; + char buf[25] = "/proc/" ; + + if (!dir) strerr_diefu1sys(111, "open /proc") ; + for (;;) + { + pscan_t pscan = PSCAN_ZERO ; + uint64_t u ; + int dirfd ; + errno = 0 ; + d = readdir(dir) ; + if (!d) break ; + if (!uint640_scan(d->d_name, &u)) continue ; + pscan.pid = u ; + strcpy(buf+6, d->d_name) ; + dirfd = open_read(buf) ; + if (dirfd < 0) continue ; + + if (needstatdir) + { + struct stat st ; + if (fstat(dirfd, &st) < 0) goto errindir ; + pscan.uid = st.st_uid ; + pscan.gid = st.st_gid ; + } + if (needstat) + { + if (!slurpit(dirfd, &pscan.data, buf, "stat", &pscan.statlen)) + goto errindir ; + if (!slurpit(dirfd, &pscan.data, buf, "comm", &pscan.commlen)) + goto errindir ; + if (pscan.commlen) { pscan.commlen-- ; pscan.data.len-- ; } + } + if (fbf & (1 << PFIELD_ARGS)) + { + if (!slurpit(dirfd, &pscan.data, buf, "cmdline", &pscan.cmdlen)) goto errindir ; + while (!pscan.data.s[pscan.data.len-1]) + { + pscan.cmdlen-- ; + pscan.data.len-- ; + } + } + if (fbf & (1 << PFIELD_ENV)) slurpit(dirfd, &pscan.data, buf, "environ", &pscan.envlen) ; + fd_close(dirfd) ; + if (!genalloc_append(pscan_t, &pscans, &pscan)) + strerr_diefu1sys(111, "genalloc_append") ; + if (pscan.pid == mypid) mypos = genalloc_len(pscan_t, &pscans) ; + continue ; + errindir: + fd_close(dirfd) ; + stralloc_free(&pscan.data) ; + } + if (errno) strerr_diefu1sys(111, "readdir /proc") ; + dir_close(dir) ; + } + + /* Add a process 0 as a root and sentinel */ + { + pscan_t pscan = { .pid = 0, .ppid = 0 } ; + if (!genalloc_append(pscan_t, &pscans, &pscan)) strerr_diefu1sys(111, "genalloc_append") ; + } + + p = genalloc_s(pscan_t, &pscans) ; + n = genalloc_len(pscan_t, &pscans) - 1 ; + + { + unsigned int orderedlist[n+1] ; /* 1st element will be 0, ignored */ + unsigned int i = 0 ; + + /* Order the processes for display */ + + { + AVLTREEN_DECLARE_AND_INIT(pidtree, n+1, &pid_dtok, &uint32_cmp, p) ; + for (i = 0 ; i < n ; i++) + { + if (needstat && !s6ps_statparse(p+i)) + strerr_diefu1sys(111, "parse process stats") ; + if (!avltreen_insert(&pidtree, i)) + strerr_diefu1sys(111, "avltreen_insert") ; + } + if (!avltreen_insert(&pidtree, n)) + strerr_diefu1sys(111, "avltreen_insert") ; + + if (flagtree) s6ps_otree(p, n+1, &pidtree, orderedlist) ; + else avltreen_iter_nocancel(&pidtree, avltreen_totalsize(&pidtree), &fillo_notree, orderedlist) ; + } + + + /* Format, compute length, output */ + + if (fbf & ((1 << PFIELD_START) | ((uint64_t)1 << PFIELD_TSTART) | (1 << PFIELD_PCPU) | ((uint64_t)1 << PFIELD_CPCPU))) + { + tain_wallclock_read_g() ; + s6ps_compute_boottime(p, mypos) ; + } + if (fbf & (1 << PFIELD_USER) && !s6ps_pwcache_init()) + strerr_diefu1sys(111, "init user name cache") ; + if (fbf & (1 << PFIELD_GROUP) && !s6ps_grcache_init()) + strerr_diefu1sys(111, "init group name cache") ; + if (fbf & (1 << PFIELD_TTY) && !s6ps_ttycache_init()) + strerr_diefu1sys(111, "init tty name cache") ; + if (fbf & (1 << PFIELD_WCHAN) && !s6ps_wchan_init(wchanfile)) + { + if (wchanfile) strerr_warnwu2sys("init wchan file ", wchanfile) ; + else strerr_warnwu1sys("init wchan") ; + } + + { + size_t fmtpos[n][nfields] ; + size_t fmtlen[n][nfields] ; + size_t maxlen[nfields] ; + unsigned int maxspaces = 0 ; + for (i = 0 ; i < nfields ; i++) maxlen[i] = strlen(s6ps_fieldheaders[fieldlist[i]]) ; + for (i = 0 ; i < n ; i++) + { + unsigned int j = 0 ; + for (; j < nfields ; j++) + { + if (!(*s6ps_pfield_fmt[fieldlist[j]])(p+i, &fmtpos[i][j], &fmtlen[i][j])) + strerr_diefu1sys(111, "format fields") ; + if (fmtlen[i][j] > maxlen[j]) maxlen[j] = fmtlen[i][j] ; + } + } + for (i = 0 ; i < nfields ; i++) + if (maxlen[i] > maxspaces) maxspaces = maxlen[i] ; + maxspaces += spacing ; + if (fbf & (1 << PFIELD_USER)) s6ps_pwcache_finish() ; + if (fbf & (1 << PFIELD_GROUP)) s6ps_grcache_finish() ; + if (fbf & (1 << PFIELD_TTY)) s6ps_ttycache_finish() ; + if (fbf & (1 << PFIELD_WCHAN)) s6ps_wchan_finish() ; + stralloc_free(&satmp) ; + { + char spaces[maxspaces] ; + for (i = 0 ; i < maxspaces ; i++) spaces[i] = ' ' ; + for (i = 0 ; i < nfields ; i++) + { + unsigned int rightformatted = !!(((uint64_t)1 << fieldlist[i]) & RIGHTFORMATTED) ; + size_t len = strlen(s6ps_fieldheaders[fieldlist[i]]) ; + if (rightformatted && (buffer_put(buffer_1, spaces, maxlen[i] - len) < (ssize_t)(maxlen[i] - len))) + goto nowrite ; + if (buffer_put(buffer_1, s6ps_fieldheaders[fieldlist[i]], len) < (ssize_t)len) + goto nowrite ; + if ((i < nfields-1) && (buffer_put(buffer_1, spaces, !rightformatted * (maxlen[i] - len) + spacing) < (ssize_t)(!rightformatted * (maxlen[i] - len) + spacing))) + goto nowrite ; + } + if (buffer_put(buffer_1, "\n", 1) < 1) goto nowrite ; + for (i = 0 ; i < n ; i++) + { + unsigned int oi = orderedlist[i+1] ; + unsigned int j = 0 ; + for (; j < nfields ; j++) + { + unsigned int rightformatted = !!(((uint64_t)1 << fieldlist[j]) & RIGHTFORMATTED) ; + if (rightformatted && (buffer_put(buffer_1, spaces, maxlen[j] - fmtlen[oi][j]) < (ssize_t)(maxlen[j] - fmtlen[oi][j]))) + goto nowrite ; + if (buffer_put(buffer_1, p[oi].data.s + fmtpos[oi][j], fmtlen[oi][j]) < (ssize_t)fmtlen[oi][j]) + goto nowrite ; + if ((j < nfields-1) && (buffer_put(buffer_1, spaces, !rightformatted * (maxlen[j] - fmtlen[oi][j]) + spacing) < (ssize_t)(!rightformatted * (maxlen[j] - fmtlen[oi][j]) + spacing))) + goto nowrite ; + } + if (buffer_put(buffer_1, "\n", 1) < 1) goto nowrite ; + } + } + } + } + buffer_flush(buffer_1) ; + return 0 ; + + nowrite: + strerr_diefu1sys(111, "write to stdout") ; +} diff --git a/src/s6-linux-utils/s6-swapoff.c b/src/s6-linux-utils/s6-swapoff.c new file mode 100644 index 0000000..13a2530 --- /dev/null +++ b/src/s6-linux-utils/s6-swapoff.c @@ -0,0 +1,53 @@ +/* ISC license. */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-swapoff device s6-swapoff -a" + +static int swapoffall (void) +{ + char buf[4096] ; + buffer b ; + stralloc sa = STRALLOC_ZERO ; + int e = 0 ; + int r ; + int fd = open_readb("/proc/swaps") ; + if (fd < 0) strerr_diefu1sys(111, "open_readb /proc/swaps") ; + buffer_init(&b, &buffer_read, fd, buf, 4096) ; + if (skagetln(&b, &sa, '\n') < 0) strerr_diefu1sys(111, "skagetln") ; + for (;;) + { + size_t n ; + sa.len = 0 ; + r = skagetln(&b, &sa, '\n') ; + if (r < 0) strerr_diefu1sys(111, "skagetln") ; + if (!r) break ; + n = byte_chr(sa.s, sa.len, ' ') ; + if (n >= sa.len) strerr_dief1x(111, "invalid line in /proc/swaps") ; + sa.s[n] = 0 ; + if (swapoff(sa.s) < 0) { e++ ; strerr_warnwu2sys("swapoff ", sa.s) ; } + } + fd_close(fd) ; + stralloc_free(&sa) ; + return e ; +} + +int main (int argc, char const *const *argv) +{ + PROG = "s6-swapoff" ; + if (argc < 2) strerr_dieusage(100, USAGE) ; + if ((argv[1][0] == '-') && (argv[1][1] == 'a') && !argv[1][2]) + return swapoffall() ; + if (swapoff(argv[1]) == -1) strerr_diefu2sys(111, "swapoff ", argv[1]) ; + return 0 ; +} diff --git a/src/s6-linux-utils/s6-swapon.c b/src/s6-linux-utils/s6-swapon.c new file mode 100644 index 0000000..d9166a7 --- /dev/null +++ b/src/s6-linux-utils/s6-swapon.c @@ -0,0 +1,38 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include + +#include + +#define USAGE "s6-swapon device s6-swapon -a" + +static int swaponall (void) +{ + struct mntent *d ; + int e = 0 ; + FILE *yuck = setmntent("/etc/fstab", "r") ; + if (!yuck) strerr_diefu1sys(111, "setmntent /etc/fstab") ; + while ((d = getmntent(yuck))) + if (!strcmp(d->mnt_type, "swap") && (swapon(d->mnt_fsname, 0) == -1)) + { + e++ ; + strerr_warnwu2sys("swapon ", d->mnt_fsname) ; + } + endmntent(yuck) ; + return e ; +} + +int main (int argc, char const *const *argv) +{ + PROG = "s6-swapon" ; + if (argc < 2) strerr_dieusage(100, USAGE) ; + if ((argv[1][0] == '-') && (argv[1][1] == 'a') && !argv[1][2]) + return swaponall() ; + if (swapon(argv[1], 0) == -1) + strerr_diefu2sys(111, "swapon ", argv[1]) ; + return 0 ; +} diff --git a/src/s6-linux-utils/s6-umount.c b/src/s6-linux-utils/s6-umount.c new file mode 100644 index 0000000..8a9b918 --- /dev/null +++ b/src/s6-linux-utils/s6-umount.c @@ -0,0 +1,67 @@ +/* ISC license. */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-umount mountpoint s6-umount -a" + +#define UMOUNTALL_MAXLINES 512 + +static int umountall (void) +{ + stralloc mountpoints[UMOUNTALL_MAXLINES] ; + char buf[4096] ; + buffer b ; + stralloc sa = STRALLOC_ZERO ; + unsigned int line = 0 ; + int e = 0 ; + int r ; + int fd = open_readb("/proc/mounts") ; + if (fd < 0) strerr_diefu1sys(111, "open /proc/mounts") ; + memset(mountpoints, 0, sizeof(mountpoints)) ; + buffer_init(&b, &buffer_read, fd, buf, 4096) ; + for (;;) + { + size_t n, p ; + if (line >= UMOUNTALL_MAXLINES) + strerr_dief1x(111, "/proc/mounts too big") ; + sa.len = 0 ; + r = skagetln(&b, &sa, '\n') ; + if (r <= 0) break ; + p = byte_chr(sa.s, sa.len, ' ') ; + if (p >= sa.len) strerr_dief1x(111, "bad /proc/mounts format") ; + p++ ; + n = byte_chr(sa.s + p, sa.len - p, ' ') ; + if (n == sa.len - p) strerr_dief1x(111, "bad /proc/mounts format") ; + if (!stralloc_catb(&mountpoints[line], sa.s + p, n) || !stralloc_0(&mountpoints[line])) + strerr_diefu1sys(111, "store mount point") ; + line++ ; + } + fd_close(fd) ; + stralloc_free(&sa) ; + if (r < 0) strerr_diefu1sys(111, "read /proc/mounts") ; + while (line--) + if (umount(mountpoints[line].s) == -1) + { + e++ ; + strerr_warnwu2sys("umount ", mountpoints[line].s) ; + } + return e ; +} + +int main (int argc, char const *const *argv) +{ + PROG = "s6-umount" ; + if (argc < 2) strerr_dieusage(100, USAGE) ; + if ((argv[1][0] == '-') && (argv[1][1] == 'a') && !argv[1][2]) + return umountall() ; + if (umount(argv[1]) == -1) strerr_diefu2sys(111, "umount ", argv[1]) ; + return 0 ; +} -- cgit v1.2.3