├── src ├── s6-linux-utils │ ├── deps-exe │ │ ├── fstab2s6rc │ │ ├── s6-chroot │ │ ├── s6-hostname │ │ ├── s6-logwatch │ │ ├── s6-mount │ │ ├── s6-swapoff │ │ ├── s6-swapon │ │ ├── s6-umount │ │ ├── s6-freeramdisk │ │ ├── s6-pivotchroot │ │ ├── rngseed │ │ └── s6-ps │ ├── s6-chroot.c │ ├── s6-freeramdisk.c │ ├── s6-pivotchroot.c │ ├── s6-hostname.c │ ├── s6-swapon.c │ ├── s6-swapoff.c │ ├── s6-umount.c │ ├── s6-logwatch.c │ ├── s6-mount.c │ ├── rngseed.c │ └── s6-ps.c ├── multicall │ └── deps-exe │ │ └── s6-linux-utils ├── libs6ps │ ├── deps-lib │ │ └── s6ps │ ├── s6ps-internal.h │ ├── s6ps_cache.c │ ├── s6ps_grcache.c │ ├── s6ps_pwcache.c │ ├── s6ps_wchan.c │ ├── s6ps_otree.c │ ├── s6ps_ttycache.c │ ├── s6ps_statparse.c │ └── s6ps_pfield.c └── include-local │ ├── mount-constants.h │ └── s6ps.h ├── package ├── configure-snippets │ ├── configure_extra_checks │ ├── configure_help_install │ ├── configure_expand_dirs │ ├── configure_help_dependencies │ ├── configure_slashpackage_other │ ├── configure_generate_configh │ ├── configure_init_vars │ ├── configure_help_options │ ├── configure_generate_make │ └── configure_case_lines ├── info ├── deps-build ├── modes ├── targets.mak └── deps.mak ├── CONTRIBUTING ├── .gitignore ├── AUTHORS ├── tools ├── run-test.sh ├── gen-configure.el ├── install.sh ├── gen-multicall.sh ├── gen-dotpc.sh ├── gen-deps.sh └── configure.template ├── COPYING ├── README ├── doc ├── s6-freeramdisk.html ├── s6-swapoff.html ├── s6-swapon.html ├── s6-hostname.html ├── s6-umount.html ├── s6-chroot.html ├── s6-pivotchroot.html ├── s6-linux-utils.html ├── s6-logwatch.html ├── s6-mount.html ├── rngseed.html ├── index.html ├── fstab2s6rc.html ├── s6-ps.html └── upgrade.html ├── DCO ├── NEWS ├── Makefile └── INSTALL /src/s6-linux-utils/deps-exe/fstab2s6rc: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-linux-utils/deps-exe/s6-chroot: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-linux-utils/deps-exe/s6-hostname: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-linux-utils/deps-exe/s6-logwatch: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-linux-utils/deps-exe/s6-mount: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-linux-utils/deps-exe/s6-swapoff: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-linux-utils/deps-exe/s6-swapon: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-linux-utils/deps-exe/s6-umount: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /package/configure-snippets/configure_extra_checks: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /package/configure-snippets/configure_help_install: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/s6-linux-utils/deps-exe/s6-freeramdisk: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-linux-utils/deps-exe/s6-pivotchroot: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /package/configure-snippets/configure_expand_dirs: -------------------------------------------------------------------------------- 1 | shebangdir 2 | -------------------------------------------------------------------------------- /package/configure-snippets/configure_help_dependencies: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /package/configure-snippets/configure_slashpackage_other: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/s6-linux-utils/deps-exe/rngseed: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | ${SYSCLOCK_LIB} 3 | -------------------------------------------------------------------------------- /package/configure-snippets/configure_generate_configh: -------------------------------------------------------------------------------- 1 | echo "#define RNGSEED_DIR \"$seeddir\"" 2 | -------------------------------------------------------------------------------- /src/s6-linux-utils/deps-exe/s6-ps: -------------------------------------------------------------------------------- 1 | libs6ps.a.xyzzy 2 | ${LIBNSSS} 3 | -lskarnet 4 | ${MAYBEPTHREAD_LIB} 5 | -------------------------------------------------------------------------------- /package/configure-snippets/configure_init_vars: -------------------------------------------------------------------------------- 1 | usensss=false 2 | multicall=false 3 | seeddir=/var/lib/rngseed 4 | -------------------------------------------------------------------------------- /package/info: -------------------------------------------------------------------------------- 1 | package=s6-linux-utils 2 | version=2.6.4.0 3 | category=admin 4 | package_macro_name=S6_LINUX_UTILS 5 | -------------------------------------------------------------------------------- /src/multicall/deps-exe/s6-linux-utils: -------------------------------------------------------------------------------- 1 | libs6ps.a.xyzzy 2 | ${LIBNSSS} 3 | -lskarnet 4 | ${SYSCLOCK_LIB} 5 | ${MAYBEPTHREAD_LIB} 6 | -------------------------------------------------------------------------------- /src/libs6ps/deps-lib/s6ps: -------------------------------------------------------------------------------- 1 | s6ps_cache.o 2 | s6ps_grcache.o 3 | s6ps_otree.o 4 | s6ps_pfield.o 5 | s6ps_pwcache.o 6 | s6ps_statparse.o 7 | s6ps_ttycache.o 8 | s6ps_wchan.o 9 | -------------------------------------------------------------------------------- /package/deps-build: -------------------------------------------------------------------------------- 1 | true true /package/prog/skalibs 2.14.5.0 libskarnet 2 | $usensss false /package/admin/nsss 0.2.1.1 libnsss 3 | true true /package/admin/execline 2.9.8.0 4 | -------------------------------------------------------------------------------- /package/modes: -------------------------------------------------------------------------------- 1 | fstab2s6rc 0755 2 | rngseed 0744 3 | s6-chroot 0744 4 | s6-freeramdisk 0744 5 | s6-hostname 0755 6 | s6-logwatch 0755 7 | s6-mount 0755 8 | s6-pivotchroot 0744 9 | s6-ps 0755 10 | s6-swapoff 0744 11 | s6-swapon 0744 12 | s6-umount 0755 13 | s6-linux-utils 0755 14 | -------------------------------------------------------------------------------- /package/configure-snippets/configure_help_options: -------------------------------------------------------------------------------- 1 | --enable-nsss use the nsss library for user information [disabled] 2 | --with-seed-dir=DIR make DIR the default rngseed directory [/var/lib/rngseed] 3 | --enable-multicall build a multicall binary [disabled] 4 | 5 | -------------------------------------------------------------------------------- /CONTRIBUTING: -------------------------------------------------------------------------------- 1 | Please add a Signed-Off-By: line at the end of your commit, 2 | which certifies that you have the right and authority to pass 3 | it on as an open-source patch, as explicited in the Developer's 4 | Certificate of Origin available in this project's DCO file, 5 | or at https://developercertificate.org/ 6 | -------------------------------------------------------------------------------- /package/configure-snippets/configure_generate_make: -------------------------------------------------------------------------------- 1 | if $usensss ; then 2 | echo "LIBNSSS := -lnsss" 3 | echo "MAYBEPTHREAD_LIB := -lpthread" 4 | else 5 | echo "LIBNSSS :=" 6 | echo "MAYBEPTHREAD_LIB :=" 7 | fi 8 | if $multicall ; then 9 | echo "MULTICALL := 1" 10 | else 11 | echo "MULTICALL :=" 12 | fi 13 | -------------------------------------------------------------------------------- /src/libs6ps/s6ps-internal.h: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #ifndef S6PS_INTERNAL_H 4 | #define S6PS_INTERNAL_H 5 | 6 | #include 7 | #include 8 | 9 | typedef struct dius_s dius_t, *dius_t_ref ; 10 | struct dius_s 11 | { 12 | uint32_t left ; 13 | size_t right ; 14 | } ; 15 | #define DIUS_ZERO { .left = 0, .right = 0 } 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /*.pc 2 | *.o 3 | *.lo 4 | /lib*.a.xyzzy 5 | /lib*.so.xyzzy 6 | /config.mak 7 | /src/include/s6-linux-utils/config.h 8 | /src/multicall/s6-linux-utils.c 9 | /s6-linux-utils 10 | /fstab2s6rc 11 | /rngseed 12 | /s6-chroot 13 | /s6-freeramdisk 14 | /s6-hostname 15 | /s6-logwatch 16 | /s6-mount 17 | /s6-pivotchroot 18 | /s6-ps 19 | /s6-swapoff 20 | /s6-swapon 21 | /s6-umount 22 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Main author: 2 | Laurent Bercot 3 | 4 | Contributors: 5 | Eric Le Bihan 6 | Mira Ressel 7 | John Regan 8 | Fabrice Fontaine 9 | 10 | Thanks to: 11 | Dan J. Bernstein 12 | Jorge Almeida 13 | Olivier Brunel 14 | Natanael Copa 15 | Jason Donenfeld 16 | -------------------------------------------------------------------------------- /package/configure-snippets/configure_case_lines: -------------------------------------------------------------------------------- 1 | --shebangdir=*) shebangisdefault=false ; shebangdir=${arg#*=} ;; 2 | --enable-nsss|--enable-nsss=yes) usensss=true ;; 3 | --disable-nsss|--enable-nsss=no) usensss=false ;; 4 | --enable-pedantic-posix|--enable-pedantic-posix=yes) pposix=true ;; 5 | --disable-pedantic-posix|--enable-pedantic-posix=no) pposix=false ;; 6 | --enable-multicall|--enable-multicall=yes) multicall=true ;; 7 | --disable-multicall|--enable-multicall=no) multicall=false ;; 8 | -------------------------------------------------------------------------------- /src/s6-linux-utils/s6-chroot.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #define USAGE "s6-chroot dir prog..." 10 | 11 | int main (int argc, char const *const *argv) 12 | { 13 | PROG = "s6-chroot" ; 14 | if (argc < 3) strerr_dieusage(100, USAGE) ; 15 | if (chdir(argv[1]) == -1) strerr_diefu2sys(111, "chdir to ", argv[1]) ; 16 | if (chroot(".") == -1) strerr_diefu2sys(111, "chroot in ", argv[1]) ; 17 | xexec(argv+2) ; 18 | } 19 | -------------------------------------------------------------------------------- /tools/run-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | prog="$1" 4 | 5 | if test -x "./src/tests/${prog}.wrapper" ; then 6 | cmd="./src/tests/${prog}.wrapper $prog" 7 | else 8 | cmd="./$prog" 9 | fi 10 | 11 | if test -r "./src/tests/${prog}.expected" ; then 12 | cp -f "./src/tests/${prog}.expected" "./${prog}.expected" 13 | elif test -x "./src/tests/${prog}.baseline" ; then 14 | "./src/tests/${prog}.baseline" > "./${prog}.expected" 15 | else 16 | echo "run-test.sh: fatal: missing baseline for $prog" 1>&2 ; exit 100 17 | fi 18 | 19 | $cmd | diff "./${prog}.expected" - 20 | 21 | rm -f "./${prog}.expected" 22 | echo "run-test.sh: info: $prog: pass" 1>&2 23 | -------------------------------------------------------------------------------- /src/s6-linux-utils/s6-freeramdisk.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #define USAGE "s6-freeramdisk ramdisk_device" 13 | 14 | int main (int argc, char const *const *argv) 15 | { 16 | int fd ; 17 | PROG = "s6-freeramdisk" ; 18 | if (argc < 2) strerr_dieusage(100, USAGE) ; 19 | fd = open2(argv[1], O_RDWR) ; 20 | if (fd < 0) strerr_diefu3sys(111, "open ", argv[1], " in read-write mode") ; 21 | if (ioctl(fd, BLKFLSBUF) < 0) strerr_diefu2sys(111, "ioctl ", argv[1]) ; 22 | return 0 ; 23 | } 24 | -------------------------------------------------------------------------------- /src/s6-linux-utils/s6-pivotchroot.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #define USAGE "s6-pivotchroot old-place-for-new-root new-place-for-old-root prog..." 10 | 11 | extern int pivot_root (char const *, char const *) ; 12 | 13 | int main (int argc, char const *const *argv) 14 | { 15 | PROG = "s6-pivotchroot" ; 16 | if (argc < 4) strerr_dieusage(100, USAGE) ; 17 | if (chdir(argv[1]) < 0) strerr_diefu2sys(111, "chdir to ", argv[1]) ; 18 | if (pivot_root(".", argv[2]) < 0) strerr_diefu1sys(111, "pivot_root") ; 19 | if (chroot(".") < 0) strerr_diefu1sys(111, "chroot") ; 20 | xexec(argv+3) ; 21 | } 22 | -------------------------------------------------------------------------------- /package/targets.mak: -------------------------------------------------------------------------------- 1 | LIBEXEC_TARGETS := 2 | 3 | ifeq ($(MULTICALL),1) 4 | 5 | BIN_TARGETS := $(package) 6 | BIN_SYMLINKS := $(notdir $(wildcard src/$(package)/deps-exe/*)) 7 | EXTRA_TARGETS += src/multicall/$(package).c 8 | 9 | define symlink_definition 10 | SYMLINK_TARGET_$(1) := $(package) 11 | endef 12 | $(foreach name,$(BIN_SYMLINKS),$(eval $(call symlink_definition,$(name)))) 13 | 14 | src/multicall/$(package).c: tools/gen-multicall.sh $(BIN_SYMLINKS:%=src/$(package)/%.c) 15 | ./tools/gen-multicall.sh $(package) > src/multicall/$(package).c 16 | 17 | src/multicall/$(package).o: src/multicall/$(package).c src/include/$(package)/config.h 18 | 19 | else 20 | 21 | BIN_TARGETS := $(notdir $(wildcard src/$(package)/deps-exe/*)) 22 | BIN_SYMLINKS := 23 | 24 | endif 25 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2025 Laurent Bercot 2 | 3 | Permission to use, copy, modify, and distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /src/libs6ps/s6ps_cache.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include "s6ps.h" 9 | #include "s6ps-internal.h" 10 | 11 | static void *left_dtok (unsigned int d, void *x) 12 | { 13 | return (void *)&genalloc_s(dius_t, (genalloc *)x)[d].left ; 14 | } 15 | 16 | int s6ps_uint32_cmp (void const *a, void const *b, void *x) 17 | { 18 | uint32_t aa = *(uint32_t *)a ; 19 | uint32_t bb = *(uint32_t *)b ; 20 | (void)x ; 21 | return (aa < bb) ? -1 : (aa > bb) ; 22 | } 23 | 24 | int s6ps_cache_init (s6ps_cache_t *cache) 25 | { 26 | avltree_init(&cache->tree, 5, 3, 8, &left_dtok, &s6ps_uint32_cmp, &cache->index) ; 27 | return 1 ; 28 | } 29 | 30 | void s6ps_cache_finish (s6ps_cache_t *cache) 31 | { 32 | avltree_free(&cache->tree) ; 33 | genalloc_free(dius_t, &cache->index) ; 34 | } 35 | -------------------------------------------------------------------------------- /src/s6-linux-utils/s6-hostname.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define USAGE "s6-hostname [ hostname ]" 14 | 15 | static int hostname_getit (void) 16 | { 17 | stralloc sa = STRALLOC_ZERO ; 18 | if (sagethostname(&sa) < 0) strerr_diefu1sys(111, "get hostname") ; 19 | sa.s[sa.len++] = '\n' ; 20 | if (allwrite(1, sa.s, sa.len) < sa.len) 21 | strerr_diefu1sys(111, "write to stdout") ; 22 | return 0 ; 23 | } 24 | 25 | static int hostname_setit (char const *h) 26 | { 27 | if (sethostname(h, strlen(h)) < 0) 28 | strerr_diefu1sys(111, "set hostname") ; 29 | return 0 ; 30 | } 31 | 32 | int main (int argc, char const *const *argv) 33 | { 34 | PROG = "s6-hostname" ; 35 | return (argc < 2) ? hostname_getit() : hostname_setit(argv[1]) ; 36 | } 37 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | s6-linux-utils - tiny Linux-specific utilities 2 | ---------------------------------------------- 3 | 4 | s6-linux-utils is a set of tiny Linux-specific utilities, 5 | some performing well-known tasks such as mount and swapon, 6 | other being nonstandard but typically useful for a s6-based 7 | system. They have been optimized for simplicity and small size. 8 | They were designed for embedded systems and other constrained 9 | environments, but they work on any Linux system. 10 | 11 | Of particular interest in this package are the following 12 | programs: 13 | - s6-ps, an independent ps implementation 14 | 15 | See https://skarnet.org/software/s6-linux-utils/ for details. 16 | 17 | 18 | * Installation 19 | ------------ 20 | 21 | See the INSTALL file. 22 | 23 | 24 | * Contact information 25 | ------------------- 26 | 27 | Laurent Bercot 28 | 29 | Please use the mailing-list for 30 | questions about s6-linux-utils. 31 | -------------------------------------------------------------------------------- /tools/gen-configure.el: -------------------------------------------------------------------------------- 1 | #!/command/execlineb -S0 2 | 3 | # For dev use only. Don't run this, it overwrites your configure. 4 | 5 | # The quoting interactions in sed and sh make it impossible to get 6 | # such a simple thing done. It's amazing how bad traditional Unix is. 7 | 8 | backtick -E TEMPLATE { redirfd -r 0 tools/configure.template s6-cat } 9 | s6-envdir -Lf package/configure-snippets 10 | multisubstitute 11 | { 12 | importas -uS configure_help_install 13 | importas -uS configure_help_dependencies 14 | importas -uS configure_help_options 15 | importas -uS configure_init_vars 16 | importas -uS configure_case_lines 17 | importas -uS configure_expand_dirs 18 | importas -uS configure_slashpackage_other 19 | importas -uS configure_extra_checks 20 | importas -uS configure_generate_make 21 | importas -uS configure_generate_configh 22 | } 23 | 24 | if 25 | { 26 | redirfd -w 1 configure.new 27 | if { heredoc 0 ${TEMPLATE} s6-cat } 28 | s6-echo 29 | } 30 | 31 | if { s6-chmod 0755 configure.new } 32 | s6-rename configure.new configure 33 | -------------------------------------------------------------------------------- /doc/s6-freeramdisk.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-linux-utils: the s6-freeramdisk program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-linux-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-freeramdisk program

20 | 21 |

22 | s6-freeramdisk frees the memory occupied by a RAM disk. Call it 23 | when your RAM disk is not in use anymore. 24 |

25 | 26 |

Interface

27 | 28 |
29 |      s6-freeramdisk ramdisk-device
30 | 
31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/s6-linux-utils/s6-swapon.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #define USAGE "s6-swapon [ -a ] [ device ]" 13 | 14 | static int swaponall (void) 15 | { 16 | struct mntent *d ; 17 | int e = 0 ; 18 | FILE *yuck = setmntent("/etc/fstab", "r") ; 19 | if (!yuck) strerr_diefu1sys(111, "setmntent /etc/fstab") ; 20 | while ((d = getmntent(yuck))) 21 | if (!strcmp(d->mnt_type, "swap") && (swapon(d->mnt_fsname, 0) == -1)) 22 | { 23 | e++ ; 24 | strerr_warnwu2sys("swapon ", d->mnt_fsname) ; 25 | } 26 | endmntent(yuck) ; 27 | return e ; 28 | } 29 | 30 | int main (int argc, char const *const *argv) 31 | { 32 | static gol_bool const rgolb[] = 33 | { 34 | { .so = 'a', .lo = "all", .clear = 0, .set = 1 }, 35 | } ; 36 | uint64_t wgolb = 0 ; 37 | unsigned int golc ; 38 | PROG = "s6-swapon" ; 39 | golc = gol_main(argc, argv, rgolb, 1, 0, 0, &wgolb, 0) ; 40 | argc -= golc ; argv += golc ; 41 | if (wgolb & 1) _exit(swaponall()) ; 42 | if (!argc) strerr_dieusage(100, USAGE) ; 43 | if (swapon(argv[0], 0) == -1) strerr_diefu2sys(111, "swapon ", argv[0]) ; 44 | _exit(0) ; 45 | } 46 | -------------------------------------------------------------------------------- /doc/s6-swapoff.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-linux-utils: the s6-swapoff program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-linux-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-swapoff program

20 | 21 | s6-swapoff deactivates swap partitions. 22 | 23 |

Interface

24 | 25 |
26 |      s6-swapoff [ -a | device ]
27 | 
28 | 29 |
    30 |
  • s6-swapoff deactivates the swap on device.
  • 31 |
  • If the -a option is given instead of device, 32 | s6-swapoff looks for swap partitions in 33 | /proc/swaps and deactivates them all.
  • 34 |
35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/s6-swapon.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-linux-utils: the s6-swapon program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-linux-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-swapon program

20 | 21 | s6-swapon activates swap partitions. 22 | 23 |

Interface

24 | 25 |
26 |      s6-swapon [ -a | device ]
27 | 
28 | 29 |
    30 |
  • s6-swapon activates the swap on device.
  • 31 |
  • If the -a option is given instead of device, 32 | s6-swapon looks for partitions marked swap in 33 | /etc/fstab and activates them all.
  • 34 |
35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/s6-hostname.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-linux-utils: the s6-hostname program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-linux-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-hostname program

20 | 21 |

22 | s6-hostname gets or sets the machine hostname. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-hostname [ name ]
29 | 
30 | 31 |
    32 |
  • When called without an argument, s6-hostname prints the 33 | machine hostname to stdout.
  • 34 |
  • When called with an argument, s6-hostname sets the machine 35 | hostname to name.
  • 36 |
  • Then it exits 0.
  • 37 |
38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /doc/s6-umount.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-linux-utils: the s6-umount program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-linux-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-umount program

20 | 21 |

22 | s6-umount unmounts filesystems. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-umount [ -a | mntpoint ]
29 | 
30 | 31 |
    32 |
  • s6-umount -a unmounts all partitions according to /proc/mounts.
  • 33 |
  • If the -a option is not given, 34 | s6-umount unmounts the filesystem mounted on mntpoint.
  • 35 |
  • s6-umount does not touch /etc/mtab.
  • 36 |
37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /tools/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | usage() { 4 | echo "usage: $0 [ -D ] [ -l ] [ -m mode ] [ -O owner:group ] src dst" 1>&2 5 | exit 1 6 | } 7 | 8 | mkdirp=false 9 | symlink=false 10 | mode=0755 11 | og= 12 | 13 | while getopts Dlm:O: name ; do 14 | case "$name" in 15 | D) mkdirp=true ;; 16 | l) symlink=true ;; 17 | m) mode=$OPTARG ;; 18 | O) og=$OPTARG ;; 19 | ?) usage ;; 20 | esac 21 | done 22 | shift $(($OPTIND - 1)) 23 | 24 | test "$#" -eq 2 || usage 25 | src=$1 26 | dst=$2 27 | tmp="$dst.tmp.$$" 28 | 29 | case "$dst" in 30 | */) echo "$0: $dst ends in /" 1>&2 ; exit 1 ;; 31 | esac 32 | 33 | set -C 34 | set -e 35 | 36 | if $mkdirp ; then 37 | umask 022 38 | case "$2" in 39 | */*) mkdir -p "${dst%/*}" ;; 40 | esac 41 | fi 42 | 43 | trap 'rm -f "$tmp"' EXIT INT QUIT TERM HUP 44 | 45 | umask 077 46 | 47 | if $symlink ; then 48 | ln -s "$src" "$tmp" 49 | else 50 | cat < "$1" > "$tmp" 51 | if test -n "$og" ; then 52 | chown -- "$og" "$tmp" 53 | fi 54 | chmod -- "$mode" "$tmp" 55 | fi 56 | 57 | mv -f "$tmp" "$dst" 58 | if test -d "$dst" ; then 59 | rm -f "$dst/$(basename $tmp)" 60 | if $symlink ; then 61 | mkdir "$tmp" 62 | ln -s "$src" "$tmp/$(basename $dst)" 63 | mv -f "$tmp/$(basename $dst)" "${dst%/*}" 64 | rmdir "$tmp" 65 | else 66 | echo "$0: $dst is a directory" 1>&2 67 | exit 1 68 | fi 69 | fi 70 | -------------------------------------------------------------------------------- /doc/s6-chroot.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-linux-utils: the s6-chroot program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-linux-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-chroot program

20 | 21 |

22 | s6-chroot executes a program in a chroot jail. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-chroot newroot prog...
29 | 
30 | 31 |
    32 |
  • s6-chroot sets the root filesystem for the current 33 | process to newroot, which must be an existing directory.
  • 34 |
  • s6-chroot changes directory to this new root, and 35 | executes prog 36 | with its arguments. prog is searched under the new root.
  • 37 |
  • s6-chroot's parent process is unaffected by the root change.
  • 38 |
39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/libs6ps/s6ps_grcache.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "s6ps.h" 14 | #include "s6ps-internal.h" 15 | 16 | int s6ps_grcache_lookup (s6ps_cache_t *cache, stralloc *sa, gid_t gid) 17 | { 18 | dius_t d = { .left = (uint32_t)gid, .right = satmp.len } ; 19 | uint32_t i ; 20 | if (!avltree_search(&cache->tree, &d.left, &i)) 21 | { 22 | struct group *gr ; 23 | size_t n = genalloc_len(dius_t, &cache->index) ; 24 | errno = 0 ; 25 | gr = getgrgid(gid) ; 26 | if (!gr) 27 | { 28 | if (errno) return 0 ; 29 | if (!stralloc_readyplus(&satmp, UINT_FMT + 2)) return 0 ; 30 | stralloc_catb(&satmp, "(", 1) ; 31 | satmp.len += uint_fmt(satmp.s + satmp.len, gid) ; 32 | stralloc_catb(&satmp, ")", 2) ; 33 | } 34 | else if (!stralloc_cats(&satmp, gr->gr_name) || !stralloc_0(&satmp)) return 0 ; 35 | if (!genalloc_append(dius_t, &cache->index, &d)) goto err ; 36 | if (!avltree_insert(&cache->tree, n)) 37 | { 38 | genalloc_setlen(dius_t, &cache->index, n) ; 39 | goto err ; 40 | } 41 | i = n ; 42 | } 43 | return stralloc_cats(sa, satmp.s + genalloc_s(dius_t, &cache->index)[i].right) ; 44 | err: 45 | satmp.len = d.right ; 46 | return 0 ; 47 | } 48 | -------------------------------------------------------------------------------- /src/libs6ps/s6ps_pwcache.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "s6ps.h" 14 | #include "s6ps-internal.h" 15 | 16 | int s6ps_pwcache_lookup (s6ps_cache_t *cache, stralloc *sa, uid_t uid) 17 | { 18 | dius_t d = { .left = (uint32_t)uid, .right = satmp.len } ; 19 | uint32_t i ; 20 | if (!avltree_search(&cache->tree, &d.left, &i)) 21 | { 22 | struct passwd *pw ; 23 | size_t n = genalloc_len(dius_t, &cache->index) ; 24 | errno = 0 ; 25 | pw = getpwuid(uid) ; 26 | if (!pw) 27 | { 28 | if (errno) return 0 ; 29 | if (!stralloc_readyplus(&satmp, UINT_FMT + 2)) return 0 ; 30 | stralloc_catb(&satmp, "(", 1) ; 31 | satmp.len += uint_fmt(satmp.s + satmp.len, uid) ; 32 | stralloc_catb(&satmp, ")", 2) ; 33 | } 34 | else if (!stralloc_cats(&satmp, pw->pw_name) || !stralloc_0(&satmp)) return 0 ; 35 | if (!genalloc_append(dius_t, &cache->index, &d)) goto err ; 36 | if (!avltree_insert(&cache->tree, n)) 37 | { 38 | genalloc_setlen(dius_t, &cache->index, n) ; 39 | goto err ; 40 | } 41 | i = n ; 42 | } 43 | return stralloc_cats(sa, satmp.s + genalloc_s(dius_t, &cache->index)[i].right) ; 44 | err: 45 | satmp.len = d.right ; 46 | return 0 ; 47 | } 48 | -------------------------------------------------------------------------------- /DCO: -------------------------------------------------------------------------------- 1 | Developer Certificate of Origin 2 | Version 1.1 3 | 4 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 5 | 1 Letterman Drive 6 | Suite D4700 7 | San Francisco, CA, 94129 8 | 9 | Everyone is permitted to copy and distribute verbatim copies of this 10 | license document, but changing it is not allowed. 11 | 12 | 13 | Developer's Certificate of Origin 1.1 14 | 15 | By making a contribution to this project, I certify that: 16 | 17 | (a) The contribution was created in whole or in part by me and I 18 | have the right to submit it under the open source license 19 | indicated in the file; or 20 | 21 | (b) The contribution is based upon previous work that, to the best 22 | of my knowledge, is covered under an appropriate open source 23 | license and I have the right under that license to submit that 24 | work with modifications, whether created in whole or in part 25 | by me, under the same open source license (unless I am 26 | permitted to submit under a different license), as indicated 27 | in the file; or 28 | 29 | (c) The contribution was provided directly to me by some other 30 | person who certified (a), (b) or (c) and I have not modified 31 | it. 32 | 33 | (d) I understand and agree that this project and the contribution 34 | are public and that a record of the contribution (including all 35 | personal information I submit with it, including my sign-off) is 36 | maintained indefinitely and may be redistributed consistent with 37 | this project or the open source license(s) involved. 38 | -------------------------------------------------------------------------------- /doc/s6-pivotchroot.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-linux-utils: the s6-pivotchroot program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-linux-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-pivotchroot program

20 | 21 |

22 | s6-pivotchroot performs a pivot_root system call, 23 | then changes root to the new root filesystem and executes a program. 24 |

25 | 26 |

Interface

27 | 28 |
29 |      s6-pivotchroot newroot putold prog...
30 | 
31 | 32 |
    33 |
  • s6-pivotchroot sets the root filesystem to newroot, 34 | which must be a mounted filesystem entry point. The old root filesystem 35 | will be available under putold (relative to the old root).
  • 36 |
  • s6-pivotchroot changes directory to the new root, performs 37 | a chroot system call to the new root, and executes prog 38 | with its arguments. prog is searched under the new root.
  • 39 |
40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/s6-linux-utils/s6-swapoff.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define USAGE "s6-swapoff [ -a ] [ device ]" 17 | 18 | static int swapoffall (void) 19 | { 20 | char buf[4096] ; 21 | buffer b ; 22 | stralloc sa = STRALLOC_ZERO ; 23 | int e = 0 ; 24 | int r ; 25 | int fd = open_readb("/proc/swaps") ; 26 | if (fd < 0) strerr_diefu1sys(111, "open_readb /proc/swaps") ; 27 | buffer_init(&b, &buffer_read, fd, buf, 4096) ; 28 | if (skagetln(&b, &sa, '\n') < 0) strerr_diefu1sys(111, "skagetln") ; 29 | for (;;) 30 | { 31 | size_t n ; 32 | sa.len = 0 ; 33 | r = skagetln(&b, &sa, '\n') ; 34 | if (r < 0) strerr_diefu1sys(111, "skagetln") ; 35 | if (!r) break ; 36 | n = byte_chr(sa.s, sa.len, ' ') ; 37 | if (n >= sa.len) strerr_dief1x(111, "invalid line in /proc/swaps") ; 38 | sa.s[n] = 0 ; 39 | if (swapoff(sa.s) < 0) { e++ ; strerr_warnwu2sys("swapoff ", sa.s) ; } 40 | } 41 | fd_close(fd) ; 42 | stralloc_free(&sa) ; 43 | return e ; 44 | } 45 | 46 | int main (int argc, char const *const *argv) 47 | { 48 | static gol_bool const rgolb[] = 49 | { 50 | { .so = 'a', .lo = "all", .clear = 0, .set = 1 }, 51 | } ; 52 | uint64_t wgolb = 0 ; 53 | unsigned int golc ; 54 | PROG = "s6-swapoff" ; 55 | golc = gol_main(argc, argv, rgolb, 1, 0, 0, &wgolb, 0) ; 56 | argc -= golc ; argv += golc ; 57 | if (wgolb & 1) _exit(swapoffall()) ; 58 | if (!argc) strerr_dieusage(100, USAGE) ; 59 | if (swapoff(argv[0]) == -1) strerr_diefu2sys(111, "swapoff ", argv[0]) ; 60 | _exit(0) ; 61 | } 62 | -------------------------------------------------------------------------------- /doc/s6-linux-utils.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-linux-utils: the s6-linux-utils multicall binary 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-linux-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-linux-utils multicall binary

20 | 21 |

22 | The s6-linux-utils program is only available when the 23 | --enable-multicall option has been given to the configure 24 | program at build time. In this configuration, s6-linux-utils is 25 | a multicall binary implementing the functionality of all 26 | the programs in the s6-linux-utils package; and the other programs, instead 27 | of being executables of their own, are symbolic links to the 28 | s6-linux-utils binary. 29 |

30 | 31 |

Interface

32 | 33 |
34 |      s6-linux-utils subcommand subcommand_arguments...
35 | 
36 | 37 |

38 | s6-linux-utils will run the subcommand with its arguments. For 39 | instance, s6-linux-utils s6-ps -H will run the equivalent of the 40 | s6-ps program, so this command will print a 41 | tree of the currently running processes. 42 |

43 | 44 |

45 | Alternatively, if s6-linux-utils is called with the name of an existing 46 | command, it will run the equivalent of that command. For instance, 47 | if the /usr/bin/s6-ps file is a (hard or symbolic) link to 48 | the s6-linux-utils binary, /usr/bin/s6-ps -H will print 49 | a tree of the currently running processes. 50 |

51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /src/s6-linux-utils/s6-umount.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define USAGE "s6-umount [ -a ] [ mountpoint ]" 16 | 17 | #define UMOUNTALL_MAXLINES 512 18 | 19 | static int umountall (void) 20 | { 21 | stralloc mountpoints[UMOUNTALL_MAXLINES] ; 22 | char buf[4096] ; 23 | buffer b ; 24 | stralloc sa = STRALLOC_ZERO ; 25 | unsigned int line = 0 ; 26 | int e = 0 ; 27 | int r ; 28 | int fd = open_readb("/proc/mounts") ; 29 | if (fd < 0) strerr_diefu1sys(111, "open /proc/mounts") ; 30 | memset(mountpoints, 0, sizeof(mountpoints)) ; 31 | buffer_init(&b, &buffer_read, fd, buf, 4096) ; 32 | for (;;) 33 | { 34 | size_t n, p ; 35 | if (line >= UMOUNTALL_MAXLINES) 36 | strerr_dief1x(111, "/proc/mounts too big") ; 37 | sa.len = 0 ; 38 | r = skagetln(&b, &sa, '\n') ; 39 | if (r <= 0) break ; 40 | p = byte_chr(sa.s, sa.len, ' ') ; 41 | if (p >= sa.len) strerr_dief1x(111, "bad /proc/mounts format") ; 42 | p++ ; 43 | n = byte_chr(sa.s + p, sa.len - p, ' ') ; 44 | if (n == sa.len - p) strerr_dief1x(111, "bad /proc/mounts format") ; 45 | if (!stralloc_catb(&mountpoints[line], sa.s + p, n) || !stralloc_0(&mountpoints[line])) 46 | strerr_diefu1sys(111, "store mount point") ; 47 | line++ ; 48 | } 49 | fd_close(fd) ; 50 | stralloc_free(&sa) ; 51 | if (r < 0) strerr_diefu1sys(111, "read /proc/mounts") ; 52 | while (line--) 53 | if (umount(mountpoints[line].s) == -1) 54 | { 55 | e++ ; 56 | strerr_warnwu2sys("umount ", mountpoints[line].s) ; 57 | } 58 | return e ; 59 | } 60 | 61 | int main (int argc, char const *const *argv) 62 | { 63 | static gol_bool const rgolb[] = 64 | { 65 | { .so = 'a', .lo = "all", .clear = 0, .set = 1 }, 66 | } ; 67 | uint64_t wgolb = 0 ; 68 | unsigned int golc ; 69 | PROG = "s6-umount" ; 70 | golc = gol_main(argc, argv, rgolb, 1, 0, 0, &wgolb, 0) ; 71 | argc -= golc ; argv += golc ; 72 | if (wgolb & 1) _exit(umountall()) ; 73 | if (!argc) strerr_dieusage(100, USAGE) ; 74 | if (umount(argv[0]) == -1) strerr_diefu2sys(111, "unmount ", argv[0]) ; 75 | _exit(0) ; 76 | } 77 | -------------------------------------------------------------------------------- /src/include-local/mount-constants.h: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #ifndef MOUNT_CONSTANTS_H 4 | #define MOUNT_CONSTANTS_H 5 | 6 | /* taken from util-linux */ 7 | 8 | #ifndef MS_RDONLY 9 | #define MS_RDONLY 1 /* Mount read-only */ 10 | #endif 11 | #ifndef MS_NOSUID 12 | #define MS_NOSUID 2 /* Ignore suid and sgid bits */ 13 | #endif 14 | #ifndef MS_NODEV 15 | #define MS_NODEV 4 /* Disallow access to device special files */ 16 | #endif 17 | #ifndef MS_NOEXEC 18 | #define MS_NOEXEC 8 /* Disallow program execution */ 19 | #endif 20 | #ifndef MS_SYNCHRONOUS 21 | #define MS_SYNCHRONOUS 16 /* Writes are synced at once */ 22 | #endif 23 | #ifndef MS_REMOUNT 24 | #define MS_REMOUNT 32 /* Alter flags of a mounted FS */ 25 | #endif 26 | #ifndef MS_MANDLOCK 27 | #define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */ 28 | #endif 29 | #ifndef MS_DIRSYNC 30 | #define MS_DIRSYNC 128 /* Directory modifications are synchronous */ 31 | #endif 32 | #ifndef MS_NOSYMFOLLOW 33 | #define MS_NOSYMFOLLOW 256 /* Don't follow symlinks */ 34 | #endif 35 | #ifndef MS_NOATIME 36 | #define MS_NOATIME 0x400 /* 1024: Do not update access times. */ 37 | #endif 38 | #ifndef MS_NODIRATIME 39 | #define MS_NODIRATIME 0x800 /* 2048: Don't update directory access times */ 40 | #endif 41 | #ifndef MS_BIND 42 | #define MS_BIND 0x1000 /* 4096: Mount existing tree also elsewhere */ 43 | #endif 44 | #ifndef MS_MOVE 45 | #define MS_MOVE 0x2000 /* 8192: Atomically move tree */ 46 | #endif 47 | #ifndef MS_REC 48 | #define MS_REC 0x4000 /* 16384: Recursive loopback */ 49 | #endif 50 | #ifndef MS_SILENT 51 | #define MS_SILENT 0x8000 /* 32768: Don't emit certain kernel messages */ 52 | #endif 53 | #ifndef MS_UNBINDABLE 54 | #define MS_UNBINDABLE (1<<17) /* 131072: Make unbindable */ 55 | #endif 56 | #ifndef MS_PRIVATE 57 | #define MS_PRIVATE (1<<18) /* 262144: Make private */ 58 | #endif 59 | #ifndef MS_SLAVE 60 | #define MS_SLAVE (1<<19) /* 524288: Make slave */ 61 | #endif 62 | #ifndef MS_SHARED 63 | #define MS_SHARED (1<<20) /* 1048576: Make shared */ 64 | #endif 65 | #ifndef MS_RELATIME 66 | #define MS_RELATIME (1<<21) /* 2097152: Update atime relative to mtime/ctime */ 67 | #endif 68 | #ifndef MS_I_VERSION 69 | #define MS_I_VERSION (1<<23) /* Update the inode I_version field */ 70 | #endif 71 | #ifndef MS_STRICTATIME 72 | #define MS_STRICTATIME (1<<24) /* Always perform atime updates */ 73 | #endif 74 | #ifndef MS_LAZYTIME 75 | #define MS_LAZYTIME (1<<25) /* Update the on-disk [acm]times lazily */ 76 | #endif 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /tools/gen-multicall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | LC_ALL=C ; export LC_ALL 4 | 5 | P="$1" 6 | p=`echo $P | tr - _` 7 | 8 | echo '/* ISC license. */' 9 | echo 10 | echo '#include ' 11 | echo 12 | { echo '#include ' ; echo '#include ' ; cat src/$P/*.c | grep '^#include <' | grep -vF -e ' 17 | 18 | #include 19 | 20 | #include <$P/config.h> 21 | #include "s6ps.h" 22 | 23 | typedef int emain_func (int, char const *const *, char const *const *) ; 24 | typedef emain_func *emain_func_ref ; 25 | 26 | typedef struct multicall_app_s multicall_app, *multicall_app_ref ; 27 | struct multicall_app_s 28 | { 29 | char const *name ; 30 | emain_func_ref mainf ; 31 | } ; 32 | 33 | EOF 34 | 35 | for i in `ls -1 src/$P/deps-exe` ; do 36 | j=`echo $i | tr - _` 37 | echo 38 | grep -v '^#include ' < src/$P/${i}.c | grep -vF '/* ISC license. */' | sed -e "s/int main (.*)$/int ${j}_main (int argc, char const *const *argv, char const *const *envp)/" 39 | echo 40 | echo '#undef USAGE' 41 | echo '#undef dieusage' 42 | echo '#undef dienomem' 43 | done 44 | 45 | cat <mainf))(argc-1, argv+1, envp) ; 72 | } 73 | 74 | int main (int argc, char const *const *argv, char const *const *envp) 75 | { 76 | multicall_app const *p ; 77 | char const *name = strrchr(argv[0], '/') ; 78 | if (name) name++ ; else name = argv[0] ; 79 | p = bsearch(name, multicall_apps, sizeof(multicall_apps) / sizeof(multicall_app), sizeof(multicall_app), &str_bcmp) ; 80 | return p ? (*(p->mainf))(argc, argv, envp) : ${p}_main(argc, argv, envp) ; 81 | } 82 | EOF 83 | -------------------------------------------------------------------------------- /tools/gen-dotpc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | isunique () { 4 | x=$1 5 | set -- $2 6 | while test "$#" -gt 0 ; do 7 | if test "$x" = "$1" ; then 8 | return 1 9 | fi 10 | shift 11 | done 12 | return 0 13 | } 14 | 15 | uniqit () { 16 | res= 17 | while test "$#" -gt 0 ; do 18 | if isunique "$1" "$res" ; then 19 | res="${res}${res:+ }${1}" 20 | fi 21 | shift 22 | done 23 | printf %s\\n "$res" 24 | } 25 | 26 | filterout () { 27 | res= 28 | filter="$1" 29 | shift 30 | while test "$#" -gt 0 ; do 31 | if isunique "$1" "$filter" ; then 32 | res="${res}${res:+ }${1}" 33 | fi 34 | shift 35 | done 36 | printf %s\\n "$res" 37 | } 38 | 39 | print_requires () { 40 | line= 41 | oldifs="$IFS" 42 | while IFS=" " read condvar usedinlibs pkg ver libs ; do 43 | IFS="$oldifs" 44 | for h ; do 45 | i=lib${h##-l} 46 | for j in $libs ; do 47 | if test "$i" = "$j" ; then 48 | line="${line}${line:+, }${i} >= ${ver}" 49 | fi 50 | done 51 | done 52 | done < package/deps-build 53 | IFS="$oldifs" 54 | echo "Requires: $line" 55 | } 56 | 57 | . package/info 58 | 59 | ilist= 60 | dlist= 61 | slist= 62 | 63 | if test "${includedir}" != /usr/include ; then 64 | ilist="-I${includedir}" 65 | fi 66 | if test -n "${extra_includedirs}" ; then 67 | ilist="${ilist}${ilist:+ }${extra_includedirs}" 68 | fi 69 | ilist=`uniqit ${ilist}` 70 | 71 | if test "${dynlibdir}" != /usr/lib && test "${dynlibdir}" != /lib ; then 72 | dlist="-L${dynlibdir}" 73 | fi 74 | 75 | if test "${libdir}" != /usr/lib && test "${libdir}" != /lib ; then 76 | slist="-L${libdir}" 77 | fi 78 | if test -n "${extra_libdirs}" ; then 79 | slist="${slist}${slist:+ }${extra_libdirs}" 80 | fi 81 | slist="$(filterout "${dlist}" $(uniqit ${slist}))" 82 | 83 | echo "prefix=${prefix}" 84 | echo "includedir=${includedir}" 85 | echo "libdir=${libdir}" 86 | echo "dynlibdir=${dynlibdir}" 87 | echo 88 | echo "Name: lib${library}" 89 | echo "Version: ${version}" 90 | echo "Description: ${description:-The ${library} library.}" 91 | echo "URL: ${url:-https://skarnet.org/software/${package}/}" 92 | if test -n "${extra_libs}" ; then 93 | print_requires ${extra_libs} 94 | fi 95 | if test -n "$ilist" ; then 96 | echo "Cflags: ${ilist}" 97 | fi 98 | echo "Libs: ${dlist}${dlist:+ }-l${library}${ldlibs:+ }${ldlibs}" 99 | if test -n "${extra_libs}" ; then 100 | echo "Libs.private: ${slist}${slist:+ }${extra_libs}" 101 | fi 102 | -------------------------------------------------------------------------------- /doc/s6-logwatch.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-linux-utils: the s6-logwatch program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-linux-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-logwatch program

20 | 21 |

22 | s6-logwatch watches the current file of a logdir, printing it 23 | in real time. 24 |

25 | 26 |

Interface

27 | 28 |
29 |      s6-logwatch [ -m buflen ] logdir
30 | 
31 | 32 |
    33 |
  • s6-logwatch prints logdir/current and watches 34 | the file.
  • 35 |
  • logdir must be managed by a 36 | s6-log instance.
  • 37 |
  • When new logs are appended to the current file, s6-logwatch prints 38 | them in real-time to stdout.
  • 39 |
  • When a rotation happens, s6-logwatch notices, and keeps watching the 40 | new current file.
  • 41 |
  • s6-logwatch runs forever until killed.
  • 42 |
43 | 44 |

Options

45 | 46 |
    47 |
  • -m buflen : accumulate at most buflen 48 | bytes into the stdout buffer before flushing it. By default, buflen is 49 | 4000.
  • 50 |
51 | 52 |

Bugs

53 | 54 |
    55 |
  • s6-logwatch is not entirely reliable because there is an unavoidable 56 | race condition when a rotation occurs; it's a hack for humans to keep reading 57 | logs across rotations, not a tool to be used in safe programming. When the 58 | race condition is triggered, s6-logwatch will be unable to understand what 59 | state logdir is in and will exit 101 with an error message.
  • 60 |
  • Specific support in the logger program would be needed to avoid this 61 | race condition; it would significantly bloat the logger program, so it has 62 | not been deemed useful.
  • 63 |
64 | 65 |

Notes

66 | 67 |
    68 |
  • s6-logwatch is Linux-specific because it uses the 69 | inotify interface.
  • 70 |
71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /doc/s6-mount.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-linux-utils: the s6-mount program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-linux-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-mount program

20 | 21 |

22 | s6-mount mounts filesystems. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-mount -a [ -z fstab ]
29 |      s6-mount [ -n ] [ -r | -w ] [ -t fstype ] [ -o option[,option...] ] device mntpoint
30 | 
31 | 32 |
    33 |
  • s6-mount -a mounts all partitions according to /etc/fstab.
  • 34 |
  • If the -a option is not given, 35 | s6-mount mounts device on mntpoint.
  • 36 |
  • s6-mount does not touch /etc/mtab.
  • 37 |
38 | 39 |

Exit codes

40 | 41 |
    42 |
  • 0: success
  • 43 |
  • 1: mount() returned -EBUSY — most likely, the filesystem is already mounted
  • 44 |
  • 100: wrong usage
  • 45 |
  • 111: system call failed
  • 46 |
  • n: s6-mount -a was called, and n fstab entries couldn't be mounted
  • 47 |
48 | 49 |

Options

50 | 51 |
    52 |
  • -a : process /etc/fstab instead of command 53 | line arguments
  • 54 |
  • -z fstab : read file at fstab 55 | instead of /etc/fstab
  • 56 |
  • -n : ignored 57 |
  • -t fstype : filesystem is of type fstype. 58 | You probably need to specify this.
  • 59 |
  • -r : mount read-only
  • 60 |
  • -w : mount read-write (default)
  • 61 |
  • -o option : mount with option option. 62 | Currently recognized options: defaults, ro, rw, remount, sync, async, 63 | nodev, dev, noexec, exec, nosuid, suid, noatime, atime, nodiratime, diratime, 64 | bind, nobind, move, nomove. Unrecognized options are given directly to the kernel.
  • 65 |
66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/libs6ps/s6ps_wchan.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "s6ps.h" 12 | 13 | int s6ps_wchan_init (s6ps_wchan_t *w, char const *file) 14 | { 15 | if (file) 16 | { 17 | if (!openslurpclose(&w->sysmap, file)) return 0 ; 18 | } 19 | else 20 | { 21 | char *files[3] = { "/proc/kallsyms", 0, "/boot/System.map" } ; 22 | struct utsname uts ; 23 | size_t n ; 24 | if (uname(&uts) < 0) return 0 ; 25 | n = strlen(uts.release) ; 26 | { 27 | char buf[18 + n] ; 28 | unsigned int i = 0 ; 29 | memcpy(buf, "/boot/System.map", 16) ; 30 | buf[16] = '-' ; 31 | memcpy(buf + 17, uts.release, n + 1) ; 32 | files[1] = buf ; 33 | for (; i < 3 ; i++) 34 | if (openslurpclose(&w->sysmap, files[i])) break ; 35 | if (i >= 3) return 0 ; 36 | } 37 | } 38 | { 39 | size_t i = 0 ; 40 | if (!genalloc_append(size_t, &w->ind, &i)) goto err2 ; 41 | for (i = 1 ; i <= w->sysmap.len ; i++) 42 | if (w->sysmap.s[i-1] == '\n') 43 | if (!genalloc_append(size_t, &w->ind, &i)) goto err ; 44 | } 45 | return 1 ; 46 | err: 47 | genalloc_free(size_t, &w->ind) ; 48 | err2: 49 | stralloc_free(&w->sysmap) ; 50 | return 0 ; 51 | } 52 | 53 | void s6ps_wchan_finish (s6ps_wchan_t *w) 54 | { 55 | genalloc_free(size_t, &w->ind) ; 56 | stralloc_free(&w->sysmap) ; 57 | } 58 | 59 | static inline size_t lookup (s6ps_wchan_t const *w, uint64_t addr, size_t *i) 60 | { 61 | size_t low = 0, mid, high = genalloc_len(size_t, &w->ind), len ; 62 | for (;;) 63 | { 64 | uint64_t cur ; 65 | mid = (low + high) >> 1 ; 66 | len = uint64_xscan(w->sysmap.s + genalloc_s(size_t, &w->ind)[mid], &cur) ; 67 | if (!len) return 0 ; 68 | if (cur == addr) break ; 69 | if (mid == low) return 0 ; 70 | if (addr < cur) high = mid ; else low = mid ; 71 | } 72 | *i = mid ; 73 | return len ; 74 | } 75 | 76 | int s6ps_wchan_lookup (s6ps_wchan_t const *w, stralloc *sa, uint64_t addr) 77 | { 78 | if (addr == (sizeof(void *) == 8 ? 0xffffffffffffffffULL : 0xffffffffUL)) 79 | return stralloc_catb(sa, "*", 1) ; 80 | if (!addr) return stralloc_catb(sa, "-", 1) ; 81 | if (w->sysmap.len) 82 | { 83 | size_t i, pos, len = lookup(w, addr, &i) ; 84 | if (!len) return stralloc_catb(sa, "?", 1) ; 85 | pos = genalloc_s(size_t, &w->ind)[i] + len + 3 ; 86 | return stralloc_catb(sa, w->sysmap.s + pos, genalloc_s(size_t, &w->ind)[i+1] - 1 - pos) ; 87 | } 88 | if (!stralloc_readyplus(sa, UINT64_FMT + 3)) return 0 ; 89 | stralloc_catb(sa, "(0x", 3) ; 90 | sa->len += uint64_fmt(sa->s + sa->len, addr) ; 91 | stralloc_catb(sa, ")", 1) ; 92 | return 1 ; 93 | } 94 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | Changelog for s6-linux-utils. 2 | 3 | In 2.6.4.0 4 | ---------- 5 | 6 | - Bugfixes. 7 | - Support of shared libraries on MacOS. 8 | - New binary: fstab2s6rc. 9 | 10 | 11 | In 2.6.3.0 12 | ---------- 13 | 14 | - Bugfixes. 15 | - pkg-config support. 16 | 17 | 18 | In 2.6.2.1 19 | ---------- 20 | 21 | - Align configure script to the rest of skaware. 22 | 23 | 24 | In 2.6.2.0 25 | ---------- 26 | 27 | - Bugfixes. 28 | - s6-ps now supports minflt, cminflt, majflt, cmajflt. 29 | 30 | 31 | In 2.6.1.2 32 | ---------- 33 | 34 | - Bugfixes. 35 | 36 | 37 | In 2.6.1.1 38 | ---------- 39 | 40 | - Bugfixes. 41 | 42 | 43 | In 2.6.1.0 44 | ---------- 45 | 46 | - s6-mount: modernize option support. 47 | - New multicall binary: s6-linux-utils. 48 | 49 | 50 | In 2.6.0.1 51 | ---------- 52 | 53 | - Adaptation to skalibs-2.13.0.0. 54 | 55 | 56 | In 2.6.0.0 57 | ---------- 58 | 59 | - Adaptation to skalibs-2.12.0.0. 60 | - s6-fillurandompool removed. 61 | - New program: rngseed, replacing s6-fillurandompool, with 62 | a lot more features. 63 | 64 | 65 | In 2.5.1.7 66 | ---------- 67 | 68 | - Bugfixes. 69 | 70 | 71 | In 2.5.1.6 72 | ---------- 73 | 74 | - Adaptation to skalibs-2.11.0.0. 75 | 76 | 77 | In 2.5.1.5 78 | ---------- 79 | 80 | - Bugfixes. 81 | 82 | 83 | In 2.5.1.4 84 | ---------- 85 | 86 | - Bugfixes. 87 | - Version that works with skalibs-2.10.0.0. 88 | 89 | 90 | In 2.5.1.3 91 | ---------- 92 | 93 | - Bugfixes. 94 | 95 | 96 | In 2.5.1.2 97 | ---------- 98 | 99 | - Bugfixes. 100 | 101 | 102 | In 2.5.1.1 103 | ---------- 104 | 105 | - Bugfixes. 106 | 107 | 108 | In 2.5.1.0 109 | ---------- 110 | 111 | - Adaptation to skalibs-2.9.0.0. 112 | 113 | 114 | In 2.5.0.1 115 | ---------- 116 | 117 | - Build fix for clang. 118 | - Adaptation to skalibs-2.8.0.0. 119 | - Everything now builds as PIC by default. 120 | 121 | 122 | In 2.5.0.0 123 | ---------- 124 | 125 | - Optional nsss support. 126 | - s6-devd, s6-uevent-listener, s6-uevent-spawner removed. 127 | 128 | 129 | In 2.4.0.2 130 | ---------- 131 | 132 | - s6-logwatch rewrite. 133 | - Better portability with old glibc versions. 134 | - s6-uevent-listener and s6-uevent-spawner are marked as 135 | deprecated. (The mdevd package obsoletes them.) 136 | 137 | 138 | In 2.4.0.1 139 | ---------- 140 | 141 | - Adaptation to skalibs-2.6.0.0. The chain-loading programs have 142 | changed exit codes when they fail to execute into another program. 143 | 144 | 145 | In 2.4.0.0 146 | ---------- 147 | 148 | - Linux dependency bumped to 3.5, because the /proc format changed. 149 | things *may* work with older kernels, but it's likely that s6-ps 150 | will not. 151 | - s6-uevent-listener now writes events to stdout instead of spawning 152 | a program itself. s6-uevent-spawner now reads on stdin. Instead of 153 | running "s6-uevent-listener s6-uevent-spawner mdev", people now run 154 | "s6-uevent-listener | s6-uevent-spawner mdev". 155 | - s6-devd API unchanged: it hides the details. 156 | 157 | 158 | In 2.3.0.0 159 | ---------- 160 | 161 | - Added this NEWS file. :) 162 | - Major types overhaul to make them more POSIXly correct: 163 | compatibility with skalibs-2.5.0.0. 164 | 165 | -------------------------------------------------------------------------------- /src/libs6ps/s6ps_otree.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include "s6ps.h" 8 | 9 | typedef struct ptreeiter_s ptreeiter_t, *ptreeiter_t_ref ; 10 | struct ptreeiter_s 11 | { 12 | unsigned int *childlist ; 13 | unsigned int const *childindex ; 14 | unsigned int const *ppindex ; 15 | unsigned int *cpos ; 16 | } ; 17 | 18 | typedef struct pstuff_s pstuff_t, *pstuff_t_ref ; 19 | struct pstuff_s 20 | { 21 | unsigned int *orderedlist ; 22 | pscan_t *p ; 23 | unsigned int const *childlist ; 24 | unsigned int const *childindex ; 25 | unsigned int const *nchild ; 26 | } ; 27 | 28 | static int fillchildlist (unsigned int i, unsigned int h, void *x) 29 | { 30 | ptreeiter_t *pt = x ; 31 | unsigned int j = pt->ppindex[i] ; 32 | pt->childlist[pt->childindex[j] + pt->cpos[j]++] = i ; 33 | (void)h ; 34 | return 1 ; 35 | } 36 | 37 | static void fillo_tree_rec (pstuff_t *blah, unsigned int root, signed int h) 38 | { 39 | static unsigned int j = 0 ; 40 | unsigned int i = !blah->p[root].pid ; 41 | if (blah->p[root].pid == 1) h = -1 ; 42 | blah->p[root].height = (h > 0) ? h : 0 ; 43 | blah->orderedlist[j++] = root ; 44 | for (; i < blah->nchild[root] ; i++) 45 | fillo_tree_rec(blah, blah->childlist[blah->childindex[root] + i], h+1) ; 46 | } 47 | 48 | /* 49 | Fills up orderedlist with the right indices to print a process tree. 50 | O(n log n) time, O(n) space, all in the stack. 51 | */ 52 | 53 | void s6ps_otree (pscan_t *p, unsigned int n, avltreen *pidtree, unsigned int *orderedlist) 54 | { 55 | unsigned int childlist[n] ; 56 | unsigned int childindex[n] ; 57 | unsigned int nchild[n] ; 58 | unsigned int i = 0 ; 59 | for (; i < n ; i++) nchild[i] = 0 ; 60 | 61 | /* Compute the ppid tree */ 62 | for (i = 0 ; i < n ; i++) 63 | { 64 | uint32_t k ; 65 | if (!avltreen_search(pidtree, &p[i].ppid, &k)) k = n-1 ; 66 | orderedlist[i] = k ; /* using orderedlist as ppindex */ 67 | nchild[k]++ ; 68 | } 69 | { 70 | unsigned int j = 0 ; 71 | for (i = 0 ; i < n ; i++) 72 | { 73 | childindex[i] = j ; 74 | j += nchild[i] ; 75 | } 76 | } 77 | 78 | /* Fill the childlist by increasing pids so it is sorted */ 79 | { 80 | unsigned int cpos[n] ; 81 | ptreeiter_t blah = { .childlist = childlist, .childindex = childindex, .ppindex = orderedlist, .cpos = cpos } ; 82 | for (i = 0 ; i < n ; i++) cpos[i] = 0 ; 83 | avltreen_iter_nocancel(pidtree, avltreen_totalsize(pidtree), &fillchildlist, &blah) ; 84 | } 85 | 86 | /* If we have init, make it the last in the orphan list */ 87 | if (n > 1 && p[childlist[childindex[n-1]+1]].pid == 1) 88 | { 89 | unsigned int pos1 = childlist[childindex[n-1] + 1] ; 90 | for (i = 2 ; i < nchild[n-1] ; i++) 91 | childlist[childindex[n-1]+i-1] = childlist[childindex[n-1]+i] ; 92 | childlist[childindex[n-1]+nchild[n-1]-1] = pos1 ; 93 | } 94 | 95 | /* Finally, fill orderedlist by walking the childindex tree. */ 96 | { 97 | pstuff_t blah = { .orderedlist = orderedlist, .p = p, .childlist = childlist, .childindex = childindex, .nchild = nchild } ; 98 | fillo_tree_rec(&blah, n-1, -1) ; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /tools/gen-deps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | . package/info 4 | 5 | echo '#' 6 | echo '# This file has been generated by tools/gen-deps.sh' 7 | echo '#' 8 | echo 9 | 10 | internal_libs= 11 | 12 | for dir in src/include/${package} src/* ; do 13 | for file in $(ls -1 $dir | grep -- \\.h$) ; do 14 | { 15 | grep -F -- "#include <${package}/" < ${dir}/$file | cut -d'<' -f2 | cut -d'>' -f1 ; 16 | grep -- '#include ".*\.h"' < ${dir}/$file | cut -d'"' -f2 17 | } | sort -u | { 18 | deps= 19 | while read dep ; do 20 | if echo $dep | grep -q "^${package}/" ; then 21 | deps="$deps src/include/$dep" 22 | elif test -f "${dir}/$dep" ; then 23 | deps="$deps ${dir}/$dep" 24 | else 25 | deps="$deps src/include-local/$dep" 26 | fi 27 | done 28 | if test -n "$deps" ; then 29 | echo "${dir}/${file}:${deps}" 30 | fi 31 | } 32 | done 33 | done 34 | 35 | for dir in src/* ; do 36 | for file in $(ls -1 $dir | grep -- \\.c$) ; do 37 | { 38 | grep -F -- "#include <${package}/" < ${dir}/$file | cut -d'<' -f2 | cut -d'>' -f1 ; 39 | grep -- '#include ".*\.h"' < ${dir}/$file | cut -d'"' -f2 40 | } | sort -u | { 41 | deps=" ${dir}/$file" 42 | while read dep ; do 43 | if echo $dep | grep -q "^${package}/" ; then 44 | deps="$deps src/include/$dep" 45 | elif test -f "${dir}/$dep" ; then 46 | deps="$deps ${dir}/$dep" 47 | else 48 | deps="$deps src/include-local/$dep" 49 | fi 50 | done 51 | o=$(echo $file | sed s/\\.c$/.o/) 52 | lo=$(echo $file | sed s/\\.c$/.lo/) 53 | echo "${dir}/${o} ${dir}/${lo}:${deps}" 54 | } 55 | done 56 | done 57 | echo 58 | 59 | for dir in $(ls -1 src | grep -v ^include) ; do 60 | for file in $(ls -1 src/$dir/deps-lib) ; do 61 | deps= 62 | libs= 63 | while read dep ; do 64 | if echo $dep | grep -q -e '^\${LIB' -e '^-l' -e '^\${.*_LIB}' ; then 65 | libs="$libs $dep" 66 | else 67 | deps="$deps src/$dir/$dep" 68 | fi 69 | done < src/$dir/deps-lib/$file 70 | echo 'ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),)' 71 | echo "lib${file}.a.xyzzy:${deps}" 72 | echo else 73 | echo "lib${file}.a.xyzzy:$(echo ${deps} | sed 's/\.o/.lo/g')" 74 | echo endif 75 | if grep -qE "^LIB_DEFS [+:]= .*=$file" package/targets.mak ; then 76 | echo "lib${file}.pc: EXTRA_LIBS :=${libs}" 77 | echo "lib${file}.so.xyzzy: EXTRA_LIBS :=$libs" 78 | echo "lib${file}.so.xyzzy:$(echo ${deps} | sed 's/\.o/.lo/g')" 79 | echo "lib${file}.dylib.xyzzy: EXTRA_LIBS :=$libs" 80 | echo "lib${file}.dylib.xyzzy:$(echo ${deps} | sed 's/\.o/.lo/g')" 81 | else 82 | internal_libs="$internal_libs lib${file}.a.xyzzy" 83 | fi 84 | done 85 | 86 | for file in $(ls -1 src/$dir/deps-exe) ; do 87 | deps= 88 | libs= 89 | while read dep ; do 90 | if echo $dep | grep -q \\.o$ ; then 91 | dep="src/$dir/$dep" 92 | fi 93 | if echo $dep | grep -qx '\${.*_LIB}' ; then 94 | libs="$libs $dep" 95 | else 96 | deps="$deps $dep" 97 | fi 98 | done < src/$dir/deps-exe/$file 99 | echo "$file: EXTRA_LIBS :=$libs" 100 | echo "$file: src/$dir/$file.o$deps" 101 | done 102 | done 103 | echo "INTERNAL_LIBS :=$internal_libs" 104 | -------------------------------------------------------------------------------- /src/libs6ps/s6ps_ttycache.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "s6ps.h" 19 | #include "s6ps-internal.h" 20 | 21 | static int check (char const *s, dev_t ttynr) 22 | { 23 | struct stat st ; 24 | if (stat(s, &st) < 0) return 0 ; 25 | return S_ISCHR(st.st_mode) && (st.st_rdev == ttynr) ; 26 | } 27 | 28 | 29 | /* No blind scanning of all /dev or /sys/devices, kthx */ 30 | 31 | static int ttyguess (stralloc *sa, dev_t ttynr) 32 | { 33 | unsigned int maj = major(ttynr), min = minor(ttynr) ; 34 | 35 | /* Try /dev/tty? and /dev/pts/? */ 36 | if (maj == 4 && min < 64) 37 | { 38 | char tmp[11] = "/dev/tty" ; 39 | tmp[uint_fmt(tmp+8, min)] = 0 ; 40 | if (check(tmp, ttynr)) return stralloc_cats(sa, tmp+5) && stralloc_0(sa) ; 41 | } 42 | else if (maj >= 136 && maj < 144) 43 | { 44 | unsigned int n = ((maj - 136) << 20) | min ; 45 | char tmp[9 + UINT_FMT] = "/dev/pts/" ; 46 | tmp[9 + uint_fmt(tmp+9, n)] = 0 ; 47 | if (check(tmp, ttynr)) return stralloc_cats(sa, tmp+5) && stralloc_0(sa) ; 48 | } 49 | 50 | /* Use /sys/dev/char/maj:min if it exists */ 51 | { 52 | int fd ; 53 | size_t pos = 14 ; 54 | char path[23 + 2 * UINT_FMT] = "/sys/dev/char/" ; 55 | pos += uint_fmt(path + pos, maj) ; 56 | path[pos++] = ':' ; 57 | pos += uint_fmt(path + pos, min) ; 58 | memcpy(path + pos, "/uevent", 8) ; 59 | fd = open_read(path) ; 60 | if (fd >= 0) 61 | { 62 | char buf[4097] ; 63 | buffer b = BUFFER_INIT(&fd_readv, fd, buf, 4097) ; 64 | size_t start = satmp.len ; 65 | int r ; 66 | for (;;) 67 | { 68 | satmp.len = start ; 69 | r = skagetln(&b, &satmp, '\n') ; 70 | if (r <= 0) break ; 71 | if ((satmp.len - start) > 8 && !memcmp(satmp.s + start, "DEVNAME=", 8)) break ; 72 | } 73 | fd_close(fd) ; 74 | if (r > 0) 75 | { 76 | satmp.s[satmp.len - 1] = 0 ; 77 | satmp.len = start ; 78 | memcpy(satmp.s + start + 3, "/dev/", 5) ; 79 | if (check(satmp.s + start + 3, ttynr)) 80 | return stralloc_cats(sa, satmp.s + start + 8) && stralloc_0(sa) ; 81 | } 82 | } 83 | } 84 | 85 | /* Fallback: print explicit maj:min */ 86 | { 87 | size_t pos = 1 ; 88 | char tmp[3 + 2 * UINT_FMT] = "(" ; 89 | pos += uint_fmt(tmp + pos, maj) ; 90 | tmp[pos++] = ':' ; 91 | pos += uint_fmt(tmp + pos, min) ; 92 | tmp[pos++] = ')' ; 93 | tmp[pos++] = 0 ; 94 | return stralloc_catb(sa, tmp, pos) ; 95 | } 96 | } 97 | 98 | int s6ps_ttycache_lookup (s6ps_cache_t *cache, stralloc *sa, dev_t ttynr) 99 | { 100 | dius_t d = { .left = (uint32_t)ttynr, .right = satmp.len } ; 101 | uint32_t i ; 102 | if (!avltree_search(&cache->tree, &d.left, &i)) 103 | { 104 | size_t n = genalloc_len(dius_t, &cache->index) ; 105 | if (!ttyguess(&satmp, ttynr)) return 0 ; 106 | if (!genalloc_append(dius_t, &cache->index, &d)) goto err ; 107 | if (!avltree_insert(&cache->tree, n)) 108 | { 109 | genalloc_setlen(dius_t, &cache->index, n) ; 110 | goto err ; 111 | } 112 | i = n ; 113 | } 114 | return stralloc_cats(sa, satmp.s + genalloc_s(dius_t, &cache->index)[i].right) ; 115 | err: 116 | satmp.len = d.right ; 117 | return 0 ; 118 | } 119 | -------------------------------------------------------------------------------- /package/deps.mak: -------------------------------------------------------------------------------- 1 | # 2 | # This file has been generated by tools/gen-deps.sh 3 | # 4 | 5 | src/libs6ps/s6ps_cache.o src/libs6ps/s6ps_cache.lo: src/libs6ps/s6ps_cache.c src/libs6ps/s6ps-internal.h src/include-local/s6ps.h 6 | src/libs6ps/s6ps_grcache.o src/libs6ps/s6ps_grcache.lo: src/libs6ps/s6ps_grcache.c src/libs6ps/s6ps-internal.h src/include-local/s6ps.h 7 | src/libs6ps/s6ps_otree.o src/libs6ps/s6ps_otree.lo: src/libs6ps/s6ps_otree.c src/include-local/s6ps.h 8 | src/libs6ps/s6ps_pfield.o src/libs6ps/s6ps_pfield.lo: src/libs6ps/s6ps_pfield.c src/include-local/s6ps.h 9 | src/libs6ps/s6ps_pwcache.o src/libs6ps/s6ps_pwcache.lo: src/libs6ps/s6ps_pwcache.c src/libs6ps/s6ps-internal.h src/include-local/s6ps.h 10 | src/libs6ps/s6ps_statparse.o src/libs6ps/s6ps_statparse.lo: src/libs6ps/s6ps_statparse.c src/include-local/s6ps.h 11 | src/libs6ps/s6ps_ttycache.o src/libs6ps/s6ps_ttycache.lo: src/libs6ps/s6ps_ttycache.c src/libs6ps/s6ps-internal.h src/include-local/s6ps.h 12 | src/libs6ps/s6ps_wchan.o src/libs6ps/s6ps_wchan.lo: src/libs6ps/s6ps_wchan.c src/include-local/s6ps.h 13 | src/multicall/s6-linux-utils.o src/multicall/s6-linux-utils.lo: src/multicall/s6-linux-utils.c src/include/s6-linux-utils/config.h src/include-local/s6ps.h 14 | src/s6-linux-utils/fstab2s6rc.o src/s6-linux-utils/fstab2s6rc.lo: src/s6-linux-utils/fstab2s6rc.c src/include/s6-linux-utils/config.h 15 | 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 16 | src/s6-linux-utils/s6-chroot.o src/s6-linux-utils/s6-chroot.lo: src/s6-linux-utils/s6-chroot.c 17 | src/s6-linux-utils/s6-freeramdisk.o src/s6-linux-utils/s6-freeramdisk.lo: src/s6-linux-utils/s6-freeramdisk.c 18 | src/s6-linux-utils/s6-hostname.o src/s6-linux-utils/s6-hostname.lo: src/s6-linux-utils/s6-hostname.c 19 | src/s6-linux-utils/s6-logwatch.o src/s6-linux-utils/s6-logwatch.lo: src/s6-linux-utils/s6-logwatch.c 20 | 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 21 | src/s6-linux-utils/s6-pivotchroot.o src/s6-linux-utils/s6-pivotchroot.lo: src/s6-linux-utils/s6-pivotchroot.c 22 | src/s6-linux-utils/s6-ps.o src/s6-linux-utils/s6-ps.lo: src/s6-linux-utils/s6-ps.c src/include-local/s6ps.h 23 | src/s6-linux-utils/s6-swapoff.o src/s6-linux-utils/s6-swapoff.lo: src/s6-linux-utils/s6-swapoff.c 24 | src/s6-linux-utils/s6-swapon.o src/s6-linux-utils/s6-swapon.lo: src/s6-linux-utils/s6-swapon.c 25 | src/s6-linux-utils/s6-umount.o src/s6-linux-utils/s6-umount.lo: src/s6-linux-utils/s6-umount.c 26 | 27 | ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),) 28 | libs6ps.a.xyzzy: src/libs6ps/s6ps_cache.o src/libs6ps/s6ps_grcache.o src/libs6ps/s6ps_otree.o src/libs6ps/s6ps_pfield.o src/libs6ps/s6ps_pwcache.o src/libs6ps/s6ps_statparse.o src/libs6ps/s6ps_ttycache.o src/libs6ps/s6ps_wchan.o 29 | else 30 | libs6ps.a.xyzzy:src/libs6ps/s6ps_cache.lo src/libs6ps/s6ps_grcache.lo src/libs6ps/s6ps_otree.lo src/libs6ps/s6ps_pfield.lo src/libs6ps/s6ps_pwcache.lo src/libs6ps/s6ps_statparse.lo src/libs6ps/s6ps_ttycache.lo src/libs6ps/s6ps_wchan.lo 31 | endif 32 | s6-linux-utils: EXTRA_LIBS := ${SYSCLOCK_LIB} ${MAYBEPTHREAD_LIB} 33 | s6-linux-utils: src/multicall/s6-linux-utils.o libs6ps.a.xyzzy ${LIBNSSS} -lskarnet 34 | fstab2s6rc: EXTRA_LIBS := 35 | fstab2s6rc: src/s6-linux-utils/fstab2s6rc.o -lskarnet 36 | rngseed: EXTRA_LIBS := ${SYSCLOCK_LIB} 37 | rngseed: src/s6-linux-utils/rngseed.o -lskarnet 38 | s6-chroot: EXTRA_LIBS := 39 | s6-chroot: src/s6-linux-utils/s6-chroot.o -lskarnet 40 | s6-freeramdisk: EXTRA_LIBS := 41 | s6-freeramdisk: src/s6-linux-utils/s6-freeramdisk.o -lskarnet 42 | s6-hostname: EXTRA_LIBS := 43 | s6-hostname: src/s6-linux-utils/s6-hostname.o -lskarnet 44 | s6-logwatch: EXTRA_LIBS := 45 | s6-logwatch: src/s6-linux-utils/s6-logwatch.o -lskarnet 46 | s6-mount: EXTRA_LIBS := 47 | s6-mount: src/s6-linux-utils/s6-mount.o -lskarnet 48 | s6-pivotchroot: EXTRA_LIBS := 49 | s6-pivotchroot: src/s6-linux-utils/s6-pivotchroot.o -lskarnet 50 | s6-ps: EXTRA_LIBS := ${MAYBEPTHREAD_LIB} 51 | s6-ps: src/s6-linux-utils/s6-ps.o libs6ps.a.xyzzy ${LIBNSSS} -lskarnet 52 | s6-swapoff: EXTRA_LIBS := 53 | s6-swapoff: src/s6-linux-utils/s6-swapoff.o -lskarnet 54 | s6-swapon: EXTRA_LIBS := 55 | s6-swapon: src/s6-linux-utils/s6-swapon.o -lskarnet 56 | s6-umount: EXTRA_LIBS := 57 | s6-umount: src/s6-linux-utils/s6-umount.o -lskarnet 58 | INTERNAL_LIBS := libs6ps.a.xyzzy 59 | -------------------------------------------------------------------------------- /src/libs6ps/s6ps_statparse.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "s6ps.h" 13 | 14 | 15 | /* 16 | going to great lengths to avoid scanf(), but all this code 17 | is still smaller than scanf (no floating point parsing etc.) 18 | */ 19 | 20 | #define STATVARS 49 21 | 22 | typedef size_t pscan_func (char const *, void *) ; 23 | typedef pscan_func *pscan_func_ref ; 24 | 25 | static size_t f64 (char const *s, void *u64) 26 | { 27 | uint64_t *u = u64 ; 28 | return uint64_scan(s, u) ; 29 | } 30 | 31 | #define DEFUNU(name, type) \ 32 | static size_t name (char const *s, void *p) \ 33 | { \ 34 | uint64_t u ; \ 35 | size_t len = uint64_scan(s, &u) ; \ 36 | *(type *)p = u ; \ 37 | return len ; \ 38 | } \ 39 | 40 | #define DEFUNS(name, type) \ 41 | static size_t name (char const *s, void *p) \ 42 | { \ 43 | int64_t d ; \ 44 | size_t len = int64_scan(s, &d) ; \ 45 | *(type *)p = d ; \ 46 | return len ; \ 47 | } \ 48 | 49 | DEFUNS(fint, int) 50 | DEFUNS(fpid, pid_t) 51 | DEFUNU(fdev, dev_t) 52 | 53 | static pscan_func_ref scanfuncs[STATVARS] = 54 | { 55 | &fpid, /* ppid */ 56 | &fpid, /* pgrp */ 57 | &fpid, /* session */ 58 | &fdev, /* tty_nr */ 59 | &fpid, /* tpgid */ 60 | &f64, /* flags */ 61 | &f64, /* minflt */ 62 | &f64, /* cminflt */ 63 | &f64, /* majflt */ 64 | &f64, /* cmajflt */ 65 | &f64, /* utime */ 66 | &f64, /* stime */ 67 | &f64, /* cutime */ 68 | &f64, /* cstime */ 69 | &fint, /* priority */ 70 | &fint, /* nice */ 71 | &f64, /* num_threads */ 72 | &f64, /* itrealvalue */ 73 | &f64, /* starttime */ 74 | &f64, /* vsize */ 75 | &f64, /* rss */ 76 | &f64, /* rsslim */ 77 | &f64, /* startcode */ 78 | &f64, /* endcode */ 79 | &f64, /* startstack */ 80 | &f64, /* kstkesp */ 81 | &f64, /* kstkeip */ 82 | &f64, /* signal */ 83 | &f64, /* blocked */ 84 | &f64, /* sigignore */ 85 | &f64, /* sigcatch */ 86 | &f64, /* wchan */ 87 | &f64, /* nswap */ 88 | &f64, /* cnswap */ 89 | &fint, /* exit_signal */ 90 | &f64, /* processor */ 91 | &f64, /* rt_priority */ 92 | &f64, /* policy */ 93 | &f64, /* delayacct_blkio_ticks */ 94 | &f64, /* guest_time */ 95 | &f64, /* cguest_time */ 96 | &f64, /* start_data */ 97 | &f64, /* end_data */ 98 | &f64, /* start_brk */ 99 | &f64, /* arg_start */ 100 | &f64, /* arg_end */ 101 | &f64, /* env_start */ 102 | &f64, /* env_end */ 103 | &fint /* exit_code */ 104 | } ; 105 | 106 | int s6ps_statparse (pscan_t *p) 107 | { 108 | uint64_t dummy64 ; 109 | int dummyint ; 110 | size_t pos = 0 ; 111 | void *scanresults[STATVARS] = 112 | { 113 | &p->ppid, 114 | &p->pgrp, 115 | &p->session, 116 | &p->ttynr, 117 | &p->tpgid, 118 | &dummy64, 119 | &p->minflt, 120 | &p->cminflt, 121 | &p->majflt, 122 | &p->cmajflt, 123 | &p->utime, 124 | &p->stime, 125 | &p->cutime, 126 | &p->cstime, 127 | &p->prio, 128 | &p->nice, 129 | &p->threads, 130 | &dummy64, 131 | &p->start, 132 | &p->vsize, 133 | &p->rss, 134 | &p->rsslim, 135 | &dummy64, 136 | &dummy64, 137 | &dummy64, 138 | &dummy64, 139 | &dummy64, 140 | &dummy64, 141 | &dummy64, 142 | &dummy64, 143 | &dummy64, 144 | &p->wchan, 145 | &dummy64, 146 | &dummy64, 147 | &dummy64, 148 | &p->cpuno, 149 | &p->rtprio, 150 | &p->policy, 151 | &dummy64, 152 | &dummy64, 153 | &dummy64, 154 | &dummy64, 155 | &dummy64, 156 | &dummy64, 157 | &dummy64, 158 | &dummy64, 159 | &dummy64, 160 | &dummy64, 161 | &dummyint 162 | } ; 163 | unsigned int i = 0 ; 164 | 165 | if (!p->statlen) return 0 ; 166 | pos = uint64_scan(p->data.s, &dummy64) ; 167 | if (!pos) return 0 ; 168 | if (dummy64 != p->pid) return 0 ; 169 | if (pos + 5 + p->commlen > p->statlen) return 0 ; 170 | if (p->data.s[pos++] != ' ') return 0 ; 171 | if (p->data.s[pos++] != '(') return 0 ; 172 | pos += p->commlen ; 173 | if (p->data.s[pos++] != ')') return 0 ; 174 | if (p->data.s[pos++] != ' ') return 0 ; 175 | p->state = pos++ ; 176 | for (; i < STATVARS ; i++) 177 | { 178 | size_t w ; 179 | if (pos + 1 > p->statlen) return 0 ; 180 | if (p->data.s[pos++] != ' ') return 0 ; 181 | w = (*scanfuncs[i])(p->data.s + pos, scanresults[i]) ; 182 | if (!w) return 0 ; 183 | pos += w ; 184 | } 185 | return 1 ; 186 | } 187 | -------------------------------------------------------------------------------- /src/include-local/s6ps.h: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #ifndef S6PS_H 4 | #define S6PS_H 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | typedef enum pfield_e pfield_t, *pfield_t_ref ; 17 | enum pfield_e 18 | { 19 | PFIELD_PID, 20 | PFIELD_COMM, 21 | PFIELD_STATE, 22 | PFIELD_PPID, 23 | PFIELD_PGRP, 24 | PFIELD_SESSION, 25 | PFIELD_TTY, 26 | PFIELD_TPGID, 27 | PFIELD_MINFLT, 28 | PFIELD_CMINFLT, 29 | PFIELD_MAJFLT, 30 | PFIELD_CMAJFLT, 31 | PFIELD_UTIME, 32 | PFIELD_STIME, 33 | PFIELD_CUTIME, 34 | PFIELD_CSTIME, 35 | PFIELD_PRIO, 36 | PFIELD_NICE, 37 | PFIELD_THREADS, 38 | PFIELD_START, 39 | PFIELD_VSIZE, 40 | PFIELD_RSS, 41 | PFIELD_RSSLIM, 42 | PFIELD_CPUNO, 43 | PFIELD_RTPRIO, 44 | PFIELD_RTPOLICY, 45 | PFIELD_USER, 46 | PFIELD_GROUP, 47 | PFIELD_PMEM, 48 | PFIELD_WCHAN, 49 | PFIELD_ARGS, 50 | PFIELD_ENV, 51 | PFIELD_PCPU, 52 | PFIELD_TTIME, 53 | PFIELD_CTTIME, 54 | PFIELD_TSTART, 55 | PFIELD_CPCPU, 56 | PFIELD_PHAIL 57 | } ; 58 | 59 | typedef struct pscan_s pscan_t, *pscan_t_ref ; 60 | struct pscan_s 61 | { 62 | stralloc data ; 63 | pid_t pid ; 64 | signed int height ; 65 | size_t statlen ; 66 | size_t commlen ; 67 | size_t cmdlen ; 68 | size_t envlen ; 69 | uid_t uid ; 70 | gid_t gid ; 71 | pid_t ppid ; 72 | unsigned int state ; 73 | pid_t pgrp ; 74 | pid_t session ; 75 | dev_t ttynr ; 76 | pid_t tpgid ; 77 | uint64_t minflt ; 78 | uint64_t cminflt ; 79 | uint64_t majflt ; 80 | uint64_t cmajflt ; 81 | uint64_t utime ; 82 | uint64_t stime ; 83 | uint64_t cutime ; 84 | uint64_t cstime ; 85 | int prio ; 86 | int nice ; 87 | uint64_t threads ; 88 | uint64_t start ; 89 | uint64_t vsize ; 90 | uint64_t rss ; 91 | uint64_t rsslim ; 92 | uint64_t wchan ; 93 | uint64_t cpuno ; 94 | uint64_t rtprio ; 95 | uint64_t policy ; 96 | } ; 97 | 98 | #define PSCAN_ZERO \ 99 | { \ 100 | .data = STRALLOC_ZERO, \ 101 | .pid = 0, \ 102 | .height = 0, \ 103 | .statlen = 0, \ 104 | .commlen = 0, \ 105 | .cmdlen = 0, \ 106 | .envlen = 0, \ 107 | .uid = 0, \ 108 | .gid = 0, \ 109 | .ppid = 0, \ 110 | .state = 0, \ 111 | .pgrp = 0, \ 112 | .session = 0, \ 113 | .ttynr = 0, \ 114 | .tpgid = -1, \ 115 | .minflt = 0, \ 116 | .cminflt = 0, \ 117 | .majflt = 0, \ 118 | .cmajflt = 0, \ 119 | .utime = 0, \ 120 | .stime = 0, \ 121 | .cutime = 0, \ 122 | .cstime = 0, \ 123 | .prio = 0, \ 124 | .nice = 0, \ 125 | .threads = 0, \ 126 | .start = 0, \ 127 | .vsize = 0, \ 128 | .rss = 0, \ 129 | .rsslim = 0, \ 130 | .wchan = 0, \ 131 | .cpuno = 0, \ 132 | .rtprio = 0, \ 133 | .policy = 0 \ 134 | } 135 | 136 | typedef struct s6ps_cache_s s6ps_cache_t, *s6ps_cache_t_ref ; 137 | struct s6ps_cache_s 138 | { 139 | avltree tree ; 140 | genalloc index ; 141 | } ; 142 | #define S6PS_CACHE_ZERO { .tree = AVLTREE_ZERO, .index = GENALLOC_ZERO } 143 | 144 | typedef struct s6ps_wchan_s s6ps_wchan_t, *s6ps_wchan_t_ref ; 145 | struct s6ps_wchan_s 146 | { 147 | stralloc sysmap ; 148 | genalloc ind ; 149 | } ; 150 | #define S6PS_WCHAN_ZERO { .sysmap = STRALLOC_ZERO, .ind = GENALLOC_ZERO } 151 | 152 | typedef struct s6ps_auxinfo_s s6ps_auxinfo_t, *s6ps_auxinfo_t_ref ; 153 | struct s6ps_auxinfo_s 154 | { 155 | tain boottime ; 156 | s6ps_cache_t caches[3] ; 157 | s6ps_wchan_t wchan ; 158 | unsigned int hz ; 159 | unsigned int pgsz ; 160 | uint64_t totalmem ; 161 | } ; 162 | #define S6PS_AUXINFO_ZERO { .boottime = TAIN_EPOCH, .caches = { S6PS_CACHE_ZERO, S6PS_CACHE_ZERO, S6PS_CACHE_ZERO }, .wchan = S6PS_WCHAN_ZERO, .hz = 0, .pgsz = 0, .totalmem = 0 } 163 | 164 | typedef int pfieldfmt_func (s6ps_auxinfo_t *, pscan_t *, size_t *, size_t *) ; 165 | typedef pfieldfmt_func *pfieldfmt_func_ref ; 166 | 167 | 168 | /* exported by s6ps_pfield.c */ 169 | 170 | extern char const *const *s6ps_opttable ; 171 | extern char const *const *s6ps_fieldheaders ; 172 | extern pfieldfmt_func_ref const *const s6ps_pfield_fmt ; 173 | extern int s6ps_compute_boottime (s6ps_auxinfo_t *, pscan_t *, unsigned int) ; 174 | 175 | 176 | /* exported by s6ps_statparse.c */ 177 | 178 | extern int s6ps_statparse (pscan_t *) ; 179 | 180 | 181 | /* exported by s6ps_otree.c */ 182 | 183 | extern void s6ps_otree (pscan_t *, unsigned int, avltreen *, unsigned int *) ; 184 | 185 | 186 | /* exported by s6ps_cache.c */ 187 | 188 | extern int s6ps_cache_init (s6ps_cache_t *) ; 189 | extern void s6ps_cache_finish (s6ps_cache_t *) ; 190 | extern int s6ps_uint32_cmp (void const *, void const *, void *) ; 191 | 192 | 193 | /* exported by s6ps_pwcache.c */ 194 | 195 | extern int s6ps_pwcache_lookup (s6ps_cache_t *, stralloc *, uid_t) ; 196 | 197 | 198 | /* exported by s6ps_grcache.c */ 199 | 200 | extern int s6ps_grcache_lookup (s6ps_cache_t *, stralloc *, gid_t) ; 201 | 202 | 203 | /* exported by s6ps_ttycache.c */ 204 | 205 | extern int s6ps_ttycache_lookup (s6ps_cache_t *, stralloc *, dev_t) ; 206 | 207 | 208 | /* exported by s6ps_wchan.c */ 209 | 210 | extern int s6ps_wchan_init (s6ps_wchan_t *, char const *) ; 211 | extern void s6ps_wchan_finish (s6ps_wchan_t *) ; 212 | extern int s6ps_wchan_lookup (s6ps_wchan_t const *, stralloc *, uint64_t) ; 213 | 214 | #endif 215 | -------------------------------------------------------------------------------- /src/s6-linux-utils/s6-logwatch.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #define USAGE "s6-logwatch [ logdir ]" 22 | #define dieusage() strerr_dieusage(100, USAGE) 23 | 24 | #define LOGWATCH_READING 0 25 | #define LOGWATCH_BLOCKING 1 26 | #define LOGWATCH_WAITING 2 27 | 28 | union inotify_event_u 29 | { 30 | struct inotify_event event ; 31 | char buf[sizeof(struct inotify_event) + NAME_MAX + 1] ; 32 | } ; 33 | 34 | static inline void logwatch_goteof (int *fd, unsigned int *state, int *newcurrent) 35 | { 36 | if (*newcurrent) 37 | { 38 | fd_close(*fd) ; 39 | *fd = open_read("current") ; 40 | if (*fd < 0) strerr_diefu1sys(111, "current") ; 41 | *newcurrent = 0 ; 42 | *state = LOGWATCH_READING ; 43 | } 44 | else *state = LOGWATCH_BLOCKING ; 45 | } 46 | 47 | static int logwatch_readit (int *fd, unsigned int *state, int *newcurrent) 48 | { 49 | struct iovec v[2] ; 50 | ssize_t r ; 51 | buffer_wpeek(buffer_1, v) ; 52 | r = fd_readv(*fd, v, 2) ; 53 | switch (r) 54 | { 55 | case -1 : return 0 ; 56 | case 0 : logwatch_goteof(fd, state, newcurrent) ; break ; 57 | default : buffer_wseek(buffer_1, r) ; 58 | } 59 | return 1 ; 60 | } 61 | 62 | static inline void logwatch_maketransition (unsigned int transition, int *fd, unsigned int *state, int *newcurrent) 63 | { 64 | static unsigned char const table[3][3] = { 65 | { 0x10, 0x00, 0x00 }, 66 | { 0x60, 0x22, 0x00 }, 67 | { 0x40, 0x03, 0x02 } 68 | } ; 69 | unsigned char c = table[*state][transition] ; 70 | *state = c & 0x0f ; 71 | if (*state == 3) strerr_dief1x(101, "current moved twice without being recreated") ; 72 | if (c & 0x10) *newcurrent = 1 ; 73 | if (c & 0x20) { fd_close(*fd) ; *fd = -1 ; } 74 | if (c & 0x40) 75 | { 76 | *fd = open_read("current") ; 77 | if (*fd < 0) strerr_diefu1sys(111, "current") ; 78 | } 79 | } 80 | 81 | static void logwatch_handle_event (int ifd, int watch, int *fd, unsigned int *state, int *newcurrent) 82 | { 83 | ssize_t r ; 84 | size_t offset = 0 ; 85 | union inotify_event_u u ; 86 | r = read(ifd, u.buf, sizeof(u.buf)) ; 87 | while (r > 0) 88 | { 89 | struct inotify_event *event = (struct inotify_event *)(u.buf + offset) ; 90 | offset += sizeof(struct inotify_event) + event->len ; 91 | r -= sizeof(struct inotify_event) + event->len ; 92 | if (event->wd == watch && !strcmp(event->name, "current")) 93 | { 94 | int transition = -1 ; 95 | if (event->mask & IN_CREATE) transition = 0 ; 96 | else if (event->mask & IN_MOVED_FROM) transition = 1 ; 97 | else if (event->mask & IN_MODIFY) transition = 2 ; 98 | if (transition >= 0) logwatch_maketransition(transition, fd, state, newcurrent) ; 99 | } 100 | } 101 | } 102 | 103 | int main (int argc, char const *const *argv) 104 | { 105 | iopause_fd x[2] = { { .events = IOPAUSE_READ }, { .fd = 1 } } ; 106 | char const *dir = "." ; 107 | int watch ; 108 | int fd ; 109 | unsigned int state ; 110 | int newcurrent = 0 ; 111 | unsigned int maxlen = 4096 ; 112 | PROG = "s6-logwatch" ; 113 | { 114 | subgetopt l = SUBGETOPT_ZERO ; 115 | for (;;) 116 | { 117 | int opt = subgetopt_r(argc, argv, "m:", &l) ; 118 | if (opt == -1) break ; 119 | switch (opt) 120 | { 121 | case 'm' : 122 | if (!uint0_scan(l.arg, &maxlen)) dieusage() ; 123 | strerr_warnw1x("the -m option is deprecated") ; 124 | break ; 125 | default : dieusage() ; 126 | } 127 | } 128 | argc -= l.ind ; argv += l.ind ; 129 | } 130 | 131 | if (argc) dir = *argv ; 132 | if (chdir(dir) < 0) strerr_diefu2sys(111, "chdir to ", dir) ; 133 | if (!fd_sanitize()) strerr_diefu1sys(111, "sanitize standard fds") ; 134 | 135 | x[0].fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC) ; 136 | if (x[0].fd < 0) strerr_diefu1sys(111, "inotify_init") ; 137 | watch = inotify_add_watch(x[0].fd, ".", IN_CREATE | IN_MOVED_FROM | IN_MODIFY) ; 138 | if (watch < 0) strerr_diefu1sys(111, "inotify_add_watch") ; 139 | fd = open_readb("current") ; 140 | if (fd < 0) 141 | { 142 | if (errno != ENOENT) strerr_diefu3sys(111, "open ", dir, "/current") ; 143 | state = LOGWATCH_WAITING ; 144 | } 145 | else state = LOGWATCH_READING ; 146 | if (!sig_ignore(SIGPIPE)) strerr_diefu1sys(111, "sig_ignore(SIGPIPE)") ; 147 | if (state == LOGWATCH_READING) 148 | { 149 | if (!logwatch_readit(&fd, &state, &newcurrent)) strerr_diefu3sys(111, "read from ", dir, "/current") ; 150 | } 151 | 152 | for (;;) 153 | { 154 | int r ; 155 | x[1].events = buffer_len(buffer_1) ? IOPAUSE_WRITE : 0 ; 156 | r = iopause(x, 2, 0, 0) ; 157 | if (r < 0) strerr_diefu1sys(111, "iopause") ; 158 | if (x[0].revents & IOPAUSE_EXCEPT) x[0].revents |= IOPAUSE_READ ; 159 | if (x[1].revents & IOPAUSE_EXCEPT) x[1].revents |= IOPAUSE_WRITE ; 160 | if (x[1].revents & IOPAUSE_WRITE) 161 | { 162 | if (!buffer_flush(buffer_1) && !error_isagain(errno)) 163 | strerr_diefu1sys(111, "write to stdout") ; 164 | if (x[1].revents & IOPAUSE_EXCEPT) break ; 165 | } 166 | if (state == LOGWATCH_READING && buffer_available(buffer_1)) 167 | { 168 | if (!logwatch_readit(&fd, &state, &newcurrent)) strerr_diefu3sys(111, "read from ", dir, "/current") ; 169 | } 170 | if (x[0].revents & IOPAUSE_READ) logwatch_handle_event(x[0].fd, watch, &fd, &state, &newcurrent) ; 171 | } 172 | return 0 ; 173 | } 174 | -------------------------------------------------------------------------------- /doc/rngseed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-linux-utils: the rngseed program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-linux-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The rngseed program

20 | 21 |

22 | rngseed manipulates the Linux kernel's entropy pool. It can seed 23 | the kernel's random number generator from a file, save a new seed into a 24 | file, wait until the entropy pool is full, and so on. Please read the 25 | options list carefully in order to use it in a secure way. 26 |

27 | 28 |

29 | rngseed can only be run as root. 30 |

31 | 32 |

Interface

33 | 34 |
 35 |      rngseed [ -r | -R ] [ -N | -n ] [ -w | -W ] [ -d dir ] [ -v verbosity ]
 36 | 
37 | 38 |

39 | The behaviour of rngseed depends on what options it is given. By default, it 40 | just waits until the entropy pool is full, then exits 0. 41 |

42 | 43 |

Options

44 | 45 |

Configuration options

46 | 47 |
    48 |
  • -v verbosity : be more or less verbose. 49 | Default is 1, meaning rngseed will print warning and error 50 | messages. 0 will make it only print error messages, not warnings. 51 | 2 or more will make it add informational messages.
  • 52 |
  • -d dir : use dir as the 53 | directory where the seed file is located (for reading as well as writing). 54 | dir must be located on a writable, permanent filesystem. 55 | Default is /var/lib/rngseed.
  • 56 |
57 | 58 |

Behaviour options

59 | 60 |
    61 |
  • -r : read from a seed file. rngseed will attempt to read 62 | some bits from dir/seed and seed the kernel's RNG with the data. 63 | dir must be on a writable filesystem, because the seed file will be unlinked 64 | (the same data must not be used to seed the RNG twice). rngseed -r is 65 | typically used at boot time, in init scripts, right after mounting the 66 | filesystem where the seed has been saved.
  • 67 |
  • -R : read from a seed file, ignoring creditability. 68 | Behaves like -r, but will not increase the entropy count of the 69 | kernel RNG even if the seed file is marked as creditable.
  • 70 |
  • -w : write to a seed file. rngseed will save some 71 | random bits into dir/seed, marking the seed as creditable if the 72 | RNG's entropy pool is fully initialized. rngseed -w is typically used at 73 | shutdown time, right before unmounting filesystems; the point is to store 74 | a seed on disk so it can be reused on next boot by rngseed -r.
  • 75 |
  • -W : write to a seed file, without registering 76 | creditability. Behaves like -w, but does not mark the new seed 77 | file as creditable.
  • 78 |
  • -N : block. After reading a seed file if required, 79 | and before writing a new seed file if required, rngseed will wait until the 80 | entropy pool is ready. This ensures that future readings of the kernel 81 | RNG will be cryptographically secure, and that new seed files will be 82 | creditable. This is the default.
  • 83 |
  • -n : do not block. Immediately proceed even if the entropy 84 | pool is not ready. This may make a new seed file non-creditable.
  • 85 |
86 | 87 |

Creditability

88 | 89 |

90 | A seed is said to be creditable if it has been obtained through a 91 | cryptographically secure RNG. This means it is safe from replay attacks, and 92 | safe to use to count towards the entropy pool when seeding the kernel RNG. 93 | rngseed -w will normally always create a creditable seed file, 94 | especially if used at shutdown time: by then, the kernel's entropy pool 95 | should have been initialized for a while. 96 |

97 | 98 |

99 | An uncreditable seed can be used to add to the random pool, but 100 | should not increment the entropy count, because it is not safe from 101 | replay attacks. rngseed -r will do the right thing if the seed 102 | it reads is uncreditable. 103 |

104 | 105 |

106 | rngseed uses the seed file's permissions to mark creditability. 107 | An uncreditable seed has rights 0600; a creditable seed has rights 0400. 108 |

109 | 110 |

Exit codes

111 | 112 |
    113 |
  • 0: success
  • 114 |
  • 100: wrong usage
  • 115 |
  • 111: system call failure
  • 116 |
117 | 118 |

Notes

119 | 120 |
    121 |
  • rngseed -N replaces the old s6-fillurandompool program, 122 | that only waited for the entropy pool to get ready, but did not include any 123 | seed file management.
  • 124 |
  • The options are named r and w from the seed file's 125 | point of view. 126 | rngseed -r reads from the file (and unlinks it) and writes to the kernel 127 | RNG. rngseed -w reads from the kernel RNG and writes to the file.
  • 128 |
  • It is a good idea to use rngseed -rw at boot time, rather than 129 | rngseed -r. This ensures that a seed file will be present on next boot 130 | even if the system doesn't undergo a clean shutdown (e.g. the power fails). 131 | Of course, this does not preclude running rngseed -w in the shutdown 132 | sequence, so the next boot runs with the freshest possible seed.
  • 133 |
  • rngseed is inspired by Jason Donenfeld's 134 | seedrng program. It is, 135 | however, an independent implementation of the same concept.
  • 136 |
137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /doc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-linux-utils - skarnet's tiny Linux-specific utilities 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | Software
15 | skarnet.org 16 |

17 | 18 |

s6-linux-utils

19 | 20 |

What is it ?

21 | 22 |

23 | s6-linux-utils is a set of minimalistic Linux-specific system utilities. 24 |

25 | 26 |

27 | Prefixing the name of this package — and the names of the binaries it 28 | provides — with s6- was a naming mistake. It happened in the 29 | early days of the 30 | s6 project, before it grew and 31 | became an ecosystem focused on supervision, service management and init; 32 | despite sharing the same author and the same philosophy, and being designed 33 | to work with it, s6-linux-utils is not, 34 | stricto sensu, part of the s6 ecosystem, and if you arrived here while trying 35 | to understand what s6 is, you are 36 | on the wrong page. I apologize for the confusion. 37 |

38 | 39 |
40 | 41 |

Installation

42 | 43 |

Requirements

44 | 45 |
    46 |
  • A Linux-based system with a standard C development environment. 47 | The Linux kernel must be 3.5 or later.
  • 48 |
  • GNU make, version 3.81 or later
  • 49 |
  • skalibs version 50 | 2.14.5.0 or later. It's a build-time requirement. It's also a run-time 51 | requirement if you link against the shared version of the skalibs 52 | library.
  • 53 |
  • execline version 54 | 2.9.8.0 or later. It's a build-time requirement.
  • 55 |
56 | 57 |

Licensing

58 | 59 |

60 | s6-linux-utils is free software. It is available under the 61 | ISC license. 62 |

63 | 64 |

Download

65 | 66 |
    67 |
  • The current released version of s6-linux-utils is 68 | 2.6.4.0. 69 | You can access its checksum here.
  • 70 |
  • Alternatively, you can checkout a copy of the 71 | s6-linux-utils 72 | git repository: 73 |
     git clone git://git.skarnet.org/s6-linux-utils 
  • 74 |
  • There's also a 75 | GitHub mirror, or a 76 | SourceHut mirror">SourceHut mirror 77 | of the s6-linux-utils git repository.
  • 78 |
79 | 80 |

Compilation

81 | 82 |
    83 |
  • See the enclosed INSTALL file for installation details.
  • 84 |
  • Starting with version 2.6.1.0, you can use the 85 | --enable-multicall configure option to save disk space.
  • 86 |
87 | 88 |

Upgrade notes

89 | 90 |
    91 |
  • This page lists the differences to be aware of between 92 | the previous versions of s6-linux-utils and the current one.
  • 93 |
94 | 95 |
96 | 97 |

Reference

98 | 99 |

Commands

100 | 101 |

102 | All these commands exit 111 if they encounter a temporary error, and 103 | 100 if they encounter a permanent error - such as a misuse. They exit 104 | 127 if they're trying to execute into a program and cannot find it, and 105 | 126 if they fail to execute into a program for another reason. 106 |

107 | 108 |

109 | (Miscellaneous tools) 110 |

111 | 125 |

126 | (Multicall configuration) 127 |

128 | 131 | 132 |

Related resources

133 | 134 |
    135 |
  • s6-linux-utils is discussed on the 136 | skaware mailing-list.
  • 137 |
138 | 139 |

Similar work

140 | 141 |

142 | There are several good projects aiming to provide a minimal userspace 143 | environment for Linux, suitable for embedded systems. Among them, for 144 | instance: 145 |

146 | 147 | 153 | 154 |

155 | Most of the time, these projects aim to implement standard commands in a 156 | lightweight way, and 157 | they do it well enough. So, although some standard reimplentation already 158 | exists in s6-linux-utils and its sibling package 159 | s6-portable-utils, 160 | it is an explicit non-goal of those packages to duplicate the work of those 161 | projects, and no more rewriting of standard commands will occur. 162 |

163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /src/s6-linux-utils/s6-mount.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "mount-constants.h" 17 | 18 | #define USAGE "s6-mount [ -a ] [ -z fstab ] | s6-mount [ -n ] [ -t type ] [ -o option[,option...] ]... device mountpoint" 19 | #define dienomem() strerr_diefu1sys(111, "stralloc_catb") 20 | 21 | struct mount_flag_modif_s 22 | { 23 | char const *name ; 24 | unsigned long add ; 25 | unsigned long del ; 26 | } ; 27 | 28 | static int mount_flag_cmp (void const *a, void const *b) 29 | { 30 | char const *key = a ; 31 | struct mount_flag_modif_s const *p = b ; 32 | return strcmp(key, p->name) ; 33 | } 34 | 35 | static void mount_scanopt (stralloc *data, unsigned long *flags, char const *s) 36 | { 37 | static struct mount_flag_modif_s const mount_flag_modifs[] = 38 | { 39 | { .name = "async", .add = 0, .del = MS_SYNCHRONOUS }, 40 | { .name = "atime", .add = 0, .del = MS_NOATIME }, 41 | { .name = "bind", .add = MS_BIND, .del = 0 }, 42 | { .name = "defaults", .add = 0, .del = MS_RDONLY | MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_SYNCHRONOUS }, 43 | { .name = "dev", .add = 0, .del = MS_NODEV }, 44 | { .name = "diratime", .add = 0, .del = MS_NODIRATIME }, 45 | { .name = "dirsync", .add = MS_DIRSYNC, .del = 0 }, 46 | { .name = "exec", .add = 0, .del = MS_NOEXEC }, 47 | { .name = "lazytime", .add = MS_LAZYTIME, .del = 0 }, 48 | { .name = "loud", .add = 0, .del = MS_SILENT }, 49 | { .name = "mandlock", .add = MS_MANDLOCK, .del = 0 }, 50 | { .name = "move", .add = MS_MOVE, .del = 0 }, 51 | { .name = "noatime", .add = MS_NOATIME, .del = 0 }, 52 | { .name = "nobind", .add = 0, .del = MS_BIND }, 53 | { .name = "nodev", .add = MS_NODEV, .del = 0 }, 54 | { .name = "nodiratime", .add = MS_NODIRATIME, .del = 0 }, 55 | { .name = "nodirsync", .add = 0, .del = MS_DIRSYNC }, 56 | { .name = "noexec", .add = MS_NOEXEC, .del = 0 }, 57 | { .name = "nolazytime", .add = 0, .del = MS_LAZYTIME }, 58 | { .name = "nomandlock", .add = 0, .del = MS_MANDLOCK }, 59 | { .name = "nomove", .add = 0, .del = MS_MOVE }, 60 | { .name = "norelatime", .add = 0, .del = MS_RELATIME }, 61 | { .name = "nostrictatime", .add = 0, .del = MS_STRICTATIME }, 62 | { .name = "nosuid", .add = MS_NOSUID, .del = 0 }, 63 | { .name = "nosymfollow", .add = MS_NOSYMFOLLOW, .del = 0 }, 64 | { .name = "private", .add = MS_PRIVATE, .del = MS_SHARED | MS_SLAVE | MS_UNBINDABLE }, 65 | { .name = "relatime", .add = MS_RELATIME, .del = 0 }, 66 | { .name = "remount", .add = MS_REMOUNT, .del = 0 }, 67 | { .name = "ro", .add = MS_RDONLY, .del = 0 }, 68 | { .name = "rw", .add = 0, .del = MS_RDONLY }, 69 | { .name = "shared", .add = MS_SHARED, .del = MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE }, 70 | { .name = "silent", .add = MS_SILENT, .del = 0 }, 71 | { .name = "slave", .add = MS_SLAVE, .del = MS_SHARED | MS_PRIVATE | MS_UNBINDABLE }, 72 | { .name = "strictatime", .add = MS_STRICTATIME, .del = 0 }, 73 | { .name = "suid", .add = 0, .del = MS_NOSUID }, 74 | { .name = "symfollow", .add = 0, .del = MS_NOSYMFOLLOW }, 75 | { .name = "sync", .add = MS_SYNCHRONOUS, .del = 0 }, 76 | { .name = "unbindable", .add = MS_UNBINDABLE, .del = MS_SHARED | MS_PRIVATE | MS_SLAVE }, 77 | } ; 78 | 79 | while (*s) 80 | { 81 | struct mount_flag_modif_s const *p ; 82 | size_t n = str_chr(s, ',') ; 83 | char opt[n+1] ; 84 | memcpy(opt, s, n) ; 85 | opt[n] = 0 ; 86 | 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) ; 87 | if (p) 88 | { 89 | *flags &= ~p->del ; 90 | *flags |= p->add ; 91 | } 92 | else 93 | { 94 | if (data->s && data->len && !stralloc_catb(data, ",", 1)) dienomem() ; 95 | if (!stralloc_catb(data, s, n)) dienomem() ; 96 | } 97 | s += n + (s[n] == ',') ; 98 | } 99 | } 100 | 101 | static int mountall (char const *fstab) 102 | { 103 | int e = 0 ; 104 | stralloc data = STRALLOC_ZERO ; 105 | FILE *yuck = setmntent(fstab, "r") ; 106 | if (!yuck) strerr_diefu2sys(111, "open ", fstab) ; 107 | for (;;) 108 | { 109 | unsigned long flags = 0 ; 110 | struct mntent *d ; 111 | errno = 0 ; 112 | d = getmntent(yuck) ; 113 | if (!d) break ; 114 | mount_scanopt(&data, &flags, d->mnt_opts) ; 115 | if (!stralloc_0(&data)) strerr_diefu1sys(111, "build data string") ; 116 | if (mount(d->mnt_fsname, d->mnt_dir, d->mnt_type, flags, data.s) == -1) 117 | { 118 | e++ ; 119 | strerr_warnwu4sys("mount ", d->mnt_fsname, " on ", d->mnt_dir) ; 120 | } 121 | data.len = 0 ; 122 | } 123 | if (errno) strerr_diefu2sys(111, "getmntent on ", fstab) ; 124 | endmntent(yuck) ; 125 | // stralloc_free(&data) ; 126 | return e ; 127 | } 128 | 129 | int main (int argc, char const *const *argv) 130 | { 131 | stralloc data = STRALLOC_ZERO ; 132 | unsigned long flags = 0 ; 133 | char const *fstype = "none" ; 134 | char const *fstab = "/etc/fstab" ; 135 | PROG = "s6-mount" ; 136 | { 137 | int doall = 0 ; 138 | subgetopt l = SUBGETOPT_ZERO ; 139 | for (;;) 140 | { 141 | int opt = subgetopt_r(argc, argv, "nz:arwt:o:", &l) ; 142 | if (opt == -1) break ; 143 | switch (opt) 144 | { 145 | case 'n' : break ; 146 | case 'z' : fstab = l.arg ; break ; 147 | case 'a' : doall = 1 ; break ; 148 | case 't' : fstype = l.arg ; break ; 149 | case 'w' : mount_scanopt(&data, &flags, "rw") ; break ; 150 | case 'r' : mount_scanopt(&data, &flags, "ro") ; break ; 151 | case 'o' : mount_scanopt(&data, &flags, l.arg) ; break ; 152 | default : strerr_dieusage(100, USAGE) ; 153 | } 154 | } 155 | argc -= l.ind ; argv += l.ind ; 156 | if (doall) return mountall(fstab) ; 157 | } 158 | if (!argc) 159 | { 160 | int fd = open_readb("/proc/mounts") ; 161 | if (fd < 0) strerr_diefu2sys(111, "read ", "/proc/mounts") ; 162 | if (fd_cat(fd, 1) < 0) strerr_diefu2sys(111, "fd_cat ", "/proc/mounts") ; 163 | fd_close(fd) ; 164 | } 165 | else if (argc == 1) strerr_dieusage(100, USAGE) ; 166 | else if (!stralloc_0(&data)) strerr_diefu1sys(111, "build data string") ; 167 | else if (mount(argv[0], argv[1], fstype, flags, data.s) == -1) 168 | strerr_diefu4sys(errno == EBUSY ? 1 : 111, "mount ", argv[0], " on ", argv[1]) ; 169 | return 0 ; 170 | } 171 | -------------------------------------------------------------------------------- /doc/fstab2s6rc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-linux-utils: the fstab2s6rc program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-linux-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The fstab2s6rc program

20 | 21 |

22 | fstab2s6rc reads the /etc/fstab file, listing the filesystems and swap partitions 23 | to mount at boot time, and builds a set of service definition directories from it, meant to 24 | be fed to s6-rc-compile, having the 25 | effect of mounting these partitions when run by s6-rc. 26 |

27 | 28 |

29 | This method has several advantages over the classic mount -a: 30 |

31 | 32 |
    33 |
  • Parallelization. Dependencies between the mount points are respected: if /var 34 | and /var/log are mount points in /etc/fstab, s6-rc will not attempt to 35 | mount /var/log before /var is successfully mounted. But apart from this 36 | necessary serialization, s6-rc will perform in parallel as much as it can.
  • 37 |
  • Granularity. mount -a in the boot sequence treats all the mounts as one 38 | unit; and although the output of fstab2s6rc can provide a bundle listing all the mounts, 39 | each mount is available as a separate service.
  • 40 |
41 | 42 |

43 | fstab2s6rc is an offline tool. It does not perform mounts or unmounts itself; 44 | it just converts the data in /etc/fstab, which is in a format usable by mount, 45 | into a format usable — after compilation — by s6-rc. 46 |

47 | 48 |

Interface

49 | 50 |
 51 |      fstab2s6rc [ -A | -a ] [ -U | -u ] [ -E | -e ] [ -F fstab ] [ -m mode ] [ -B bundle ] [ -d basedep ] dir
 52 | 
53 | 54 |
    55 |
  • fstab2s6rc creates a directory dir in the filesystem to host all the service definition it will create. 56 | dir must not previously exist.
  • 57 |
  • fstab2s6rc reads the /etc/fstab file. For every mount defined 58 | in the file, it creates a subdirectory of dir that is a suitable definition 59 | directory for an s6-rc service performing that mount.
  • 60 |
  • The service is named after the mount point: the service mounting /var/log 61 | will be called mount-var:log (slashes being replaced with colons, first slash 62 | omitted).
  • 63 |
  • For swap partitions, the partition named is used: the service activating swap on 64 | /dev/sda2 will be called swap-dev:sda2.
  • 65 |
66 | 67 |

Options

68 | 69 |
70 |
-F fstab, --fstab=fstab
71 |
Read mount point information from file fstab instead of /etc/fstab.
72 | 73 |
-m mode, --mode=mode
74 |
Create dir with permissions mode. mode is interpreted in octal.
75 | 76 |
-B bundle, --bundle=bundle
77 |
Create a bundle named bundle containing all the created services. 78 | The mount point services will also be grouped under a bundle named bundle-mounts 79 | and the swap services will be grouped under a bundle named bundle-swaps. 80 | fstab lines that have the noauto option will not be included in these bundles.
81 | 82 |
-d dep, --base-dependency=dep
83 |
Add a dependency to a service named dep to all the created services. 84 | This is useful e.g. in a boot sequence to ensure that the mounts will not start before 85 | a certain point.
86 | 87 |
-A, --include-noauto
88 |
Include mount points and swaps marked noauto in the output. These 89 | services will not be marked as essential or recommended, and they will not be included 90 | in any bundle, but they will be there. This is the default.
91 | 92 |
-a, --exclude-noauto
93 |
Exclude mount points and swaps marked noauto. No service will be created 94 | for these fstab entries.
95 | 96 |
-U, --without-uuid
97 |
The created services will use s6-linux-utils commands such as 98 | s6-mount and s6-swapon. 99 | This makes the created services only depend on s6-linux-utils, but the fstab 100 | entries must not contain util-linux-specific syntax such as UUID= or 101 | LABEL= in place of device names (if they do, the fstab2s6rc invocation 102 | will work, but will generate nonsensical commands, interpreting the device 103 | names literally). This is the default.
104 | 105 |
-u, --with-uuid
106 |
The created services will use util-linux commands such as 107 | mount and 108 | swapon. Running 109 | the services will depend on having such commands installed, but syntax 110 | for labels and uuids will be understood.
111 | 112 |
-E, --essential
113 |
Mark the services as essential, and do not create down scripts 114 | for them. This makes services suitable to be part of a base init sequence where 115 | all the listed filesystems are mounted early, and never unmounted until right 116 | before the machine reboots. (noauto entries will not be marked as 117 | essential.) This is the default.
118 | 119 |
-e, --not-essential
120 |
Mark the services as recommended rather than essential; create down 121 | scripts to unmount the filesystem. This makes services suitable for being called 122 | later than the base init sequence, as an optional part of a system's 123 | functionality. Stopping the services will unmount the 124 | corresponding filesystems and turn off the corresponding swap devices. 125 | noauto entries will not be marked as recommended.
126 |
127 | 128 |

Exit codes

129 | 130 |
131 |
0
Success.
132 |
1
Invalid fstab file.
133 |
100
Incorrect usage.
134 |
111
System call failed.
135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /doc/s6-ps.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-linux-utils: the s6-ps program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-linux-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-ps program

20 | 21 |

22 | s6-ps shows a list of processes on the system. 23 |

24 | 25 |

Interface

26 | 27 |
 28 |      s6-ps [ -H ] [ -w spacing ] [ -W chanfile ] [ -l | -o field,field,... ]
 29 | 
30 | 31 |
    32 |
  • s6-ps assumes the proc filesystem is mounted on /proc. 33 | It scans /proc for a list of all processes on the system.
  • 34 |
  • It prints a header line, then information about the processes it has found, 35 | one process per line. Then it exits 0.
  • 36 |
  • If s6-ps is not allowed to read a field, it will print * (a star) instead 37 | of the field's content. - (a dash) means the field is unapplicable here, 38 | for instance the "tty" field for a process that has no controlling terminal.
  • 39 |
40 | 41 |

Options

42 | 43 |
    44 |
  • -H : tree. s6-ps will display he process list as a tree, 45 | as ps f does. It will print kernel processes first, then user processes. 46 | By default, the processes are simply ordered by increasing pid number, without 47 | care for the process hierarchy.
  • 48 |
  • -w spacing : leave at least spacing 49 | space characters between two adjacent fields. Minimum is 1, default is 2, 50 | maximum is 256.
  • 51 |
  • -W wchanfile : force wchanfile as the 52 | file listing kernel addresses for WCHAN fields. By default, s6-ps tries to use 53 | /proc/kallsyms, /boot/System.map-`uname -r`, and 54 | /boot/System.map, in that order.
  • 55 |
  • -l : long. Equivalent to 56 | -o user,pid,cpcpu,pmem,vsize,rss,tty,s,start,cttime,args.
  • 57 |
  • -o fieldlist : list of fields to print. 58 | fieldlist must be a comma-separated list of fields, without spaces. 59 | Fields cannot be duplicated. They will be printed in the given order. 60 | The valid field names are listed below. The default field list is 61 | user,pid,tty,s,start,args.
  • 62 |
63 | 64 |

Fields

65 | 66 |

67 | The -o option makes it possible to customize s6-ps's output. Here are the 68 | recognized field keywords and the corresponding information they display. 69 |

70 | 71 |
    72 |
  • pid : the process id number.
  • 73 |
  • comm : the command name as known by the kernel.
  • 74 |
  • s : the one-character state of the process, then s 75 | if the process is a session leader or + if it is a foreground 76 | process group leader, then N if 77 | the process is niced or < if it is anti-niced. Unlike ps, s6-ps 78 | cannot tell whether a process has locked memory pages or not.
  • 79 |
  • ppid : the parent process' pid.
  • 80 |
  • pgrp : the process group number.
  • 81 |
  • sess : the session leader's pid.
  • 82 |
  • tty : the name of the process's controlling terminal.
  • 83 |
  • tpgid : the pid of the foreground process group.
  • 84 |
  • minflt : the number of minor page fault the process has encountered.
  • 85 |
  • cminflt : the cumulative number of minor page fault the process and its dead children have encountered.
  • 86 |
  • majflt : the number of major page fault the process has encountered.
  • 87 |
  • cmajflt : the cumulative number of major page fault the process and its dead children have encountered.
  • 88 |
  • utime : the time the process spent in user mode.
  • 89 |
  • stime : the time the process spent in kernel mode.
  • 90 |
  • cutime : the time spent in user mode by the process and 91 | all its dead children.
  • 92 |
  • cstime : the time spent in kernel mode by the process and 93 | all its dead children.
  • 94 |
  • prio : the process' priority as computed by the kernel.
  • 95 |
  • nice : the process' nice value.
  • 96 |
  • thcount : the number of threads in the process.
  • 97 |
  • start : the start time of the process.
  • 98 |
  • vsize : the virtual memory size of the process.
  • 99 |
  • rss : the resident set size of the process.
  • 100 |
  • rsslimit : the maximum rss allowed for the process.
  • 101 |
  • psr : the number of the CPU the process is running on.
  • 102 |
  • rtprio : the real-time priority of the process.
  • 103 |
  • policy : the real-time policy of the process - a symbolic name.
  • 104 |
  • user : the user the process is running as.
  • 105 |
  • group : the group the process is running as.
  • 106 |
  • pmem : the percentage of the available virtual memory the process 107 | is using. Be aware that it is a very rough estimate: determining exactly how much memory 108 | a process is using is a complex task.
  • 109 |
  • wchan : the name or address of the kernel function where the 110 | proces is sleeping. It is actually very rare that a kernel is configured to properly 111 | export that value, because it incurs a small performance cost.
  • 112 |
  • args : the command line of the process.
  • 113 |
  • env : the process environment. s6-ps can normally only print 114 | the environment for processes running as the same user, or if it is run as root. 115 | Be aware that the environment is usually quite large, and will create very long 116 | lines, likely to mess up the display on a standard terminal.
  • 117 |
  • pcpu : the percentage of CPU used by the process (total cpu time 118 | divided by total running time). It is a mean value and does not reflect current CPU 119 | usage.
  • 120 |
  • ttime : total CPU time used by the process (user + kernel mode).
  • 121 |
  • cttime : total CPU time used by the process and all its dead 122 | children (user + kernel mode).
  • 123 |
  • tstart : the start time of the process as a 124 | TAI64N value.
  • 125 |
  • cpcpu : the percentage of CPU used by the process and its dead 126 | children (total cpu time 127 | divided by total running time). It is a mean value and does not reflect current CPU 128 | usage.
  • 129 |
130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /doc/upgrade.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-linux-utils: how to upgrade 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-linux-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

What has changed in s6-linux-utils

20 | 21 |

in 2.6.4.0

22 | 23 |
    24 |
  • skalibs 25 | dependency bumped to 2.14.5.0.
  • 26 |
  • execline 27 | dependency (to 2.9.8.0) introduced.
  • 28 |
  • Shared libraries are now supported on MacOS.
  • 29 |
  • New binary: fstab2s6rc.
  • 30 |
31 | 32 |

in 2.6.3.0

33 | 34 |
    35 |
  • skalibs 36 | dependency bumped to 2.14.4.0.
  • 37 |
38 | 39 |

in 2.6.2.1

40 | 41 |
    42 |
  • skalibs 43 | dependency bumped to 2.14.3.0.
  • 44 |
  • Static libraries (if any, which isn't the case for now) 45 | are installed in /usr/lib by default.
  • 46 |
47 | 48 |

in 2.6.2.0

49 | 50 |
    51 |
  • skalibs 52 | dependency bumped to 2.14.0.0.
  • 53 |
54 | 55 |

in 2.6.1.2

56 | 57 |
    58 |
  • No functional changes.
  • 59 |
60 | 61 |

in 2.6.1.1

62 | 63 |
    64 |
  • No functional changes.
  • 65 |
66 | 67 |

in 2.6.1.0

68 | 69 | 75 | 76 |

in 2.6.0.1

77 | 78 |
    79 |
  • skalibs 80 | dependency bumped to 2.13.0.0.
  • 81 |
82 | 83 |

in 2.6.0.0

84 | 85 |
    86 |
  • skalibs 87 | dependency bumped to 2.12.0.0.
  • 88 |
  • s6-fillurandompool has been replaced with the new 89 | rngseed program.
  • 90 |
91 | 92 |

in 2.5.1.7

93 | 94 |
    95 |
  • skalibs 96 | dependency bumped to 2.11.1.0.
  • 97 |
98 | 99 |

in 2.5.1.6

100 | 101 |
    102 |
  • skalibs 103 | dependency bumped to 2.11.0.0.
  • 104 |
105 | 106 |

in 2.5.1.5

107 | 108 |
    109 |
  • skalibs 110 | dependency bumped to 2.10.0.3.
  • 111 |
112 | 113 |

in 2.5.1.4

114 | 115 |
    116 |
  • skalibs 117 | dependency bumped to 2.10.0.0.
  • 118 |
119 | 120 |

in 2.5.1.3

121 | 122 |
    123 |
  • skalibs 124 | dependency bumped to 2.9.3.0.
  • 125 |
126 | 127 |

in 2.5.1.2

128 | 129 |
    130 |
  • skalibs 131 | dependency bumped to 2.9.2.0.
  • 132 |
133 | 134 |

in 2.5.1.1

135 | 136 |
    137 |
  • skalibs 138 | dependency bumped to 2.9.1.0.
  • 139 |
140 | 141 |

in 2.5.1.0

142 | 143 |
    144 |
  • skalibs 145 | dependency bumped to 2.9.0.0.
  • 146 |
147 | 148 |

in 2.5.0.1

149 | 150 |
    151 |
  • skalibs 152 | dependency bumped to 2.8.0.0.
  • 153 |
  • Everything now builds as PIC by default no matter 154 | the toolchain's settings. Use the --disable-all-pic configure 155 | option to build executables and static libraries as non-PIC.
  • 156 |
157 | 158 |

in 2.5.0.0

159 | 160 |
    161 |
  • skalibs dependency bumped to 2.7.0.0.
  • 162 |
  • Optional nsss support added.
  • 163 |
  • s6-devd, s6-uevent-listener and s6-uevent-spawner 164 | have been removed: mdevd obsoletes 165 | them.
  • 166 |
167 | 168 |

in 2.4.0.2

169 | 170 |
    171 |
  • skalibs dependency bumped to 2.6.0.2.
  • 172 |
173 | 174 |

in 2.4.0.1

175 | 176 |
    177 |
  • skalibs dependency bumped to 2.6.0.0.
  • 178 |
179 | 180 |

in 2.4.0.0

181 | 182 |
    183 |
  • Linux dependency bumped to 3.5.
  • 184 |
  • skalibs dependency bumped to 2.5.1.0.
  • 185 |
  • The interface between s6-uevent-listener 186 | and s6-uevent-spawner has changed.
  • 187 |
188 | 189 |

in 2.3.0.0

190 | 191 |
    192 |
  • skalibs dependency bumped to 2.5.0.0.
  • 193 |
194 | 195 |

in 2.2.0.0

196 | 197 |
    198 |
  • skalibs dependency bumped to 2.4.0.0.
  • 199 |
  • s6-halt, s6-poweroff and s6-reboot are not provided 200 | by this package anymore: they're now a part of the 201 | s6-linux-init 202 | package.
  • 203 |
  • The s6-fillurandompool 204 | program has been added.
  • 205 |
206 | 207 |

in 2.1.0.0

208 | 209 |
    210 |
  • skalibs dependency bumped to 2.3.10.0
  • 211 |
  • s6-halt, 212 | s6-poweroff and 213 | s6-reboot have changed behaviours. 214 | They now send a signal to process 1 by default; to make them 215 | perform a hard shutdown, add the -f option.
  • 216 |
217 | 218 |

in 2.0.2.3

219 | 220 |
    221 |
  • GNU make dependency pushed back to 3.81.
  • 222 |
  • skalibs dependency bumped to 2.3.8.0
  • 223 |
224 | 225 |

in 2.0.2.2

226 | 227 |
    228 |
  • skalibs dependency bumped to 2.3.6.1
  • 229 |
230 | 231 |

in 2.0.2.1

232 | 233 |
    234 |
  • skalibs dependency bumped to 2.3.5.1
  • 235 |
236 | 237 |

in 2.0.2.0

238 | 239 | 247 | 248 |

in 2.0.1.0

249 | 250 |
    251 |
  • skalibs dependency bumped to 2.3.1.0
  • 252 |
  • s6-hiercopy removed. (Moved to s6-portable-utils.)
  • 253 |
254 | 255 |

in 2.0.0.1

256 | 257 |
    258 |
  • skalibs dependency bumped to 2.1.0.0
  • 259 |
260 | 261 |

in 2.0.0.0

262 | 263 |
    264 |
  • The build system has completely changed. It is now a standard 265 | ./configure && make && sudo make install 266 | build system. See the enclosed INSTALL file for details.
  • 267 |
  • slashpackage is not activated by default.
  • 268 |
  • shared libraries are not used by default.
  • 269 |
  • skalibs dependency bumped to 2.0.0.0
  • 270 |
271 | 272 | 273 | 274 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This Makefile requires GNU make. 3 | # 4 | # Do not make changes here. 5 | # Use the included .mak files. 6 | # 7 | 8 | it: all 9 | 10 | make_need := 3.81 11 | ifeq "" "$(strip $(filter $(make_need), $(firstword $(sort $(make_need) $(MAKE_VERSION)))))" 12 | fail := $(error Your make ($(MAKE_VERSION)) is too old. You need $(make_need) or newer) 13 | endif 14 | 15 | uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1))) 16 | 17 | CC = $(error Please use ./configure first) 18 | 19 | STATIC_LIBS := 20 | SHARED_LIBS := 21 | INTERNAL_LIBS := 22 | EXTRA_TARGETS := 23 | PC_TARGETS := 24 | LIB_DEFS := 25 | BIN_SYMLINKS := 26 | TEST_BINS := 27 | 28 | -include config.mak 29 | include package/targets.mak 30 | 31 | define library_definition 32 | LIB$(1) := lib$(2).$(if $(DO_ALLSTATIC),a,$(SHLIB_EXT)).xyzzy 33 | ifdef DO_SHARED 34 | SHARED_LIBS += lib$(2).$(SHLIB_EXT).xyzzy 35 | endif 36 | ifdef DO_STATIC 37 | STATIC_LIBS += lib$(2).a.xyzzy 38 | endif 39 | ifdef DO_PKGCONFIG 40 | PC_TARGETS += lib$(2).pc 41 | endif 42 | 43 | lib$(2).pc: 44 | exec env \ 45 | library="$(2)" \ 46 | includedir="$(includedir)" \ 47 | dynlibdir="$(dynlibdir)" \ 48 | libdir="$(libdir)" \ 49 | extra_includedirs="$(extra_includedirs)" \ 50 | extra_libdirs="$(extra_libdirs)" \ 51 | extra_libs="$$(strip $$(EXTRA_LIBS))" \ 52 | description="$$($(1)_DESCRIPTION)" \ 53 | url="$$($(1)_URL)" \ 54 | ldlibs="$(LDLIBS)" \ 55 | ./tools/gen-dotpc.sh > $$@.tmp 56 | exec mv -f $$@.tmp $$@ 57 | 58 | endef 59 | 60 | define binary_installation_rule 61 | $(DESTDIR)$(1)/$(2): ./$(2) package/modes 62 | exec $(INSTALL) -D -m 600 $$< $$@ 63 | grep -- ^$$(@F) < package/modes | { read name mode owner && \ 64 | if [ x$$$$owner != x ] ; then chown -- $$$$owner $$@ ; fi && \ 65 | chmod $$$$mode $$@ ; } 66 | endef 67 | 68 | define symlink_installation_rule 69 | $(DESTDIR)$(1)/$(2): $(DESTDIR)$(1)/$(SYMLINK_TARGET_$(2)) 70 | exec $(INSTALL) -l $$( $$package-$$version.tar.gz.sha256 && \ 116 | exec rm -rf /tmp/$$package-$$version 117 | 118 | strip: $(ALL_LIBS) $(ALL_BINS) 119 | ifneq ($(strip $(STATIC_LIBS)),) 120 | exec $(STRIP) -x -R .note -R .comment $(STATIC_LIBS) 121 | endif 122 | ifneq ($(strip $(ALL_BINS)$(SHARED_LIBS)),) 123 | exec $(STRIP) -R .note -R .comment $(ALL_BINS) $(SHARED_LIBS) 124 | endif 125 | 126 | install: install-dynlib install-libexec install-bin install-symlinks install-lib install-include install-pkgconfig 127 | install-dynlib: $(SHARED_LIBS:lib%.$(SHLIB_EXT).xyzzy=$(DESTDIR)$(dynlibdir)/lib%.$(SHLIB_EXT)) 128 | install-libexec: $(LIBEXEC_TARGETS:%=$(DESTDIR)$(libexecdir)/%) 129 | install-bin: $(BIN_TARGETS:%=$(DESTDIR)$(bindir)/%) 130 | install-symlinks: $(BIN_SYMLINKS:%=$(DESTDIR)$(bindir)/%) 131 | install-lib: $(STATIC_LIBS:lib%.a.xyzzy=$(DESTDIR)$(libdir)/lib%.a) 132 | install-include: $(ALL_INCLUDES:src/include/$(package)/%.h=$(DESTDIR)$(includedir)/$(package)/%.h) $(EXTRA_INCLUDES:src/include/%.h=$(DESTDIR)$(includedir)/%.h) 133 | install-pkgconfig: $(PC_TARGETS:%=$(DESTDIR)$(pkgconfdir)/%) 134 | 135 | tests: $(TEST_BINS) 136 | 137 | check: tests 138 | @for i in $(TEST_BINS) ; do ./tools/run-test.sh $$i || exit 1 ; done 139 | 140 | ifneq ($(exthome),) 141 | 142 | $(DESTDIR)$(exthome): $(DESTDIR)$(home) 143 | exec $(INSTALL) -l $(notdir $(home)) $(DESTDIR)$(exthome) 144 | 145 | update: $(DESTDIR)$(exthome) 146 | 147 | global-links: $(DESTDIR)$(exthome) $(SHARED_LIBS:lib%.so.xyzzy=$(DESTDIR)$(sproot)/library.so/lib%.so.$(version_M)) $(BIN_TARGETS:%=$(DESTDIR)$(sproot)/command/%) $(BIN_SYMLINKS:%=$(DESTDIR)$(sproot)/command/%) 148 | 149 | $(DESTDIR)$(sproot)/command/%: $(DESTDIR)$(home)/command/% 150 | exec $(INSTALL) -D -l ..$(subst $(sproot),,$(exthome))/command/$( 4 | 5 | #ifndef SKALIBS_HASCLOCKBOOT 6 | # error "CLOCK_BOOTTIME required" 7 | #endif 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #ifdef SKALIBS_HASGETRANDOM 16 | #include 17 | #endif 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | #define USAGE "rngseed [ -d seeddir ] [ -v verbosity ] [ -r | -R ] [ -n | -N ] [ -w | -W ]" 35 | #define dieusage() strerr_dieusage(100, USAGE) 36 | 37 | #define RNGSEED_HASH_PREFIX "SeedRNG v1 Old+New Prefix" 38 | 39 | struct rngseed_flags_s 40 | { 41 | unsigned int read: 1 ; 42 | unsigned int rcred: 1 ; 43 | unsigned int block: 1 ; 44 | unsigned int write: 1 ; 45 | unsigned int wcred: 1 ; 46 | } ; 47 | #define RNGSEED_FLAGS_ZERO { .read = 0, .rcred = 1, .block = 1, .write = 0, .wcred = 1 } 48 | 49 | struct randpoolinfo_s 50 | { 51 | int entropy_count ; 52 | int buf_size ; 53 | char buffer[512] ; 54 | } ; 55 | 56 | static inline int rngseed_read_seed_nb (char *s, size_t len) 57 | { 58 | int wcred ; 59 | size_t w = 0 ; 60 | #ifdef SKALIBS_HASGETRANDOM 61 | while (w < len) 62 | { 63 | ssize_t r = getrandom(s + w, len - w, GRND_NONBLOCK) ; 64 | if (r == -1) 65 | { 66 | if (errno == EINTR) continue ; 67 | if (error_isagain(errno)) break ; 68 | strerr_diefu1sys(111, "getrandom") ; 69 | } 70 | else w += r ; 71 | } 72 | wcred = w >= len ; 73 | if (!wcred) 74 | #else 75 | tain dummy = TAIN_EPOCH ; 76 | iopause_fd x = { .events = IOPAUSE_READ } ; 77 | x.fd = openbc_read("/dev/random") ; 78 | if (x.fd == -1) strerr_diefu2sys(111, "open ", "/dev/random") ; 79 | wcred = iopause(&x, 1, &dummy, &dummy) ; 80 | if (wcred == -1) strerr_diefu1sys(111, "iopause") ; 81 | fd_close(x.fd) ; 82 | #endif 83 | random_devurandom(s + w, len - w) ; 84 | return wcred ; 85 | } 86 | 87 | int main (int argc, char const *const *argv) 88 | { 89 | blake2s_ctx ctx = BLAKE2S_INIT(32) ; 90 | char const *seeddir = RNGSEED_DIR ; 91 | struct rngseed_flags_s flags = RNGSEED_FLAGS_ZERO ; 92 | unsigned int verbosity = 1 ; 93 | PROG = "rngseed" ; 94 | { 95 | subgetopt l = SUBGETOPT_ZERO ; 96 | for (;;) 97 | { 98 | int opt = subgetopt_r(argc, argv, "d:v:rRnNwW", &l) ; 99 | if (opt == -1) break ; 100 | switch (opt) 101 | { 102 | case 'd' : seeddir = l.arg ; break ; 103 | case 'v' : if (!uint0_scan(l.arg, &verbosity)) dieusage() ; break ; 104 | case 'r' : flags.read = 1 ; flags.rcred = 1 ; break ; 105 | case 'R' : flags.read = 1 ; flags.rcred = 0 ; break ; 106 | case 'n' : flags.block = 0 ; break ; 107 | case 'N' : flags.block = 1 ; break ; 108 | case 'w' : flags.write = 1 ; flags.wcred = 1 ; break ; 109 | case 'W' : flags.write = 1 ; flags.wcred = 0 ; break ; 110 | default : dieusage() ; 111 | } 112 | } 113 | argc -= l.ind ; argv += l.ind ; 114 | } 115 | 116 | { 117 | size_t dirlen = strlen(seeddir) ; 118 | char file[dirlen + 6] ; 119 | memcpy(file, seeddir, dirlen) ; 120 | while (dirlen && file[dirlen-1] == '/') dirlen-- ; 121 | memcpy(file + dirlen, "/seed", 6) ; 122 | 123 | if (flags.write) 124 | { 125 | struct timespec ts ; 126 | if (dirlen) 127 | { 128 | file[dirlen] = 0 ; 129 | if (mkdirp2(file, 0700) == -1) 130 | { 131 | struct stat st ; 132 | if (errno != EEXIST) strerr_diefu2sys(111, "mkdir ", file) ; 133 | if (stat(file, &st) == -1) 134 | strerr_diefu2sys(111, "stat ", file) ; 135 | if (st.st_mode & 0077) 136 | { 137 | if (verbosity) 138 | strerr_warnw2sys(file, "has permissive modes, changing it to 0700") ; 139 | if (chmod(file, 0700) == -1) 140 | strerr_diefu2sys(111, "chmod ", file) ; 141 | } 142 | } 143 | file[dirlen] = '/' ; 144 | } 145 | blake2s_update(&ctx, RNGSEED_HASH_PREFIX, sizeof(RNGSEED_HASH_PREFIX) - 1) ; 146 | clock_gettime(CLOCK_REALTIME, &ts) ; 147 | blake2s_update(&ctx, (char *)&ts, sizeof ts) ; 148 | clock_gettime(CLOCK_BOOTTIME, &ts) ; 149 | blake2s_update(&ctx, (char *)&ts, sizeof ts) ; 150 | } 151 | 152 | if (flags.read) 153 | { 154 | struct randpoolinfo_s req ; 155 | struct stat st ; 156 | size_t seedlen ; 157 | int fd ; 158 | if (verbosity >= 2) strerr_warni2x("reading seed from ", file) ; 159 | fd = openbc_read(file) ; 160 | if (fd == -1) strerr_diefu2sys(111, "open ", file) ; 161 | errno = 0 ; 162 | seedlen = allread(fd, req.buffer, 512) ; 163 | if (errno) strerr_diefu2sys(111, "read from ", file) ; 164 | if (!seedlen) strerr_dief2x(100, "empty ", file) ; 165 | if (fstat(fd, &st) == -1) strerr_diefu2sys(111, "stat ", file) ; 166 | if (unlink(file) == -1) strerr_diefu2sys(111, "unlink ", file) ; 167 | fd_close(fd) ; 168 | if (flags.write) 169 | { 170 | blake2s_update(&ctx, (char *)&seedlen, sizeof(seedlen)) ; 171 | blake2s_update(&ctx, req.buffer, seedlen) ; 172 | } 173 | if (flags.rcred && st.st_mode & S_IWUSR && verbosity) 174 | strerr_warnw2x(file, " was not marked as creditable") ; 175 | req.entropy_count = flags.rcred && !(st.st_mode & S_IWUSR) ? (seedlen << 3) : 0 ; 176 | req.buf_size = seedlen ; 177 | fd = openbc_read("/dev/urandom") ; 178 | if (fd == -1) strerr_diefu2sys(111, "open ", "/dev/urandom") ; 179 | if (verbosity >= 2) 180 | { 181 | char fmt[SIZE_FMT] ; 182 | fmt[size_fmt(fmt, seedlen << 3)] = 0 ; 183 | strerr_warni4x("seeding with ", fmt, " bits", req.entropy_count ? "" : " without crediting") ; 184 | } 185 | if (ioctl(fd, RNDADDENTROPY, &req) == -1) 186 | strerr_diefu1sys(111, "seed") ; 187 | fd_close(fd) ; 188 | } 189 | 190 | if (flags.block) 191 | { 192 | if (verbosity >= 2) 193 | strerr_warni1x("waiting for the entropy pool to initialize") ; 194 | #ifdef SKALIBS_HASGETRANDOM 195 | char c ; 196 | ssize_t r = getrandom(&c, 1, 0) ; 197 | if (r == -1) strerr_diefu1sys(111, "getrandom") ; 198 | #else 199 | iopause_fd x = { .events = IOPAUSE_READ } ; 200 | x.fd = openbc_read("/dev/random") ; 201 | if (x.fd == -1) strerr_diefu2sys(111, "open ", "/dev/random") ; 202 | if (iopause(&x, 1, 0, 0) == -1) strerr_diefu1sys(111, "iopause") ; 203 | fd_close(x.fd) ; 204 | #endif 205 | } 206 | 207 | if (flags.write) 208 | { 209 | char seed[512] ; 210 | size_t len = 512 ; 211 | int wcred = 1 ; 212 | char s[SIZE_FMT] = "" ; 213 | int fd = openbc_read("/proc/sys/kernel/random/poolsize") ; 214 | if (fd < 0) 215 | { 216 | if (verbosity) strerr_warnwu2sys("open ", "/proc/sys/kernel/random/poolsize") ; 217 | } 218 | else 219 | { 220 | size_t r ; 221 | errno = 0 ; 222 | r = allread(fd, s, SIZE_FMT - 1) ; 223 | if (errno) 224 | { 225 | if (verbosity) strerr_warnwu2sys("read from ", "/proc/sys/kernel/random/poolsize") ; 226 | } 227 | else 228 | { 229 | s[r] = 0 ; 230 | if (!size_scan(s, &r)) 231 | { 232 | if (verbosity) strerr_warnwu2sys("understand ", "/proc/sys/kernel/random/poolsize") ; 233 | } 234 | else len = (r + 7) >> 3 ; 235 | } 236 | fd_close(fd) ; 237 | } 238 | if (len < 32) len = 32 ; 239 | if (len > 512) len = 512 ; 240 | 241 | if (verbosity >= 2) 242 | { 243 | s[size_fmt(s, len << 3)] = 0 ; 244 | strerr_warni3x("reading ", s, " bits of random to make the seed") ; 245 | } 246 | if (flags.block) random_buf(seed, len) ; 247 | else wcred = rngseed_read_seed_nb(seed, len) ; 248 | if (!wcred && verbosity) strerr_warnwu1x("make the seed creditable") ; 249 | blake2s_update(&ctx, (char *)&len, sizeof(len)) ; 250 | blake2s_update(&ctx, seed, len) ; 251 | blake2s_final(&ctx, seed + len - 32) ; 252 | if (verbosity >= 2) strerr_warni2x("writing seed to ", file) ; 253 | umask(0077) ; 254 | if (!openwritenclose_unsafe_sync(file, seed, len)) 255 | strerr_diefu2sys(111, "write to ", file) ; 256 | if (flags.wcred && wcred) 257 | { 258 | if (chmod(file, 0400) == -1 && verbosity) 259 | strerr_warnwu3sys("mark ", file, "as creditable") ; 260 | } 261 | } 262 | } 263 | 264 | return 0 ; 265 | } 266 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Build Instructions 2 | ------------------ 3 | 4 | * Requirements 5 | ------------ 6 | 7 | - A Linux-based system with a standard C development environment 8 | - GNU make version 3.81 or later 9 | - skalibs version 2.14.5.0 or later: https://skarnet.org/software/skalibs/ 10 | 11 | This software is Linux-specific. It will run on a Linux kernel, 12 | version 3.5 or later. 13 | 14 | 15 | * Standard usage 16 | -------------- 17 | 18 | ./configure && make && sudo make install 19 | 20 | will work for most users. 21 | It will install the binaries in /bin. 22 | 23 | You can strip the binaries and libraries of their extra symbols via 24 | "make strip" before the "make install" phase. It will shave a few bytes 25 | off them. 26 | 27 | 28 | * pkg-config 29 | ---------- 30 | 31 | pkg-config is a tool used by some Linux and BSD distributions, providing 32 | a registry to store policy information about libraries exported by a 33 | software package; that is supposed to make it easier to build software 34 | depending on these libraries, by having a tool to automatically extract 35 | the various flags to pass to the compiler and linker in order to correctly 36 | build against these libraries. 37 | This package supports pkg-config, but you need to explicitly ask for it: 38 | - To use the pkg-config tool to *read* information from the registry and 39 | use it to build *this* package: --with-pkgconfig[=PROG]. This assumes 40 | PROG supports the pkg-config interface (as the popular pkgconf 41 | implementation does). If PROG is not supplied, the PKG_CONFIG environment 42 | variable is used to find the program to use, and if empty/unset, it defaults 43 | to pkg-config. 44 | - To build a .pc file for each library exported by this package, and then 45 | install it to the pkg-config registry, in other words to *write* information 46 | so that other software can use pkg-config to build against this package, 47 | use --enable-pkgconfig. 48 | 49 | pkg-config and slashpackage (see below) configure options can be set 50 | together, but the slashpackage convention provides its own installation 51 | policies that generally make it unnecessary to use pkg-config. You 52 | probably should not mix both. 53 | 54 | 55 | * Customization 56 | ------------- 57 | 58 | You can customize paths via flags given to configure. 59 | See ./configure --help for a list of all available configure options. 60 | 61 | 62 | * Environment variables 63 | --------------------- 64 | 65 | Controlling a build process via environment variables is a big and 66 | dangerous hammer. You should try and pass flags to configure instead; 67 | nevertheless, a few standard environment variables are recognized. 68 | 69 | If the CC environment variable is set, its value will override compiler 70 | detection by configure. The --host=HOST option will still add a HOST- 71 | prefix to the value of CC. 72 | 73 | The values of CFLAGS, CPPFLAGS and LDFLAGS will be appended to flags 74 | auto-detected by configure. To entirely override the flags set by 75 | configure instead, use make variables. 76 | 77 | 78 | * Make variables 79 | -------------- 80 | 81 | You can invoke make with a few variables for more configuration. 82 | 83 | CC, CFLAGS, CPPFLAGS, LDFLAGS, LDLIBS, AR, RANLIB, STRIP, INSTALL and 84 | CROSS_COMPILE can all be overridden on the make command line. This is 85 | an even bigger hammer than running ./configure with environment 86 | variables, so it is advised to only do this when it is the only way of 87 | obtaining the behaviour you want. 88 | 89 | DESTDIR can be given on the "make install" command line in order to 90 | install to a staging directory. 91 | 92 | 93 | * Shared libraries 94 | ---------------- 95 | 96 | Software from skarnet.org is small enough that shared libraries are 97 | generally not worth using. Static linking is simpler and incurs less 98 | runtime overhead and less points of failure: so by default, shared 99 | libraries are not built and binaries are linked against the static 100 | versions of the skarnet.org libraries. Nevertheless, you can: 101 | * build shared libraries: --enable-shared 102 | * link binaries against shared libraries: --disable-allstatic 103 | 104 | 105 | * Static binaries 106 | --------------- 107 | 108 | By default, binaries are linked against static versions of all the 109 | libraries they depend on, except for the libc. You can enforce 110 | linking against the static libc with --enable-static-libc. 111 | 112 | Be aware that the GNU libc behaves badly with static linking and 113 | produces huge executables, which is why it is not the default. 114 | Other libcs are better suited to static linking, for instance 115 | musl: http://musl-libc.org/ 116 | 117 | 118 | * Cross-compilation 119 | ----------------- 120 | 121 | skarnet.org packages centralize all the difficulty of 122 | cross-compilation in one place: skalibs. Once you have 123 | cross-compiled skalibs, the rest is easy. 124 | 125 | * Use the --host=HOST option to configure, HOST being the triplet 126 | for your target. 127 | * Make sure your cross-toolchain binaries (i.e. prefixed with HOST-) 128 | are accessible via your PATH environment variable. 129 | * Make sure to use the correct version of skalibs for your target, 130 | and the correct sysdeps directory, making use of the 131 | --with-include, --with-lib, --with-dynlib and --with-sysdeps 132 | options as necessary. 133 | 134 | 135 | * The slashpackage convention 136 | --------------------------- 137 | 138 | The slashpackage convention (http://cr.yp.to/slashpackage.html) 139 | is a package installation scheme that provides a few guarantees 140 | over other conventions such as the FHS, for instance fixed 141 | absolute pathnames. skarnet.org packages support it: use the 142 | --enable-slashpackage option to configure, or 143 | --enable-slashpackage=DIR for a prefixed DIR/package tree. 144 | This option will activate slashpackage support during the build 145 | and set slashpackage-compatible installation directories. 146 | If $package_home is the home of the package, defined as 147 | DIR/package/$category/$package-$version with the variables 148 | read from the package/info file, then: 149 | 150 | --dynlibdir is set to $package_home/library.so 151 | --bindir is set to $package_home/command 152 | --sbindir is also set to $package_home/command (slashpackage 153 | differentiates root-only binaries by their Unix rights, not their 154 | location in the filesystem) 155 | --libexecdir is also set to $package_home/command (slashpackage 156 | does not need a specific directory for internal binaries) 157 | --libdir is set to $package_home/library 158 | --includedir is set to $package_home/include 159 | 160 | --prefix is pretty much ignored when you use --enable-slashpackage. 161 | You should probably not use both --enable-slashpackage and --prefix. 162 | 163 | When using slashpackage, two additional Makefile targets are 164 | available after "make install": 165 | - "make update" changes the default version of the software to the 166 | freshly installed one. (This is useful when you have several installed 167 | versions of the same software, which slashpackage supports.) 168 | - "make -L global-links" adds links from /command and /library.so to the 169 | default version of the binaries and shared libraries. The "-L" option to 170 | make is necessary because targets are symbolic links, and the default make 171 | behaviour is to check the pointed file's timestamp and not the symlink's 172 | timestamp. 173 | 174 | 175 | * Absolute pathnames 176 | ------------------ 177 | 178 | You may want to use fixed absolute pathnames even if you're not 179 | following the slashpackage convention: for instance, the Nix packaging 180 | system prefers calling binaries with immutable paths rather than rely on 181 | PATH resolution. If you are in that case, use the --enable-absolute-paths 182 | option to configure. This will ensure that programs calling binaries from 183 | this package will call them with their full installation path (in bindir) 184 | without relying on a PATH search. 185 | 186 | 187 | * Out-of-tree builds 188 | ------------------ 189 | 190 | skarnet.org packages do not support out-of-tree builds. They 191 | are small, so it does not cost much to duplicate the entire 192 | source tree if parallel builds are needed. 193 | 194 | 195 | * Multicall binary 196 | ---------------- 197 | 198 | Starting with version 2.6.1.0, the s6-linux-utils package comes 199 | with an alternative build in the form of a multicall binary, simply 200 | called "s6-linux-utils", that includes the functionality of *all* 201 | the other binaries; it switches functionalities depending on the name 202 | it is called with, or the subcommand it is given: 203 | "s6-linux-utils s6-ps -H" will print a tree of the current running 204 | processes, same as "s6-ps -H" if s6-ps is a link to the 205 | s6-linux-utils program. 206 | 207 | To use this, use the --enable-multicall option to configure. Only 208 | the s6-linux-utils binary will be built, and other programs will be 209 | created as symbolic links to s6-linux-utils at installation time. 210 | 211 | The multicall setup saves a lot of disk space, at the price of 212 | an unnoticeable amount of CPU usage. RAM usage is about equivalent 213 | and difficult to assess. The setup is meant for embedded devices 214 | or small distributions with a focus on saving disk space. 215 | -------------------------------------------------------------------------------- /src/s6-linux-utils/s6-ps.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "s6ps.h" 31 | 32 | #define USAGE "s6-ps [ -H ] [ -w spacing ] [ -W wchanfile ] [ -l | -o field,field... ]" 33 | 34 | #define RIGHTFORMATTED ( \ 35 | (1ULL << PFIELD_PID) | \ 36 | (1ULL << PFIELD_PPID) | \ 37 | (1ULL << PFIELD_PGRP) | \ 38 | (1ULL << PFIELD_SESSION) | \ 39 | (1ULL << PFIELD_TPGID) | \ 40 | (1ULL << PFIELD_MINFLT) | \ 41 | (1ULL << PFIELD_CMINFLT) | \ 42 | (1ULL << PFIELD_MAJFLT) | \ 43 | (1ULL << PFIELD_CMAJFLT) | \ 44 | (1ULL << PFIELD_PRIO) | \ 45 | (1ULL << PFIELD_NICE) | \ 46 | (1ULL << PFIELD_THREADS) | \ 47 | (1ULL << PFIELD_VSIZE) | \ 48 | (1ULL << PFIELD_RSS) | \ 49 | (1ULL << PFIELD_RSSLIM) | \ 50 | (1ULL << PFIELD_CPUNO) | \ 51 | (1ULL << PFIELD_RTPRIO) | \ 52 | (1ULL << PFIELD_PMEM) | \ 53 | (1ULL << PFIELD_PCPU) | \ 54 | (1ULL << PFIELD_CPCPU)) 55 | 56 | static void *pid_dtok (unsigned int d, void *x) 57 | { 58 | return &((pscan_t *)x)[d].pid ; 59 | } 60 | 61 | static int ps_fillo_notree (unsigned int i, unsigned int h, void *x) 62 | { 63 | static unsigned int j = 0 ; 64 | unsigned int *list = x ; 65 | list[j++] = i ; 66 | (void)h ; 67 | return 1 ; 68 | } 69 | 70 | static inline unsigned int ps_fieldscan (char const *s, pfield_t *list, uint64_t *fbf) 71 | { 72 | uint64_t bits = 0 ; 73 | unsigned int n = 0 ; 74 | int cont = 1 ; 75 | for (; cont ; n++) 76 | { 77 | size_t len = str_chr(s, ',') ; 78 | pfield_t i = 0 ; 79 | if (!len) strerr_dief3x(100, "invalid", " (empty)", " field for -o option") ; 80 | if (!s[len]) cont = 0 ; 81 | { 82 | char tmp[len+1] ; 83 | memcpy(tmp, s, len) ; 84 | tmp[len] = 0 ; 85 | for (; i < PFIELD_PHAIL ; i++) if (!strcmp(tmp, s6ps_opttable[i])) break ; 86 | if (i >= PFIELD_PHAIL) 87 | strerr_dief4x(100, "invalid", " field for -o option", ": ", tmp) ; 88 | if (bits & (1ULL << i)) 89 | strerr_dief4x(100, "duplicate", " field for -o option", ": ", tmp) ; 90 | } 91 | s += len + 1 ; 92 | list[n] = i ; 93 | bits |= ((uint64_t)1 << i) ; 94 | } 95 | *fbf = bits ; 96 | return n ; 97 | } 98 | 99 | static int ps_slurpit (unsigned int dirfd, stralloc *data, char const *buf, char const *what, size_t *len) 100 | { 101 | size_t start = data->len ; 102 | int fd = open_readat(dirfd, what) ; 103 | if (fd < 0) return 0 ; 104 | if (!slurp(data, fd)) strerr_diefu4sys(111, "slurp ", buf, "/", what) ; 105 | fd_close(fd) ; 106 | *len = data->len - start ; 107 | return 1 ; 108 | } 109 | 110 | int main (int argc, char const *const *argv) 111 | { 112 | genalloc pscans = GENALLOC_ZERO ; /* array of pscan_t */ 113 | pfield_t fieldlist[PFIELD_PHAIL] = { PFIELD_USER, PFIELD_PID, PFIELD_TTY, PFIELD_STATE, PFIELD_START, PFIELD_ARGS } ; 114 | uint64_t fbf = (1 << PFIELD_USER) | (1 << PFIELD_PID) | (1 << PFIELD_TTY) | (1 << PFIELD_STATE) | (1 << PFIELD_START) | (1 << PFIELD_ARGS) ; 115 | size_t mypos = 0 ; 116 | unsigned int nfields = 6 ; 117 | pscan_t *p ; 118 | size_t n ; 119 | unsigned int spacing = 2 ; 120 | int flagtree = 0 ; 121 | char const *wchanfile = 0 ; 122 | int needstat ; 123 | PROG = "s6-ps" ; 124 | 125 | { 126 | subgetopt l = SUBGETOPT_ZERO ; 127 | for (;;) 128 | { 129 | int opt = subgetopt_r(argc, argv, "Hlw:W:o:", &l) ; 130 | if (opt == -1) break ; 131 | switch (opt) 132 | { 133 | case 'H' : flagtree = 1 ; break ; 134 | case 'l' : 135 | { 136 | nfields = 11 ; 137 | fbf = (1ULL << PFIELD_USER) | (1ULL << PFIELD_PID) | (1ULL << PFIELD_CPCPU) | (1ULL << PFIELD_PMEM) | (1ULL << PFIELD_VSIZE) | (1ULL << PFIELD_RSS) | (1ULL << PFIELD_TTY) | (1ULL << PFIELD_STATE) | (1ULL << PFIELD_START) | (1ULL << PFIELD_CTTIME) | (1ULL << PFIELD_ARGS) ; 138 | fieldlist[0] = PFIELD_USER ; 139 | fieldlist[1] = PFIELD_PID ; 140 | fieldlist[2] = PFIELD_CPCPU ; 141 | fieldlist[3] = PFIELD_PMEM ; 142 | fieldlist[4] = PFIELD_VSIZE ; 143 | fieldlist[5] = PFIELD_RSS ; 144 | fieldlist[6] = PFIELD_TTY ; 145 | fieldlist[7] = PFIELD_STATE ; 146 | fieldlist[8] = PFIELD_START ; 147 | fieldlist[9] = PFIELD_CTTIME ; 148 | fieldlist[10] = PFIELD_ARGS ; 149 | break ; 150 | } 151 | case 'w' : 152 | { 153 | if (!uint0_scan(l.arg, &spacing)) strerr_dieusage(100, USAGE) ; 154 | break ; 155 | } 156 | case 'W' : wchanfile = l.arg ; break ; 157 | case 'o' : 158 | { 159 | nfields = ps_fieldscan(l.arg, fieldlist, &fbf) ; 160 | break ; 161 | } 162 | default : strerr_dieusage(100, USAGE) ; 163 | } 164 | } 165 | argc -= l.ind ; argv += l.ind ; 166 | } 167 | 168 | if (!spacing) spacing = 1 ; 169 | if (spacing > 256) spacing = 256 ; 170 | 171 | needstat = flagtree || !!(fbf & ( 172 | (1ULL << PFIELD_PID) | 173 | (1ULL << PFIELD_COMM) | 174 | (1ULL << PFIELD_STATE) | 175 | (1ULL << PFIELD_PPID) | 176 | (1ULL << PFIELD_PGRP) | 177 | (1ULL << PFIELD_SESSION) | 178 | (1ULL << PFIELD_TTY) | 179 | (1ULL << PFIELD_TPGID) | 180 | (1ULL << PFIELD_MINFLT) | 181 | (1ULL << PFIELD_CMINFLT) | 182 | (1ULL << PFIELD_MAJFLT) | 183 | (1ULL << PFIELD_CMAJFLT) | 184 | (1ULL << PFIELD_UTIME) | 185 | (1ULL << PFIELD_STIME) | 186 | (1ULL << PFIELD_CUTIME) | 187 | (1ULL << PFIELD_CSTIME) | 188 | (1ULL << PFIELD_PRIO) | 189 | (1ULL << PFIELD_NICE) | 190 | (1ULL << PFIELD_THREADS) | 191 | (1ULL << PFIELD_START) | 192 | (1ULL << PFIELD_VSIZE) | 193 | (1ULL << PFIELD_RSS) | 194 | (1ULL << PFIELD_RSSLIM) | 195 | (1ULL << PFIELD_CPUNO) | 196 | (1ULL << PFIELD_RTPRIO) | 197 | (1ULL << PFIELD_RTPOLICY) | 198 | (1ULL << PFIELD_PMEM) | 199 | (1ULL << PFIELD_WCHAN) | 200 | (1ULL << PFIELD_PCPU) | 201 | (1ULL << PFIELD_TTIME) | 202 | (1ULL << PFIELD_CTTIME) | 203 | (1ULL << PFIELD_TSTART) | 204 | (1ULL << PFIELD_CPCPU))) ; 205 | 206 | 207 | /* Scan /proc */ 208 | 209 | { 210 | int needstatdir = !!(fbf & ((1 << PFIELD_USER) | (1 << PFIELD_GROUP))) ; 211 | pid_t mypid = getpid() ; 212 | DIR *dir = opendir("/proc") ; 213 | direntry *d ; 214 | char buf[25] = "/proc/" ; 215 | 216 | if (!dir) strerr_diefu1sys(111, "open /proc") ; 217 | for (;;) 218 | { 219 | pscan_t pscan = PSCAN_ZERO ; 220 | uint64_t u ; 221 | int dirfd ; 222 | errno = 0 ; 223 | d = readdir(dir) ; 224 | if (!d) break ; 225 | if (!uint640_scan(d->d_name, &u)) continue ; 226 | pscan.pid = u ; 227 | strcpy(buf+6, d->d_name) ; 228 | dirfd = open_read(buf) ; 229 | if (dirfd < 0) continue ; 230 | 231 | if (needstatdir) 232 | { 233 | struct stat st ; 234 | if (fstat(dirfd, &st) < 0) goto errindir ; 235 | pscan.uid = st.st_uid ; 236 | pscan.gid = st.st_gid ; 237 | } 238 | if (needstat) 239 | { 240 | if (!ps_slurpit(dirfd, &pscan.data, buf, "stat", &pscan.statlen)) 241 | goto errindir ; 242 | if (!ps_slurpit(dirfd, &pscan.data, buf, "comm", &pscan.commlen)) 243 | goto errindir ; 244 | if (pscan.commlen) { pscan.commlen-- ; pscan.data.len-- ; } 245 | } 246 | if (fbf & (1 << PFIELD_ARGS)) 247 | { 248 | if (!ps_slurpit(dirfd, &pscan.data, buf, "cmdline", &pscan.cmdlen)) goto errindir ; 249 | while (!pscan.data.s[pscan.data.len-1]) 250 | { 251 | pscan.cmdlen-- ; 252 | pscan.data.len-- ; 253 | } 254 | } 255 | if (fbf & (1 << PFIELD_ENV)) ps_slurpit(dirfd, &pscan.data, buf, "environ", &pscan.envlen) ; 256 | fd_close(dirfd) ; 257 | if (!genalloc_append(pscan_t, &pscans, &pscan)) 258 | strerr_diefu1sys(111, "genalloc_append") ; 259 | if (pscan.pid == mypid) mypos = genalloc_len(pscan_t, &pscans) ; 260 | continue ; 261 | errindir: 262 | fd_close(dirfd) ; 263 | stralloc_free(&pscan.data) ; 264 | } 265 | if (errno) strerr_diefu1sys(111, "readdir /proc") ; 266 | dir_close(dir) ; 267 | } 268 | 269 | /* Add a process 0 as a root and sentinel */ 270 | { 271 | pscan_t pscan = { .pid = 0, .ppid = 0 } ; 272 | if (!genalloc_append(pscan_t, &pscans, &pscan)) strerr_diefu1sys(111, "genalloc_append") ; 273 | } 274 | 275 | p = genalloc_s(pscan_t, &pscans) ; 276 | n = genalloc_len(pscan_t, &pscans) - 1 ; 277 | 278 | { 279 | s6ps_auxinfo_t aux = S6PS_AUXINFO_ZERO ; 280 | unsigned int i = 0 ; 281 | unsigned int orderedlist[n+1] ; /* 1st element will be 0, ignored */ 282 | 283 | /* Order the processes for display */ 284 | 285 | { 286 | AVLTREEN_DECLARE_AND_INIT(pidtree, n+1, &pid_dtok, &s6ps_uint32_cmp, p) ; 287 | for (i = 0 ; i < n ; i++) 288 | { 289 | if (needstat && !s6ps_statparse(p+i)) 290 | strerr_diefu1sys(111, "parse process stats") ; 291 | if (!avltreen_insert(&pidtree, i)) 292 | strerr_diefu1sys(111, "avltreen_insert") ; 293 | } 294 | if (!avltreen_insert(&pidtree, n)) 295 | strerr_diefu1sys(111, "avltreen_insert") ; 296 | 297 | if (flagtree) s6ps_otree(p, n+1, &pidtree, orderedlist) ; 298 | else avltreen_iter_nocancel(&pidtree, avltreen_totalsize(&pidtree), &ps_fillo_notree, orderedlist) ; 299 | } 300 | 301 | 302 | /* Format, compute length, output */ 303 | 304 | if (fbf & ((1ULL << PFIELD_START) | (1ULL << PFIELD_TSTART) | (1ULL << PFIELD_PCPU) | (1ULL << PFIELD_CPCPU))) 305 | { 306 | tain_wallclock_read_g() ; 307 | s6ps_compute_boottime(&aux, p, mypos) ; 308 | } 309 | if (fbf & (1ULL << PFIELD_USER) && !s6ps_cache_init(&aux.caches[0])) 310 | strerr_diefu1sys(111, "init user name cache") ; 311 | if (fbf & (1ULL << PFIELD_GROUP) && !s6ps_cache_init(&aux.caches[1])) 312 | strerr_diefu1sys(111, "init group name cache") ; 313 | if (fbf & (1ULL << PFIELD_TTY) && !s6ps_cache_init(&aux.caches[2])) 314 | strerr_diefu1sys(111, "init tty name cache") ; 315 | if (fbf & (1ULL << PFIELD_WCHAN) && !s6ps_wchan_init(&aux.wchan, wchanfile)) 316 | { 317 | if (wchanfile) strerr_warnwu2sys("init wchan file ", wchanfile) ; 318 | else strerr_warnwu1sys("init wchan") ; 319 | } 320 | 321 | { 322 | size_t fmtpos[n][nfields] ; 323 | size_t fmtlen[n][nfields] ; 324 | size_t maxlen[nfields] ; 325 | unsigned int maxspaces = 0 ; 326 | for (i = 0 ; i < nfields ; i++) maxlen[i] = strlen(s6ps_fieldheaders[fieldlist[i]]) ; 327 | for (i = 0 ; i < n ; i++) 328 | { 329 | unsigned int j = 0 ; 330 | for (; j < nfields ; j++) 331 | { 332 | if (!(*s6ps_pfield_fmt[fieldlist[j]])(&aux, p+i, &fmtpos[i][j], &fmtlen[i][j])) 333 | strerr_diefu1sys(111, "format fields") ; 334 | if (fmtlen[i][j] > maxlen[j]) maxlen[j] = fmtlen[i][j] ; 335 | } 336 | } 337 | for (i = 0 ; i < nfields ; i++) 338 | if (maxlen[i] > maxspaces) maxspaces = maxlen[i] ; 339 | maxspaces += spacing ; 340 | if (fbf & (1ULL << PFIELD_USER)) s6ps_cache_finish(&aux.caches[0]) ; 341 | if (fbf & (1ULL << PFIELD_GROUP)) s6ps_cache_finish(&aux.caches[1]) ; 342 | if (fbf & (1ULL << PFIELD_TTY)) s6ps_cache_finish(&aux.caches[2]) ; 343 | if (fbf & (1ULL << PFIELD_WCHAN)) s6ps_wchan_finish(&aux.wchan) ; 344 | stralloc_free(&satmp) ; 345 | { 346 | char spaces[maxspaces] ; 347 | for (i = 0 ; i < maxspaces ; i++) spaces[i] = ' ' ; 348 | for (i = 0 ; i < nfields ; i++) 349 | { 350 | unsigned int rightformatted = !!(((uint64_t)1 << fieldlist[i]) & RIGHTFORMATTED) ; 351 | size_t len = strlen(s6ps_fieldheaders[fieldlist[i]]) ; 352 | if (rightformatted && (buffer_put(buffer_1, spaces, maxlen[i] - len) < (ssize_t)(maxlen[i] - len))) 353 | goto nowrite ; 354 | if (buffer_put(buffer_1, s6ps_fieldheaders[fieldlist[i]], len) < (ssize_t)len) 355 | goto nowrite ; 356 | if ((i < nfields-1) && (buffer_put(buffer_1, spaces, !rightformatted * (maxlen[i] - len) + spacing) < (ssize_t)(!rightformatted * (maxlen[i] - len) + spacing))) 357 | goto nowrite ; 358 | } 359 | if (buffer_put(buffer_1, "\n", 1) < 1) goto nowrite ; 360 | for (i = 0 ; i < n ; i++) 361 | { 362 | unsigned int oi = orderedlist[i+1] ; 363 | unsigned int j = 0 ; 364 | for (; j < nfields ; j++) 365 | { 366 | unsigned int rightformatted = !!(((uint64_t)1 << fieldlist[j]) & RIGHTFORMATTED) ; 367 | if (rightformatted && (buffer_put(buffer_1, spaces, maxlen[j] - fmtlen[oi][j]) < (ssize_t)(maxlen[j] - fmtlen[oi][j]))) 368 | goto nowrite ; 369 | if (buffer_put(buffer_1, p[oi].data.s + fmtpos[oi][j], fmtlen[oi][j]) < (ssize_t)fmtlen[oi][j]) 370 | goto nowrite ; 371 | 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))) 372 | goto nowrite ; 373 | } 374 | if (buffer_put(buffer_1, "\n", 1) < 1) goto nowrite ; 375 | } 376 | } 377 | } 378 | } 379 | buffer_flush(buffer_1) ; 380 | return 0 ; 381 | 382 | nowrite: 383 | strerr_diefu1sys(111, "write to stdout") ; 384 | } 385 | -------------------------------------------------------------------------------- /src/libs6ps/s6ps_pfield.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "s6ps.h" 17 | 18 | static char const *const fieldheaders[PFIELD_PHAIL] = 19 | { 20 | "PID", 21 | "COMM", 22 | "STAT", 23 | "PPID", 24 | "PGRP", 25 | "SESSION", 26 | "TTY", 27 | "TPGID", 28 | "MINFLT", 29 | "CMINFLT", 30 | "MAJFLT", 31 | "CMAJFLT", 32 | "UTIME", 33 | "STIME", 34 | "CUTIME", 35 | "CSTIME", 36 | "PRIO", 37 | "NICE", 38 | "THREADS", 39 | "START", 40 | "VSZ", 41 | "RSS", 42 | "RSSLIM", 43 | "CPU", 44 | "RTPRIO", 45 | "RTPOLICY", 46 | "USER", 47 | "GROUP", 48 | "%MEM", 49 | "WCHAN", 50 | "COMMAND", 51 | "ENVIRONMENT", 52 | "%CPU", 53 | "TTIME", 54 | "CTTIME", 55 | "TSTART", 56 | "C%CPU" 57 | } ; 58 | 59 | char const *const *s6ps_fieldheaders = fieldheaders ; 60 | 61 | static char const *const opttable[PFIELD_PHAIL] = 62 | { 63 | "pid", 64 | "comm", 65 | "s", 66 | "ppid", 67 | "pgrp", 68 | "sess", 69 | "tty", 70 | "tpgid", 71 | "minflt", 72 | "cminflt", 73 | "majflt", 74 | "cmajflt", 75 | "utime", 76 | "stime", 77 | "cutime", 78 | "cstime", 79 | "prio", 80 | "nice", 81 | "thcount", 82 | "start", 83 | "vsize", 84 | "rss", 85 | "rsslimit", 86 | "psr", 87 | "rtprio", 88 | "policy", 89 | "user", 90 | "group", 91 | "pmem", 92 | "wchan", 93 | "args", 94 | "env", 95 | "pcpu", 96 | "ttime", 97 | "cttime", 98 | "tstart", 99 | "cpcpu" 100 | } ; 101 | 102 | char const *const *s6ps_opttable = opttable ; 103 | 104 | static int fmt_64 (pscan_t *p, size_t *pos, size_t *len, uint64_t u) 105 | { 106 | if (!stralloc_readyplus(&p->data, UINT64_FMT)) return 0 ; 107 | *pos = p->data.len ; 108 | *len = uint64_fmt(p->data.s + *pos, u) ; 109 | p->data.len += *len ; 110 | return 1 ; 111 | } 112 | 113 | static int fmt_i (pscan_t *p, size_t *pos, size_t *len, int d) 114 | { 115 | if (!stralloc_readyplus(&p->data, UINT32_FMT+1)) return 0 ; 116 | *pos = p->data.len ; 117 | *len = int_fmt(p->data.s + *pos, d) ; 118 | p->data.len += *len ; 119 | return 1 ; 120 | } 121 | 122 | static int fmt_pid (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 123 | { 124 | (void)aux ; 125 | return fmt_64(p, pos, len, p->pid) ; 126 | } 127 | 128 | static int fmt_comm (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 129 | { 130 | (void)aux ; 131 | *pos = p->statlen ; 132 | *len = p->commlen ; 133 | return 1 ; 134 | } 135 | 136 | static int fmt_s (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 137 | { 138 | (void)aux ; 139 | if (!stralloc_readyplus(&p->data, 4)) return 0 ; 140 | *pos = p->data.len ; 141 | p->data.s[p->data.len++] = p->data.s[p->state] ; 142 | if (p->pid == p->session) p->data.s[p->data.len++] = 's' ; 143 | if (p->threads > 1) p->data.s[p->data.len++] = 'l' ; 144 | if ((p->tpgid > 0) && ((unsigned int)p->tpgid == p->pgrp)) 145 | p->data.s[p->data.len++] = '+' ; 146 | if (p->nice) p->data.s[p->data.len++] = (p->nice < 0) ? '<' : 'N' ; 147 | 148 | *len = p->data.len - *pos ; 149 | return 1 ; 150 | } 151 | 152 | static int fmt_ppid (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 153 | { 154 | (void)aux ; 155 | return fmt_64(p, pos, len, p->ppid) ; 156 | } 157 | 158 | static int fmt_pgrp (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 159 | { 160 | (void)aux ; 161 | return fmt_64(p, pos, len, p->pgrp) ; 162 | } 163 | 164 | static int fmt_session (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 165 | { 166 | (void)aux ; 167 | return fmt_64(p, pos, len, p->session) ; 168 | } 169 | 170 | static int fmt_ttynr(s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 171 | { 172 | if (p->ttynr) 173 | { 174 | size_t tmppos = p->data.len ; 175 | if (!s6ps_ttycache_lookup(&aux->caches[2], &p->data, p->ttynr)) return 0 ; 176 | *pos = tmppos ; 177 | *len = p->data.len - tmppos ; 178 | } 179 | else 180 | { 181 | if (!stralloc_catb(&p->data, "-", 1)) return 0 ; 182 | *pos = p->data.len - 1 ; 183 | *len = 1 ; 184 | } 185 | return 1 ; 186 | } 187 | 188 | static int fmt_tpgid (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 189 | { 190 | (void)aux ; 191 | return p->tpgid < 0 ? fmt_i(p, pos, len, -1) : fmt_64(p, pos, len, p->tpgid) ; 192 | } 193 | 194 | static unsigned int gethz (s6ps_auxinfo_t *aux) 195 | { 196 | if (!aux->hz) 197 | { 198 | long jiffies = sysconf(_SC_CLK_TCK) ; 199 | if (jiffies < 1) 200 | { 201 | char fmt[ULONG_FMT + 1] ; 202 | fmt[long_fmt(fmt, jiffies)] = 0 ; 203 | strerr_warnw3x("invalid _SC_CLK_TCK value (", fmt, "), using 100") ; 204 | aux->hz = 100 ; 205 | } 206 | else aux->hz = (unsigned int)jiffies ; 207 | } 208 | return aux->hz ; 209 | } 210 | 211 | int s6ps_compute_boottime (s6ps_auxinfo_t *aux, pscan_t *p, unsigned int mypos) 212 | { 213 | if (!mypos--) 214 | { 215 | strerr_warnwu1x("compute boot time - using epoch") ; 216 | return 0 ; 217 | } 218 | else 219 | { 220 | unsigned int hz = gethz(aux) ; 221 | tain offset = { .sec = { .x = p[mypos].start / hz }, .nano = (p[mypos].start % hz) * (1000000000 / hz) } ; 222 | tain_sub(&aux->boottime, &STAMP, &offset) ; 223 | return 1 ; 224 | } 225 | } 226 | 227 | static int fmt_jiffies (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len, uint64_t j) 228 | { 229 | unsigned int hz = gethz(aux) ; 230 | uint32_t hrs, mins, secs, hfrac ; 231 | if (!stralloc_readyplus(&p->data, UINT64_FMT + 13)) return 0 ; 232 | hfrac = (j % hz) * 100 / hz ; 233 | *pos = p->data.len ; 234 | j /= hz ; 235 | secs = j % 60 ; j /= 60 ; 236 | mins = j % 60 ; j /= 60 ; 237 | hrs = j % 24 ; j /= 24 ; 238 | if (j) 239 | { 240 | p->data.len += uint64_fmt(p->data.s + p->data.len, j) ; 241 | p->data.s[p->data.len++] = 'd' ; 242 | } 243 | if (j || hrs) 244 | { 245 | uint320_fmt(p->data.s + p->data.len, hrs, 2) ; 246 | p->data.len += 2 ; 247 | p->data.s[p->data.len++] = 'h' ; 248 | } 249 | if (j || hrs || mins) 250 | { 251 | uint320_fmt(p->data.s + p->data.len, mins, 2) ; 252 | p->data.len += 2 ; 253 | p->data.s[p->data.len++] = 'm' ; 254 | } 255 | uint320_fmt(p->data.s + p->data.len, secs, 2) ; 256 | p->data.len += 2 ; 257 | if (!j && !hrs && !mins) 258 | { 259 | p->data.s[p->data.len++] = '.' ; 260 | uint320_fmt(p->data.s + p->data.len, hfrac, 2) ; 261 | p->data.len += 2 ; 262 | } 263 | p->data.s[p->data.len++] = 's' ; 264 | *len = p->data.len - *pos ; 265 | return 1 ; 266 | } 267 | 268 | static int fmt_minflt (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 269 | { 270 | (void)aux ; 271 | return fmt_64(p, pos, len, p->minflt) ; 272 | } 273 | 274 | static int fmt_cminflt (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 275 | { 276 | (void)aux ; 277 | return fmt_64(p, pos, len, p->cminflt) ; 278 | } 279 | 280 | static int fmt_majflt (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 281 | { 282 | (void)aux ; 283 | return fmt_64(p, pos, len, p->majflt) ; 284 | } 285 | 286 | static int fmt_cmajflt (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 287 | { 288 | (void)aux ; 289 | return fmt_64(p, pos, len, p->cmajflt) ; 290 | } 291 | 292 | static int fmt_utime (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 293 | { 294 | return fmt_jiffies(aux, p, pos, len, p->utime) ; 295 | } 296 | 297 | static int fmt_stime (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 298 | { 299 | return fmt_jiffies(aux, p, pos, len, p->stime) ; 300 | } 301 | 302 | static int fmt_cutime (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 303 | { 304 | return fmt_jiffies(aux, p, pos, len, p->utime + p->cutime) ; 305 | } 306 | 307 | static int fmt_cstime (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 308 | { 309 | return fmt_jiffies(aux, p, pos, len, p->stime + p->cstime) ; 310 | } 311 | 312 | static int fmt_prio (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 313 | { 314 | (void)aux ; 315 | return fmt_i(p, pos, len, p->prio) ; 316 | } 317 | 318 | static int fmt_nice (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 319 | { 320 | (void)aux ; 321 | return fmt_i(p, pos, len, p->nice) ; 322 | } 323 | 324 | static int fmt_threads (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 325 | { 326 | (void)aux ; 327 | return fmt_64(p, pos, len, p->threads) ; 328 | } 329 | 330 | static int fmt_timedate (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len, struct tm const *tm) 331 | { 332 | static struct tm nowtm = { .tm_year = 0 } ; 333 | size_t tmplen ; 334 | char *tmpstrf = "%F" ; 335 | if (!nowtm.tm_year && !localtm_from_tai(&nowtm, tain_secp(&STAMP), 1)) return 0 ; 336 | if (!stralloc_readyplus(&p->data, 20)) return 0 ; 337 | if (tm->tm_year == nowtm.tm_year && tm->tm_yday == nowtm.tm_yday) 338 | tmpstrf = "%T" ; 339 | else if (tm->tm_year == nowtm.tm_year || (tm->tm_year+1 == nowtm.tm_year && (nowtm.tm_mon + 12 - tm->tm_mon) % 12 < 9)) 340 | tmpstrf = "%b%d %R" ; 341 | tmplen = strftime(p->data.s + p->data.len, 20, tmpstrf, tm) ; 342 | if (!tmplen) return 0 ; 343 | *len = tmplen ; 344 | *pos = p->data.len ; 345 | p->data.len += tmplen ; 346 | return 1 ; 347 | } 348 | 349 | static int fmt_start (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 350 | { 351 | struct tm starttm ; 352 | unsigned int hz = gethz(aux) ; 353 | tain blah = { .sec = { .x = p->start / hz }, .nano = (p->start % hz) * (1000000000 / hz) } ; 354 | tain_add(&blah, &aux->boottime, &blah) ; 355 | if (!localtm_from_tai(&starttm, tain_secp(&blah), 1)) return 0 ; 356 | return fmt_timedate(aux, p, pos, len, &starttm) ; 357 | } 358 | 359 | static unsigned int getpgsz (s6ps_auxinfo_t *aux) 360 | { 361 | if (!aux->pgsz) 362 | { 363 | long sz = sysconf(_SC_PAGESIZE) ; 364 | if (sz < 1) 365 | { 366 | char fmt[ULONG_FMT + 1] ; 367 | fmt[long_fmt(fmt, sz)] = 0 ; 368 | strerr_warnw3x("invalid _SC_PAGESIZE value (", fmt, "), using 4096") ; 369 | aux->pgsz = 4096 ; 370 | } 371 | else aux->pgsz = sz ; 372 | } 373 | return aux->pgsz ; 374 | } 375 | 376 | static int fmt_vsize (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 377 | { 378 | (void)aux ; 379 | return fmt_64(p, pos, len, p->vsize / 1024) ; 380 | } 381 | 382 | static int fmt_rss (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 383 | { 384 | return fmt_64(p, pos, len, p->rss * (getpgsz(aux) / 1024)) ; 385 | } 386 | 387 | static int fmt_rsslim (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 388 | { 389 | (void)aux ; 390 | return fmt_64(p, pos, len, p->rsslim / 1024) ; 391 | } 392 | 393 | static int fmt_cpuno (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 394 | { 395 | (void)aux ; 396 | return fmt_64(p, pos, len, p->cpuno) ; 397 | } 398 | 399 | static int fmt_rtprio (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 400 | { 401 | (void)aux ; 402 | return fmt_64(p, pos, len, p->rtprio) ; 403 | } 404 | 405 | static int fmt_policy (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 406 | { 407 | static char const *const policies[8] = { "NORMAL", "FIFO", "RR", "BATCH", "ISO", "IDLE", "UNKNOWN", "UNKNOWN" } ; 408 | size_t tmppos = p->data.len ; 409 | if (!stralloc_cats(&p->data, policies[p->policy & 7])) return 0 ; 410 | *pos = tmppos ; 411 | *len = p->data.len - tmppos ; 412 | (void)aux ; 413 | return 1 ; 414 | } 415 | 416 | static int fmt_user (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 417 | { 418 | size_t tmppos = p->data.len ; 419 | if (!s6ps_pwcache_lookup(&aux->caches[0], &p->data, p->uid)) return 0 ; 420 | *pos = tmppos ; 421 | *len = p->data.len - tmppos ; 422 | return 1 ; 423 | } 424 | 425 | static int fmt_group (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 426 | { 427 | size_t tmppos = p->data.len ; 428 | if (!s6ps_grcache_lookup(&aux->caches[1], &p->data, p->gid)) return 0 ; 429 | *pos = tmppos ; 430 | *len = p->data.len - tmppos ; 431 | return 1 ; 432 | } 433 | 434 | static uint64_t gettotalmem (s6ps_auxinfo_t *aux) 435 | { 436 | if (!aux->totalmem) 437 | { 438 | struct sysinfo si = { .totalram = 0, .loads = { 0, 0, 0 } } ; 439 | if (sysinfo(&si) < 0) return 0 ; 440 | aux->totalmem = si.totalram ; 441 | aux->totalmem *= si.mem_unit ; 442 | } 443 | return aux->totalmem ; 444 | } 445 | 446 | static int percent (stralloc *sa, unsigned int n, size_t *pos, size_t *len) 447 | { 448 | if (!stralloc_readyplus(sa, UINT64_FMT+1)) return 0 ; 449 | *pos = sa->len ; 450 | sa->len += uint_fmt(sa->s + sa->len, n / 100) ; 451 | sa->s[sa->len++] = '.' ; 452 | uint0_fmt(sa->s + sa->len, n % 100, 2) ; 453 | sa->len += 2 ; 454 | *len = sa->len - *pos ; 455 | return 1 ; 456 | } 457 | 458 | static int fmt_pmem (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 459 | { 460 | uint64_t l = gettotalmem(aux) ; 461 | return l ? percent(&p->data, p->rss * getpgsz(aux) * 10000 / l, pos, len) : 0 ; 462 | } 463 | 464 | static int fmt_wchan (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 465 | { 466 | size_t tmppos = p->data.len ; 467 | if (!s6ps_wchan_lookup(&aux->wchan, &p->data, p->wchan)) return 0 ; 468 | *len = p->data.len - tmppos ; 469 | *pos = tmppos ; 470 | return 1 ; 471 | } 472 | 473 | static int fmt_args (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 474 | { 475 | if (!stralloc_readyplus(&p->data, (p->height << 2) + (p->cmdlen ? p->cmdlen : p->commlen + (p->data.s[p->state] == 'Z' ? 11 : 3)))) 476 | return 0 ; 477 | *pos = p->data.len ; 478 | if (p->height) 479 | { 480 | unsigned int i = 0 ; 481 | for (; i < 4 * (unsigned int)p->height - 3 ; i++) 482 | p->data.s[p->data.len + i] = ' ' ; 483 | memcpy(p->data.s + p->data.len + 4 * p->height - 3, "\\_ ", 3) ; 484 | p->data.len += p->height << 2 ; 485 | } 486 | if (p->cmdlen) 487 | { 488 | char const *r = p->data.s + p->statlen + p->commlen ; 489 | char *w = p->data.s + p->data.len ; 490 | size_t i = p->cmdlen ; 491 | while (i--) 492 | { 493 | char c = *r++ ; 494 | *w++ = c ? c : ' ' ; 495 | } 496 | p->data.len += p->cmdlen ; 497 | } 498 | else if (p->data.s[p->state] == 'Z') 499 | { 500 | stralloc_catb(&p->data, p->data.s + uint32_fmt(0, p->pid) + 2, p->commlen) ; 501 | stralloc_catb(&p->data, " ", 10) ; 502 | } 503 | else 504 | stralloc_catb(&p->data, p->data.s + uint32_fmt(0, p->pid) + 1, p->commlen+2) ; 505 | *len = p->data.len - *pos ; 506 | (void)aux ; 507 | return 1 ; 508 | } 509 | 510 | static int fmt_env (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 511 | { 512 | size_t i = 0 ; 513 | if (!p->envlen) 514 | { 515 | if (!stralloc_catb(&p->data, "*", 1)) return 0 ; 516 | *pos = p->data.len - 1 ; 517 | *len = 1 ; 518 | return 1 ; 519 | } 520 | *pos = p->statlen + p->commlen + p->cmdlen ; 521 | *len = p->envlen ; 522 | for (; i < *len ; i++) 523 | if (!p->data.s[*pos + i]) p->data.s[*pos + i] = ' ' ; 524 | (void)aux ; 525 | return 1 ; 526 | } 527 | 528 | static uint64_t gettotalj (s6ps_auxinfo_t *aux, uint64_t j) 529 | { 530 | tain totaltime ; 531 | unsigned int hz = gethz(aux) ; 532 | tain_sub(&totaltime, &STAMP, &aux->boottime) ; 533 | j = totaltime.sec.x * hz + totaltime.nano / (1000000000 / hz) - j ; 534 | if (!j) j = 1 ; 535 | return j ; 536 | } 537 | 538 | static int fmt_pcpu (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 539 | { 540 | return percent(&p->data, 10000 * (p->utime + p->stime) / gettotalj(aux, p->start), pos, len) ; 541 | } 542 | 543 | static int fmt_ttime (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 544 | { 545 | return fmt_jiffies(aux, p, pos, len, p->utime + p->stime) ; 546 | } 547 | 548 | static int fmt_cttime (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 549 | { 550 | return fmt_jiffies(aux, p, pos, len, p->utime + p->stime + p->cutime + p->cstime) ; 551 | } 552 | 553 | static int fmt_tstart (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 554 | { 555 | unsigned int hz = gethz(aux) ; 556 | tain blah = { .sec = { .x = p->start / hz }, .nano = (p->start % hz) * (1000000000 / hz) } ; 557 | if (!stralloc_readyplus(&p->data, TIMESTAMP)) return 0 ; 558 | tain_add(&blah, &aux->boottime, &blah) ; 559 | *pos = p->data.len ; 560 | *len = timestamp_fmt(p->data.s + p->data.len, &blah) ; 561 | p->data.len += *len ; 562 | return 1 ; 563 | } 564 | 565 | static int fmt_cpcpu (s6ps_auxinfo_t *aux, pscan_t *p, size_t *pos, size_t *len) 566 | { 567 | return percent(&p->data, 10000 * (p->utime + p->stime + p->cutime + p->cstime) / gettotalj(aux, p->start), pos, len) ; 568 | } 569 | 570 | static pfieldfmt_func_ref const pfieldfmt_table[PFIELD_PHAIL] = 571 | { 572 | &fmt_pid, 573 | &fmt_comm, 574 | &fmt_s, 575 | &fmt_ppid, 576 | &fmt_pgrp, 577 | &fmt_session, 578 | &fmt_ttynr, 579 | &fmt_tpgid, 580 | &fmt_minflt, 581 | &fmt_cminflt, 582 | &fmt_majflt, 583 | &fmt_cmajflt, 584 | &fmt_utime, 585 | &fmt_stime, 586 | &fmt_cutime, 587 | &fmt_cstime, 588 | &fmt_prio, 589 | &fmt_nice, 590 | &fmt_threads, 591 | &fmt_start, 592 | &fmt_vsize, 593 | &fmt_rss, 594 | &fmt_rsslim, 595 | &fmt_cpuno, 596 | &fmt_rtprio, 597 | &fmt_policy, 598 | &fmt_user, 599 | &fmt_group, 600 | &fmt_pmem, 601 | &fmt_wchan, 602 | &fmt_args, 603 | &fmt_env, 604 | &fmt_pcpu, 605 | &fmt_ttime, 606 | &fmt_cttime, 607 | &fmt_tstart, 608 | &fmt_cpcpu 609 | } ; 610 | 611 | pfieldfmt_func_ref const *const s6ps_pfield_fmt = pfieldfmt_table ; 612 | -------------------------------------------------------------------------------- /tools/configure.template: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd `dirname "$0"` 4 | . package/info 5 | 6 | usage () { 7 | cat </dev/null 2>&1 && { echo "$1" ; return 0 ; } 67 | $1 68 | EOF 69 | echo "$1" | sed -e "s/'/'\\\\''/g" -e "1s/^/'/" -e "\$s/\$/'/" -e "s#^'\([-[:alnum:]_,./:]*\)=\(.*\)\$#\1='\2#" -e "s|\*/|* /|g" 70 | } 71 | 72 | fail () { 73 | echo "$*" 74 | exit 1 75 | } 76 | 77 | fnmatch () { 78 | eval "case \"\$2\" in $1) return 0 ;; *) return 1 ;; esac" 79 | } 80 | 81 | cmdexists () { 82 | type "$1" >/dev/null 2>&1 83 | } 84 | 85 | trycc () { 86 | test -z "$CC_AUTO" && cmdexists "$1" && CC_AUTO="$*" 87 | } 88 | 89 | stripdir () { 90 | while eval "fnmatch '*/' \"\${$1}\"" ; do 91 | eval "$1=\${$1%/}" 92 | done 93 | } 94 | 95 | tryflag () { 96 | echo "Checking whether compiler accepts $2 ..." 97 | echo "typedef int x;" > "$tmpc" 98 | if $CC_AUTO $CPPFLAGS_AUTO $CPPFLAGS $CPPFLAGS_POST $CFLAGS_AUTO $CFLAGS $CFLAGS_POST "$2" -c -o "$tmpo" "$tmpc" >/dev/null 2>&1 ; then 99 | echo " ... yes" 100 | eval "$1=\"\${$1} \$2\"" 101 | eval "$1=\${$1# }" 102 | return 0 103 | else 104 | echo " ... no" 105 | return 1 106 | fi 107 | } 108 | 109 | tryldflag () { 110 | echo "Checking whether linker accepts $2 ..." 111 | echo "typedef int x;" > "$tmpc" 112 | if $CC_AUTO $CFLAGS_AUTO $CFLAGS $CFLAGS_POST $LDFLAGS_AUTO $LDFLAGS $LDFLAGS_POST -nostdlib "$2" -o "$tmpe" "$tmpc" >/dev/null 2>&1 ; then 113 | echo " ... yes" 114 | eval "$1=\"\${$1} \$2\"" 115 | eval "$1=\${$1# }" 116 | return 0 117 | else 118 | echo " ... no" 119 | return 1 120 | fi 121 | } 122 | 123 | 124 | # Actual script 125 | 126 | CC_AUTO= 127 | CPPFLAGS_AUTO="-D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -iquote src/include-local -Isrc/include" 128 | CPPFLAGS_POST="$CPPFLAGS" 129 | CPPFLAGS= 130 | CFLAGS_AUTO="-pipe -Wall" 131 | CFLAGS_POST="$CFLAGS" 132 | CFLAGS=-O2 133 | LDFLAGS_AUTO= 134 | LDFLAGS_POST="$LDFLAGS" 135 | LDFLAGS= 136 | LDFLAGS_NOSHARED= 137 | LDFLAGS_SHARED=-shared 138 | prefix= 139 | exec_prefix='$prefix' 140 | dynlibdir='$prefix/lib' 141 | libexecdir='$exec_prefix/libexec' 142 | bindir='$exec_prefix/bin' 143 | libdir='$prefix/lib' 144 | includedir='$prefix/include' 145 | sysconfdir='$prefix/etc' 146 | pkgconfdir='$prefix/lib/pkgconfig' 147 | shebangdir='$bindir' 148 | sysdeps='$prefix/lib/skalibs/sysdeps' 149 | manualsysdeps=false 150 | shlibext=so 151 | shared=false 152 | static=true 153 | allpic=true 154 | slashpackage=false 155 | abspath=false 156 | pcw=false 157 | sproot= 158 | home= 159 | exthome= 160 | allstatic=true 161 | evenmorestatic=false 162 | pkgconf= 163 | addincpath='' 164 | addlibspath='' 165 | addlibdpath='' 166 | depincpath='' 167 | deplibpath='' 168 | vpaths='' 169 | vpathd='' 170 | build= 171 | ${configure_init_vars} 172 | 173 | for arg ; do 174 | case "$arg" in 175 | --help) usage ;; 176 | --prefix=*) prefix=${arg#*=} ;; 177 | --exec-prefix=*) exec_prefix=${arg#*=} ;; 178 | --dynlibdir=*) dynlibdir=${arg#*=} ;; 179 | --libexecdir=*) libexecdir=${arg#*=} ;; 180 | --bindir=*) bindir=${arg#*=} ;; 181 | --libdir=*) libdir=${arg#*=} ;; 182 | --includedir=*) includedir=${arg#*=} ;; 183 | --sysconfdir=*) sysconfdir=${arg#*=} ;; 184 | --pkgconfdir=*) pkgconfdir=${arg#*=} ;; 185 | --with-sysdeps=*) sysdeps=${arg#*=} manualsysdeps=true ;; 186 | --with-include=*) var=${arg#*=} ; stripdir var ; addincpath="$addincpath -I$var" ; depincpath="${depincpath}${depincpath:+ }-I$var" ;; 187 | --with-lib=*) var=${arg#*=} ; stripdir var ; addlibspath="$addlibspath -L$var" ; deplibpath="${deplibpath}${deplibpath:+ }-L$var" ; vpaths="$vpaths $var" ;; 188 | --with-dynlib=*) var=${arg#*=} ; stripdir var ; addlibdpath="$addlibdpath -L$var" ; vpathd="$vpathd $var" ;; 189 | --with-pkgconfig=*) pkgconf=${arg#*=} ;; 190 | --with-pkgconfig) pkgconf=${PKG_CONFIG:-pkg-config} ;; 191 | --without-pkgconfig) pkgconf= ;; 192 | --enable-shared|--enable-shared=yes) shared=true ;; 193 | --disable-shared|--enable-shared=no) shared=false ;; 194 | --enable-static|--enable-static=yes) static=true ;; 195 | --disable-static|--enable-static=no) static=false ;; 196 | --enable-allstatic|--enable-allstatic=yes) static=true ; allstatic=true ;; 197 | --disable-allstatic|--enable-allstatic=no) allstatic=false ; evenmorestatic=false ; shared=true ;; 198 | --enable-static-libc|--enable-static-libc=yes) static=true ; allstatic=true ; evenmorestatic=true ;; 199 | --disable-static-libc|--enable-static-libc=no) evenmorestatic=false ;; 200 | --enable-all-pic|--enable-all-pic=yes) allpic=true ;; 201 | --disable-all-pic|--enable-all-pic=no) allpic=false ;; 202 | --enable-pkgconfig|--enable-pkgconfig=yes) pcw=true ;; 203 | --disable-pkgconfig|--enable-pkgconfig=no) pcw=false ;; 204 | --enable-slashpackage=*) sproot=${arg#*=} ; slashpackage=true ; ;; 205 | --enable-slashpackage) sproot= ; slashpackage=true ;; 206 | --disable-slashpackage) sproot= ; slashpackage=false ;; 207 | --enable-absolute-paths|--enable-absolute-paths=yes) abspath=true ;; 208 | --disable-absolute-paths|--enable-absolute-paths=no) abspath=false ;; 209 | ${configure_case_lines} 210 | --enable-*|--disable-*|--with-*|--without-*|--*dir=*) ;; 211 | --enable-*|--disable-*|--with-*|--without-*|--*dir=*) ;; 212 | --host=*|--target=*) target=${arg#*=} ;; 213 | --build=*) build=${arg#*=} ;; 214 | -* ) echo "$0: unknown option $arg" ;; 215 | *=*) eval "${arg%%=*}=\${arg#*=}" ;; 216 | *) target=$arg ;; 217 | esac 218 | done 219 | 220 | # Add /usr in the default default case 221 | if test -z "$prefix" ; then 222 | if test "$libdir" = '$prefix/lib' ; then 223 | libdir=/usr/lib 224 | fi 225 | if test "$includedir" = '$prefix/include' ; then 226 | includedir=/usr/include 227 | fi 228 | if test "$pkgconfdir" = '$prefix/lib/pkgconfig' ; then 229 | pkgconfdir=/usr/lib/pkgconfig 230 | fi 231 | if test "$sysdeps" = '$prefix/lib/skalibs/sysdeps' ; then 232 | sysdeps=/usr/lib/skalibs/sysdeps 233 | fi 234 | fi 235 | 236 | # Expand installation directories 237 | stripdir prefix 238 | for i in exec_prefix dynlibdir libexecdir bindir libdir includedir sysconfdir pkgconfdir sysdeps sproot ${configure_expand_dirs} ; do 239 | eval tmp=\${$i} 240 | eval $i=$tmp 241 | stripdir $i 242 | done 243 | 244 | # Process deps-build 245 | if test -n "$pkgconf" || $pcw || $slashpackage ; then 246 | oldifs="$IFS" 247 | while IFS=" " read cond usedinlibs pkg ver libs ; do 248 | IFS="$oldifs" 249 | eval "cond=$cond; usedinlibs=$usedinlibs" 250 | if $cond ; then 251 | if test -n "$pkgconf" ; then 252 | for lib in $libs ; do 253 | if ! $pkgconf --atleast-version=${ver} --print-errors -- "$lib" ; then 254 | echo "./configure: fatal: $pkgconf --atleast-version=${ver} --print-errors -- $lib failed" 1>&2 255 | exit 1 256 | fi 257 | thisinc="`$pkgconf --cflags-only-I -- $lib`" 258 | sldflags="`$pkgconf --libs-only-L --static -- $lib`" 259 | dldflags="`$pkgconf --libs-only-L -- $lib`" 260 | addincpath="${addincpath}${thisinc:+ }$thisinc" 261 | addlibspath="${addlibspath}${sldflags:+ }$sldflags" 262 | addlibdpath="${addlibdpath}${dldflags:+ }$dldflags" 263 | for i in $sldflags ; do 264 | vpaths="$vpaths ${i##-L}" 265 | done 266 | for i in $dldflags ; do 267 | vpathd="$vpathd ${i##-L}" 268 | done 269 | if $usedinlibs ; then 270 | depincpath="${depincpath}${thisinc:+ }$thisinc" 271 | deplibpath="${deplibpath}${sldflags:+ }$sldflags" 272 | fi 273 | done 274 | fi 275 | if $slashpackage ; then 276 | addincpath="$addincpath -I${DESTDIR}${sproot}${pkg}/include" 277 | vpaths="$vpaths ${DESTDIR}${sproot}${pkg}/library" 278 | addlibspath="$addlibspath -L${DESTDIR}${sproot}${pkg}/library" 279 | vpathd="$vpathd ${DESTDIR}${sproot}${pkg}/library.so" 280 | addlibdpath="$addlibdpath -L${DESTDIR}${sproot}${pkg}/library.so" 281 | if $usedinlibs ; then 282 | depincpath="$depincpath -I${DESTDIR}${sproot}${pkg}/include" 283 | deplibpath="$deplibpath -L${DESTDIR}${sproot}${pkg}/library" 284 | fi 285 | fi 286 | fi 287 | done < package/deps-build 288 | IFS="$oldifs" 289 | fi 290 | 291 | # Other slashpackage values 292 | if $slashpackage ; then 293 | home=${sproot}/package/${category}/${package}-${version} 294 | exthome=${sproot}/package/${category}/${package} 295 | if $manualsysdeps ; then 296 | : 297 | else 298 | sysdeps=${DESTDIR}${sproot}/package/prog/skalibs/sysdeps 299 | fi 300 | extbinprefix=${exthome}/command 301 | dynlibdir=${home}/library.so 302 | bindir=${home}/command 303 | libdir=${home}/library 304 | libexecdir=$bindir 305 | includedir=${home}/include 306 | pkgconfdir=${home}/pkgconfig 307 | ${configure_slashpackage_other} 308 | fi 309 | 310 | # Get usable temp filenames 311 | i=0 312 | set -C 313 | while : ; do 314 | i=$(($i+1)) 315 | tmpc="./tmp-configure-$$-$PPID-$i.c" 316 | tmpo="./tmp-configure-$$-$PPID-$i.o" 317 | tmpe="./tmp-configure-$$-$PPID-$i.tmp" 318 | 2>|/dev/null > "$tmpc" && break 319 | 2>|/dev/null > "$tmpo" && break 320 | 2>|/dev/null > "$tmpe" && break 321 | test "$i" -gt 50 && fail "$0: cannot create temporary files" 322 | done 323 | set +C 324 | trap 'rm -f "$tmpc" "$tmpo" "$tmpe"' EXIT ABRT INT QUIT TERM HUP 325 | 326 | # Find a C compiler to use 327 | if test -n "$target" && test x${build} != x${target} ; then 328 | cross=${target}- 329 | else 330 | cross= 331 | fi 332 | echo "Checking for C compiler..." 333 | trycc ${CC} 334 | if test -n "$CC_AUTO" ; then 335 | b=`basename "$CC"` 336 | adjust_cross=false 337 | if test "$b" != "$CC" ; then 338 | adjust_cross=true 339 | echo "$0: warning: compiler $CC is declared with its own path. If it's not accessible via PATH, you will need to pass AR, RANLIB and STRIP make variables to the make invocation." 1>&2 340 | fi 341 | if test -n "$cross" ; then 342 | if test "$b" = "${b##$cross}" ; then 343 | echo "$0: warning: compiler $CC is declared as a cross-compiler for target $target but does not start with prefix ${cross}" 1>&2 344 | elif $adjust_cross ; then 345 | cross=`dirname "$CC"`/"$cross" 346 | fi 347 | fi 348 | fi 349 | trycc ${cross}gcc 350 | trycc ${cross}clang 351 | trycc ${cross}cc 352 | test -n "$CC_AUTO" || { echo "$0: cannot find a C compiler" ; exit 1 ; } 353 | echo " ... $CC_AUTO" 354 | echo "Checking whether C compiler works... " 355 | echo "typedef int x;" > "$tmpc" 356 | if $CC_AUTO $CPPFLAGS_AUTO $CPPFLAGS $CPPFLAGS_POST $CFLAGS_AUTO $CFLAGS $CFLAGS_POST -c -o "$tmpo" "$tmpc" 2>"$tmpe" ; then 357 | echo " ... yes" 358 | else 359 | echo " ... no. Compiler output follows:" 360 | cat < "$tmpe" 361 | exit 1 362 | fi 363 | 364 | echo "Checking target system type..." 365 | if test -z "$target" ; then 366 | if test -n "$build" ; then 367 | target=$build ; 368 | else 369 | target=$($CC_AUTO -dumpmachine 2>/dev/null) || target=unknown 370 | fi 371 | fi 372 | echo " ... $target" 373 | if test ! -d $sysdeps || test ! -f $sysdeps/target ; then 374 | echo "$0: error: $sysdeps is not a valid sysdeps directory" 375 | exit 1 376 | fi 377 | if test "$target" != "$(cat $sysdeps/target)" ; then 378 | echo "$0: error: target $target does not match the contents of $sysdeps/target" 379 | exit 1 380 | fi 381 | 382 | echo "Shared libraries will be named ..." 383 | libc="${target##*-}" 384 | if test "${libc##darwin}" != "$libc" ; then 385 | shlibext=dylib 386 | fi 387 | echo " ... *.$shlibext" 388 | 389 | if $allpic ; then 390 | tryflag CPPFLAGS_AUTO -fPIC 391 | fi 392 | 393 | pthread_lib=$(cat $sysdeps/pthread.lib) 394 | socket_lib=$(cat $sysdeps/socket.lib) 395 | spawn_lib=$(cat $sysdeps/spawn.lib) 396 | sysclock_lib=$(cat $sysdeps/sysclock.lib) 397 | timer_lib=$(cat $sysdeps/timer.lib) 398 | util_lib=$(cat $sysdeps/util.lib) 399 | 400 | tryflag CFLAGS_AUTO -std=c99 401 | tryflag CFLAGS -fomit-frame-pointer 402 | tryflag CFLAGS_AUTO -fno-exceptions 403 | tryflag CFLAGS_AUTO -fno-unwind-tables 404 | tryflag CFLAGS_AUTO -fno-asynchronous-unwind-tables 405 | tryflag CPPFLAGS_AUTO -Werror=implicit-function-declaration 406 | tryflag CPPFLAGS_AUTO -Werror=implicit-int 407 | tryflag CPPFLAGS_AUTO -Werror=pointer-sign 408 | tryflag CPPFLAGS_AUTO -Werror=pointer-arith 409 | tryflag CFLAGS_AUTO -ffunction-sections 410 | tryflag CFLAGS_AUTO -fdata-sections 411 | 412 | tryldflag LDFLAGS_AUTO -Wl,--sort-section=alignment 413 | tryldflag LDFLAGS_AUTO -Wl,--sort-common 414 | 415 | CPPFLAGS_AUTO="${CPPFLAGS_AUTO}${addincpath}" 416 | 417 | if $evenmorestatic ; then 418 | LDFLAGS_NOSHARED=" -static" 419 | fi 420 | 421 | if $shared ; then 422 | tryldflag LDFLAGS -Wl,--hash-style=both 423 | fi 424 | 425 | LDFLAGS_SHARED="${LDFLAGS_SHARED}${addlibdpath}" 426 | 427 | if $allstatic ; then 428 | LDFLAGS_NOSHARED="${LDFLAGS_NOSHARED}${addlibspath}" 429 | tryldflag LDFLAGS_NOSHARED -Wl,--gc-sections 430 | else 431 | LDFLAGS_NOSHARED="${LDFLAGS_NOSHARED}${addlibdpath}" 432 | fi 433 | 434 | ${configure_extra_checks} 435 | 436 | echo "Creating config.mak..." 437 | cmdline=$(quote "$0") 438 | for i ; do cmdline="$cmdline $(quote "$i")" ; done 439 | exec 3>&1 1>config.mak 440 | cat << EOF 441 | # This file was generated by: 442 | # $cmdline 443 | # Any changes made here will be lost if configure is re-run. 444 | 445 | target := $target 446 | package := $package 447 | prefix := $prefix 448 | exec_prefix := $exec_prefix 449 | dynlibdir := $dynlibdir 450 | libexecdir := $libexecdir 451 | bindir := $bindir 452 | libdir := $libdir 453 | includedir := $includedir 454 | sysconfdir := $sysconfdir 455 | pkgconfdir := $pkgconfdir 456 | sysdeps := $sysdeps 457 | slashpackage := $slashpackage 458 | sproot := $sproot 459 | version := $version 460 | home := $home 461 | exthome := $exthome 462 | extra_includedirs :=$depincpath 463 | extra_libdirs :=$deplibpath 464 | 465 | PTHREAD_LIB := ${pthread_lib} 466 | SOCKET_LIB := ${socket_lib} 467 | SPAWN_LIB := ${spawn_lib} 468 | SYSCLOCK_LIB := ${sysclock_lib} 469 | TIMER_LIB := ${timer_lib} 470 | UTIL_LIB := ${util_lib} 471 | 472 | CC := $CC_AUTO 473 | CPPFLAGS_AUTO := $CPPFLAGS_AUTO 474 | CPPFLAGS := ${CPPFLAGS}${CPPFLAGS_POST:+ }$CPPFLAGS_POST 475 | CFLAGS_AUTO := $CFLAGS_AUTO 476 | CFLAGS := ${CFLAGS}${CFLAGS_POST:+ }$CFLAGS_POST 477 | LDFLAGS_AUTO := $LDFLAGS_AUTO 478 | LDFLAGS := ${LDFLAGS}${LDFLAGS_POST:+ }$LDFLAGS_POST 479 | LDFLAGS_SHARED := $LDFLAGS_SHARED 480 | LDFLAGS_NOSHARED :=$LDFLAGS_NOSHARED 481 | CROSS_COMPILE := $cross 482 | SHLIB_EXT := ${shlibext} 483 | 484 | vpath lib%.a$vpaths 485 | vpath lib%.${shlibext}$vpathd 486 | 487 | EOF 488 | if $allstatic ; then 489 | echo ".LIBPATTERNS := lib%.a" 490 | echo "DO_ALLSTATIC := 1" 491 | else 492 | echo ".LIBPATTERNS := lib%.${shlibext}" 493 | echo "DO_ALLSTATIC :=" 494 | fi 495 | if $static ; then 496 | echo "DO_STATIC := 1" 497 | else 498 | echo "DO_STATIC :=" 499 | fi 500 | if $shared ; then 501 | echo "DO_SHARED := 1" 502 | else 503 | echo "DO_SHARED :=" 504 | fi 505 | if $pcw ; then 506 | echo "DO_PKGCONFIG := 1" 507 | else 508 | echo "DO_PKGCONFIG :=" 509 | fi 510 | if $allpic ; then 511 | echo "STATIC_LIBS_ARE_PIC := 1" 512 | else 513 | echo "STATIC_LIBS_ARE_PIC :=" 514 | fi 515 | ${configure_generate_make} 516 | exec 1>&3 3>&- 517 | echo " ... done." 518 | 519 | echo "Creating src/include/${package}/config.h..." 520 | mkdir -p -m 0755 src/include/${package} 521 | exec 3>&1 1> src/include/${package}/config.h 522 | cat <&3 3>&- 551 | echo " ... done." 552 | --------------------------------------------------------------------------------