summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--krebs/2configs/security-workarounds.nix2
-rw-r--r--krebs/3modules/external/mic92.nix66
-rw-r--r--krebs/3modules/setuid.nix16
-rw-r--r--tv/1systems/au/config.nix1
-rw-r--r--tv/1systems/bu/config.nix1
-rw-r--r--tv/1systems/xu/config.nix1
-rw-r--r--tv/2configs/xsessions/default.nix5
-rw-r--r--tv/2configs/xsessions/urxvtd.nix15
-rw-r--r--tv/3modules/default.nix1
-rw-r--r--tv/3modules/org.freedesktop.machine1.host-shell.nix28
-rw-r--r--tv/5pkgs/haskell/xmonad-tv/src/main.hs8
-rw-r--r--tv/5pkgs/simple/stardict/default.nix235
12 files changed, 371 insertions, 8 deletions
diff --git a/krebs/2configs/security-workarounds.nix b/krebs/2configs/security-workarounds.nix
index 27d1f848..0743f2b4 100644
--- a/krebs/2configs/security-workarounds.nix
+++ b/krebs/2configs/security-workarounds.nix
@@ -1,6 +1,6 @@
{ config, lib, pkgs, ... }:
with import <stockholm/lib>;
{
- # https://github.com/berdav/CVE-2021-4034
+ # https://github.com/Lassulus/CVE-2021-4034
security.wrappers.pkexec.source = lib.mkForce (pkgs.writeText "pkexec" "");
}
diff --git a/krebs/3modules/external/mic92.nix b/krebs/3modules/external/mic92.nix
index cd11fb2c..27a2beed 100644
--- a/krebs/3modules/external/mic92.nix
+++ b/krebs/3modules/external/mic92.nix
@@ -805,10 +805,16 @@ in {
mickey = {
owner = config.krebs.users.mic92;
nets = rec {
+ internet = {
+ # mickey.dse.in.tum.de
+ ip4.addr = "131.159.102.10";
+ ip6.addr = "2a09:80c0:102::10";
+ aliases = [ "mickey.i" ];
+ };
retiolum = {
+ via = internet;
aliases = [ "mickey.r" ];
tinc.pubkey = ''
- Ed25519PublicKey = cE450gYxzp9kAzV5ytU9N7aV+WdnD7wQMjkPWV7r/bC
-----BEGIN RSA PUBLIC KEY-----
MIICCgKCAgEA7TwI3/tyl3z46Enr6p/0bpl5CpG6DZLxjAhsMcWBM+4xTL9s18IZ
2FGbyS3EyOBprMBQULrik1u0rfZ0AL8XdO6h+r1BD6XmlZtUu3FJaVeXrLBPGtC0
@@ -823,6 +829,64 @@ in {
RA8gQM/P3j1EmDvemlskWOoCLVELR40BtKdM9MFiGqxGMoNh3DvGWTECAwEAAQ==
-----END RSA PUBLIC KEY-----
'';
+ tinc.pubkey_ed25519 = "cE450gYxzp9kAzV5ytU9N7aV+WdnD7wQMjkPWV7r/bC";
+ };
+ };
+ };
+
+ astrid = {
+ owner = config.krebs.users.mic92;
+ nets = rec {
+ internet = {
+ # astrid.dse.in.tum.de
+ ip4.addr = "131.159.102.11";
+ ip6.addr = "2a09:80c0:102::11";
+ aliases = [ "astrid.i" ];
+ };
+ retiolum = {
+ aliases = [ "astrid.r" ];
+ tinc.pubkey = ''
+ -----BEGIN RSA PUBLIC KEY-----
+ MIIBCgKCAQEArYO78+rLxDYBxt1MZ4VDjdSvoxJ8/De5R+/Yo0Uh1vJJtlkQUfAK
+ o2uOQvX76Y1EByAu1hMKsquDJrmnEQKyaBVUv1xkU9kQPxDoUkHdQaMoyjjCLKHV
+ 7OjRRQ+PCAjCVfaIR4P0pXGXShBYVqITdr8R/fH7f+M6I+s/H4KTo9zpRY9YUzXV
+ V6t3PCTMBXWxa2kNTSTe1zpGHccOd3FWs6r+0DZ2bPg/6Qh/VszQI7NXRqgSLNgi
+ J1+PaO0h9IfICNYYaWg1r9gh6nd52U9S2B6eipizrdWdyHuufWzn52liNztSEe9g
+ 5VC0PPAZFIxEkhoAP/HGTnNvXLOo960IXwIDAQAB
+ -----END RSA PUBLIC KEY-----
+ '';
+ tinc.pubkey_ed25519 = "I0rk5Co9QEuyramaxNSI2Rq43qgRF2tJr5Lf8nlBjUO";
+ };
+ };
+ };
+ dan = {
+ owner = config.krebs.users.mic92;
+ nets = rec {
+ internet = {
+ # dan.dse.in.tum.de
+ ip4.addr = "131.159.102.12";
+ ip6.addr = "2a09:80c0:102::12";
+ aliases = [ "dan.i" ];
+ };
+ retiolum = {
+ via = internet;
+ aliases = [ "dan.r" ];
+ tinc.pubkey = ''
+ -----BEGIN RSA PUBLIC KEY-----
+ MIICCgKCAgEAoZq+Nt1H+tcLRVE5LiJXyAItRIcIJNVeFenN54era7Yr0+OE7s14
+ r19N7g8cb3ytgbxb1P0t8Dd2ziKUdEoOdVK7/dqx6oM1lwjOBy4rtcGmy6hHGRhT
+ +Si6NxHnQVkswzL2/4DcBxg+D40GDIz0QlNhT7TC3TW6gtKbTopHMZoC3cyw1iXF
+ iZB8HEv22Daq+/gFt9rcV2cRhdsDIX3TEAu+wXhDMtB9V78CzgOHV7IBrlnQHTeq
+ 3TmcQ+AHKZB3nY5cUDvbSUWHOrG4CQ0w2pf034s7l3AMLClXcr0IORZtCgEhCmE5
+ tgg9Y6vKH2S0a25naf5rOFCvEXt8TZF9lCc42hfKCJo/LE2LoqKluAMUWgXUtv6s
+ Od6AcV5RW3QkgRiDi6niPVVAnDGSUfqUNaJhmBzlfD6PzwBpPlcODf5dk/H/FhzZ
+ nGpG4lptvknrBZxz9Vdyv3a/CE9VA5FbgDdOJMk5fbNG6XH4BoESjKQ/tHwvDRwO
+ Xz11V5MQYk4aYq++AgkoyCgw37rWqgR2WE/X9tV63qUAiBHJoZ48QPmqrZwEt8LC
+ 92eTKbxfl2iroqs5vBqKiXcRAWgXwO25rb+4CJUfD8b9AdAlm4unoCcoYluJ9rO1
+ 5xs2x/b09U3YXkMgO67cju+Vg68ROnihokH+5pyfuMMsHSAANC+uWD8CAwEAAQ==
+ -----END RSA PUBLIC KEY-----
+ '';
+ tinc.pubkey_ed25519 = "bEWH72WNDGtn6uGy1h1m3T8rH2pHoL8zNU1ADq4TW+L";
};
};
};
diff --git a/krebs/3modules/setuid.nix b/krebs/3modules/setuid.nix
index 64fedb91..b141c7de 100644
--- a/krebs/3modules/setuid.nix
+++ b/krebs/3modules/setuid.nix
@@ -30,6 +30,10 @@ with import <stockholm/lib>;
};
apply = toString;
};
+ capabilities = mkOption {
+ default = [];
+ type = types.listOf types.str;
+ };
owner = mkOption {
default = "root";
type = types.enum (attrNames users);
@@ -62,18 +66,26 @@ with import <stockholm/lib>;
inherit (cfg) envp filename;
};
dst = "${cfg.wrapperDir}/${cfg.name}";
- in ''
+ in /* sh */ ''
mkdir -p ${cfg.wrapperDir}
cp ${src} ${dst}
chown ${cfg.owner}.${cfg.group} ${dst}
chmod ${cfg.mode} ${dst}
+ ${optionalString (cfg.capabilities != []) /* sh */ ''
+ ${pkgs.libcap.out}/bin/setcap ${concatMapStringsSep "," shell.escape cfg.capabilities} ${dst}
+ ''}
'';
}));
};
imp = {
system.activationScripts."krebs.setuid" = stringAfter [ "wrappers" ]
- (concatMapStringsSep "\n" (getAttr "activate") (attrValues config.krebs.setuid));
+ (concatMapStringsSep "\n"
+ (cfg: /* sh */ ''
+ ${cfg.activate}
+ rm -f ${cfg.wrapperDir}/${cfg.name}.real
+ '')
+ (attrValues config.krebs.setuid));
};
in out
diff --git a/tv/1systems/au/config.nix b/tv/1systems/au/config.nix
index d9ba5391..2521059b 100644
--- a/tv/1systems/au/config.nix
+++ b/tv/1systems/au/config.nix
@@ -5,6 +5,7 @@
<stockholm/tv/2configs/hw/x220.nix>
<stockholm/tv/2configs/ppp.nix>
<stockholm/tv/2configs/retiolum.nix>
+ <stockholm/tv/2configs/xsessions>
];
krebs.build.host = config.krebs.hosts.au;
diff --git a/tv/1systems/bu/config.nix b/tv/1systems/bu/config.nix
index 69c5848f..11cdac39 100644
--- a/tv/1systems/bu/config.nix
+++ b/tv/1systems/bu/config.nix
@@ -10,6 +10,7 @@ in {
<stockholm/tv/2configs/gitconfig.nix>
<stockholm/tv/2configs/pulse.nix>
<stockholm/tv/2configs/retiolum.nix>
+ <stockholm/tv/2configs/xsessions>
];
environment.homeBinInPath = true;
diff --git a/tv/1systems/xu/config.nix b/tv/1systems/xu/config.nix
index 90d90ef3..05c5c11b 100644
--- a/tv/1systems/xu/config.nix
+++ b/tv/1systems/xu/config.nix
@@ -20,6 +20,7 @@ with import <stockholm/lib>;
<stockholm/tv/2configs/br.nix>
<stockholm/tv/2configs/xp-332.nix>
<stockholm/tv/2configs/xserver>
+ <stockholm/tv/2configs/xsessions>
<stockholm/tv/2configs/xserver/xkiller.nix>
{
environment.systemPackages = with pkgs; [
diff --git a/tv/2configs/xsessions/default.nix b/tv/2configs/xsessions/default.nix
new file mode 100644
index 00000000..384c9c5e
--- /dev/null
+++ b/tv/2configs/xsessions/default.nix
@@ -0,0 +1,5 @@
+{
+ imports = [
+ ./urxvtd.nix
+ ];
+}
diff --git a/tv/2configs/xsessions/urxvtd.nix b/tv/2configs/xsessions/urxvtd.nix
new file mode 100644
index 00000000..de16a634
--- /dev/null
+++ b/tv/2configs/xsessions/urxvtd.nix
@@ -0,0 +1,15 @@
+{ pkgs, ... }: {
+ systemd.user.sockets.urxvtd = {
+ wantedBy = [ "sockets.target" ];
+ socketConfig.ListenStream = "%t/urxvtd";
+ };
+ systemd.user.services.urxvtd = {
+ restartIfChanged = false;
+ environment = {
+ RXVT_SOCKET = "%t/urxvtd";
+ };
+ serviceConfig = {
+ ExecStart = "${pkgs.rxvt_unicode}/bin/urxvtd";
+ };
+ };
+}
diff --git a/tv/3modules/default.nix b/tv/3modules/default.nix
index 9f2f8e60..b6b4faa5 100644
--- a/tv/3modules/default.nix
+++ b/tv/3modules/default.nix
@@ -8,6 +8,7 @@
./hw.nix
./im.nix
./iptables.nix
+ ./org.freedesktop.machine1.host-shell.nix
./slock.nix
./x0vncserver.nix
./Xresources.nix
diff --git a/tv/3modules/org.freedesktop.machine1.host-shell.nix b/tv/3modules/org.freedesktop.machine1.host-shell.nix
new file mode 100644
index 00000000..e1a5323d
--- /dev/null
+++ b/tv/3modules/org.freedesktop.machine1.host-shell.nix
@@ -0,0 +1,28 @@
+{ config, ... }: let lib = import ../../lib; in {
+ options.org.freedesktop.machine1.host-shell.access = lib.mkOption {
+ default = {};
+ type =
+ lib.types.addCheck
+ (lib.types.attrsOf (lib.types.attrsOf lib.types.bool))
+ (x:
+ lib.all
+ lib.types.username.check
+ (lib.concatLists
+ (lib.mapAttrsToList
+ (name: value: [name] ++ lib.attrNames value)
+ x)));
+ };
+ config.security.polkit.extraConfig = let
+ cfg = config.org.freedesktop.machine1.host-shell;
+ enable = cfg.access != {};
+ in lib.optionalString enable /* js */ ''
+ polkit.addRule(function () {
+ var access = ${lib.toJSON cfg.access};
+ return function(action, subject) {
+ if (action.id === "org.freedesktop.machine1.host-shell"
+ && (access[subject.user]||{})[action.lookup("user")])
+ return polkit.Result.YES;
+ }
+ }());
+ '';
+}
diff --git a/tv/5pkgs/haskell/xmonad-tv/src/main.hs b/tv/5pkgs/haskell/xmonad-tv/src/main.hs
index e720981a..cf0c0f53 100644
--- a/tv/5pkgs/haskell/xmonad-tv/src/main.hs
+++ b/tv/5pkgs/haskell/xmonad-tv/src/main.hs
@@ -205,12 +205,12 @@ myKeys conf = Map.fromList $
_4CM = _4 .|. _C .|. _M
_4SM = _4 .|. _S .|. _M
- pactl args = forkFile {-pkg:pulseaudio-}"pactl" args Nothing
+ amixer args = forkFile {-pkg:alsaUtils-}"amixer" args Nothing
pavucontrol args = forkFile {-pkg-}"pavucontrol" args Nothing
- audioLowerVolume = pactl ["--", "set-sink-volume", "@DEFAULT_SINK@", "-5%"]
- audioRaiseVolume = pactl ["--", "set-sink-volume", "@DEFAULT_SINK@", "+5%"]
- audioMute = pactl ["--", "set-sink-mute", "@DEFAULT_SINK@", "toggle"]
+ audioLowerVolume = amixer ["-q", "sset", "Master", "5%-"]
+ audioRaiseVolume = amixer ["-q", "sset", "Master", "5%+"]
+ audioMute = amixer ["-q", "sset", "Master", "toggle"]
resetLayout = setLayout $ XMonad.layoutHook conf
diff --git a/tv/5pkgs/simple/stardict/default.nix b/tv/5pkgs/simple/stardict/default.nix
new file mode 100644
index 00000000..2135cc05
--- /dev/null
+++ b/tv/5pkgs/simple/stardict/default.nix
@@ -0,0 +1,235 @@
+{ lib, pkgs }:
+let
+ classicsDictionaries = {
+ Pape = pkgs.fetchzip {
+ url = "http://tovotu.de/data/stardict/pape_gr-de.zip";
+ sha256 = "1kmbdjqinrcxkc6jdyyrq5rl2wzhnrychyynnh91yhrjwjxlh44k";
+ };
+ Woodhouse = pkgs.fetchzip {
+ url = "https://c.krebsco.de/Woodhouse.zip";
+ sha256 = "1dvnc2679yb048q2f3hr2h34acvhan0n3iir6h9ajlrdzz48mlkq";
+ stripRoot = false;
+ };
+ LSJ = pkgs.fetchzip {
+ url = "https://github.com/nikita-moor/latin-dictionary/releases/download/2020-02-14/LiddellScott1940-stardict.zip";
+ sha256 = "13rprgd9jvnhxk9735c91xr6ywr0j5jiwkjnpm3qpvy93isyjbys";
+ };
+ GreekMorphology = pkgs.fetchzip {
+ url = "https://github.com/latin-dict/Morphologia-Graeca/releases/download/v0.5/morphology-mobile-goldendict.oxia.zip";
+ sha256 = "0m75cppjjjmvv18cs7yh9f4p7ckqzxfznnndgkiw3yrfd50k8p96";
+ };
+ Frisk = pkgs.fetchzip {
+ url = "https://github.com/latin-dict/Frisk1960/releases/download/v1.1/Frisk1960-stardict.zip";
+ sha256 = "1rk5a3n3fpfdcmg4bc5945m88s6ldxql8cjn4jqs33rgklh7n046";
+ };
+ Georges-De-Lat = pkgs.fetchzip {
+ url = "http://tovotu.de/data/stardict/georges_de-lat.zip";
+ sha256 = "1gx4vv64bi9lxw2zgd861j469jvw4f2hhfwy1gglb12id8r7rdrl";
+ };
+ Georges-Lat-De = pkgs.fetchzip { # TODO find out why this does not work with sdcv
+ url = "http://tovotu.de/data/stardict/georges_lat-de.zip";
+ sha256 = "0cc5xipn60anxvq8z2mw53d4gi1k92wbrj9m4ws3g9rh87fmkvgz";
+ };
+ LewisShort = pkgs.fetchzip {
+ url = "https://github.com/latin-dict/LewisShort1879/releases/download/v1.3/LewisShort1879-stardict.zip";
+ sha256 = "1y3ans47iv8bzzb1paimdqvcid8ms04ikjbqy3iw077i2js3qbjk";
+ };
+ DoederleinSynonymes = pkgs.fetchzip {
+ url = "https://github.com/latin-dict/Doederlein1874/releases/download/v1.1/Doederlein1875-stardict.zip";
+ sha256 = "0mhik7gjxl8ncr9g5z2l4pfk60k1c5n0gc1w0cnp2x1v6lqvb57h";
+ };
+ };
+
+ englishGermanDictionaries = {
+ Etymonline = pkgs.fetchzip {
+ url = "http://tovotu.de/data/stardict/etymonline.zip";
+ sha256 = "1bjja3n3layfd08xa1r0a6375dxh5zi6hlv7chkhgnx800cx7hxn";
+ };
+ Roget = builtins.fetchTarball {
+ url = "http://download.huzheng.org/bigdict/stardict-Roget_s_II_The_New_Thesaurus_3th_Ed-2.4.2.tar.bz2";
+ sha256 = "1szyny9497bpyyccf9l5kr3bnw0wvl4cnsd0n1zscxpyzlsrqqbz";
+ };
+ JargonFile = builtins.fetchTarball {
+ url = "http://download.huzheng.org/dict.org/stardict-dictd-jargon-2.4.2.tar.bz2";
+ sha256 = "096phar9qpmm0fnaqv5nz8x9lpxwnfj78g4vjfcfyd7kqp7iqla4";
+ };
+ Oxford-Collocations = builtins.fetchTarball {
+ url = "http://download.huzheng.org/bigdict/stardict-Oxford_Collocations_Dictionary_2nd_Ed-2.4.2.tar.bz2";
+ sha256 = "1zkfs0zxkcn21z2lhcabrs77v4ma9hpv7qm119hpyi1d8ajcw07q";
+ };
+ Langenscheidt-Deu-En = builtins.fetchTarball {
+ url = "http://download.huzheng.org/babylon/german/stardict-Handw_rterbuch_Deutsch_Englisc-2.4.2.tar.bz2";
+ sha256 = "12q9i5azq7ylyrpb6jqbaf1rxalc3kzcwjvbinvb0yabdxb80y30";
+ };
+ Langenscheidt-En-Deu = builtins.fetchTarball {
+ url = "http://download.huzheng.org/babylon/german/stardict-Handw_rterbuch_Englisch_Deutsc-2.4.2.tar.bz2";
+ sha256 = "087b05h155j5ldshfgx91pz81h6ijq2zaqjirg7ma8ig3l96zb59";
+ };
+ Duden_Das_Fremdworterbuch = builtins.fetchTarball {
+ url = "http://download.huzheng.org/babylon/german/stardict-Duden_Das_Fremdworterbuch-2.4.2.tar.bz2";
+ sha256 = "1zrcay54ccl031s6dvjwsah5slhanmjab87d81rxlcy8fx0xd8wq";
+ };
+ Duden_De_De = builtins.fetchTarball {
+ url = "http://download.huzheng.org/babylon/german/stardict-Duden_De_De-2.4.2.tar.bz2";
+ sha256 = "1fhay04w5aaj83axfmla2ql34nb60gb05dgv0k94ig7p8x4yxxlf";
+ };
+ ConciseOED = builtins.fetchTarball {
+ url = "http://download.huzheng.org/bigdict/stardict-Concise_Oxford_English_Dictionary-2.4.2.tar.bz2";
+ sha256 = "19kpcxbhqzpmhi94mp48nalgmsh6s7rsx1gb4kwkhirp2pbjcyl7";
+ };
+ # Duden_Rechtschreibung = builtins.fetchTarball {
+ # url = "http://download.huzheng.org/babylon/german/stardict-Duden_Rechtschreibung-2.4.2.tar.bz2";
+ # sha256 = "0xiprb45s88w62rn8rlbjrsagbiliay9hszsiy20glwabf6zsfji";
+ # };
+ Duden_Synonym = builtins.fetchTarball {
+ url = "http://download.huzheng.org/babylon/german/stardict-Duden_Synonym-2.4.2.tar.bz2";
+ sha256 = "0cx086zvb86bmz7i8vnsch4cj4fb0cp165g4hig4982zakj6f2jd";
+ };
+ # Duden = builtins.fetchTarball {
+ # url = "http://download.huzheng.org/de/stardict-duden-2.4.2.tar.bz2";
+ # sha256 = "049i4ynfqqxykv1nlkyks94mvn14s22qdax5gg7hx1ks5y4xw64j";
+ # };
+ # FreeOnlineDictionaryOfComputing = builtins.fetchTarball {
+ # url = "http://download.huzheng.org/dict.org/stardict-dictd_www.dict.org_foldoc-2.4.2.tar.bz2";
+ # sha256 = "1lw2i8dzxpx929cpgvv0x366dnh4drr10wzqmrhcd0kvwglqawgm";
+ # };
+ };
+
+ sanskritDictionaries = {
+ BoehtlingkRoth = pkgs.fetchzip {
+ url = "https://c.krebsco.de/Bohtlingk-and-Roth-Grosses-Petersburger-Worterbuch.zip";
+ sha256 = "13414a8rgd7hd5ffar6nl68nk3ys60wjkgb7m11hp0ahaasmf6ly";
+ stripRoot = false;
+ };
+ MonierWilliams = pkgs.fetchzip {
+ url = "https://c.krebsco.de/mw-cologne.zip";
+ sha256 = "0p99ybxwxmmd94hf035hvm2hhnfy84av7qq79xf28bh2rbx6s9ng";
+ stripRoot = false;
+ };
+ MonierWilliamsEnglish = pkgs.fetchzip {
+ url = "https://c.krebsco.de/mw-english-sanskrit.zip";
+ sha256 = "09a61hhii4b1m2fkrlh4rm2xnlgwrllh84iypbc6wyj00w9jkl3x";
+ stripRoot = false;
+ };
+ };
+
+ swahiliDictionaries = {
+ vickio = pkgs.fetchzip {
+ url = "http://swahili.vickio.net/files/Swahili-English.zip";
+ sha256 = "0m6wkwc83fcim43ijn17lcsda4clkra587gxaz6m59qd0yfwzakw";
+ stripRoot = false;
+ };
+ };
+
+ makeStardictDataDir = dicts: pkgs.linkFarm "dictionaries" (lib.mapAttrsToList (name: path: { inherit name path; }) dicts);
+
+ sdcvPager = pkgs.writeDash "sdcvPager" ''
+ export PATH=${lib.makeBinPath [pkgs.gnused pkgs.ncurses]}
+ sed "
+ s! style=\"color: #...\"!!g;
+ s!<span class=\"zenoTXSpaced\">\([^<>]*\)</span>!\1!g;
+ s!</\?dictionary[^>]*>!!g;
+ s!<style.*</style>!!g;
+ s!<author>\([^<>]*\)</author>!\1 !g;
+ s!<quote lang=\"\(greek\|la\)\">\([^<>]*\)</quote>!$(tput sitm)\2$(tput sgr0)!g;
+ s!<biblScope>\([^<>]*\)</biblScope>!\1!g;
+ s!<mood>\([^<>]*\)</mood>!$(tput sitm)\1$(tput sgr0)!g;
+ s!<adv>\([^<>]*\)</adv>!$(tput sitm)\1$(tput sgr0)!g;
+ s!<gram[^>]*>\([^<>]*\)</gram>!$(tput sitm)\1$(tput sgr0)!g;
+ s!<bibl_title>\([^<>]*\)</bibl_title>!$(tput sitm)\1$(tput sgr0) !g;
+ s!<hi rend=\"ital\">\([^<>]*\)</hi>!$(tput sitm)\1$(tput sgr0) !g;
+ s!<dict_tr>\([^<>]*\)</dict_tr>!$(tput setaf 3)\1$(tput sgr0)!g;
+ s!<headword>\([^<>]*\)</headword>!$(tput bold)\1$(tput sgr0)\t!g;
+ s!</\?a[^>]*>!!g
+ s!</\?[cp]b[^>]*>!!g
+ s!</\?gramGrp[^>]*>!!g
+ s!</\?lbl[^>]*>!!g
+ s!</\?xr[^>]*>!!g
+ s!</\?pron[^>]*>!!g
+ s!</\?gen[^>]*>!!g
+ s!</\?etym[^>]*>!!g
+ s!<foreign[^>]*>!$(tput sitm)!g
+ s!</foreign[^>]*>!$(tput sgr0)!g
+ s!</\?date[^>]*>!!g
+ s!</\?placeName[^>]*>!!g
+ s!</\?itype[^>]*>!!g
+ s!</\?p>!!g
+ s!<input[^>]*>!!g
+ s!</\?orth[^>]*>!!g
+ s!</\?forename[^>]*>!!g
+ s!</\?persName[^>]*>!!g
+ s!</\?surname[^>]*>!!g
+ s!</\?entryFree[^>]*>!!g
+ s!</\?def[^>]*>!!g
+ s!</\?cit[^>]*>!!g
+ s!</\?pos[^>]*>!!g
+ s!</\?usg[^>]*>!!g
+ s!</\?span>!!g
+ s!<bibl[^>]*>!$(tput setaf 245)!g
+ s!</bibl[^>]*>!$(tput sgr0)!g
+ s/<dt>/$(tput bold)/g;
+ s:</dt>:$(tput sgr0):g;
+ s/<dd>/\n/g;
+ s:</dd>::g;
+ s/<[bB]>/$(tput bold)/g;
+ s:</[bB]>:$(tput sgr0):g;
+ s:<[bB][rR]\s*/\?>:\n:g;
+ s:<[iI]>:$(tput sitm):g;
+ s:</[iI]>:$(tput sgr0):g;
+ s:<[uU]>:$(tput smul):g;
+ s:</[uU]>:$(tput sgr0):g;
+ s:<FONT face=[^>]*>::g;
+ s:</FONT>::g;
+ s!<head>\([^<>]*\)</head>!$(tput bold)\1$(tput sgr0)!g;
+ s!<span lang=\"\(gr\|la\)\">\([^<>]*\)</span>!\2!g
+ s#<div style=\"margin-left:1em\">\(.*\)</div>#\\1#g;
+ s:<font color=\"brown\">\([^<>]*\)</font>:$(tput setaf 3)\\1$(tput sgr0):g;
+ s:<font color=\"blue\">\([^<>]*\)</font>:$(tput setaf 4)\\1$(tput sgr0):g;
+ s:<font color=\"red\">\([^<>]*\)</font>:$(tput setaf 1)\\1$(tput sgr0):g;
+ s:<font color=\"darkviolet\">\([^<>]*\)</font>:$(tput setaf 5)\\1$(tput sgr0):g;
+ s:<font color=\"#a0a\">\([^<>]*\)</font>:$(tput bold)\1$(tput sgr0):g
+ s:<font color=\"#838\">\([^<>]*\)</font>:$(tput setaf 3)\1$(tput sgr0):g
+ s:&#x27;:':g
+ s:&lt;:<:g
+ s:&gt;:>:g
+ s:<font color=\"#007000\">\([^<>]*\)</font>:$(tput setaf 2)\\1$(tput sgr0):g;
+ s:<font color=\"#007000\">\([^<>]*\)</font>:$(tput setaf 2)\\1$(tput sgr0):g;
+ s:<font color=#000099>\([^<>]*\)</font>:$(tput setaf 4)\\1$(tput sgr0):g;
+ s:<font color=0000FF>\([^<>]*\)</font>:$(tput bold)\\1$(tput sgr0):g;
+ s:<IMG src=\"223E9A06.bmp\"[^>]*>:ː:g;
+ s:<IMG src=\"502F5DDA.bmp\"[^>]*>::g;
+ s!</\?TABLE>!!g
+ s!</\?TR[^>]*>!!g
+ s!</\?TD>!!g
+ s!</\?FONT[^>]*>!!g
+ s!</\?A[^>]*>!!g
+ s!<SPAN class=\"bsptext\">\([^<>]*\)</SPAN>!$(tput setaf 245)\1$(tput sgr0)!g
+ s!</\?SPAN[^>]*>!!g
+ s! +! !g;
+ s!<div part=\"[^\"]*\">!\n\n&!g
+ s!<sense n=\"\([^\"]*\)\"!\n$(tput setaf 5)\1.$(tput sgr0) &!g;
+ s!</\?sense[^>]*>!!g
+ s!</\?div[^>]*>!!g
+ s!<span lang=\"gr\">!!g # unbalanced in Frisk
+ s!^\s*[0-9])!$(tput setaf 5)&$(tput sgr0)!g
+ s#^\(-->.*\)\$#$(tput bold)\1$(tput sgr0)#
+ "
+ '';
+
+ mkDictBin = name: dicts:
+ pkgs.writers.writeDashBin name ''
+ set -efu
+ export SDCV_PAGER=${toString sdcvPager}
+ exec ${pkgs.sdcv}/bin/sdcv --data-dir ${makeStardictDataDir dicts} "$@"
+ '';
+in
+
+pkgs.symlinkJoin {
+ name = "stardict";
+ paths = [
+ (mkDictBin "sd-classics" classicsDictionaries)
+ (mkDictBin "sd-sanskrit" sanskritDictionaries)
+ (mkDictBin "sd-swahili" swahiliDictionaries)
+ (mkDictBin "sd" englishGermanDictionaries)
+ ];
+}