atom_content.xml - www.codemadness.org - www.codemadness.org saait content files (HTM) git clone git://git.codemadness.org/www.codemadness.org (DIR) Log (DIR) Files (DIR) Refs (DIR) README (DIR) LICENSE --- atom_content.xml (158164B) --- 1 <?xml version="1.0" encoding="UTF-8"?> 2 <feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"> 3 <title>Codemadness</title> 4 <subtitle>blog with various projects and articles about computer-related things</subtitle> 5 <updated>2024-07-17T00:00:00Z</updated> 6 <link rel="alternate" type="text/html" href="https://www.codemadness.org" /> 7 <id>https://www.codemadness.org/atom_content.xml</id> 8 <link rel="self" type="application/atom+xml" href="https://www.codemadness.org/atom_content.xml" /> 9 <entry> 10 <title>Chess puzzle book generator</title> 11 <link rel="alternate" type="text/html" href="https://www.codemadness.org/chess-puzzles.html" /> 12 <id>https://www.codemadness.org/chess-puzzles.html</id> 13 <updated>2024-02-04T00:00:00Z</updated> 14 <published>2024-02-02T00:00:00Z</published> 15 <author> 16 <name>Hiltjo</name> 17 <uri>https://www.codemadness.org</uri> 18 </author> 19 <summary>Chess puzzle book generator</summary> 20 <content type="html"><![CDATA[<h1>Chess puzzle book generator</h1> 21 <p><strong>Last modification on </strong> <time>2024-02-04</time></p> 22 <p>This was a christmas hack for fun and non-profit. 23 I wanted to write a chess puzzle book generator. 24 Inspired by <a href="https://archive.org/details/1001deadlycheckm0000nunn">1001 Deadly Checkmates by John Nunn, ISBN-13: 978-1906454258</a> and 25 similar puzzle books.</p> 26 <h1>Example output</h1> 27 <ul> 28 <li>English version: <a href="https://codemadness.org/downloads/puzzles/">https://codemadness.org/downloads/puzzles/</a></li> 29 <li>Dutch version: <a href="https://hiltjo.nl/puzzles/">https://hiltjo.nl/puzzles/</a></li> 30 </ul> 31 <p>Terminal version:</p> 32 <pre><code>curl -s 'https://codemadness.org/downloads/puzzles/index.vt' | less -R 33 </code></pre> 34 <p>I may or may not periodially update this page :)</p> 35 <p>Time flies (since Christmas), here is a valentine edition with <a href="https://lichess.org/practice/intermediate-tactics/attraction/">attraction</a> 36 puzzles (not only checkmates) using the red "love" theme. 37 It is optimized for his and her pleasure:</p> 38 <p><a href="https://codemadness.org/downloads/puzzles-valentine/">https://codemadness.org/downloads/puzzles-valentine/</a></p> 39 <h2>Clone</h2> 40 <pre><code>git clone git://git.codemadness.org/chess-puzzles 41 </code></pre> 42 <h2>Browse</h2> 43 <p>You can browse the source-code at:</p> 44 <ul> 45 <li><a href="https://git.codemadness.org/chess-puzzles/">https://git.codemadness.org/chess-puzzles/</a></li> 46 <li><a href="gopher://codemadness.org/1/git/chess-puzzles">gopher://codemadness.org/1/git/chess-puzzles</a></li> 47 </ul> 48 <h1>Quick overview of how it works</h1> 49 <p>The generate.sh shellscript generates the output and files for the puzzles.</p> 50 <p>The puzzles used are from the lichess.org puzzle database: 51 <a href="https://database.lichess.org/#puzzles">https://database.lichess.org/#puzzles</a></p> 52 <p>This database is a big CSV file containing the initial board state in the 53 Forsyth-Edwards Notation (FEN) format and the moves in Universal Chess 54 Interface (UCI) format. Each line contains the board state and the initial and 55 solution moves.</p> 56 <p>The generated index page is a HTML page, it lists the puzzles. Each puzzle on 57 this page is an SVG image. This scalable image format looks good in all 58 resolutions.</p> 59 <h1>Open puzzle data</h1> 60 <p>Lichess is an <a href="https://lichess.org/source">open-source</a> and gratis website to play on-line chess. There are 61 no paid levels to unlock features. All the software hosting Lichess is 62 open-source and anyone can register and play chess on it for free. Most of the 63 data about the games played is also open.</p> 64 <p>However, the website depends on your donations or contributions. If you can, 65 <a href="https://lichess.org/about">please do so</a>.</p> 66 <h1>generate.sh</h1> 67 <p>Reads puzzles from the database and shuffle them. Do some rough sorting and 68 categorization based on difficulty and assign score points.</p> 69 <p>The random shuffling is done using a hard-coded <a href="https://en.wikipedia.org/wiki/Random_seed">random seed</a>. This means on the 70 same machine with the same puzzle database it will regenerate the same sequence 71 of random puzzles in a deterministic manner.</p> 72 <p>It outputs HTML, with support for CSS dark mode and does not use Javascript. 73 It includes a plain-text listing of the solutions in PGN notation for the 74 puzzles. 75 It also outputs .vt files suitable for the terminal. It uses unicode symbols 76 for the chess pieces and RGB color sequence for the board theme</p> 77 <h1>fen.c</h1> 78 <p>This is a program written in C to read and parse the board state in FEN format 79 and read the UCI moves. It can output to various formats.</p> 80 <p>See the man page for detailed usage information.</p> 81 <p>fen.c supports the following output formats:</p> 82 <ul> 83 <li>ascii - very simple ASCII mode.</li> 84 <li><a href="https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation">fen</a> - output FEN of the board state (from FEN and optional played moves).</li> 85 <li><a href="https://en.wikipedia.org/wiki/Portable_Game_Notation">pgn</a> - Portable Game Notation.</li> 86 <li>speak - mode to output a description of the moves in words.</li> 87 <li><a href="https://en.wikipedia.org/wiki/SVG">SVG</a> - Scalable Vector Graphics image.</li> 88 <li>tty - Terminal output with some markup using escape codes.</li> 89 </ul> 90 <p>fen.c can also run in <a href="https://en.wikipedia.org/wiki/Common_Gateway_Interface">CGI</a> mode. This can be used on a HTTP server:</p> 91 <p><img src="https://codemadness.org/onlyfens?fen=6k1/ppq3bp/2n2np1/5p2/2P2P2/4rBN1/PP3K1P/RQ6%20w%20-%20-%200%2023&moves=f2e3&flip=1" alt="Position from game: Rene Letelier Martner - Robert James Fischer, 1960-10-24" /></p> 92 <ul> 93 <li><a href="https://codemadness.org/onlyfens">https://codemadness.org/onlyfens</a></li> 94 <li><a href="https://codemadness.org/onlyfens?moves=e2e4%20e7e5&flip=1&theme=green&output=svg">https://codemadness.org/onlyfens?moves=e2e4%20e7e5&flip=1&theme=green&output=svg</a></li> 95 <li><a href="https://codemadness.org/onlyfens?moves=e2e4%20e7e5&output=pgn">https://codemadness.org/onlyfens?moves=e2e4%20e7e5&output=pgn</a></li> 96 <li><a href="https://codemadness.org/onlyfens?moves=e2e4%20e7e5&output=speak">https://codemadness.org/onlyfens?moves=e2e4%20e7e5&output=speak</a></li> 97 <li><a href="https://codemadness.org/onlyfens?moves=e2e4%20e7e5&output=ascii">https://codemadness.org/onlyfens?moves=e2e4%20e7e5&output=ascii</a></li> 98 <li><a href="https://codemadness.org/onlyfens?moves=e2e4%20e7e5&output=fen">https://codemadness.org/onlyfens?moves=e2e4%20e7e5&output=fen</a></li> 99 </ul> 100 <p>Terminal output:</p> 101 <pre><code>curl -s 'https://codemadness.org/onlyfens?moves=e2e4%20e7e5&output=tty' 102 </code></pre> 103 <h1>Support for Dutch notated PGN and output</h1> 104 <p>For pgn and "speak mode" it has an option to output Dutch notated PGN or speech 105 too.</p> 106 <p>For example:</p> 107 <ul> 108 <li>Queen = Dame (Q -> D), translated: lady.</li> 109 <li>Rook = Toren (R -> T), translated: tower.</li> 110 <li>Bishop = Loper (B -> L), translated: walker.</li> 111 <li>Knight = Paard (N -> P), translated: horse.</li> 112 </ul> 113 <h1>Example script to stream games from Lichess</h1> 114 <p>There is an included example script that can stream Lichess games to the 115 terminal. It uses the <a href="https://lichess.org/api">Lichess API</a>. It will display the board using terminal 116 escape codes. The games are automatically annotated with PGN notation and with 117 text how a human would say the notation. This can also be piped to a speech 118 synthesizer like <a href="https://github.com/espeak-ng/espeak-ng/">espeak</a> as audio.</p> 119 <p>pgn-extract is a useful tool to convert Portable Game Notation (PGN) to 120 Universal Chess Interface (UCI) moves (or do many other useful chess related 121 things!).</p> 122 <h1>Example script to generate an animated gif from PGN</h1> 123 <p>Theres also an example script included that can generate an animated gif from 124 PGN using <a href="https://ffmpeg.org/">ffmpeg</a>.</p> 125 <p>It creates an optimal color palette from the input images and generates an 126 optimized animated gif. The last move (typically some checkmate) is displayed 127 slightly longer.</p> 128 <h1>References and chess related links</h1> 129 <ul> 130 <li><p>chess-puzzles source-code:<br /> 131 <a href="https://www.codemadness.org/git/chess-puzzles/file/README.html">https://www.codemadness.org/git/chess-puzzles/file/README.html</a></p> 132 </li> 133 <li><p>Lichess FEN puzzle database:<br /> 134 <a href="https://database.lichess.org/#puzzles">https://database.lichess.org/#puzzles</a></p> 135 </li> 136 <li><p>lichess.org:<br /> 137 <a href="https://lichess.org/">https://lichess.org/</a></p> 138 </li> 139 <li><p>SVG of the individual pieces used in fen.c:<br /> 140 <a href="https://github.com/lichess-org/lila/tree/master/public/piece/cburnett">https://github.com/lichess-org/lila/tree/master/public/piece/cburnett</a></p> 141 </li> 142 <li><p>pgn-extract:<br /> 143 A great multi-purpose PGN manipulation program with many options:<br /> 144 <a href="https://www.cs.kent.ac.uk/people/staff/djb/pgn-extract/">https://www.cs.kent.ac.uk/people/staff/djb/pgn-extract/</a></p> 145 <p>An example to convert PGN games to UCI moves:<br /> 146 <code>pgn-extract --notags -Wuc</code></p> 147 </li> 148 <li><p>Lichess API:<br /> 149 <a href="https://lichess.org/api">https://lichess.org/api</a></p> 150 </li> 151 <li><p>Stockfish:<br /> 152 Strong open-source chess engine and analysis tool:<br /> 153 <a href="https://stockfishchess.org/">https://stockfishchess.org/</a></p> 154 </li> 155 </ul> 156 ]]></content> 157 </entry> 158 <entry> 159 <title>xargs: an example for parallel batch jobs</title> 160 <link rel="alternate" type="text/html" href="https://www.codemadness.org/xargs.html" /> 161 <id>https://www.codemadness.org/xargs.html</id> 162 <updated>2023-12-17T00:00:00Z</updated> 163 <published>2023-11-22T00:00:00Z</published> 164 <author> 165 <name>Hiltjo</name> 166 <uri>https://www.codemadness.org</uri> 167 </author> 168 <summary>xargs: an example for parallel batch jobs</summary> 169 <content type="html"><![CDATA[<h1>xargs: an example for parallel batch jobs</h1> 170 <p><strong>Last modification on </strong> <time>2023-12-17</time></p> 171 <p>This describes a simple shellscript programming pattern to process a list of 172 jobs in parallel. This script example is contained in one file.</p> 173 <h1>Simple but less optimal example</h1> 174 <pre><code>#!/bin/sh 175 maxjobs=4 176 177 # fake program for example purposes. 178 someprogram() { 179 echo "Yep yep, I'm totally a real program!" 180 sleep "$1" 181 } 182 183 # run(arg1, arg2) 184 run() { 185 echo "[$1] $2 started" >&2 186 someprogram "$1" >/dev/null 187 status="$?" 188 echo "[$1] $2 done" >&2 189 return "$status" 190 } 191 192 # process the jobs. 193 j=1 194 for f in 1 2 3 4 5 6 7 8 9 10; do 195 run "$f" "something" & 196 197 jm=$((j % maxjobs)) # shell arithmetic: modulo 198 test "$jm" = "0" && wait 199 j=$((j+1)) 200 done 201 wait 202 </code></pre> 203 <h1>Why is this less optimal</h1> 204 <p>This is less optimal because it waits until all jobs in the same batch are finished 205 (each batch contain $maxjobs items).</p> 206 <p>For example with 2 items per batch and 4 total jobs it could be:</p> 207 <ul> 208 <li>Job 1 is started.</li> 209 <li>Job 2 is started.</li> 210 <li>Job 2 is done.</li> 211 <li>Job 1 is done.</li> 212 <li>Wait: wait on process status of all background processes.</li> 213 <li>Job 3 in new batch is started.</li> 214 </ul> 215 <p>This could be optimized to:</p> 216 <ul> 217 <li>Job 1 is started.</li> 218 <li>Job 2 is started.</li> 219 <li>Job 2 is done.</li> 220 <li>Job 3 in new batch is started (immediately).</li> 221 <li>Job 1 is done.</li> 222 <li>...</li> 223 </ul> 224 <p>It also does not handle signals such as SIGINT (^C). However the xargs example 225 below does:</p> 226 <h1>Example</h1> 227 <pre><code>#!/bin/sh 228 maxjobs=4 229 230 # fake program for example purposes. 231 someprogram() { 232 echo "Yep yep, I'm totally a real program!" 233 sleep "$1" 234 } 235 236 # run(arg1, arg2) 237 run() { 238 echo "[$1] $2 started" >&2 239 someprogram "$1" >/dev/null 240 status="$?" 241 echo "[$1] $2 done" >&2 242 return "$status" 243 } 244 245 # child process job. 246 if test "$CHILD_MODE" = "1"; then 247 run "$1" "$2" 248 exit "$?" 249 fi 250 251 # generate a list of jobs for processing. 252 list() { 253 for f in 1 2 3 4 5 6 7 8 9 10; do 254 printf '%s\0%s\0' "$f" "something" 255 done 256 } 257 258 # process jobs in parallel. 259 list | CHILD_MODE="1" xargs -r -0 -P "${maxjobs}" -L 2 "$(readlink -f "$0")" 260 </code></pre> 261 <h1>Run and timings</h1> 262 <p>Although the above example is kindof stupid, it already shows the queueing of 263 jobs is more efficient.</p> 264 <p>Script 1:</p> 265 <pre><code>time ./script1.sh 266 [...snip snip...] 267 real 0m22.095s 268 </code></pre> 269 <p>Script 2:</p> 270 <pre><code>time ./script2.sh 271 [...snip snip...] 272 real 0m18.120s 273 </code></pre> 274 <h1>How it works</h1> 275 <p>The parent process:</p> 276 <ul> 277 <li>The parent, using xargs, handles the queue of jobs and schedules the jobs to 278 execute as a child process.</li> 279 <li>The list function writes the parameters to stdout. These parameters are 280 separated by the NUL byte separator. The NUL byte separator is used because 281 this character cannot be used in filenames (which can contain spaces or even 282 newlines) and cannot be used in text (the NUL byte terminates the buffer for 283 a string).</li> 284 <li>The -L option must match the amount of arguments that are specified for the 285 job. It will split the specified parameters per job.</li> 286 <li>The expression "$(readlink -f "$0")" gets the absolute path to the 287 shellscript itself. This is passed as the executable to run for xargs.</li> 288 <li>xargs calls the script itself with the specified parameters it is being fed. 289 The environment variable $CHILD_MODE is set to indicate to the script itself 290 it is run as a child process of the script.</li> 291 </ul> 292 <p>The child process:</p> 293 <ul> 294 <li><p>The command-line arguments are passed by the parent using xargs.</p> 295 </li> 296 <li><p>The environment variable $CHILD_MODE is set to indicate to the script itself 297 it is run as a child process of the script.</p> 298 </li> 299 <li><p>The script itself (ran in child-mode process) only executes the task and 300 signals its status back to xargs and the parent.</p> 301 </li> 302 <li><p>The exit status of the child program is signaled to xargs. This could be 303 handled, for example to stop on the first failure (in this example it is not). 304 For example if the program is killed, stopped or the exit status is 255 then 305 xargs stops running also.</p> 306 </li> 307 </ul> 308 <h1>Description of used xargs options</h1> 309 <p>From the OpenBSD man page: <a href="https://man.openbsd.org/xargs">https://man.openbsd.org/xargs</a></p> 310 <pre><code>xargs - construct argument list(s) and execute utility 311 </code></pre> 312 <p>Options explained:</p> 313 <ul> 314 <li>-r: Do not run the command if there are no arguments. Normally the command 315 is executed at least once even if there are no arguments.</li> 316 <li>-0: Change xargs to expect NUL ('\0') characters as separators, instead of 317 spaces and newlines.</li> 318 <li>-P maxprocs: Parallel mode: run at most maxprocs invocations of utility 319 at once.</li> 320 <li>-L number: Call utility for every number of non-empty lines read. A line 321 ending in unescaped white space and the next non-empty line are considered 322 to form one single line. If EOF is reached and fewer than number lines have 323 been read then utility will be called with the available lines.</li> 324 </ul> 325 <h1>xargs options -0 and -P, portability and historic context</h1> 326 <p>Some of the options, like -P are as of writing (2023) non-POSIX: 327 <a href="https://pubs.opengroup.org/onlinepubs/9699919799/utilities/xargs.html">https://pubs.opengroup.org/onlinepubs/9699919799/utilities/xargs.html</a>. 328 However many systems support this useful extension for many years now.</p> 329 <p>The specification even mentions implementations which support parallel 330 operations:</p> 331 <p>"The version of xargs required by this volume of POSIX.1-2017 is required to 332 wait for the completion of the invoked command before invoking another command. 333 This was done because historical scripts using xargs assumed sequential 334 execution. Implementations wanting to provide parallel operation of the invoked 335 utilities are encouraged to add an option enabling parallel invocation, but 336 should still wait for termination of all of the children before xargs 337 terminates normally."</p> 338 <p>Some historic context:</p> 339 <p>The xargs -0 option was added on 1996-06-11 by Theo de Raadt, about a year 340 after the NetBSD import (over 27 years ago at the time of writing):</p> 341 <p><a href="http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/xargs/xargs.c?rev=1.2&content-type=text/x-cvsweb-markup">CVS log</a></p> 342 <p>On OpenBSD the xargs -P option was added on 2003-12-06 by syncing the FreeBSD 343 code:</p> 344 <p><a href="http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/xargs/xargs.c?rev=1.14&content-type=text/x-cvsweb-markup">CVS log</a></p> 345 <p>Looking at the imported git history log of GNU findutils (which has xargs), the 346 very first commit already had the -0 and -P option:</p> 347 <p><a href="https://savannah.gnu.org/git/?group=findutils">git log</a></p> 348 <pre><code>commit c030b5ee33bbec3c93cddc3ca9ebec14c24dbe07 349 Author: Kevin Dalley <kevin@seti.org> 350 Date: Sun Feb 4 20:35:16 1996 +0000 351 352 Initial revision 353 </code></pre> 354 <h1>xargs: some incompatibilities found</h1> 355 <ul> 356 <li>Using the -0 option empty fields are handled differently in different 357 implementations.</li> 358 <li>The -n and -L option doesn't work correctly in many of the BSD implementations. 359 Some count empty fields, some don't. In early implementations in FreeBSD and 360 OpenBSD it only processed the first line. In OpenBSD it has been improved 361 around 2017.</li> 362 </ul> 363 <p>Depending on what you want to do a workaround could be to use the -0 option 364 with a single field and use the -n flag. Then in each child program invocation 365 split the field by a separator.</p> 366 <h1>References</h1> 367 <ul> 368 <li>xargs: <a href="https://man.openbsd.org/xargs">https://man.openbsd.org/xargs</a></li> 369 <li>printf: <a href="https://man.openbsd.org/printf">https://man.openbsd.org/printf</a></li> 370 <li>ksh, wait: <a href="https://man.openbsd.org/ksh#wait">https://man.openbsd.org/ksh#wait</a></li> 371 <li>wait(2): <a href="https://man.openbsd.org/wait">https://man.openbsd.org/wait</a></li> 372 </ul> 373 ]]></content> 374 </entry> 375 <entry> 376 <title>Improved Youtube RSS/Atom feed</title> 377 <link rel="alternate" type="text/html" href="https://www.codemadness.org/youtube-feed.html" /> 378 <id>https://www.codemadness.org/youtube-feed.html</id> 379 <updated>2023-11-20T00:00:00Z</updated> 380 <published>2023-11-20T00:00:00Z</published> 381 <author> 382 <name>Hiltjo</name> 383 <uri>https://www.codemadness.org</uri> 384 </author> 385 <summary>Improved Youtube Atom feed by adding video duration and filtering away shorts</summary> 386 <content type="html"><![CDATA[<h1>Improved Youtube RSS/Atom feed</h1> 387 <p><strong>Last modification on </strong> <time>2023-11-20</time></p> 388 <p>... improved at least for my preferences ;)</p> 389 <p>It scrapes the channel data from Youtube and combines it with the parsed Atom 390 feed from the channel on Youtube.</p> 391 <p>The Atom parser is based on sfeed, with some of the code removed because it is 392 not needed by this program. It scrapes the metadata of the videos from the 393 channel its HTML page and uses my custom JSON parser to convert the 394 Javascript/JSON structure.</p> 395 <p>This parser is also used by the <a href="json2tsv.html">json2tsv</a> tool. It has few dependencies.</p> 396 <h2>Features</h2> 397 <ul> 398 <li>Add the video duration to the title to quickly see how long the video is.</li> 399 <li>Filter away Youtube shorts and upcoming videos / announcements: only videos are shown.</li> 400 <li>Supports more output formats: Atom, <a href="https://www.jsonfeed.org/version/1.1/">JSON Feed</a> or 401 <a href="sfeed.1.txt">sfeed</a> Tab-Separated-Value format.</li> 402 <li>Easy to build and deploy: can be run as a CGI program as a static-linked 403 binary in a chroot.</li> 404 <li>Secure: additionally to running in a chroot it can use pledge(2) and unveil(2) 405 on OpenBSD to restrict system calls and access to the filesystem.</li> 406 </ul> 407 <h2>How to use</h2> 408 <p>There is an option to run directly from the command-line or in CGI-mode. When 409 the environment variable $REQUEST_URI is set then it is automatically run in 410 CGI mode.</p> 411 <p>Command-line usage:</p> 412 <pre><code>youtube_feed channelid atom 413 youtube_feed channelid gph 414 youtube_feed channelid html 415 youtube_feed channelid json 416 youtube_feed channelid tsv 417 youtube_feed channelid txt 418 </code></pre> 419 <p>CGI program usage:</p> 420 <p>The last basename part of the URL should be the channelid + the output format 421 extension. It defaults to TSV if there is no extension. 422 The CGI program can be used with a HTTPd or a Gopher daemon such as geomyidae.</p> 423 <p>For example:</p> 424 <pre><code>Atom XML: https://codemadness.org/yt-chan/UCrbvoMC0zUvPL8vjswhLOSw.xml 425 HTML: https://codemadness.org/yt-chan/UCrbvoMC0zUvPL8vjswhLOSw.html 426 JSON: https://codemadness.org/yt-chan/UCrbvoMC0zUvPL8vjswhLOSw.json 427 TSV: https://codemadness.org/yt-chan/UCrbvoMC0zUvPL8vjswhLOSw.tsv 428 twtxt: https://codemadness.org/yt-chan/UCrbvoMC0zUvPL8vjswhLOSw.txt 429 TSV, default: https://codemadness.org/yt-chan/UCrbvoMC0zUvPL8vjswhLOSw 430 431 Gopher dir: gopher://codemadness.org/1/feed.cgi/UCrbvoMC0zUvPL8vjswhLOSw.gph 432 Gopher TSV: gopher://codemadness.org/0/feed.cgi/UCrbvoMC0zUvPL8vjswhLOSw 433 </code></pre> 434 <p>An OpenBSD httpd.conf using slowcgi as an example:</p> 435 <pre><code>server "codemadness.org" { 436 location "/yt-chan/*" { 437 request strip 1 438 root "/cgi-bin/yt-chan" 439 fastcgi socket "/run/slowcgi.sock" 440 } 441 } 442 </code></pre> 443 <h2>Using it with <a href="sfeed.html">sfeed</a></h2> 444 <p>sfeedrc example of an existing Youtube RSS/Atom feed:</p> 445 <pre><code># list of feeds to fetch: 446 feeds() { 447 # feed <name> <feedurl> [basesiteurl] [encoding] 448 # normal Youtube Atom feed. 449 feed "yt IM" "https://www.youtube.com/feeds/videos.xml?channel_id=UCrbvoMC0zUvPL8vjswhLOSw" 450 } 451 </code></pre> 452 <p>Use the new Atom feed directly using the CGI-mode and Atom output format:</p> 453 <pre><code># list of feeds to fetch: 454 feeds() { 455 # feed <name> <feedurl> [basesiteurl] [encoding] 456 # new Youtube Atom feed. 457 feed "idiotbox IM" "https://codemadness.org/yt-chan/UCrbvoMC0zUvPL8vjswhLOSw.xml" 458 } 459 </code></pre> 460 <p>... or convert directly using a custom connector program on the local system via the command-line:</p> 461 <pre><code># fetch(name, url, feedfile) 462 fetch() { 463 case "$1" in 464 "connector example") 465 youtube_feed "$2";; 466 *) 467 curl -L --max-redirs 0 -H "User-Agent:" -f -s -m 15 \ 468 "$2" 2>/dev/null;; 469 esac 470 } 471 472 # parse and convert input, by default XML to the sfeed(5) TSV format. 473 # parse(name, feedurl, basesiteurl) 474 parse() { 475 case "$1" in 476 "connector example") 477 cat;; 478 *) 479 sfeed "$3";; 480 esac 481 } 482 483 # list of feeds to fetch: 484 feeds() { 485 # feed <name> <feedurl> [basesiteurl] [encoding] 486 feed "connector example" "UCrbvoMC0zUvPL8vjswhLOSw" 487 } 488 </code></pre> 489 <h2>Screenshot using sfeed_curses</h2> 490 <p><a href="downloads/screenshots/sfeed_curses_youtube.png"><img src="downloads/screenshots/sfeed_curses_youtube.png" alt="Screenshot showing the improved Youtube feed" width="480" height="270" loading="lazy" /></a></p> 491 <h2>Clone</h2> 492 <pre><code>git clone git://git.codemadness.org/frontends 493 </code></pre> 494 <h2>Browse</h2> 495 <p>You can browse the source-code at:</p> 496 <ul> 497 <li><a href="https://git.codemadness.org/frontends/file/youtube/feed.c.html">https://git.codemadness.org/frontends/file/youtube/feed.c.html</a></li> 498 <li><a href="gopher://codemadness.org/1/git/frontends/file/youtube/feed.c.gph">gopher://codemadness.org/1/git/frontends/file/youtube/feed.c.gph</a></li> 499 </ul> 500 <p>The program is: youtube/feed</p> 501 <h2>Dependencies</h2> 502 <ul> 503 <li>C compiler.</li> 504 <li>LibreSSL + libtls.</li> 505 </ul> 506 <h2>Build and install</h2> 507 <pre><code>$ make 508 # make install 509 </code></pre> 510 <h2>That's all</h2> 511 <p>I hope by sharing this it is useful to someone other than me as well.</p> 512 ]]></content> 513 </entry> 514 <entry> 515 <title>webdump HTML to plain-text converter</title> 516 <link rel="alternate" type="text/html" href="https://www.codemadness.org/webdump.html" /> 517 <id>https://www.codemadness.org/webdump.html</id> 518 <updated>2024-07-17T00:00:00Z</updated> 519 <published>2023-11-20T00:00:00Z</published> 520 <author> 521 <name>Hiltjo</name> 522 <uri>https://www.codemadness.org</uri> 523 </author> 524 <summary>webdump HTML to plain-text converter</summary> 525 <content type="html"><![CDATA[<h1>webdump HTML to plain-text converter</h1> 526 <p><strong>Last modification on </strong> <time>2024-07-17</time></p> 527 <p>webdump is (yet another) HTML to plain-text converter tool.</p> 528 <p>It reads HTML in UTF-8 from stdin and writes plain-text to stdout.</p> 529 <h2>Goals and scope</h2> 530 <p>The main goal of this tool for me is to use it for converting HTML mails to 531 plain-text and to convert HTML content in RSS feeds to plain-text.</p> 532 <p>The tool will only convert HTML to stdout, similarly to links -dump or lynx 533 -dump but simpler and more secure.</p> 534 <ul> 535 <li>HTML and XHTML will be supported.</li> 536 <li>There will be some workarounds and quirks for broken and legacy HTML code.</li> 537 <li>It will be usable and secure for reading HTML from mails and RSS/Atom feeds.</li> 538 <li>No remote resources which are part of the HTML will be downloaded: 539 images, video, audio, etc. But these may be visible as a link reference.</li> 540 <li>Data will be written to stdout. Intended for plain-text or a text terminal.</li> 541 <li>No support for Javascript, CSS, frame rendering or form processing.</li> 542 <li>No HTTP or network protocol handling: HTML data is read from stdin.</li> 543 <li>Listings for references and some options to extract them in a list that is 544 usable for scripting. Some references are: link anchors, images, audio, video, 545 HTML (i)frames, etc.</li> 546 <li>Security: on OpenBSD it uses pledge("stdio", NULL).</li> 547 <li>Keep the code relatively small, simple and hackable.</li> 548 </ul> 549 <h2>Features</h2> 550 <ul> 551 <li>Support for word-wrapping.</li> 552 <li>A mode to enable basic markup: bold, underline, italic and blink ;)</li> 553 <li>Indentation of headers, paragraphs, pre and list items.</li> 554 <li>Basic support to query elements or hide them.</li> 555 <li>Show link references.</li> 556 <li>Show link references and resources such as img, video, audio, subtitles.</li> 557 <li>Export link references and resources to a TAB-separated format.</li> 558 </ul> 559 <h2>Usage examples</h2> 560 <pre><code>url='https://codemadness.org/sfeed.html' 561 562 curl -s "$url" | webdump -r -b "$url" | less 563 564 curl -s "$url" | webdump -8 -a -i -l -r -b "$url" | less -R 565 566 curl -s "$url" | webdump -s 'main' -8 -a -i -l -r -b "$url" | less -R 567 </code></pre> 568 <p>Yes, all these option flags look ugly, a shellscript wrapper could be used :)</p> 569 <h2>Practical examples</h2> 570 <p>To use webdump as a HTML to text filter for example in the mutt mail client, 571 change in ~/.mailcap:</p> 572 <pre><code>text/html; webdump -i -l -r < %s; needsterminal; copiousoutput 573 </code></pre> 574 <p>In mutt you should then add:</p> 575 <pre><code>auto_view text/html 576 </code></pre> 577 <p>Using webdump as a HTML to text filter for sfeed_curses (otherwise the default is lynx):</p> 578 <pre><code>SFEED_HTMLCONV="webdump -d -8 -r -i -l -a" sfeed_curses ~/.sfeed/feeds/* 579 </code></pre> 580 <h1>Query/selector examples</h1> 581 <p>The query syntax using the -s option is a bit inspired by CSS (but much more limited).</p> 582 <p>To get the title from a HTML page:</p> 583 <pre><code>url='https://codemadness.org/sfeed.html' 584 585 title=$(curl -s "$url" | webdump -s 'title') 586 printf '%s\n' "$title" 587 </code></pre> 588 <p>List audio and video-related content from a HTML page, redirect fd 3 to fd 1 (stdout):</p> 589 <pre><code>url="https://media.ccc.de/v/051_Recent_features_to_OpenBSD-ntpd_and_bgpd" 590 curl -s "$url" | webdump -x -s 'audio,video' -b "$url" 3>&1 >/dev/null | cut -f 2 591 </code></pre> 592 <h2>Clone</h2> 593 <pre><code>git clone git://git.codemadness.org/webdump 594 </code></pre> 595 <h2>Browse</h2> 596 <p>You can browse the source-code at:</p> 597 <ul> 598 <li><a href="https://git.codemadness.org/webdump/">https://git.codemadness.org/webdump/</a></li> 599 <li><a href="gopher://codemadness.org/1/git/webdump">gopher://codemadness.org/1/git/webdump</a></li> 600 </ul> 601 <h2>Build and install</h2> 602 <pre><code>$ make 603 # make install 604 </code></pre> 605 <h2>Dependencies</h2> 606 <ul> 607 <li>C compiler.</li> 608 <li>libc + some BSDisms.</li> 609 </ul> 610 <h2>Trade-offs</h2> 611 <p>All software has trade-offs.</p> 612 <p>webdump processes HTML in a single-pass. It does not buffer the full DOM tree. 613 Although due to the nature of HTML/XML some parts like attributes need to be 614 buffered.</p> 615 <p>Rendering tables in webdump is very limited. Twibright Links has really nice 616 table rendering. However implementing a similar feature in the current design of 617 webdump would make the code much more complex. Twibright links 618 processes a full DOM tree and processes the tables in multiple passes (to 619 measure the table cells) etc. Of course tables can be nested also, or HTML tables 620 that are used for creating layouts (these are mostly older webpages).</p> 621 <p>These trade-offs and preferences are chosen for now. It may change in the 622 future. Fortunately there are the usual good suspects for HTML to plain-text 623 conversion, each with their own chosen trade-offs of course:</p> 624 <ul> 625 <li>twibright links: <a href="http://links.twibright.com/">http://links.twibright.com/</a></li> 626 <li>lynx: <a href="https://lynx.invisible-island.net/">https://lynx.invisible-island.net/</a></li> 627 <li>w3m: <a href="https://w3m.sourceforge.net/">https://w3m.sourceforge.net/</a></li> 628 <li>xmllint (part of libxml2): <a href="https://gitlab.gnome.org/GNOME/libxml2/-/wikis/home">https://gitlab.gnome.org/GNOME/libxml2/-/wikis/home</a></li> 629 <li>xmlstarlet: <a href="https://xmlstar.sourceforge.net/">https://xmlstar.sourceforge.net/</a></li> 630 </ul> 631 ]]></content> 632 </entry> 633 <entry> 634 <title>Setup your own mail paste service</title> 635 <link rel="alternate" type="text/html" href="https://www.codemadness.org/mailservice.html" /> 636 <id>https://www.codemadness.org/mailservice.html</id> 637 <updated>2024-02-10T00:00:00Z</updated> 638 <published>2023-10-25T00:00:00Z</published> 639 <author> 640 <name>Hiltjo</name> 641 <uri>https://www.codemadness.org</uri> 642 </author> 643 <summary>Setup your own mail paste service using mblaze</summary> 644 <content type="html"><![CDATA[<h1>Setup your own mail paste service</h1> 645 <p><strong>Last modification on </strong> <time>2024-02-10</time></p> 646 <h2>How it works</h2> 647 <ul> 648 <li>The user sends a mail with an attachment to a certain mail address, for 649 example: paste@somehost.org</li> 650 <li>The mail daemon configuration has an mail alias to pipe the raw mail to a 651 shellscript.</li> 652 <li>This shellscript processes the raw mail contents from stdin.</li> 653 </ul> 654 <h2>What it does</h2> 655 <ul> 656 <li>Process a mail with the attachments automatically.</li> 657 <li>The script processes the attachments in the mail and stores them.</li> 658 <li>It will mail (back) the URL where the file(s) are stored.</li> 659 </ul> 660 <p>This script is tested on OpenBSD using OpenBSD smtpd and OpenBSD httpd and the 661 gopher daemon geomyidae.</p> 662 <h2>Install dependencies</h2> 663 <p>On OpenBSD:</p> 664 <pre><code>pkg_add mblaze 665 </code></pre> 666 <h2>smtpd mail configuration</h2> 667 <p>In your mail aliases (for example /etc/mail/aliases) put:</p> 668 <pre><code>paste: |/usr/local/bin/paste-mail 669 </code></pre> 670 <p>This pipes the mail to the script paste-mail for processing, this script is 671 described below. Copy the below contents in /usr/local/bin/paste-mail</p> 672 <p>Script:</p> 673 <pre><code>#!/bin/sh 674 675 d="/home/www/domains/www.codemadness.org/htdocs/mailpaste" 676 tmpmsg=$(mktemp) 677 tmpmail=$(mktemp) 678 679 cleanup() { 680 rm -f "$tmpmail" "$tmpmsg" 681 } 682 683 # store whole mail from stdin temporarily, on exit remove temporary file. 684 trap "cleanup" EXIT 685 cat > "$tmpmail" 686 687 # mblaze: don't store mail sequence. 688 MAILSEQ=/dev/null 689 export MAILSEQ 690 691 # get from address (without display name). 692 from=$(maddr -a -h 'From' /dev/stdin < "$tmpmail") 693 694 # check if allowed or not. 695 case "$from" in 696 "hiltjo@codemadness.org") 697 ;; 698 *) 699 exit 0;; 700 esac 701 702 # prevent mail loop. 703 if printf '%s' "$from" | grep -q "paste@"; then 704 exit 0 705 fi 706 707 echo "Thank you for using the enterprise paste service." > "$tmpmsg" 708 echo "" >> "$tmpmsg" 709 echo "Your file(s) are available at:" >> "$tmpmsg" 710 echo "" >> "$tmpmsg" 711 712 # process each attachment. 713 mshow -n -q -t /dev/stdin < "$tmpmail" | sed -nE 's@.*name="(.*)".*@\1@p' | while read -r name; do 714 test "$name" = "" && continue 715 716 # extract attachment. 717 tmpfile=$(mktemp -p "$d" XXXXXXXXXXXX) 718 mshow -n -O /dev/stdin "$name" < "$tmpmail" > "$tmpfile" 719 720 # use file extension. 721 ext="${name##*/}" 722 case "$ext" in 723 *.tar.*) 724 # special case: support .tar.gz, tar.bz2, etc. 725 ext="tar.${ext##*.}";; 726 *.*) 727 ext="${ext##*.}";; 728 *) 729 ext="";; 730 esac 731 ext="${ext%%*.}" 732 733 # use file extension if it is set. 734 outputfile="$tmpfile" 735 if test "$ext" != ""; then 736 outputfile="$tmpfile.$ext" 737 fi 738 mv "$tmpfile" "$outputfile" 739 b=$(basename "$outputfile") 740 741 chmod 666 "$outputfile" 742 url="gopher://codemadness.org/9/mailpaste/$b" 743 744 echo "$name:" >> "$tmpmsg" 745 echo " Text file: gopher://codemadness.org/0/mailpaste/$b" >> "$tmpmsg" 746 echo " Image file: gopher://codemadness.org/I/mailpaste/$b" >> "$tmpmsg" 747 echo " Binary file: gopher://codemadness.org/9/mailpaste/$b" >> "$tmpmsg" 748 echo "" >> "$tmpmsg" 749 done 750 751 echo "" >> "$tmpmsg" 752 echo "Sincerely," >> "$tmpmsg" 753 echo "Your friendly paste_bot" >> "$tmpmsg" 754 755 # mail back the user. 756 mail -r "$from" -s "Your files" "$from" < "$tmpmsg" 757 758 cleanup 759 </code></pre> 760 <p>The mail daemon processing the mail needs of course to be able to have 761 permissions to write to the specified directory. The user who received the mail 762 needs to be able to read it from a location they can access and have 763 permissions for it also.</p> 764 <h2>Room for improvements</h2> 765 <p>This is just an example script. There is room for many improvements. 766 Feel free to change it in any way you like.</p> 767 <h2>References</h2> 768 <ul> 769 <li><a href="https://man.openbsd.org/aliases">https://man.openbsd.org/aliases</a></li> 770 <li><a href="https://man.openbsd.org/smtpd">https://man.openbsd.org/smtpd</a></li> 771 <li><a href="https://man.openbsd.org/httpd">https://man.openbsd.org/httpd</a></li> 772 <li><a href="https://github.com/leahneukirchen/mblaze">https://github.com/leahneukirchen/mblaze</a></li> 773 </ul> 774 <h2>Bye bye</h2> 775 <p>I hope this enterprise(tm) mail service is inspirational or something ;)</p> 776 ]]></content> 777 </entry> 778 <entry> 779 <title>A simple TODO application</title> 780 <link rel="alternate" type="text/html" href="https://www.codemadness.org/todo-application.html" /> 781 <id>https://www.codemadness.org/todo-application.html</id> 782 <updated>2022-07-01T00:00:00Z</updated> 783 <published>2022-07-01T00:00:00Z</published> 784 <author> 785 <name>Hiltjo</name> 786 <uri>https://www.codemadness.org</uri> 787 </author> 788 <summary>A simple TODO application workflow</summary> 789 <content type="html"><![CDATA[<h1>A simple TODO application</h1> 790 <p><strong>Last modification on </strong> <time>2022-07-01</time></p> 791 <p>This article describes a TODO application or workflow.</p> 792 <h2>Workflow</h2> 793 <p>It works like this:</p> 794 <ul> 795 <li>Open any text editor.</li> 796 <li>Edit the text.</li> 797 <li>Save it in a file (probably named "TODO").</li> 798 <li>Feel happy about it.</li> 799 </ul> 800 <h2>The text format</h2> 801 <p>The text format I use is this:</p> 802 <pre><code>[indendations]<symbol><SPACE><item text><NEWLINE> 803 </code></pre> 804 <p>Most of the time an item is just one line. 805 This format is just a general guideline to keep the items somewhat structured.</p> 806 <h2>Symbols</h2> 807 <p>Items are prefixed with a symbol.</p> 808 <ul> 809 <li>- is an item which is planned to be done at some point.</li> 810 <li>x is an item which is done.</li> 811 <li>? is an item which I'm not (yet) sure about. It can also be an idea.</li> 812 </ul> 813 <p>I use an indendation with a TAB before an item to indicate item dependencies. 814 The items can be nested.</p> 815 <p>For the prioritization I put the most important items and sections from the top 816 to the bottom. These can be reshuffled as you wish of course.</p> 817 <p>To delete an item you remove the line. To archive an item you keep the line.</p> 818 <h2>Sections</h2> 819 <p>A section is a line which has no symbol. This is like a header to group items.</p> 820 <h2>Example</h2> 821 <pre><code>Checklist for releasing project 0.1: 822 - Test project with different compilers and check for warnings. 823 - Documentation: 824 - Proofread and make sure it matches all program behaviour. 825 - Run mandoc -Tlint on the man pages. 826 ? Copy useful examples from the README file to the man page? 827 - Run testsuite and check for failures before release. 828 829 830 project 0.2: 831 ? Investigate if feature mentioned by some user is worth adding. 832 </code></pre> 833 <h1>Example: secure remote cloud-encrypted edit session(tm)</h1> 834 <pre><code>ssh -t host 'ed TODO' 835 </code></pre> 836 <h1>Example: multi-user secure remote cloud-encrypted edit session(tm)</h1> 837 <pre><code>ssh host 838 tmux or tmux a 839 ed TODO 840 </code></pre> 841 <h1>Example: version-controlled multi-user secure remote cloud-encrypted edit session(tm)</h1> 842 <pre><code>ssh host 843 tmux or tmux a 844 ed TODO 845 git add TODO 846 git commit -m 'TODO: update' 847 </code></pre> 848 <h2>Pros</h2> 849 <ul> 850 <li>When you open the TODO file the most important items are at the top.</li> 851 <li>The items are easy to read and modify with any text editor.</li> 852 <li>It is easy to extend the format and use with other text tools.</li> 853 <li>The format is portable: it works on sticky-notes on your CRT monitor too!</li> 854 <li>No monthly online subscription needed and full NO-money-back guarantee.</li> 855 </ul> 856 <h2>Cons</h2> 857 <ul> 858 <li>Complex lists with interconnected dependencies might not work, maybe.</li> 859 <li>It's assumed there is one person maintaining the TODO file. Merging items 860 from multiple people at the same time in this workflow is not recommended.</li> 861 <li>It is too simple: noone will be impressed by it.</li> 862 </ul> 863 <p>I hope this is inspirational or something,</p> 864 ]]></content> 865 </entry> 866 <entry> 867 <title>2FA TOTP without crappy authenticator apps</title> 868 <link rel="alternate" type="text/html" href="https://www.codemadness.org/totp.html" /> 869 <id>https://www.codemadness.org/totp.html</id> 870 <updated>2022-10-29T00:00:00Z</updated> 871 <published>2022-03-23T00:00:00Z</published> 872 <author> 873 <name>Hiltjo</name> 874 <uri>https://www.codemadness.org</uri> 875 </author> 876 <summary>Using 2FA TOTP without crappy authenticator apps</summary> 877 <content type="html"><![CDATA[<h1>2FA TOTP without crappy authenticator apps</h1> 878 <p><strong>Last modification on </strong> <time>2022-10-29</time></p> 879 <p>This describes how to use 2FA without using crappy authenticator "apps" or a 880 mobile device.</p> 881 <h2>Install</h2> 882 <p>On OpenBSD:</p> 883 <pre><code>pkg_add oath-toolkit zbar 884 </code></pre> 885 <p>On Void Linux:</p> 886 <pre><code>xbps-install oath-toolkit zbar 887 </code></pre> 888 <p>There is probably a package for your operating system.</p> 889 <ul> 890 <li>oath-toolkit is used to generate the digits based on the secret key.</li> 891 <li>zbar is used to scan the QR barcode text from the image.</li> 892 </ul> 893 <h2>Steps</h2> 894 <p>Save the QR code image from the authenticator app, website to an image file. 895 Scan the QR code text from the image:</p> 896 <pre><code>zbarimg image.png 897 </code></pre> 898 <p>An example QR code:</p> 899 <p><img src="downloads/2fa/qr.png" alt="QR code example" /></p> 900 <p>The output is typically something like:</p> 901 <pre><code>QR-Code:otpauth://totp/Example:someuser@codemadness.org?secret=SECRETKEY&issuer=Codemadness 902 </code></pre> 903 <p>You only need to scan this QR-code for the secret key once. 904 Make sure to store the secret key in a private safe place and don't show it to 905 anyone else.</p> 906 <p>Using the secret key the following command outputs a 6-digit code by default. 907 In this example we also assume the key is base32-encoded. 908 There can be other parameters and options, this is documented in the Yubico URI 909 string format reference below.</p> 910 <p>Command:</p> 911 <pre><code>oathtool --totp -b SOMEKEY 912 </code></pre> 913 <ul> 914 <li>The --totp option uses the time-variant TOTP mode, by default it uses HMAC SHA1.</li> 915 <li>The -b option uses base32 encoding of KEY instead of hex.</li> 916 </ul> 917 <p>Tip: you can create a script that automatically puts the digits in the 918 clipboard, for example:</p> 919 <pre><code>oathtool --totp -b SOMEKEY | xclip 920 </code></pre> 921 <h2>References</h2> 922 <ul> 923 <li><a href="https://linux.die.net/man/1/zbarimg">zbarimg(1) man page</a></li> 924 <li><a href="https://www.nongnu.org/oath-toolkit/man-oathtool.html">oathtool(1) man page</a></li> 925 <li><a href="https://datatracker.ietf.org/doc/html/rfc6238">RFC6238 - TOTP: Time-Based One-Time Password Algorithm</a></li> 926 <li><a href="https://docs.yubico.com/yesdk/users-manual/application-oath/uri-string-format.html">Yubico.com - otpauth URI string format</a></li> 927 </ul> 928 ]]></content> 929 </entry> 930 <entry> 931 <title>Setup an OpenBSD RISCV64 VM in QEMU</title> 932 <link rel="alternate" type="text/html" href="https://www.codemadness.org/openbsd-riscv64-vm.html" /> 933 <id>https://www.codemadness.org/openbsd-riscv64-vm.html</id> 934 <updated>2021-10-26T00:00:00Z</updated> 935 <published>2021-10-23T00:00:00Z</published> 936 <author> 937 <name>Hiltjo</name> 938 <uri>https://www.codemadness.org</uri> 939 </author> 940 <summary>Setup an OpenBSD RISCV-64 VM in QEMU</summary> 941 <content type="html"><![CDATA[<h1>Setup an OpenBSD RISCV64 VM in QEMU</h1> 942 <p><strong>Last modification on </strong> <time>2021-10-26</time></p> 943 <p>This describes how to setup an OpenBSD RISCV64 VM in QEMU.</p> 944 <p>The shellscript below does the following:</p> 945 <ul> 946 <li>Set up the disk image (raw format).</li> 947 <li>Patch the disk image with the OpenBSD miniroot file for the installation.</li> 948 <li>Downloads the opensbi and u-boot firmware files for qemu.</li> 949 <li>Run the VM with the supported settings.</li> 950 </ul> 951 <p>The script is tested on the host GNU/Void Linux and OpenBSD-current.</p> 952 <p><strong>IMPORTANT!: The signature and checksum for the miniroot, u-boot and opensbi 953 files are not verified. If the host is OpenBSD make sure to instead install the 954 packages (pkg_add u-boot-riscv64 opensbi) and adjust the firmware path for the 955 qemu -bios and -kernel options. </strong></p> 956 <h2>Shellscript</h2> 957 <pre><code>#!/bin/sh 958 # mirror list: https://www.openbsd.org/ftp.html 959 mirror="https://ftp.bit.nl/pub/OpenBSD/" 960 release="7.0" 961 minirootname="miniroot70.img" 962 963 miniroot() { 964 test -f "${minirootname}" && return # download once 965 966 url="${mirror}/${release}/riscv64/${minirootname}" 967 curl -o "${minirootname}" "${url}" 968 } 969 970 createrootdisk() { 971 test -f disk.raw && return # create once 972 qemu-img create disk.raw 10G # create 10 GB disk 973 dd conv=notrunc if=${minirootname} of=disk.raw # write miniroot to disk 974 } 975 976 opensbi() { 977 f="opensbi.tgz" 978 test -f "${f}" && return # download and extract once. 979 980 url="${mirror}/${release}/packages/amd64/opensbi-0.9p0.tgz" 981 curl -o "${f}" "${url}" 982 983 tar -xzf "${f}" share/opensbi/generic/fw_jump.bin 984 } 985 986 uboot() { 987 f="uboot.tgz" 988 test -f "${f}" && return # download and extract once. 989 990 url="${mirror}/${release}/packages/amd64/u-boot-riscv64-2021.07p0.tgz" 991 curl -o "${f}" "${url}" 992 993 tar -xzf "${f}" share/u-boot/qemu-riscv64_smode/u-boot.bin 994 } 995 996 setup() { 997 miniroot 998 createrootdisk 999 opensbi 1000 uboot 1001 } 1002 1003 run() { 1004 qemu-system-riscv64 \ 1005 -machine virt \ 1006 -nographic \ 1007 -m 2048M \ 1008 -smp 2 \ 1009 -bios share/opensbi/generic/fw_jump.bin \ 1010 -kernel share/u-boot/qemu-riscv64_smode/u-boot.bin \ 1011 -drive file=disk.raw,format=raw,id=hd0 -device virtio-blk-device,drive=hd0 \ 1012 -netdev user,id=net0,ipv6=off -device virtio-net-device,netdev=net0 1013 } 1014 1015 setup 1016 run 1017 </code></pre> 1018 ]]></content> 1019 </entry> 1020 <entry> 1021 <title>Sfeed_curses: a curses UI front-end for sfeed</title> 1022 <link rel="alternate" type="text/html" href="https://www.codemadness.org/sfeed_curses-ui.html" /> 1023 <id>https://www.codemadness.org/sfeed_curses-ui.html</id> 1024 <updated>2022-05-08T00:00:00Z</updated> 1025 <published>2020-06-25T00:00:00Z</published> 1026 <author> 1027 <name>Hiltjo</name> 1028 <uri>https://www.codemadness.org</uri> 1029 </author> 1030 <summary>Sfeed_curses is a curses UI front-end for the sfeed RSS/Atom parser</summary> 1031 <content type="html"><![CDATA[<h1>Sfeed_curses: a curses UI front-end for sfeed</h1> 1032 <p><strong>Last modification on </strong> <time>2022-05-08</time></p> 1033 <p>sfeed_curses is a curses UI front-end for <a href="sfeed.html">sfeed</a>. 1034 It is now part of sfeed.</p> 1035 <p>It shows the TAB-separated feed items in a graphical command-line UI. The 1036 interface has a look inspired by the <a href="http://www.mutt.org/">mutt mail client</a>. It has a sidebar 1037 panel for the feeds, a panel with a listing of the items and a small statusbar 1038 for the selected item/URL. Some functions like searching and scrolling are 1039 integrated in the interface itself.</p> 1040 <h2>Features</h2> 1041 <ul> 1042 <li>Relatively few LOC, about 2.5K lines of C.</li> 1043 <li>Few dependencies: a C compiler and a curses library (typically ncurses). 1044 It also requires a terminal (emulator) supporting UTF-8.</li> 1045 <li>Easy to customize by modifying the small source-code and shellscripts.</li> 1046 <li>Quite fast.</li> 1047 <li>Plumb support: open the URL or an enclosure URL directly with any program.</li> 1048 <li>Pipe support: pipe the selected Tab-Separated Value line to a program for 1049 scripting purposes. Like viewing the content in any way you like.</li> 1050 <li>Yank support: copy the URL or an enclosure URL to the clipboard.</li> 1051 <li>Familiar keybinds: supports both vi-like, emacs-like and arrow keys for 1052 actions.</li> 1053 <li>Mouse support: it supports xterm X10 and extended SGR encoding.</li> 1054 <li>Support two ways of managing read/unread items. 1055 By default sfeed_curses marks the feed items of the last day as new/bold. 1056 Alternatively a simple plain-text list with the read URLs can be used.</li> 1057 <li>UI layouts: supports vertical, horizontal and monocle (full-screen) layouts. 1058 Useful for different kind of screen sizes.</li> 1059 <li>Auto-execute keybind commands at startup to automate setting a preferred 1060 layout, toggle showing new items or other actions.</li> 1061 </ul> 1062 <p>Like the format programs included in sfeed you can run it by giving the feed 1063 files as arguments like this:</p> 1064 <pre><code>sfeed_curses ~/.sfeed/feeds/* 1065 </code></pre> 1066 <p>... or by reading directly from stdin:</p> 1067 <pre><code>sfeed_curses < ~/.sfeed/feeds/xkcd 1068 </code></pre> 1069 <p>It will show a sidebar if one or more files are specified as parameters. It 1070 will not show the sidebar by default when reading from stdin.</p> 1071 <p><a href="downloads/screenshots/sfeed_curses_screenshot.png"><img src="downloads/screenshots/sfeed_curses_screenshot.png" alt="Screenshot showing what the UI looks" width="480" height="270" loading="lazy" /></a></p> 1072 <p>On pressing the 'o' or ENTER keybind it will open the link URL of an item with 1073 the plumb program. On pressing the 'a', 'e' or '@' keybind it will open the 1074 enclosure URL if there is one. The default plumb program is set to <a href="https://portland.freedesktop.org/doc/xdg-open.html">xdg-open</a>, 1075 but can be modified by setting the environment variable $SFEED_PLUMBER. The 1076 plumb program receives the URL as a command-line argument.</p> 1077 <p>The TAB-Separated-Value line of the current selected item in the feed file can 1078 be piped to a program by pressing the 'c', 'p' or '|' keybind. This allows much 1079 flexibility to make a content formatter or write other custom actions or views. 1080 This line is in the exact same format as described in the sfeed(5) man page.</p> 1081 <p>The pipe program can be changed by setting the environment variable 1082 $SFEED_PIPER.</p> 1083 <p><a href="downloads/screenshots/sfeed_curses_pipe_screenshot.png"><img src="downloads/screenshots/sfeed_curses_pipe_screenshot.png" alt="Screenshot showing the output of the pipe content script" width="480" height="270" loading="lazy" /></a></p> 1084 <p>The above screenshot shows the included <a href="https://git.codemadness.org/sfeed_curses/file/sfeed_content.html">sfeed_content</a> shellscript which uses 1085 the <a href="https://invisible-island.net/lynx/">lynx text-browser</a> to convert HTML to plain-text. It pipes the formatted 1086 plain-text to the user $PAGER (or "less").</p> 1087 <p>Of course the script can be easily changed to use a different browser or 1088 HTML-to-text converter like:</p> 1089 <ul> 1090 <li><a href="https://www.dillo.org/">dillo</a></li> 1091 <li><a href="http://www.jikos.cz/~mikulas/links/">links</a></li> 1092 <li><a href="http://w3m.sourceforge.net/">w3m</a></li> 1093 <li><a href="https://git.codemadness.org/webdump/file/README.html">webdump</a></li> 1094 </ul> 1095 <p>It's easy to modify the color-theme by changing the macros in the source-code 1096 or set a predefined theme at compile-time. The README file contains information 1097 how to set a theme. On the left a <a href="https://templeos.org/">TempleOS</a>-like color-theme on the right a 1098 <a href="https://newsboat.org/">newsboat</a>-like colorscheme.</p> 1099 <p><a href="downloads/screenshots/sfeed_curses_theme_screenshot.png"><img src="downloads/screenshots/sfeed_curses_theme_screenshot.png" alt="Screenshot showing a custom colorscheme" width="480" height="270" loading="lazy" /></a></p> 1100 <p>It supports a vertical layout, horizontal and monocle (full-screen) layout. 1101 This can be useful for different kind of screen sizes. The keybinds '1', '2' 1102 and '3' can be used to switch between these layouts.</p> 1103 <p><a href="downloads/screenshots/sfeed_curses_horizontal_screenshot.png"><img src="downloads/screenshots/sfeed_curses_horizontal_screenshot.png" alt="Screenshot showing the horizontal layout" width="480" height="270" loading="lazy" /></a></p> 1104 <h2>Clone</h2> 1105 <pre><code>git clone git://git.codemadness.org/sfeed 1106 </code></pre> 1107 <h2>Browse</h2> 1108 <p>You can browse the source-code at:</p> 1109 <ul> 1110 <li><a href="https://git.codemadness.org/sfeed/">https://git.codemadness.org/sfeed/</a></li> 1111 <li><a href="gopher://codemadness.org/1/git/sfeed">gopher://codemadness.org/1/git/sfeed</a></li> 1112 </ul> 1113 <h2>Download releases</h2> 1114 <p>Releases are available at:</p> 1115 <ul> 1116 <li><a href="https://codemadness.org/releases/sfeed/">https://codemadness.org/releases/sfeed/</a></li> 1117 <li><a href="gopher://codemadness.org/1/releases/sfeed">gopher://codemadness.org/1/releases/sfeed</a></li> 1118 </ul> 1119 <h2>Build and install</h2> 1120 <pre><code>$ make 1121 # make install 1122 </code></pre> 1123 ]]></content> 1124 </entry> 1125 <entry> 1126 <title>hurl: HTTP, HTTPS and Gopher file grabber</title> 1127 <link rel="alternate" type="text/html" href="https://www.codemadness.org/hurl.html" /> 1128 <id>https://www.codemadness.org/hurl.html</id> 1129 <updated>2020-07-20T00:00:00Z</updated> 1130 <published>2019-11-10T00:00:00Z</published> 1131 <author> 1132 <name>Hiltjo</name> 1133 <uri>https://www.codemadness.org</uri> 1134 </author> 1135 <summary>hurl: HTTP, HTTPS and Gopher file grabber</summary> 1136 <content type="html"><![CDATA[<h1>hurl: HTTP, HTTPS and Gopher file grabber</h1> 1137 <p><strong>Last modification on </strong> <time>2020-07-20</time></p> 1138 <p>hurl is a relatively simple HTTP, HTTPS and Gopher client/file grabber.</p> 1139 <h2>Why?</h2> 1140 <p>Sometimes (or most of the time?) you just want to fetch a file via the HTTP, 1141 HTTPS or Gopher protocol.</p> 1142 <p>The focus of this tool is only this.</p> 1143 <h2>Features</h2> 1144 <ul> 1145 <li>Uses OpenBSD pledge(2) and unveil(2). Allow no filesystem access (writes to 1146 stdout).</li> 1147 <li>Impose time-out and maximum size limits.</li> 1148 <li>Use well-defined exitcodes for reliable scripting (curl sucks at this).</li> 1149 <li>Send as little information as possible (no User-Agent etc by default).</li> 1150 </ul> 1151 <h2>Anti-features</h2> 1152 <ul> 1153 <li>No HTTP byte range support.</li> 1154 <li>No HTTP User-Agent.</li> 1155 <li>No HTTP If-Modified-Since/If-* support.</li> 1156 <li>No HTTP auth support.</li> 1157 <li>No HTTP/2+ support.</li> 1158 <li>No HTTP keep-alive.</li> 1159 <li>No HTTP chunked-encoding support.</li> 1160 <li>No HTTP redirect support.</li> 1161 <li>No (GZIP) compression support.</li> 1162 <li>No cookie-jar or cookie parsing support.</li> 1163 <li>No Gopher text handling (".\r\n").</li> 1164 <li>... etc...</li> 1165 </ul> 1166 <h2>Dependencies</h2> 1167 <ul> 1168 <li>C compiler (C99).</li> 1169 <li>libc + some BSD functions like err() and strlcat().</li> 1170 <li>LibreSSL(-portable)</li> 1171 <li>libtls (part of LibreSSL).</li> 1172 </ul> 1173 <h2>Optional dependencies</h2> 1174 <ul> 1175 <li>POSIX make(1) (for Makefile).</li> 1176 <li>mandoc for documentation: <a href="https://mdocml.bsd.lv/">https://mdocml.bsd.lv/</a></li> 1177 </ul> 1178 <h2>Clone</h2> 1179 <pre><code>git clone git://git.codemadness.org/hurl 1180 </code></pre> 1181 <h2>Browse</h2> 1182 <p>You can browse the source-code at:</p> 1183 <ul> 1184 <li><a href="https://git.codemadness.org/hurl/">https://git.codemadness.org/hurl/</a></li> 1185 <li><a href="gopher://codemadness.org/1/git/hurl">gopher://codemadness.org/1/git/hurl</a></li> 1186 </ul> 1187 <h2>Download releases</h2> 1188 <p>Releases are available at:</p> 1189 <ul> 1190 <li><a href="https://codemadness.org/releases/hurl/">https://codemadness.org/releases/hurl/</a></li> 1191 <li><a href="gopher://codemadness.org/1/releases/hurl">gopher://codemadness.org/1/releases/hurl</a></li> 1192 </ul> 1193 <h2>Build and install</h2> 1194 <pre><code>$ make 1195 # make install 1196 </code></pre> 1197 <h2>Examples</h2> 1198 <p>Fetch the Atom feed from this site using a maximum filesize limit of 1MB and 1199 a time-out limit of 15 seconds:</p> 1200 <pre><code>hurl -m 1048576 -t 15 "https://codemadness.org/atom.xml" 1201 </code></pre> 1202 <p>There is an -H option to add custom headers. This way some of the anti-features 1203 listed above are supported. For example some CDNs like Cloudflare are known to 1204 block empty or certain User-Agents.</p> 1205 <p>User-Agent:</p> 1206 <pre><code>hurl -H 'User-Agent: some browser' 'https://codemadness.org/atom.xml' 1207 </code></pre> 1208 <p>HTTP Basic Auth (base64-encoded username:password):</p> 1209 <pre><code>hurl -H 'Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=' \ 1210 'https://codemadness.org/atom.xml' 1211 </code></pre> 1212 <p>GZIP (this assumes the served response Content-Type is gzip):</p> 1213 <pre><code>hurl -H 'Accept-Encoding: gzip' 'https://somesite/' | gzip -d 1214 </code></pre> 1215 ]]></content> 1216 </entry> 1217 <entry> 1218 <title>json2tsv: a JSON to TSV converter</title> 1219 <link rel="alternate" type="text/html" href="https://www.codemadness.org/json2tsv.html" /> 1220 <id>https://www.codemadness.org/json2tsv.html</id> 1221 <updated>2021-09-25T00:00:00Z</updated> 1222 <published>2019-10-13T00:00:00Z</published> 1223 <author> 1224 <name>Hiltjo</name> 1225 <uri>https://www.codemadness.org</uri> 1226 </author> 1227 <summary>json2tsv: a JSON to TAB-Separated Value converter</summary> 1228 <content type="html"><![CDATA[<h1>json2tsv: a JSON to TSV converter</h1> 1229 <p><strong>Last modification on </strong> <time>2021-09-25</time></p> 1230 <p>Convert JSON to TSV or separated output.</p> 1231 <p>json2tsv reads JSON data from stdin. It outputs each JSON type to a TAB- 1232 Separated Value format per line by default.</p> 1233 <h2>TAB-Separated Value format</h2> 1234 <p>The output format per line is:</p> 1235 <pre><code>nodename<TAB>type<TAB>value<LF> 1236 </code></pre> 1237 <p>Control-characters such as a newline, TAB and backslash (\n, \t and \) are 1238 escaped in the nodename and value fields. Other control-characters are 1239 removed.</p> 1240 <p>The type field is a single byte and can be:</p> 1241 <ul> 1242 <li>a for array</li> 1243 <li>b for bool</li> 1244 <li>n for number</li> 1245 <li>o for object</li> 1246 <li>s for string</li> 1247 <li>? for null</li> 1248 </ul> 1249 <p>Filtering on the first field "nodename" is easy using awk for example.</p> 1250 <h2>Features</h2> 1251 <ul> 1252 <li>Accepts all <strong>valid</strong> JSON.</li> 1253 <li>Designed to work well with existing UNIX programs like awk and grep.</li> 1254 <li>Straightforward and not much lines of code: about 475 lines of C.</li> 1255 <li>Few dependencies: C compiler (C99), libc.</li> 1256 <li>No need to learn a new (meta-)language for processing data.</li> 1257 <li>The parser supports code point decoding and UTF-16 surrogates to UTF-8.</li> 1258 <li>It does not output control-characters to the terminal for security reasons by 1259 default (but it has a -r option if needed).</li> 1260 <li>On OpenBSD it supports <a href="https://man.openbsd.org/pledge">pledge(2)</a> for syscall restriction: 1261 pledge("stdio", NULL).</li> 1262 <li>Supports setting a different field separator and record separator with the -F 1263 and -R option.</li> 1264 </ul> 1265 <h2>Cons</h2> 1266 <ul> 1267 <li>For the tool there is additional overhead by processing and filtering data 1268 from stdin after parsing.</li> 1269 <li>The parser does not do complete validation on numbers.</li> 1270 <li>The parser accepts some bad input such as invalid UTF-8 1271 (see <a href="https://tools.ietf.org/html/rfc8259#section-8.1">RFC8259 - 8.1. Character Encoding</a>). 1272 json2tsv reads from stdin and does not do assumptions about a "closed 1273 ecosystem" as described in the RFC.</li> 1274 <li>The parser accepts some bad JSON input and "extensions" 1275 (see <a href="https://tools.ietf.org/html/rfc8259#section-9">RFC8259 - 9. Parsers</a>).</li> 1276 <li>Encoded NUL bytes (\u0000) in strings are ignored. 1277 (see <a href="https://tools.ietf.org/html/rfc8259#section-9">RFC8259 - 9. Parsers</a>). 1278 "An implementation may set limits on the length and character contents of 1279 strings."</li> 1280 <li>The parser is not the fastest possible JSON parser (but also not the 1281 slowest). For example: for ease of use, at the cost of performance all 1282 strings are decoded, even though they may be unused.</li> 1283 </ul> 1284 <h2>Why Yet Another JSON parser?</h2> 1285 <p>I wanted a tool that makes parsing JSON easier and work well from the shell, 1286 similar to <a href="https://stedolan.github.io/jq/">jq</a>.</p> 1287 <p>sed and grep often work well enough for matching some value using some regex 1288 pattern, but it is not good enough to parse JSON correctly or to extract all 1289 information: just like parsing HTML/XML using some regex is not good (enough) 1290 or a good idea :P.</p> 1291 <p>I didn't want to learn a new specific <a href="https://stedolan.github.io/jq/manual/#Builtinoperatorsandfunctions">meta-language</a> which jq has and wanted 1292 something simpler.</p> 1293 <p>While it is more efficient to embed this query language for data aggregation, 1294 it is also less simple. In my opinion it is simpler to separate this and use 1295 pattern-processing by awk or an other filtering/aggregating program.</p> 1296 <p>For the parser, there are many JSON parsers out there, like the efficient 1297 <a href="https://github.com/zserge/jsmn">jsmn parser</a>, however a few parser behaviours I want to have are:</p> 1298 <ul> 1299 <li>jsmn buffers data as tokens, which is very efficient, but also a bit 1300 annoying as an API as it requires another layer of code to interpret the 1301 tokens.</li> 1302 <li>jsmn does not handle decoding strings by default. Which is very efficient 1303 if you don't need parts of the data though.</li> 1304 <li>jsmn does not keep context of nested structures by default, so may require 1305 writing custom utility functions for nested data.</li> 1306 </ul> 1307 <p>This is why I went for a parser design that uses a single callback per "node" 1308 type and keeps track of the current nested structure in a single array and 1309 emits that.</p> 1310 <h2>Clone</h2> 1311 <pre><code>git clone git://git.codemadness.org/json2tsv 1312 </code></pre> 1313 <h2>Browse</h2> 1314 <p>You can browse the source-code at:</p> 1315 <ul> 1316 <li><a href="https://git.codemadness.org/json2tsv/">https://git.codemadness.org/json2tsv/</a></li> 1317 <li><a href="gopher://codemadness.org/1/git/json2tsv">gopher://codemadness.org/1/git/json2tsv</a></li> 1318 </ul> 1319 <h2>Download releases</h2> 1320 <p>Releases are available at:</p> 1321 <ul> 1322 <li><a href="https://codemadness.org/releases/json2tsv/">https://codemadness.org/releases/json2tsv/</a></li> 1323 <li><a href="gopher://codemadness.org/1/releases/json2tsv">gopher://codemadness.org/1/releases/json2tsv</a></li> 1324 </ul> 1325 <h2>Build and install</h2> 1326 <pre><code>$ make 1327 # make install 1328 </code></pre> 1329 <h2>Examples</h2> 1330 <p>An usage example to parse posts of the JSON API of <a href="https://www.reddit.com/">reddit.com</a> and format them 1331 to a plain-text list using awk:</p> 1332 <pre><code>#!/bin/sh 1333 curl -s -H 'User-Agent:' 'https://old.reddit.com/.json?raw_json=1&limit=100' | \ 1334 json2tsv | \ 1335 awk -F '\t' ' 1336 function show() { 1337 if (length(o["title"]) == 0) 1338 return; 1339 print n ". " o["title"] " by " o["author"] " in r/" o["subreddit"]; 1340 print o["url"]; 1341 print ""; 1342 } 1343 $1 == ".data.children[].data" { 1344 show(); 1345 n++; 1346 delete o; 1347 } 1348 $1 ~ /^\.data\.children\[\]\.data\.[a-zA-Z0-9_]*$/ { 1349 o[substr($1, 23)] = $3; 1350 } 1351 END { 1352 show(); 1353 }' 1354 </code></pre> 1355 <h2>References</h2> 1356 <ul> 1357 <li>Sites: 1358 <ul> 1359 <li><a href="http://seriot.ch/parsing_json.php">seriot.ch - Parsing JSON is a Minefield</a></li> 1360 <li><a href="https://github.com/nst/JSONTestSuite">A comprehensive test suite for RFC 8259 compliant JSON parsers</a></li> 1361 <li><a href="https://json.org/">json.org</a></li> 1362 </ul> 1363 </li> 1364 <li>Current standard: 1365 <ul> 1366 <li><a href="https://tools.ietf.org/html/rfc8259">RFC8259 - The JavaScript Object Notation (JSON) Data Interchange Format</a></li> 1367 <li><a href="https://www.ecma-international.org/publications/standards/Ecma-404.htm">Standard ECMA-404 - The JSON Data Interchange Syntax (2nd edition (December 2017)</a></li> 1368 </ul> 1369 </li> 1370 <li>Historic standards: 1371 <ul> 1372 <li><a href="https://tools.ietf.org/html/rfc7159">RFC7159 - The JavaScript Object Notation (JSON) Data Interchange Format (obsolete)</a></li> 1373 <li><a href="https://tools.ietf.org/html/rfc7158">RFC7158 - The JavaScript Object Notation (JSON) Data Interchange Format (obsolete)</a></li> 1374 <li><a href="https://tools.ietf.org/html/rfc4627">RFC4627 - The JavaScript Object Notation (JSON) Data Interchange Format (obsolete, original)</a></li> 1375 </ul> 1376 </li> 1377 </ul> 1378 ]]></content> 1379 </entry> 1380 <entry> 1381 <title>OpenBSD: setup a local auto-installation server</title> 1382 <link rel="alternate" type="text/html" href="https://www.codemadness.org/openbsd-autoinstall.html" /> 1383 <id>https://www.codemadness.org/openbsd-autoinstall.html</id> 1384 <updated>2020-04-30T00:00:00Z</updated> 1385 <published>2019-04-24T00:00:00Z</published> 1386 <author> 1387 <name>Hiltjo</name> 1388 <uri>https://www.codemadness.org</uri> 1389 </author> 1390 <summary>OpenBSD: setup a local auto-installation server</summary> 1391 <content type="html"><![CDATA[<h1>OpenBSD: setup a local auto-installation server</h1> 1392 <p><strong>Last modification on </strong> <time>2020-04-30</time></p> 1393 <p>This guide describes how to setup a local mirror and installation/upgrade 1394 server that requires little or no input interaction.</p> 1395 <h2>Setup a local HTTP mirror</h2> 1396 <p>The HTTP mirror will be used to fetch the base sets and (optional) custom sets. 1397 In this guide we will assume <strong>192.168.0.2</strong> is the local installation server 1398 and mirror, the CPU architecture is amd64 and the OpenBSD release version is 1399 6.5. We will store the files in the directory with the structure:</p> 1400 <pre><code>http://192.168.0.2/pub/OpenBSD/6.5/amd64/ 1401 </code></pre> 1402 <p>Create the www serve directory and fetch all sets and install files 1403 (if needed to save space *.iso and install65.fs can be skipped):</p> 1404 <pre><code>$ cd /var/www/htdocs 1405 $ mkdir -p pub/OpenBSD/6.5/amd64/ 1406 $ cd pub/OpenBSD/6.5/amd64/ 1407 $ ftp 'ftp://ftp.nluug.nl/pub/OpenBSD/6.5/amd64/*' 1408 </code></pre> 1409 <p>Verify signature and check some checksums:</p> 1410 <pre><code>$ signify -C -p /etc/signify/openbsd-65-base.pub -x SHA256.sig 1411 </code></pre> 1412 <p>Setup <a href="https://man.openbsd.org/httpd.8">httpd(8)</a> for simple file serving:</p> 1413 <pre><code># $FAVORITE_EDITOR /etc/httpd.conf 1414 </code></pre> 1415 <p>A minimal example config for <a href="https://man.openbsd.org/httpd.conf.5">httpd.conf(5)</a>:</p> 1416 <pre><code>server "*" { 1417 listen on * port 80 1418 } 1419 </code></pre> 1420 <p>The default www root directory is: /var/www/htdocs/</p> 1421 <p>Enable the httpd daemon to start by default and start it now:</p> 1422 <pre><code># rcctl enable httpd 1423 # rcctl start httpd 1424 </code></pre> 1425 <h2>Creating an installation response/answer file</h2> 1426 <p>The installer supports loading responses to the installation/upgrade questions 1427 from a simple text file. We can do a regular installation and copy the answers 1428 from the saved file to make an automated version of it.</p> 1429 <p>Do a test installation, at the end of the installation or upgrade when asked the 1430 question:</p> 1431 <pre><code>Exit to (S)hell, (H)alt or (R)eboot? 1432 </code></pre> 1433 <p>Type S to go to the shell. Find the response file for an installation and copy 1434 it to some USB stick or write down the response answers:</p> 1435 <pre><code>cp /tmp/i/install.resp /mnt/usbstick/ 1436 </code></pre> 1437 <p>A response file could be for example:</p> 1438 <pre><code>System hostname = testvm 1439 Which network interface do you wish to configure = em0 1440 IPv4 address for em0 = dhcp 1441 IPv6 address for em0 = none 1442 Which network interface do you wish to configure = done 1443 Password for root account = $2b$10$IqI43aXjgD55Q3nLbRakRO/UAG6SAClL9pyk0vIUpHZSAcLx8fWk. 1444 Password for user testuser = $2b$10$IqI43aXjgD55Q3nLbRakRO/UAG6SAClL9pyk0vIUpHZSAcLx8fWk. 1445 Start sshd(8) by default = no 1446 Do you expect to run the X Window System = no 1447 Setup a user = testuser 1448 Full name for user testuser = testuser 1449 What timezone are you in = Europe/Amsterdam 1450 Which disk is the root disk = wd0 1451 Use (W)hole disk MBR, whole disk (G)PT, (O)penBSD area or (E)dit = OpenBSD 1452 Use (A)uto layout, (E)dit auto layout, or create (C)ustom layout = a 1453 Location of sets = http 1454 HTTP proxy URL = none 1455 HTTP Server = 192.168.0.2 1456 Server directory = pub/OpenBSD/6.5/amd64 1457 Unable to connect using https. Use http instead = yes 1458 Location of sets = http 1459 Set name(s) = done 1460 Location of sets = done 1461 Exit to (S)hell, (H)alt or (R)eboot = R 1462 </code></pre> 1463 <p>Get custom encrypted password for response file:</p> 1464 <pre><code>$ printf '%s' 'yourpassword' | encrypt 1465 </code></pre> 1466 <h2>Changing the RAMDISK kernel disk image</h2> 1467 <p><a href="https://man.openbsd.org/rdsetroot.8">rdsetroot(8)</a> is publicly exposed now in base since 6.5. Before 6.5 it is 1468 available in the /usr/src/ tree as elfrdsetroot, see also the <a href="https://man.openbsd.org/rd.4">rd(4)</a> man page.</p> 1469 <pre><code>$ mkdir auto 1470 $ cd auto 1471 $ cp pubdir/bsd.rd . 1472 $ rdsetroot -x bsd.rd disk.fs 1473 # vnconfig vnd0 disk.fs 1474 # mkdir mount 1475 # mount /dev/vnd0a mount 1476 </code></pre> 1477 <p>Copy the response file (install.resp) to: mount/auto_install.conf 1478 (installation) <strong>or</strong> mount/auto_upgrade.conf (upgrade), but not both. In this 1479 guide we will do an auto-installation.</p> 1480 <p>Unmount, detach and patch RAMDISK:</p> 1481 <pre><code># umount mount 1482 # vnconfig -u vnd0 1483 $ rdsetroot bsd.rd disk.fs 1484 </code></pre> 1485 <p>To test copy bsd.rd to the root of some testmachine like /bsd.test.rd then 1486 (re)boot and type:</p> 1487 <pre><code>boot /bsd.test.rd 1488 </code></pre> 1489 <p>In the future (6.5+) it will be possible to copy to a file named "/bsd.upgrade" 1490 in the root of a current system and automatically load the kernel: 1491 <a href="https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/stand/boot/boot.c?rev=1.46&content-type=text/x-cvsweb-markup">See the script bsd.upgrade in CVS.</a> 1492 Of course this is possible with PXE boot or some custom USB/ISO also. 1493 As explained in the <a href="https://man.openbsd.org/autoinstall.8">autoinstall(8)</a> man page: create either an 1494 auto_upgrade.conf <strong>or</strong> an auto_install.conf, but not both.</p> 1495 <h2>Create bootable miniroot</h2> 1496 <p>In this example the miniroot will boot the custom kernel, but fetch all the 1497 sets from the local network.</p> 1498 <p>We will base our miniroot of the official version: miniroot65.fs.</p> 1499 <p>We will create a 16MB miniroot to boot from (in this guide it is assumed the 1500 original miniroot is about 4MB and the modified kernel image fits in the new 1501 allocated space):</p> 1502 <pre><code>$ dd if=/dev/zero of=new.fs bs=512 count=32768 1503 </code></pre> 1504 <p>Copy first part of the original image to the new disk (no truncation):</p> 1505 <pre><code>$ dd conv=notrunc if=miniroot65.fs of=new.fs 1506 # vnconfig vnd0 new.fs 1507 </code></pre> 1508 <p>Expand disk OpenBSD boundaries:</p> 1509 <pre><code># disklabel -E vnd0 1510 > b 1511 Starting sector: [1024] 1512 Size ('*' for entire disk): [8576] * 1513 > r 1514 Total free sectors: 1168. 1515 > c a 1516 Partition a is currently 8576 sectors in size, and can have a maximum 1517 size of 9744 sectors. 1518 size: [8576] * 1519 > w 1520 > q 1521 </code></pre> 1522 <p>or:</p> 1523 <pre><code># printf 'b\n\n*\nc a\n*\nw\n' | disklabel -E vnd0 1524 </code></pre> 1525 <p>Grow filesystem and check it and mark as clean:</p> 1526 <pre><code># growfs -y /dev/vnd0a 1527 # fsck -y /dev/vnd0a 1528 </code></pre> 1529 <p>Mount filesystem:</p> 1530 <pre><code># mount /dev/vnd0a mount/ 1531 </code></pre> 1532 <p>The kernel on the miniroot is GZIP compressed. Compress our modified bsd.rd and 1533 overwrite the original kernel:</p> 1534 <pre><code># gzip -c9n bsd.rd > mount/bsd 1535 </code></pre> 1536 <p>Or to save space (+- 500KB) by stripping debug symbols, taken from bsd.gz target 1537 <a href="https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/distrib/amd64/iso/Makefile">in this Makefile</a>.</p> 1538 <pre><code>$ cp bsd.rd bsd.strip 1539 $ strip bsd.strip 1540 $ strip -R .comment -R .SUNW_ctf bsd.strip 1541 $ gzip -c9n bsd.strip > bsd.gz 1542 $ cp bsd.gz mount/bsd 1543 </code></pre> 1544 <p>Now unmount and detach:</p> 1545 <pre><code># umount mount/ 1546 # vnconfig -u vnd0 1547 </code></pre> 1548 <p>Now you can <a href="https://man.openbsd.org/dd.1">dd(1)</a> the image new.fs to your bootable (USB) medium.</p> 1549 <h2>Adding custom sets (optional)</h2> 1550 <p>For patching <a href="https://man.openbsd.org/rc.firsttime.8">/etc/rc.firsttime</a> and other system files it is useful to use a 1551 customized installation set like siteVERSION.tgz, for example: site65.tgz. The 1552 sets can even be specified per host/MAC address like 1553 siteVERSION-$(hostname -s).tgz so for example: site65-testvm.tgz</p> 1554 <p>When the installer checks the base sets of the mirror it looks for a file 1555 index.txt. To add custom sets the site entries have to be added.</p> 1556 <p>For example:</p> 1557 <pre><code>-rw-r--r-- 1 1001 0 4538975 Oct 11 13:58:26 2018 site65-testvm.tgz 1558 </code></pre> 1559 <p>The filesize, permissions etc do not matter and are not checked by the 1560 installer. Only the filename is matched by a regular expression.</p> 1561 <h2>Sign custom site* tarball sets (optional)</h2> 1562 <p>If you have custom sets without creating a signed custom release you will be 1563 prompted for the messages:</p> 1564 <pre><code>checksum test failed 1565 </code></pre> 1566 <p>and:</p> 1567 <pre><code>unverified sets: continue without verification 1568 </code></pre> 1569 <p>OpenBSD uses the program <a href="https://man.openbsd.org/signify.1">signify(1)</a> to cryptographically sign and 1570 verify filesets.</p> 1571 <p>To create a custom public/private keypair (ofcourse make sure to store the 1572 private key privately):</p> 1573 <pre><code>$ signify -G -n -c "Custom 6.5 install" -p custom-65-base.pub -s custom-65-base.sec 1574 </code></pre> 1575 <p>Create new checksum file with filelist of the current directory (except SHA256* 1576 files):</p> 1577 <pre><code>$ printf '%s\n' * | grep -v SHA256 | xargs sha256 > SHA256 1578 </code></pre> 1579 <p>Sign SHA256 and store as SHA256.sig, embed signature:</p> 1580 <pre><code>$ signify -S -e -s /privatedir/custom-65-base.sec -m SHA256 -x SHA256.sig 1581 </code></pre> 1582 <p>Verify the created signature and data is correct:</p> 1583 <pre><code>$ signify -C -p /somelocation/custom-65-base.pub -x SHA256.sig 1584 </code></pre> 1585 <p>Copy <strong>only</strong> the <strong>public</strong> key to the RAMDISK:</p> 1586 <pre><code>$ cp custom-65-base.pub mount/etc/signify/custom-65-base.pub 1587 </code></pre> 1588 <p>Now we have to patch the install.sub file to check our public key. If you know 1589 a better way without having to patch this script, please let me know.</p> 1590 <p>Change the variable PUB_KEY in the shellscript mount/install.sub from:</p> 1591 <pre><code>PUB_KEY=/etc/signify/openbsd-${VERSION}-base.pub 1592 </code></pre> 1593 <p>To:</p> 1594 <pre><code>PUB_KEY=/etc/signify/custom-${VERSION}-base.pub 1595 </code></pre> 1596 <p>And for upgrades from:</p> 1597 <pre><code>$UPGRADE_BSDRD && 1598 PUB_KEY=/mnt/etc/signify/openbsd-$((VERSION + 1))-base.pub 1599 </code></pre> 1600 <p>To:</p> 1601 <pre><code>$UPGRADE_BSDRD && 1602 PUB_KEY=/mnt/etc/signify/custom-$((VERSION + 1))-base.pub 1603 </code></pre> 1604 <h2>Ideas</h2> 1605 <ul> 1606 <li>Patch <a href="https://man.openbsd.org/rc.firsttime.8">rc.firsttime(8)</a>: and run syspatch, add ports, setup xenodm etc.</li> 1607 <li>Custom partitioning scheme, see <a href="https://man.openbsd.org/autoinstall.8">autoinstall(8)</a> "URL to autopartitioning 1608 template for disklabel = url".</li> 1609 <li>Setup <a href="https://man.openbsd.org/pxeboot.8">pxeboot(8)</a> to boot and install over the network using 1610 <a href="https://man.openbsd.org/dhcpd.8">dhcpd(8)</a> and 1611 <a href="https://man.openbsd.org/tftpd.8">tftpd(8)</a> then not even some USB stick is required.</li> 1612 </ul> 1613 <h2>References</h2> 1614 <ul> 1615 <li>Main OpenBSD installation and upgrade shellscript: 1616 <a href="https://cvsweb.openbsd.org/src/distrib/miniroot/install.sub">/usr/src/distrib/miniroot/install.sub</a></li> 1617 </ul> 1618 ]]></content> 1619 </entry> 1620 <entry> 1621 <title>Idiotbox: Youtube interface</title> 1622 <link rel="alternate" type="text/html" href="https://www.codemadness.org/idiotbox.html" /> 1623 <id>https://www.codemadness.org/idiotbox.html</id> 1624 <updated>2021-12-25T00:00:00Z</updated> 1625 <published>2019-02-10T00:00:00Z</published> 1626 <author> 1627 <name>Hiltjo</name> 1628 <uri>https://www.codemadness.org</uri> 1629 </author> 1630 <summary>Idiotbox: Youtube interface</summary> 1631 <content type="html"><![CDATA[<h1>Idiotbox: Youtube interface</h1> 1632 <p><strong>Last modification on </strong> <time>2021-12-25</time></p> 1633 <p>Idiotbox is a less resource-heavy Youtube interface. For viewing videos it is 1634 recommended to use it with <a href="https://mpv.io/">mpv</a> or 1635 <a href="https://mplayerhq.hu/">mplayer</a> with 1636 <a href="https://youtube-dl.org/">youtube-dl</a> or 1637 <a href="https://github.com/yt-dlp/yt-dlp">yt-dlp</a>.</p> 1638 <p>For more (up-to-date) information see the <a href="/git/frontends/file/youtube/README.html">README</a> file.</p> 1639 <h2>Why</h2> 1640 <p>In my opinion the standard Youtube web interface is:</p> 1641 <ul> 1642 <li>Non-intuitive, too much visual crap.</li> 1643 <li>Too resource-hungry, both in CPU and bandwidth.</li> 1644 <li>Doesn't work well on simpler (text-based) browsers such as netsurf and links.</li> 1645 </ul> 1646 <h2>Features</h2> 1647 <ul> 1648 <li>Doesn't use JavaScript.</li> 1649 <li>Doesn't use (tracking) cookies.</li> 1650 <li>CSS is optional.</li> 1651 <li>Multiple interfaces available: HTTP CGI, command-line, Gopher CGI (gph), 1652 this is a work-in-progress.</li> 1653 <li>Doesn't use or require the Google API.</li> 1654 <li>CGI interface works nice in most browsers, including text-based ones.</li> 1655 <li>On OpenBSD it runs "sandboxed" and it can be compiled as a static-linked 1656 binary with <a href="https://man.openbsd.org/pledge">pledge(2)</a>, 1657 <a href="https://man.openbsd.org/unveil">unveil(2)</a> in a chroot.</li> 1658 </ul> 1659 <h2>Cons</h2> 1660 <ul> 1661 <li>Order by upload date is incorrect (same as on Youtube).</li> 1662 <li>Some Youtube features are not supported.</li> 1663 <li>Uses scraping so might break at any point.</li> 1664 </ul> 1665 <h2>Clone</h2> 1666 <pre><code>git clone git://git.codemadness.org/frontends 1667 </code></pre> 1668 <h2>Browse</h2> 1669 <p>You can browse the source-code at:</p> 1670 <ul> 1671 <li><a href="https://git.codemadness.org/frontends/">https://git.codemadness.org/frontends/</a></li> 1672 <li><a href="gopher://codemadness.org/1/git/frontends">gopher://codemadness.org/1/git/frontends</a></li> 1673 </ul> 1674 <h2>Download releases</h2> 1675 <p>Releases are available at:</p> 1676 <ul> 1677 <li><a href="https://codemadness.org/releases/frontends/">https://codemadness.org/releases/frontends/</a></li> 1678 <li><a href="gopher://codemadness.org/1/releases/frontends">gopher://codemadness.org/1/releases/frontends</a></li> 1679 </ul> 1680 <h2>View</h2> 1681 <p>You can view it here: <a href="https://codemadness.org/idiotbox/">https://codemadness.org/idiotbox/</a></p> 1682 <p>For example you can search using the query string parameter "q": 1683 <a href="https://codemadness.org/idiotbox/?q=gunther+tralala">https://codemadness.org/idiotbox/?q=gunther+tralala</a></p> 1684 <p>The gopher version is here: <a href="gopher://codemadness.org/7/idiotbox.cgi">gopher://codemadness.org/7/idiotbox.cgi</a></p> 1685 ]]></content> 1686 </entry> 1687 <entry> 1688 <title>Gopher HTTP proxy</title> 1689 <link rel="alternate" type="text/html" href="https://www.codemadness.org/gopher-proxy.html" /> 1690 <id>https://www.codemadness.org/gopher-proxy.html</id> 1691 <updated>2020-08-30T00:00:00Z</updated> 1692 <published>2018-08-17T00:00:00Z</published> 1693 <author> 1694 <name>Hiltjo</name> 1695 <uri>https://www.codemadness.org</uri> 1696 </author> 1697 <summary>Gopher HTTP proxy</summary> 1698 <content type="html"><![CDATA[<h1>Gopher HTTP proxy</h1> 1699 <p><strong>Last modification on </strong> <time>2020-08-30</time></p> 1700 <p>For fun I wrote a small HTTP Gopher proxy CGI program in C. It only supports 1701 the basic Gopher types and has some restrictions to prevent some abuse.</p> 1702 <p>For your regular Gopher browsing I recommend the simple Gopher client <a href="https://git.fifth.space/sacc/">sacc</a>.</p> 1703 <p>For more information about Gopher check out <a href="http://gopherproject.org/">gopherproject.org</a>.</p> 1704 <h2>Clone</h2> 1705 <pre><code>git clone git://git.codemadness.org/gopherproxy-c 1706 </code></pre> 1707 <h2>Browse</h2> 1708 <p>You can browse the source-code at:</p> 1709 <ul> 1710 <li><a href="https://git.codemadness.org/gopherproxy-c/">https://git.codemadness.org/gopherproxy-c/</a></li> 1711 <li><a href="gopher://codemadness.org/1/git/gopherproxy-c">gopher://codemadness.org/1/git/gopherproxy-c</a></li> 1712 </ul> 1713 <h2>View</h2> 1714 <p>You can view it here: 1715 <a href="https://codemadness.org/gopherproxy/">https://codemadness.org/gopherproxy/</a></p> 1716 <p>For example you can also view my gopherhole using the proxy, the query string 1717 parameter "q" reads the URI: 1718 <a href="https://codemadness.org/gopherproxy/?q=codemadness.org">https://codemadness.org/gopherproxy/?q=codemadness.org</a></p> 1719 ]]></content> 1720 </entry> 1721 <entry> 1722 <title>Setup your own file paste service</title> 1723 <link rel="alternate" type="text/html" href="https://www.codemadness.org/paste-service.html" /> 1724 <id>https://www.codemadness.org/paste-service.html</id> 1725 <updated>2018-03-10T00:00:00Z</updated> 1726 <published>2018-03-10T00:00:00Z</published> 1727 <author> 1728 <name>Hiltjo</name> 1729 <uri>https://www.codemadness.org</uri> 1730 </author> 1731 <summary>Howto setup your own secure file paste service</summary> 1732 <content type="html"><![CDATA[<h1>Setup your own file paste service</h1> 1733 <p><strong>Last modification on </strong> <time>2018-03-10</time></p> 1734 <h2>Setup SSH authentication</h2> 1735 <p>Make sure to setup SSH public key authentication so you don't need to enter a 1736 password each time and have a more secure authentication.</p> 1737 <p>For example in the file $HOME/.ssh/config:</p> 1738 <pre><code>Host codemadness 1739 Hostname codemadness.org 1740 Port 22 1741 IdentityFile ~/.ssh/codemadness/id_rsa 1742 </code></pre> 1743 <p>Of course also make sure to generate the private and public keys.</p> 1744 <h2>Shell alias</h2> 1745 <p>Make an alias or function in your shell config:</p> 1746 <pre><code>pastesrv() { 1747 ssh user@codemadness "cat > /your/www/publicdir/paste/$1" 1748 echo "https://codemadness.org/paste/$1" 1749 } 1750 </code></pre> 1751 <p>This function reads any data from stdin and transfers the output securely via 1752 SSH and writes it to a file at the specified path. This path can be visible via 1753 HTTP, gopher or an other protocol. Then it writes the absolute URL to stdout, 1754 this URL can be copied to the clipboard and pasted anywhere like to an e-mail, 1755 IRC etc.</p> 1756 <h2>Usage and examples</h2> 1757 <p>To use it, here are some examples:</p> 1758 <p>Create a patch of the last commit in the git repo and store it:</p> 1759 <pre><code>git format-patch --stdout HEAD^ | pastesrv 'somepatch.diff' 1760 </code></pre> 1761 <p>Create a screenshot of your current desktop and paste it:</p> 1762 <pre><code>xscreenshot | ff2png | pastesrv 'screenshot.png' 1763 </code></pre> 1764 <p>There are many other uses of course, use your imagination :)</p> 1765 ]]></content> 1766 </entry> 1767 <entry> 1768 <title>Setup your own git hosting service</title> 1769 <link rel="alternate" type="text/html" href="https://www.codemadness.org/setup-git-hosting.html" /> 1770 <id>https://www.codemadness.org/setup-git-hosting.html</id> 1771 <updated>2022-08-07T00:00:00Z</updated> 1772 <published>2018-02-25T00:00:00Z</published> 1773 <author> 1774 <name>Hiltjo</name> 1775 <uri>https://www.codemadness.org</uri> 1776 </author> 1777 <summary>Howto setup your own git hosting service</summary> 1778 <content type="html"><![CDATA[<h1>Setup your own git hosting service</h1> 1779 <p><strong>Last modification on </strong> <time>2022-08-07</time></p> 1780 <p><strong>This article assumes you use OpenBSD for the service files and OS-specific 1781 examples.</strong></p> 1782 <h2>Why</h2> 1783 <p>A good reason to host your own git repositories is because of having and 1784 keeping control over your own computing infrastructure.</p> 1785 <p>Some bad examples:</p> 1786 <ul> 1787 <li><a href="https://en.wikipedia.org/wiki/SourceForge#Controversies">The SourceForge ads/malware/hijack controversies. Injecting malware into projects</a>.</li> 1788 <li><a href="https://gitlab.com/gitlab-org/gitaly/issues/2113">As of 2019-10-23 Gitlab added telemetry to their software</a>.</li> 1789 <li><a href="https://about.gitlab.com/blog/2019/10/10/update-free-software-and-telemetry/">On 2019-10-24 Gitlab reverted it again because many people complained</a>.</li> 1790 <li><a href="https://github.blog/2020-11-16-standing-up-for-developers-youtube-dl-is-back/">On 2020-11-16 Github reinstated youtube-dl, to reverse a Digital Millennium Copyright Act (DMCA) takedown</a>.</li> 1791 <li><a href="https://arstechnica.com/gadgets/2021/03/critics-fume-after-github-removes-exploit-code-for-exchange-vulnerabilities/">On 2021-03-11 Github (owned by Microsoft) removes exploit code for Microsoft Exchange vulnerabilities</a>.</li> 1792 <li><a href="https://www.bleepingcomputer.com/news/security/github-suspends-accounts-of-russian-devs-at-sanctioned-companies/">On 2022-04-16 Russian software developers are reporting that their GitHub accounts are being suspended without warning if they work for or previously worked for companies under US sanctions</a>.</li> 1793 <li><a href="https://www.theregister.com/2022/08/04/gitlab_data_retention_policy/">On 2022-08-04 GitLab plans to delete dormant projects in free accounts</a>.</li> 1794 <li><a href="https://www.theregister.com/2022/08/05/gitlab_reverses_deletion_policy/">On 2022-08-05 GitLab U-turns on deleting dormant projects after backlash</a>.</li> 1795 </ul> 1796 <p>The same thing can happen with Github, Atlassian Bitbucket or other similar 1797 services. After all: they are just a company with commercial interests. These 1798 online services also have different pricing plans and various (arbitrary) 1799 restrictions. When you host it yourself the restrictions are the resource 1800 limits of the system and your connection, therefore it is a much more flexible 1801 solution.</p> 1802 <p>Always make sure you own the software (which is <a href="https://www.gnu.org/philosophy/free-sw.html">Free</a> or open-source) and you 1803 can host it yourself, so you will be in control of it.</p> 1804 <h2>Creating repositories</h2> 1805 <p>For the hosting it is recommended to use a so-called "bare" repository. A bare 1806 repository means no files are checked out in the folder itself. To create a 1807 bare repository use git init with the --bare argument:</p> 1808 <pre><code>$ git init --bare 1809 </code></pre> 1810 <p>I recommend to create a separate user and group for the source-code 1811 repositories. In the examples we will assume the user is called "src".</p> 1812 <p>Login as the src user and create the files. To create a directory for the 1813 repos, in this example /home/src/src:</p> 1814 <pre><code>$ mkdir -p /home/src/src 1815 $ cd /home/src/src 1816 $ git init --bare someproject 1817 $ $EDITOR someproject/description 1818 </code></pre> 1819 <p>Make sure the git-daemon process has access permissions to these repositories.</p> 1820 <h2>Install git-daemon (optional)</h2> 1821 <p>Using git-daemon you can clone the repositories publicly using the efficient 1822 git:// protocol. An alternative without having to use git-daemon is by using 1823 (anonymous) SSH, HTTPS or any public shared filesystem.</p> 1824 <p>When you use a private-only repository I recommend to just use SSH without 1825 git-daemon because it is secure.</p> 1826 <p>Install the git package. The package should contain "git daemon":</p> 1827 <pre><code># pkg_add git 1828 </code></pre> 1829 <p>Enable the daemon:</p> 1830 <pre><code># rcctl enable gitdaemon 1831 </code></pre> 1832 <p>Set the gitdaemon service flags to use the src directory and use all the 1833 available repositories in this directory. The command-line flags "--export-all" 1834 exports all repositories in the base path. Alternatively you can use the 1835 "git-daemon-export-ok" file (see the git-daemon man page).</p> 1836 <pre><code># rcctl set gitdaemon flags --export-all --base-path="/home/src/src" 1837 </code></pre> 1838 <p>To configure the service to run as the user _gitdaemon:</p> 1839 <pre><code># rcctl set gitdaemon user _gitdaemon 1840 </code></pre> 1841 <p>To run the daemon directly as the user _gitdaemon (without dropping privileges 1842 from root to the user) set the following flags in /etc/rc.d/gitdaemon:</p> 1843 <pre><code>daemon_flags="--user=_gitdaemon" 1844 </code></pre> 1845 <p>Which will also avoid this warning while cloning:</p> 1846 <pre><code>"can't access /root/.git/config" 1847 </code></pre> 1848 <p>Now start the daemon:</p> 1849 <pre><code># rcctl start gitdaemon 1850 </code></pre> 1851 <h2>Cloning and fetching changes</h2> 1852 <p>To test and clone the repository do:</p> 1853 <pre><code>$ git clone git://yourdomain/someproject 1854 </code></pre> 1855 <p>if you skipped the optional git-daemon installation then just clone via SSH:</p> 1856 <pre><code>$ git clone ssh://youraccount@yourdomain:/home/src/src/someproject 1857 </code></pre> 1858 <p>When cloning via SSH make sure to setup private/public key authentication for 1859 security and convenience.</p> 1860 <p>You should also make sure the firewall allows connections to the services like 1861 the git daemon, HTTPd or SSH, for example using OpenBSD pf something like this 1862 can be set in <a href="https://man.openbsd.org/pf.conf">/etc/pf.conf</a>:</p> 1863 <pre><code>tcp_services="{ ssh, gopher, http, https, git }" 1864 pass in on egress proto tcp from any to (egress) port $tcp_services 1865 </code></pre> 1866 <h2>Pushing changes</h2> 1867 <p>Add the repository as a remote:</p> 1868 <pre><code>$ git remote add myremote ssh://youraccount@yourdomain:/home/src/src/someproject 1869 </code></pre> 1870 <p>Then push the changes:</p> 1871 <pre><code>$ git push myremote master:master 1872 </code></pre> 1873 <h2>Git history web browsing (optional)</h2> 1874 <p>Sometimes it's nice to browse the git history log of the repository in a web 1875 browser or some other program without having to look at the local repository.</p> 1876 <ul> 1877 <li><a href="stagit.html">Stagit</a> is a static HTML page generator for git.</li> 1878 <li><a href="stagit-gopher.html">Stagit-gopher</a> is a static page generator for 1879 <a href="http://gopherproject.org/">gopher</a> and 1880 <a href="gopher://bitreich.org/1/scm/geomyidae">geomyidae</a>.</li> 1881 <li>cgit is a CGI-based program which shows HTML views of your repository, see 1882 also the page: <a href="openbsd-httpd-and-cgit.html">OpenBSD httpd, slowcgi and cgit</a>.</li> 1883 </ul> 1884 <p>It's also possible with these tools to generate an Atom feed and then use a 1885 RSS/Atom reader to track the git history:</p> 1886 <ul> 1887 <li>An example url from cgit: <a href="https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/atom/?h=master">Linux kernel tree</a>.</li> 1888 <li>An example url from stagit for the <a href="/git/stagit/atom.xml">commit log</a>.</li> 1889 <li>An example url from stagit for the <a href="/git/stagit/tags.xml">releases</a>.</li> 1890 </ul> 1891 <p>My <a href="sfeed.html">sfeed</a> program can be used as a RSS/Atom reader.</p> 1892 <h2>Setting up git hooks (optional)</h2> 1893 <p>Using git hooks you can setup automated triggers, for example when pushing to a 1894 repository. Some useful examples can be:</p> 1895 <ul> 1896 <li><a href="/git/stagit/file/example_post-receive.sh.html">For stagit: update the repo files (example post-receive hook).</a></li> 1897 <li>Send an e-mail with the commit subject and message.</li> 1898 <li>Log/notify commits and changes to an IRC channel using a fifo: <a href="https://tools.suckless.org/ii/">ii</a>.</li> 1899 <li>Create a release tarball and checksum file on a tag push/change.</li> 1900 <li>Checkout files for website content.</li> 1901 </ul> 1902 ]]></content> 1903 </entry> 1904 <entry> 1905 <title>Setup an OpenBSD SPARC64 VM in QEMU</title> 1906 <link rel="alternate" type="text/html" href="https://www.codemadness.org/openbsd-sparc64-vm.html" /> 1907 <id>https://www.codemadness.org/openbsd-sparc64-vm.html</id> 1908 <updated>2020-04-18T00:00:00Z</updated> 1909 <published>2017-12-11T00:00:00Z</published> 1910 <author> 1911 <name>Hiltjo</name> 1912 <uri>https://www.codemadness.org</uri> 1913 </author> 1914 <summary>Setup an OpenBSD SPARC64 VM in QEMU</summary> 1915 <content type="html"><![CDATA[<h1>Setup an OpenBSD SPARC64 VM in QEMU</h1> 1916 <p><strong>Last modification on </strong> <time>2020-04-18</time></p> 1917 <p>This describes how to setup an OpenBSD SPARC64 VM in QEMU.</p> 1918 <h2>Create a disk image</h2> 1919 <p>To create a 5GB disk image:</p> 1920 <pre><code>qemu-img create -f qcow2 fs.qcow2 5G 1921 </code></pre> 1922 <h2>Install</h2> 1923 <p>In this guide we'll use the installation ISO to install OpenBSD. Make sure to 1924 download the latest (stable) OpenBSD ISO, for example install62.iso.</p> 1925 <ul> 1926 <li>Change -boot c to -boot d to boot from the CD-ROM and do a clean install.</li> 1927 <li>Change -cdrom install62.iso to the location of your ISO file.</li> 1928 <li>When the install is done type: halt -p</li> 1929 <li>Change -boot d back to -boot c.</li> 1930 </ul> 1931 <p>Start the VM:</p> 1932 <pre><code>#!/bin/sh 1933 LC_ALL=C QEMU_AUDIO_DRV=none \ 1934 qemu-system-sparc64 \ 1935 -machine sun4u,usb=off \ 1936 -realtime mlock=off \ 1937 -smp 1,sockets=1,cores=1,threads=1 \ 1938 -rtc base=utc \ 1939 -m 1024 \ 1940 -boot c \ 1941 -drive file=fs.qcow2,if=none,id=drive-ide0-0-1,format=qcow2,cache=none \ 1942 -cdrom install62.iso \ 1943 -device ide-hd,bus=ide.0,unit=0,drive=drive-ide0-0-1,id=ide0-0-1 \ 1944 -msg timestamp=on \ 1945 -serial pty -nographic \ 1946 -net nic,model=ne2k_pci -net user 1947 </code></pre> 1948 <p>The VM has the following properties:</p> 1949 <ul> 1950 <li>No audio.</li> 1951 <li>No USB.</li> 1952 <li>No VGA graphics: serial console.</li> 1953 <li>Netdev is ne0 (Realtek 8029).</li> 1954 <li>1024MB memory.</li> 1955 </ul> 1956 <p>From your host connect to the serial device indicated by QEMU, for example:</p> 1957 <pre><code>(qemu) 2017-11-19T15:14:20.884312Z qemu-system-sparc64: -serial pty: char device redirected to /dev/ttyp0 (label serial0) 1958 </code></pre> 1959 <p>Then you can use the serial terminal emulator <strong>cu</strong> to attach:</p> 1960 <pre><code>cu -l /dev/ttyp0 1961 </code></pre> 1962 <p>Another option could be using the <a href="https://git.suckless.org/st/">simple terminal(st)</a> from suckless.</p> 1963 <pre><code>st -l /dev/ttyp0 1964 </code></pre> 1965 <p>using cu to detach the <a href="https://man.openbsd.org/cu#~^D">cu(1) man page</a> says:</p> 1966 <pre><code>Typed characters are normally transmitted directly to the remote machine (which 1967 does the echoing as well). A tilde ('~') appearing as the first character of a 1968 line is an escape signal; the following are recognized: 1969 1970 ~^D or ~. Drop the connection and exit. Only the connection is 1971 the login session is not terminated. 1972 </code></pre> 1973 <p>On boot you have to type:</p> 1974 <pre><code>root device: wd0a 1975 for swap use the default (wd0b) Press enter 1976 </code></pre> 1977 <h2>Initial settings on first boot (optional)</h2> 1978 <p>Automatic network configuration using DHCP</p> 1979 <pre><code>echo "dhcp" > /etc/hostname.ne0 1980 </code></pre> 1981 <p>To bring up the interface (will be automatic on the next boot):</p> 1982 <pre><code>sh /etc/netstart 1983 </code></pre> 1984 <p>Add a mirror to /etc/installurl for package installation. Make sure to lookup 1985 the most efficient/nearby mirror site on the OpenBSD mirror page.</p> 1986 <pre><code>echo "https://ftp.hostserver.de/pub/OpenBSD" > /etc/installurl 1987 </code></pre> 1988 ]]></content> 1989 </entry> 1990 <entry> 1991 <title>Tscrape: a Twitter scraper</title> 1992 <link rel="alternate" type="text/html" href="https://www.codemadness.org/tscrape.html" /> 1993 <id>https://www.codemadness.org/tscrape.html</id> 1994 <updated>2020-07-20T00:00:00Z</updated> 1995 <published>2017-09-24T00:00:00Z</published> 1996 <author> 1997 <name>Hiltjo</name> 1998 <uri>https://www.codemadness.org</uri> 1999 </author> 2000 <summary>Tscrape: a Twitter scraper</summary> 2001 <content type="html"><![CDATA[<h1>Tscrape: a Twitter scraper</h1> 2002 <p><strong>Last modification on </strong> <time>2020-07-20</time></p> 2003 <p>Tscrape is a Twitter web scraper and archiver.</p> 2004 <p>Twitter removed the functionality to follow users using a RSS feed without 2005 authenticating or using their API. With this program you can format tweets in 2006 any way you like relatively anonymously.</p> 2007 <p>For more (up-to-date) information see the <a href="/git/tscrape/file/README.html">README</a> file.</p> 2008 <h2>Clone</h2> 2009 <pre><code>git clone git://git.codemadness.org/tscrape 2010 </code></pre> 2011 <h2>Browse</h2> 2012 <p>You can browse the source-code at:</p> 2013 <ul> 2014 <li><a href="https://git.codemadness.org/tscrape/">https://git.codemadness.org/tscrape/</a></li> 2015 <li><a href="gopher://codemadness.org/1/git/tscrape">gopher://codemadness.org/1/git/tscrape</a></li> 2016 </ul> 2017 <h2>Download releases</h2> 2018 <p>Releases are available at:</p> 2019 <ul> 2020 <li><a href="https://codemadness.org/releases/tscrape/">https://codemadness.org/releases/tscrape/</a></li> 2021 <li><a href="gopher://codemadness.org/1/releases/tscrape">gopher://codemadness.org/1/releases/tscrape</a></li> 2022 </ul> 2023 <h2>Examples</h2> 2024 <p>Output format examples:</p> 2025 <ul> 2026 <li><a href="tscrape/tscrape_html.html">tscrape_html: HTML</a></li> 2027 <li><a href="tscrape/tscrape_plain.txt">tscrape_plain: Text</a></li> 2028 </ul> 2029 ]]></content> 2030 </entry> 2031 <entry> 2032 <title>jsdatatable: a small datatable Javascript</title> 2033 <link rel="alternate" type="text/html" href="https://www.codemadness.org/datatable.html" /> 2034 <id>https://www.codemadness.org/datatable.html</id> 2035 <updated>2020-07-20T00:00:00Z</updated> 2036 <published>2017-09-24T00:00:00Z</published> 2037 <author> 2038 <name>Hiltjo</name> 2039 <uri>https://www.codemadness.org</uri> 2040 </author> 2041 <summary>jsdatatable: a small datatable Javascript</summary> 2042 <content type="html"><![CDATA[<h1>jsdatatable: a small datatable Javascript</h1> 2043 <p><strong>Last modification on </strong> <time>2020-07-20</time></p> 2044 <p>This is a small datatable Javascript with no dependencies.</p> 2045 <h2>Features</h2> 2046 <ul> 2047 <li>Small: 2048 <ul> 2049 <li>Filesize: +- 9.1KB.</li> 2050 <li>Lines: +- 300, not much code, so hopefully easy to understand.</li> 2051 <li>No dependencies on other libraries like jQuery.</li> 2052 </ul> 2053 </li> 2054 <li>Sorting on columns, multi-column support with shift-click.</li> 2055 <li>Filtering values: case-insensitively, tokenized (separated by space).</li> 2056 <li>Able to add custom filtering, parsing and sorting functions.</li> 2057 <li>Helper function for delayed (150ms) filtering, so filtering feels more 2058 responsive for big datasets.</li> 2059 <li>Permissive ISC license, see LICENSE file.</li> 2060 <li>"Lazy scroll" mode: 2061 <ul> 2062 <li>fixed column headers and renders only visible rows, this allows you to 2063 "lazily" render millions of rows.</li> 2064 </ul> 2065 </li> 2066 <li>Officially supported browsers are: 2067 <ul> 2068 <li>Firefox and Firefox ESR.</li> 2069 <li>Chrome and most recent webkit-based browsers.</li> 2070 <li>IE10+.</li> 2071 </ul> 2072 </li> 2073 </ul> 2074 <h2>Why? and a comparison</h2> 2075 <p>It was created because all the other datatable scripts suck balls.</p> 2076 <p>Most Javascripts nowadays have a default dependency on jQuery, Bootstrap or 2077 other frameworks.</p> 2078 <p>jQuery adds about 97KB and Bootstrap adds about 100KB to your scripts and CSS 2079 as a dependency. This increases the CPU, memory and bandwidth consumption and 2080 latency. It also adds complexity to your scripts.</p> 2081 <p>jQuery was mostly used for backwards-compatibility in the Internet Explorer 2082 days, but is most often not needed anymore. It contains functionality to query 2083 the DOM using CSS-like selectors, but this is now supported with for example 2084 document.querySelectorAll. Functionality like a JSON parser is standard 2085 available now: JSON.parse().</p> 2086 <h3>Size comparison</h3> 2087 <p>All sizes are not "minified" or gzipped.</p> 2088 <pre><code>Name | Total | JS | CSS | Images | jQuery 2089 ---------------------------------+---------+---------+-------+--------+------- 2090 jsdatatable | 12.9KB | 9.1KB | 2.5KB | 1.3KB | - 2091 datatables.net (without plugins) | 563.4KB | 449.3KB | 16KB | 0.8KB | 97.3KB 2092 jdatatable | 154.6KB | 53KB | 1KB | 3.3KB | 97.3KB 2093 </code></pre> 2094 <ul> 2095 <li><a href="https://datatables.net/">datatables.net</a> (without plugins).</li> 2096 <li><a href="https://plugins.jquery.com/jdatatable/">jdatatable</a></li> 2097 </ul> 2098 <p>Of course jsdatatable has less features (less is more!), but it does 90% of 2099 what's needed. Because it is so small it is also much simpler to understand and 2100 extend with required features if needed.</p> 2101 <p>See also: 2102 <a href="https://idlewords.com/talks/website_obesity.htm">The website obesity crisis</a></p> 2103 <h2>Clone</h2> 2104 <pre><code>git clone git://git.codemadness.org/jscancer 2105 </code></pre> 2106 <h2>Browse</h2> 2107 <p>You can browse the source-code at:</p> 2108 <ul> 2109 <li><a href="https://git.codemadness.org/jscancer/">https://git.codemadness.org/jscancer/</a></li> 2110 <li><a href="gopher://codemadness.org/1/git/jscancer">gopher://codemadness.org/1/git/jscancer</a></li> 2111 </ul> 2112 <p>It is in the datatable directory.</p> 2113 <h2>Download releases</h2> 2114 <p>Releases are available at:</p> 2115 <ul> 2116 <li><a href="https://codemadness.org/releases/jscancer/">https://codemadness.org/releases/jscancer/</a></li> 2117 <li><a href="gopher://codemadness.org/1/releases/jscancer">gopher://codemadness.org/1/releases/jscancer</a></li> 2118 </ul> 2119 <h2>Usage</h2> 2120 <h3>Examples</h3> 2121 <p>See example.html for an example. A stylesheet file datatable.css is also 2122 included, it contains the icons as embedded images.</p> 2123 <p>A table should have the classname "datatable" set, it must contain a <thead> 2124 for the column headers (<td> or <th>) and <tbody> element for the data. The 2125 minimal code needed for a working datatable:</p> 2126 <pre><code><html> 2127 <body> 2128 <input class="filter-text" /><!-- optional --> 2129 <table class="datatable"> 2130 <thead><!-- columns --> 2131 <tr><td>Click me</td></tr> 2132 </thead> 2133 <tbody><!-- data --> 2134 <tr><td>a</td></tr> 2135 <tr><td>b</td></tr> 2136 </tbody> 2137 </table> 2138 <script type="text/javascript" src="datatable.js"></script> 2139 <script type="text/javascript">var datatables = datatable_autoload();</script> 2140 </body> 2141 </html> 2142 </code></pre> 2143 <h3>Column attributes</h3> 2144 <p>The following column attributes are supported:</p> 2145 <ul> 2146 <li>data-filterable: if "1" or "true" specifies if the column can be filtered, 2147 default: "true".</li> 2148 <li>data-parse: specifies how to parse the values, default: "string", which is 2149 datatable_parse_string(). See PARSING section below.</li> 2150 <li>data-sort: specifies how to sort the values: default: "default", which is 2151 datatable_sort_default(). See SORTING section below.</li> 2152 <li>data-sortable: if "1" or "true" specifies if the column can be sorted, 2153 default: "true".</li> 2154 </ul> 2155 <h3>Parsing</h3> 2156 <p>By default only parsing for the types: date, float, int and string are 2157 supported, but other types can be easily added as a function with the name: 2158 datatable_parse_<typename>(). The parse functions parse the data-value 2159 attribute when set or else the cell content (in order). Because of this 2160 behaviour you can set the actual values as the data-value attribute and use the 2161 cell content for display. This is useful to display and properly sort 2162 locale-aware currency, datetimes etc.</p> 2163 <h3>Filtering</h3> 2164 <p>Filtering will be done case-insensitively on the cell content and when set also 2165 on the data-value attribute. The filter string is split up as tokens separated 2166 by space. Each token must match at least once per row to display it.</p> 2167 <h3>Sorting</h3> 2168 <p>Sorting is done on the parsed values by default with the function: 2169 datatable_sort_default(). To change this you can set a customname string on 2170 the data-sort attribute on the column which translates to the function: 2171 datatable_sort_<customname>().</p> 2172 <p>In some applications locale values are used, like for currency, decimal numbers 2173 datetimes. Some people also like to use icons or extended HTML elements inside 2174 the cell. Because jsdatatable sorts on the parsed value (see section PARSING) 2175 it is possible to sort on the data-value attribute values and use the cell 2176 content for display.</p> 2177 <p>For example:</p> 2178 <ul> 2179 <li>currency, decimal numbers: use data-value attribute with floating-point 2180 number, set data-parse column to "float".</li> 2181 <li>date/datetimes: use data-value attribute with UNIX timestamps (type int), set 2182 data-parse on column to "int" or set the data-parse attribute on column to 2183 "date" which is datatable_parse_date(), then make sure to use Zulu times, like: 2184 "2016-01-01T01:02:03Z" or other time strings that are parsable as the 2185 data-value attribute.</li> 2186 <li>icons: generally use data-value attribute with integer as weight value to 2187 sort on, set data-parse column to "int".</li> 2188 </ul> 2189 <h3>Dynamically update data</h3> 2190 <p>To update data dynamically see example-ajax.html for an example how to do this.</p> 2191 <h3>Caveats</h3> 2192 <ul> 2193 <li>A date, integer, float or other values must be able to parse properly, when 2194 the parse function returns NaN, null or undefined etc. the sorting behaviour is 2195 also undefined. It is recommended to always set a zero value for each type.</li> 2196 <li><tfoot> is not supported in datatables in "lazy" mode.</li> 2197 </ul> 2198 <h2>Demo / example</h2> 2199 <p><strong>For the below example to work you need to have Javascript enabled.</strong></p> 2200 <p><a href="datatable-example.html">datatable-example.html</a></p> 2201 ]]></content> 2202 </entry> 2203 <entry> 2204 <title>Stagit-gopher: a static git page generator for gopher</title> 2205 <link rel="alternate" type="text/html" href="https://www.codemadness.org/stagit-gopher.html" /> 2206 <id>https://www.codemadness.org/stagit-gopher.html</id> 2207 <updated>2021-04-11T00:00:00Z</updated> 2208 <published>2017-08-04T00:00:00Z</published> 2209 <author> 2210 <name>Hiltjo</name> 2211 <uri>https://www.codemadness.org</uri> 2212 </author> 2213 <summary>a static git page generator for gopher</summary> 2214 <content type="html"><![CDATA[<h1>Stagit-gopher: a static git page generator for gopher</h1> 2215 <p><strong>Last modification on </strong> <time>2021-04-11</time></p> 2216 <p>stagit-gopher is a static page generator for Gopher. It creates the pages as 2217 static <a href="http://git.r-36.net/geomyidae/">geomyidae</a> .gph files. stagit-gopher is a modified version from the 2218 HTML version of stagit.</p> 2219 <p><a href="/git/stagit-gopher/file/README.html">Read the README for more information about it.</a></p> 2220 <p>I also run a gopherhole and stagit-gopher, you can see how it looks here: 2221 <a href="gopher://codemadness.org/1/git/">gopher://codemadness.org/1/git/</a></p> 2222 <p><a href="https://git.fifth.space/sacc/log.html">sacc</a> is a good Gopher client to view it.</p> 2223 <h2>Features</h2> 2224 <ul> 2225 <li>Log of all commits from HEAD.</li> 2226 <li>Log and diffstat per commit.</li> 2227 <li>Show file tree with line numbers.</li> 2228 <li>Show references: local branches and tags.</li> 2229 <li>Detect README and LICENSE file from HEAD and link it as a webpage.</li> 2230 <li>Detect submodules (.gitmodules file) from HEAD and link it as a webpage.</li> 2231 <li>Atom feed of the commit log (atom.xml).</li> 2232 <li>Atom feed of the tags/refs (tags.xml).</li> 2233 <li>Make index page for multiple repositories with stagit-gopher-index.</li> 2234 <li>After generating the pages (relatively slow) serving the files is very fast, 2235 simple and requires little resources (because the content is static), a 2236 geomyidae Gopher server is required.</li> 2237 <li>Security: all pages are static. No CGI or dynamic code is run for the 2238 interface. Using it with a secure Gopher server such as geomyidae it is 2239 privilege-dropped and chroot(2)'d.</li> 2240 <li>Simple to setup: the content generation is clearly separated from serving it. 2241 This makes configuration as simple as copying a few directories and scripts.</li> 2242 <li>Usable with Gopher clients such as lynx and <a href="https://git.fifth.space/sacc/log.html">sacc</a>.</li> 2243 </ul> 2244 <h2>Cons</h2> 2245 <ul> 2246 <li>Not suitable for large repositories (2000+ commits), because diffstats are 2247 an expensive operation, the cache (-c flag) is a workaround for this in 2248 some cases.</li> 2249 <li>Not suitable for large repositories with many files, because all files are 2250 written for each execution of stagit. This is because stagit shows the lines 2251 of textfiles and there is no "cache" for file metadata (this would add more 2252 complexity to the code).</li> 2253 <li>Not suitable for repositories with many branches, a quite linear history is 2254 assumed (from HEAD).</li> 2255 <li>Relatively slow to run the first time (about 3 seconds for sbase, 2256 1500+ commits), incremental updates are faster.</li> 2257 <li>Does not support some of the dynamic features cgit has (for HTTP), like: 2258 <ul> 2259 <li>Snapshot tarballs per commit.</li> 2260 <li>File tree per commit.</li> 2261 <li>History log of branches diverged from HEAD.</li> 2262 <li>Stats (git shortlog -s).</li> 2263 </ul> 2264 </li> 2265 </ul> 2266 <p>This is by design, just use git locally.</p> 2267 <h2>Clone</h2> 2268 <pre><code>git clone git://git.codemadness.org/stagit-gopher 2269 </code></pre> 2270 <h2>Browse</h2> 2271 <p>You can browse the source-code at:</p> 2272 <ul> 2273 <li><a href="https://git.codemadness.org/stagit-gopher/">https://git.codemadness.org/stagit-gopher/</a></li> 2274 <li><a href="gopher://codemadness.org/1/git/stagit-gopher">gopher://codemadness.org/1/git/stagit-gopher</a></li> 2275 </ul> 2276 <h2>Download releases</h2> 2277 <p>Releases are available at:</p> 2278 <ul> 2279 <li><a href="https://codemadness.org/releases/stagit-gopher/">https://codemadness.org/releases/stagit-gopher/</a></li> 2280 <li><a href="gopher://codemadness.org/1/releases/stagit-gopher">gopher://codemadness.org/1/releases/stagit-gopher</a></li> 2281 </ul> 2282 ]]></content> 2283 </entry> 2284 <entry> 2285 <title>Saait: a boring HTML page generator</title> 2286 <link rel="alternate" type="text/html" href="https://www.codemadness.org/saait.html" /> 2287 <id>https://www.codemadness.org/saait.html</id> 2288 <updated>2020-07-20T00:00:00Z</updated> 2289 <published>2017-06-10T00:00:00Z</published> 2290 <author> 2291 <name>Hiltjo</name> 2292 <uri>https://www.codemadness.org</uri> 2293 </author> 2294 <summary>Saait: a boring HTML page generator</summary> 2295 <content type="html"><![CDATA[<h1>Saait: a boring HTML page generator</h1> 2296 <p><strong>Last modification on </strong> <time>2020-07-20</time></p> 2297 <p>Saait is the most boring static HTML page generator.</p> 2298 <p>Meaning of saai (dutch): boring. Pronunciation: site</p> 2299 <p><a href="/git/saait/file/README.html">Read the README for more information about it.</a></p> 2300 <p>I used to use <a href="/git/static-site-scripts/files.html">shellscripts</a> to generate the static pages, but realised I 2301 wanted a small program that works on each platform consistently. There are 2302 many incompatibilities or unimplemented features in base tools across different 2303 platforms: Linux, UNIX, Windows.</p> 2304 <p>This site is created using saait.</p> 2305 <h2>Features</h2> 2306 <ul> 2307 <li>Single small binary that handles all the things. At run-time no dependency on 2308 other tools.</li> 2309 <li>Few lines of code (about 575 lines of C) and no dependencies except: a C 2310 compiler and libc.</li> 2311 <li>Works on most platforms: tested on Linux, *BSD, Windows.</li> 2312 <li>Simple template syntax.</li> 2313 <li>Uses HTML output by default, but can easily be modified to generate any 2314 textual content, like gopher pages, wiki pages or other kinds of documents.</li> 2315 <li>Out-of-the-box supports: creating an index page of all pages, Atom feed, 2316 twtxt.txt feed, sitemap.xml and urllist.txt.</li> 2317 </ul> 2318 <h2>Cons</h2> 2319 <ul> 2320 <li>Simple template syntax, but very basic. Requires C knowledge to extend it if 2321 needed.</li> 2322 <li>Only basic (no nested) template blocks supported.</li> 2323 </ul> 2324 <h2>Clone</h2> 2325 <pre><code>git clone git://git.codemadness.org/saait 2326 </code></pre> 2327 <h2>Browse</h2> 2328 <p>You can browse the source-code at:</p> 2329 <ul> 2330 <li><a href="https://git.codemadness.org/saait/">https://git.codemadness.org/saait/</a></li> 2331 <li><a href="gopher://codemadness.org/1/git/saait">gopher://codemadness.org/1/git/saait</a></li> 2332 </ul> 2333 <h2>Download releases</h2> 2334 <p>Releases are available at:</p> 2335 <ul> 2336 <li><a href="https://codemadness.org/releases/saait/">https://codemadness.org/releases/saait/</a></li> 2337 <li><a href="gopher://codemadness.org/1/releases/saait">gopher://codemadness.org/1/releases/saait</a></li> 2338 </ul> 2339 <h2>Documentation / man page</h2> 2340 <p>Below is the saait(1) man page, which includes usage examples.</p> 2341 <pre><code> 2342 SAAIT(1) General Commands Manual SAAIT(1) 2343 2344 NAME 2345 saait the most boring static page generator 2346 2347 SYNOPSIS 2348 saait [-c configfile] [-o outputdir] [-t templatesdir] pages... 2349 2350 DESCRIPTION 2351 saait writes HTML pages to the output directory. 2352 2353 The arguments pages are page config files, which are processed in the 2354 given order. 2355 2356 The options are as follows: 2357 2358 -c configfile 2359 The global configuration file, the default is "config.cfg". Each 2360 page configuration file inherits variables from this file. These 2361 variables can be overwritten per page. 2362 2363 -o outputdir 2364 The output directory, the default is "output". 2365 2366 -t templatesdir 2367 The templates directory, the default is "templates". 2368 2369 DIRECTORY AND FILE STRUCTURE 2370 A recommended directory structure for pages, although the names can be 2371 anything: 2372 pages/001-page.cfg 2373 pages/001-page.html 2374 pages/002-page.cfg 2375 pages/002-page.html 2376 2377 The directory and file structure for templates must be: 2378 templates/<templatename>/header.ext 2379 templates/<templatename>/item.ext 2380 templates/<templatename>/footer.ext 2381 2382 The following filename prefixes are detected for template blocks and 2383 processed in this order: 2384 2385 "header." 2386 Header block. 2387 2388 "item." 2389 Item block. 2390 2391 "footer." 2392 Footer block. 2393 2394 The files are saved as output/<templatename>, for example 2395 templates/atom.xml/* will become: output/atom.xml. If a template block 2396 file does not exist then it is treated as if it was empty. 2397 2398 Template directories starting with a dot (".") are ignored. 2399 2400 The "page" templatename is special and will be used per page. 2401 2402 CONFIG FILE 2403 A config file has a simple key=value configuration syntax, for example: 2404 2405 # this is a comment line. 2406 filename = example.html 2407 title = Example page 2408 description = This is an example page 2409 created = 2009-04-12 2410 updated = 2009-04-14 2411 2412 The following variable names are special with their respective defaults: 2413 2414 contentfile 2415 Path to the input content filename, by default this is the path 2416 of the config file with the last extension replaced to ".html". 2417 2418 filename 2419 The filename or relative file path for the output file for this 2420 page. By default the value is the basename of the contentfile. 2421 The path of the written output file is the value of filename 2422 appended to the outputdir path. 2423 2424 A line starting with # is a comment and is ignored. 2425 2426 TABs and spaces before and after a variable name are ignored. TABs and 2427 spaces before a value are ignored. 2428 2429 TEMPLATES 2430 A template (block) is text. Variables are replaced with the values set 2431 in the config files. 2432 2433 The possible operators for variables are: 2434 2435 $ Escapes a XML string, for example: < to the entity &lt;. 2436 2437 # Literal raw string value. 2438 2439 % Insert contents of file of the value of the variable. 2440 2441 For example in a HTML item template: 2442 2443 <article> 2444 <header> 2445 <h1><a href="">${title}</a></h1> 2446 <p> 2447 <strong>Last modification on </strong> 2448 <time datetime="${updated}">${updated}</time> 2449 </p> 2450 </header> 2451 %{contentfile} 2452 </article> 2453 2454 EXIT STATUS 2455 The saait utility exits 0 on success, and >0 if an error occurs. 2456 2457 EXAMPLES 2458 A basic usage example: 2459 2460 1. Create a directory for a new site: 2461 2462 mkdir newsite 2463 2464 2. Copy the example pages, templates, global config file and example 2465 stylesheets to a directory: 2466 2467 cp -r pages templates config.cfg style.css print.css newsite/ 2468 2469 3. Change the current directory to the created directory. 2470 2471 cd newsite/ 2472 2473 4. Change the values in the global config.cfg file. 2474 2475 5. If you want to modify parts of the header, like the navigation menu 2476 items, you can change the following two template files: 2477 templates/page/header.html 2478 templates/index.html/header.html 2479 2480 6. Create any new pages in the pages directory. For each config file 2481 there has to be a corresponding HTML file. By default this HTML 2482 file has the path of the config file, but with the last extension 2483 (".cfg" in this case) replaced to ".html". 2484 2485 7. Create an output directory: 2486 2487 mkdir -p output 2488 2489 8. After any modifications the following commands can be used to 2490 generate the output and process the pages in descending order: 2491 2492 find pages -type f -name '*.cfg' -print0 | sort -zr | xargs -0 saait 2493 2494 9. Copy the modified stylesheets to the output directory also: 2495 2496 cp style.css print.css output/ 2497 2498 10. Open output/index.html locally in your webbrowser to review the 2499 changes. 2500 2501 11. To synchronize files, you can securely transfer them via SSH using 2502 rsync: 2503 2504 rsync -av output/ user@somehost:/var/www/htdocs/ 2505 2506 TRIVIA 2507 The most boring static page generator. 2508 2509 Meaning of saai (dutch): boring, pronunciation of saait: site 2510 2511 SEE ALSO 2512 find(1), sort(1), xargs(1) 2513 2514 AUTHORS 2515 Hiltjo Posthuma <hiltjo@codemadness.org> 2516 </code></pre> 2517 ]]></content> 2518 </entry> 2519 <entry> 2520 <title>Stagit: a static git page generator</title> 2521 <link rel="alternate" type="text/html" href="https://www.codemadness.org/stagit.html" /> 2522 <id>https://www.codemadness.org/stagit.html</id> 2523 <updated>2021-04-11T00:00:00Z</updated> 2524 <published>2017-05-10T00:00:00Z</published> 2525 <author> 2526 <name>Hiltjo</name> 2527 <uri>https://www.codemadness.org</uri> 2528 </author> 2529 <summary>a static git page generator</summary> 2530 <content type="html"><![CDATA[<h1>Stagit: a static git page generator</h1> 2531 <p><strong>Last modification on </strong> <time>2021-04-11</time></p> 2532 <p>stagit is a static page generator for git.</p> 2533 <p><a href="/git/stagit/file/README.html">Read the README for more information about it.</a></p> 2534 <p>My git repository uses stagit, you can see how it looks here: 2535 <a href="https://codemadness.org/git/">https://codemadness.org/git/</a></p> 2536 <h2>Features</h2> 2537 <ul> 2538 <li>Log of all commits from HEAD.</li> 2539 <li>Log and diffstat per commit.</li> 2540 <li>Show file tree with linkable line numbers.</li> 2541 <li>Show references: local branches and tags.</li> 2542 <li>Detect README and LICENSE file from HEAD and link it as a webpage.</li> 2543 <li>Detect submodules (.gitmodules file) from HEAD and link it as a webpage.</li> 2544 <li>Atom feed of the commit log (atom.xml).</li> 2545 <li>Atom feed of the tags/refs (tags.xml).</li> 2546 <li>Make index page for multiple repositories with stagit-index.</li> 2547 <li>After generating the pages (relatively slow) serving the files is very fast, 2548 simple and requires little resources (because the content is static), only 2549 a HTTP file server is required.</li> 2550 <li>Security: all pages are static. No CGI or dynamic code is run for the 2551 interface. Using it with a secure httpd such as OpenBSD httpd it is 2552 privilege-separated, chroot(2)'d and pledge(2)'d.</li> 2553 <li>Simple to setup: the content generation is clearly separated from serving 2554 it. This makes configuration as simple as copying a few directories and 2555 scripts.</li> 2556 <li>Usable with text-browsers such as dillo, links, lynx and w3m.</li> 2557 </ul> 2558 <h2>Cons</h2> 2559 <ul> 2560 <li>Not suitable for large repositories (2000+ commits), because diffstats are 2561 an expensive operation, the cache (-c flag) or (-l maxlimit) is a workaround 2562 for this in some cases.</li> 2563 <li>Not suitable for large repositories with many files, because all files are 2564 written for each execution of stagit. This is because stagit shows the lines 2565 of textfiles and there is no "cache" for file metadata (this would add more 2566 complexity to the code).</li> 2567 <li>Not suitable for repositories with many branches, a quite linear history is 2568 assumed (from HEAD).</li> 2569 </ul> 2570 <p>In these cases it is better to use <a href="https://git.zx2c4.com/cgit/">cgit</a> or 2571 possibly change stagit to run as a CGI program.</p> 2572 <ul> 2573 <li>Relatively slow to run the first time (about 3 seconds for sbase, 2574 1500+ commits), incremental updates are faster.</li> 2575 <li>Does not support some of the dynamic features cgit has, like: 2576 <ul> 2577 <li>Snapshot tarballs per commit.</li> 2578 <li>File tree per commit.</li> 2579 <li>History log of branches diverged from HEAD.</li> 2580 <li>Stats (git shortlog -s).</li> 2581 </ul> 2582 </li> 2583 </ul> 2584 <p>This is by design, just use git locally.</p> 2585 <h2>Clone</h2> 2586 <pre><code>git clone git://git.codemadness.org/stagit 2587 </code></pre> 2588 <h2>Browse</h2> 2589 <p>You can browse the source-code at:</p> 2590 <ul> 2591 <li><a href="https://git.codemadness.org/stagit/">https://git.codemadness.org/stagit/</a></li> 2592 <li><a href="gopher://codemadness.org/1/git/stagit">gopher://codemadness.org/1/git/stagit</a></li> 2593 </ul> 2594 <h2>Download releases</h2> 2595 <p>Releases are available at:</p> 2596 <ul> 2597 <li><a href="https://codemadness.org/releases/stagit/">https://codemadness.org/releases/stagit/</a></li> 2598 <li><a href="gopher://codemadness.org/1/releases/stagit">gopher://codemadness.org/1/releases/stagit</a></li> 2599 </ul> 2600 ]]></content> 2601 </entry> 2602 <entry> 2603 <title>OpenBSD httpd, slowcgi and cgit</title> 2604 <link rel="alternate" type="text/html" href="https://www.codemadness.org/openbsd-httpd-and-cgit.html" /> 2605 <id>https://www.codemadness.org/openbsd-httpd-and-cgit.html</id> 2606 <updated>2021-04-11T00:00:00Z</updated> 2607 <published>2015-07-05T00:00:00Z</published> 2608 <author> 2609 <name>Hiltjo</name> 2610 <uri>https://www.codemadness.org</uri> 2611 </author> 2612 <summary>OpenBSD httpd, slowcgi and cgit</summary> 2613 <content type="html"><![CDATA[<h1>OpenBSD httpd, slowcgi and cgit</h1> 2614 <p><strong>Last modification on </strong> <time>2021-04-11</time></p> 2615 <p>This is a guide to get <a href="https://git.zx2c4.com/cgit/">cgit</a> working with 2616 <a href="https://man.openbsd.org/httpd.8">OpenBSD httpd(8)</a> and 2617 <a href="https://man.openbsd.org/slowcgi.8">slowcgi(8)</a> in base. OpenBSD httpd is very simple to setup, but nevertheless 2618 this guide might help someone out there.</p> 2619 <h2>Installation</h2> 2620 <p>Install the cgit package:</p> 2621 <pre><code># pkg_add cgit 2622 </code></pre> 2623 <p>or build it from ports:</p> 2624 <pre><code># cd /usr/ports/www/cgit && make && make install 2625 </code></pre> 2626 <h2>Configuration</h2> 2627 <h3>httpd</h3> 2628 <p>An example of <a href="https://man.openbsd.org/httpd.conf.5">httpd.conf(5)</a>: 2629 <a href="downloads/openbsd-httpd/httpd.conf">httpd.conf</a>.</p> 2630 <h3>slowcgi</h3> 2631 <p>By default the slowcgi UNIX domain socket is located at: 2632 /var/www/run/slowcgi.sock. For this example we use the defaults.</p> 2633 <h3>cgit</h3> 2634 <p>The cgit binary should be located at: /var/www/cgi-bin/cgit.cgi (default).</p> 2635 <p>cgit uses the $CGIT_CONFIG environment variable to locate its config. By 2636 default on OpenBSD this is set to /conf/cgitrc (chroot), which is 2637 /var/www/conf/cgitrc. An example of the cgitrc file is here: <a href="downloads/openbsd-httpd/cgitrc">cgitrc</a>.</p> 2638 <p>In this example the cgit cache directory is set to /cgit/cache (chroot), which 2639 is /var/www/cgit/cache. Make sure to give this path read and write permissions 2640 for cgit (www:daemon).</p> 2641 <p>In the example the repository path (scan-path) is set to /htdocs/src (chroot), 2642 which is /var/www/htdocs/src.</p> 2643 <p>The footer file is set to /conf/cgit.footer. Make sure this file exists or you 2644 will get warnings:</p> 2645 <pre><code># >/var/www/conf/cgit.footer 2646 </code></pre> 2647 <p>Make sure cgit.css (stylesheet) and cgit.png (logo) are accessible, by default: 2648 /var/www/cgit/cgit.{css,png} (location can be changed in httpd.conf).</p> 2649 <p>To support .tar.gz snapshots a static gzip binary is required in the chroot 2650 /bin directory:</p> 2651 <pre><code>cd /usr/src/usr.bin/compress 2652 make clean && make LDFLAGS="-static -pie" 2653 cp obj/compress /var/www/bin/gzip 2654 </code></pre> 2655 <h2>Running the services</h2> 2656 <p>Enable the httpd and slowcgi services to automatically start them at boot:</p> 2657 <pre><code># rcctl enable httpd slowcgi 2658 </code></pre> 2659 <p>Start the services:</p> 2660 <pre><code># rcctl start httpd slowcgi 2661 </code></pre> 2662 ]]></content> 2663 </entry> 2664 <entry> 2665 <title>twitch: application to watch Twitch streams</title> 2666 <link rel="alternate" type="text/html" href="https://www.codemadness.org/twitch-interface.html" /> 2667 <id>https://www.codemadness.org/twitch-interface.html</id> 2668 <updated>2020-12-14T00:00:00Z</updated> 2669 <published>2014-11-23T00:00:00Z</published> 2670 <author> 2671 <name>Hiltjo</name> 2672 <uri>https://www.codemadness.org</uri> 2673 </author> 2674 <summary>twitch: application to watch Twitch streams</summary> 2675 <content type="html"><![CDATA[<h1>twitch: application to watch Twitch streams</h1> 2676 <p><strong>Last modification on </strong> <time>2020-12-14</time></p> 2677 <p><strong>Update: as of 2020-05-06:</strong> I stopped maintaining it. 2678 Twitch now requires OAUTH and 2-factor authentication. It requires me to expose 2679 personal information such as my phone number.</p> 2680 <p><strong>Update: as of ~2020-01-03:</strong> I rewrote this application from Golang to C. 2681 The Twitch Kraken API used by the Golang version was deprecated. It was 2682 rewritten to use the Helix API.</p> 2683 <p>This program/script allows to view streams in your own video player like so the 2684 bloated Twitch interface is not needed. It is written in C.</p> 2685 <h2>Features</h2> 2686 <ul> 2687 <li>No Javascript, cookies, CSS optional.</li> 2688 <li>Works well in all browsers, including text-based ones.</li> 2689 <li>Has a HTTP CGI and Gopher CGI version.</li> 2690 <li>Atom feed for VODs.</li> 2691 </ul> 2692 <h2>Clone</h2> 2693 <pre><code>git clone git://git.codemadness.org/frontends 2694 </code></pre> 2695 <h2>Browse</h2> 2696 <p>You can browse the source-code at:</p> 2697 <ul> 2698 <li><a href="https://git.codemadness.org/frontends/">https://git.codemadness.org/frontends/</a></li> 2699 <li><a href="gopher://codemadness.org/1/git/frontends">gopher://codemadness.org/1/git/frontends</a></li> 2700 </ul> 2701 ]]></content> 2702 </entry> 2703 <entry> 2704 <title>Userscript: focus input field</title> 2705 <link rel="alternate" type="text/html" href="https://www.codemadness.org/userscript-focus-input-field.html" /> 2706 <id>https://www.codemadness.org/userscript-focus-input-field.html</id> 2707 <updated>2014-03-02T00:00:00Z</updated> 2708 <published>2014-03-02T00:00:00Z</published> 2709 <author> 2710 <name>Hiltjo</name> 2711 <uri>https://www.codemadness.org</uri> 2712 </author> 2713 <summary>Userscript to focus the first input field on a page with a hotkey</summary> 2714 <content type="html"><![CDATA[<h1>Userscript: focus input field</h1> 2715 <p><strong>Last modification on </strong> <time>2014-03-02</time></p> 2716 <p>This is an userscript I wrote a while ago which allows to focus the first input 2717 field on a page with ctrl+space. This is useful if a site doesn't specify the 2718 autofocus attribute for an input field and you don't want to switch to it using 2719 the mouse.</p> 2720 <h2>Download</h2> 2721 <p><a href="downloads/input_focus.user.js">Download userscript input_focus.user.js</a></p> 2722 ]]></content> 2723 </entry> 2724 <entry> 2725 <title>Userscript: Youtube circumvent age verification</title> 2726 <link rel="alternate" type="text/html" href="https://www.codemadness.org/userscript-youtube-circumvent-age-verification.html" /> 2727 <id>https://www.codemadness.org/userscript-youtube-circumvent-age-verification.html</id> 2728 <updated>2020-12-27T00:00:00Z</updated> 2729 <published>2013-02-21T00:00:00Z</published> 2730 <author> 2731 <name>Hiltjo</name> 2732 <uri>https://www.codemadness.org</uri> 2733 </author> 2734 <summary>Userscript to circumvent Youtube age verification and redirect to the video</summary> 2735 <content type="html"><![CDATA[<h1>Userscript: Youtube circumvent age verification</h1> 2736 <p><strong>Last modification on </strong> <time>2020-12-27</time></p> 2737 <p>This is an userscript I wrote a while ago which circumvents requiring to login 2738 with an account on Youtube if a video requires age verification.</p> 2739 <p><strong>Note: this is an old script and does not work anymore.</strong></p> 2740 <h2>Download</h2> 2741 <p><a href="downloads/youtube_circumvent_sign_in.user.js">Download userscript Youtube_circumvent_sign_in.user.js</a></p> 2742 ]]></content> 2743 </entry> 2744 <entry> 2745 <title>Userscript: block stupid fonts</title> 2746 <link rel="alternate" type="text/html" href="https://www.codemadness.org/userscript-block-stupid-fonts.html" /> 2747 <id>https://www.codemadness.org/userscript-block-stupid-fonts.html</id> 2748 <updated>2020-03-10T00:00:00Z</updated> 2749 <published>2012-10-21T00:00:00Z</published> 2750 <author> 2751 <name>Hiltjo</name> 2752 <uri>https://www.codemadness.org</uri> 2753 </author> 2754 <summary>Userscript to whitelist your favorite fonts and block the rest</summary> 2755 <content type="html"><![CDATA[<h1>Userscript: block stupid fonts</h1> 2756 <p><strong>Last modification on </strong> <time>2020-03-10</time></p> 2757 <p>This is an userscript I wrote a while ago which white-lists fonts I like and 2758 blocks the rest. The reason I made this is because I don't like the 2759 inconsistency of custom fonts used on a lot of websites.</p> 2760 <h2>Download</h2> 2761 <p><a href="downloads/block_stupid_fonts_v1.2.user.js">Download userscript Block_stupid_fonts_v1.2.user.js</a></p> 2762 <p>Old version: <a href="downloads/block_stupid_fonts.user.js">Download userscript Block_stupid_fonts.user.js</a></p> 2763 ]]></content> 2764 </entry> 2765 <entry> 2766 <title>Sfeed: simple RSS and Atom parser</title> 2767 <link rel="alternate" type="text/html" href="https://www.codemadness.org/sfeed-simple-feed-parser.html" /> 2768 <id>https://www.codemadness.org/sfeed-simple-feed-parser.html</id> 2769 <updated>2022-11-05T00:00:00Z</updated> 2770 <published>2011-04-01T00:00:00Z</published> 2771 <author> 2772 <name>Hiltjo</name> 2773 <uri>https://www.codemadness.org</uri> 2774 </author> 2775 <summary>Sfeed is a simple RSS and Atom parser (and format programs to add reader functionality)</summary> 2776 <content type="html"><![CDATA[<h1>Sfeed: simple RSS and Atom parser</h1> 2777 <p><strong>Last modification on </strong> <time>2022-11-05</time></p> 2778 <p>Sfeed is a RSS and Atom parser (and some format programs).</p> 2779 <p>It converts RSS or Atom feeds from XML to a TAB-separated file. There are 2780 formatting programs included to convert this TAB-separated format to various 2781 other formats. There are also some programs and scripts included to import and 2782 export OPML and to fetch, filter, merge and order feed items.</p> 2783 <p>For the most (up-to-date) information see the <a href="/git/sfeed/file/README.html">README</a>.</p> 2784 <h2>Clone</h2> 2785 <pre><code>git clone git://git.codemadness.org/sfeed 2786 </code></pre> 2787 <h2>Browse</h2> 2788 <p>You can browse the source-code at:</p> 2789 <ul> 2790 <li><a href="https://git.codemadness.org/sfeed/">https://git.codemadness.org/sfeed/</a></li> 2791 <li><a href="gopher://codemadness.org/1/git/sfeed">gopher://codemadness.org/1/git/sfeed</a></li> 2792 </ul> 2793 <h2>Download releases</h2> 2794 <p>Releases are available at:</p> 2795 <ul> 2796 <li><a href="https://codemadness.org/releases/sfeed/">https://codemadness.org/releases/sfeed/</a></li> 2797 <li><a href="gopher://codemadness.org/1/releases/sfeed">gopher://codemadness.org/1/releases/sfeed</a></li> 2798 </ul> 2799 <h2>Build and install</h2> 2800 <pre><code>$ make 2801 # make install 2802 </code></pre> 2803 <h2>Screenshot and examples</h2> 2804 <p><a href="downloads/screenshots/sfeed-screenshot.png"><img src="downloads/screenshots/sfeed-thumb.png" alt="Screenshot of sfeed piped to sfeed_plain using dmenu in vertical-list mode" width="400" height="232" loading="lazy" /></a></p> 2805 <p>The above screenshot uses the sfeed_plain format program with <a href="https://tools.suckless.org/dmenu/">dmenu</a>. This 2806 program outputs the feed items in a compact way per line as plain-text to 2807 stdout. The dmenu program reads these lines from stdin and displays them as a 2808 X11 list menu. When an item is selected in dmenu it prints this item to stdout. 2809 A simple written script can then filter for the URL in this output and do some 2810 action, like opening it in some browser or open a podcast in your music player.</p> 2811 <p>For example:</p> 2812 <pre><code>#!/bin/sh 2813 url=$(sfeed_plain "$HOME/.sfeed/feeds/"* | dmenu -l 35 -i | \ 2814 sed -n 's@^.* \([a-zA-Z]*://\)\(.*\)$@\1\2@p') 2815 test -n "${url}" && $BROWSER "${url}" 2816 </code></pre> 2817 <p>However this is just one way to format and interact with feed items. 2818 See also the README for other practical examples.</p> 2819 <p>Below are some examples of output that are supported by the included format 2820 programs:</p> 2821 <ul> 2822 <li><a href="downloads/sfeed/plain/feeds.txt">plain text (UTF-8)</a></li> 2823 <li><a href="downloads/sfeed/atom/feeds.xml">atom</a></li> 2824 <li>gopher</li> 2825 <li><a href="downloads/sfeed/html/feeds.html">HTML (CSS)</a></li> 2826 <li><a href="downloads/sfeed/frames/index.html">HTML frames</a></li> 2827 <li><a href="jsonfeed_content.json">JSON Feed</a></li> 2828 <li><a href="downloads/sfeed/mbox/feeds.mbox">mbox</a></li> 2829 <li><a href="downloads/sfeed/twtxt/twtxt.txt">twtxt</a></li> 2830 </ul> 2831 <p>There is also a curses UI front-end, see the page <a href="sfeed_curses.html">sfeed_curses</a>. 2832 It is now part of sfeed.</p> 2833 <h2>Videos</h2> 2834 <p>Here are some videos of other people showcasing some of the functionalities of 2835 sfeed, sfeed_plain and sfeed_curses. To the creators: thanks for making these!</p> 2836 <ul> 2837 <li><a href="https://www.youtube.com/watch?v=RnuY32DP9jU">sfeed: RSS/Atom Feeds without the Suck (Youtube)</a><br /> 2838 by <a href="https://www.youtube.com/channel/UCQQB104oMOos758GTOdx_kQ">noocsharp</a> 2839 <a href="downloads/sfeed/videos/sfeed_without_the_suck.mp4">(mirror)</a><br /> 2840 Video published on March 8 2020.</li> 2841 <li><a href="https://www.youtube.com/watch?v=ok8k639GoRU">Sfeed - news in the terminal with minimalism (Youtube)</a><br /> 2842 by <a href="https://www.youtube.com/channel/UCJetJ7nDNLlEzDLXv7KIo0w">Gavin Freeborn</a> 2843 <a href="downloads/sfeed/videos/sfeed_news_in_terminal.mp4">(mirror)</a><br /> 2844 Video published on January 15 2021.</li> 2845 <li><a href="https://www.youtube.com/watch?v=xMkW4iJzot0">Sfeed - Peak Minimal RSS Feed Reader (Youtube)</a><br /> 2846 by <a href="https://www.youtube.com/channel/UCld68syR8Wi-GY_n4CaoJGA">Brodie Robertson</a> 2847 <a href="downloads/sfeed/videos/sfeed_minimalism.mp4">(mirror)</a><br /> 2848 Video published on February 23 2021.</li> 2849 <li><a href="https://www.youtube.com/watch?v=O8x0MAyqvt0">RSS with sfeed, fdm, and mblaze! (Youtube)</a><br /> 2850 by <a href="https://www.youtube.com/channel/UCz_u0h4usMbnFsIHSVdjUQw">Joseph Choe</a> 2851 <a href="downloads/sfeed/videos/rss_with_sfeed_fdm_and_mblaze.mp4">(mirror)</a><br /> 2852 Website: <a href="https://josephchoe.com/rss-terminal">https://josephchoe.com/rss-terminal</a><br /> 2853 Video published on 4 November 2022.</li> 2854 </ul> 2855 ]]></content> 2856 </entry> 2857 <entry> 2858 <title>Vim theme: relaxed</title> 2859 <link rel="alternate" type="text/html" href="https://www.codemadness.org/vim-theme-relaxed.html" /> 2860 <id>https://www.codemadness.org/vim-theme-relaxed.html</id> 2861 <updated>2011-01-07T00:00:00Z</updated> 2862 <published>2011-01-07T00:00:00Z</published> 2863 <author> 2864 <name>Hiltjo</name> 2865 <uri>https://www.codemadness.org</uri> 2866 </author> 2867 <summary>a dark VIM theme I made and use on a daily basis</summary> 2868 <content type="html"><![CDATA[<h1>Vim theme: relaxed</h1> 2869 <p><strong>Last modification on </strong> <time>2011-01-07</time></p> 2870 <p>This is a dark theme I made for <a href="https://www.vim.org/">vim</a>. This is a theme I personally used for 2871 quite a while now and over time tweaked to my liking. It is made for gvim, but 2872 also works for 16-colour terminals (with small visual differences). The 2873 relaxed.vim file also has my .Xdefaults file colours listed at the top for 2874 16+-colour terminals on X11.</p> 2875 <p>It is inspired by the "desert" theme available at 2876 <a href="https://www.vim.org/scripts/script.php?script_id=105">https://www.vim.org/scripts/script.php?script_id=105</a>, although I removed the 2877 cursive and bold styles and changed some colours I didn't like.</p> 2878 <h2>Download</h2> 2879 <p><a href="downloads/themes/vim/relaxed.vim">relaxed.vim</a></p> 2880 <h2>Screenshot</h2> 2881 <p><a href="downloads/themes/vim/vim_relaxed_theme.png"><img src="downloads/themes/vim/vim_relaxed_theme_thumb.png" alt="Screenshot of VIM theme relaxed on the left is gvim (GUI), on the right is vim in urxvt (terminal)" width="480" height="300" loading="lazy" /></a></p> 2882 ]]></content> 2883 </entry> 2884 <entry> 2885 <title>Seturgent: set urgency hints for X applications</title> 2886 <link rel="alternate" type="text/html" href="https://www.codemadness.org/seturgent-set-urgency-hints-for-x-applications.html" /> 2887 <id>https://www.codemadness.org/seturgent-set-urgency-hints-for-x-applications.html</id> 2888 <updated>2020-07-20T00:00:00Z</updated> 2889 <published>2010-10-31T00:00:00Z</published> 2890 <author> 2891 <name>Hiltjo</name> 2892 <uri>https://www.codemadness.org</uri> 2893 </author> 2894 <summary>Seturgent is a small utility to set an application it's urgency hint</summary> 2895 <content type="html"><![CDATA[<h1>Seturgent: set urgency hints for X applications</h1> 2896 <p><strong>Last modification on </strong> <time>2020-07-20</time></p> 2897 <p>Seturgent is a small utility to set an application its urgency hint. For most 2898 windowmanager's and panel applications this will highlight the application and 2899 will allow special actions.</p> 2900 <h2>Clone</h2> 2901 <pre><code> git clone git://git.codemadness.org/seturgent 2902 </code></pre> 2903 <h2>Browse</h2> 2904 <p>You can browse the source-code at:</p> 2905 <ul> 2906 <li><a href="https://git.codemadness.org/seturgent/">https://git.codemadness.org/seturgent/</a></li> 2907 <li><a href="gopher://codemadness.org/1/git/seturgent">gopher://codemadness.org/1/git/seturgent</a></li> 2908 </ul> 2909 <h2>Download releases</h2> 2910 <p>Releases are available at:</p> 2911 <ul> 2912 <li><a href="https://codemadness.org/releases/seturgent/">https://codemadness.org/releases/seturgent/</a></li> 2913 <li><a href="gopher://codemadness.org/1/releases/seturgent">gopher://codemadness.org/1/releases/seturgent</a></li> 2914 </ul> 2915 ]]></content> 2916 </entry> 2917 <entry> 2918 <title>DWM-hiltjo: my windowmanager configuration</title> 2919 <link rel="alternate" type="text/html" href="https://www.codemadness.org/dwm-hiltjo-my-windowmanager-configuration.html" /> 2920 <id>https://www.codemadness.org/dwm-hiltjo-my-windowmanager-configuration.html</id> 2921 <updated>2020-07-20T00:00:00Z</updated> 2922 <published>2010-08-12T00:00:00Z</published> 2923 <author> 2924 <name>Hiltjo</name> 2925 <uri>https://www.codemadness.org</uri> 2926 </author> 2927 <summary>My DWM configuration; a few added features to suit my needs</summary> 2928 <content type="html"><![CDATA[<h1>DWM-hiltjo: my windowmanager configuration</h1> 2929 <p><strong>Last modification on </strong> <time>2020-07-20</time></p> 2930 <p><a href="https://dwm.suckless.org/">DWM</a> is a very minimal windowmanager. It has the most essential features I 2931 need, everything else is "do-it-yourself" or extending it with the many 2932 available <a href="https://dwm.suckless.org/patches/">patches</a>. The vanilla version is less than 2000 SLOC. This makes it 2933 easy to understand and modify it.</p> 2934 <p>I really like my configuration at the moment and want to share my changes. Some 2935 of the features listed below are patches from suckless.org I applied, but there 2936 are also some changes I made.</p> 2937 <p>This configuration is entirely tailored for my preferences of course.</p> 2938 <h2>Features</h2> 2939 <ul> 2940 <li>Titlebar: 2941 <ul> 2942 <li>Shows all clients of the selected / active tags.</li> 2943 <li>Divide application titlebars evenly among available space.</li> 2944 <li>Colour urgent clients in the taskbar on active tags.</li> 2945 <li>Left-click focuses clicked client.</li> 2946 <li>Right-click toggles monocle layout.</li> 2947 <li>Middle-click kills the clicked client.</li> 2948 </ul> 2949 </li> 2950 <li>Tagbar: 2951 <ul> 2952 <li>Only show active tags.</li> 2953 <li>Colour inactive tags with urgent clients.</li> 2954 </ul> 2955 </li> 2956 <li>Layouts: 2957 <ul> 2958 <li>Cycle layouts with Modkey + Space (next) and Modkey + Control + Space 2959 (previous).</li> 2960 <li>Fullscreen layout (hides topbar and removes borders).</li> 2961 </ul> 2962 </li> 2963 <li>Other: 2964 <ul> 2965 <li>Move tiled clients around with the mouse (drag-move), awesomewm-like.</li> 2966 <li>Add some keybinds for multimedia keyboards (audio play / pause, mute, www, 2967 volume buttons, etc).</li> 2968 </ul> 2969 </li> 2970 <li>... and more ;) ...</li> 2971 </ul> 2972 <h2>Clone</h2> 2973 <pre><code>git clone -b hiltjo git://git.codemadness.org/dwm 2974 </code></pre> 2975 <h2>Screenshot</h2> 2976 <p><a href="downloads/screenshots/dwm-screenshot.png"><img src="downloads/screenshots/dwm-screenshot-thumb.png" alt="Screenshot showing what dwm-hiltjo looks like" width="480" height="300" loading="lazy" /></a></p> 2977 ]]></content> 2978 </entry> 2979 <entry> 2980 <title>Query unused CSS rules on current document state</title> 2981 <link rel="alternate" type="text/html" href="https://www.codemadness.org/query-unused-css-rules-on-current-document-state.html" /> 2982 <id>https://www.codemadness.org/query-unused-css-rules-on-current-document-state.html</id> 2983 <updated>2010-04-21T00:00:00Z</updated> 2984 <published>2010-04-21T00:00:00Z</published> 2985 <author> 2986 <name>Hiltjo</name> 2987 <uri>https://www.codemadness.org</uri> 2988 </author> 2989 <summary>How to see all the rules in a stylesheet (CSS) that are not used for the current document</summary> 2990 <content type="html"><![CDATA[<h1>Query unused CSS rules on current document state</h1> 2991 <p><strong>Last modification on </strong> <time>2010-04-21</time></p> 2992 <p>Today I was doing some web development and wanted to see all the rules in a 2993 stylesheet (CSS) that were not used for the current document. I wrote the 2994 following Javascript code which you can paste in the Firebug console and run:</p> 2995 <pre><code>(function() { 2996 for (var i=0;i<document.styleSheets.length;i++) { 2997 var rules = document.styleSheets[i].cssRules || []; 2998 var sheethref = document.styleSheets[i].href || 'inline'; 2999 for (var r=0;r<rules.length;r++) 3000 if (!document.querySelectorAll(rules[r].selectorText).length) 3001 console.log(sheethref + ': "' + rules[r].selectorText + '" not found.'); 3002 } 3003 })(); 3004 </code></pre> 3005 <p>This will output all the (currently) unused CSS rules per selector, the output can be for example:</p> 3006 <pre><code>http://www.codemadness.nl/blog/wp-content/themes/codemadness/style.css: "fieldset, a img" not found. 3007 http://www.codemadness.nl/blog/wp-content/themes/codemadness/style.css: "#headerimg" not found. 3008 http://www.codemadness.nl/blog/wp-content/themes/codemadness/style.css: "a:hover" not found. 3009 http://www.codemadness.nl/blog/wp-content/themes/codemadness/style.css: "h2 a:hover, h3 a:hover" not found. 3010 http://www.codemadness.nl/blog/wp-content/themes/codemadness/style.css: ".postmetadata-center" not found. 3011 http://www.codemadness.nl/blog/wp-content/themes/codemadness/style.css: ".thread-alt" not found. 3012 </code></pre> 3013 <p>Just a trick I wanted to share, I hope someone finds this useful :)</p> 3014 <p>For webkit-based browsers you can use "Developer Tools" and use "Audits" under 3015 "Web Page Performance" it says "Remove unused CSS rules". For Firefox there is 3016 also Google Page Speed: <a href="https://code.google.com/speed/page-speed/">https://code.google.com/speed/page-speed/</a> this adds 3017 an extra section under Firebug.</p> 3018 <p>Tested on Chrome and Firefox.</p> 3019 ]]></content> 3020 </entry> 3021 <entry> 3022 <title>Driconf: enabling S3 texture compression on Linux</title> 3023 <link rel="alternate" type="text/html" href="https://www.codemadness.org/driconf-enabling-s3-texture-compression-on-linux.html" /> 3024 <id>https://www.codemadness.org/driconf-enabling-s3-texture-compression-on-linux.html</id> 3025 <updated>2020-08-21T00:00:00Z</updated> 3026 <published>2009-07-05T00:00:00Z</published> 3027 <author> 3028 <name>Hiltjo</name> 3029 <uri>https://www.codemadness.org</uri> 3030 </author> 3031 <summary>driconf: enabling S3 texture compression</summary> 3032 <content type="html"><![CDATA[<h1>Driconf: enabling S3 texture compression on Linux</h1> 3033 <p><strong>Last modification on </strong> <time>2020-08-21</time></p> 3034 <p><strong>Update: the DXTC patent expired on 2018-03-16, many distros enable this by 3035 default now.</strong></p> 3036 <p>S3TC (also known as DXTn or DXTC) is a patented lossy texture compression 3037 algorithm. See: <a href="https://en.wikipedia.org/wiki/S3TC">https://en.wikipedia.org/wiki/S3TC</a> for more detailed 3038 information. Many games use S3TC and if you use Wine to play games you 3039 definitely want to enable it if your graphics card supports it.</p> 3040 <p>Because this algorithm was <a href="https://dri.freedesktop.org/wiki/S3TC/">patented it is disabled by default on many Linux 3041 distributions</a>.</p> 3042 <p>To enable it you can install the library "libtxc" if your favorite OS has not 3043 installed it already.</p> 3044 <p>For easy configuration you can install the optional utility DRIconf, which you 3045 can find at: <a href="https://dri.freedesktop.org/wiki/DriConf">https://dri.freedesktop.org/wiki/DriConf</a>. DriConf can safely be 3046 removed after configuration.</p> 3047 <h2>Steps to enable it</h2> 3048 <p>Install libtxc_dxtn:</p> 3049 <p>ArchLinux: 3050 <pre><code># pacman -S libtxc_dxtn 3051 </code></pre> 3052 <p>Debian: 3053 <pre><code># aptitude install libtxc-dxtn-s2tc0 3054 </code></pre> 3055 </p> 3056 </p> 3057 <p>Install driconf (optional):</p> 3058 <p>ArchLinux:</p> 3059 <pre><code># pacman -S driconf 3060 </code></pre> 3061 <p>Debian:</p> 3062 <pre><code># aptitude install driconf 3063 </code></pre> 3064 <p>Run driconf and enable S3TC:</p> 3065 <p><a href="downloads/screenshots/driconf.png"><img src="downloads/screenshots/driconf-thumb.png" alt="Screenshot of DRIconf window and its options" width="300" height="266" loading="lazy" /></a></p> 3066 <h2>Additional links</h2> 3067 <ul> 3068 <li>S3TC: <a href="https://dri.freedesktop.org/wiki/S3TC/">https://dri.freedesktop.org/wiki/S3TC/</a></li> 3069 <li>DriConf: <a href="https://dri.freedesktop.org/wiki/DriConf">https://dri.freedesktop.org/wiki/DriConf</a></li> 3070 </ul> 3071 ]]></content> 3072 </entry> 3073 <entry> 3074 <title>Getting the USB-powerline bridge to work on Linux</title> 3075 <link rel="alternate" type="text/html" href="https://www.codemadness.org/getting-the-usb-powerline-bridge-to-work-on-linux.html" /> 3076 <id>https://www.codemadness.org/getting-the-usb-powerline-bridge-to-work-on-linux.html</id> 3077 <updated>2019-12-06T00:00:00Z</updated> 3078 <published>2009-04-13T00:00:00Z</published> 3079 <author> 3080 <name>Hiltjo</name> 3081 <uri>https://www.codemadness.org</uri> 3082 </author> 3083 <summary>A guide to get a USB-powerline bridge with the Intellon 51x1 chipset working on Linux</summary> 3084 <content type="html"><![CDATA[<h1>Getting the USB-powerline bridge to work on Linux</h1> 3085 <p><strong>Last modification on </strong> <time>2019-12-06</time></p> 3086 <p><strong>NOTE: this guide is obsolete, a working driver is now included in the Linux 3087 kernel tree (<a href="https://lkml.org/lkml/2009/4/18/121">since Linux 2.6.31</a>)</strong></p> 3088 <h2>Introduction</h2> 3089 <p>A USB to powerline bridge is a network device that instead of using an ordinary 3090 Ethernet cable (CAT5 for example) or wireless LAN it uses the powerlines as a 3091 network to communicate with similar devices. A more comprehensive explanation 3092 of what it is and how it works you can find here: 3093 <a href="https://en.wikipedia.org/wiki/IEEE_1901">https://en.wikipedia.org/wiki/IEEE_1901</a>.</p> 3094 <p>Known products that use the Intellon 51x1 chipset:</p> 3095 <ul> 3096 <li>MicroLink dLAN USB</li> 3097 <li>"Digitus network"</li> 3098 <li>Intellon USB Ethernet powerline adapter</li> 3099 <li>Lots of other USB-powerline adapters...</li> 3100 </ul> 3101 <p>To check if your device is supported:</p> 3102 <pre><code>$ lsusb | grep -i 09e1 3103 Bus 001 Device 003: ID 09e1:5121 Intellon Corp. 3104 </code></pre> 3105 <p>If the vendor (09e1) and product (5121) ID match then it's probably supported.</p> 3106 <h2>Installation</h2> 3107 <p>Get drivers from the official site: 3108 <a href="http://www.devolo.co.uk/consumer/downloads-44-microlink-dlan-usb.html?l=en">http://www.devolo.co.uk/consumer/downloads-44-microlink-dlan-usb.html?l=en</a> or 3109 <a href="downloads/int51x1/dLAN-linux-package-v4.tar.gz">mirrored here</a>. 3110 The drivers from the official site were/are more up-to-date.</p> 3111 <p>Extract them:</p> 3112 <pre><code>$ tar -xzvf dLAN-linux-package-v4.tar.gz 3113 </code></pre> 3114 <p>Go to the extracted directory and compile them:</p> 3115 <pre><code>$ ./configure 3116 $ make 3117 </code></pre> 3118 <p>Depending on the errors you got you might need to <a href="downloads/int51x1/int51x1.patch">download</a> and apply 3119 my patch:</p> 3120 <pre><code>$ cd dLAN-linux-package-v4/ (or other path to the source code) 3121 $ patch < int51x1.patch 3122 </code></pre> 3123 <p>Try again:</p> 3124 <pre><code>$ ./configure 3125 $ make 3126 </code></pre> 3127 <p>If that failed try:</p> 3128 <pre><code>$ ./configure 3129 $ KBUILD_NOPEDANTIC=1 make 3130 </code></pre> 3131 <p>If that went OK install the drivers (as root):</p> 3132 <pre><code># make install 3133 </code></pre> 3134 <p>Check if the "devolo_usb" module is loaded:</p> 3135 <pre><code>$ lsmod | grep -i devolo_usb 3136 </code></pre> 3137 <p>If it shows up then it's loaded. Now check if the interface is added:</p> 3138 <pre><code>$ ifconfig -a | grep -i dlanusb 3139 dlanusb0 Link encap:Ethernet HWaddr 00:12:34:56:78:9A 3140 </code></pre> 3141 <h2>Configuration</h2> 3142 <p>It is assumed you use a static IP, otherwise you can just use your DHCP client 3143 to get an unused IP address from your DHCP server. Setting up the interface is 3144 done like this (change the IP address and netmask accordingly if it's 3145 different):</p> 3146 <pre><code># ifconfig dlanusb0 192.168.2.12 netmask 255.255.255.0 3147 </code></pre> 3148 <h2>Checking if the network works</h2> 3149 <p>Try to ping an IP address on your network to test for a working connection:</p> 3150 <pre><code>$ ping 192.168.2.1 3151 PING 192.168.2.1 (192.168.2.1) 56(84) bytes of data. 3152 64 bytes from 192.168.2.1: icmp_seq=1 ttl=30 time=2.49 ms 3153 64 bytes from 192.168.2.1: icmp_seq=2 ttl=30 time=3.37 ms 3154 64 bytes from 192.168.2.1: icmp_seq=3 ttl=30 time=2.80 ms 3155 --- 192.168.2.1 ping statistics --- 3156 3 packets transmitted, 3 received, 0% packet loss, time 2005ms 3157 rtt min/avg/max/mdev = 2.497/2.891/3.374/0.368 ms 3158 </code></pre> 3159 <p>You can now set up a network connection like you normally do with any Ethernet 3160 device. The route can be added like this for example:</p> 3161 <pre><code># route add -net 0.0.0.0 netmask 0.0.0.0 gw 192.168.2.1 dlanusb0 3162 </code></pre> 3163 <p>Change the IP address of your local gateway accordingly. Also make sure your 3164 nameserver is set in /etc/resolv.conf, something like:</p> 3165 <pre><code>nameserver 192.168.2.1 3166 </code></pre> 3167 <p>Test your internet connection by doing for example:</p> 3168 <pre><code>$ ping codemadness.org 3169 PING codemadness.org (64.13.232.151) 56(84) bytes of data. 3170 64 bytes from acmkoieeei.gs02.gridserver.com (64.13.232.151): icmp_seq=1 ttl=52 time=156 ms 3171 64 bytes from acmkoieeei.gs02.gridserver.com (64.13.232.151): icmp_seq=2 ttl=52 time=156 ms 3172 64 bytes from acmkoieeei.gs02.gridserver.com (64.13.232.151): icmp_seq=3 ttl=52 time=155 ms 3173 --- codemadness.org ping statistics --- 3174 3 packets transmitted, 3 received, 0% packet loss, time 1999ms 3175 rtt min/avg/max/mdev = 155.986/156.312/156.731/0.552 ms 3176 </code></pre> 3177 <p>If this command failed you probably have not setup your DNS/gateway properly. 3178 If it worked then good for you :)</p> 3179 <h2>References</h2> 3180 <ul> 3181 <li><a href="http://www.devolo.co.uk/consumer/downloads-44-microlink-dlan-usb.html?l=en">Devolo download page with drivers (USB version).</a></li> 3182 <li><a href="downloads/int51x1/dLAN-linux-package-v4.tar.gz">dLAN-linux-package-v4.tar.gz</a></li> 3183 <li><a href="downloads/int51x1/int51x1.patch">Patch for recent 2.6.x kernels</a></li> 3184 <li><a href="downloads/int51x1/INT51X1_datasheet.pdf">INT51X1 datasheet</a></li> 3185 </ul> 3186 ]]></content> 3187 </entry> 3188 <entry> 3189 <title>Gothic 1 game guide</title> 3190 <link rel="alternate" type="text/html" href="https://www.codemadness.org/gothic-1-guide.html" /> 3191 <id>https://www.codemadness.org/gothic-1-guide.html</id> 3192 <updated>2022-08-07T00:00:00Z</updated> 3193 <published>2009-04-12T00:00:00Z</published> 3194 <author> 3195 <name>Hiltjo</name> 3196 <uri>https://www.codemadness.org</uri> 3197 </author> 3198 <summary>Gothic 1 game guide with some useful tips</summary> 3199 <content type="html"><![CDATA[<h1>Gothic 1 game guide</h1> 3200 <p><strong>Last modification on </strong> <time>2022-08-07</time></p> 3201 <p><strong>Disclaimer:</strong> 3202 Some (including myself) may find some of these hints/exploits cheating. This 3203 guide is just for educational and fun purposes. Some of these hints/tips apply 3204 to Gothic 2 as well. I got the meat exploit from a guide somewhere on the 3205 internet I can't recall where, anyway kudos to that person. Some of the 3206 exploits I discovered myself.</p> 3207 <h2>Configuration</h2> 3208 <h3>Widescreen resolution</h3> 3209 <p>Gothic supports widescreen resolutions with a small tweak, add the following 3210 text string as a command-line argument:</p> 3211 <pre><code>-zRes:1920,1200,32 3212 </code></pre> 3213 <p>This also works for Gothic 2. Here 1920 is the width, 1200 the height and 32 3214 the bits per pixel, change this to your preferred resolution.</p> 3215 <h3>Fix crash with Steam version</h3> 3216 <p>Disable steam overlay. If that doesn't work rename GameOverlayRenderer.dll in 3217 your steam folder to _GameOverlayRenderer.dll. I strongly recommend to buy the 3218 better version from <a href="https://www.gog.com/game/gothic">GOG.com</a>. The GOG version has no DRM and allows easier 3219 modding, it also allows playing in most published languages: German, English, 3220 Polish, furthermore it has some original artwork and soundtrack included.</p> 3221 <h3>Upgrade Steam version to stand-alone version and remove Steam DRM (Gothic 1 and 2)</h3> 3222 <p>You can install the Gothic playerkit and patches to remove the Steam DRM.</p> 3223 <p><a href="https://www.worldofgothic.de/">WorldOfGothic</a> playerkit patches:</p> 3224 <ul> 3225 <li>Gothic 1 (EN): <a href="https://www.worldofgothic.com/dl/?go=dlfile&fileid=28">https://www.worldofgothic.com/dl/?go=dlfile&fileid=28</a></li> 3226 <li>Gothic 1 (DE): <a href="https://www.worldofgothic.de/dl/download_34.htm">https://www.worldofgothic.de/dl/download_34.htm</a></li> 3227 <li>Gothic 2 (EN/DE): <a href="https://www.worldofgothic.de/dl/download_168.htm">https://www.worldofgothic.de/dl/download_168.htm</a></li> 3228 </ul> 3229 <h3>Play Gothic in a different language with English subtitles</h3> 3230 <p>If you're like me and have played the English version many times, but would 3231 like to hear the (original) German voice audio or if you would like to play 3232 with different audio than you're used to, then you can copy the speech.vdf file 3233 of your preferred version to your game files. Optionally turn on subtitles. 3234 I've used this to play the English version of Gothic with the original German 3235 voice audio and English subtitles. 3236 This works best with the version from GOG as it allows easier modding.</p> 3237 <h2>Easy money/weapons/armour/other items</h2> 3238 <h3>Steal from Huno</h3> 3239 <p>At night attack Huno the smith in the Old Camp and steal all his steel. Then 3240 make some weapons and sell them with a merchant. When you ask Huno about 3241 blacksmith equipment it will respawn with 5 of each kind of steel. This is also 3242 a fairly good starting weapon (requires 20 strength). Also his chest located 3243 near the sharpening stone and fire contains some steel as well, lock-pick it. 3244 The combination is: RRLRLL. The chest contains at least 20 raw steel, forge it 3245 to get 20 crude swords which you can sell for 50 ore each to a merchant. This 3246 will generate some nice starting money (1000+ ore) :)</p> 3247 <h3>Steal weapons from the castle in the Old Camp</h3> 3248 <p>This tip is useful for getting pretty good starting weapons.</p> 3249 <p>Before entering the castle itself drop your ore (Left control + down for me) 3250 in front of it. This will ensure when you get caught (and you probably will ;)) 3251 no ore will get stolen by the guards. Now use the "slip past guard" technique 3252 described below and you should be able to get into Gomez his castle. Run to the 3253 left where some weapons are stored. Now make sure you at least steal the best 3254 weapon (battle sword) and steal as much as you can until you get whacked. I 3255 usually stand in the corner since that's where the best weapons are (battle 3256 sword, judgement sword, etc). You'll now have some nice starting weapon(s) and 3257 the good thing is they require very little attributes (about 13 strength).</p> 3258 <h3>Free scraper armour the New Camp</h3> 3259 <p>In the New Camp go to the mine and talk to Swiney at the bottom of "The 3260 Hollow". Ask who he is and then ask to join the scrapers. He will give you a 3261 "Diggers dress" worth 250 ore. It has the following stats: + 10 against 3262 weapons. + 5 against fire. This will also give you free entrance to the bar in 3263 the New Camp.</p> 3264 <h3>Unlimited water bottles in the New Camp</h3> 3265 <p>In the quest from Lefty you will be assigned to get water bottles from the 3266 rice lord. He will give you infinite amounts of water bottles, in batches of 3267 12.</p> 3268 <h3>Armour amulet and increase HP potion</h3> 3269 <p>In the Old Camp in the main castle there are at least 3 chests with valuable 3270 items that don't require a key:</p> 3271 <ul> 3272 <li>Middle right side (looking from the entrance), 1 chest: 3273 <ul> 3274 <li>lock combination: LLLLRLRL</li> 3275 <li>loot: 3276 <ul> 3277 <li>+15 against weapons, +15 against arrows (amulet of stone skin) 3278 (worth: 1000 ore)</li> 3279 </ul> 3280 </li> 3281 <li>additionally there are 2 locked doors at the right side in this room. In 3282 the final room there are 3 floors with lots of chests.</li> 3283 </ul> 3284 </li> 3285 <li>Left side, 1 chest: 3286 <ul> 3287 <li>lock combination: RLLLLLRR</li> 3288 <li>loot: 3289 <ul> 3290 <li>+8 mana amulet (worth: 600 ore)</li> 3291 <li>2 potions (+70 hp)</li> 3292 <li>dreamcall (weed)</li> 3293 <li>120 coins (worth: nothing)</li> 3294 </ul> 3295 </li> 3296 </ul> 3297 </li> 3298 <li>Right side, 2 chests with: 3299 <ul> 3300 <li>lock combination: RLLLRLLR</li> 3301 <li>loot: 3302 <ul> 3303 <li>armour amulets, +15 against weapons (worth: 600 ore)</li> 3304 <li>maximum life potion, +10 maximum life (worth: 1000 ore)</li> 3305 <li>speed potion (1 minute duration)</li> 3306 <li>4 potions (+70 hp)</li> 3307 </ul> 3308 </li> 3309 </ul> 3310 </li> 3311 </ul> 3312 <h3>Swamp/Sect Camp harvest twice</h3> 3313 <p>In the swamp-weed harvest quest you must get swamp-weed for a guru. After this 3314 quest you can get the harvest again, but you can keep the harvest without 3315 consequences.</p> 3316 <h2>Exploits</h2> 3317 <h3>Slip past guards</h3> 3318 <p>This exploit is really simple, just draw your weapon before you're "targeted" 3319 by the guard and run past them, this bypasses the dialog sequence. When you're 3320 just out of their range holster your weapon again, so the people around won't 3321 get pissed off.</p> 3322 <p>Works really well on the guards in front of the Old camp's castle, Y'Berrion 3323 templars and New Camp mercenaries near the Water magicians, just to name a few.</p> 3324 <h3>Meat duplication</h3> 3325 <p>Go to a pan and focus / target it so it says "frying pan" or similar. Now open 3326 your inventory and select the meat. Now cook the meat (for me Left Control + 3327 Arrow up). The inventory should remain open. You'll now have twice as much meat 3328 as you had before. Do this a few times and you'll have a lot of meat, easy for 3329 trading with ore/other items as well. This exploit does not work with the 3330 community patch applied.</p> 3331 <h3>Fall from great heights</h3> 3332 <p>When you fall or jump from where you usually get fall damage you can do the 3333 following trick: slightly before the ground use left or right strafe. This 3334 works because it resets the falling animation. There are also other ways to 3335 achieve the same thing cancelling the falling animation, such as attacking with 3336 a weapon in the air.</p> 3337 <h2>Experience / level up tips</h2> 3338 <h3>Test of faith (extra exp)</h3> 3339 <p>You get an additional 750 exp (from Lares) when you forge the letter in the new 3340 camp and then give it to Diego. You can still join both camps after this.</p> 3341 <h3>Fighting skeleton mages and their skeletons</h3> 3342 <p>An easy way to get more experience is to let the skeleton mages summon as much 3343 skeletons as they can, instead of rushing to kill the summoner immediately. 3344 After you have defeated all of them: kill the skeleton mage.</p> 3345 <h3>Permanent str/dex/mana/hp potions/items and teachers</h3> 3346 <p>When you want to get the maximum power at the end of the game you should save 3347 up the items that give you a permanent boost. Teachers of strength, dexterity 3348 and mana won't train over 100 of each skill. However using potions and quest 3349 rewards you can increase this over 100.</p> 3350 <p>You should also look out for the following:</p> 3351 <ul> 3352 <li><p>Learn to get extra force into your punch from Horatio (strength +5, this 3353 can't be done after level 100 strength). Talking to Jeremiah in the New Camp 3354 bar unlocks the dialog option to train strength at Horatio.</p> 3355 </li> 3356 <li><p>Smoke the strongest non-quest joint (+2 mana).</p> 3357 </li> 3358 </ul> 3359 <h3>Permanent potions in Sleeper temple</h3> 3360 <p>This one is really obvious, but I would like to point out the mummy's on each 3361 side where Xardas is located have lots and I mean lots of permanent potions. 3362 This will give you a nice boost before the end battle.</p> 3363 <h3>Permanent potions as reward in quests</h3> 3364 <p>Always pick the permanent potion as a reward for quests when you can, for 3365 example the quest for delivering the message to the High Fire magicians (mana 3366 potion) or the one for fetching the almanac for the Sect Camp. Don't forget to 3367 pick up the potions from Riordian the water magician when you're doing the 3368 focus stones quest, it contains a strength and dexterity potion (+3).</p> 3369 <h3>Random/beginner tips</h3> 3370 <ul> 3371 <li><p>If you want to talk to a NPC, but some animation of them takes too long (like 3372 eating, drinking, smoking) you can sometimes force them out of it by quickly 3373 unsheathing/sheathing your weapon.</p> 3374 </li> 3375 <li><p>When in the Old Camp: Baal Parvez can take you to the Sect Camp, he can be 3376 found near the campfire near Fisk and Dexter. 3377 Mordrag can take you to the New Camp, he can be found near the south gate, 3378 slightly after the campfire near Baal Parvez.</p> 3379 <p>When you follow them and when they kill monsters then you also get the 3380 experience.</p> 3381 </li> 3382 <li><p>The NPC Wolf in the New Camp sells "The Bloodflies" book for 150 ore. When 3383 you read this book you learn how to remove bloodflies parts (without having to 3384 spend learning points). After you read the book and learned its skill then you 3385 can sell the book back for 75 ore. This investment quickly pays back: Per 3386 bloodfly: sting: 25 ore (unsold value), 2x wings (15 ore each unsold value).</p> 3387 </li> 3388 <li><p>The templar Gor Na Drak (usually near the old mine and walks around with 3389 another templar): talking to him teaches you how to learn to get secretion from 3390 minecrawlers for free.</p> 3391 </li> 3392 <li><p>The spell scroll "Transform into bloodfly" is very useful: 3393 <ul> 3394 <li>A bloodfly is very fast.</li> 3395 <li>Can also fly over water.</li> 3396 <li>The scroll costs 100 ore. Its the same price as a potion of speed, but it 3397 has no duration (just until you transform back).</li> 3398 <li>You have no fall damage.</li> 3399 <li>You can climb some steep mountains this way.</li> 3400 <li>Some monsters won't attack you, but some NPCs will attack you.</li> 3401 <li>Your attribute stats will temporary change.</li> 3402 <li>It requires 10 mana to cast (low requirement).</li> 3403 </ul> 3404 </p> 3405 </li> 3406 <li><p>Almost all mummies that are lootable in the game (Orc temple and The Sleeper 3407 temple) have really good loot: permanent and regular potions and amulets and 3408 rings.</p> 3409 </li> 3410 </ul> 3411 <h3>In conclusion</h3> 3412 <p>When you use the tips described above Gothic should be a really easy game and 3413 you should be able to get at a high(er) level with lots of mana/strength/hp.</p> 3414 <p>Have fun!</p> 3415 ]]></content> 3416 </entry> 3417 </feed>