home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / ncftp-2.3.0-src.tgz / tar.out / contrib / ncftp / Put.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  6KB  |  299 lines

  1. /* Put.c */
  2.  
  3. #include "Sys.h"
  4.  
  5. #include <signal.h>
  6.  
  7. #include "Util.h"
  8. #include "RCmd.h"
  9. #include "Xfer.h"
  10. #include "Cmds.h"
  11. #include "Get.h"
  12. #include "Getopt.h"
  13. #include "Glob.h"
  14. #include "Put.h"
  15.  
  16. extern int gTransferType;
  17. extern int gOptInd, gXferAbortFlag;
  18.  
  19. /* Ascii put should probably be optimized in a similar way that we do
  20.  * for ascii get.  But then again, how often do you need to do ascii puts?
  21.  */
  22.  
  23. long AsciiGetLocalProc(char *buf, size_t bufsize, XferSpecPtr xp)
  24. {
  25.     long len;
  26.     int len2;
  27.  
  28.     /* Problems may arise if the user tries putting a binary file in
  29.      * ascii mode, because a binary file could have zero-bytes
  30.      * mixed in.  
  31.      */
  32.     len2 = BufferGets(buf, bufsize, xp);
  33.  
  34.     if (len2 < 0) {
  35.         len = -1L;
  36.         buf[0] = '\0';
  37.     } else {
  38.         /* Ascii FTP strings need to end with CR/LF's, not just LF's. */
  39.         if (buf[len2 - 1] == '\n') {
  40.             strcpy(buf + len2 - 1, "\r\n");
  41.         }
  42.         len = (long) len2;
  43.     }
  44.     return (len);
  45. }    /* AsciiGetLocalProc */
  46.  
  47.  
  48.  
  49.  
  50. long AsciiPutRemoteProc(char *buf, size_t bufsize, XferSpecPtr xp)
  51. {
  52.     long len, len2;
  53.  
  54.     len = (long) strlen(buf);
  55.     len2 = (long) WriteOrTimeout(xp->outStream, buf, len);
  56.     if (len != len2) {
  57.         if (len2 < 0L)
  58.             len = len2;        /* May be kTimeoutErr. */
  59.         else
  60.             len = -1L;
  61.     }
  62.     return (len);
  63. }    /* AsciiPutRemoteProc */
  64.  
  65.  
  66.  
  67.  
  68. int BinaryPut(char *remoteName, int infile, char *localName, long size)
  69. {
  70.     int result;
  71.     XferSpecPtr xp;
  72.  
  73.     /* We don't do a SETBINARY here. Instead, we set it to gTransferType,
  74.      * which we know is not ascii.  Most often this will mean binary mode,
  75.      * but perhaps we're dealing with a tenex machine.
  76.      */
  77.     SetType(gTransferType);
  78.  
  79.     /* Setup the parameter block to give to RDataCmd. */
  80.     xp = InitXferSpec();
  81.     xp->netMode = kNetWriting;
  82.     xp->getBlock = BinaryGetProc;    /* Same routines as in Get.c. */
  83.     xp->putBlock = BinaryPutProc;
  84.     xp->inStream = infile;
  85.     /* xp->outStream = gDataSocket;  RDataCmd fills this in when it gets it. */
  86.     
  87.     /* This group is needed for the progress reporting and logging stuff.
  88.      * Otherwise, it isn't that important.
  89.      */
  90.     xp->doReports = (size > 0) ? 1 : 0;
  91.     xp->localFileName = localName;
  92.     xp->remoteFileName = remoteName;
  93.     xp->expectedSize = size;
  94.     
  95.     result = RDataCmd(xp, "STOR %s", remoteName);
  96.     DoneWithXferSpec(xp);
  97.  
  98.     return (result);
  99. }    /* BinaryPut */
  100.  
  101.  
  102.  
  103.  
  104. int AsciiPut(char *remoteName, int infile, char *localName, long size)
  105. {
  106.     int result;
  107.     XferSpecPtr xp;
  108.  
  109.     SETASCII;
  110.     
  111.     /* Setup the parameter block to give to RDataCmd. */
  112.     xp = InitXferSpec();
  113.     xp->netMode = kNetWriting;
  114.     xp->getBlock = AsciiGetLocalProc;
  115.     xp->putBlock = AsciiPutRemoteProc;
  116.     xp->inStream = infile;
  117.     /* xp->outStream = gDataSocket;  RDataCmd fills this in when it gets it. */
  118.     
  119.     /* This group is needed for the progress reporting and logging stuff.
  120.      * Otherwise, it isn't that important.
  121.      */
  122.     xp->doReports = (size > 0) ? 1 : 0;
  123.     xp->localFileName = localName;
  124.     xp->remoteFileName = remoteName;
  125.     xp->expectedSize = size;
  126.  
  127.     result = RDataCmd(xp, "STOR %s", remoteName);
  128.     DoneWithXferSpec(xp);
  129.  
  130.     return (result);
  131. }    /* AsciiPut */
  132.  
  133.  
  134.  
  135.  
  136. void GetLocalSendFileName(char *localName, char *remoteName, size_t siz)
  137. {
  138.     char *cp;
  139.     
  140.     /* Create a remote file name.  We want this to be just the same
  141.      * as the local file name, but with the directory path stripped off.
  142.      */ 
  143.     cp = strrchr(localName, '/');
  144.     if (cp == NULL)
  145.         cp = localName;
  146.     else
  147.         cp++;
  148.     
  149.     Strncpy(remoteName, cp, siz);
  150. }    /* GetLocalSendFileName */
  151.  
  152.  
  153.  
  154.  
  155. int OpenLocalSendFile(char *localName, long *size)
  156. {
  157.     int fd;
  158.     struct stat st;
  159.     
  160.     *size = kSizeUnknown;
  161.  
  162.     if ((fd = open(localName, O_RDONLY)) < 0) {
  163.         Error(kDoPerror, "Can't open local file %s.\n", localName);
  164.     } else {
  165.         /* While we're here, get the size of the file.  This is useful
  166.          * for the progress reporting functions.
  167.          */
  168.         if (stat(localName, &st) == 0)
  169.             *size = st.st_size;
  170.     }
  171.     return fd;
  172. }    /* OpenLocalSendFile */
  173.  
  174.  
  175.  
  176.  
  177. int PutCmd(int argc, char **argv)
  178. {
  179.     int fd;
  180.     int i, result, errs, opt;
  181.     string remote;
  182.     long fileSize;
  183.     LineList globFiles;
  184.     LinePtr globFile;
  185.     int renameMode;
  186.  
  187.     errs = 0;
  188.     renameMode = 0;
  189.     GetoptReset();
  190.     while ((opt = Getopt(argc, argv, "Rrz")) >= 0) {
  191.         switch (opt) {
  192.             case 'R':
  193.             case 'r':
  194.                 PrintF("Recursive put not implemented yet.\n");
  195.                 break;
  196.             case 'z':
  197.                 renameMode = 1;
  198.                 break;
  199.             default:
  200.                 return (kUsageErr);
  201.         }
  202.     }
  203.     argv += gOptInd;
  204.     argc -= gOptInd;
  205.  
  206.     if (renameMode) {
  207.         /* User wanted to transfer a local file, but name it different. */
  208.         if (argc < 2)
  209.             return (kUsageErr);
  210.         fd = OpenLocalSendFile(argv[0], &fileSize);
  211.         if (fd < 0) {
  212.             --errs;
  213.         } else {
  214.             if (gTransferType == 'A') {        
  215.                 result = AsciiPut(
  216.                     argv[1],    /* Remote */
  217.                     fd,
  218.                     argv[0],    /* Local */
  219.                     fileSize
  220.                 );
  221.             } else {
  222.                 result = BinaryPut(
  223.                     argv[1],    /* Remote */
  224.                     fd,
  225.                     argv[0],    /* Local */
  226.                     fileSize
  227.                 );
  228.             }
  229.             (void) close(fd);
  230.             if (result < 0) {
  231.                 --errs;
  232.                 /* Maybe remove the remote file. */
  233.             }
  234.         }
  235.     } else for (i=0; i<argc; i++) {
  236.         InitLineList(&globFiles);
  237.         LocalGlob(&globFiles, argv[i]);
  238.         for (globFile = globFiles.first; globFile != NULL;
  239.             globFile = globFile->next)
  240.         {
  241.             GetLocalSendFileName(globFile->line, remote, sizeof(remote));
  242.             fd = OpenLocalSendFile(globFile->line, &fileSize);
  243.             if (fd < 0)
  244.                 continue;
  245.             if (gTransferType == 'A') {        
  246.                 result = AsciiPut(
  247.                     remote,
  248.                     fd,
  249.                     globFile->line,
  250.                     fileSize
  251.                 );
  252.             } else {
  253.                 result = BinaryPut(
  254.                     remote,
  255.                     fd,
  256.                     globFile->line,
  257.                     fileSize
  258.                 );
  259.             }
  260.             (void) close(fd);
  261.             if (result < 0) {
  262.                 --errs;
  263.                 /* Maybe remove the remote file. */
  264.             }
  265.             if (gXferAbortFlag == SIGINT)
  266.                 break;
  267.         }
  268.         DisposeLineListContents(&globFiles);
  269.     }
  270.  
  271.     return (errs);
  272. }    /* PutCmd */
  273.  
  274.  
  275.  
  276.  
  277. int CreateCmd(int argc, char **argv)
  278. {
  279.     int fd;
  280.     string remote;
  281.     int result;
  282.  
  283.     /* Good ol' /dev/null always returns EOF on reads. */
  284.     fd = open("/dev/null", O_RDONLY);
  285.     if (fd < 0)
  286.         return (kCmdErr);
  287.     
  288.     STRNCPY(remote, argv[1]);
  289.     result = BinaryPut(
  290.         remote,
  291.         fd,
  292.         "/dev/null",
  293.         0L
  294.     );
  295.  
  296.     (void) close(fd);
  297.     return (result);
  298. }    /* CreateCmd */
  299.