Posts tagged "computing":

02 Aug 2019

The Danger of fuzzy matching over one's PATH

Awhile back I noticed my personal mnt/ directory, my (empty) personal tmp/ directory, and a few symbolic links disappeared from my home directory. I only noticed because I use unison1 to synchronize my desktop and laptop homedirs. The actual amount of removed directories and symbolic links were staggering, and it costed me five minutes of extra effort to search through the unison UI to ignore files I don’t want to synchronize. Repeat this a few times a day, with the problem occurring at seemingly random intervals, and you’ve wasted minutes out of every day, which adds up to hours every month.

For months I had not figured out what the problem was. By chance I had noticed while using my application launcher, I had accidentally not ran links -g 2 but instead had ran cleanlinks. I wonder to myself what was I running by accident, as I had done this before, but had not thought anything of it, assuming it was a program that would print usage or perform a no-operation by default.

I was wrong.

Turns out cleanlinks searches the current working directory for empty directories and broken symbolic links. Both are useful. For example I keep empty directories in ~/mnt/ to mount sshfs stuff, and I prefer to use ~/tmp/ as a work directory because no system scripts will touch it.3 I had a few broken symbolic links scattered about, from weird git repositories working trees to some stale user-level systemd unit links from my archlinux install.

Making things more interesting, if you run cleanlinks --help, or with any flags, it operates as usual. So it’s a mistake to also do cleanlinks /some/directory/i/want/to/clean. As a part of imake,4 the old X11 ecosystem build tools, cleanlinks will be installed on many systems and it’s not safe to run it lest you enjoy random stuff being messed about with in your current directory.

How did I manage to run cleanlinks so many times? I did not have links installed on the affected machine. And even after I did install it, I forgot to remove cleanlinks from my rofi runcache. So it had a higher precedence to match than links in certain cases. Hence I ran it a few times on accident even after installing links.

Therefore, I strongly recommend one doesn’t fuzzy match over their PATH. Who knows what other nasty tools ship on your system that will lay waste your productivity, or worse, damage your personal files.

Regardless, I have yet to heed my own warning. Maybe I should just use .desktop files, but then again, maybe there exists a cleanlinks.desktop… Ideally, I’ll create a directory of symlinks to programs I want to launch from rofi. Someday :)

About Unison

I should mention unison is a superb tool for synchronizing your data. It shows the user a list of changes to each directory being synchronized, waits for the user to decide which way each file should be synchronized:

  1. Send file from host A to B
  2. Send file from host B to A
  3. Ignore the file this time
  4. Ignore the file permanently
  5. Merge the files

Because unison doesn’t try to be fancy or automatic, it is easy to understand what is happening.



Links 2 is the best web 1.0 browser. It even shows images and different text sizes. Screenshots on this page.


/var/tmp/ could also work, but this way I know nobody is gunna mess with my files and I won’t accidentally mess up permissions on sensitive data.


imake on freedesktop’s GitLab. See also what packages depend on imake in Arch Linux. I use Gentoo across my laptop and workstation, so it’s necessary to have imake installed.

Tags: computing rant
28 Jul 2019

Open URL in existing Qutebrowser from Emacs Daemon on Gentoo

On my Gentoo desktops, I use Emacs Daemon via sys-emacs/emacs-daemon1 to ensure an Emacs instance is ready to go and always available from boot. This is done via creating a symbolic link like /etc/init.d/emacs.winston to /etc/init.d/emacs which will start Emacs for the given user. See the package README for more details.

A shortcoming of this setup is XDG_RUNTIME_DIR2 is not set, as this is set by my Desktop Session - maybe LightDM or consolekit set this? As a result, when I open a URL from Emacs Daemon, it opens a fresh qutebrowser session, loading the saved default session, and making a mess of my workflow.

One approach to fix this might be to instead run Emacs daemon from my .xsession script, but I rather not supervise daemons at the user level; if I were to consider this, I'd be better off to switch to systemd for user-level services anyway.

The solution I came up with is to add some lines to my init.el to ensure XDG_RUNTIME_DIR is set to the expected value:

(defun winny/ensure-XDG_RUNTIME_DIR ()
  "Ensure XDG_RUNTIME_DIR is set. Used by qutebrowser and other utilities."
  (let ((rd (getenv "XDG_RUNTIME_DIR")))
    (when (or (not rd) (string-empty-p rd))
      (setenv "XDG_RUNTIME_DIR" (format "/run/user/%d" (user-uid))))))

(add-hook 'after-init-hook #'winny/ensure-XDG_RUNTIME_DIR)

A strange emacs-ism: (user-uid) returns float or integer, despite the backing uid_t (on *nix) is guarenteed to be an integer type. I'll just assume this'll never return a float. Please contact me otherwise, I'd love to hear about this.


Tags: emacs productivity computing gentoo qutebrowser
22 Jan 2019

Blink Shell: First Thoughts

As a heavy user of SSH to manage computers and IRC via command line clients, the most used application on my phone besides the web browser is a SSH client. Previously I have used Prompt and it worked, but barely. My issues with Prompt include crashing on emoji spam that is common in certain IRC channels, very slow terminal rendering to the point that watching the output of compiling a large package will cause Prompt to lag uncontrollably for tens of seconds, and a relatively un-intuitive UI. Please note I am referring to Prompt, not Prompt 21, which is another problem in itself (the idea I need to pay for the same product but rewritten to actually work is just ludicrous).


Another thing to note before I dig into Blink is I'm not a big fan of mobile devices. They get the job done, but in most cases I rather crack open my netbook and not fight with the learn-by-fiddling mobile UI paradigms most devices have adopted. I am also not a fan of Apple's ecosystem, but I'm pretty content with my iPhone and iPad for my basic use cases: browse the web, chat applications, making phone calls, casual mobile gaming, logging into other computers via SSH.

Enter Blink2. This application does a few things differently from other mobile SSH clients. It offers a command-line first user interface. At first I thought this would be painful, but the application's verbs are pretty simple and appear to match up with how one uses ssh and mosh in a terminal emulator. The terminal emulator is responsive, significantly more stable than Prompt, and looks good. I can even load up my favorite font: Droid Sans Mono3 (thanks to its support for loading webfonts via a URL to a CSS file).

Another thing Blink does different is it offers Mosh support4. Mosh is an alternative to SSH that can "roam" across networks and device power state changes. One thing to note is Mosh requires SSH to make the initial login, then switches to Mosh which uses a different protocol. When using mosh, I tend to log in once throughout the day. I can then switch networks and mosh will gracefully reconnect as soon as the server is reachable again. In addition, when I sleep my netbook, the session isn't lost (but don't go using this instead of tmux or screen). Instead when I wake my netbook, it also gracefully reconnects to the server. The same is true of Blink's Mosh support. It even appears to save state between changing iOS application states, sans forcing the application to quit (or rebooting your device). This means I only log in once on my phone throughout the day, and the connection is gracefully dropped when the app becomes inactive and reconnects when the app is opened again.

I did notice I crashed Blink after writing non-ascii binary data to the terminal followed by some other operations, but did not manage to reproduce the crash yet. If I do, I am confident I can report the bug and get meaningful feedback too, as Blink has a bug tracker on GitHub5. The code is available under GPLv3 (but not to worry, as the single copyright holder can safely relicense it to deploy on the iOS App Store6). I could probably build it myself and install that, but I neither own a Mac (or wish to install Mac OS X in a VM) nor want to ever open XCode again even if I had a way to. That life isn't for me. Again, I'm very practical about how I use my iOS devices and don't enjoy using them more than I have to, so I'm willing to pay $20 for an application I'll use every day of my life on this walled garden platform. An added silver lining is this investment goes towards the development of such a great app that appears to have active maintainership.

Note: I did not explore some of Blink's features such as using it a local iOS shell or settings synchronization. YMMV.

Getting started

Here are the steps I used to get started with Blink, as it was relatively unclear where to find documentation and which settings are necessary to configure. Usage information can be found via the help command, the README on GitHub7, and fiddling with the UI.

  1. Run the config command.
    1. Default User -> set to your preferred username on most of your servers
    2. Add a new font via: Appearance -> Add a new font. Open the gallery and grab the raw CSS file (you can get a raw URL after switching to GitHub desktop), then paste it into the URL Address Field. I prefer Droid Sans Mono for its readability at all sizes.
    3. Keys -> + -> Create New

      Please use ssh keypair authentication. Password authentication requires you to memorize a password to log in which can be bruteforced or otherwise leaked when typing it in the wrong context. Also, be sure to use a unique key on each of your devices to make revocation easier when a device is no longer used.

      Note: it appears keys are always stored as plaintext, which is acceptable for your uses, but it appears ssh-keygen can create a key with a passphrase. I wasn't able to get Blink to work with Passphrase protected keys, but I didn't try very hard. YMMV.

      • Type: RSA
      • Bits: 4096 (why not?)
      • Name: id_rsa
    4. Hosts -> +
      • Host: the name you gave your host when running ssh host or mosh host. This is not related to the server's hostname, though it can be the same. I prefer simple names, usually the hostname before the first dot (e.g. becomes simply worf)
      • User: make sure this is correct
      • Key: select a key to use.
  2. Now you need to install the SSH public key:
    1. Run config again
    2. Keys -> id_rsa -> Copy Public Key
    3. Install it some way.

      I usually prefer to visit and paste the public key, hit Paste, then copy the url with the text of "created". You can then curl on the server via another login setup (or ssh from a set up machine) and add it to your ~/.ssh/authorized_keys. Make sure that file is mode 0600 (chmod 0600 ~/.ssh/authorized_keys). Also make sure the .ssh directory is 0700 (chmod 0700 ~/.ssh). OpenSSH refuses to use authorized_keys if these permissions are world readable.

  3. Run ssh worf. Congratuations, you now have a SSH session on the best iOS client available at this time.
  4. To use mosh, ensure mosh is installed on the server.8 Then run mosh worf.


Tags: computing
13 Jan 2019

GNU C Style

No. Do not use it please! There are far easier-to-read and easier-to-use styles for C!1



Tags: computing rant
11 Jan 2019

Publishing with org-static-blog


After reviewing a list of org-mode1 capable static website generators2, I decided to see if org-static-blog3 could suffice my simple needs. My criteria for choosing an org-mode static site generator was:

  • it must be actively maintained,
  • it must be simple to set up with customizations,
  • and it must work with Emacs 26 and later.

This ruled out quite a few right away. I didn't attempt using org-publish, as it looked like a great deal of configuration to achieve a minimum viable web-page for this project.

Configuration of org-static-blog

Following the org-static-blog README documentation, it is very straight forward to get a minimal viable website generated. I added the following to my init.el:

(add-to-list 'auto-mode-alist (cons (concat org-static-blog-posts-directory ".*\\.org\\'") 'org-static-blog-mode))
(setq org-static-blog-publish-title "")
(setq org-static-blog-publish-url "")
(setq org-static-blog-publish-directory "~/projects/blog/")
(setq org-static-blog-posts-directory "~/projects/blog/posts/")
(setq org-static-blog-drafts-directory "~/projects/blog/drafts/")
(setq org-static-blog-enable-tags t)

(setq org-static-blog-page-header
<link href=\"static/style.css\" rel=\"stylesheet\" type=\"text/css\" />

I opted to setq all the configuration variables; I will likely switch to using M-x customize-group RET org-static-blog RET in the future however. It's a better experience.

Then I simply create a new post with M-x org-static-blog-create-new-post RET <TITLE> RET, edit the buffer, save it, then run M-x org-static-blog-publish RET. I also added some styling to my style.css4 based off the Tachyons CSS framework5. I had previously used Bootstrap6 for styling but was hoping to avoid adding framework and other extra tooling that shouldn't be necessary to generate a simple site like this one.

Deploying with Caddy and GitHub

I am a fan of the Caddy7 web server which offers automatic HTTPS via LetsEncrypt with only a few lines of configuration. In addition Caddy has a plugin named git which offers the ability to automatically deploy content from git repositories with webhook support. To deploy the following steps are taken:

  1. M-x org-static-blog-publish RET from Emacs to regenerate the static site,
  2. commit the changes in git,
  3. and finally push the git branch to GitHub.

After these steps, GitHub automatically sends a HTTP POST request to my Caddy server with information about the new git commits and Caddy pulls the git repository. If everything went well and the webhook successfully fired, the website is now deployed.

Server Configuration

I switched most of my personal internet-related services to Docker8 in conjunction with docker-compose9 last year. The main rationale is I can move my configuration without dealing with systems package versions. I already had Caddy set up, so it was as simple as adding this to my Caddyfile: {
        root /srv/www/
        log /logs/
        git {
                hook /webhook top-secret-password-redacted

The relevant lines of my docker-compose.yml looks like this:

version: "2.1"
    image: abiosoft/caddy:no-stats
    ports:  # Expose the webserver ports to the internet
      - "80:80"
      - "443:443"
      # This is where caddy places certs after ACME negotiation.
      CADDYPATH: "/etc/caddycerts"
      ACME_AGREE: "true"
      - /srv/caddy/certs:/etc/caddycerts
      - /srv/caddy/Caddyfile:/etc/Caddyfile  # Configuration
      - /srv/www:/srv/www  # the websites
      - /srv/caddy/logs:/logs

A keen docker-compose-savy reader will notice I did not specify a restart: always entry. I had Caddy configured to always restart, however, when requesting new HTTPS certificates from LetsEncrypt, there is a tendency to misconfigure the domain configuration or Caddyfile, and if Caddy requests too many HTTPS certificates in a short amount of time, LetsEcrypt will rate-limit my future requests. Usually this is only requires an hour or two of waiting, but is frustrating to deal with when trying to fix my configuration. Instead I rather Caddy exit after failing to activate all the domains and fix my configuration first.

GitHub Configuration

Simply create the GitHub repository, then add a webhook. It is important to note the webhook must send a JSON payload. By default a newly created webhook will send a application/x-www-form-urlencoded payload and will not work.


With this simple setup I can write posts. I can easily move the configuration to a new host at will. In addition my setup does not depend on future use of GitHub as GitLab, Gogs, and other git hosts offer webhook support in the same way. Most importantly, I can author org-mode files and have a better balance between features and ease of use than what markdown offers.

Web dev is one of my least favorite programming exercises. Between all the testing necessary to ensure a simple site works across many platforms, the trend to use a very complex system such as webpack and many other tools to produce simple websites, and the perpetual flux-and-flow between vendors only partially implementing good features, web dev just doesn't do it for me. Hence, I am very pleased how simple this project turned out to be.


Tags: computing
09 Jan 2019

Toggle Redshift with Keyboard Shortcut

Redshift is a screen-tinting program that achieves similar goals to the popular f.lux1 program.

I perused through the redshift man-pages and noticed there is no documented way to toggle redshift. Of course one can click the notification area icon when using redshift-gtk or SIGTERM the redshift process, but neither is very user friendly. (The mouse is not user friendly.) After some awkward DuckDuckGo-ing and Googling I found an obvious solution on the redshift homepage2: simply send SIGUSR1 to the redshift or redshift-gtk process. When using redshift-gtk, one can choose to send SIGUSR1 to either redshift or redshift-gtk.

This is the script I came up with:

set -eu
if ! pkill -x -SIGUSR1 redshift; then
    echo 'Could not find redshift process to toggle.' >&2
    exit 1

After installing the script into my system's PATH, now all I have to do is add a line to my Xbindkeys3 configuration file (~/.xbindkeysrc.scm) such as:

(xbindkey '(Mod4 F2) "toggle-redshift")

Now I can type Mod4-F2 and toggle Redshift.


Tags: productivity computing
Other posts