Welcome to little lamb

Code » anopa » commit 4d8cb93

Support --double-output about everywhere

author Olivier Brunel
2015-07-30 17:32:31 UTC
committer Olivier Brunel
2015-08-07 17:24:48 UTC
parent 25708434949e5e91597ea9ab0b3612012cdd2b46

Support --double-output about everywhere

aa-sync does not, but it doesn't ever output anything so it's ok.

This is useful for even warnings/errors (from aa_strerr_*) when stderr
is redirected to a file. Note that parsing order matters, so put your -D
first.

Note: aa-setready had its -D switch to -N for --unready, better
consistency that way. (Also with the latest s6 there's a new event 'D'
so ours will be renamed to 'N' as well, or just removed.)

doc/aa-chroot.pod +8 -1
doc/aa-ctty.pod +8 -1
doc/aa-incmdline.pod +8 -1
doc/aa-kill.pod +8 -1
doc/aa-mount.pod +8 -1
doc/aa-mvlog.pod +8 -1
doc/aa-pivot.pod +8 -1
doc/aa-reboot.pod +8 -1
doc/aa-service.pod +8 -1
doc/aa-setready.pod +12 -5
doc/aa-test.pod +9 -2
doc/aa-tty.pod +8 -1
doc/aa-umount.pod +8 -1
src/scripts/aa-stage0 +3 -3
src/scripts/aa-stage1 +1 -1
src/scripts/aa-stage2 +2 -2
src/scripts/aa-stage3 +2 -2
src/utils/aa-chroot.c +7 -1
src/utils/aa-ctty.c +7 -1
src/utils/aa-incmdline.c +9 -3
src/utils/aa-kill.c +13 -8
src/utils/aa-mount.c +7 -1
src/utils/aa-mvlog.c +45 -18
src/utils/aa-pivot.c +7 -1
src/utils/aa-reboot.c +7 -1
src/utils/aa-service.c +36 -13
src/utils/aa-setready.c +10 -4
src/utils/aa-test.c +7 -1
src/utils/aa-tty.c +33 -8
src/utils/aa-umount.c +7 -1

diff --git a/doc/aa-chroot.pod b/doc/aa-chroot.pod
index 2bc0fc6..1a5db74 100644
--- a/doc/aa-chroot.pod
+++ b/doc/aa-chroot.pod
@@ -4,12 +4,19 @@ aa-chroot - Execute command within given chroot jail
 
 =head1 SYNOPSIS
 
-B<aa-chroot> I<NEWROOT> I<COMMAND> [I<ARG...>]
+B<aa-chroot> [B<-D>] I<NEWROOT> I<COMMAND> [I<ARG...>]
 
 =head1 OPTIONS
 
 =over
 
+=item B<-D, --double-output>
+
+Enable double-output mode. Instead of using stdout for regular output, and
+stderr for warnings and errors, everything is sent both to stdout and stderr.
+This is intended to redirect stderr to a log file, so full output can be both
+shown on console and logged.
+
 =item B<-h, --help>
 
 Show help screen and exit.
diff --git a/doc/aa-ctty.pod b/doc/aa-ctty.pod
index 65a756c..217eefe 100644
--- a/doc/aa-ctty.pod
+++ b/doc/aa-ctty.pod
@@ -4,12 +4,19 @@ aa-ctty - Helper for execline script to set controlling terminal
 
 =head1 SYNOPSIS
 
-B<aa-ctty> [B<-f> I<FD>] [B<-s>] I<PROG...>
+B<aa-ctty> [B<-D>] [B<-f> I<FD>] [B<-s>] I<PROG...>
 
 =head1 OPTIONS
 
 =over
 
+=item B<-D, --double-output>
+
+Enable double-output mode. Instead of using stdout for regular output, and
+stderr for warnings and errors, everything is sent both to stdout and stderr.
+This is intended to redirect stderr to a log file, so full output can be both
+shown on console and logged.
+
 =item B<-f, --fd> I<FD>
 
 Use file descriptor I<FD> as terminal; Defaults to stdin (0).
diff --git a/doc/aa-incmdline.pod b/doc/aa-incmdline.pod
index 3a730d9..2cfc832 100644
--- a/doc/aa-incmdline.pod
+++ b/doc/aa-incmdline.pod
@@ -4,12 +4,19 @@ aa-incmdline - Helper to parse kernel command line
 
 =head1 SYNOPSIS
 
-B<aa-incmdline> [B<-q>] [B<-f> I<FILE>] [B<-r>] [B<-s>] I<NAME>
+B<aa-incmdline> [B<-D>] [B<-q>] [B<-f> I<FILE>] [B<-r>] [B<-s>] I<NAME>
 
 =head1 OPTIONS
 
 =over
 
+=item B<-D, --double-output>
+
+Enable double-output mode. Instead of using stdout for regular output, and
+stderr for warnings and errors, everything is sent both to stdout and stderr.
+This is intended to redirect stderr to a log file, so full output can be both
+shown on console and logged.
+
 =item B<-f, --file> I<FILE>
 
 Read command line from I<FILE> instead of I</proc/cmdline>
diff --git a/doc/aa-kill.pod b/doc/aa-kill.pod
index 1caeed4..ee61ba9 100644
--- a/doc/aa-kill.pod
+++ b/doc/aa-kill.pod
@@ -4,12 +4,19 @@ aa-kill - Send signals to (almost) all processes
 
 =head1 SYNOPSIS
 
-B<aa-kill> [B<-u>] [B<-t>] [B<-k>] [B<-s>]
+B<aa-kill> [B<-D>] [B<-u>] [B<-t>] [B<-k>] [B<-s>]
 
 =head1 OPTIONS
 
 =over
 
+=item B<-D, --double-output>
+
+Enable double-output mode. Instead of using stdout for regular output, and
+stderr for warnings and errors, everything is sent both to stdout and stderr.
+This is intended to redirect stderr to a log file, so full output can be both
+shown on console and logged.
+
 =item B<-h, --help>
 
 Show help screen and exit.
diff --git a/doc/aa-mount.pod b/doc/aa-mount.pod
index 971670a..11d5ff9 100644
--- a/doc/aa-mount.pod
+++ b/doc/aa-mount.pod
@@ -4,7 +4,7 @@ aa-mount - Mount a filesystem
 
 =head1 SYNOPSIS
 
-B<aa-mount> [B<-B> | B<-M>] [B<-r> | B<-w>] [B<-d>] [B<-t> I<FSTYPE>]
+B<aa-mount> [B<-D>] [B<-B> | B<-M>] [B<-r> | B<-w>] [B<-d>] [B<-t> I<FSTYPE>]
 [B<-o> I<OPTIONS>] I<DEVICE> I<MOUNTPOINT>
 
 =head1 OPTIONS
@@ -20,6 +20,13 @@ e.g:
     aa-mount -B olddir newdir
     aa-mount -o remount,ro,bind olddir newdir
 
+=item B<-D, --double-output>
+
+Enable double-output mode. Instead of using stdout for regular output, and
+stderr for warnings and errors, everything is sent both to stdout and stderr.
+This is intended to redirect stderr to a log file, so full output can be both
+shown on console and logged.
+
 =item B<-d, --mkdir>
 
 Create directory I<MOUNTPOINT> before doing the mount. Note that this only tries
diff --git a/doc/aa-mvlog.pod b/doc/aa-mvlog.pod
index da69fe9..962f55c 100644
--- a/doc/aa-mvlog.pod
+++ b/doc/aa-mvlog.pod
@@ -4,12 +4,19 @@ aa-mvlog - Helper to move & rename log file
 
 =head1 SYNOPSIS
 
-B<aa-mvlog> I<LOGFILE> I<DESTDIR>
+B<aa-mvlog> [B<-D>] I<LOGFILE> I<DESTDIR>
 
 =head1 OPTIONS
 
 =over
 
+=item B<-D, --double-output>
+
+Enable double-output mode. Instead of using stdout for regular output, and
+stderr for warnings and errors, everything is sent both to stdout and stderr.
+This is intended to redirect stderr to a log file, so full output can be both
+shown on console and logged.
+
 =item B<-h, --help>
 
 Show help screen and exit.
diff --git a/doc/aa-pivot.pod b/doc/aa-pivot.pod
index 84706b0..811359a 100644
--- a/doc/aa-pivot.pod
+++ b/doc/aa-pivot.pod
@@ -4,12 +4,19 @@ aa-pivot - Pivot root directory
 
 =head1 SYNOPSIS
 
-B<aa-pivot> I<NEWROOT> I<OLDROOT>
+B<aa-pivot> [B<-D>] I<NEWROOT> I<OLDROOT>
 
 =head1 OPTIONS
 
 =over
 
+=item B<-D, --double-output>
+
+Enable double-output mode. Instead of using stdout for regular output, and
+stderr for warnings and errors, everything is sent both to stdout and stderr.
+This is intended to redirect stderr to a log file, so full output can be both
+shown on console and logged.
+
 =item B<-h, --help>
 
 Show help screen and exit.
diff --git a/doc/aa-reboot.pod b/doc/aa-reboot.pod
index 3294ced..1cff94f 100644
--- a/doc/aa-reboot.pod
+++ b/doc/aa-reboot.pod
@@ -4,12 +4,19 @@ aa-reboot - Reboots, powers off or halts the machine instantly
 
 =head1 SYNOPSIS
 
-B<aa-reboot> B<-r> | B<-p> | B<-H>
+B<aa-reboot> [B<-D>] B<-r> | B<-p> | B<-H>
 
 =head1 OPTIONS
 
 =over
 
+=item B<-D, --double-output>
+
+Enable double-output mode. Instead of using stdout for regular output, and
+stderr for warnings and errors, everything is sent both to stdout and stderr.
+This is intended to redirect stderr to a log file, so full output can be both
+shown on console and logged.
+
 =item B<-H, --halt>
 
 Halts the machine.
diff --git a/doc/aa-service.pod b/doc/aa-service.pod
index 88eaec5..c3ead1f 100644
--- a/doc/aa-service.pod
+++ b/doc/aa-service.pod
@@ -4,12 +4,19 @@ aa-service - Helper for execline script to get service name/instance
 
 =head1 SYNOPSIS
 
-B<aa-service> [B<-l>] I<PROG...>
+B<aa-service> [B<-D>] [B<-l>] I<PROG...>
 
 =head1 OPTIONS
 
 =over
 
+=item B<-D, --double-output>
+
+Enable double-output mode. Instead of using stdout for regular output, and
+stderr for warnings and errors, everything is sent both to stdout and stderr.
+This is intended to redirect stderr to a log file, so full output can be both
+shown on console and logged.
+
 =item B<-h, --help>
 
 Show help screen and exit.
diff --git a/doc/aa-setready.pod b/doc/aa-setready.pod
index 7c8e66a..b461443 100644
--- a/doc/aa-setready.pod
+++ b/doc/aa-setready.pod
@@ -4,26 +4,33 @@ aa-setready - Set a service (un)ready
 
 =head1 SYNOPSIS
 
-B<aa-setready> [B<-U> | B<-D>] I<SERVICEDIR>
+B<aa-setready> [B<-D>] [B<-U> | B<-N>] I<SERVICEDIR>
 
 =head1 OPTIONS
 
 =over
 
-=item B<-U, --ready>
+=item B<-D, --double-output>
 
-Mark the service ready, i.e. create the I<ready> file and emit event 'U' on
-I<event> fifodir. This is the default.
+Enable double-output mode. Instead of using stdout for regular output, and
+stderr for warnings and errors, everything is sent both to stdout and stderr.
+This is intended to redirect stderr to a log file, so full output can be both
+shown on console and logged.
 
 =item B<-h, --help>
 
 Show help screen and exit.
 
-=item B<-D, --unready>
+=item B<-N, --unready>
 
 Mark the service unready, i.e. remove the I<ready> file (if exists) and emit
 event 'D' on I<event> fifodir.
 
+=item B<-U, --ready>
+
+Mark the service ready, i.e. create the I<ready> file and emit event 'U' on
+I<event> fifodir. This is the default.
+
 =item B<-V, --version>
 
 Show version information and exit.
diff --git a/doc/aa-test.pod b/doc/aa-test.pod
index db0a1e4..e212a82 100644
--- a/doc/aa-test.pod
+++ b/doc/aa-test.pod
@@ -4,8 +4,8 @@ aa-test - Test file types
 
 =head1 SYNOPSIS
 
-B<aa-test> [B<-b> | B<-d> | B<-e> | B<-f> | B<-L> | B<-p> | B<-S> | B<-r> |
-B<-w> | B<-x>] [B<-R> [I<TIMES>]] I<FILE>
+B<aa-test> [B<-D>] [B<-b> | B<-d> | B<-e> | B<-f> | B<-L> | B<-p> | B<-S> |
+B<-r> | B<-w> | B<-x>] [B<-R> [I<TIMES>]] I<FILE>
 
 =head1 OPTIONS
 
@@ -15,6 +15,13 @@ B<-w> | B<-x>] [B<-R> [I<TIMES>]] I<FILE>
 
 Test whether I<FILE> exists and is a block special
 
+=item B<-D, --double-output>
+
+Enable double-output mode. Instead of using stdout for regular output, and
+stderr for warnings and errors, everything is sent both to stdout and stderr.
+This is intended to redirect stderr to a log file, so full output can be both
+shown on console and logged.
+
 =item B<-d, --directory>
 
 Test whether I<FILE> exists and is a directory
diff --git a/doc/aa-tty.pod b/doc/aa-tty.pod
index ee8d16d..ddbe543 100644
--- a/doc/aa-tty.pod
+++ b/doc/aa-tty.pod
@@ -4,12 +4,19 @@ aa-tty - Prints the device name of the active tty
 
 =head1 SYNOPSIS
 
-B<aa-tty>
+B<aa-tty> [B<-D>]
 
 =head1 OPTIONS
 
 =over
 
+=item B<-D, --double-output>
+
+Enable double-output mode. Instead of using stdout for regular output, and
+stderr for warnings and errors, everything is sent both to stdout and stderr.
+This is intended to redirect stderr to a log file, so full output can be both
+shown on console and logged.
+
 =item B<-h, --help>
 
 Show help screen and exit.
diff --git a/doc/aa-umount.pod b/doc/aa-umount.pod
index 4246a0d..70ee992 100644
--- a/doc/aa-umount.pod
+++ b/doc/aa-umount.pod
@@ -4,12 +4,19 @@ aa-umount - Unmount a filesystem
 
 =head1 SYNOPSIS
 
-B<aa-umount> [B<-f> | B<-l>] I<MOUNTPOINT>
+B<aa-umount> [B<-D>] [B<-f> | B<-l>] I<MOUNTPOINT>
 
 =head1 OPTIONS
 
 =over
 
+=item B<-D, --double-output>
+
+Enable double-output mode. Instead of using stdout for regular output, and
+stderr for warnings and errors, everything is sent both to stdout and stderr.
+This is intended to redirect stderr to a log file, so full output can be both
+shown on console and logged.
+
 =item B<-f, --force>
 
 Force unmount even if busy (only for NFS mounts). This can cause data loss.
diff --git a/src/scripts/aa-stage0 b/src/scripts/aa-stage0
index bec91e5..87e8b2b 100755
--- a/src/scripts/aa-stage0
+++ b/src/scripts/aa-stage0
@@ -45,10 +45,10 @@ umask 022
 # Start services
 foreground { if -n
 {
-  if { emptyenv -c s6-setsid aa-ctty -s aa-start -D -r /services -l onboot }
+  if { emptyenv -c s6-setsid aa-ctty -Ds aa-start -D -r /services -l onboot }
   foreground {
     # if "break" was specified on kernel cmdline, let's open a shell
-    if -t { aa-incmdline -qf /root-fs/proc/cmdline break }
+    if -t { aa-incmdline -Dqf /root-fs/proc/cmdline break }
     foreground { aa-echo -DB "Break requested" }
     foreground { aa-echo -Dt "Trying to open a shell; " +g exit +w " to continue" }
     emptyenv -c sh -i
@@ -66,7 +66,7 @@ emptyenv -c sh -i
 if { aa-echo -DB "Moving /root-fs to /..." }
 # First we mount bind the rootfs (initramfs) onto /run/initramfs so we can come
 # back to it for stage 4
-if { aa-mount -Bd / /root-fs/run/initramfs }
+if { aa-mount -DBd / /root-fs/run/initramfs }
 fdmove -c 2 1
 backtick -n -D /sbin/init INIT { aa-incmdline -rf /root-fs/proc/cmdline init }
 import -u INIT
diff --git a/src/scripts/aa-stage1 b/src/scripts/aa-stage1
index b0bec89..d8f4170 100755
--- a/src/scripts/aa-stage1
+++ b/src/scripts/aa-stage1
@@ -47,7 +47,7 @@ foreground { emptyenv -c
 aa-enable -Dl /etc/anopa/enabled -k uncaught-logs -f @LIBEXECDIR@/aa-stage3 }
 
 # Make sure the FIFO needed for the switch to stage 2 is there
-ifelse -X -n { aa-test -p /run/services/.scandir/uncaught-logs/fifo }
+ifelse -X -n { aa-test -Dp /run/services/.scandir/uncaught-logs/fifo }
 {
     foreground { aa-echo -DBe "Cannot start s6-svscan: No uncaught-logs fifo found" }
     fdmove -c 2 1
diff --git a/src/scripts/aa-stage2 b/src/scripts/aa-stage2
index f970662..4b2ac3d 100755
--- a/src/scripts/aa-stage2
+++ b/src/scripts/aa-stage2
@@ -43,12 +43,12 @@ if -n -t
   redirfd -w 1 /dev/console
   # And start everything
   foreground { aa-echo -DB "Stage 2: Initializing system..." }
-  backtick -n -D onboot LISTDIR { aa-incmdline -rs aa }
+  backtick -n -D onboot LISTDIR { aa-incmdline -Drs aa }
   import -u LISTDIR
   # We have a tty in stdin, become session leader and set controlling terminal.
   # This is so Ctrl+C will trigger a SIGINT to aa-start, so one can manually
   # timeout a service.
-  if { emptyenv -c s6-setsid aa-ctty aa-start -D -l /etc/anopa/listdirs/${LISTDIR} }
+  if { emptyenv -c s6-setsid aa-ctty -D aa-start -D -l /etc/anopa/listdirs/${LISTDIR} }
   foreground { aa-echo -DB "System ready." }
   # close logger
   fdmove -c 2 1
diff --git a/src/scripts/aa-stage3 b/src/scripts/aa-stage3
index 017efcb..f93b89d 100755
--- a/src/scripts/aa-stage3
+++ b/src/scripts/aa-stage3
@@ -44,7 +44,7 @@ foreground { aa-echo -DB "Stage 3: Preparing ${1}..." }
 # Stop all running services -- s6-svscan did only exec into us, leaving the
 # whole supervised tree intact. Here we stop everything (longrun & oneshot) in
 # order.
-foreground { emptyenv -c s6-setsid aa-ctty -s aa-stop -D -ak uncaught-logs }
+foreground { emptyenv -c s6-setsid aa-ctty -Ds aa-stop -D -ak uncaught-logs }
 # We left the catch-all running (in case), make sure everything will exit
 # properly when we send TERM
 foreground { s6-svc -x /run/services/uncaught-logs }
@@ -52,7 +52,7 @@ foreground { s6-svc -x /run/services/uncaught-logs }
 # Kill everything left
 foreground { aa-echo -DB "Killing remaining processes..." }
 foreground { aa-echo -Dt "Sending SIGTERM to all processes..." }
-foreground { aa-kill -st }
+foreground { aa-kill -Dst }
 wait -r { } # Reap zombies
 # logger was killed, and we won't open it back
 fdmove -c 2 1
diff --git a/src/utils/aa-chroot.c b/src/utils/aa-chroot.c
index ac84ed3..4d6a3e5 100644
--- a/src/utils/aa-chroot.c
+++ b/src/utils/aa-chroot.c
@@ -32,6 +32,7 @@ static void
 dieusage (int rc)
 {
     aa_die_usage (rc, "NEWROOT COMMAND [ARG...]",
+            " -D, --double-output           Enable double-output mode\n"
             " -h, --help                    Show this help screen and exit\n"
             " -V, --version                 Show version information and exit\n"
             );
@@ -45,17 +46,22 @@ main (int argc, char * const argv[], char * const envp[])
     for (;;)
     {
         struct option longopts[] = {
+            { "double-output",      no_argument,        NULL,   'D' },
             { "help",               no_argument,        NULL,   'h' },
             { "version",            no_argument,        NULL,   'V' },
             { NULL, 0, 0, 0 }
         };
         int c;
 
-        c = getopt_long (argc, argv, "hV", longopts, NULL);
+        c = getopt_long (argc, argv, "DhV", longopts, NULL);
         if (c == -1)
             break;
         switch (c)
         {
+            case 'D':
+                aa_set_double_output (1);
+                break;
+
             case 'h':
                 dieusage (0);
 
diff --git a/src/utils/aa-ctty.c b/src/utils/aa-ctty.c
index 2ef7f14..4b4a6c8 100644
--- a/src/utils/aa-ctty.c
+++ b/src/utils/aa-ctty.c
@@ -32,6 +32,7 @@ static void
 dieusage (int rc)
 {
     aa_die_usage (rc, "[OPTION...] PROG...",
+            " -D, --double-output           Enable double-output mode\n"
             " -f, --fd=FD                   Use FD as terminal (Default: 0)\n"
             " -s, --steal                   Steal terminal from other session if needed\n"
             " -h, --help                    Show this help screen and exit\n"
@@ -49,6 +50,7 @@ main (int argc, char * const argv[], char const * const *envp)
     for (;;)
     {
         struct option longopts[] = {
+            { "double-output",      no_argument,        NULL,   'D' },
             { "fd",                 required_argument,  NULL,   'f' },
             { "help",               no_argument,        NULL,   'h' },
             { "steal",              no_argument,        NULL,   's' },
@@ -57,11 +59,15 @@ main (int argc, char * const argv[], char const * const *envp)
         };
         int c;
 
-        c = getopt_long (argc, argv, "+f:hsV", longopts, NULL);
+        c = getopt_long (argc, argv, "+Df:hsV", longopts, NULL);
         if (c == -1)
             break;
         switch (c)
         {
+            case 'D':
+                aa_set_double_output (1);
+                break;
+
             case 'f':
                 if (!uint0_scan (optarg, &fd))
                     aa_strerr_diefu1sys (1, "set fd");
diff --git a/src/utils/aa-incmdline.c b/src/utils/aa-incmdline.c
index ea007f4..8bc27ca 100644
--- a/src/utils/aa-incmdline.c
+++ b/src/utils/aa-incmdline.c
@@ -32,6 +32,7 @@ static void
 dieusage (int rc)
 {
     aa_die_usage (rc, "[OPTION] NAME",
+            " -D, --double-output           Enable double-output mode\n"
             " -f, --file FILE               Use FILE instead of /proc/cmdline\n"
             " -q, --quiet                   Don't write value (if any) to stdout\n"
             " -s, --safe[=C]                Ignore argument if value contain C (default: '/')\n"
@@ -57,6 +58,7 @@ main (int argc, char * const argv[])
     for (;;)
     {
         struct option longopts[] = {
+            { "double-output",      no_argument,        NULL,   'D' },
             { "file",               no_argument,        NULL,   'f' },
             { "help",               no_argument,        NULL,   'h' },
             { "quiet",              no_argument,        NULL,   'q' },
@@ -67,11 +69,15 @@ main (int argc, char * const argv[])
         };
         int c;
 
-        c = getopt_long (argc, argv, "f:hqrs::V", longopts, NULL);
+        c = getopt_long (argc, argv, "Df:hqrs::V", longopts, NULL);
         if (c == -1)
             break;
         switch (c)
         {
+            case 'D':
+                aa_set_double_output (1);
+                break;
+
             case 'f':
                 file = optarg;
                 break;
@@ -154,8 +160,8 @@ main (int argc, char * const argv[])
                     return 3;
                 else if (!quiet)
                 {
-                    buffer_putnoflush (buffer_1small, sa.s + start, len);
-                    buffer_putsflush (buffer_1small, "\n");
+                    aa_bb_noflush (AA_OUT, sa.s + start, len);
+                    aa_bs_flush (AA_OUT, "\n");
                 }
                 return 0;
             }
diff --git a/src/utils/aa-kill.c b/src/utils/aa-kill.c
index cc631d6..d7ec8a6 100644
--- a/src/utils/aa-kill.c
+++ b/src/utils/aa-kill.c
@@ -43,7 +43,6 @@ static struct {
 static char ownpid[UINT_FMT];
 
 #if 0
-#include <skalibs/buffer.h>
 static void _kill (pid_t pid, int sig)
 {
     char buf[UINT_FMT];
@@ -51,14 +50,14 @@ static void _kill (pid_t pid, int sig)
 
     u = pid;
     buf[uint_fmt (buf, u)] = 0;
-    buffer_putsnoflush (buffer_1small, "kill(");
+    aa_bs_noflush (AA_OUT, "kill(");
     if (u == (unsigned int) -1)
-        buffer_putsnoflush (buffer_1small, "-1");
+        aa_bs_noflush (AA_OUT, "-1");
     else
-        buffer_putsnoflush (buffer_1small, buf);
-    buffer_putsnoflush (buffer_1small, ",");
-    buffer_putsnoflush (buffer_1small, sig_name (sig));
-    buffer_putsflush (buffer_1small, ")\n");
+        aa_bs_noflush (AA_OUT, buf);
+    aa_bs_noflush (AA_OUT, ",");
+    aa_bs_noflush (AA_OUT, sig_name (sig));
+    aa_bs_flush (AA_OUT, ")\n");
 }
 #else
 #define _kill(pid,sig)  kill (pid, sig)
@@ -117,6 +116,7 @@ static void
 dieusage (int rc)
 {
     aa_die_usage (rc, "[OPTION...]",
+            " -D, --double-output           Enable double-output mode\n"
             " -u, --hup                     Send SIGHUP\n"
             " -t, --term                    Send SIGTERM then SIGCONT\n"
             " -k, --kill                    Send SIGKILL\n"
@@ -134,6 +134,7 @@ main (int argc, char * const argv[])
     for (;;)
     {
         struct option longopts[] = {
+            { "double-output",      no_argument,        NULL,   'D' },
             { "help",               no_argument,        NULL,   'h' },
             { "kill",               no_argument,        NULL,   'k' },
             { "skip-at",            no_argument,        NULL,   's' },
@@ -144,11 +145,15 @@ main (int argc, char * const argv[])
         };
         int c;
 
-        c = getopt_long (argc, argv, "hkstuV", longopts, NULL);
+        c = getopt_long (argc, argv, "DhkstuV", longopts, NULL);
         if (c == -1)
             break;
         switch (c)
         {
+            case 'D':
+                aa_set_double_output (1);
+                break;
+
             case 'h':
                 dieusage (0);
 
diff --git a/src/utils/aa-mount.c b/src/utils/aa-mount.c
index 96c70dc..ef39c32 100644
--- a/src/utils/aa-mount.c
+++ b/src/utils/aa-mount.c
@@ -124,6 +124,7 @@ static void
 dieusage (int rc)
 {
     aa_die_usage (rc, "[OPTION...] DEVICE MOUNTPOINT",
+            " -D, --double-output           Enable double-output mode\n"
             " -B, --bind                    Remount a subtree somewhere else\n"
             " -M, --move                    Move a subtree to some other place\n"
             " -t, --type FSTYPE             Use FSTYPE as type of filesystem\n"
@@ -149,6 +150,7 @@ main (int argc, char * const argv[])
     {
         struct option longopts[] = {
             { "bind",               no_argument,        NULL,   'B' },
+            { "double-output",      no_argument,        NULL,   'D' },
             { "mkdir",              no_argument,        NULL,   'd' },
             { "help",               no_argument,        NULL,   'h' },
             { "move",               no_argument,        NULL,   'M' },
@@ -161,7 +163,7 @@ main (int argc, char * const argv[])
         };
         int c;
 
-        c = getopt_long (argc, argv, "BdhMo:rt:Vw", longopts, NULL);
+        c = getopt_long (argc, argv, "BDdhMo:rt:Vw", longopts, NULL);
         if (c == -1)
             break;
         switch (c)
@@ -171,6 +173,10 @@ main (int argc, char * const argv[])
                     aa_strerr_diefu1sys (2, "build user options");
                 break;
 
+            case 'D':
+                aa_set_double_output (1);
+                break;
+
             case 'd':
                 mk = 1;
                 break;
diff --git a/src/utils/aa-mvlog.c b/src/utils/aa-mvlog.c
index e6800fb..7cfd515 100644
--- a/src/utils/aa-mvlog.c
+++ b/src/utils/aa-mvlog.c
@@ -20,6 +20,7 @@
  * anopa. If not, see http://www.gnu.org/licenses/
  */
 
+#include <getopt.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <skalibs/djbunix.h>
@@ -32,6 +33,7 @@ static void
 dieusage (int rc)
 {
     aa_die_usage (rc, "[OPTION] LOGFILE DESTDIR",
+            " -D, --double-output           Enable double-output mode\n"
             " -h, --help                    Show this help screen and exit\n"
             " -V, --version                 Show version information and exit\n"
             );
@@ -43,46 +45,71 @@ main (int argc, char * const argv[])
     PROG = "aa-mvlog";
     struct stat st;
 
-    if (argc == 2)
+    for (;;)
     {
-        if (str_equal (argv[1], "-V") || str_equal (argv[1], "--version"))
-            aa_die_version ();
-        else if (str_equal (argv[1], "-h") || str_equal (argv[1], "--help"))
-            dieusage (0);
+        struct option longopts[] = {
+            { "double-output",      no_argument,        NULL,   'D' },
+            { "help",               no_argument,        NULL,   'h' },
+            { "version",            no_argument,        NULL,   'V' },
+            { NULL, 0, 0, 0 }
+        };
+        int c;
+
+        c = getopt_long (argc, argv, "DhV", longopts, NULL);
+        if (c == -1)
+            break;
+        switch (c)
+        {
+            case 'D':
+                aa_set_double_output (1);
+                break;
+
+            case 'h':
+                dieusage (0);
+
+            case 'V':
+                aa_die_version ();
+
+            default:
+                dieusage (1);
+        }
     }
-    if (argc != 3)
+    argc -= optind;
+    argv += optind;
+
+    if (argc != 2)
         dieusage (1);
 
-    if (stat (argv[1], &st) < 0)
-        aa_strerr_diefu2sys (2, "stat ", argv[1]);
+    if (stat (argv[0], &st) < 0)
+        aa_strerr_diefu2sys (2, "stat ", argv[0]);
     else if (!S_ISREG (st.st_mode))
-        aa_strerr_dief2x (2, argv[1], ": not a file");
+        aa_strerr_dief2x (2, argv[0], ": not a file");
 
     {
-        int l = strlen (argv[2]);
+        int l = strlen (argv[1]);
         char newname[l + 27];
         char target[26];
 
-        byte_copy (newname, l, argv[2]);
+        byte_copy (newname, l, argv[1]);
         newname[l] = '/';
-        if (openreadnclose (argv[1], newname + l + 1, 25) != 25)
-            aa_strerr_diefu2sys (2, "read new name from ", argv[1]);
+        if (openreadnclose (argv[0], newname + l + 1, 25) != 25)
+            aa_strerr_diefu2sys (2, "read new name from ", argv[0]);
         if (newname[l + 1] != '@'
                 || byte_chr (newname + l + 1, 25, '/') < 25
                 || byte_chr (newname + l + 1, 25, '\0') < 25)
-            aa_strerr_dief2x (2, "invalid new name read from ", argv[1]);
+            aa_strerr_dief2x (2, "invalid new name read from ", argv[0]);
         newname[l + 26] = '\0';
 
-        if (aa_copy_file (argv[1], newname, st.st_mode, AA_CP_CREATE) < 0)
-            aa_strerr_diefu4sys (2, "copy ", argv[1], " as ", newname);
+        if (aa_copy_file (argv[0], newname, st.st_mode, AA_CP_CREATE) < 0)
+            aa_strerr_diefu4sys (2, "copy ", argv[0], " as ", newname);
 
         byte_copy (target, 26, newname + l + 1);
         byte_copy (newname + l + 1, 8, "current");
         unlink (newname);
         if (symlink (target, newname) < 0)
             aa_strerr_warnu2sys ("create symlink ", newname);
-        if (unlink (argv[1]) < 0)
-            aa_strerr_warnu2sys ("remove source file ", argv[1]);
+        if (unlink (argv[0]) < 0)
+            aa_strerr_warnu2sys ("remove source file ", argv[0]);
     }
 
     return 0;
diff --git a/src/utils/aa-pivot.c b/src/utils/aa-pivot.c
index 26b8e69..8045476 100644
--- a/src/utils/aa-pivot.c
+++ b/src/utils/aa-pivot.c
@@ -34,6 +34,7 @@ static void
 dieusage (int rc)
 {
     aa_die_usage (rc, "NEWROOT OLDROOT",
+            " -D, --double-output           Enable double-output mode\n"
             " -h, --help                    Show this help screen and exit\n"
             " -V, --version                 Show version information and exit\n"
             );
@@ -47,17 +48,22 @@ main (int argc, char * const argv[])
     for (;;)
     {
         struct option longopts[] = {
+            { "double-output",      no_argument,        NULL,   'D' },
             { "help",               no_argument,        NULL,   'h' },
             { "version",            no_argument,        NULL,   'V' },
             { NULL, 0, 0, 0 }
         };
         int c;
 
-        c = getopt_long (argc, argv, "hV", longopts, NULL);
+        c = getopt_long (argc, argv, "DhV", longopts, NULL);
         if (c == -1)
             break;
         switch (c)
         {
+            case 'D':
+                aa_set_double_output (1);
+                break;
+
             case 'h':
                 dieusage (0);
 
diff --git a/src/utils/aa-reboot.c b/src/utils/aa-reboot.c
index 533882a..51837ca 100644
--- a/src/utils/aa-reboot.c
+++ b/src/utils/aa-reboot.c
@@ -30,6 +30,7 @@ static void
 dieusage (int rc)
 {
     aa_die_usage (rc, "OPTION",
+            " -D, --double-output           Enable double-output mode\n"
             " -r, --reboot                  Reboot the machine NOW\n"
             " -H, --halt                    Halt the machine NOW\n"
             " -p, --poweroff                Power off the machine NOW\n"
@@ -56,6 +57,7 @@ main (int argc, char * const argv[])
     for (;;)
     {
         struct option longopts[] = {
+            { "double-output",      no_argument,        NULL,   'D' },
             { "halt",               no_argument,        NULL,   'H' },
             { "help",               no_argument,        NULL,   'h' },
             { "poweroff",           no_argument,        NULL,   'p' },
@@ -65,11 +67,15 @@ main (int argc, char * const argv[])
         };
         int c;
 
-        c = getopt_long (argc, argv, "HhprV", longopts, NULL);
+        c = getopt_long (argc, argv, "DHhprV", longopts, NULL);
         if (c == -1)
             break;
         switch (c)
         {
+            case 'D':
+                aa_set_double_output (1);
+                break;
+
             case 'H':
                 i = 0;
                 break;
diff --git a/src/utils/aa-service.c b/src/utils/aa-service.c
index 2e603b0..3bfd229 100644
--- a/src/utils/aa-service.c
+++ b/src/utils/aa-service.c
@@ -20,6 +20,7 @@
  * anopa. If not, see http://www.gnu.org/licenses/
  */
 
+#include <getopt.h>
 #include <unistd.h>
 #include <skalibs/djbunix.h>
 #include <skalibs/env.h>
@@ -161,7 +162,10 @@ static void
 dieusage (int rc)
 {
     aa_die_usage (rc, "[OPTION] PROG...",
+            " -D, --double-output           Enable double-output mode\n"
             " -l, --log                     Use parent directory as servicedir\n"
+            " -h, --help                    Show this help screen and exit\n"
+            " -V, --version                 Show version information and exit\n"
             );
 }
 
@@ -174,23 +178,42 @@ main (int argc, char const **argv, char const *const *envp)
     stralloc dst = STRALLOC_ZERO;
     int r;
 
-    if (argc > 1 && *argv[1] == '-')
+    for (;;)
     {
-        if (str_equal (argv[1], "-h") || str_equal (argv[1], "--help"))
-            dieusage (0);
-        else if (str_equal (argv[1], "-l") || str_equal (argv[1], "--log"))
+        struct option longopts[] = {
+            { "double-output",      no_argument,        NULL,   'D' },
+            { "help",               no_argument,        NULL,   'h' },
+            { "log",                no_argument,        NULL,   'l' },
+            { "version",            no_argument,        NULL,   'V' },
+            { NULL, 0, 0, 0 }
+        };
+        int c;
+
+        c = getopt_long (argc, (char * const *) argv, "+DhlV", longopts, NULL);
+        if (c == -1)
+            break;
+        switch (c)
         {
-            islog = 1;
-            --argc;
-            ++argv;
+            case 'D':
+                aa_set_double_output (1);
+                break;
+
+            case 'h':
+                dieusage (0);
+
+            case 'l':
+                islog = 1;
+                break;
+
+            case 'V':
+                aa_die_version ();
+
+            default:
+                dieusage (1);
         }
-        else if (str_equal (argv[1], "-V") || str_equal (argv[1], "--version"))
-            aa_die_version ();
-        else
-            dieusage (1);
     }
-    --argc;
-    ++argv;
+    argc -= optind;
+    argv += optind;
 
     r = aa_service (&info);
     if (r < 0)
diff --git a/src/utils/aa-setready.c b/src/utils/aa-setready.c
index aa91424..bc985f2 100644
--- a/src/utils/aa-setready.c
+++ b/src/utils/aa-setready.c
@@ -33,8 +33,9 @@ static void
 dieusage (int rc)
 {
     aa_die_usage (rc, "[OPTION] SERVICEDIR",
+            " -D, --double-output           Enable double-output mode\n"
             " -U, --ready                   Mark service ready; This is the default.\n"
-            " -D, --unready                 Mark service not ready\n"
+            " -N, --unready                 Mark service not ready\n"
             "\n"
             " -h, --help                    Show this help screen and exit\n"
             " -V, --version                 Show version information and exit\n"
@@ -51,26 +52,31 @@ main (int argc, char * const argv[])
     for (;;)
     {
         struct option longopts[] = {
-            { "unready",            no_argument,        NULL,   'D' },
+            { "double-output",      no_argument,        NULL,   'D' },
             { "help",               no_argument,        NULL,   'h' },
+            { "unready",            no_argument,        NULL,   'N' },
             { "ready",              no_argument,        NULL,   'U' },
             { "version",            no_argument,        NULL,   'V' },
             { NULL, 0, 0, 0 }
         };
         int c;
 
-        c = getopt_long (argc, argv, "DhUV", longopts, NULL);
+        c = getopt_long (argc, argv, "DhNUV", longopts, NULL);
         if (c == -1)
             break;
         switch (c)
         {
             case 'D':
-                ready = 0;
+                aa_set_double_output (1);
                 break;
 
             case 'h':
                 dieusage (0);
 
+            case 'N':
+                ready = 0;
+                break;
+
             case 'U':
                 ready = 1;
                 break;
diff --git a/src/utils/aa-test.c b/src/utils/aa-test.c
index c4ffd1b..49154a7 100644
--- a/src/utils/aa-test.c
+++ b/src/utils/aa-test.c
@@ -52,6 +52,7 @@ static void
 dieusage (int rc)
 {
     aa_die_usage (rc, "OPTION FILE",
+            " -D, --double-output           Enable double-output mode\n"
             " -b, --block                   Test whether FILE is a block special\n"
             " -d, --directory               Test whether FILE is a directory\n"
             " -e, --exists                  Test whether FILE exists\n"
@@ -83,6 +84,7 @@ main (int argc, char * const argv[])
     {
         struct option longopts[] = {
             { "block",              no_argument,        NULL,   'b' },
+            { "double-output",      no_argument,        NULL,   'D' },
             { "directory",          no_argument,        NULL,   'd' },
             { "exists",             no_argument,        NULL,   'e' },
             { "file",               no_argument,        NULL,   'f' },
@@ -99,7 +101,7 @@ main (int argc, char * const argv[])
         };
         int c;
 
-        c = getopt_long (argc, argv, "bdefhLprR::SVwx", longopts, NULL);
+        c = getopt_long (argc, argv, "bDdefhLprR::SVwx", longopts, NULL);
         if (c == -1)
             break;
         switch (c)
@@ -117,6 +119,10 @@ main (int argc, char * const argv[])
                 test = c;
                 break;
 
+            case 'D':
+                aa_set_double_output (1);
+                break;
+
             case 'h':
                 dieusage (0);
 
diff --git a/src/utils/aa-tty.c b/src/utils/aa-tty.c
index 0d26885..88f8acd 100644
--- a/src/utils/aa-tty.c
+++ b/src/utils/aa-tty.c
@@ -20,6 +20,7 @@
  * anopa. If not, see http://www.gnu.org/licenses/
  */
 
+#include <getopt.h>
 #include <errno.h>
 #include <skalibs/bytestr.h>
 #include <skalibs/djbunix.h>
@@ -33,6 +34,7 @@ static void
 dieusage (int rc)
 {
     aa_die_usage (rc, "",
+            " -D, --double-output           Enable double-output mode\n"
             " -h, --help                    Show this help screen and exit\n"
             " -V, --version                 Show version information and exit\n"
             );
@@ -47,16 +49,39 @@ main (int argc, char * const argv[])
     char name[max];
     int r;
 
-    if (argc == 2)
+    for (;;)
     {
-        if (str_equal (argv[1], "-h") || str_equal (argv[1], "--help"))
-            dieusage (0);
-        else if (str_equal (argv[1], "-V") || str_equal (argv[1], "--version"))
-            aa_die_version ();
-        else
-            dieusage (1);
+        struct option longopts[] = {
+            { "double-output",      no_argument,        NULL,   'D' },
+            { "help",               no_argument,        NULL,   'h' },
+            { "version",            no_argument,        NULL,   'V' },
+            { NULL, 0, 0, 0 }
+        };
+        int c;
+
+        c = getopt_long (argc, argv, "DhV", longopts, NULL);
+        if (c == -1)
+            break;
+        switch (c)
+        {
+            case 'D':
+                aa_set_double_output (1);
+                break;
+
+            case 'h':
+                dieusage (0);
+
+            case 'V':
+                aa_die_version ();
+
+            default:
+                dieusage (1);
+        }
     }
-    else if (argc != 1)
+    argc -= optind;
+    argv += optind;
+
+    if (argc != 0)
         dieusage (1);
 
     byte_copy (file, sizeof (PREFIX) - 1, PREFIX);
diff --git a/src/utils/aa-umount.c b/src/utils/aa-umount.c
index a7548c6..ac0f57b 100644
--- a/src/utils/aa-umount.c
+++ b/src/utils/aa-umount.c
@@ -33,6 +33,7 @@ static void
 dieusage (int rc)
 {
     aa_die_usage (rc, "[OPTIONS...] MOUNTPOINT",
+            " -D, --double-output           Enable double-output mode\n"
             " -f, --force                   Force unmount even if busy (NFS only)\n"
             " -l, --lazy                    Perform lazy unmounting\n"
             " -h, --help                    Show this help screen and exit\n"
@@ -49,6 +50,7 @@ main (int argc, char * const argv[])
     for (;;)
     {
         struct option longopts[] = {
+            { "double-output",      no_argument,        NULL,   'D' },
             { "force",              no_argument,        NULL,   'f' },
             { "help",               no_argument,        NULL,   'h' },
             { "lazy",               no_argument,        NULL,   'l' },
@@ -57,11 +59,15 @@ main (int argc, char * const argv[])
         };
         int c;
 
-        c = getopt_long (argc, argv, "fhlV", longopts, NULL);
+        c = getopt_long (argc, argv, "DfhlV", longopts, NULL);
         if (c == -1)
             break;
         switch (c)
         {
+            case 'D':
+                aa_set_double_output (1);
+                break;
+
             case 'f':
                 flags = MNT_FORCE;
                 break;