home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / DataScope 2.0.3 / DataScope2l / TCPSource / bkgr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-04  |  28.9 KB  |  1,344 lines  |  [TEXT/MPS ]

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