blob: eb4a1ac7162095d772d928ea4686d4ae24292d7c (
plain) (
tree)
|
|
#!bash
#
# Copyright (C) 2016, 2018, 2021 Tom Ryder <tom@sanctum.geek.nz>
#
# This file is part of doomsh.
#
# doomsh is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# doomsh is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# doomsh. If not, see <https://www.gnu.org/licenses/>.
# doomsh: Play with low ulimits in Bash
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 "$stack" \
-v "$memory" \
|| 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"
|