├── .gitignore ├── AUTHORS ├── COPYING ├── HISTORY ├── INSTALL ├── LICENSE ├── Makefile ├── README.md ├── configure ├── doc ├── aa-chroot.pod ├── aa-command.pod ├── aa-ctty.pod ├── aa-echo.pod ├── aa-enable.pod ├── aa-incmdline.pod ├── aa-kill.pod ├── aa-mount.pod ├── aa-pivot.pod ├── aa-reboot.pod ├── aa-reset.pod ├── aa-service.pod ├── aa-setready.pod ├── aa-shutdown.pod ├── aa-stage0.pod ├── aa-stage1.pod ├── aa-stage2.pod ├── aa-stage3.pod ├── aa-stage4.pod ├── aa-start.pod ├── aa-status.pod ├── aa-stop.pod ├── aa-sync.pod ├── aa-terminate.pod ├── aa-test.pod ├── aa-tty.pod ├── aa-umount.pod ├── anopa.pod └── footer.pod ├── package ├── deps-build ├── info ├── modes └── targets.mak ├── src ├── anopa │ ├── aa-enable.c │ ├── aa-reset.c │ ├── aa-start.c │ ├── aa-status.c │ ├── aa-stop.c │ ├── common.h │ ├── deps-exe │ │ ├── aa-enable │ │ ├── aa-reset │ │ ├── aa-start │ │ ├── aa-status │ │ └── aa-stop │ ├── start-stop.c │ ├── start-stop.h │ ├── util.c │ └── util.h ├── include │ └── anopa │ │ ├── anopa.h │ │ ├── common.h │ │ ├── copy_file.h │ │ ├── enable_service.h │ │ ├── err.h │ │ ├── ga_int_list.h │ │ ├── ga_list.h │ │ ├── init_repo.h │ │ ├── output.h │ │ ├── progress.h │ │ ├── scan_dir.h │ │ ├── service.h │ │ ├── service_status.h │ │ └── stats.h ├── libanopa │ ├── copy_file.c │ ├── deps-lib │ │ └── anopa │ ├── die_usage.c │ ├── die_version.c │ ├── enable_service.c │ ├── errmsg.c │ ├── eventmsg.c │ ├── exec_longrun.c │ ├── exec_oneshot.c │ ├── ga_list.c │ ├── init_repo.c │ ├── output.c │ ├── progress.c │ ├── sa_sources.c │ ├── scan_dir.c │ ├── service.c │ ├── service_internal.h │ ├── service_name.c │ ├── service_start.c │ ├── service_status.c │ ├── service_stop.c │ ├── services.c │ └── stats.c ├── scripts │ ├── aa-command │ ├── aa-shutdown │ ├── aa-stage0 │ ├── aa-stage1 │ ├── aa-stage2 │ ├── aa-stage3 │ └── aa-stage4 └── utils │ ├── aa-chroot.c │ ├── aa-ctty.c │ ├── aa-echo.c │ ├── aa-incmdline.c │ ├── aa-kill.c │ ├── aa-mount.c │ ├── aa-pivot.c │ ├── aa-reboot.c │ ├── aa-service.c │ ├── aa-setready.c │ ├── aa-sync.c │ ├── aa-terminate.c │ ├── aa-test.c │ ├── aa-tty.c │ ├── aa-umount.c │ ├── deps-exe │ ├── aa-chroot │ ├── aa-ctty │ ├── aa-echo │ ├── aa-incmdline │ ├── aa-kill │ ├── aa-mount │ ├── aa-pivot │ ├── aa-reboot │ ├── aa-service │ ├── aa-setready │ ├── aa-sync │ ├── aa-terminate │ ├── aa-test │ ├── aa-tty │ └── aa-umount │ └── mount-constants.h └── tools ├── gen-deps.sh └── install.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.bak 3 | *.o 4 | *.a 5 | *.lo 6 | *.so 7 | *.orig 8 | *.rej 9 | .dirstamp 10 | /package/deps.mak 11 | /config.mak 12 | /src/include/anopa/config.h 13 | /anopa.1 14 | /aa-* 15 | /libanopa.a 16 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | anopa is developed by Olivier Brunel 2 | See LICENSE for more 3 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Build Instructions 2 | ------------------ 3 | 4 | * Requirements 5 | ------------ 6 | 7 | - A POSIX-compliant C development environment 8 | - GNU make version 4.0 or later 9 | - skalibs version 2.5.0.0 or later: http://skarnet.org/software/skalibs/ 10 | - execline version 2.3.0.1 or later: http://skarnet.org/software/execline/ 11 | - s6 version 2.5.0.0 or later: http://skarnet.org/software/s6/ 12 | 13 | Noting that both execline and s6 are also runtime dependencies, the former only 14 | if using the aa-stage{0..4} scripts. 15 | 16 | 17 | * Standard usage 18 | -------------- 19 | 20 | ./configure && make && sudo make install 21 | 22 | will work for most users. 23 | 24 | 25 | * Customization 26 | ------------- 27 | 28 | You can customize paths via flags given to configure. 29 | See ./configure --help for a list of all available configure options. 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | anopa is released under the GNU General Public License v3+ 2 | Copyright (C) 2015-2017 Olivier Brunel 3 | See COPYING 4 | 5 | Build system based on s6's by Laurent Bercot. 6 | -------------------------------------------------------------------------------- /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 | CC = $(error Please use ./configure first) 11 | 12 | STATIC_LIBS := 13 | SHARED_LIBS := 14 | INTERNAL_LIBS := 15 | EXTRA_TARGETS := 16 | DOC_TARGETS := 17 | 18 | -include config.mak 19 | include package/targets.mak 20 | include package/deps.mak 21 | 22 | version_m := $(basename $(version)) 23 | version_M := $(basename $(version_m)) 24 | CPPFLAGS_ALL := -iquote src/include-local -Isrc/include $(CPPFLAGS) 25 | CFLAGS_ALL := $(CFLAGS) -pipe -Wall 26 | CFLAGS_SHARED := -fPIC 27 | LDFLAGS_ALL := $(LDFLAGS) 28 | LDFLAGS_SHARED := -shared 29 | LDLIBS_ALL := $(LDLIBS) 30 | REALCC = $(CROSS_COMPILE)$(CC) 31 | AR := $(CROSS_COMPILE)ar 32 | RANLIB := $(CROSS_COMPILE)ranlib 33 | STRIP := $(CROSS_COMPILE)strip 34 | INSTALL := ./tools/install.sh 35 | POD2MAN := pod2man 36 | 37 | ALL_BINS := $(LIBEXEC_TARGETS) $(BIN_TARGETS) $(SBIN_TARGETS) 38 | ALL_LIBS := $(SHARED_LIBS) $(STATIC_LIBS) $(INTERNAL_LIBS) 39 | ALL_INCLUDES := $(wildcard src/include/$(package)/*.h) 40 | ALL_SCRIPTS := $(LIBEXEC_SCRIPTS_TARGET) $(BIN_SCRIPTS_TARGET) 41 | 42 | all: $(ALL_LIBS) $(ALL_BINS) $(ALL_SCRIPTS) $(ALL_INCLUDES) $(DOC_TARGETS) 43 | 44 | clean: 45 | @exec rm -f $(ALL_LIBS) $(ALL_BINS) $(ALL_SCRIPTS) $(wildcard src/*/*.o src/*/*.lo) $(EXTRA_TARGETS) 46 | 47 | distclean: clean 48 | @exec rm -f config.mak package/deps.mak src/include/${package}/config.h $(DOC_TARGETS) 49 | 50 | txz: distclean $(DOC_TARGETS) 51 | @./tools/gen-deps.sh > package/deps.mak 2> /dev/null && \ 52 | . package/info && \ 53 | rm -rf /tmp/$$package-$$version && \ 54 | cp -a . /tmp/$$package-$$version && \ 55 | cd /tmp && \ 56 | tar -Jpcv --owner=0 --group=0 --numeric-owner --exclude=.git* -f /tmp/$$package-$$version.tar.xz $$package-$$version && \ 57 | exec rm -rf /tmp/$$package-$$version 58 | 59 | strip: $(ALL_LIBS) $(ALL_BINS) 60 | ifneq ($(strip $(ALL_LIBS)),) 61 | exec ${STRIP} -x -R .note -R .comment -R .note.GNU-stack $(ALL_LIBS) 62 | endif 63 | ifneq ($(strip $(ALL_BINS)),) 64 | exec ${STRIP} -R .note -R .comment -R .note.GNU-stack $(ALL_BINS) 65 | endif 66 | 67 | install: install-dynlib install-libexec install-bin install-sbin install-lib install-include install-doc 68 | install-dynlib: $(SHARED_LIBS:lib%.so=$(DESTDIR)$(dynlibdir)/lib%.so) 69 | install-libexec: $(LIBEXEC_TARGETS:%=$(DESTDIR)$(libexecdir)/%) $(LIBEXEC_SCRIPTS_TARGET:%=$(DESTDIR)$(libexecdir)/%) 70 | install-bin: $(BIN_TARGETS:%=$(DESTDIR)$(bindir)/%) $(BIN_SCRIPTS_TARGET:%=$(DESTDIR)$(bindir)/%) 71 | install-sbin: $(SBIN_TARGETS:%=$(DESTDIR)$(sbindir)/%) 72 | install-lib: $(STATIC_LIBS:lib%.a=$(DESTDIR)$(libdir)/lib%.a) 73 | install-include: $(ALL_INCLUDES:src/include/$(package)/%.h=$(DESTDIR)$(includedir)/$(package)/%.h) 74 | install-doc: $(DOC_TARGETS:%=$(DESTDIR)/usr/share/man/man1/%) 75 | 76 | ifneq ($(exthome),) 77 | 78 | update: 79 | exec $(INSTALL) -l $(notdir $(home)) $(DESTDIR)$(exthome) 80 | 81 | global-links: $(DESTDIR)$(exthome) $(SHARED_LIBS:lib%.so=$(DESTDIR)$(sproot)/library.so/lib%.so) $(BIN_TARGETS:%=$(DESTDIR)$(sproot)/command/%) $(SBIN_TARGETS:%=$(DESTDIR)$(sproot)/command/%) 82 | 83 | $(DESTDIR)$(sproot)/command/%: $(DESTDIR)$(home)/command/% 84 | exec $(INSTALL) -D -l ..$(subst $(sproot),,$(exthome))/command/$( $@ 133 | 134 | %.1: doc/%.pod doc/footer.pod 135 | @exec cat $< doc/footer.pod > $(basename $@).pod 136 | exec $(POD2MAN) --center="$(package)" --section=1 --release="$(version)" $(basename $@).pod > $@ 137 | @exec rm $(basename $@).pod 138 | 139 | .PHONY: it all clean distclean tgz strip install install-dynlib install-bin install-sbin install-lib install-include install-doc 140 | 141 | .DELETE_ON_ERROR: 142 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # anopa: init system/service manager build around s6 supervision suite 3 | 4 | anopa is an collection of tools and scripts aimed to provide an init system and 5 | service manager for Linux systems, based around the s6 supervision suite[1]. 6 | 7 | It provides some execline[2] scripts that can be used as init for different 8 | stage of the boot process, leaving stage 2 to be handled by s6-svscan, as well 9 | as tools that can be used to create a runtime repository of servicedirs, 10 | start/stop them and other related functions. 11 | 12 | ## Free Software 13 | 14 | anopa - Copyright (C) 2015-2017 Olivier Brunel 15 | 16 | anopa is free software: you can redistribute it and/or modify it under the 17 | terms of the GNU General Public License as published by the Free Software 18 | Foundation, either version 3 of the License, or (at your option) any later 19 | version. 20 | 21 | anopa is distributed in the hope that it will be useful, but WITHOUT ANY 22 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 23 | PARTICULAR PURPOSE. 24 | See the GNU General Public License for more details. 25 | 26 | You should have received a copy of the GNU General Public License along with 27 | anopa (COPYING). If not, see http://www.gnu.org/licenses/ 28 | 29 | ## Want to know more? 30 | 31 | Some useful links if you're looking for more info: 32 | 33 | - [official site](https://jjacky.com/anopa "anopa @ jjacky.com") 34 | 35 | - [source code & issue tracker](https://github.com/jjk-jacky/anopa "anopa @ GitHub.com") 36 | 37 | - [origin story](https://jjacky.com/2015-04-10-has-arch-lost-its-way "Has Arch lost its Way? @ jjacky.com") 38 | 39 | - [PKGBUILD in AUR](https://aur.archlinux.org/packages/anopa "AUR: anopa") 40 | 41 | - [1: s6 supervision suite](http://skarnet.org/software/s6/ "s6 @ skarnet.org") 42 | 43 | - [2: execline](http://skarnet.org/software/execline/ "execline @ skarnet.org") 44 | 45 | Plus, anopa comes with man pages. 46 | -------------------------------------------------------------------------------- /doc/aa-chroot.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-chroot - Execute command within given chroot jail 4 | 5 | =head1 SYNOPSIS 6 | 7 | B [B<-D>] I I [I] 8 | 9 | =head1 OPTIONS 10 | 11 | =over 12 | 13 | =item B<-D, --double-output> 14 | 15 | Enable double-output mode. Instead of using stdout for regular output, and 16 | stderr for warnings and errors, everything is sent both to stdout and stderr. 17 | This is intended to redirect stderr to a log file, so full output can be both 18 | shown on console and logged. 19 | 20 | =item B<-h, --help> 21 | 22 | Show help screen and exit. 23 | 24 | =item B<-V, --version> 25 | 26 | Show version information and exit. 27 | 28 | =back 29 | 30 | =head1 DESCRIPTION 31 | 32 | B(1) sets the root filesytem for the current process to I, 33 | which must exists, goes into this directory, chroots into it and chdir into the 34 | (new) root ("/"). It then executes into I (searched under the new root) 35 | with the given I (if any). 36 | 37 | Note that B(1)'s parent process if unaffected by the change. 38 | -------------------------------------------------------------------------------- /doc/aa-command.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-command - Helper to trigger one of anopa's commands 4 | 5 | =head1 SYNOPSIS 6 | 7 | B I [I] 8 | 9 | =head1 DEPRECATED 10 | 11 | B(1) has been deprecated and will be removed in the next version of 12 | B. A better way to achieve similar results is via a longrun service, thus 13 | guaranteeing same environment, proper logging, etc 14 | 15 | For example, such longrun could be named aa-command and have the following 16 | I file : 17 | 18 | #!/usr/bin/execlineb -P 19 | fdmove -c 2 1 20 | fdmove -c 4 1 21 | fdmove 1 3 22 | s6-ipcserver -1 -- socket 23 | s6-ipcserver-access -i rules -- 24 | fdmove 2 4 25 | s6-sudod -2 26 | ./aa-command 27 | 28 | With the following I file : 29 | 30 | #!/usr/bin/execlineb -s1 31 | ifelse -n { test $1 = start -o $1 = stop -o =1 = reset } 32 | { if { aa-echo -De "Invalid command: $1" } exit 1 } 33 | if { aa-echo -Dn +w "Running: " +b "aa-${1} $@" } 34 | exec aa-${1} -D $@ 35 | 36 | And to e.g. start service foobar, one would simply do something like : 37 | 38 | s6-sudo /run/services/aa-command/socket start foobar 39 | 40 | =head1 DESCRIPTION 41 | 42 | B(1) is a simple B script that can be used to run one of 43 | anopa's command, ensuring proper environment and logging the output. 44 | 45 | That is, instead of running e.g. `aa-start -W foo bar` to start those two 46 | services (but not auto-start any "wants"), one could do: 47 | 48 | aa-command start -W foo bar 49 | 50 | This would simply reset the environment to load it from I (much 51 | like what happens on boot, i.e. in the B scripts), set up a pipe on 52 | stderr to log things (timestamped via B) by appending into 53 | I; then execute `B> -D I` 54 | 55 | As a result, the command runs with a clean/predictable environment, and in 56 | addition to the output showing on the terminal, it gets added to the log of the 57 | current boot (again, as per the B scripts). 58 | -------------------------------------------------------------------------------- /doc/aa-ctty.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-ctty - Helper for execline script to set controlling terminal 4 | 5 | =head1 SYNOPSIS 6 | 7 | B [B<-D>] [B<-f> I] [B<-s>] I 8 | 9 | =head1 OPTIONS 10 | 11 | =over 12 | 13 | =item B<-D, --double-output> 14 | 15 | Enable double-output mode. Instead of using stdout for regular output, and 16 | stderr for warnings and errors, everything is sent both to stdout and stderr. 17 | This is intended to redirect stderr to a log file, so full output can be both 18 | shown on console and logged. 19 | 20 | =item B<-f, --fd> I 21 | 22 | Use file descriptor I as terminal; Defaults to stdin (0). 23 | 24 | =item B<-h, --help> 25 | 26 | Show help screen and exit. 27 | 28 | =item B<-s, --steal> 29 | 30 | Steal controlling terminal if already controlling terminal of a different 31 | session. 32 | 33 | =item B<-V, --version> 34 | 35 | Show version information and exit. 36 | 37 | =back 38 | 39 | =head1 DESCRIPTION 40 | 41 | B(1) will set the controlling terminal (via ioctl(TIOCSCTTY)) to that 42 | of the device open as file descriptor 0, or specified with B<--fd>. In typical 43 | B fashion, it then executes into the rest of its command line. 44 | 45 | If the ioctl call fails, a warning is printed and it still executes into the 46 | rest of its command line. If it fails to do so, it returns 111. 47 | -------------------------------------------------------------------------------- /doc/aa-echo.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-echo - Shows a message 4 | 5 | =head1 SYNOPSIS 6 | 7 | B [B<-D>] [B<-B>] [B<-T> | B<-t> | B<-w> | B<-e> | B<-n>] I 8 | 9 | =head1 OPTIONS 10 | 11 | =over 12 | 13 | =item B<-B, --blank-first> 14 | 15 | Prints a blank line (LF) first. 16 | 17 | =item B<-D, --double-output> 18 | 19 | Enable double-output mode. Instead of using stdout for regular output, and 20 | stderr for warnings and errors, everything is sent both to stdout and stderr. 21 | This is intended to redirect stderr to a log file, so full output can be both 22 | shown on console and logged. 23 | 24 | =item B<-e, --error> 25 | 26 | Show I as an error message. A red prefix "==> ERROR: " will be 27 | printed before the message. 28 | 29 | =item B<-h, --help> 30 | 31 | Show help screen and exit. 32 | 33 | =item B<-n, --normal> 34 | 35 | Show I as regular text, i.e. without any prefix or color. This can 36 | be used for simple echo, but make sure to see how arguments making up 37 | I are processed. 38 | 39 | =item B<-T, --title> 40 | 41 | Show I as a main title. A green "==> " prefix will be printed before 42 | the message. This is the default, if no other option is used. 43 | 44 | =item B<-t, --title2> 45 | 46 | Show I as a secondary title. A blue " -> " prefix will be printed 47 | before the message. 48 | 49 | =item B<-V, --version> 50 | 51 | Show version information and exit. 52 | 53 | =item B<-w, --warning> 54 | 55 | Show I as a warning. A yellow "==> WARNING: " prefix will be printed 56 | before the message. 57 | 58 | =back 59 | 60 | =head1 DESCRIPTION 61 | 62 | This is a little helper to easily print messages using the same color code as 63 | other B tools do. Note that all arguments making up I are 64 | printed one after the other, without adding a blank space; In other words, 65 | `aa-echo foo bar` will result in the string "==> foobar" being printed. 66 | 67 | This is due to the way B(1) processes its arguments, to allow you to 68 | set the text color. Any argument making up I can indeed be one of: 69 | 70 | =over 71 | 72 | =item B<+g, +green> 73 | 74 | Set color to green. 75 | 76 | =item B<+b, +blue> 77 | 78 | Set color to blue. 79 | 80 | =item B<+y, +yellow> 81 | 82 | Set color to yellow. 83 | 84 | =item B<+r, +red> 85 | 86 | Set color to red. 87 | 88 | =item B<+w, +white> 89 | 90 | Set color to white. 91 | 92 | =item B<+n, +normal> 93 | 94 | Reset color to normal. 95 | 96 | =item B<++TEXT> 97 | 98 | To print +TEXT 99 | 100 | =back 101 | 102 | For example: `aa-echo -w "The file " +r "/foo/bar" +n " doesn't exist"` 103 | -------------------------------------------------------------------------------- /doc/aa-incmdline.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-incmdline - Helper to parse kernel command line 4 | 5 | =head1 SYNOPSIS 6 | 7 | B [B<-D>] [B<-q>] [B<-f> I] [B<-r>] [B<-s>] I 8 | 9 | =head1 OPTIONS 10 | 11 | =over 12 | 13 | =item B<-D, --double-output> 14 | 15 | Enable double-output mode. Instead of using stdout for regular output, and 16 | stderr for warnings and errors, everything is sent both to stdout and stderr. 17 | This is intended to redirect stderr to a log file, so full output can be both 18 | shown on console and logged. 19 | 20 | =item B<-f, --file> I 21 | 22 | Read command line from I instead of I 23 | 24 | =item B<-h, --help> 25 | 26 | Show help screen and exit. 27 | 28 | =item B<-q, --quiet> 29 | 30 | Do not print value (if any) on stdout 31 | 32 | =item B<-r, --required> 33 | 34 | Ignore argument (i.e. exit 3) if no value was specified. 35 | 36 | =item B<-s, --safe>[=I] 37 | 38 | Ignore argument (i.e. exit 3) if it contains I (defaults to I). 39 | 40 | =item B<-V, --version> 41 | 42 | Show version information and exit. 43 | 44 | =back 45 | 46 | =head1 DESCRIPTION 47 | 48 | B(1) is a small helper to parse arguments from the kernel command 49 | line. It will read I (or I specified with B<--file>) and 50 | look for an argument I. If reading the file fails, it exits 2. If no 51 | I was specified, it exits 1. 52 | 53 | If there's no such argument on the command line, or B<--safe> was used and the 54 | argument's value contains I, or there's no value and B<--required> was used, 55 | it exits 3; Else it exits 0. 56 | 57 | If the argument had a value specified it will be printed on stdout unless 58 | B<--quiet> was used. 59 | -------------------------------------------------------------------------------- /doc/aa-kill.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-kill - Send signals to (almost) all processes 4 | 5 | =head1 SYNOPSIS 6 | 7 | B [B<-D>] [B<-u>] [B<-t>] [B<-k>] [B<-s>] 8 | 9 | =head1 OPTIONS 10 | 11 | =over 12 | 13 | =item B<-D, --double-output> 14 | 15 | Enable double-output mode. Instead of using stdout for regular output, and 16 | stderr for warnings and errors, everything is sent both to stdout and stderr. 17 | This is intended to redirect stderr to a log file, so full output can be both 18 | shown on console and logged. 19 | 20 | =item B<-h, --help> 21 | 22 | Show help screen and exit. 23 | 24 | =item B<-k, --kill> 25 | 26 | Send SIGKILL 27 | 28 | =item B<-s, --skip> 29 | 30 | Skip processes whose argv[0][0] is '@' This can be useful to ignore some 31 | long-running processes that needs to be dealt with e.g. back in the initramfs, 32 | only after umounting the root filesystem. 33 | 34 | =item B<-t, --term> 35 | 36 | Send SIGTERM then SIGCONT 37 | 38 | =item B<-u, --hup> 39 | 40 | Send SIGHUP 41 | 42 | =item B<-V, --version> 43 | 44 | Show version information and exit. 45 | 46 | =back 47 | 48 | =head1 DESCRIPTION 49 | 50 | B(1) can be used to send signals to (almost) all running processes. It 51 | is for example used during stage 3, after B(1) and before 52 | B(1) to kill any & all procesess that may have not been stopped 53 | otherwise. 54 | 55 | By default it sends nothing, so at least one of B<--hup>, B<--term> or B<--kill> 56 | must be specified. You can combine them to send all specified signals. They will 57 | always be sent in that order (SIGHUP, SIGTERM/SIGCONT, SIGKILL). 58 | 59 | If B<--skip> was not used, signals are sent using B(3) with a pid of -1. 60 | If B<--skip> was used, B(1) will then scan through I to list all 61 | running processes, and check their argv[0][0] (i.e. I) to 62 | skip any that starts with an '@' Also skipped will be process without cmdline 63 | (i.e. kernel threads), PID 1, and B(1) itself. 64 | 65 | Note that B(1) will ignore the signals it sends when B<--skip> isn't 66 | used, though that won't do much against SIGKILL. 67 | -------------------------------------------------------------------------------- /doc/aa-mount.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-mount - Mount a filesystem 4 | 5 | =head1 SYNOPSIS 6 | 7 | B [B<-D>] [B<-B> | B<-M>] [B<-r> | B<-w>] [B<-d>] [B<-t> I] 8 | [B<-o> I] I I 9 | 10 | =head1 OPTIONS 11 | 12 | =over 13 | 14 | =item B<-B, --bind> 15 | 16 | Remount subtree specified as I onto I, making it available 17 | in the two places. Note that the filesystem moun options remain the same and 18 | cannot be changed via B<--options>, you need a second call to change options, 19 | e.g: 20 | aa-mount -B olddir newdir 21 | aa-mount -o remount,ro,bind olddir newdir 22 | 23 | =item B<-D, --double-output> 24 | 25 | Enable double-output mode. Instead of using stdout for regular output, and 26 | stderr for warnings and errors, everything is sent both to stdout and stderr. 27 | This is intended to redirect stderr to a log file, so full output can be both 28 | shown on console and logged. 29 | 30 | =item B<-d, --mkdir> 31 | 32 | Create directory I before doing the mount. Note that this only tries 33 | to create the last element of the path, so all parents must already exists. 34 | 35 | =item B<-h, --help> 36 | 37 | Show help screen and exit. 38 | 39 | =item B<-M, --move> 40 | 41 | Move subtree specified as I to I So the content will be 42 | atomically moved from its old location (I) into the new one 43 | (I). 44 | 45 | =item B<-o, --options> I 46 | 47 | Set I as mount options to be used. They will be combined with any other 48 | options specified. 49 | 50 | =item B<-r, --read-only> 51 | 52 | Mount filesystem read-only 53 | 54 | =item B<-t, --fstype> I 55 | 56 | Use I as type of filesystem. Note that "auto" isn't supported. 57 | 58 | =item B<-V, --version> 59 | 60 | Show version information and exit. 61 | 62 | =item B<-w, --read-write> 63 | 64 | Mount filesystem read-write. 65 | 66 | =back 67 | 68 | =head1 DESCRIPTION 69 | 70 | B(1) mounts the specified filesystem using to the given options. It 71 | does not read I (or any other file), and therefore always requires 72 | both I and I to be specified; It also doesn't support an 73 | option to mount all filesystems from anywhere. 74 | 75 | This also means that when using option remount you need to specify all the 76 | options to be set, since B(1) will not read I to combine 77 | options from there with those on the command line, as B(8) does. 78 | 79 | Supported options are: defaults, ro, rw, bind, move, async, atime, noatime, dev, 80 | nodev, diratime, nodiratime, dirsync, exec, noexec, mand, nomand, relatime, 81 | norelatime, strictatime, nostrictatime, suid, nosuid, remount, sync. 82 | 83 | Any other options will be given to the kernel as-is. 84 | -------------------------------------------------------------------------------- /doc/aa-pivot.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-pivot - Pivot root directory 4 | 5 | =head1 SYNOPSIS 6 | 7 | B [B<-D>] I I 8 | 9 | =head1 OPTIONS 10 | 11 | =over 12 | 13 | =item B<-D, --double-output> 14 | 15 | Enable double-output mode. Instead of using stdout for regular output, and 16 | stderr for warnings and errors, everything is sent both to stdout and stderr. 17 | This is intended to redirect stderr to a log file, so full output can be both 18 | shown on console and logged. 19 | 20 | =item B<-h, --help> 21 | 22 | Show help screen and exit. 23 | 24 | =item B<-V, --version> 25 | 26 | Show version information and exit. 27 | 28 | =back 29 | 30 | =head1 DESCRIPTION 31 | 32 | B(1) moves the root filesystem of the current process to I 33 | and makes I the new root filesystem. Since it simply calls 34 | B(2), refer to that man page for further details. 35 | 36 | Note that B(1) doesn't change directory nor chroots, so for proper 37 | use, you should first chdir into I, call B(1) and then chroot 38 | into the current directory, e.g. using B(1). For example: 39 | 40 | cd NEWROOT 41 | aa-pivot . OLDROOT 42 | aa-chroot . COMMAND 43 | -------------------------------------------------------------------------------- /doc/aa-reboot.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-reboot - Reboots, powers off or halts the machine instantly 4 | 5 | =head1 SYNOPSIS 6 | 7 | B [B<-D>] B<-r> | B<-p> | B<-H> 8 | 9 | =head1 OPTIONS 10 | 11 | =over 12 | 13 | =item B<-D, --double-output> 14 | 15 | Enable double-output mode. Instead of using stdout for regular output, and 16 | stderr for warnings and errors, everything is sent both to stdout and stderr. 17 | This is intended to redirect stderr to a log file, so full output can be both 18 | shown on console and logged. 19 | 20 | =item B<-H, --halt> 21 | 22 | Halts the machine. 23 | 24 | =item B<-h, --help> 25 | 26 | Show help screen and exit. 27 | 28 | =item B<-p, --poweroff> 29 | 30 | Powers off the machine. 31 | 32 | =item B<-r, --reboot> 33 | 34 | Reboots the machine. 35 | 36 | =item B<-V, --version> 37 | 38 | Show version information and exit. 39 | 40 | =back 41 | 42 | =head1 DESCRIPTION 43 | 44 | B(1) is a simple wrapper around a B(2) call. 45 | 46 | You should never trigger it manually/directly. Instead, use B(1), 47 | that will send the appropriate commands to B (PID 1) in order to 48 | properly shut down the system, before (probably) ending with a call to 49 | B(1) at the end of stage 4. 50 | -------------------------------------------------------------------------------- /doc/aa-reset.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-reset - Reset status of one-shot services 4 | 5 | =head1 SYNOPSIS 6 | 7 | B [B<-D>] [B<-r> I] [B<-A> | B<-a> | B<-o>] [I] 8 | 9 | =head1 OPTIONS 10 | 11 | =over 12 | 13 | =item B<-A, --auto> 14 | 15 | Automatic mode; See L|/DESCRIPTION> below for what will be done. 16 | 17 | =item B<-a, --started> 18 | 19 | Reset to "Started" 20 | 21 | =item B<-D, --double-output> 22 | 23 | Enable double-output mode. Instead of using stdout for regular output, and 24 | stderr for warnings and errors, everything is sent both to stdout and stderr. 25 | This is intended to redirect stderr to a log file, so full output can be both 26 | shown on console and logged. 27 | 28 | =item B<-h, --help> 29 | 30 | Show help screen and exit. 31 | 32 | =item B<-o, --stopped> 33 | 34 | Reset to "Stopped" 35 | 36 | =item B<-r, --repodir> I 37 | 38 | Use I as repository directory. This is where servicedirs will be looked 39 | for. 40 | 41 | =item B<-V, --version> 42 | 43 | Show version information and exit. 44 | 45 | =back 46 | 47 | =head1 DESCRIPTION 48 | 49 | B(1) will reset the status of the specified one-shot services as 50 | specified: 51 | 52 | - to "Started" if B<--started> was specified, 53 | 54 | - to "Stopped" if B<--stopped> was specified, 55 | 56 | - or when B<--auto> was specified it will reset "Starting failed" and "Start 57 | failed" to "Started"; and "Stopping failed" and "Stop failed" to "Stopped" 58 | 59 | Note that a service either "Starting" or "Stopping" will never be reset. 60 | 61 | You can use B<-> as service name to read actual service names from stdin, where 62 | there must be one name per line. 63 | -------------------------------------------------------------------------------- /doc/aa-service.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-service - Helper for execline script to get service name/instance 4 | 5 | =head1 SYNOPSIS 6 | 7 | B [B<-D>] [B<-l>] I 8 | 9 | =head1 OPTIONS 10 | 11 | =over 12 | 13 | =item B<-D, --double-output> 14 | 15 | Enable double-output mode. Instead of using stdout for regular output, and 16 | stderr for warnings and errors, everything is sent both to stdout and stderr. 17 | This is intended to redirect stderr to a log file, so full output can be both 18 | shown on console and logged. 19 | 20 | =item B<-h, --help> 21 | 22 | Show help screen and exit. 23 | 24 | =item B<-l, --log> 25 | 26 | To use for a service logger run script, i.e. when current folder will be 27 | subfolder I of the servicedir. 28 | 29 | =item B<-V, --version> 30 | 31 | Show version information and exit. 32 | 33 | =back 34 | 35 | =head1 DESCRIPTION 36 | 37 | This is a little helper for execline scripts (e.g. a service's I script) 38 | that will perform variable substitution on I for: 39 | 40 | =over 41 | 42 | =item B 43 | 44 | Will be the name of the current folder, i.e. full service name (e.g. I 45 | or I) 46 | 47 | =item B 48 | 49 | Will be the name of the service, without the instance name if any (e.g. 50 | I or I) 51 | 52 | =item B 53 | 54 | Will be the instance name of the service if any, else empty string (e.g. empty 55 | string or I) 56 | 57 | =back 58 | 59 | This can be useful to get the service/instance name dynamicly; e.g. a service 60 | could use I<${INSTANCE}> as argument, and a generic logger could then use 61 | I as logdir. 62 | -------------------------------------------------------------------------------- /doc/aa-setready.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-setready - Set a service (un)ready 4 | 5 | =head1 SYNOPSIS 6 | 7 | B [B<-D>] [B<-U> | B<-N>] I 8 | 9 | =head1 OPTIONS 10 | 11 | =over 12 | 13 | =item B<-D, --double-output> 14 | 15 | Enable double-output mode. Instead of using stdout for regular output, and 16 | stderr for warnings and errors, everything is sent both to stdout and stderr. 17 | This is intended to redirect stderr to a log file, so full output can be both 18 | shown on console and logged. 19 | 20 | =item B<-h, --help> 21 | 22 | Show help screen and exit. 23 | 24 | =item B<-N, --unready> 25 | 26 | Mark the service unready and emit event 'N' on I fifodir. 27 | 28 | =item B<-U, --ready> 29 | 30 | Mark the service ready and emit event 'U' on I fifodir. This is the 31 | default. 32 | 33 | =item B<-V, --version> 34 | 35 | Show version information and exit. 36 | 37 | =back 38 | 39 | =head1 DESCRIPTION 40 | 41 | B(1) is a simple tool to mark a long-running service ready or 42 | "unready". 43 | 44 | Marking a service ready or unready means updating its s6 status file, and 45 | emitting the corresponding event on the service's fifodir I. 46 | Unreadiness is meant for service that can stay up (running) but lose their ready 47 | state (e.g. connection dropped). 48 | 49 | Obviously you need to have the appropriate permissions to perform all the needed 50 | tasks. 51 | 52 | =head1 RETURN VALUE 53 | 54 | B(1) will return 0 on success, or one of the following on error: 55 | 56 | =over 57 | 58 | =item B<1> 59 | 60 | Syntax error (e.g. unknown option) 61 | 62 | =item B<2> 63 | 64 | Failed to read s6 status file 65 | 66 | =item B<3> 67 | 68 | Service is not up 69 | 70 | =item B<4> 71 | 72 | Failed to init timestamp (needed for readiness timestamp, when marking ready) 73 | 74 | =item B<5> 75 | 76 | Failed to write s6 status file 77 | 78 | =item B<6> 79 | 80 | Failed to sent the event on I fifodir 81 | 82 | =back 83 | -------------------------------------------------------------------------------- /doc/aa-shutdown.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-shutdown - Helper to trigger a reboot/power off/halt of the machine 4 | 5 | =head1 SYNOPSIS 6 | 7 | B [B<-r> | B<-p> | B<-H>] 8 | 9 | =head1 OPTIONS 10 | 11 | =over 12 | 13 | =item B<-H, --halt> 14 | 15 | Halts the machine. 16 | 17 | =item B<-h, --help> 18 | 19 | Show help screen and exit. 20 | 21 | =item B<-p, --poweroff> 22 | 23 | Powers off the machine. 24 | 25 | =item B<-r, --reboot> 26 | 27 | Reboots the machine. 28 | 29 | =item B<-V, --version> 30 | 31 | Show version information and exit. 32 | 33 | =back 34 | 35 | =head1 DESCRIPTION 36 | 37 | B(1) is a simple helper that will send the appropriate commands to 38 | B (using B). 39 | 40 | It obviously expects it to be running (as PID 1) using I 41 | as its scandir. 42 | 43 | Additionally, if called as B, B or B then it 44 | automatically defaults to the corresponding action. This allows to use symlinks 45 | by those names pointing to B(1). Note that in this case: 46 | 47 | - An option isn't required; i.e. calling it as `reboot` will trigger the 48 | reboot, as would `aa-shutdown --reboot` have done; 49 | 50 | - If an option is specified, it takes precedence. So calling it `reboot -p` will 51 | power off the machine. 52 | -------------------------------------------------------------------------------- /doc/aa-stage0.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-stage0 - Stage 0: Mounting root file system 4 | 5 | =head1 SYNOPSIS 6 | 7 | B 8 | 9 | =head1 DESCRIPTION 10 | 11 | B(1) is an B script meant to be used as I inside an 12 | initramfs. 13 | 14 | It loads the environment from I (via B), and will log 15 | messages into file I, prefixing them with a TAI timestamp via 16 | B. 17 | 18 | It doesn't do much in itself, the bulk of the work being done via services, much 19 | like during system init (stage 1/2). It will simply call B(1) using 20 | I as repodir, and I as listdir for 21 | services to start. 22 | 23 | Note that this refer to the initramfs itself, so the content of 24 | I would differ on that from the system, or more 25 | likely be the same as I from the root fs. 26 | 27 | Services are meant to mount the root file system on to I and mount all 28 | API file systems in there as well: I, I, 29 | I and I 30 | 31 | It is also up to them to load required kernel modules in order to do so. 32 | 33 | Once B(1) is done, B(1) will mount bind the rootfs (of the 34 | initramfs) onto I (so it's possible to pivot back into 35 | it at the end of stage 3) before doing a mount move of I onto I and 36 | executing (via B(1)) into I, or whatever was specified 37 | via I on the kernel command line. 38 | 39 | If B(1) exits non-zero, e.g. if an essential service failed to be 40 | started, B(1) assumes the root file system couldn't be mounted, and 41 | tries to open a shell (I) to give you a possibility to fix things. 42 | Exiting the shell will resume the process. 43 | 44 | You can also specify I on the kernel command line to open a shell after 45 | B(1) succesfully completed, before moving I to I (also 46 | before mount binding the rootfs). 47 | -------------------------------------------------------------------------------- /doc/aa-stage1.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-stage1 - Stage 1: Preparing system 4 | 5 | =head1 SYNOPSIS 6 | 7 | B 8 | 9 | =head1 DESCRIPTION 10 | 11 | B(1) is an B script meant to be used as I for the 12 | system. 13 | 14 | It loads the environment from I (via B), and first 15 | checks if a file I exists, and if so imports its 16 | content into I (This is aimed to import log messages from 17 | the initramfs, as e.g. B(1) generates them.) 18 | 19 | It will log its own messages into file I, prefixing them 20 | with a TAI timestamp via B. 21 | 22 | It doesn't do much in itself, the bulk of the work being done via services. It 23 | will create the runtime repository I using B(1) and 24 | I as listdir. 25 | 26 | A service I must exist and be a logger that will be used to catch 27 | all "uncaught logs" (i.e. anything not redirected to a service logger). A FIFO 28 | must be created as I and will be 29 | automatically started by B; It will also be used as trigger for 30 | B(1). 31 | 32 | -------------------------------------------------------------------------------- /doc/aa-stage2.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-stage2 - Stage 2: Initialyzing system 4 | 5 | =head1 SYNOPSIS 6 | 7 | B 8 | 9 | =head1 DESCRIPTION 10 | 11 | B(1) is an B script called by B once the runtime 12 | repository has been created and B is running as PID 1, to actually 13 | perform all initialization tasks. 14 | 15 | It will log messages into file I, prefixing them with a 16 | TAI timestamp via B. 17 | 18 | It starts all services via B(1) using I as 19 | listdir, unless argument B was specified on kernel command line, in which 20 | case I is used as listdir intead. 21 | 22 | If B(1) exits non-zero, it assumes there might not even be a getty 23 | running, and will try to open a shell (I). Else, the system is assumed to 24 | be ready. 25 | -------------------------------------------------------------------------------- /doc/aa-stage3.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-stage3 - Stage 3: Preparing reboot/poweroff/halt 4 | 5 | =head1 SYNOPSIS 6 | 7 | B 8 | 9 | =head1 DESCRIPTION 10 | 11 | B(1) is an B script B will exec into when told, 12 | e.g. via B(1). 13 | 14 | It will log messages into file I, prefixing them with a 15 | TAI timestamp via B, also sending them to I. 16 | 17 | It stops all services via B(1) using option B<--all>, and skipping 18 | service I to catch all possible logs as long as possible. The 19 | B process of that service will be sent command 'x' so it simply 20 | exits when the supervised process will. 21 | 22 | Signal SIGTERM is then sent to (almost) all processes, using B(1) with 23 | option B<--skip>; Then SIGKILL is sent similarly. 24 | 25 | It will then pivot root (back) into I via B(1) and 26 | exec into I will the same argument it received from B, so 27 | either "halt", "reboot" or "poweroff". 28 | 29 | If B(1) fails, it will try to open a shell (I) to let you deal 30 | with things manually. 31 | -------------------------------------------------------------------------------- /doc/aa-stage4.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-stage4 - Stage 4: Unmounting root file system 4 | 5 | =head1 SYNOPSIS 6 | 7 | B 8 | 9 | =head1 DESCRIPTION 10 | 11 | B(1) is an B script meant to be used as I inside 12 | an initramfs. 13 | 14 | It loads the environment from I (via B). 15 | 16 | It doesn't do much in itself, the bulk of the work being done via services, much 17 | like during system shutdown (stage 3). It will simply call B(1) using 18 | I as repodir, with option B<--all>. 19 | 20 | Services are meant to unmount the root file system from I as well as 21 | all API file systems in there: I, I, 22 | I and I 23 | 24 | Then it will mount I and I in order to run B(1) to 25 | make sure everything is closed/unmounted. It then performs the requested action 26 | (on stage 3) via B(1). 27 | -------------------------------------------------------------------------------- /doc/aa-stop.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-stop - Stop services 4 | 5 | =head1 SYNOPSIS 6 | 7 | B [B<-D>] [B<-r> I] [B<-l> I] [B<-a>] 8 | [B<-k> I] [B<-t> I] [B<-n>] [B<-v>] [I] 9 | 10 | =head1 OPTIONS 11 | 12 | =over 13 | 14 | =item B<-a, --all> 15 | 16 | Stops all running/started services. 17 | 18 | Specify this option twice to enable "stop-all" mode, intended to bring down the 19 | entire supervised tree (i.e. be used during stage 3, after B has been 20 | brought down). 21 | When used, you shouldn't specify any service on the command line. 22 | 23 | Also see below as well as B<--timeout> for more implications. 24 | 25 | =item B<-D, --double-output> 26 | 27 | Enable double-output mode. Instead of using stdout for regular output, and 28 | stderr for warnings and errors, everything is sent both to stdout and stderr. 29 | This is intended to redirect stderr to a log file, so full output can be both 30 | shown on console and logged. 31 | 32 | =item B<-h, --help> 33 | 34 | Show help screen and exit. 35 | 36 | =item B<-k, --skip> I 37 | 38 | If I was asked to be stopped, silently ignore it. This is intended for 39 | use alongside B<--all --all> to keep the catch-all logger service running as 40 | long as possible. Its B will only be sent an 'x' command, so 41 | stopping the service next will automatically have its supervisor exit as well. 42 | 43 | =item B<-l, --listdir> I 44 | 45 | Use I to list services to start. Only one can be set, if specified more 46 | than once the last one will be used. 47 | 48 | If I doesn't start with a slash or dot, it will be prefixed with 49 | I 50 | 51 | =item B<-n, --dry-list> 52 | 53 | Only print the name of the services, but do not stop anything. 54 | 55 | =item B<-r, --repodir> I 56 | 57 | Use I as repository directory. This is where servicedirs will be looked 58 | for. 59 | 60 | =item B<-t, --timeout> I 61 | 62 | Set default timeout to I seconds. You can use 0 for no timeout. 63 | Timeout can also be set in service in a file I in its servicedir. 64 | 65 | If the "stop-all" mode is enabled (i.e. option B<--all> used twice), the default 66 | timeout (whether or not set on command line) will also be used as a maximum 67 | value. 68 | 69 | =item B<-V, --version> 70 | 71 | Show version information and exit. 72 | 73 | =item B<-v, --verbose> 74 | 75 | Print auto-added dependencies (from "needs"). Note that dependencies are 76 | "reversed" here, i.e. if foo needs bar, B(1) will print "bar needs foo" 77 | as to indicate that stopping bar needs to (first) stop foo. 78 | 79 | Also note that this will always print dependencies for all started services, 80 | whether or not they'll apply to the requested operation. 81 | 82 | This will be printed on stdout unless B<--dry-list> was used, then it goes to 83 | stderr. 84 | 85 | =back 86 | 87 | =head1 DESCRIPTION 88 | 89 | B(1) allows to stop one or more services. It works in similar fashion 90 | to B(1) but processing order and dependencies "in reverse" so to 91 | speak. 92 | 93 | That is to say if service A was to be started after service B, then it will be 94 | stopped before B. And if A had a dependency (I) on C, then stopping C 95 | will also cause for A to be stopped. 96 | 97 | You can use B<-> as service name to read actual service names from stdin, where 98 | there must be one name per line. 99 | 100 | Refer to B(1) for descriptions of servicedirs and service dependencies. 101 | 102 | B(1) works in a very similar manner as B(1), with the 103 | following differences : 104 | 105 | =head1 STOPPING A LONG-RUN SERVICE 106 | 107 | B(1) will check if the service is running, and if not simply announce 108 | it as not up. 109 | 110 | If the "stop-all" mode is enabled (i.e. option B<--all> used twice), failing 111 | dependencies will not cause not to stop services. That is, is A needs B, 112 | stopping B would depend on stopping A first, and if that failed B wouldn't be 113 | stopped (Stopping failed: Failed dependency: A). However with this mode B 114 | would be stopped, as if A had been successfully stopped. 115 | 116 | Additionally, B(1) will send command 'x' to B of all down 117 | services, while it will send commands 'dx' (instead of 'd') to the up services' 118 | B, so that after bringing their services down they exit as well. 119 | This is obviously all intended to bring the supervised tree all down, as is 120 | expected, and shouldn't be used if B is still running (as it would 121 | bring the B back up). 122 | 123 | =head2 Service not up 124 | 125 | When you call B(1) it will first create a list of all services to be 126 | stopped. Any service specified that isn't up will simply be ignored with a "Not 127 | up" message shown. 128 | 129 | It should be noted that, for long-run services, it is possible that a service 130 | was up then, but will be down by the time B(1) wants to stop it. E.g. 131 | because other services stopped first caused it to stop/crash. 132 | 133 | In such a case, the message "Stopping service..." will be shown, and 134 | B(1) will send the command as usual; But it won't check for errors 135 | (nor wait for the 'd' event) and simply report the service as "Not up" instead. 136 | 137 | This should ensure that e.g. s6 doesn't restart the service, or stops it if that 138 | was already (being) done. 139 | 140 | =head1 STOPPING A ONE-SHOT SERVICE 141 | 142 | Obviously, the script used is I and not I. Other than that, the 143 | process is much the same, so you can refer to B(1) for more. 144 | -------------------------------------------------------------------------------- /doc/aa-sync.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-sync - Flush filesystems buffers 4 | 5 | =head1 SYNOPSIS 6 | 7 | B 8 | 9 | =head1 OPTIONS 10 | 11 | =over 12 | 13 | =item B<-h, --help> 14 | 15 | Show help screen and exit. 16 | 17 | =item B<-V, --version> 18 | 19 | Show version information and exit. 20 | 21 | =back 22 | 23 | =head1 DESCRIPTION 24 | 25 | B(1) causes all buffered modifications to file metadata and data to be 26 | written to the underlying filesystems. 27 | 28 | This is just a wrapper for B(2) 29 | -------------------------------------------------------------------------------- /doc/aa-terminate.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-teminate - Tries to close/unmount everything it can 4 | 5 | =head1 SYNOPSIS 6 | 7 | B [B<-D>] [B<-l>] [B<-a>] [B<-q> | B<-v>] 8 | 9 | =head1 OPTIONS 10 | 11 | =over 12 | 13 | =item B<-a, --apis> 14 | 15 | When done, unmount API file systems: I, I, I and I If a 16 | regular umount call fails, a lazy umount will be performed. 17 | 18 | =item B<-D, --double-output> 19 | 20 | Enable double-output mode. Instead of using stdout for regular output, and 21 | stderr for warnings and errors, everything is sent both to stdout and stderr. 22 | This is intended to redirect stderr to a log file, so full output can be both 23 | shown on console and logged. 24 | 25 | =item B<-h, --help> 26 | 27 | Show help screen and exit. 28 | 29 | =item B<-l, --lazy-umounts> 30 | 31 | When nothing can be done anymore (see L|/DESCRIPTION> below) and 32 | there are still active mount points, run the loop again performing lazy 33 | unmounts: making the mount point unavailable for new accesses, and actually 34 | performing the unmount when the mount point ceases to be busy. 35 | 36 | =item B<-q, --quiet> 37 | 38 | Do not output anything (not even warnings of "left overs" when done; See 39 | B<--verbose> for more). 40 | 41 | =item B<-V, --version> 42 | 43 | Show version information and exit. 44 | 45 | =item B<-v, --verbose> 46 | 47 | Out information about everything that is tried. By default it only outputs when 48 | something succeeds (and warnings of "left-overs" when done, listing anything 49 | that couldn't be closed/removed/unmounted). 50 | With this option, B(1) will output about any operation it 51 | attempts, as well as an error message on failure. This is usually not important 52 | information and mostly useful for testing/debugging purposes. 53 | 54 | =back 55 | 56 | =head1 DESCRIPTION 57 | 58 | Ideally, when shutting down/rebooting the system, anything that was 59 | opened/mounted on boot (i.e. via B(1) during stage 0/1) should be 60 | closed/unmounted automatically (i.e. via B(1) during stage 3/4), as 61 | defined on the relevant services. 62 | 63 | However, things might not go as planned, for one reason or another (starting 64 | with, things might have been opened/mounted outside of any services). 65 | 66 | B(1) is aimed at closing/unmounting all that can be done at the 67 | end of e.g. stage 3/4, right before powering off/rebooting. 68 | 69 | To do so, it will try to: 70 | 71 | =over 72 | 73 | =item 1. Turn all swaps off 74 | 75 | =item 2. Unmount everything but I, I, I, I and I 76 | 77 | =item 3. Close all loop devices (I) 78 | 79 | =item 4. Remove all DM block devices (I) 80 | 81 | =back 82 | 83 | When done, if there are still things to do (i.e. certain operations failed) and 84 | at least one attempt was successful, it will try it all again, until either 85 | there's nothing left to do, or it can't do anything else. 86 | 87 | If option B<--lazy-umounts> was specified and there are still active mount 88 | points, it will try all over again, performing lazy umounts. 89 | 90 | Then, if option B<--apis> was specified it will umount API file systems: 91 | I, I, I and I If a regular umount call fails, a lazy 92 | umount will be performed (regardless of whether option B<--lazy-umounts> was 93 | used or not). 94 | 95 | Finally, unless option B<--quiet> was specified, warnings will be emitted for 96 | everything left (swaps, mount points, loop/block devices that couldn't be 97 | closed/unmounted/removed), if there is any. 98 | 99 | =head1 NOTE 100 | 101 | B(1) requires I and I to be mounted. Specifically, it 102 | reads I to list active swaps and I for mount points; 103 | It also reads I for loop/block devices, and uses I to 104 | remove block devices. 105 | 106 | =head1 RETURN VALUES 107 | 108 | B(1) returns 0 on success (no "left-overs"), 1 on syntax error 109 | (e.g. invalid option) and 2 if there is at least one left-over (excluding API 110 | file systems). 111 | -------------------------------------------------------------------------------- /doc/aa-test.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-test - Test file types 4 | 5 | =head1 SYNOPSIS 6 | 7 | B [B<-D>] [B<-b> | B<-d> | B<-e> | B<-f> | B<-L> | B<-p> | B<-S> | 8 | B<-r> | B<-w> | B<-x>] [B<-R> [I]] I 9 | 10 | =head1 OPTIONS 11 | 12 | =over 13 | 14 | =item B<-b, --block> 15 | 16 | Test whether I exists and is a block special 17 | 18 | =item B<-D, --double-output> 19 | 20 | Enable double-output mode. Instead of using stdout for regular output, and 21 | stderr for warnings and errors, everything is sent both to stdout and stderr. 22 | This is intended to redirect stderr to a log file, so full output can be both 23 | shown on console and logged. 24 | 25 | =item B<-d, --directory> 26 | 27 | Test whether I exists and is a directory 28 | 29 | =item B<-e, --exists> 30 | 31 | Test whether I exists 32 | 33 | =item B<-f, --file> 34 | 35 | Test whether I exists and is a regular file 36 | 37 | =item B<-h, --help> 38 | 39 | Show help screen and exit. 40 | 41 | =item B<-L, --symlink> 42 | 43 | Test whether I exists and is a symlink 44 | 45 | =item B<-p, --pipe> 46 | 47 | Test whether I exists and is a named pipe (FIFO) 48 | 49 | =item B<-R, --repeat> [I] 50 | 51 | If I doesn't exist, wait 1 second and try again, repeating the test up to 52 | I times. By default 0 is used, meaning repeat the test forever. 53 | 54 | =item B<-r, --read> 55 | 56 | Test whether I exists and read permission is granted 57 | 58 | =item B<-S, --socket> 59 | 60 | Test whether I exists and is a socket 61 | 62 | =item B<-V, --version> 63 | 64 | Show version information and exit. 65 | 66 | =item B<-w, --write> 67 | 68 | Test whether I exists and write permission is granted 69 | 70 | =item B<-x, --execute> 71 | 72 | Test whether I exists and execute (search) permission is granted 73 | 74 | =back 75 | 76 | =head1 DESCRIPTION 77 | 78 | B(1) is a simple tool to check file types/permissions as specified, and 79 | return 0 when true, else: 80 | 81 | 1: Syntax error (e.g. invalid option) 82 | 83 | 2: System error (e.g. permission denied) 84 | 85 | 3: I doesn't exist 86 | 87 | 4: I exists, but the rest of the test failed (e.g. wrong type) 88 | -------------------------------------------------------------------------------- /doc/aa-tty.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-tty - Prints the device name of the active tty 4 | 5 | =head1 SYNOPSIS 6 | 7 | B [B<-D>] 8 | 9 | =head1 OPTIONS 10 | 11 | =over 12 | 13 | =item B<-D, --double-output> 14 | 15 | Enable double-output mode. Instead of using stdout for regular output, and 16 | stderr for warnings and errors, everything is sent both to stdout and stderr. 17 | This is intended to redirect stderr to a log file, so full output can be both 18 | shown on console and logged. 19 | 20 | =item B<-h, --help> 21 | 22 | Show help screen and exit. 23 | 24 | =item B<-V, --version> 25 | 26 | Show version information and exit. 27 | 28 | =back 29 | 30 | =head1 DESCRIPTION 31 | 32 | B(1) is a small tool that will print to device name of the active tty. 33 | It determines it by reading I files in I starting with 34 | I and "going up" as much as possible. 35 | -------------------------------------------------------------------------------- /doc/aa-umount.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | aa-umount - Unmount a filesystem 4 | 5 | =head1 SYNOPSIS 6 | 7 | B [B<-D>] [B<-f> | B<-l>] I 8 | 9 | =head1 OPTIONS 10 | 11 | =over 12 | 13 | =item B<-D, --double-output> 14 | 15 | Enable double-output mode. Instead of using stdout for regular output, and 16 | stderr for warnings and errors, everything is sent both to stdout and stderr. 17 | This is intended to redirect stderr to a log file, so full output can be both 18 | shown on console and logged. 19 | 20 | =item B<-f, --force> 21 | 22 | Force unmount even if busy (only for NFS mounts). This can cause data loss. 23 | 24 | =item B<-h, --help> 25 | 26 | Show help screen and exit. 27 | 28 | =item B<-l, --lazy> 29 | 30 | Perform a lazy unmount: make the mount point unavailable for new accesses, and 31 | actually perform the unmount when the mount point ceases to be busy. 32 | 33 | =item B<-V, --version> 34 | 35 | Show version information and exit. 36 | 37 | =back 38 | 39 | =head1 DESCRIPTION 40 | 41 | B(1) unmounts the specified mount point. It isn't possible to unmount 42 | a filesystem if it is busy, e.g. there are still open files. This could even be 43 | caused by B(1) itself; It is possible to avoid this using the 44 | B<--lazy> option. 45 | -------------------------------------------------------------------------------- /doc/footer.pod: -------------------------------------------------------------------------------- 1 | 2 | =head1 BUGS 3 | 4 | They're probably crawling somewhere in there... if you happen to catch one, 5 | (or more) report it and I'll do my best to squash it. 6 | 7 | =head1 REPOSITORY 8 | 9 | You can find the latest source code of B as well as report bugs and/or 10 | suggest features on its GitHub repository, available at 11 | L; or visit its official website at 12 | L 13 | 14 | =head1 AUTHOR 15 | 16 | =over 17 | 18 | =item Olivier Brunel 19 | 20 | =back 21 | -------------------------------------------------------------------------------- /package/deps-build: -------------------------------------------------------------------------------- 1 | /package/admin/s6 2 | /package/prog/skalibs 3 | /package/admin/execline 4 | -------------------------------------------------------------------------------- /package/info: -------------------------------------------------------------------------------- 1 | package=anopa 2 | version=0.5.0 3 | category=admin 4 | package_macro_name=ANOPA 5 | -------------------------------------------------------------------------------- /package/modes: -------------------------------------------------------------------------------- 1 | aa-chroot 0755 2 | aa-command 0755 3 | aa-ctty 0755 4 | aa-echo 0755 5 | aa-enable 0755 6 | aa-incmdline 0755 7 | aa-kill 0755 8 | aa-mount 0755 9 | aa-pivot 0755 10 | aa-reboot 0755 11 | aa-reset 0755 12 | aa-service 0755 13 | aa-setready 0755 14 | aa-shutdown 0755 15 | aa-stage0 0755 16 | aa-stage1 0755 17 | aa-stage2 0755 18 | aa-stage3 0755 19 | aa-stage4 0755 20 | aa-start 0755 21 | aa-status 0755 22 | aa-stop 0755 23 | aa-sync 0755 24 | aa-terminate 0755 25 | aa-test 0755 26 | aa-tty 0755 27 | aa-umount 0755 28 | -------------------------------------------------------------------------------- /package/targets.mak: -------------------------------------------------------------------------------- 1 | BIN_TARGETS := \ 2 | aa-chroot \ 3 | aa-ctty \ 4 | aa-echo \ 5 | aa-enable \ 6 | aa-incmdline \ 7 | aa-kill \ 8 | aa-mount \ 9 | aa-pivot \ 10 | aa-reboot \ 11 | aa-reset \ 12 | aa-service \ 13 | aa-setready \ 14 | aa-start \ 15 | aa-status \ 16 | aa-stop \ 17 | aa-sync \ 18 | aa-terminate \ 19 | aa-test \ 20 | aa-tty \ 21 | aa-umount 22 | 23 | BIN_SCRIPTS_TARGET := \ 24 | aa-command \ 25 | aa-shutdown 26 | 27 | LIBEXEC_SCRIPTS_TARGET := \ 28 | aa-stage0 \ 29 | aa-stage1 \ 30 | aa-stage2 \ 31 | aa-stage3 \ 32 | aa-stage4 33 | 34 | DOC_TARGETS := \ 35 | anopa.1 \ 36 | aa-chroot.1 \ 37 | aa-command.1 \ 38 | aa-ctty.1 \ 39 | aa-echo.1 \ 40 | aa-enable.1 \ 41 | aa-incmdline.1 \ 42 | aa-kill.1 \ 43 | aa-mount.1 \ 44 | aa-pivot.1 \ 45 | aa-reboot.1 \ 46 | aa-reset.1 \ 47 | aa-service.1 \ 48 | aa-setready.1 \ 49 | aa-shutdown.1 \ 50 | aa-stage0.1 \ 51 | aa-stage1.1 \ 52 | aa-stage2.1 \ 53 | aa-stage3.1 \ 54 | aa-stage4.1 \ 55 | aa-start.1 \ 56 | aa-status.1 \ 57 | aa-stop.1 \ 58 | aa-sync.1 \ 59 | aa-terminate.1 \ 60 | aa-test.1 \ 61 | aa-tty.1 \ 62 | aa-umount.1 63 | 64 | ifdef DO_ALLSTATIC 65 | LIBANOPA := libanopa.a 66 | else 67 | LIBANOPA := libanopa.so 68 | endif 69 | 70 | ifdef DO_SHARED 71 | SHARED_LIBS := libanopa.so 72 | endif 73 | 74 | ifdef DO_STATIC 75 | STATIC_LIBS := libanopa.a 76 | endif 77 | -------------------------------------------------------------------------------- /src/anopa/aa-reset.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * aa-reset.c 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #define _BSD_SOURCE 24 | 25 | #include "anopa/config.h" 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include "util.h" 39 | 40 | enum 41 | { 42 | MODE_NONE = 0, 43 | MODE_AUTO, 44 | MODE_STARTED, 45 | MODE_STOPPED 46 | }; 47 | 48 | static void 49 | reset_service (const char *name, intptr_t mode) 50 | { 51 | aa_service *s; 52 | int si; 53 | int r; 54 | aa_evt old_event; 55 | aa_evt event; 56 | 57 | r = aa_get_service (name, &si, 1); 58 | if (r < 0) 59 | { 60 | aa_put_err (name, errmsg[-r], 1); 61 | return; 62 | } 63 | 64 | r = aa_preload_service (si); 65 | if (r < 0) 66 | { 67 | aa_put_err (name, errmsg[-r], 1); 68 | return; 69 | } 70 | 71 | s = aa_service (si); 72 | if (aa_service_status_read (&s->st, aa_service_name (s)) < 0 && errno != ENOENT) 73 | { 74 | int e = errno; 75 | 76 | aa_put_err (name, "Failed to read service status file: ", 0); 77 | aa_bs_noflush (AA_ERR, strerror (e)); 78 | aa_end_err (); 79 | return; 80 | } 81 | 82 | if (s->st.type == AA_TYPE_LONGRUN) 83 | { 84 | aa_put_err (name, "Can only reset ont-shot services", 1); 85 | return; 86 | } 87 | 88 | /* Starting/Stopping cannot be reset */ 89 | if (s->st.event == AA_EVT_STARTING || s->st.event == AA_EVT_STOPPING) 90 | return; 91 | 92 | if (mode == MODE_AUTO) 93 | { 94 | if (s->st.event == AA_EVT_STARTING_FAILED || s->st.event == AA_EVT_START_FAILED) 95 | event = AA_EVT_STARTED; 96 | else if (s->st.event == AA_EVT_STOPPING_FAILED || s->st.event == AA_EVT_STOP_FAILED) 97 | event = AA_EVT_STOPPED; 98 | else 99 | return; 100 | } 101 | else 102 | event = (mode == MODE_STARTED) ? AA_EVT_STARTED : AA_EVT_STOPPED; 103 | 104 | if (s->st.event == event) 105 | return; 106 | 107 | tain_now_g (); 108 | old_event = s->st.event; 109 | s->st.event = event; 110 | s->st.stamp = STAMP; 111 | aa_service_status_set_msg (&s->st, ""); 112 | if (aa_service_status_write (&s->st, aa_service_name (s)) < 0) 113 | { 114 | int e = errno; 115 | 116 | aa_put_err (name, "Failed to write service status file: ", 0); 117 | aa_bs_noflush (AA_ERR, strerror (e)); 118 | aa_end_err (); 119 | } 120 | else 121 | { 122 | aa_put_title (1, name, "", 0); 123 | aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_OFF); 124 | aa_bs_noflush (AA_OUT, eventmsg[old_event]); 125 | aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_ON); 126 | aa_bs_noflush (AA_OUT, " -> "); 127 | aa_bs_noflush (AA_OUT, eventmsg[event]); 128 | aa_end_title (); 129 | } 130 | } 131 | 132 | static void 133 | dieusage (int rc) 134 | { 135 | aa_die_usage (rc, "[OPTION...] [service...]", 136 | " -D, --double-output Enable double-output mode\n" 137 | " -r, --repodir DIR Use DIR as repository directory\n" 138 | " -A, --auto Automatic mode\n" 139 | " -a, --started Reset to Started\n" 140 | " -o, --stopped Reset to Stopped\n" 141 | " -h, --help Show this help screen and exit\n" 142 | " -V, --version Show version information and exit\n" 143 | ); 144 | } 145 | 146 | int 147 | main (int argc, char * const argv[]) 148 | { 149 | PROG = "aa-reset"; 150 | const char *path_repo = "/run/services"; 151 | intptr_t mode = MODE_NONE; 152 | int i; 153 | int r; 154 | 155 | for (;;) 156 | { 157 | struct option longopts[] = { 158 | { "auto", no_argument, NULL, 'A' }, 159 | { "started", no_argument, NULL, 'a' }, 160 | { "double-output", no_argument, NULL, 'D' }, 161 | { "help", no_argument, NULL, 'h' }, 162 | { "stopped", no_argument, NULL, 'o' }, 163 | { "repodir", required_argument, NULL, 'r' }, 164 | { "version", no_argument, NULL, 'V' }, 165 | { NULL, 0, 0, 0 } 166 | }; 167 | int c; 168 | 169 | c = getopt_long (argc, argv, "AaDhor:V", longopts, NULL); 170 | if (c == -1) 171 | break; 172 | switch (c) 173 | { 174 | case 'A': 175 | mode = MODE_AUTO; 176 | break; 177 | 178 | case 'a': 179 | mode = MODE_STARTED; 180 | break; 181 | 182 | case 'D': 183 | aa_set_double_output (1); 184 | break; 185 | 186 | case 'h': 187 | dieusage (0); 188 | 189 | case 'o': 190 | mode = MODE_STOPPED; 191 | break; 192 | 193 | case 'r': 194 | unslash (optarg); 195 | path_repo = optarg; 196 | break; 197 | 198 | case 'V': 199 | aa_die_version (); 200 | 201 | default: 202 | dieusage (1); 203 | } 204 | } 205 | argc -= optind; 206 | argv += optind; 207 | 208 | if (argc < 1 || mode == MODE_NONE) 209 | dieusage (1); 210 | 211 | r = aa_init_repo (path_repo, AA_REPO_READ); 212 | if (r < 0) 213 | aa_strerr_diefu2sys (2, "init repository ", path_repo); 214 | 215 | for (i = 0; i < argc; ++i) 216 | if (str_equal (argv[i], "-")) 217 | { 218 | if (process_names_from_stdin ((names_cb) reset_service, (void *) mode) < 0) 219 | aa_strerr_diefu1sys (ERR_IO, "process names from stdin"); 220 | } 221 | else 222 | reset_service (argv[i], mode); 223 | 224 | return 0; 225 | } 226 | -------------------------------------------------------------------------------- /src/anopa/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * common.h 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #ifndef _AA_COMMON_H 24 | #define _AA_COMMON_H 25 | 26 | #define LISTDIR_PREFIX "/etc/anopa/listdirs/" 27 | 28 | #endif /* _AA_COMMON_H */ 29 | -------------------------------------------------------------------------------- /src/anopa/deps-exe/aa-enable: -------------------------------------------------------------------------------- 1 | util.o 2 | ${LIBANOPA} 3 | -ls6 4 | -lskarnet 5 | ${TAINNOW_LIB} 6 | -------------------------------------------------------------------------------- /src/anopa/deps-exe/aa-reset: -------------------------------------------------------------------------------- 1 | util.o 2 | ${LIBANOPA} 3 | -ls6 4 | -lskarnet 5 | ${TAINNOW_LIB} 6 | -------------------------------------------------------------------------------- /src/anopa/deps-exe/aa-start: -------------------------------------------------------------------------------- 1 | util.o 2 | start-stop.o 3 | ${LIBANOPA} 4 | -ls6 5 | -lskarnet 6 | ${TAINNOW_LIB} 7 | -------------------------------------------------------------------------------- /src/anopa/deps-exe/aa-status: -------------------------------------------------------------------------------- 1 | util.o 2 | ${LIBANOPA} 3 | -ls6 4 | -lskarnet 5 | ${TAINNOW_LIB} 6 | -------------------------------------------------------------------------------- /src/anopa/deps-exe/aa-stop: -------------------------------------------------------------------------------- 1 | util.o 2 | start-stop.o 3 | ${LIBANOPA} 4 | -ls6 5 | -lskarnet 6 | ${TAINNOW_LIB} 7 | -------------------------------------------------------------------------------- /src/anopa/start-stop.h: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * start-stop.h 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #ifndef AA_START_STOP_H 24 | #define AA_START_STOP_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #define SECS_BEFORE_WAITING 7 35 | #define DEFAULT_TIMEOUT_SECS 300 36 | 37 | #define ANSI_PREV_LINE "\x1B[F" 38 | #define ANSI_CLEAR_AFTER "\x1B[K" 39 | #define ANSI_CLEAR_BEFORE "\x1B[1K" 40 | #define ANSI_START_LINE "\x1B[1G" 41 | 42 | extern genalloc ga_iop; 43 | extern genalloc ga_progress; 44 | extern genalloc ga_pid; 45 | extern tain_t iol_deadline; 46 | extern unsigned int draw; 47 | extern int nb_already; 48 | extern int nb_done; 49 | extern int nb_wait_longrun; 50 | extern genalloc ga_failed; 51 | extern genalloc ga_timedout; 52 | extern int cols; 53 | extern int is_utf8; 54 | extern int ioloop; 55 | extern int si_password; 56 | extern int si_active; 57 | 58 | enum 59 | { 60 | DRAW_CUR_WAITING = (1 << 0), 61 | DRAW_CUR_PROGRESS = (1 << 1), 62 | DRAW_CUR_PASSWORD = (1 << 2), 63 | DRAW_HAS_CUR = (1 << 3) - 1, 64 | 65 | DRAW_NEED_WAITING = (1 << 3), 66 | DRAW_NEED_PROGRESS = (1 << 4), 67 | DRAW_NEED_PASSWORD = (1 << 5), 68 | DRAW_HAS_NEED = (1 << 6) - DRAW_HAS_CUR - 1 69 | }; 70 | 71 | enum 72 | { 73 | DRAWN_NOT = 0, 74 | DRAWN = 1, 75 | 76 | DRAWN_PASSWORD_WAITMSG = -1, 77 | DRAWN_PASSWORD_READY = -2, 78 | DRAWN_PASSWORD_WRITING = -3 79 | }; 80 | 81 | struct progress 82 | { 83 | aa_progress aa_pg; 84 | int si; 85 | int is_drawn; 86 | int secs_timeout; 87 | }; 88 | 89 | void free_progress (struct progress *pg); 90 | int refresh_draw (); 91 | void draw_waiting (int already_drawn); 92 | void draw_progress_for (int si); 93 | void clear_draw (); 94 | void add_name_to_ga (const char *name, genalloc *ga); 95 | void iol_deadline_addsec (int n); 96 | void remove_fd_from_iop (int fd); 97 | void close_fd_for (int fd, int si); 98 | int handle_fd_out (int si); 99 | int handle_fd_progress (int si); 100 | int handle_fd_in (void); 101 | int handle_fd (int fd); 102 | int handle_longrun (aa_mode mode, uint16 id, char event); 103 | int is_locale_utf8 (void); 104 | int get_cols (int fd); 105 | int handle_signals (aa_mode mode); 106 | void prepare_cb (int cur, int next, int is_needs, size_t first); 107 | void exec_cb (int si, aa_evt evt, pid_t pid); 108 | void mainloop (aa_mode mode, aa_scan_cb scan_cb); 109 | void show_stat_service_names (genalloc *ga, const char *title, const char *ansi_color); 110 | 111 | #define end_err() aa_end_err () 112 | #define put_err(name,msg,end) do { \ 113 | clear_draw (); \ 114 | aa_put_err (name, msg, end); \ 115 | } while (0) 116 | #define add_err(s) aa_bs_noflush (AA_ERR, s) 117 | #define put_err_service(name,err,end) put_err (name, errmsg[err], end) 118 | #define end_warn() aa_end_warn () 119 | #define put_warn(name,msg,end) do { \ 120 | clear_draw (); \ 121 | aa_put_warn (name, msg, end); \ 122 | } while (0) 123 | #define add_warn(s) aa_bs_noflush (AA_ERR, s) 124 | #define end_title() aa_end_title () 125 | #define put_title(main,name,title,end) do { \ 126 | clear_draw (); \ 127 | aa_put_title (main, name, title, end); \ 128 | } while (0) 129 | #define add_title(s) aa_bs_noflush (AA_OUT, s) 130 | 131 | #endif /* AA_START_STOP_H */ 132 | -------------------------------------------------------------------------------- /src/anopa/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * util.c 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "util.h" 29 | 30 | int 31 | process_names_from_stdin (names_cb process_name, void *data) 32 | { 33 | size_t salen = satmp.len; 34 | int r; 35 | 36 | for (;;) 37 | { 38 | satmp.len = salen; 39 | r = skagetlnsep (buffer_0small, &satmp, "\n", 1); 40 | if (r < 0) 41 | { 42 | if (errno != EPIPE) 43 | break; 44 | } 45 | else if (r == 0) 46 | break; 47 | else 48 | satmp.len--; 49 | 50 | if (!stralloc_0 (&satmp)) 51 | { 52 | r = -1; 53 | break; 54 | } 55 | process_name (satmp.s + salen, data); 56 | } 57 | 58 | satmp.len = salen; 59 | return r; 60 | } 61 | 62 | void 63 | unslash (char *s) 64 | { 65 | size_t l = strlen (s); 66 | 67 | if (l <= 1) 68 | return; 69 | --l; 70 | if (s[l] == '/') 71 | s[l] = '\0'; 72 | } 73 | -------------------------------------------------------------------------------- /src/anopa/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * util.h 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #ifndef AA_UTIL_H 24 | #define AA_UTIL_H 25 | 26 | typedef void (*names_cb) (const char *name, void *data); 27 | 28 | int process_names_from_stdin (names_cb process_name, void *data); 29 | void unslash (char *s); 30 | 31 | #endif /* AA_UTIL_H */ 32 | -------------------------------------------------------------------------------- /src/include/anopa/anopa.h: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * anopa.h 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #ifndef AA_ANOPA_H 24 | #define AA_ANOPA_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #endif /* AA_ANOPA_H */ 34 | -------------------------------------------------------------------------------- /src/include/anopa/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * common.h 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #ifndef AA_COMMON_H 24 | #define AA_COMMON_H 25 | 26 | #define AA_SCANDIR_DIRNAME ".scandir" 27 | 28 | void aa_die_usage (int rc, const char *usage, const char *details); 29 | void aa_die_version (void); 30 | 31 | #endif /* AA_COMMON_H */ 32 | -------------------------------------------------------------------------------- /src/include/anopa/copy_file.h: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * copy_file.h 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #ifndef AA_COPY_FILE_H 24 | #define AA_COPY_FILE_H 25 | 26 | typedef enum 27 | { 28 | AA_CP_CREATE = 0, 29 | AA_CP_OVERWRITE, 30 | AA_CP_APPEND, 31 | _AA_CP_NB 32 | } aa_cp; 33 | 34 | int aa_copy_file (const char *src, const char *dst, mode_t mode, aa_cp cp); 35 | 36 | #endif /* AA_COPY_FILE_H */ 37 | -------------------------------------------------------------------------------- /src/include/anopa/enable_service.h: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * enable_service.h 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #ifndef AA_ENABLE_SERVICE_H 24 | #define AA_ENABLE_SERVICE_H 25 | 26 | #include 27 | #include 28 | 29 | typedef enum 30 | { 31 | AA_FLAG_AUTO_ENABLE_NEEDS = (1 << 0), 32 | AA_FLAG_AUTO_ENABLE_WANTS = (1 << 1), 33 | AA_FLAG_SKIP_DOWN = (1 << 2), 34 | AA_FLAG_UPGRADE_SERVICEDIR = (1 << 3), 35 | AA_FLAG_NO_SUPERVISE = (1 << 4), 36 | /* private */ 37 | _AA_FLAG_IS_SERVICEDIR = (1 << 5), 38 | _AA_FLAG_IS_CONFIGDIR = (1 << 6), 39 | _AA_FLAG_IS_1OF4 = (1 << 7), 40 | _AA_FLAG_IS_LOGGER = (1 << 8) 41 | } aa_enable_flags; 42 | 43 | extern stralloc aa_sa_sources; 44 | 45 | typedef void (*aa_warn_fn) (const char *name, int err); 46 | typedef void (*aa_auto_enable_cb) (const char *name, aa_enable_flags type); 47 | 48 | extern int aa_enable_service (const char *name, 49 | aa_warn_fn warn_fn, 50 | aa_enable_flags flags, 51 | aa_auto_enable_cb ae_cb); 52 | 53 | #endif /* AA_ENABLE_SERVICE_H */ 54 | -------------------------------------------------------------------------------- /src/include/anopa/err.h: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * err.h 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #ifndef AA_ERR_H 24 | #define AA_ERR_H 25 | 26 | enum 27 | { 28 | ERR_INVALID_NAME = 1, 29 | ERR_UNKNOWN, 30 | ERR_DEPEND, 31 | ERR_IO, 32 | ERR_WRITE_STATUS, 33 | ERR_CHDIR, 34 | ERR_EXEC, 35 | ERR_PIPES, 36 | ERR_S6, 37 | ERR_FAILED, 38 | ERR_TIMEDOUT, 39 | ERR_IO_REPODIR, 40 | ERR_IO_SCANDIR, 41 | ERR_FAILED_ENABLE, 42 | /* not actual service error, see aa_ensure_service_loaded() */ 43 | ERR_ALREADY_UP, 44 | ERR_NOT_UP, 45 | _NB_ERR 46 | }; 47 | 48 | extern const char const *errmsg[_NB_ERR]; 49 | 50 | #endif /* AA_ERR_H */ 51 | -------------------------------------------------------------------------------- /src/include/anopa/ga_int_list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * ga_int_list.h 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #ifndef AA_GA_INT_LIST_H 24 | #define AA_GA_INT_LIST_H 25 | 26 | #include 27 | 28 | #define list_get(ga, i) ga_get (int, ga, i) 29 | #define add_to_list(ga, si, chk_dupes) ga_add_val (ga, sizeof (int), (char const *) &si, chk_dupes) 30 | #define remove_from_list(ga, si) ga_remove_val (ga, sizeof (int), (char const *) &si) 31 | #define is_in_list(ga, si) (ga_find (ga, sizeof (int), (char const *) &si) >= 0) 32 | 33 | #endif /* AA_GA_INT_LIST_H */ 34 | -------------------------------------------------------------------------------- /src/include/anopa/ga_list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2016 Olivier Brunel 3 | * 4 | * ga_list.h 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #ifndef AA_GA_LIST_H 24 | #define AA_GA_LIST_H 25 | 26 | #include 27 | #include 28 | 29 | #define ga_get(type, ga, i) (genalloc_s (type, ga)[i]) 30 | 31 | void ga_remove (genalloc *ga, size_t size, int i); 32 | int ga_find (genalloc *ga, size_t size, void const *val); 33 | int ga_add_val (genalloc *ga, size_t size, void const *val, int check_for_dupes); 34 | int ga_remove_val (genalloc *ga, size_t size, void const *val); 35 | 36 | #endif /* AA_GA_LIST_H */ 37 | -------------------------------------------------------------------------------- /src/include/anopa/init_repo.h: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * init_repo.h 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #ifndef AA_INIT_REPO_H 24 | #define AA_INIT_REPO_H 25 | 26 | typedef enum 27 | { 28 | AA_REPO_READ = 0, 29 | AA_REPO_WRITE, 30 | AA_REPO_CREATE 31 | } aa_repo_init; 32 | 33 | int aa_init_repo (const char *path_repo, aa_repo_init ri); 34 | 35 | #endif /* AA_INIT_REPO_H */ 36 | -------------------------------------------------------------------------------- /src/include/anopa/progress.h: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * progress.h 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #ifndef AA_PROGRESS_H 24 | #define AA_PROGRESS_H 25 | 26 | #include 27 | 28 | typedef struct 29 | { 30 | int step; 31 | double pctg; 32 | stralloc sa; 33 | } aa_progress; 34 | 35 | extern void aa_progress_free (aa_progress *p); 36 | extern int aa_progress_update (aa_progress *pg); 37 | extern void aa_progress_draw (aa_progress *pg, const char *title, int cols, int is_utf8); 38 | 39 | #endif /* AA_PROGRESS_H */ 40 | -------------------------------------------------------------------------------- /src/include/anopa/scan_dir.h: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * scan_dir.h 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #ifndef AA_SCAN_DIR_H 24 | #define AA_SCAN_DIR_H 25 | 26 | #include 27 | #include 28 | 29 | typedef int (*aa_sd_it_fn) (direntry *d, void *data); 30 | 31 | int aa_scan_dir (stralloc *sa, int files_only, aa_sd_it_fn iterator, void *data); 32 | 33 | #endif /* AA_SCAN_DIR_H */ 34 | -------------------------------------------------------------------------------- /src/include/anopa/service.h: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * service.h 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #ifndef AA_SERVICE_H 24 | #define AA_SERVICE_H 25 | 26 | #include 27 | #include 28 | #include /* pid_t */ 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #define AA_START_FILENAME "start" 35 | #define AA_STOP_FILENAME "stop" 36 | #define AA_GETS_READY_FILENAME "gets-ready" 37 | 38 | extern genalloc aa_services; 39 | extern stralloc aa_names; 40 | extern genalloc aa_main_list; 41 | extern genalloc aa_tmp_list; 42 | extern genalloc aa_pid_list; 43 | extern unsigned int aa_secs_timeout; 44 | 45 | #define aa_service(i) (&((aa_service *) aa_services.s)[i]) 46 | #define aa_service_name(service) (aa_names.s + (service)->offset_name) 47 | 48 | typedef enum 49 | { 50 | AA_SERVICE_FROM_MAIN = 0, 51 | AA_SERVICE_FROM_TMP, 52 | } aa_sf; 53 | 54 | typedef enum 55 | { 56 | AA_MODE_START = (1 << 0), 57 | AA_MODE_STOP = (1 << 1), 58 | AA_MODE_STOP_ALL = (1 << 2), 59 | AA_MODE_IS_DRY = (1 << 3), 60 | AA_MODE_IS_DRY_FULL = (1 << 4) 61 | } aa_mode; 62 | 63 | typedef enum 64 | { 65 | AA_AUTOLOAD_NEEDS = 0, 66 | AA_AUTOLOAD_WANTS, 67 | } aa_al; 68 | 69 | typedef enum 70 | { 71 | AA_LOAD_NOT, 72 | AA_LOAD_ING, 73 | AA_LOAD_DONE, 74 | AA_LOAD_DONE_CHECKED, 75 | AA_LOAD_FAIL 76 | } aa_ls; 77 | 78 | typedef struct 79 | { 80 | size_t offset_name; 81 | int nb_mark; 82 | genalloc needs; 83 | genalloc wants; 84 | genalloc after; 85 | unsigned int secs_timeout; 86 | aa_ls ls; 87 | aa_service_status st; 88 | tain_t ts_exec; 89 | /* longrun */ 90 | uint16_t ft_id; 91 | int gets_ready; 92 | /* oneshot */ 93 | int fd_in; 94 | int fd_out; 95 | stralloc sa_out; 96 | int fd_progress; 97 | int pi; 98 | int timedout; 99 | } aa_service; 100 | 101 | typedef void (*aa_close_fd_fn) (int fd); 102 | typedef void (*aa_autoload_cb) (int si, aa_al al, const char *name, int err); 103 | typedef void (*aa_prepare_cb) (int si, int si_next, int is_needs, size_t first); 104 | typedef void (*aa_scan_cb) (int si, int sni); 105 | typedef void (*aa_exec_cb) (int si, aa_evt evt, pid_t pid); 106 | 107 | extern void aa_free_services (aa_close_fd_fn close_fd_fn); 108 | extern size_t aa_add_name (const char *name); 109 | extern int aa_get_service (const char *name, int *si, int new_in_main); 110 | extern void aa_unmark_service (int si); 111 | extern int aa_mark_service (aa_mode mode, int si, int in_main, int no_wants, aa_autoload_cb al_cb); 112 | extern int aa_preload_service (int si); 113 | extern int aa_ensure_service_loaded (int si, aa_mode mode, int no_wants, aa_autoload_cb al_cb); 114 | extern int aa_prepare_mainlist (aa_prepare_cb prepare_cb, aa_exec_cb exec_cb); 115 | extern void aa_scan_mainlist (aa_scan_cb scan_cb, aa_mode mode); 116 | extern int aa_exec_service (int si, aa_mode mode); 117 | extern int aa_get_longrun_info (uint16_t *id, char *event); 118 | extern int aa_unsubscribe_for (uint16_t id); 119 | 120 | #endif /* AA_SERVICE_H */ 121 | -------------------------------------------------------------------------------- /src/include/anopa/service_status.h: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * service_status.h 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #ifndef AA_SERVICE_STATUS_H 24 | #define AA_SERVICE_STATUS_H 25 | 26 | #include 27 | #include 28 | 29 | typedef enum 30 | { 31 | AA_EVT_NONE = 0, 32 | AA_EVT_ERROR, 33 | AA_EVT_STARTING, 34 | AA_EVT_STARTING_FAILED, 35 | AA_EVT_START_FAILED, 36 | AA_EVT_STARTED, 37 | AA_EVT_STOPPING, 38 | AA_EVT_STOPPING_FAILED, 39 | AA_EVT_STOP_FAILED, 40 | AA_EVT_STOPPED, 41 | _AA_NB_EVT 42 | } aa_evt; 43 | 44 | extern const char const *eventmsg[_AA_NB_EVT]; 45 | 46 | enum 47 | { 48 | AA_TYPE_UNKNOWN = 0, 49 | AA_TYPE_ONESHOT, 50 | AA_TYPE_LONGRUN 51 | }; 52 | 53 | typedef struct 54 | { 55 | tain_t stamp; 56 | aa_evt event; 57 | int code; 58 | stralloc sa; 59 | /* not saved to status file */ 60 | unsigned int type; 61 | } aa_service_status; 62 | 63 | #define AA_SVST_FIXED_SIZE 20 64 | #define AA_SVST_MAX_MSG_SIZE 255 65 | #define AA_SVST_FILENAME "status.anopa" 66 | 67 | extern void aa_service_status_free (aa_service_status *svst); 68 | extern int aa_service_status_read (aa_service_status *svst, const char *dir); 69 | extern int aa_service_status_write (aa_service_status *svst, const char *dir); 70 | extern int aa_service_status_set_msg (aa_service_status *svst, const char *msg); 71 | extern int aa_service_status_set_err (aa_service_status *svst, int err, const char *msg); 72 | #define aa_service_status_get_msg(svst) \ 73 | (((svst)->sa.len > AA_SVST_FIXED_SIZE) ? (svst)->sa.s + AA_SVST_FIXED_SIZE : NULL) 74 | 75 | #endif /* AA_SERVICE_STATUS_H */ 76 | -------------------------------------------------------------------------------- /src/include/anopa/stats.h: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * stats.h 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #ifndef AA_STATS_H 24 | #define AA_STATS_H 25 | 26 | #include 27 | 28 | void aa_show_stat_nb (int nb, const char *title, const char *ansi_color); 29 | void aa_show_stat_names (const char *names, 30 | genalloc *ga_offets, 31 | const char *title, 32 | const char *ansi_color); 33 | 34 | #endif /* AA_STATS_H */ 35 | -------------------------------------------------------------------------------- /src/libanopa/copy_file.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * copy_file.c 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | int 29 | aa_copy_file (const char *src, const char *dst, mode_t mode, aa_cp cp) 30 | { 31 | int fd_src; 32 | int fd_dst; 33 | int flag[_AA_CP_NB]; 34 | 35 | fd_src = open_readb (src); 36 | if (fd_src < 0) 37 | return -1; 38 | 39 | flag[AA_CP_CREATE] = O_EXCL; 40 | flag[AA_CP_OVERWRITE] = O_TRUNC; 41 | flag[AA_CP_APPEND] = O_APPEND; 42 | 43 | fd_dst = open3 (dst, O_WRONLY | O_CREAT | flag[cp], mode); 44 | if (fd_dst < 0) 45 | { 46 | int e = errno; 47 | fd_close (fd_src); 48 | errno = e; 49 | return -1; 50 | } 51 | 52 | if (fd_cat (fd_src, fd_dst) < 0) 53 | { 54 | int e = errno; 55 | fd_close (fd_src); 56 | fd_close (fd_dst); 57 | errno = e; 58 | return -1; 59 | } 60 | 61 | fd_close (fd_src); 62 | fd_close (fd_dst); 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /src/libanopa/deps-lib/anopa: -------------------------------------------------------------------------------- 1 | copy_file.o 2 | die_usage.o 3 | die_version.o 4 | enable_service.o 5 | errmsg.o 6 | eventmsg.o 7 | exec_longrun.o 8 | exec_oneshot.o 9 | ga_list.o 10 | init_repo.o 11 | output.o 12 | progress.o 13 | sa_sources.o 14 | service.o 15 | service_name.o 16 | service_start.o 17 | service_stop.o 18 | services.o 19 | service_status.o 20 | scan_dir.o 21 | stats.o 22 | -------------------------------------------------------------------------------- /src/libanopa/die_usage.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * die_usage.c 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include 25 | 26 | extern char const *PROG; 27 | 28 | void 29 | aa_die_usage (int rc, const char *usage, const char *details) 30 | { 31 | aa_bs_noflush (AA_OUT, "Usage: "); 32 | aa_bs_noflush (AA_OUT, PROG); 33 | aa_bs_noflush (AA_OUT, " "); 34 | aa_bs_noflush (AA_OUT, usage); 35 | aa_bs_noflush (AA_OUT, "\n\n"); 36 | aa_bs_flush (AA_OUT, details); 37 | _exit (rc); 38 | } 39 | -------------------------------------------------------------------------------- /src/libanopa/die_version.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * die_version.c 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include "anopa/config.h" 24 | 25 | #include 26 | #include 27 | 28 | extern char const *PROG; 29 | 30 | void 31 | aa_die_version (void) 32 | { 33 | aa_bs_noflush (AA_OUT, PROG); 34 | aa_bs_noflush (AA_OUT, " v" ANOPA_VERSION "\n"); 35 | aa_bs_flush (AA_OUT, 36 | "Copyright (C) 2015-2017 Olivier Brunel - https://jjacky.com/anopa\n" 37 | "License GPLv3+: GNU GPL version 3 or later \n" 38 | "This is free software: you are free to change and redistribute it.\n" 39 | "There is NO WARRANTY, to the extent permitted by law.\n" 40 | ); 41 | _exit (0); 42 | } 43 | -------------------------------------------------------------------------------- /src/libanopa/errmsg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * errmsg.c 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | 25 | const char const *errmsg[_NB_ERR] = { 26 | "", 27 | "Invalid name", 28 | "Unknown service", 29 | "Failed dependency", 30 | "I/O error", 31 | "Uable to write service status file", 32 | "Unable to get into service directory", 33 | "Unable to exec", 34 | "Unable to setup pipes", 35 | "Failed to communicate with s6", 36 | "Failed", 37 | "Timed out", 38 | "Failed to create repository directory", 39 | "Failed to create scandir directory", 40 | "Failed to enable/create servicedir", 41 | 42 | "Already up", 43 | "Not up" 44 | }; 45 | -------------------------------------------------------------------------------- /src/libanopa/eventmsg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * eventmsg.c 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | 25 | const char const *eventmsg[_AA_NB_EVT] = { 26 | "Unknown status", 27 | "Error", 28 | "Starting", 29 | "Starting failed", 30 | "Start failed", 31 | "Started", 32 | "Stopping", 33 | "Stopping failed", 34 | "Stop failed", 35 | "Stopped" 36 | }; 37 | -------------------------------------------------------------------------------- /src/libanopa/ga_list.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2016 Olivier Brunel 3 | * 4 | * ga_list.c 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include 25 | 26 | void 27 | ga_remove (genalloc *ga, size_t size, int i) 28 | { 29 | size_t len = ga->len / size; 30 | size_t c = len - i - 1; 31 | 32 | if (i < 0 || (size_t) i >= len) 33 | return; 34 | if (c > 0) 35 | memmove (ga->s + (i * size), ga->s + ((i + 1) * size), c * size); 36 | 37 | ga->len -= size; 38 | } 39 | 40 | int 41 | ga_find (genalloc *ga, size_t size, void const *val) 42 | { 43 | size_t len = ga->len / size; 44 | size_t i; 45 | 46 | for (i = 0; i < len; ++i) 47 | if (memcmp (ga->s + (i * size), val, size) == 0) 48 | return i; 49 | return -1; 50 | } 51 | 52 | int 53 | ga_add_val (genalloc *ga, size_t size, void const *val, int check_for_dupes) 54 | { 55 | if (check_for_dupes) 56 | { 57 | int i = ga_find (ga, size, val); 58 | 59 | if (i >= 0) 60 | return 0; 61 | } 62 | 63 | stralloc_catb (ga, val, size); 64 | return 1; 65 | } 66 | 67 | int 68 | ga_remove_val (genalloc *ga, size_t size, void const *val) 69 | { 70 | int i = ga_find (ga, size, val); 71 | 72 | if (i < 0) 73 | return 0; 74 | 75 | ga_remove (ga, size, i); 76 | return 1; 77 | } 78 | -------------------------------------------------------------------------------- /src/libanopa/init_repo.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * init_repo.c 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | int 31 | aa_init_repo (const char *path_repo, aa_repo_init ri) 32 | { 33 | int amode; 34 | 35 | umask (0); 36 | 37 | if (ri == AA_REPO_CREATE && mkdir (path_repo, 38 | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) 39 | { 40 | struct stat st; 41 | 42 | if (errno != EEXIST) 43 | return -ERR_IO_REPODIR; 44 | if (stat (path_repo, &st) < 0) 45 | return -ERR_IO_REPODIR; 46 | if (!S_ISDIR (st.st_mode)) 47 | { 48 | errno = ENOTDIR; 49 | return -ERR_IO_REPODIR; 50 | } 51 | } 52 | if (chdir (path_repo) < 0) 53 | return -ERR_IO; 54 | 55 | if (ri == AA_REPO_CREATE && mkdir (AA_SCANDIR_DIRNAME, S_IRWXU) < 0) 56 | { 57 | struct stat st; 58 | 59 | if (errno != EEXIST) 60 | return -ERR_IO_SCANDIR; 61 | if (stat (AA_SCANDIR_DIRNAME, &st) < 0) 62 | return -ERR_IO_SCANDIR; 63 | if (!S_ISDIR (st.st_mode)) 64 | { 65 | errno = ENOTDIR; 66 | return -ERR_IO_SCANDIR; 67 | } 68 | } 69 | 70 | amode = R_OK; 71 | if (ri != AA_REPO_READ) 72 | amode |= W_OK; 73 | 74 | if (access (".", amode) < 0) 75 | return -ERR_IO; 76 | 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /src/libanopa/output.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * output.c 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include /* isatty() */ 24 | #include 25 | #include 26 | #include 27 | 28 | static int istty[2] = { -1, 0 }; 29 | static int double_output = 0; 30 | 31 | #define is_tty(n) (istty[0] > -1 || chk_tty ()) && istty[n] 32 | 33 | #define putb_noflush(w,s,l) buffer_putnoflush ((w) ? buffer_2 : buffer_1small, s, l) 34 | #define putb_flush(w,s,l) buffer_putflush ((w) ? buffer_2 : buffer_1small, s, l) 35 | 36 | static int 37 | chk_tty (void) 38 | { 39 | istty[0] = isatty (1); 40 | istty[1] = isatty (2); 41 | return 1; 42 | } 43 | 44 | void 45 | aa_set_double_output (int enabled) 46 | { 47 | double_output = !!enabled; 48 | } 49 | 50 | void 51 | aa_bb_noflush (int where, const char *s, size_t len) 52 | { 53 | putb_noflush (where, s, len); 54 | if (double_output) 55 | putb_noflush (!where, s, len); 56 | } 57 | 58 | void 59 | aa_bb_flush (int where, const char *s, size_t len) 60 | { 61 | putb_flush (where, s, len); 62 | if (double_output) 63 | putb_flush (!where, s, len); 64 | } 65 | 66 | void 67 | aa_ib_noflush (int where, const char *s, size_t len) 68 | { 69 | if (is_tty (where)) 70 | putb_noflush (where, s, len); 71 | if (double_output && is_tty (!where)) 72 | putb_noflush (!where, s, len); 73 | } 74 | 75 | void 76 | aa_ib_flush (int where, const char *s, size_t len) 77 | { 78 | if (is_tty (where)) 79 | putb_flush (where, s, len); 80 | if (double_output && is_tty (!where)) 81 | putb_flush (!where, s, len); 82 | } 83 | 84 | void 85 | aa_bs_end (int where) 86 | { 87 | aa_is_noflush (where, ANSI_HIGHLIGHT_OFF); 88 | aa_bs_flush (where, "\n"); 89 | } 90 | 91 | void 92 | aa_put_err (const char *name, const char *msg, int end) 93 | { 94 | aa_is_noflush (AA_ERR, ANSI_HIGHLIGHT_RED_ON); 95 | aa_bs_noflush (AA_ERR, "==> ERROR: "); 96 | aa_is_noflush (AA_ERR, ANSI_HIGHLIGHT_ON); 97 | aa_bs_noflush (AA_ERR, name); 98 | if (msg) 99 | { 100 | aa_bs_noflush (AA_ERR, ": "); 101 | aa_bs_noflush (AA_ERR, msg); 102 | } 103 | if (end) 104 | aa_end_err (); 105 | } 106 | 107 | void 108 | aa_put_warn (const char *name, const char *msg, int end) 109 | { 110 | aa_is_noflush (AA_ERR, ANSI_HIGHLIGHT_YELLOW_ON); 111 | aa_bs_noflush (AA_ERR, "==> WARNING: "); 112 | aa_is_noflush (AA_ERR, ANSI_HIGHLIGHT_ON); 113 | aa_bs_noflush (AA_ERR, name); 114 | if (msg) 115 | { 116 | aa_bs_noflush (AA_ERR, ": "); 117 | aa_bs_noflush (AA_ERR, msg); 118 | } 119 | if (end) 120 | aa_end_warn (); 121 | } 122 | 123 | void 124 | aa_put_title (int main, const char *name, const char *title, int end) 125 | { 126 | aa_is_noflush (AA_OUT, (main) ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_BLUE_ON); 127 | aa_bs_noflush (AA_OUT, (main) ? "==> " : " -> "); 128 | aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_ON); 129 | aa_bs_noflush (AA_OUT, name); 130 | if (title) 131 | { 132 | aa_bs_noflush (AA_OUT, ": "); 133 | aa_bs_noflush (AA_OUT, title); 134 | } 135 | if (end) 136 | aa_end_title (); 137 | } 138 | 139 | void 140 | aa_strerr_warn (const char *s1, 141 | const char *s2, 142 | const char *s3, 143 | const char *s4, 144 | const char *s5, 145 | const char *s6, 146 | const char *s7, 147 | const char *s8, 148 | const char *s9, 149 | const char *s10) 150 | { 151 | aa_bs_noflush (AA_ERR, PROG); 152 | aa_bs_noflush (AA_ERR, ": "); 153 | if (s1) 154 | aa_bs_noflush (AA_ERR, s1); 155 | if (s2) 156 | aa_bs_noflush (AA_ERR, s2); 157 | if (s3) 158 | aa_bs_noflush (AA_ERR, s3); 159 | if (s4) 160 | aa_bs_noflush (AA_ERR, s4); 161 | if (s5) 162 | aa_bs_noflush (AA_ERR, s5); 163 | if (s6) 164 | aa_bs_noflush (AA_ERR, s6); 165 | if (s7) 166 | aa_bs_noflush (AA_ERR, s7); 167 | if (s8) 168 | aa_bs_noflush (AA_ERR, s8); 169 | if (s9) 170 | aa_bs_noflush (AA_ERR, s9); 171 | if (s10) 172 | aa_bs_noflush (AA_ERR, s10); 173 | aa_bs_flush (AA_ERR, "\n"); 174 | } 175 | 176 | void 177 | aa_strerr_die (int rc, 178 | const char *s1, 179 | const char *s2, 180 | const char *s3, 181 | const char *s4, 182 | const char *s5, 183 | const char *s6, 184 | const char *s7, 185 | const char *s8, 186 | const char *s9) 187 | { 188 | aa_strerr_warn ("fatal: ", s1, s2, s3, s4, s5, s6, s7, s8, s9); 189 | _exit (rc); 190 | } 191 | -------------------------------------------------------------------------------- /src/libanopa/progress.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * progress.c 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #if 0 29 | static const char *utf8_edge[] = { "\u2595", " ", "\u258f" }; 30 | static const char *utf8_bars[] = { " ", "\u258f", "\u258e", "\u258d", "\u258c", "\u258b", "\u258a", "\u2589", "\u2588" }; 31 | #define utf8_per_c sizeof (utf8_bars) / sizeof (*utf8_bars) 32 | #else 33 | static const char *utf8_edge[] = { "\u2590", " ", "\u258c" }; 34 | static const char *utf8_bars[] = { " ", "\u258c", "\u2588" }; 35 | #define utf8_per_c sizeof (utf8_bars) / sizeof (*utf8_bars) 36 | #endif 37 | 38 | static const char *ascii_edge[] = { "[", " ", "]" }; 39 | static const char *ascii_bars[] = { " ", "-", "=", "#" }; 40 | #define ascii_per_c sizeof (ascii_bars) / sizeof (*ascii_bars) 41 | 42 | void 43 | aa_progress_free (aa_progress *p) 44 | { 45 | stralloc_free (&p->sa); 46 | } 47 | 48 | int 49 | aa_progress_update (aa_progress *pg) 50 | { 51 | char *s; 52 | size_t skip; 53 | size_t len; 54 | size_t rr; 55 | int cur; 56 | int max; 57 | size_t r; 58 | 59 | /* sanity: we require at least a NUL byte (for empty msg) */ 60 | if (pg->sa.len == 0) 61 | return -1; 62 | 63 | /* moving past msg */ 64 | skip = byte_chr (pg->sa.s, pg->sa.len, '\0') + 1; 65 | s = pg->sa.s + skip; 66 | len = pg->sa.len - skip; 67 | if (len <= 0) 68 | return -1; 69 | 70 | /* now look for last full line to process */ 71 | r = byte_rchr (s, len, '\n'); 72 | if (r >= len) 73 | return -1; 74 | s[r] = '\0'; 75 | 76 | rr = byte_rchr (s, r, '\n'); 77 | if (rr < r) 78 | { 79 | s += rr + 1; 80 | len = r - rr - 1; 81 | } 82 | else 83 | len = r; 84 | 85 | /* step */ 86 | for (rr = 0; *s != ' ' && len > 0; ++s, --len) 87 | { 88 | if (*s < '0' || *s > '9') 89 | goto err; 90 | rr *= 10; 91 | rr += *s - '0'; 92 | } 93 | if (len <= 1) 94 | goto err; 95 | ++s; --len; 96 | 97 | for (cur = 0; *s != ' ' && len > 0; ++s, --len) 98 | { 99 | if (*s < '0' || *s > '9') 100 | goto err; 101 | cur *= 10; 102 | cur += *s - '0'; 103 | } 104 | if (len <= 1) 105 | goto err; 106 | ++s; --len; 107 | 108 | for (max = 0; *s != ' ' && len > 0; ++s, --len) 109 | { 110 | if (*s < '0' || *s > '9') 111 | goto err; 112 | max *= 10; 113 | max += *s - '0'; 114 | } 115 | if (*s == ' ') 116 | { 117 | ++s; --len; 118 | } 119 | else if (len > 0) 120 | goto err; 121 | 122 | pg->step = rr; 123 | pg->pctg = (double) cur / (double) max; 124 | 125 | ++len; /* include NUL */ 126 | memmove (pg->sa.s, s, len); 127 | pg->sa.len = len; 128 | return 0; 129 | 130 | err: 131 | s = pg->sa.s + skip + r + 1; 132 | len = pg->sa.len - skip - r - 1; 133 | memmove (pg->sa.s + skip, s, len); 134 | pg->sa.len = skip + len; 135 | return -2; 136 | } 137 | 138 | void 139 | aa_progress_draw (aa_progress *pg, const char *title, int cols, int is_utf8) 140 | { 141 | const char **edge; 142 | const char **bars; 143 | int per_c; 144 | char buf[UINT_FMT]; 145 | unsigned int p1; 146 | unsigned int p2; 147 | size_t w; 148 | double d; 149 | size_t n; 150 | size_t i; 151 | 152 | p1 = 100 * pg->pctg; 153 | p2 = 10000 * pg->pctg - (100 * p1); 154 | if (p2 == 100) 155 | { 156 | ++p1; 157 | p2 = 0; 158 | } 159 | 160 | if (is_utf8) 161 | { 162 | edge = utf8_edge; 163 | bars = utf8_bars; 164 | per_c = utf8_per_c; 165 | } 166 | else 167 | { 168 | edge = ascii_edge; 169 | bars = ascii_bars; 170 | per_c = ascii_per_c; 171 | } 172 | 173 | /* 7: for "100.0% " 10: margin on the right */ 174 | w = (size_t) cols - strlen (title) - 1 - 7 - 10; 175 | if (pg->sa.s[0] != '\0') 176 | w -= byte_chr (pg->sa.s, pg->sa.len, '\0'); 177 | if (w < 10) 178 | w = 0; 179 | d = pg->pctg * w * per_c; 180 | n = d / per_c; 181 | 182 | aa_is_noflush (AA_OUT, title); 183 | aa_is_noflush (AA_OUT, ":"); 184 | if (w) 185 | { 186 | aa_is_noflush (AA_OUT, edge[0]); 187 | for (i = 0; i < n; ++i) 188 | aa_is_noflush (AA_OUT, bars[per_c - 1]); 189 | if (n < w) 190 | aa_is_noflush (AA_OUT, bars[(int) d % per_c]); 191 | for (i = n + 1; i < w; ++i) 192 | aa_is_noflush (AA_OUT, edge[1]); 193 | aa_is_noflush (AA_OUT, edge[2]); 194 | } 195 | aa_is_noflush (AA_OUT, " "); 196 | 197 | buf[uint_fmt (buf, p1)] = '\0'; 198 | aa_is_noflush (AA_OUT, buf); 199 | aa_is_noflush (AA_OUT, "."); 200 | if (uint_fmt (buf, p2) == 1) 201 | buf[1] = '0'; 202 | buf[2] = '\0'; 203 | aa_is_noflush (AA_OUT, buf); 204 | aa_is_noflush (AA_OUT, "% "); 205 | 206 | if (pg->sa.s[0] != '\0') 207 | aa_is_noflush (AA_OUT, pg->sa.s); 208 | aa_is_flush (AA_OUT, "\n"); 209 | } 210 | -------------------------------------------------------------------------------- /src/libanopa/sa_sources.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * sa_sources.c 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include 25 | 26 | stralloc aa_sa_sources = STRALLOC_ZERO; 27 | -------------------------------------------------------------------------------- /src/libanopa/scan_dir.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * scan_dir.c 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #define _BSD_SOURCE 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | 34 | /* breaking the rule here: we get a stralloc* but we don't own it, it's just so 35 | * we can use it if needed to stat() */ 36 | int 37 | aa_scan_dir (stralloc *sa, int files_only, aa_sd_it_fn iterator, void *data) 38 | { 39 | DIR *dir; 40 | int e = 0; 41 | int r = 0; 42 | 43 | dir = opendir (sa->s); 44 | if (!dir) 45 | return -ERR_IO; 46 | 47 | for (;;) 48 | { 49 | direntry *d; 50 | 51 | errno = 0; 52 | d = readdir (dir); 53 | if (!d) 54 | { 55 | e = errno; 56 | break; 57 | } 58 | if (d->d_name[0] == '.' 59 | && (d->d_name[1] == '\0' || (d->d_name[1] == '.' && d->d_name[2] == '\0'))) 60 | continue; 61 | if (d->d_type == DT_UNKNOWN) 62 | { 63 | struct stat st; 64 | size_t l; 65 | int rr; 66 | 67 | l = sa->len; 68 | sa->s[l - 1] = '/'; 69 | stralloc_catb (sa, d->d_name, strlen (d->d_name) + 1); 70 | rr = stat (sa->s, &st); 71 | sa->len = l; 72 | sa->s[l - 1] = '\0'; 73 | if (rr != 0) 74 | continue; 75 | if (S_ISREG (st.st_mode)) 76 | d->d_type = DT_REG; 77 | else if (S_ISDIR (st.st_mode)) 78 | d->d_type = DT_DIR; 79 | else if (S_ISBLK (st.st_mode)) 80 | d->d_type = DT_BLK; 81 | } 82 | if (d->d_type != DT_REG && ( 83 | files_only == 1 84 | || (files_only == 0 && d->d_type != DT_DIR) 85 | || (files_only == 2 && d->d_type != DT_BLK) 86 | )) 87 | continue; 88 | 89 | r = iterator (d, data); 90 | if (r < 0) 91 | break; 92 | } 93 | dir_close (dir); 94 | 95 | if (e > 0) 96 | { 97 | r = -ERR_IO; 98 | errno = e; 99 | } 100 | return r; 101 | } 102 | -------------------------------------------------------------------------------- /src/libanopa/service_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * service_internal.h 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #ifndef AA_SERVICE_INTERNAL_H 24 | #define AA_SERVICE_INTERNAL_H 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | extern ftrigr_t _aa_ft; 31 | extern aa_exec_cb _exec_cb; 32 | 33 | struct it_data 34 | { 35 | aa_mode mode; 36 | int si; 37 | int no_wants; 38 | aa_autoload_cb al_cb; 39 | }; 40 | 41 | extern int _is_valid_service_name (const char *name, size_t len); 42 | 43 | extern int _name_start_needs (const char *name, struct it_data *it_data); 44 | extern int _it_start_needs (direntry *d, void *data); 45 | extern int _it_start_wants (direntry *d, void *data); 46 | extern int _it_start_after (direntry *d, void *data); 47 | extern int _it_start_before (direntry *d, void *data); 48 | 49 | extern int _name_stop_needs (const char *name, struct it_data *it_data); 50 | extern int _it_stop_needs (direntry *d, void *data); 51 | extern int _it_stop_after (direntry *d, void *data); 52 | extern int _it_stop_before (direntry *d, void *data); 53 | 54 | extern int _exec_oneshot (int si, aa_mode mode); 55 | extern int _exec_longrun (int si, aa_mode mode); 56 | 57 | #endif /* AA_SERVICE_INTERNAL_H */ 58 | -------------------------------------------------------------------------------- /src/libanopa/service_name.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * service_name.c 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include "service_internal.h" 25 | 26 | int 27 | _is_valid_service_name (const char *name, size_t len) 28 | { 29 | size_t r; 30 | 31 | if (len == 0) 32 | return 0; 33 | if (name[0] == '.') 34 | return 0; 35 | if (name[0] == '@' || name[len - 1] == '@') 36 | return 0; 37 | r = byte_chr (name, len, '/'); 38 | if (r < len && !str_equal (name + r, "/log")) 39 | return 0; 40 | return 1; 41 | } 42 | -------------------------------------------------------------------------------- /src/libanopa/service_start.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * service_start.c 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "service_internal.h" 31 | 32 | void 33 | aa_unmark_service (int si) 34 | { 35 | aa_service *s = aa_service (si); 36 | size_t i; 37 | 38 | if (--s->nb_mark > 0) 39 | return; 40 | 41 | for (i = 0; i < genalloc_len (int, &s->needs); ++i) 42 | aa_unmark_service (list_get (&s->needs, i)); 43 | for (i = 0; i < genalloc_len (int, &s->wants); ++i) 44 | aa_unmark_service (list_get (&s->wants, i)); 45 | 46 | add_to_list (&aa_tmp_list, si, 0); 47 | remove_from_list (&aa_main_list, si); 48 | } 49 | 50 | int 51 | aa_mark_service (aa_mode mode, int si, int in_main, int no_wants, aa_autoload_cb al_cb) 52 | { 53 | int r; 54 | 55 | r = aa_ensure_service_loaded (si, mode, no_wants, al_cb); 56 | if (r < 0) 57 | { 58 | if (in_main) 59 | { 60 | add_to_list (&aa_tmp_list, si, 0); 61 | remove_from_list (&aa_main_list, si); 62 | } 63 | return r; 64 | } 65 | 66 | if (!in_main) 67 | { 68 | add_to_list (&aa_main_list, si, 0); 69 | remove_from_list (&aa_tmp_list, si); 70 | } 71 | 72 | aa_service (si)->nb_mark++; 73 | return 0; 74 | } 75 | 76 | int 77 | _name_start_needs (const char *name, struct it_data *it_data) 78 | { 79 | int type; 80 | int sni; 81 | int r; 82 | 83 | tain_now_g (); 84 | type = aa_get_service (name, &sni, 1); 85 | if (type < 0) 86 | r = type; 87 | else 88 | r = aa_mark_service (it_data->mode, sni, type == AA_SERVICE_FROM_MAIN, 89 | it_data->no_wants, it_data->al_cb); 90 | if (r == -ERR_ALREADY_UP) 91 | return 0; 92 | else if (r < 0) 93 | { 94 | aa_service *s = aa_service (it_data->si); 95 | size_t l = genalloc_len (int, &s->needs); 96 | size_t i; 97 | 98 | for (i = 0; i < l; ++i) 99 | aa_unmark_service (list_get (&s->needs, i)); 100 | 101 | if (!(it_data->mode & AA_MODE_IS_DRY)) 102 | { 103 | size_t l_n = strlen (name); 104 | size_t l_em = strlen (errmsg[-r]); 105 | char buf[l_n + 2 + l_em + 1]; 106 | 107 | byte_copy (buf, l_n, name); 108 | byte_copy (buf + l_n, 2, ": "); 109 | byte_copy (buf + l_n + 2, l_em + 1, errmsg[-r]); 110 | 111 | aa_service_status_set_err (&s->st, ERR_DEPEND, buf); 112 | if (aa_service_status_write (&s->st, aa_service_name (s)) < 0) 113 | aa_strerr_warnu2sys ("write service status file for ", aa_service_name (s)); 114 | } 115 | 116 | r = -ERR_DEPEND; 117 | } 118 | 119 | if (r == 0) 120 | { 121 | add_to_list (&aa_service (it_data->si)->needs, sni, 0); 122 | add_to_list (&aa_service (it_data->si)->after, sni, 1); 123 | } 124 | 125 | if (it_data->al_cb) 126 | it_data->al_cb (it_data->si, AA_AUTOLOAD_NEEDS, name, -r); 127 | 128 | return r; 129 | } 130 | 131 | int 132 | _it_start_needs (direntry *d, void *data) 133 | { 134 | return _name_start_needs (d->d_name, (struct it_data *) data); 135 | } 136 | 137 | int 138 | _it_start_wants (direntry *d, void *data) 139 | { 140 | struct it_data *it_data = data; 141 | int type; 142 | int swi; 143 | int r; 144 | 145 | tain_now_g (); 146 | type = aa_get_service (d->d_name, &swi, 1); 147 | if (type < 0) 148 | r = type; 149 | else 150 | r = aa_mark_service (it_data->mode, swi, type == AA_SERVICE_FROM_MAIN, 151 | it_data->no_wants, it_data->al_cb); 152 | if (r == -ERR_ALREADY_UP) 153 | return 0; 154 | 155 | if (r == 0) 156 | add_to_list (&aa_service (it_data->si)->wants, swi, 0); 157 | 158 | if (it_data->al_cb) 159 | it_data->al_cb (it_data->si, AA_AUTOLOAD_WANTS, d->d_name, -r); 160 | 161 | return r; 162 | } 163 | 164 | int 165 | _it_start_after (direntry *d, void *data) 166 | { 167 | struct it_data *it_data = data; 168 | int sai; 169 | int r; 170 | 171 | tain_now_g (); 172 | r = aa_get_service (d->d_name, &sai, 0); 173 | if (r < 0) 174 | return 0; 175 | 176 | add_to_list (&aa_service (it_data->si)->after, sai, 1); 177 | return 0; 178 | } 179 | 180 | int 181 | _it_start_before (direntry *d, void *data) 182 | { 183 | struct it_data *it_data = data; 184 | int sbi; 185 | int r; 186 | 187 | tain_now_g (); 188 | r = aa_get_service (d->d_name, &sbi, 0); 189 | if (r < 0) 190 | return 0; 191 | 192 | add_to_list (&aa_service (sbi)->after, it_data->si, 1); 193 | return 0; 194 | } 195 | -------------------------------------------------------------------------------- /src/libanopa/service_status.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * service_status.c 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | 34 | void 35 | aa_service_status_free (aa_service_status *svst) 36 | { 37 | stralloc_free (&svst->sa); 38 | } 39 | 40 | int 41 | aa_service_status_read (aa_service_status *svst, const char *dir) 42 | { 43 | size_t len = strlen (dir); 44 | char file[len + 1 + sizeof (AA_SVST_FILENAME)]; 45 | uint32_t u; 46 | 47 | /* most cases should be w/out a message, so we'll only need FIXED_SIZE and 48 | * one extra byte to NUL-terminate the (empty) message */ 49 | if (!stralloc_ready_tuned (&svst->sa, AA_SVST_FIXED_SIZE + 1, 0, 0, 1)) 50 | return -1; 51 | 52 | byte_copy (file, len, dir); 53 | byte_copy (file + len, 1 + sizeof (AA_SVST_FILENAME), "/" AA_SVST_FILENAME); 54 | 55 | if (!openreadfileclose (file, &svst->sa, AA_SVST_FIXED_SIZE + AA_SVST_MAX_MSG_SIZE) 56 | || svst->sa.len < AA_SVST_FIXED_SIZE) 57 | { 58 | int e = errno; 59 | tain_now_g (); 60 | errno = e; 61 | return -1; 62 | } 63 | tain_now_g (); 64 | 65 | if (svst->sa.len >= svst->sa.a 66 | && !stralloc_ready_tuned (&svst->sa, svst->sa.len + 1, 0, 0, 1)) 67 | return -1; 68 | svst->sa.s[svst->sa.len] = '\0'; 69 | svst->sa.len++; 70 | 71 | tain_unpack (svst->sa.s, &svst->stamp); 72 | uint32_unpack (svst->sa.s + 12, &u); 73 | svst->event = (unsigned int) u; 74 | uint32_unpack (svst->sa.s + 16, &u); 75 | svst->code = (int) u; 76 | 77 | return 0; 78 | } 79 | 80 | int 81 | aa_service_status_write (aa_service_status *svst, const char *dir) 82 | { 83 | size_t len = strlen (dir); 84 | char file[len + 1 + sizeof (AA_SVST_FILENAME)]; 85 | mode_t mask; 86 | int r; 87 | int e; 88 | 89 | if (!stralloc_ready_tuned (&svst->sa, AA_SVST_FIXED_SIZE, 0, 0, 1)) 90 | return -1; 91 | 92 | tain_pack (svst->sa.s, &svst->stamp); 93 | uint32_pack (svst->sa.s + 12, (uint32_t) svst->event); 94 | uint32_pack (svst->sa.s + 16, (uint32_t) svst->code); 95 | if (svst->sa.len < AA_SVST_FIXED_SIZE) 96 | svst->sa.len = AA_SVST_FIXED_SIZE; 97 | 98 | byte_copy (file, len, dir); 99 | byte_copy (file + len, 1 + sizeof (AA_SVST_FILENAME), "/" AA_SVST_FILENAME); 100 | 101 | mask = umask (0033); 102 | if (!openwritenclose_suffix (file, svst->sa.s, 103 | svst->sa.len + ((svst->sa.len > AA_SVST_FIXED_SIZE) ? -1 : 0), ".new")) 104 | r = -1; 105 | else 106 | r = 0; 107 | e = errno; 108 | umask (mask); 109 | 110 | tain_now_g (); 111 | errno = e; 112 | return r; 113 | } 114 | 115 | int 116 | aa_service_status_set_msg (aa_service_status *svst, const char *msg) 117 | { 118 | size_t len; 119 | 120 | len = strlen (msg); 121 | if (len > AA_SVST_MAX_MSG_SIZE) 122 | len = AA_SVST_MAX_MSG_SIZE; 123 | 124 | if (!stralloc_ready_tuned (&svst->sa, AA_SVST_FIXED_SIZE + len + 1, 0, 0, 1)) 125 | return -1; 126 | 127 | svst->sa.len = AA_SVST_FIXED_SIZE; 128 | stralloc_catb (&svst->sa, msg, len); 129 | stralloc_0 (&svst->sa); 130 | return 0; 131 | } 132 | 133 | int 134 | aa_service_status_set_err (aa_service_status *svst, int err, const char *msg) 135 | { 136 | svst->event = AA_EVT_ERROR; 137 | svst->code = err; 138 | tain_copynow (&svst->stamp); 139 | return aa_service_status_set_msg (svst, (msg) ? msg : ""); 140 | } 141 | -------------------------------------------------------------------------------- /src/libanopa/service_stop.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * service_stop.c 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include "service_internal.h" 27 | 28 | int 29 | _name_stop_needs (const char *name, struct it_data *it_data) 30 | { 31 | int sni; 32 | int r; 33 | 34 | tain_now_g (); 35 | r = aa_get_service (name, &sni, 0); 36 | if (r < 0) 37 | return 0; 38 | 39 | if (it_data->al_cb) 40 | it_data->al_cb (sni, AA_AUTOLOAD_NEEDS, aa_service_name (aa_service (it_data->si)), 0); 41 | 42 | add_to_list (&aa_service (sni)->needs, it_data->si, 0); 43 | add_to_list (&aa_service (sni)->after, it_data->si, 1); 44 | return 0; 45 | } 46 | 47 | int 48 | _it_stop_needs (direntry *d, void *data) 49 | { 50 | return _name_stop_needs (d->d_name, (struct it_data *) data); 51 | } 52 | 53 | int 54 | _it_stop_after (direntry *d, void *data) 55 | { 56 | struct it_data *it_data = data; 57 | int sai; 58 | int r; 59 | 60 | tain_now_g (); 61 | r = aa_get_service (d->d_name, &sai, 0); 62 | if (r < 0) 63 | return 0; 64 | 65 | add_to_list (&aa_service (sai)->after, it_data->si, 1); 66 | return 0; 67 | } 68 | 69 | int 70 | _it_stop_before (direntry *d, void *data) 71 | { 72 | struct it_data *it_data = data; 73 | int sbi; 74 | int r; 75 | 76 | tain_now_g (); 77 | r = aa_get_service (d->d_name, &sbi, 0); 78 | if (r < 0) 79 | return 0; 80 | 81 | add_to_list (&aa_service (it_data->si)->after, sbi, 1); 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /src/libanopa/services.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * services.c 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | genalloc aa_services = GENALLOC_ZERO; 29 | stralloc aa_names = STRALLOC_ZERO; 30 | genalloc aa_main_list = GENALLOC_ZERO; 31 | genalloc aa_tmp_list = GENALLOC_ZERO; 32 | unsigned int aa_secs_timeout = 0; 33 | 34 | ftrigr_t _aa_ft = FTRIGR_ZERO; 35 | aa_exec_cb _exec_cb = NULL; 36 | -------------------------------------------------------------------------------- /src/libanopa/stats.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * stats.c 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | void 30 | aa_show_stat_nb (int nb, const char *title, const char *ansi_color) 31 | { 32 | char buf[UINT_FMT]; 33 | 34 | if (nb <= 0) 35 | return; 36 | 37 | aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_BLUE_ON); 38 | aa_bs_noflush (AA_OUT, " -> "); 39 | aa_is_noflush (AA_OUT, ansi_color); 40 | aa_bs_noflush (AA_OUT, title); 41 | aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_ON); 42 | aa_bs_noflush (AA_OUT, ": "); 43 | buf[uint_fmt (buf, nb)] = '\0'; 44 | aa_bs_noflush (AA_OUT, buf); 45 | aa_end_title (); 46 | } 47 | 48 | void 49 | aa_show_stat_names (const char *names, 50 | genalloc *ga_offets, 51 | const char *title, 52 | const char *ansi_color) 53 | { 54 | size_t i; 55 | 56 | if (genalloc_len (size_t, ga_offets) <= 0) 57 | return; 58 | 59 | aa_put_title (0, title, "", 0); 60 | for (i = 0; i < genalloc_len (size_t, ga_offets); ++i) 61 | { 62 | if (i > 0) 63 | aa_bs_noflush (AA_OUT, "; "); 64 | aa_is_noflush (AA_OUT, ansi_color); 65 | aa_bs_noflush (AA_OUT, names + ga_get (size_t, ga_offets, i)); 66 | aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_ON); 67 | } 68 | aa_end_title (); 69 | } 70 | -------------------------------------------------------------------------------- /src/scripts/aa-command: -------------------------------------------------------------------------------- 1 | #!@BINDIR@/execlineb 2 | # 3 | # anopa - Copyright (C) 2015-2017 Olivier Brunel 4 | # 5 | # aa-command 6 | # Copyright (C) 2015-2017 Olivier Brunel 7 | # 8 | # This file is part of anopa. 9 | # 10 | # anopa is free software: you can redistribute it and/or modify it under the 11 | # terms of the GNU General Public License as published by the Free Software 12 | # Foundation, either version 3 of the License, or (at your option) any later 13 | # version. 14 | # 15 | # anopa is distributed in the hope that it will be useful, but WITHOUT ANY 16 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 17 | # FOR A PARTICULAR PURPOSE. 18 | # See the GNU General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU General Public License along with 21 | # anopa. If not, see http://www.gnu.org/licenses/ 22 | # 23 | 24 | importas CMD 1 25 | shift 26 | elgetpositionals 27 | 28 | emptyenv s6-envdir /etc/anopa/env exec 29 | 30 | # Set up a pipe to log messages 31 | piperw 3 4 32 | background 33 | { 34 | fdclose 4 fdmove 0 3 35 | redirfd -a 1 /var/log/boot/current 36 | fdmove -c 2 1 37 | s6-tai64n 38 | } 39 | fdclose 3 40 | fdmove 2 4 41 | 42 | # log what we do 43 | foreground 44 | { 45 | fdmove -c 1 2 46 | aa-echo -B -- "Running: aa-${CMD}" " ${@}" 47 | } 48 | 49 | foreground { aa-echo -w "aa-command has been deprecated, see aa-command(1) for more" } 50 | aa-${CMD} -D ${@} 51 | -------------------------------------------------------------------------------- /src/scripts/aa-shutdown: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # anopa - Copyright (C) 2015-2017 Olivier Brunel 4 | # 5 | # aa-shutdown 6 | # Copyright (C) 2015 Olivier Brunel 7 | # 8 | # This file is part of anopa. 9 | # 10 | # anopa is free software: you can redistribute it and/or modify it under the 11 | # terms of the GNU General Public License as published by the Free Software 12 | # Foundation, either version 3 of the License, or (at your option) any later 13 | # version. 14 | # 15 | # anopa is distributed in the hope that it will be useful, but WITHOUT ANY 16 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 17 | # FOR A PARTICULAR PURPOSE. 18 | # See the GNU General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU General Public License along with 21 | # anopa. If not, see http://www.gnu.org/licenses/ 22 | # 23 | 24 | dieusage() { 25 | cat << EOF 26 | Usage: aa-shutdown [OPTION] 27 | -r, --reboot Reboot the machine 28 | -H, --halt Halt the machine 29 | -p, --poweroff Power off the machine 30 | -h, --help Show this help screen and exit 31 | -V, --version Show version information and exit 32 | EOF 33 | exit $1 34 | } 35 | 36 | dieversion() { 37 | cat << EOF 38 | aa-shutdown v@VERSION@ 39 | Copyright (C) 2015 Olivier Brunel - https://jjacky.com/anopa 40 | License GPLv3+: GNU GPL version 3 or later 41 | This is free software: you are free to change and redistribute it. 42 | There is NO WARRANTY, to the extent permitted by law. 43 | EOF 44 | exit 0 45 | } 46 | 47 | cmd= 48 | case "${0##*/}" in 49 | halt) 50 | cmd=s 51 | ;; 52 | reboot) 53 | cmd=r 54 | ;; 55 | poweroff) 56 | cmd=p 57 | ;; 58 | esac 59 | 60 | if [ $# -ne 1 ] && [ -z $cmd ]; then 61 | dieusage 1 62 | fi 63 | 64 | case "$1" in 65 | -H|--halt) 66 | cmd=s 67 | ;; 68 | -h|--help) 69 | dieusage 0 70 | ;; 71 | -p|--poweroff) 72 | cmd=p 73 | ;; 74 | -r|--reboot) 75 | cmd=r 76 | ;; 77 | -V|--version) 78 | dieversion 79 | ;; 80 | *) 81 | [ -z cmd ] && dieusage 1 82 | esac 83 | 84 | exec s6-svscanctl -${cmd}b /run/services/.scandir 85 | -------------------------------------------------------------------------------- /src/scripts/aa-stage0: -------------------------------------------------------------------------------- 1 | #!/bin/execlineb -P 2 | # 3 | # anopa - Copyright (C) 2015-2017 Olivier Brunel 4 | # 5 | # aa-stage0 6 | # Copyright (C) 2015-2017 Olivier Brunel 7 | # 8 | # This file is part of anopa. 9 | # 10 | # anopa is free software: you can redistribute it and/or modify it under the 11 | # terms of the GNU General Public License as published by the Free Software 12 | # Foundation, either version 3 of the License, or (at your option) any later 13 | # version. 14 | # 15 | # anopa is distributed in the hope that it will be useful, but WITHOUT ANY 16 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 17 | # FOR A PARTICULAR PURPOSE. 18 | # See the GNU General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU General Public License along with 21 | # anopa. If not, see http://www.gnu.org/licenses/ 22 | # 23 | # 24 | /bin/emptyenv /bin/s6-envdir /etc/anopa/env /bin/exec 25 | 26 | # Set up a pipe to log messages 27 | piperw 3 4 28 | background 29 | { 30 | fdclose 4 fdmove 0 3 31 | redirfd -a 1 /boot.log 32 | fdmove -c 2 1 33 | s6-tai64n 34 | } 35 | 36 | # aa-* tools will send output to both 1 & 2 via -D 37 | fdclose 3 38 | fdmove 2 4 39 | foreground { aa-echo -D "Stage 0: Mounting root file system..." } 40 | 41 | # Safety 42 | cd / 43 | umask 022 44 | 45 | # Start services 46 | foreground { if -n 47 | { 48 | if { emptyenv -c s6-setsid aa-ctty -Ds aa-start -D -r /services -l onboot } 49 | foreground { 50 | # if "break" was specified on kernel cmdline, let's open a shell 51 | if -t { aa-incmdline -Dqf /root-fs/proc/cmdline break } 52 | foreground { aa-echo -DB "Break requested" } 53 | foreground { aa-echo -Dt "Trying to open a shell; " +g exit +w " to continue" } 54 | fdmove -c 2 1 55 | emptyenv -c sh -i 56 | } 57 | } 58 | 59 | # aa-start failed (i.e. an essential service failed to be started), so we assume 60 | # the root fs wasn't mounted: try a shell so user has a chance to fix things 61 | foreground { aa-echo -DBe "Mouting root file system failed" } 62 | foreground { aa-echo -Dt "Trying to open a shell; " +g exit +w " to continue" } 63 | fdmove -c 2 1 64 | emptyenv -c sh -i 65 | } 66 | 67 | if { aa-echo -DB "Moving /root-fs to /..." } 68 | # First we mount bind the rootfs (initramfs) onto /run/initramfs so we can come 69 | # back to it for stage 4 70 | if { aa-mount -DBd / /root-fs/run/initramfs } 71 | fdmove -c 2 1 72 | backtick -n -D /sbin/init INIT { aa-incmdline -rf /root-fs/proc/cmdline init } 73 | importas -u INIT INIT 74 | cd /root-fs 75 | if { aa-mount -M . / } 76 | ./run/initramfs/bin/emptyenv -c ./run/initramfs/bin/aa-chroot . ${INIT} 77 | -------------------------------------------------------------------------------- /src/scripts/aa-stage1: -------------------------------------------------------------------------------- 1 | #!@BINDIR@/execlineb -P 2 | # 3 | # anopa - Copyright (C) 2015-2017 Olivier Brunel 4 | # 5 | # aa-stage1 6 | # Copyright (C) 2015 Olivier Brunel 7 | # 8 | # This file is part of anopa. 9 | # 10 | # anopa is free software: you can redistribute it and/or modify it under the 11 | # terms of the GNU General Public License as published by the Free Software 12 | # Foundation, either version 3 of the License, or (at your option) any later 13 | # version. 14 | # 15 | # anopa is distributed in the hope that it will be useful, but WITHOUT ANY 16 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 17 | # FOR A PARTICULAR PURPOSE. 18 | # See the GNU General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU General Public License along with 21 | # anopa. If not, see http://www.gnu.org/licenses/ 22 | # 23 | 24 | @BINDIR@/emptyenv @BINDIR@/s6-envdir /etc/anopa/env @BINDIR@/exec 25 | 26 | # Import log messages from initramfs, if possible 27 | foreground { 28 | if -X { aa-test -f /run/initramfs/boot.log } 29 | redirfd -a 1 /var/log/boot/current cat /run/initramfs/boot.log 30 | } 31 | 32 | # Set up a pipe to log messages 33 | piperw 3 4 34 | background 35 | { 36 | fdclose 4 fdmove 0 3 37 | redirfd -a 1 /var/log/boot/current 38 | fdmove -c 2 1 39 | s6-tai64n 40 | } 41 | 42 | # aa-* tools will send output to both 1 & 2 via -D 43 | fdclose 3 44 | fdmove 2 4 45 | foreground { aa-echo -DB "Stage 1: Preparing system..." } 46 | 47 | # Safety 48 | cd / 49 | umask 022 50 | 51 | # Create the repository 52 | foreground { emptyenv -c 53 | aa-enable -Dql /etc/anopa/enabled -k uncaught-logs -f @LIBEXECDIR@/aa-stage3 } 54 | 55 | # Make sure the FIFO needed for the switch to stage 2 is there 56 | ifelse -X -n { aa-test -Dp /run/services/.scandir/uncaught-logs/fifo } 57 | { 58 | foreground { aa-echo -DBe "Cannot start s6-svscan: No uncaught-logs fifo found" } 59 | fdmove -c 2 1 60 | foreground { aa-echo -t "Trying to open a shell..." } 61 | emptyenv -c sh -i 62 | } 63 | 64 | # Reopen stdin/stdout/stderr to make them point to the right places 65 | redirfd -r 0 /dev/null 66 | redirfd -wnb 1 /run/services/uncaught-logs/fifo # (black magic: doesn't block) 67 | fdmove -c 2 1 68 | 69 | # Fork the stage2 script and have it ready to start as soon as the catch-all 70 | # logger is in place 71 | background 72 | { 73 | s6-setsid 74 | redirfd -w 1 /run/services/uncaught-logs/fifo # (blocks until the logger reads) 75 | @LIBEXECDIR@/aa-stage2 76 | } 77 | 78 | # Start the "real" stage 2 (as far as PID 1 goes) 79 | emptyenv -c s6-svscan -t0 /run/services/.scandir 80 | -------------------------------------------------------------------------------- /src/scripts/aa-stage2: -------------------------------------------------------------------------------- 1 | #!@BINDIR@/execlineb -P 2 | # 3 | # anopa - Copyright (C) 2015-2017 Olivier Brunel 4 | # 5 | # aa-stage2 6 | # Copyright (C) 2015-2017 Olivier Brunel 7 | # 8 | # This file is part of anopa. 9 | # 10 | # anopa is free software: you can redistribute it and/or modify it under the 11 | # terms of the GNU General Public License as published by the Free Software 12 | # Foundation, either version 3 of the License, or (at your option) any later 13 | # version. 14 | # 15 | # anopa is distributed in the hope that it will be useful, but WITHOUT ANY 16 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 17 | # FOR A PARTICULAR PURPOSE. 18 | # See the GNU General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU General Public License along with 21 | # anopa. If not, see http://www.gnu.org/licenses/ 22 | # 23 | 24 | # Set up a pipe to log messages 25 | piperw 3 4 26 | background 27 | { 28 | fdclose 4 fdmove 0 3 29 | redirfd -a 1 /var/log/boot/current 30 | fdmove -c 2 1 31 | s6-tai64n 32 | } 33 | fdclose 3 34 | fdmove 2 4 35 | 36 | if -n -t 37 | { 38 | # We want the actual tty on stdin 39 | backtick -n TTY { aa-tty } 40 | importas -u TTY TTY 41 | redirfd -r 0 ${TTY} 42 | # Reopen the console for stdout 43 | redirfd -w 1 /dev/console 44 | # And start everything 45 | foreground { aa-echo -DB "Stage 2: Initializing system..." } 46 | backtick -n -D onboot LISTDIR { aa-incmdline -Drs aa } 47 | importas -u LISTDIR LISTDIR 48 | # We have a tty in stdin, become session leader and set controlling terminal. 49 | # This is so Ctrl+C will trigger a SIGINT to aa-start, so one can manually 50 | # timeout a service. 51 | if { emptyenv -c s6-setsid aa-ctty -D aa-start -D -l /etc/anopa/listdirs/${LISTDIR} } 52 | aa-echo -DB "System ready." 53 | } 54 | 55 | # Something went wrong, likely aa-start failed (i.e. an essential service failed 56 | # to be started), so we assume there's not event a getty: try a shell so user 57 | # has a chance to fix things 58 | redirfd -r 0 /dev/console 59 | redirfd -w 1 /dev/console 60 | foreground { aa-echo -DBe "System initialization failed" } 61 | fdmove -c 2 1 62 | foreground { aa-echo -t "Trying to open a shell..." } 63 | emptyenv -c sh -i 64 | -------------------------------------------------------------------------------- /src/scripts/aa-stage3: -------------------------------------------------------------------------------- 1 | #!@BINDIR@/execlineb -S0 2 | # 3 | # anopa - Copyright (C) 2015-2017 Olivier Brunel 4 | # 5 | # aa-stage3 6 | # Copyright (C) 2015-2017 Olivier Brunel 7 | # 8 | # This file is part of anopa. 9 | # 10 | # anopa is free software: you can redistribute it and/or modify it under the 11 | # terms of the GNU General Public License as published by the Free Software 12 | # Foundation, either version 3 of the License, or (at your option) any later 13 | # version. 14 | # 15 | # anopa is distributed in the hope that it will be useful, but WITHOUT ANY 16 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 17 | # FOR A PARTICULAR PURPOSE. 18 | # See the GNU General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU General Public License along with 21 | # anopa. If not, see http://www.gnu.org/licenses/ 22 | # 23 | 24 | # Set up a pipe to log messages 25 | piperw 3 4 26 | background 27 | { 28 | fdclose 4 fdmove 0 3 29 | redirfd -a 1 /var/log/boot/current 30 | fdmove -c 2 1 31 | s6-tai64n 32 | } 33 | fdclose 3 34 | fdmove 2 4 35 | 36 | # Make sure we're sane 37 | cd / 38 | backtick -n TTY { aa-tty } 39 | importas -u TTY TTY 40 | redirfd -r 0 ${TTY} 41 | redirfd -w 1 /dev/console 42 | 43 | foreground { aa-echo -DB "Stage 3: Preparing ${1}..." } 44 | # Stop all running services -- s6-svscan did only exec into us, leaving the 45 | # whole supervised tree intact. Here we stop everything (longrun & oneshot) in 46 | # order, save for the catch-all (it will get an 'x' though). 47 | foreground { emptyenv -c s6-setsid aa-ctty -Ds aa-stop -D -aak uncaught-logs -t20 } 48 | # Now stop the catch-all logger (its supervisor will then exit) 49 | foreground { emptyenv -c s6-setsid aa-stop -D uncaught-logs } 50 | 51 | # Kill everything left 52 | foreground { aa-echo -DB "Killing remaining processes..." } 53 | foreground { aa-echo -Dt "Sending SIGTERM to all processes..." } 54 | foreground { aa-kill -Dst } 55 | wait -t 4200 { } # Reap zombies 56 | # logger was killed, and we won't open it back 57 | fdmove -c 2 1 58 | foreground { pipeline { aa-echo -Dt "Sending SIGKILL to all processes..." } 59 | redirfd -a 1 /var/log/boot/current 60 | s6-tai64n 61 | } 62 | foreground { aa-kill -sk } 63 | wait -t 2300 { } # Wait for all children 64 | 65 | foreground { aa-sync } 66 | foreground { pipeline { aa-echo -DB "Pivoting root..." } 67 | redirfd -a 1 /var/log/boot/current 68 | s6-tai64n 69 | } 70 | 71 | cd /run/initramfs 72 | foreground { 73 | if -n 74 | { 75 | # grab the chroot binary for after the pivot 76 | if { cp /bin/aa-chroot . } 77 | # PIVOT! 78 | if { aa-pivot . root-fs } 79 | } 80 | 81 | # Something went wrong 82 | foreground { pipeline { aa-echo -DBe "Unable to ${1}: Failed to pivot root" } 83 | redirfd -a 1 /var/log/boot/current 84 | s6-tai64n 85 | } 86 | foreground { aa-echo -t "Trying to open a shell..." } 87 | emptyenv -c sh -i 88 | } 89 | # And let initramfs end things ($1 is halt/reboot/poweroff) 90 | ./aa-chroot . /shutdown ${1} 91 | -------------------------------------------------------------------------------- /src/scripts/aa-stage4: -------------------------------------------------------------------------------- 1 | #!/bin/execlineb -S0 2 | # 3 | # anopa - Copyright (C) 2015-2017 Olivier Brunel 4 | # 5 | # aa-stage4 6 | # Copyright (C) 2015 Olivier Brunel 7 | # 8 | # This file is part of anopa. 9 | # 10 | # anopa is free software: you can redistribute it and/or modify it under the 11 | # terms of the GNU General Public License as published by the Free Software 12 | # Foundation, either version 3 of the License, or (at your option) any later 13 | # version. 14 | # 15 | # anopa is distributed in the hope that it will be useful, but WITHOUT ANY 16 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 17 | # FOR A PARTICULAR PURPOSE. 18 | # See the GNU General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU General Public License along with 21 | # anopa. If not, see http://www.gnu.org/licenses/ 22 | # 23 | 24 | /bin/emptyenv /bin/s6-envdir /etc/anopa/env /bin/exec 25 | 26 | foreground { aa-echo -B "Stage 4: Unmounting root file system..." } 27 | foreground { emptyenv -c aa-stop -r /services -a } 28 | 29 | # At this point everything should be unmounted, so we need to remount what's 30 | # needed for aa-terminate to work. We can't not umount /proc & /dev in aa-stop 31 | # above and then assume they're here, since e.g. moving them back (from root-fs) 32 | # might have failed. (And trying to mount /dev on top of it won't prevent 33 | # aa-terminate from doing its thing properly.) 34 | foreground { aa-echo -B "Mounting /dev & /proc and terminating..." } 35 | foreground { aa-mount -t devtmpfs dev /dev } 36 | foreground { aa-mount -t proc proc /proc } 37 | foreground { if -n { aa-terminate -la } 38 | foreground { aa-echo -Be "Failed to terminate (umount/close all)" } 39 | foreground { aa-echo -t "Mounting /dev & /proc and trying to open a shell; " +g exit +w " to ${1}" } 40 | foreground { aa-mount -t devtmpfs dev /dev } 41 | foreground { aa-mount -t proc proc /proc } 42 | redirfd -r 0 /dev/console redirfd -w 1 /dev/console fdmove -c 2 1 43 | emptyenv -c sh -i 44 | } 45 | aa-reboot --${1} 46 | -------------------------------------------------------------------------------- /src/utils/aa-chroot.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * aa-chroot.c 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #define _BSD_SOURCE 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | static void 32 | dieusage (int rc) 33 | { 34 | aa_die_usage (rc, "NEWROOT COMMAND [ARG...]", 35 | " -D, --double-output Enable double-output mode\n" 36 | " -h, --help Show this help screen and exit\n" 37 | " -V, --version Show version information and exit\n" 38 | ); 39 | } 40 | 41 | int 42 | main (int argc, char * const argv[], char * const envp[]) 43 | { 44 | PROG = "aa-chroot"; 45 | 46 | for (;;) 47 | { 48 | struct option longopts[] = { 49 | { "double-output", no_argument, NULL, 'D' }, 50 | { "help", no_argument, NULL, 'h' }, 51 | { "version", no_argument, NULL, 'V' }, 52 | { NULL, 0, 0, 0 } 53 | }; 54 | int c; 55 | 56 | c = getopt_long (argc, argv, "DhV", longopts, NULL); 57 | if (c == -1) 58 | break; 59 | switch (c) 60 | { 61 | case 'D': 62 | aa_set_double_output (1); 63 | break; 64 | 65 | case 'h': 66 | dieusage (0); 67 | 68 | case 'V': 69 | aa_die_version (); 70 | 71 | default: 72 | dieusage (1); 73 | } 74 | } 75 | argc -= optind; 76 | argv += optind; 77 | 78 | if (argc < 2) 79 | dieusage (1); 80 | 81 | if (chdir (argv[0]) < 0) 82 | aa_strerr_diefu2sys (2, "chdir to ", argv[0]); 83 | if (chroot (".") < 0) 84 | aa_strerr_diefu1sys (3, "chroot"); 85 | if (chdir ("/") < 0) 86 | aa_strerr_diefu1sys (3, "chdir to new root"); 87 | pathexec_run (argv[1], (char const * const *) argv + 1, (char const * const *) envp); 88 | aa_strerr_dieexec (4, argv[1]); 89 | } 90 | -------------------------------------------------------------------------------- /src/utils/aa-ctty.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * aa-ctty.c 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | static void 32 | dieusage (int rc) 33 | { 34 | aa_die_usage (rc, "[OPTION...] PROG...", 35 | " -D, --double-output Enable double-output mode\n" 36 | " -f, --fd=FD Use FD as terminal (Default: 0)\n" 37 | " -s, --steal Steal terminal from other session if needed\n" 38 | " -h, --help Show this help screen and exit\n" 39 | " -V, --version Show version information and exit\n" 40 | ); 41 | } 42 | 43 | int 44 | main (int argc, char * const argv[], char const * const *envp) 45 | { 46 | PROG = "aa-ctty"; 47 | int fd = 0; 48 | int steal = 0; 49 | 50 | for (;;) 51 | { 52 | struct option longopts[] = { 53 | { "double-output", no_argument, NULL, 'D' }, 54 | { "fd", required_argument, NULL, 'f' }, 55 | { "help", no_argument, NULL, 'h' }, 56 | { "steal", no_argument, NULL, 's' }, 57 | { "version", no_argument, NULL, 'V' }, 58 | { NULL, 0, 0, 0 } 59 | }; 60 | int c; 61 | 62 | c = getopt_long (argc, argv, "+Df:hsV", longopts, NULL); 63 | if (c == -1) 64 | break; 65 | switch (c) 66 | { 67 | case 'D': 68 | aa_set_double_output (1); 69 | break; 70 | 71 | case 'f': 72 | if (!uint0_scan (optarg, (unsigned int *) &fd)) 73 | aa_strerr_diefu1sys (1, "set fd"); 74 | break; 75 | 76 | case 'h': 77 | dieusage (0); 78 | 79 | case 's': 80 | steal = 1; 81 | break; 82 | 83 | case 'V': 84 | aa_die_version (); 85 | 86 | default: 87 | dieusage (1); 88 | } 89 | } 90 | argc -= optind; 91 | argv += optind; 92 | 93 | if (argc == 0) 94 | dieusage (1); 95 | 96 | if (ioctl (fd, TIOCSCTTY, steal) < 0) 97 | aa_strerr_warnu1sys ("set controlling terminal"); 98 | 99 | pathexec_run (argv[0], (char const * const *) argv, envp); 100 | aa_strerr_dieexec (111, argv[0]); 101 | } 102 | -------------------------------------------------------------------------------- /src/utils/aa-echo.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * aa-echo.c 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | typedef void (*put_fn) (const char *name, const char *msg, int end); 29 | 30 | static void 31 | put_title (const char *name, const char *msg, int end) 32 | { 33 | aa_put_title (1, name, msg, end); 34 | } 35 | 36 | static void 37 | put_title2 (const char *name, const char *msg, int end) 38 | { 39 | aa_put_title (0, name, msg, end); 40 | } 41 | 42 | static void 43 | dieusage (int rc) 44 | { 45 | aa_die_usage (rc, "[OPTION...] MESSAGE...", 46 | " -D, --double-output Enable double-output mode\n" 47 | " -B, --blank-first Print a blank line (LF) first\n" 48 | " -T, --title Show a main title (default)\n" 49 | " -t, --title2 Show a secondary title\n" 50 | " -w, --warning Show a warning\n" 51 | " -e, --error Show an error\n" 52 | " -n, --normal Show \"normal\" text\n" 53 | " -h, --help Show this help screen and exit\n" 54 | " -V, --version Show version information and exit\n" 55 | "\n" 56 | "MESSAGE can be used to set the text color:\n" 57 | "\n" 58 | " +g, +green Set color to green\n" 59 | " +b, +blue Set color to blue\n" 60 | " +y, +yellow Set color to yellow\n" 61 | " +r, +red Set color to red\n" 62 | " +w, +white Set color to white\n" 63 | " +n, +normal Set color to normal\n" 64 | " ++TEXT To just print +TEXT\n" 65 | ); 66 | } 67 | 68 | int 69 | main (int argc, char * const argv[]) 70 | { 71 | PROG = "aa-echo"; 72 | int blank = 0; 73 | put_fn put = put_title; 74 | int where = AA_OUT; 75 | int i; 76 | 77 | for (;;) 78 | { 79 | struct option longopts[] = { 80 | { "blank-first", no_argument, NULL, 'B' }, 81 | { "double-output", no_argument, NULL, 'D' }, 82 | { "error", no_argument, NULL, 'e' }, 83 | { "help", no_argument, NULL, 'h' }, 84 | { "normal", no_argument, NULL, 'n' }, 85 | { "title", no_argument, NULL, 'T' }, 86 | { "title2", no_argument, NULL, 't' }, 87 | { "version", no_argument, NULL, 'V' }, 88 | { "warning", no_argument, NULL, 'w' }, 89 | { NULL, 0, 0, 0 } 90 | }; 91 | int c; 92 | 93 | c = getopt_long (argc, argv, "BDehnTtVw", longopts, NULL); 94 | if (c == -1) 95 | break; 96 | switch (c) 97 | { 98 | case 'B': 99 | blank = 1; 100 | break; 101 | 102 | case 'D': 103 | aa_set_double_output (1); 104 | break; 105 | 106 | case 'e': 107 | put = aa_put_err; 108 | where = AA_ERR; 109 | break; 110 | 111 | case 'h': 112 | dieusage (0); 113 | 114 | case 'n': 115 | put = NULL; 116 | where = AA_OUT; 117 | break; 118 | 119 | case 'T': 120 | put = put_title; 121 | where = AA_OUT; 122 | break; 123 | 124 | case 't': 125 | put = put_title2; 126 | where = AA_OUT; 127 | break; 128 | 129 | case 'V': 130 | aa_die_version (); 131 | 132 | case 'w': 133 | put = aa_put_warn; 134 | where = AA_ERR; 135 | break; 136 | 137 | default: 138 | dieusage (1); 139 | } 140 | } 141 | argc -= optind; 142 | argv += optind; 143 | 144 | if (argc < 1) 145 | dieusage (1); 146 | 147 | if (blank) 148 | aa_bs_noflush (where, "\n"); 149 | if (put) 150 | put ("", NULL, 0); 151 | for (i = 0; i < argc; ++i) 152 | { 153 | if (*argv[i] == '+') 154 | { 155 | if (str_equal (argv[i], "+g") || str_equal (argv[i], "+green")) 156 | aa_is_noflush (where, ANSI_HIGHLIGHT_GREEN_ON); 157 | else if (str_equal (argv[i], "+b") || str_equal (argv[i], "+blue")) 158 | aa_is_noflush (where, ANSI_HIGHLIGHT_BLUE_ON); 159 | else if (str_equal (argv[i], "+y") || str_equal (argv[i], "+yellow")) 160 | aa_is_noflush (where, ANSI_HIGHLIGHT_YELLOW_ON); 161 | else if (str_equal (argv[i], "+r") || str_equal (argv[i], "+red")) 162 | aa_is_noflush (where, ANSI_HIGHLIGHT_RED_ON); 163 | else if (str_equal (argv[i], "+w") || str_equal (argv[i], "+white")) 164 | aa_is_noflush (where, ANSI_HIGHLIGHT_ON); 165 | else if (str_equal (argv[i], "+n") || str_equal (argv[i], "+normal")) 166 | aa_is_noflush (where, ANSI_HIGHLIGHT_OFF); 167 | else 168 | aa_bs_noflush (where, argv[i] + 1); 169 | } 170 | else 171 | aa_bs_noflush (where, argv[i]); 172 | } 173 | aa_bs_end (where); 174 | 175 | return 0; 176 | } 177 | -------------------------------------------------------------------------------- /src/utils/aa-incmdline.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * aa-incmdline.c 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | static void 32 | dieusage (int rc) 33 | { 34 | aa_die_usage (rc, "[OPTION] NAME", 35 | " -D, --double-output Enable double-output mode\n" 36 | " -f, --file FILE Use FILE instead of /proc/cmdline\n" 37 | " -q, --quiet Don't write value (if any) to stdout\n" 38 | " -s, --safe[=C] Ignore argument if value contain C (default: '/')\n" 39 | " -r, --required Ignore argument if no value specified\n" 40 | " -h, --help Show this help screen and exit\n" 41 | " -V, --version Show version information and exit\n" 42 | ); 43 | } 44 | 45 | int 46 | main (int argc, char * const argv[]) 47 | { 48 | PROG = "aa-incmdline"; 49 | stralloc sa = STRALLOC_ZERO; 50 | const char *file = "/proc/cmdline"; 51 | int quiet = 0; 52 | int req = 0; 53 | char safe = '\0'; 54 | size_t len_arg; 55 | size_t start; 56 | size_t i; 57 | 58 | for (;;) 59 | { 60 | struct option longopts[] = { 61 | { "double-output", no_argument, NULL, 'D' }, 62 | { "file", no_argument, NULL, 'f' }, 63 | { "help", no_argument, NULL, 'h' }, 64 | { "quiet", no_argument, NULL, 'q' }, 65 | { "required", no_argument, NULL, 'r' }, 66 | { "safe", optional_argument, NULL, 's' }, 67 | { "version", no_argument, NULL, 'V' }, 68 | { NULL, 0, 0, 0 } 69 | }; 70 | int c; 71 | 72 | c = getopt_long (argc, argv, "Df:hqrs::V", longopts, NULL); 73 | if (c == -1) 74 | break; 75 | switch (c) 76 | { 77 | case 'D': 78 | aa_set_double_output (1); 79 | break; 80 | 81 | case 'f': 82 | file = optarg; 83 | break; 84 | 85 | case 'h': 86 | dieusage (0); 87 | 88 | case 'q': 89 | quiet = 1; 90 | break; 91 | 92 | case 'r': 93 | req = 1; 94 | break; 95 | 96 | case 's': 97 | if (!optarg) 98 | safe = '/'; 99 | else if (!*optarg || optarg[1]) 100 | dieusage (1); 101 | else 102 | safe = *optarg; 103 | break; 104 | 105 | case 'V': 106 | aa_die_version (); 107 | 108 | default: 109 | dieusage (1); 110 | } 111 | } 112 | argc -= optind; 113 | argv += optind; 114 | 115 | if (argc < 1) 116 | dieusage (1); 117 | 118 | if (!openslurpclose (&sa, file)) 119 | aa_strerr_diefu2sys (2, "read ", file); 120 | 121 | len_arg = strlen (argv[0]); 122 | for (start = i = 0; i < sa.len; ++i) 123 | { 124 | if (sa.s[i] == '=' || sa.s[i] == ' ' || sa.s[i] == '\t' 125 | || sa.s[i] == '\n' || sa.s[i] == '\0') 126 | { 127 | int found = (i - start == len_arg && !str_diffn (sa.s + start, argv[0], len_arg)); 128 | size_t len; 129 | 130 | if (sa.s[i] != '=') 131 | { 132 | if (found) 133 | return (req) ? 3 : 0; 134 | start = ++i; 135 | goto next; 136 | } 137 | else if (found && quiet && !safe) 138 | return (req) ? 3 : 0; 139 | 140 | start = ++i; 141 | if (sa.s[start] != '"') 142 | for (len = 0; 143 | start + len < sa.len 144 | && sa.s[start + len] != ' ' && sa.s[start + len] != '\t'; 145 | ++len) 146 | ; 147 | else 148 | { 149 | ++start; 150 | len = byte_chr (sa.s + start, sa.len - start, '"'); 151 | } 152 | 153 | if (found) 154 | { 155 | if (len == sa.len - start) 156 | --len; 157 | if (safe && byte_chr (sa.s + start, len, safe) < len) 158 | return 3; 159 | if (req && len == 0) 160 | return 3; 161 | else if (!quiet) 162 | { 163 | aa_bb_noflush (AA_OUT, sa.s + start, len); 164 | aa_bs_flush (AA_OUT, "\n"); 165 | } 166 | return 0; 167 | } 168 | 169 | start += len; 170 | i = ++start; 171 | next: 172 | while (i < sa.len && (sa.s[i] == ' ' || sa.s[i] == '\t')) 173 | start = ++i; 174 | } 175 | } 176 | 177 | return 3; 178 | } 179 | -------------------------------------------------------------------------------- /src/utils/aa-kill.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * aa-kill.c 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #define _BSD_SOURCE 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | static struct { 38 | unsigned int term : 1; 39 | unsigned int kill : 1; 40 | unsigned int hup : 1; 41 | 42 | unsigned int skip_at : 1; 43 | } send = { 0, }; 44 | static char ownpid[UINT_FMT]; 45 | 46 | #if 0 47 | static void _kill (pid_t pid, int sig) 48 | { 49 | char buf[UINT_FMT]; 50 | unsigned int u; 51 | 52 | u = pid; 53 | buf[uint_fmt (buf, u)] = 0; 54 | aa_bs_noflush (AA_OUT, "kill("); 55 | if (u == (unsigned int) -1) 56 | aa_bs_noflush (AA_OUT, "-1"); 57 | else 58 | aa_bs_noflush (AA_OUT, buf); 59 | aa_bs_noflush (AA_OUT, ","); 60 | aa_bs_noflush (AA_OUT, sig_name (sig)); 61 | aa_bs_flush (AA_OUT, ")\n"); 62 | } 63 | #else 64 | #define _kill(pid,sig) kill (pid, sig) 65 | #endif 66 | 67 | static int 68 | it_kill (direntry *d, void *data) 69 | { 70 | stralloc *sa = data; 71 | char c; 72 | size_t l; 73 | ssize_t r; 74 | 75 | /* ignore files, not-number dirs, PID 1 and ourself */ 76 | if (d->d_type != DT_DIR || *d->d_name < '1' || *d->d_name > '9' 77 | || str_equal (d->d_name, "1") || str_equal (d->d_name, ownpid)) 78 | return 0; 79 | 80 | l = sa->len; 81 | sa->s[l - 1] = '/'; 82 | if (stralloc_cats (sa, d->d_name) 83 | && stralloc_catb (sa, "/cmdline", sizeof ("/cmdline"))) 84 | r = openreadnclose (sa->s, &c, 1); 85 | else 86 | r = -1; 87 | sa->len = l; 88 | sa->s[l - 1] = '\0'; 89 | 90 | /* skip empty cmdline (kernel threads) and anything starting with '@' */ 91 | if (r == 1 && c != '@') 92 | { 93 | unsigned int u; 94 | pid_t pid; 95 | 96 | if (!uint_scan (d->d_name, &u)) 97 | goto done; 98 | pid = (pid_t) u; 99 | if (send.hup) 100 | _kill (pid, SIGHUP); 101 | if (send.term) 102 | { 103 | _kill (pid, SIGTERM); 104 | _kill (pid, SIGCONT); 105 | } 106 | if (send.kill) 107 | _kill (pid, SIGKILL); 108 | } 109 | 110 | done: 111 | return 0; 112 | } 113 | 114 | static void 115 | dieusage (int rc) 116 | { 117 | aa_die_usage (rc, "[OPTION...]", 118 | " -D, --double-output Enable double-output mode\n" 119 | " -u, --hup Send SIGHUP\n" 120 | " -t, --term Send SIGTERM then SIGCONT\n" 121 | " -k, --kill Send SIGKILL\n" 122 | " -s, --skip-at Skip processes whose cmdline starts with '@'\n" 123 | " -h, --help Show this help screen and exit\n" 124 | " -V, --version Show version information and exit\n" 125 | ); 126 | } 127 | 128 | int 129 | main (int argc, char * const argv[]) 130 | { 131 | PROG = "aa-kill"; 132 | 133 | for (;;) 134 | { 135 | struct option longopts[] = { 136 | { "double-output", no_argument, NULL, 'D' }, 137 | { "help", no_argument, NULL, 'h' }, 138 | { "kill", no_argument, NULL, 'k' }, 139 | { "skip-at", no_argument, NULL, 's' }, 140 | { "term", no_argument, NULL, 't' }, 141 | { "hup", no_argument, NULL, 'u' }, 142 | { "version", no_argument, NULL, 'V' }, 143 | { NULL, 0, 0, 0 } 144 | }; 145 | int c; 146 | 147 | c = getopt_long (argc, argv, "DhkstuV", longopts, NULL); 148 | if (c == -1) 149 | break; 150 | switch (c) 151 | { 152 | case 'D': 153 | aa_set_double_output (1); 154 | break; 155 | 156 | case 'h': 157 | dieusage (0); 158 | 159 | case 'k': 160 | send.kill = 1; 161 | break; 162 | 163 | case 's': 164 | send.skip_at = 1; 165 | break; 166 | 167 | case 't': 168 | send.term = 1; 169 | break; 170 | 171 | case 'u': 172 | send.hup = 1; 173 | break; 174 | 175 | case 'V': 176 | aa_die_version (); 177 | 178 | default: 179 | dieusage (1); 180 | } 181 | } 182 | argc -= optind; 183 | argv += optind; 184 | 185 | if (argc > 0 || (!send.hup && !send.term && !send.kill)) 186 | dieusage (1); 187 | 188 | if (send.skip_at) 189 | { 190 | stralloc sa = STRALLOC_ZERO; 191 | unsigned int u; 192 | 193 | u = (unsigned int) getpid (); 194 | ownpid[uint_fmt (ownpid, u)] = '\0'; 195 | 196 | if (!stralloc_catb (&sa, "/proc", sizeof ("/proc"))) 197 | aa_strerr_diefu1sys (1, "stralloc_catb"); 198 | if (aa_scan_dir (&sa, 0, it_kill, &sa) < 0) 199 | aa_strerr_diefu1sys (1, "scan /proc"); 200 | stralloc_free (&sa); 201 | } 202 | else 203 | { 204 | if (send.hup) 205 | { 206 | sig_ignore (SIGHUP); 207 | _kill (-1, SIGHUP); 208 | } 209 | 210 | if (send.term) 211 | { 212 | sig_ignore (SIGTERM); 213 | _kill (-1, SIGTERM); 214 | _kill (-1, SIGCONT); 215 | } 216 | 217 | if (send.kill) 218 | _kill (-1, SIGKILL); 219 | } 220 | 221 | return 0; 222 | } 223 | -------------------------------------------------------------------------------- /src/utils/aa-pivot.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * aa-pivot.c 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #ifndef NULL 28 | #define NULL (void *) 0 29 | #endif 30 | 31 | extern int pivot_root (char const *new_root, char const *old_root); 32 | 33 | static void 34 | dieusage (int rc) 35 | { 36 | aa_die_usage (rc, "NEWROOT OLDROOT", 37 | " -D, --double-output Enable double-output mode\n" 38 | " -h, --help Show this help screen and exit\n" 39 | " -V, --version Show version information and exit\n" 40 | ); 41 | } 42 | 43 | int 44 | main (int argc, char * const argv[]) 45 | { 46 | PROG = "aa-pivot"; 47 | 48 | for (;;) 49 | { 50 | struct option longopts[] = { 51 | { "double-output", no_argument, NULL, 'D' }, 52 | { "help", no_argument, NULL, 'h' }, 53 | { "version", no_argument, NULL, 'V' }, 54 | { NULL, 0, 0, 0 } 55 | }; 56 | int c; 57 | 58 | c = getopt_long (argc, argv, "DhV", longopts, NULL); 59 | if (c == -1) 60 | break; 61 | switch (c) 62 | { 63 | case 'D': 64 | aa_set_double_output (1); 65 | break; 66 | 67 | case 'h': 68 | dieusage (0); 69 | 70 | case 'V': 71 | aa_die_version (); 72 | 73 | default: 74 | dieusage (1); 75 | } 76 | } 77 | argc -= optind; 78 | argv += optind; 79 | 80 | if (argc < 2) 81 | dieusage (1); 82 | 83 | if (pivot_root (argv[0], argv[1]) < 0) 84 | aa_strerr_diefu2sys (2, "pivot into ", argv[0]); 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /src/utils/aa-reboot.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * aa-reboot.c 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | static void 30 | dieusage (int rc) 31 | { 32 | aa_die_usage (rc, "OPTION", 33 | " -D, --double-output Enable double-output mode\n" 34 | " -r, --reboot Reboot the machine NOW\n" 35 | " -H, --halt Halt the machine NOW\n" 36 | " -p, --poweroff Power off the machine NOW\n" 37 | " -h, --help Show this help screen and exit\n" 38 | " -V, --version Show version information and exit\n" 39 | ); 40 | } 41 | 42 | int 43 | main (int argc, char * const argv[]) 44 | { 45 | PROG = "aa-reboot"; 46 | struct 47 | { 48 | int cmd; 49 | const char *desc; 50 | } cmd[3] = { 51 | { .cmd = RB_HALT_SYSTEM, .desc = "halt" }, 52 | { .cmd = RB_POWER_OFF, .desc = "power off" }, 53 | { .cmd = RB_AUTOBOOT, .desc = "reboot" } 54 | }; 55 | int i = -1; 56 | 57 | for (;;) 58 | { 59 | struct option longopts[] = { 60 | { "double-output", no_argument, NULL, 'D' }, 61 | { "halt", no_argument, NULL, 'H' }, 62 | { "help", no_argument, NULL, 'h' }, 63 | { "poweroff", no_argument, NULL, 'p' }, 64 | { "reboot", no_argument, NULL, 'r' }, 65 | { "version", no_argument, NULL, 'V' }, 66 | { NULL, 0, 0, 0 } 67 | }; 68 | int c; 69 | 70 | c = getopt_long (argc, argv, "DHhprV", longopts, NULL); 71 | if (c == -1) 72 | break; 73 | switch (c) 74 | { 75 | case 'D': 76 | aa_set_double_output (1); 77 | break; 78 | 79 | case 'H': 80 | i = 0; 81 | break; 82 | 83 | case 'h': 84 | dieusage (0); 85 | 86 | case 'p': 87 | i = 1; 88 | break; 89 | 90 | case 'r': 91 | i = 2; 92 | break; 93 | 94 | case 'V': 95 | aa_die_version (); 96 | 97 | default: 98 | dieusage (1); 99 | } 100 | } 101 | argc -= optind; 102 | argv += optind; 103 | 104 | if (argc != 0 || i < 0) 105 | dieusage (1); 106 | 107 | if (reboot (cmd[i].cmd) < 0) 108 | aa_strerr_diefu2sys (2, cmd[i].desc, " the machine"); 109 | 110 | /* unlikely :p */ 111 | return 0; 112 | } 113 | -------------------------------------------------------------------------------- /src/utils/aa-setready.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * aa-setready.c 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | static void 34 | dieusage (int rc) 35 | { 36 | aa_die_usage (rc, "[OPTION] SERVICEDIR", 37 | " -D, --double-output Enable double-output mode\n" 38 | " -U, --ready Mark service ready; This is the default.\n" 39 | " -N, --unready Mark service not ready\n" 40 | "\n" 41 | " -h, --help Show this help screen and exit\n" 42 | " -V, --version Show version information and exit\n" 43 | ); 44 | } 45 | 46 | int 47 | main (int argc, char * const argv[]) 48 | { 49 | PROG = "aa-setready"; 50 | int ready = 1; 51 | 52 | for (;;) 53 | { 54 | struct option longopts[] = { 55 | { "double-output", no_argument, NULL, 'D' }, 56 | { "help", no_argument, NULL, 'h' }, 57 | { "unready", no_argument, NULL, 'N' }, 58 | { "ready", no_argument, NULL, 'U' }, 59 | { "version", no_argument, NULL, 'V' }, 60 | { NULL, 0, 0, 0 } 61 | }; 62 | int c; 63 | 64 | c = getopt_long (argc, argv, "DhNUV", longopts, NULL); 65 | if (c == -1) 66 | break; 67 | switch (c) 68 | { 69 | case 'D': 70 | aa_set_double_output (1); 71 | break; 72 | 73 | case 'h': 74 | dieusage (0); 75 | 76 | case 'N': 77 | ready = 0; 78 | break; 79 | 80 | case 'U': 81 | ready = 1; 82 | break; 83 | 84 | case 'V': 85 | aa_die_version (); 86 | 87 | default: 88 | dieusage (1); 89 | } 90 | } 91 | argc -= optind; 92 | argv += optind; 93 | 94 | if (argc != 1) 95 | dieusage (1); 96 | 97 | { 98 | size_t l = strlen (argv[0]); 99 | char fifodir[l + 1 + sizeof (S6_SUPERVISE_EVENTDIR)]; 100 | s6_svstatus_t st6 = S6_SVSTATUS_ZERO; 101 | 102 | byte_copy (fifodir, l, argv[0]); 103 | fifodir[l] = '/'; 104 | byte_copy (fifodir + l + 1, sizeof (S6_SUPERVISE_EVENTDIR), S6_SUPERVISE_EVENTDIR); 105 | 106 | if (!s6_svstatus_read (argv[0], &st6)) 107 | aa_strerr_diefu1sys (2, "read s6 status"); 108 | if (!(st6.pid && !st6.flagfinishing)) 109 | aa_strerr_dief1x (3, "service is not up"); 110 | 111 | if (ready) 112 | { 113 | st6.flagready = 1; 114 | if (!tain_now (&st6.readystamp)) 115 | aa_strerr_diefu1sys (4, "tain_now"); 116 | } 117 | else 118 | st6.flagready = 0; 119 | 120 | if (!s6_svstatus_write (argv[0], &st6)) 121 | aa_strerr_diefu1sys (5, "write s6 status"); 122 | 123 | if (ftrigw_notify (fifodir, (ready) ? 'U' : 'N') < 0) 124 | aa_strerr_diefu4sys (6, "send event ", (ready) ? "U": "N" , " via ", fifodir); 125 | } 126 | 127 | return 0; 128 | } 129 | -------------------------------------------------------------------------------- /src/utils/aa-sync.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * aa-sync.c 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | const char *PROG; 28 | 29 | static void 30 | dieusage (int rc) 31 | { 32 | aa_die_usage (rc, "[OPTION]", 33 | " -h, --help Show this help screen and exit\n" 34 | " -V, --version Show version information and exit\n" 35 | ); 36 | } 37 | 38 | int 39 | main (int argc, char * const argv[]) 40 | { 41 | PROG = "aa-sync"; 42 | 43 | if (argc == 1) 44 | { 45 | sync (); 46 | return 0; 47 | } 48 | 49 | if (argc == 2 && (str_equal (argv[1], "-V") || str_equal (argv[1], "--version"))) 50 | aa_die_version (); 51 | dieusage ((argc == 2 && (str_equal (argv[1], "-h") || str_equal (argv[1], "--help"))) ? 0 : 1); 52 | } 53 | -------------------------------------------------------------------------------- /src/utils/aa-test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * aa-test.c 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | static int 32 | is_group_member (gid_t gid) 33 | { 34 | int nb = getgroups (0, NULL); 35 | gid_t groups[nb]; 36 | int i; 37 | 38 | if (gid == getgid () || gid == getegid()) 39 | return 1; 40 | 41 | if (getgroups (nb, groups) < 0) 42 | return 0; 43 | 44 | for (i = 0; i < nb; ++i) 45 | if (gid == groups[i]) 46 | return 1; 47 | 48 | return 0; 49 | } 50 | 51 | static void 52 | dieusage (int rc) 53 | { 54 | aa_die_usage (rc, "OPTION FILE", 55 | " -D, --double-output Enable double-output mode\n" 56 | " -b, --block Test whether FILE is a block special\n" 57 | " -d, --directory Test whether FILE is a directory\n" 58 | " -e, --exists Test whether FILE exists\n" 59 | " -f, --file Test whether FILE is a regular file\n" 60 | " -L, --symlink Test whether FILE is a symbolic link\n" 61 | " -p, --pipe Test whether FILE is a named pipe\n" 62 | " -S, --socket Test whether FILE is a socket\n" 63 | " -r, --read Test for read permission on FILE\n" 64 | " -w, --write Test for write permission on FILE\n" 65 | " -x, --execute Test for execute permission on FILE\n" 66 | " -R, --repeat[=TIMES] Repeat test every second up to TIMES times\n" 67 | "\n" 68 | " -h, --help Show this help screen and exit\n" 69 | " -V, --version Show version information and exit\n" 70 | ); 71 | } 72 | 73 | int 74 | main (int argc, char * const argv[]) 75 | { 76 | PROG = "aa-test"; 77 | struct stat st; 78 | uid_t euid; 79 | int mode = 0; /* silence warning */ 80 | char test = 0; 81 | unsigned int repeat = 0; 82 | 83 | for (;;) 84 | { 85 | struct option longopts[] = { 86 | { "block", no_argument, NULL, 'b' }, 87 | { "double-output", no_argument, NULL, 'D' }, 88 | { "directory", no_argument, NULL, 'd' }, 89 | { "exists", no_argument, NULL, 'e' }, 90 | { "file", no_argument, NULL, 'f' }, 91 | { "help", no_argument, NULL, 'h' }, 92 | { "symlink", no_argument, NULL, 'L' }, 93 | { "pipe", no_argument, NULL, 'p' }, 94 | { "read", no_argument, NULL, 'r' }, 95 | { "repeat", optional_argument, NULL, 'R' }, 96 | { "socket", no_argument, NULL, 'S' }, 97 | { "version", no_argument, NULL, 'V' }, 98 | { "write", no_argument, NULL, 'w' }, 99 | { "execute", no_argument, NULL, 'x' }, 100 | { NULL, 0, 0, 0 } 101 | }; 102 | int c; 103 | 104 | c = getopt_long (argc, argv, "bDdefhLprR::SVwx", longopts, NULL); 105 | if (c == -1) 106 | break; 107 | switch (c) 108 | { 109 | case 'b': 110 | case 'd': 111 | case 'e': 112 | case 'f': 113 | case 'L': 114 | case 'p': 115 | case 'r': 116 | case 'S': 117 | case 'w': 118 | case 'x': 119 | test = c; 120 | break; 121 | 122 | case 'D': 123 | aa_set_double_output (1); 124 | break; 125 | 126 | case 'h': 127 | dieusage (0); 128 | 129 | case 'R': 130 | if (optarg && !uint0_scan (optarg, &repeat)) 131 | aa_strerr_diefu2sys (1, "set repeat counter to ", optarg); 132 | else if (!optarg) 133 | repeat = 1; 134 | else 135 | ++repeat; 136 | break; 137 | 138 | case 'V': 139 | aa_die_version (); 140 | 141 | default: 142 | dieusage (1); 143 | } 144 | } 145 | argc -= optind; 146 | argv += optind; 147 | 148 | if (argc != 1 || test == 0) 149 | dieusage (1); 150 | 151 | again: 152 | if (lstat (argv[0], &st) < 0) 153 | { 154 | if (errno != ENOENT) 155 | aa_strerr_diefu2sys (2, "stat ", argv[0]); 156 | else if (repeat >= 1) 157 | { 158 | if (repeat > 2) 159 | --repeat; 160 | else if (repeat == 2) 161 | return 3; 162 | sleep (1); 163 | goto again; 164 | } 165 | else 166 | return 3; 167 | } 168 | 169 | switch (test) 170 | { 171 | case 'b': 172 | return (S_ISBLK (st.st_mode)) ? 0 : 4; 173 | 174 | case 'd': 175 | return (S_ISDIR (st.st_mode)) ? 0 : 4; 176 | 177 | case 'e': 178 | return 0; 179 | 180 | case 'f': 181 | return (S_ISREG (st.st_mode)) ? 0 : 4; 182 | 183 | case 'L': 184 | return (S_ISLNK (st.st_mode)) ? 0 : 4; 185 | 186 | case 'p': 187 | return (S_ISFIFO (st.st_mode)) ? 0 : 4; 188 | 189 | case 'r': 190 | mode = R_OK; 191 | break; 192 | 193 | case 'S': 194 | return (S_ISSOCK (st.st_mode)) ? 0 : 4; 195 | 196 | case 'w': 197 | mode = W_OK; 198 | break; 199 | 200 | case 'x': 201 | mode = X_OK; 202 | break; 203 | } 204 | 205 | euid = geteuid (); 206 | if (euid == 0) 207 | { 208 | /* root can read/write any file */ 209 | if (mode != X_OK) 210 | return 0; 211 | /* and execute anything any execute permission set */ 212 | else if (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) 213 | return 0; 214 | else 215 | return 4; 216 | } 217 | 218 | if (st.st_uid == euid) 219 | mode <<= 6; 220 | else if (is_group_member (st.st_gid)) 221 | mode <<= 3; 222 | 223 | return (st.st_mode & mode) ? 0 : 4; 224 | } 225 | -------------------------------------------------------------------------------- /src/utils/aa-tty.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * aa-tty.c 5 | * Copyright (C) 2015-2017 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #define PREFIX "/sys/class/tty/" 31 | #define NAME "/active" 32 | 33 | static void 34 | dieusage (int rc) 35 | { 36 | aa_die_usage (rc, "", 37 | " -D, --double-output Enable double-output mode\n" 38 | " -h, --help Show this help screen and exit\n" 39 | " -V, --version Show version information and exit\n" 40 | ); 41 | } 42 | 43 | int 44 | main (int argc, char * const argv[]) 45 | { 46 | PROG = "aa-tty"; 47 | char file[256]; 48 | size_t max = sizeof (file) - sizeof (PREFIX) - sizeof (NAME) + 1; 49 | char name[max]; 50 | size_t skip; 51 | ssize_t r; 52 | 53 | for (;;) 54 | { 55 | struct option longopts[] = { 56 | { "double-output", no_argument, NULL, 'D' }, 57 | { "help", no_argument, NULL, 'h' }, 58 | { "version", no_argument, NULL, 'V' }, 59 | { NULL, 0, 0, 0 } 60 | }; 61 | int c; 62 | 63 | c = getopt_long (argc, argv, "DhV", longopts, NULL); 64 | if (c == -1) 65 | break; 66 | switch (c) 67 | { 68 | case 'D': 69 | aa_set_double_output (1); 70 | break; 71 | 72 | case 'h': 73 | dieusage (0); 74 | 75 | case 'V': 76 | aa_die_version (); 77 | 78 | default: 79 | dieusage (1); 80 | } 81 | } 82 | argc -= optind; 83 | argv += optind; 84 | 85 | if (argc != 0) 86 | dieusage (1); 87 | 88 | byte_copy (file, sizeof (PREFIX) - 1, PREFIX); 89 | byte_copy (file + sizeof (PREFIX) - 1, 7, "console"); 90 | byte_copy (file + sizeof (PREFIX) + 6, sizeof (NAME), NAME); 91 | r = openreadnclose (file, name, max); 92 | if (r <= 0) 93 | aa_strerr_diefu2sys (2, "read ", file); 94 | /* last entry is the active one */ 95 | skip = byte_rchr (name, r, ' ') + 1; 96 | if (skip > (size_t) r) 97 | skip = 0; 98 | 99 | for (;;) 100 | { 101 | const char *s = name + skip; 102 | size_t l = r - skip; 103 | 104 | byte_copy (file + sizeof (PREFIX) - 1, l, s); 105 | byte_copy (file + sizeof (PREFIX) - 2 + l, sizeof (NAME), NAME); 106 | r = openreadnclose (file, name, max); 107 | if (r <= 0) 108 | { 109 | if (errno == ENOENT) 110 | { 111 | aa_bs_noflush (AA_OUT, "/dev/"); 112 | aa_bb_flush (AA_OUT, s, l); 113 | return 0; 114 | } 115 | else 116 | aa_strerr_diefu2sys (2, "read ", file); 117 | } 118 | skip = 0; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/utils/aa-umount.c: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * aa-umount.c 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #ifndef NULL 29 | #define NULL (void *) 0 30 | #endif 31 | 32 | static void 33 | dieusage (int rc) 34 | { 35 | aa_die_usage (rc, "[OPTIONS...] MOUNTPOINT", 36 | " -D, --double-output Enable double-output mode\n" 37 | " -f, --force Force unmount even if busy (NFS only)\n" 38 | " -l, --lazy Perform lazy unmounting\n" 39 | " -h, --help Show this help screen and exit\n" 40 | " -V, --version Show version information and exit\n" 41 | ); 42 | } 43 | 44 | int 45 | main (int argc, char * const argv[]) 46 | { 47 | PROG = "aa-umount"; 48 | int flags = 0; 49 | 50 | for (;;) 51 | { 52 | struct option longopts[] = { 53 | { "double-output", no_argument, NULL, 'D' }, 54 | { "force", no_argument, NULL, 'f' }, 55 | { "help", no_argument, NULL, 'h' }, 56 | { "lazy", no_argument, NULL, 'l' }, 57 | { "version", no_argument, NULL, 'V' }, 58 | { NULL, 0, 0, 0 } 59 | }; 60 | int c; 61 | 62 | c = getopt_long (argc, argv, "DfhlV", longopts, NULL); 63 | if (c == -1) 64 | break; 65 | switch (c) 66 | { 67 | case 'D': 68 | aa_set_double_output (1); 69 | break; 70 | 71 | case 'f': 72 | flags = MNT_FORCE; 73 | break; 74 | 75 | case 'h': 76 | dieusage (0); 77 | 78 | case 'l': 79 | flags = MNT_DETACH; 80 | break; 81 | 82 | case 'V': 83 | aa_die_version (); 84 | 85 | default: 86 | dieusage (1); 87 | } 88 | } 89 | argc -= optind; 90 | argv += optind; 91 | 92 | if (argc != 1) 93 | dieusage (1); 94 | 95 | if (umount2 (argv[0], flags) < 0) 96 | aa_strerr_diefu2sys (3, "unmount ", argv[0]); 97 | 98 | return 0; 99 | } 100 | -------------------------------------------------------------------------------- /src/utils/deps-exe/aa-chroot: -------------------------------------------------------------------------------- 1 | ${LIBANOPA} 2 | -lskarnet 3 | -------------------------------------------------------------------------------- /src/utils/deps-exe/aa-ctty: -------------------------------------------------------------------------------- 1 | ${LIBANOPA} 2 | -lskarnet 3 | -------------------------------------------------------------------------------- /src/utils/deps-exe/aa-echo: -------------------------------------------------------------------------------- 1 | ${LIBANOPA} 2 | -lskarnet 3 | -------------------------------------------------------------------------------- /src/utils/deps-exe/aa-incmdline: -------------------------------------------------------------------------------- 1 | ${LIBANOPA} 2 | -lskarnet 3 | -------------------------------------------------------------------------------- /src/utils/deps-exe/aa-kill: -------------------------------------------------------------------------------- 1 | ${LIBANOPA} 2 | -lskarnet 3 | -------------------------------------------------------------------------------- /src/utils/deps-exe/aa-mount: -------------------------------------------------------------------------------- 1 | ${LIBANOPA} 2 | -lskarnet 3 | -------------------------------------------------------------------------------- /src/utils/deps-exe/aa-pivot: -------------------------------------------------------------------------------- 1 | ${LIBANOPA} 2 | -lskarnet 3 | -------------------------------------------------------------------------------- /src/utils/deps-exe/aa-reboot: -------------------------------------------------------------------------------- 1 | ${LIBANOPA} 2 | -lskarnet 3 | -------------------------------------------------------------------------------- /src/utils/deps-exe/aa-service: -------------------------------------------------------------------------------- 1 | ${LIBANOPA} 2 | -lexecline 3 | -lskarnet 4 | -------------------------------------------------------------------------------- /src/utils/deps-exe/aa-setready: -------------------------------------------------------------------------------- 1 | ${LIBANOPA} 2 | -ls6 3 | -lskarnet 4 | -------------------------------------------------------------------------------- /src/utils/deps-exe/aa-sync: -------------------------------------------------------------------------------- 1 | ${LIBANOPA} 2 | -lskarnet 3 | -------------------------------------------------------------------------------- /src/utils/deps-exe/aa-terminate: -------------------------------------------------------------------------------- 1 | ${LIBANOPA} 2 | -lskarnet 3 | -------------------------------------------------------------------------------- /src/utils/deps-exe/aa-test: -------------------------------------------------------------------------------- 1 | ${LIBANOPA} 2 | -lskarnet 3 | -------------------------------------------------------------------------------- /src/utils/deps-exe/aa-tty: -------------------------------------------------------------------------------- 1 | ${LIBANOPA} 2 | -lskarnet 3 | -------------------------------------------------------------------------------- /src/utils/deps-exe/aa-umount: -------------------------------------------------------------------------------- 1 | ${LIBANOPA} 2 | -lskarnet 3 | -------------------------------------------------------------------------------- /src/utils/mount-constants.h: -------------------------------------------------------------------------------- 1 | /* 2 | * anopa - Copyright (C) 2015-2017 Olivier Brunel 3 | * 4 | * mount-constants.h 5 | * Copyright (C) 2015 Olivier Brunel 6 | * 7 | * This file is part of anopa. 8 | * 9 | * anopa is free software: you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation, either version 3 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * anopa is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * anopa. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #ifndef AA_MOUNT_CONSTANTS_H 24 | #define AA_MOUNT_CONSTANTS_H 25 | 26 | /* taken from util-linux-ng */ 27 | 28 | #ifndef MS_RDONLY 29 | #define MS_RDONLY 1 /* Mount read-only */ 30 | #endif 31 | #ifndef MS_NOSUID 32 | #define MS_NOSUID 2 /* Ignore suid and sgid bits */ 33 | #endif 34 | #ifndef MS_NODEV 35 | #define MS_NODEV 4 /* Disallow access to device special files */ 36 | #endif 37 | #ifndef MS_NOEXEC 38 | #define MS_NOEXEC 8 /* Disallow program execution */ 39 | #endif 40 | #ifndef MS_SYNCHRONOUS 41 | #define MS_SYNCHRONOUS 16 /* Writes are synced at once */ 42 | #endif 43 | #ifndef MS_REMOUNT 44 | #define MS_REMOUNT 32 /* Alter flags of a mounted FS */ 45 | #endif 46 | #ifndef MS_MANDLOCK 47 | #define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */ 48 | #endif 49 | #ifndef MS_DIRSYNC 50 | #define MS_DIRSYNC 128 /* Directory modifications are synchronous */ 51 | #endif 52 | #ifndef MS_NOATIME 53 | #define MS_NOATIME 0x400 /* 1024: Do not update access times. */ 54 | #endif 55 | #ifndef MS_NODIRATIME 56 | #define MS_NODIRATIME 0x800 /* 2048: Don't update directory access times */ 57 | #endif 58 | #ifndef MS_BIND 59 | #define MS_BIND 0x1000 /* 4096: Mount existing tree also elsewhere */ 60 | #endif 61 | #ifndef MS_MOVE 62 | #define MS_MOVE 0x2000 /* 8192: Atomically move tree */ 63 | #endif 64 | #ifndef MS_REC 65 | #define MS_REC 0x4000 /* 16384: Recursive loopback */ 66 | #endif 67 | #ifndef MS_VERBOSE 68 | #define MS_VERBOSE 0x8000 /* 32768 */ 69 | #endif 70 | #ifndef MS_RELATIME 71 | #define MS_RELATIME 0x200000 /* 200000: Update access times relative to mtime/ctime */ 72 | #endif 73 | #ifndef MS_UNBINDABLE 74 | #define MS_UNBINDABLE (1<<17) /* 131072 unbindable */ 75 | #endif 76 | #ifndef MS_PRIVATE 77 | #define MS_PRIVATE (1<<18) /* 262144 Private */ 78 | #endif 79 | #ifndef MS_SLAVE 80 | #define MS_SLAVE (1<<19) /* 524288 Slave */ 81 | #endif 82 | #ifndef MS_SHARED 83 | #define MS_SHARED (1<<20) /* 1048576 Shared */ 84 | #endif 85 | #ifndef MS_I_VERSION 86 | #define MS_I_VERSION (1<<23) /* update inode I_version field */ 87 | #endif 88 | #ifndef MS_STRICTATIME 89 | #define MS_STRICTATIME (1<<24) /* strict atime semantics */ 90 | #endif 91 | /* 92 | * Magic mount flag number. Had to be or-ed to the flag values. 93 | */ 94 | #ifndef MS_MGC_VAL 95 | #define MS_MGC_VAL 0xC0ED0000 /* magic flag number to indicate "new" flags */ 96 | #endif 97 | #ifndef MS_MGC_MSK 98 | #define MS_MGC_MSK 0xffff0000 /* magic flag number mask */ 99 | #endif 100 | 101 | #endif /* AA_MOUNT_CONSTANTS_H */ 102 | -------------------------------------------------------------------------------- /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 | for dir in src/include/${package} src/* ; do 11 | for file in $(ls -1 $dir | grep -- \\.h$) ; do 12 | { 13 | grep -F -- "#include <${package}/" < ${dir}/$file | cut -d'<' -f2 | cut -d'>' -f1 ; 14 | grep -- '#include ".*\.h"' < ${dir}/$file | cut -d'"' -f2 15 | } | sort -u | { 16 | deps= 17 | while read dep ; do 18 | if echo $dep | grep -q "^${package}/" ; then 19 | deps="$deps src/include/$dep" 20 | elif test -f "${dir}/$dep" ; then 21 | deps="$deps ${dir}/$dep" 22 | else 23 | deps="$deps src/include-local/$dep" 24 | fi 25 | done 26 | if test -n "$deps" ; then 27 | echo "${dir}/${file}:${deps}" 28 | fi 29 | } 30 | done 31 | done 32 | 33 | for dir in src/* ; do 34 | for file in $(ls -1 $dir | grep -- \\.c$) ; do 35 | { 36 | grep -F -- "#include <${package}/" < ${dir}/$file | cut -d'<' -f2 | cut -d'>' -f1 ; 37 | grep -- '#include ".*\.h"' < ${dir}/$file | cut -d'"' -f2 38 | } | sort -u | { 39 | deps=" ${dir}/$file" 40 | while read dep ; do 41 | if echo $dep | grep -q "^${package}/" ; then 42 | deps="$deps src/include/$dep" 43 | elif test -f "${dir}/$dep" ; then 44 | deps="$deps ${dir}/$dep" 45 | else 46 | deps="$deps src/include-local/$dep" 47 | fi 48 | done 49 | o=$(echo $file | sed s/\\.c$/.o/) 50 | lo=$(echo $file | sed s/\\.c$/.lo/) 51 | echo "${dir}/${o} ${dir}/${lo}:${deps}" 52 | } 53 | done 54 | done 55 | echo 56 | 57 | for dir in $(ls -1 src | grep -v ^include) ; do 58 | for file in $(ls -1 src/$dir/deps-lib) ; do 59 | deps= 60 | while read dep ; do 61 | deps="$deps src/$dir/$dep" 62 | done < src/$dir/deps-lib/$file 63 | echo "lib$file.a: $deps" 64 | echo "lib${file}.so: $(echo "$deps" | sed 's/\.o/.lo/g')" 65 | done 66 | 67 | for file in $(ls -1 src/$dir/deps-exe) ; do 68 | deps= 69 | libs= 70 | while read dep ; do 71 | if echo $dep | grep -q -- \\.o$ ; then 72 | dep="src/$dir/$dep" 73 | fi 74 | if echo $dep | grep -q '^\${.*_LIB}' ; then 75 | libs="$libs $dep" 76 | else 77 | deps="$deps $dep" 78 | fi 79 | done < src/$dir/deps-exe/$file 80 | echo "$file: private EXTRA_LIBS :=$libs" 81 | echo "$file: src/$dir/$file.o$deps" 82 | done 83 | done 84 | 85 | for file in $(ls -1 src/scripts) ; do 86 | echo "$file: src/scripts/$file" 87 | done 88 | -------------------------------------------------------------------------------- /tools/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | usage() { 4 | echo "usage: $0 [-D] [-l] [-m mode] src dst" 1>&2 5 | exit 1 6 | } 7 | 8 | mkdirp=false 9 | symlink=false 10 | mode=0755 11 | 12 | while getopts Dlm: name ; do 13 | case "$name" in 14 | D) mkdirp=true ;; 15 | l) symlink=true ;; 16 | m) mode=$OPTARG ;; 17 | ?) usage ;; 18 | esac 19 | done 20 | shift $(($OPTIND - 1)) 21 | 22 | test "$#" -eq 2 || usage 23 | src=$1 24 | dst=$2 25 | tmp="$dst.tmp.$$" 26 | 27 | case "$dst" in 28 | */) echo "$0: $dst ends in /" 1>&2 ; exit 1 ;; 29 | esac 30 | 31 | set -C 32 | set -e 33 | 34 | if $mkdirp ; then 35 | umask 022 36 | case "$2" in 37 | */*) mkdir -p "${dst%/*}" ;; 38 | esac 39 | fi 40 | 41 | trap 'rm -f "$tmp"' EXIT INT QUIT TERM HUP 42 | 43 | umask 077 44 | 45 | if $symlink ; then 46 | ln -s "$src" "$tmp" 47 | else 48 | cat < "$1" > "$tmp" 49 | chmod "$mode" "$tmp" 50 | fi 51 | 52 | mv -f "$tmp" "$dst" 53 | if test -d "$dst" ; then 54 | rm -f "$dst/$(basename $tmp)" 55 | if $symlink ; then 56 | mkdir "$tmp" 57 | ln -s "$src" "$tmp/$(basename $dst)" 58 | mv -f "$tmp/$(basename $dst)" "${dst%/*}" 59 | rmdir "$tmp" 60 | else 61 | echo "$0: $dst is a directory" 1>&2 62 | exit 1 63 | fi 64 | fi 65 | --------------------------------------------------------------------------------