Sunday, 19 November 2017

Parental control in Linux

Having small children, I needed to find a way to control how much time they spent daily using the computer.

The page https://wiki.archlinux.org/index.php/Parental_Control suggests timekpr and timoutd but both seem to be obsolete, since I couldn't make them work properly.

In the end, the solution that fits me is to use both PAM and Workrave.


  • PAM (http://www.linux-pam.org/) "is a suite of shared libraries that enable the local system administrator to choose how applications authenticate users", and there is a module called pam_time that "restricts access to a system and or specific applications at various times of the day and on specific days". So, with this I can limit access to the computer to only, for example, the weekends.

  • Workrave (http://www.workrave.org/). Workrave is originally designed to assist "in the recovery and prevention of Repetitive Strain Injury (RSI). The program frequently alerts you to take micro-pauses, rest breaks and restricts you to your daily limit." 


PAM is easy to configure and the children cannot stop it, but Workrave is not meant as a parental control software, so by default it shows a window, which the children could easily close in order to avoid the prescribed time limit. In order to fix this, I just make Workrave not to show in the Icon Tray, and just to open as a regular window, which then I hide from the taskbar with wmctrl. I create the following minimal script, which I configure to start up automatically with each session, so Workrave starts in the background, and the children cannot easily close it (when they learn a bit more about Linux they will easily figure out how to stop it, but I still have a few years until that happens!).

#!/bin/bash
/usr/sbin/workrave --sm-client-disable &
sleep 1
wmctrl -r "Workrave" -b add,skip_taskbar

When they reach the daily limit, Workrave will show them a warning and give them 30 seconds before the session is blocked (I would like to give them perhaps 5 minutes before the session is blocked, but for the moment I didn't figure out how to change this).

The Workrave configuration I used can be seen in the following images:





Friday, 17 November 2017

Emacs interface to Recoll

Lately I'm using Recoll (a desktop full-text search tool), https://www.lesbonscomptes.com/recoll/, which comes with a GUI, but it also can be used from a terminal. I wanted to be able to use it from within Emacs and I found two existing ways:


  1. helm-recoll https://github.com/emacs-helm/helm-recoll
  2. counsel-recoll, bundled with swiper https://github.com/abo-abo/swiper
I already use Ivy/Swiper/Counsel, which is very nice, so route 1) didn't appeal much to me: I would have to install Helm just to get Emacs-Recoll interaction and perhaps suffer some problems by having Helm and Ivy together.

Route 2) was not very nice either because counsel-recoll will interactively search the database for matches and it will show in the mini-buffer the names of the files whose contents match the given search so you can quickly open them, but you can not see any context in the files around the search you are trying to do.

So I ended up writing a small functon (ag-recoll), that suits me better. I can give a number of words, which recoll will use to do a search, and then only on those files matching, I will call ag, which will create a buffer with all the places in the files where the given words match. The given buffer is a "compilation" buffer, so the lines are hyperlinks, which can be easily followed to open the file at the place of interest.

The function is as simple as:


(defun ag-recoll (string directory)
  "Search using ag based on the findings of recoll. Search will be done in a given DIRECTORY, and the STRING will be interpreted as concatenated by ANDs for recoll and with ORs for ag.

   The idea is that when I search, for example, for 'openacc mpi', recoll will give me all the files that have those two words somewhere in the file, and ag will find lines that match any of the terms.

   For the moment this is very crude, and most options to recoll and ag are hard-coded in the ag-recoll.sh script, most notably that ag will look for a maximum of 10 matches in each file to avoid huge lists with common searches."

  (interactive (list (ag/read-from-minibuffer "Search string")
                   (read-directory-name "Directory: ")))
  (setq command-string (format "%s %s %s" "/home/angelv/localhacks/ag-recoll.sh" directory string))
  (setq regexp nil)
  (compilation-start
   command-string
   #'ag-mode
   `(lambda (mode-name) ,(ag/buffer-name string directory regexp))))

which uses the ag-recoll.sh script:

#!/bin/bash
dir=$1; shift
ors=$(printf '%s|' address@hidden)
recoll -t -b $@ dir:$dir | sed -e "s/file:\/\///" | xargs -d '\n' ag --max-count 10 --group --line-number column --color --color-match 30\;43 --color-path 1\;32 --smart-case ${ors%|}


So, as an example, when I call ag-recoll with STRING 'openacc pgi' and DIRECTORY /home/angelv/Learning in my workstation, the result is like this:



where each line is a hyperlink to the corresponding match in the file and you can use the common grep-mode commands to open a file, go to the next match C-x `, etc.

This is useful already as it is, but I will try to make it more flexible (being able to pass arguments to recoll and ag, etc. [I'm a total noob with Emacs Lisp, so any suggestions on how to improve the code are very welcome].