home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Networking / ncftp-2.4.2-MIHS / src / List.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-28  |  10.7 KB  |  481 lines

  1. /* List.c */
  2.  
  3. #include "Sys.h"
  4.  
  5. #include <signal.h>
  6. #include <setjmp.h>
  7.  
  8. #include "Util.h"
  9. #include "RCmd.h"
  10. #include "Xfer.h"
  11. #include "Cmds.h"
  12. #include "List.h"
  13. #include "Glob.h"
  14. #include "Bookmark.h"
  15. #include "Complete.h"
  16.  
  17. jmp_buf gPDirJmp;
  18. jmp_buf gLocalListJmp;
  19. LineList gRedir;
  20. extern int gStdout;
  21. extern longstring gPager;
  22. extern Bookmark gRmtInfo;
  23. extern int gNetworkTimeout;
  24.  
  25. int
  26. ListReceiveProc(XferSpecPtr xp)
  27. {
  28.     int nread;
  29.     int nwrote;
  30.     int fd;
  31.     char xbuf[256];
  32.     char buf2[256];
  33.  
  34.     fd = xp->outStream;
  35.     for (;;) {
  36.         nread = BufferGets(xbuf, sizeof(xbuf), xp);
  37.         if (nread <= 0)
  38.             break;
  39.  
  40.         if (xp->outIsTTY != 0) {
  41.             if (xbuf[nread - 1] == '\n')
  42.                 xbuf[--nread] = '\0';
  43.             MakeStringPrintable(buf2, (unsigned char *) xbuf, sizeof(buf2));
  44.             MultiLinePrintF("%s\n", buf2);
  45.             AddLine(&gRedir, buf2);
  46.             CompleteParse(buf2);
  47.         } else {
  48.             nwrote = Swrite(xp->outStream, xbuf, nread, gNetworkTimeout);
  49.             if (nwrote < 0) {
  50.                 nread = nwrote;
  51.                 break;
  52.             }
  53.             if (xbuf[nread - 1] == '\n')
  54.                 xbuf[--nread] = '\0';
  55.             AddLine(&gRedir, xbuf);
  56.             CompleteParse(xbuf);
  57.         }
  58.  
  59.     }
  60.     return (nread);    /* 0 or -1 */
  61. }    /* ListReceiveProc */
  62.  
  63.  
  64.  
  65.  
  66. int
  67. ListToMemoryReceiveProc(XferSpecPtr xp)
  68. {
  69.     int nread;
  70.     char xbuf[256];
  71.  
  72.     for (;;) {
  73.         nread = BufferGets(xbuf, sizeof(xbuf), xp);
  74.         if (nread <= 0)
  75.             break;
  76.  
  77.         if (xbuf[nread - 1] == '\n')
  78.             xbuf[--nread] = '\0';
  79.         AddLine((LineListPtr) xp->miscPtr, xbuf);
  80.     }
  81.     return (nread);    /* 0 or -1 */
  82. }    /* ListToMemoryReceiveProc */
  83.  
  84.  
  85.  
  86.  
  87. void
  88. ListToMemory(LineListPtr fileList, char *cmd, char *flags, char *what)
  89. {
  90.     XferSpecPtr xp;
  91.  
  92.     fileList->first = fileList->last = NULL;
  93.  
  94.     /* Setup the parameter block for RDataCmd.  Note that we purposely
  95.      * leave the other fields unset, since we don't use them, and
  96.      * being zeroed-out is okay.
  97.      */
  98.     xp = InitXferSpec();
  99.     xp->netMode = kNetReading;
  100.     xp->xProc = ListToMemoryReceiveProc;
  101.     xp->outStream = -1;            /* Not used... */
  102.     xp->miscPtr = fileList;
  103.     
  104.     SETASCII;    /* Directory listings should be in ascii mode. */
  105.     if ((flags == NULL) || (gRmtInfo.isUnix == 0))
  106.         (void) RDataCmd(xp, "%s %s", cmd, what);
  107.     else
  108.         (void) RDataCmd(xp, "%s %s %s", cmd, flags, what);
  109.         
  110.     DoneWithXferSpec(xp);            /* Doesn't dispose miscPtr. */
  111. }    /* ListToMemory */
  112.  
  113.  
  114.  
  115.  
  116. int
  117. FileListReceiveProc(XferSpecPtr xp)
  118. {
  119.     int nread;
  120.     longstring str, buf;
  121.     char *cp;
  122.     int c;
  123.  
  124.     for (;;) {
  125.         nread = BufferGets(buf, sizeof(buf), xp);
  126.         if (nread <= 0)
  127.             break;
  128.         cp = buf;
  129.  
  130.         /* Unix dependency: ls message */
  131.         if (strncmp(buf, "can not access", SZ(14)) == 0) {
  132.             EPrintF("%s", buf);
  133.             return (0L);
  134.         }
  135.  
  136.         cp += nread - 2;    /* Want last char of name, but also have \n. */
  137.         if (gRmtInfo.isUnix) {
  138.             c = *cp;
  139.             switch(c) {
  140.                 /* Unix dependency:  ls -F format. */
  141.                 case '/': c = 'd'; goto subt;
  142.                 case '@': c = 'l'; goto subt;
  143.                 case '*': c = '-'; goto subt;
  144.                 /* No (supported) suffix, so treat it like a plain file. */
  145.                 default:  c = '-'; cp[1] = '\0'; break;
  146.                 subt: *cp = '\0';    /* Remove suffix. */
  147.             }
  148.         } else {
  149.             /* For non unix, just have to assume file. */
  150.             c = '-';
  151.             cp[1] = '\0';
  152.         }
  153.  
  154.         /* Just want the item names, no path prefixes. */
  155.         cp = strrchr(buf, '/');
  156.         if (cp != NULL) {
  157.             cp = Strncpy(str, cp + 1, sizeof(str));
  158.         } else {
  159.             cp = Strncpy(str, buf, sizeof(str));
  160.         }
  161.  
  162.         /* We write the one-char file type, followed by the item name. */
  163.         *buf = c;
  164.         (void) Strncpy(buf + 1, str, sizeof(buf) - 1);
  165.         AddLine((LineListPtr) xp->miscPtr, buf);
  166.     }
  167.     return (nread);    /* 0 or -1 */
  168. }    /* FileListReceiveProc */
  169.  
  170.  
  171.  
  172.  
  173. void GetFileList(LineListPtr fileList, char *what)
  174. {
  175.     XferSpecPtr xp;
  176.  
  177.     fileList->first = fileList->last = NULL;
  178.  
  179.     /* Setup the parameter block for RDataCmd.  Note that we purposely
  180.      * leave the other fields unset, since we don't use them, and
  181.      * being zeroed-out is okay.
  182.      */
  183.     xp = InitXferSpec();
  184.     xp->netMode = kNetReading;
  185.     xp->xProc = FileListReceiveProc;
  186.     xp->outStream = -1;            /* Not used... */
  187.     xp->miscPtr = fileList;
  188.     
  189.     SETASCII;    /* Directory listings should be in ascii mode. */
  190.     if (gRmtInfo.isUnix)
  191.         (void) RDataCmd(xp, "NLST -F %s", what);
  192.     else
  193.         (void) RDataCmd(xp, "NLST %s", what);
  194.     DoneWithXferSpec(xp);            /* Doesn't dispose miscPtr. */
  195. }    /* GetFileList */
  196.  
  197.  
  198.  
  199.  
  200. int DoList(int argc, char **argv, char *lsMode)
  201. {
  202.     char flags[64];
  203.     char flags2[64];
  204.     char *cmd;
  205.     char thingsToList[256];
  206.     int i, wildcards;
  207.     XferSpecPtr xp;
  208.  
  209.     SETASCII;    /* Directory listings should be in ascii mode. */
  210.     thingsToList[0] = '\0';
  211.     flags2[0] = '\0';
  212.     wildcards = 0;
  213.  
  214.     if (STREQ(lsMode, kListLongMode)) {
  215.         cmd = "LIST";
  216.         CompleteSetFlags("-l");
  217.         flags[0] = '\0';
  218.     } else {
  219.         cmd = "NLST";
  220.         STRNCPY(flags, lsMode + 1);
  221.         CompleteSetFlags(lsMode);
  222.     }
  223.  
  224.     /* Go through and find all the things that look like dash-flags,
  225.      * and combine them into one string.  We do the same thing
  226.      * for the items to list, so we'll have to groups of things
  227.      * to hand to RDataCmd.
  228.      */
  229.     for (i=1; i<argc; i++) {
  230.         CompleteSetFlags(argv[i]);
  231.         if (argv[i][0] == '-')
  232.             STRNCAT(flags2, argv[i] + 1);
  233.         else {
  234.             STRNCAT(thingsToList, " ");
  235.             STRNCAT(thingsToList, argv[i]);            
  236.             if (GLOBCHARSINSTR(argv[i]))
  237.                 wildcards = 1;
  238.         }
  239.     }
  240.  
  241.     /* For some unknown reason, traditional servers can do "LIST -t *.tar"
  242.      * but not "NLST -t *.tar."  This kludges around that limitation.
  243.      */
  244.     if ((wildcards) && STREQ(cmd, "NLST")) {
  245.         if (flags2[0] == '\0') {
  246.             /* They didn't give any other flags, so use NLST, but without
  247.              * our usual -CF, but with the wildcard expression.
  248.              */
  249.             flags[0] = '\0';
  250.         } else {
  251.             /* They gave some other flags, but print them a warning, and
  252.              * switch them over to LIST, and retain their flags.
  253.              */
  254.             cmd = "LIST";
  255.             STRNCPY(flags, flags2);
  256.             BoldPrintF("Warning: cannot use both flags and wildcards with ls, using dir instead.\n");
  257.         }
  258.     } else {
  259.         /* Append their flags to the default flags. */
  260.         STRNCAT(flags, flags2);
  261.     }
  262.  
  263.     /* Setup the parameter block for RDataCmd.  Note that we purposely
  264.      * leave the other fields unset, since we don't use them, and
  265.      * being zeroed-out is okay.
  266.      */
  267.     xp = InitXferSpec();
  268.     xp->netMode = kNetReading;
  269.     xp->xProc = ListReceiveProc;
  270.     /* xp->inStream = gDataSocket;  RDataCmd fills this in when it gets it. */
  271.     xp->outStream = gStdout;
  272.     /* The rest of the xp parameters can be left zeroed, since we won't
  273.      * be using them, and progress reports will not be activated, so
  274.      * they won't use them either.
  275.      */
  276.      
  277.     MultiLineInit();
  278.  
  279.     /* Dispose previous buffer, and also be set up for a new one. */
  280.     DisposeLineListContents(&gRedir);
  281.  
  282.     if ((flags[0]) && (gRmtInfo.isUnix != 0))
  283.         (void) RDataCmd(xp, "%s -%s%s", cmd, flags, thingsToList);
  284.     else
  285.         (void) RDataCmd(xp, "%s%s", cmd, thingsToList);
  286.  
  287.     DoneWithXferSpec(xp);
  288.  
  289.     return 0;
  290. }    /* DoList */
  291.  
  292.  
  293.  
  294.  
  295. static
  296. void PDirHandler(void)
  297. {
  298.     alarm(0);
  299.     longjmp(gPDirJmp, 1);
  300. }    /* PDirHandler */
  301.  
  302.  
  303.  
  304.  
  305. /* Do a remote directory listing, to the screen (or file), or
  306.  * through your pager.
  307.  */
  308. int ListCmd(int argc, char **argv)
  309. {
  310.     char *cp;
  311.     char *volatile lsMode;
  312.     volatile int result;
  313.     volatile int pageMode;
  314.     FILE *volatile pager;
  315.     volatile int saved;
  316.     volatile Sig_t si, sp;
  317.  
  318.     result = kNoErr;
  319.     cp = argv[0];
  320.     pageMode = kNoPaging;
  321.     pager = NULL;
  322.     saved = -1;
  323.     lsMode = kListShortMode;
  324.     if (*cp == 'p') {
  325.         /* If the command started with 'p' we should be paging this. */
  326.         if (gPager[0] == '\0') {
  327.             EPrintF("You haven't specified a program to use as a pager.\n");
  328.             EPrintF("You can set this from the preferences screen (prefs command).\n");
  329.             return (-1);
  330.         }
  331.         ++cp;
  332.         pageMode = kPageMode;
  333.         pager = POpen(gPager, "w", 1);
  334.         if (pager == NULL) {
  335.             RestoreScreen(1);
  336.             Error(kDoPerror, "Could not open: %s\n", gPager);
  337.             return (-1);
  338.         }
  339.         
  340.         /* Now replace our own stdout stream with the pager stream,
  341.          * so that writes go to the pager instead.
  342.          */
  343.         saved = (volatile int) gStdout;
  344.         gStdout = fileno((FILE *) pager);
  345.     }
  346.     if (*cp == 'd')
  347.         lsMode = kListLongMode;        /* i.e. "dir" or "pdir" */
  348.  
  349.     CompleteStart(".");
  350.     if (setjmp(gPDirJmp) == 0) {
  351.         sp = SIGNAL(SIGPIPE, PDirHandler);
  352.         si = SIGNAL(SIGINT, PDirHandler);
  353.         result = DoList(argc, argv, lsMode);
  354.     }
  355.     CompleteFinish();
  356.  
  357.     if (pageMode == kPageMode) {
  358.         /* Cleanup the mess we made. */
  359.         (void) SIGNAL(SIGPIPE, SIG_IGN);
  360.         (void) SIGNAL(SIGINT, SIG_IGN);
  361.         if (pager != NULL)
  362.             PClose((FILE *) pager);
  363.         gStdout = saved;
  364.         RestoreScreen(1);
  365.     }
  366.     (void) SIGNAL(SIGPIPE, sp);
  367.     (void) SIGNAL(SIGINT, si);
  368.     return (result);
  369. }    /* ListCmd */
  370.  
  371.  
  372.  
  373.  
  374. static void SigLocalList(void)
  375. {
  376.     alarm(0);
  377.     longjmp(gLocalListJmp, 1);
  378. }    /* SigLocalList */
  379.  
  380.  
  381.  
  382. /* Run ls on the local host.  This is mostly useful for visual mode, where
  383.  * it is troublesome to spawn commands.
  384.  */
  385. int LocalListCmd(int argc, char **argv)
  386. {
  387.     volatile FILE *fp;
  388.     VSig_t si, sp;
  389.     longstring str;
  390.     int i, cf;
  391.  
  392.     si = (VSig_t) kNoSignalHandler;
  393.     sp = (VSig_t) kNoSignalHandler;
  394.  
  395.     str[0] = '\0';
  396.     STRNCPY(str, LS);
  397.     cf = 1;
  398.     if (argc > 1) {
  399.         /* Look for "-l", and turn of -CF if we find it. */
  400.         for (i=1; (i < argc) && (argv[i][0] == '-'); i++) {
  401.             if (strchr(argv[i], 'l') != NULL) {
  402.                 cf = 0;
  403.                 break;
  404.             }
  405.         }
  406.     }
  407.     if (cf)
  408.         STRNCAT(str, " -CF");
  409.     for (i=1; i<argc; i++) {
  410.         STRNCAT(str, " ");
  411.         STRNCAT(str, argv[i]);
  412.     }
  413.  
  414.     DebugMsg("%s\n", str);
  415.     fp = (volatile FILE *) POpen(str, "r", 0);
  416.     if (fp != NULL) {
  417.         if (setjmp(gLocalListJmp) == 0) {
  418.             /* Command was not interrupted. */
  419.             si = SIGNAL(SIGINT, SigLocalList);
  420.             sp = SIGNAL(SIGPIPE, SigLocalList);
  421.             MultiLineInit();
  422.             while (fgets(str, ((int) sizeof(str)) - 1, (FILE *)fp) != NULL)
  423.                 MultiLinePrintF("%s", str);
  424.         }
  425.         (void) SIGNAL(SIGINT, SIG_IGN);
  426.         (void) SIGNAL(SIGPIPE, SIG_IGN);
  427.         PClose((FILE *) fp);
  428.     }
  429.  
  430.     if (si != (VSig_t) kNoSignalHandler)
  431.         (void) SIGNAL(SIGINT, si);
  432.     if (sp != (VSig_t) kNoSignalHandler)
  433.         (void) SIGNAL(SIGPIPE, sp);
  434.     return (kNoErr);
  435. }    /* LocalListCmd */
  436.  
  437.  
  438.  
  439.  
  440. int RedirCmd(int argcUNUSED, char **argv)
  441. {
  442.     LinePtr lp;
  443.     volatile FILE *pager;
  444.     VSig_t si, sp;
  445.  
  446.     si = (VSig_t) kNoSignalHandler;
  447.     sp = (VSig_t) kNoSignalHandler;
  448.  
  449.     if (argv[0][0] == 'p') {
  450.         /* If the command started with 'p' we should be paging this. */
  451.         if (gPager[0] == '\0') {
  452.             EPrintF("You haven't specified a program to use as a pager.\n");
  453.             EPrintF("You can set this from the preferences screen (prefs command).\n");
  454.             return (-1);
  455.         }
  456.         pager = (volatile FILE *) POpen(gPager, "w", 1);
  457.         if (pager == NULL) {
  458.             Error(kDoPerror, "Could not open: %s\n", gPager);
  459.             return (-1);
  460.         }
  461.         if (setjmp(gPDirJmp) == 0) {
  462.             /* Command was not interrupted. */
  463.             sp = SIGNAL(SIGPIPE, PDirHandler);
  464.             si = SIGNAL(SIGINT, PDirHandler);
  465.             for (lp = gRedir.first; lp != NULL; lp = lp->next)
  466.                 fprintf((FILE *) pager, "%s\n", lp->line);
  467.             PClose((FILE *) pager);
  468.             RestoreScreen(1);
  469.         }
  470.     } else {
  471.         MultiLineInit();
  472.         for (lp = gRedir.first; lp != NULL; lp = lp->next)
  473.             MultiLinePrintF("%s\n", lp->line);
  474.     }
  475.     if (si != (VSig_t) kNoSignalHandler)
  476.         (void) SIGNAL(SIGINT, si);
  477.     if (sp != (VSig_t) kNoSignalHandler)
  478.         (void) SIGNAL(SIGPIPE, sp);
  479.     return (kNoErr);
  480. }    /* RedirCmd */
  481.