superjamie.github.io Insert witty tagline https://superjamie.github.io/ Thu, 09 Apr 2026 05:48:03 +0000 Thu, 09 Apr 2026 05:48:03 +0000 Jekyll v3.10.0 Caddy container with DNS provider <p>I’ve been using <a href="https://caddyserver.com/">Caddy</a> as a reverse proxy for a while. It’s very well documented and easy to configure.</p> <p>Gone are the days of figuring out HTTPS and paying for a certificate, many webservers and proxies offer an automated TLS certificate via Let’s Encrypt automated challenges. Getting a valid TLS certificate is just one line in a config file.</p> <p>The default way to do this is with a “HTTP Challenge” where the webserver must listen on port 80, and the provider makes sure the webserver asking for the certificate is the webserver at the domain.</p> <p>I want to move to Wildcard domains, which requires a “DNS Challenge”, where the webserver contacts the DNS provider via an API.</p> <p>Caddy implements this as additional modules, however modules cannot be dynamically loaded, you need to either <a href="https://caddyserver.com/download?package=github.com%2Fcaddy-dns%2Fcloudflare">download a Caddy binary from the build service, or build Caddy yourself</a>.</p> <p>This wasn’t very appealing to me, I just want a container that works.</p> <p>Luckily, I found the <a href="https://github.com/caddyserver/gateway/blob/master/caddy.Containerfile">Caddy Gateway Containerfile</a> which shows an example of an automated build and copy into the regular Caddy container.</p> <p>I modified this a little for my needs:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ARG CADDY_VERSION=2 FROM docker.io/library/caddy:${CADDY_VERSION}-builder AS builder RUN XCADDY_SETCAP=0 XCADDY_SUDO=0 xcaddy build \ --with github.com/caddy-dns/cloudflare FROM docker.io/library/caddy:${CADDY_VERSION} COPY --from=builder /usr/bin/caddy /usr/bin/caddy </code></pre></div></div> <p>Now I can <code class="language-plaintext highlighter-rouge">podman build .</code> and I get a new image at the end of it:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[2/2] STEP 2/2: COPY --from=builder /usr/bin/caddy /usr/bin/caddy [2/2] COMMIT --&gt; 4d7a6ac83a0 4d7a6ac83a0783425c0b569684190c8233a484374ddb1fa24239903e01e1bf48 </code></pre></div></div> <p>I can give this a tag:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ podman image tag 4d7a6ac83a07 caddy-cloudflare:latest </code></pre></div></div> <p>Done! I now have the regular Caddy image with the built binary in it.</p> <p>Any time the base container updates, I can just rebuild it and continue like normal.</p> Sat, 02 Nov 2024 00:00:00 +0000 https://superjamie.github.io/2024/11/02/caddy-container-with-dns-provider https://superjamie.github.io/2024/11/02/caddy-container-with-dns-provider Goodbye, Neovim <p>I’ve been using Neovim for a while now and it’s been fun. I didn’t see any real killer feature for it, but I wrote previously about <a href="other-reasons-to-switch-to-neovim">other reasons to switch to Neovim</a>.</p> <p>However, I kept all my config in Vimscript and didn’t migrate to Lua for a couple of reasons.</p> <p>First, I need to use Vim on systems where Neovim isn’t easily available, and I didn’t feel like manually updating the AppImage.</p> <p>Second, I was being careful in case something made Neovim unviable for me.</p> <p>That day has come with <a href="https://github.com/neovim/neovim/pull/20545">Neovim’s removal of the cscope feature</a> in Neovim 0.9.</p> <p>LSP is great for small codebases where you can easily do a build or generate the compilation database, however it’s not very enjoyable for large codebases like <a href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/">the Linux kernel</a> or maybe one of the modern BSDs, where a build to generate <code class="language-plaintext highlighter-rouge">compile_commands.json</code> is a large undertaking, and especially if you switch around different historical revisions of the codebase a lot, which is my exact usecase.</p> <p>For that sort of code browsing, it’s much better to use <a href="https://www.gnu.org/software/global/">GNU Global</a> tags and the <a href="https://cvs.savannah.gnu.org/viewvc/*checkout*/global/global/gtags-cscope.vim">gtags-cscope.vim</a> plugin.</p> <p>Nothing else in Neovim really made a huge difference to me. The <code class="language-plaintext highlighter-rouge">vim-gtk3</code> Ubuntu/Debian package supports <code class="language-plaintext highlighter-rouge">set clipboard=unnamedplus</code> for yank persistence, and at least Vim 8 supports <code class="language-plaintext highlighter-rouge">:terminal</code> buffers too.</p> <p>Maybe I can finally pull my finger out and get the <code class="language-plaintext highlighter-rouge">t_SI</code>/<code class="language-plaintext highlighter-rouge">t_SR</code>/<code class="language-plaintext highlighter-rouge">t_EI</code> escape sequences working under tmux so Vim has the nice <code class="language-plaintext highlighter-rouge">guicursor</code> too.</p> <p>Edit: Well, that was surprisingly easy, just set the escape sequences (press actual <strong>Ctrl+k</strong> then <strong>Esc</strong>, don’t use literal <code class="language-plaintext highlighter-rouge">ESC</code>). <a href="https://stackoverflow.com/questions/42377945/vim-adding-cursorshape-support-over-tmux-ssh">Reference</a>.</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>" guicursor in terminal set t_SI=ESC[6\ q set t_SR=ESC[4\ q set t_EI=ESC[2\ q </code></pre></div></div> <p>Anyway, goodbye Neovim, it was fun while it lasted.</p> Sun, 09 Apr 2023 00:00:00 +0000 https://superjamie.github.io/2023/04/09/goodbye-neovim https://superjamie.github.io/2023/04/09/goodbye-neovim HP t530 Thin Client with Linux <p>I love collecting gadgets. I recently noticed you can get these thin clients pretty cheap off eBay. These were going for AU$60 (US$40) so I picked one up.</p> <p>The full specifications are <a href="https://support.hp.com/us-en/document/c05696381">on HP’s website</a> but in summary:</p> <ul> <li>CPU: AMD GX-215JJ System-on-Chip (<code class="language-plaintext highlighter-rouge">x86_64</code>), dual-core 1.5 GHz (boost to 2.0 GHz)</li> <li>RAM: DDR4 1866 SODIMM, one slot up to 16G</li> <li>GPU: Radeon R2E, roughly equal to HD4550 or GeForce 9400GT</li> <li>Display ports: 2x DisplayPort, can do dual 4K</li> <li>Video decode: x264 and x265 in hardware at 1080p</li> <li>WiFi: Intel 3168NGW (802.11ac), <code class="language-plaintext highlighter-rouge">iwlwifi</code> driver, PCI ID <code class="language-plaintext highlighter-rouge">8086:24fb</code></li> <li>LAN: RealTek Gigabit, <code class="language-plaintext highlighter-rouge">r8169</code> driver, PCI ID <code class="language-plaintext highlighter-rouge">10ec:8168</code></li> <li>Storage: M.2 SATA 6.0 Gbps, 2280/2260/2242 up to 512G</li> <li>USB: 2.0 and 3.0, 1x USB-A and USB-C on front, several on rear</li> </ul> <p>It’s also fanless so is completely silent.</p> <p>That’s really good for the sort of things I like to play with.</p> <p>Mine came with some modern Windows and Secure Boot enabled, but that was easy to disable in the BIOS.</p> <p>Booting Ubuntu 22.04 (kernel v5.15) worked without a problem. It found all the hardware, including the internal speaker, sound output via video, Ethernet, and WiFi. Using Linux on few-year-old hardware is delightfully boring these days, everything just works.</p> <p>Plugging into a TV with HDMI worked fine with a DisplayPort-to-HDMI cable off eBay. Mine also includes the optional VGA out connector.</p> <p>I had a spare SSD lying around, and bought 16G RAM off eBay (ironically, for more than the cost of the entire thin client).</p> <p>Performance in emulators is good enough for me:</p> <ul> <li>PSX (DuckStation) - 100% speed at 3x scaling (720p), struggled with 5x (1080p). Tested with Wipeout 3 (US).</li> <li>PSP (PPSSPP) - 100% speed at 1x scaling, struggled with any more. Tested with Outrun 2006 Coast 2 Coast.</li> </ul> <p>Sadly PS2 (PCSX2) isn’t an option. Gran Turismo 3 ran at ~40% speed even with graphics settings turned down.</p> <p>This is a better option than a Raspberry Pi 4 if you’re looking for a movie/TV box for Kodi, or something to run emulators on like RetroArch or Lakka or the PC install of RetroPie, or just use with a wireless keyboard and mouse from the couch. It’s also still cheaper than even a 5th Gen Celeron Intel NUC goes for these days.</p> <p>It also supports virtualization CPU extensions, so there’s no reason you couldn’t run VMs or even a small fleet of container hosts on it, maybe useful for Kubernetes or OpenShift learning.</p> <p>Overall, I’m very happy with this.</p> <p>Here’s a YouTube video showing the unit and the easy access to the internal components:</p> <!-- https://silvercircle.subspace.cc/2017/10/10/embed-youtube-jekyll/ --> <div style="width: ; margin:0 auto;"> <div class="ytcontainer"> <iframe class="yt" allowfullscreen="" src="https://www.youtube.com/embed/d4vHfr-Pvjg"></iframe> </div> </div> Sat, 11 Feb 2023 00:00:00 +0000 https://superjamie.github.io/2023/02/11/hp-t530-thin-client-linux https://superjamie.github.io/2023/02/11/hp-t530-thin-client-linux Repeated Keypresses - an application usage anti-pattern <p>Repeated keypresses are an application usage anti-pattern. We should try to recognise when we’re using repeated keypresses, and replace them with more meaningful alternatlves.</p> <p>This whole idea comes from disabling your arrow keys in the Vim editor, because repeatedly pressing <strong>Up,Up,Up,Up</strong> is an inefficient way to use the editor. For that particular movement you could have used <code class="language-plaintext highlighter-rouge">4k</code> to move up three lines.</p> <p>There are many others places that repeated keypresses can be removed, here are a few ideas for:</p> <ul> <li>Vim</li> <li>Web browsers</li> <li>Desktop Alt+Tab and application launching</li> </ul> <h2 id="vim">Vim</h2> <p>If you get serious about learning Vim, one of the first things you should do is disable the arrow keys to train yourself away from them.</p> <p>Unfortunately, that often leads to just repeating the same anti-pattern with the <code class="language-plaintext highlighter-rouge">hjkl</code> movement keys, like pressing <code class="language-plaintext highlighter-rouge">kkkk</code> to move up 4 lines.</p> <p>Drew Neil (<a href="http://vimcasts.org/episodes/archive/">Vimcasts</a> videos, <a href="https://pragprog.com/titles/dnvim2/practical-vim-second-edition/">Practical Vim</a> book) has a post about this: <a href="http://vimcasts.org/blog/2013/02/habit-breaking-habit-making/">Habit breaking, habit making (2013)</a> where he introduces the idea of disabling the arrow and <code class="language-plaintext highlighter-rouge">hjkl</code> keys, and shows the old <a href="https://github.com/wikitopian/hardmode">vim-hardmode</a> plugin which is deprecated now.</p> <p>The modern version of hardmode is <a href="https://github.com/takac/vim-hardtime">vim-hardtime</a>. I recommend using this and enabling it by default in your <code class="language-plaintext highlighter-rouge">~/.vimrc</code>. Here are my settings:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>let g:hardtime_default_on = 1 let g:hardtime_maxcount = 3 </code></pre></div></div> <p>This lets me use one of the motion keys up to three times like <code class="language-plaintext highlighter-rouge">jjj</code> (to address overshoots and nearby quick movements) but no more.</p> <p>To move around text, you can use the <code class="language-plaintext highlighter-rouge">fF</code> (forward/backward to character) or <code class="language-plaintext highlighter-rouge">tT</code> (to character) motions, or the <code class="language-plaintext highlighter-rouge">/?</code> keys (search forward/backward).</p> <p>You can combine these with editing commands, for example, given the cursor at <code class="language-plaintext highlighter-rouge">█</code>:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>The █quick brown fox jumped over the lazy dog. </code></pre></div></div> <p>You could delete to “lazy” with <code class="language-plaintext highlighter-rouge">dtl</code> (delete, to, “l”). This gives us:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>The █lazy dog. </code></pre></div></div> <p>What about more difficult text with similar characters?</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>She █sells sea shells by the sea shore. </code></pre></div></div> <p>This is where <a href="https://github.com/justinmk/vim-sneak">vim-sneak</a> becomes useful. It uses the same ideas as the <code class="language-plaintext highlighter-rouge">fFtT</code> mappings, but matches <strong>two</strong> characters.</p> <p>We could delete up to “shore” with <code class="language-plaintext highlighter-rouge">dzsh;</code> (delete, zneak, “sh”, next match). The “next match” is used because “shells” also starts with “sh”. This gives us:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>She █shore. </code></pre></div></div> <p>The <code class="language-plaintext highlighter-rouge">zZ</code> mappings are used in motions because <code class="language-plaintext highlighter-rouge">sS</code> is more commonly used by <a href="https://github.com/tpope/vim-surround">vim-surround</a>.</p> <p>Moving around text normally, you use the <code class="language-plaintext highlighter-rouge">sS</code> motions.</p> <p>To just move to “shore” we would have used <code class="language-plaintext highlighter-rouge">ssh;</code> (sneak to, sh, next match). This gives us:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>She sells sea shells by the sea █shore. </code></pre></div></div> <p>vim-sneak also adds little coloured annotations so you can see all the “next matches” available on the page, and move to them with one letter. See the <a href="https://github.com/justinmk/vim-sneak">vim-sneak</a> page for an image of those.</p> <p>To move around lines easier, you could use <a href="https://github.com/jeffkreeftmeijer/vim-numbertoggle">vim-numbertoggle</a>, which sets relative numbers and absolute numbers in a sensible way. Again see the link for a great image.</p> <h2 id="web-browser">Web Browser</h2> <p>We all use web browsers with a lot of tabs these days, you probably find yourself using <strong>Ctrl+PgUp/PgDn</strong> to move through tabs. But that’s a repeated keypress. Is there a better way?</p> <p>If you have 9 or less tabs open, you can move to them with <strong>Alt+number</strong>. For example, moving to the first tab is <strong>Alt+1</strong>, moving to the second tab is <strong>Alt+2</strong> and so on. But we hit a limitation with 9 tabs, because <strong>Alt+8</strong> is the 8th tab, and <strong>Alt+9</strong> is the rightmost tab.</p> <p>You can cycle through tabs with <strong>Ctrl+Tab</strong> and cycle backwards with <strong>Ctrl+Shift+Tab</strong>, but again this is a repeated keypress.</p> <p>Firefox (the superior browser) allows tab search in its awesomebar. Hit <strong>Ctrl+L</strong> to focus the address bar and start typing an open tab match. You’ll get an option “Switch to Tab”, so press down and Enter and you’re there!</p> <p>Firefox also allows you to map <strong>Ctrl+Tab</strong> to “switch to last tab”, for easily moving back and forth between two tabs. In Preferences, this is <strong>Ctrl+Tab cycles through tabs in recently used order</strong>.</p> <p>Chrome/Chromium doesn’t have this as far as I can see. I don’t use the Chromium family of browsers at all, so I don’t know of an option there. Maybe there’s an extension? Maybe you should use Firefox.</p> <p>Both browsers support this <strong>Ctrl+L</strong> to focus the address bar where you can:</p> <ul> <li>Search with your default search engine: type a word and press <strong>Enter</strong></li> <li>Go to a <code class="language-plaintext highlighter-rouge">.com</code> domain: type the domain like “google” and press <strong>Ctrl+Enter</strong> to go to <code class="language-plaintext highlighter-rouge">google.com</code></li> </ul> <p>Both browsers support searching in the current page with <strong>Ctrl+f</strong>.</p> <p>Firefox also supports finding clickable text with the <strong>‘</strong> (single quote, next to semicolon in US layout) then <strong>Enter</strong> to follow the link. This is great for browsing text-heavy pages like <a href="https://www.wikipedia.org/">Wikipedia</a>. Try it now with <strong>‘wiki</strong> in Firefox (the search is not case sensitive).</p> <p>Generally you should learn your browser keyboard shortcuts:</p> <ul> <li><a href="https://support.mozilla.org/en-US/kb/keyboard-shortcuts-perform-firefox-tasks-quickly">Firefox: Keyboard shortcuts - Perform common Firefox tasks quickly</a></li> <li><a href="https://support.google.com/chrome/answer/157179">Chrome: Chrome keyboard shortcuts</a></li> </ul> <h2 id="alttab">Alt+Tab</h2> <p>Here’s a spicy one. The pattern of switching through application with repeated <strong>Alt*Tab</strong> is one of the worst desktop usage patterns.</p> <p>Tiling window managers like <a href="https://i3wm.org/">i3</a> and <a href="https://swaywm.org/">Sway</a> try to avoid this by having applications on different workspaces (virtual desktops) which you can switch to with <strong>Win+number</strong>, or by having applications in a split which you switch to with the Vim direction keys <strong>Win+hjkl</strong>. This is pretty good.</p> <p>The <a href="https://davatorium.github.io/rofi/">rofi</a> application launcher does smart partial matching of commands or applications to launch, narrowing down options as you type.</p> <p>So you can <code class="language-plaintext highlighter-rouge">rofi -show drun</code> and start typing <code class="language-plaintext highlighter-rouge">fir</code> then just press <strong>Enter</strong> to launch Firefox.</p> <p>i3 and Sway bind <code class="language-plaintext highlighter-rouge">rofi -show drun</code> to <strong>Win+d</strong> for this purpose.</p> <p>I propose to change this to <code class="language-plaintext highlighter-rouge">rofi -combi-modi window,drun,run -show combi</code> which adds a window switcher. You can use <code class="language-plaintext highlighter-rouge">windowcd</code> to limit it to the current workspace. I bind this to <strong>Win+Space</strong> for my desktop, but you could bind it to <strong>Win+d</strong> if you use i3/Sway, or take the plunge and bind it to <strong>Alt+Tab</strong>.</p> <p>Now you can hit your key, type the partial name of the window you want, and switch to it with <strong>Enter</strong>. Much quicker and better than cycling through <strong>Alt+Tab</strong> until you get there.</p> <p>This has the added advantage that if the appication isn’t already open, it’s launched instead!</p> <p>This is also a much better way to launch applications than clicking a “Start” button and browsing through a menu. I prefer this to the “activities” idea that desktops like GNOME/Pantheon/Unity try to implement.</p> <h2 id="summary">Summary</h2> <p>Find repeated keypresses in your current workflow and eliminate them.</p> <p>This will give you a more efficient and more intentioned application usage experience.</p> <p>Get the computer to do what you actually want quickly, instead of doomscrolling through all available options.</p> <p>What replacements have you found which are useful?</p> Sat, 28 Jan 2023 00:00:00 +0000 https://superjamie.github.io/2023/01/28/repeated-keypresses https://superjamie.github.io/2023/01/28/repeated-keypresses Other reasons to switch to Neovim <p><a href="https://neovim.io/">Neovim</a> has become very popular as a replacement for plain <a href="https://www.vim.org/">Vim</a>. Most advice about moving to Neovim is centred around the LSP and Lua features, but I don’t care about those. This post explores a few other reasons you might want to switch to Neovim.</p> <h2 id="better-cursor">Better Cursor</h2> <p>In Vim, regardless of what mode or context you’re in, the cursor is always the same. Usually the terminal’s default block cursor.</p> <p>In Neovim, the cursor changes to a vertical bar in Insert mode, and changes to an underbar when you’re in a character context like <code class="language-plaintext highlighter-rouge">r</code>eplace.</p> <p>This seems a very minor difference, but it made a big difference to me, notably helping determine where text would be inserted when I entered <code class="language-plaintext highlighter-rouge">i</code>nsert or <code class="language-plaintext highlighter-rouge">a</code>ppend.</p> <p>While you can apply a similar thing with plain Vim using ANSI escapes, I couldn’t get those working in tmux, despite many cryptic settings copy-pasted from StackOverflow.</p> <p>I didn’t realise how much I loved this feature until I had it. Now I’d be very unwilling to give it up.</p> <p>(according to <a href="https://codekoalas.com/blog/why-you-should-still-use-neovim">codekoalas</a> this is actually the <code class="language-plaintext highlighter-rouge">guicursor</code> feature of GVim)</p> <h2 id="yank-persistence">Yank Persistence</h2> <p>For those who use Vim in tmux, it’s always been a pest to have one Vim instance open and wish to yank/paste across to another Vim instance in another pane/window/session.</p> <p>This “just works” in Neovim.</p> <p>As an added bonus, you can even <code class="language-plaintext highlighter-rouge">y</code>ank something, <code class="language-plaintext highlighter-rouge">q</code>uit the editor altogether, open a new editor, and <code class="language-plaintext highlighter-rouge">p</code>aste - and that works too!</p> <p>While it’s possible to work around this with the system clipboard in Vim, Neovim’s native persistence does this better.</p> <h2 id="built-in-terminal">Built-in Terminal</h2> <p>In Neovim you can run <code class="language-plaintext highlighter-rouge">:terminal</code> and a buffer is opened with a terminal emulator. You can even open a command directly in a split like <code class="language-plaintext highlighter-rouge">:vsplit term://top</code>:</p> <p>You can enter <code class="language-plaintext highlighter-rouge">i</code>nsert or <code class="language-plaintext highlighter-rouge">a</code>ppend mode to run commands, then when you have output ready you can <code class="language-plaintext highlighter-rouge">Ctrl+\ Ctrl+n</code> to return to Normal mode.</p> <p>If that’s too much to remember, the help suggests a more normal binding:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>if has('nvim') tnoremap &lt;Esc&gt; &lt;C-\&gt;&lt;C-n&gt; endif </code></pre></div></div> <p>Now the terminal buffer is treated like any other text buffer in Normal mode.</p> <p>I regularly switch between editor and terminal in my work, copy and pasting between the two, but I’d really rather use Vim full-time. I’m looking forward to using this more.</p> <h2 id="proper-vscode-integration">Proper VSCode integration</h2> <p>I like to dabble in Visual Studio Code, though it usually ends up annoying me. Anyway.</p> <p>It has a <a href="https://github.com/VSCodeVim/Vim">Vim emulation plugin</a> which is <em>sort of</em> like Vim but not quite, and you can’t use actual Vim plugins in it.</p> <p>However, the <a href="https://github.com/vscode-neovim/vscode-neovim">neovim plugin</a> isn’t an emulation, it’s actual real Neovim.</p> <p>This means all your plugins and config work just like a real editor.</p> <p>This is possible because Neovim completely decouples the frontend and backend of the editor, so the editor can be embedded anywhere.</p> <h2 id="you-dont-have-to-switch-entirely">You don’t have to switch entirely</h2> <p>There’s a lot of info out there about rewriting your config in Neovim’s native Lua, but I still have to SSH into systems where Neovim isn’t available and I can’t (or can’t be bothered) getting the latest Neovim working.</p> <p>But that’s fine.</p> <p>Front-and-center on the documentation page is <a href="https://neovim.io/doc/user/nvim.html#nvim-from-vim"><code class="language-plaintext highlighter-rouge">:help nvim-from-vim</code></a> which guides you through using your existing <code class="language-plaintext highlighter-rouge">~/.vimrc</code> and everything else right in Neovim.</p> <p>So I can keep the same VimScript config for places where I don’t have Neovim, and I can use all the above handy features in places where I do have Neovim.</p> <p>Best of both worlds.</p> <p>Which I guess is what this post is all about - using Vim but getting something even better. That’s what Neovim is all about!</p> Mon, 09 Jan 2023 00:00:00 +0000 https://superjamie.github.io/2023/01/09/other-reasons-to-switch-to-neovim https://superjamie.github.io/2023/01/09/other-reasons-to-switch-to-neovim Distro Surfing 2022 Part 2 <p>After <a href="/2022/12/24/distro-surfing-2022">my last post</a> about trying out various Linux distros, <a href="https://chaos.social/@globalc/109567190594790615">my friend Christian said</a> he was using <a href="https://swaywm.org/">Sway</a> which is the Wayland version of <a href="https://i3wm.org/">i3</a>. It’s been a while since I used i3 so I wanted to give it a try again and went hunting for a LiveCD of it.</p> <p>I ended up finding several more spins of desktop environments, so gave them a go:</p> <h2 id="sway">Sway</h2> <ul> <li>Sway 1.7 on Ubuntu Sway 22.10</li> </ul> <p>Pretty nice. I use a set of keybindings similar to i3 already, so this wasn’t a huge gap for me. The built-in help popup showed me how to drive it and some experimentation got me comfortable. It was a little difficult to set the bar to the bottom of the screen but I figured it out. I had some weird font scaling issues with <code class="language-plaintext highlighter-rouge">foot</code> terminal unless I set <code class="language-plaintext highlighter-rouge">dpi-aware=no</code>. Some minor polish issues like no graphical NetworkManager installed by default, but that’s more the distro than the DE. This confirms my thought that I’d probably be very comfortable using i3 now, though I imagine it would take some learning and config time to get it perfect, which MATE and Cinnamon do almost by default. Good desktop that makes me want to explore it more.</p> <p><strong>Rating: 4/5</strong></p> <h2 id="unity">Unity</h2> <ul> <li>Unity 7.6 in Ubuntu Unity 22.04</li> </ul> <p>Another Mac copy but they actually get the top bar right, with File/Edit/etc controls up there. The rest of the desktop didn’t thrill me, I didn’t like the launcher or “lens” concept. It hijacks too many keyboard shortcuts that I want to use. Lots of animation and blue and eye candy cruft. I’d be unhappy using this, just as I would be with Gnome.</p> <p><strong>Rating: 0/5</strong></p> <h2 id="deepin">Deepin</h2> <ul> <li>Deepin 5.10? on Ubuntu DDE 22.04</li> </ul> <p>Interesting looking desktop with lots of big buttons and transparency. Is this made for beginners? Seems to be based on KDE. The only reason I know this is because the very first thing I tried (switching to dark mode) resulted in a constant flood of ”KWin Exited Unexpectedly” messages and made the system completely unusable and I had to force power off. Trying again gave me many things which just didn’t work, keyboard shortcuts which can’t be changed, window transparent corners which don’t work properly so the window has a square shadow in the corner. Evidently needs a lot more work.</p> <p><strong>Rating: 0/5</strong></p> <h2 id="kylin">Kylin</h2> <ul> <li>UKUI 3.1 on Ubuntu Kylin 22.04</li> </ul> <p>Chinese desktop environment, even defaults to Chinese language by default. Wikipedia says this started out as a MATE fork, but has lost a lot of the customisation and options that MATE has. What’s left is a strange desktop with few configuration options that reminds me more of using Windows XP or 7 than Linux. Seems to use applications from different graphical toolkits (GTK, Qt, etc) to get whatever job done that it needs. The English translation is not the best, and even with English selected, some text is not translated. I wouldn’t use it.</p> <p><strong>Rating: 0/5</strong></p> <h2 id="bonus-android">Bonus: Android</h2> <p>I don’t really expect to use Android as a desktop, but I was interested to see how these ran as a way to play mobile games on the computer. I tried:</p> <ul> <li><a href="https://blissos.org/">Bliss</a> v11.13 (Nov 2020)</li> </ul> <p>This didn’t go so well, it seems sometimes laptop touchpad clicks registered and sometimes they didn’t. It couldn’t decide what it wanted to use for a Home app, and I got a lot of force closes. Playing Monument Valley was very laggy and registered some clicks half a minute after making them. I think this was Android 8 or 9.</p> <ul> <li><a href="https://www.primeos.in/">PrimeOS</a> 2.13 (July 2022)</li> </ul> <p>This worked a lot better! Games played smoothly, even 3D games like Riptide GP Renegade. It even comes with a keymapper to help play games, though it seems to be full of ads. I could also install all the usual things like Firefox and Termux so was quite at home. This is based on Android 11. It even has what it calls a “bridge” which allows execution of Arm games on x86 somehow. If I want to try Android games on the computer I’ll give this a go again.</p> Sat, 07 Jan 2023 00:00:00 +0000 https://superjamie.github.io/2023/01/07/distro-surfing-2022-part-2 https://superjamie.github.io/2023/01/07/distro-surfing-2022-part-2 Small JSON libraries in C <p>I wanted a serialisation and parsing library to create and load savegames in plain C. Considering <a href="https://cataclysmdda.org/">Cataclysm: Dark Days Ahead</a> uses JSON, I figured that was good enough for me. Now to find a library.</p> <p>A large list of libraries is available at the <a href="https://github.com/miloyip/nativejson-benchmark">Native JSON Benchmark</a> repository. This also lists scores of some standards conformance tests, and offers some comparative performance numbers of speed and memory usage.</p> <p>I’m aware of <a href="https://github.com/akheron/jansson">Jansson</a> and <a href="https://github.com/json-c/json-c">json-c</a>, however these are large shared libraries made up of many individual files. I am looking for something with one or two files that I can compile right into my project.</p> <p>My first try was <a href="https://github.com/kgabis/parson">Parson</a> but the API was very confusing to me, and I couldn’t understand how to build arrays of integer values. There’s even <a href="https://stackoverflow.com/questions/49957648/how-to-construct-json-array-with-parson">an answer on StackOverflow</a> which didn’t enlighten me. No go there.</p> <p>Next I looked at <a href="https://github.com/DaveGamble/cJSON">cJSON</a> which is nice and well documented. I particularly like the single data type used for all objects, the memory ownership model, and the fact you can still change an object after you’ve added it to something. This leads to a good coding pattern like:</p> <ul> <li>allocate root object</li> <li>allocate branch object</li> <li>add branch object to root</li> <li>add data to branch object</li> </ul> <p>Then if any step fails, you can jump to a failure case which frees the root object, and frees any branches and data you’ve added.</p> <p>However, I wasn’t a huge fan of the mixed-case coding style and the 64% standards conformance score didn’t inspire confidence, so I kept looking.</p> <p>I then tried <a href="https://github.com/json-parser/json-builder">json-builder</a> and its accompanying <a href="https://github.com/json-parser/json-parser">json-parser</a>, which ended up being exactly what I’m after.</p> <p>It has a very similar structure to cJSON, with a single data type <code class="language-plaintext highlighter-rouge">json_value</code> and same memory model.</p> <p>Despite having almost no documentation, the API is very concise and the examples given are simple enough to understand it.</p> <p>It also uses all <code class="language-plaintext highlighter-rouge">snake_case</code> and underscores, so appears to me visually.</p> <p>An example of the above coding pattern in <code class="language-plaintext highlighter-rouge">json-builder</code> is:</p> <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define ARRAY_SIZE 4 </span><span class="kt">char</span> <span class="o">*</span><span class="nf">json_output</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span> <span class="cm">/* data to serialise */</span> <span class="kt">int</span> <span class="n">my_array</span><span class="p">[</span><span class="n">ARRAY_SIZE</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span> <span class="p">};</span> <span class="cm">/* create root object which will contain all other data */</span> <span class="n">json_value</span> <span class="o">*</span><span class="n">root_obj</span> <span class="o">=</span> <span class="n">json_object_new</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">root_obj</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> <span class="cm">/* create an array, and if that works, instantly attach to the root */</span> <span class="n">json_value</span> <span class="o">*</span><span class="n">array_branch</span> <span class="o">=</span> <span class="n">json_array_new</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">array_branch</span><span class="p">)</span> <span class="k">goto</span> <span class="n">out</span><span class="p">;</span> <span class="n">json_object_push</span><span class="p">(</span><span class="n">root_obj</span><span class="p">,</span> <span class="s">"array"</span><span class="p">,</span> <span class="n">array_branch</span><span class="p">);</span> <span class="cm">/* walk the array, appending values */</span> <span class="k">for</span> <span class="p">(</span><span class="kt">size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">ARRAY_SIZE</span> <span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="n">json_value</span> <span class="o">*</span><span class="n">array_int</span> <span class="o">=</span> <span class="n">json_integer_new</span><span class="p">(</span><span class="n">my_array</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">array_int</span><span class="p">)</span> <span class="k">goto</span> <span class="n">out</span><span class="p">;</span> <span class="n">json_array_push</span><span class="p">(</span><span class="n">array_branch</span><span class="p">,</span> <span class="n">array_int</span><span class="p">);</span> <span class="p">}</span> <span class="cm">/* serialise */</span> <span class="kt">char</span> <span class="o">*</span><span class="n">buffer</span> <span class="o">=</span> <span class="n">calloc</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">json_measure</span><span class="p">(</span><span class="n">root_obj</span><span class="p">));</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">buffer</span><span class="p">)</span> <span class="k">goto</span> <span class="n">out</span><span class="p">;</span> <span class="n">json_serialize</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="n">root_obj</span><span class="p">);</span> <span class="cm">/* clean up and exit in the success case */</span> <span class="n">json_builder_free</span><span class="p">(</span><span class="n">root_obj</span><span class="p">);</span> <span class="k">return</span> <span class="n">buffer</span><span class="p">;</span> <span class="nl">out:</span> <span class="cm">/* any time we land here, the root object owns all the data, so * we can clean up with this one call to free the root object */</span> <span class="n">json_builder_free</span><span class="p">(</span><span class="n">root_obj</span><span class="p">);</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <p>This gives us a nice JSON object containing a named array:</p> <div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span> <span class="dl">"</span><span class="s2">array</span><span class="dl">"</span><span class="p">:</span> <span class="p">[</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span> <span class="p">]</span> <span class="p">}</span> </code></pre></div></div> <p>If you’re unfamiliar with this exit style with <code class="language-plaintext highlighter-rouge">goto</code>, it’s quite common in the Linux kernel and other similar system software. I don’t know if there’s a name for this but I call them “goto trees”. More at:</p> <ul> <li><a href="https://www.kernel.org/doc/html/latest/process/coding-style.html#centralized-exiting-of-functions">Centralized exiting of functions - Linux kernel coding style</a></li> <li><a href="https://blog.regehr.org/archives/894">Use of Goto in Systems Code - John Regehr</a></li> </ul> <p>Anyway, I’m very happy with this, I will use <code class="language-plaintext highlighter-rouge">json-builder</code> and <code class="language-plaintext highlighter-rouge">json-parser</code>.</p> Thu, 05 Jan 2023 00:00:00 +0000 https://superjamie.github.io/2023/01/05/small-json-libraries-in-c https://superjamie.github.io/2023/01/05/small-json-libraries-in-c Distro Surfing 2022 <p><em>Update: I also have a <a href="/2023/01/07/distro-surfing-2022-part-2">Part 2</a></em></p> <p>I have a preferred desktop setup with <a href="https://mate-desktop.org/">MATE</a>, but I like to go distro surfing every so often to look at what other desktop environments have to offer, know what’s out there, and maybe get some new ideas.</p> <p>Here’s what I looked at recently, in no particular order:</p> <h2 id="cinnamon">Cinnamon</h2> <ul> <li>Cinnamon 5.6.5 in Linux Mint 21.1</li> </ul> <p>Really good! I could configure everything I wanted. All the keyboard shortcuts I’m used to (except Super+Space). Could turn off lots of animations and thumbnails and desktop and other cruft. This is honestly probably a better desktop environment than MATE, even if it does use <a href="https://itvision.altervista.org/linux-desktop-environments-system-usage.html">a little bit more RAM</a>. I’d happily use Mint and Cinnamon right now. I would need to figure out how to write a <a href="https://github.com/superjamie/onepx">one pixel window border</a>.</p> <p><strong>Rating: 5 stars!</strong></p> <h2 id="xfce">XFCE</h2> <ul> <li>XFCE v4.16 in Linux Mint 21.1</li> </ul> <p>Unusable. Inconsistent theming with dark settings, some windows appear with dark borders, some appear with light borders. Strange to have two places to configure keyboard shortcuts (Keyboard settings, Window Manager settings). Some key presses and mouse clicks visually register but don’t actually do anything. Trying again works. Most importantly, after removing some default shortcut, the panel took over Super and broke my whole workflow. A broken disappointment.</p> <p><strong>Rating: 0 stars</strong></p> <h2 id="gnome">GNOME</h2> <ul> <li>GNOME 42.2 in Ubuntu 22.04</li> <li>GNOME 42.5 in Pop OS 22.04</li> </ul> <p>I dislike the mouse-dependent “activities” flyover paradigm this is going for, it’s like it’s trying to copy the Mac desktop without actually understanding the ideas behind the environment. No way to disable desktop icons. No way to center windows. Keyboard settings are very tedious, requiring an extra click to set <em>every</em> setting. Some button text overrides its borders. Big ugly top window borders that waste so much space. Side dock taking up unnecessary space, though it can be covered by windows. Top panel taking up more space for minimal functionality, and I dislike top panels as they’re an ergonomic anti-pattern. The irony of having “privacy” options which default to the bad settings. I’d be very unhappy if I had to use this.</p> <p><strong>Rating: 0 stars</strong></p> <h2 id="pantheon">Pantheon</h2> <ul> <li>elementary 6.1</li> </ul> <p>Does the whole “activities” thing like Mac too. Copies Mac in some unintuitive ways (eg: similarly useless top bar like GNOME) but doesn’t box you into its own ideas so much. Not a fan of the default terminal, which has transparency and no way to change the colour theme. “Code” editor has Vim emulation but no way to tell what mode you’re in. “Web” browser based on Epiphany is limited but supports Firefox Sync. Overall not my preference, would take a lot of configuration and extra apps, still probably stuck with big top window borders and top panel. Better than GNOME and maybe the path of least resistance to get Mac users onto Linux.</p> <p><strong>Rating: 2 stars</strong></p> <h2 id="lxqt">LXQt</h2> <ul> <li>LXQt 0.17.0 in Lubuntu 22.04</li> </ul> <p>Like going back in time 15 years. Janky unmatched theming, basic inferior apps, Openbox window manager. Needs dark widget theme, better text editor, better terminal. If I used this I’d be configuring Openbox manually with the text file like I did in 2009 and be using apps from other DEs. At least it is minimal and gets out of the way. Viable with a lot of effort but not optimal.</p> <p><strong>Rating: 1 star</strong></p> <h2 id="budgie">Budgie</h2> <ul> <li>Ubuntu Budgie 22.10</li> </ul> <p>I had read this was a whole new DE, but it’s obviously just GNOME with very minor changes. No thanks.</p> <p><strong>Rating: 0 stars</strong></p> <h2 id="kde">KDE</h2> <ul> <li>KDE Plasma 5.20 in Kubuntu 22.04</li> </ul> <p>Very surprising! I’d always heard how this was a very polished and modern environment, but it actually felt very “old Linux” with lots of settings everywhere. So many settings that it’s a little overwhelming at times. There are some animations and other heavy cruft which appear to be all configurable. Kate editor looks intersting, many options including Vim mode, Git, and even LSP support! Quite powerful how you can configure toolbars for each application. Nice to see all the apps don’t start with K anymore like they used to in KDE3.</p> <p>I can see why people love KDE, they’ve invested a lot of time learning it (so feel that same self-taught pride like driving a car) and setting it up just how they want. The developers obviously respect the users and try to make it all things to all people, and they appear to have largely succeeded. Not my primary choice but I think I could grow to enjoy it.</p> <p>I like the idea of binding <code class="language-plaintext highlighter-rouge">Win+.</code> to an emoji/unicode selector, I will steal that.</p> <p><strong>Rating: 3 stars</strong></p> <h2 id="bonus-ventoy">Bonus: Ventoy</h2> <ul> <li><a href="https://www.ventoy.net/">https://www.ventoy.net/</a></li> </ul> <p>Not a desktop environment, but a shoutout to this great USB drive booloader. It lets you copy ISOs to a USB drive and boot from them with a menu. Much easier than <code class="language-plaintext highlighter-rouge">dd</code>‘ing every image individually.</p> Sat, 24 Dec 2022 00:00:00 +0000 https://superjamie.github.io/2022/12/24/distro-surfing-2022 https://superjamie.github.io/2022/12/24/distro-surfing-2022 A small story about premature optimisation <p>There’s that saying in software “Premature optimisation is the root of all evil”, popularised by <a href="https://en.wikipedia.org/wiki/Donald_Knuth">Donald Knuth</a> and which some say can be attributed to <a href="https://en.wikipedia.org/wiki/Tony_Hoare">Tony Hoare</a>. The full quote from Knuth’s paper <a href="https://dl.acm.org/doi/10.1145/356635.356640">Structured Programming with go to Statements</a> reads:</p> <blockquote> <p>There is no doubt that the grail of efficiency leads to abuse. Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We <em>should</em> forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.</p> </blockquote> <p>For a little roguelike tile engine I’m writing, I wanted to do a character lookup from Unicode to <a href="https://en.wikipedia.org/wiki/Code_page_437">Codepage 437</a>. The canonical reference is seen in <a href="https://github.com/Journeyman-dev/cp437.h/blob/main/include/cp437.h">cp437.h</a> and the same lookup table is <a href="https://github.com/libtcod/libtcod/blob/main/src/libtcod/tileset.h">in libtcod</a> too.</p> <p>Going the other way is easy, from Codepage 437 to Unicode, simply use the character code to look up the array.</p> <p>For example, the second character is the smiley face, so we pick <code class="language-plaintext highlighter-rouge">TABLE[1]</code> and get <code class="language-plaintext highlighter-rouge">0x263A</code> which sure enough is Unicode ☺. What a nice O(1) algorithm.</p> <p>But what if we want to do the reverse lookup?</p> <p>The most naive way is just scan the table from start to end, but that becomes an O(n) algorithm, and especially bad if I’m looking up the later characters like line drawing or the second-to-last “black square” ■.</p> <p>A co-worker and I did some bike-shedding about this and thought of several ways to improve it, but when I went to implement it I just did the dumb worst algorithm to get it done.</p> <p>I measured the performance of drawing random Codepage 437 characters to the screen and got about 315 frames per second.</p> <p>I then performed the same test drawing a random unicode character and causing the lookup to happen for every character and got… about 315 frames per second.</p> <p>So, at least for now, this part of my program is not the bottleneck and doesn’t need further optimisation.</p> <p><small>(the utility of measuring frames per second in a turn-based game engine is an exercise left to the reader)</small></p> Thu, 15 Dec 2022 00:00:00 +0000 https://superjamie.github.io/2022/12/15/premature-optimisation https://superjamie.github.io/2022/12/15/premature-optimisation Light mode is actually quite scary <p>The dark-mode vs light-mode discussion <a href="https://news.ycombinator.com/item?id=33947820">popped up on Hacker News again</a> so I wanted to summarise all I cound find about it.</p> <p>In chronological order:</p> <ul> <li><a href="https://www.sciencedirect.com/science/article/abs/pii/0003687084900607">An overview of standards and guidelines for visual display terminals</a> (Sept 1984)</li> </ul> <p>Suggests that contrast ratio over 20:1 is associated with user eye fatigute, and dark-mode displays are associated with “higher comfort” and “higher user acceptance”. Also discusses many other points like green-screen vs orange-screen, keyboard height, etc.</p> <ul> <li><a href="https://doi.org/10.1080/00140139.2014.948496">Smaller pupil size and better proofreading performance with positive than with negative polarity displays</a> (Sept 2013)</li> </ul> <p>“Positive polarity” (light mode) results in better proofreading performance.</p> <ul> <li><a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6020759/">Digital eye strain: prevalence, measurement and amelioration</a> (April 2018)</li> </ul> <p>Digital eye strain (DES) is most likely associated with not blinking for long periods, too-small fonts, or undiagnosed eye defects (astigmatism). Blue light might be a factor.</p> <ul> <li><a href="https://www.nature.com/articles/s41598-018-28904-x">Reading and Myopia: Contrast Polarity Matters</a> (July 2018)</li> </ul> <p><strong>Prolonged exposure to black-on-white (light mode) thins the choroid which is associated with myopia, while white-on-black (dark mode) thickens the choroid which inhibits myopia.</strong></p> <ul> <li><a href="https://www.sciencedaily.com/releases/2019/12/191216173654.htm">Blue light may not be as disruptive to our sleep patterns as originally thought</a></li> </ul> <p>Blue light might not be so bad, bright yellow light produced poor sleep patterns <code class="language-plaintext highlighter-rouge">#inmice</code>. Suggests dim cool colours in evening, bright warm colours in the day.</p> <ul> <li><a href="https://www.nngroup.com/articles/dark-mode/">Dark Mode vs. Light Mode: Which Is Better? - NN Group</a> (Feb 2020)</li> </ul> <p>Light mode is better for small cognitive tasks, but the effect decreases with age. People with cloudy vision defects might perform better with light mode. Cites the “Reading and Myopia” paper above.</p> <ul> <li><a href="https://stitcher.io/blog/why-light-themes-are-better-according-to-science">Which colour scheme is better? - Brent from Stitcher</a> (Sept 2020)</li> </ul> <p>Coding with a dark theme adds measurable milliseconds of cognitive delay. Etienne Grandjean’s “Ergonomic Aspects of Visual Display Terminals” (1980) [<a href="https://www.semanticscholar.org/paper/Ergonomic-aspects-of-visual-display-terminals-Grandjean-Vigliani/fdfb8d1c430a7bb75c19f29b1dcf1da8add15746">1</a>, <a href="https://www.semanticscholar.org/paper/Ergonomic-Aspects-of-Visual-Display-Terminals%3A-of-Grandjean-Vigliani/568f00581cd402d7821bc3b9773af7e72891a5a7">2</a>, <a href="https://www.amazon.com.au/Ergonomic-Aspects-Visual-Display-Terminals/dp/0850662117">3</a>, <a href="https://dl.acm.org/doi/book/10.5555/578434">4</a>] determined that it’s easier to proofread dark text on light background (light mode). I wish there was a copy of this paper online.</p> <ul> <li><a href="https://kevquirk.com/is-dark-mode-such-a-good-idea/">https://kevquirk.com/is-dark-mode-such-a-good-idea/</a> (2020)</li> </ul> <p>Cites the NN Group page about light mode performance increase. Cites a <a href="https://www.vice.com/en/article/ywyqxw/apple-dark-mode-eye-strain-battery-life">2019 Vice article</a> which cites the “Digital eye strain” study. Dark mode doesn’t save battery unless it’s true <code class="language-plaintext highlighter-rouge">#000</code> black on OLED screen. Users should be given flexibility to choose. Somehow comes to the conclusion that dark mode damages eyes?</p> <ul> <li><a href="https://medium.com/codesphere-cloud/should-you-really-be-coding-in-dark-mode-1c34c7cf5f99">https://medium.com/codesphere-cloud/should-you-really-be-coding-in-dark-mode-1c34c7cf5f99</a> (June 2021)</li> </ul> <p>Cites the “Smaller pupil size” paper. Cites the “Blue light” study and says that screen use altogether before bed isn’t great. True-black-on-OLED power usage again. Users should be given flexibility to choose.</p> <hr /> <p>I actually started this post intending to write about accepting Brent from Stitcher’s challenge and try light mode for a week with the following:</p> <ul> <li>Terminal: <a href="https://github.com/solarized/xresources/blob/master/Xresources.light">https://github.com/solarized/xresources/blob/master/Xresources.light</a></li> <li>Vim: <a href="https://github.com/altercation/vim-colors-solarized">https://github.com/altercation/vim-colors-solarized</a> with <code class="language-plaintext highlighter-rouge">background=light</code></li> <li>Firefox: <a href="https://addons.mozilla.org/en-US/firefox/addon/zen-fox/">https://addons.mozilla.org/en-US/firefox/addon/zen-fox/</a></li> <li>GTK: <a href="https://github.com/Ferdi265/numix-solarized-gtk-theme">https://github.com/Ferdi265/numix-solarized-gtk-theme</a></li> </ul> <p>However, having sorted through the above, two major points stand out to me:</p> <h3 id="risk-of-myopia-increases-with-light-mode">Risk of myopia increases with light mode</h3> <p>Use of dark mode also builds resilience <em>against</em> myopia.</p> <p>This is the most important to me.</p> <p>My eyesight is fairly perfect and I’d like to keep it that way.</p> <h3 id="cognitive-advantage-of-light-mode-is-unsure">Cognitive advantage of light mode is unsure</h3> <p>Whilst there is a repeatable cognitive advantage of light mode:</p> <ul> <li>It decreases with age after 20s.</li> </ul> <p>I’m older than that now, so any cognitive advantage seems irrelevant to me.</p> <ul> <li>All research seems to be on instantaneous “glancing” cognition, like reading a sign, or proofreading of small passages.</li> </ul> <p>I don’t see research specifically to exposure for 8+ hours a day and to the cognition of knowledge work like programming and problem-solving.</p> <p>Even if it makes me work a little slower, saving my eyes is more important so that I can continue to be productive into the future.</p> <h2 id="summary">Summary</h2> <p>With that, I’m switching back to dark mode.</p> Tue, 13 Dec 2022 00:00:00 +0000 https://superjamie.github.io/2022/12/13/light-mode-is-actually-quite-scary https://superjamie.github.io/2022/12/13/light-mode-is-actually-quite-scary Swap CSS stylesheet with JavaScript <p>I wanted a button to toggle between a light and dark stylesheet for my <a href="https://github.com/superjamie/emdee">dynamic Markdown renderer</a>.</p> <p>This proved to be a lot more difficult than I expected.</p> <p>The code to achieve this is:</p> <div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;html&gt;</span> <span class="nt">&lt;head&gt;</span> <span class="nt">&lt;link</span> <span class="na">id=</span><span class="s">"sheet_light"</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">type=</span><span class="s">"text/css"</span> <span class="na">href=</span><span class="s">"light.css"</span> <span class="nt">/&gt;</span> <span class="nt">&lt;link</span> <span class="na">id=</span><span class="s">"sheet_dark"</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">type=</span><span class="s">"text/css"</span> <span class="na">href=</span><span class="s">"dark.css"</span> <span class="na">disabled</span><span class="nt">/&gt;</span> <span class="nt">&lt;script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">&gt;</span> <span class="kd">function</span> <span class="nx">swap</span><span class="p">()</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">sheet_dark</span><span class="dl">"</span><span class="p">).</span><span class="nx">disabled</span> <span class="o">==</span> <span class="kc">true</span><span class="p">)</span> <span class="p">{</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">sheet_dark</span><span class="dl">"</span><span class="p">).</span><span class="nx">removeAttribute</span><span class="p">(</span><span class="dl">'</span><span class="s1">disabled</span><span class="dl">'</span><span class="p">);</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">sheet_light</span><span class="dl">"</span><span class="p">).</span><span class="nx">disabled</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">sheet_light</span><span class="dl">"</span><span class="p">).</span><span class="nx">removeAttribute</span><span class="p">(</span><span class="dl">'</span><span class="s1">disabled</span><span class="dl">'</span><span class="p">);</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">sheet_dark</span><span class="dl">"</span><span class="p">).</span><span class="nx">disabled</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span> <span class="p">}</span> <span class="p">}</span> <span class="nt">&lt;/script&gt;</span> <span class="nt">&lt;/head&gt;</span> <span class="nt">&lt;body&gt;</span> <span class="nt">&lt;button</span> <span class="na">id=</span><span class="s">"sheet_button"</span> <span class="na">onclick=</span><span class="s">"swap();"</span><span class="nt">&gt;</span><span class="ni">&amp;#x1F4A1;</span><span class="nt">&lt;/button&gt;</span> <span class="nt">&lt;/body&gt;</span> <span class="nt">&lt;/html&gt;</span> </code></pre></div></div> <p>A few notes on the implementation:</p> <p>There are other solutions around which suggest to modify the <code class="language-plaintext highlighter-rouge">href</code> attribute of the link, however this causes a momentary “flicker” the first time the style is swapped, as the browser loads the new stylesheet. This flicker occurred every time I swapped the sheet in Chromium, but not in Firefox.</p> <p>Using the <a href="https://www.w3schools.com/jsref/prop_link_disabled.asp">disabled property of the link object</a> avoids this, because the browser loads both stylesheets on page load. Switching between the sheets by toggling the <code class="language-plaintext highlighter-rouge">disabled</code> property switches between already-loaded stylesheets and avoids the flicker.</p> <p>Just toggling <code class="language-plaintext highlighter-rouge">disabled</code> to true/false did work for me, but I found several answers on StackOverflow which say it’s better to remove the propertly altogether with <code class="language-plaintext highlighter-rouge">.removeAttribute()</code>.</p> <p>Unrelated to this implementation but very annoying to figure out, <code class="language-plaintext highlighter-rouge">document.getElementById("whatever").href</code> and <code class="language-plaintext highlighter-rouge">document.getElementById("whatever").getAttribute("href")</code> are <strong>not</strong> the same thing. The former is the full URL including the <code class="language-plaintext highlighter-rouge">http://</code> onwards, but the attribute is just the file’s basename. I only discovered this by using the JavaScript console in Firefox.</p> <p>Hopefully this pops up in someone’s search results and saves them the hours it took me to figure this out.</p> Tue, 06 Dec 2022 00:00:00 +0000 https://superjamie.github.io/2022/12/06/swap-stylesheet-with-javascript https://superjamie.github.io/2022/12/06/swap-stylesheet-with-javascript Hacker News Solarized Dark Nice theme for Stylus Sun, 20 Nov 2022 00:00:00 +0000 https://superjamie.github.io/2022/11/20/hacker-news-solarized-dark-nice-theme-for-stylus https://superjamie.github.io/2022/11/20/hacker-news-solarized-dark-nice-theme-for-stylus How to do SDL 2D Fullscreen and Scaling <p>While tinkering with roguelike development, I ended up writing my own 2D tile engine in SDL. It takes a <a href="https://dwarffortresswiki.org/Tileset_repository">Dwarf Fortress Tileset</a> of <a href="https://en.wikipedia.org/wiki/Code_page_437">Codepage 437</a> symbols, and allows you to create a window on a modern graphical OS which behaves like a DOS text window.</p> <p>If you’ve done any roguelike dev before this will sound familiar to you, and you probably know that <a href="https://invisible-island.net/ncurses/">ncurses</a>/<a href="https://pdcurses.org/">PDCurses</a> do this in the terminal, and at least one of the better grahical alternatives:</p> <ul> <li><a href="https://github.com/libtcod/libtcod">libtcod</a></li> <li><a href="http://foo.wyrd.name/en:bearlibterminal">BearLibTerminal</a></li> <li><a href="https://github.com/tommyettinger/TinyCurses">TinyCurses</a></li> </ul> <p>A DOS-sized window of 80x25 characters with the <a href="https://dwarffortresswiki.org/index.php/File:EGA8x14.png">EGA 8x14</a> or <a href="https://dwarffortresswiki.org/index.php/File:VGA8x16.png">VGA 8x16</a> font ends up quite small on a modern high-res screen, so you’ll want to scale this up.</p> <p>Scaling up pixel graphics like this always looks bad at arbitrary scaling sizes, so you’ll want to scale by integer factors (eg: 2x or 3x, but not 2.5x or 1.333x).</p> <p>When you set your SDL window fullscreen with <a href="https://wiki.libsdl.org/SDL_SetWindowFullscreen"><code class="language-plaintext highlighter-rouge">SDL_SetWindowFullscreen(SDL_WINDOW_FULLSCREEN_DESKTOP)</code></a> you’ll want to restrict scaling to the largest sensible size for the display, and center the display so it draws in the middle of the screen.</p> <p>I had done all this manually, multiplying my <code class="language-plaintext highlighter-rouge">SDL_RenderFillRect</code> by a scaling factor, working out my content size and how large the client window was so I could center the content, etc. I actually hadn’t done that last part about maximum scale factor for a fullscreen viewport and wasn’t exactly sure of the best way to do it.</p> <p>Turns out I’d been doing things the hard way. <a href="https://github.com/HexDecimal">HexDecimal</a> (author of libtcod) recently informed me of two incredibly useful SDL functions:</p> <ul> <li><a href="https://wiki.libsdl.org/SDL_RenderSetLogicalSize"><code class="language-plaintext highlighter-rouge">SDL_RenderSetLogicalSize</code></a></li> <li><a href="https://wiki.libsdl.org/SDL_RenderSetIntegerScale"><code class="language-plaintext highlighter-rouge">SDL_RenderSetIntegerScale</code></a></li> </ul> <p>Work out your content width/height and provide it to <code class="language-plaintext highlighter-rouge">SDL_RenderSetLogicalSize</code>, enable integer scaling with <code class="language-plaintext highlighter-rouge">SDL_RenderSetIntegerScale</code>. Now when you go fullscreen, the content is automatically scaled to the largest possible integer scaling factor for the content/screen, and is automatically centered in the fullscreen viewport.</p> <p>I also discovered:</p> <ul> <li><a href="https://wiki.libsdl.org/SDL_RenderSetScale"><code class="language-plaintext highlighter-rouge">SDL_RenderSetScale</code></a></li> </ul> <p>When the window is <strong>not</strong> fullscreen, this will do scaling for you, though you still have to work out the correct window size and resize with <a href="https://wiki.libsdl.org/SDL_SetWindowSize"><code class="language-plaintext highlighter-rouge">SDL_SetWindowSize</code></a>.</p> <p>Be sure to disallow <code class="language-plaintext highlighter-rouge">SDL_RenderSetScale</code> when the window is fullscreen, otherwise SDL gets confused.</p> <p>This allowed me to rip out several lines of my own code and maths, leverage the library, and end up with a superior result.</p> <p>Hopefully it helps you too!</p> <p>Many thanks to HexDecimal and the positive helpful sharing nature of the entire <a href="https://www.reddit.com/r/roguelikedev/">roguelike development</a> community.</p> Sun, 06 Nov 2022 00:00:00 +0000 https://superjamie.github.io/2022/11/06/sdl-fullscreen-scaling https://superjamie.github.io/2022/11/06/sdl-fullscreen-scaling C Static Analysis Tools - Part 2 <p>Earlier in the year I wrote about <a href="/2022/05/24/c-static-analysis-tools">static analysis tools for C</a> and wanted to cover a couple more.</p> <p>Let’s continue with our simple array-out-of-bounds test from the last post:</p> <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span> <span class="kt">int</span> <span class="n">my_array</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">0</span> <span class="p">};</span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">6</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="n">my_array</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <h2 id="gcc-static-analysis">GCC Static Analysis</h2> <p>Red Hat’s David Malcolm has been busy adding a static analyser to GCC with the <code class="language-plaintext highlighter-rouge">-fanalyzer</code> switch, covered in Red Hat Developer blog posts:</p> <ul> <li><a href="https://developers.redhat.com/articles/2022/04/12/state-static-analysis-gcc-12-compiler">https://developers.redhat.com/articles/2022/04/12/state-static-analysis-gcc-12-compiler</a></li> <li><a href="https://developers.redhat.com/blog/2021/01/28/static-analysis-updates-in-gcc-11">https://developers.redhat.com/blog/2021/01/28/static-analysis-updates-in-gcc-11</a></li> <li><a href="https://developers.redhat.com/blog/2020/03/26/static-analysis-in-gcc-10">https://developers.redhat.com/blog/2020/03/26/static-analysis-in-gcc-10</a></li> </ul> <p>Unfortunately I couldn’t get it to find an error on the above code, neither with GCC-11 in Ubuntu 22.04, nor with Compiler Explorer’s current “static analysis” or “trunk” versions of GCC (which appear to be daily builds).</p> <p>I emailed David and <a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107566">logged by bug with GCC</a> for this.</p> <p>Turns out Compiler Explorer’s <strong>gcc (static analysis)</strong> branch was almost 3 years out of date, <a href="https://github.com/compiler-explorer/compiler-explorer/issues/4256">logged an Issue</a> to fix that too.</p> <h2 id="pvs-studio">PVS-Studio</h2> <p>I came across this commercial static analyzer from a series of blog posts about writing good code:</p> <ul> <li><a href="https://pvs-studio.com/en/blog/posts/cpp/0391/">2016 - The Ultimate Question of Programming, Refactoring, and Everything</a></li> <li><a href="https://pvs-studio.com/en/blog/posts/cpp/a0070/">2011 - How to make fewer errors at the stage of code writing. Part N1</a></li> <li><a href="https://pvs-studio.com/en/blog/posts/cpp/a0072/">2011 - How to make fewer errors at the stage of code writing. Part N2</a></li> </ul> <p>Usually commercial products like this are inaccessible to us mere mortals, and I expect a paid license of this runs into at least 4 figures per seat. They <a href="https://pvs-studio.com/en/order/single-user/">don’t even offer single licenses</a>, only commercial volume.</p> <p>However, they provide a <a href="https://pvs-studio.com/en/blog/posts/0614/">free license</a> to students, open source projects, and even non-commercial personal projects. Very nice!</p> <p>It’s also available via <a href="https://godbolt.org/">Compiler Explorer</a> as a plugin. In the compiler window just go <strong>Add Tool</strong> and <strong>PVS-Studio</strong>.</p> <p>This is awesome, and a good way to get your product in front of people who’ll later use it in industry, where companies are more willing pay for it.</p> <p>From the above blog posts you can see that PVS-Studio catches lots of things that other static analyzers don’t, and it picks up our incorrect access too:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>The documentation for all analyzer warnings is available here: https://pvs-studio.com/en/docs/warnings/. &lt;source&gt;:6:1: warning: V557 Array overrun is possible. The value of 'i' index could reach 5. </code></pre></div></div> <p>Not as friendly as <code class="language-plaintext highlighter-rouge">cppcheck</code> was in the last post, but does the job.</p> Fri, 04 Nov 2022 00:00:00 +0000 https://superjamie.github.io/2022/11/04/c-static-analysis-tools-part-2 https://superjamie.github.io/2022/11/04/c-static-analysis-tools-part-2 How to ncursesw (as of 2022) <p>Roguelike authors might be interested in using Unicode in curses, particularly for drawing <a href="https://en.wikipedia.org/wiki/Code_page_437">Codepage 437</a> symbols in modern OSes, or just to get “beautiful” characters like <a href="https://sites.google.com/site/broguegame/">Brogue</a>.</p> <p>This post is more-or-less an updated version of this howto page from 2014:</p> <ul> <li><a href="http://dillingers.com/blog/2014/08/10/ncursesw-and-unicode/">http://dillingers.com/blog/2014/08/10/ncursesw-and-unicode/</a></li> </ul> <p>This page explains the new API well with some function cheatsheet too:</p> <ul> <li><a href="https://reversed.top/2019-02-05/more-than-256-curses-color-pairs/">https://reversed.top/2019-02-05/more-than-256-curses-color-pairs/</a></li> </ul> <p>Journeyman on Discord has written a small header to make CP437 symbols easier in C:</p> <ul> <li><a href="https://github.com/Journeyman-dev/cp437.h">https://github.com/Journeyman-dev/cp437.h</a></li> </ul> <h2 id="prerequisites">Prerequisites</h2> <p>This assumes you have the following:</p> <ul> <li>A terminal which supports Unicode - <code class="language-plaintext highlighter-rouge">mate-terminal</code> and <code class="language-plaintext highlighter-rouge">guake</code> do for me</li> <li>A font with Unicode ligatures - <a href="https://int10h.org/oldschool-pc-fonts/fontlist/?1#ibm-g2">PxPlus IBM VGA 8x16</a> does for me</li> <li>Know how to type Unicode symbols on your system. On Linux I do: <ul> <li>MATE desktop: <strong>Ctrl+Shift</strong> and hold them, <strong>u</strong> and release it, type <strong>hex code</strong>, release all keys</li> <li>vim Insert Mode: <strong>Ctrl+v</strong> and release it, <strong>u</strong> and release it, type <strong>hex code</strong></li> </ul> </li> <li>The ncurses and ncursesw library package, development package, documentation package. On Ubuntu 22.04 this is at least: <code class="language-plaintext highlighter-rouge">libncurses6 libncursesw6 libncurses-dev ncurses-doc</code></li> </ul> <h2 id="man-ncurses">man ncurses</h2> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>There are two common configurations of the library: ncursesw the so-called "wide" library, which handles multibyte characters (see the section on ALTERNATE CONFIGURATIONS). The "wide" library includes all of the calls from the "normal" library. It adds about one third more calls using data types which store multibyte characters: cchar_t corresponds to chtype. However it is a structure, because more data is stored than can fit into an integer. The characters are large enough to require a full integer value - and there may be more than one character per cell. The video attributes and color are stored in separate fields of the structure. Each cell (row and column) in a WINDOW is stored as a cchar_t. The setcchar(3X) and getcchar(3X) functions store and retrieve the data from a cchar_t structure. wchar_t stores a “wide” character. Like chtype, this may be an integer. wint_t stores a wchar_t or WEOF - not the same, though both may have the same size. The "wide" library provides new functions which are analogous to functions in the "normal" library. There is a naming convention which relates many of the normal/wide variants: a "_w" is inserted into the name. For example, waddch becomes wadd_wch. </code></pre></div></div> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ALTERNATE CONFIGURATIONS --enable-widec The configure script renames the library and (if the --disable-overwrite option is used) puts the header files in a different subdirectory. All of the library names have a "w" appended to them, i.e., instead of -lncurses you link with -lncursesw You must also enable the wide-character features in the header file when compiling for the wide-character library to use the extended (wide-character) functions. The symbol which enables these features has changed since XSI Curses, Issue 4: * Originally, the wide-character feature required the symbol _XOPEN_SOURCE_EXTENDED but that was only valid for XPG4 (1996). * Later, that was deemed conflicting with _XOPEN_SOURCE defined to 500. * As of mid-2018, none of the features in this implementation require a _XOPEN_SOURCE feature greater than 600. However, X/Open Curses, Issue 7 (2009) recommends defining it to 700. * Alternatively, you can enable the feature by defining NCURSES_WIDECHAR with the caveat that some other header file than curses.h may require a specific value for _XOPEN_SOURCE (or a system-specific symbol). The curses.h file which is installed for the wide-character library is designed to be compatible with the normal library's header. Only the size of the WINDOW structure differs, and very few applications require more than a pointer to WINDOWs. If the headers are installed allowing overwrite, the wide-character library's headers should be installed last, to allow applications to be built using either library from the same set of headers. </code></pre></div></div> <h2 id="headers">Headers</h2> <p>Before <em>any</em> library includes in <em>all</em> your files, even if not using ncurses in those files, define:</p> <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define _XOPEN_SOURCE_EXTENDED </span></code></pre></div></div> <p>If you are including <code class="language-plaintext highlighter-rouge">&lt;stdarg.h&gt;</code> to get variadics, you must include that before including ncurses.</p> <p>Aside: you should be including system libraries (like <code class="language-plaintext highlighter-rouge">stdarg</code>) before external libraries (like <code class="language-plaintext highlighter-rouge">ncursesw</code>) anyway, see <a href="https://google.github.io/styleguide/cppguide.html#Names_and_Order_of_Includes">https://google.github.io/styleguide/cppguide.html#Names_and_Order_of_Includes</a>:</p> <blockquote> <p>Include headers in the following order: Related header, C system headers, C++ standard library headers, other libraries’ headers, your project’s headers.</p> </blockquote> <p>Finally, to include ncurses with wide support, do not use the regular <code class="language-plaintext highlighter-rouge">#include &lt;curses.h&gt;</code>, instead you need to:</p> <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;ncursesw/curses.h&gt;</span><span class="cp"> </span></code></pre></div></div> <h2 id="compilation">Compilation</h2> <p>When linking, ensure your linker is picking up the wide version of the library with:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>-lncursesw </code></pre></div></div> <p>I presume if you are using other curses helpers like panels, they still go first, eg:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>-lpanel -lncursesw </code></pre></div></div> <p>but I haven’t tested this yet.</p> <h2 id="locale---system">Locale - System</h2> <p>Check your locale in the terminal with:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>locale <span class="nv">LANG</span><span class="o">=</span>en_AU.UTF-8 <span class="nv">LANGUAGE</span><span class="o">=</span>en_AU:en <span class="nv">LC_CTYPE</span><span class="o">=</span><span class="s2">"en_AU.UTF-8"</span> ... </code></pre></div></div> <p>On Ubuntu, you can change what locales to generate interactively with:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>dpkg-reconfigure locales </code></pre></div></div> <p>Or uncomment locales of interest in here:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">grep</span> <span class="nt">-E</span> <span class="s2">"^[^#]"</span> /etc/locale.gen en_AU.UTF-8 UTF-8 en_US.UTF-8 UTF-8 </code></pre></div></div> <p>Then either of these commands probably work:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dpkg-reconfigure <span class="nt">--frontend</span> noninteractive locales <span class="nb">sudo </span>locale-gen </code></pre></div></div> <p>I suggest to always generate <code class="language-plaintext highlighter-rouge">en_US.UTF-8</code> even if it’s not your primary locale, because most systems probably have the US locale (which have not intentionally excluded English altogether).</p> <h2 id="locale---program-code">Locale - Program Code</h2> <p>The default locale <code class="language-plaintext highlighter-rouge">C</code> does not support wide characters by default. Set your program’s locale before starting curses with:</p> <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;locale.h&gt;</span><span class="cp"> #include</span> <span class="cpf">&lt;ncursesw/curses.h&gt;</span><span class="cp"> </span> <span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span> <span class="n">setlocale</span><span class="p">(</span><span class="n">LC_ALL</span><span class="p">,</span> <span class="s">"en_US.UTF-8"</span><span class="p">);</span> <span class="n">initscr</span><span class="p">();</span> </code></pre></div></div> <p>If your curses program prints escape codes like <code class="language-plaintext highlighter-rouge">^@</code> instead of Unicode, you haven’t got locales working right.</p> <h2 id="using-wide-characters">Using Wide Characters</h2> <p>To get the wide character type <code class="language-plaintext highlighter-rouge">wchar_t</code>:</p> <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;stddef.h&gt;</span><span class="cp"> </span></code></pre></div></div> <p>A <code class="language-plaintext highlighter-rouge">wchar_t</code> literal is a “long” character or string qualified by <code class="language-plaintext highlighter-rouge">L</code>, so:</p> <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">wchar_t</span> <span class="n">my_wide_character</span> <span class="o">=</span> <span class="sc">L'a'</span><span class="p">;</span> <span class="kt">wchar_t</span> <span class="n">my_wide_string</span><span class="p">[]</span> <span class="o">=</span> <span class="s">L"Hello"</span><span class="p">;</span> <span class="kt">wchar_t</span> <span class="n">my_hammer_and_sickle_unicode</span> <span class="o">=</span> <span class="sc">L'☭'</span> <span class="kt">wchar_t</span> <span class="n">my_hammer_and_sickle_codepoint</span> <span class="o">=</span> <span class="n">L</span><span class="err">'\</span><span class="n">x262d</span><span class="err">'</span> <span class="c1">// ☭ </span> </code></pre></div></div> <p>Long string literals are null-terminated with the long null character: <code class="language-plaintext highlighter-rouge">L'\0'</code></p> <p>ncursesw also supports its own “complex character type” <code class="language-plaintext highlighter-rouge">cchar_t</code> which includes a character and attributes like bold, colorpair, etc. You can pack its contents and attributes with <code class="language-plaintext highlighter-rouge">setcchar()</code>, which takes arguments of:</p> <ul> <li>Pointer to <code class="language-plaintext highlighter-rouge">cchar_t</code> to pack</li> <li>Pointer to wide character string, terminated with wide null <code class="language-plaintext highlighter-rouge">L\0</code></li> <li>ncurses wide attributes starting <code class="language-plaintext highlighter-rouge">WA_*</code></li> <li><code class="language-plaintext highlighter-rouge">short</code> color pair</li> <li><code class="language-plaintext highlighter-rouge">options</code> not used here (it’s for when you need more than <code class="language-plaintext highlighter-rouge">SHRT_MAX</code> colorpairs)</li> </ul> <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">cchar_t</span> <span class="n">my_cchar</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">0</span> <span class="p">};</span> <span class="n">setcchar</span><span class="p">(</span><span class="o">&amp;</span><span class="n">my_cchar</span><span class="p">,</span> <span class="s">L"☭"</span><span class="p">,</span> <span class="n">WA_NORMAL</span><span class="p">,</span> <span class="n">colorpair</span><span class="p">(</span><span class="n">C_RED</span><span class="p">,</span> <span class="n">C_BLK</span><span class="p">),</span> <span class="nb">NULL</span><span class="p">);</span> <span class="n">mvadd_wch</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">my_cchar</span><span class="p">);</span> <span class="n">refresh</span><span class="p">();</span> <span class="kt">wint_t</span> <span class="n">keypress</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">0</span> <span class="p">};</span> <span class="kt">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="n">get_wch</span><span class="p">(</span><span class="o">&amp;</span><span class="n">keypress</span><span class="p">);</span> </code></pre></div></div> <h2 id="functions---ncurses">Functions - ncurses</h2> <p>Change to using all wide character and new API functions, don’t use any of the old functions anymore.</p> <p>Set attributes with <code class="language-plaintext highlighter-rouge">wattr_set()</code>. Use new API version of the attribute macros, like changing <code class="language-plaintext highlighter-rouge">A_BOLD</code> to <code class="language-plaintext highlighter-rouge">WA_BOLD</code>.</p> <p>Get input characters with <code class="language-plaintext highlighter-rouge">get_wch()</code>. Note the return value is a status - <code class="language-plaintext highlighter-rouge">OK</code> for wide character, <code class="language-plaintext highlighter-rouge">KEY_CODE_YES</code> for function key, <code class="language-plaintext highlighter-rouge">ERR</code> for error. The actual keypressed is placed into the <code class="language-plaintext highlighter-rouge">*wch</code> parameter you provide to the function. This is different to the old <code class="language-plaintext highlighter-rouge">getch()</code> which returns the key pressed.</p> <p>I don’t see the use of packing entire strings full of complex characters (<code class="language-plaintext highlighter-rouge">cchar_t</code>), so for strings, use <code class="language-plaintext highlighter-rouge">wchar_t</code> and long strings and place with <code class="language-plaintext highlighter-rouge">mvaddwstr()</code> or <code class="language-plaintext highlighter-rouge">mvwaddwstr()</code>.</p> <p>For single characters, you can pack a <code class="language-plaintext highlighter-rouge">cchar_t</code> with <code class="language-plaintext highlighter-rouge">setcchar()</code> and place it with <code class="language-plaintext highlighter-rouge">mvadd_wch()</code> or <code class="language-plaintext highlighter-rouge">mvwadd_wch()</code>.</p> <p>However you can also skip using <code class="language-plaintext highlighter-rouge">cchar_t</code> altogether and write single long characters (eg: <code class="language-plaintext highlighter-rouge">L"@"</code>) with the long string functions.</p> <p>A complete list of wide curses functions is in the source like:</p> <ul> <li><a href="https://github.com/mirror/ncurses/blob/master/include/curses.wide">https://github.com/mirror/ncurses/blob/master/include/curses.wide</a></li> </ul> <h2 id="functions---wide-strings">Functions - Wide Strings</h2> <p>To use wide string functions you must <code class="language-plaintext highlighter-rouge">#include &lt;wchar.h&gt;</code>. Some references:</p> <ul> <li><a href="https://en.wikibooks.org/wiki/C_Programming/wchar.h">C Programming Wikibook - wchar.h</a></li> <li><a href="https://en.wikipedia.org/wiki/C_string_handling">C Programming Wikibook - String Handling</a></li> <li><a href="https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/wchar.h.html">POSIX 2018 - wchar.h</a></li> </ul> <p>A few replacement functions are:</p> <table> <thead> <tr> <th>Purpose</th> <th>Old</th> <th>New</th> </tr> </thead> <tbody> <tr> <td>string length</td> <td><code class="language-plaintext highlighter-rouge">strlen()</code></td> <td><code class="language-plaintext highlighter-rouge">wcslen()</code></td> </tr> <tr> <td>string n length</td> <td><code class="language-plaintext highlighter-rouge">strnlen()</code></td> <td><code class="language-plaintext highlighter-rouge">wcsnlen()</code></td> </tr> <tr> <td>string width</td> <td>N/A</td> <td><code class="language-plaintext highlighter-rouge">wcswidth()</code></td> </tr> <tr> <td>string compare</td> <td><code class="language-plaintext highlighter-rouge">strcmp()</code></td> <td><code class="language-plaintext highlighter-rouge">wcscmp()</code></td> </tr> <tr> <td>string n compare</td> <td><code class="language-plaintext highlighter-rouge">strncmp()</code></td> <td><code class="language-plaintext highlighter-rouge">wcsncmp()</code></td> </tr> <tr> <td>string copy</td> <td><code class="language-plaintext highlighter-rouge">strcpy()</code></td> <td><code class="language-plaintext highlighter-rouge">wcscpy()</code></td> </tr> <tr> <td>string n copy</td> <td><code class="language-plaintext highlighter-rouge">strncpy()</code></td> <td><code class="language-plaintext highlighter-rouge">wcpncpy()</code></td> </tr> <tr> <td>memory set</td> <td><code class="language-plaintext highlighter-rouge">memset()</code></td> <td><code class="language-plaintext highlighter-rouge">wmemset()</code></td> </tr> <tr> <td>string to long int</td> <td><code class="language-plaintext highlighter-rouge">strtol()</code></td> <td><code class="language-plaintext highlighter-rouge">wcstol()</code></td> </tr> <tr> <td>string to double</td> <td><code class="language-plaintext highlighter-rouge">strtod()</code></td> <td><code class="language-plaintext highlighter-rouge">wcstod()</code></td> </tr> </tbody> </table> <ul> <li>Convert old <code class="language-plaintext highlighter-rouge">char</code> strings to <code class="language-plaintext highlighter-rouge">wchar_t</code> with <code class="language-plaintext highlighter-rouge">mbstowcs()</code> “multibyte string to wide-character string” from <code class="language-plaintext highlighter-rouge">&lt;stdlib.h&gt;</code>, or <code class="language-plaintext highlighter-rouge">swprintf</code> with <code class="language-plaintext highlighter-rouge">%hs</code> <a href="https://stackoverflow.com/questions/4826189/convert-char-to-wchar-in-c">reference</a></li> <li>Note file I/O functions like <code class="language-plaintext highlighter-rouge">fgetws()</code>, <code class="language-plaintext highlighter-rouge">fputws()</code>, <code class="language-plaintext highlighter-rouge">fwprintf()</code>, <code class="language-plaintext highlighter-rouge">swprintf()</code>, etc</li> </ul> <h2 id="a-complete-example">A Complete Example</h2> <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define _XOPEN_SOURCE_EXTENDED </span> <span class="cm">/* gcc -o ncwtest -std=c99 -Wall -Wextra -Wpedantic main.c -lncursesw */</span> <span class="cp">#define SCREEN_X 80 #define SCREEN_Y 24 </span> <span class="cp">#include</span> <span class="cpf">&lt;inttypes.h&gt;</span><span class="cp"> #include</span> <span class="cpf">&lt;locale.h&gt;</span><span class="cp"> #include</span> <span class="cpf">&lt;stdbool.h&gt;</span><span class="cp"> #include</span> <span class="cpf">&lt;stddef.h&gt;</span><span class="cp"> #include</span> <span class="cpf">&lt;stdint.h&gt;</span><span class="cp"> #include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"> #include</span> <span class="cpf">&lt;unistd.h&gt;</span><span class="cp"> </span> <span class="cp">#include</span> <span class="cpf">&lt;ncursesw/curses.h&gt;</span><span class="cp"> </span> <span class="cm">/** * Get the value of our custom curses color pair. * * @param fg Foreground color using one of the COLOR_ macros * @param bg Background color using one of the COLOR_ macros * @return Curses color pair to use with COLOR_PAIR() */</span> <span class="k">static</span> <span class="kt">short</span> <span class="nf">colorpair</span><span class="p">(</span><span class="kt">short</span> <span class="n">fg</span><span class="p">,</span> <span class="kt">short</span> <span class="n">bg</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// the original 16 colorpairs should not be modified</span> <span class="k">return</span> <span class="mi">16</span> <span class="o">+</span> <span class="n">fg</span> <span class="o">+</span> <span class="p">(</span><span class="n">bg</span> <span class="o">*</span> <span class="mi">8</span><span class="p">);</span> <span class="p">}</span> <span class="kt">void</span> <span class="nf">curses_on</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span> <span class="n">initscr</span><span class="p">();</span> <span class="k">if</span> <span class="p">(</span><span class="n">has_colors</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">can_change_color</span><span class="p">())</span> <span class="p">{</span> <span class="n">start_color</span><span class="p">();</span> <span class="k">for</span> <span class="p">(</span><span class="kt">short</span> <span class="n">bg</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">bg</span> <span class="o">&lt;</span> <span class="mi">8</span><span class="p">;</span> <span class="n">bg</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="k">for</span> <span class="p">(</span><span class="kt">short</span> <span class="n">fg</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">fg</span> <span class="o">&lt;</span> <span class="mi">8</span><span class="p">;</span> <span class="n">fg</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="kt">short</span> <span class="n">pair</span> <span class="o">=</span> <span class="n">colorpair</span><span class="p">(</span><span class="n">fg</span><span class="p">,</span> <span class="n">bg</span><span class="p">);</span> <span class="n">init_pair</span><span class="p">(</span><span class="n">pair</span><span class="p">,</span> <span class="n">fg</span><span class="p">,</span> <span class="n">bg</span><span class="p">);</span> <span class="p">}</span> <span class="p">}</span> <span class="p">}</span> <span class="n">cbreak</span><span class="p">();</span> <span class="n">noecho</span><span class="p">();</span> <span class="n">keypad</span><span class="p">(</span><span class="n">stdscr</span><span class="p">,</span> <span class="n">TRUE</span><span class="p">);</span> <span class="n">curs_set</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="p">}</span> <span class="kt">void</span> <span class="nf">curses_off</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span> <span class="n">erase</span><span class="p">();</span> <span class="n">refresh</span><span class="p">();</span> <span class="n">endwin</span><span class="p">();</span> <span class="p">}</span> <span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span> <span class="n">setlocale</span><span class="p">(</span><span class="n">LC_ALL</span><span class="p">,</span> <span class="s">"en_US.UTF-8"</span><span class="p">);</span> <span class="n">curses_on</span><span class="p">();</span> <span class="c1">//wchar_t my_sym[] = { L'\x262d', L'\0' }; // ☭</span> <span class="n">cchar_t</span> <span class="n">my_cchar</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">0</span> <span class="p">};</span> <span class="n">attr_t</span> <span class="n">my_attrs</span> <span class="o">=</span> <span class="n">WA_NORMAL</span><span class="p">;</span> <span class="n">setcchar</span><span class="p">(</span><span class="o">&amp;</span><span class="n">my_cchar</span><span class="p">,</span> <span class="s">L"☭"</span><span class="p">,</span> <span class="n">my_attrs</span><span class="p">,</span> <span class="n">colorpair</span><span class="p">(</span><span class="n">COLOR_RED</span><span class="p">,</span> <span class="n">COLOR_BLACK</span><span class="p">),</span> <span class="nb">NULL</span><span class="p">);</span> <span class="n">mvadd_wch</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">my_cchar</span><span class="p">);</span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">y</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">y</span> <span class="o">&lt;</span> <span class="p">(</span><span class="n">SCREEN_Y</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="n">y</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="p">(</span><span class="n">SCREEN_X</span> <span class="o">-</span> <span class="mi">2</span><span class="p">);</span> <span class="n">x</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="n">mvadd_wch</span><span class="p">(</span><span class="n">y</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">my_cchar</span><span class="p">);</span> <span class="p">}</span> <span class="p">}</span> <span class="n">refresh</span><span class="p">();</span> <span class="kt">wint_t</span> <span class="n">keypress</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">0</span> <span class="p">};</span> <span class="kt">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="n">get_wch</span><span class="p">(</span><span class="o">&amp;</span><span class="n">keypress</span><span class="p">);</span> <span class="n">curses_off</span><span class="p">();</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <h2 id="history">History</h2> <ul> <li>v1.0 - 2022-08-06 - Initial commit</li> <li>v1.1 - 2022-09-26 - Added wide char stuff, made some header bits clearer</li> <li>v1.2 - 2022-09-27 - Clarified text more, simplified standalone example</li> <li>v1.3 - 2022-10-04 - Wide character function table, added some more common functions</li> </ul> Sat, 06 Aug 2022 00:00:00 +0000 https://superjamie.github.io/2022/08/06/ncursesw https://superjamie.github.io/2022/08/06/ncursesw C Static Analysis Tools <p><a href="https://en.wikipedia.org/wiki/Static_program_analysis">Static analysis</a> of computer programs can be simply defined as automated inspection of the source code to find programming errors. These might be very obvious errors that human code inspection or software testing would probably have caught, but also less visible coding errors which are hard for humans to find and might even compile and run okay.</p> <p>For example, this code has an obvious array out-of-bound error. This array has three members starting at zero, so we cannot access member three or four or five:</p> <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span> <span class="kt">int</span> <span class="n">my_array</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">0</span> <span class="p">};</span> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">6</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="n">my_array</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <p>It will even compile without complaint:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>gcc array-out-of-bounds.c <span class="nt">-o</span> array-out-of-bounds <span class="nv">$ </span><span class="nb">echo</span> <span class="nv">$?</span> 0 </code></pre></div></div> <p>Though running it (correctly) produces an abort:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>./array-out-of-bounds <span class="k">***</span> stack smashing detected <span class="k">***</span>: terminated Aborted <span class="o">(</span>core dumped<span class="o">)</span> </code></pre></div></div> <p>The <a href="https://stackoverflow.com/questions/1145191/static-code-analyzers-for-c">top Stack Overflow answer</a> about static analysis tools lists PC-Lint and <a href="https://splint.org/">Splint</a> as the top answers.</p> <p>PC-Lint is proprietary and expensive (~US$400 per license, over a decade ago) so inaccessible to me.</p> <p>Splint is open source, but development seems inactive with the last commit over 3 years ago and I couldn’t get it running anyway.</p> <p>What other options do we have?</p> <h2 id="gcc-compiler-warnings">GCC Compiler Warnings</h2> <p>One way we could have detected this was better GCC warnings, which performs a sort of static analysis:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>gcc <span class="nt">-Wall</span> array-out-of-bounds.c <span class="nt">-o</span> array-out-of-bounds array-out-of-bounds.c: In <span class="k">function</span> ‘main’: array-out-of-bounds.c:3:13: warning: variable ‘my_array’ <span class="nb">set </span>but not used <span class="o">[</span><span class="nt">-Wunused-but-set-variable</span><span class="o">]</span> 3 | int my_array[3] <span class="o">=</span> <span class="o">{</span> 0 <span class="o">}</span><span class="p">;</span> | ^~~~~~~~ </code></pre></div></div> <p>However, that’s just telling me I haven’t used the variable I defined, not about the actual programming error.</p> <p>My preference for GCC compiler flags is:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>-std=c99 -Wall -Werror -Wpedantic </code></pre></div></div> <p>(considering <a href="https://www.phoronix.com/scan.php?page=news_item&amp;px=Linux-Kernel-C89-To-C11">the Linux Kernel has updated to C11</a>, maybe I should too!)</p> <p>You can also add <code class="language-plaintext highlighter-rouge">-Werror</code> if you wish any warnings to be considered as errors and stop compilation.</p> <h2 id="cppcheck">cppcheck</h2> <p><a href="http://cppcheck.net/">http://cppcheck.net/</a></p> <p>cppcheck is a static analysis tool for both C and C++ which is actively developed and has packages and plugins for many environments.</p> <p>On Ubuntu, install with <code class="language-plaintext highlighter-rouge">sudo apt install cppcheck</code></p> <p>Using it is very easy, just run it with your source file as an argument:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>cppcheck array-out-of-bounds.c Checking array-out-of-bounds.c ... array-out-of-bounds.c:6:11: error: Array <span class="s1">'my_array[3]'</span> accessed at index 5, which is out of bounds. <span class="o">[</span>arrayIndexOutOfBounds] my_array[i] <span class="o">=</span> i<span class="p">;</span> ^ array-out-of-bounds.c:5:19: note: Assuming that condition <span class="s1">'i&lt;6'</span> is not redundant <span class="k">for</span><span class="o">(</span>int i <span class="o">=</span> 0<span class="p">;</span> i &lt; 6<span class="p">;</span> i++<span class="o">)</span> ^ array-out-of-bounds.c:6:11: note: Array index out of bounds my_array[i] <span class="o">=</span> i<span class="p">;</span> ^ </code></pre></div></div> <p>That’s found our problem and explained it nicely.</p> <p>There are other arguments, I like to enable all checks, but suppress <code class="language-plaintext highlighter-rouge">missingIncludeSystem</code> so that it doesn’t check system library includes.</p> <p>I add this to my <code class="language-plaintext highlighter-rouge">Makefile</code> template like so:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.PHONY: check check: $(SRCS) cppcheck --enable=all --std=c99 --suppress=missingIncludeSystem $^ </code></pre></div></div> <p>Now I can run <code class="language-plaintext highlighter-rouge">make check</code> and get this output.</p> <h2 id="clang-static-analysis">Clang Static Analysis</h2> <p><a href="https://clang-analyzer.llvm.org/">https://clang-analyzer.llvm.org/</a></p> <p>The Clang compiler frontend also has a static analysis tool.</p> <p>On Ubuntu, install with <code class="language-plaintext highlighter-rouge">sudo apt install clang-tools</code></p> <p>This works by running <code class="language-plaintext highlighter-rouge">scan-build</code> in front of your usual compilation command.</p> <p>We can run it like:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ scan-build gcc array-out-of-bounds.c -o array-out-of-bounds scan-build: Using '/usr/lib/llvm-14/bin/clang' for static analysis scan-build: Analysis run complete. scan-build: Removing directory '/tmp/scan-build-2022-05-24-103834-26933-1' because it contains no reports. scan-build: No bugs found. </code></pre></div></div> <p>Oh dear, no bugs found. That’s unfortunate. I logged <a href="https://github.com/llvm/llvm-project/issues/55668">an Issue</a> with the LLVM project.</p> <p>This has found other errors for me in the past on larger projects, so don’t take this as any suggestion that the Clang Analyzer sucks or doesn’t work. As the webpage says, it’s still a work in progress.</p> <p>One particularly nice feature is how <code class="language-plaintext highlighter-rouge">scan-build</code> works. It uses the shell environment variables <code class="language-plaintext highlighter-rouge">CC</code> and <code class="language-plaintext highlighter-rouge">CXX</code> to override the compiler with its own tool. This supports <code class="language-plaintext highlighter-rouge">gcc</code>, <code class="language-plaintext highlighter-rouge">g++</code>, and even <code class="language-plaintext highlighter-rouge">make</code>.</p> <p>So an existing project with a <code class="language-plaintext highlighter-rouge">Makefile</code> has nothing to do to add Clang static analysis, simply run the usual command:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>scan-build make </code></pre></div></div> <h2 id="summary">Summary</h2> <p>Static analysis tools are another tool in the toolbox that developers should use to ensure their code is free of errors.</p> <p>As we have found, not every tool is perfect and some things will pick up warnings or errors that others don’t.</p> <p>So it’s a good idea to add as many checks to your code as you reasonably can, both compiler warnings and static analyzers.</p> <h2 id="part-2">Part 2</h2> <ul> <li><a href="/2022/11/04/c-static-analysis-tools-part-2">C Static Analysis Tools - Part 2</a></li> </ul> Tue, 24 May 2022 00:00:00 +0000 https://superjamie.github.io/2022/05/24/c-static-analysis-tools https://superjamie.github.io/2022/05/24/c-static-analysis-tools Raspberry Pi OS (Raspbian) Bash PS1 Prompt Explained <p>The bash shell has variable <code class="language-plaintext highlighter-rouge">PS1</code> which controls how the prompt is displayed.</p> <p>You can find many examples of how to customise the prompt: <a href="https://duckduckgo.com/?q=Bash+PS1">https://duckduckgo.com/?q=Bash+PS1</a></p> <p>For a long time I have kept this <code class="language-plaintext highlighter-rouge">PS1</code> around from Raspbian, but today I wondered what everything actually did:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">PS1</span><span class="o">=</span><span class="s2">"</span><span class="se">\[\0</span><span class="s2">33]0;</span><span class="se">\u</span><span class="s2">@</span><span class="se">\h</span><span class="s2">: </span><span class="se">\w\0</span><span class="s2">07</span><span class="se">\]\[\e</span><span class="s2">[1;32m</span><span class="se">\]\h\[\e</span><span class="s2">[1;32m</span><span class="se">\]</span><span class="s2">:</span><span class="se">\[\e</span><span class="s2">[1;34m</span><span class="se">\]\w</span><span class="s2"> </span><span class="se">\[\e</span><span class="s2">[0m</span><span class="se">\]\\</span><span class="nv">$ </span><span class="s2">"</span> </code></pre></div></div> <p>You can just paste this into bash to see what it looks like. It will show something like this, with your computer’s name as <code class="language-plaintext highlighter-rouge">hostname</code> and your cursor blinking at <code class="language-plaintext highlighter-rouge">_</code>:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">hostname</span>:~ <span class="nv">$ </span>_ </code></pre></div></div> <p>If you change to a directory, then that directory name is added to the prompt, eg:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">hostname</span>:~ <span class="nv">$ </span><span class="nb">cd </span>Downloads <span class="nb">hostname</span>:~/Downloads <span class="nv">$ </span>_ </code></pre></div></div> <p>I started looking into this, and the first part of it baffled me:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">PS1</span><span class="o">=</span><span class="s2">"</span><span class="se">\[\0</span><span class="s2">33]0;</span><span class="se">\u</span><span class="s2">@</span><span class="se">\h</span><span class="s2">: </span><span class="se">\w\0</span><span class="s2">07</span><span class="se">\]</span><span class="s2"> </span></code></pre></div></div> <p>So I skipped that for now and focused on the rest, I already knew what these did:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="se">\[\e</span><span class="o">[</span>1<span class="p">;</span>32m<span class="se">\]\h\[\e</span><span class="o">[</span>1<span class="p">;</span>32m<span class="se">\]</span>:<span class="se">\[\e</span><span class="o">[</span>1<span class="p">;</span>34m<span class="se">\]\w</span> <span class="se">\[\e</span><span class="o">[</span>0m<span class="se">\]\\</span><span class="nv">$ </span> </code></pre></div></div> <p>The bash colours are explained better by others (with actual colour) at pages such as:</p> <ul> <li><a href="https://www.shellhacks.com/bash-colors/">https://www.shellhacks.com/bash-colors/</a></li> <li><a href="https://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html">https://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html</a></li> <li>or just search around for “bash colors” or “ansi colors”</li> </ul> <p>They are explained as:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>\[ start non-printing characters \e[1;32m bold green \] end non-printing characters \h hostname \[ start non-printing characters \e[1;32m set text color to bold/bright green \] end non-printing characters : literal colon character ":" \[ start non-printing characters \e[1;34m set text color to bold/bright blue \] end non-printing characters \w current working directory, with home abbreviated as ~ _ a literal space character " " \[ start non-printing characters \e[0m reset text to no color \] end non-printing characters \\$ </code></pre></div></div> <p>And the last line creates the prompt. If effective UID is 0 (eg: you’ve done <code class="language-plaintext highlighter-rouge">sudo -s</code> to open a root shell) then it becomes <code class="language-plaintext highlighter-rouge">#</code>, otherwise if you’re a non-root user then it is <code class="language-plaintext highlighter-rouge">$</code>.</p> <p>Now, back to the first part:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">PS1</span><span class="o">=</span><span class="s2">"</span><span class="se">\[\0</span><span class="s2">33]0;</span><span class="se">\u</span><span class="s2">@</span><span class="se">\h</span><span class="s2">: </span><span class="se">\w\0</span><span class="s2">07</span><span class="se">\]</span><span class="s2"> </span></code></pre></div></div> <p>We can already spot some of these, such as <code class="language-plaintext highlighter-rouge">\]</code> and <code class="language-plaintext highlighter-rouge">\]</code> to delimit non-printing characters, <code class="language-plaintext highlighter-rouge">\w</code> for the current working directory with <code class="language-plaintext highlighter-rouge">~</code> for home, and I happen to know <code class="language-plaintext highlighter-rouge">\u@\h</code> shows <code class="language-plaintext highlighter-rouge">username@hostname</code>. But what are the rest?</p> <p>The answer is hidden <a href="https://askubuntu.com/a/832382/704762">over here on the Ask Ubuntu StackExchange site</a>.</p> <p>The <code class="language-plaintext highlighter-rouge">\033]</code> is an Octal character named <code class="language-plaintext highlighter-rouge">ESC</code>, and the <code class="language-plaintext highlighter-rouge">]</code> after it means an “Operating System Command” or OSC.</p> <p>We can see in the <a href="https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Operating-System-Commands">xterm Control Sequence manual</a> that <code class="language-plaintext highlighter-rouge">0;</code> means “Set Text Parameters” and “Change Icon Name and Window Title”. The <code class="language-plaintext highlighter-rouge">username@hostname: cwd</code> now makes sense, that’s the graphical terminal window’s title text!</p> <p>The <code class="language-plaintext highlighter-rouge">\007</code> is an ASCII BEL character, which is used to end the OSC.</p> <p>So looking at it again:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">PS1</span><span class="o">=</span><span class="s2">"</span><span class="se">\[\0</span><span class="s2">33]0;</span><span class="se">\u</span><span class="s2">@</span><span class="se">\h</span><span class="s2">: </span><span class="se">\w\0</span><span class="s2">07</span><span class="se">\]</span><span class="s2"> </span></code></pre></div></div> <p>We can explain this as:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> \[ begin a sequence of non-printing characters \033 octal 033 "Esc" ] OSC 0; change icon and window name to: \u@\h username@hostname : a literal colon and space ": " \w working directory, with home abbreviated as ~ \007 octal 007 terminal bell, end the OSC \] end non-printing characters </code></pre></div></div> <p>The answer I linked on Ask Ubuntu isn’t the most upvoted answer, but it is the correct answer.</p> <p>Looking at the author of the answer, it shouldn’t come as a surprise that it’s the correct answer.</p> <p>It’s written by <a href="https://invisible-island.net/">Thomas Dickey</a>, a long-time open source software developer, and maintainer of many low-level pieces of software such as <code class="language-plaintext highlighter-rouge">ncurses</code> and <code class="language-plaintext highlighter-rouge">xterm</code> itself!</p> Mon, 24 Jan 2022 00:00:00 +0000 https://superjamie.github.io/2022/01/24/raspberry-pi-os-raspbian-bash-ps1-prompt-explained https://superjamie.github.io/2022/01/24/raspberry-pi-os-raspbian-bash-ps1-prompt-explained How to install Ubuntu with LUKS Encryption on LVM Thu, 25 Nov 2021 00:00:00 +0000 https://superjamie.github.io/2021/11/25/install-ubuntu-luks-lvm https://superjamie.github.io/2021/11/25/install-ubuntu-luks-lvm Delay Loop in 6502 Assembly <p>The Android app <a href="https://play.google.com/store/apps/details?id=com.redlee90.learn6502assembly">Learn 6502 Assembly</a> provides a reasonably good 6502 CPU emulator and debugger, integrated with an Android text editor and a small game-console-like interface (memory-mapped graphics, d-pad, A and B).</p> <p>The emulator seems to be the one from <a href="http://skilldrick.github.io/easy6502/">Easy 6502</a>.</p> <p>It provides several example programs, but at least the “game-like” programs run way too fast to be pratical on my modern phone.</p> <p>So let’s make a delay. We’ll do this by counting from 0 to 65535 (a 16-bit variable).</p> <p>Within the game loop, you can call subroutine <code class="language-plaintext highlighter-rouge">JSR delay</code></p> <pre><code class="language-asm">delay: ; save state. we'll be using the A register, so save it off to RAM ; and restore it before leaving. use another address if needed STA $40 ; zero the A register ready for our use LDA #$00 ; store that zero off to RAM too. registers only hold 8-bits so ; we'll store the high byte of our number off to RAM STA $41 ; high byte delayloop: ADC #01 ; usually adding 1 into A won't set the Zero bit. when the reigster ; overflows and the value of A becomes #$00, the Zero flag will be ; set. BNE jumps when the Z bit is not set BNE delayloop ; so we only land here after we've counted past #$FF ; clear carry flag so we don't add it next ADC CLC INC $41 ; same strategy is used here, we jump unless the INC overflowed ; back to zero BNE delayloop ; clear carry flag so we don't add it next ADC CLC ; exit ; restore state of the A register LDA $40 RTS ~~~ Or without comments: ~~~ delay: STA $40 ; save state LDA #$00 STA $41 ; high byte delayloop: ADC #01 BNE delayloop CLC INC $41 BNE delayloop CLC ; exit LDA $40 ; restore state RTS </code></pre> <p>Thanks Revenant for the catch where I missed <code class="language-plaintext highlighter-rouge">CLC</code>.</p> Tue, 14 Jan 2020 00:00:00 +0000 https://superjamie.github.io/2020/01/14/delay-loop-in-6502-assembly https://superjamie.github.io/2020/01/14/delay-loop-in-6502-assembly Reversing for Dummies <p>Notes for a talk given at <a href="https://www.meetup.com/SecTalks-Brisbane/">Brisbane SecTalks</a>.</p> <hr /> <p>Jamie Bainbridge - <a href="http://jbainbri.github.io/">http://jbainbri.github.io/</a></p> <h2 id="why">Why?</h2> <p>To understand how a program works.</p> <ul> <li>Break copy protection</li> <li>Commercial/military espionage</li> <li>Security analysis</li> <li>Understand a segfault/panic/bug and fix/patch it</li> <li>Add features</li> <li>Re-implementation in another language or create a clone</li> </ul> <h2 id="what">What?</h2> <ul> <li>OS-specific instructions to link and execute a program</li> <li>Several binary <strong>formats</strong> <ul> <li>MS-DOS: <code class="language-plaintext highlighter-rouge">COM</code> and <code class="language-plaintext highlighter-rouge">MZ</code></li> <li>Win16: <code class="language-plaintext highlighter-rouge">NE</code></li> <li>Win32/Win64: <code class="language-plaintext highlighter-rouge">PE</code></li> <li>System V ABI: <code class="language-plaintext highlighter-rouge">ELF</code> - we’ll be talking about this one</li> </ul> </li> <li>ELF binaries are made up of <strong>sections</strong> (each section links to one or more <strong>segments</strong>)</li> <li>Common section headers: <ul> <li><code class="language-plaintext highlighter-rouge">.text</code> for executable code</li> <li><code class="language-plaintext highlighter-rouge">.data</code> for initialized data</li> <li><code class="language-plaintext highlighter-rouge">.rodata</code> for read-only initialized data</li> <li><code class="language-plaintext highlighter-rouge">.bss</code> for uninitialized data, will be blank</li> <li><code class="language-plaintext highlighter-rouge">.plt</code> for the linker to link in library functions</li> </ul> </li> <li>Within a code section we’ll usually have <strong>symbol names</strong></li> </ul> <h2 id="how">How?</h2> <h4 id="non-assembly-tools">Non-assembly Tools</h4> <ul> <li><code class="language-plaintext highlighter-rouge">strings</code> finds ASCII text within the file</li> <li><code class="language-plaintext highlighter-rouge">file</code> gives a basic fie type and some info</li> <li><code class="language-plaintext highlighter-rouge">readelf</code> and <code class="language-plaintext highlighter-rouge">nm</code> to read more stuff</li> </ul> <h4 id="decompilers">Decompilers</h4> <p>These disassemble a binary then try to make source code back out of it. Original variable names are not preserved, nor are inlined functions, modern optimising compilers might make this a very confusing mess. May work ok for very simple programs, probably impractical with anything serious.</p> <h4 id="disassemblers">Disassemblers</h4> <p><code class="language-plaintext highlighter-rouge">objdump</code>, <code class="language-plaintext highlighter-rouge">dasm2.pl</code>, <code class="language-plaintext highlighter-rouge">ndisasm</code>, radare2, IDA Pro, Hopper. These present binary in assembly code, sometimes with niceties like showing offsets and strings. radare has a scriptable API, IDA has a GUI!</p> <h4 id="debuggers">Debuggers</h4> <p><code class="language-plaintext highlighter-rouge">gdb</code>, WinDbg, OllyDbg, IDEs like Visual Studio or Eclipse. Allow you to load an executable, watch/step live execution, stop execution with <strong>breakpoints</strong>, view/edit registers, stack frames, other memory contents.</p> <h3 id="assembly">Assembly</h3> <p>A processor understands <strong>machine language</strong> or <strong>machine code</strong>, these are binary instructions which are loaded into the CPU and executed each clock cycle.</p> <p>A <strong>compiler</strong> takes source code, <strong>assembles</strong> it into machine language object files, and a <strong>linker</strong> creates a binary out of your various assembled files and the libraries you used.</p> <p>Assembly language is a human-readable representation of binary machine code instructions, assembly translates directly into machine code.</p> <p>A CPU is made up of <strong>registers</strong> which can store a word-width of data (8-bit, 16-bit, 32-bit, 64-bit, etc), and has some way to access system memory.</p> <p>The actual instructions are concerned with:</p> <ul> <li><code class="language-plaintext highlighter-rouge">MOV</code> - moving data around registers</li> <li><code class="language-plaintext highlighter-rouge">SUB</code>, <code class="language-plaintext highlighter-rouge">ADD</code> - doing mathematical operations on register contents</li> <li><code class="language-plaintext highlighter-rouge">CMP</code> - comparing values</li> <li><code class="language-plaintext highlighter-rouge">JMP</code>, <code class="language-plaintext highlighter-rouge">CALL</code> - moving to other parts of the program</li> <li>or doing so conditionally: <ul> <li><code class="language-plaintext highlighter-rouge">JE</code> - <strong>j</strong>ump if the last comparison was <strong>e</strong>qual</li> <li><code class="language-plaintext highlighter-rouge">JNE</code> - <strong>j</strong>ump if the last comparison was <strong>n</strong>ot <strong>e</strong>qual)</li> </ul> </li> <li><code class="language-plaintext highlighter-rouge">NOP</code> - doing nothing</li> </ul> <p>Each instruction mnemonic translates directly into hex.</p> <ul> <li>Reference for x86 assembly instructions: <a href="http://ref.x86asm.net/">http://ref.x86asm.net/</a></li> <li>This is a 32-bit binary so we’ll want: <a href="http://ref.x86asm.net/coder32.html">http://ref.x86asm.net/coder32.html</a></li> </ul> <h4 id="syntax">Syntax</h4> <p>There are two common syntaxes for asm, <strong>AT&amp;T</strong> syntax and <strong>Intel</strong> syntax.</p> <p>AT&amp;T syntax places the destination last:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>MOV $50, A ; move hex 50 into register A </code></pre></div></div> <p>Intel syntax places the destination first:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>MOV A, $50 ; move hex 50 into register A </code></pre></div></div> <h3 id="tools">Tools</h3> <ul> <li><code class="language-plaintext highlighter-rouge">file</code></li> </ul> <p>Uses “magic” to classify a file. Magic is just a list of known signatures, like how a PNG image always starts with <code class="language-plaintext highlighter-rouge">89 50 4e 47</code> (<code class="language-plaintext highlighter-rouge"> PNG</code>).</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>file ./reverseme1 ./reverseme1: ELF 32-bit LSB executable, Intel 80386, version 1 <span class="o">(</span>SYSV<span class="o">)</span>, dynamically linked <span class="o">(</span>uses shared libs<span class="o">)</span>, <span class="k">for </span>GNU/Linux 2.6.32, BuildID <span class="o">[</span>sha1]<span class="o">=</span>8835077d876c5544ac9766af68c2e98d3c137917, not stripped </code></pre></div></div> <ul> <li><code class="language-plaintext highlighter-rouge">strings</code></li> </ul> <p>Looks for ASCII strings 4 or more characters long. Helps to remove the non-printable characters from a binary.</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>strings ./reverseme1 | <span class="nb">grep </span>flag False_flag<span class="o">{</span>RobotBully<span class="o">}!</span> DEBUG off. No flag <span class="k">for </span>yews! </code></pre></div></div> <ul> <li>Just run it</li> </ul> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">chmod</span> +x ./reverseme1 <span class="nv">$ </span>./reverseme1 DEBUG off. No flag <span class="k">for </span>yews! </code></pre></div></div> <ul> <li><code class="language-plaintext highlighter-rouge">dasm2.pl</code></li> </ul> <p>A perl script reverser. The author claims this is only useful if your system doesn’t have <code class="language-plaintext highlighter-rouge">objdump</code> but it finds strings from <code class="language-plaintext highlighter-rouge">.data</code> sections and resolves jumps to symbol names, which not many others do!</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>dasm2.pl <span class="nt">-p</span> <span class="nt">-output</span><span class="o">=</span>dasm.txt ./reverseme1 <span class="nv">$ </span>less dasm.txt </code></pre></div></div> <ul> <li><code class="language-plaintext highlighter-rouge">objdump</code></li> </ul> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>objdump <span class="nt">-d</span> <span class="nt">-j</span> .text <span class="nt">--file-offsets</span> <span class="nt">--prefix-addresses</span> <span class="nt">--show-raw-insn</span> ./reverseme1 | <span class="nb">awk</span> <span class="s1">'/&lt;main/'</span> <span class="o">&gt;</span> objd.txt <span class="nv">$ </span>less objd.txt </code></pre></div></div> <ul> <li>GDB</li> </ul> <p>This debugger has a disassembler too:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>disassemble /r </code></pre></div></div> <h2 id="ctf-reverse-me-1">CTF Reverse Me 1</h2> <p>Look for where the “DEBUG off” string is printed, understand why.</p> <p>The debug message is printed after a jump:</p> <ul> <li>dasm2</li> </ul> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> 08048551 sub $c,%esp ; referenced from jump(s) at 080484df; 08048554 push $8048618 ; reference to data : "DEBUG off. No flag for yews!" 08048559 call 08048310 ; (this is a call to puts, to print the above string) </code></pre></div></div> <ul> <li>objdump</li> </ul> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>08048551 &lt;main+0xf6&gt; (File Offset: 0x551) 83 ec 0c sub $0xc,%esp 08048554 &lt;main+0xf9&gt; (File Offset: 0x554) 68 18 86 04 08 push $0x8048618 08048559 &lt;main+0xfe&gt; (File Offset: 0x559) e8 b2 fd ff ff call 08048310 &lt;puts@plt&gt; (File Offset: 0x310) </code></pre></div></div> <p>The jump relies on a condition:</p> <ul> <li>dasm2</li> </ul> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> 080484d4 movl $0,-14(%ebp) ; reference to data : "putchar" 080484db cmpl $0,-14(%ebp) ; reference to data : "putchar" 080484df je 08048551 ; 080484e1 movl $0,-c(%ebp) ; reference to data : "putchar" 080484e8 jmp 0804852c ; </code></pre></div></div> <ul> <li>objdump</li> </ul> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>080484d4 &lt;main+0x79&gt; (File Offset: 0x4d4) c7 45 ec 00 00 00 00 movl $0x0,-0x14(%ebp) 080484db &lt;main+0x80&gt; (File Offset: 0x4db) 83 7d ec 00 cmpl $0x0,-0x14(%ebp) 080484df &lt;main+0x84&gt; (File Offset: 0x4df) 74 70 je 08048551 &lt;main+0xf6&gt; (File Offset: 0x551) ^^^^^^^^^^^^^^^^^^ 080484e1 &lt;main+0x86&gt; (File Offset: 0x4e1) c7 45 f4 00 00 00 00 movl $0x0,-0xc(%ebp) 080484e8 &lt;main+0x8d&gt; (File Offset: 0x4e8) eb 42 jmp 0804852c &lt;main+0xd1&gt; (File Offset: 0x52c) </code></pre></div></div> <p>Let’s just turn off that jump:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ hexdump -C ./reverseme1 | egrep -A1 "0*04d. " 000004d0 00 86 04 08 c7 45 ec 00 00 00 00 83 7d ec 00 74 |.....E......}..t| 000004e0 70 c7 45 f4 00 00 00 00 eb 42 8d 55 d4 8b 45 f4 |p.E......B.U..E.| </code></pre></div></div> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ hexdump -C ./reverseme1done | egrep -A1 "0*04d. " 000004d0 00 86 04 08 c7 45 ec 00 00 00 00 83 7d ec 00 90 |.....E......}...| 000004e0 90 c7 45 f4 00 00 00 00 eb 42 8d 55 d4 8b 45 f4 |..E......B.U..E.| </code></pre></div></div> <p>And run again:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>./reverseme1done flag<span class="o">{}</span> </code></pre></div></div> <h2 id="references">References</h2> <p><code class="language-plaintext highlighter-rouge">dasm2.pl</code></p> <ul> <li><a href="https://www.lxtreme.nl/source/dasm2/">https://www.lxtreme.nl/source/dasm2/</a></li> </ul> <p>ELF binaries</p> <ul> <li><a href="http://wiki.osdev.org/ELF">http://wiki.osdev.org/ELF</a></li> <li><a href="https://lwn.net/Articles/531148/">https://lwn.net/Articles/531148/</a></li> <li><a href="http://jvns.ca/blog/2014/09/06/how-to-read-an-executable/">http://jvns.ca/blog/2014/09/06/how-to-read-an-executable/</a></li> </ul> <p>x86 Assembly and Disassembly</p> <ul> <li><a href="https://idea.popcount.org/2013-07-16-baby-steps-in-x86-assembly/">https://idea.popcount.org/2013-07-16-baby-steps-in-x86-assembly/</a></li> <li><a href="https://en.wikipedia.org/wiki/X86_assembly_language">https://en.wikipedia.org/wiki/X86_assembly_language</a></li> <li><a href="https://en.wikibooks.org/wiki/X86_Assembly">https://en.wikibooks.org/wiki/X86_Assembly</a></li> <li><a href="https://en.wikibooks.org/wiki/X86_Disassembly">https://en.wikibooks.org/wiki/X86_Disassembly</a></li> <li><a href="https://en.wikipedia.org/wiki/X86_calling_conventions">https://en.wikipedia.org/wiki/X86_calling_conventions</a></li> </ul> <h2 id="resources">Resources</h2> <ul> <li><a href="http://microcorruption.com/">http://microcorruption.com/</a> - Web-based reversing CTF with great debugger and fictional corporate espionage story, uses the actual <a href="https://en.wikipedia.org/wiki/TI_MSP430">Texas Instruments MSP430</a> assembly language.</li> <li><a href="http://www.crackmes.de/">http://www.crackmes.de/</a> - The reversers’ playground. A community of people who post and solve each others’ binaries for fun. Ranges from very easy to insanely difficult.</li> <li><a href="http://tcrf.net/">http://tcrf.net/</a> - People who reverse old video games to understand the file formats, look for unpublished content, create editing tools, etc</li> <li><a href="http://www.romhacking.net/">http://www.romhacking.net/</a> - Index of video game hacks to change graphics, gameplay, translate, etc</li> <li><a href="https://github.com/djyt/cannonball">https://github.com/djyt/cannonball</a> - This guy spent 4 years reversing the Outrun arcade ROM, re-implementing it in C++ and SDL, then started extending it with widescreen, 60fps, track editors, etc.</li> </ul> Thu, 28 Apr 2016 00:00:00 +0000 https://superjamie.github.io/2016/04/28/reversing-for-dummies https://superjamie.github.io/2016/04/28/reversing-for-dummies Raspberry Pi Vpn Router <hr /> <p>title: Raspberry Pi VPN Router external-url: https://gist.github.com/superjamie/ac55b6d2c080582a3e64 —-</p> Sat, 24 Oct 2015 00:00:00 +0000 https://superjamie.github.io/2015/10/24/raspberry-pi-vpn-router https://superjamie.github.io/2015/10/24/raspberry-pi-vpn-router Running a Python script only if it's not already running <p>I have a simple Linux graphical desktop environment, using the Openbox window manager and tint2 panel. I use <a href="https://github.com/dmedvinsky/gsimplecal">gsimplecal</a> to display a small GTK Calendar widget when I click the panel clock. When I click the clock again, the calendar disappears.</p> <p>gsimplecal is written in C++ but I thought it might be fun to rewrite it in Python.</p> <p>The hardest part was detecting the running process, so a script would find another instance of itself then kill that instance and exit, but run if there was no existing instance. I came up with this fairly universal solution:</p> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/python </span> <span class="kn">from</span> <span class="nn">os</span> <span class="kn">import</span> <span class="n">getpid</span> <span class="kn">from</span> <span class="nn">sys</span> <span class="kn">import</span> <span class="n">argv</span><span class="p">,</span> <span class="nb">exit</span> <span class="kn">import</span> <span class="nn">psutil</span> <span class="c1">## pip install psutil </span> <span class="n">myname</span> <span class="o">=</span> <span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="n">mypid</span> <span class="o">=</span> <span class="n">getpid</span><span class="p">()</span> <span class="k">for</span> <span class="n">process</span> <span class="ow">in</span> <span class="n">psutil</span><span class="p">.</span><span class="n">process_iter</span><span class="p">():</span> <span class="k">if</span> <span class="n">process</span><span class="p">.</span><span class="n">pid</span> <span class="o">!=</span> <span class="n">mypid</span><span class="p">:</span> <span class="k">for</span> <span class="n">path</span> <span class="ow">in</span> <span class="n">process</span><span class="p">.</span><span class="n">cmdline</span><span class="p">():</span> <span class="k">if</span> <span class="n">myname</span> <span class="ow">in</span> <span class="n">path</span><span class="p">:</span> <span class="k">print</span> <span class="s">"process found"</span> <span class="n">process</span><span class="p">.</span><span class="n">terminate</span><span class="p">()</span> <span class="nb">exit</span><span class="p">()</span> <span class="c1">## your program here... </span></code></pre></div></div> Fri, 31 Oct 2014 00:00:00 +0000 https://superjamie.github.io/2014/10/31/running-a-python-script-only-if-its-not-already-running https://superjamie.github.io/2014/10/31/running-a-python-script-only-if-its-not-already-running The 8-Byte Two-Step Redux <p>Over <a href="https://news.ycombinator.com/item?id=8345410">on Hacker News</a>, Z posted a fantastic article called <a href="http://zinascii.com/2014/the-8-byte-two-step.html">The 8-Byte Two-Step</a> where the concept of aligning to byte boundaries was explored.</p> <p>I thought this was a fantastic post, it goes right down to binary and logical operators then back up again.</p> <p>After understanding the alignment, Z then writes three other ways of doing the same thing, disassembles them and benchmarks them.</p> <p>Discussing this on HN, I said:</p> <blockquote> <p>I have banned myself from using printfs to figure out things like this. Instead I would use a debugger and breakpoints to view the live variables in their different data formats.</p> <p>In GDB, that’s p/t for binary and p/d for decimal.</p> </blockquote> <p>To which Z replied:</p> <blockquote> <p>I would like to try the method you describe… I’ll be curious to use your method and see how it compares.</p> </blockquote> <p>So I figured I’d show how. Knowledge of the original post <a href="http://zinascii.com/2014/the-8-byte-two-step.html">The 8-Byte Two-Step</a> is required before progressing further.</p> <p>I had to include <code class="language-plaintext highlighter-rouge">&lt;stdint.h</code>&gt; for the <code class="language-plaintext highlighter-rouge">uint_64t</code>, and I removed the <code class="language-plaintext highlighter-rouge">printf()</code>s. This is the code I am using:</p> <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"> #include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"> #include</span> <span class="cpf">&lt;sys/types.h&gt;</span><span class="cp"> #include</span> <span class="cpf">&lt;stdint.h&gt;</span><span class="cp"> </span> <span class="cp">#define MQ_ALIGNSIZE 8 </span> <span class="kt">char</span> <span class="o">*</span><span class="nf">as_binary</span><span class="p">(</span><span class="kt">uint32_t</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> <span class="kt">int</span> <span class="n">bit_i</span> <span class="o">=</span> <span class="mi">31</span><span class="p">;</span> <span class="kt">char</span> <span class="o">*</span><span class="n">bits</span><span class="p">;</span> <span class="kt">uint64_t</span> <span class="n">on_bit</span><span class="p">;</span> <span class="n">bits</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="kt">char</span><span class="p">)</span> <span class="o">*</span> <span class="mi">33</span><span class="p">);</span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">32</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">bit_i</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> <span class="n">on_bit</span> <span class="o">=</span> <span class="mi">1u</span> <span class="o">&lt;&lt;</span> <span class="n">bit_i</span><span class="p">;</span> <span class="n">bits</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">on_bit</span> <span class="o">&amp;</span> <span class="n">n</span><span class="p">)</span> <span class="o">?</span> <span class="sc">'1'</span> <span class="o">:</span> <span class="sc">'0'</span><span class="p">;</span> <span class="p">}</span> <span class="n">bits</span><span class="p">[</span><span class="mi">32</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span> <span class="k">return</span> <span class="n">bits</span><span class="p">;</span> <span class="p">}</span> <span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span> <span class="p">{</span> <span class="kt">uint32_t</span> <span class="n">size</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="kt">uint32_t</span> <span class="n">temp</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">;</span> <span class="n">size</span> <span class="o">=</span> <span class="n">atoi</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> <span class="n">a</span> <span class="o">=</span> <span class="p">(</span><span class="n">size</span> <span class="o">+</span> <span class="n">MQ_ALIGNSIZE</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="n">b</span> <span class="o">=</span> <span class="o">~</span><span class="p">(</span><span class="n">MQ_ALIGNSIZE</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="n">temp</span> <span class="o">=</span> <span class="n">a</span> <span class="o">&amp;</span> <span class="n">b</span><span class="p">;</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <p>Compile with debugging symbols (add <code class="language-plaintext highlighter-rouge">-g</code>) so we can use a debugger:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>cc <span class="nt">-g</span> <span class="nt">-std</span><span class="o">=</span>c99 aligner.c <span class="nt">-o</span> aligner </code></pre></div></div> <p>Start the debugger with the program loaded:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>gdb ./aligner </code></pre></div></div> <p>Add a commandline parameter to the program:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">(</span>gdb<span class="o">)</span> <span class="nb">set </span>args 1023 </code></pre></div></div> <p>Set a breakpoint at line 32 (just before the return):</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">(</span>gdb<span class="o">)</span> b aligner.c:32 </code></pre></div></div> <p>Run and let GDB pause at the breakpoint. Here’s it’s about to run the return but has stopped before doing so. Now the application is frozen at this point in time:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">(</span>gdb<span class="o">)</span> r Starting program: /home/superjamie/code/8-byte-two-step/aligner 1023 Breakpoint 1, main <span class="o">(</span><span class="nv">argc</span><span class="o">=</span>2, <span class="nv">argv</span><span class="o">=</span>0x7fffffffdf08<span class="o">)</span> at aligner.c:33 33 <span class="k">return </span>0<span class="p">;</span> </code></pre></div></div> <p>Looking at the <code class="language-plaintext highlighter-rouge">size</code> variable:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">(</span>gdb<span class="o">)</span> p/t size <span class="nv">$1</span> <span class="o">=</span> 1111111111 <span class="o">(</span>gdb<span class="o">)</span> p/d size <span class="nv">$2</span> <span class="o">=</span> 1023 </code></pre></div></div> <p>And the rest of the variables:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">(</span>gdb<span class="o">)</span> p/t a <span class="nv">$3</span> <span class="o">=</span> 10000000110 <span class="o">(</span>gdb<span class="o">)</span> p/d a <span class="nv">$4</span> <span class="o">=</span> 1030 <span class="o">(</span>gdb<span class="o">)</span> p/t b <span class="nv">$5</span> <span class="o">=</span> 11111111111111111111111111111000 <span class="o">(</span>gdb<span class="o">)</span> p/d b <span class="nv">$6</span> <span class="o">=</span> 4294967288 <span class="o">(</span>gdb<span class="o">)</span> p/t temp <span class="nv">$7</span> <span class="o">=</span> 10000000000 <span class="o">(</span>gdb<span class="o">)</span> p/d temp <span class="nv">$8</span> <span class="o">=</span> 1024 </code></pre></div></div> <p>One obvious advantage of the <code class="language-plaintext highlighter-rouge">printf()</code> method is that it looks a lot nicer, remember Z’s output:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>./align_debug 1023 size: 00000000000000000000001111111111 <span class="o">(</span>1023<span class="o">)</span> a: 00000000000000000000010000000110 <span class="o">(</span>1030<span class="o">)</span> b: 11111111111111111111111111111000 <span class="o">(</span>4294967288<span class="o">)</span> temp: 00000000000000000000010000000000 <span class="o">(</span>1024<span class="o">)</span> </code></pre></div></div> <p>I find GDB to also be a fantastic disassembler and lets you see the contents of registers as you run a program.</p> <p>Try the following:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>gdb ./aligner <span class="o">(</span>gdb<span class="o">)</span> layout asm <span class="o">(</span>gdb<span class="o">)</span> layout regs </code></pre></div></div> <p>This turns on GDB’s disassembly layout and register monitor. You’ll see the entire binary disassembled and the contents of the registers above. They’ll be blank because we’re not running anything yet.</p> <p>Add our argument as before, and set a breakpoint:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">(</span>gdb<span class="o">)</span> <span class="nb">set </span>args 1023 <span class="o">(</span>gdb<span class="o">)</span> b main </code></pre></div></div> <p>This sets a breakpoint as we enter <code class="language-plaintext highlighter-rouge">main()</code>. Assembly wise, we’ll have just setup <code class="language-plaintext highlighter-rouge">main()</code>’s stack frame (<code class="language-plaintext highlighter-rouge">push %rbp</code> and <code class="language-plaintext highlighter-rouge">mov %rsp,%rbp</code>) be ready to start executing.</p> <p>We can type <code class="language-plaintext highlighter-rouge">stepi</code> to proceed to the next assembly instruction, then press the <strong>Enter</strong> key to repeat that <code class="language-plaintext highlighter-rouge">stepi</code> command.</p> <p>The disassembler will step down as we execute, and the register monitor will highlight registers which change value.</p> Sun, 21 Sep 2014 00:00:00 +0000 https://superjamie.github.io/2014/09/21/the-8-byte-two-step-redux https://superjamie.github.io/2014/09/21/the-8-byte-two-step-redux