summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregor Kleen <gkleen@yggdrasil.li>2018-04-05 22:05:05 +0200
committerGregor Kleen <gkleen@yggdrasil.li>2018-04-05 22:05:05 +0200
commitaf359b71b000651812e1ee70638b480502eba0ec (patch)
tree8f246fa120b54c29f3bdf64e8e3b389ec5311851
parentfbc53fdb0e012524b1a22083d19a6928cc87870e (diff)
downloadnixos-af359b71b000651812e1ee70638b480502eba0ec.tar
nixos-af359b71b000651812e1ee70638b480502eba0ec.tar.gz
nixos-af359b71b000651812e1ee70638b480502eba0ec.tar.bz2
nixos-af359b71b000651812e1ee70638b480502eba0ec.tar.xz
nixos-af359b71b000651812e1ee70638b480502eba0ec.zip
media-server on odin
-rw-r--r--custom/uucp-mediaserver.nix59
-rw-r--r--custom/uucp-mediaserver/scripts.nix32
-rwxr-xr-xcustom/uucp-mediaserver/scripts/mediaspace9
-rwxr-xr-xcustom/uucp-mediaserver/scripts/queue134
-rwxr-xr-xcustom/uucp-mediaserver/scripts/queuesize24
-rwxr-xr-xcustom/uucp-mediaserver/scripts/queuestatus41
-rwxr-xr-xcustom/uucp-mediaserver/scripts/update-queuesize10
-rw-r--r--odin.nix8
-rw-r--r--users/gkleen.nix2
9 files changed, 318 insertions, 1 deletions
diff --git a/custom/uucp-mediaserver.nix b/custom/uucp-mediaserver.nix
new file mode 100644
index 00000000..a8af8bc6
--- /dev/null
+++ b/custom/uucp-mediaserver.nix
@@ -0,0 +1,59 @@
1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.uucp.media-server;
7
8 touchStateFiles = name: ''
9 touch ${cfg.queueDir}/${name}.queue
10 touch ${cfg.queueDir}/${name}.space
11 touch ${cfg.queueDir}/${name}.queuesize
12
13 chown ${cfg.owner}:${cfg.group} ${cfg.queueDir}/${name}.queue ${cfg.queueDir}/${name}.space ${cfg.queueDir}/${name}.queuesize
14 '';
15in {
16 options = {
17 services.uucp.media-server = {
18 enable = mkEnableOption "UUCP media server";
19
20 remoteNodes = mkOption {
21 type = types.listOf types.str;
22 default = [];
23 description = ''
24 Clients to track
25 '';
26 };
27
28 queueDir = mkOption {
29 type = types.path;
30 default = "/var/spool/media";
31 description = "Queue directory";
32 };
33
34 owner = mkOption {
35 type = types.str;
36 default = "root";
37 description = "Owner of the various queue files";
38 };
39
40 group = mkOption {
41 type = types.str;
42 default = "media";
43 description = "Group of the various queue files";
44 };
45 };
46 };
47
48 config = mkIf cfg.enable {
49 system.activationScripts."uucp-media-server" = ''
50 mkdir -p ${cfg.queueDir}
51 chmod 750 ${cfg.queueDir}
52 chown ${cfg.owner}:${cfg.group} ${cfg.queueDir}
53
54 ${concatStringsSep "\n" (map touchStateFiles cfg.remoteNodes)}
55 '';
56
57 environment.systemPackages = [ (pkgs.callPackage ./uucp-mediaserver/scripts.nix { config = cfg; }) ];
58 };
59}
diff --git a/custom/uucp-mediaserver/scripts.nix b/custom/uucp-mediaserver/scripts.nix
new file mode 100644
index 00000000..21eab6de
--- /dev/null
+++ b/custom/uucp-mediaserver/scripts.nix
@@ -0,0 +1,32 @@
1{ stdenv, zsh, config }:
2
3let
4 mkSymlinks = name: ''
5 ln -s $out/libexec/mediaspace $out/bin/mediaspace.${name}
6 ln -s $out/libexec/queue $out/bin/queue.${name}
7 ln -s $out/libexec/queuesize $out/bin/queuesize.${name}
8 ln -s $out/libexec/queuestatus $out/bin/queuestatus.${name}
9 ln -s $out/libexec/update-queuesize $out/bin/update-queuesize.${name}
10 '';
11in stdenv.mkDerivation {
12 name = "uucp-mediaserver";
13 src = ./scripts;
14
15 phases = [ "installPhase" ];
16
17 inherit (config) queueDir;
18
19 installPhase = ''
20 mkdir -p $out/libexec
21
22 substituteFile $src/mediaspace $out/libexec/mediaspace
23 substituteFile $src/queue $out/libexec/queue
24 substituteFile $src/queuesize $out/libexec/queuesize
25 substituteFile $src/queuestatus $out/libexec/queuestatus
26 substituteFile $src/update-queuesize $out/libexec/update-queuesize
27
28 mkdir -p $out/bin
29
30 ${concatStringsSep "\n" (map mkSymlinks config.remoteNodes)}
31 '';
32}
diff --git a/custom/uucp-mediaserver/scripts/mediaspace b/custom/uucp-mediaserver/scripts/mediaspace
new file mode 100755
index 00000000..5d636a53
--- /dev/null
+++ b/custom/uucp-mediaserver/scripts/mediaspace
@@ -0,0 +1,9 @@
1#!@zsh@/bin/zsh
2
3base=$(basename $0)
4suffix=${base##*.}
5
6printf "%d\n" "$1" > @queueDir@/mediaspace.$suffix
7echo > @queueDir@/queuesize.$suffix
8update-queuesize.$suffix
9
diff --git a/custom/uucp-mediaserver/scripts/queue b/custom/uucp-mediaserver/scripts/queue
new file mode 100755
index 00000000..0039b3b8
--- /dev/null
+++ b/custom/uucp-mediaserver/scripts/queue
@@ -0,0 +1,134 @@
1#!@zsh@/bin/zsh
2
3logTag=${0:t}
4exec 1> >(logger -t "$logTag" -p news.notice)
5exec 2> >(logger -t "$logTag" -p news.error)
6
7doDebug=false
8debug() {
9 if $doDebug; then
10 logger -t "$logTag" -p news.debug
11 else
12 cat >/dev/null
13 fi
14}
15verbose() { $@ | debug }
16
17function mungefilename() {
18 print ${@} | tr -s $';&*|<> \t!_' '_'
19}
20
21typeset -a cleanupCmds
22cleanupCmds=()
23
24function doCleanup {
25 for cmd (${cleanupCmds}); do
26 eval ${cmd} | debug
27 done
28}
29
30trap doCleanup EXIT
31
32function cleanup() {
33 local cmd
34 cmd=""
35 for arg ($@); do
36 [[ -n "${cmd}" ]] && cmd="${cmd} "
37 cmd="${cmd}${(qq)arg}"
38 done
39
40 cleanupCmds+=(${cmd})
41}
42
43base=$(basename $0)
44suffix=${base##*.}
45
46force=0
47if [[ "$1" == "-f" ]]; then
48 shift
49 force=1
50 if [[ -n "$1" && "$1" -eq "$1" ]] 2>/dev/null; then
51 force="$1"
52 shift
53 fi
54fi
55
56noCall=false
57if [[ "$1" == "-r" ]]; then
58 shift
59 noCall=true
60fi
61
62for f (${@}); do
63 f=$(readlink -f ${f})
64 if grep -q ${f} @queueDir@/${suffix}.queue; then
65 printf "‘%s’ is already in queue file\n" ${f:t} | warn
66 continue
67 fi
68 if uustat | grep -q ${f:t}; then
69 printf "‘%s’ is already in uucp queue\n" ${f:t} | warn
70 fi
71 print -r ${f} >> @queueDir@/${suffix}.queue
72done
73
74offset=1
75
76advance() {
77 cat =(head -n $((offset - 1)) @queuedir@/${suffix}.queue) =(tail -n +$((offset + 1)) @queueDir@/${suffix}.queue) >@queueDir@/${suffix}.queue
78}
79
80while true; do
81 [[ $(wc -l @queueDir@/${suffix}.queue | cut -d ' ' -f 1) -lt $offset ]] && break
82 file=$(tail -n +${offset} @queueDir@/${suffix}.queue | head -n 1)
83 printf "Considering ‘%s’" ${file} | debug
84 if [[ -z "${file}" || ! -e "${file}" ]]; then
85 if [[ -n "${file}" ]]; then
86 printf "‘%s’ does not exist, skipping\n" "${file}" >&2
87 printf "Subject: Missing file in %s\n\n%s" $logTag ${file} \
88 | sendmail gkleen \
89 && echo "Sent mail."
90 fi
91 advance
92 continue
93 fi
94
95 space=$(($(cat @queueDir@/${suffix}.space) - $(queuesize.$suffix)))
96 printf "%s left on %s\n" $(numfmt --suffix=B --to=iec-i -- $space) $suffix | debug
97
98 size=$(stat -c "%s" "${file}")
99 printf "‘%s’ is %s\n" ${file:t} $(numfmt --suffix=B --to=iec-i -- $size) | debug
100 if [[ "${size}" -le "${space}" || "${force}" -gt 0 ]]; then
101 printf "queuing ‘%s’ for %s\n" ${file:t} ${suffix} | debug
102 function send() {
103 typeset -a cmd
104 cmd=(uux $(if ${noCall}; then echo "-r"; fi) -g z)
105
106 compatibleName=${file}
107 function munge() { [[ $(mungefilename ${file}) != ${file} ]] }
108
109 if munge; then
110 compatibleName=${file:h}/$(mungefilename ${file:t})
111 [[ -e ${compatibleName} ]] || verbose ln -vs ${file} ${compatibleName}
112 cmd+=(-C)
113 cleanup rm -v ${compatibleName}
114 fi
115
116 cmd+=("${suffix}!recv-media" "!${compatibleName}" "$(date --date=@$(stat -c '%Y' "${file}") "+%Y%m%d%H%M.%S")")
117
118 if munge; then
119 cmd+=("$(print -- ${file:t} | base64 -w0)")
120 fi
121 $cmd && printf "Queued ‘%s’ for %s\n" ${file:t} $suffix
122 }
123
124 function skip() {
125 offset=$((offset + 1))
126 printf "Failed to queue ‘%s’\n" ${file} >&2
127 }
128
129 { { [[ ! -e "${file}" ]] || send } && advance && update-queuesize.$suffix } || skip
130 force=$(($force - 1))
131 else
132 break
133 fi
134done
diff --git a/custom/uucp-mediaserver/scripts/queuesize b/custom/uucp-mediaserver/scripts/queuesize
new file mode 100755
index 00000000..3b98ccdb
--- /dev/null
+++ b/custom/uucp-mediaserver/scripts/queuesize
@@ -0,0 +1,24 @@
1#!@zsh@/bin/zsh
2
3base=$(basename $0)
4suffix=${base##*.}
5
6#sent=$(cat /var/queuesize.$suffix)
7#uustat -s $suffix | grep 'Executing recv-media' | sed -r 's/^.*\(sending ([0-9]+) bytes\)/\1/' | awk "BEGIN{s=${sent}}{s+=\$1}END{print s}"
8
9awk 'BEGIN{s=0}{s+=$1}END{print s;}' @queueDir@/${suffix}.queuesize
10
11# typeset -a queued
12# queued=()
13
14# ids=$({ uustat -s $suffix | cut -d ' ' -f 1; cut -d ' ' -f 2 /var/queuesize.$suffix } | sort | uniq -d )
15# queued=(${(f)ids})
16
17# sum=0
18
19# while read size id; do
20# [[ ${queued[(r)$id]} == ${(q)id} ]] || continue
21# sum=$((sum + size))
22# done < /var/queuesize.$suffix
23
24# print $sum
diff --git a/custom/uucp-mediaserver/scripts/queuestatus b/custom/uucp-mediaserver/scripts/queuestatus
new file mode 100755
index 00000000..babacfea
--- /dev/null
+++ b/custom/uucp-mediaserver/scripts/queuestatus
@@ -0,0 +1,41 @@
1#!@zsh@/bin/zsh
2
3typeset -a queue
4queue=()
5
6suffix=${${0:t}##*.}
7uucpsize() {
8 command queuesize.${suffix} ${@}
9}
10mediaspace() {
11 cat @queueDir@/${suffix}.space
12}
13queuesize() {
14 local sum=0
15 for file (${queue}); do
16 local size=$(stat -c "%s" "${file}") || continue
17 sum=$((sum + size))
18 done
19 printf "%d" ${sum}
20}
21
22queueTxt=$(grep -vE '^\s*$' @queueDir@/${suffix}.queue)
23queue=(${(f)queueTxt})
24
25printf "Space: %s\n Reported: %s\n UUCP queue size: %s\n" \
26 $(numfmt --to=iec-i --suffix=B -- $(($(mediaspace) - $(uucpsize)))) \
27 $(mediaspace | numfmt --to=iec-i --suffix=B) \
28 $(uucpsize | numfmt --to=iec-i --suffix=B)
29
30printf "Queue: %d\n Size: %s\n" \
31 ${#queue} \
32 $(queuesize | numfmt --to=iec-i --suffix=B)
33
34printf "\n"
35
36for file (${queue}); do
37 size() {
38 stat -c "%s" "${file}" | numfmt --to=iec-i --suffix=B
39 }
40 printf "%6s %s\n" $(size || printf "N/A") ${file:t}
41done
diff --git a/custom/uucp-mediaserver/scripts/update-queuesize b/custom/uucp-mediaserver/scripts/update-queuesize
new file mode 100755
index 00000000..db1b3e2a
--- /dev/null
+++ b/custom/uucp-mediaserver/scripts/update-queuesize
@@ -0,0 +1,10 @@
1#!@zsh@/bin/zsh
2
3base=$(basename $0)
4suffix=${base##*.}
5
6uustat -s $suffix | grep 'Executing recv-media' | sed -r 's/^([^ ]+) .*\(sending ([0-9]+) bytes\)/\2 \1/' >> @queueDir@/${suffix}.queuesize
7tmpFile=$(mktemp --tmpdir=$HOME)
8sort -k 2 @queueDir@/${suffix}.queuesize | uniq -f 1 > "${tmpFile}"
9cat "${tmpFile}" >! @queueDir@/${suffix}.queuesize
10rm "${tmpFile}"
diff --git a/odin.nix b/odin.nix
index 82af945f..61a127fa 100644
--- a/odin.nix
+++ b/odin.nix
@@ -10,6 +10,7 @@
10 ./odin/hw.nix 10 ./odin/hw.nix
11 ./users.nix 11 ./users.nix
12 ./custom/uucp.nix 12 ./custom/uucp.nix
13 ./custom/uucp-mediaserver.nix
13 ]; 14 ];
14 15
15 # Use the GRUB 2 boot loader. 16 # Use the GRUB 2 boot loader.
@@ -93,8 +94,15 @@
93 ''; 94 '';
94 commandPath = ["${pkgs.rmail}/bin"]; 95 commandPath = ["${pkgs.rmail}/bin"];
95 defaultCommands = ["rmail"]; 96 defaultCommands = ["rmail"];
97
98 media-server = {
99 enable = true;
100 remoteNodes = [ "hel" ];
101 };
96 }; 102 };
97 103
104 users.groups."media" = {};
105
98 services.postfix = { 106 services.postfix = {
99 enable = true; 107 enable = true;
100 enableSmtp = false; 108 enableSmtp = false;
diff --git a/users/gkleen.nix b/users/gkleen.nix
index 648f4ab1..b503b46b 100644
--- a/users/gkleen.nix
+++ b/users/gkleen.nix
@@ -1,7 +1,7 @@
1{ 1{
2 name = "gkleen"; 2 name = "gkleen";
3 description = "Gregor Kleen"; 3 description = "Gregor Kleen";
4 extraGroups = [ "wheel" "network" "lp" "dialout" "audio" "xmpp" "mail" "ssh" "vboxusers" ]; 4 extraGroups = [ "wheel" "network" "lp" "dialout" "audio" "xmpp" "mail" "ssh" "vboxusers" "media" ];
5 group = "users"; 5 group = "users";
6 uid = 1000; 6 uid = 1000;
7 createHome = true; 7 createHome = true;