diff options
Diffstat (limited to 'doomsh')
-rwxr-xr-x | doomsh | 137 |
1 files changed, 137 insertions, 0 deletions
@@ -0,0 +1,137 @@ +#!/usr/bin/env bash + +# +# doomsh: Play with low ulimits in Bash +# +# Author: Tom Ryder +# Copyright: 2016 +# License: MIT (see LICENSE.markdown) +# +self=doomsh + +# Don't try to play doomsh if already playing doomsh +if [[ $DOOMSH ]] ; then + printf '%s: Already playing doomsh!\n' \ + "$self" >&2 + exit 2 +fi + +# Show the coloured logo; thanks to Frans P. de Vries for the classic ASCII art +# <http://www.gamers.org/~fpv/doombann.html> +printf >&2 %s "$( { + tput AF 3 || tput setaf 3 + tput md || tput bold +} 2>/dev/null )" +while IFS= read -r line ; do + printf >&2 '%s\n' "$line" +done <<EOF +______ _____ _____ __ ___ +| __ \ _ | _ | \ / | +| | \ | | | | | | | . V . | +| | / | \_/ | \_/ | |\ /| | +| |/ / \ / \ /| | V | | +| ' / \_/ \_/ \_| | | +|__/ \_| +EOF +printf >&2 %s "$( { + tput me || tput sgr0 +} 2>/dev/null )" + +# Need to figure out a skill level +declare -i skill + +# If we have an argument, that must be the skill level +if (($#)) ; then + skill=$1 + shift + +# Otherwise, we'll give the user a menu to choose from +else + while IFS= read -r line ; do + printf >&2 '%s\n' "$line" + done <<EOF + +1. I'm too young to die +2. Hey, not too rough +3. Hurt me plenty +4. Ultra-Violence +5. Nightmare! + +EOF + read -er -p '[1-5]: ' skill + + # If the user chose "Nightmare!" mode, get them to confirm, in the true + # spirit of things; otherwise, quit + if ((skill == 5)) ; then + while IFS= read -r line ; do + printf '%s\n' "$line" >&2 + done <<EOF + +Are you sure? This skill level isn't even remotely fair. +EOF + read -er -p '[y/N]: ' confirm + [[ $confirm == [Yy]* ]] || exit 1 + fi +fi + +# Don't accept any other skill level settings +case $skill in + 1|2|3|4|5) + ;; + *) + printf '%s: Unknown skill level\n' \ + "$self" >&2 + exit 2 +esac + +# Form a red prompt (hopefully) using terminal escapes +ps1=$(printf '%sdoomsh[%u]\$%s ' \ + "$( { + tput AF 1 || tput setaf 1 + } 2>/dev/null )" \ + "$skill" \ + "$( { + tput me || tput sgr0 + } 2>/dev/null )" +) + +# Set the limits based on the skill level +declare -i filesize files stack memory +filesize=$((1 << (8 - skill))) +files=$((11 - skill)) +stack=$((1 << (11 - skill))) +memory=$((1 << (19 - skill))) + +# Display the limits +printf >&2 '\n' +printf >&2 'File size writing limit: %u blocks\n' \ + "$filesize" +printf >&2 'Open files limit: %u\n' \ + "$files" +printf >&2 'Stack size: %u kbytes\n' \ + "$stack" +printf >&2 'Memory size: %u kbytes\n' \ + "$memory" +printf >&2 '\n' + +# Record the current seconds since shell start, so we can tell how long the +# user lasts before giving up or segfaulting +declare -i start +start=$SECONDS + +# Open a subshell so that the ulimit settings don't persist after the fork +( + # We only proceed if the ulimit call succeeds + ulimit \ + -f "$filesize" \ + -n "$files" \ + -s "$((1 << (10 - skill)))" \ + -v "$((1 << (19 - skill)))" \ + || exit 2 + DOOMSH=$skill PS1=$ps1 bash --norc +) + +# Give the user some statistics about their performance +printf >&2 '%s: You lasted %u seconds at skill level %u!\n' \ + "$self" "$((SECONDS - start))" "$skill" + |