home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / info-service / gopher / Unix / gopher+1.2b4 / gopherd / ftp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-14  |  11.8 KB  |  488 lines

  1. /********************************************************************
  2.  * lindner
  3.  * 3.3
  4.  * 1993/04/15 04:48:09
  5.  * /home/mudhoney/GopherSrc/CVS/gopher+/gopherd/ftp.c,v
  6.  * Exp
  7.  *
  8.  * Paul Lindner, University of Minnesota CIS.
  9.  *
  10.  * Copyright 1991, 1992 by the Regents of the University of Minnesota
  11.  * see the file "Copyright" in the distribution for conditions of use.
  12.  *********************************************************************
  13.  * MODULE: ftp.c
  14.  * Routines to translate gopher protocol to ftp protocol.
  15.  *********************************************************************
  16.  * Revision History:
  17.  * ftp.c,v
  18.  * Revision 3.3  1993/04/15  04:48:09  lindner
  19.  * Debug code from Mitra
  20.  *
  21.  * Revision 3.2  1993/03/24  20:15:06  lindner
  22.  * FTP gateway now gets filetypes from gopherd.conf
  23.  *
  24.  * Revision 3.1.1.1  1993/02/11  18:02:51  lindner
  25.  * Gopher+1.2beta release
  26.  *
  27.  * Revision 1.2  1993/01/11  23:18:09  lindner
  28.  * Changed password to be the host of the remote client, not the gateway.
  29.  *
  30.  * Revision 1.1  1992/12/10  23:13:27  lindner
  31.  * gopher 1.1 release
  32.  *
  33.  *
  34.  *********************************************************************/
  35.  
  36.  
  37. /* -------------------------------------------------
  38.  *    g2fd.c          Gopher to FTP gateway daemon.
  39.  *    Version 0.3 Hacked up: April 1992.  Farhad Anklesaria.
  40.  *    Based on a Perl story by John Ladwig.
  41.  *    Based on a Perl story by Farhad Anklesaria.
  42.  *
  43.  *      Modified by Greg Smith, Bucknell University, 24 Nov 1992
  44.  *      to handle multiline status replies.
  45.  *
  46.  ---------------------------------------------------- */
  47.  
  48. #include "gopherd.h"
  49. #include <signal.h>
  50.  
  51. #include <stdio.h>
  52. #include "ext.h"
  53.  
  54. #define SLEN    255    /* Generic small buffer length */
  55. #define    TMOUT    180    /* 3 minutes is plenty long enough */
  56.  
  57. int     GLOBALsockfd;   /* For cleanup */
  58. char    *appname;
  59. char    ftptmp[SLEN] = LIST;
  60. char    query[BUFSIZ];                /* input redirected by inetd */
  61. char     *host, *thing;                /* pointers into query */
  62. int    gettingFile = 1;
  63. int    gettingBinary = 0;
  64. int    childpid;
  65.  
  66. /*** Some forward declarations ***/
  67. boolean NotText();
  68. int     Abort();
  69. boolean IsBinaryType();
  70. void    GenerateUniqueFiles();
  71. void    GopherType();
  72. void    Cleanup();
  73. void    RoundEmUp();
  74. void    FailErr();
  75. int     getreply();
  76. /**************************/
  77.  
  78. int
  79. getreply(theStream,inputline,maxlen)
  80.   int theStream;
  81.   char *inputline;
  82.   int maxlen;
  83. {
  84.      int code = 0;
  85.      char origcode[4];
  86.      
  87.  
  88.      if (DEBUG) fprintf(stderr,"getreply...");
  89.      readline(theStream, inputline, maxlen);
  90.      if (DEBUG) printf(inputline);
  91.      strncpy(origcode, inputline, 3);  /*** Stash away the original code ***/
  92.  
  93.      while (inputline[3] == '-') {
  94.       if (readline(theStream, inputline, maxlen)<=0)
  95.            return(-1);
  96.       if (DEBUG) printf(inputline);
  97.  
  98.       if (!isdigit(inputline[0]) && !isdigit(inputline[1]) &&
  99.           !isdigit(inputline[2]))
  100.            inputline[3] = '-';
  101.       else
  102.            /*** Keep going if response code isn't the same as original **/
  103.            if (strncmp(origcode, inputline, 3) != 0)
  104.             inputline[3] = '-';
  105.      }
  106.      return (0);
  107. }
  108.  
  109. void
  110. SendFtpQuery(sockfd, query)
  111.   char *query;
  112. {
  113.      int       sLen, termCh;
  114.      char      *at, *cp;
  115.      char      inputline[512];
  116.      char      ipnum[64];
  117.      char      buf[1600];     /*** Nice MTU size ***/
  118.      int       tmpfd;
  119.      int       ftp_control, ftp_data;
  120.      int       ftp_dataport, nRead;
  121.      GopherObj *gs;
  122.  
  123.      /*** hook onto the gs code to do our ftp socket connects ***/
  124.      gs = GSnew();
  125.  
  126.      /** Get ready for some cleanup action **/
  127.      signal(SIGPIPE, Cleanup);
  128.      signal(SIGINT, Cleanup);
  129.      signal(SIGALRM, Cleanup);
  130.  
  131.      if (DEBUG)
  132.       printf("The full query was %s\n", query);
  133.      
  134.      if ((sLen = strlen(query)) <= 2) Abort(sockfd,"No host name specified.");
  135.      host = query;
  136.      at = strchr(query, '@');
  137.      
  138.      if (at == NULL) 
  139.       Abort(sockfd, "Not a valid ftp query.");
  140.      
  141.      GenerateUniqueFiles(ftptmp);
  142.      tmpfd = uopen(ftptmp, O_RDWR|O_CREAT,0755);
  143.      
  144.      if (tmpfd < 0)
  145.       Abort(sockfd, "Sorry, out of tmp transfer space!");
  146.  
  147.      thing = at + 1;
  148.      *at = '\0';             /*Sneakily chop it into two strings*/
  149.  
  150.      sLen = strlen(thing);
  151.      termCh = thing[sLen - 1];            /* Grab possible end char: / etc */
  152.      
  153.      if ((termCh == '*') || (termCh == '@'))  /*  || (termCh == '/')  */
  154.       thing[sLen - 1] = '\0';
  155.      
  156.      if (DEBUG)
  157.       printf("At this point host: %s   thing: %s\n", host, thing);
  158.      
  159.  
  160.  
  161.      /*** Open an ftp control connection ***/
  162.      GSsetHost(gs, host);
  163.      GSsetPort(gs, 21);
  164.      
  165.      ftp_control = GSconnect(gs);
  166.      if (ftp_control < 0)
  167.       Abort(sockfd, "unable to connect to ftp server!");
  168.  
  169.      /*** Strip off the connection message ***/
  170.      getreply(ftp_control,inputline,sizeof inputline);
  171.  
  172.      if (*inputline != '2')
  173.       /*** Some sort of error, urg! ***/
  174.       Abort(sockfd, inputline +3);
  175.  
  176.      /*** Send username ***/
  177.      writestring(ftp_control, "USER anonymous\r\n");
  178.  
  179.      getreply(ftp_control,inputline,sizeof inputline);
  180.  
  181.      if (*inputline != '3')
  182.       /*** Some sort of error, urg! ***/
  183.       Abort(sockfd, inputline +3);
  184.  
  185.      /** Send password***/
  186.      writestring(ftp_control, "PASS -gopher@");
  187.      inet_netnames(sockfd, inputline, ipnum);
  188.      writestring(ftp_control, inputline);
  189.      writestring(ftp_control, "\r\n");
  190.      if (DEBUG) printf("Password was -gopher@%s\n", inputline);
  191.      getreply(ftp_control,inputline,sizeof inputline);
  192.  
  193.      if (*inputline != '2')
  194.       /*** Some sort of error, urg! ***/
  195.       Abort(sockfd, inputline +3);
  196.  
  197.      /**** Send PASV and set up the data port ***/
  198.      writestring(ftp_control, "PASV\r\n");
  199.  
  200.      getreply(ftp_control,inputline,sizeof inputline);
  201.  
  202.      if (strncmp(inputline, "227", 3))
  203.       Abort(sockfd,inputline +3);
  204.      
  205.      /*** Find out the port number of the data connection ***/
  206.      inputline[strlen(inputline)] = '\0';  /** Zap the right paren **/
  207.      cp = strrchr(inputline, ',');         /** lower order octet **/
  208.      if (cp == NULL)  Abort(sockfd,"PASV failed- cannot ftp!");
  209.      *cp = '\0';
  210.      cp ++;
  211.      ftp_dataport = atoi(cp);
  212.  
  213.      cp = strrchr(inputline, ',');         /** upper octet **/
  214.      if (cp == NULL)  Abort(sockfd,"PASV failed- cannot ftp!");
  215.      *cp = '\0';
  216.      cp ++;
  217.      ftp_dataport = atoi(cp) * 256 + ftp_dataport;
  218.      if (DEBUG) printf("Data port is %d\n", ftp_dataport);
  219.  
  220.      GSsetPort(gs, ftp_dataport);
  221.      ftp_data = GSconnect(gs);
  222.      if (ftp_data < 0)
  223.       Abort(sockfd,"Unable to establish data connection!");
  224.  
  225.      
  226.      if (termCh == '/') {    /* We have a directory */
  227.       gettingFile = 0;
  228.  
  229.       writestring(ftp_control, "NLST -LF ");
  230.       if (strlen(thing) > 0)
  231.            writestring(ftp_control, thing);
  232.       writestring(ftp_control, "\r\n");
  233.  
  234.       getreply(ftp_control,inputline,sizeof inputline);
  235.  
  236.       if (*inputline != '1')
  237.            Abort(sockfd,inputline + 4);
  238.      }
  239.      else {                    /* We have a file */
  240.       gettingFile = 1;
  241.       if (gettingBinary = IsBinaryType(thing))  {
  242.            writestring(ftp_control, "TYPE I\r\n");
  243.            getreply(ftp_control,inputline,sizeof inputline);
  244.            if (*inputline != '2')
  245.             Abort(sockfd,"Unable to transfer files in binary");
  246.       }
  247.       writestring(ftp_control, "RETR ");
  248.       writestring(ftp_control, thing);
  249.       writestring(ftp_control, "\r\n");
  250.  
  251.       getreply(ftp_control,inputline,sizeof inputline);
  252.       if (*inputline != '1')
  253.            Abort(sockfd,inputline + 4);
  254.      }
  255.  
  256.      /*** Transfer the data... ***/
  257.      while ((nRead = read(ftp_data, buf, sizeof buf)) > 0)
  258.       writen(tmpfd, buf, nRead);
  259.  
  260.      close(ftp_data);
  261.      
  262.      getreply(ftp_control,inputline,sizeof inputline);
  263.  
  264.      if (*inputline != '2')
  265.       Abort(sockfd,inputline + 3);
  266.  
  267.      writestring(ftp_control, "QUIT\r\n");
  268.  
  269.      getreply(ftp_control,inputline,sizeof inputline);
  270.  
  271.      if (*inputline != '2')
  272.       Abort(sockfd,inputline + 3);
  273.  
  274.      close(ftp_control);
  275. }
  276.  
  277. /*--------------------------------*/
  278. void
  279. TranslateResults(sockfd)
  280.   int sockfd;
  281. {
  282.      FILE  *fp, *OpenOrDie();
  283.      char  buf[BUFSIZ], theName[SLEN];
  284.      int   fd, nRead, checkIt;
  285.      char  outputline[512];
  286.      
  287.      checkIt = 1;
  288.      
  289.      signal(SIGPIPE, Cleanup);
  290.      signal(SIGINT, Cleanup);
  291.  
  292.      if (gettingFile) {
  293.       if (gettingBinary) {                /* icky binary file */
  294.            if (DEBUG)
  295.             printf("Whoa!  That's a binary file\n");
  296.            fp = OpenOrDie(ftptmp, "r");
  297.            fd = fileno(fp);
  298.            
  299.            if (DEBUG)
  300.             printf("fd %d\n",fd);
  301.            while ((nRead = read(fd, buf, sizeof buf)) > 0)
  302.                     writen(sockfd, buf, nRead);
  303.            
  304.            writen(sockfd, buf, nRead);
  305.            fclose(fp);
  306.       } else {            /* must be a nice texty file */
  307.            fp = OpenOrDie(ftptmp, "r");
  308.            while (fgets(buf, sizeof buf, fp) != NULL) {
  309.             if (checkIt) { /* Just peek at it once */
  310.              checkIt = 0;
  311.              if (NotText(buf)) {
  312.                   fclose(fp);
  313.                   Abort(sockfd,"Sorry.  File does not appear to contain text.");
  314.              }
  315.             }
  316.             ZapCRLF(buf);
  317.             FailErr(writestring(sockfd, buf));
  318.             FailErr(writestring(sockfd, "\r\n"));
  319.            }
  320.            fclose(fp);
  321.            FailErr(writestring(sockfd,".\r\n"));
  322.       }
  323.      } else {                       /* Must be a directory */
  324.       fp = OpenOrDie(ftptmp, "r");
  325.       while (fgets(buf, sizeof buf, fp) != NULL) {
  326.            ZapCRLF(buf);
  327.            GopherType(buf, theName);
  328.            sprintf(outputline, "%s\tftp:%s@%s%s\t%s\t%d\r\n", theName,
  329.                host, thing, buf, Zehostname, GopherPort);
  330.            FailErr(writestring(sockfd, outputline));
  331.       }
  332.       fclose(fp);
  333.       FailErr(writestring(sockfd, ".\r\n"));
  334.      }
  335.  
  336.      Cleanup();
  337. }
  338.  
  339. /*--------------------------------*/
  340.  
  341. FILE *OpenOrDie(file, mode)
  342.   char *file, *mode;
  343. {
  344.      FILE *fp, *fopen();
  345.      if ((fp = ufopen(file, mode,0755)) != NULL) {
  346.       return(fp);
  347.      } else {
  348.       Cleanup();
  349.       exit(-1);
  350.      }
  351.      return(NULL);  /** Shouldn't get here **/
  352. }
  353.  
  354.  
  355. /*--------------------------------*/
  356. boolean
  357. NotText(buf)
  358.   char * buf;
  359. {
  360.      int max;   char *c;
  361.      
  362.      if ((max = strlen(buf)) >= (BUFSIZ - 50)) max = BUFSIZ - 50;
  363.      for (c = buf; c < (buf + max); c++) {
  364.       if (*c > '~') return(TRUE);
  365.      }
  366.      return(FALSE);
  367. }
  368.  
  369. /*--------------------------------*/
  370.  
  371. int
  372. Abort(sockfd, complaint)
  373.   int sockfd;
  374.   char *complaint;
  375. {
  376.      char errmsg[512];
  377.      sprintf(errmsg, "3 Error: %s\r\n.\r\n", complaint); 
  378.      writestring(sockfd, errmsg);
  379.      fflush(stdout);
  380.      Cleanup();
  381.      exit(1);
  382. }
  383.  
  384. /*--------------------------------*/
  385.  
  386. boolean
  387. IsBinaryType(thing)
  388.   char *thing;
  389. {
  390.     char Gtype, *prefix;
  391.     Extobj *ext;
  392.     
  393.     if (GDCViewExtension(Config, thing, &ext)) {
  394.      Gtype = EXgetObjtype(ext);
  395.      
  396.      if(Gtype == A_FILE || Gtype == A_MACHEX) 
  397.           return FALSE;
  398.      else
  399.           return TRUE;
  400.     } else
  401.      return(FALSE);
  402.  
  403.     return TRUE;
  404. }
  405.  
  406. /*--------------------------------*/
  407.  
  408. void
  409. GenerateUniqueFiles(tmpList)
  410.   char *tmpList;
  411. {
  412.      char *s;
  413.      int pid;
  414.      
  415.      pid = getpid();
  416.      s = strchr(tmpList, '+');
  417.      sprintf(s, "%d", pid);
  418. }
  419.  
  420. /*--------------------------------*/
  421.  
  422. void
  423. GopherType(buf, theName)
  424.   char *buf, *theName;
  425. {
  426.     char    Gtype, *prefix;
  427.     int        last;
  428.     char    tmpName[SLEN];    
  429.     Extobj      *ext;
  430.      
  431.     last = strlen(buf) -1;
  432.     
  433.     strcpy(tmpName, buf);
  434.     if (buf[last] == '/') {
  435.     tmpName[last] = '\0';
  436.     sprintf(theName, "%c%s", A_DIRECTORY, tmpName);
  437.     return;
  438.     }
  439.     if ((buf[last] == '*') || (buf[last] == '@')) {    /* Hack out * and @ */
  440.     buf[last] = '\0';
  441.     tmpName[last] = '\0';
  442.     }
  443.      
  444.     /* At this point we're looking at a file */
  445.     if (GDCViewExtension(Config, buf, &ext)) {  
  446.      Gtype = EXgetObjtype(ext);
  447.      
  448.      sprintf(theName, "%c%s", Gtype, tmpName);
  449.      return;
  450.     }
  451.      
  452.     sprintf(theName, "%c%s", A_FILE, tmpName);
  453.     return;        /* Some other and hopefully text file */
  454. }
  455.  
  456. /*--------------------------------*/
  457.  
  458. void
  459. Cleanup()
  460. {
  461.      unlink(ftptmp);
  462.      if (DEBUG)
  463.       printf("Cleaning up %s\n", ftptmp);
  464.  
  465.      exit(1);
  466. }
  467.  
  468. /*--------------------------------*/
  469. void
  470. RoundEmUp()
  471. {
  472.      
  473.      kill(childpid, SIGKILL);
  474.      Cleanup();
  475. }
  476.  
  477. /*--------------------------------*/
  478. void
  479. FailErr(result)
  480.   int result;
  481. {
  482.      if (result < 0) {
  483.       Cleanup();
  484.      }
  485. }
  486.  
  487. /*--------------------------------*/
  488.