Cover V11, I12

Article
Listing 1
Listing 2

dec2002.tar

Listing 1 superserver/subserver, superclient/subclient quartet

SG.AWK -------------------------------------------------------------

#!/bin/awk -f
# sg.awk PORT_NUMBER SUBSERVER_PORT_CUR SUBSERVER_PORT_BEG SUBSERVER_PORT_END
#
# This superserver spawns subservers to service requests to transfer
# files on the server to remote clients. When the superserver is contacted
# by a superclient, it is passed the type of file being transferred.  The
# superserver uses a block of port numbers whose extremes are passed on the
# cmdline. The current port number in use is held in ARGV[2]. It then spawns
# a subserver, sg2.awk, passing it on the commandline the port on which to
# service and the type of file, ?/b, being transferred to the superclient.
# The superserver then writes the port number being used by the spawned
# server to the socket connected to the superclient. The superclient will
# spawn a client to complete the transaction on the passed port. The
# superserver then closes the socket and spawns another copy of itself to
# service the superport.
#
# Superserver SG.AWK pairs with superclient CP.AWK.
# Superserver SG.AWK spawns subserver SG2.AWK.
# Superclient CP.AWK spawns subclient CP2.AWK.

BEGIN {
# Client picks up port here.
  system("echo " ARGV[1] " > /var/run/sg.port")
  Net = ("/inet/tcp/" ARGV[1] "/localhost/0")
# Sit on the socket, awaiting a Client. Client transmits
# (host filetype)
  Net |& getline
  if (NF<2) {
    print $0
    print "Bad argument count: 2 expected."
  } else {
  # Spawn SUBSERVER. In this order, pass HOST PORT FILETYPE
    sys = sprintf ("/cmn/scr/sg2.awk %s %d %s &",$1,ARGV[2],$2)
    system (sys)
  # Give the SUBSERVER time to establish a  port.
    system("sleep 2")
  # Tell the SUPERCLIENT what port the SUBCLIENT should talk on.
    print ARGV[2] |& Net
    close (Net)
  # Calculate next port number.
    port=ARGV[2]+1
    if (port > ARGV[4]) port=ARGV[3]
  }
  close (Net)
# Get forked.
  sys=sprintf("/cmn/scr/sg.awk %d %d %d %d &",ARGV[1],port,ARGV[3],ARGV[4])
  system (sys)
}

SG2.AWK ------------------------------------------------------------

#!/bin/awk -f
# sg2.awk REMOTE_HOST PORT_NUMBER ?/b &
#
# This subserver is passed the following commandline parameters:
# ARGV[1]: ip number of remote host
# ARGV[2]: port to connect to on localhost on which to talk to SUBCLIENT.
# ARGV[3]: type of file being transferred. ?/b for text/binary.
#
# From the SUBCLIENT, this subserver receives the following items in this order:
# 1. In one transmission, two items separated by space:
#    - $1 : A string of permissions to be applied to the created file.
#    - $2 : The name of a file to create on this server's box.
# 2. Streaming content copied to the local file named in [1].
#
# This subserver is spawned by superserver SG.AWK.

BEGIN {
  Net = ("/inet/tcp/" ARGV[2] "/localhost/0")
# Sit on the socket, awaiting the SUBCLIENT.
  Net |& getline
# Get permissions to apply and name of file to create.
  perm = $1
  file = $2
# Transfer algorithm dictated by filetype.
  if (ARGV[3]=="b") {
    n=1
    while (1) {
      rc1 = Net |& getline rec1
      if (rc1<=0) {
        printf "%s",rec2 > file
        break
      }
      if (n>1) print rec2 > file
      rc2 = Net |& getline rec2
      if (rc2<=0) {
        printf "%s",rec1 > file
        break
      }
      print rec1 > file
      ++n
    }
  } else {
    while ((Net |& getline rec) > 0) print rec > file
  }
  close (Net)
  system ("chmod " perm " " file)
  system ("date >> /var/log/sg2")
  l = sprintf("/cmn/scr/sg2.awk %s %s (file=%s, perm=%s)",ARGV[1],ARGV[2],file,perm)
  print l >> "/var/log/sg2"
}

CP.AWK ------------------------------------------------------------

#!/bin/awk -f
# cp.awk  remotehost  permissions  ftype  local-file  [remote-file]
#
# This superclient contacts a remote superserver in order to initiate a file 
# transfer from the remote server to the client. The superclient contacts the 
# superserver by sending it the name of the client's host and a character: 
# ?/b, for the type of file being requested. The superclient then sits on the 
# socket awaiting the port number on which to transfer the file. When it 
# receives the port number, the superclient spawns a subclient to receive the 
# file. It passes along its commandline data to the subclient plus the port 
# number on which to perform the transfer.
#
# Superclient CP.AWK spawns subclient CP2.AWK. 
# Superclient CP.AWK pairs with superserver SG.AWK.

BEGIN {
  if (ARGC<5) {
    print ("cp.awk " ARGV[1] " " ARGV[2] " " ARGV[3] " " ARGV[4])
    print "cp.awk remotehost permissions ftype local-file [remote-file]"
    print "if ARGV[5] is absent, ARGV[5]=ARGV[4]"
    print "cp.awk  galleon  u+x  [?,b]  /local/file  /remote/file"
#          0       1        2    3      4            5
  } else {
#   Get port on which to talk to a remote SG.AWK
    getline < "/var/run/sg.port"
    if (NF==0) {
      print "cp.awk: no file: /var/run/sg.port"
      exit 1
    }
# Sanity check
   if (ENVIRON["HOSTNAME"]=="") {
     print "cp.awk: environment variable HOSTNAME is null."
     exit
   }
# Setup tcp/ip
    Net = ("/inet/tcp/0/" ARGV[1] "/" $1)
# If no [5], the path/file is identical on the remote host.
    if (ARGC<6) ARGV[5]=ARGV[4]
# Transmit (host filetype) to the remote server
   sys=sprintf ("%s %s",ENVIRON["HOSTNAME"],ARGV[3]) 
   print sys |& Net
# Await the transaction subport
    Net |& getline subport
    close (Net)
# Invoke subclient
    sys = sprintf ("/cmn/scr/cp2.awk %s %s %s %s %s \
                   &",ARGV[1],subport,ARGV[2],ARGV[4],ARGV[5])
    system (sys)
  }
}

CP2.AWK ----------------------------------------------------------------

#!/bin/awk -f
# This subclient transmits three items in this order to a subserver:
# 1. A string of permissions to be applied to the file on the server's end.
# 2. The name of a file to be created by the server on the server's machine.
# 3. The content of the file named in [1].
#
# This subclient is spawned by superclient CP.AWK.
# This subclient pairs with subserver SG2.AWK.
#
#  Usage: cp2.awk remotehost port permissions local-file remote-file

BEGIN {
  if (ARGC<6) {
    print "cp2.awk remotehost port permissions local-file remote-file"
    print "cp2.awk  galleon  port  u+x  /local/file  /remote/file"
#          0        1        2     3    4            5
  } else {
    Net = ("/inet/tcp/0/" ARGV[1] "/" ARGV[2])
    args = (ARGV[3] " " ARGV[5])
    print args |& Net
    while ((getline rec < ARGV[4]) > 0) print rec |& Net
    close (Net)
    system ("date >> /var/log/cp2")
    l = sprintf("/cmn/scr/cp2.awk %s %s %s %s \
                %s",ARGV[1],ARGV[2],ARGV[3],ARGV[4],ARGV[5])
    print l >> "/var/log/cp2"
  }
}