home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / t / tel2305s.zip / ENGINE / BKGR.C < prev    next >
C/C++ Source or Header  |  1992-03-28  |  32KB  |  1,208 lines

  1. /*      BKGR.C
  2. *
  3. *    Background routines( FTP and RCP )
  4. *
  5. ***************************************************************************
  6. *                                                                          *
  7. *      part of:                                                            *
  8. *      TCP/IP kernel for NCSA Telnet                                       *
  9. *      by Tim Krauskopf                                                    *
  10. *                                                                          *
  11. *      National Center for Supercomputing Applications                     *
  12. *      152 Computing Applications Building                                 *
  13. *      605 E. Springfield Ave.                                             *
  14. *      Champaign, IL  61820                                                *
  15. *                                                                          *
  16. ***************************************************************************
  17. *
  18. *    Revision history:
  19. *
  20. *    11/86    Started by Timk
  21. *    xx/88    Rewritten by everyone
  22. *    5/89    clean up for 2.3 release, JKM    
  23. *    10/89    fixed ftp bugs                QAK
  24. *
  25. */
  26.  
  27. /*
  28. *    Includes
  29. */
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <fcntl.h>
  33. #include <string.h>
  34. #include <ctype.h>
  35. #ifdef MSC
  36. #ifdef __TURBOC__
  37. #include <alloc.h>
  38. #else
  39. #include <malloc.h>
  40. #endif
  41. #endif
  42. #include "whatami.h"
  43. #include "hostform.h"
  44.  
  45. /*
  46. *    Defines
  47. */
  48.  
  49. #define HTELNET 23
  50. #define HRSHD 514
  51. #define HFTP 21
  52. #define BUFFERS 8000
  53. #define PATHLEN 256
  54.  
  55. #define RCPSEGSIZE 1024
  56. #define EOLCHAR 10
  57.  
  58. #ifdef MSC
  59. #define O_RAW    O_BINARY
  60. #ifdef __TURBOC__
  61. #include <dir.h>
  62. #else
  63. #include <direct.h>
  64. #endif
  65.  
  66. #include <sys/types.h>
  67. #include <sys/stat.h>
  68. #include <io.h>
  69. #endif    /* msc */
  70.  
  71. #include "externs.h"
  72.  
  73.  
  74. /*
  75. *    Global Variables
  76. */
  77.  
  78. static int ftpenable=0,            /* is file transfer enabled? */
  79.     ftpDir=0,
  80.     rcpenable=0,                /* is rcp enabled? */
  81.     ftpdata=-1,                    /* port for ftp data connection */
  82.     fnum=-1,                    /* port number for incoming ftp */
  83.     rsnum=-1,                    /* port number for incoming rshell */
  84.     rserr=-1,                    /* port number for rshd()stderr */
  85.     lstype;                        /* what type of ftp list to do */
  86. static unsigned char xs[BUFFERS+10],    /* buffer space for file transfer */
  87.         pathname[PATHLEN],            /* space to keep path names */
  88.         newfile[PATHLEN],            /* current file being received */
  89.         myuser[17],                    /* user name on my machine */
  90.         hisuser[17],                /* user name on his machine */
  91.         waitchar;                    /* character waiting for from net */
  92.  
  93. static int 
  94.     curstate=-1,            /* state machine for background processes */
  95.     retstate=200,            /* to emulate a subroutine call */
  96.     ftpstate=0,                /* state of the ftp data transfer */
  97.     isdir=0,                /* flag for rcp target pathname */
  98.     waitpos=0,                /* marker for gathering strings from net */
  99.     cnt=0,                    /* number of characters from last netread()*/
  100.     fh=0,                    /* file handle when transfer file is open */
  101.     ftpfh=0,                /* file handle for ftp data */
  102.     xp=0,                    /* general pointer */
  103.     towrite=0,                /* file transfer pointer */
  104.     len=0;                    /* file transfer length */
  105.  
  106. static long int
  107.     filelen=0L;                /* length of current file for transfer */
  108.  
  109. static char bkgr_path[PATHLEN];
  110. static unsigned int curr_drive;
  111. static char mungbuf[1024],crfound=0;
  112. static char *nextfile;        /* pointer to the next filename returned by DOS */
  113.  
  114. static int Sfwrite(int ,char *,int );
  115. static int Sfread(int ,char *,int );
  116.  
  117. extern char Sptypes[NPORTS];/* flags for port #'s */
  118. #define PFTP 1
  119. #define PRCP 2
  120. #define PDATA 3
  121.  
  122. #ifdef PC
  123.  
  124. #define ga() while(!netwrite(rsnum,"",1))netsleep(0)
  125.  
  126. /************************************************************************/
  127. /*  unsetrshd
  128. *   remove the acceptance of rshd calls(rcp)
  129. */
  130. void unsetrshd(void )
  131. {
  132.     netclose(rsnum);
  133.     rsnum=-1;
  134.     rcpenable=0;
  135. }
  136.  
  137. /************************************************************************/
  138. void setrshd(void )
  139. {
  140.     int i;
  141. /*
  142. *  set up to receive a rsh call connection 
  143. */
  144.     if(rsnum>=0)
  145.         return;
  146.     curstate=199;                    /* waiting for connection */
  147.     i=netsegsize(RCPSEGSIZE);
  148.     rsnum=netlisten(HRSHD);
  149.     netsegsize(i);
  150.     if(rsnum>=0)
  151.         Sptypes[rsnum]=PRCP;
  152.     rcpenable=1;
  153. }
  154.  
  155. /************************************************************************/
  156. /*  rshell
  157. *   take an incoming rshell request and service it.  Designed to handle
  158. *   rcp primarily.
  159. */
  160. void rshd(int code)
  161. {
  162.     int i,j;
  163.  
  164.     if(!rcpenable)
  165.         return;
  166.     switch(curstate) {
  167.         case 199:                    /* wait to get started */
  168.             if(code!=CONOPEN)
  169.                 break;
  170.  
  171.             curstate=0;
  172.             netputuev(SCLASS,RCPACT,rsnum);        /* keep us alive */
  173.             break;
  174. /*
  175. * in effect, this is a subroutine that captures network traffic while
  176. * waiting for a specific character to be received
  177. */
  178.         case 50:
  179.             while(0<(cnt=netread(rsnum,&xs[waitpos],1))){
  180.                 if(xs[waitpos]==waitchar){
  181.                     curstate=retstate;
  182.                     netputuev(SCLASS,RCPACT,rsnum);        /* keep us alive */
  183.                     break;
  184.                   }
  185.                 else 
  186.                     waitpos+=cnt;
  187.              }
  188.             netpush(rsnum);
  189.             break;
  190.  
  191.         case 51:                /* for recursion, passes straight through */
  192.             break;
  193.  
  194.         case 0:                    /* waiting for first string */
  195.             retstate=1;
  196.             curstate=50;
  197.             waitchar=0;
  198.             waitpos=0;
  199.             netputuev(SCLASS,RCPACT,rsnum);        /* keep us alive */
  200.             break;
  201.  
  202.         case 1:                    /* we have received stderr port number */
  203.             i=atoi(xs);            /* port number */
  204.             curstate=51;
  205.             if(i) {
  206.                 cnt=-1;                /* abort it all, we don't take rsh */
  207.                 break;
  208.               }
  209.             else
  210.                 rserr=-1;
  211.             retstate=2; 
  212.             curstate=50;
  213.             waitpos=0; 
  214.             waitchar=0;
  215.             break;
  216.  
  217.         case 2:                        /* get user name, my machine */
  218.             strncpy(myuser,xs,16);
  219.             retstate=3; 
  220.             curstate=50;
  221.             waitpos=0; 
  222.             waitchar=0;
  223.             break;
  224.  
  225.         case 3:                         /* get user name, his machine */
  226.             strncpy(hisuser,xs,16);
  227.                                     /*ftransinfo(hisuser); */
  228.             retstate=4; 
  229.             curstate=50;
  230.             waitchar=0; 
  231.             waitpos=0;
  232.             break;
  233.  
  234.         case 4:
  235.                                     /*ftransinfo(xs);*/
  236. /*
  237. * ACK receipt of command line
  238. */
  239.             if(rserr>=0)
  240.                 netwrite(rserr,(char *)&xp,1);        /* send null byte */
  241.             else
  242.                 ga();                        /* send NULL on main connection */
  243.             if(!strncmp(xs,"rcp ",4)){
  244. /*
  245. *  rcp will be using wildcards, target must be a directory
  246. */
  247.                 if(!strncmp(&xs[4],"-d -t",5)){
  248.                     strncpy(pathname,&xs[10],PATHLEN);
  249.                     if(direxist(pathname)){
  250.                         /* ftransinfo("no directory by that name "); */
  251.                         netwrite(rsnum,"\001 No dir found ",16);
  252.                         netpush(rsnum);
  253.                         cnt=-1;
  254.                         break;
  255.                       }
  256.                     isdir=1;
  257.                     retstate=20; curstate=50;
  258.                     waitchar='\012'; waitpos=0;
  259.                     ga();                    /* ready for them to start */
  260.                     break;
  261.                   }
  262. /*
  263. * target could be a directory or a complete file spec
  264. */
  265.                 if(!strncmp(&xs[4],"-t",2)){
  266.                     strncpy(pathname,&xs[7],PATHLEN);
  267.                     if(!direxist(pathname))
  268.                         isdir=1;
  269.                     else
  270.                         isdir=0;
  271.                     retstate=20; 
  272.                     curstate=50;
  273.                     waitchar='\012'; 
  274.                     waitpos=0;
  275.                     ga();            /* ready for rcp to start */
  276.                     break;
  277.                   }
  278. /*
  279. *  rcp is requesting me to transfer file(s)(or giving directory name)
  280. */
  281.                 if(!strncmp(&xs[4],"-f",2)){
  282.                     strncpy(pathname,&xs[7],PATHLEN);
  283. /*
  284. *  direxist returns whether the path spec refers to a directory, and if
  285. *  it does, prepares it as a prefix.  Therefore, if it is a dir, we append
  286. *  a '*' to it to wildcard all members of the directory.
  287. *  Firstname()takes a file spec(with wildcards)and returns a pointer
  288. *  to a prepared ACTUAL file name.  nextname()returns successive ACTUAL
  289. *  filenames based on firstname().
  290. */
  291.                     if(!direxist(pathname)){
  292.                         i=strlen(pathname);
  293.                         pathname[i]='*';        /* all members of directory*/
  294.                         pathname[++i]='\0';
  295.                       }
  296.                     nextfile=(char *)firstname(pathname,0);
  297.                     if(nextfile==NULL){
  298.                         /*ftransinfo(" file or directory not found ");*/
  299.                         netwrite(rsnum,"\001 File not found ",18);
  300.                         netpush(rsnum);
  301.                         cnt=-1;
  302.                       }
  303.                     else {
  304.                                                 /* wait for other side to be ready */
  305.                         retstate=30;    
  306.                         curstate=50;
  307.                         waitchar=0; 
  308.                         waitpos=0;
  309.                       }
  310.                     break;
  311.                   }
  312.               }
  313.             break;
  314.  
  315.         case 20:
  316.             xs[waitpos]='\0';        /* add terminator */
  317.  
  318. /*
  319. *  get working values from command line just received
  320. *  open file for receive
  321. */
  322.             if(xs[0]!='C'||xs[5]!=' '){
  323.                 /*ftransinfo(" Cannot parse filename line "); */
  324.                 netwrite(rsnum,"\001 Problem with file name ",26);
  325.                 cnt=-1;
  326.                 break;
  327.               }
  328.  
  329.             filelen=atol(&xs[6]);
  330.             for(i=6; xs[i]!=' '; i++)
  331.                 if(!xs[i]){
  332.                     /*ftransinfo(" premature EOL ");*/
  333.                     netwrite(rsnum,"\001 Problem with file name ",26);
  334.                     cnt=-1;
  335.                     break;
  336.                   }
  337.             strcpy(newfile,pathname);        /* path spec for file */
  338.             if(isdir)                        /* add file name for wildcards */
  339.                 strcat(newfile,&xs[++i]);
  340. #ifdef MSC
  341.             if(0>(fh=open(newfile,O_BINARY|O_CREAT|O_TRUNC|O_WRONLY, S_IREAD|S_IWRITE))){
  342. #else                    
  343.             if(0>(fh=creat(newfile,O_RAW))){
  344. #endif    
  345.                 netwrite(rsnum,"\001 Cannot open file for write ",29);
  346.                 cnt=-1;
  347.                 break;
  348.              }
  349.             netputevent(USERCLASS,RCPBEGIN,-1);
  350.             ga();                            /* start sending the file to me */
  351.             xp=len=0;
  352.             curstate=21;                    /* receive file, fall through */
  353.             break;
  354.  
  355.         case 21:
  356.             do {                /* wait until xs is full before writing to disk */
  357.                 if(len<=0) {
  358.                     if(xp) {
  359.                         write(fh,xs,xp);
  360.                         xp=0;
  361.                       }
  362.                     if(filelen>(long)BUFFERS)
  363.                         len=BUFFERS;
  364.                     else
  365.                         len=(int)filelen;
  366.                   }
  367.                 cnt=netread(rsnum,&xs[xp],len);
  368.                 filelen-=(long)cnt;
  369.                 len-=cnt;
  370.                 xp+=cnt;
  371.                             /*printf(" %ld %d %d %d ",filelen,len,xp,cnt);n_row(); n_puts(""); */
  372.                 if(filelen<=0L || cnt<0) {
  373.                     write(fh,xs,xp);        /* write last block */
  374.                     close(fh);
  375.                     fh=0;                    /* wait for NULL byte at end after closing file */
  376.                     curstate=50;  
  377.                     retstate=22;
  378.                     waitchar=0;   
  379.                     waitpos=0;
  380.                     break;
  381.                   }
  382.               } while(cnt>0);
  383.             break;
  384.  
  385.         case 22:
  386.     /* cause next sequence of bytes to be saved as next filename to transfer     */
  387.             ga();                    /* tell other side, I am ready */
  388.             waitchar='\012'; 
  389.             waitpos=0;
  390.             curstate=50; 
  391.             retstate=20;
  392.             break;
  393. /*
  394. *  transfer file(s)to the sun via rcp
  395. */
  396.         case 30:
  397. #ifdef MSC
  398.             if(0>(fh=open(nextfile,O_BINARY|O_RDONLY))) {
  399. #else
  400.             if(0>(fh=open(nextfile,O_RAW))){
  401. #endif
  402.                 netwrite(rsnum,"\001 File not found ",19);
  403.                 /*ftransinfo("Cannot open file to transfer: ");ftransinfo(nextfile); */
  404.                 cnt=-1;
  405.                 break;
  406.               }
  407.             netputevent(USERCLASS,RCPBEGIN,-1);
  408.             filelen=lseek(fh,0L,2);        /* how long is file? */
  409.             lseek(fh,0L,0);                /* back to beginning */
  410.             for(i=0,j=-1; nextfile[i]; i++)
  411.                 if(nextfile[i]=='\\')
  412.                     j=i;
  413.             sprintf(xs,"C0755 %lu %s\012",filelen,&nextfile[j+1]);
  414.             netwrite(rsnum,xs,strlen(xs));    /* send info to other side */
  415.                                             /*ftransinfo(xs);check it */
  416.             retstate=31; 
  417.             curstate=50;
  418.             waitchar=0;  
  419.             waitpos=0;
  420.             towrite=xp=0;
  421.             break;
  422.  
  423.         case 31:
  424. /*
  425. *   we are in the process of sending the file 
  426. */
  427.             netputuev(SCLASS,RCPACT,rsnum);        /* keep us alive */
  428.             if(towrite<=xp){
  429.                 towrite=read(fh,xs,BUFFERS);
  430.                 xp=0;
  431.                 filelen -=(long)towrite;
  432.               }
  433.             i=netwrite(rsnum,&xs[xp],towrite-xp);
  434.             if(i>0)
  435.                 xp+=i;
  436.                                                 /*printf(" %d %d %d %ld\012",i,xp,towrite,filelen);n_row();*/
  437. /*
  438. *  done if:  the file is all read from disk and all sent
  439. *  or other side has ruined connection
  440. */
  441.             if((filelen<=0L && xp>=towrite) || netest(rsnum)){
  442.                 close(fh);
  443.                 fh=0;
  444.                 nextfile=(char *)nextname(0);            /* case of wildcards */
  445.                 ga(); 
  446.                 netputuev(SCLASS,RCPACT,rsnum);
  447.                 if(nextfile==NULL)
  448.                     retstate=32;
  449.                 else
  450.                     retstate=30;
  451.                 curstate=50;
  452.                 waitchar=0;    waitpos=0;
  453.               }
  454.             break;
  455.  
  456.         case 32:
  457.             cnt=-1;
  458.             break;
  459.  
  460.         case 5:
  461.             break;
  462.  
  463.         default:
  464.             break;
  465.  
  466.       }
  467. /*
  468. *  after reading from connection, if the connection is closed,
  469. *  reset up shop.
  470. */
  471.     if(cnt<0){
  472.         if(fh>0){
  473.             close(fh);
  474.             fh=0;
  475.         }
  476.         curstate=5;
  477.         cnt=0;
  478.         netclose(rsnum);
  479.         rsnum=-1;
  480.         netputevent(USERCLASS,RCPEND,-1);
  481.         setrshd();                    /* reset for next transfer */
  482.       }
  483. }
  484. #endif
  485.  
  486. /***********************************************************************/
  487. /***********************************************************************/
  488. /***********************************************************************/
  489. /************************************************************************/
  490. /*  ftp section
  491. *   This should be extracted from rcp so that it compiles cleanly
  492. */
  493.  
  494. #define CRESP(A) netwrite(fnum, messs[(A)], strlen(messs[(A)]))
  495. #define FCRESP3(A,B,C) {char msg[80];sprintf(msg,messs[(A)],B,C),netwrite(fnum, msg, strlen(msg));}
  496.  
  497. #ifdef MSC
  498. #ifdef __TURBOC__
  499. #define FASCII O_RAW
  500. #else
  501. #define FASCII O_TEXT
  502. #endif
  503. #else
  504. #define FASCII    0
  505. #endif
  506. #define FIMAGE O_RAW
  507. #define FAMODE 0
  508. #define FIMODE 1
  509. #define FMMODE 2                /* Mac Binary, when ready */
  510.  
  511. extern int bypass_passwd;        /* flag to indicate whether or not to bypass the password check */
  512.  
  513. static int rfstate,
  514.     portnum[8],
  515.     ftpfilemode=FASCII,            /* how to open the file */
  516.     ftptmode=FAMODE;            /* how to transfer the file on net */
  517.  
  518. /*
  519. *  set up to receive a telnet connection for ftp commands
  520. */
  521. static uint16 fdport;
  522.  
  523. void setftp(void )
  524. {
  525.     rfstate=0;
  526.     ftpstate=0;
  527.     fnum=netlisten(HFTP);
  528.     ftpenable=1;
  529.  
  530.     if(fnum>=0)                    /* signal that events should be caught */
  531.         Sptypes[fnum]=PFTP;
  532.     strcpy(myuser,"unknown");    /* set unknown user name */
  533. }
  534.  
  535. void unsetftp(void )
  536. {
  537.     rfstate=0;
  538.     ftpstate=0;
  539.     netclose(fnum);
  540.     fnum=-1;
  541.     ftpenable=0;
  542. }
  543.  
  544. /***********************************************************************/
  545. /*
  546. *  resident ftp server -- enables initiation of ftp without a username
  547. *  and password, as long as this telnet is active at the same time
  548. *  Now checks for the need of passwords.
  549. */
  550.  
  551. static char *messs[]={
  552.     "220 PC Resident FTP server, ready \015\012",
  553.     "451 Error in processing list command \015\012",
  554.     "221 Goodbye \015\012",                        /*2*/
  555.     "200 This space intentionally left blank<>\015\012",
  556.     "150 Opening %s mode connection for file %s\015\012",
  557.     "226 Transfer complete \015\012",            /*5*/
  558.     "200 Type set to A, ASCII transfer mode \015\012",
  559.     "200 Type set to I, binary transfer mode \015\012",
  560.     "500 Command not understood \015\012",        /*8*/
  561.     "200 Okay \015\012",
  562.     "230 User logged in \015\012",
  563.     "550 File not found \015\012",                /*11*/
  564.     "501 Directory not present or syntax error\015\012",
  565.     "250 Chdir okay\015\012",
  566.     "257 \"",
  567.     "\" is the current directory \015\012",        /*15*/
  568.     "501 File not found \015\012",
  569.     "504 Parameter not accepted, not implemented\015\012",
  570.     "200 Stru F, file structure\015\012",
  571.     "200 Mode S, stream mode\015\012",        /*19*/
  572.     "202 Allocate and Account not required for this server\015\012",
  573.     "501 Cannot open file to write, check for valid name\015\012",
  574.     "530 USER and PASS required to activate me\015\012",
  575.     "331 Password required\015\012",      /*23 */
  576.     "530 Login failed\015\012",
  577.     "200 MacBinary Mode enabled\015\012",
  578.     "200 MacBinary Mode disabled\015\012",  /*26 */
  579.     "552 Disk write error, probably disk full\015\012",
  580.     "214-NCSA Telnet FTP server, supported commands:\015\012",
  581.     "    USER  PORT  RETR  ALLO  PASS  STOR  CWD  XCWD  XPWD  LIST  NLST\015\012",
  582.     "    HELP  QUIT  MODE  TYPE  STRU  ACCT  CDUP  DELE  MKD  RMD  NOOP\015\012", /*30*/
  583.     "    A Macintosh version of NCSA Telnet is also available.\015\012",
  584.     "214 Direct comments and bugs to pctelbug@ncsa.uiuc.edu\015\012",
  585.     "200 Type set to I, binary transfer mode [MACBINARY ENABLED]\015\012",                /* 33 */
  586.     "200 Type set to I, binary transfer mode [macbinary disabled]\015\012",
  587.     "\" created\015\012",        /*35*/
  588.     "553 File name not allowed\015\012",
  589.     "502 Command not implemented\015\012",
  590.     ""
  591. };
  592.  
  593. void rftpd(int code)
  594. {
  595.     int i;
  596.  
  597.     if(!ftpenable)
  598.         return;
  599.  
  600.     netpush(fnum);
  601.  
  602.     switch(rfstate) {
  603.         case 0:
  604.             if(code!=CONOPEN)
  605.                 break;
  606.             ftpfilemode=FASCII;
  607.             ftptmode=FAMODE;
  608.             netputevent(USERCLASS,FTPCOPEN,-1);
  609.             rfstate=1;                    /* drop through */
  610.  
  611.         case 1:
  612.             dopwd(bkgr_path,256);
  613.             getdrive(&curr_drive);
  614.             CRESP(0);
  615.             netgetftp(portnum,fnum);    /* get default ftp information */
  616.             for(i=0; i<4; i++)            /* copy IP number */
  617.                 hisuser[i]=(char)portnum[i];
  618.             fdport=portnum[6]*256+portnum[7];
  619.             waitpos=0; 
  620.             waitchar='\012';
  621.             rfstate=50;                   /* note skips over */
  622.             if(Sneedpass())
  623.                 retstate=3;                /* check pass */
  624.             else
  625.                 retstate=5;                /* who needs one ? */
  626.             break;
  627.  
  628.         case 3:     /* check for passwords */
  629.         case 4:
  630.             waitpos=0;  
  631.             waitchar='\012';
  632.             rfstate=50;  
  633.             if(!strncmp("USER",xs,4)) {
  634.                 strncpy(myuser,&xs[5],16);        /* keep user name */
  635.                 netputevent(USERCLASS,FTPUSER,-1);
  636.                 CRESP(23);
  637.                 retstate=4;                        /* wait for password */
  638.                 break;
  639.               } /* end if */
  640.             if(!strncmp("PASS",xs,4)) {
  641.                 if(Scheckpass(myuser,&xs[5]) || (bypass_passwd)) {  /* check for correct passwd, or check whether we bypassed the passwd from the keyboard */
  642.                     if(bypass_passwd)        /* reset the bypassing flag */
  643.                         bypass_passwd=0;
  644.                     netputevent(USERCLASS,FTPPWOK,-1);
  645.                     CRESP(10);
  646.                     retstate=5;
  647.                   } /* end if */
  648.                 else {
  649.                     netputevent(USERCLASS,FTPPWNO,-1);
  650.                     CRESP(24);
  651.                     retstate=3;
  652.                   } /* end else */
  653.                 break;
  654.               } /* end if */
  655.             if(!strncmp("QUIT",xs,4)) {
  656.                 CRESP(2);
  657.                 cnt=-1;
  658.               } /* end if */
  659.             else
  660.                 CRESP(22);
  661.             retstate=3;            /* must have password first */
  662.             break;                
  663.                 
  664. /*
  665. *  interpret commands that are received from the other side
  666. */
  667.         case 5:
  668.             for(i=4; (unsigned int)i < strlen(xs); i++)
  669.                 if(xs[i]=='/')        /* flip slashes */
  670.                     xs[i]='\\';
  671. /*
  672. *  set to a safe state to handle recursion
  673. *  wait for another command line from client
  674. *  
  675. */
  676.             rfstate=50; 
  677.             retstate=5;
  678.             waitchar='\012';  
  679.             waitpos=0;
  680.             if(!strncmp(xs,"LIST",4) || !strncmp(xs,"NLST",4)) {
  681.                 if(!strncmp(xs,"LIST",4)) {
  682.                     if((strlen(xs)<6) || (xs[5]=='.'))
  683.                         strcpy(xs,"LIST *");
  684.                     lstype=1;
  685.                   }    /* end if */
  686.                 else {
  687.                     if((strlen(xs)<6) || (xs[5]=='.'))
  688.                         strcpy(xs,"NLST *");
  689.                     lstype=0;
  690.                   } /* end else */
  691.                 nextfile=(char *)firstname(&xs[5],lstype);    /* find first name */
  692.                 if(nextfile==NULL)
  693.                     CRESP(16);
  694.                 else {
  695.                     ftpgo();                            /* open the connection */
  696.                     fdport=portnum[6]*256+portnum[7];     /* reset to def */
  697.                     if(ftpdata>=0)
  698.                         Sptypes[ftpdata]=PDATA;
  699.                     ftpstate=40;                        /* ready to transmit */
  700.                     FCRESP3(4,"ASCII","list");
  701.                     netputevent(USERCLASS,FTPLIST,-1);
  702.                   }    /* end else */
  703.               }    /* end if */
  704.             else if(!strncmp(xs,"CWD",3)) {
  705.                 if(chgdir(fixdirnm(&xs[4])))                    /* failed */
  706.                     CRESP(12);
  707.                 else                                /* success */
  708.                     CRESP(13);
  709.                 }    /* end if */
  710.             else if(!strncmp(xs,"CDUP",4)) {
  711.                 if(chgdir(".."))                    /* failed */
  712.                     CRESP(12);
  713.                 else                                /* success */
  714.                     CRESP(13);
  715.                 }    /* end if */
  716.             else if(!strncmp(xs,"MKD",3)) {
  717.                 if(mkdir(&xs[4]))                    /* failed */
  718.                     CRESP(36);
  719.                 else {                                /* success */
  720.                     CRESP(14);                        /* start reply */
  721.                     netwrite(fnum,&xs[4],strlen(&xs[4]));    /* write dir name */
  722.                     CRESP(35);                        /* finish reply */
  723.                   }    /* end else */
  724.                 }    /* end if */
  725.             else if(!strncmp(xs,"RMD",3)) {
  726.                 if(rmdir(&xs[4]))                    /* failed */
  727.                     CRESP(11);
  728.                 else                                /* success */
  729.                     CRESP(9);
  730.                 }    /* end if */
  731.             else if(!strncmp(xs,"DELE",4)) {
  732.                 if(remove(&xs[5]))                    /* failed */
  733.                     CRESP(11);
  734.                 else                                /* success */
  735.                     CRESP(9);
  736.                 }    /* end if */
  737.             else if(!strncmp(xs,"STOR",4)) {
  738.                    ftpDir=1;
  739. #ifdef MSC
  740.                 if(0>(ftpfh=open(&xs[5],ftpfilemode|O_CREAT|O_TRUNC|O_WRONLY, S_IREAD|S_IWRITE))) {
  741. #else                    
  742.                 if(0>(ftpfh=creat(&xs[5],ftpfilemode))) {
  743. #endif                
  744.                     CRESP(21);
  745.                     break;
  746.                   } /* end if */
  747.                 ftpstate=0;
  748.                 strncpy(newfile,&xs[5],PATHLEN-1);
  749.                 ftpgo();                        /* open connection */
  750.                 fdport=portnum[6]*256+portnum[7]; /* reset to def */
  751.                 if(ftpdata>=0)
  752.                     Sptypes[ftpdata]=PDATA;
  753.                 FCRESP3(4,(ftpfilemode==FASCII)?"ASCII":"BINARY",&xs[5]);
  754.                 ftpstate=30;                /* ready for data */
  755.               }    /* end if */
  756.             else if(!strncmp(xs,"RETR",4)) {
  757.                 ftpDir=0;
  758. #ifdef MSC
  759.                 if(0>(ftpfh=open(&xs[5], ftpfilemode|O_RDONLY))) {
  760. #else                    
  761.                 if(0>(ftpfh=creat(&xs[5],ftpfilemode))) {
  762. #endif
  763.                     CRESP(11);
  764.                     break;
  765.                   } /* end if */
  766.                 strncpy(newfile,&xs[5],PATHLEN-1);
  767.                 ftpgo();                /* open connection */
  768.                 fdport=portnum[6]*256+portnum[7]; /* reset to def */
  769.                 ftpstate=20;        /* ready for data */
  770.                 if(ftpdata>=0)
  771.                     Sptypes[ftpdata]=PDATA;
  772.                 FCRESP3(4,(ftpfilemode==FASCII)?"ASCII":"BINARY",&xs[5]);
  773.               }    /* end if */
  774.             else if(!strncmp(xs,"TYPE",4)) {
  775.                 if(toupper(xs[5])=='I') {
  776.                     ftpfilemode=FIMAGE;
  777.                     ftptmode=FIMODE;
  778.                     CRESP(7);
  779.                   } /* end if */
  780.                 else 
  781.                     if(toupper(xs[5])=='A') {
  782.                         ftpfilemode=FASCII;
  783.                         ftptmode=FAMODE;
  784.                         CRESP(6);
  785.                       } /* end if */
  786.                     else
  787.                         CRESP(17);
  788.               }    /* end if */
  789.             else if(!strncmp(xs,"PORT",4)) {
  790. /*
  791. * get the requested port number from the command given
  792. */
  793.                 sscanf(&xs[5],"%d,%d,%d,%d,%d,%d",&portnum[0],&portnum[1],&portnum[2],&portnum[3],&portnum[4],&portnum[5]);
  794.                 fdport=portnum[4]*256+portnum[5];
  795.                 CRESP(3);
  796.               }    /* end if */
  797.             else if(!strncmp(xs,"QUIT",4)) {
  798.                 chgdir(bkgr_path);
  799.                 setdrive(curr_drive);
  800.                 CRESP(2);
  801.                 rfstate=60;
  802.                 netputuev(CONCLASS,CONDATA,fnum);    /* post back to me */
  803.               }    /* end if */
  804.             else if(!strncmp(xs,"XPWD",4) || !strncmp(xs,"PWD",3)) {
  805.                 CRESP(14);                        /* start reply */
  806.                 dopwd(xs,1000);                    /* get directory */
  807.                 netwrite(fnum,xs,strlen(xs));    /* write dir name */
  808.                 CRESP(15);                        /* finish reply */
  809.                 }    /* end if */
  810.             else if(!strncmp(xs,"USER",4)) {
  811.                 strncpy(myuser,&xs[5],16);        /* keep user name */
  812.                 netputevent(USERCLASS,FTPUSER,-1);    /* confirm log in without password */
  813.                 CRESP(10);
  814.               }    /* end if */
  815.             else if(!strncmp(xs,"STRU",4)) {    /* only one stru allowed */
  816.                 if(xs[5]=='F')
  817.                     CRESP(18);
  818.                 else
  819.                     CRESP(17);
  820.               }    /* end if */
  821.             else if(!strncmp(xs,"MODE",4)) {    /* only one mode allowed */
  822.                 if(xs[5]=='S')
  823.                     CRESP(19);
  824.                 else
  825.                     CRESP(17);
  826.               }    /* end if */
  827.             else if(!strncmp(xs,"ALLO",4) || !strncmp(xs,"ACCT",4))
  828.                 CRESP(20);
  829.             else if(!strncmp(xs,"HELP",4)) {
  830.                 for(i=28; i<33; i++)
  831.                     CRESP(i);
  832.               }    /* end if */
  833.             else if(!strncmp(xs,"NOOP",4))
  834.                 CRESP(9);
  835.             else if(!strncmp(xs,"REIN",4) || !strncmp(xs,"PASV",4) || 
  836.                         !strncmp(xs,"APPE",4) || !strncmp(xs,"REST",4) || 
  837.                         !strncmp(xs,"RNFR",4) || !strncmp(xs,"RNTO",4) || 
  838.                         !strncmp(xs,"ABOR",4) || !strncmp(xs,"SITE",4) || 
  839.                         !strncmp(xs,"STAT",4) || !strncmp(xs,"SMNT",4) || 
  840.                         !strncmp(xs,"SMNT",4) || !strncmp(xs,"SYST",4) || 
  841.                         !strncmp(xs,"STOU",4))        /* unimplemented commands */
  842.                 CRESP(37);
  843.             else            /* command not understood */
  844.                 CRESP(8);
  845.             break;
  846. /*
  847. *  subroutine to wait for a particular character
  848. */
  849.         case 50:
  850.             while(0<(cnt=netread(fnum,&xs[waitpos],1))) {
  851.                 if(xs[waitpos]==waitchar) {
  852.                     rfstate=retstate;
  853.                     while(xs[waitpos]<33)        /* find end of string */
  854.                         waitpos--;
  855.                     xs[++waitpos]='\0';            /* put in terminator */
  856.                     for(i=0; i<4; i++)                /* want upper case */
  857.                         xs[i]=(unsigned char)toupper((int)xs[i]);
  858.                     break;
  859.                   }    /* end if */
  860.                 else
  861.                     waitpos+=cnt;
  862.               }    /* end while */
  863.             break;
  864.  
  865.         case 60:    /* wait for message to get through or connection is broken */
  866.                     /* printf("%d,%d",netpush(fnum),netest(fnum));*/
  867.             if(!netpush(fnum) || netest(fnum))
  868.                 cnt=-1;
  869.             else
  870.                 netputuev(CONCLASS,CONDATA,fnum);    /* post back to me */
  871.             break;
  872.  
  873.         default:
  874.             break;
  875.       } /* end switch */
  876.     if(cnt<0) {
  877.         if(ftpfh>0) {
  878.             close(ftpfh);
  879.             ftpfh=0;
  880.           } /* end if */
  881.         if(ftpdata>0) {
  882.             netclose(ftpdata);
  883.             netputevent(USERCLASS,FTPEND,-1);
  884.           } /* end if */
  885.         rfstate=100;
  886.         ftpstate=0;
  887.         cnt=0;
  888.         netclose(fnum);
  889.         netputevent(USERCLASS,FTPCLOSE,-1);
  890.         fnum=-1;
  891.         ftpdata=-1;
  892.         setftp();                /* reset it */
  893.       } /* end if */
  894. }   /* end rftpd() */
  895.  
  896. /***********************************************************************/
  897. /* ftpgo
  898. *  open the FTP data connection to the remote host
  899. */
  900. void ftpgo(void )
  901. {
  902.     int savest;
  903.     struct machinfo *m;
  904.  
  905.     xs[0]=(unsigned char)portnum[0];
  906.     xs[1]=(unsigned char)portnum[1];
  907.     xs[2]=(unsigned char)portnum[2];
  908.     xs[3]=(unsigned char)portnum[3];
  909.  
  910.     netfromport(20);     /* ftp data port */
  911.  
  912.     if(NULL==(m=Slookip(xs))){        /* use default entry */
  913.         if(NULL==(m=Shostlook("default")))
  914.             return;
  915.         savest=m->mstat;
  916.         m->mstat=HAVEIP;
  917.         movebytes(m->hostip,xs,4);
  918.         ftpdata=Snetopen(m,fdport);
  919.         m->mstat=savest;
  920.         movebytes(m->hostip,"\0\0\0\0",4);
  921.         return;
  922.       }
  923.     ftpdata=Snetopen(m,fdport);
  924. }
  925.  
  926. /*********************************************************************/
  927. /*
  928. *  FTP receive and send file functions
  929. */
  930. static int fcnt=0;
  931.  
  932. void ftpd(int code,int curcon)
  933. {
  934.     int i;
  935.  
  936.     if(curcon!=ftpdata)        /* wrong event, was for someone else */
  937.         return;
  938.     switch(ftpstate) {
  939.         default:
  940.             break;
  941.  
  942.         case 40:                /* list file names in current dir */
  943.             if(code==CONFAIL)    /* something went wrong */
  944.                 fcnt=-1;
  945.             if(code!=CONOPEN)    /* waiting for connection to open */
  946.                 break;
  947.             ftpstate=41;
  948. /*
  949. *  send the "nextfile" string and then see if there is another file
  950. *  name to send
  951. */
  952.         case 41:
  953.             netputuev(SCLASS,FTPACT,ftpdata);
  954.             netpush(ftpdata);
  955.             i=strlen(nextfile);
  956.             if(i!=netwrite(ftpdata,nextfile,i)) {
  957.                 CRESP(1);
  958.                 fcnt=-1;
  959.                 break;
  960.               }
  961.             netwrite(ftpdata,"\015\012",2);
  962.             if(NULL==(nextfile=nextname(lstype)))    /* normal end */
  963.                 ftpstate=22;                           /* push data through */
  964.             break;
  965.             
  966.         case 30:
  967.             if(code==CONFAIL)    /* something went wrong */
  968.                 fcnt=-1;
  969.             if(code!=CONOPEN)    /* waiting for connection to open */
  970.                 break;
  971.             ftpstate=31;
  972.             crfound=0;
  973.             len=xp=0;
  974.             filelen=0L;
  975.             netputevent(USERCLASS,FTPBEGIN,-2);
  976.             break;
  977.  
  978.         case 31:
  979. /*
  980. * file has already been opened, take everything from the connection
  981. * and place into the open file: ftpfh
  982. */
  983.             do {                /* wait until xs is full before writing to disk */
  984.                 if(len<=2000) {
  985.                     if(xp) {
  986.                         if(0>write(ftpfh,xs,xp)) {   /* disk full err */
  987.                             netclose(ftpdata);
  988.                             fcnt=-1;
  989.                             CRESP(27);
  990.                             break;
  991.                           } /* end if */
  992.                         xp=0;
  993.                       } /* end if */
  994.                     len=BUFFERS;        /* expected or desired len to go */
  995.                   } /* end if */
  996.                 if(ftptmode==FAMODE)
  997.                     fcnt=Sfread(ftpdata,&xs[xp],len);
  998.                 else
  999.                     fcnt=netread(ftpdata,&xs[xp],len);
  1000.                 if(fcnt>=0) {
  1001.                     len-=fcnt;
  1002.                     xp+=fcnt;
  1003.                     filelen+=fcnt;
  1004.                   } /* end if */
  1005. /*                printf(" %d %d %d \012",len,xp,fcnt);
  1006.                 n_row();  
  1007. */
  1008.                 if(fcnt<0) {
  1009.                     if(0>write(ftpfh,xs,xp)) {   /* disk full check */
  1010.                         CRESP(27);
  1011.                         break;
  1012.                       } /* end if */
  1013.                     close(ftpfh);
  1014.                     ftpfh=0;
  1015.                     CRESP(5);
  1016.                   } /* end if */
  1017.               } while(fcnt>0);
  1018.             break;
  1019.  
  1020.         case 20:
  1021.             if(code==CONFAIL)                    /* something went wrong */
  1022.                 fcnt=-1;
  1023.             if(code!=CONOPEN)                    /* waiting for connection to open */
  1024.                 break;
  1025.             ftpstate=21;
  1026.             filelen=lseek(ftpfh,0L,2);            /* how long is file? */
  1027.             lseek(ftpfh,0L,0);                    /* back to beginning */
  1028.             towrite=0;
  1029.             xp=0;
  1030.             netputevent(USERCLASS,FTPBEGIN,-1);
  1031.  
  1032.         case 21:
  1033. /*
  1034. *  transfer file(s)to the other host via ftp request
  1035. *  file is already open=ftpfh
  1036. */
  1037.             netputuev(SCLASS,FTPACT,ftpdata);
  1038.             if(towrite<=xp) {
  1039.                 i=BUFFERS;
  1040.                 towrite=read(ftpfh,xs,i);
  1041.                 xp=0;
  1042.               } /* end if */
  1043.             if(towrite<=0 || netest(ftpdata)) {
  1044.                 ftpstate=22;
  1045.                 break;
  1046.               } /* end if */
  1047.             if(ftptmode==FAMODE)
  1048.                 i=Sfwrite(ftpdata,&xs[xp],towrite-xp);
  1049.             else
  1050.                 i=netwrite(ftpdata,&xs[xp],towrite-xp);
  1051.             if(i>0) {
  1052.                 xp+=i;
  1053.                 filelen-=i;
  1054.                 if(filelen<0L)
  1055.                     filelen=0L;
  1056.               } /* end if */
  1057.             break;
  1058.  
  1059.         case 22:                        /* wait for data to be accepted */
  1060.             netputuev(SCLASS,FTPACT,ftpdata);
  1061.             fcnt=netpush(ftpdata);        /* will go negative on err */
  1062.             if(!fcnt || netest(ftpdata))
  1063.                 fcnt=-1;
  1064.             if(fcnt<0)
  1065.                 CRESP(5);
  1066.             break;
  1067.  
  1068.         case 0:
  1069.             break;
  1070.       }  /* end of switch */
  1071.  
  1072. /*
  1073. *  after reading from connection, if the connection is closed,
  1074. *  reset up shop.
  1075. */
  1076.     if(fcnt<0) {
  1077.         if(ftpfh>0) {
  1078.             close(ftpfh);
  1079.             ftpfh=0;
  1080.           } /* end if */
  1081.         ftpstate=0;
  1082.         fcnt=0;
  1083.         if(ftpdata>=0) {
  1084.             netclose(ftpdata);
  1085.             netputevent(USERCLASS,FTPEND,-1);
  1086.             ftpdata=-1;
  1087.           } /* end if */
  1088.       } /* end if */
  1089. }   /* end ftpd() */
  1090.  
  1091. /***************************************************************************/
  1092. /*  Sfwrite
  1093. *   Write an EOL translated buffer into netwrite.
  1094. *   Returns the number of bytes which were processed from the incoming
  1095. *   buffer.  Uses its own 1024 byte buffer for the translation(with Sfread).
  1096. */
  1097. static int Sfwrite(int pnum,char *buf,int nsrc)
  1098. {
  1099.     int i,ndone,nout,lim;
  1100.     char *p,*q;
  1101.  
  1102.     ndone=0;
  1103.  
  1104.     while(ndone<nsrc){
  1105.         if(0>(i=netroom(pnum)))
  1106.             return(-1);
  1107.         if(i<1024)                    /* not enough room to work with */
  1108.             return(ndone);
  1109. /*
  1110. *  process up to 512 source bytes for output(could produce 1K bytes out)
  1111. */
  1112.         if(nsrc-ndone>512)
  1113.             lim=512;
  1114.         else
  1115.             lim=nsrc-ndone;
  1116.         p=buf+ndone;                /* where to start this block */
  1117.         q=mungbuf;                    /* where munged stuff goes */
  1118.         for(i=0; i<lim; i++) {
  1119.             if(*p==EOLCHAR) {
  1120.                 *q++=13;
  1121.                 *q++=10;
  1122.                 p++;
  1123.               }
  1124.             else
  1125.                 *q++=*p++;
  1126.           }
  1127.         ndone+=lim;                    /* # of chars processed */
  1128.         nout=q-mungbuf;                /* # of chars new */
  1129.         netwrite(pnum,mungbuf,nout);    /* send them on their way */
  1130.       }
  1131.     return(ndone);
  1132. }
  1133.  
  1134. /*
  1135. *  important note:  for Sfread, nwant must be 256 bytes LARGER than the amount
  1136. *  which will probably be read from the connection.
  1137. *  Sfread will stop anywhere from 0 to 256 bytes short of filling nwant
  1138. *  number of bytes.
  1139. */
  1140. static int Sfread(int pnum,char *buf,int nwant)
  1141. {
  1142.     int i,ndone,lim;
  1143.     char *p,*q;
  1144.  
  1145.     if(nwant<1024)
  1146.         return(-1);
  1147.     ndone=0;
  1148.     while(ndone<nwant - 1024){        /* bugfix 6/88 - TK(added -1024)*/
  1149.         if(0>=(lim=netread(pnum,mungbuf,1024))) {
  1150.             if(ndone || !lim)            /* if this read is valid, but no data */
  1151.                 return(ndone);
  1152.             else
  1153.                 return(-1);                /* if connection is closed for good */
  1154.           }
  1155.         p=mungbuf;
  1156.         q=buf+ndone;
  1157.         for(i=0; i<lim; i++) {
  1158.             if(crfound) {
  1159.                 if(*p==10)
  1160.                     *q++=EOLCHAR;
  1161.                 else 
  1162.                     if(*p==0)
  1163.                         *q++=13;            /* CR-NUL means CR */
  1164.                 crfound=0;
  1165.               }
  1166.             else 
  1167.                 if(*p==13)
  1168.                     crfound=1;
  1169.                 else 
  1170.                     *q++=*p;                /* copy the char */
  1171.             p++;
  1172.           }
  1173.         ndone=q-buf;                    /* count chars ready */
  1174.       }
  1175.     return(ndone);
  1176. }
  1177.  
  1178. /***********************************************************************/
  1179. /* Sftpname and Sftpuser and Sftphost
  1180. *  record the name of the file being transferred, to use in the status
  1181. *  line updates
  1182. */
  1183. void Sftpname(char *s)
  1184. {
  1185.     strcpy(s,newfile);
  1186. }
  1187.  
  1188. void Sftpuser(char *user)
  1189. {
  1190.     strcpy(user,myuser);            /* user name entered to log in */
  1191. }
  1192.  
  1193. int SftpDirection(void)
  1194. {
  1195.     return ftpDir;
  1196. }
  1197.  
  1198. void Sftphost(char *host)
  1199. {
  1200.     movebytes(host,hisuser,4);        /* IP address of remote host */
  1201. }
  1202.  
  1203. void Sftpstat(long *byt)
  1204. {
  1205.     *byt=filelen;
  1206. }
  1207.  
  1208.