#!/bin/ksh
# @(#)95        0.2  sendto1.sh   June 10 2002

VERSION="0.3"

#
# COMPONENT_NAME: SENDTO1/GETFROM1
#
# FUNCTIONS:
#
# ORIGINS:
#   5-02-2002 - IHS/RAW created sendto1
#   6-10-2002 - IHS/RAW added the -w option to specify a directory to
#               capture the log and error file.
#
# FILE NAME: sendto1
#
# FILE DESCRIPTION: High-level KORN shell script to send/get a file
#   to/from a site via ftp.
#
#   Install sendto1 into the /usr/bin directory and link to getfrom1:
#     install -o sendto1
#     ln -f /usr/bin/sendto1 /usr/bin/getfrom1
#
#   Basic functions performed are:
#     1)  transmit file(s) to site(s) that are on the Internet network via
#         FTP.
#     2)  receive a file from a site that are on the Internet network via
#         FTP.
#
#     See Usage message for explanation of parms
#
#
# RETURN VALUE DESCRIPTION:
#                             0         Successful
#                             non-zero  Unsuccessful
#
# EXTERNAL PROCEDURES CALLED: (other than standard utilities)
#       ftp - The -n is used to avoid clashing with .netrc files.
#             The -i to avoid interactive prompting with multiple files.
#             The -v to get a dialog of the ftp session and hence its
#             results.
#             By default, files are grabbed from the anonymous ftp pub
#             directory remotely and placed in the anonymous ftp pub
#             directory locally.
#      gzip - The -v is used for verbose mode.
#             The -9 is used to compress better.
#  compress - The -f is used to Force compression of the file
#             The -v is used write the percentage of compression
#
# GLOBAL VARIABLES:
#   DEBUG - Set DEBUG to true and export to invoke debug mode for the
#           script. (ex. export DEBUG=true )
#    RDIR - The Remote DIR variable can be set prior to call to use
#           other than the default directories.
#    LDIR - The Local DIR variable can be set prior to call to use
#           other than the default directories.
#    Note:  The remote directory must always be either the ftp pub
#           directory or one of its subdirectories.
#

################################# USAGE #######################################
#
# NAME: USAGE()
#
# DESCRIPTION: Issue "usage" message and exit.
#
# INPUT:
#        None
#
# OUTPUT:
#        Error messages (Standard Error)
#
# RETURN VALUE DESCRIPTION:
#                           2
#
# NOTE: This function will not return (i.e., it will exit the entire
#       script with exit status of 2).

USAGE () {
  sendtohelp () {
    if [ -x /usr/bin/gzip ]
    then
      print - "\t-g = compress file with 'gzip' before sending"
    else
      print - "\t-c = compress file with 'compress' before sending"
    fi
    print - "\nFTP Options:"
    print - "\t-b = invoke binary mode (default is ascii)"
    print - "\t-l user:password = use user:password as ftp login"
    print - "\t-r remote_dir = use remote subdirectory to send the file into"
    print - "\t-u = to turn OFF copy unique (sunique)"
    print - "\t-w work_dir = use local directory to retain copy of activity"
    print - "\t              and error log files"
    print - "\nExample:"
    print - "\tTo send a file to cmbsyb compressed with the 'gzip' utility:"
    print - "\t\tsendto1 -g cmbsyb filename"
  }
  
  getfromhelp () {
    print - "\t-b = invoke binary mode (default is ascii)"
    print - "\t-l user:password = use user:password as ftp login"
    print - "\t-r remote_dir = use remote subdirectory to get the file from"
    print - "\t-u = to turn OFF copy unique (runique)"
    print - "\t-w work_dir = use local directory to retain copy of activity"
    print - "\t              and error log files"
    print - "\nExample:"
    print - "\tTo retrieve a file from cmbsyb PATCHES directory:"
    print - "\t\tgetfrom1 -rPATCHES cmbsyb patchfile"
  }

  print - "\nUSAGE:  ${PROG} [ options ] host_name file_name [ EXT ]"
  print - "\nGeneral Options:"
  case ${PROG} in
    sendto1)   sendtohelp ;;
    getfrom1)  getfromhelp ;;
  esac
  print - "\n\tEXT - if provided, the number will be used as a file name"
  print - "\t      extension for the error and log files. The user will"
  print - "\t      have to perform a manual purge of the files"
  exit 2
}

preproc () {
  [ "${DEBUG}" = "true" ] && set -x
  errcheck () {
    sleep 2
    [ -s ${ERRORFIL} ] && ERROR=$(awk '{if ($1>499) print}' ${ERRORFIL})
    [ -n "${ERROR}" ] && return 3
    return 0
  }

  unset ERROR
  while true
  do
    [ ${SYS} = "${LSYS}" -a -n "$(uname -a | grep AIX)" ] &&\
       print "copylocal"
    print - "user ${FTPUSER} ${PASS}"
    errcheck || break
    print - "${FTYPE}"
    if [ "${COPYUNIQUE}" = "true" ]
    then
      case ${PROG} in
        sendto1)   print - "sunique" ;;
        getfrom1)  print - "lcd ${FTPLDIR}"
                   print - "runique"
                   ;;
      esac
    fi
    if [ -n "${FTPRDIR}" ]
    then
      print - "cd ${FTPRDIR}"
      errcheck || break
    fi
    if [ ${DIRNAM} != "." ]
    then
      case ${PROG} in
        sendto1)   print - "lcd ${DIRNAM}" ;;
        getfrom1)  print - "cd ${DIRNAM}"
                   errcheck || break
                   ;;
      esac
    fi
    print - "${FILECOM} ${FILNAM}"
    errcheck || break
    [ ${PROG} = getfrom1 ] && print - "cdup"
    break
  done
  print - "bye"
}

postproc () {
  while read LINE
  do
    print - ${LINE}
    print - ${LINE} |\
      awk '/^[0-9][0-9][0-9] / {if ($1>399 && $2!~/byte/)
        print $0 > x}' x=${ERRORFIL}
  done
}

parseopts () {
  MINARG=2                           # MINimum ARGuments default
  case ${PROG} in                    # Set the appropriate options for
    sendto1)   OPTARGS="bcduxl:r:w:".   # parsing by getopts.
               [ -x /usr/bin/gzip ] && OPTARGS="bdguxl:r:w:"
               ;;
    getfrom1)  OPTARGS="bduxl:r:w:" ;;
  esac

  # Parse command flags and arguments
  set -- $(getopt ${OPTARGS} $*)
  [ $? -ne 0 ] && USAGE
  for ARG in $*
  do
    case ${ARG} in
      -b)  FTYPE=bi                  # Change to binary mode for ftp
           shift
           ;;
      -c)  PACK="compress -fv"       # Set file compression command to
           FILEXT=Z                  # use 'compress'
           shift
           ;;
      -d)  FTPCOMMAND="ftp -dniv"    # Set for ftp debug mode on
           shift
           ;;
      -g)  PACK="gzip -9v"           # Set file compression command to
           FILEXT=gz                 # use 'gzip'
           shift
           ;;
      -u)  COPYUNIQUE=false          # Set to turn off copy unique
           shift
           ;;
      -x)  DEBUG=true
           shift
           ;;
      -l)  shift
           FTPUSER=${1%%:*}          # Parse out login name
           PASS=${1##*:}             # Parse out password
           shift
           ;;
      -r)  shift                     # Check if '/' is first character
           RDIR=${1#/}               # Insert directory name to '/'
           shift                     # A '/' precedes directory name
           ;;
      -w)  shift
           [ -d "${1}" ] && TMP=${1}
           unset FILDEL
           shift
           ;;
      --)  shift; break;;
    esac
  done

  #  check for MINinmum ARGuments
  [ $# -lt ${MINARG} ] && USAGE
  if host ${1} > /dev/null 2>&1
  then
    SYS=$(host ${1} | awk '{print $1}')
  else
    SYS=${1}
  fi
  FIL=${2}
  if [ -n "${3}" ]
  then
    [ ${TMP} = "/usr/tmp" ] && TMP=${HOME}
    EXT=${3}
    unset FILDEL
  fi
}

parmchk () {
  [ "${DEBUG}" = "true" ] && set -x
  if [ ! -d "${FTPLDIR}" ]
  then
    print - "001 '${FTPLDIR}' directory not found" >> ${ERRORFIL}
    return 1
  fi

  # Check to ensure that the FIL argument is a file and length is > 0
  if [ ${PROG} = sendto1 ]
  then
    if [ ! -s ${FIL} ]
    then
      print - "001 '${FIL}' file not found or is zero length" >> ${ERRORFIL}
      return 1
    fi
    if [ -n "${PACK}" ]
    then                          # If file needs to be compressed
      if ${PACK} ${FIL}           # then execute the compression command
      then
        FIL=${FIL}.${FILEXT}
      else
        print - "001 Error in packing ${FIL} file" >> ${ERRORFIL}
        return 1
      fi
    fi
  fi
  [ ${FIL##*.} = z -o ${FIL##*.} = Z -o ${FIL##*.} = gz ] &&\
    FTYPE=bi
  FILNAM=$(basename ${FIL})
  DIRNAM=$(dirname ${FIL})

  # Check to ensure the systemid is a valid system id
  unset COMMAND
  if ftpchek ${SYS} > /dev/null 2>&1
  then
    COMMAND=${FTPCOMMAND:-"ftp -niv"}
    case ${PROG} in
      sendto1) FILECOM=put ;;
      getfrom1) FILECOM=get ;;
    esac
  else
    print - "001 '${SYS}' system not recognized on the Network." >> ${ERRORFIL}
    return 1
  fi
}

main () {
  [ "${DEBUG}" = "true" ] && set -x
  ####################  DEFAULTS  ##############################################
  #
  FTPUSER=${FTPUSER:-anonymous}
  PASS=${PASS:-${LOGNAME}@$(hostname)}
  FTYPE=${FTYPE:-as}
  COPYUNIQUE=${COPYUNIQUE:-true}
  LSYS=$(hostname)
  if [ "${FTPUSER}" = "anonymous" ]
  then
    FTPRDIR="pub"
    FTPLDIR=${LDIR:-$(awk -F: '/^anonymou/ {print $6}' /etc/passwd)/pub}
  elif [ -n "${RDIR}" ]
  then
    FTPRDIR=${RDIR}
  else
    unset FTPRDIR
  fi
  [ -n "${RDIR}" -a "${FTPUSER}" = "anonymous" ] && FTPRDIR=pub/${RDIR}
  FTPLDIR=${FTPLDIR:-${HOME}}

  parmchk || return 1

  # FTP Processing
  print - "Attempting ftp connection to ${SYS}"
  preproc | ${COMMAND} ${SYS} | postproc
}

############################## main ############################################

# Ensure that Korn SHell is the executing shell
[ "${RANDOM}" = "${RANDOM}" ] && exec /bin/ksh -c "${0}" ${@+"${@}"}
# Debug mode is activated
if [ "${DEBUG}" = "true" ]
then
  unset DEBUG
  exec /bin/ksh -x "${0}" -dx ${@+"${@}"}
fi
PROG=$(basename $0)                # Capture name of PROGram
EXT=$$
FILDEL=true
TMP=/usr/tmp
parseopts $*
ERRORFIL=${TMP}/${PROG}.error.${EXT}
LOGFIL=${TMP}/${PROG}.log.${EXT}
{
print - "${PROG} Version ${VERSION}\n"
main
} | tee ${LOGFIL}

if [ -s ${ERRORFIL} ]
then
  print - "\n${PROG}: \c"
  cat ${ERRORFIL}
  ERROR=$(awk '/^[0-9][0-9][0-9] / {print $1}' ${ERRORFIL})
  [ -n "${FILDEL}" ] && rm -f ${ERRORFIL} ${LOGFIL}
  exit ${ERROR}
else
  exit 0
fi
