Here's the (nearly last) refactoring:
(text should word wrap at 80, but the news program wants to wrap earlier---)

#!/usr/bin/ruby -w
#########################################################
#
# log_CID.rb
#
# Ruby CID logging script
#
#    Logs all activity at a modem set to decipher CID
#    (Caller ID) information. Archives the daily logs as well.
#
##########################################################

require 'zip/zip'
require 'serialport/serialport.so'
require 'yaml'

# name of config file (YAML format)
config_yaml = 'log_CID.yml'

#################################

# script local classes

class ModemCIDMonitor
     attr_reader :port_err_count, :config, :log_blank_lines
     attr :debug, :port_err_count

     def initialize(config_hash, logger)
         @port_err_count     = config_hash['port_err_count']         || 0
         @port_name          = config_hash['port_name']              || 
'COM1:'
         @port               = SerialPort.new(@port_name)
         @MAX_PORT_ERRORS    = config_hash['MAX_PORT_ERRORS']        || 100
         @debug              = config_hash['DEBUG']                  || 
false
         @log_blank_lines    = config_hash['log_blank_lines']        || 
false
         @logger             = logger
         @port.read_timeout  = 0
         @port_err_count     = 0
         @modem_init_string  =
           config_hash['modem_init_string'] || "AT+VCID=1\r\n"
         @port.puts(@modem_init_string)
     end

     def log(txt)
         print txt if debug
         @logger.log_text(txt)
     end

     def run
         print  "Starting run with port ",  @port_name,
           " and logging to dir ", @logger.archive_dir, "\n"
         loop do
             @port.each_line do | text |
                 # log text unless it is just spaces
                 next unless text =~ /\S/ or log_blank_lines
                     # squeeze double \r, etc to just \n
                     text.sub!(/[\r\n]+/, "\n")
                     log(text)
             end
             msg =
              "#{Time.now.to_s}: dropped out of system call, restarting 
loop.\n"
             log(msg) if debug
             @port_err_count += 1
             if(@port_err_count > MAX_PORT_ERRORS)
                 errmsg = "Too many port errors...ending run\n"
                 log(errmsg)
                 return errmsg
             end
         end
     end
end

class CID_Config
     attr_reader :config_file, :as_hash

     def initialize(config_file)
         @config_file    = config_file
         @as_hash        = YAML::load( File.open(@config_file))
     end
end

class DailyLogWithArchive
     attr_reader :archive_dir, :base_log_name, :archive_zip_filename,
       :archive_days_secs, :archive_days_interval
     attr :debug

     def initialize(config_hash)
         @archive_dir            = config_hash['archive_dir'] 
  || './'
         @base_log_name          = config_hash['base_log_name'] 
  || 'CID'
         @debug                  = config_hash['DEBUG'] 
  || false
         @archive_days_interval  = config_hash['archive_days_interval'] 
  || 1
         @archive_zip_filename   = config_hash['archive_zip_filename']   ||
                                     'CID_archive.zip'
         @last_archive_day       = -1
         @archive_days_secs      = 60 * 60 * 24 * 7
         @archive_days_secs      =
           60 * 60 * 24 * config_hash['days_before_archive'] if
             (config_hash['days_before_archive'])
     end

     def current_fname
         "#{archive_dir}/#{base_log_name}#{Time.now.strftime("%Y%m%d")}.log"
     end

     def archive_old_to_zip
         time = Time.now
         wd = Dir.getwd
         Dir.chdir(@archive_dir)
         dir = Dir.open(@archive_dir)
         moved = dir.inject(0) do | move_count, logfile |
             next unless logfile
             next unless logfile =~ /^#{base_log_name}/
             next unless time > File.stat(logfile).mtime + 
@archive_days_secs
             if(move_to_archive(logfile))
                 log_text("LOGGER: Archiving file " + logfile + "\n") if 
@debug
                 next move_count + 1
             else
                 next move_count
             end
         end
         dir.close
         Dir.chdir(wd)
         return moved
     end

     def move_to_archive(fname)
         Zip::ZipFile.open(@archive_zip_filename, 1) {
             | zfile |
             return nil if zfile.exist?(fname)
             zfile.add(fname, fname)
         }
         File.delete(fname)
     end

     def log_text(txt)
         wd = Dir.getwd
         Dir.chdir(@archive_dir)
         logfile = File.new(current_fname, "a")
         logfile.print(txt)
         logfile.close
         # check if we should do periodic archiving (up to daily)
         time = Time.now
         yday = time.yday
         if(yday != @last_archive_day and
           (yday >= @last_archive_day + @archive_days_interval or yday 
== 0) )
             archive_old_to_zip
             @last_archive_day = yday
         end
         Dir.chdir(wd)
     end
end


###############################
# begin main program

# get config from YAML text file
config = CID_Config.new(config_yaml)

# set up the logging class
logger = DailyLogWithArchive.new(config.as_hash)

# set up modem monitor
monitor = ModemCIDMonitor.new(config.as_hash, logger)

# run -- no return from this unless abort on port timeouts or errors
errmsg = monitor.run

print errmsg

return 0

=================================================

log_CID.yml file:

############################################
#
# log_CID YAML config file.
#

# name of archive file--daily logs are moved to this archive
archive_zip_filename:   CID_Data.zip

# modem initialization string.
# need to set to log verbose caller ID information (+VCID=1 or #CID=1, etc)
# also need to set to NOT answer, just monitor line (usually the default)
modem_init_string:      AT+VCID=1\r\n

# directory to keep log files
archive_dir:            c:/USR/log_CID

# base log name for daily log files
# daily log file name is this, plus YYYYMMDD date, plus .log extension
# eg. CID20041004.log
base_log_name:          CID

# the comm port having the CID-capable modem
port_name:              'COM3:'

# days that a daily log file is kept prior to archiving the file
days_before_archive:    7

# maximum port read errors allowed before aborting run
MAX_PORT_ERRORS:        3000

# whether to log whitespace-only lines
log_blank_lines:        false

# debug on or off?
DEBUG:                  true

#
# end YAML config file.
#
#####################################################