#!/bin/bash
# CDcontrol error messages handling

#
# Receive as first argument the CD drive number and as second the formatted date type
#
function cdcontrol_rel_gravados {
 local S_DATA
 S_DATA=`date +%d-%b-%Y`
 # Make a lock file, so other CD drivers that has sucess on write wait you 
 # time to write the status file.
 while lockfile -1 -! -r10 ${TMP_DIR}/.Gravados-${S_DATA}.lock;do 
  echo >/dev/null
 done
 #
 if [ ! -f ${LOG_DIR}/Gravados-$2 ];then
  touch ${LOG_DIR}/Gravados-$2
  for L_WRITTER in `seq 1 ${WRITTERS}`;do
   echo DRIVE${L_WRITTER}=0 >>${LOG_DIR}/Gravados-$2
  done
 fi
 #
 cat ${LOG_DIR}/Gravados-$2| \
     sed -e s/"DRIVE$1=.*"/"DRIVE$1=$[`cat ${LOG_DIR}/Gravados-$2| \
     grep DRIVE$1|cut -d '=' -f 2`+1]"/ >${LOG_DIR}/Gravados-$2
 # Remove o Lock File
 rm -f ${TMP_DIR}/.Gravados-${S_DATA}.lock
}


# Receive as first argumment the CD drive number and as second the formatted
# date type
function cdcontrol_rel_falhas {
 local S_DATA
 S_DATA=`date +%d-%b-%Y`
 # Make a lock file, so the CD drives will have to wait it time to write the status
 # file.
 while lockfile -1 -! -r10 ${TMP_DIR}/.Falhas-${S_DATA}.lock;do echo >/dev/null;done
 #
 if [ ! -f ${LOG_DIR}/Falhas-$2 ];then
  touch ${LOG_DIR}/Falhas-$2
  for L_WRITTER in `seq 1 ${WRITTERS}`;do
   echo DRIVE${L_WRITTER}=0 >>${LOG_DIR}/Falhas-$2
  done
 fi
 #
 cat ${LOG_DIR}/Falhas-$2| \
     sed -e s/"DRIVE$1=.*"/"DRIVE$1=$[`cat ${LOG_DIR}/Falhas-$2| \
     grep DRIVE$1|cut -d '=' -f 2`+1]"/ >${LOG_DIR}/Falhas-$2
 # Remove o Lock File
 rm -f ${TMP_DIR}/.Falhas-${S_DATA}.lock
}


# Create/Modify the technical report of error messages
# Receive as first argument the CD drive number
function cdcontrol_log_erros {
 echo "---------------------------[ `date +%T` ]---------------------------------" >>${LOG_DIR}/tec/Erros-Unidade$1-`date +%b-%d-%Y`
 cat ${TMP_DIR}/recorder$1-out >>${LOG_DIR}/tec/Erros-Unidade$1-`date +%b-%d-%Y`
 echo "--------------------------------------------------------------------------" >>${LOG_DIR}/tec/Erros-Unidade$1-`date +%b-%d-%Y`
}


# Change the ERROR field on configuration file, disable the drive on 
# excess of errors also writting a note about the drive being disabled.
# Receive as first argument the drive number and as second the error code
# (0 or 1)
function change_error_field {
 local L_VALOR
 L_VALOR="20000000000000000000000000000000000000000000000000000000000000000000000000000000"
 sed -e s/"ERRORS=2.*"/"$(cat ${CFG_DIR}/Recorder$1.cfg|grep 'ERRORS=')$2"/ \
     ${CFG_DIR}/Recorder$1.cfg >${TMP_DIR}/Recorder$1.temp
 mv -f ${TMP_DIR}/Recorder$1.temp ${CFG_DIR}/Recorder$1.cfg
 # Disable the drive if the number of errors excedeed the maximum limit 
 # (6 consecutive errors). The ERRORS fiel also is reseted (if the program don't 
 # do that, whan the drive will be again enabled will be possible to use it, but
 # if errors happen again, it will be disabled again).
 if [ $2 = 1 ];then
  if cat ${CFG_DIR}/Recorder$1.cfg|grep 'ERRORS='|grep '111111' >/dev/null;then
   echo $"Drive $1: Maximum error count excedeed! Writter auto disabled."
   cat ${CFG_DIR}/Recorder$1.cfg | \
     sed -e s/'ENABLED=1'/'ENABLED=0'/ -e s/"ERRORS=2.*"/'ERRORS=2'/ \
         -e s/"OBS=.*"/"OBS=Auto disabled due fails at $(date +'%d-%m-%Y - %T')"/ >${TMP_DIR}/Recorder$1.temp
     mv -f ${TMP_DIR}/Recorder$1.temp ${CFG_DIR}/Recorder$1.cfg
  fi
 fi
 # If the ERRORS field get really big, reduce it to ERRORS=2
 # (The previous errors were not preserved).
 if [ "$(echo ${L_VALOR}/`cat ${CFG_DIR}/Recorder$1.cfg|grep 'ERRORS='| \
        sed -e s/'ERRORS='//`|bc)" = "0" ];then
  cat ${CFG_DIR}/Recorder$1.cfg| \
    sed -e s/'ERRORS=2.*'/'ERRORS=2'/ >${TMP_DIR}/Recorder$1.temp
  mv -f ${TMP_DIR}/Recorder$1.temp ${CFG_DIR}/Recorder$1.cfg  
 fi
 # Log the sucess or fails of drive, running apropriate actions
 # acoording with the code $2
 if [ $2 = 0 ];then
  cdcontrol_rel_gravados $1 `date +%b-%d-%Y`.log
 else
  cdcontrol_rel_falhas $1 `date +%b-%d-%Y`.log
  cdcontrol_log_erros $1
 fi
}


# Eject a CD drive
# The SCSI ID argument should be passed as argument
function cdcontrol_eject_cd {
 cdrecord -eject -dev=`eval echo $1` &>/dev/null &
}


# Check the log file of each drive seeking for defaults and send messages to console
# Returns 1 if any error type happen and 0 if nothing was found and got to end 
# of conditions check. Receive as first argument the drive number and as second 
# it SCSI ID
function check_log_drive {
 local L_DRIVEMSG
 if [ ${VERBOSE} = 0 ];then
  L_DRIVEMSG=`grep 'Sense Code' ${TMP_DIR}/recorder$1-out`
  ###

  if echo ${L_DRIVEMSG}|grep -i 'invalid field in cdb' && \
     cat ${TMP_DIR}/recorder$1-out|grep -i 'Drive needs to reload the media' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mCD already written, ignoring the recording from this time"
   cdcontrol_eject_cd $2
   return 1
  fi

  # Thie was the message returned by Panasonic CW-7502/CW-7503 after insert a 
  # already written CD
  if echo ${L_DRIVEMSG}|grep -i 'illegal mode for this track' && \
     cat ${TMP_DIR}/recorder$1-out|grep -i 'Drive needs to reload the media' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mCD already written, ignoring the recording from this time"
   cdcontrol_eject_cd $2
   return 1
  fi

  #
  # This message was returned by Teac R55S after insert a alrealdy written CD
  #
  if echo ${L_DRIVEMSG}|grep -i 'write address is efm area - aleady written' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mCD already written, ignoring the recording from this time"
   cdcontrol_eject_cd $2
   return 1
  fi

  if echo ${L_DRIVEMSG}|grep -i 'tray open' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mTray open, ignoring the record this time"
   return 1
  fi

  if echo ${L_DRIVEMSG}|grep -i 'medium not present - tray closed' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mMedium not present or take out from drive"
   return 1
  fi

  if echo ${L_DRIVEMSG}|grep -i 'medium not present' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mMedium not present, ignoring the record from this time"
   return 1
  fi

  if echo ${L_DRIVEMSG}|grep -i 'write error - recovery failed' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mWrite fail due a medium problem (CD LOSED)."
   return 1
  fi

  if echo ${L_DRIVEMSG}|grep -i 'power calibration area is full' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mThe power calibration area is full, will not"
   echo $"            possible to write the CD here (try to write it on other recorder)"
   change_error_field $1 1
   return 1
  fi

  if echo ${L_DRIVEMSG}|grep -i 'illegal mode for this track' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mProblems found to write the CD (verify if the CD was written"
   echo $"            in most cases the CD isn't losed)."
   change_error_field $1 1
   return 1
  fi

  if echo ${L_DRIVEMSG}|grep -i 'power calibration area error' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mFail to adjust the laser power (the CD wasn't losed)."
   echo $"           Try to write the CD again, could be a heat excess"
   echo $"           on the drive. Also try to write the CD in another drive."
   echo $"           If the problem persists, send the $1 writter for repair."
   change_error_field $1 1
   return 1
  fi

  if echo ${L_DRIVEMSG}|grep -i 'write emergency' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mEmergency interrupt while writting the CD (the CD"
   echo $"            was losed). If this problem persists, sent the writter"
   echo $"            $1 for repair."
   change_error_field $1 1
   return 1
  fi

  if echo ${L_DRIVEMSG}|grep -i 'write error - loss of streaming' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mLoss of streaming - the CD was losed. It could be"
   echo $"            happen because of bad configuration or incompatibility)"
   change_error_field $1 1
   return 1
  fi

  if echo ${L_DRIVEMSG}|grep -i 'command sequence error' && \
     cat ${TMP_DIR}/recorder$1-out|grep -i 'min fill was 0' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mSource data error (the CD was losed)."
   cdcontrol_log_erros $1
   return 1
  fi

  if echo ${L_DRIVEMSG}|grep -i 'command sequence error' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mCommand sequence error (check the CD,"
   echo $"            maybe nothing was written on it)."
   change_error_field $1 1
   return 1
  fi

  if echo ${L_DRIVEMSG}|grep -i 'power on, reset, or bus device reset' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mThe writter was reseted, shutdown or happened a bus reset"
   echo $"            (wasn't possible to know if the CD was losed)"
   change_error_field $1 1
   return 1
  fi

  if echo ${L_DRIVEMSG}|grep -i 'logical unit is in process of becoming ready' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mNo response from unity (wasn't possible to know if"
   echo $"            the CD was losed)"
   change_error_field $1 1
   return 1
  fi

  if echo ${L_DRIVEMSG}|grep -i 'incompatible medium installed' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mIncompatible medium (the CD wasn't written)"
   return 1
  fi
  
  # Is recommended leave this as last by contained in some errors messages
  if echo ${L_DRIVEMSG}|grep -i 'invalid field in cdb' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mInvalid field in CDB (the CD was losed)"
   return 1
  fi


  #
  ## If no one "Sense Code" standard was found, process the checks bellow 
  #
  # incorrect SCSI ID
  if cat ${TMP_DIR}/recorder$1-out|grep -i 'Cannot open SCSI driver' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mCannot open SCSI driver from the specified SCSI ID"
   change_error_field $1 1
   return 1
  fi

  if cat ${TMP_DIR}/recorder$1-out|grep -i 'Trouble flushing the cache' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mTrouble flushing the cache (the CD was losed)"
   change_error_field $1 1
   return 1
  fi
  
  if cat ${TMP_DIR}/recorder$1-out|grep -i 'no disk / wrong disk' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mMedium not present or take out from drive"
   return 1
  fi

  if cat ${TMP_DIR}/recorder$1-out|grep -i 'OPC failed' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mOptimum Power Calibration error (the CD wasn't losed."
   echo $"            If the problem persists, sent the writter $1 for repair."
   change_error_field $1 1
   return 1
  fi
  if cat ${TMP_DIR}/recorder$1-out|grep -i 'no disk / wrong disk' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mThe CD wasn't inserted or removed from drive, ignoring write on this drive"
   return 1
  fi

  # Gravador falhando ao ler o CD virgem inserido na unidade
  if cat ${TMP_DIR}/recorder$1-out|grep -i 'Recorder not ready' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mCould't read the blank media"
   change_error_field $1 1
   return 1
  fi

  # Opo -data especificada para a gravao de audio
  if cat ${TMP_DIR}/recorder$1-out|grep -i 'Bad audio track size' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mOptions or image incompatible to write in audio mode"
   cdcontrol_log_erros $1
   return 1
  fi

  # Opo -audio especificada para a gravao de dados
  if cat ${TMP_DIR}/recorder$1-out|grep -i 'Inappropriate audio coding in' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mOptions or image incompatible to write in data mode"
   cdcontrol_log_erros $1
   return 1
  fi

  if cat ${TMP_DIR}/recorder$1-out|grep -i 'Data does not fit on current disk' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mThe data does not fit on current disk (the CD wasn't losed)."
   return 1
  fi

  if cat ${TMP_DIR}/recorder$1-out|grep -i 'No read access for' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mNo read access to source image"
   return 1
  fi
  
  if cat ${TMP_DIR}/recorder$1-out|grep -i 'SAO writing not available' >/dev/null;then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mSAO mode not available for this writter"
   return 1
  fi

  #
  # Leave by last. If no one Sense Code value be retornado mean that the writting
  # was not finished with sucess (some errors return exitcodes 0), so a unknown
  # error will be returned.
  #
  if [ ! -z "${L_DRIVEMSG}" ];then
   echo;echo -e $"\033[1;36mWritter $1: \033[0mUnknown error code, tell the program author (gleydson@debian.org), and sent the output written for this writter"
   cdcontrol_log_erros $1
   return 1
  fi

  ###
 fi
 return 0
}


#
# Receive as argument the CD drive number and as second argumment the SCSI ID.
# DON'T PUT NO ONE COMMAND ON FUNCTION START, IT WILL CHECK THE EXIT CODE OF
# LAST RUN COMMAND PASSED TO IT.
#
function check_cdcontrol_codes {
 if [ $? = 255 ];then
  # alto could happen when the -audio parameter is used on a data cd, for instance, 
  # whan you use a invalid SCSI ID for a drive (check if a repeated SCSI ID on a 
  # drive already in use generate this problem)
  check_log_drive $1 $2
  return
 fi 

 if [ $? = 254 ];then
  check_log_drive $1 $2
  return
 fi

 if [ $? = 2 ];then
  echo;echo -e $"\033[1;36mWritter $1: \033[0;36mWriting canceled by user"
  cdcontrol_eject_cd $2
  return
 fi

 #
 # All related steps with sucessfull on write should be placed here
 #
 if [ $? = 0 ];then
  # Also is returned when the writting is cancelled with a CTRL+C, or when
  # a writed media is inserted on drive
  check_log_drive $1 $2
  # Only change the ERRORS field if the write really had sucess, as some errors 
  # return exitcodes 0 and this is the reason of this function and don't allow
  # false count or fake reports
  if [ $? = 0 ];then
   change_error_field $1 0
   echo $[`cat ${TMP_DIR}/.c_total.temp`-1] >${TMP_DIR}/.c_total.temp
   echo;echo -e $"\033[1;36mWritter $1: \033[0mSuccessfully written"
   cdcontrol_eject_cd $2
  fi
  return
 fi
 
 # If come from here, mean that other exitcode was returned and you shold tell the
 # program's author
 echo $"Drive $1: Error code unknown, tell the program author at <gleydson@debian.org>"
 cdcontrol_log_erros $1
 cdcontrol_eject_cd $2
 
}

