#!/bin/sh 

usage_exit () {
	echo "$0 <baudrate> <-sys|-conf <-f> >"
	echo "   -sys   modify baud via sysctl"
	echo "   -conf  modify baud via /boot/loader.conf"
	echo "   -f	specify location of loader.conf"
	echo "   default: both sysctl and conf modified"
	echo
	echo "   Configure the console port for this baud instantly,"
	echo "   and remember it as default automatically on next boot."
	if [ "X$1" != "X" ]; then
	    echo ""
	    echo "$1"
	fi
	exit 1
}

if [ $# = 0 ] ; then
	usage_exit ""
fi

SYS=0;
CONF=0;
CONFFILE=""
BAUD=9600

while [ $# -gt 0 ]; do
	case "$1" in
		-sys)  				SYS=1   ; shift;;
		-conf) 				CONF=1  ; shift;;
		-f)				CONFFILE=$2 ; shift 2 ;;
		## Verify that the argument is usable as a baudrate
		[0-9][0-9][0-9][0-9])		BAUD=$1 ; shift ;;
		[0-9][0-9][0-9][0-9][0-9])	BAUD=$1 ; shift ;;
		[0-9][0-9][0-9][0-9][0-9][0-9])	BAUD=$1 ; shift ;;
		*) usage_exit "   Error -- $1 couldn't be parsed as a <baudrate>" ; shift ;;
	esac
done

# script defaults to changing both conf file and sysctl if -sys and/or -conf flags not seen
if [ $SYS -eq 0 -a $CONF -eq 0 ] ; then
	SYS=1;
	CONF=1;
fi

if [ $CONF -eq 1 ] ; then
    if [ -z $CONFFILE ] ; then
    	LOADERCONF=/boot/loader.conf
    else
    	echo "switch to ${CONFFILE}"
    	LOADERCONF=$CONFFILE
    fi
    DQ='"' #simplify expressions
    
    #
    # NOTE: As a result of merging with FreeBSD 6.x, we inherited a new
    #       syntax for setting console speed. The new syntax involves
    #       an explicit line in the file to change the speed, rather than
    #       the old syntax which appended the speed to the end of the line 
    #       that sets the console to comconsole. Here are examples of both
    #       the old and new syntax:
    #
    #       old syntax: console="comconsole:115200"
    #       new syntax: comconsole_speed="115200"
    #
    #       Attempt to extract the existing baud rate from the configuration
    #       file (using the new syntax).
    #
    NOWBAUD=`cat ${LOADERCONF} | grep -e '^comconsole_speed=' | cut -d ${DQ} -f 2 | sed -e s/${DQ}//g`
    
    # if there is no (existing) baudrate set, change it to something clean 
    # for the printout
    if [ "X$NOWBAUD" = "X" ] ; then
    	NOWBAUD="(default)"
    fi
    
    # if the rate is not what we're looking for, echo and change
    if [ "X$NOWBAUD" != "X$BAUD" ] ; then
        echo "Switching loader.conf from $NOWBAUD to $BAUD" 
    
        # check if loader.conf can be written to
        /usr/bin/touch ${LOADERCONF}.tmp
    
        if [ $? -gt 0 ] ; then
	    echo "  cannot write to loader.conf ... leaving loader.conf unchanged" 
        else
	    if [ $NOWBAUD = "(default)" ] ; then
		#
		# the file does not currently contain a line that sets the 
		# baud rate so, add a line to set the new rate immediately 
		# after the line that sets the console to the comconsole. 
		#
		# we add the new line using the "new" syntax, but then we also
		# modify the line that sets the console to comconsole to also
		# have the new baud rate (this is the "old" syntax). this is
		# done so that if we end up booting off a disk with the old
		# boot loader which does not understand the new syntax, the
		# new rate is set using the old syntax as well. refer to 
		# bugzilla #27185 (and also related bug #11932).
		#
		cat ${LOADERCONF} | sed -E "/^console.*comconsole/a\\
comconsole_speed=${DQ}${BAUD}${DQ}
" > ${LOADERCONF}.tmp
		cat ${LOADERCONF}.tmp | sed -E "s~^(console=${DQ}comconsole):?([^${DQ}]*)(${DQ})\$~\1:${BAUD}\3~" > ${LOADERCONF}.tmp1
	    else
		#
		# the file contains an old setting so replace the old 
		# rate with the new rate (using both the "old" and "new" 
		# syntax). see the comment above for an explaination
		#
		cat ${LOADERCONF} | sed -E "s~^(console=${DQ}comconsole):?([^${DQ}]*)(${DQ})\$~\1:${BAUD}\3~" > ${LOADERCONF}.tmp
	    	cat ${LOADERCONF}.tmp | sed -E "s/^comconsole_speed.*$/comconsole_speed=${DQ}${BAUD}${DQ}/" > ${LOADERCONF}.tmp1
	    fi
    	    /bin/mv -f ${LOADERCONF}.tmp1 ${LOADERCONF}
	    /bin/rm -f ${LOADERCONF}.tmp
        fi
    fi
fi

if [ $SYS -eq 1 ] ; then
    CONSPEED=machdep.conspeed
    GDBSPEED=machdep.gdbspeed
    ## extract the old baud rate from the current setting
    NOWBAUD=`sysctl -n ${CONSPEED}`
    
    ## if that's not what we're looking for, force current now
    if [ "X$NOWBAUD" != "X$BAUD" ] ; then
        echo "Switching current baud from $NOWBAUD to $BAUD"
        sysctl ${CONSPEED}=${BAUD} > /dev/null
        sysctl ${GDBSPEED}=${BAUD} > /dev/null
    
        ## If we did just switch baudrate, all prior printouts were
        ## lost, so print something else now.  Make sure the serial port
        ## has a chance to idle first too.
        sleep 1
        echo "Finished switching baud from $NOWBAUD to $BAUD"
    fi
fi
