#!/bin/sh # -*- tab-width: 4 -*- ;; Emacs # vi: set tabstop=4 :: Vi/ViM # # Revision: 2.0 # Last Modified: June 28th, 2011 ############################################################ COPYRIGHT # # (c)2011. Devin Teske. All Rights Reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # ############################################################ INFORMATION # # Displays a list of users that were on the system when it last went down. # # Command Usage: # # lastdown [-h] [-f FILE] [-#] # # OPTIONS: # -h Print this message to stderr and exit # -f FILE Optional path to wtmp log (default: /var/log/wtmp) # -# A number from 1-9 to subtract in minutes from the boot time. # A value of zero means ten. Can be passed multiple times. # # Dependencies (sorted alphabetically): # # date(1) last(1) printf(1)* sysctl(8) # # * Is a shell-builtin on some releases. # ############################################################ GLOBALS # # Global exit status variables # SUCCESS=0 FAILURE=1 # # Program name # progname="${0##*/}" # # Default location of the UTMP(5) log # WTMP=/var/log/wtmp # # Optional component to subtract time from the boot_epoch # TIMEWARP=0 ############################################################ FUNCTIONS # fprintf $fd $fmt [ $opts ... ] # # Like printf, except allows you to print to a specific file-descriptor. Useful # for printing to stderr (fd=2) or some other known file-descriptor. # fprintf() { local fd=$1 [ $# -gt 1 ] || return $FAILURE shift 1 printf "$@" >&$fd } # eprintf $fmt [ $opts ... ] # # Print a message to stderr (fd=2). # eprintf() { fprintf 2 "$@" } # die [ $fmt [ $opts ... ]] # # Optionally print a message to stderr before exiting with failure status. # die() { local fmt="$1" [ $# -gt 0 ] && shift 1 [ "$fmt" ] && eprintf "$fmt\n" "$@" exit $FAILURE } # usage # # Prints a short syntax statement and exits. # usage() { local optfmt="\t%-11s%s\n" local envfmt="\t%-17s%s\n" eprintf "Usage: %s [-h] [-f FILE]" "$progname" eprintf "OPTIONS:\n" eprintf "$optfmt" "-h" \ "Print this message to stderr and exit" eprintf "$optfmt" "-f FILE" \ "Optioal path to UTMP(5) log (default: /var/log/wtmp)" eprintf "$optfmt" "-#" \ "A number from 1-9 to subtract in minutes from the boot time." eprintf "$optfmt" "" \ "A value of zero means ten. Can be passed multiple times." die } # eval2 $cmd ... # # Print a command to stdout before executing it. # eval2() { echo "$*" eval "$@" } # boottime_sec # # Returns the "seconds" portion of the ``kern.boottime'' sysctl(8) MIB. # boottime_sec() { set -- `sysctl -n kern.boottime` while [ "$1" != "sec" ]; do shift; done echo ${3%,} } ############################################################ MAIN SOURCE # # Read optional script arguments # while getopts hf:1234567890 flag; do case "$flag" in h) usage;; f) [ "$OPTARG" ] || die \ "%s: Missing or null argument to \`-f' flag" "$progname" WTMP="$OPTARG";; 1) TIMEWARP=$(( $TIMEWARP + 60*1 ));; 2) TIMEWARP=$(( $TIMEWARP + 60*2 ));; 3) TIMEWARP=$(( $TIMEWARP + 60*3 ));; 4) TIMEWARP=$(( $TIMEWARP + 60*4 ));; 5) TIMEWARP=$(( $TIMEWARP + 60*5 ));; 6) TIMEWARP=$(( $TIMEWARP + 60*6 ));; 7) TIMEWARP=$(( $TIMEWARP + 60*7 ));; 8) TIMEWARP=$(( $TIMEWARP + 60*8 ));; 9) TIMEWARP=$(( $TIMEWARP + 60*9 ));; 0) TIMEWARP=$(( $TIMEWARP + 60*10 ));; \?) usage;; esac done shift $(( $OPTIND -1 )) # # What was the epoch when we booted? # boot_epoch=$( boottime_sec ) # # ``Subtract one'' (make last(1) report on the time just prior to boot) # boot_epoch=$(( $boot_epoch - 1 )) # Pedantic really # # Go backwards in time (subtract TIMEWARP; which defaults to zero) # boot_epoch=$(( $boot_epoch - $TIMEWARP )) # # Convert boot_epoch into a format that last(1) accepts as an argument for # determining who was logged on the system at the particular date/time. # (resolution is 1-second) # start_time=$( date -r $boot_epoch +%Y%m%d%H%M.%S ) # # Get the list of users that were on the system at that time # eval2 last -d $start_time -f "$WTMP"