lots of stuff, fixes and features
authorIan Kelling <ian@iankelling.org>
Wed, 7 Oct 2026 09:55:41 +0000 (05:55 -0400)
committerIan Kelling <ian@iankelling.org>
Wed, 7 Oct 2026 09:55:41 +0000 (05:55 -0400)
40 files changed:
.perlcriticrc
brc
brc2
conflink
distro-end
dynamic-ip-update
filesystem/etc/docker/daemon.json [new file with mode: 0644]
filesystem/etc/etckeeper/commit.d/20iank-mirror [new file with mode: 0644]
filesystem/etc/profile.d/environment.sh
filesystem/etc/systemd/system.conf.d/tz.conf
filesystem/usr/local/bin/frodo-route [new file with mode: 0755]
filesystem/usr/local/bin/i3-chat
filesystem/usr/local/bin/imidpri [new file with mode: 0755]
filesystem/usr/local/bin/mon-brightness-cycle
filesystem/usr/local/bin/mount-latest-subvol
filesystem/usr/local/bin/prof-tail
filesystem/usr/local/bin/rootsshsync
filesystem/usr/local/bin/switch-mail-host
fsf-script-lib
g-lib.sh
i3-sway/bar.conf
i3-sway/common.conf
icc-load
icc/U3225QE #1 2026-09-24 03-06 D6500 S XYZLUT+MTX.icc [new file with mode: 0644]
icc/VP2488-4K #1 2026-09-24 01-14 D6500 2.2 F-S XYZLUT+MTX.icc [new file with mode: 0644]
machine_specific/frodo/filesystem/etc/default/isc-dhcp-server [new file with mode: 0644]
machine_specific/frodo/filesystem/etc/dhcp/dhcpd.conf-orig [new file with mode: 0644]
machine_specific/frodo/filesystem/etc/network/interfaces.d/eth10g [deleted file]
machine_specific/frodo/filesystem/etc/systemd/system/frodo-route.service [new file with mode: 0644]
machine_specific/frodo/filesystem/etc/systemd/system/wg-quick-tr-pre@.service
machine_specific/frodo/filesystem/etc/systemd/system/wg-quick-tr@.service
machine_specific/kd/filesystem/etc/network/interfaces.d/eth10g [deleted file]
machine_specific/li/filesystem/etc/openvpn/client-config-hole/frodo
mail-setup
mailtest-check
myx
myx-old [new file with mode: 0755]
pkgs
primary-setup
system-status

index 178402f350366a4deb4a5f78e557573455927188..c8a207dcb12169f671d2f24467379e434b45ee20 100644 (file)
@@ -1,2 +1,24 @@
+# false positives: tidy, checked syscalls. rest are preferences.
+
+[-CodeLayout::RequireTidyCode]
+[-InputOutput::RequireCheckedSyscalls]
+[-ValuesAndExpressions::ProhibitVersionStrings]
+[-Modules::ProhibitAutomaticExportation]
+[-Variables::ProhibitPackageVars]
+[-ControlStructures::ProhibitPostfixControls]
+[-ValuesAndExpressions::ProhibitImplicitNewlines]
+[-ValuesAndExpressions::RequireQuotedHeredocTerminator]
 [-Subroutines::RequireArgUnpacking]
 [-Subroutines::RequireFinalReturn]
+[-RegularExpressions::RequireExtendedFormatting]
+[-ControlStructures::ProhibitCascadingIfElse]
+[-Variables::ProhibitConditionalDeclarations]
+[-Modules::RequireBarewordIncludes]
+[-Variables::ProhibitPunctuationVars]
+
+[Subroutines::ProhibitExcessComplexity]
+add_themes = complex_mess
+[ControlStructures::ProhibitDeepNests]
+add_themes = complex_mess
+[Subroutines::ProhibitManyArgs]
+add_themes = complex_mess
diff --git a/brc b/brc
index 042bdb646faed7ab1ed0eda6e60ca9d8593cd715..09850c458d973e8e5b38c23a46db047c91bc8d46 100644 (file)
--- a/brc
+++ b/brc
@@ -722,7 +722,7 @@ jdo() {
   $sdrun_prefix systemd-run $sdrun_args --unit "$unit_name" --wait --collect "$cmd" "$@" || ret=$?
   # The sleep lets the journal output its last line
   # before the prompt comes up.
-  sleep .5
+  sleep 1
   kill $jr_pid &>/dev/null ||:
   unset jr_pid
   fg &>/dev/null ||:
@@ -1817,22 +1817,22 @@ faf() {
        -o -name .hg -prune -o -name .editor-backups -prune \
        -o -name .undo-tree-history -prune \) \! -type d 2>/dev/null
 }
-# fas = find all shebang. filter by the last word in the shebang path
+# fas = find all shebang. filter by the last word in the shebang path.
 # usage: $0 INTERPRETER_BINARY_NAME [FIND_INITIAL_ARGS...]
 fas() {
   local name="$1"
   shift
-  find "$@" -not \( -name .svn -prune -o -name .git -prune \
+  find "$@" \! \( -name .svn -prune -o -name .git -prune \
        -o -name .hg -prune -o -name .editor-backups -prune \
        -o -name .undo-tree-history -prune \) \! -type d \
        -exec awk 'FNR==1 && /^#![^ ]*\/'"$name( |$)/ {print FILENAME; nextfile}" {} + 2>/dev/null
-  }
+}
 
 # like faf, but sort by modification time. like lt()
 faft() {
   find "$@" -not \( -name .svn -prune -o -name .git -prune \
        -o -name .hg -prune -o -name .editor-backups -prune \
-       -o -name .undo-tree-history -prune \) \! -type d \
+       -o -name .undo-tree-history -prune \) -type f \
        -printf "%T@ %P\n" | sort -n | cut -d' ' -f2-
 }
 
@@ -2659,7 +2659,7 @@ pubip6() { wget -6 -q -O- https://icanhazip.com; }
 whatismyip() { pubip; }
 
 
-q() { # quietly start / launch a program
+q() { # quietly start / launch a program, as long as it doesn't fail within a second.
   "$@" &> /dev/null & disown
   # online, I ran into a version that runs in a subshell with ( ), I
   # suppose that might quiet some programs that try to talk to the tty
@@ -2840,6 +2840,11 @@ ri() {
   "$@" | sponge "$file"
 }
 
+# in-place perltidy with settings i like.
+pltidy() {
+  ri perltidy -i=2 -l=200 -pt=2 -nsfs -ce -conv -st --valign-exclusion-list='if unless and or err for foreach while until' "$@"
+}
+
 # rsync with nice defaults.
 # scp is a bit insecure and deprecated.
 sp() {
@@ -4963,16 +4968,6 @@ lswc-avg() {
 
 }
 
-# usage $0  PID...
-maxpri() {
-  # we try process group (-g, -P) to hit related processes. If this fails, fall back to pid: (-p, -p)
-  if ! s renice -20 -g "$@"; then
-    m s renice -20 -p "$@"
-    m s ionice -c1 -n0 -p "$@"
-    return 0
-  fi
-  s ionice -c1 -n0 -P "$@"
-}
 
 # usage $0  PID...
 minpri() {
@@ -4981,9 +4976,11 @@ minpri() {
     m s ionice -c3 -p "$@"
     return 0
   fi
-  s ionice -c3 -P "$@"
+  m s ionice -c3 -P "$@"
 }
-# Prefix for launching a command:
+
+
+# Prefix for launching a command (missing the :
 # shellcheck disable=SC2034 # false positive
 maxpri="s nice -n-40 ionice -c1 -n0"
 # shellcheck disable=SC2034 # false positive
@@ -5025,11 +5022,318 @@ loc() {
 
 wg-log-on() {
   e module wireguard +p | s tee /sys/kernel/debug/dynamic_debug/control
-  }
+}
 wg-log-off() {
   e module wireguard -p | s tee /sys/kernel/debug/dynamic_debug/control
 }
 
+
+### begin debug-setx related functions ###
+#
+# usage: debug-setx
+#
+# Print executing commands like "set -x", but:
+#
+# - Skips printing many boring/redundant lines. There are related
+#   functions below to modify/toggle what gets printed.
+#
+# - Related function h() to prompt before executing printed command.
+#
+# Printing of uninteresting commands can be limited:
+#
+# 1: Do not print command when stack depth is >= debug_max_stack_depth.
+#
+# 2: Allow printing in specific functions with setx-func (see its doc below).
+#
+# There is a hard-coded list of commands to skip or maybe skip. You can
+# improve this.
+#
+debug-setx() {
+  local existing_debug_trap
+
+  # Note on commands we skip printing:
+  # - read ends up being what is shown for 'while read' loops.
+
+  # for inheriting debug in subshells
+  shopt -s extdebug
+
+  debug_prompt=false
+  debug_skip=false
+  debug_force_print=false
+
+  existing_debug_trap=$(trap -p DEBUG 2>&1)
+  if [[ $existing_debug_trap && $existing_debug_trap != *_debug-setx-func ]]; then
+    trap "$existing_debug_trap; _debug-setx-func" DEBUG
+  else
+    trap _debug-setx-func DEBUG
+  fi
+}
+# internal function called via debug-setx trap.
+_debug-setx-func() {
+  local doprint=false random_delimiter func cmd col debug_cmd
+
+  if [[ $debug_max_stack_depth ]]; then
+    funcname_count_max=$(( debug_max_stack_depth + 1 ))
+  else
+    # within 0 func level, FUNCNAME has 2 in here, eg debug-setx-func main.
+    funcname_count_max=99999
+  fi
+
+  if [[ $BASH_SUBSHELL != [01] ]]; then
+    return 0
+  fi
+
+  if $debug_skip; then
+    debug_skip=false
+    return 0
+  fi
+
+  if $debug_prompt; then
+    doprint=true
+  fi
+
+  if $debug_force_print; then
+    debug_force_print=false
+    doprint=true
+  fi
+
+  if $debug_print_default; then
+
+    ## block for debug_print_funcs
+    if ! $doprint; then
+      for func in ${debug_print_funcs[@]}; do
+        if [[ $func == "${FUNCNAME[1}" ]]; then
+          doprint=true
+          break
+        fi
+      done
+    fi
+
+    ## block for default command & function ignoring
+    if ! $doprint && (( ${#FUNCNAME[*]} <= funcname_count_max )); then
+      # debug
+      #e "${FUNCNAME[*]} ${#FUNCNAME[*]} <= $funcname_count_max"
+      case $BASH_COMMAND in
+        e\ *|err\ *|echo\ *|printf\ *|read\ *|h|ux|ux\ *)
+          : ;;
+        for\ *)
+          # try to print just the first for loop iteration.
+          _debug_setx_cur_for="$BASH_COMMAND ${BASH_LINENO[0]} ${FUNCNAME[1]}"
+          if [[ $_debug_setx_cur_for != "$_debug_setx_last_for" ]]; then
+            doprint=true
+          fi
+          _debug_setx_last_for="$_debug_setx_cur_for"
+          ;;
+        *)
+          doprint=true
+          ;;
+      esac
+    fi
+
+  fi
+
+  if $doprint; then
+    # Expanding $1 will be empty, so skip expansion in that case, and some others.
+    #
+    # TODO: we should be able to grab $1 from the function tracing facilities.
+    #
+    # Note, we could split the command up and expand other parts
+    # but I'm not going to bother.
+    if [[ $BASH_COMMAND != *\$[0-9]* && $BASH_COMMAND != *\`* && $BASH_COMMAND != *\$\(* && $BASH_COMMAND == *\$* ]]; then
+      random_delimiter=$RANDOM$RANDOM$RANDOM
+      # shellcheck disable=SC1003
+      _d="$BASH_COMMAND" _d="${_d//'\\'/SUBfopguensOfRifejmu${random_delimiter}SUB}" _d="${_d//\\[adehHjlnrstT@AuvVwW\!\#\$[\]]/\\&}" _d="${_d//\\D\{*\}/\\&}" _d="${_d//\\[012][0-9][0-9]/\\&}" _d="${_d//\\3[0-6][0-9]/\\&}" _d="${_d//\\37[0-7]/\\&}" _d="${_d//SUBfopguensOfRifejmu${random_delimiter}SUB/'\\\\'}"
+      cmd="${_d@P}"
+    else
+      cmd="$BASH_COMMAND"
+    fi
+    [[ $COLUMNS ]] || { _s=$(stty size); COLUMNS=${_s#* }; }
+    if [[ $COLUMNS == *[0-9]* ]]; then
+      # generally fill up 2 rows
+      col=$(( COLUMNS * 2 - 20 ))
+    else
+      col=150
+    fi
+    if (( ${#cmd} > col )); then
+      cmd="$(( ${#cmd} - col)) cut: ${cmd:0:col}"
+    fi
+    echo "+ $cmd" >&2
+  fi
+
+  if $debug_prompt; then
+    # we can type in commands here to inspect the program state.
+    read -r -e -p "DEBUG $ " debug_cmd
+    while [[ $debug_cmd ]]; do
+      eval $debug_cmd
+      read -r -e -p "DEBUG $ " debug_cmd
+    done
+    debug_prompt=false
+  fi
+}
+
+# usage: ux [COMMAND...]
+#
+# disable/unset debug-setx default command printing. Runs COMMAND if
+# given. Command arg exists only because the args would be otherwise
+# unused.
+ux() {
+  debug_print_default=false
+  if [[ $1 ]]; then "$@"; fi
+}
+
+# usage: u1 [COMMAND...]
+#
+# Disable debug-setx printing just for the next command.
+u1() {
+  # we have this strange logic because [[ is a command, easier to not
+  # have that be between debug_skip=true and $@ and trigger a debug
+  # trap.
+  if [[ $1 ]]; then
+    debug_skip=true
+    "$@"
+  else
+    debug_skip=true
+  fi
+}
+
+# usage: dx [COMMAND...]
+#
+# Undo ux() and reenable debug-setx printing.
+dx() {
+  if [[ $1 ]]; then
+    debug_print_default=true
+    "$@"
+  else
+    debug_print_default=true
+  fi
+}
+
+# usage: d1 [COMMAND...]
+#
+# For just one command, reenable debug-setx printing.
+d1() {
+  if [[ $1 ]]; then
+    debug_force_print=true
+    "$@"
+  else
+    debug_force_print=true
+  fi
+}
+
+
+
+# usage: setx-func [FUNCTION...]
+#
+# Do debug-setx printing within current function or FUNCTION(s) even
+# when called with function stack size greater than
+# $debug_max_stack_depth.
+setx-func() {
+  local new_func new_funcs found existing_func
+  if [[ ! -v debug_print_funcs ]]; then
+    debug_print_funcs=()
+  fi
+
+  e "${FUNCNAME[*]}"
+  if [[ $1 ]]; then
+    new_funcs="$*"
+  else
+    new_funcs="${FUNCNAME[0]}"
+  fi
+  for new_func in $new_funcs; do
+    found=false
+    for existing_func in ${debug_print_funcs[@]}; do
+      if [[ $existing_func == "$new_func" ]]; then
+        found=true
+        break
+      fi
+    done
+    if $found; then
+      break
+    fi
+    debug_print_funcs+=($new_func)
+  done
+}
+
+### end debug-setx related functions ###
+
+## begin debug-setx background / development notes
+#
+# I often end up writing little 5-10 line scripts. To log what they are doing,
+# I was annoyed with the available options. #1 There is set -x, which usually ends up
+# being > 50% useless lines, very anoying. #2
+# m() { printf "%s\n" "$*";
+#"$@"; } that annoyingly conflicts with command
+# redirected output, and I constantly forget to add it.
+#
+# Better option: debug trap, where we can print $BASH_COMMAND. The main
+# annoying thing about this is that $BASH_COMMAND doesn't have expanded
+# variables.
+#
+# options to expand variables in a $BASH_COMMAND:
+#
+# 1. get bash to do readline's shell-expand-line. I know a hacky way
+# with read, but it wasn't reliable when I tried it in a
+# prompt_command. I could probably create a c program that uses readline
+# to do it pretty easily
+#
+# 2. Use the prompt expansion features @P, but first escape the special
+# prompt characters if there are any. This was the option I went
+# with. It has a small flaw that I realized without calling a regex
+# substitution program, my escaping is not perfect: I temporarily insert
+# a long random string to identify "\\", but it is possible this string
+# could exist in the command and then I would improperly replace
+# it. However, my use case is simply viewing commands I intend to run
+# and I don't see any reason I would intend to run a command with that
+# or that even if I did, it would cause any serious problem to have it
+# be incorrectly displayed.
+#
+# NOTE: One imperfection with both of these, is that we don't want to
+# expand $() or ``, so I look for those chars and then avoid doing it. I
+# think the only way to avoid this would be to modify bash itself in
+# order to do shell-expand-line and then use the result, just as if you
+# pressed the key for it.
+#
+# \\ -> \\\\ : creates problem matching eg: \e
+#
+# alternate:
+#
+# \134 -> RANDOM_LONG_STRING
+#
+# \\ -> \134\134 : creates problem matching \134, we need to match \134!(\134), solved by the RANDOM_LONG_STRING
+#
+# \a -> \134a
+#
+# \D{*} and \123 -> \\&
+#
+# RANDOM_LONG_STRING -> \\134
+#
+# alternate, best:
+#
+# \\ -> RANDOM_LONG_STRING
+#
+# \a -> \\a
+#
+# \D{*} and \123 -> \\&
+#
+# RANDOM_LONG_STRING -> \\\\
+#
+# # incrementally built up test cases, where the output is expected to be the same as the initial _d
+#
+# _d='ok\\\\jyes'; _d="${_d//'\\'/SUBfopguensOfRifejmuSUB}" _d="${_d//\\[adehHjlnrstT@AuvVwW\!\#\$[\]]/\\&}" _d="${_d//SUBfopguensOfRifejmuSUB/'\\\\'}"; e "$_d  +  ${_d@P}"
+#
+# _d='ok\D{z_ds}yes'; _d="${_d//'\\'/SUBfopguensOfRifejmuSUB}" _d="${_d//\\[adehHjlnrstT@AuvVwW\!\#\$[\]]/\\&}" _d="${_d//\\D\{*\}/\\&}" _d="${_d//SUBfopguensOfRifejmuSUB/'\\\\'}"; e "$_d  +  ${_d@P}"
+#
+# _d='ok\144ye\134s'; _d="${_d//'\\'/SUBfopguensOfRifejmuSUB}" _d="${_d//\\[adehHjlnrstT@AuvVwW\!\#\$[\]]/\\&}" _d="${_d//\\D\{*\}/\\&}" _d="${_d//\\[012][0-9][0-9]/\\&}" _d="${_d//\\3[0-6][0-9]/\\&}" _d="${_d//\\37[0-7]/\\&}" _d="${_d//SUBfopguensOfRifejmuSUB/'\\\\'}"; e "$_d  +  ${_d@P}"
+#
+#
+# random interesting script:
+# x=4
+# echo "\$x ${BASH_COMMAND@P}"
+# Warning: Program '/bin/bash' crashed.
+#
+## end debug-setx background / development notes
+
+
 # * stuff that makes sense to be at the end
 
 # note, if we unset IFS, that will mess up completion scripts which
diff --git a/brc2 b/brc2
index 9f43626a1922a4ba55cb2bbf1defaeca11b9cb40..c9ac4f1e01a9850ab6ab473c154330feea83e434 100644 (file)
--- a/brc2
+++ b/brc2
@@ -1016,7 +1016,7 @@ btrbk-host-debug-show-host() {
 # Alt is just the other host that takes snapshots
 # besides the local host.
 btrbk-host-debug() {
-local host remote alt f
+  local host remote alt f
   remote=b8.nz
   alt=sywg.b8.nz
 
@@ -1237,7 +1237,7 @@ lipush() {
     /p/c/subdir_files
   )
   a="-ahviSAXPH --specials --devices --delete --delete-excluded --relative --exclude-from=/p/c/li-rsync-excludes"
-  for h in li je bk; do
+  for h in li bk; do
     m s rsync "$@" $a ${fs[@]} /p/c/machine_specific/$h root@$h.b8.nz:/
     ## only li is debian11
     #p[0]=/a/opt/emacs-trisuqel10
@@ -1252,8 +1252,8 @@ bkpush() {
   local -a fs
   local -i ret=0
   fs=(/a/bin /a/exe /a/h /a/c /p/c/machine_specific/vps{,.hosts}
-     /a/f/ans/roles/prom_export/files/simple/usr/local/bin/fsf-install-node-exporter
-    )
+      /a/f/ans/roles/prom_export/files/simple/usr/local/bin/fsf-install-node-exporter
+     )
   a="-ahviSAXPH --specials --devices --delete --relative --exclude-from=/p/c/li-rsync-excludes"
   ret=0
   m rsync "$@" $a ${fs[@]} /p/c/machine_specific/bk root@bk.b8.nz:/ || ret=$?
@@ -1264,8 +1264,8 @@ jepush() { # no emacs. for running faster.
   local -a fs
   local -i ret=0
   fs=(/a/bin /a/exe /a/h /a/c /p/c/machine_specific/vps{,.hosts}
-     /a/f/ans/roles/prom_export/files/simple/usr/local/bin/fsf-install-node-exporter
-    )
+      /a/f/ans/roles/prom_export/files/simple/usr/local/bin/fsf-install-node-exporter
+     )
 
   a="-ahviSAXPH --specials --devices --delete --relative --exclude-from=/p/c/li-rsync-excludes"
   ret=0
@@ -2041,7 +2041,7 @@ host-info-all() {
 
   bindpushb8
   # for wireguard configs
-  ssh iank@li.b8.nz "conflink; ser reload wg-quick-mail"
+  ssh iank@li.b8.nz "conflink; ser reload wg-quick@mail"
   wrt-setup
 }
 
@@ -2068,7 +2068,7 @@ hiup() {
   for h in ${root_hosts[@]}; do
     root_hosts+=(${h}ex)
   done
-  root_hosts+=(cmc)
+  root_hosts+=(cmc wrtap w33)
 
   work_hosts=(10.8.0.97 10.8.0.99)
 
@@ -2237,6 +2237,26 @@ WantedBy=multi-user.target
 EOF
   done
 
+
+  cat >/p/c/machine_specific/frodo/filesystem/etc/dhcp/dhcpd.conf <<'EOF'
+# generated by hiup
+authoritative;
+#option dhcp-max-message-size 2048;
+use-host-decl-names on;
+
+subnet 10.0.0.0 netmask 255.255.0.0 {
+  range 10.0.0.100 10.0.0.199;
+  option routers 10.0.0.1;
+  option domain-name "b8.nz";
+  option domain-search "b8.nz";
+  option domain-name-servers 8.8.8.8;
+  option ntp-servers 0.ubuntu.pool.ntp.org, 1.ubuntu.pool.ntp.org, ntp.ubuntu.com;
+}
+
+default-lease-time 600;
+max-lease-time 7200;
+EOF
+
   for host in ${!vpn_ips[@]}; do
     if [[ ${root_hosts_a[$host]} ]]; then
       continue
@@ -2259,6 +2279,7 @@ EOF
     echo "EOF"
   } | u /p/c/ptr-data
 
+  # this is for old setup where dhcp is done by cmc.
   {
     echo "cat <<EOF"
     for host in ${!host_macs[@]}; do
@@ -2269,6 +2290,18 @@ EOF
   } | u /p/c/dnsmasq-data
 
 
+  for host in ${!host_macs[@]}; do
+    if [[ ${host_macs[$host]} != *:* ]]; then continue; fi
+
+    ipsuf=${host_ips[$host]}
+    cat >>/p/c/machine_specific/frodo/filesystem/etc/dhcp/dhcpd.conf <<EOF
+host $host {
+  hardware ethernet ${host_macs[$host]};
+  fixed-address 10.0.0.$ipsuf;
+}
+EOF
+  done
+
   #b8_ip=$(dig +short b8.nz @iankelling.org | tail -1)
   # if our dynamic ip updates broke, set manually, eg:
   b8_ip=108.26.192.250  # 72.74.193.xxx
@@ -2286,12 +2319,12 @@ i       A       $b8_ip
 EOF
     for host in ${!nonvpn_ips[@]}; do
       ipsuf=${nonvpn_ips[$host]}
-      echo "$host      A       10.2.0.$ipsuf"
+      echo "$host      A       10.0.0.$ipsuf"
     done
     for host in ${!vpn_ips[@]}; do
       ipsuf=${vpn_ips[$host]}
       cat <<EOF
-$host  A       10.2.0.$ipsuf
+$host  A       10.0.0.$ipsuf
 ${host}wg      A       10.8.0.$ipsuf
 ${host}vp      A       10.5.5.$ipsuf
 ${host}tr      A       10.174.$ipsuf.2
@@ -2662,7 +2695,10 @@ mnsnonet() {
   if ! s ip netns list | grep -Fx nonet &>/dev/null; then
     s ip netns add nonet
   fi
-  mns $ns --net=/var/run/netns/nonet sudo -E -u iank /bin/bash
+  user=$USER
+  env-tmpf bash
+  mns-setup $ns
+  m sudm /usr/bin/nsenter --mount=/root/mount_namespaces/$ns --net=/var/run/netns/nonet sudo -u iank -i bash -c ". $tmpf"
   lomh
 }
 
@@ -2950,7 +2986,17 @@ s/^[^ ]*\.txt:\((.{2}).(.{2}).(.{4}) (.{8}) (.{2})\)?/\3-\1-\2_\4_\5/' \
 
 # my profanity
 #
+# usage: $0 [weeks]
 myprof() {
+  local weeks
+  if [[ $1 ]]; then
+    weeks=$1
+  elif [[ $(date +%A) == Monday ]]; then
+    weeks=2
+  else
+    weeks=5
+  fi
+
 
   pushd /home/iank/.local/share/profanity/chatlogs/iank_at_fsf.org/rooms/office_at_conference.fsf.org
   logs=(*)
@@ -2966,11 +3012,7 @@ myprof() {
     i=0
   fi
   # usually do this on monday, sometimes later
-  if [[ $(date +%A) == Monday ]]; then
-    min_date=$(date -d 'monday 2 weeks ago' +%s)
-  else
-    min_date=$(date -d 'monday 5 weeks ago' +%s)
-  fi
+  min_date=$(date -d "monday $weeks weeks ago" +%s)
   for (( ; i < logcount; i++ )); do
     log_base=${logs[$i]}
     day_logs=()
@@ -3674,7 +3716,8 @@ servicepid() {
       # could just get this in the first place, but i don't know if that
       # is always the case.
       procsf=$dir/${unit%.service}.service/cgroup.procs
-      if [[ -s $procsf ]]; then
+      # note: ls will show the file as empty even though it isn't
+      if [[ -e $procsf ]]; then
         pid=$(head -n1 $procsf)
       else
         pid=
@@ -3887,6 +3930,7 @@ vpncmdroot() {
 vpni() {
   local n="$1" ser_suf=tr
   if [[ $n ]]; then ser_suf=nn; fi
+  vpnc $n
   # m sudo nsenter --net=/var/run/netns/client sudo -u iank -i bash # for just the netns
   sdncmd wg-quick-$ser_suf@client$n.service bash
 }
@@ -4047,9 +4091,11 @@ vpnc() {
   local n="$1" ser_suf=tr
   if [[ $n ]]; then ser_suf=nn; fi
   unit=wg-quick-$ser_suf@client$n
-  sudo -v
+  if [[ $EUID != 0 ]]; then
+    sudo -v
+  fi
   if [[ $(systemctl is-active $unit) != active ]]; then
-    s systemctl start $unit
+    m s systemctl start $unit
     sleep 1
   fi
 }
@@ -4358,6 +4404,16 @@ else
   alias rg=grr
 fi
 
+# find all perl files
+fapl() {
+  fas perl \! -name '*.*'; faf \( -name '*.pl' -o -name '*.pm' \)
+}
+
+# rg perl files
+rgpl() {
+  rg "$@" $(fapl)
+}
+
 # rg with respecting vcs ignore files
 rgv() {
   local path_arg ret=0
index b303d539dee3b5a468d1426d350740118276016a..0948c2439d93ad39c4a64042476876571b31ea39 100755 (executable)
--- a/conflink
+++ b/conflink
@@ -273,6 +273,8 @@ case $user in
         etc/systemd/resolved.conf.d/*)
           restart_services[systemd-resolved]=t
           ;;
+        # todo: this isnt working
+        etc/dhcp/dhcpd.conf) restart_services[isc-dhcp-server]=t ;;
       esac
       # Previously did this with tar, but it doesn't
       # update directory permissions.
index 488075c1a3f4c5148a5ac59ef5004c1123a3ccb0..8423458c8662ccc92c5a021c87bd56b9d69d91fa 100755 (executable)
@@ -1015,6 +1015,16 @@ if [[ -e /p/c/machine_specific/$HOSTNAME/filesystem/etc/openvpn/client/hole.crt
   sgo openvpn-client@hole
 fi
 
+case $HOSTNAME in
+  $d_host)
+    sgo frodo-route
+    sgo isc-dhcp-server
+    # Avoid the dhcp on other hosts. it seems static ips could be
+    # configured but i'm not bothering.
+    pi dropbear-initramfs
+    ;;
+esac
+
 ############# begin syncthing setup ###########
 case $HOSTNAME in
   $d_host)
@@ -1584,7 +1594,8 @@ m /a/bin/buildscripts/textern
 #m /a/bin/buildscripts/alacritty
 #m /a/bin/buildscripts/kitty
 
-pi-nostart virtinst virt-manager
+# qemu & zsync are quickemu dependencies
+pi-nostart virtinst virt-manager qemu-system zsync
 soff libvirtd
 # i cant if this is whats causing it to start even though
 # its disabled. note: it leaves around dnsmasq instances even
@@ -2016,12 +2027,14 @@ esac
 #
 #
 # initial config goes to /home/iank/.config/gh
-curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
-  && sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
-  && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
+curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/etc/apt/keyrings/githubcli-archive-keyring.gpg \
+  && sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
+  && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
   && sudo apt-get update \
   && sudo apt-get install gh -y
 
+# fix old path on old computers.
+sudo sed -ri 's,/usr/share/key,/etc/apt/key,' /etc/apt/sources.list.d/github-cli.list
 ### end gh ####
 
 
@@ -2033,14 +2046,12 @@ if [[ ! -e /etc/apt/sources.list.d/pgdg.sources ]]; then
   pi postgresql-common
   sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -y noble
   pi-nostart postgresql-$ver postgresql-doc-$ver
-  # when we run it, do:
-  #sudo -u postgres createuser -d iank
   sudo usermod -a -G postgres iank
   if ! out=$(psql -XAtq -Pfieldsep=' ' -vON_ERROR_STOP=on postgres <<<"select 1 from pg_user where usename = 'iank';" 2>/dev/null) || [[ $out != 1 ]]; then
     sudo -u postgres createuser -d iank
   fi
   # initial db creation with:
-  # createdb -O iank db_name
+  # createdb -O iank dl
 
   e "vm.hugetlb_shm_group=$(getent group postgres|awk -F : '{print $3}')" |  sd /etc/sysctl.d/80-iank-hugepage-postgres.conf
   sudo sysctl -p/etc/sysctl.d/80-iank-hugepage-postgres.conf
index 1238451a1aaa257acb9dbb3549d409cbc8f64590..16180ec4d214c97b5c8d9b23d1cac91d9c8642af 100755 (executable)
@@ -85,21 +85,22 @@ main() {
       exit 0
     fi
   fi
+
+
+
+
   read -r _ _  gateway _ ifdev _ <<<"$tmp"
 
-  case $gateway in
-    10.2.0.1)
-      dyndomain=b8.nz
-      # This domain is for any case where we want some different
-      # configuration based on lan vs wan. For right now, the only use
-      # is for ssh config to use port forwarding ports on the wan
-      # domain.
-      dyndomain_internet=i.b8.nz
-      ;;
-    *)
-      return 0
-      ;;
-  esac
+  if [[ $HOSTNAME == frodo || $gateway == 10.2.0.1 ]]; then
+    dyndomain=b8.nz
+    # This domain is for any case where we want some different
+    # configuration based on lan vs wan. For right now, the only use
+    # is for ssh config to use port forwarding ports on the wan
+    # domain.
+    dyndomain_internet=i.b8.nz
+  else
+    return 0
+  fi
 
   # We check if we are at home by testing gateway ssh
   # fingerprint. However, if we found in the past that we are, I dont
@@ -115,9 +116,12 @@ main() {
       printf "%s\n" "$newbytes" >/dev/shm/dynamic-ip-update-state
     fi
   fi
-  if ! $athome && timeout -s 9 5 ssh-keyscan -p 2220 -t rsa $gateway 2>/dev/null | grep -qFx "[$gateway]:2220 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCH+/h1dGEfKEusBblndU2e6QT4wLCm5+yqr/sqh/0X9YfjR7BfWWm8nNmuP55cYc+Wuf5ljB1H1acXEcsl1y8e0j3agHfF0V74FE1N1zz5nn2Ep8NHnmqgEhza38ZxMPh+4p3X7zklEKU7+3SzybKBi8sg0wLzlS2LM0JaUN80zR2sK11Kye3dURUXPk78u5wodOkgcEYRwSYaDMJlUzWP+poRXIDJwFaMQnwmxbl/c84yOyaU0x/d6hFwoRscWecihX+vvBNeSyxR4xr2HDOyUWwJkctyAgt2p7w3tfkXOKcCRzTAjGVIMQLTvo0sG/yJbcyHoEFdFybCsgDvfyYn"; then
-    athome=true
-    awk '$1 == "'$ifdev':" {print $2 + $10}' /proc/net/dev > /dev/shm/dynamic-ip-update-state
+
+  if ! $athome; then
+    if [[ $HOSTNAME == frodo ]] || timeout -s 9 5 ssh-keyscan -t ed25519 $gateway 2>/dev/null | grep -qFx "$gateway ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIHggN4OjyqJCF5lmqMEBmFAyTFvNruZgNqxj0a9ztls"; then
+      athome=true
+      awk '$1 == "'$ifdev':" {print $2 + $10}' /proc/net/dev > /dev/shm/dynamic-ip-update-state
+    fi
   fi
 
 
diff --git a/filesystem/etc/docker/daemon.json b/filesystem/etc/docker/daemon.json
new file mode 100644 (file)
index 0000000..4d95dc2
--- /dev/null
@@ -0,0 +1 @@
+{ "default-address-pools": [ { "base": "172.31.0.0/20", "size": 24 } ] }
diff --git a/filesystem/etc/etckeeper/commit.d/20iank-mirror b/filesystem/etc/etckeeper/commit.d/20iank-mirror
new file mode 100644 (file)
index 0000000..7870e2e
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/bash
+# I, Ian Kelling, follow the GNU license recommendations at
+# https://www.gnu.org/licenses/license-recommendations.en.html. They
+# recommend that small programs, < 300 lines, be licensed under the
+# Apache License 2.0. This file contains or is part of one or more small
+# programs. If a small program grows beyond 300 lines, I plan to change
+# to a recommended GPL license.
+
+# Copyright 2025 Ian Kelling
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# for saving files outside of /etc with etckeeper
+
+rsync -a --relative --mkpath /var/lib/exim4/config.autogenerated /etc/etckeeper/fsmirror/
index 5457716990ae560313492e373f44f21203861f26..ecd724f3c63c6bd3059c13a8a90f63bf85c3e02e 100644 (file)
@@ -47,7 +47,8 @@ export PITHOSFLY_SAVE_DIR=/a/pandora_rips4
 # I also set this in
 # /a/c/filesystem/etc/systemd/system.conf.d/tz.conf
 # https://blog.packagecloud.io/eng/2017/02/21/set-environment-variable-save-thousands-of-system-calls/
-export TZ=:/etc/localtime
+# # However, those instructions backfired because emacs erc didn't understand the value
+# export TZ=:/etc/localtime
 
 # ubuntu starts gpg agent automatically with  /etc/X11/Xsession.d/90gpg-agent.
 # fedora doesn't, which left me to figure this out, and google was no help.
index dcfba4579b5d6cac68544afa605be77b0a328bd0..f843501acfa946a4aafc92e6d7885f29ac4d02d2 100644 (file)
@@ -1,3 +1,4 @@
 [Manager]
-DefaultEnvironment=TZ=:/etc/localtime
+# see /b/ds/filesystem/etc/profile.d/environment.sh
+#DefaultEnvironment=TZ=:/etc/localtime
 # also set in profile.d/environment.sh with explanation there
diff --git a/filesystem/usr/local/bin/frodo-route b/filesystem/usr/local/bin/frodo-route
new file mode 100755 (executable)
index 0000000..85d728f
--- /dev/null
@@ -0,0 +1,36 @@
+#!/bin/bash
+# I, Ian Kelling, follow the GNU license recommendations at
+# https://www.gnu.org/licenses/license-recommendations.en.html. They
+# recommend that small programs, < 300 lines, be licensed under the
+# Apache License 2.0. This file contains or is part of one or more small
+# programs. If a small program grows beyond 300 lines, I plan to change
+# to a recommended GPL license.
+
+# Copyright 2025 Ian Kelling
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -eE -o pipefail
+trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
+
+if [[ $EUID != 0 ]]; then
+  echo "$0: error: expected to be root."
+  exit 1
+fi
+
+
+rule="POSTROUTING -s 10.0.0.0/16 -o eth1 -j MASQUERADE"
+
+if ! iptables -t nat -C $rule &>/dev/null; then
+  iptables -t nat -I $rule
+fi
index 13034c5bd9c1913e5c2ebd074b863a2569d4ed31..ce2e24a3d53c4457f7d311ea1d4d204b7616ee0e 100755 (executable)
@@ -23,7 +23,7 @@
 i3-msg "workspace 4"
 # start emacs daemon for profanity/znc if it doesnt exist.
 
-id=$(i3-msg -t get_tree | jq -e '.. | select(.name?) | select(.name | test("^iznc ")).id')
+id=$(i3-msg -t get_tree | jq -e '.. | select(.name?) | select(.name | test("^e-profanity ")).id')
 
 if [[ ! $id ]]; then
   emacsclient -s profanity -nc  &>/dev/null
diff --git a/filesystem/usr/local/bin/imidpri b/filesystem/usr/local/bin/imidpri
new file mode 100755 (executable)
index 0000000..d5b7398
--- /dev/null
@@ -0,0 +1,92 @@
+#!/bin/bash
+
+# usage: [-v] -d|-m PID|PGREP_FULL_REGEX...
+#
+# -d Set pids to default priority.
+# -m Set pids to max priority.
+#
+# -v = verbose output.
+
+[[ $EUID == 0 ]] || exec sudo "${BASH_SOURCE[0]}" "$@"
+
+
+. /a/c/fsf-script-lib
+
+maxpri() {
+  for pid; do
+    chrt --all-tasks --rr --reset-on-fork --pid 50 $pid
+  done
+  # we try process group (-g, -P) to hit related processes. If this fails, fall back to pid: (-p, -p)
+  if ! renice -20 -g "$@"; then
+    renice -20 -p "$@"
+    # c1 = realtime, it can starve other processes, which is probably
+    # not something I'd probably want.
+    ionice -c2 -n0 -p "$@"
+    return 0
+  fi
+  ionice -c2 -n0 -P "$@"
+}
+
+
+midpri() {
+  local pid
+  local -a tids
+  for pid; do
+    chrt --all-tasks --other --pid 0 $pid
+    for task in /proc/$pid/task/*; do
+      tids+=("${task##*/}")
+    done
+  done
+  renice -n 0 -p "${tids[@]}"
+  ionice -c 0 -p "${tids[@]}"
+}
+
+#verbose=false
+if [[ $1 == -v ]]; then
+  set -x
+  #verbose=true
+  shift
+fi
+
+
+if [[ $1 == -m ]]; then
+  max=true
+elif [[ $1 == -d ]]; then
+  max=false
+else
+  err "invalid 1st cli arg"
+  exit 1
+fi
+shift
+
+maxpids=()
+midpids=()
+
+while [[ $1 ]]; do
+  unset pids # not needed, just for clarity.
+  if [[ $1 == -m ]]; then
+    max=true
+  elif [[ $1 == -d ]]; then
+    max=false
+  else
+    if [[ $1 =~ $uint_regex ]]; then
+      pids=$1
+    else
+      pids=$(pgrep -d ' ' -f "$1")
+    fi
+    if $max; then
+      maxpids+=( $pids )
+    else
+      midpids+=( $pids )
+    fi
+  fi
+  shift
+done
+
+if (( ${#maxpids[@]} )); then
+  maxpri ${maxpids[@]}
+fi
+
+if (( ${#midpids[@]} )); then
+  midpri ${midpids[@]}
+fi
index 32ac2184afb94ac6fe800ce9c7bcb19cbdd84fa3..0c59e23042a9a6cc0db090eeedcf8f705820a333 100755 (executable)
@@ -27,10 +27,23 @@ state_f=/tmp/user/1000/tmp_mon_bright.KROSZousbE
 low_level=70
 
 set-bright() {
-  ddcutil --display 1 setvcp 10 $1
+  # loop using proper detection
+  #for dnum in ${displays[@]}; do
+  #
+  for (( dnum=display_count; dnum >= 1; dnum-- )); do
+    # note: I tried running this in the background, but it turns out a 2nd call in parallel
+    # breaks the 1st call.
+    ddcutil --display $dnum setvcp 10 $1
+  done
   echo $1 >$state_f
 }
 
+# proper detection, but slow, like .75 seconds.
+#displays=( $(ddcutil detect -t| sed -rn 's/^Display[[:space:]]+([0-9]+)[[:space:]]*$/\1/p' | tac) )
+# instead:
+declare -i display_count
+display_count=$(xrandr | awk '$2 == "connected" {count++} END {print count}')
+
 if [[ -s $state_f ]]; then
   cur_bright=$(cat $state_f)
   # echo "state_f: $cur_bright" # debug
index 3757814368d2b1fea3d3d940d8bb2391cc3b7c3a..005b693f863c82825f063ad7b372fa2987dfe05a 100755 (executable)
@@ -152,7 +152,8 @@ get-btrfs-root-mountpoint() {
       mapper-dev devx
     fi
     d devx=$devx
-    root_dir=$(sed -rn "s,^\s*$devx\s+(\S+).*\bsubvolid=[05]\b.*,\1,p" /etc/mtab /etc/fstab|head -n1)
+    # note: we could also test for "subvol=/", but no need.
+    root_dir=$(awk '$1 == "'"$devx"'" && $3 == "btrfs" && ( $4 !~ /subvol=/ || $4 ~ /subvolid=[05](,|$)/ ) {print $2}' /etc/mtab /etc/fstab|head -n1)
     if [[ $root_dir ]]; then
       d root_dir=$root_dir
       break
index f3df29700a02c7c71d374e681074685e3f64d057..0529fdd9238d5381ff8f8e96fc743ca475ef7835 100755 (executable)
@@ -122,10 +122,12 @@ notify-cmd() {
   if [[ $line ]] && ! i3-check-profanity &>/dev/null; then
     dunstify -h string:x-dunst-stack-tag:profanity -- "$line"
   fi
+  sleep 1
 }
 
 pre="^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}-[0-9]{2} -"
 
+declare -i ret
 while true; do
   midnight=$(date -d '00:00:00 tomorrow' +%s)
   log_today=$(date '+%Y_%m_%d' "${dev_date[@]}").log
@@ -137,9 +139,15 @@ while true; do
 
   tail-cmd | while true; do
     if (( EPOCHSECONDS > midnight + 3 )); then break; fi
-    read -t 15 -r l 2>/dev/null || continue
+    ret=0; read -t 15 -r l 2>/dev/null || ret=$?
+    # eg false|read
+    if (( ret == 1 )); then break; fi
+    # timeout
+    if (( ret == 142 )); then
+      continue
+    fi
     notify-cmd "$l"
-  done
+  done ||:
 
   sleep 2
 done
index 887fbb5adb13a30dc3d4ddcd15410d90ab87d56e..2cc0b34a3892560d56053bc420c723acd00b28c7 100755 (executable)
@@ -88,6 +88,7 @@ if [[ -e /etc/systemd/system/ssh-agent-root.service ]]; then
   systemctl enable --now ssh-agent-root
 fi
 
+if [[ -d /usr/share/doc/dropbear-initramfs ]]; then
 
 # note: i previously had $auth_dir/root/.ssh/authorized_keys
 # but /usr/share/doc/dropbear-initramfs/README.initramfs
@@ -104,6 +105,7 @@ if [[ ! -e $auth_file ]] || ! diff -q /root/.ssh/authorized_keys $auth_file; the
   cp -p /root/.ssh/authorized_keys $auth_file
   update-initramfs -u -k all
 fi
+fi
 
 if [[ -e /p/c/subdir_files/.dsh ]]; then
   rsync -tpur /p/c/subdir_files/.dsh /root
index 809b4f5490d48481eca81b83a18180b07ef2efea..e9d6d63619197f384a192bb62dfd53db7c77f037 100755 (executable)
@@ -371,7 +371,7 @@ if (( ret )); then
   e finished restoring old host as primary, now exiting $ret due to earlier failed btrbk of /o.
   exit $ret
 fi
-_s=$(stty size); c=${_s#* }; while ((c-- >0)); do printf $; done; echo
+echo '$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$'
 # new system is usable at this point
 
 # once I accidentally accepted incoming mail on old host. I used this script to copy over that mail:
index d561fc6ed99e593e71d7320a7ffb1a84182fc6ae..cea16f74b3558d48531a7c5ef92c0e31371ddd2d 100644 (file)
@@ -1,10 +1,5 @@
 #!/bin/bash
 
-# Copyright (C) 2023 Free Software Foundation <sysadmin@fsf.org>
-#
-# Note: the FSF recommends copyleft licensing for programs > 300 lines, see
-# https://www.gnu.org/licenses/license-recommendations.en.html.
-#
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 # block.
 set -e
 if [[ -s /usr/local/lib/bash-bear ]]; then
+  # shellcheck disable=SC1091
   . /usr/local/lib/bash-bear
 elif [[ -s /usr/local/lib/err ]]; then
   # old name
   # shellcheck disable=SC1091
   . /usr/local/lib/err
+elif [[ -s ${BASH_SOURCE[0]%/*}/bash-bear ]]; then
+  # shellcheck disable=SC1091 # checking script dir.
+  . ${BASH_SOURCE[0]%/*}/bash-bear
 elif [[ $- != *i* ]]; then
   # error if this is a script, not an interactive shell.
   echo "error: exit 1: missing dependency: /usr/local/lib/bash-bear"
@@ -183,6 +182,13 @@ mq() {
 # echo MESSAGE, but use printf so it is safe from options.
 e() { printf "%s\n" "$*"; }
 
+# echo but only when verbose is true.
+ev() {
+  if [[ $verbose == true ]]; then
+    e "$@"
+  fi
+}
+
 # usage: ml COMMAND...
 #
 # Write successful command to log.
@@ -254,158 +260,12 @@ dr() {
 # 2025-01-03 03:51:59 main: test message2
 err() { echo "$(date "+%F %T") ${FUNCNAME[1]}: $*" >&2; }
 
-### begin debug-setx related functions ###
-#
-# usage: debug-setx
-#
-# Print executing commands like "set -x", but:
-#
-# - Skips printing many boring/redundant lines. There are related
-#   functions below to modify/toggle what gets printed.
-#
-# - Related function h() to prompt before executing printed command.
-#
-# Printing of uninteresting commands can be limited:
-#
-# 1: Do not print command when stack depth is >= debug_max_stack_depth.
-#
-# 2: Allow printing in specific functions with setx-func (see its doc below).
-#
-# There is a hard-coded list of commands to skip or maybe skip. You can
-# improve this.
-#
-debug-setx() {
-  local existing_debug_trap
-
-  # Note on commands we skip printing:
-  # - read ends up being what is shown for 'while read' loops.
-
-  # for inheriting debug in subshells
-  shopt -s extdebug
-
-  debug_prompt=false
-  debug_skip=false
-  debug_force_print=false
-
-  existing_debug_trap=$(trap -p DEBUG 2>&1)
-  if [[ $existing_debug_trap && $existing_debug_trap != *_debug-setx-func ]]; then
-    trap "$existing_debug_trap; _debug-setx-func" DEBUG
-  else
-    trap _debug-setx-func DEBUG
-  fi
+# Do the equivalent of head on file that might not have line breaks or
+# might be gobblygook. The sed fixes any missing final newline.
+peek() {
+  cat -Ans -- "$1" | head -n20 | head -c1500 | sed a\\  || [[ $? == 141 ]]
 }
-# internal function called via debug-setx trap.
-_debug-setx-func() {
-  local doprint=false random_delimiter func cmd col debug_cmd
 
-  if [[ $debug_max_stack_depth ]]; then
-    funcname_count_max=$(( debug_max_stack_depth + 1 ))
-  else
-    # within 0 func level, FUNCNAME has 2 in here, eg debug-setx-func main.
-    funcname_count_max=99999
-  fi
-
-  if [[ $BASH_SUBSHELL != [01] ]]; then
-    return 0
-  fi
-
-  if $debug_skip; then
-    debug_skip=false
-    return 0
-  fi
-
-  if $debug_prompt; then
-    doprint=true
-  fi
-
-  if $debug_force_print; then
-    debug_force_print=false
-    doprint=true
-  fi
-
-  if $debug_print_default; then
-
-    ## block for debug_print_funcs
-    if ! $doprint; then
-      for func in ${debug_print_funcs[@]}; do
-        if [[ $func == "${FUNCNAME[1}" ]]; then
-          doprint=true
-          break
-        fi
-      done
-    fi
-
-    ## block for default command & function ignoring
-    if ! $doprint && (( ${#FUNCNAME[*]} <= funcname_count_max )); then
-      # debug
-      #e "${FUNCNAME[*]} ${#FUNCNAME[*]} <= $funcname_count_max"
-      case $BASH_COMMAND in
-        e\ *|err\ *|echo\ *|printf\ *|read\ *|h|ux|ux\ *)
-          : ;;
-        for\ *)
-          # try to print just the first for loop iteration.
-          _debug_setx_cur_for="$BASH_COMMAND ${BASH_LINENO[0]} ${FUNCNAME[1]}"
-          if [[ $_debug_setx_cur_for != "$_debug_setx_last_for" ]]; then
-            doprint=true
-          fi
-          _debug_setx_last_for="$_debug_setx_cur_for"
-          ;;
-        *)
-          doprint=true
-          ;;
-      esac
-    fi
-
-  fi
-
-  if $doprint; then
-    # Expanding $1 will be empty, so skip expansion in that case, and some others.
-    #
-    # TODO: we should be able to grab $1 from the function tracing facilities.
-    #
-    # Note, we could split the command up and expand other parts
-    # but I'm not going to bother.
-    if [[ $BASH_COMMAND != *\$[0-9]* && $BASH_COMMAND != *\`* && $BASH_COMMAND != *\$\(* && $BASH_COMMAND == *\$* ]]; then
-      random_delimiter=$RANDOM$RANDOM$RANDOM
-      # shellcheck disable=SC1003
-      _d="$BASH_COMMAND" _d="${_d//'\\'/SUBfopguensOfRifejmu${random_delimiter}SUB}" _d="${_d//\\[adehHjlnrstT@AuvVwW\!\#\$[\]]/\\&}" _d="${_d//\\D\{*\}/\\&}" _d="${_d//\\[012][0-9][0-9]/\\&}" _d="${_d//\\3[0-6][0-9]/\\&}" _d="${_d//\\37[0-7]/\\&}" _d="${_d//SUBfopguensOfRifejmu${random_delimiter}SUB/'\\\\'}"
-      cmd="${_d@P}"
-    else
-      cmd="$BASH_COMMAND"
-    fi
-    [[ $COLUMNS ]] || { _s=$(stty size); COLUMNS=${_s#* }; }
-    if [[ $COLUMNS == *[0-9]* ]]; then
-      # generally fill up 2 rows
-      col=$(( COLUMNS * 2 - 20 ))
-    else
-      col=150
-    fi
-    if (( ${#cmd} > col )); then
-      cmd="$(( ${#cmd} - col)) cut: ${cmd:0:col}"
-    fi
-    echo "+ $cmd" >&2
-  fi
-
-  if $debug_prompt; then
-    # we can type in commands here to inspect the program state.
-    read -r -e -p "DEBUG $ " debug_cmd
-    while [[ $debug_cmd ]]; do
-      eval $debug_cmd
-      read -r -e -p "DEBUG $ " debug_cmd
-    done
-    debug_prompt=false
-  fi
-}
-
-# usage: ux [COMMAND...]
-#
-# disable/unset debug-setx default command printing. Runs COMMAND if
-# given. Command arg exists only because the args would be otherwise
-# unused.
-ux() {
-  debug_print_default=false
-  if [[ $1 ]]; then "$@"; fi
-}
 
 # usage: h [COMMAND...]
 #
@@ -414,11 +274,10 @@ ux() {
 #
 # note: h = random free letter.
 h() {
+  # shellcheck disable=SC2034
+  debug_prompt=true
   if [[ $1 ]]; then
-    debug_prompt=true
     "$@"
-  else
-    debug_prompt=true
   fi
 }
 
@@ -428,153 +287,3 @@ die() {
   exit 1
 }
 
-# usage: u1 [COMMAND...]
-#
-# Disable debug-setx printing just for the next command.
-u1() {
-  # we have this strange logic because [[ is a command, easier to not
-  # have that be between debug_skip=true and $@ and trigger a debug
-  # trap.
-  if [[ $1 ]]; then
-    debug_skip=true
-    "$@"
-  else
-    debug_skip=true
-  fi
-}
-
-# usage: dx [COMMAND...]
-#
-# Undo ux() and reenable debug-setx printing.
-dx() {
-  if [[ $1 ]]; then
-    debug_print_default=true
-    "$@"
-  else
-    debug_print_default=true
-  fi
-}
-
-# usage: d1 [COMMAND...]
-#
-# For just one command, reenable debug-setx printing.
-d1() {
-  if [[ $1 ]]; then
-    debug_force_print=true
-    "$@"
-  else
-    debug_force_print=true
-  fi
-}
-
-
-# usage: setx-func [FUNCTION...]
-#
-# Do debug-setx printing within current function or FUNCTION(s) even
-# when called with function stack size greater than
-# $debug_max_stack_depth.
-setx-func() {
-  local new_func new_funcs found existing_func
-  if [[ ! -v debug_print_funcs ]]; then
-    debug_print_funcs=()
-  fi
-
-  e "${FUNCNAME[*]}"
-  if [[ $1 ]]; then
-    new_funcs="$*"
-  else
-    new_funcs="${FUNCNAME[0]}"
-  fi
-  for new_func in $new_funcs; do
-    found=false
-    for existing_func in ${debug_print_funcs[@]}; do
-      if [[ $existing_func == "$new_func" ]]; then
-        found=true
-        break
-      fi
-    done
-    if $found; then
-      break
-    fi
-    debug_print_funcs+=($new_func)
-  done
-}
-
-### end debug-setx related functions ###
-
-## begin debug-setx background / development notes
-#
-# I often end up writing little 5-10 line scripts. To log what they are doing,
-# I was annoyed with the available options. #1 There is set -x, which usually ends up
-# being > 50% useless lines, very anoying. #2
-# m() { printf "%s\n" "$*";
-#"$@"; } that annoyingly conflicts with command
-# redirected output, and I constantly forget to add it.
-#
-# Better option: debug trap, where we can print $BASH_COMMAND. The main
-# annoying thing about this is that $BASH_COMMAND doesn't have expanded
-# variables.
-#
-# options to expand variables in a $BASH_COMMAND:
-#
-# 1. get bash to do readline's shell-expand-line. I know a hacky way
-# with read, but it wasn't reliable when I tried it in a
-# prompt_command. I could probably create a c program that uses readline
-# to do it pretty easily
-#
-# 2. Use the prompt expansion features @P, but first escape the special
-# prompt characters if there are any. This was the option I went
-# with. It has a small flaw that I realized without calling a regex
-# substitution program, my escaping is not perfect: I temporarily insert
-# a long random string to identify "\\", but it is possible this string
-# could exist in the command and then I would improperly replace
-# it. However, my use case is simply viewing commands I intend to run
-# and I don't see any reason I would intend to run a command with that
-# or that even if I did, it would cause any serious problem to have it
-# be incorrectly displayed.
-#
-# NOTE: One imperfection with both of these, is that we don't want to
-# expand $() or ``, so I look for those chars and then avoid doing it. I
-# think the only way to avoid this would be to modify bash itself in
-# order to do shell-expand-line and then use the result, just as if you
-# pressed the key for it.
-#
-# \\ -> \\\\ : creates problem matching eg: \e
-#
-# alternate:
-#
-# \134 -> RANDOM_LONG_STRING
-#
-# \\ -> \134\134 : creates problem matching \134, we need to match \134!(\134), solved by the RANDOM_LONG_STRING
-#
-# \a -> \134a
-#
-# \D{*} and \123 -> \\&
-#
-# RANDOM_LONG_STRING -> \\134
-#
-# alternate, best:
-#
-# \\ -> RANDOM_LONG_STRING
-#
-# \a -> \\a
-#
-# \D{*} and \123 -> \\&
-#
-# RANDOM_LONG_STRING -> \\\\
-#
-# # incrementally built up test cases, where the output is expected to be the same as the initial _d
-#
-# _d='ok\\\\jyes'; _d="${_d//'\\'/SUBfopguensOfRifejmuSUB}" _d="${_d//\\[adehHjlnrstT@AuvVwW\!\#\$[\]]/\\&}" _d="${_d//SUBfopguensOfRifejmuSUB/'\\\\'}"; e "$_d  +  ${_d@P}"
-#
-# _d='ok\D{z_ds}yes'; _d="${_d//'\\'/SUBfopguensOfRifejmuSUB}" _d="${_d//\\[adehHjlnrstT@AuvVwW\!\#\$[\]]/\\&}" _d="${_d//\\D\{*\}/\\&}" _d="${_d//SUBfopguensOfRifejmuSUB/'\\\\'}"; e "$_d  +  ${_d@P}"
-#
-# _d='ok\144ye\134s'; _d="${_d//'\\'/SUBfopguensOfRifejmuSUB}" _d="${_d//\\[adehHjlnrstT@AuvVwW\!\#\$[\]]/\\&}" _d="${_d//\\D\{*\}/\\&}" _d="${_d//\\[012][0-9][0-9]/\\&}" _d="${_d//\\3[0-6][0-9]/\\&}" _d="${_d//\\37[0-7]/\\&}" _d="${_d//SUBfopguensOfRifejmuSUB/'\\\\'}"; e "$_d  +  ${_d@P}"
-#
-#
-# random interesting script:
-# x=4
-# echo "\$x ${BASH_COMMAND@P}"
-# Warning: Program '/bin/bash' crashed.
-#
-## end debug-setx background / development notes
index 54acd6b93b6b4eaa82ab9ffdcbc5fd7edbf725f4..7bbf8d14ae3fa3440bae22582dde13ae3b75c96b 100755 (executable)
--- a/g-lib.sh
+++ b/g-lib.sh
@@ -38,7 +38,7 @@ g() {
   fi
 
   if [[ $server == none ]]; then
-    server=
+    server=server
   else
     args+=" -s$server"
   fi
index 192b185372ece99a6fbd9728141406c83bdf49e7..4244a3a40324cbc493a131b963f9489e61cb6b34 100644 (file)
@@ -1,24 +1,16 @@
-# by default, new workspaces are created on whatever screen doesn't have
-# one active or else the current one. That is annoying, I have one
-# primary monitor, I don't want a new workspace created on secondary
-# monitor just because I happen be focused on it. This fixes that.
-workspace 1 output primary
-workspace 2 output MON-LEFT
-workspace 3 output MON-RIGHT
-workspace 4 output MON-RIGHT
-workspace 5 output MON-RIGHT
-workspace 6 output MON-RIGHT
-workspace 7 output MON-RIGHT
-workspace 8 output MON-RIGHT
-workspace 9 output MON-RIGHT
-workspace 10 output MON-RIGHT
+
 
 # todo: this is probably preferable on an x200. Makes the default layout be splitv instead of splith.
 #default_orientation vertical
 
+
 # bar is needed for kde connect
 bar {
 
+# conditionally set in myx
+#mode hide
+#hidden_state hide
+
 # keep it only on secondary monitor to save space and make for less
 # missing pixes in obs live stream. For docs on this, search "output
 # primary" in the i3 guide.
index f8bdc7bfd5349dc9690ea2cb5a93b63e984ae447..7f5245b9e0104ee05250754c736bd4d35da579e7 100644 (file)
@@ -65,6 +65,9 @@ bindsym $mod+r $ex "/a/bin/ds/xl"
 bindsym $mod+backslash $ex "scrot"
 
 bindsym $mod+t $ex "i3-set-layout splitv"
+## but this is set dynamically by myx
+bindsym $mod+Shift+t "move workspace to output next"
+
 
 bindsym $mod+g $ex "i3-set-layout tabbed"
 
@@ -154,6 +157,23 @@ bindsym $mod+8 workspace 9
 bindsym $mod+Shift+9 move container to workspace 10
 bindsym $mod+9 workspace 10
 
+# by default, new workspaces are created on whatever screen doesn't have
+# one active or else the current one. That is annoying, I have one
+# primary monitor, I don't want a new workspace created on secondary
+# monitor just because I happen be focused on it. This fixes that.
+
+workspace 1 output primary
+workspace 2 output primary
+workspace 3 output primary
+workspace 4 output primary
+workspace 5 output primary
+workspace 6 output primary
+workspace 7 output primary
+workspace 8 output primary
+workspace 9 output primary
+workspace 10 output primary
+
+
 bindsym $mod+m $ex "dunstctl close-all"
 bindsym $mod+Shift+m border toggle
 
@@ -229,4 +249,3 @@ for_window [class="focus" instance="focus"] floating disable
 client.focused          #4c7899 #285577 #ffffff #2e9ef4   #ff4400
 client.focused_inactive #333333 #5f676a #ffffff #484e50   #B8C8CD
 client.unfocused        #333333 #222222 #888888 #292d2e   #B8C8CD
-
index 4c72051dab5cd5a2b4193e031f15bf4394590020..f98592359a6cef6276caa312eb126c0623050e95 100755 (executable)
--- a/icc-load
+++ b/icc-load
 # https://wiki.archlinux.org/title/ICC_profiles said it was less
 # compatible, so I didn't bother.
 
+
+#    I got a viewsonic and found its color to be noticably different
+#    than the dell, so recalibrated. However, I've realized that to
+#    generate a better icc profile, I should extract some data from the
+#    windows software to calibrate my specific device, and to compare
+#    the icc profile it generates with displaycal, and to read the
+#    displaycal manual and test some things. Until then, I'm happy to
+#    just rely on osd settings that make the monitors look good and
+#    similar in a test video showing lots of skin tones.
+
+
+exit 0
+
 case $HOSTNAME in
   frodo)
 
-    /usr/bin/dispwin -v -d1 -c -I '/a/bin/ds/icc/U3225QE #1 2025-07-29 01-57 D6500 2.2 F-S XYZLUT+MTX.icc'
+
+#    /usr/bin/dispwin -v -d1 -c -I '/a/bin/ds/icc/U3225QE #1 2025-07-29 01-57 D6500 2.2 F-S XYZLUT+MTX.icc'
+#    /usr/bin/dispwin -v -d1 -c -I '/a/bin/ds/icc/U3225QE #1 2026-09-24 03-06 D6500 S XYZLUT+MTX.icc'
     # test that it worked with:
     # dispwin -v -d1 -V '/etc/xdgcolor/icc/devices/display/U3225QE #1 2025-07-29 01-57 D6500 2.2 F-S XYZLUT+MTX.icc'
     #
     # You can also watch the grey color of konsole change slightly when it loads.
+    /usr/bin/dispwin -v -d3 -c -I '/a/bin/ds/icc/VP2488-4K #1 2026-09-24 01-14 D6500 2.2 F-S XYZLUT+MTX.icc'
     ;;
 esac
diff --git a/icc/U3225QE #1 2026-09-24 03-06 D6500 S XYZLUT+MTX.icc b/icc/U3225QE #1 2026-09-24 03-06 D6500 S XYZLUT+MTX.icc
new file mode 100644 (file)
index 0000000..cab888f
Binary files /dev/null and b/icc/U3225QE #1 2026-09-24 03-06 D6500 S XYZLUT+MTX.icc differ
diff --git a/icc/VP2488-4K #1 2026-09-24 01-14 D6500 2.2 F-S XYZLUT+MTX.icc b/icc/VP2488-4K #1 2026-09-24 01-14 D6500 2.2 F-S XYZLUT+MTX.icc
new file mode 100644 (file)
index 0000000..a6a32c8
Binary files /dev/null and b/icc/VP2488-4K #1 2026-09-24 01-14 D6500 2.2 F-S XYZLUT+MTX.icc differ
diff --git a/machine_specific/frodo/filesystem/etc/default/isc-dhcp-server b/machine_specific/frodo/filesystem/etc/default/isc-dhcp-server
new file mode 100644 (file)
index 0000000..b8dd017
--- /dev/null
@@ -0,0 +1,18 @@
+# Defaults for isc-dhcp-server (sourced by /etc/init.d/isc-dhcp-server)
+
+# Path to dhcpd's config file (default: /etc/dhcp/dhcpd.conf).
+#DHCPDv4_CONF=/etc/dhcp/dhcpd.conf
+#DHCPDv6_CONF=/etc/dhcp/dhcpd6.conf
+
+# Path to dhcpd's PID file (default: /var/run/dhcpd.pid).
+#DHCPDv4_PID=/var/run/dhcpd.pid
+#DHCPDv6_PID=/var/run/dhcpd6.pid
+
+# Additional options to start dhcpd with.
+#      Don't use options -cf or -pf here; use DHCPD_CONF/ DHCPD_PID instead
+#OPTIONS=""
+
+# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
+#      Separate multiple interfaces with spaces, e.g. "eth0 eth1".
+INTERFACESv4="eth0"
+INTERFACESv6=""
diff --git a/machine_specific/frodo/filesystem/etc/dhcp/dhcpd.conf-orig b/machine_specific/frodo/filesystem/etc/dhcp/dhcpd.conf-orig
new file mode 100644 (file)
index 0000000..138993d
--- /dev/null
@@ -0,0 +1,111 @@
+# dhcpd.conf
+#
+# Sample configuration file for ISC dhcpd
+#
+# Attention: If /etc/ltsp/dhcpd.conf exists, that will be used as
+# configuration file instead of this file.
+#
+
+# option definitions common to all supported networks...
+option domain-name "example.org";
+option domain-name-servers ns1.example.org, ns2.example.org;
+
+default-lease-time 600;
+max-lease-time 7200;
+
+# The ddns-updates-style parameter controls whether or not the server will
+# attempt to do a DNS update when a lease is confirmed. We default to the
+# behavior of the version 2 packages ('none', since DHCP v2 didn't
+# have support for DDNS.)
+ddns-update-style none;
+
+# If this DHCP server is the official DHCP server for the local
+# network, the authoritative directive should be uncommented.
+#authoritative;
+
+# Use this to send dhcp log messages to a different log file (you also
+# have to hack syslog.conf to complete the redirection).
+#log-facility local7;
+
+# No service will be given on this subnet, but declaring it helps the
+# DHCP server to understand the network topology.
+
+#subnet 10.152.187.0 netmask 255.255.255.0 {
+#}
+
+# This is a very basic subnet declaration.
+
+#subnet 10.254.239.0 netmask 255.255.255.224 {
+#  range 10.254.239.10 10.254.239.20;
+#  option routers rtr-239-0-1.example.org, rtr-239-0-2.example.org;
+#}
+
+# This declaration allows BOOTP clients to get dynamic addresses,
+# which we don't really recommend.
+
+#subnet 10.254.239.32 netmask 255.255.255.224 {
+#  range dynamic-bootp 10.254.239.40 10.254.239.60;
+#  option broadcast-address 10.254.239.31;
+#  option routers rtr-239-32-1.example.org;
+#}
+
+# A slightly different configuration for an internal subnet.
+#subnet 10.5.5.0 netmask 255.255.255.224 {
+#  range 10.5.5.26 10.5.5.30;
+#  option domain-name-servers ns1.internal.example.org;
+#  option domain-name "internal.example.org";
+#  option subnet-mask 255.255.255.224;
+#  option routers 10.5.5.1;
+#  option broadcast-address 10.5.5.31;
+#  default-lease-time 600;
+#  max-lease-time 7200;
+#}
+
+# Hosts which require special configuration options can be listed in
+# host statements.   If no address is specified, the address will be
+# allocated dynamically (if possible), but the host-specific information
+# will still come from the host declaration.
+
+#host passacaglia {
+#  hardware ethernet 0:0:c0:5d:bd:95;
+#  filename "vmunix.passacaglia";
+#  server-name "toccata.example.com";
+#}
+
+# Fixed IP addresses can also be specified for hosts.   These addresses
+# should not also be listed as being available for dynamic assignment.
+# Hosts for which fixed IP addresses have been specified can boot using
+# BOOTP or DHCP.   Hosts for which no fixed address is specified can only
+# be booted with DHCP, unless there is an address range on the subnet
+# to which a BOOTP client is connected which has the dynamic-bootp flag
+# set.
+#host fantasia {
+#  hardware ethernet 08:00:07:26:c0:a5;
+#  fixed-address fantasia.example.com;
+#}
+
+# You can declare a class of clients and then do address allocation
+# based on that.   The example below shows a case where all clients
+# in a certain class get addresses on the 10.17.224/24 subnet, and all
+# other clients get addresses on the 10.0.29/24 subnet.
+
+#class "foo" {
+#  match if substring (option vendor-class-identifier, 0, 4) = "SUNW";
+#}
+
+#shared-network 224-29 {
+#  subnet 10.17.224.0 netmask 255.255.255.0 {
+#    option routers rtr-224.example.org;
+#  }
+#  subnet 10.0.29.0 netmask 255.255.255.0 {
+#    option routers rtr-29.example.org;
+#  }
+#  pool {
+#    allow members of "foo";
+#    range 10.17.224.10 10.17.224.250;
+#  }
+#  pool {
+#    deny members of "foo";
+#    range 10.0.29.10 10.0.29.230;
+#  }
+#}
diff --git a/machine_specific/frodo/filesystem/etc/network/interfaces.d/eth10g b/machine_specific/frodo/filesystem/etc/network/interfaces.d/eth10g
deleted file mode 100644 (file)
index 3770183..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-## example of 2 independent networks:
-
-# # top port
-# auto eth2
-# iface eth2 inet static
-# address 10.3.0.4/24
-
-# # bottom port
-# auto eth1
-# iface eth1 inet static
-# address 10.9.0.4/24
-
-
-## manual bond configuration example:
-# modprobe bonding
-# echo +bond0 > /sys/class/net/bonding_masters
-# echo +eth2 > /sys/class/net/bond0/bonding/slaves
-# echo +eth1 > /sys/class/net/bond0/bonding/slaves
-# ip addr add 10.3.0.4/24 dev bond0
-# ip link set bond0 up
-
-## things not needed for us, but could be useful elsewhere:
-
-# Set MII monitoring interval to 100ms for link detection
-#echo 100 > /sys/class/net/bond0/bonding/miimon
-
-## bonding mode (we happen to be using the default)
-#ip link set bond0 down
-#echo balance-rr > /sys/class/net/bond0/bonding/mode
-
-# Also, set slaves to down before adding them.
-
-# status lookup:
-# cat /proc/net/bonding/bond0
-# cat /sys/class/net/bond0/bonding/slaves
-# cat /sys/class/net/bonding_masters
-
-
-auto eth1
-iface eth1 inet static
-address 10.3.0.4/24
diff --git a/machine_specific/frodo/filesystem/etc/systemd/system/frodo-route.service b/machine_specific/frodo/filesystem/etc/systemd/system/frodo-route.service
new file mode 100644 (file)
index 0000000..804ebb5
--- /dev/null
@@ -0,0 +1,13 @@
+[Unit]
+Description=Setup of frodo routing rules
+After=network.target
+Wants=network.target
+StartLimitIntervalSec=0
+
+[Service]
+Type=oneshot
+RemainAfterExit=true
+ExecStart=/usr/local/bin/frodo-route
+
+[Install]
+WantedBy=multi-user.target
index 1e6017eb32c45cd3c2d51f2618cb77364312f807..128c86c11b4e17d8b3c0614b2e1a443ebfdd9b74 100644 (file)
@@ -3,7 +3,7 @@ Description=Initial setup of netns for wg-quick-tr %I
 
 [Service]
 Type=oneshot
-ExecStart=/usr/bin/flock -w 20 /tmp/newns.flock /usr/local/bin/newns -n 10.174.34 start %i
+ExecStart=/usr/bin/flock -w 20 /tmp/newns.flock /usr/local/bin/newns -n 10.174.1 start %i
 ExecStop=/usr/bin/flock -w 20 /tmp/newns.flock /usr/local/bin/newns stop %i
 RemainAfterExit=yes
 
index 2afc64314b1afe6bceb87aee5046af9978efbb5e..b2ef48afb5b5fc44f81cc640f791031201241142 100644 (file)
@@ -9,11 +9,11 @@ Documentation=man:wg(8)
 Type=simple
 ExecReload=/bin/bash -c 'exec /usr/bin/wg syncconf %i <(exec /usr/bin/wg-quick strip %i)'
 ExecStartPre=/sbin/iptables-restore /a/bin/distro-setup/transmission-firewall/netns.rules
-ExecStartPre=/usr/sbin/ip r add 10.8.0.0/24 via 10.174.34.1 dev veth1-client
+ExecStartPre=/usr/sbin/ip r add 10.8.0.0/24 via 10.174.1.1 dev veth1-client
 ExecStartPre=/usr/bin/wg-quick up %i
 ExecStart=/bin/sleep infinity
 ExecStopPost=/usr/bin/wg-quick down %i
-ExecStopPost=/usr/sbin/ip r del 10.8.0.0/24 via 10.174.34.1 dev veth1-client
+ExecStopPost=/usr/sbin/ip r del 10.8.0.0/24 via 10.174.1.1 dev veth1-client
 NetworkNamespacePath=/var/run/netns/%i
 BindReadOnlyPaths=/etc/tr-resolv:/run/systemd/resolve:norbind /etc/basic-nsswitch:/etc/resolved-nsswitch:norbind
 # copied from wg-quick@.service
diff --git a/machine_specific/kd/filesystem/etc/network/interfaces.d/eth10g b/machine_specific/kd/filesystem/etc/network/interfaces.d/eth10g
deleted file mode 100644 (file)
index 50d8bb4..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-
-## example of 2 independent networks:
-
-# # top right port
-# auto eth0
-# iface eth0 inet static
-# address 10.3.0.2/24
-
-# # bottom left port
-# auto eth2
-# iface eth2 inet static
-# address 10.9.0.2/24
-# #
-
-
-auto eth0
-iface eth0 inet static
-address 10.3.0.2/24
-#
index 7fbb17ceb20d2d98f434f918d78ba5b607acca80..de17a560c1fa10286c08c101c4cc483b86cb5165 100644 (file)
@@ -1 +1 @@
-ifconfig-push 10.5.5.34 255.255.255.0
+ifconfig-push 10.5.5.1 255.255.255.0
index 971ec5c1e7676f454d35675732a8b3539603528a..d4987ff76437af0db5ae986c39da1eba21b71290 100755 (executable)
 
 # SPDX-License-Identifier: GPL-3.0-or-later
 
-# TODO: track the actual generated exim config files in git. Somehow an
-# exim update screwed up the config file, probably by generating it
-# outside of the normal processes. It was fixed when I reran this file,
-# but then I didn't actually know for sure what went wrong.
+# TODO: on desktop, somehow
+# exim updates screwed up the config file, probably by generating it
+# outside of the normal processes. I'm tracking those changes via
+# copies to
+# /etc/etckeeper/fsmirror/var/lib/exim4/config.autogenerated
+# which is done via the script:
+# /a/c/filesystem/etc/etckeeper/commit.d/20iank-mirror. use that
+# to figure out a solution
+#
 
 # todo:
 # on bk (and fsf servers that run multiple exim4 daemons, eg eximfsf2 and eximfsf3),
@@ -412,9 +417,12 @@ son() {
   for service; do
     enabled=$(systemctl is-enabled $service 2>/dev/null ||:)
     if [[ $enabled != enabled ]]; then
-      m systemctl enable $service
+      m systemctl --now enable $service
+      continue
+    fi
+    if ! systemctl --quiet is-active $service; then
+      m systemctl start $service
     fi
-    m systemctl start $service
   done
 }
 mailhost() {
@@ -510,14 +518,6 @@ use_rspamd=false
 # installs epanicclean iptables-exim ip6tables-exim
 /a/bin/ds/install-my-scripts
 
-if [[ $(debian-codename-compat) == bionic ]]; then
-  cat >/etc/apt/preferences.d/spamassassin <<'EOF'
-Package: spamassassin sa-compile spamc
-Pin: release n=focal,o=Ubuntu
-Pin-Priority: 500
-EOF
-fi
-
 
 unit-exists() {
   systemctl cat $1 &>/dev/null
@@ -572,26 +572,6 @@ esac
 # bad packages that sometimes get automatically installed
 pu openresolv resolvconf
 
-soff openvpn
-
-
-if [[ $(debian-codename) == etiona ]]; then
-  # ip6tables stopped loading on boot. openvpn has reduced capability set,
-  # so running iptables as part of openvpn startup wont work. This should do it.
-  pi iptables-persistent
-  cat >/etc/iptables/rules.v6 <<'EOF'
-*mangle
-COMMIT
-*nat
-COMMIT
-EOF
-  # load it now.
-  m ip6tables -S >/dev/null
-fi
-
-# our nostart pi fails to avoid enabling
-
-
 
 # * initial dns config & daemon setup
 #
@@ -699,9 +679,12 @@ EOF
 # old file. remove when all hosts updated, 2023-09-11
 rm -fv /etc/exim4/conf.d/clamav_data_acl
 
+if ! groups clamav | grep -q Debian-exim; then
+  m usermod -a -G Debian-exim clamav
+fi
+
 pi-nostart clamav
 
-m usermod -a -G Debian-exim clamav
 
 u /etc/systemd/system/clamav-daemon.service.d/fix.conf <<EOF
 [Service]
@@ -4745,7 +4728,7 @@ EOF
     ;;&
   $MAIL_HOST)
     test_froms=(ian@iankelling.org z@zroe.org iank@gnu.org)
-    test_tos=(testignore@je.b8.nz testignore@amnimal.ninja jtuttle@gnu.org)
+    test_tos=(testignore@amnimal.ninja jtuttle@gnu.org)
 
     cat >>/etc/cron.d/mailtest <<EOF
 # 10 am friday
@@ -4755,7 +4738,7 @@ EOF
     ;;&
   bk)
     test_froms=(testignore@amnimal.ninja)
-    test_tos=(testignore@iankelling.org testignore@je.b8.nz)
+    test_tos=(testignore@iankelling.org)
     # We dont need to send from different addresses to the same
     # address. this breaks down our nice elegant logic of building up
     # froms and tos , so I just handle amnimal.ninja in a special case
index d17c3080379661991d2fb6830a735e50c2bddd1a..5f86212700d6e239969e2627e7760db5548a28fe 100755 (executable)
@@ -160,7 +160,7 @@ spamc-process() {
       BAYES_00|BODY_SINGLE_WORD|FROM_FMBLA_NEWDOM*|autolearn) : ;;
 
       # These have somewhat randomly been added and removed, resulting in useless alerts, so ignore them.
-      RCVD_IN_DNSWL_MED|DKIMWL_WL_HIGH) : ;;
+      RCVD_IN_DNSWL_MED|DKIMWL_WL_HIGH|RCVD_IN_DNSWL_LOW) : ;;
 
       SPF_HELO_NEUTRAL)
         # some of my domains use neutral spf, treat them the same.
@@ -263,7 +263,7 @@ main() {
   case $HOSTNAME in
     bk)
       folders=(/m/md/amnimal.ninja/testignore)
-      froms=(ian@iankelling.org z@zroe.org testignore@je.b8.nz iank@gnu.org)
+      froms=(ian@iankelling.org z@zroe.org iank@gnu.org)
       ;;
     je)
       froms=(ian@iankelling.org z@zroe.org iank@gnu.org testignore@amnimal.ninja)
@@ -272,7 +272,7 @@ main() {
     *)
       folders=(/m/md/l/testignore)
       # save some cpu cycles
-      froms=(testignore@je.b8.nz testignore@amnimal.ninja ian@iankelling.org z@zroe.org)
+      froms=(testignore@amnimal.ninja ian@iankelling.org z@zroe.org)
       if ! $int; then
         ### begin rsyncing fencepost email ###
         # We dont want to exit if rsync fails, that will get caught by
diff --git a/myx b/myx
index 9f03a1225cc9b05e39744f75b43f191f3e320b62..69bd02aa6e47c137d3effdf515d86900a4c5793a 100755 (executable)
--- a/myx
+++ b/myx
@@ -27,26 +27,18 @@ usage() {
   cat <<EOF
 Usage: $script_name [OPTIONS]
 
-Turns on/off secondary monitor.
-
-Sets resolution.
-
-Alters i3 config.
+Alters i3 config depending on host & a few other things.
 
 note: I used to run it in ~/.xsession, but then I made it sudo which
 doesn't work with that.
 
--n  Dry run
-
--f  No split, full resolution, like the screen would be without any
-    modifications. This happens automatically for small screens.
+note: sometimes windows end up on workspaces that we don't have keybinds
+to switch to, like 12. I don't yet know a good solution, but some useful
+commands:
 
--r  Restart secondary monitor
-
--s split type. split monitor into 1 or more virtual screens
-   full (default): no split, full screen.
-   tall: half screen.
-   quarter: left side is 2 quarter screens, right is 1 tall screen
+i3-msg -t get_workspaces
+i3-msg workspace 11
+i3-msg workspace 12
 
 
 
@@ -67,23 +59,10 @@ i3() {
     i3-msg "$@"
   fi
 }
-xmod() {
-  xrandr "$@"
-  gen_arg=-r
-}
 
 date "+%A, %B %d, %r, %S seconds"
 
 
-dry_run=false
-downres=false
-quarter=false
-tall=false
-restart=false
-
-
-xf=$(mktemp)
-xrandr >$xf
 
 m() {
   if $dry_run; then
@@ -93,108 +72,12 @@ m() {
   fi
 }
 
-
-
-primary_info=$(awk '$2 == "connected" && $3 == "primary" {print $1,$4}' $xf)
-
-secondary_out=$(awk '$2 == "connected" && $3 != "primary" {print $1}' $xf)
-# Some systems only have a non-primary connected.
-if [[ ! $primary_info ]]; then
-  primary_info=$(awk '$2 == "connected" {print $1,$3}' $xf)
-  xrandr --output $secondary_out --primary
-  secondary_out=
-fi
-
-# res_info eg: 3840x2160+1920+0
-read -r primary_out primary_res_info <<<"$primary_info"
-
-primary_res=${primary_res_info%%+*}
-primary_x=${primary_res%x*}
-primary_y=${primary_res#*x}
-
-if [[ $secondary_out ]]; then
-
-  x_offset=$primary_x
-  left_right_arg=--right-of
-
-  # dp-1 moves from left to right sometimes, i just move it out of the
-  # conditional and comment it as needed.
-
-  winchair=false
-  if edid-test 192efbdcef; then
-    winchair=true
-  fi
-
-  if $winchair; then
-    left_right_arg=--left-of
-    x_offset=0
-  fi
-
-
-  # its a small monitor, so I run:
-  # startx -- -dpi 120
-  #
-  # And x decides the primary display should have non-full
-  # resolution. This is a quick hopefully temporary fix.
-  if $winchair; then
-    xrandr --output eDP-1 --mode 1920x1200
-  fi
-
-
-  left_right_arg="$left_right_arg $primary_out"
-
-  target_out=$secondary_out
-  target_res=$(grep -A1 -E "^$secondary_out " $xf | tail -n1 | awk '{print $1}')
-  target_x=${target_res%x*}
-  target_y=${target_res#*x}
-else
-  target_out=$primary_out
-  x_offset=0
-  target_res=$primary_res
-  target_x=$primary_x
-  target_y=$primary_y
-fi
-
-
-if (( target_x <= 1280 )); then
-  quarter=false
-  tall=false
-elif (( target_x <= 1920 )); then
-  quarter=false
-  tall=true
-fi
-
-
 ##### begin command line parsing ########
 
-temp=$(getopt -l help fnrs: "$@") || usage 1
+temp=$(getopt -l help h "$@") || usage 1
 eval set -- "$temp"
 while true; do
   case $1 in
-    -f)
-      downres=false
-      quarter=false
-      tall=false
-      ;;
-    -n) dry_run=true ;;
-    -s)
-      case $2 in
-        tall)
-          tall=true
-          quarter=false
-          ;;
-        quarter)
-          tall=false
-          quarter=true
-          ;;
-        full)
-          tall=false
-          quarter=false
-          ;;
-      esac
-      shift
-      ;;
-    -r) restart=true ;;
     -h|--help) usage 0 ;;
     --) shift; break ;;
     *) echo "$0: Internal error! unexpected args: $*" ; exit 1 ;;
@@ -205,136 +88,29 @@ done
 ##### end command line parsing ########
 
 
-if $downres && (( target_x > 2560 )); then
-  target_x=2560
-  target_y=1440
-  target_res=${target_x}x$target_y
+if [[ $HOSTNAME == frodo ]]; then
+  # saved arandr command
+  xrandr --output HDMI-0 --mode 3840x2160 --pos 11520x0 --rotate normal --output DP-0 --primary --mode 3840x2160 --pos 0x0 --rotate normal --output DP-1 --off --output DP-2 --mode 3840x2160 --pos 3840x0 --rotate normal --output DP-3 --off --output DP-4 --mode 3840x2160 --pos 7680x0 --rotate normal --output DP-5 --off
 fi
 
 
-half_x=$(( target_x / 2 ))
-half_y=$(( target_y / 2 ))
-
-
-for mon_suffix in TOP-LEFT BOTTOM-LEFT LEFT RIGHT; do
-  if xrandr --listmonitors | awk '$2 == "MON-'$mon_suffix\" |grep . >/dev/null; then
-    m xmod --delmonitor MON-$mon_suffix
-  fi
-done
-
-if [[ ! $secondary_out ]] || grep -A1 disconnected $xf | grep '^[[:space:]]'; then
-  # gets rid of leftover secondary
-  if [[ $HOSTNAME != frodo ]]; then
-  m xmod --auto
-
-  # new monitor on frodo, I've been having to run this to get the full refresh rate:
-  # xrandr --output DP-0 --mode 3840x2160  --rate 120
-  # testing if this xmod is getting in the way.
-  fi
-fi
-
-if [[ $secondary_out ]] && $restart; then
-  m xmod --output $secondary_out --off
-  m sleep 2
-fi
-
-if [[ $secondary_out || $primary_res != "$target_res" ]]; then
-  m xmod --output $target_out $left_right_arg --mode $target_res
-fi
-
-if $tall; then
-  # 298 & 336 are millimeters. I took them from a monitor I was using. I
-  # don't know if they are important, I assume not important enough to
-  # change for different monitors.
-  m xmod --setmonitor MON-LEFT $half_x/298x$target_y/336+$x_offset+0 $target_out
-  m xmod --setmonitor MON-RIGHT $half_x/298x$target_y/336+$(( x_offset + half_x ))+0 none
-
-elif $quarter; then
-  m xmod --setmonitor MON-LEFT $half_x/298x$half_y/336+$x_offset+0 $target_out
-  # note: this bottom left is buggy when it comes to context menus,
-  # including in web pages. In the tall configuration, I sometimes see
-  # them in another "monitor" area, but with this bottom left monitor,
-  # they aren't displayed at all, as if the window system is displaying
-  # them off screen. When that happens, I just switch to the tall
-  # configuration, use the dialog, and them maybe switch back.
-  m xmod --setmonitor MON-BOTTOM-LEFT $half_x/298x$half_y/336+$x_offset+$half_y none
-  m xmod --setmonitor MON-RIGHT $half_x/298x$target_y/336+$(( x_offset + half_x ))+0 none
-fi
-
-
-## begin i3 config ##
-move_outputs=()
-ws_outputs=()
-if [[ $secondary_out ]]; then
-  ws1_output=$primary_out
-  move_outputs=($primary_out)
-elif $tall || $quarter; then
-  ws1_output=MON-RIGHT
-fi
-
-ws_outputs=(
-  $ws1_output
-)
-
-
-if $tall; then
-  ws_outputs+=(
-    MON-LEFT
-    MON-RIGHT
-  )
-  move_outputs+=(MON-RIGHT)
-elif $quarter; then
-  ws_outputs+=(
-    MON-LEFT
-    MON-BOTTOM-LEFT
-    MON-RIGHT
-  )
-  move_outputs+=(MON-BOTTOM-LEFT MON-RIGHT)
-elif [[ $secondary_out ]]; then
-  move_outputs+=($secondary_out)
-  ws_outputs+=($secondary_out)
-
-fi
-
-#echo d1 ${ws_outputs[@]}
-
-rm -f ~/i3-myx.conf
-total_ws_count=11
-for (( i=0; i<total_ws_count; i++ )); do
-  ws=$(( i+1 ))
-  tmp=${ws_outputs[$i]}
-  # use the last output in the array for all remaining workspaces
-  if [[ $tmp ]]; then
-    ws_out=$tmp
-  fi
-  echo "workspace $ws output $ws_out" >>~/i3-myx.conf
-done
-
 {
   cat /a/bin/ds/i3-sway/bar.conf
 
-  ## for when we are temporarily running some automation which auto-unhides the bar constantly
-  ## and overlaps the bottom of windows, so for now, i'm unconditionally
-  ## displaying it. When that is done, remove the below echo and
-  ## uncomment the conditional below.
+
+  ## I made this conditional once when running some automation which
+  ## auto-unhides the bar constantly and overlaps the bottom of windows
+  #
   #echo "}"
 
-  if [[ $secondary_out ]]; then
-    echo "}"
-  else
     echo 'mode hide
 hidden_state hide
 }'
-  fi
 
 } >> ~/i3-myx.conf
 
-if (( ${#move_outputs[@]} )); then
-  echo "bindsym \$mod+Shift+t move workspace to output ${move_outputs[*]} # set by myx" >>~/i3-myx.conf
-else
-  echo "# bindsym \$mod+Shift+t move workspace to output XXX XXX # note: if we had logical X screen or multimons, this would be set by myx" >>~/i3-myx.conf
-fi
 # give it some time to reload or adjust to new x settings.
+sleep 1
 
 # i3-msg -t get_outputs | jq -C .
 # showed
@@ -365,57 +141,8 @@ fi
 # This was incorrect. The correct thing is that DP-1 is active, HDMI-2 is not active.
 # Restarting i3 did not help.
 
-sleep 1
-m /a/bin/ds/i3-sway/gen $gen_arg
-
-if (( ${#ws_outputs[@]} )); then
-
-  declare -A ws_expected_out
-
-  for (( i=0; i<total_ws_count; i++ )); do
-    ws=$(( i+1 ))
-    tmp=${ws_outputs[$i]}
-    # use the last output in the array for all remaining workspaces
-    if [[ $tmp ]]; then
-      ws_out=$tmp
-    fi
-    ws_expected_out[$((i + 1))]=$ws_out
-  done
-
-  # If we move a workspace, it could cause an empty workspace to
-  # disappear, and then we need to refresh our list. refresh_count is a
-  # sanity check to make sure this doesn't go wrong and cause an
-  # infinite loop.
-  refresh_count=0
-  refresh_workspaces=true
-  while $refresh_workspaces; do
-    if (( refresh_count > 20 )); then
-      cat <<'EOF' >&2
-
-ERROR: moving workspaces is not working as expected I've seen it happen
-that an output should not exist anymore. Restarting i3 fixed it, reloading did not.
-This script did a restart, but it might need a sleep before doing so.
-EOF
-      exit 1
-    fi
-    refresh_count=$(( refresh_count + 1 ))
-    refresh_workspaces=false
-    tmps=$(i3 -t get_workspaces)
-    tmps=$(jq -r '.[] | .num, .output' <<<"$tmps")
-    while read -r ws; do
-      read -r output || break
-      if [[ $ws != [0-9] && $ws != 10 ]]; then
-        echo "$0: error: unexpected workspace found: $ws. continuing"
-        continue
-      fi
-      if [[ ${ws_expected_out[$ws]} != "$output" ]]; then
-        m i3 '[workspace="'$ws'"]' move workspace to output ${ws_expected_out[$ws]}
-        refresh_workspaces=true
-        break
-      fi
-    done <<<"$tmps"
-  done
-fi
+m /a/bin/ds/i3-sway/gen
+
 ## end i3 config ##
 
 
@@ -425,21 +152,3 @@ m /a/exe/input-setup
 echo -n "myx end: "
 date "+%A, %B %d, %r, %S seconds"
 
-
-# myx -f
-# Tuesday, July 23, 05:54:37 PM, 37 seconds
-# myx: xmod --delmonitor MON-LEFT
-# myx: xmod --delmonitor MON-RIGHT
-# myx: xmod --output DP-1 --right-of eDP-1 --mode 3840x2160
-# d1 eDP-1 DP-1
-# myx: /a/bin/ds/i3-sway/gen -r
-# /a/bin/ds/i3-sway/gen: i3-msg restart
-# [{"success":true}]
-# myx: i3 [workspace="2"] move workspace to output DP-1
-# ERROR: No output matched
-# [{"success":false,"error":"No output matched"}]
-# /a/exe/myx:63: `i3-msg "$@"' returned 2
-#   from /a/exe/myx:63:in `i3 [workspace="2"] move workspace to output DP-1'
-#   from /a/exe/myx:88:in `m i3 [workspace="2"] move workspace to output DP-1'
-#   from /a/exe/myx:330:in `main -f'
-# /a/exe/myx: exiting with status 2
diff --git a/myx-old b/myx-old
new file mode 100755 (executable)
index 0000000..64ad5b5
--- /dev/null
+++ b/myx-old
@@ -0,0 +1,439 @@
+#!/bin/bash
+# I, Ian Kelling, follow the GNU license recommendations at
+# https://www.gnu.org/licenses/license-recommendations.en.html. They
+# recommend that small programs, < 300 lines, be licensed under the
+# Apache License 2.0. This file contains or is part of one or more small
+# programs. If a small program grows beyond 300 lines, I plan to change
+# to a recommended GPL license.
+
+# Copyright 2024 Ian Kelling
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -e; . /usr/local/lib/bash-bear; set +e
+
+script_name="${0##*/}"
+usage() {
+  cat <<EOF
+Usage: $script_name [OPTIONS]
+
+Turns on/off secondary monitor.
+
+Sets resolution.
+
+Alters i3 config.
+
+note: I used to run it in ~/.xsession, but then I made it sudo which
+doesn't work with that.
+
+note: sometimes windows end up on workspaces that we don't have keybinds
+to switch to, like 12. I don't yet know a good solution, but some useful
+commands:
+
+i3-msg -t get_workspaces
+i3-msg workspace 11
+i3-msg workspace 12
+
+
+-n  Dry run
+
+-f  No split, full resolution, like the screen would be without any
+    modifications. This is default.
+
+-r  Restart secondary monitor
+
+-s split type. split monitor into 1 or more virtual screens
+   full (default): no split, full screen.
+   tall: half screen.
+   quarter: left side is 2 quarter screens, right is 1 tall screen
+   auto: One of the above depending on screen size.
+
+
+
+-h|--help             Print help and exit.
+
+Note: Uses GNU getopt options parsing style
+EOF
+  exit $1
+}
+
+edid-test() {
+  local edid_10_prefix="$1"
+  sha256sum /sys/class/drm/*/edid | grep -Eq ^$edid_10_prefix &>/dev/null || [[ $? == 141 ]]
+}
+
+i3() {
+  if [[ $I3SOCK ]]; then
+    i3-msg "$@"
+  fi
+}
+xmod() {
+  xrandr "$@"
+  gen_arg=-r
+}
+
+date "+%A, %B %d, %r, %S seconds"
+
+
+dry_run=false
+downres=false
+quarter=false
+tall=false
+restart=false
+
+
+xf=$(mktemp)
+xrandr >$xf
+
+m() {
+  if $dry_run; then
+    printf "$script_name: dry run: %s\n" "$*"
+  else
+    printf "$script_name: %s\n" "$*"; "$@"
+  fi
+}
+
+
+
+primary_info=$(awk '$2 == "connected" && $3 == "primary" {print $1,$4}' $xf)
+
+secondary_out=$(awk '$2 == "connected" && $3 != "primary" {print $1}' $xf)
+# Some systems only have a non-primary connected.
+if [[ ! $primary_info ]]; then
+  primary_info=$(awk '$2 == "connected" {print $1,$3}' $xf)
+  xrandr --output $secondary_out --primary
+  secondary_out=
+fi
+
+# res_info eg: 3840x2160+1920+0
+read -r primary_out primary_res_info <<<"$primary_info"
+
+primary_res=${primary_res_info%%+*}
+primary_x=${primary_res%x*}
+primary_y=${primary_res#*x}
+
+if [[ $secondary_out ]]; then
+
+  x_offset=$primary_x
+  left_right_arg=--right-of
+
+  left_right_arg="$left_right_arg $primary_out"
+
+  target_out=$secondary_out
+  target_res=$(grep -A1 -E "^$secondary_out " $xf | tail -n1 | awk '{print $1}')
+  target_x=${target_res%x*}
+  target_y=${target_res#*x}
+else
+  target_out=$primary_out
+  x_offset=0
+  target_res=$primary_res
+  target_x=$primary_x
+  target_y=$primary_y
+fi
+
+tall=false
+quarter=false
+downres=false
+
+
+##### begin command line parsing ########
+
+temp=$(getopt -l help fnrs: "$@") || usage 1
+eval set -- "$temp"
+while true; do
+  case $1 in
+    -f)
+      downres=false
+      quarter=false
+      tall=false
+      ;;
+    -n) dry_run=true ;;
+    -s)
+      case $2 in
+        auto)
+          if (( target_x <= 1280 )); then
+            quarter=false
+            tall=false
+          elif (( target_x <= 1920 )); then
+            quarter=false
+            tall=true
+          fi
+          ;;
+        tall)
+          tall=true
+          quarter=false
+          ;;
+        quarter)
+          tall=false
+          quarter=true
+          ;;
+        full)
+          tall=false
+          quarter=false
+          ;;
+      esac
+      shift
+      ;;
+    -r) restart=true ;;
+    -h|--help) usage 0 ;;
+    --) shift; break ;;
+    *) echo "$0: Internal error! unexpected args: $*" ; exit 1 ;;
+  esac
+  shift
+done
+
+##### end command line parsing ########
+
+
+if $downres && (( target_x > 2560 )); then
+  target_x=2560
+  target_y=1440
+  target_res=${target_x}x$target_y
+fi
+
+
+half_x=$(( target_x / 2 ))
+half_y=$(( target_y / 2 ))
+
+
+for mon_suffix in TOP-LEFT BOTTOM-LEFT LEFT RIGHT; do
+  if xrandr --listmonitors | awk '$2 == "MON-'$mon_suffix\" |grep . >/dev/null; then
+    m xmod --delmonitor MON-$mon_suffix
+  fi
+done
+
+if [[ ! $secondary_out ]] || grep -A1 disconnected $xf | grep '^[[:space:]]'; then
+  # gets rid of leftover secondary
+  if [[ $HOSTNAME != frodo ]]; then
+    m xmod --auto
+
+    # new monitor on frodo, I've been having to run this to get the full refresh rate:
+    # xrandr --output DP-0 --mode 3840x2160  --rate 120
+    # testing if this xmod is getting in the way.
+  fi
+fi
+
+if [[ $secondary_out ]] && $restart; then
+  m xmod --output $secondary_out --off
+  m sleep 2
+fi
+
+if [[ $secondary_out || $primary_res != "$target_res" ]]; then
+  : # todo: update this based on current monitor setup.
+  #m xmod --output $target_out $left_right_arg --mode $target_res
+fi
+
+if $tall; then
+  # 298 & 336 are millimeters. I took them from a monitor I was using. I
+  # don't know if they are important, I assume not important enough to
+  # change for different monitors.
+  m xmod --setmonitor MON-LEFT $half_x/298x$target_y/336+$x_offset+0 $target_out
+  m xmod --setmonitor MON-RIGHT $half_x/298x$target_y/336+$(( x_offset + half_x ))+0 none
+
+elif $quarter; then
+  m xmod --setmonitor MON-LEFT $half_x/298x$half_y/336+$x_offset+0 $target_out
+  # note: this bottom left is buggy when it comes to context menus,
+  # including in web pages. In the tall configuration, I sometimes see
+  # them in another "monitor" area, but with this bottom left monitor,
+  # they aren't displayed at all, as if the window system is displaying
+  # them off screen. When that happens, I just switch to the tall
+  # configuration, use the dialog, and them maybe switch back.
+  m xmod --setmonitor MON-BOTTOM-LEFT $half_x/298x$half_y/336+$x_offset+$half_y none
+  m xmod --setmonitor MON-RIGHT $half_x/298x$target_y/336+$(( x_offset + half_x ))+0 none
+fi
+
+
+## begin i3 config ##
+move_outputs=()
+ws_outputs=()
+if [[ $secondary_out ]]; then
+  ws1_output=$primary_out
+  move_outputs=($primary_out)
+elif $tall || $quarter; then
+  ws1_output=MON-RIGHT
+fi
+
+ws_outputs=(
+  $ws1_output
+)
+
+
+if $tall; then
+  ws_outputs+=(
+    MON-LEFT
+    MON-RIGHT
+  )
+  move_outputs+=(MON-RIGHT)
+elif $quarter; then
+  ws_outputs+=(
+    MON-LEFT
+    MON-BOTTOM-LEFT
+    MON-RIGHT
+  )
+  move_outputs+=(MON-BOTTOM-LEFT MON-RIGHT)
+elif [[ $secondary_out ]]; then
+  move_outputs+=($secondary_out)
+  ws_outputs+=($secondary_out)
+
+fi
+
+#echo d1 ${ws_outputs[@]}
+
+rm -f ~/i3-myx.conf
+total_ws_count=11
+for (( i=0; i<total_ws_count; i++ )); do
+  ws=$(( i+1 ))
+  tmp=${ws_outputs[$i]}
+  # use the last output in the array for all remaining workspaces
+  if [[ $tmp ]]; then
+    ws_out=$tmp
+  fi
+  if [[ $HOSTNAME != frodo ]]; then
+    echo "workspace $ws output $ws_out" >>~/i3-myx.conf
+  fi
+done
+
+{
+  cat /a/bin/ds/i3-sway/bar.conf
+
+  ## for when we are temporarily running some automation which auto-unhides the bar constantly
+  ## and overlaps the bottom of windows, so for now, i'm unconditionally
+  ## displaying it. When that is done, remove the below echo and
+  ## uncomment the conditional below.
+  #echo "}"
+
+  if [[ $secondary_out && $HOSTNAME != frodo ]]; then
+    echo "}"
+  else
+    echo 'mode hide
+hidden_state hide
+}'
+  fi
+
+} >> ~/i3-myx.conf
+
+if (( ${#move_outputs[@]} )); then
+  echo "bindsym \$mod+Shift+t move workspace to output next # set by myx" >>~/i3-myx.conf
+  #echo "bindsym \$mod+Shift+t move workspace to output ${move_outputs[*]} # set by myx" >>~/i3-myx.conf
+else
+  echo "# bindsym \$mod+Shift+t move workspace to output XXX XXX # note: if we had logical X screen or multimons, this would be set by myx" >>~/i3-myx.conf
+fi
+# give it some time to reload or adjust to new x settings.
+
+# i3-msg -t get_outputs | jq -C .
+# showed
+# {
+#   "name": "HDMI-2",
+#   "active": true,
+#   "primary": false,
+#   "rect": {
+#     "x": 1920,
+#     "y": 0,
+#     "width": 3840,
+#     "height": 2160
+#   },
+#   "current_workspace": "3"
+# },
+# {
+#   "name": "DP-1",
+#   "active": false,
+#   "primary": false,
+#   "rect": {
+#     "x": 1920,
+#     "y": 0,
+#     "width": 3840,
+#     "height": 2160
+#   },
+#   "current_workspace": null
+# }
+# This was incorrect. The correct thing is that DP-1 is active, HDMI-2 is not active.
+# Restarting i3 did not help.
+
+sleep 1
+m /a/bin/ds/i3-sway/gen $gen_arg
+
+if (( ${#ws_outputs[@]} )); then
+
+  declare -A ws_expected_out
+
+  for (( i=0; i<total_ws_count; i++ )); do
+    ws=$(( i+1 ))
+    tmp=${ws_outputs[$i]}
+    # use the last output in the array for all remaining workspaces
+    if [[ $tmp ]]; then
+      ws_out=$tmp
+    fi
+    ws_expected_out[$((i + 1))]=$ws_out
+  done
+
+  # If we move a workspace, it could cause an empty workspace to
+  # disappear, and then we need to refresh our list. refresh_count is a
+  # sanity check to make sure this doesn't go wrong and cause an
+  # infinite loop.
+  refresh_count=0
+  refresh_workspaces=true
+  while $refresh_workspaces; do
+    if (( refresh_count > 20 )); then
+      cat <<'EOF' >&2
+
+ERROR: moving workspaces is not working as expected I've seen it happen
+that an output should not exist anymore. Restarting i3 fixed it, reloading did not.
+This script did a restart, but it might need a sleep before doing so.
+EOF
+      exit 1
+    fi
+    refresh_count=$(( refresh_count + 1 ))
+    refresh_workspaces=false
+    tmps=$(i3 -t get_workspaces)
+    tmps=$(jq -r '.[] | .num, .output' <<<"$tmps")
+    while read -r ws; do
+      read -r output || break
+      if [[ $ws != [0-9] && $ws != 10 ]]; then
+        echo "$0: error: unexpected workspace found: $ws. continuing"
+        continue
+      fi
+      if [[ ${ws_expected_out[$ws]} != "$output" ]]; then
+        m i3 '[workspace="'$ws'"]' move workspace to output ${ws_expected_out[$ws]}
+        refresh_workspaces=true
+        break
+      fi
+    done <<<"$tmps"
+  done
+fi
+## end i3 config ##
+
+
+
+m /a/exe/input-setup
+
+echo -n "myx end: "
+date "+%A, %B %d, %r, %S seconds"
+
+
+# myx -f
+# Tuesday, July 23, 05:54:37 PM, 37 seconds
+# myx: xmod --delmonitor MON-LEFT
+# myx: xmod --delmonitor MON-RIGHT
+# myx: xmod --output DP-1 --right-of eDP-1 --mode 3840x2160
+# d1 eDP-1 DP-1
+# myx: /a/bin/ds/i3-sway/gen -r
+# /a/bin/ds/i3-sway/gen: i3-msg restart
+# [{"success":true}]
+# myx: i3 [workspace="2"] move workspace to output DP-1
+# ERROR: No output matched
+# [{"success":false,"error":"No output matched"}]
+# /a/exe/myx:63: `i3-msg "$@"' returned 2
+#   from /a/exe/myx:63:in `i3 [workspace="2"] move workspace to output DP-1'
+#   from /a/exe/myx:88:in `m i3 [workspace="2"] move workspace to output DP-1'
+#   from /a/exe/myx:330:in `main -f'
+# /a/exe/myx: exiting with status 2
diff --git a/pkgs b/pkgs
index f786c6936ce041e9fc927c9543dca5ed96422e59..2be63fb3c58a776113895ca863b13c691cf9954f 100644 (file)
--- a/pkgs
+++ b/pkgs
@@ -126,6 +126,7 @@ p3=(
   debug-me
   debootstrap
   debconf-doc
+  dejagnu
   devscripts
   ddcutil
   dillo
index c5f528a0a6a296d56a7587e300cb80587572718b..7587408d8c18592cc2ebac7ac000b9ece0eac6c5 100755 (executable)
@@ -101,11 +101,14 @@ if dpkg -s rss2email &>/dev/null; then
   fi
 fi
 
-if [[ $HOSTNAME == "$HOST2" ]]; then
-  m sudo -u iank XDG_RUNTIME_DIR=/run/user/1000 systemctl --no-block --user enable --now awatch.service ||:
-else
-  m sudo -u iank XDG_RUNTIME_DIR=/run/user/1000 systemctl --no-block --user disable --now awatch.service ||:
-fi
+# commented because i'm trying out the status bar that stays hidden until super is
+# pressed, which causes an awatch error. Don't feel like fixing it
+# atm.
+# if [[ $HOSTNAME == "$HOST2" ]]; then
+#   m sudo -u iank XDG_RUNTIME_DIR=/run/user/1000 systemctl --no-block --user enable --now awatch.service ||:
+# else
+#   m sudo -u iank XDG_RUNTIME_DIR=/run/user/1000 systemctl --no-block --user disable --now awatch.service ||:
+# fi
 
 
 # todo: whats going on here? figure out if this should be removed.
index 92c5b85c5fe729954836acb146d50bfe21a41a12..1882acee8a799eac1dca7b021a78b0a6acc8b4a7 100755 (executable)
@@ -452,7 +452,7 @@ write-status() {
         mtest_found=true
       fi
     done
-    if (( mtest_count < 4 )); then
+    if (( mtest_count < 3 )); then
       mtest_found=true
     fi
     if $mtest_found; then