home *** CD-ROM | disk | FTP | other *** search
- /*
- * nextfile.c by Mingqi Deng, July 6, 1989
- *
- * get next requested file from an input file and prepare an ftp
- * script file for ftpget.c (cf. ftpget.c) The requested file
- * will be deleted from the input file.
- *
- * Compile:
- * cc -o nextfile nextfile.c
- * Execute:
- * nextfile in_file RemoteHost login password ftp_script
- * where
- * in_file :- input file to autoftp30.sh (cf. README) that consists
- * of two types of lines:
- * a) Device-directory line (DDL):
- * Format:
- * -d|c|l device_directory_name [dir_file]
- * where
- * "-d" :- the name on that line is a device_directory_name
- * that defines the directory where a subsequently
- * requested file resides, at the remote host.
- * This flag requires one name after the option.
- * "-c" :- a request to change the local directory so that
- * requested files will be put into that directory.
- * The name on that line is an existing local
- * directory. This flag requires one name after
- * the option, too.
- * "-l" :- a request to obtain a directory listing for the
- * remote directory named on that line. This flag
- * requires two names after the option: the name
- * of the remote directory, and the name of the
- * file to which the listing is to be stored.
- * Example:
- * -d PD1:<MSDOS.DSKUTL>
- * -l PD:<ANONYMOUS> root.dirlst
- * -c download
- * Function:
- * A "-d" DDL line defines the directory from which all
- * files on the subsequent file-lines, up to a new "-d"
- * DDL line, are to be fetched.
- * A "-l" DDL line gets a directory listing.
- * A "-c" DDL line changes the local directory PERMANANTLY
- * upto next "-c" DDL line.
- *
- * b) File lines (FL):
- * Format:
- * [-a|b|8|t] RemoteFile [LocalFile]
- * where:
- * a,b,8,t are flags of options:
- * "-a" :- a file is to be transferred in ASCII mode
- * "-b" :- a file is to be transferred in binary mode
- * "-t" or "-8"
- * :- a file is to be transferred in tenex mode
- * (32->8 bits conversion, which is the mode
- * you should use if you are ftp'ing into
- * SIMTEL20 from a DEC VAX or a SUN)
- * If the option is omitted, the default is "-t".
- * RemoteFile is the requested file's name at the remote host
- * LocalFile (optional) is the file name under which the
- * RemoteFile is to be received at the local machine.
- * If it is omitted, the default is RemoteFile.
- * Examples:
- * -a 00-INDEX.TXT DSKUTL.IDX
- * -8 BACKEZ.ARC
- * DISCACHE.ARC CACHE.ARC
- * TIMEPARK.ARC
- * -a VDSK.ASM
- * Functions:
- * An FL line specifies the name of a requested file
- * (whose directory is specified by a preceding DDL line),
- * and the transfer mode for the file.
- * *NOTE*
- * 1) An option on an FL line must NOT be omitted if the
- * RemoteFile starts with a "-". And only the first letter
- * of an option is effective.
- * 2) Options and names are separated by blanks or TABs.
- * No other delimiters can be used.
- * 3) There can be more than one blank or TAB between the
- * options and names.
- * 4) There can be blanks or TABs before an option. But
- * nothing should be inserted between "-" and a flag.
- * 5) A DDL or FL line can appear anywhere in an input file
- * though some sequence may not be meaningful.
- * 6) The input file may contain any number of blank line
- * anywhere. They are simply ignored.
- * 7) The file name on an FL line, and directory names on a
- * "-d" or "-l" DDL line can be either in lower or upper
- * case. This makes no difference as far as autoftp30.sh is
- * concerned. However, all options must be in lower case.
- *
- * RemoteHost:- the host name of the anonymous ftp session
- * login :- the login id for the anonymous ftp session
- * password :- the password for the anonymous ftp session
- * ftp_script:- the output file that consists of ftp commands
- *
- * Example:
- * nextfile 123input WSMR-SIMTEL20.ARMY.MIL anonymous guest 123ftp.script
- * Note :
- * 1. The maximum number of characters contained on each line in
- * file in_file (cf. sample.dat) is no more than max_line_length.
- * The default is 80. Adjust it if necessary.
- * 2. The constant TENEX in the second "#define" may need adjusting.
- * Instead of being '"tenex"', it may have to be '"type L 8"',
- * '"type local"' or '"type local byte"'. Do a "man ftp" to see
- * how your system wants it.
- */
-
- #include <stdio.h>
- #include <string.h>
-
- #define max_line_length 80
- #define TENEX "tenex"
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int no_more, /* 1 if end of file */
- dir_path, /* 1 if a DDL line of -d option seen */
- chdir_req, /* 1 if an lcd request on current DDL*/
- not_done, /* contol while loop */
- to_chdir, /* 1 if a pending lcd request */
- chdir_flg, /* 1 if an lcd request seen */
- action; /* 1 if usful request (dir, get) seen */
- char cmd[80],type[10],*dummy=NULL,
- op_flg, option(),
- s1[max_line_length+1],
- s2[max_line_length+1],
- chdir_name[max_line_length+1],/* local dir name to chage to */
- dir1[max_line_length+1], /* remote dir name to get dir list */
- dir2[max_line_length+1], /* file to get remote dir list */
- dpath[max_line_length+1]; /* the directory path in DDL line*/
- FILE *fin,*fftp;
-
- if (argc != 6) {
- fprintf(stderr,
- "***Usage: nextfile input RemoteHost login password ftp.script\n");
- exit(3);
- }
- if ( (fin = fopen(argv[1],"r")) == NULL) {
- fprintf(stderr,"***The input file does not exist!\n"); exit(3);
- }
-
- /* Create an ftp command file which will be executed once
- ftp starts up. This is true no matter whether a login
- failed or not. A quit command is always issued. */
- fftp = fopen(argv[5],"w");
- fprintf(fftp,"open %s\n",argv[2]);
- fprintf(fftp,"user %s %s\n",argv[3],argv[4]);
- fprintf(fftp,"type ascii\n");
- fprintf(fftp,"verbose\n");
-
- action=0; dir_path=0; to_chdir=0; chdir_flg=0; chdir_flg=0;
- not_done=1;
- while (not_done) {
- /* process a sequence of DDL lines with -c option */
- no_more=lcd(fin,chdir_name,&chdir_req,&op_flg,s1,s2);
- if (chdir_req) { to_chdir = 1; /* delay issuing lcd command, since
- only the last one is effective */
- chdir_flg = 1; /* neet to remember the lcd for
- subsequent file transfer */
- }
-
- if (no_more) {
- printf("=======Last request .......\n");
- if (action==0)
- printf( "***Warning: No files requested!\n");
- fprintf(fftp,"bye\n");
- fclose(fftp);
- update_fin(fin,argv[1],dummy,0,dummy);
- exit(0);
- }
- /* if not eof, is it a DDL or FL line? */
- if (op_flg == 'l') {
- if (s1[0] == '\0' || s2[0] == '\0') {
- fprintf(stderr,
- "***Invalid '-l' DDL line in the input file!\n");
- exit(3);
- }
- if (to_chdir)
- { fprintf(fftp,"lcd %s\n",chdir_name); to_chdir=0; }
- fprintf(fftp,"cd %s\n",s1); /* note that ascii mode was set */
- fprintf(fftp,"dir *.* %s\n",s2);
- action=1;
- } else
- if (op_flg == 'd') {
- if (s1[0]=='\0') {
- fprintf(stderr,
- "***Invalid device-directory-line(DDL) in the input file!\n");
- exit(3);
- }
- dir_path=1;
- strcpy(dpath,s1);
- } else { /* not a -c, -l, or -d line, must be an FL line */
- if (dir_path==0) { /* no -d DDL line seen yet */
- fprintf(stderr,
- "***Device-directory line missing in the input file!\n");
- exit(3);
- }
- not_done = 0;
- }
- } /* of while */
- if (to_chdir) /* delayed lcd: only the last lcd is effective*/
- fprintf(fftp,"lcd %s\n",chdir_name);
-
- /******* process an FL line *****/
- if (s1[0]=='\0') {
- fprintf(stderr,"***The requested file name is blank!\n");
- exit(3);
- }
- if (s2[0]=='\0') strcpy(s2,s1);
-
- /* set the file transfer mode */
- if (op_flg == 'b') strcpy(type,"binary");
- if (op_flg == 't') strcpy(type,TENEX);
- if (op_flg == '8') strcpy(type,TENEX);
-
- printf("=======Start requesting file %s .........\n",s1);
- /* type ascii has been set at the beginning */
- if (op_flg != 'a') fprintf(fftp,"type %s\n", type);
- fprintf(fftp,"get %s%s %s\nbye\n",dpath,s1,s2);
- fclose(fftp);
-
- update_fin(fin,argv[1],dpath,chdir_flg,chdir_name);
- }
-
- /* gets next non-blank line from file fin, return 1 if EOF */
- nextline(s,f)
- char *s;
- FILE *f;
- {
- char *p;
-
- while( (p=fgets(s,max_line_length,f)) != NULL)
- if (nonblank(s)) break;
- return(p==NULL);
- }
-
- /* nonblank(s)
- * returns true (non-zero) if s contains non-blank chars.
- */
- nonblank(s)
- char *s;
- {
- int i,flag;
-
- if (s==NULL) return(0);
- i = 0; flag = 0;
- for (i=0; i<strlen(s) && flag==0; i++)
- flag = (s[i]==' ' || s[i]==9 || s[i]=='\n' )? 0:1; /* 9 is tab*/
- return(flag);
- }
-
- /* extract(s,num,s0,s1,s2)
- * extracts num (1-3) many substring from s to s0, s1 and s2, where
- * blanks, tabs are delimiters, new line character is ignored. S is
- * terminated by a null character as usual, so will s0, s1 and s3.
- * Depending on s, any of s0, s1 or s2 can be an empty string.
- */
- extract(s,num,s0,s1,s2)
- char s[],s0[],s1[],s2[];
- int num;
- {
- int i,head,tail,ptr,l;
-
- l = strlen(s); tail=0;
- for (i=0;i<num;i++) {
- ptr=0;
- head=tail;
- while(s[head]==' ' || /* skip blanks, tabs and new line
- ('\0' is after '\n') */
- s[head]==9 ||
- s[head]=='\n') head++;
- tail=head;
-
- while(tail<l && /* stop if end of the string s */
- s[tail]!=' '&& /* stop if a blank, tab or NL is seen */
- s[tail]!=9 &&
- s[tail]!='\n')
- switch(i) {
- case 0: s0[ptr++]=s[tail++]; break;
- case 1: s1[ptr++]=s[tail++]; break;
- case 2: s2[ptr++]=s[tail++]; break;
- }
- switch(i) {
- case 0: s0[ptr]='\0'; break;
- case 1: s1[ptr]='\0'; break;
- case 2: s2[ptr]='\0'; break;
- }
- }
- }
-
- /*
- * extract options of a non-blank input line, detects invalid options,
- * and will "insert" '-t' option to a default FL line. When returning,
- * s2 and s3 are set to the 2nd and 3rd string on the line.
- */
- char option(s,n,s2,s3)
- char *s,*s2,*s3;
- int n;
- {
- char s1[max_line_length+1];
-
- extract(s,n,s1,s2,s3);
- if (s1[0] != '-') { /* default FL line option (-t) */
- strcpy(s3,s2); /* re-set s2 and s3 */
- strcpy(s2,s1);
- return('t');
- }
- if (s1[1] == '8') return('8');
- if (s1[1] == 'a') return('a');
- if (s1[1] == 'b') return('b');
- if (s1[1] == 'c') return('c');
- if (s1[1] == 'd') return('d');
- if (s1[1] == 'l') return('l');
- if (s1[1] == 't') return('t');
- /* unrecognizable option */
- fprintf(stderr, "***Invalid option in the input file!\n");
- exit(3);
- }
-
- /*
- * process a sequence of DDL lines with -c flags. note that only
- * last -c line retains its effect.
- */
- lcd(f,chdir_name,chdir_req,op_flg,s1,s2)
- int *chdir_req;
- char *op_flg,*chdir_name,*s1,*s2;
- FILE *f;
- {
- int chdir_line,flg;
- char c,s0[max_line_length+1];
-
- *chdir_req=0;
-
- chdir_line = 1;
- while (chdir_line) {
-
- flg=nextline(s0,f);
- if (flg) return(1); /* eof encountered, s0 is NULL */
-
- c=option(s0,3,s1,s2);
- if (c=='c') { *chdir_req=1; strcpy(chdir_name,s1); }
- else chdir_line = 0;
- }
- *op_flg = c;
- return(0);
- }
-
- /*
- * update the input file to delete the processed requests
- */
- update_fin(fin,nfin,dpath,chdir_flg,chdir_name)
- int chdir_flg; /* 1 if an lcd opertion was performed. */
- char *dpath, /* directory path in the last DDL (-d) line */
- *nfin, /* name of the input file */
- *chdir_name; /* name of the local directory changed to */
- FILE *fin; /* file pointer for the input file */
- {
- char name[10],s[max_line_length+1];
- int pid;
- FILE *ftmp;
-
- pid=getpid();
- sprintf(name,"%d%tmp",pid);
- ftmp = fopen(name,"w");
- /* save the DDL line if there is more FL in the input*/
- if ( nextline(s,fin) == 0 ) { /* if more non-blank lines */
- if (chdir_flg)
- fprintf(ftmp,"-c %s\n",chdir_name);
- fprintf(ftmp, "-d %s\n",dpath);
- fputs(s,ftmp);
- while ( fgets(s,max_line_length,fin) != NULL) fputs(s,ftmp);
- }
- fclose(fin);
- fclose(ftmp);
-
- /* replace in_file by the temporary file (maybe empty) */
- sprintf(s,"rm '%s'",nfin);
- system(s);
- /* rename the tmp_file to in_file */
- sprintf(s,"mv '%s' '%s'",name,nfin);
- system(s);
- }
-