AutoFTP (Crossposting)

David F. Skoll dfs at doe.carleton.ca
Thu Dec 13 04:57:38 AEST 1990


This program was originally posted on comp.binaries.ibm.pc.d by Kevin
D. Quitt.  I posted a patch to it on alt.sources; many people wrote
asking where the original program appeared.  So here it is!
(Actually, this is a reposting of a reposting...)

----- REPOSTED ARTICLE ----
>From comp.binaries.ibm.pc.d Wed Dec 12 12:55:30 1990
Path: cunews!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sdd.hp.com!usc!srhqla!demott!kdq
From: kdq at demott.com (Kevin D. Quitt)
Newsgroups: comp.binaries.ibm.pc.d
Subject: AUTOFTP30 - Here it is!
Message-ID: <1990Dec6.222640.9709 at demott.com>
Date: 6 Dec 90 22:26:40 GMT
Reply-To: kdq at demott.COM (Kevin D. Quitt)
Organization: DeMott Electronics Co., Van Nuys CA
Lines: 1384


    I got 10 requests with 6 hours!  Note that this is a reposting:

Article xxxx of comp.binaries.ibm.pc.d:
~From: weisen at eniac.seas.upenn.edu (Neil Weisenfeld)
~Newsgroups: comp.binaries.ibm.pc.d
~Date: 30 Mar 90 22:04:44 GMT
      ^^^^^^^^^

               O /
----------------X---------------- Cut Here
               O \


#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	README
#	autoftp30.sh
#	checkout.c
#	ftpget.c
#	nextfile.c
#	sample.dat
# This archive created: Tue Jul 18 16:29:20 1989
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'README'" '(13337 characters)'
if test -f 'README'
then
	echo shar: "will not over-write existing file 'README'"
else
sed 's/^	X//' << \SHAR_EOF > 'README'
	X
	X		        AutoFtp Version 3.0
	X			 (Previously GET21)
	X
	X		     	     FreeWare
	X
	X	 		    Mingqi Deng
	X			    July 6, 1989
	X
	X
	X			     Contents
	X	1) .......................................... Description
	X	2) .............................. Contents of Version 3.0
	X	3) ............................................... Set Up
	X	4) ............................................ Execution
	X	5) .............................................. History
	X	
	X
	X   AutoFtp is a UNIX Bourne shell program that automates the ftp processes
	Xto get a number of files from a site that allows ftp file transfer. It 
	Xwill repeatedly try for a good connection until all the files requested
	Xare transferred.  A user need not baby-sit the ftp process, thus is 
	Xrelieved from the frustration of numerous unsuccessful ftp attempts. 
	X
	X   The program is based on GET20 ftp script by Ferd Boundick, and was 
	Xoriginally written for my own use after a long suffering from ftp into 
	XSIMTEL20.  It has been fully tested. This release has the following new
	Xfeatures:
	X
	X   1) A bug that allows a request for a non-existing file to go on
	X      forever has been fixed.
	X   2) Users now can run a process of name [*]sleep[*] while running the
	X      autoftp without having any interferences in between. This is
	X      because the new version of autoftp uses process ID in its actions
	X      instead of their names as in the old version.
	X   3) Changing local directory during ftp and getting directory list are
	X      supported now.
	X   4) This versio will not affect the .netrc file. It simply avoids
	X      using it.
	X   5) A randomized retry timing sequence has been implemented. In the 
	X      previous version, there is a chance that several copies of the 
	X      auto-ftp can get into synchrony. Consequently, none of them can get 
	X      logged into SIMTEL20. This release minimizes this possibility and
	X      also smoothes the load at SIMTEL20 thus all users will have a better
	X      chance to login to SIMTEL20 on the average.
	X   6) More and better error handlings are implemented. In particular, 
	X      it will complain if the ALARM is too small for a large file. 
	X   7) The awkward run.sh file in release 2.1 has been replaced by a 
	X      simpler input file.
	X   8) The number of working files is reduced to 5 for the entire run
	X      from 5 for each file requested. Moreover, there is just one
	X      file for the entire ftp history instead one for each file
	X      requested.
	X
	X   This release is a complete rewriting of the previous version, as 
	Xa result of my discussion with Keith Peterson at SIMTEL20. The major 
	Xpart of the shell script has been replaced by three C programs. This 
	Xprovides a more natural and better program structure, thus more freedom
	Xin analyzing each ftp session.
	X
	X   This is a freeware, meaning that it can be copied and used freely. 
	XBut the programs must NOT be sold for profit.
	X
	X   Problems, improvements, comments and suggestions can be sent to the
	Xauthor at:
	X
	XE-mail:				Postal Mail:
	X
	X  deng at shire.cs.psu.edu	          333 Whitmore Lab
	X  deng at psuvaxs.bitnet		  Computer Science Department
	X  deng at psuvaxs.uucp		  The Pennsylvania State University
	X				  University Park, PA 16802
	X========================================================================
	X
	XAll of the files contained in version 3.0 are:
	X
	X   	README        this file
	X   	autoftp30.sh  the main program
	X   	nextfile.c    used by autoftp30.sh to prepare for an ftp attempt
	X   	ftpget.c      used by autoftp30.sh for one ftp attempt
	X   	checkout.c    used by autoftp30.sh to analyze an ftp's result
	X        sample.dat    a sample input data file for autoftp30.sh,
	X		      consisting of a name list of the requested files
	X		      to be transferred from WSMR-SIMTEL20.ARMY.MIL.
	X
	X========================================================================
	X
	XSet Up:
	X
	X  1. Do a "man ftp" to see if the constant TENEX defined on line 49 in 
	X     nextfile.c needs to be adjusted. Refer to Note #2 in the head 
	X     comment block in nextfile.c for more instructions.
	X
	X  2. Compile the three C programs by typing:
	X
	X           cc -o checkout checkout.c
	X           cc -o ftpget   ftpget.c
	X           cc -o nextfile nextfile.c
	X
	X     This will produce three executable files named "checkout", "ftpget"
	X     and "nextfile".
	X
	X     *NOTE*: Each of the programs has a "Note" section in their head
	X	     comment block that provides information about the pre-
	X	     defined constants used in the program. If anything goes
	X	     suspiciously, adjust them properly.
	X
	X  3. Place the three compiled C programs in a directory of your choice.
	X     However, if the directory is not named "bin" and in your home 
	X     directory, you will have to adjust the shell variable FtpLibDir
	X     in autoftp30.sh (cf. autoftp30.sh). The default is $HOME/bin. For
	X     example, if your home directory is "/usr/usr/deng", then the 
	X     default directory is "/usr/usr/deng/bin".
	X
	X  4. Adjust the following three shell variables in autoftp30.sh:
	X
	X     		RemoteHost, ALARM, FtpLibDir
	X
	X     Instructions and examples are given in autoftp30.sh.
	X   
	X     *NOTE*: You may have to change LocalHost in autoftp30.sh (on the
	X	     lines next to RemoteHost) from "guest" to your machine's
	X	     address, if login to SIMTEL20 is always denied. Refer
	X	     to autoftp30.sh.
	X
	X  5. If you have any executable files of your own of the following names:
	X
	X         cat chmod cp echo expr grep mv rm sed sh sleep test
	X
	X     then rename them using different names. These are UNIX commands'
	X     names, thus should not be taken over by a user's own executables.
	X
	X========================================================================
	X
	XExecution:
	X
	X  1. Prepare an input file that contains a name list of files you want
	X     to get from a remote host (cf. sample.dat). The file consists of 
	X     two types of lines: device-directory line (DDL) and file-line (FL).
	X
	X     a) Device-directory line (DDL):
	X        Format:   
	X		  -d|c|l  device_directory_name [dir_file]
	X	   where 
	X	      d,c,l are flags indicating a DDL line:
	X	        "-d" :- the name on that line is a device_directory_name
	X			that defines the directory where a subsequently
	X			requested file resides, at the remote host.
	X			This flag requires one name after the option.
	X	        "-c" :- a request to change the local directory so that
	X			requested files will be put into that directory.
	X			The name on that line is an existing local
	X			directory. This flag requires zero or one name 
	X			after the option. If no name is followed, then
	X			a change to the home directory is performed.
	X	        "-l" :- a request to obtain a directory listing for the
	X			remote directory named on that line. This flag
	X			requires two names after the option: the name
	X			of the remote directory, and the name of the
	X			file to which the listing is to be stored.
	X        Example:
	X		-d PD1:<MSDOS.DSKUTL>
	X		-l PD:<ANONYMOUS> root.dirlst
	X 		-c download
	X        Function:
	X            A "-d" DDL line defines the directory from which all files 
	X	        on the subsequent file-lines, up to a new "-d" DDL line,
	X		are to be fetched.
	X            A "-l" DDL line gets a directory listing to aid the download.
	X	    A "-c" DDL line changes the local directory PERMANENTLY upto
	X		the next "-c" DDL line to help organize the downloaded 
	X		file.
	X 
	X      *NOTE*: PS:<ANONYMOUS> directory contains general information
	X	      and many directory lists at SIMTEL20. New users are
	X	      particularly encouraged to look into this directory.
	X
	X     b) File lines (FL):
	X         Format:
	X 	          [-a|b|8|t] RemoteFile [LocalFile]
	X             where:
	X                a,b,8,t are flags:
	X   	  	   "-a" :- a file is to be transferred in ASCII mode 
	X   		   "-b" :- a file is to be transferred in binary mode 
	X   		   "-t" or "-8" 
	X		        :- a file is to be transferred in tenex mode
	X		 	   (32->8 bits conversion, which is the mode
	X			    you should use if you are ftp'ing into
	X			    SIMTEL20 from a DEC VAX or a SUN)
	X		   The option can be omitted (indicated by the bracket
	X		   "[","]".) If it is omitted, the default is "-t" 
	X		   (identical to "-8").
	X 	        RemoteFile is the requested file's name at the remote host
	X 	        LocalFile (optional) is the file name under which the 
	X		   RemoteFile is to be received at the local machine.
	X                   If it is omitted, the default is RemoteFile.
	X         Examples:
	X		-a 	00-INDEX.TXT  DSKUTL.IDX
	X		-8 	BACKEZ.ARC
	X		DISCACHE.ARC	CACHE.ARC
	X		TIMEPARK.ARC
	X		-a	VDSK.ASM
	X	 Functions:
	X	      An FL line specifies the name of a requested file (whose
	X	      directory is specified by a preceding DDL line), and the
	X	      transfer mode for the file.
	X
	X      *NOTE* 1) An option on an FL line must NOT be omitted if the 
	X		RemoteFile starts with a "-". And only the first letter
	X		of an option is effective.
	X             2) Options and names are separated by blanks or TABs.
	X		No other delimiters can be used. 
	X	     3) There can be more than one blank or TAB between the 
	X		options and names. 
	X	     4) There can be blanks or TABs before an option. But 
	X		nothing should be inserted between "-" and a flag.
	X	     5) A DDL or FL line can appear anywhere in an input file
	X		though some sequence may not be meaningful.
	X	     6) The input file may contain any number of blank line
	X		anywhere. They are simply ignored.
	X	     7) The file name on an FL line, and directory names on a 
	X		"-d" or "-l" DDL line can be either in lower or upper 
	X		case. This makes no difference as far as autoftp30.sh is
	X		concerned. However, all options must be in lower case.
	X	
	X  2. Run the program: 
	X     There are two ways:
	X        i) run as a background job (strongly recommended) by typing:
	X	  	sh autoftp30.sh in_file &
	X        ii) run as a foreground job (not recommended) by typing: 
	X	  	sh autoftp30.sh in_file 
	X     where in_file is the name of the input file prepared as above.
	X
	X     If the program is run as a background job (indicated by "&" at the
	X     end of the line, do a "man sh" for more information), then the 
	X     terminal on which this command is issued is freed right away. Thus
	X     the user can immediately issue whatever other commands he may want.
	X     Otherwise, the terminal is taken by the autoftp process, and the 
	X     user has to wait until its completion (upto several hours) before 
	X     he can issue any other command.
	X
	X     While the program is running background, its status can be checked
	X     by issuing "ps -xg" (do a "man ps" for more information). It can
	X     be terminated, if the user wishes, by "kill -9 pid" where "pid" is
	X     the process id, shown by "ps", of the very process to be terminated
	X     (do a "man kill" for more information.)
	X
	X  3. The results are a number of files: the files received, and 6 working
	X     files created by the execution. Among the 6 files, 5 of them only
	X     exist during the execution.
	X
	X     a) XXXXXmsg :-   (XXXXX is a process ID number, as shown by a "ps"
	X		       command in UNIX.)
	X          This is the only working file that is usually left after the
	X       execution and the only working file the user should be concerned
	X       with. It contains the history of the ftp attempts. Check this file
	X       to see if each requested file is successfully transferred. A file
	X       transfer fails only when it is too large or has a wrong name,
	X       which will be reported in this file. (If your local system goes
	X       down, or the process is killed by a "kill" command, the transfer
	X       will of course be interrupted and no message will be reported in
	X       these cases.)
	X
	X     b) XXXXXstdout, XXXXXstderr, XXXXXftp.script, XXXXXtmp :-   
	X		(XXXXX is again a process ID number, as shown by a "ps"
	X		 command in UNIX.)
	X          These files are temporary working files. XXXXXtmp only exists
	X        momentarily. If the autoftp30.sh terminates gracefully, they will
	X        all be erased upon its completion. Otherwise, the user can always
	X        delete them manually (this happens if the autoftp30.sh is killed
	X        by a kill command of UNIX, the local machine went down in the
	X        middle of the execution, or due to a situation unanticipated by
	X        the AutoFtp.)
	X
	X========================================================================
	X
	XHistory:
	X
	X  Version 2.1 (GET21), by Mingqi Deng, Jan. 12, 1989
	X  --------------------------------------------------
	X
	X     1. Unlike Get20, Get21 will not give up when connection is refused
	X        or disrupted. Therefore the users will be relieved from the
	X        frustration of running it over and over again for a good
	X        connection.
	X     2. To get out from a silent connection, there is a time out for 
	X	each connection. The default is one hour. For large files or 
	X	slow communication lines, the user is advised to increase the 
	X	value.
	X     3. A separate shell program sample is included for transferring
	X        multiple files from SIMTEL20. 
	X
	X-----------------------------------------------------------------------
	X
	XVersion 2.0 (GET20) by  : Ferd Boundick
	X---------------------------------------
	X
	X   date written: some time in 1983
	X   modification: 22 March 84
	X
	X     1. ftp modes are referred to as "ascii, binary, and tenex"
	X     2. The option -8 is identical to -t for tenex (36->8) transfers.
	X     3. Remote host name now is stored in the variable "RemoteHost".
	X     4. Local host name now is stored in the variable "LocalHost" for
	X	  remote login usage.
SHAR_EOF
if test 13337 -ne "`wc -c < 'README'`"
then
	echo shar: "error transmitting 'README'" '(should have been 13337 characters)'
fi
fi
echo shar: "extracting 'autoftp30.sh'" '(5769 characters)'
if test -f 'autoftp30.sh'
then
	echo shar: "will not over-write existing file 'autoftp30.sh'"
else
sed 's/^	X//' << \SHAR_EOF > 'autoftp30.sh'
	X#! /bin/sh
	X#
	X# AutoFtp Version 3.0, by Mingqi Deng, July 6, 1989
	X# -------------------------------------------------
	X# 
	X# Refer to file README for instructions to run the program
	X
	X# Set-up: 
	X#
	X# 1. Set the following 3 parameters in this program on lines 23-62:
	X#
	X#      		ALARM, RemoteHost, FtpLibDir 
	X#
	X#    Instructions and examples are given as comments in the following.
	X#
	X# 2. Make sure that you do NOT have any executable files of the same
	X#    name as the following UNIX commands' names:
	X#
	X# 	   cat chmod cp echo expr grep mv rm sh sleep sed test
	X#
	X#    Otherwise, rename your files to different names.
	X
	X# An ftp attempt will be aborted after ALARM many seconds. It must at 
	X# least be equal to 300. The default # is 3600, eg., ALARM=3600 (do 
	X# not leave blanks between '=' and '3600'!)
	X
	XALARM=3600
	X
	X# Define host names:
	X#   Use one of the following addresses for simtel20 archive site for the
	X# parameter RemoteHost below:
	X#         "26.2.0.74"
	X#         "WSMR-SIMTEL20.ARMY.MIL"
	X#         "SIMTEL20.ARPA"
	X# The first one is highly recommended if it works, since it is the 
	X# most time-saving address to use. The second is the official name. The
	X# third is an alias, thus least recommended. However, you may find only
	X# one of them works for you, depending on how your UNIX installation
	X# handles the addresses. One symptom is a quickly failed ftp (less than
	X# 5 seconds), which can be noticed by the ps command of UNIX.
	X#
	X# Also note that it has been noticed that some system does not recognize
	X# the address in upper case. Therefore, if none of the above three
	X# works for you, change the names to lower case and try again.
	X#
	X# LocalHost is set to "guest". If you find it not working, replace
	X# it with the host name of your machine on which this program is run.
	X#   eg.,     RemoteHost="26.2.0.74"
	X#            LocalHost="shire.cs.psu.edu"
	X
	XRemoteHost="26.2.0.74" 
	XLocalHost="guest"
	X
	X# Set the path name for the directory where three compiled C programs
	X# ftpget.c, nextfile.c and checkout.c are. This program assumes as 
	X# default that the three compiled programs are in $HOME/bin (a directory
	X# "bin" in your home directory). If they are to be put in a different
	X# directory, say, lib in your home directory, you should set FtpLibDir 
	X# as:
	X#        FtpLibDir="$HOME/lib"
	X# Otherwise, just leave 'FtpLibDir=""' on next line as it is.
	XFtpLibDir=""
	X
	X#
	X#-------AUTOFTP30.SH Set-up Stops Here: No further set-up needed------
	X#
	X
	Xtest 1$FtpLibDir = 1 && FtpLibDir=$HOME/bin
	X_ftpget="$FtpLibDir/ftpget"
	X_checkout="$FtpLibDir/checkout"
	X_nextfile="$FtpLibDir/nextfile"
	X
	Xtest -s "$_ftpget" ||
	X   { echo "***Cannot find file '$_ftpget'!"
	X     echo "   Please compile 'ftpget.c', name the compiled program as"
	X     echo "   'ftpget' and place it in your '$FtpLibDir' directory." ; 
	X     exit 2 ; }
	Xtest -s "$_checkout" ||
	X   { echo "***Cannot find file '$_checkout'!"
	X     echo "   Please compile 'checkout.c', name the compiled program as"
	X     echo "   'checkout' and place it in your '$FtpLibDir' directory." ;
	X     exit 2 ; }
	Xtest -s "$_nextfile" ||
	X   { echo "***Cannot find file '$_nextfile'!"
	X     echo "   Please compile 'nextfile.c', name the compiled program as"
	X     echo "   'nextfile' and place it in your '$FtpLibDir' directory." ;
	X     exit 2 ; }
	X
	Xtest $# != 1 && 
	X   { echo "***Usage: sh autoftp30.sh in_file" ; exit 2; }
	X
	Xexec 1>$$stdout 2>$$stderr
	X
	X# Try FTP into simtel20 SLEEP many seconds until being connected
	X# SLEEP will be increased and decreased randomly for subsequent tries.
	XSLEEP=60
	X
	X# save messages
	Xcat  $$stdout $$stderr > $$msg
	X
	X#initialize the loop
	XWS=`expr \( $SLEEP \* 47 + 31 \) \% 89 + 50`
	X
	Xctr=1
	Xcp $1 $$input
	Xretry=no
	X
	X# Repeat if there is more request in the input file or if the last
	X# attempt failed and a retry can be performed.
	Xwhile { test -s $$input || test $retry = yes ; }
	Xdo
	X
	X  > $$stderr
	X  > $$stdout
	X
	X# If not a re-try for a requested file, then fetch next requested 
	X# file name. If the fetch fails, then quit autoftp30.sh.
	X  test $retry = no && 
	X  { echo "%%%%%%% Process File Request #$ctr %%%%%%%" >> $$msg
	X    ctr=`expr $ctr + 1`
	X    $_nextfile $$input $RemoteHost anonymous $LocalHost $$ftp.script >> $$msg || 
	X    { status=92; break;}
	X  }
	X
	X# Attempt to get the file. If not able to make an attempt, then quit.
	X# Note that exit status=99 means there is no alarm call.
	X  chmod og-rx $$ftp.script
	X  $_ftpget $ALARM $$ftp.script ||
	X  { test $? = 99 &&        # alarm called, do not quit yet, $_checkout 
	X			   # will respond 
	X     { status=93; break; } ; }
	X
	X# Check the result of the transfer. If a retry is not to be made, then 
	X# set "retry" to no, otherwise set it to yes.
	X  $_checkout $$stdout $$stderr $$ftp.script $$tmp >> $$msg
	X  status=$?
	X  { test $status = 99 && { status=94; break ; } ; } ||
	X  { test $status = 0  && retry=no ; } || retry=yes
	X
	X# if not the last request, i.e., $$input is not empty or retry=yes, 
	X# then wait for a while before next attempt. Otherwise done!!!
	X  test -s $$input || test $retry = yes || { status=95; break ; }
	X
	X# save the messages for only the last attempt on a request
	X  test $retry = no && cat  $$tmp >> $$msg
	X  rm $$tmp
	X
	X  sleep $WS
	X  WS=`expr \( $WS \* 13 \/ 10 \) \% 900 + 60`
	X
	Xdone
	X
	Xtest $status -ge 92 && 
	X   { test $status -le 93 &&  cat $$stderr >> $$msg || 
	X        { cat $$tmp >> $$msg ; rm $$tmp ; }   # status=94,95
	X   }
	X  
	Xcase $status in
	X 92) echo "*******Fatal error: when preparing an ftp attempt!*******" >> $$msg;;
	X 93) echo "*******Fatal error: during an ftp attempt!*******" >> $$msg;;
	X 94) echo "*******Fatal error: when checking last ftp result!*******" >> $$msg;;
	X 95) echo "###################Execution Completed###################" >> $$msg;;
	X  *) ;;
	Xesac
	X
	X#remove ftp command and working files
	Xrm $$ftp.script $$stderr $$stdout $$input
	X
	Xexit 0
SHAR_EOF
if test 5769 -ne "`wc -c < 'autoftp30.sh'`"
then
	echo shar: "error transmitting 'autoftp30.sh'" '(should have been 5769 characters)'
fi
chmod +x 'autoftp30.sh'
fi
echo shar: "extracting 'checkout.c'" '(10184 characters)'
if test -f 'checkout.c'
then
	echo shar: "will not over-write existing file 'checkout.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'checkout.c'
	X/*
	X * checkout.c by Mingqi Deng, July 6, 1989
	X *
	X *    checks the result of an ftp attempt made by autoftp30.sh (cf. 
	X *    ftpget.c) to get a file from a remote host.
	X *
	X *  Compile:  
	X *             cc -o checkout checkout.c
	X *  Execute:
	X *             checkout f_stdout f_stderr ftp_script f_tmp
	X *    where:
	X *      f_stdout   :- the standard output file used by ftpget.c
	X *      f_stderr   :- the standard error-message file used by ftpget.c
	X *      ftp_script :- the ftp command script file created by nextfile(.c)
	X *      f_tmp      :- a temporary file for deleting null chars in
	X *		      f_stderr and f_stdout, also used as stderr by
	X *                    checkout(.c) for most of its error messages.
	X *
	X *  Exit status:
	X *         99  : fatal error, quit this session of autoftp30.sh
	X *          0  : finish an attempt, no further attempt should be made
	X *		 on this requested file (either file successfully 
	X * 		 received, ALARM in autoftp30.sh too small, or a wrong 
	X *		 file name)
	X *	    2  : a failed attempt that should be retried
	X *
	X *  Example:   
	X *            checkout 1234stdout 1234stderr 1234ftp.script 1234tmp
	X *
	X *  Note   :
	X *     Two constants max_line_length and max_line defined on the
	X *     "#define" lines below specify the maximum length of lines in
	X *     f_stderr and f_stdout, and the maximum number of lines in them
	X *     altogether.In case they are not large enough (your will get a 
	X *     message saying so), increase them.
	X */
	X
	X#include <stdio.h>
	X#include <sys/types.h>
	X#include <sys/stat.h>
	X#include <sys/timeb.h>
	X
	X#define max_line_length    160
	X#define max_line           400
	X
	Xchar hold[max_line][max_line_length+1];
	Xint  ctr,     /* number of lines in f_stderr and f_stdout */
	X     letter;  /* number of letters in f_stderr and f_stdout */
	XFILE *f_tmp;
	X
	Xmain(argc, argv)
	Xint argc;
	Xchar *argv[];
	X{
	X  int flag,ftp_get_file;
	X  char cmd[80],s[80],s1[80],s2[80],*rfile,*lfile,*sprintf(),*malloc();
	X  FILE *f_err, *f_out, *f_ftp;
	X  struct stat *buf;
	X  time_t tloc,timeofday;
	X
	X  f_tmp = fopen(argv[4],"w");
	X  if (argc != 5) {
	X     fprintf(stderr,"***Usage: checkout stdout stderr ftp_script f_tmp\n");
	X     exit(99);
	X  }
	X  f_out = fopen(argv[1],"r");
	X  f_err = fopen(argv[2],"r");
	X  f_ftp = fopen(argv[3],"r");
	X  if (f_err == NULL || f_out == NULL || f_ftp == NULL) 
	X     { fprintf(f_tmp,"***File(s) '%s', '%s' or '%s' do not exist\n",
	X	       argv[1],argv[2],argv[3]);
	X       exit(99);}
	X
	X  ctr=0; letter=0;      /* read in the stdout file of the ftp session*/
	X  while ((ctr<max_line) && (getline(hold[ctr],f_out,f_tmp)!=0)) ctr++;
	X  if (ctr == max_line) {
	X     fprintf(f_tmp,"%s\n%s\n%s\n",
	X      "***Increase the constant 'max_line' on the '#define' line",
	X      "   in file checkout.c, recompile it, then try again!");
	X     exit(99);
	X  }
	X
	X                        /* read in the stderr file of the ftp session*/
	X  while ((ctr<max_line) && (getline(hold[ctr],f_err,f_tmp)!=0)) ctr++;
	X  if (ctr == max_line) {
	X     fprintf(f_tmp,"%s\n%s\n%s\n",
	X      "***Increase the constant 'max_line' on the '#define' line",
	X      "   in file checkout.c, recompile it, then try again!");
	X     exit(99);
	X  }
	X  if (letter==0)     /* empty file: a silent connection, try again */
	X      { printf("A silent connection, will try again.\n"); exit(2);} 
	X   
	X  flag  = detect("unknown host");
	X  flag  = (flag)? 1: detect("Unknown host");
	X  if (flag) {
	X         /* wrong remote host name, quit attempt for this run */
	X     fprintf(f_tmp,"***host unknown: check RemoteHost in autoftp30.sh!\n"); 
	X     exit(99);   
	X  }
	X
	X           /* get the requested file names from the ftp script file 
	X		if a 'get' is performed. */
	X  ftp_get_file=0;
	X  while( fgets(s,max_line_length,f_ftp) != NULL)
	X     if (strncmp(s,"get",3) == 0) {
	X           extract3(s,s1,s1,s2);
	X           if (s1[0]!='\0') { rfile = s1; }
	X           else {
	X	     fprintf(f_tmp,"***Invalid ftp_script file '%s'\n",argv[3]);
	X     	     exit(99);
	X           }
	X	   if (s2[0]!='\0') lfile=s2;
	X           else             lfile=s1;
	X	   ftp_get_file=1;
	X     }
	X
	X  flag = detect("Invalid use of terminal designator"); 
	X  flag = (flag)? 1:detect("File not accessible");
	X  flag = (flag)? 1:detect("File not accessable");
	X  flag = (flag)? 1:detect("file not found");
	X  flag = (flag)? 1:detect("File not found");
	X  flag = (flag)? 1:detect("not found");
	X  flag = (flag)? 1:detect("No such file");
	X  flag = (flag)? 1:detect("No such directory");
	X
	X  if (flag) {
	X         /* wrong remote file name, quit attempt for this file */
	X     if (ftp_get_file) 
	X        fprintf(f_tmp,
	X		"***Remote file/direcortory %s not found!\n",rfile); 
	X     else 
	X        fprintf(f_tmp, "***Remote direcortory not found!\n"); 
	X     exit(0);    /* abort the current request */
	X  }
	X  
	X  flag = detect("refused");
	X  flag = (flag)? 1: detect("unreachable");
	X  flag = (flag)? 1: detect("failed");
	X  flag = (flag)? 1: detect("Connection timed out");
	X  flag = (flag)? 1: detect("timed out");
	X  flag = (flag)? 1: detect("Not connected");
	X  flag = (flag)? 1: detect("not connected");
	X  flag = (flag)? 1: detect("not accessable");
	X  flag = (flag)? 1: detect("not accessible");
	X  flag = (flag)? 1: detect("not available");
	X  flag = (flag)? 1: detect("time out");
	X  flag = (flag)? 1: detect("times out");
	X 
	X  if (flag) {		/* a bad connection, try again */
	X      printf("A bad connection, will try again.\n"); 
	X			/* remove the incomplete file if it exists */
	X      sprintf(cmd,"test -f '%s' && rm '%s'",lfile,lfile);
	X      system(cmd);
	X      exit(2);   /* try again */
	X  }
	X
	X  flag  = detect("Transfer complete");
	X  flag  = (flag)? 1:detect("received");
	X  if (flag != 0)  {
	X      if (ftp_get_file) {
	X         fprintf(f_tmp,"=======File '%s'\n",rfile);
	X         fprintf(f_tmp,
	X		"       successfully received as '%s'.=======\n",lfile);
	X      } else
	X         fprintf(f_tmp,"=======Transfer successfully completed.\n");
	X      exit(0);  /* done for this RemoteFile */
	X  } else {
	X      flag = detect("Alarm call");
	X      if (ftp_get_file==0) {
	X         printf("   A silented connection. Will try again.\n");
	X         exit(2);
	X      }
	X
	X         /* then check if too large a requested file */
	X      buf=(struct stat *)malloc(sizeof(struct stat));
	X      stat(lfile,buf);    /* get GMT time in seconds (from 12/31/1969
	X				19:00:00) for the file being received 
	X				since last modification. If the file 
	X				does not exist, 0 is returned. */
	X      timeofday = time(&tloc);   /* get current time */
	X		/* if the file was modified in last 5 minutes*/
	X      if (timeofday - buf->st_mtime < 300)  {
	X         if (flag == 0) fprintf(f_tmp, 
	X		"***I am confused. But most likely the chance is:\n");
	X         fprintf(f_tmp, "%s\n%s%s%s%s%s\n%s%s%s\n",
	X          "***'alarm' in autoftp30.sh appears too small for remote file",
	X          "   '",rfile,"' (to be received as '",lfile,"').",
	X          "   File '",lfile,"' removed, increase the 'alarm' and try again.");
	X 		/* remove the incomplete file (it must exist
	X			   since the difference is < 300)  */
	X          sprintf(cmd,"rm '%s'",lfile);
	X          system(cmd);
	X	  exit(0);   /* abort this request, do not try any more. */
	X      } else {
	X         if (flag == 0) 
	X 	   printf("***I am confused. But most likely the chance is:\n");
	X         printf("   A silented connection. Will try again.\n");
	X			/* remove the file if it exists. */
	X	 sprintf(cmd,"test -f '%s' && rm '%s'",lfile,lfile);
	X         system(cmd);
	X	 exit(2);   /* do not abort this request, try again. */
	X      } 
	X  } 
	X}
	X
	X/* detect(s)
	X *   returns 1 if string s is in the file f_err and f_out that have been
	X * read into array hold.
	X */
	Xdetect(s)
	Xchar *s;
	X{
	X  int i,flag;
	X
	X  for (i=0; i<ctr && ((flag=substring(hold[i],s))==0); i++);
	X  return(flag);
	X}
	X
	X/* substring:
	X *   returns 1 if s2 is a substring of s1, 0 otherwise.
	X */
	Xsubstring(s1,s2)
	Xchar *s1,*s2;
	X{
	X   int i,l1,l2,found;
	X
	X   l1 = strlen(s1); 
	X   l2 = strlen(s2); 
	X  
	X   found = 1; 
	X   for (i=0; i<=l1-l2 && found!=0; i++) 
	X       found = strncmp(s1+i,s2,l2);
	X
	X   return(found==0);
	X}
	X
	X/* getline(s,fin,fout)
	X*      reads an input line from file fin, and skips null chars, count 
	X*  the number of letters in the input file (result kept in global var
	X*  letter). All non-null characters are written to fout to eliminate
	X*  numerous annoying null character (inserted by ftp?) that causes very
	X*  slow scrolling when using MORE of UNIX to display the file fin.
	X*      return 0 if eof.
	X*/
	Xgetline(s,fin,fout)
	Xchar s[];
	XFILE *fin,*fout;
	X{
	X   char c;
	X   int  i,cc;  /* cc used to avoid machine dependent comparison
	X                  of getc()'s return value to EOF */
	X
	X   i = 0; 
	X   while( ((cc=getc(fin)) != EOF) && i <= max_line_length) {
	X      c=cc;
	X      if (c=='\n') 
	X           { s[i]='\0'; putc(c,fout); return(1); }
	X      else 
	X           if (c != '\0') { 
	X   		putc(c,fout);
	X                if (c > 64 && c < 91 || c > 96 && c < 123 ) 
	X		     { letter++; s[i++]=c; }
	X                else 
	X		     if (c==' ')  s[i++]=c;
	X	   }
	X   }
	X
	X   if (i>max_line_length) 
	X       { fprintf(f_tmp,"%s\n%s\n",
	X           "***'max_line_length' in checkout.c appears too small.",
	X           "   Please increase it, recompile and try again!");
	X         exit(99);
	X       }
	X  
	X   s[i] = '\0';
	X   return(0);
	X}
	X
	X/* extract3(s,s0,s1,s2)
	X*     extracts 3 substring from s to s0, s1 and s2, where 
	X*   blanks, tabs are delimiters, new line character is ignored. S is 
	X*   terminated by a null character as usual, so will s0, s1 and s3.
	X*/
	Xextract3(s,s0,s1,s2)
	Xchar s[],s0[],s1[],s2[];
	X{
	X   int i,head,tail,ptr,l;
	X
	X   l = strlen(s); tail=0;
	X   for (i=0;i<3;i++) {
	X       ptr=0;
	X       head=tail;
	X       while(s[head]==' ' ||  /* skip blanks, tabs and new line */
	X	     s[head]==9   ||
	X	     s[head]=='\n') head++;
	X       tail=head;
	X
	X       while(tail<l      &&  
	X	     s[tail]!=' '&&   /* stop if a blank, tab or NL is seen */
	X	     s[tail]!=9  &&
	X	     s[tail]!='\n')  
	X          switch(i) {
	X              case 0:  s0[ptr++]=s[tail++]; break;
	X              case 1:  s1[ptr++]=s[tail++]; break;
	X              case 2:  s2[ptr++]=s[tail++]; break;
	X          }
	X        switch(i) {
	X              case 0:  s0[ptr]='\0'; break;
	X              case 1:  s1[ptr]='\0'; break;
	X              case 2:  s2[ptr]='\0'; break;
	X        }
	X   }
	X}
	X
SHAR_EOF
if test 10184 -ne "`wc -c < 'checkout.c'`"
then
	echo shar: "error transmitting 'checkout.c'" '(should have been 10184 characters)'
fi
fi
echo shar: "extracting 'ftpget.c'" '(2525 characters)'
if test -f 'ftpget.c'
then
	echo shar: "will not over-write existing file 'ftpget.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'ftpget.c'
	X/*
	X * ftpget.c by Mingqi Deng, July 6, 1989
	X *
	X *    makes one attempt to get a file from a remote host.
	X *
	X *  Compile:  
	X *             cc -o ftpget ftpget.c
	X *  Execute:
	X *             ftpget alarm remotehost ftp_script
	X *    where
	X *      alarm      :- the number in seconds that an ftp attempt can last
	X *      ftp_script :- ftp command script created by nextfile.c
	X *
	X *  Example:   
	X *             ftpget 3600 wsmr-simtel20.army.mil 123ftp_script
	X *  Note   : 
	X *    1. The maximum number of characters contained on ftpget's command
	X *       line is defined in the constant ftpget_cmd_line_length. The
	X *       default is 160.
	X *    2. The host name is assumed to have no more than 80 characters. 
	X *       Adjust the constant hostname_length if necessary.
	X */
	X
	X#include <stdio.h>
	X#include <signal.h>
	X
	Xint id,pgid,mask;
	X
	X#define ftpget_cmd_line_length     160
	X#define hostname_length             80
	X
	Xmain(argc, argv)
	Xint argc;
	Xchar *argv[];
	X{
	X  unsigned t_alarm;
	X  char cmd[ftpget_cmd_line_length+1];
	X  void  handler();
	X  FILE *f;
	X
	X  if (argc != 3) {
	X     fprintf(stderr,"***Type 'ftpget alarm ftp.script' to run\n");
	X     exit(99);
	X  }
	X		/* check if file ftp_script exists. */
	X  f = fopen(argv[2],"r");
	X  if (f == NULL) {
	X     fprintf(stderr,"***Ftp script file '%s' does not exist.\n",argv[2]);
	X     exit(99);
	X  }
	X  fclose(f);
	X
	X  sscanf(argv[1],"%u",&t_alarm);
	X  if (t_alarm < 300) { 
	X     fprintf(stderr,"***'alarm'(= %d < 300) in autoftp30.sh too small!\n",t_alarm);
	X     exit(99);
	X  }
	X
	X  mask=sigsetmask(0);   /* do not block any signals */
	X  id=getpid();  pgid=getpgrp(id);   /* get process group id */
	X  setpgrp(id,pgid+1);   /* modify process group id so that only this 
	X			   and all of its subprocesses (with this id)
	X			   can be terminated by a signal */
	X  signal(SIGALRM,handler);  /* catch the alarm signal and use procedure
	X				"handler" to process it */
	X             /* create a command "ftp remotehost < ftp_script" to
	X                be run in current shell (instead of a subshell)*/
	X  sprintf(cmd,"exec ftp -n < '%s'",argv[2]);
	X
	X  alarm(t_alarm);   /* timing the system call next: send a SIGALRM 
	X			signal to the current process after t_alarm 
	X			many seconds */
	X  system(cmd);      /* execute "ftp remotehost < ftp_script" */
	X  alarm(0);         /* stop the alarm if "cmd" ends before the alarm
	X			call*/
	X}
	X
	X/* SIGALRM signal handling */
	Xvoid handler()
	X{
	X   fprintf(stderr,"Alarm call!\n");
	X   killpg(pgid+1,SIGHUP);  /* kill the current process and its
	X				subprocess (ftp ....) */
	X   exit(5);
	X}
SHAR_EOF
if test 2525 -ne "`wc -c < 'ftpget.c'`"
then
	echo shar: "error transmitting 'ftpget.c'" '(should have been 2525 characters)'
fi
fi
echo shar: "extracting 'nextfile.c'" '(12936 characters)'
if test -f 'nextfile.c'
then
	echo shar: "will not over-write existing file 'nextfile.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'nextfile.c'
	X/*
	X * nextfile.c by Mingqi Deng, July 6, 1989
	X *
	X *     get next requested file from an input file and prepare an ftp
	X *     script file for ftpget.c (cf. ftpget.c) The requested file
	X *     will be deleted from the input file.
	X *
	X *  Compile:  
	X *           cc -o nextfile nextfile.c
	X *  Execute:
	X *           nextfile in_file RemoteHost login password ftp_script
	X *    where
	X *      in_file   :- input file to autoftp30.sh (cf. README) that consists
	X *		     of two types of lines:
	X * 	  a) Device-directory line (DDL):
	X *     	      Format:   
	X *	    	  -d|c|l  device_directory_name [dir_file]
	X *	      where 
	X *	        "-d" :- the name on that line is a device_directory_name
	X *			that defines the directory where a subsequently
	X *			requested file resides, at the remote host.
	X *			This flag requires one name after the option.
	X *	        "-c" :- a request to change the local directory so that
	X *			requested files will be put into that directory.
	X *			The name on that line is an existing local
	X *			directory. This flag requires one name after
	X *			the option, too.
	X *	        "-l" :- a request to obtain a directory listing for the
	X *			remote directory named on that line. This flag
	X *			requires two names after the option: the name
	X *			of the remote directory, and the name of the
	X *			file to which the listing is to be stored.
	X * 	       Example:
	X *			-d PD1:<MSDOS.DSKUTL>
	X *			-l PD:<ANONYMOUS> root.dirlst
	X * 			-c download
	X *	       Function:
	X *                 A "-d" DDL line defines the directory from which all
	X *		   files on the subsequent file-lines, up to a new "-d"
	X *		   DDL line, are to be fetched.
	X *             	   A "-l" DDL line gets a directory listing.
	X *		   A "-c" DDL line changes the local directory PERMANANTLY
	X *		   upto next "-c" DDL line.
	X * 
	X *    	    b) File lines (FL):
	X *             Format:
	X * 	          [-a|b|8|t] RemoteFile [LocalFile]
	X *             where:
	X *                a,b,8,t are flags of options:
	X *   	  	   "-a" :- a file is to be transferred in ASCII mode 
	X *   		   "-b" :- a file is to be transferred in binary mode 
	X *   		   "-t" or "-8" 
	X *		        :- a file is to be transferred in tenex mode
	X *		 	   (32->8 bits conversion, which is the mode
	X *			    you should use if you are ftp'ing into
	X *			    SIMTEL20 from a DEC VAX or a SUN)
	X *		   If the option is omitted, the default is "-t".
	X * 	        RemoteFile is the requested file's name at the remote host
	X * 	        LocalFile (optional) is the file name under which the 
	X *		   RemoteFile is to be received at the local machine.
	X *                   If it is omitted, the default is RemoteFile.
	X *	        Examples:
	X *			-a 	00-INDEX.TXT  DSKUTL.IDX
	X *			-8 	BACKEZ.ARC
	X *			DISCACHE.ARC	CACHE.ARC
	X *			TIMEPARK.ARC
	X *			-a	VDSK.ASM
	X *		Functions:
	X *	      	  An FL line specifies the name of a requested file 
	X *		  (whose directory is specified by a preceding DDL line),
	X * 		  and the transfer mode for the file.
	X *         *NOTE*
	X *	      1) An option on an FL line must NOT be omitted if the 
	X *		RemoteFile starts with a "-". And only the first letter
	X *		of an option is effective.
	X *            2) Options and names are separated by blanks or TABs.
	X *	  	No other delimiters can be used. 
	X *	      3) There can be more than one blank or TAB between the 
	X *		options and names. 
	X *	      4) There can be blanks or TABs before an option. But 
	X *		nothing should be inserted between "-" and a flag.
	X *	      5) A DDL or FL line can appear anywhere in an input file
	X *		though some sequence may not be meaningful.
	X *	      6) The input file may contain any number of blank line
	X *		anywhere. They are simply ignored.
	X *	      7) The file name on an FL line, and directory names on a 
	X *		"-d" or "-l" DDL line can be either in lower or upper 
	X *		case. This makes no difference as far as autoftp30.sh is
	X *		concerned. However, all options must be in lower case.
	X *
	X *      RemoteHost:- the host name of the anonymous ftp session
	X *      login     :- the login id for the anonymous ftp session
	X *      password  :- the password for the anonymous ftp session
	X *      ftp_script:- the output file that consists of ftp commands
	X *
	X *  Example:   
	X *      nextfile 123input WSMR-SIMTEL20.ARMY.MIL anonymous guest 123ftp.script
	X *  Note   : 
	X *    1. The maximum number of characters contained on each line in
	X *       file in_file (cf. sample.dat) is no more than max_line_length. 
	X *       The default is 80. Adjust it if necessary.
	X *    2. The constant TENEX in the second "#define" may need adjusting.
	X *       Instead of being '"tenex"', it may have to be '"type L 8"', 
	X *       '"type local"' or '"type local byte"'.  Do a "man ftp" to see 
	X *       how your system wants it.
	X */
	X
	X#include <stdio.h>
	X#include <string.h>
	X
	X#define max_line_length              80
	X#define TENEX                       "tenex"
	X
	Xmain(argc, argv)
	Xint argc;
	Xchar *argv[];
	X{
	X  int  no_more, 		 /* 1 if end of file */
	X       dir_path, 		 /* 1 if a DDL line of -d option seen */
	X       chdir_req, 		 /* 1 if an lcd request on current DDL*/
	X       not_done,		 /* contol while loop */ 
	X       to_chdir,	 	 /* 1 if a pending lcd request */
	X       chdir_flg,	 	 /* 1 if an lcd request seen */
	X       action;			 /* 1 if usful request (dir, get) seen */
	X  char cmd[80],type[10],*dummy=NULL,
	X       op_flg, option(), 
	X       s1[max_line_length+1],        
	X       s2[max_line_length+1],       
	X       chdir_name[max_line_length+1],/* local dir name to chage to */
	X       dir1[max_line_length+1],      /* remote dir name to get dir list */
	X       dir2[max_line_length+1],      /* file to get remote dir list */
	X       dpath[max_line_length+1];     /* the directory path in DDL line*/
	X  FILE *fin,*fftp;
	X
	X  if (argc != 6) {
	X     fprintf(stderr,
	X     "***Usage: nextfile input RemoteHost login password ftp.script\n");
	X     exit(3);
	X  }
	X  if ( (fin = fopen(argv[1],"r")) == NULL) {
	X     fprintf(stderr,"***The input file does not exist!\n"); exit(3);
	X  }
	X
	X            /* Create an ftp command file which will be executed once 
	X	       ftp starts up. This is true no matter whether a login 
	X	       failed or not. A quit command is always issued. */
	X  fftp = fopen(argv[5],"w");   
	X  fprintf(fftp,"open %s\n",argv[2]);
	X  fprintf(fftp,"user %s %s\n",argv[3],argv[4]);
	X  fprintf(fftp,"type ascii\n");
	X  fprintf(fftp,"verbose\n");
	X
	X  action=0; dir_path=0; to_chdir=0; chdir_flg=0; chdir_flg=0;
	X  not_done=1;
	X  while (not_done) {
	X	    /* process a sequence of DDL lines with -c option */
	X     no_more=lcd(fin,chdir_name,&chdir_req,&op_flg,s1,s2);
	X     if (chdir_req) { to_chdir = 1; /* delay issuing lcd command, since 
	X				      only the last one is effective */
	X		      chdir_flg = 1; /* neet to remember the lcd for
	X				        subsequent file transfer */
	X		    }
	X
	X     if (no_more) {
	X        printf("=======Last request .......\n");
	X        if (action==0)
	X            printf( "***Warning: No files requested!\n"); 
	X        fprintf(fftp,"bye\n");
	X  	fclose(fftp);
	X	update_fin(fin,argv[1],dummy,0,dummy);
	X        exit(0);
	X     }
	X   	    /* if not eof, is it a DDL or FL line? */
	X     if (op_flg == 'l') {
	X        if (s1[0] == '\0' || s2[0] == '\0') {
	X           fprintf(stderr,
	X	     "***Invalid '-l' DDL line in the input file!\n");
	X           exit(3); 
	X        }
	X        if (to_chdir)  
	X	   { fprintf(fftp,"lcd %s\n",chdir_name); to_chdir=0; }
	X        fprintf(fftp,"cd %s\n",s1);   /* note that ascii mode was set */
	X        fprintf(fftp,"dir *.* %s\n",s2);
	X	action=1;
	X  } else 
	X     if (op_flg == 'd') {
	X        if (s1[0]=='\0') {
	X           fprintf(stderr,
	X	     "***Invalid device-directory-line(DDL) in the input file!\n");
	X           exit(3); 
	X        } 
	X        dir_path=1;
	X        strcpy(dpath,s1); 
	X  } else {	/* not a -c, -l, or -d line, must be an FL line */
	X      if (dir_path==0) {  /* no -d DDL line seen yet */
	X         fprintf(stderr,
	X	    "***Device-directory line missing in the input file!\n");
	X         exit(3); 
	X      } 
	X      not_done = 0;
	X  }
	X  }  /* of while */
	X  if (to_chdir) 	/* delayed lcd: only the last lcd is effective*/
	X     fprintf(fftp,"lcd %s\n",chdir_name); 
	X
	X   /*******  process an FL line *****/
	X  if (s1[0]=='\0') {
	X      fprintf(stderr,"***The requested file name is blank!\n");
	X      exit(3); 
	X  }
	X  if (s2[0]=='\0') strcpy(s2,s1);
	X
	X            /* set the file transfer mode */
	X  if (op_flg == 'b')  strcpy(type,"binary");
	X  if (op_flg == 't')  strcpy(type,TENEX);
	X  if (op_flg == '8')  strcpy(type,TENEX);
	X
	X  printf("=======Start requesting file %s .........\n",s1);
	X	/* type ascii has been set at the beginning */
	X  if (op_flg != 'a') fprintf(fftp,"type %s\n", type); 
	X  fprintf(fftp,"get %s%s %s\nbye\n",dpath,s1,s2);
	X  fclose(fftp);
	X
	X  update_fin(fin,argv[1],dpath,chdir_flg,chdir_name);
	X}
	X
	X/* gets next non-blank line from file fin, return 1 if EOF  */
	Xnextline(s,f)
	Xchar *s;
	XFILE *f;
	X{
	X  char *p;
	X
	X  while( (p=fgets(s,max_line_length,f)) != NULL) 
	X       if (nonblank(s)) break; 
	X  return(p==NULL);  
	X}
	X
	X/* nonblank(s)
	X*      returns true (non-zero) if s contains non-blank chars.
	X*/
	Xnonblank(s)
	Xchar *s;
	X{
	X  int i,flag;
	X  
	X  if (s==NULL) return(0);
	X  i = 0; flag = 0;
	X  for (i=0; i<strlen(s) && flag==0; i++) 
	X	flag = (s[i]==' ' || s[i]==9 || s[i]=='\n' )? 0:1; /* 9 is tab*/
	X  return(flag);
	X}
	X
	X/* extract(s,num,s0,s1,s2)
	X*     extracts num (1-3) many substring from s to s0, s1 and s2, where 
	X*   blanks, tabs are delimiters, new line character is ignored. S is 
	X*   terminated by a null character as usual, so will s0, s1 and s3.
	X*   Depending on s, any of s0, s1 or s2 can be an empty string.
	X*/
	Xextract(s,num,s0,s1,s2)
	Xchar s[],s0[],s1[],s2[];
	Xint num;
	X{
	X   int i,head,tail,ptr,l;
	X
	X   l = strlen(s); tail=0;
	X   for (i=0;i<num;i++) {
	X       ptr=0;
	X       head=tail;
	X       while(s[head]==' ' ||  /* skip blanks, tabs and new line 
	X				 ('\0' is after '\n') */
	X	     s[head]==9   ||
	X	     s[head]=='\n') head++;
	X       tail=head;
	X
	X       while(tail<l      &&   /* stop if end of the string s */
	X	     s[tail]!=' '&&   /* stop if a blank, tab or NL is seen */
	X	     s[tail]!=9  &&
	X	     s[tail]!='\n')  
	X          switch(i) {
	X              case 0:  s0[ptr++]=s[tail++]; break;
	X              case 1:  s1[ptr++]=s[tail++]; break;
	X              case 2:  s2[ptr++]=s[tail++]; break;
	X          }
	X        switch(i) {
	X              case 0:  s0[ptr]='\0'; break;
	X              case 1:  s1[ptr]='\0'; break;
	X              case 2:  s2[ptr]='\0'; break;
	X        }
	X   }
	X}
	X
	X/*
	X * extract options of a non-blank input line, detects invalid options,
	X * and will "insert" '-t' option to a default FL line. When returning,
	X * s2 and s3 are set to the 2nd and 3rd string on the line.
	X */
	Xchar option(s,n,s2,s3)
	Xchar *s,*s2,*s3;
	Xint n;
	X{
	X   char s1[max_line_length+1];
	X
	X   extract(s,n,s1,s2,s3);
	X   if (s1[0] != '-') {    /* default FL line option (-t) */
	X      strcpy(s3,s2);      /* re-set s2 and s3 */
	X      strcpy(s2,s1);
	X      return('t');     
	X   }
	X   if (s1[1] == '8') return('8');
	X   if (s1[1] == 'a') return('a');
	X   if (s1[1] == 'b') return('b');
	X   if (s1[1] == 'c') return('c');
	X   if (s1[1] == 'd') return('d');
	X   if (s1[1] == 'l') return('l');
	X   if (s1[1] == 't') return('t');
	X		/* unrecognizable option */
	X   fprintf(stderr, "***Invalid option in the input file!\n");
	X   exit(3); 
	X}
	X
	X/*
	X * process a sequence of DDL lines with -c flags. note that only
	X * last -c line retains its effect.
	X */
	Xlcd(f,chdir_name,chdir_req,op_flg,s1,s2)
	Xint  *chdir_req;
	Xchar *op_flg,*chdir_name,*s1,*s2;
	XFILE *f;
	X{
	X   int  chdir_line,flg;
	X   char c,s0[max_line_length+1];
	X
	X   *chdir_req=0;
	X
	X   chdir_line = 1;
	X   while (chdir_line) {
	X
	X      flg=nextline(s0,f);
	X      if (flg) return(1);  /* eof encountered, s0 is NULL */
	X
	X      c=option(s0,3,s1,s2);
	X      if (c=='c')   { *chdir_req=1; strcpy(chdir_name,s1); }
	X      else 	       chdir_line = 0;
	X   }
	X   *op_flg = c;
	X   return(0);
	X}
	X
	X/* 
	X * update the input file to delete the processed requests
	X */
	Xupdate_fin(fin,nfin,dpath,chdir_flg,chdir_name)
	Xint  chdir_flg;      /* 1 if an lcd opertion was performed. */
	Xchar *dpath,         /* directory path in the last DDL (-d) line */
	X     *nfin,    	     /* name of the input file */
	X     *chdir_name;    /* name of the local directory changed to */
	XFILE *fin;     	     /* file pointer for the input file */
	X{ 
	X  char name[10],s[max_line_length+1];
	X  int  pid;
	X  FILE *ftmp;
	X  
	X  pid=getpid(); 
	X  sprintf(name,"%d%tmp",pid);
	X  ftmp = fopen(name,"w");
	X            /* save the DDL line if there is more FL in the input*/
	X  if ( nextline(s,fin) == 0 ) {   /* if more non-blank lines */
	X      if (chdir_flg)
	X	fprintf(ftmp,"-c %s\n",chdir_name);
	X      fprintf(ftmp, "-d %s\n",dpath);
	X      fputs(s,ftmp);
	X      while ( fgets(s,max_line_length,fin) != NULL) fputs(s,ftmp); 
	X  }
	X  fclose(fin);
	X  fclose(ftmp);
	X
	X	    /* replace in_file by the temporary file (maybe empty) */ 
	X  sprintf(s,"rm '%s'",nfin);  
	X  system(s);
	X		     /* rename the tmp_file to in_file */
	X  sprintf(s,"mv '%s' '%s'",name,nfin);  
	X  system(s);
	X}
SHAR_EOF
if test 12936 -ne "`wc -c < 'nextfile.c'`"
then
	echo shar: "error transmitting 'nextfile.c'" '(should have been 12936 characters)'
fi
fi
echo shar: "extracting 'sample.dat'" '(262 characters)'
if test -f 'sample.dat'
then
	echo shar: "will not over-write existing file 'sample.dat'"
else
sed 's/^	X//' << \SHAR_EOF > 'sample.dat'
	X-l PS:<ANONYMOUS> root.dirlst
	X-d PD1:<MSDOS.DSKUTL>
	X-a	00-INDEX.TXT  DSKUTL.IDX
	X-8	DISCACHE.ARC  CACHE.ARC
	X	TIMEPARK.ARC
	X-a	VDSK.ASM
	X-d PD1:<MSDOS.SYSUTL>
	X-a	00-INDEX.TXT  SYSUTL.IDX
	X  	BENCH410.ARC
	X-a	BOOTCODE.ASM
	X  	CNFGTXT.ARC
	X  	DOS33HLP.ARC
	X  	DOS33PAT.ARC
SHAR_EOF
if test 262 -ne "`wc -c < 'sample.dat'`"
then
	echo shar: "error transmitting 'sample.dat'" '(should have been 262 characters)'
fi
fi
exit 0
#	End of shell archive
               O /
----------------X---------------- Cut Here
               O \



-- 
 _
Kevin D. Quitt         demott!kdq   kdq at demott.com
DeMott Electronics Co. 14707 Keswick St.   Van Nuys, CA 91405-1266
VOICE (818) 988-4975   FAX (818) 997-1190  MODEM (818) 997-4496 PEP last



More information about the Alt.sources mailing list