blob: 4133ff720cf6b6243389eae76d291dc3ebb8b548 (
plain) (
tree)
|
|
#!/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"
|