Tomb close automatically with a timer
Hi,
Thank you for Tomb, it is just amazing!
I wonder if there is a feature already available to automatically close a tomb after X minutes. I have seen that feature in the pass-tomb plugin, but apparently it is not something within Tomb, but the plugin itself.
In pass-tomb is something like this:
pass tomb <gpg-id> --timer=10min
And after 10min the tomb automagically closes, which is very convenient IMHO for security.
Is there any way to achieve this with pure Tomb?
Thank you very much.
Currently not. And looking at the timer solution in pass-tomb, I doubt it would be implemented like that as it uses a systemd timer. Maybe as an extra tool. An alternative would be a classic cron-job (and working with the issue, that this specific crontab entry needs to be dropped). Additionally, if only tombs should be closed if x min/h/whatever have gone without user interaction (plus using Xorg) then something could be done with xautolock (only working if tomb script can be used without entering a sudo password)
Tomb currently does not support timer. I don't know if @jaromil likes this idea, but it could be easy to add it in tomb using a cron-job.
@Narrat For the record, I plan to rewrite the timer part in pass-tomb because indeed it is crappy.
@roddhjav: Whatever gets the job done. :) I don't have a problem with systemd based solutions. The issue is more like, it requires distributions which use systemd. The rest is left behind. On the other hand relying on cron is of a similar problem. Distributions with systemd don't necessarily offer a cron implementation installed per default (although this case is easier to solve: installing one). And personally I uninstalled cronie after timer became available.
So whatever is chosen it should be optional (100% sure it would happen like that anyway), and if it is implemented, should it be in the script itself or put into extras/.
Hello. This would be a nice usability feature indeed.
I see problems with both systemd and cron solutions, mostly related to minimalist design and to what cron is really meant for. FTR in UNIX systems the standard tool to schedule a single event in the future is ATD(8) which may come handy.
In my standard practice when in need to schedule a future event I do not use ATD myself, but use this little python script that runs alarms and other things while showing me a countdown (but can also be launched in background). In my own setup this script is called ding and accepts a human-friendly syntax like ding in 4m to count 4 minutes and then start an alarm.
#!/usr/bin/env python
"""Simple CLI beep tool"""
from __future__ import unicode_literals
from __future__ import print_function
import os
import sys
import time
import datetime
EXIT_MSG = """Invalid arguments: {}\n---------
$ ding at hh[:mm[:ss]]
$ ding in \d+[smh]( +\d+[smh])*
Examples:
$ ding at 15:30
$ ding in 5m 30s
"""
VERSION = '1.2.0'
N_BEEPS = 4
WAIT_BEEPS = 0.15
class InvalidArguments(Exception):
pass
def check_input(args):
"""Validate user input"""
if len(args) < 2 or args[0] not in ['in', 'at']:
raise InvalidArguments('insufficient number of arguments')
if args[0] == 'in':
if not all(arg.endswith(('s', 'm', 'h')) for arg in args[1:]):
raise InvalidArguments('please use s/m/h suffixes')
if not all(arg[:-1].isdigit() for arg in args[1:]):
raise InvalidArguments('please use numbers for specifying the duration of time units')
if args[0] == 'at':
if len(args) > 2:
raise InvalidArguments('too many arguments')
if not all([arg.isdigit() for arg in args[1].split(':')]):
raise InvalidArguments('there should only be numbers optionally separated by ":"')
# Valid time
try:
datetime.time(*map(int, args[1].split(':')))
except ValueError as e:
raise InvalidArguments(e)
return args
class TimeParser():
"""Class helping with parsing user provided time into seconds"""
time_map = {
's': 1,
'm': 60,
'h': 60 * 60,
}
def __init__(self, time, relative):
self.time = time
self.relative = relative
def get_seconds(self):
return self._get_seconds_relative() if self.relative else self._get_seconds_absolute()
def _get_seconds_relative(self):
return sum([self.time_map[t[-1]] * int(t[:-1]) for t in self.time])
def _get_seconds_absolute(self):
now = datetime.datetime.now()
user_time = (datetime.datetime.combine(datetime.date.today(),
datetime.time(*map(int, self.time[0].split(':')))))
return ((user_time - now).seconds if user_time > now
else (user_time + datetime.timedelta(days=1) - now).seconds)
def print_time(seconds):
"""Print countdown for `seconds`"""
while seconds > 0:
start = time.time()
os.system('cls' if os.name == 'nt' else 'clear') # accommodate Windows
print(datetime.timedelta(seconds=seconds))
seconds -= 1
time.sleep(1 - time.time() + start)
def beep(seconds):
"""Make the beep noise"""
for _ in range(N_BEEPS):
# sys.stdout.write('\a')
os.system('beep')
sys.stdout.flush()
time.sleep(WAIT_BEEPS)
def parse_time(args):
"""Figure out the number of seconds to wait"""
relative = True if args[0] == 'in' else False
user_time = args[1:]
parser = TimeParser(user_time, relative)
return parser.get_seconds()
def main(args=sys.argv[1:]):
if args and args[0] == '--version':
print(VERSION)
sys.exit()
try:
seconds = parse_time(check_input(args))
except InvalidArguments as e:
sys.exit(EXIT_MSG.format(e))
print_time(seconds)
beep(seconds)
if __name__ == '__main__':
main()
Also see in cryptsetup 2.0:
* Deferral removal
Cryptsetup now can mark device for deferred removal by using a new option
--deferred. This means that close command will not fail if the device is still
in use, but will instruct the kernel to remove the device automatically after
use count drops to zero (for example, once the filesystem is unmounted).
from: https://www.kernel.org/pub/linux/utils/cryptsetup/v2.0/v2.0.0-rc0-ReleaseNotes
Well, it seems cryptsetup might be the best solution to add a timer to tomb. We don't need to support systemd or cron, but can we require cryptsetup 2.0 for the timer to work in tomb? What about the distribution that will not have cryptsetup before long?
I suspect this won't solve the issue. Cryptsetup close command is different from losetup -d which will fail anyway until the actual close is done, plus this is not a callback but a kernel-level flag inside dm-crypt. It can be part of the solution of this and another issue I still have with running processes preventing the local loopback device to detach.
I was travelling due to a family medical issue and got off for some days.
Thanks for your comments and the healthy discussion.