#!/bin/bash
#
# script: rc.serial
#
# Initializes the serial ports on your system
#
# chkconfig: 2345 50 75
# description: This initializes the settings of the serial port
#
# FILE_VERSION: 19981128
#
# Distributed with setserial and the serial driver.  We need to use the
# FILE_VERSION field to assure that we don't overwrite a newer rc.serial
# file with a newer one.
#
# XXXX For now, the autosave feature doesn't work if you are
# using the multiport feature; it doesn't save the multiport configuration
# (for now).  Autosave also doesn't work for the hayes devices.
#
# LimeTech - modified for Unraid OS
# Bergware - modified for Unraid OS, October 2023

# Set the path.
PATH=/bin:/sbin:/usr/bin

RCLOCKFILE="/var/lock/subsys/serial"
DIRS="/lib/modules/`uname -r`/misc /lib/modules /usr/lib/modules ."
DRIVER="serial"
DRIVER_NAME="serial"
MODULE_REGEXP="serial\b"
SERIAL="/etc/serial.conf"
ALLDEVS="/dev/ttyS?"
SETSERIAL=""
LOADED=""

# run & log functions
. /etc/rc.d/rc.runlog

if ls /dev/ttyS?? >& /dev/null; then
  ALLDEVS="$ALLDEVS /dev/ttyS??"
fi

if [[ -x /bin/setserial ]]; then
  SETSERIAL=/bin/setserial
elif [[ -x /sbin/setserial ]]; then
  SETSERIAL=/sbin/setserial
fi

# See if the serial driver is loaded
if [[ -f /proc/devices ]]; then
  if grep -q " ttyS$" /proc/devices; then
    LOADED="yes"
  else
    LOADED="no"
  fi
fi

# Find the serial driver
for i in $DIRS; do
  if [[ -z $MODULE && -f $i/$DRIVER.o ]]; then
    MODULE=$i/$DRIVER.o
  fi
done
[[ -f /proc/modules ]] || MODULE=""

# Handle System V init conventions...
case "$1" in
'start')
  ACTION="start"
  ;;
'stop')
  ACTION="stop"
  ;;
*)
  ACTION="start"
esac

if [[ $ACTION == stop ]]; then
  if [[ -n $SETSERIAL && $LOADED != no && "$(head -1 $SERIAL)X" == "###AUTOSAVE###X" ]]; then
    log "Saving state of serial devices."
    grep "^#" $SERIAL >/etc/.serial.conf.new
    $SETSERIAL -G -g $ALLDEVS >>/etc/.serial.conf.new
    mv $SERIAL /etc/.serial.conf.old
    mv /etc/.serial.conf.new $SERIAL
  fi
  if [[ -n $MODULE ]]; then
    MODULE=$(grep $MODULE_REGEXP /proc/modules | awk '{print $1}')
    if [[ -z $MODULE ]]; then
      log "The $DRIVER_NAME driver is not loaded."
      rm -f $RCLOCKFILE
      exit 0
    fi
    if ! rmmod $MODULE; then
      log "The $DRIVER_NAME driver could NOT be unloaded."
      exit 1
    fi
    log "The $DRIVER_NAME driver has been unloaded."
  fi
  rm -f $RCLOCKFILE
  exit 0
fi

# If not stop, it must be a start....
if [[ -n $MODULE && $LOADED != yes ]]; then
  if insmod -f $MODULE $DRIVER_ARG; then
    true
  else
    log "Couldn't load $DRIVER_NAME driver."
    exit 1
  fi
fi

if [[ -f $SERIAL ]]; then
  if [[ -n $SETSERIAL ]]; then
    grep -v ^# <$SERIAL | while read DEVICE ARGS; do
      if [[ -n $DEVICE && -n $ARGS ]]; then
        $SETSERIAL -z $DEVICE $ARGS
      fi
    done
  fi
else
  echo "###AUTOSAVE###" >$SERIAL
fi

touch $RCLOCKFILE
$SETSERIAL -bg $ALLDEVS
exit 0
