home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / MSDOS / NCSA / TEL2307S.ZIP / FTP / FTPBIN.C
Encoding:
C/C++ Source or Header  |  1993-11-19  |  86.0 KB  |  2,537 lines

  1. /*
  2. *  User FTP
  3. *  6/8/87
  4. ****************************************************************************
  5. *                                                                          *
  6. *      by Tim Krauskopf and Swami Natarajan                                *
  7. *             Microsoft port by Heeren Pathak                               *
  8. *                                                                          *
  9. *      National Center for Supercomputing Applications                     *
  10. *      152 Computing Applications Building                                 *
  11. *      605 E. Springfield Ave.                                             *
  12. *      Champaign, IL  61820                                                *
  13. *                                                                          *
  14. *                                                                          *
  15. ****************************************************************************
  16. *
  17. */
  18.  
  19. /*
  20.  *Thanks to Jyrki Kuoppala(jkp@hutcs.hut.fi) for the basis of changes for
  21.  * MSC 5.1 
  22. */
  23.  
  24. #define FTPMASTER
  25.  
  26. #ifdef __TURBOC__
  27. #include "turboc.h"
  28. #endif
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <fcntl.h>
  32. #include <ctype.h>
  33. #include <sys/types.h>
  34. #include <sys/stat.h>
  35. #include <signal.h>
  36. #include <time.h>
  37. #include <io.h>
  38. #include <errno.h>
  39. #include <string.h>
  40. #include <conio.h>
  41.  
  42. #ifdef    MSC
  43. #define    O_RAW O_BINARY
  44. #include <dos.h>
  45. #ifndef _TURBOC_
  46. #include <direct.h>
  47. #endif
  48. #include <malloc.h>
  49. #endif
  50.  
  51. #ifdef MEMORY_DEBUG
  52. #include "memdebug.h"
  53. #endif
  54. #include "nkeys.h"
  55. #include "hostform.h"
  56. #include "whatami.h"
  57. #include "ftppi.h"              /* list of commands, help strings */
  58. #include "defines.h"
  59. #include "vidinfo.h"
  60. #include "version.h"
  61. #include "externs.h"
  62.  
  63. #define FASCII  0
  64. #define FIMAGE  1
  65. #define HFTP   21
  66.  
  67. #define FALSE        0
  68. #define TRUE        1
  69. #define SUCCESS        2
  70. #define HAVEDATA    4
  71. #define ERROR      -1
  72. #define NONE       -2
  73. #define ABORT       -3
  74. #define INCOMPLETE -4
  75. #define AMBIGUOUS  -5
  76.  
  77. int xp=0,                    /* general pointer */
  78.     towrite=0,                /* file transfer pointer */
  79.     len=0,                    /* file transfer length */
  80.     ftpnum,                    /* current command port */
  81.     ftpdata=-1,                /* current data port */
  82.     ftpfh,                    /* file handle for ftp */
  83.     ftpstate=0,                /* state for background process */
  84.   fcnt=0,                 /* counter for ftpd */
  85.     ftpfilemode=0,            /* file open mode for transfer */
  86.     foundbreak=0,            /* cntrl-break pending */
  87.     connected=0,            /* not connected */
  88.     debug=0,                /* debug level */
  89.     hash=0,                    /* hash mark printing */
  90.     sendport=1,                /* to send ports or not */
  91.     verbose=1,                /* informative messages */
  92.     redirect=1,                /* check for ouput redirection */
  93.     bell=0,                    /* sound bell */
  94.     autologin=1,            /* login on connect */
  95.     prompt=1,                /* check on multiple commands */
  96.     tempprompt=0,            /* temp var for Yes/No/All/Quit convenience */
  97.     glob=1,                    /* expand wildcards */
  98.     slashflip=1,            /* change \ to / */
  99.     capture=0,                /* capture data or not */
  100.     usemore=0,                /* use |more */
  101.     numlines=24,            /* number of lines for |more */
  102.     lineslft=24,            /* number of lines left for |more */
  103.     ttypass=0,                /* use interactive for password */
  104.     fromtty=1,                /* default input from tty */
  105.     f_enter_login=FALSE,    /* noninteractive but ask for user and pass */
  106.     display_init=FALSE,        /* TRUE if title line has been given */
  107.   scrsetup=0,       /* FALSE if need to clear screen */
  108.     dos_color;                /* storage for the DOS color setup */
  109.  
  110. FILE *fromfp=NULL;            /* file pointer for input */
  111. unsigned int curftpprt=0;    /* port to use */
  112. unsigned char destname[50]={0,0},    /* who to connect to */
  113.     s[550],                    /* temporary string */
  114.     path_name[_MAX_DRIVE+_MAX_DIR],        /* character storage for the path name */
  115.     captlist[2001],            /* response string */
  116.     ftpcommand[200];        /* command to execute */
  117. char printline[2001];        /* line to display */
  118.  
  119. struct config def;
  120.  
  121. char *config;
  122.  
  123. #ifdef _TURBOC_
  124. int use_mouse=0;
  125. #endif
  126.  
  127. #ifdef _TURBOC_
  128. #define BUFFERS 10000        /* size of buffer */
  129. #else
  130. #define BUFFERS 20000        /* size of buffer */
  131. #endif
  132. #define READSIZE 256        /* how much to read */
  133.  
  134. static unsigned char xs[BUFFERS+10];    /* buffer space for file transfer */
  135.  
  136. long start=0L,                /* timing var */
  137.     lengthfile=0L;            /* length of current file for transfer */
  138.  
  139. /* function prototypes for local functions */
  140. int main(int argc,char *argv[]);
  141. static char *stpblk(char *ch);
  142. static void breakstop(void );
  143. static unsigned int ftpport(void );
  144. static char *stptok(char *p,char *toword,int len,char *delim);
  145. static void nputs(char *line);
  146. static int printerr(void );
  147. static int ftppi(char *command);
  148. static int putstring(char *string);
  149. static int ftpgets(char *s,int lim,int echo);
  150. static int ftpdo(char *s,char *ofile);
  151. static int checkevent(void );
  152. static void nputchar(char ch);
  153. static int dumpcon(int cnum);
  154. static void telnet(int cnt);
  155. static int getword(char *string,char *word);
  156. static int finduniq(char *name,char *list[],int listsize);
  157. static int checkoredir(char *command,char *filename,int slashflip);
  158. static void flip_slashes(char *command,char *filename);
  159. static void getdir(int drive,char *path);
  160. static int ftpreplies(int cnum,int *rcode);
  161. static int getnname(char *string,char *word);
  162. static int rgetline(int cnum);
  163. static void userftpd(void );
  164. int numrows(void);
  165. void give_args(void);
  166. int domore(void);
  167. static char *check_file_name (char *in_fname, char *out_fname);
  168.  
  169. /************************************************************************/
  170. /* main-main procedure.  Displays opening message, parses arguments,
  171. /*      initializes network, reads user commands and executes them, and
  172. /*      cleans up.
  173. /************************************************************************/
  174. main(int argc,char *argv[])
  175. {
  176.     int i,c;
  177.     static char Configfile[50]="config.tel";
  178.     static char fromfile[20]="";
  179.  
  180.     /* Initialize the video configuration, and retrieve it */
  181.     initvideo();
  182.     getvconfig(&tel_vid_info);
  183.  
  184.     n_window(0,0,tel_vid_info.rows-1,tel_vid_info.cols-1);   /* to correctly handle non standard screen sizes (changed to work with n_puts  rmg 931100) */
  185. #ifdef __TURBOC__
  186.     fnsplit(argv[0],path_name,s,captlist,printline);   /* split path up */
  187. #else
  188.     _splitpath(argv[0],path_name,s,captlist,printline); /* split the full path name of telbin.exe into it's components */
  189. #endif
  190.     strcat(path_name,s);    /* append the real path name to the drive specifier */
  191.  
  192.     config=getenv("CONFIG.TEL");
  193.     if(config)
  194.         strcpy(Configfile,config);
  195.  
  196.     destname[0]='\0';        /* destination unknown */
  197.  
  198.     for(i=1; i<argc; i++) {     /* parse arguments */
  199.         if(argv[i][0]=='-' || argv[i][0]=='/') {
  200.             switch(tolower(argv[i][1])) {
  201.                 case 'r':        /* turn off output redirection */
  202.                     redirect=FALSE;
  203.                     break;
  204.  
  205.                 case 'v':        /* display informative messages */
  206.                     verbose=TRUE;
  207.                     break;
  208.  
  209.                 case 'n':        /* do not login on connect */
  210.                     autologin=FALSE;
  211.                     break;
  212.  
  213.                 case 'i':        /* interactive prompting off */
  214.                     prompt=FALSE;
  215.                     break;
  216.  
  217.                 case 'g':        /* wildcard expansion off */
  218.                     glob=FALSE;
  219.                     break;
  220.  
  221.                 case 'd':        /* debug, optional level */
  222.                     if(sscanf(argv[++i],"%d",&debug)<=0)
  223.                         debug=TRUE;
  224.                     break;
  225.  
  226.                 case 's':        /* do not change \ to / */
  227.                     slashflip=FALSE;
  228.                     break;
  229.  
  230.                 case 'h':        /* host file name */
  231.                     strcpy(Configfile,argv[++i]);
  232.                     break;
  233.  
  234.                 case 'm':        /* use built in |more */
  235.                     printf("\nusing more...");
  236.                     usemore=TRUE;
  237.                     lineslft=numlines=tel_vid_info.rows;
  238.                     printf("\nusing more...");
  239.                     break;
  240.  
  241.                 case 'e':        /* noninteractive commands with interactive login */
  242.                     f_enter_login=TRUE;
  243.  
  244.                 case 'p':        /* noninteractive with interactive password */
  245.                     ttypass=TRUE;
  246.  
  247.                 case 'f':                        /* noninteractive, optional filename */
  248.           fromtty=FALSE;  /* noninteractive input */
  249.                     strcpy(fromfile,argv[++i]);
  250.                     if(fromfile[0]) {
  251.                            fromfp=fopen(fromfile,"r");
  252.                            if(fromfp==NULL) {
  253.                 sprintf(printline,"Could not open file: %s",fromfile);
  254.                 nputs(printline);
  255.                 return(1);
  256.               } /* end if */
  257.           } /* end if */
  258.                     break;
  259.  
  260.                 case '?':
  261.                     give_args();
  262.  
  263.                 default:                        /* unknown option */
  264.                     sprintf(printline,"Unrecognized option -%c ignored",argv[i][1]);
  265.                     nputs(printline);
  266.                     break;
  267.               } /* end switch */
  268.           } /* end if */
  269.         else
  270.             sscanf(argv[i],"%s",destname);     /* destination host */
  271.       } /* end for */
  272.  
  273. #ifdef OLD_WAY
  274.     *strrchr(argv[0],'\\')==0;    /* put null at end of pathname string */
  275.     Shostpath(argv[0]);                /* and set the path */
  276. #endif
  277.     Shostfile(Configfile);        /* open host file */
  278.  
  279.  
  280. /*
  281. *  initialize network
  282. */
  283.     if(c=Snetinit()) {      /* cannot initialize network */
  284.         printerr();         /* display TCP/IP message */
  285.         nputs("Error initializing network");
  286.         if(c==-3)    /* check for BOOTP server not responding */
  287.             netshut();    /* release network */
  288.         return(1);
  289.       } /* end if */
  290.  
  291.     install_break((int *)&foundbreak);      /* install our BREAK handler */
  292.  
  293.     Sgetconfig(&def);               /* get information provided in hosts file */
  294.     if(destname[0]) 
  295.         sprintf(ftpcommand,"open %s",destname);    /* if destination specified, connect to it */
  296.   nputs("");                  /* initializes screen if not done */
  297.  
  298.     do {
  299.   /* cRMG  */
  300.     if(*ftpcommand) {
  301.       ftppi(ftpcommand);      /* if command available, execute it */
  302.       if(debug>4)
  303.         nputs("after returning from ftppi() ");
  304.     } /* end if */
  305. /*        if(fromtty)
  306.           n_cur(n_row(),0);                 in case screen messed up */
  307.     putstring("ftp> ");       /* prompt */
  308.     lineslft=numlines;              /* for |more */
  309.     c=ftpgets(ftpcommand,200,1);  /* read cmd from user */
  310.   } while(c!=ABORT);                /* Alt-F3 aborts */
  311.     netclose(ftpnum);                    /* close command connection */
  312.     netshut();                            /* terminate network stuff */
  313.     remove_break();                     /* restore previous break handler */
  314.  
  315.     return(0);
  316. }   /* end main() */
  317.  
  318. void give_args(void) {
  319.     nputs("FTP [-dfghimnprsv?]  [hostname]");
  320.     nputs("     d-Debug [level]");
  321.     nputs("     f-input File <filename>");
  322.     nputs("     g-Global wildcard expansion off");
  323.     nputs("     h-Host file <filename>");
  324.     nputs("     i-Interactive prompting off");
  325.     nputs("     m-use built in More");
  326.     nputs("     n-No login on connect");
  327.     nputs("     p-input file with interactive Password <filename>");
  328.     nputs("     r-turn off command line output Redirection");
  329.     nputs("     s-turn off Slash flip (/\\)");
  330.     nputs("     v-Verbose");
  331.     nputs("     ?-This list");
  332.     exit(1);
  333. }   /* end give_args() */
  334.  
  335. /**********************************************************************
  336. * ftpgets-read a line from the keyboard
  337. *       returns ABORT if aborted, non-zero on success
  338. * char *s;            where to put the line
  339. * int lim,echo;       max chars to read, echo?
  340. ************************************************************************/
  341. static int ftpgets(char *s,int lim,int echo)
  342. {
  343.     int c,count,i;
  344.     char *save, *ret;
  345.  
  346.     count=0;        /* none read */
  347.     save=s;            /* beginning of line */
  348.  
  349.     if(foundbreak) {
  350.         foundbreak=0;
  351.         *s='\0';
  352.         nputs("");
  353.         return(ABORT);
  354.       } /* end if */
  355.     if(!fromtty) {
  356.         if(fromfp==NULL)
  357.             ret=fgets(s,lim,stdin);
  358.         else
  359.             ret=fgets(s,lim,fromfp);
  360.         if(ret==NULL) {
  361.             nputs("EOF or error on read from file\n");
  362.             if(connected) {
  363.                 ftpdo("QUIT","");
  364.                 connected=FALSE;
  365.               } /* end if */
  366.             netclose(ftpnum);                   /* close command connection */
  367.             netshut();
  368.             remove_break();
  369. #ifdef NOT
  370.             if(display_init) {                 /* Restore DOS' color scheme */
  371.                 n_color(dos_color);
  372.                 n_clear();          /* clear screen */
  373. #ifdef NOT
  374.                 n_wrap(1);          /* cursor positioning */
  375. #endif
  376.                 n_cur(0,0);
  377.               } /* end if */
  378. #endif
  379.             exit(1);
  380.           } /* end if */
  381.         s[strlen(s)-1]='\0';     /* remove newline */
  382.         if(echo && fromfp)
  383.             nputs(s);
  384.         return(strlen(s));
  385.       } /* end if */
  386.     while(1) {
  387.         if(foundbreak) {        /* abort */
  388.             s=save;             /* reset line */
  389.             *s='\0';            /* null line */
  390.       nputs("");      /* newline */
  391.             foundbreak=0;        /* break processed */
  392.             return(ABORT);    
  393.           }
  394.         /* SAR 9/13/90 */
  395.         if(!kbhit()) {         /* if no char available */
  396.             checkevent();        /* check event queue */
  397.             c=0;
  398.           } /* end if */
  399.         else
  400.             c=getch();         /* else get character */
  401.         switch(c) {                /* allow certain editing chars */
  402.             case BACKSPACE:
  403.             case 8:                /* backspace */
  404.                 if(count) {
  405.                     if(echo) {
  406.             n_putchar((char)8);
  407.             n_putchar(' ');
  408.             n_putchar((char)8);
  409.                       } /* end if */
  410.                     count--;    /* one less character */
  411.                     s--;        /* move pointer backward */
  412.                   } /* end if */
  413.                 break;
  414.  
  415.             case EOF:
  416.             case 13:            /* carriage return,=ok */
  417.                 nputs("");        /* newline */
  418.                 *s='\0';        /* terminate the string */
  419.                 return(c);        /* return ok */
  420.  
  421.             case 10:            /* line feed */
  422.                 break;            /* ignore */
  423.  
  424.             case 21:            /* kill line */
  425.                 for(i=0; i<s-save; i++) {    /* length of line */
  426.                     if(echo) {                /* erase */
  427.                         nputchar(8);
  428.                         nputchar(' ');
  429.                         nputchar(8);
  430.                       } /* end if */
  431.                   } /* end for */
  432.                 s=save;    /* reset line */
  433.                 break;
  434.  
  435.             case 0:                /* do nothing */
  436.                 break;
  437.  
  438.             default:                        /* not special char */
  439.                 if(c>31&&c<127) {            /* printable */
  440.                     if(echo) nputchar((char)c);    /* display */
  441.                     *s++=(char)c;                /* add to string */
  442.                     count++;    /* length of string */
  443.                   } /* end if */
  444.                 else            /* acts as eol */
  445.                     return(c);    /* value of special char */
  446.                 if(count==lim) {            /* to length limit */
  447.                     *s='\0';    /* terminate */
  448.                     return(c);    
  449.                   } /* end if */
  450.             break;
  451.           } /* end switch */
  452.       } /* end while */
  453. }   /* end ftpgets() */
  454.  
  455. /************************************************************************
  456. * dumpcon
  457. *  take everything from a connection and send it to the screen
  458. *  return -1 on closed connection, else 0, 1 if paused
  459. ************************************************************************/
  460.  
  461. static int dumpcon(int cnum)
  462. {
  463.     int cnt;
  464.  
  465.     if(fromtty && n_scrlck())
  466.         return(TRUE);                /* if paused, nothing to do */
  467.     do {
  468.         cnt=netread(cnum,s,64);        /* get some from queue */
  469.         telnet(cnt);                /* display on screen, etc.*/
  470.       } while(cnt>0);
  471.     return(cnt);                    /* 0 normally, -1 if connection closed */
  472. }   /* end dumpcon() */
  473.  
  474. /***********************************************************************
  475. *  telnet
  476. *   filter telnet options on incoming data
  477. ************************************************************************/
  478. static void telnet(int cnt)
  479. {
  480.     int i;
  481.  
  482. if(debug>4) {
  483.     sprintf(printline,"telnet(): cnt=%d ",cnt);
  484.     nputs(printline);
  485.   }    /* end if */
  486.     for(i=0; i<cnt; i++) {                    /* put on screen */
  487.         if(s[i] & 128) {                    /* if over ASCII 128 */
  488.             sprintf(printline," %d ",(int)s[i]);    /* show as number */
  489.             nputs(printline);
  490.           } /* end if */
  491.         else
  492.             nputchar(s[i]);
  493.       } /* end for */
  494. if(debug>4) {
  495.     nputs("telnet(): leaving ");
  496.   }    /* end if */
  497. }   /* end telnet() */
  498.  
  499. /********************************************************************
  500. * ftppi()
  501. *  Protocol interpreter for user interface commands
  502. *  Will permit any command to be abbreviated uniquely.
  503. *  Recognizes commands, translates them to the protocol commands to be
  504. *  sent to the other server, and uses userftpd, the daemon, to do data
  505. *  transfers.
  506. ***********************************************************************/
  507. static int ftppi(char *command)
  508. {
  509.     int retry;
  510.     int cmdno,i,j;
  511.     char cmdname[50],
  512.         word[50],
  513.         line[100],
  514.         answer[20],
  515.         ofilename[50];
  516.     char *p;
  517.     struct machinfo *mp;
  518.  
  519. if(debug>1) {           /* print command */
  520.     sprintf(printline,"command: %s",command);
  521.     nputs(printline);
  522.   } /* end if */
  523.  
  524.     if(!getword(command,cmdname))   /* removes first word from command */
  525.         return(FALSE);
  526.  
  527.     strlwr(cmdname);
  528.     cmdno=finduniq(cmdname,ftp_cmdlist,NCMDS);    /* search cmdlist for prefix */
  529.     if(cmdno==AMBIGUOUS) {        /* not unique abbreviation */
  530.         nputs("?Ambiguous command");
  531.         return(FALSE);
  532.       } /* end if */
  533.     if(cmdno==NONE) {        /* not a prefix of any command */
  534.         nputs("?Invalid command");
  535.         return(FALSE);
  536.       } /* end if */
  537.  
  538. /* change \ to / and check if command output redirected */
  539.     if(cmdno!=BANG) {        /* don't alter shell escape */
  540.         if(redirect) {        /* check for ouput redirection selected */
  541.             if(cmdno!=LLS)        /* do not flip slashes for LLS */
  542.                 checkoredir(command,ofilename,slashflip);    /* check redirection, flip \ */
  543.             else
  544.                 checkoredir(command,ofilename,FALSE);    /* check redirection */
  545.           }    /* end if */
  546.         else {                /* no output redirection */
  547.             if(cmdno!=LLS && slashflip)        /* don't flip slashes for LLS and check for slashflipping here and assume it in routine */
  548.                 flip_slashes(command,ofilename);
  549.           }    /* end else */
  550.       } /* end if */
  551.  
  552.     switch(cmdno) {     /* process commands */
  553.         case QMARK:
  554.         case HELP:
  555.             if(!command[0]) {                        /* no argument */
  556.                 nputs("Commands may be abbreviated. Commands are:\n");
  557. /* display command list */
  558.                 printline[0]='\0';
  559.                 for(i=0; i<NCMDS; i++) {
  560.                     sprintf(word,"%-16s",ftp_cmdlist[i]);    /* get word from list */
  561.                     strcat(printline,word);            /* add to line */
  562.                     if(i%5==4) {                    /* display line */
  563.                         printline[79]='\0';
  564.                         nputs(printline);
  565.                         printline[0]='\0';
  566.                       } /* end if */
  567.                   } /* end for */
  568.                 if(i%5!=4)
  569.                     nputs(printline);                /* last line */
  570.                 return(TRUE);
  571.               } /* end if */
  572. /* help for specific commands */
  573.             else {
  574.                 while(getword(command,word)) {        /* loop for all args */
  575.                     i=finduniq(word,ftp_cmdlist,NCMDS);       /* which command? */
  576.                     if(i==AMBIGUOUS)                        /* non-unique command name */
  577.                         sprintf(printline,"?Ambiguous help command %s",word);
  578.                     else 
  579.                         if(i==NONE)                    /* no such command */
  580.                             sprintf(printline,"?Invalid help command %s",word);
  581.                         else                            /* display help string */
  582.                             sprintf(printline,"%s",helpstrings[i-1]);
  583.                     nputs(printline);
  584.                   } /* end while */
  585.                 return(TRUE);
  586.               } /* end else */
  587.             break;
  588.  
  589. #ifndef NO_WRT
  590.     case BANG:              /* shell escape */
  591.             fflush(stdout);
  592.             if(*(stpblk(command))) {        /* command specified */
  593.                 system(command);            /* execute command */
  594.                 return(TRUE);
  595.               } /* end if */
  596.             dosescape();                    /* subshell */
  597.             return(TRUE);
  598. #endif
  599.  
  600.         case BELL:
  601.             if(getword(command,word)) {        /* scan arg */
  602.                 strlwr(word);
  603.                 if(!strcmp(word,"off"))
  604.                      bell=FALSE;
  605.                 else 
  606.                     if(!strcmp(word,"on"))
  607.                         bell=TRUE;
  608.                 else 
  609.                     bell=!bell;
  610.               } /* end if */
  611.             else
  612.                  bell=!bell;
  613.             if(bell) 
  614.                 nputs("Bell mode on.");
  615.             else 
  616.                 nputs("Bell mode off.");
  617.             return(TRUE);
  618.  
  619.         case BYE:
  620.         case QUIT:
  621.             if(connected) {
  622.                 ftpdo("QUIT",ofilename);
  623.                 connected=FALSE;
  624.               } /* end if */
  625.             netclose(ftpnum);                    /* close command connection */
  626.             netshut();
  627.       remove_break();
  628.       if(fromtty)
  629.             if(display_init) {                 /* Restore DOS' color scheme */
  630.                 n_color(dos_color);
  631.                 n_clear();          /* clear screen */
  632. #ifdef NOT
  633.                 n_wrap(1);          /* cursor positioning */
  634. #endif
  635.                 n_cur(0,0);
  636.               } /* end if */
  637.             exit(0);
  638.  
  639.         case DEBUG:                /* turn on/off debugging, optional level */
  640.             if(sscanf(command,"%d",&i)>0)
  641.                 debug=i;                            /* level */
  642.             else
  643.                 if(getword(command,word)) {            /* scan arg */
  644.                     strlwr(word);
  645.                     if(!strcmp(word,"off"))
  646.                         debug=FALSE;
  647.                     else 
  648.                         if(!strcmp(word,"on"))
  649.                             debug=TRUE;
  650.                         else
  651.                             debug=!debug;
  652.                   } /* end if */
  653.             else
  654.                 debug=!debug;
  655.             if(debug) {
  656.                 sprintf(printline,"Debugging on(debug=%d).",debug);
  657.                 nputs(printline);
  658.               } /* end if */
  659.             else 
  660.                 nputs("Debugging off.");
  661.             return(TRUE);
  662.  
  663.         case GLOB:        /* wildcard expansion */
  664.             if(getword(command,word)) {
  665.                 strlwr(word);
  666.                 if(!strcmp(word,"off")) 
  667.                     glob=FALSE;
  668.                 else 
  669.                     if(!strcmp(word,"on")) 
  670.                         glob=TRUE;
  671.                     else 
  672.                         glob=!glob;
  673.               } /* end if */
  674.             else 
  675.                 glob=!glob;
  676.             if(glob) 
  677.                 nputs("Globbing on.");
  678.             else 
  679.                 nputs("Globbing off.");
  680.             return(TRUE);
  681.  
  682.         case HASH:        /* hash mark printing */
  683.             if(getword(command,word)) {
  684.                 strlwr(word);
  685.                 if(!strcmp(word,"off")) 
  686.                     hash=FALSE;
  687.                 else 
  688.                     if(!strcmp(word,"on")) 
  689.                         hash=TRUE;
  690.                     else 
  691.                         hash=!hash;
  692.               } /* end if */
  693.             else 
  694.                 hash=!hash;
  695.             if(hash) 
  696.                 nputs("Hash mark printing on(1024 bytes/hash mark).");
  697.             else 
  698.                 nputs("Hash printing off.");
  699.             return(TRUE);
  700.  
  701.         case INTERACTIVE:    /* prompting on multiple transfers */
  702.             prompt=TRUE;
  703.             nputs("Interactive mode on.");
  704.             return(TRUE);
  705.  
  706.         case LCD:        /* change local directory */
  707.             if(command[1]==':') {        /* if disk specified */
  708. #ifdef    MSC
  709. #ifdef __TURBOC__
  710.                 setdisk(tolower(command[0])-'a');
  711. #else
  712.                 unsigned int bogus;
  713.                 _dos_setdrive( tolower( command[0])-'a'+1,&bogus);
  714. #endif
  715. #else
  716.                 chgdsk(tolower(command[0])-'a');
  717. #endif
  718.                 strcpy(command,&command[2]);
  719.               } /* end if */
  720.             if(*(stpblk(command))&&chdir(command))     /* CD */
  721.                 nputs("Unable to change directory");
  722.             getdir(0,line);        /* current directory */
  723.             sprintf(printline,"Local directory now %s",line);
  724.             nputs(printline);
  725.             return(TRUE);
  726.  
  727.         case LLS:        /* local DIR */
  728.             sprintf(line,"DIR %s",command);
  729.             fflush(stdout);
  730.             system(line);
  731.             return(TRUE);
  732.  
  733.         case MORE:        /* toggle use of MORE */
  734.             if(getword(command,word)) {
  735.                 strlwr(word);
  736.                 if(!strcmp(word,"off"))
  737.                     usemore=FALSE;
  738.                 else if(!strcmp(word,"on"))
  739.                     usemore=TRUE;
  740.               } /* end if */
  741.             else
  742.                 usemore=!usemore;
  743.             if(usemore)
  744.                 nputs("Use of built in | more on.");
  745.             else
  746.                 nputs("Use of built in | more off.");
  747.             lineslft=numlines=tel_vid_info.rows;
  748.             break;
  749.  
  750.         case NONINTERACTIVE:    /* turn off interactive prompting */
  751.             prompt=FALSE;
  752.             nputs("Interactive mode off.");
  753.             return(TRUE);
  754.  
  755.         case OPEN:        /* open connection to host */
  756.             if(connected) {
  757.                 nputs("Already connected.");
  758.                 return(FALSE);
  759.               } /* end if */
  760.             while(!(*(stpblk(command)))) {        /* no argument */
  761.                 putstring("To: ");
  762.                 if(ftpgets(command,100,1)==ABORT) 
  763.                     return(FALSE);
  764.               } /* end while */
  765.             getword(command,destname);  /* host name */
  766.             mp=Sgethost(destname);        /* get host info */
  767.             if(foundbreak)
  768.                 return(FALSE);          /* abort */
  769.             if(mp==NULL) {                /* try domain serving */
  770.                 Sdomain(destname);
  771.                 while(mp==NULL) {
  772.                     switch(checkevent()) {
  773.                         case ABORT:
  774.                             return(FALSE);    /* abort */
  775.  
  776.                         case DOMFAIL:
  777.                             printerr();
  778.                             sprintf(printline,"Unknown host: %s\n",destname);
  779.                             nputs(printline);
  780.                             return(FALSE);
  781.  
  782.                         case DOMOK:
  783.                             mp=Slooknum(ftpnum);    /* get host info */
  784.                             break;
  785.  
  786.                         default:
  787.                             break;
  788.                       } /* end switch */
  789.                   } /* end while */
  790.               } /* end if */
  791.       display_init=TRUE;
  792.       def.color[0]=(unsigned char)(mp->nfcolor+(mp->nbcolor<<4));
  793.       scrsetup=FALSE;
  794.       nputs("");
  795.       if(sscanf(command,"%d",&i)>0) /* port number specified */
  796.                 ftpnum=Snetopen(mp,i);
  797.             else
  798.                 ftpnum=Snetopen(mp,HFTP);        /* default port */
  799.             if(foundbreak)
  800.                 return(FALSE);       /* abort */
  801.             if(ftpnum<0) {                /* error on open */
  802.                 printerr();
  803.                 sprintf(printline,"Unable to connect to %s",destname);
  804.                 nputs(printline);
  805.                 return(FALSE);
  806.               } /* end if */
  807.             j=ftpreplies(ftpnum,&i);      /* response from other end */
  808.             if(j==FALSE || j==ERROR || j==NONE || j==ABORT) {
  809.                 return(FALSE);
  810.               } /* end if */
  811.             if(foundbreak)
  812.                 return(FALSE);
  813.             connected=TRUE;
  814.             if(autologin) {        /* execute login command */
  815.                 strcpy(command,"user");
  816.                 ftppi(command);
  817.               } /* end if */
  818.             return(TRUE);
  819.  
  820.         case PROMPT:            /* interactive prompting */
  821.             if(getword(command,word)) {
  822.                 strlwr(word);
  823.                 if(!strcmp(word,"off")) 
  824.                     prompt=FALSE;
  825.                 else 
  826.                     if(!strcmp(word,"on")) 
  827.                         prompt=TRUE;
  828.                     else
  829.                         prompt=!prompt;
  830.               } /* end if */
  831.             else 
  832.                 prompt=!prompt;
  833.             if(prompt) 
  834.                 nputs("Interactive mode on.");
  835.             else 
  836.                 nputs("Interactive mode off.");
  837.             return(TRUE);
  838.  
  839.         case SENDPORT:            /* send PORT commands for each transfer */
  840.             if(getword(command,word)) {
  841.                 strlwr(word);
  842.                 if(!strcmp(word,"off")) 
  843.                     sendport=FALSE;
  844.                 else 
  845.                     if(!strcmp(word,"on")) 
  846.                         sendport=TRUE;
  847.                     else 
  848.                         sendport=!sendport;
  849.               } /* end if */
  850.             else 
  851.                 sendport=!sendport;
  852.             if(sendport) 
  853.                 nputs("Use of PORT cmds on.");
  854.             else 
  855.                 nputs("Use of PORT cmds off.");
  856.             return(TRUE);
  857.  
  858.         case SLASHFLIP:            /* change \ to / */
  859.             if(getword(command,word)) {
  860.                 strlwr(word);
  861.                 if(!strcmp(word,"off")) 
  862.                     slashflip=FALSE;
  863.                 else 
  864.                     if(!strcmp(word,"on")) 
  865.                         slashflip=TRUE;
  866.                     else 
  867.                         slashflip=!slashflip;
  868.               } /* end if */
  869.             else 
  870.                 slashflip=!slashflip;
  871.             if(slashflip) 
  872.                 nputs("Slash translation on.");
  873.             else 
  874.                 nputs("Slash translation off.");
  875.             return(TRUE);
  876.  
  877.         case STATUS:        /* display status info */
  878.             if(connected) {
  879.                 sprintf(printline,"Connected to %s",destname);
  880.                 nputs(printline);
  881.               } /* end if */
  882.             if(ftpfilemode==FASCII) 
  883.                 nputs("Transfer mode is ascii.");
  884.             else 
  885.                 nputs("Transfer mode is binary.");
  886.             if(bell) 
  887.                 nputs("Bell on."); else nputs("Bell off.");
  888.             if(debug) {
  889.                 sprintf(printline,"Debugging on.(Debug=%d)",debug);
  890.                 nputs(printline);
  891.               } /* end if */
  892.             else 
  893.                 nputs("Debugging off.");
  894.             if(glob) 
  895.                 nputs("Filename globbing on."); 
  896.             else 
  897.                 nputs("Filename globbing off.");
  898.             if(hash) 
  899.                 nputs("Hash-mark printing on.");
  900.             else 
  901.                 nputs("Hash-mark printing off.");
  902.             if(prompt)
  903.                 nputs("Interactive prompting on."); 
  904.             else 
  905.                 nputs("Interactive prompting off.");
  906.             if(sendport) 
  907.                 nputs("Sending of port commands on.");
  908.             else 
  909.                 nputs("Sending of PORT cmds off.");
  910.             if(slashflip) 
  911.                 nputs("Flipping \\ to / on.");
  912.             else
  913.                 nputs("Flipping \\ to / off.");
  914.             if(verbose) 
  915.                 nputs("Verbose mode on."); 
  916.             else 
  917.                 nputs("Verbose mode off.");
  918.             if(usemore)
  919.                 nputs("Use of built in | more on.");
  920.             else
  921.                 nputs("Use of built in | more off.");
  922.             if(connected) {        /* send STAT command */
  923.                 nputs("\nRemote status:");
  924.                 ftpdo("STAT",ofilename);
  925.               } /* end if */
  926.             return(TRUE);
  927.  
  928.         case VERBOSE:        /* display informative messages */
  929.             if(getword(command,word)) {
  930.                 strlwr(word);
  931.                 if(!strcmp(word,"off")) 
  932.                     verbose=FALSE;
  933.                 else 
  934.                     if(!strcmp(word,"on")) 
  935.                         verbose=TRUE;
  936.                     else 
  937.                         verbose=!verbose;
  938.               } /* end if */
  939.             else 
  940.                 verbose=!verbose;
  941.             if(verbose) 
  942.                 nputs("Verbose mode on.");
  943.             else 
  944.                 nputs("Verbose mode off.");
  945.             return(TRUE);
  946.  
  947.         default:        /* The other commands valid only if connected */
  948.             if(!connected) {
  949.                 nputs("Not connected.");
  950.                 return(FALSE);
  951.               } /* end if */
  952.  
  953.             switch(cmdno) {
  954.                 case ASCII:         /* transfer mode */
  955.                     ftpdo("TYPE A",ofilename);
  956.                     return(TRUE);
  957.  
  958. #ifndef NO_WRT
  959.                 case BGET:          /* get file in binary mode */
  960.                     i=ftpfilemode;  /* save current mode */
  961.                     if(i==FASCII)
  962.                         ftpdo("TYPE I",ofilename);
  963.                     while(!(*(stpblk(command)))) {
  964.                         putstring("File: ");
  965.                         if(ftpgets(command,100,1)==ABORT)
  966.                             return(FALSE);
  967.                       } /* end while */
  968.                     sprintf(line,"RETR %s",command);
  969.                     ftpdo(line,ofilename);      /* get file */
  970.                     if(i==FASCII)
  971.                         ftpdo("TYPE A",ofilename);  /* restore mode */
  972.                     return(TRUE);
  973. #endif
  974.  
  975.                 case BINARY:        /* binary mode */
  976.                     ftpdo("TYPE I",ofilename);
  977.                     return(TRUE);
  978.  
  979.                 case BPUT:          /* put file in binary mode */
  980.                     i=ftpfilemode;
  981.                     if(i==FASCII)
  982.                         ftpdo("TYPE I",ofilename);
  983.                     while(!(*(stpblk(command)))) {      /* if no arg */
  984.                         putstring("File: ");    /* get from user */
  985.                         if(ftpgets(command,100,1)==ABORT)
  986.                             return(FALSE);
  987.                       } /* end while */
  988.                     sprintf(line,"STOR %s",command);
  989.                     for(retry=0; retry<5; retry++) {
  990.                         if((i=ftpdo(line,ofilename))==TRUE) {
  991.                             if(i==FASCII)
  992.                                 ftpdo("TYPE A",ofilename);
  993.                             return(TRUE);
  994.                           } /* end if */
  995.                         else
  996.                             if(i!=FALSE) {
  997.                                 if(i==FASCII)
  998.                                     ftpdo("TYPE A",ofilename);
  999.                                 return(ERROR);
  1000.                               } /* end if */
  1001.                         printf("\nRetrying...");
  1002.                       } /* end for */
  1003.                     printf("Maximum retry count reached.  Aborting this file transfer...");
  1004.                     return(FALSE);
  1005.  
  1006.                 case CD:        /* change remote directory */
  1007.                     while(!(*(stpblk(command)))) {      /* if no arg, get from user */
  1008.                         putstring("To: ");
  1009.                         if(ftpgets(command,100,1)==ABORT)
  1010.                             return(FALSE);  /* abort */
  1011.                       } /* end while */
  1012.                     getword(command,word);
  1013.                     if(!strcmp(word,"..")) {    /* special case */
  1014.                         i=ftpdo("CDUP",ofilename);
  1015.                         if(i!=ERROR)
  1016.                             return(TRUE);       /* if CDUP understood */
  1017.                         nputs("Trying again...");
  1018.                         i=ftpdo("XCUP",ofilename);  /* try alternative */
  1019.                         if(i!=ERROR)
  1020.                             return(TRUE);
  1021.                         nputs("Trying again...");       /* else try usual CD */
  1022.                       } /* end if */
  1023.                     sprintf(line,"CWD %s",word);        /* try CWD */
  1024.                     i=ftpdo(line,ofilename);
  1025.                     if(i!=ERROR)
  1026.                         return(TRUE);
  1027.                     nputs("Trying again...");
  1028.                     sprintf(line,"XCWD %s",word);       /* try XCWD */
  1029.                     ftpdo(line,ofilename);
  1030.                     return(TRUE);
  1031.  
  1032.                 case CLOSE:             /* drop connection */
  1033.                     ftpdo("QUIT",ofilename);
  1034.                     connected=FALSE;
  1035.                     return(TRUE);
  1036.  
  1037.                 case DEL:
  1038.                 case RM:
  1039.                     getword(command,word);
  1040.                     while(!word[0]) {   /* get arg from user */
  1041.                         putstring("File: ");
  1042.                         if(ftpgets(word,100,1)==ABORT)
  1043.                             return(FALSE);  /* abort */
  1044.                       } /* end while */
  1045.                     if(prompt) {        /* check interactively */
  1046.                         sprintf(printline,"Delete %s? ",word);
  1047.                         putstring(printline);
  1048.                         ftpgets(answer,20,1);
  1049.                         if(tolower(*(stpblk(answer)))!='y')
  1050.                             return(TRUE);
  1051.                       } /* end if */
  1052.                     sprintf(line,"DELE %s",word);
  1053.                     ftpdo(line,ofilename);
  1054.                     return(TRUE);
  1055.  
  1056.                 case DIR:       /* get list of remote files */
  1057.                     i=ftpfilemode;  /* save mode */
  1058.                     if(i==FIMAGE)
  1059.                         ftpdo("TYPE A",ofilename);
  1060.                     if(getword(command,word)) { /* do DIR */
  1061.                         sprintf(line,"LIST %s",word);
  1062.                         ftpdo(line,ofilename);
  1063.                       } /* end if */
  1064.                     else
  1065.                         ftpdo("LIST",ofilename);
  1066.                     if(i==FIMAGE)
  1067.                         ftpdo("TYPE I",ofilename);
  1068.                     return(TRUE);
  1069.  
  1070. #ifndef NO_WRT
  1071.                 case GET:
  1072.                 case RECV:      /* get remote file */
  1073.                     while(!(*(stpblk(command)))) {      /* if no arg */
  1074.                         putstring("File: ");
  1075.                         if(ftpgets(command,100,1)==ABORT)
  1076.                             return(FALSE);  /* abort */
  1077.                       } /* end while */
  1078.                     sprintf(line,"RETR %s",command);
  1079.                     ftpdo(line,ofilename);
  1080.                     return(TRUE);
  1081. #endif
  1082.  
  1083.                 case LS:        /* get remote file list-short */
  1084.                     i=ftpfilemode;
  1085.                     if(i==FIMAGE)
  1086.                         ftpdo("TYPE A",ofilename);
  1087.                     if(getword(command,word)) {
  1088.                         sprintf(line,"NLST %s",word);
  1089.                         ftpdo(line,ofilename);
  1090.                       } /* end if */
  1091.                     else
  1092.                         ftpdo("NLST",ofilename);
  1093.                     if(i==FIMAGE)
  1094.                         ftpdo("TYPE I",ofilename);
  1095.                     return(TRUE);
  1096.  
  1097.                 case MDELETE:
  1098.                     while(!(*(stpblk(command)))) {      /* no arg */
  1099.                         putstring("Files: ");
  1100.                         if(ftpgets(command,100,1)==ABORT)
  1101.                             return(FALSE);  /* abort */
  1102.                       } /* end while */
  1103.                     while(getword(command,word)) {      /* for each arg */
  1104.                         if(glob) {      /* wildcard expansion */
  1105.                             sprintf(line,"NLST %s",word);
  1106.                             capture=TRUE;
  1107.                             ftpdo(line,ofilename);  /* put exapnsion in captlist */
  1108.                             capture=FALSE;
  1109.                           } /* end if */
  1110.                         else
  1111.                             strcpy(captlist,word);  /* captlist has name(s) now */
  1112.                         while(getnname(captlist,word)) {    /* for each name */
  1113.                             if(prompt) {    /* check */
  1114.                                 sprintf(printline,"mdelete %s? ",word);
  1115.                                 putstring(printline);
  1116.                                 if(ftpgets(answer,20,1)==ABORT) {   /* abort */
  1117.                                     command[0]='\0';    /* no more processing */
  1118.                                     break;          /* quit immediately */
  1119.                                   } /* end if */
  1120.                                 if(tolower(*(stpblk(answer)))!='y')
  1121.                                     continue;
  1122.                               } /* end if */
  1123.                             sprintf(line,"DELE %s",word);   /* delete */
  1124.                             ftpdo(line,ofilename);
  1125.                           } /* end while */
  1126.                       } /* end while */
  1127.                     return(TRUE);
  1128.  
  1129.                 case MDIR:      /* remote multiple DIR */
  1130.                     i=ftpfilemode;  /* save mode */
  1131.                     if(i==FIMAGE)
  1132.                         ftpdo("TYPE A",ofilename);
  1133.                     while(!(*(stpblk(command)))) {      /* no arg */
  1134.                         putstring("Directories: ");
  1135.                         if(ftpgets(command,100,1)==ABORT)
  1136.                             return(FALSE);    /* abort */
  1137.                       } /* end while */
  1138.                     while(getword(command,word)) {      /* for each arg */
  1139.                         if(glob) {      /* expand wildcards */
  1140.                             sprintf(line,"NLST %s",word);
  1141.                             capture=TRUE;
  1142.                             ftpdo(line,ofilename);
  1143.                             capture=FALSE;
  1144.                           } /* end if */
  1145.                         else
  1146.                             strcpy(captlist,word);
  1147.                         while(getnname(captlist,word)) {    /* for each name */
  1148.                             if(prompt) {    /* check */
  1149.                                 sprintf(printline,"mdir %s? ",word);
  1150.                                 putstring(printline);
  1151.                                 if(ftpgets(answer,20,1)==ABORT) {   /* abort */
  1152.                                     command[0]='\0';    /* no more processing */
  1153.                                     break;          /* quit immediately */
  1154.                                   } /* end if */
  1155.                                 if(tolower(*(stpblk(answer)))!='y')
  1156.                                     continue;
  1157.                               } /* end if */
  1158.                             sprintf(line,"LIST %s",word);   /* DIR */
  1159.                             ftpdo(line,ofilename);
  1160.                           } /* end while */
  1161.                       } /* end while */
  1162.                     if(i==FIMAGE)
  1163.                         ftpdo("TYPE I",ofilename);
  1164.                     return(TRUE);
  1165.  
  1166. #ifndef NO_WRT
  1167.                 case MGET:      /* get multiple files */
  1168. #ifdef OLD_WAY
  1169.                     getword(command,line);
  1170. #else
  1171.                     strcpy(line,command);
  1172. #endif
  1173.                     while(!line[0]) {   /* no arg */
  1174.                         putstring("Files: ");
  1175.                         if(ftpgets(line,100,1)==ABORT)
  1176.                             return(FALSE);  /* abort */
  1177.                       } /* end if */
  1178.                     while(getword(line,word)) { /* for each arg */
  1179.                         if(glob) {      /* expand wildcards */
  1180.                             sprintf(command,"NLST %s",word);
  1181.                             capture=TRUE;
  1182.                             ftpdo(command,ofilename);
  1183.                             capture=FALSE;
  1184.                           } /* end if */
  1185.                         else
  1186.                             strcpy(captlist,word);
  1187.                         while(getnname(captlist,word)) {    /* for each name */
  1188.                             if(prompt) {    /* check */
  1189.                                 sprintf(printline,"mget %s? (Yes/No/All/Quit) ",word);
  1190.                                 putstring(printline);
  1191.                                 if((ftpgets(answer,20,1)==ABORT) || (tolower(*(stpblk(answer)))=='q')) {  /* abort */
  1192.                                     command[0]='\0';    /* no more processing */
  1193.                                     break;          /* quit immediately */
  1194.                                   } /* end if */
  1195.                                 if(tolower(*(stpblk(answer)))=='a') {   /* All */
  1196.                                     prompt=FALSE;
  1197.                                     tempprompt=TRUE;
  1198.                                   } /* end if */
  1199.                                 if((tolower(*(stpblk(answer)))!='y') && (tolower(*(stpblk(answer)))!='a'))
  1200.                                     continue;
  1201.                               } /* end if */
  1202.                             sprintf(command,"RETR \"%s\"",word);
  1203.                             ftpdo(command,ofilename);
  1204.                           } /* end while */
  1205.                         if(tempprompt==TRUE) {
  1206.                             prompt=TRUE;
  1207.                             tempprompt=FALSE;
  1208.                           } /* end if */
  1209.                       } /* end while */
  1210.                     return(TRUE);
  1211. #endif
  1212.  
  1213.                 case MKDIR:     /* create directory */
  1214.                     while(!(*(stpblk(command)))) {      /* no arg */
  1215.                         putstring("Directory: ");
  1216.                         if(ftpgets(command,100,1)==ABORT)
  1217.                             return(FALSE);  /* abort */
  1218.                       } /* end while */
  1219.                     sprintf(line,"XMKD %s",command);    /* try XMKD */
  1220.                     i=ftpdo(line,ofilename);
  1221.                     if(i!=ERROR)
  1222.                         return(TRUE);
  1223.                     nputs("Trying again...");
  1224.                     sprintf(line,"MKD %s",command);     /* else try MKD */
  1225.                     ftpdo(line,ofilename);
  1226.                     return(TRUE);
  1227.  
  1228.                 case MLS:
  1229.                     i=ftpfilemode;
  1230.                     if(i==FIMAGE)
  1231.                         ftpdo("TYPE A",ofilename);
  1232.                     while(!(*(stpblk(command)))) {      /* no arg */
  1233.                         putstring("Directories: ");
  1234.                         if(ftpgets(command,100,1)==ABORT)
  1235.                             return(FALSE);  /* abort */
  1236.                       } /* end while */
  1237.                     while(getword(command,word)) {      /* for each arg */
  1238.                         if(glob) {      /* exapnd wildcards */
  1239.                             sprintf(line,"NLST %s",word);
  1240.                             capture=TRUE;
  1241.                             ftpdo(line,ofilename);
  1242.                             capture=FALSE;
  1243.                           } /* end if */
  1244.                         else
  1245.                             strcpy(captlist,word);
  1246.                         while(getnname(captlist,word)) {    /* for each name */
  1247.                             if(prompt) {        /* check */
  1248.                                 sprintf(printline,"mls %s? ",word);
  1249.                                 putstring(printline);
  1250.                                 if(ftpgets(answer,20,1)==ABORT) {  /* abort */
  1251.                                     command[0]='\0';    /* no more processing */
  1252.                                     break;          /* quit immediately */
  1253.                                   } /* end if */
  1254.                                 if(tolower(*(stpblk(answer)))!='y')
  1255.                                     continue;
  1256.                               } /* end if */
  1257.                             sprintf(line,"NLST %s",word);   /* DIR */
  1258.                             ftpdo(line,ofilename);
  1259.                           } /* end while */
  1260.                       } /* end while */
  1261.                     if(i==FIMAGE)
  1262.                         ftpdo("TYPE I",ofilename);
  1263.                     return(TRUE);
  1264.  
  1265.                 case MODE:      /* set stream mode */
  1266.                     getword(command,word);
  1267.                     strlwr(word);
  1268.                     if(strncmp(word,"stream",strlen(word)))
  1269.                         nputs("We only support stream mode, sorry.");
  1270.                     else
  1271.                         nputs("Mode is stream.");
  1272.                     return(TRUE);
  1273.  
  1274.                 case MPUT:      /* put multiple files */
  1275. #ifdef OLD_WAY
  1276.                     getword(command,line);
  1277. #else
  1278.                     strcpy(line,command);
  1279. #endif
  1280.                     while(!line[0]) {   /* no arg */
  1281.                         putstring("Files: ");
  1282.                         if(ftpgets(line,100,1)==ABORT)
  1283.                             return(FALSE);  /* abort */
  1284.                       } /* end while */
  1285.                     p=NULL; /* no names expanded yet */
  1286.                     while(getword(line,word)) { /* for each arg */
  1287.                         do {        /* for each name */
  1288.                             if(glob) {      /* local wildcard expansion */
  1289.                                 if(p==NULL) {   /* if no expansions yet */
  1290.                                     p=firstname(word,0);    /* get first name, with no file information attached */
  1291.                                     if(p==NULL) {   /* if no expansions */
  1292.                                         sprintf(printline,"No match for %s",word);
  1293.                                         nputs(printline);
  1294.                                         continue;
  1295.                                       } /* end if */
  1296.                                   } /* end if */
  1297.                                 else {      /* not first name */
  1298.                                     p=nextname(0);      /* get next name, with no file information attached */
  1299.                                     if(p==NULL)
  1300.                                         continue;   /* if no names, next arg */
  1301.                                   } /* end else */
  1302.                               } /* end if */
  1303.                             else
  1304.                                 p=word;     /* no expansion */
  1305.                             if(prompt) {    /* check */
  1306.                                 sprintf(printline,"mput %s? (Yes/No/All/Quit) ",p);
  1307.                                 putstring(printline);
  1308.                                 if((ftpgets(answer,20,1)==ABORT)||(tolower(*(stpblk(answer)))=='q')) {  /* abort */
  1309.                                     command[0]='\0';    /* no more processing */
  1310.                                     break;          /* quit immediately */
  1311.                                   } /* end if */
  1312.                                 if(tolower(*(stpblk(answer)))=='a') {
  1313.                                     prompt=FALSE;
  1314.                                     tempprompt=TRUE;
  1315.                                   } /* end if */
  1316.                                 if((tolower(*(stpblk(answer)))!='y')&&(tolower(*(stpblk(answer)))!='a'))
  1317.                                     continue;
  1318.                               } /* end if */
  1319.                             sprintf(command,"STOR \"%s\"",p);   /* name may have special chars */
  1320.                             ftpdo(command,ofilename);
  1321.                           } while(glob && p!=NULL);       /* Not last expansion */
  1322.                         if(tempprompt) {
  1323.                             prompt=TRUE;
  1324.                             tempprompt=FALSE;
  1325.                           } /* end if */
  1326.                       } /* end while */
  1327.                     return(TRUE);
  1328.  
  1329.                 case PUT:
  1330.                 case SEND:      /* put file */
  1331.                     while(!(*(stpblk(command)))) {      /* no args */
  1332.                         putstring("File: ");
  1333.                         if(ftpgets(command,100,1)==ABORT)
  1334.                             return(FALSE);
  1335.                       } /* end while */
  1336.                     sprintf(line,"STOR %s",command);    /* put file */
  1337.                     for(retry=0; retry<5; retry++) {
  1338.                         if((i=ftpdo(line,ofilename))==TRUE)
  1339.                             return(TRUE);
  1340.                         else if(i!=FALSE)
  1341.                             return(ERROR);
  1342.                         printf("\nRetrying...");
  1343.                       } /* end for */
  1344.                     printf("\nMaximum retry count reached.  Aborting file transfer...");
  1345.                     return(ERROR);
  1346.  
  1347.                 case PWD:
  1348.                     i=ftpdo("XPWD",ofilename);      /* try XPWD */
  1349.                     if(i!=ERROR)
  1350.                         return(TRUE);
  1351.                     nputs("Trying again...");
  1352.                     ftpdo("PWD",ofilename);         /* else try PWD */
  1353.                     return(TRUE);
  1354.  
  1355.                 case QUOTE:
  1356.                     while(!(*(stpblk(command)))) {      /* no arg */
  1357.                         putstring("Command: ");
  1358.                         if(ftpgets(command,100,1)==ABORT)
  1359.                             return(FALSE);
  1360.                       } /* end while */
  1361.                     ftpdo(command,ofilename);       /* send command */
  1362.                     return(TRUE);
  1363.  
  1364.                 case REMOTEHELP:                /* get help */
  1365.                     if(*(stpblk(command))) {        /* for specific command */
  1366.                         sprintf(line,"HELP %s",command);
  1367.                         ftpdo(line,ofilename);
  1368.                       } /* end if */
  1369.                     else
  1370.                         ftpdo("HELP",ofilename);        /* generic help */
  1371.                     return(TRUE);
  1372.  
  1373.                 case RENAME:        /* rename remote file */
  1374.                     while(!(*(stpblk(command)))) {      /* no arg */
  1375.                         putstring("From: ");
  1376.                         if(ftpgets(command,100,1)==ABORT)
  1377.                             return(FALSE);
  1378.                       } /* end if */
  1379.                     getword(command,word);
  1380.                     sprintf(line,"RNFR %s",word);
  1381.                     ftpdo(line,ofilename);      /* send rename from name */
  1382.                     while(!(*(stpblk(command)))) {      /* no second arg */
  1383.                         putstring("To: ");
  1384.                         if(ftpgets(command,100,1)==ABORT) {
  1385.                             ftpdo("ABOR",ofilename);
  1386.                             return(FALSE);
  1387.                           } /* end if */
  1388.                       } /* end while */
  1389.                     sprintf(line,"RNTO %s",command); /* send rename to name */
  1390.                     ftpdo(line,ofilename);
  1391.                     return(TRUE);
  1392.  
  1393.                 case RMDIR:         /* remove remote dir */
  1394.                     while(!(*(stpblk(command)))) {      /* no arg */
  1395.                         putstring("Directory: ");
  1396.                         if(ftpgets(command,100,1)==ABORT)
  1397.                             return(FALSE);
  1398.                       } /* end while */
  1399.                     sprintf(line,"XRMD %s",command);    /* try XRMD */
  1400.                     i=ftpdo(line,ofilename);
  1401.                     if(i!=ERROR)
  1402.                         return(TRUE);
  1403.                     nputs("Trying again...");
  1404.                     sprintf(line,"RMD %s",command);     /* try RMD */
  1405.                     ftpdo(line,ofilename);
  1406.                     return(TRUE);
  1407.  
  1408.                 case STRUCT:        /* set structure type-only file */
  1409.                     getword(command,word);
  1410.                     strlwr(word);
  1411.                     if(strncmp(word,"file",strlen(word)))
  1412.                         nputs("We only support file structure, sorry.");
  1413.                     else
  1414.                         nputs("Structure is file.");
  1415.                     return(TRUE);
  1416.  
  1417.                 case TYPE:      /* set transfer type */
  1418.                     if(!getword(command,word)) {    /* no arg, just show */
  1419.                         if(ftpfilemode==FASCII)
  1420.                             nputs("Transfer type is ascii.");
  1421.                         else
  1422.                             nputs("Transfer type is binary.");
  1423.                       } /* end if */
  1424.                     strlwr(word);
  1425.                     if(!strncmp(word,"ascii",strlen(word)))
  1426.                         ftpdo("TYPE A",ofilename);
  1427.                     else
  1428.                         if(!strncmp(word,"binary",strlen(word))||!strncmp(word,"image",strlen(word)))
  1429.                             ftpdo("TYPE I",ofilename);
  1430.                         else {
  1431.                             sprintf(printline,"Unrecognized type: %s",word);
  1432.                             nputs(printline);
  1433.                           } /* end else */
  1434.                     return(TRUE);
  1435.  
  1436.                 case USER:          /* login to remote machine */
  1437.                     if(!fromtty && ttypass)
  1438.                         fromtty=TRUE; /* go interactive */
  1439.                     if(f_enter_login) {
  1440.                         fromtty=1;        /* fake interactive mode */
  1441.                         n_cur(n_row(),0);   /* in case screen is messed up */
  1442.                       } /* end if */
  1443.                     if(!(*(stpblk(command)))) { /* null response to prompt ok */
  1444.                         putstring("Username: ");
  1445.                         if(ftpgets(command,100,1)==ABORT)
  1446.                             return(FALSE);
  1447.                       } /* end if */
  1448.                     sprintf(line,"USER %s",command);    /* username */
  1449.                     switch(ftpdo(line,ofilename)) {
  1450.                         case TRUE:
  1451.                             return (TRUE);
  1452.                         case FALSE:
  1453.                         case ERROR:
  1454.                             return(FALSE);
  1455.                         case ABORT:
  1456.                             return(ABORT);
  1457.                         default:
  1458.                             break;
  1459.                       } /* end switch */
  1460.                     putstring("Password: ");
  1461.                     if(ftpgets(word,40,0)==ABORT)
  1462.                         return(FALSE);      /* no echoing */
  1463.                     if(f_enter_login)      /* restore to non-interactive mode */
  1464.                         fromtty=0;
  1465.                     sprintf(line,"PASS %s",word);       /* password */
  1466.                     if(ftpdo(line,ofilename)==INCOMPLETE) { /* if account needed */
  1467.                         do {
  1468.                             putstring("Account: ");
  1469.                             if(ftpgets(command,100,1)==ABORT)
  1470.                                 return(FALSE);
  1471.                           } while(!(*(stpblk(command))));
  1472.                         sprintf(line,"ACCT %s",command);
  1473.                         ftpdo(line,ofilename);
  1474.                       } /* end if */
  1475.                     if(ttypass)
  1476.                         fromtty=FALSE;     /* back to batch */
  1477.                     return(TRUE);
  1478.  
  1479.                 case ACCOUNT:
  1480.                     if(!(*(stpblk(command)))) {   /* null response to prompt OK */
  1481.                         putstring("Account: ");
  1482.                         if(ftpgets(command,100,0)==ABORT)
  1483.                             return(FALSE); /* no echo */
  1484.                         while (!(*(stpblk(command))));
  1485.                         sprintf(line,"ACCT %s",command);
  1486.                         ftpdo(line,ofilename);
  1487.                       } /* end if */
  1488.                     return(TRUE);
  1489.  
  1490.                 case SITE:      /* site commands */
  1491.                     while(!(*(stpblk(command)))) {      /* if no arg */
  1492.                         putstring("Site: ");
  1493.                         if(ftpgets(command,100,1)==ABORT)
  1494.                             return(FALSE);  /* abort */
  1495.                       } /* end while */
  1496.                     sprintf(line,"SITE %s",command);
  1497.                     ftpdo(line,ofilename);
  1498.                     return(TRUE);
  1499.  
  1500.                 default:    /* unknown command */
  1501.                     sprintf(printline,"***Program error: Unknown command no: %d",cmdno);
  1502.                     nputs(printline);
  1503.                     break;
  1504.               } /* end switch */
  1505.       } /* end switch */
  1506. }   /* end ftppi() */
  1507.  
  1508. /************************************************************************
  1509. * ftpdo
  1510. *  Do whatever command is sent from the user interface using
  1511. *  userftpd, the background file handler
  1512. *  Returns code from ftpreplies
  1513. ************************************************************************/
  1514.  
  1515. static int ftpdo(char *s,char *ofile)
  1516. {
  1517.     int i,
  1518.         rcode;
  1519.     char name[50],
  1520.         name2[50];
  1521.  
  1522.     for(i=0; i<4; i++)
  1523.         s[i]=(char)toupper(s[i]);  /* command to upper case */
  1524.  
  1525.     if(!strncmp(s,"STOR",4)) {    /* put file */
  1526.         getword(&s[5],name);    /* first arg-local file */
  1527.         if(!s[5]) 
  1528.             strcpy(&s[5],name);        /* if only one argument */
  1529.         else {
  1530.             getword(&s[5],name2);   /* second arg-removes quotes etc. */
  1531.             strcpy(&s[5],name2);    /* copy back into command */
  1532.           } /* end else */
  1533. #ifdef MSC
  1534.         if(0>(ftpfh=open(name,O_RDONLY | O_BINARY))) {    /* open local file */
  1535. #else
  1536.         if(0 >(ftpfh=open(name,O_RAW))) {    /* open local file */
  1537. #endif    
  1538.             nputs(" Cannot open file to transfer.");
  1539.             return(-1);
  1540.           } /* end if */
  1541.         ftpdata=netlisten(ftpport());        /* open data connection */
  1542.         ftpstate=20;
  1543.       } /* end if */
  1544.     else if(!strncmp(s,"RETR",4)) {  /* get file */
  1545.         getword(&s[5],name);            /* remote file */
  1546.         if(s[5])        /* two args present */
  1547.             getword(&s[5],name2);   /* local file */
  1548.         else
  1549.             check_file_name (name, name2);
  1550. #ifdef  MSC
  1551.         ftpfh=open(name2,O_BINARY|O_CREAT+O_WRONLY,S_IREAD|S_IWRITE);
  1552. #else
  1553.         ftpfh=creat(name2,O_RAW);              /* open local file */
  1554. #endif
  1555.         if(ftpfh<0) {
  1556.             printf(printline,"Cannot open file to receive: %s\n",name);
  1557.             nputs(printline);
  1558.             return(-1);
  1559.           } /* end if */
  1560.         strcpy(&s[5],name); /* put remote name back into command */
  1561.         ftpdata=netlisten(ftpport());       /* open data connection */
  1562.         ftpstate=30;
  1563.       } /* end if */
  1564.     else if(!strncmp(s,"LIST",4) || !strncmp(s,"NLST",4)) {
  1565.         if(capture)
  1566.             captlist[0]='\0';   /* where to put incoming data */
  1567. if(debug>4) {
  1568.     nputs("ftpdo(): before calling ftpport() ");
  1569.   }    /* end if */
  1570.         ftpdata=netlisten(ftpport());       /* data connection */
  1571. if(debug>4) {
  1572.     nputs("ftpdo(): after calling ftpport() ");
  1573.   }    /* end if */
  1574.         ftpstate=40;
  1575.       } /* end if */
  1576.     else if(!strncmp(s,"TYPE",4)) {
  1577.         if(toupper(s[5])=='I')
  1578.             ftpfilemode=FIMAGE; /* remember mode */
  1579.         else
  1580.             if(toupper(s[5])=='A')
  1581.                 ftpfilemode=FASCII;
  1582.       } /* end if */
  1583.  
  1584.     dumpcon(ftpnum);            /* clear command connection */
  1585.     netpush(ftpnum);
  1586.     netwrite(ftpnum,s,strlen(s));        /* send command */
  1587.     netwrite(ftpnum,"\r\n",2);        /* <CRLF> terminates command */
  1588.     if(!capture && ofile[0]) {        /* command redirected */
  1589.         if((ftpstate!=20) &&(ftpstate!=30)) {    /* not get or put */
  1590. #ifdef    MSC
  1591.              if(0>(ftpfh=open(ofile,O_CREAT|O_APPEND|O_WRONLY,S_IWRITE|S_IREAD)))
  1592. #else
  1593.              if(0>(ftpfh=open(ofile,O_CREAT|O_APPEND|O_WRONLY,S_IWRITE)))
  1594. #endif
  1595.                 nputs(" Cannot open output file.");
  1596.             else
  1597.                 if(ftpdata>-1)
  1598.                     ftpstate=30;    /* act as get, since data goes into file */
  1599.                 else {
  1600.                     close(ftpfh);
  1601.                     ftpfh=0;
  1602.                   } /* end else */
  1603.           } /* end if */
  1604.       } /* end if */
  1605. if(debug) {
  1606.     sprintf(printline,"---> %s",s); /* show command sent */
  1607.     nputs(printline);
  1608.     if(debug>=7) {
  1609.         for(i=0; i<(int)strlen(s); i++)
  1610.             sprintf(&printline[4*i],"%3d ",s[i]);
  1611.         nputs(printline);
  1612.       }
  1613.   }
  1614.     i=ftpreplies(ftpnum,&rcode);        /* get remote response */
  1615. if(debug) {
  1616.     nputs("after ftpreplies() call, in ftpdo ");
  1617.   }    /* end if */
  1618.     if((i==NONE) && strncmp(s,"QUIT",4)) {    /* unexpected connection drop */
  1619.         nputs("lost connection");
  1620.         connected=FALSE;
  1621.       } /* end if */
  1622.     if(i==ABORT || i==NONE || i==ERROR || i==FALSE)  {
  1623.         ftpstate=0;        /* if error, no transfer */
  1624.         if(ftpdata>-1)
  1625.             netclose(ftpdata);
  1626.         if(ftpfh!=0)
  1627.             close(ftpfh);
  1628.         ftpdata=-1;
  1629.         ftpfh=0;
  1630.       } /* end if */
  1631.     return(i);
  1632. }   /* end ftpdo() */
  1633.  
  1634. /************************************************************************
  1635. *   ftpport
  1636. *   return a new port number so that we don't try to re-use ports
  1637. *   before the mandatory TCP timeout period. (lifetime of a packet)
  1638. *   use a time-based initial port selection scheme.
  1639. ************************************************************************/
  1640. static unsigned int ftpport(void)
  1641. {
  1642.     unsigned int i,
  1643.         rcode;
  1644.     unsigned char hostnum[5];
  1645.     char sendline[60];        /* for port command */
  1646.  
  1647.     if(!sendport)            /* default port */
  1648.         return(HFTP-1);
  1649.     if(curftpprt<0x4000) {     /* restart cycle */
  1650.         i=(unsigned int)time(NULL);
  1651.         curftpprt=(unsigned int)(0x4000+(i&0x3fff));
  1652.       } /* end if */
  1653.     i=curftpprt--;            /* get port, update for next time */
  1654.     netgetip(hostnum);        /* get my ip number */
  1655.     sprintf(sendline,"PORT %d,%d,%d,%d,%d,%d\r\n",hostnum[0],hostnum[1],hostnum[2],hostnum[3],i/256,i&255);    /* full port number */
  1656. if(debug>1)
  1657.     nputs(sendline);
  1658.     netpush(ftpnum);        /* empty command connection */
  1659.     netwrite(ftpnum,sendline,strlen(sendline));    /* send PORT command */
  1660. if(debug>1) {
  1661.     nputs("ftpport(): before dumpcon() call ");
  1662.   }    /* end if */
  1663. /* check result of command, make sure port was okay */
  1664. /* return 0 on error */        /* ????? */
  1665.     dumpcon(ftpnum);
  1666. if(debug>1) {
  1667.     nputs("ftpport(): before ftpreplies() call ");
  1668.   }    /* end if */
  1669.     ftpreplies(ftpnum,&rcode);    /* get response */
  1670. if(debug>1) {
  1671.     sprintf(printline,"ftpport(): after ftpreplies() call, i=%d ",i);
  1672.     nputs(printline);
  1673.   }    /* end if */
  1674.     return(i);        /* port number */
  1675. }   /* end ftpport() */
  1676.  
  1677. /************************************************************************
  1678. * ftpreplies
  1679. * get responses to commands to server
  1680. * return TRUE on successful completion, FALSE on transient negative
  1681. * completion, INCOMPLETE if more commands needed for operation,
  1682. * NONE on lost connection, ABORT on user abort and ERROR on failure
  1683. *
  1684. ************************************************************************/
  1685. static int ftpreplies(int cnum,int *rcode)
  1686. {
  1687.     int cnt,ev,j=0;
  1688. /* cRMG not all replies coming through */
  1689.  
  1690.     while(1) {
  1691. if(debug>4) {
  1692.     nputs("ftpreplies(): before rgetline() call ");
  1693.   }    /* end if */
  1694.         cnt=rgetline(cnum);     /* get line from remote host */
  1695.  
  1696. if(debug>4) {
  1697.     sprintf(printline,"s=%s cnt=%d ",s,cnt);
  1698.     nputs(printline);
  1699.   }    /* end if */
  1700.         if(cnt==NONE)
  1701.             return(NONE);        /* lost connection */
  1702.         if(cnt==ABORT) {        /* user abort */
  1703.             netpush(cnum);
  1704.             netwrite(cnum,"ABOR\r\n",6);        /* send abort */
  1705.             return(ABORT);
  1706.           } /* end if */
  1707.         if(!sscanf(s,"%d",rcode))
  1708.             *rcode=-1;                    /* continuation line */
  1709.         if((*rcode/100)==2) {            /* positive completion */
  1710.       dumpcon(ftpnum);            /* clear command connection */
  1711.       while(ftpdata>=0) {     /* wait till transfers complete */
  1712.         ev=checkevent();
  1713. if(debug>4) {
  1714.   sprintf(printline,"ev=%d ",ev);
  1715.     nputs(printline);
  1716.   }    /* end if */
  1717.         if(ev==NONE)
  1718.                     return(NONE);        /* lost connection */
  1719.                 if(ev==ABORT)
  1720.           return(ABORT);      /* user abort */
  1721.  
  1722.                 if(ev==HAVEDATA)
  1723.                     dumpcon(ftpnum);    /* msg on command connection */
  1724.       } /* end while */
  1725.  
  1726.     } /* end if */
  1727.         if(verbose || (*rcode==-1) || (*rcode>500))
  1728.             telnet(cnt);                /* informative/error msg or display on */
  1729.         if(j)
  1730.             if(*rcode==j)
  1731.                 j=0;                    /* end of continuation */
  1732.             else 
  1733.                 continue;
  1734.         else 
  1735.             if(s[3]=='-') {                /* line with continuations */
  1736.                 j=*rcode;                            /* remember end code */
  1737.                 continue;
  1738.               } /* end if */
  1739. if(debug>4) {
  1740.     sprintf(printline,"*rcode=%d ",*rcode);
  1741.     nputs(printline);
  1742.   }    /* end if */
  1743.         switch((int)(*rcode/100)) {        /* first digit */
  1744.             case 1:                        /* preliminary */
  1745.                 continue;
  1746.     
  1747.             case 2:                        /* positive completion */
  1748. #ifdef AUX
  1749.   fprintf(stdaux," positive completion");
  1750. #endif
  1751.         return(TRUE);
  1752.                 break;
  1753.  
  1754.             case 3:                        /* intermediate */
  1755. #ifdef AUX
  1756.   fprintf(stdaux," intermediate completion ");
  1757. #endif
  1758.                 return(INCOMPLETE);
  1759.                 break;
  1760.         
  1761.             case 4:                        /* transient negative completion */
  1762.                 return(FALSE);
  1763.                 break;
  1764.  
  1765.             case 5:                        /* Permanent negative completion */
  1766.                 return(ERROR);
  1767.                 break;
  1768.  
  1769.             default:
  1770.                 nputs("Server response not understood. Terminating command\n");
  1771.                 return(ERROR);
  1772.           }    /* end switch */
  1773.       }    /* end while */
  1774. }   /* end ftpreplies() */
  1775.  
  1776. /************************************************************************
  1777. * rgetline-get a line from remote server
  1778. * return ABORT on user ABORT, NONE on lost connection,
  1779. * length of received line on success
  1780. *
  1781. ************************************************************************/
  1782. static int rgetline(int cnum)
  1783. {
  1784.     int cnt,
  1785.         i=0,
  1786.         ev;
  1787.  
  1788.     while(1) {
  1789. if(debug>4)
  1790.     nputs("rgetline(): before checkevent() ");
  1791.         ev=checkevent();
  1792. if(debug>4) {
  1793.     printf("\nevent: %d\n",ev);
  1794.     nputs("rgetline(): after checkevent() ");
  1795. }   /* end if */
  1796.  
  1797.         switch(ev) {
  1798.             case ABORT:                /* user abort */
  1799.             case NONE:                /* lost connection */
  1800.                 return(ev);
  1801.  
  1802.             case HAVEDATA:
  1803.                 if(fromtty && n_scrlck())
  1804.                     cnt=0;                    /* if paused, nothing to do */
  1805.                 else 
  1806.                     while(1) {
  1807.                         cnt=netread(cnum,&s[i],1);    /* get some from queue */
  1808.                         if(!cnt) 
  1809.                             break;            /* nothing available */
  1810.                         if(s[i++]=='\n') {    /* end of line */
  1811.                             s[i]='\0';
  1812. if(debug>3) {
  1813.     sprintf(printline,"rgetline(): s=%s, i=%d ",s,i);
  1814.     nputs(printline);
  1815.   }    /* end if */
  1816.                             return(i);        /* return line length */
  1817.                           } /* end if */
  1818.                       } /* end while */
  1819.                 break;
  1820.  
  1821.             default:        /* ignore other events */
  1822.                 break;
  1823.           } /* end switch */
  1824.       } /* end while */
  1825. }   /* end rgetline() */
  1826.  
  1827. #ifdef OLD_WAY
  1828. /************************************************************************
  1829. * breakstop
  1830. * handle cntrl-break
  1831. ************************************************************************/
  1832. static void breakstop(void)
  1833. {
  1834. #ifdef MSC
  1835.     signal(SIGINT,SIG_IGN);        /* ignore interrupts while processing this routine */
  1836. #endif
  1837.     foundbreak=1;
  1838. #ifdef MSC
  1839.     signal(SIGINT,breakstop);    /* reset Microsoft interception of break */
  1840. #endif
  1841. }   /* end breakstop() */
  1842. #endif
  1843.  
  1844. /************************************************************************
  1845. * userftpd
  1846. *  FTP receive and send file functions
  1847. ************************************************************************/
  1848. static void userftpd(void )
  1849. {
  1850.     int i,
  1851.         r1,
  1852.         r2;
  1853.     char lastchar;
  1854.     double rate;
  1855.     static int stopcapture=FALSE;    /* bytes xferred % 1024 */
  1856.     static long tbytes;
  1857.  
  1858.     switch(ftpstate) {
  1859.         default:                    /* unknown */
  1860.             break;
  1861.  
  1862.         case 40:                /* start LIST */
  1863.             if(!netest(ftpdata)) {
  1864.                 start=time(NULL);    /* current time */
  1865.                 tbytes=0;        /* received so far */
  1866.                 ftpstate=41;
  1867.               } /* end if */
  1868.             break;
  1869.  
  1870.         case 41:        /* get started */
  1871.             do {
  1872.                 if(capture && !stopcapture) {    /* into captlist */
  1873.                     fcnt=netread(ftpdata,xs,READSIZE);
  1874.                     if(fcnt>0) {        /* make certain a negative length string is not appended */
  1875.                         if(strlen(captlist)+fcnt>=2000) { /* full */
  1876.                             if(!fromtty || !n_scrlck())
  1877.                                 nputs(&xs[2001-strlen(captlist)]);    /* display excess chars */
  1878.                 strncat(captlist,xs,2000-strlen(captlist));
  1879.                 nputs("Error: capture list too long");
  1880.                 stopcapture=TRUE;
  1881.               } /* end if */
  1882.               else
  1883.               strncat(captlist,xs,fcnt);    /* append */
  1884.             } /* end if */
  1885. if(debug>2) {
  1886.     sprintf(printline,"xs %s fcnt %d ",xs,fcnt);
  1887.     nputs(printline);
  1888.     sprintf(printline,"tbytes %ld strlen(captlist) %d ",tbytes,strlen(captlist));
  1889.     nputs(printline);
  1890.   }
  1891.           } /* end if */
  1892.                 else {
  1893.                     if(fromtty && n_scrlck())
  1894.                         break;    /* paused */
  1895.                     fcnt=netread(ftpdata,xs,READSIZE);
  1896.                     for(i=0; i<fcnt; i++) {
  1897.                         nputchar(xs[i]);    /* display */
  1898.                         if(xs[i]==10)
  1899.                             domore();          /* |more */
  1900.                       } /* end for */
  1901.                   } /* end else */
  1902.                 if(fcnt>0) 
  1903.                     tbytes+= fcnt;                     /* how much */
  1904.               } while(fcnt>0);                            /* till no more input */
  1905. if(debug>1) {
  1906.     sprintf(printline,"tbytes %ld ",tbytes);
  1907.     nputs(printline);
  1908.     sprintf(printline,"captlist %s ",captlist);
  1909.     nputs(printline);
  1910.   }
  1911.             break;
  1912.  
  1913.         case 30:        /* receive */
  1914.             if(!netest(ftpdata)) {        /* connection made */
  1915.                 start=time(NULL);
  1916.                 ftpstate=31;
  1917.                 len=xp=0;
  1918.                 tbytes=0;
  1919.               } /* end if */
  1920.             break;
  1921.  
  1922.         case 31:
  1923. /*
  1924. * file has already been opened, take everything from the connection
  1925. * and place into the open file: ftpfh
  1926. */
  1927.             do {        /* wait until xs is full before writing to disk */
  1928.         if(len<=0) {
  1929.           if(xp) {
  1930.             if((write(ftpfh,xs,xp)==-1) && (errno==ENOSPC)) {
  1931.               netwrite(ftpdata,"ABOR\r\n",6); /* send abort */
  1932.               netwrite(ftpdata,"452 Disk full error.\r\n",22);
  1933.               printf("Local disk full error.\n");
  1934.             } /* end if */
  1935.             else
  1936.               xp=0;
  1937.           } /* end if */
  1938.           len=BUFFERS;    /* expected or desired len to go */
  1939.         } /* end if */
  1940. /* how much to read */
  1941.         if(len<READSIZE)
  1942.           i=len;
  1943.                 else
  1944.                     i=READSIZE;
  1945. //        if(!fcnt<0)
  1946.           fcnt=netread(ftpdata,&xs[xp],i);
  1947.                 if(fcnt>0) {    /* adjust counts */
  1948.           len-=fcnt;
  1949.           xp+=fcnt;
  1950.           tbytes+=fcnt;
  1951.          } /* end if */
  1952. if(debug>1) {
  1953.     sprintf(printline,"len %d xp %d fcnt %d",len,xp,fcnt);
  1954.     nputs(printline);
  1955.   }
  1956.         if(fcnt<0) {          /* connection closed */
  1957.                     write(ftpfh,xs,xp);            /* write last block */
  1958.                     if(ftpfilemode==FASCII) 
  1959.                         write(ftpfh,"\032",1);    /* EOF char */
  1960.                     close(ftpfh);
  1961.                     ftpfh=0;
  1962.                   } /* end if */
  1963.                 if(hash) {                        /* hash mark printing */
  1964.           for(i=(int)(((tbytes-(long)fcnt)%1024L+(long)fcnt)/1024L); i; i--)
  1965.             if(fromtty)
  1966.               nputchar('#');
  1967.             else
  1968.               putc('#',stderr);
  1969.         } /* end if */
  1970.       } while(fcnt>0);
  1971.       break;
  1972.  
  1973.         case 20:    /* send */
  1974.             if(!netest(ftpdata)) {                /* connection made */
  1975.                 start=time(NULL);
  1976.                 ftpstate=21;
  1977.                 lengthfile=lseek(ftpfh,0L,SEEK_END);   /* how long is file? */
  1978.                 lseek(ftpfh, -1L,SEEK_CUR);            /* position at last character*/
  1979.                 if(read(ftpfh, &lastchar, 1)==0) {
  1980.                     if(debug>4)
  1981.                         printf("LC Test failed.\n");
  1982.                     lastchar='\0';
  1983.                 } else {
  1984.                     if(debug>4)
  1985.                         printf("Last character test returned %d.\n",(int) lastchar);
  1986.                 }
  1987.                 lseek(ftpfh,0L,SEEK_SET);               /* back to beginning */
  1988.                 if((ftpfilemode==FASCII) && (lastchar=='\26'))       /* drop cntr-Z for ascii transfer */
  1989.                     lengthfile--;                /* leave off ctrl-Z */
  1990.                 towrite=0;
  1991.                 xp=0;
  1992.                 tbytes=0;
  1993.               } /* end if */
  1994.             break;
  1995.  
  1996.         case 21:
  1997. /*
  1998. *  transfer file(s) to the other host via ftp request
  1999. *  file is already open=ftpfh
  2000. */
  2001. if(debug>4)
  2002.     printf("lengthfile=%d  towrite=%d  xp=%d  i=%d\n",lengthfile,towrite,xp,i);
  2003.  
  2004.             if(towrite<=xp) {            /* need to read again */
  2005. if(debug>4)
  2006.     printf("towrite<=xp\n");
  2007.                 if(lengthfile<(long)BUFFERS)
  2008.                     i=(int)lengthfile;
  2009.                 else
  2010.                     i=BUFFERS;
  2011. if(debug>4)
  2012.     printf("i=%d\n",i);
  2013.                 towrite=read(ftpfh,xs,i);
  2014. if(debug>4)
  2015.     printf("towrite=%d\n",towrite);
  2016.                 xp=0;
  2017.               } /* end if */
  2018.             if(towrite>=xp)
  2019.                 i=netwrite(ftpdata,&xs[xp],towrite-xp);
  2020.             else 
  2021.                 i=netwrite(ftpdata,&xs[xp],0);
  2022.             if(i>0) {                    /* send successful, adjust counts */
  2023.                 xp+=i;
  2024.                 lengthfile-=i;
  2025.                 tbytes+=i;
  2026.               } /* end if */
  2027. if(debug>1) {
  2028.     sprintf(printline,"i %d xp %d towrite %d",i,xp,towrite);
  2029.     nputs(printline);
  2030.   } /* end if */
  2031.             if(hash) {                    /* hash printing */
  2032.         for(r1=(int)(((tbytes-(long)i)%1024L+(long)i)/1024L); r1; r1--)
  2033.           if(fromtty)
  2034.             nputchar('#');
  2035.           else
  2036.             putc('#',stderr);
  2037.               } /* end if */
  2038. /*
  2039. *  done if:  the file is all read from disk and all sent
  2040. *  or other side has ruined connection
  2041. */
  2042.       if((lengthfile<=0L && xp>=towrite) || netest(ftpdata))
  2043.                 ftpstate=22;
  2044.             break;
  2045.  
  2046.         case 22:            /* send done */
  2047. /* wait for other side to accept everything and then close */
  2048.             if(0>=(r1=netpush(ftpdata)))
  2049.                 fcnt=-1;
  2050. if(debug>1) {
  2051.     sprintf(printline,"fcnt %d r1 %d\n",fcnt,r1);
  2052.     nputs(printline);
  2053. } /* end if */
  2054.       break;
  2055.  
  2056.       } /* end switch */
  2057. /*
  2058. *  after reading from connection, if the connection is closed,
  2059. *  reset up shop.
  2060. */
  2061.   if(fcnt<0) {    /* connection lost */
  2062.         if(ftpfh>0) {    /* close file */
  2063.             close(ftpfh);
  2064.             ftpfh=0;
  2065.           } /* end if */
  2066.         ftpstate=0;    /* done */
  2067.         fcnt=0;
  2068.         i=(int)(time(NULL)-start);    /* how long to transfer */
  2069.         if(!i) 
  2070.             rate=((double)tbytes)/1024.0;
  2071.         else 
  2072.             rate=((double)tbytes)/(i*1024.0);
  2073.         r1=(int)rate;              /* integer part of rate */
  2074.         r2=(int)((rate-(double)r1)*1000);
  2075.         sprintf(printline,"Transferred %ld bytes in %d seconds(%d.%03d Kbytes/sec)",tbytes,i,r1,r2);
  2076.     if(hash)
  2077.       if(fromtty)
  2078.         nputs("");
  2079.       else
  2080.         fputs("\n",stderr);
  2081.     if(verbose) 
  2082.       nputs(printline);
  2083.         netclose(ftpdata);            /* close connection */
  2084.         ftpdata=-1;
  2085.         if(bell) 
  2086.             nputchar(7);
  2087.       } /* end if */
  2088. //n_puts("end userftpd");
  2089. }   /* end userftpd() */
  2090.  
  2091. /************************************************************************
  2092. * getword: remove a word from a string.  Things within quotes are
  2093. * assumed to be one word.
  2094. * return TRUE on success, FALSE on end of string
  2095. ************************************************************************/
  2096. static int getword(char *string,char *word)
  2097. {
  2098.     char *p,*q;
  2099.     int i=0;
  2100.  
  2101. if(debug>4) {
  2102.     sprintf(printline,"getword: string is %s",string);
  2103.     nputs(printline);
  2104.   }
  2105.     p=stpblk(string);            /* skip leading blanks */
  2106.     if(!(*p)) {                /* no words in string */
  2107.         word[0]='\0';
  2108.         return(FALSE);
  2109.       } /* end if */
  2110.     if(*p=='!') {                /*! is a word */
  2111.         word[0]=*p;
  2112.         word[1]='\0';
  2113.         strcpy(string,++p);
  2114.         return(TRUE);
  2115.       } /* end if */
  2116.     if(*p=='\"') {                /* word delimited by quotes */
  2117.         while(p[++i] && p[i]!='\"')
  2118.             word[i-1]=p[i];
  2119.         word[i-1]='\0';
  2120.         if(!p[i]) 
  2121.             nputs("Missing \". Assumed at end of string.");
  2122.         else 
  2123.             i++;
  2124.         q=p+i;
  2125.       } /* end if */
  2126.     else 
  2127.         q=stptok(p,word,50," \t\r\n");  /* get word, max len 50 */
  2128.     p=stpblk(q);                         /* remove trailing blanks */
  2129.     strcpy(string,p);                    /* remove extracted stuff */
  2130.     return(TRUE);
  2131. }   /* end getword() */
  2132.  
  2133. /************************************************************************/
  2134. /* flip_slashes: change \ to /                                            */
  2135. /************************************************************************/
  2136. static void flip_slashes(char *command,char *filename)
  2137. {
  2138.     int i;                 /* local counting variable */
  2139.  
  2140.     filename[0]='\0';                /* don't do anything with the filename */
  2141.     for(i=0; !command[i]; i++) {    /* loop over entire string */
  2142.         if(command[i]=='\\')         /* found a \ ? */
  2143.             command[i]='/';            /* flip the \ to a / */
  2144.       } /* end for */
  2145. }    /* end flip_slashes() */
  2146.  
  2147. /************************************************************************
  2148. * checkoredir: check for output redirection.  If the command contains a
  2149. * >, assume a filename follows and extract it.  Remove the redirection
  2150. * from the original command.
  2151. * Also change \ to /
  2152. * return TRUE if redirection specified, FALSE otherwise 
  2153. ************************************************************************/
  2154. static int checkoredir(char *command,char *filename,int slashflip)
  2155. {
  2156.     int i;
  2157.  
  2158.     filename[0]='\0';
  2159.     for(i=0; (command[i]!='>'); i++) {   /* process command part */
  2160.         if(command[i]=='\\' && slashflip)
  2161.             command[i]='/';
  2162.         if(!command[i]) 
  2163.             return(FALSE);                /* no redirection */
  2164.       } /* end for */
  2165.     getword(&command[i+1],filename);    /* get redirected filename */
  2166.     command[i]='\0';
  2167.     return(TRUE);
  2168. }   /* end checkoredir() */
  2169.  
  2170. /************************************************************************
  2171. * getdir: get current directory.  Finds current drive and current path
  2172. * on drive, returns a string.
  2173. *
  2174. ************************************************************************/
  2175. static void getdir(int drive,char *path)
  2176. {
  2177. #ifdef    MSC
  2178.     getcwd(path,100);
  2179.     drive=drive;            /* To get rid of annoying "Unreferenced formal parameter" warning. */
  2180. #else
  2181.     char partpath[64];
  2182.     if(!drive) drive=getdsk();                /* current disk */
  2183.         getcd(drive+1,partpath);            /* current dir */
  2184.     sprintf(path,"%c:\\%s",'A'+drive,partpath);
  2185. #endif
  2186. }   /* end getdir() */
  2187.  
  2188. /************************************************************************
  2189. * finduniq: find name that is a unique prefix of one of the entries in
  2190. * a list.  Return position of the entry, NONE if none, AMBIGUOUS if more
  2191. * than one.
  2192. *
  2193. ************************************************************************/
  2194. static int finduniq(char *name,char *list[],int listsize)
  2195. {
  2196.     int i,
  2197.         j=NONE,
  2198.         len;
  2199.  
  2200.     len=strlen(name);
  2201.     for(i=0; i<listsize; i++) {
  2202.         if(!strncmp(name,list[i],len)) {        /* prefix */
  2203.             if(len==(int)strlen(list[i]))
  2204.                 return(i+1);                    /* exact match */
  2205.             if(j!=NONE) 
  2206.                 j=AMBIGUOUS;                    /* more than one match */
  2207.             else
  2208.                 j=i+1;                              /* note prefix found */
  2209.           } /* end if */
  2210.       } /* end for */
  2211.     return(j);                                    /* prefix */
  2212. }   /* end finduniq() */
  2213.  
  2214. /************************************************************************
  2215. * checkevent
  2216. * get and process network events
  2217. * returns ABORT on user abort, HAVEDATA if data available on command
  2218. * connection, NONE if connection lost, DOMOK if domain search succeeds,
  2219. * DOMFAIL if domain search fails, TRUE if no relevant event.
  2220. ************************************************************************/
  2221. static int checkevent(void)
  2222. {
  2223.   int ev,
  2224.       class=0,
  2225.       data;
  2226.  
  2227.     kbhit();            /* check for cntrl-break */
  2228.   if(foundbreak)
  2229.     return(ABORT);
  2230.     userftpd();         /* do ftp stuff */
  2231.     Stask();            /* keep connections alive */
  2232.   ev=Sgetevent(CONCLASS|ERRCLASS|USERCLASS,&class,&data);
  2233.   if(class==CONCLASS) {
  2234.         if(data==ftpnum) {        /* command connection */
  2235.             if(ev==CONCLOSE) {    /* connection lost */
  2236.                 netclose(ftpnum);
  2237.                 if(!netest(ftpdata)) 
  2238.                     netclose(ftpdata);    /* close data connection */
  2239.                 connected=FALSE;
  2240.         return(NONE);
  2241.       } /* end if */
  2242.             if(ev==CONDATA)
  2243.                 return(HAVEDATA);    /* data received */
  2244.     } /* end if */
  2245.     /* rmg 930610 while fixing 0 byte transfers */
  2246.     if(data==ftpdata) {       /* data connection */
  2247.       if(ev==CONCLOSE) {    /* connection lost */
  2248.         netclose(ftpdata);  /* close data connection */
  2249.         ftpdata= -1;
  2250.         return(FALSE);
  2251.       } /* end if */
  2252.     }
  2253.   } /* end if */
  2254.     else 
  2255.         if(class==USERCLASS) {        
  2256.             if(ev==DOMOK) {        /* domain search succeeded */
  2257.                 ftpnum=data;
  2258.                 return(DOMOK);
  2259.       } /* end if */
  2260.             else 
  2261.                 if(ev==DOMFAIL) 
  2262.                     return(DOMFAIL);    /* domain search failed */
  2263.     } /* end if */
  2264.  
  2265. /* else if(class==ERRCLASS&&ev==ERR1) nputs(neterrstring(data)); */
  2266.     return(TRUE);
  2267. }   /* end checkevent() */
  2268.  
  2269. /************************************************************************
  2270. * putstring:
  2271. *   display string using vt100 emulation routines
  2272. ************************************************************************/
  2273. static int putstring(char *string)
  2274. {
  2275.     for(; *string; string++)
  2276.         nputchar(*string);
  2277.     return(TRUE);
  2278. }   /* end putstring() */
  2279.  
  2280. /************************************************************************
  2281. * printerr:
  2282. *   display TCP error messages-disabled
  2283. ************************************************************************/
  2284. static int printerr(void )
  2285. {
  2286. #ifdef OLD_WAY
  2287.     int data,class;
  2288.  
  2289.     while(ERR1==Sgetevent(ERRCLASS,&class,&data))
  2290.         nputs(neterrstring(data));
  2291. #endif
  2292.     return(TRUE);
  2293. }   /* end printerr() */
  2294.  
  2295. /************************************************************************
  2296. * getnname: get next name from captured list
  2297. * names delimited by newlines-<CR> or <LF>
  2298. ************************************************************************/
  2299. static int getnname(char *string,char *word)
  2300. {
  2301.     char *s;
  2302.  
  2303.     s=string;
  2304.     while((*string=='\n') || (*string=='\r'))
  2305.         string++;                        /* skip initial newlines */
  2306.     if(!(*string)) 
  2307.         return(FALSE);        /* end of captlist */
  2308.     while((*string!='\n') && (*string!='\r') && (*string))
  2309.         *(word++)=*(string++);
  2310.     while((*string=='\n') || (*string=='\r'))
  2311.         string++;    /* skip trailing newline */
  2312.     *word='\0';
  2313.     strcpy(s,string);
  2314.     return(TRUE);
  2315. }   /* end getnname() */
  2316.  
  2317. /***************************************************************************
  2318. *  dosescape
  2319. *  escape to dos for processing
  2320. *  put the connections to automated sleep while in DOS
  2321. ************************************************************************/
  2322. int dosescape(void)
  2323. {
  2324.     int i;
  2325.     char *command_shell;
  2326.  
  2327.     nputs("Warning, some programs will interfere with network communication and can");
  2328.     nputs("cause lost connections.  Do not run any network programs from this DOS shell.");
  2329.     nputs("Type 'EXIT' to return to FTP");
  2330. /*
  2331. *  invoke a put-to-sleep routine which calls netsleep every 8/18ths of a sec
  2332. */
  2333.     remove_break();
  2334.     tinst();
  2335.     command_shell=getenv("COMSPEC");
  2336.     if(command_shell!=NULL)
  2337.         i=system(command_shell);        /* call DOS */
  2338.      else
  2339.         i= -1;
  2340.     tdeinst();
  2341.     install_break(&foundbreak);
  2342.  
  2343.     if(i<0) {
  2344.         nputs("\n\nError loading COMMAND.COM");
  2345.         nputs("Make sure COMMAND.COM is specified under COMSPEC.");
  2346.         nputs("It must also be in a directory which is in your PATH statement.");
  2347.       } /* end if */
  2348.     if(fromtty) 
  2349.         n_row();
  2350.  
  2351. return 0;
  2352. }   /* end dosescape() */
  2353.  
  2354. static void nputs(char *line)
  2355. {
  2356.   if(fromtty) {
  2357.     if(!scrsetup) {
  2358.       scrsetup=1;
  2359.       if(!display_init) {
  2360.         Sgetconfig(&def);   /* get information provided in hosts file */
  2361.         display_init=TRUE;
  2362.         dos_color=n_color((int) def.color[0]);  /* set color to that set in config file */
  2363.       } /* end if */
  2364.       n_color((int) def.color[0]);  /* set color to that set in config file */
  2365.       n_clear();      /* clear screen */
  2366.   #ifdef NOT
  2367.       n_wrap(1);          /* cursor positioning */
  2368.   #endif
  2369.       n_cur(0,0);
  2370.  
  2371.       n_puts("National Center for Supercomputing Applications");
  2372.       sprintf(printline,"       %s %s",FTP_VERSION,FTP_REV_VERSION);
  2373.       n_puts(printline);
  2374.     } /* end if */
  2375.  
  2376.     if(*line) {
  2377.       n_puts(line);
  2378.     }
  2379.     else
  2380.       n_puts("");
  2381.   }
  2382.   else {
  2383.     if(!scrsetup) {
  2384.       scrsetup=1;
  2385.       if(!display_init) {
  2386.         Sgetconfig(&def);   /* get information provided in hosts file */
  2387.         display_init=TRUE;
  2388.         fputs("National Center for Supercomputing Applications",stderr);
  2389.         fputs("\n",stderr);
  2390.         sprintf(printline,"       %s %s",FTP_VERSION,FTP_REV_VERSION);
  2391.         fputs(printline,stderr);
  2392.         fputs("\n",stderr);
  2393.       } /* end if */
  2394.     } /* end if */
  2395.  
  2396.     puts(line);
  2397.   }
  2398.  
  2399. }   /* end nputs() */
  2400.  
  2401. static void nputchar(char ch)
  2402. {
  2403. #ifdef OLD_WAY
  2404.   if(fromtty && ttypass)
  2405.         putc(ch,stderr);
  2406.     else 
  2407.     n_putchar(ch);
  2408. #else
  2409.   if(!fromtty)
  2410.     putc(ch,stdout);
  2411.     else 
  2412.     n_putchar(ch);
  2413.     n_row();
  2414.     if(n_col() >= 79)
  2415.       n_puts("");
  2416. #endif
  2417. }   /* end nputchar() */
  2418.  
  2419. #ifdef    MSC
  2420. static char *stptok(char *p,char *toword,int len,char *delim)
  2421. {
  2422.     char *adv=toword;
  2423.      int i;
  2424.      int end=0;
  2425.  
  2426.      do { 
  2427.         for(i=0; i<(int)strlen(delim); i++)
  2428.             if(*p==delim[i] || (!*p))
  2429.                 end++;
  2430.         if(!end) {
  2431.              if(adv>=(toword+len-1)) 
  2432.                 end++;
  2433.              *adv++=*p++;
  2434.           } /* end if */
  2435.       } while(!end);
  2436.      *adv='\0';
  2437.     return(p);
  2438. }   /* end stptok() */
  2439.  
  2440. static char *stpblk(char *ch)
  2441. {
  2442.     while(*ch==' ' || *ch=='\t')
  2443.         ch++;
  2444.     return(ch);
  2445. }   /* end stpblk() */
  2446. #endif
  2447.  
  2448. int domore(void)
  2449. {
  2450.     int ch=0;
  2451.  
  2452.     if(usemore) {
  2453.         if(lineslft--<=1) {
  2454.             printf("-- more --");
  2455.             ch=0;
  2456.             while(!ch) {
  2457.                 if(!kbhit())       /* if no char available */
  2458.                     Stask();        /* keep the connection alive */
  2459.                 else
  2460.                     ch=getch();   /* else get a character */
  2461.                 if(foundbreak) {
  2462.                     foundbreak=0;
  2463.                     ch=32;
  2464.                   } /* end if */
  2465.               } /* end while */
  2466.             printf("\r          \r");
  2467.             if(ch==13)
  2468.                 lineslft++;
  2469.             else
  2470.                 lineslft=numlines;
  2471.           } /* end if */
  2472.       } /* end if */
  2473.     return(ch);
  2474. }   /* end domore() */
  2475.  
  2476. /************************************************************************/
  2477. /*                             check_file_name                          */
  2478. /*                                                                      */
  2479. /*  A function to check for and enforce MS-DOS file name compatibility  */
  2480. /*  and uniqueness.  All non-MS-DOS filename characters from 'in_fname' */
  2481. /*  are deleted.  If the filename exists in the current directory, a    */
  2482. /*  unique name is created to avoid file name collision.                */
  2483. /*  'out_fname' must be large enough for the full filename (13 bytes).  */
  2484. /*                                                                      */
  2485. /*       Returns:    pointer to 'out_fname'                             */
  2486. /*                                                                      */
  2487. /*       Allen W. Todd                        Dec 24, 1990              */
  2488. /*                                                                      */
  2489. /************************************************************************/
  2490. char *check_file_name(char *in_fname,char *out_fname)
  2491. {
  2492.     char buf[80],
  2493.         *s,
  2494.         *fname,
  2495.         *fextn,
  2496.         num_buf[20];
  2497.     long count=0L;
  2498.  
  2499.     strcpy(buf,in_fname);    /* make local copy */
  2500.     strlwr(buf);              /* convert to lower case */
  2501.     while((s=strpbrk(buf, "\"*+,/:;<=>?[\\]^|"))!=NULL)
  2502.         strcpy(s,s+1);        /* delete non-DOS chars */
  2503.     fname=&buf[0];           /* separate filename from file extension */
  2504.     if((fextn=strchr(buf,'.'))!=NULL)
  2505.         *fextn++='\0';
  2506.     if(strlen (fname)>8)
  2507.         *(fname+8)='\0';   /* fix filename @ 8 char */
  2508.     if(strlen(fextn)>3)
  2509.         *(fextn+3)='\0';   /* fix file extension @ 3 char */
  2510.     strcpy(out_fname,fname);     /* build complete filename */
  2511.     if(fextn) {
  2512.         strcat(out_fname,".");
  2513.         strcat(out_fname,fextn);
  2514.       } /* end if */
  2515.   /* RMG not_noclobber - not implemented yet */
  2516. //    if(check_overwrite) {
  2517.     while(access(out_fname,0)==0) {   /* if file already exists */
  2518.         ltoa(count++,num_buf,10);
  2519.         strcpy(out_fname,fname);     /* build complete filename */
  2520.         if((strlen(fextn)<3) && (strlen(num_buf)+strlen(fextn)<=3))
  2521.             strcat(fextn,num_buf);
  2522.         else {
  2523.             if(strlen(fname)>strlen(num_buf))
  2524.                 strcpy(out_fname+(strlen(fname)-strlen(num_buf)),num_buf);
  2525.             else
  2526.                 strcat(out_fname,num_buf);
  2527.           } /* end else */
  2528.         if(fextn) {
  2529.             strcat(out_fname,".");
  2530.             strcat(out_fname,fextn);
  2531.           } /* end if */
  2532.       } /* end while */
  2533. //  } /* end noclobber */
  2534.    return(out_fname);
  2535. }   /* end check_file_name() */
  2536.  
  2537.