if {[catch {set Stash $env(DSC_STASH)}]} {set Stash stash}
if {[catch {set Saved $env(DSC_SAVED)}]} {set Saved saved}
+proc readents {root typ} {
+ set ents [glob -directory $root -tails -nocomplain -- *]
+ set ents [lmap d $ents {if {[file type $root/$d] == $typ} {set d} {continue}}]
+ return [lsort $ents]
+}
+
proc walk {root typ} {
set rv [list]
set root [string trimright $root /]
- set dirs [glob -directory $root -tails -nocomplain -- *]
- set dirs [lmap d $dirs {if {[file type $root/$d] == $typ} {set d} {continue}}]
- foreach s [lsort $dirs] {
+ foreach s [readents $root $typ] {
lappend rv $root/$s
lappend rv {*}[walk $root/$s $typ]
}
proc find-opt-schema {opt} {
global Schema
- set path .
+ set pth .
set opt [string trimright $opt /]
foreach e [split $opt /] {
- if {[file exists $Schema/$path/$e]} {
- set path $path/$e
+ if {[file exists $Schema/$pth/$e]} {
+ set pth $pth/$e
continue
}
- if {[file exists $Schema/$path/*]} {
- set path $path/*
+ if {[file exists $Schema/$pth/*]} {
+ set pth $pth/*
continue
}
puts stderr "can not find $opt in schema"
exit 1
}
- return [string range $path 2 end]
+ return [string range $pth 2 end]
}
proc is-bin {opt} {
has {
assure-exists $opt
}
- get-checker {
+ find-opt-schema {
puts [find-opt-schema $opt]
}
get {
if {! [file exists $Stash/$opt]} {
exit
}
- set dirs [glob -directory $Stash/$opt -tails -nocomplain -- *]
- set dirs [lmap d $dirs { \
- if {[file type $Stash/$opt/$d] == "directory"} {set d} {continue}}]
- foreach dir [lsort $dirs] {
+ foreach dir [readents $Stash/$opt directory] {
puts $dir
}
exit
}
puts -nonewline [run-checker $opt ""]
}
+ apply {
+ set pth [find-opt-schema $opt]
+ if {[file exists $Schema/$pth/apply]} {
+ puts stderr "applying $opt..."
+ if {[catch {exec | [list "$Schema/$pth/apply" $opt] >@stdout 2>@stderr}]} {
+ exit 1
+ }
+ exit
+ }
+ if {[file exists $Schema/$pth/*]} {
+ set rc 0
+ foreach dir [readents $Stash/$opt directory] {
+ if {[catch {exec | [list dsc apply $opt/$dir] >@stdout 2>@stderr}]} {
+ set rc 1
+ }
+ }
+ exit $rc
+ }
+ foreach ent [readents $Schema/$opt directory] {
+ if {[catch {exec | [list dsc apply $opt/$ent] >@stdout 2>@stderr}]} {
+ set rc 1
+ }
+ }
+ }
diff {
set dirsSaved [file tempfile dirsSaved.XXXXX]
set fh [open $dirsSaved w]
--- /dev/null
+#!/usr/bin/env jimsh
+
+proc list-addrs {iface} {
+ set addrs [list]
+ catch {exec ip addr list dev $iface} lines
+ foreach l [split $lines \n] {
+ if {[regexp {inet (\S+)} $l _ addr]} {
+ lappend addrs $addr
+ }
+ if {[regexp {inet6 (\S+)} $l _ addr] && [string range $addr 0 4] != "fe80:"} {
+ lappend addrs $addr
+ }
+ }
+ return $addrs
+}
+
+# TODO: check that interface exists
+
+set iface [file tail [lindex $argv 0]]
+set mtu [exec dsc get net/$iface/mtu]
+puts "ip link set $iface mtu $mtu"
+puts "ip link set $iface up"
+
+set addrs [list]
+foreach addr [split [exec dsc get net/$iface/addr/*] \n] {
+ set prefixlen [exec dsc get net/$iface/addr/$addr/prefixlen]
+ lappend addrs $addr/$prefixlen
+}
+foreach addr [list-addrs $iface] {
+ set idx [lsearch -exact $addrs $addr]
+ if {$idx == -1} {
+ puts "ip addr del $addr dev $iface"
+ } else {
+ # Address is already present
+ set $addrs [lreplace $addrs $idx $idx]
+ }
+}
+foreach addr $addrs {
+ puts "ip addr add $addr dev $iface"
+}
--- /dev/null
+#!/usr/bin/env jimsh
+
+proc list-addrs {iface} {
+ set addrs [list]
+ catch {exec ip addr list dev $iface} lines
+ foreach l [split $lines \n] {
+ if {[regexp {inet (\S+)} $l _ addr]} {
+ lappend addrs $addr
+ }
+ if {[regexp {inet6 (\S+)} $l _ addr] && [string range $addr 0 4] != "fe80:"} {
+ lappend addrs $addr
+ }
+ }
+ return $addrs
+}
+
+set sysIfaces [list]
+foreach l [split [exec ip link] \n] {
+ if {[regexp {^\d+: (\w+): } $l _ iface] && $iface != "lo"} {
+ lappend sysIfaces $iface
+ }
+}
+
+set dscIfaces [split [exec dsc get net/*] \n]
+
+foreach iface $sysIfaces {
+ if {[lsearch -exact $dscIfaces $iface] == -1} {
+ # If interface is not mentioned in dsc, then disable it and remove
+ # all addresses, as they are still known to the system
+ puts "ip link set $iface down"
+ foreach addr [list-addrs $iface] {
+ puts "ip addr del $addr dev $iface"
+ }
+ } else {
+ exec | [list dsc apply net/$iface] >@stdout 2>@stderr
+ }
+}
--- /dev/null
+#!/bin/sh -e
+
+tmp=$(mktemp -d)
+trap "rm -fr $tmp" HUP PIPE INT QUIT TERM EXIT
+
+port=$(dsc get ssh/port)
+dsc get ssh/pub >$tmp/id_ed25519.pub
+
+umaskPrev=$(umask)
+umask 077
+dsc get ssh/prv >$tmp/id_ed25519
+umask $umaskPrev
+
+cat >$tmp/run <<EOF
+#!/bin/sh -e
+exec dropbear -FE -p $port -P dropbear.pid -r id_ed25519
+EOF
+chmod +x $tmp/run
+
+set -f
+dsc get ssh/authorized_keys/* | while read name ; do
+ dsc has ssh/authorized_keys/$name/pub 2>/dev/null || continue
+ dsc get ssh/authorized_keys/$name/pub >>$tmp/.authorized_keys
+done
+
+enabled=$(dsc get ssh/enabled)
+if [ "$enabled" != yes ] ; then
+ touch $tmp/down
+fi
+
+if [ -d /tmp/dropbear.srv ] ; then
+ mv /tmp/dropbear.srv $tmp/prev
+ mv $tmp /tmp/dropbear.srv
+ rm -r /tmp/dropbear.srv/prev
+else
+ mv $tmp /tmp/dropbear.srv
+fi
+
+if [ "$enabled" = yes ] ; then
+ echo sv restart /tmp/dropbear.srv
+else
+ echo sv stop /tmp/dropbear.srv
+fi
--- /dev/null
+#!/usr/bin/env jimsh
+
+set n [read -nonewline stdin]
+if {[llength $n] == 0} {
+ puts {empty name}
+ exit 1
+}
+puts $n
--- /dev/null
+#!/usr/bin/env jimsh
+
+set n [read -nonewline stdin]
+if {! [regexp {^ssh-ed25519 [.A-Za-z0-9/+]{68,68}} $n]} {
+ puts {bad ssh-ed25519 key}
+ exit 1
+}
+puts $n
--- /dev/null
+#!/usr/bin/env jimsh
+
+set n [read -nonewline stdin]
+if {$n == ""} {
+ set n no
+}
+if {! [string is boolean $n]} {
+ puts {is not boolean}
+ exit 1
+}
+puts $n
--- /dev/null
+#!/usr/bin/env tclsh8.6
+
+set n [read -nonewline stdin]
+if {$n == ""} {
+ set n 22
+}
+if {! [string is integer -strict $n]} {
+ puts "invalid integer"
+ exit 1
+}
+puts $n
--- /dev/null
+#!/usr/bin/env jimsh
+
+set n [read -nonewline stdin]
+if {! [regexp {^ssh-ed25519 [.A-Za-z0-9/+]{68,68}} $n]} {
+ puts {bad ssh-ed25519 key}
+ exit 1
+}
+puts $n
--- /dev/null
+Dropbear SSH
--- /dev/null
+#!/bin/sh -e
+
+echo "echo $(dsc get $1) >/etc/hostname"