home *** CD-ROM | disk | FTP | other *** search
/ ftp.ncftp.com / ftp.ncftp.com.zip / ftp.ncftp.com / ncftp / older_versions / ncftp-3.2.2-src.tar.bz2 / ncftp-3.2.2-src.tar / ncftp-3.2.2 / libncftp / io_listmem.c < prev    next >
C/C++ Source or Header  |  2006-03-13  |  6KB  |  252 lines

  1. /* io_listmem.c
  2.  *
  3.  * Copyright (c) 1996-2005 Mike Gleason, NcFTP Software.
  4.  * All rights reserved.
  5.  *
  6.  */
  7.  
  8. #include "syshdrs.h"
  9. #ifdef PRAGMA_HDRSTOP
  10. #    pragma hdrstop
  11. #endif
  12.  
  13. #if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__)
  14. #    define ASCII_TRANSLATION 0
  15. #endif
  16.  
  17. #ifndef ASCII_TRANSLATION
  18. #    define ASCII_TRANSLATION 1
  19. #endif
  20.  
  21. #ifndef NO_SIGNALS
  22. #    define NO_SIGNALS 1
  23. #endif
  24.  
  25. #ifndef O_BINARY
  26.     /* Needed for platforms using different EOLN sequence (i.e. DOS) */
  27. #    ifdef _O_BINARY
  28. #        define O_BINARY _O_BINARY
  29. #    else
  30. #        define O_BINARY 0
  31. #    endif
  32. #endif
  33.  
  34. int
  35. FTPListToMemory2(const FTPCIPtr cip, const char *const pattern, const FTPLineListPtr llines, const char *const lsflags, const int blankLines, int *const tryMLSD)
  36. {
  37.     char secondaryBuf[768];
  38.     char line[512];
  39.     char lsflags1[128];
  40.     const char *command = "NLST";
  41.     const char *scp;
  42.     char *dcp, *lim;
  43. #ifndef NO_SIGNALS
  44.     char *secBufPtr, *secBufLimit;
  45.     volatile FTPSigProc osigpipe;
  46.     volatile FTPCIPtr vcip;
  47.     int sj;
  48.     int nread;
  49.     volatile int result;
  50. #else    /* NO_SIGNALS */
  51.     SReadlineInfo lsSrl;
  52.     int result;
  53. #endif    /* NO_SIGNALS */
  54.  
  55.     if (cip == NULL)
  56.         return (kErrBadParameter);
  57.     if (strcmp(cip->magic, kLibraryMagic))
  58.         return (kErrBadMagic);
  59.  
  60.     if ((llines == NULL) || (pattern == NULL) || (lsflags == NULL))
  61.         return (kErrBadParameter);
  62.  
  63.     if ((tryMLSD != (int *) 0) && (*tryMLSD != 0) && (cip->hasMLSD == kCommandAvailable)) {
  64.         command = "MLSD";
  65.         if ((lsflags[0] == '-') && (strchr(lsflags, 'd') != NULL) && (cip->hasMLST == kCommandAvailable))
  66.             command = "MLST";
  67.         lsflags1[0] = '\0';
  68.         FTPRequestMlsOptions(cip);
  69.     } else {
  70.         /* Not using MLSD. */
  71.         if (tryMLSD != (int *) 0)
  72.             *tryMLSD = 0;
  73.         if (lsflags[0] == '-') {
  74.             /* See if we should use LIST instead. */
  75.             if (strstr(lsflags, "--") != NULL) {
  76.                 /* You are trying to use one of those
  77.                  * --extended-options type of flags;
  78.                  * assume you want LIST and that you
  79.                  * know what you're doing...
  80.                  */
  81.                 command = "LIST";
  82.                 (void) STRNCPY(lsflags1, lsflags);
  83.             } else {
  84.                 scp = lsflags + 1;
  85.                 dcp = lsflags1;
  86.                 lim = dcp + sizeof(lsflags1) - 2;
  87.                 for (; *scp != '\0'; scp++) {
  88.                     if (isspace((int) *scp))
  89.                         continue;
  90.                     if (*scp == '-')
  91.                         continue;
  92.                     if (*scp == 'l') {
  93.                         /* do not add the 'l' */
  94.                         command = "LIST";
  95.                     } else if (dcp < lim) {
  96.                         if (dcp == lsflags1)
  97.                             *dcp++ = '-';
  98.                         *dcp++ = *scp;
  99.                     }
  100.                 }
  101.                 *dcp = '\0';
  102.             }
  103.         } else {
  104.             (void) STRNCPY(lsflags1, lsflags);
  105.         }
  106.     }
  107.  
  108.     InitLineList(llines);
  109.  
  110.     result = FTPStartDataCmd(
  111.         cip,
  112.         kNetReading,
  113.         kTypeAscii,
  114.         (longest_int) 0,
  115.         "%s%s%s%s%s",
  116.         command,
  117.         (lsflags1[0] == '\0') ? "" : " ",
  118.         lsflags1,
  119.         (pattern[0] == '\0') ? "" : " ",
  120.         pattern
  121.     );
  122.  
  123. #ifdef NO_SIGNALS
  124.  
  125.     if (result == 0) {
  126.         if (InitSReadlineInfo(&lsSrl, cip->dataSocket, secondaryBuf, sizeof(secondaryBuf), (int) cip->xferTimeout, 1) < 0) {
  127.             /* Not really fdopen, but close in what we're trying to do. */
  128.             result = kErrFdopenR;
  129.             cip->errNo = kErrFdopenR;
  130.             FTPLogError(cip, kDoPerror, "Could not fdopen.\n");
  131.             return (result);
  132.         }
  133.         
  134.         for (;;) {
  135.             result = SReadline(&lsSrl, line, sizeof(line) - 1);
  136.             if (result == kTimeoutErr) {
  137.                 /* timeout */
  138.                 FTPLogError(cip, kDontPerror, "Could not directory listing data -- timed out.\n");
  139.                 cip->errNo = kErrDataTimedOut;
  140.                 return (cip->errNo);
  141.             } else if (result == 0) {
  142.                 /* end of listing -- done */
  143.                 cip->numListings++;
  144.                 break;
  145.             } else if (result < 0) {
  146.                 /* error */
  147.                 FTPLogError(cip, kDoPerror, "Could not read directory listing data");
  148.                 result = kErrLISTFailed;
  149.                 cip->errNo = kErrLISTFailed;
  150.                 break;
  151.             }
  152.  
  153.             if (line[result - 1] == '\n')
  154.                 line[result - 1] = '\0';
  155.  
  156.             if ((blankLines == 0) && (result <= 1))
  157.                 continue;
  158.  
  159.             /* Valid directory listing line of output */
  160. #define islsenddelim(c) ((c == '\0') || ((iscntrl((int) c)) && (! isspace((int) c))))
  161.             if ((line[0] == '.') && ((islsenddelim(line[1])) || ((line[1] == '.') && (islsenddelim(line[2])))))
  162.                 continue;    /* Skip . and .. */
  163.  
  164.             (void) AddLine(llines, line);
  165.         }
  166.  
  167.         DisposeSReadlineInfo(&lsSrl);
  168.         if (FTPEndDataCmd(cip, 1) < 0) {
  169.             result = kErrLISTFailed;
  170.             cip->errNo = kErrLISTFailed;
  171.         }
  172.     } else if (result == kErrGeneric) {
  173.         result = kErrLISTFailed;
  174.         cip->errNo = kErrLISTFailed;
  175.     }
  176.  
  177.  
  178. #else    /* NO_SIGNALS */
  179.     vcip = cip;
  180.     osigpipe = (volatile FTPSigProc) signal(SIGPIPE, BrokenData);
  181.  
  182.     gGotBrokenData = 0;
  183.     gCanBrokenDataJmp = 0;
  184.  
  185. #ifdef HAVE_SIGSETJMP
  186.     sj = sigsetjmp(gBrokenDataJmp, 1);
  187. #else
  188.     sj = setjmp(gBrokenDataJmp);
  189. #endif    /* HAVE_SIGSETJMP */
  190.  
  191.     if (sj != 0) {
  192.         (void) signal(SIGPIPE, (FTPSigProc) osigpipe);
  193.         FTPShutdownHost(vcip);
  194.         vcip->errNo = kErrRemoteHostClosedConnection;
  195.         return(vcip->errNo);
  196.     }
  197.     gCanBrokenDataJmp = 1;
  198.  
  199.     if (result == 0) {
  200.         /* This line sets the buffer pointer so that the first thing
  201.          * BufferGets will do is reset and fill the buffer using
  202.          * real I/O.
  203.          */
  204.         secBufPtr = secondaryBuf + sizeof(secondaryBuf);
  205.         secBufLimit = (char *) 0;
  206.         memset(secondaryBuf, 0, sizeof(secondaryBuf));
  207.  
  208.         for (;;) {
  209.             memset(line, 0, sizeof(line));
  210.             if (cip->xferTimeout > 0)
  211.                 (void) alarm(cip->xferTimeout);
  212.             nread = BufferGets(line, sizeof(line), cip->dataSocket, secondaryBuf, &secBufPtr, &secBufLimit, sizeof(secondaryBuf));
  213.             if (nread <= 0) {
  214.                 if (nread < 0)
  215.                     break;
  216.                 if (blankLines != 0)
  217.                     (void) AddLine(llines, line);
  218.             } else {
  219.                 cip->bytesTransferred += (longest_int) nread;
  220.  
  221.                 if ((line[0] == '.') && ((line[1] == '\0') || ((line[1] == '.') && ((line[2] == '\0') || (iscntrl(line[2]))))))
  222.                     continue;    /* Skip . and .. */
  223.  
  224.                 (void) AddLine(llines, line);
  225.             }
  226.         }
  227.         if (cip->xferTimeout > 0)
  228.             (void) alarm(0);
  229.         result = FTPEndDataCmd(cip, 1);
  230.         if (result < 0) {
  231.             result = kErrLISTFailed;
  232.             cip->errNo = kErrLISTFailed;
  233.         }
  234.         result = kNoErr;
  235.         cip->numListings++;
  236.     } else if (result == kErrGeneric) {
  237.         result = kErrLISTFailed;
  238.         cip->errNo = kErrLISTFailed;
  239.     }
  240.     (void) signal(SIGPIPE, (FTPSigProc) osigpipe);
  241. #endif    /* NO_SIGNALS */
  242.     return (result);
  243. }    /* FTPListToMemory2 */
  244.  
  245.  
  246.  
  247. int
  248. FTPListToMemory(const FTPCIPtr cip, const char *const pattern, const FTPLineListPtr llines, const char *const lsflags)
  249. {
  250.     return (FTPListToMemory2(cip, pattern, llines, lsflags, 1, (int *) 0));
  251. }    /* FTPListToMemory */
  252.