home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 4 / CDPD_IV.bin / networking / tcpip / amitcp-support / ncftp-1.5.6 / src / rcs / cmds.c,v < prev    next >
Encoding:
Text File  |  1994-06-29  |  40.2 KB  |  2,073 lines

  1. head    14020.15;
  2. access;
  3. symbols
  4.     ORIGINAL:14020.14;
  5. locks; strict;
  6. comment    @ * @;
  7.  
  8.  
  9. 14020.15
  10. date    93.10.10.20.03.06;    author alph;    state Exp;
  11. branches;
  12. next    14020.14;
  13.  
  14. 14020.14
  15. date    93.07.09.11.31.53;    author alph;    state Exp;
  16. branches;
  17. next    ;
  18.  
  19.  
  20. desc
  21. @Original version
  22. @
  23.  
  24.  
  25. 14020.15
  26. log
  27. @amigados changes
  28. @
  29. text
  30. @/* cmds.c */
  31.  
  32. /*  $RCSfile: cmds.c,v $
  33.  *  $Revision: 1.2 $
  34.  *  $Date: 1993/10/02 12:02:56 $
  35.  */
  36.  
  37. #include "sys.h"
  38. #include <sys/types.h>
  39. #include <sys/param.h>
  40.  
  41. #include <sys/wait.h>
  42.  
  43. #include <sys/stat.h>
  44. #include <sys/socket.h>
  45. #include <arpa/ftp.h>
  46. #include <setjmp.h>
  47. #include <signal.h>
  48. #include <string.h>
  49. #include <errno.h>
  50. #include <netdb.h>
  51. #include <netinet/in.h>
  52. #include <arpa/inet.h>
  53. #include <ctype.h>
  54. #include <sys/time.h>
  55. #include <time.h>
  56.  
  57. #ifdef SYSLOG
  58. #    include <syslog.h>
  59. #endif
  60.  
  61. #ifndef NO_UNISTDH
  62. #    include <unistd.h>
  63. #endif
  64.  
  65. #include "util.h"
  66. #include "cmds.h"
  67. #include "main.h"
  68. #include "ftp.h"
  69. #include "ftprc.h"
  70. #include "getpass.h"
  71. #include "glob.h"
  72. #include "open.h"
  73. #include "set.h"
  74. #include "defaults.h"
  75. #include "copyright.h"
  76.  
  77. /* cmds.c globals */
  78. int                    curtype;            /* file transfer type */
  79. char                *typeabbrs = "abiet";
  80. str32                curtypename;        /* name of file transfer type */
  81. int                    verbose;             /* verbosity level of output */
  82. int                    mprompt;            /* interactively prompt on m* cmds */
  83. int                    debug;                /* debugging level */
  84. int                    options;            /* used during socket creation */
  85. int                    macnum;                /* number of defined macros */
  86. int                    paging = 0;
  87. int                    creating = 0;
  88. struct macel        macros[MAXMACROS];
  89. char                *macbuf;            /* holds ALL macros */
  90. jmp_buf                jabort;
  91. char                *mname;                /* name of current m* command */
  92. int                    activemcmd;            /* flag: if != 0, then active multi command */
  93. int                    warnNoLSFlagsWithWildcards = 0;
  94.                                         /* Tells whether the user has been
  95.                                          * warned about not being able to use
  96.                                          * flags with ls when using wildcards.
  97.                                          */
  98. longstring            cwd;                /* current remote directory */
  99. longstring            lcwd;                /* current local directory */
  100. Hostname            lasthostname;        /* name of last host w/ lookup(). */
  101. int                    logged_in = 0;        /* TRUE if connected and user/pw OK. */
  102. int                    is_ls = 0;            /* are we doing an ls?  if so, then
  103.                                            read input into a line buffer
  104.                                            for re-use. */
  105. extern int                    buffer_only;
  106. struct lslist               *lshead = NULL;    /* hold last output from host */
  107. struct lslist               *lstail = NULL;
  108.  
  109. /* cmds.c externs */
  110. extern char                    *globerr, *home, *reply_string;
  111. extern int                    margc, connected, ansi_escapes;
  112. extern int                    code, connected;
  113. extern int                    toatty, fromatty;
  114. extern int                    data, progress_meter, remote_is_unix;
  115. extern int                    parsing_rc, keep_recent;
  116. extern char                    *altarg, *line, *margv[];
  117. extern char                    *globchars;
  118. extern Hostname                hostname;
  119. extern string                progname, pager, anon_password;
  120. extern string                prompt, version, indataline;
  121. extern longstring            logfname;
  122. extern long                    logsize;
  123. extern size_t                xferbufsize;
  124. extern struct servent        serv;
  125. extern struct cmd            cmdtab[];
  126. extern struct userinfo        uinfo;
  127. extern FILE                    *cin, *cout, *logf;
  128. extern int                    Optind;
  129. extern char                    *Optarg;
  130. extern int                    Optind;
  131. extern char                    *Optarg;
  132.  
  133. #ifdef STRICT_PROTOS
  134. extern int gethostname(char *, int), getdomainname(char *, int);
  135. #endif
  136.  
  137.  
  138. struct types types[] = {
  139.     { "ascii",  "A",    TYPE_A, 0 },
  140.     { "binary", "I",    TYPE_I, 0 },
  141.     { "image",  "I",    TYPE_I, 0 },
  142.     { "ebcdic", "E",    TYPE_E, 0 },
  143.     { "tenex",  "L",    TYPE_L, "8" },
  144.     0
  145. };
  146.  
  147.  
  148.  
  149. long GetDateAndSize(char *fName, unsigned long *mod_time)
  150. {
  151.     char *cp, *np;
  152.     string lsline;
  153.     long size = 0L;
  154.     int n, v;
  155.     struct lslist *savedh, *savedt;
  156.     
  157.     *mod_time = 0;
  158.     v = verbose; verbose = V_QUIET;
  159.     is_ls = 1;
  160.     buffer_only = 1;
  161.     savedh = lshead;
  162.     savedt = lstail;
  163.     lshead = NULL;
  164.     (void) recvrequest("LIST", "-", fName, "w");
  165.     is_ls = 0;
  166.     buffer_only = 0;
  167.     verbose = v;
  168.     if (lshead == NULL) {
  169.         PurgeLineBuffer();
  170.         lshead = savedh;
  171.         lstail = savedt;
  172.         goto aa;
  173.     }
  174.     (void) Strncpy(lsline, lshead->string);
  175.     PurgeLineBuffer();
  176.     lshead = savedh;
  177.     lstail = savedt;
  178.  
  179.     if (code >= 400 && code < 500)
  180.         goto aa;
  181.  
  182.     /* See if this line looks like a unix-style ls line. 
  183.      * If so, we can grab the date and size from it.
  184.      */    
  185.     if (strpbrk(lsline, "-dlsbcp") == lsline) {
  186.         /* See if it looks like a typical '-rwxrwxrwx' line. */
  187.         cp = lsline + 1;
  188.         if (*cp != 'r' && *cp != '-')
  189.             goto aa;
  190.         ++cp;
  191.         if (*cp != 'w' && *cp != '-')
  192.             goto aa;
  193.         cp += 2;
  194.         if (*cp != 'r' && *cp != '-')
  195.             goto aa;
  196.  
  197.          /* skip mode, links, owner (and possibly group) */
  198.          for (n = 0; n < 4; n++) {
  199.              np = cp;
  200.              while (*cp != '\0' && !isspace(*cp))
  201.                  cp++;
  202.              while (*cp != '\0' &&  isspace(*cp))
  203.                  cp++;
  204.          }
  205.          if (!isdigit(*cp))
  206.              cp = np;    /* back up (no group) */
  207.          (void) sscanf(cp, "%ld%n", &size, &n);
  208.  
  209.          *mod_time = UnLSDate(cp + n + 1);
  210.  
  211.         if (size < 100) {
  212.             /* May be the size of a link to the file, instead of the file. */
  213.             if ((cp = strstr(lsline, " -> ")) != NULL) {
  214.                 /* Yes, it was a link. */
  215.                 size = GetDateAndSize(cp + 4, mod_time); /* Try the file. */
  216.             }
  217.         }
  218.     }    
  219. aa:
  220.     return (size);
  221. }    /* GetDateAndSize */
  222.  
  223.  
  224.  
  225.  
  226. int _settype(char *typename)
  227. {
  228.     register struct types    *p;
  229.     int                        comret, c;
  230.     string                    cmd;
  231.     char                    *cp;
  232.  
  233.     c = isupper(*typename) ? tolower(*typename) : (*typename);
  234.     if ((cp = index(typeabbrs, c)) != NULL)
  235.         p = &types[(int) (cp - typeabbrs)];
  236.     else {
  237.         (void) printf("%s: unknown type\n", typename);
  238.         return USAGE;
  239.     }
  240.     if (c == 't')
  241.         (void) strcpy(cmd, "TYPE L 8");
  242.     else    
  243.         (void) sprintf(cmd, "TYPE %s", p->t_mode);
  244.     comret = command(cmd);
  245.     if (comret == COMPLETE) {
  246.         (void) Strncpy(curtypename, p->t_name);
  247.         curtype = p->t_type;
  248.     }
  249.     return NOERR;
  250. }    /* _settype */
  251.  
  252.  
  253.  
  254.  
  255. int SetTypeByNumber(int i)
  256. {
  257.     char tstr[4], *tp = tstr, c;
  258.  
  259.     tp[1] = c = 0;
  260.     switch (i) {
  261.         case TYPE_A: c = 'a'; break;
  262.         case TYPE_I: c = 'b'; break;
  263.         case TYPE_E: c = 'e'; break;
  264.         case TYPE_L: c = 't';
  265.     }
  266.     *tp = c;
  267.     return (_settype(tp));
  268. }    /* SetTypeByNumber */
  269.  
  270.  
  271.  
  272.  
  273. /*
  274.  * Set transfer type.
  275.  */
  276. int settype(int argc, char **argv)
  277. {
  278.     int result = NOERR;
  279.  
  280.     if (argc > 2) {
  281.         result = USAGE;
  282.     } else {
  283.         if (argc < 2)
  284.             goto xx;
  285.         result = _settype(argv[1]);
  286.         if (IS_VVERBOSE)
  287. xx:            (void) printf("Using %s mode to transfer files.\n", curtypename);
  288.     }
  289.     return result;
  290. }    /* settype */
  291.  
  292.  
  293.  
  294.  
  295. /*ARGSUSED*/
  296. int setbinary(int argc, char **argv) {    return (_settype("binary")); }
  297. /*ARGSUSED*/
  298. int setascii(int argc, char **argv) {    return (_settype("ascii")); }
  299.  
  300.  
  301.  
  302. /*
  303.  * Send a single file.
  304.  */
  305. int put(int argc, char **argv)
  306. {
  307.     char *cmd;
  308.  
  309.     if (argc == 2) {
  310.         argc++;
  311.         argv[2] = argv[1];
  312.     }
  313.     if (argc < 2)
  314.         argv = re_makeargv("(local-file) ", &argc);
  315.     if (argc < 2) {
  316. usage:
  317.         return USAGE;
  318.     }
  319.     if (argc < 3)
  320.         argv = re_makeargv("(remote-file) ", &argc);
  321.     if (argc < 3) 
  322.         goto usage;
  323.     cmd = (argv[0][0] == 'a') ? "APPE" : "STOR";
  324.     (void) sendrequest(cmd, argv[1], argv[2]);
  325.     return NOERR;
  326. }    /* put */
  327.  
  328.  
  329.  
  330.  
  331. /*
  332.  * Send multiple files.
  333.  */
  334. int mput(int argc, char **argv)
  335. {
  336.     register int i;
  337.     Sig_t oldintr;
  338.     char *tp;
  339.  
  340.     if (argc < 2)
  341.         argv = re_makeargv("(local-files) ", &argc);
  342.     if (argc < 2) {
  343.         return USAGE;
  344.     }
  345.     mname = argv[0];
  346.     activemcmd = 1;
  347.     oldintr = Signal(SIGINT, mabort);
  348.     (void) setjmp(jabort);
  349.     for (i = 1; i < argc; i++) {
  350.         register char **cpp, **gargs;
  351.         char *icopy;
  352.         
  353.         /* Make a copy of the argument, because glob() will just copy
  354.          * the pointer you give it to the glob-arg vector, and blkfree()
  355.          * will want to free each element of the glob-arg vector
  356.          * later.
  357.          */
  358.         if ((icopy = NewString(argv[i])) == NULL)
  359.             break;
  360.         gargs = glob(icopy);
  361.         if (globerr != NULL) {
  362.             (void) printf("%s\n", globerr);
  363.             if (gargs) {
  364.                 blkfree(gargs);
  365.                 Free(gargs);
  366.             }
  367.             continue;
  368.         }
  369.         for (cpp = gargs; cpp && *cpp != NULL; cpp++) {
  370.             if (activemcmd && confirm(argv[0], *cpp)) {
  371.                 tp = *cpp;
  372.                 (void) sendrequest("STOR", *cpp, tp);
  373.                 if (!activemcmd && fromatty) {
  374.                     if (confirm("Continue with","mput")) {
  375.                         activemcmd++;
  376.                     }
  377.                 }
  378.             }
  379.         }
  380.         if (gargs != NULL) {
  381.             blkfree(gargs);
  382.             Free(gargs);
  383.         }
  384.     }
  385.     (void) Signal(SIGINT, oldintr);
  386.     activemcmd = 0;
  387.     return NOERR;
  388. }    /* mput */
  389.  
  390.  
  391.  
  392.  
  393. int rem_glob_one(char *pattern)
  394. {
  395.     int            oldverbose, result = 0;
  396.     char        *cp;
  397.     string        str, tname;
  398.     FILE        *ftemp;
  399.  
  400.     /* Check for wildcard characters. */
  401.     if (*pattern == '|' || strpbrk(pattern, globchars) == NULL)
  402.         return 0;
  403.  
  404.     (void) tmp_name(tname);
  405.     oldverbose = verbose;
  406.     verbose = V_QUIET;
  407.     (void) recvrequest ("NLST", tname, pattern, "w");
  408.     verbose = oldverbose;
  409.     ftemp = fopen(tname, "r");
  410.     if (ftemp == NULL || FGets(str, ftemp) == NULL) {
  411.         if (NOT_VQUIET)
  412.             (void) printf("%s: no match.\n", pattern);
  413.         result = -1;
  414.         goto done;
  415.     }
  416.     if ((cp = index(str, '\n')) != NULL)
  417.         *cp = '\0';
  418.     (void) strcpy(pattern, str);
  419.     cp = FGets(str, ftemp);
  420.     /* It is an error if the pattern matched more than one file. */
  421.     if (cp != NULL) {
  422.         if (NOT_VQUIET)
  423.             (void) printf("?Ambiguous remote file name.\n");
  424.         result = -2;
  425.     }
  426. done:
  427.     if (ftemp != NULL)
  428.         (void) fclose(ftemp);
  429.     (void) unlink(tname);
  430.     return (result);
  431. }    /* rem_glob_one */
  432.  
  433.  
  434.  
  435.  
  436. /*
  437.  * Receive (and maybe page) one file.
  438.  */
  439. int get(int argc, char **argv)
  440. {
  441.     string local_file;
  442.     char remote_file[256];
  443.     char *cp;
  444.     int oldtype = curtype, try_zcat;
  445.     size_t len;
  446.  
  447.     /* paging mode is set if the command name is 'page' or 'more.' */
  448.     paging = (**argv != 'g');
  449.  
  450.     if (argc < 2)
  451.         argv = re_makeargv("(remote-file) ", &argc);
  452.  
  453.     if (argc < 2) {
  454.         return USAGE;
  455.     }
  456.     cp = Strncpy(remote_file, argv[1]);
  457.     argv[1] = cp;
  458.     if (rem_glob_one(argv[1]) < 0)
  459.         return CMDERR;
  460.  
  461.     if (paging) {
  462.         try_zcat = 0;
  463.         len = strlen(remote_file);
  464.  
  465.         if (len > (size_t) 2) {
  466.              if (remote_file[len-2] == '.') {
  467.                 /* Check for .Z files. */
  468.                 if (remote_file[len-1] == 'Z')
  469.                     try_zcat = 1;
  470. #ifdef GZCAT
  471.                 /* Check for .z (gzip) files. */
  472.                 if (remote_file[len-1] == 'z')
  473.                     try_zcat = 1;
  474. #endif    /* GZCAT */
  475.             }
  476.         }
  477.  
  478. #ifdef GZCAT
  479.         if (len > (size_t) 3) {
  480.             /* Check for ".gz" (gzip) files. */
  481.             if (strcmp(remote_file + len - 3, ".gz") == 0)
  482.                 try_zcat = 1;
  483.         }
  484. #endif    /* GZCAT */
  485.  
  486.         /* Run compressed remote files through zcat, then the pager.
  487.          * If GZCAT was defined, we also try paging gzipped files.
  488.          * Note that ZCAT is defined to be GZCAT if you defined
  489.          * GZCAT.
  490.          */
  491.          if (try_zcat) {
  492.             (void) _settype("b");
  493.             (void) sprintf(local_file, "|%s ", ZCAT);
  494.             argv[2] = Strncat(local_file, pager);
  495.         } else {
  496.             /* Try to use text mode for paging, so newlines get converted. */
  497.             (void) _settype("a");
  498.             argv[2] = pager;
  499.         }
  500.     } else {
  501.         /* normal get */
  502.         if (argc == 2) {
  503.             (void) Strncpy(local_file, argv[1]);
  504.             argv[2] = local_file;
  505.         } else {
  506.             if (argc < 3)
  507.                 argv = re_makeargv("(local-file) ", &argc);
  508.             if (argc < 3) 
  509.                 return USAGE;
  510.             if (!globulize(&argv[2])) {
  511.                 return CMDERR;
  512.             }
  513.         }
  514.     }
  515.     (void) recvrequest("RETR", argv[2], argv[1], "w");
  516.     if (paging) {
  517.         (void) SetTypeByNumber(oldtype);    /* Restore it to what it was. */
  518.         paging = 0;
  519.     }
  520.     return NOERR;
  521. }    /* get */
  522.  
  523.  
  524.  
  525. /*ARGSUSED*/
  526. void mabort SIG_PARAMS
  527. {
  528.     (void) printf("\n");
  529.     (void) fflush(stdout);
  530.     if (activemcmd && fromatty) {
  531.         if (confirm("Continue with", mname)) {
  532.             longjmp(jabort,0);
  533.         }
  534.     }
  535.     activemcmd = 0;
  536.     longjmp(jabort,0);
  537. }    /* mabort */
  538.  
  539.  
  540.  
  541.  
  542. /*
  543.  * Get multiple files.
  544.  */
  545. int mget(int argc, char **argv)
  546. {
  547.     char *cp;
  548.     longstring local;
  549.     Sig_t oldintr;
  550.  
  551.     if (argc < 2)
  552.         argv = re_makeargv("(remote-files) ", &argc);
  553.     if (argc < 2) {
  554.         return USAGE;
  555.     }
  556.     mname = argv[0];
  557.     activemcmd = 1;
  558.     oldintr = Signal(SIGINT, mabort);
  559.     (void) setjmp(jabort);
  560.     while ((cp = remglob(argv)) != NULL) {
  561.         if (*cp == '\0') {
  562.             activemcmd = 0;
  563.             continue;
  564.         }
  565.         if (activemcmd && confirm(argv[0], cp)) {
  566.             (void) Strncpy(local, cp);
  567.             (void) recvrequest("RETR", local, cp, "w");
  568.             if (!activemcmd && fromatty) {
  569.                 if (confirm("Continue with","mget")) {
  570.                     activemcmd++;
  571.                 }
  572.             }
  573.         }
  574.     }
  575.     (void) Signal(SIGINT,oldintr);
  576.     activemcmd = 0;
  577.     return NOERR;
  578. }    /* mget */
  579.  
  580.  
  581.  
  582.  
  583. char *remglob(char *argv[])
  584. {
  585.     static FILE            *ftemp = NULL;
  586.     int                    oldverbose, i;
  587.     char                *cp, *mode;
  588.     static string        tmpname, str;
  589.  
  590.     if (!activemcmd) {
  591. xx:
  592.         if (ftemp) {
  593.             (void) fclose(ftemp);
  594.             ftemp = NULL;
  595.             (void) unlink(tmpname);
  596.         }
  597.         return(NULL);
  598.     }
  599.     if (ftemp == NULL) {
  600.         (void) tmp_name(tmpname);
  601.         oldverbose = verbose, verbose = V_QUIET;
  602.         for (mode = "w", i=1; argv[i] != NULL; i++, mode = "a")
  603.             (void) recvrequest ("NLST", tmpname, argv[i], mode);
  604.         verbose = oldverbose;
  605.         ftemp = fopen(tmpname, "r");
  606.         if (ftemp == NULL) {
  607.             (void) printf("Can't find list of remote files (%s), oops.\n", tmpname);
  608.             return (NULL);
  609.         }
  610.     }
  611.     if (FGets(str, ftemp) == NULL) 
  612.         goto xx;
  613.     if ((cp = index(str, '\n')) != NULL)
  614.         *cp = '\0';
  615.     return (str);
  616. }    /* remglob */
  617.  
  618.  
  619. /*
  620.  * Turn on/off printing of server echo's, messages, and statistics.
  621.  */
  622. int setverbose(int argc, char **argv)
  623. {
  624.     if (argc > 1)
  625.         set_verbose(argv[1], 0);
  626.     else set_verbose(argv[1], -1);
  627.     return NOERR;
  628. }    /* setverbose */
  629.  
  630.  
  631.  
  632. /*
  633.  * Toggle interactive prompting
  634.  * during mget, mput, and mdelete.
  635.  */
  636. int setprompt(int argc, char **argv)
  637. {
  638.     if (argc > 1)
  639.         mprompt = StrToBool(argv[1]);
  640.     else mprompt = !mprompt;
  641.     if (IS_VVERBOSE)
  642.         (void) printf("Interactive prompting for m* commmands %s.\n", onoff(mprompt));
  643.     return NOERR;
  644. }    /* setprompt */
  645.  
  646.  
  647.  
  648.  
  649. void fix_options(void)
  650. {
  651.     if (debug)
  652.         options |= SO_DEBUG;
  653.     else
  654.     options &= ~SO_DEBUG;
  655. }   /* fix_options */
  656.  
  657.  
  658. /*
  659.  * Set debugging mode on/off and/or
  660.  * set level of debugging.
  661.  */
  662. int setdebug(int argc, char **argv)
  663. {
  664.     int val;
  665.  
  666.     if (argc > 1) {
  667.         val = StrToBool(argv[1]);
  668.         if (val < 0) {
  669.             (void) printf("%s: bad debugging value.\n", argv[1]);
  670.             return USAGE;
  671.         }
  672.     } else
  673.         val = !debug;
  674.     debug = val;
  675.     fix_options();
  676.     if (IS_VVERBOSE)
  677.         (void) printf("Debugging %s (debug=%d).\n", onoff(debug), debug);
  678.     return NOERR;
  679. }    /* debug */
  680.  
  681.  
  682.  
  683. /*
  684.  * Set current working directory
  685.  * on remote machine.
  686.  */
  687. int cd(int argc, char **argv)
  688. {
  689.     if (argc < 2)
  690.         argv = re_makeargv("(remote-directory) ", &argc);
  691.     if (argc < 2) {
  692.         return USAGE;
  693.     }
  694.     (void) _cd(argv[1]);
  695.     return NOERR;
  696. }    /* cd */
  697.  
  698.  
  699.  
  700.  
  701. int implicit_cd(char *dir)
  702. {
  703.     int i, j = 0;
  704.     
  705.     if (connected) {
  706.         i = verbose;
  707.         /* Special verbosity level that ignores errors and prints other stuff,
  708.          * so you will get just the unknown command message and not an error
  709.          * message from cd.
  710.          */
  711.         verbose = V_IMPLICITCD;
  712.         j = _cd(dir);
  713.         verbose = i;
  714.     }
  715.     return j;
  716. }    /* implicit_cd */
  717.  
  718.  
  719.  
  720.  
  721. int _cd(char *dir)
  722. {
  723.     register char *cp;
  724.     int result = 0;
  725.     string str;
  726.  
  727.     if (dir == NULL)
  728.         goto getrwd;
  729.     /* Won't work because glob really is a ls, so 'cd pu*' will match
  730.      * pub/README, pub/file2, etc.
  731.      *    if (result = rem_glob_one(dir) < 0)
  732.      *    return result;
  733.      */
  734.     if (strncmp(dir, "CDUP", (size_t) 4) == 0)
  735.         (void) Strncpy(str, dir);
  736.     else
  737.         (void) sprintf(str, "CWD %s", dir);
  738.     if (command(str) != 5) {
  739. getrwd:
  740.         (void) quiet_command("PWD");
  741.         cp = rindex(reply_string, '\"');
  742.         if (cp != NULL) {
  743.             result = 1;
  744.             *cp = '\0';
  745.             cp = index(reply_string, '\"');
  746.             if (cp != NULL)
  747.                 (void) Strncpy(cwd, ++cp);
  748.         }
  749.     }
  750.     dbprintf("Current remote directory is \"%s\"\n", cwd);
  751.     return (result);
  752. }    /* _cd */
  753.  
  754.  
  755.  
  756.  
  757. /*
  758.  * Set current working directory
  759.  * on local machine.
  760.  */
  761. int lcd(int argc, char **argv)
  762. {
  763.     if (argc < 2)
  764.         argc++, argv[1] = home;
  765.     if (argc != 2) {
  766.         return USAGE;
  767.     }
  768.     if (!globulize(&argv[1])) {
  769.         return CMDERR;
  770.     }
  771.     if (chdir(argv[1]) < 0) {
  772.         PERROR("lcd", argv[1]);
  773.         return CMDERR;
  774.     }
  775.     (void) get_cwd(lcwd, (int) sizeof(lcwd));
  776.     if (IS_VVERBOSE) 
  777.         (void) printf("Local directory now %s\n", lcwd);
  778.     return NOERR;
  779. }    /* lcd */
  780.  
  781.  
  782.  
  783.  
  784. /*
  785.  * Delete a single file.
  786.  */
  787. int do_delete(int argc, char **argv)
  788. {
  789.     string str;
  790.  
  791.     if (argc < 2)
  792.         argv = re_makeargv("(remote file to delete) ", &argc);
  793.     if (argc < 2) {
  794.         return USAGE;
  795.     }
  796.     if (rem_glob_one(argv[1]) == 0) {
  797.         (void) sprintf(str, "DELE %s", argv[1]);
  798.         (void) command(str);
  799.     }
  800.     return NOERR;
  801. }    /* do_delete */
  802.  
  803.  
  804.  
  805.  
  806. /*
  807.  * Delete multiple files.
  808.  */
  809. int mdelete(int argc, char **argv)
  810. {
  811.     char *cp;
  812.     Sig_t oldintr;
  813.     string str;
  814.  
  815.     if (argc < 2)
  816.         argv = re_makeargv("(remote-files) ", &argc);
  817.     if (argc < 2) {
  818.         return USAGE;
  819.     }
  820.     mname = argv[0];
  821.     activemcmd = 1;
  822.     oldintr = Signal(SIGINT, mabort);
  823.     (void) setjmp(jabort);
  824.     while ((cp = remglob(argv)) != NULL) {
  825.         if (*cp == '\0') {
  826.             activemcmd = 0;
  827.             continue;
  828.         }
  829.         if (activemcmd && confirm(argv[0], cp)) {
  830.             (void) sprintf(str, "DELE %s", cp);
  831.             (void) command(str);
  832.             if (!activemcmd && fromatty) {
  833.                 if (confirm("Continue with", "mdelete")) {
  834.                     activemcmd++;
  835.                 }
  836.             }
  837.         }
  838.     }
  839.     (void) Signal(SIGINT, oldintr);
  840.     activemcmd = 0;
  841.     return NOERR;
  842. }    /* mdelete */
  843.  
  844.  
  845.  
  846.  
  847. /*
  848.  * Rename a remote file.
  849.  */
  850. int renamefile(int argc, char **argv)
  851. {
  852.     string str;
  853.  
  854.     if (argc < 2)
  855.         argv = re_makeargv("(from-name) ", &argc);
  856.     if (argc < 2) {
  857. usage:
  858.         return USAGE;
  859.     }
  860.     if (argc < 3)
  861.         argv = re_makeargv("(to-name) ", &argc);
  862.     if (argc < 3)
  863.         goto usage;
  864.     if (rem_glob_one(argv[1]) < 0)
  865.         return CMDERR;
  866.     (void) sprintf(str, "RNFR %s", argv[1]);
  867.     if (command(str) == CONTINUE) {
  868.         (void) sprintf(str, "RNTO %s", argv[2]);
  869.         (void) command(str);
  870.     }
  871.     return NOERR;
  872. }    /* renamefile */
  873.  
  874.  
  875.  
  876. /*
  877.  * Get a directory listing
  878.  * of remote files.
  879.  */
  880. int ls(int argc, char **argv)
  881. {
  882.     char        *whichcmd, *cp;
  883.     str32        lsflags;
  884.     string        remote, local, str;
  885.     int            listmode, pagemode, i;
  886.  
  887.     PurgeLineBuffer();
  888.     pagemode = 0;
  889.     switch (**argv) {
  890.         case 'p':                            /* pls, pdir, pnlist */
  891.             pagemode = 1;
  892.             listmode = argv[0][1] == 'd';
  893.             break;
  894.         case 'd':                            /* dir */
  895.             listmode = 1;
  896.             break;
  897.         default:                            /* ls, nlist */
  898.             listmode = 0;
  899.     }
  900.     whichcmd = listmode ? "LIST" : "NLST";
  901.  
  902.     (void) strncpy(local, (pagemode ? pager : "-"), sizeof(local));
  903.     remote[0] = lsflags[0] = 0;
  904.     
  905.     /* Possible scenarios:
  906.      *  1.    ls
  907.      *  2.    ls -flags
  908.      *  3.    ls directory
  909.      *  4.  ls -flags >outfile
  910.      *  5.  ls directory >outfile
  911.      *  6.  ls -flags directory
  912.      *  7.  ls -flags directory >outfile
  913.      *
  914.      * Note that using a wildcard will choke with flags.  I.e., don't do
  915.      * "ls -CF *.tar," but instead do "ls *.tar."
  916.      */
  917.  
  918.     for (i=1; i<argc; i++) {
  919.         switch (argv[i][0]) {
  920.             case '-': 
  921.                 /*
  922.                  * If you give more than one set of flags, concat the each
  923.                  * additional set to the first one (without the dash).
  924.                  */
  925.                 (void) strncat(lsflags, (argv[i] + (lsflags[0] == '-')), sizeof(lsflags));
  926.                 break;
  927.             case '|':
  928.             case '>': (void) Strncpy(local, argv[i] + (argv[i][0] == '>')); break;
  929.             default:  
  930.                 cp = argv[i];
  931.                 /*
  932.                  * In case you want to get a remote file called '--README--'
  933.                  * or '>README,' you can use '\--README--' and '\>README.'
  934.                  */
  935.                 if ((cp[1] != 0) && (*cp == '\\'))
  936.                     ++cp;
  937.                 if (remote[0] != 0) {
  938.                     (void) Strncat(remote, " ");
  939.                     (void) Strncat(remote, cp);
  940.                 } else {
  941.                     (void) Strncpy(remote, cp);
  942.                 }
  943.         }    /* end switch */    
  944.     }        /* end loop */
  945.  
  946.     /*
  947.      *    If we are given an ls with some flags, make sure we use 
  948.      *    columnized output (-C) unless one column output (-1) is
  949.      *    specified.
  950.      */
  951.     if (!listmode) {
  952.         if (lsflags[0] != 0) {
  953.             (void) Strncpy(str, lsflags);
  954.             for (cp = str + 1; *cp; cp++)
  955.                 if (*cp == '1')
  956.                     goto aa;
  957.             (void) sprintf(lsflags, "-FC%s", str + 1);
  958.         } else {
  959.             if (remote_is_unix)
  960.                 (void) strcpy(lsflags, "-FC");
  961.         }
  962.         /* As noted above, we can't use -flags if the user gave a
  963.          * wildcard expr.
  964.          */
  965.         if (remote_is_unix && (strpbrk(remote, globchars) != NULL)) {
  966.             lsflags[0] = 0;
  967.             /* Warn the user what's going on. */
  968.             if ((warnNoLSFlagsWithWildcards == 0) && NOT_VQUIET) {
  969.                 (void) fprintf(stderr, "Warning: ls flags disabled with wildcard expressions.\n");
  970.                 warnNoLSFlagsWithWildcards++;
  971.             }
  972.         }
  973.     }
  974.  
  975. aa:    if (strcmp(local, "-") != 0) {
  976.         char *lp = local;
  977.  
  978.         if ((!globulize(&lp)) || ((local[0] != '|') && (!confirm("Output to local-file: ", local)))) {
  979.             return CMDERR;
  980.         } 
  981.         if (lp != local) {
  982.             (void) Strncpy(str, lp);
  983.             (void) Strncpy(local, str);
  984.         }
  985.     }
  986.     is_ls = 1; /* tells getreply() to start saving input to a buffer. */
  987.     (void) Strncpy(str, remote);
  988.     if (lsflags[0] && remote[0])
  989.         (void) sprintf(remote, "%s%c%s", lsflags, LS_FLAGS_AND_FILE, str);
  990.     else
  991.         (void) strncpy(remote, lsflags[0] ? lsflags : str, sizeof(remote));
  992.     (void) recvrequest(whichcmd, local, (remote[0] == 0 ? NULL : remote), "w");
  993.     is_ls=0;
  994.     return NOERR;
  995. }    /* ls */
  996.  
  997.  
  998.  
  999. /*
  1000.  * Do a shell escape
  1001.  */
  1002. /*ARGSUSED*/
  1003. int shell(int argc, char **argv)
  1004. {
  1005. #ifndef NO_FORK
  1006.     int                pid;
  1007.     Sig_t            old1, old2;
  1008.     char            *theShell, *namep;
  1009. #ifndef U_WAIT
  1010.     int                Status;
  1011. #else
  1012.     union wait        Status;
  1013. #endif
  1014.     string            str;
  1015.  
  1016.     old1 = signal (SIGINT, SIG_IGN);
  1017.     old2 = signal (SIGQUIT, SIG_IGN);
  1018.     if ((pid = fork()) == 0) {
  1019.         for (pid = 3; pid < 20; pid++)
  1020.             (void) close(pid);
  1021.         (void) Signal(SIGINT, SIG_DFL);
  1022.         (void) Signal(SIGQUIT, SIG_DFL);
  1023.         if ((theShell = getenv("SHELL")) == NULL)
  1024.             theShell = uinfo.shell;
  1025.         if (theShell == NULL)
  1026.             theShell = "/bin/sh";
  1027.         namep = rindex(theShell, '/');
  1028.         if (namep == NULL)
  1029.             namep = theShell;
  1030.         (void) strcpy(str, "-");
  1031.         (void) strcat(str, ++namep);
  1032.         if (strcmp(namep, "sh") != 0)
  1033.             str[0] = '+';
  1034.         dbprintf ("%s\n", theShell);
  1035.         if (argc > 1)
  1036.             (void) execl(theShell, str, "-c", altarg, (char *)0);
  1037.         else
  1038.             (void) execl(theShell, str, (char *)0);
  1039.         PERROR("shell", theShell);
  1040.         exit(1);
  1041.         }
  1042.     if (pid > 0)
  1043.         while (wait((void *) &Status) != pid)
  1044.             ;
  1045.     (void) Signal(SIGINT, old1);
  1046.     (void) Signal(SIGQUIT, old2);
  1047.     if (pid == -1) {
  1048.         PERROR("shell", "Try again later");
  1049.     }
  1050. #else
  1051.     if( argc > 1)
  1052.         if(system(altarg))
  1053.             PERROR("shell:", altarg);
  1054. #endif
  1055.     return NOERR;
  1056. }    /* shell */
  1057.  
  1058.  
  1059.  
  1060.  
  1061. /*
  1062.  * Send new user information (re-login)
  1063.  */
  1064. int do_user(int argc, char **argv)
  1065. {
  1066.     char            acct[80];
  1067.     int                n, aflag = 0;
  1068.     string            str;
  1069.  
  1070.     if (argc < 2)
  1071.         argv = re_makeargv("(username) ", &argc);
  1072.     if (argc > 4) {
  1073.         return USAGE;
  1074.     }
  1075.     (void) sprintf(str, "USER %s", argv[1]);
  1076.     n = command(str);
  1077.     if (n == CONTINUE) {
  1078.         if (argc < 3 )
  1079.             argv[2] = Getpass("Password: "), argc++;
  1080.         (void) sprintf(str, "PASS %s", argv[2]);
  1081.         n = command(str);
  1082.     }
  1083.     if (n == CONTINUE) {
  1084.         if (argc < 4) {
  1085.             (void) printf("Account: "); (void) fflush(stdout);
  1086.             (void) FGets(acct, stdin);
  1087.             acct[strlen(acct) - 1] = '\0';
  1088.             argv[3] = acct; argc++;
  1089.         }
  1090.         (void) sprintf(str, "ACCT %s", argv[3]);
  1091.         n = command(str);
  1092.         aflag++;
  1093.     }
  1094.     if (n != COMPLETE) {
  1095.         (void) fprintf(stdout, "Login failed.\n");
  1096.         logged_in = 0;
  1097.         return (0);
  1098.     }
  1099.     if (!aflag && argc == 4) {
  1100.         (void) sprintf(str, "ACCT %s", argv[3]);
  1101.         (void) command(str);
  1102.     }
  1103.     logged_in = 1;
  1104.     CheckRemoteSystemType(0);
  1105.     return NOERR;
  1106. }    /* do_user */
  1107.  
  1108.  
  1109.  
  1110.  
  1111. /*
  1112.  * Print working directory.
  1113.  */
  1114. /*ARGSUSED*/
  1115. int pwd(int argc, char **argv)
  1116. {
  1117.     (void) verbose_command("PWD");
  1118.     return NOERR;
  1119. }    /* pwd */
  1120.  
  1121.  
  1122.  
  1123.  
  1124. /*
  1125.  * Make a directory.
  1126.  */
  1127. int makedir(int argc, char **argv)
  1128. {
  1129.     string str;
  1130.  
  1131.     if (argc < 2)
  1132.         argv = re_makeargv("(directory-name) ", &argc);
  1133.     if (argc < 2) {
  1134.         return USAGE;
  1135.     }
  1136.     (void) sprintf(str, "MKD %s", argv[1]);
  1137.     (void) command(str);
  1138.     return NOERR;
  1139. }    /* makedir */
  1140.  
  1141.  
  1142.  
  1143.  
  1144. /*
  1145.  * Remove a directory.
  1146.  */
  1147. int removedir(int argc, char **argv)
  1148. {
  1149.     string str;
  1150.     if (argc < 2)
  1151.         argv = re_makeargv("(directory-name) ", &argc);
  1152.     if (argc < 2) {
  1153.         return USAGE;
  1154.     }
  1155.     if (rem_glob_one(argv[1]) == 0) {
  1156.         (void) sprintf(str, "RMD %s", argv[1]);
  1157.         (void) command(str);
  1158.     }
  1159.     return NOERR;
  1160. }    /* removedir */
  1161.  
  1162.  
  1163.  
  1164.  
  1165. /*
  1166.  * Send a line, verbatim, to the remote machine.
  1167.  */
  1168. int quote(int argc, char **argv)
  1169. {
  1170.     int i, tmpverbose;
  1171.     string str;
  1172.  
  1173.     if (argc < 2)
  1174.         argv = re_makeargv("(command line to send) ", &argc);
  1175.     if (argc < 2) {
  1176.         return USAGE;
  1177.     }
  1178.     str[0] = 0;
  1179.     if (*argv[0] == 's')    /* Command was 'site' instead of 'quote.' */
  1180.         (void) Strncpy(str, "site ");
  1181.     (void) Strncat(str, argv[1]);
  1182.     for (i = 2; i < argc; i++) {
  1183.         (void) Strncat(str, " ");
  1184.         (void) Strncat(str, argv[i]);
  1185.     }
  1186.     tmpverbose = verbose;
  1187.     verbose = V_VERBOSE;
  1188.     if (command(str) == PRELIM) {
  1189.         while (getreply(0) == PRELIM);
  1190.     }
  1191.     verbose = tmpverbose;
  1192.     return NOERR;
  1193. }    /* quote */
  1194.  
  1195.  
  1196.  
  1197.  
  1198. /*
  1199.  * Ask the other side for help.
  1200.  */
  1201. int rmthelp(int argc, char **argv)
  1202. {
  1203.     string str;
  1204.  
  1205.     if (argc == 1) (void) verbose_command("HELP");
  1206.     else {
  1207.         (void) sprintf(str, "HELP %s", argv[1]);
  1208.         (void) verbose_command(str);
  1209.     }
  1210.     return NOERR;
  1211. }    /* rmthelp */
  1212.  
  1213.  
  1214.  
  1215.  
  1216. /*
  1217.  * Terminate session and exit.
  1218.  */
  1219. /*ARGSUSED*/
  1220. int quit(int argc, char **argv)
  1221. {
  1222.     close_up_shop();
  1223.     trim_log();
  1224.     exit(0);
  1225. }    /* quit */
  1226.  
  1227.  
  1228.  
  1229. void close_streams(int wantShutDown)
  1230. {
  1231.     if (cout != NULL) {
  1232.         if (wantShutDown)
  1233.             (void) shutdown(fileno(cout), 1+1);
  1234.         (void) fclose(cout);
  1235.         cout = NULL;
  1236.     }
  1237.     if (cin != NULL) {
  1238.         if (wantShutDown)
  1239.             (void) shutdown(fileno(cin), 1+1);
  1240.         (void) fclose(cin);
  1241.         cin = NULL;
  1242.     }
  1243. }    /* close_streams */
  1244.  
  1245.  
  1246.  
  1247.  
  1248. /*
  1249.  * Terminate session, but don't exit.
  1250.  */
  1251. /*ARGSUSED*/
  1252. int disconnect(int argc, char **argv)
  1253. {
  1254. #ifdef SYSLOG
  1255.     syslog (LOG_INFO, "%s disconnected from %s.", uinfo.username, hostname);
  1256. #endif
  1257.  
  1258.     (void) command("QUIT");
  1259.     close_streams(0);
  1260.     UpdateRecentSitesList(hostname, cwd);
  1261.     hostname[0] = cwd[0] = 0;
  1262.     logged_in = connected = 0;
  1263.     data = -1;
  1264.     macnum = 0;
  1265.     return NOERR;
  1266. }    /* disconnect */
  1267.  
  1268.  
  1269.  
  1270. void
  1271. close_up_shop(void)
  1272. {
  1273.     static int only_once = 0;
  1274.     if (only_once++ > 0)
  1275.         return;
  1276.     if (connected)
  1277.         (void) disconnect(0, NULL);
  1278.     WriteRecentSitesFile();
  1279.     if (logf != NULL) {
  1280.         (void) fclose(logf);
  1281.         logf = NULL;
  1282.     }
  1283. }    /* close_up_shop */
  1284.  
  1285.  
  1286.  
  1287.  
  1288. /*
  1289.  * Glob a local file name specification with
  1290.  * the expectation of a single return value.
  1291.  * Can't control multiple values being expanded
  1292.  * from the expression, we return only the first.
  1293.  */
  1294. int globulize(char **cpp)
  1295. {
  1296.     char **globbed;
  1297.  
  1298.     (void) LocalPath(*cpp);
  1299.     globbed = glob(*cpp);
  1300.     if (globerr != NULL) {
  1301.         (void) printf("%s: %s\n", *cpp, globerr);
  1302.         if (globbed) {
  1303.             blkfree(globbed);
  1304.             Free(globbed);
  1305.         }
  1306.         return (0);
  1307.     }
  1308.     if (globbed) {
  1309.         *cpp = *globbed++;
  1310.         /* don't waste too much memory */
  1311.         if (*globbed) {
  1312.             blkfree(globbed);
  1313.             Free(globbed);
  1314.         }
  1315.     }
  1316.     return (1);
  1317. }    /* globulize */
  1318.  
  1319.  
  1320.  
  1321. /* change directory to perent directory */
  1322. /*ARGSUSED*/
  1323. int cdup(int argc, char **argv)
  1324. {
  1325.     (void) _cd("CDUP");
  1326.     return NOERR;
  1327. }    /* cdup */
  1328.  
  1329.  
  1330. /* show remote system type */
  1331. /*ARGSUSED*/
  1332. int syst(int argc, char **argv)
  1333. {
  1334.     (void) verbose_command("SYST");
  1335.     return NOERR;
  1336. }    /* syst */
  1337.  
  1338.  
  1339.  
  1340.  
  1341. int make_macro(char *name, FILE *fp)
  1342. {
  1343.     char            *tmp;
  1344.     char            *cp;
  1345.     string            str;
  1346.     size_t            len;
  1347.     int                i;
  1348.  
  1349.     if (macnum == MAXMACROS) {
  1350.         (void) fprintf(stderr, "Limit of %d macros have already been defined.\n", MAXMACROS);
  1351.         return -1;
  1352.     }
  1353.  
  1354.     /* Make sure macros have unique names.  If 'init' was attempted to be
  1355.      * redefined, just return, since it was probably cmdOpen() in a redial
  1356.      * mode which tried to define it again.
  1357.      */
  1358.     for (i = 0; i<macnum; i++) {
  1359.         if (strncmp(name, macros[i].mac_name, (size_t)8) == 0) {
  1360.             if (parsing_rc) {
  1361.                 /* Just shut up and read in the macro, but don't save it,
  1362.                  * because we already have it.
  1363.                  */
  1364.                 while ((cp = FGets(str, fp)) != NULL) {
  1365.                     /* See if we have a 'blank' line: just whitespace. */
  1366.                     while (*cp && isspace(*cp)) ++cp;
  1367.                     if (!*cp)
  1368.                         break;
  1369.                 }
  1370.             } else
  1371.                 (void) fprintf(stderr,
  1372.                     "There is already a macro named '%s.'\n", name);
  1373.             return -1;
  1374.         }
  1375.     }
  1376.     (void) strncpy(macros[macnum].mac_name, name, (size_t)8);
  1377.     if (macnum == 0)
  1378.         macros[macnum].mac_start = macbuf;
  1379.     else
  1380.         macros[macnum].mac_start = macros[macnum - 1].mac_end + 1;
  1381.     tmp = macros[macnum].mac_start;
  1382.     while (1) {
  1383.         cp = FGets(str, fp);
  1384.         if (cp == NULL) {
  1385.             /*
  1386.              * If we had started a macro, we will say it is
  1387.              * okay to skip the blank line delimiter if we
  1388.              * are at the EOF.
  1389.              */
  1390.             if (tmp > macros[macnum].mac_start)
  1391.                 goto endmac;
  1392.             (void) fprintf(stderr, "No text supplied for macro \"%s.\"\n", name);
  1393.         }
  1394.         /* see if we have a 'blank' line: just whitespace. */
  1395.         while (*cp && isspace(*cp)) ++cp;
  1396.         if (*cp == '\0') {
  1397.             /* Blank line; end this macro. */
  1398. endmac:
  1399.             macros[macnum++].mac_end = tmp;
  1400.             return 0;
  1401.         }
  1402.         /* Add the text of this line to the macro. */
  1403.         len = strlen(cp) + 1;    /* we need the \0 too. */
  1404.         if (tmp + len >= macbuf + MACBUFLEN) {
  1405.             (void) fprintf(stderr, "Macro \"%s\" not defined -- %d byte buffer exceeded.\n", name, MACBUFLEN);
  1406.             return -1;
  1407.         }
  1408.         (void) strcpy(tmp, cp);
  1409.         tmp += len;
  1410.     }
  1411. }    /* make_macro */
  1412.  
  1413.  
  1414.  
  1415.  
  1416. int macdef(int argc, char **argv)
  1417. {
  1418.     if (argc < 2)
  1419.         argv = re_makeargv("(macro name) ", &argc);
  1420.     if (argc != 2) {
  1421.         (void) domacro(0, NULL);
  1422.         return USAGE;
  1423.     }
  1424.     (void) printf("Enter macro line by line, terminating it with a blank line\n");
  1425.     (void) make_macro(argv[1], stdin);
  1426.     return NOERR;
  1427. }    /* macdef */
  1428.  
  1429.  
  1430.  
  1431.  
  1432. int domacro(int argc, char **argv)
  1433. {
  1434.     register int            i, j;
  1435.     register char            *cp1, *cp2;
  1436.     int                        count = 2, loopflg = 0;
  1437.     string                    str;
  1438.     struct cmd                *c;
  1439.  
  1440.     if (argc < 2) {
  1441.         /* print macros. */
  1442.         if (macnum == 0)
  1443.             (void) printf("No macros defined.\n");
  1444.         else {
  1445.             (void) printf("Current macro definitions:\n");
  1446.             for (i = 0; i < macnum; ++i) {
  1447.                 (void) printf("%s:\n", macros[i].mac_name);
  1448.                 cp1 = macros[i].mac_start;
  1449.                 cp2 = macros[i].mac_end;
  1450.                 while (cp1 < cp2) {
  1451.                     (void) printf("   > ");
  1452.                     while (cp1 < cp2 && *cp1)
  1453.                     {
  1454. #ifndef amigados
  1455.                         putchar(*cp1++);
  1456. #else
  1457.                     /* sideeffects */
  1458.                         putchar(*cp1);
  1459.                         ++cp1;
  1460. #endif
  1461.                     }
  1462.                     ++cp1;
  1463.                 }
  1464.             }
  1465.         }
  1466.         if (argc == 0) return (NOERR);    /* called from macdef(), above. */
  1467.         argv = re_makeargv("(macro to run) ", &argc);
  1468.     }            
  1469.     if (argc < 2) {
  1470.         return USAGE;
  1471.     }
  1472.     for (i = 0; i < macnum; ++i) {
  1473.         if (!strncmp(argv[1], macros[i].mac_name, (size_t) 9)) {
  1474.             break;
  1475.         }
  1476.     }
  1477.     if (i == macnum) {
  1478.         (void) printf("'%s' macro not found.\n", argv[1]);
  1479.         return USAGE;
  1480.     }
  1481.     (void) Strncpy(str, line);
  1482. TOP:
  1483.     cp1 = macros[i].mac_start;
  1484.     while (cp1 != macros[i].mac_end) {
  1485.         while (isspace(*cp1)) {
  1486.             cp1++;
  1487.         }
  1488.         cp2 = line;
  1489.         while (*cp1 != '\0') {
  1490.               switch(*cp1) {
  1491.                    case '\\':
  1492.                  *cp2++ = *++cp1;
  1493.                  break;
  1494.                 case '$':
  1495.                  if (isdigit(*(cp1+1))) {
  1496.                     j = 0;
  1497.                     while (isdigit(*++cp1)) {
  1498.                       j = 10*j +  *cp1 - '0';
  1499.                     }
  1500.                     cp1--;
  1501.                     if (argc - 2 >= j) {
  1502.                     (void) strcpy(cp2, argv[j+1]);
  1503.                     cp2 += strlen(argv[j+1]);
  1504.                     }
  1505.                     break;
  1506.                  }
  1507.                  if (*(cp1+1) == 'i') {
  1508.                     loopflg = 1;
  1509.                     cp1++;
  1510.                     if (count < argc) {
  1511.                        (void) strcpy(cp2, argv[count]);
  1512.                        cp2 += strlen(argv[count]);
  1513.                     }
  1514.                     break;
  1515.                 }
  1516.                 /* intentional drop through */
  1517.                 default:
  1518.                 *cp2++ = *cp1;
  1519.                 break;
  1520.               }
  1521.               if (*cp1 != '\0') {
  1522.                     cp1++;
  1523.               }
  1524.         }
  1525.         *cp2 = '\0';
  1526.         makeargv();
  1527.         c = getcmd(margv[0]);
  1528.         if ((c == (struct cmd *) -1) && !parsing_rc) {
  1529.             (void) printf("?Ambiguous command\n");
  1530.         } else if (c == NULL && !parsing_rc) {
  1531.             (void) printf("?Invalid command\n");
  1532.         } else if (c->c_conn && !connected) {
  1533.             (void) printf("Not connected.\n");
  1534.         } else {
  1535.             if (IS_VVERBOSE)
  1536.                 (void) printf("%s\n",line);
  1537.             if ((*c->c_handler)(margc, margv) == USAGE)
  1538.                 cmd_usage(c);
  1539.             (void) strcpy(line, str);
  1540.             makeargv();
  1541.             argc = margc;
  1542.             argv = margv;
  1543.         }
  1544.         if (cp1 != macros[i].mac_end) {
  1545.             cp1++;
  1546.         }
  1547.     }
  1548.     if (loopflg && ++count < argc) {
  1549.         goto TOP;
  1550.     }
  1551.     return NOERR;
  1552. }    /* domacro */
  1553.  
  1554.  
  1555.  
  1556. /*
  1557.  * get size of file on remote machine
  1558.  */
  1559. int sizecmd(int argc, char **argv)
  1560. {
  1561.     string str;
  1562.  
  1563.     if (argc < 2)
  1564.         argv = re_makeargv("(remote-file) ", &argc);
  1565.     if (argc < 2) {
  1566.         return USAGE;
  1567.     }
  1568.     if (rem_glob_one(argv[1]) == 0) {
  1569.         (void) sprintf(str, "SIZE %s", argv[1]);
  1570.         (void) verbose_command(str);
  1571.     }
  1572.     return NOERR;
  1573. }    /* sizecmd */
  1574.  
  1575.  
  1576.  
  1577.  
  1578. /*
  1579.  * get last modification time of file on remote machine
  1580.  */
  1581. int modtime(int argc, char **argv)
  1582. {
  1583.     int overbose;
  1584.     string str;
  1585.  
  1586.     if (argc < 2)
  1587.         argv = re_makeargv("(remote-file) ", &argc);
  1588.     if (argc < 2) {
  1589.         return USAGE;
  1590.     }
  1591.     if (rem_glob_one(argv[1]) == 0) {
  1592.         overbose = verbose;
  1593.         if (debug == 0)
  1594.             verbose = V_QUIET;
  1595.         (void) sprintf(str, "MDTM %s", argv[1]);
  1596.         if (command(str) == COMPLETE) {
  1597.             int yy, mo, day, hour, min, sec;
  1598.             (void) sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo,
  1599.                 &day, &hour, &min, &sec);
  1600.             /* might want to print this in local time */
  1601.             (void) printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1],
  1602.                 mo, day, yy, hour, min, sec);
  1603.         } else
  1604.             (void) fputs(reply_string, stdout);
  1605.         verbose = overbose;
  1606.     }
  1607.     return NOERR;
  1608. }    /* modtime */
  1609.  
  1610.  
  1611.  
  1612. int lookup(int argc, char **argv)
  1613. {
  1614.     int i, j, by_name, result = NOERR;
  1615.     struct hostent *host;        /* structure returned by gethostbyaddr() */
  1616.     extern int h_errno;
  1617. #ifdef BAD_INETADDR
  1618.     struct in_addr addr;        /* address in host order */
  1619. # define ADDR    addr.s_addr
  1620. #else
  1621.     unsigned long addr;            /* address in host order */
  1622. # define ADDR    addr
  1623. #endif
  1624.  
  1625.     if (argc < 2)
  1626.         argv = re_makeargv("(sitename) ", &argc);
  1627.     if (argc < 2) {
  1628.         return USAGE;
  1629.     }
  1630.  
  1631.      lasthostname[0] = 0;
  1632.     for (i=1; i<argc; i++) {
  1633.         /* does the argument look like an address? */
  1634.         if (4 == sscanf (argv[i], "%d.%d.%d.%d", &j, &j, &j, &j)) {
  1635.             /* ip */
  1636.               addr = inet_addr (argv[i]);
  1637.               if (ADDR == 0xffffffff) {
  1638.                  (void) fprintf(stderr, "## could not convert \"%s\" into a valid IP address.\n", argv[i]);
  1639.                  continue;
  1640.              }
  1641.             host = gethostbyaddr ((char *) &ADDR, 4, AF_INET);
  1642.             by_name = 0;
  1643.         } else {
  1644.             /* name */
  1645.             host = gethostbyname (argv[i]);
  1646.             by_name = 1;
  1647.         }
  1648.         if (host == NULL) {
  1649.             if (NOT_VQUIET) {
  1650.                 /* gethostxxx error */                
  1651.                 if (h_errno == HOST_NOT_FOUND) {
  1652.                      (void) printf("%s: lookup error (%d).\n",
  1653.                          argv[i], h_errno);
  1654.                      result = h_errno;
  1655.                  } else {
  1656.                      (void) printf("%s \"%s\"\n",
  1657.                          (by_name==0 ? "unknown address" : "unknown host"),
  1658.                          argv[i]);
  1659.                      result = 
  1660.                          h_errno != 0 ? h_errno :
  1661.                          -1;
  1662.                 }
  1663.             }
  1664.          } else {
  1665.              if (*host->h_name)
  1666.                  (void) Strncpy(lasthostname, host->h_name);
  1667.             if (NOT_VQUIET) {
  1668.                 (void) printf("%-32s  ", *host->h_name ? host->h_name : "???");
  1669.                 if (*host->h_addr_list) {
  1670.                     unsigned long horder;
  1671.     
  1672.                     horder = ntohl (*(unsigned long *) *(char **)host->h_addr_list);
  1673.                     (void) printf ("%lu.%lu.%lu.%lu\n",
  1674.                         (horder >> 24),
  1675.                         (horder >> 16) & 0xff,
  1676.                         (horder >> 8) & 0xff,
  1677.                         horder & 0xff);
  1678.                 }
  1679.                 else (void) printf("???\n");
  1680.             }
  1681.         }
  1682.     }    /* loop thru all sites */
  1683.     return result;
  1684. }    /* lookup */
  1685.  
  1686.  
  1687.  
  1688.  
  1689. int getlocalhostname(char *host, size_t size)
  1690. {
  1691.     int oldv, r;
  1692.     char *argv[2];
  1693.     char domain[64];
  1694.  
  1695. #ifdef HOSTNAME
  1696.     (void) strncpy(host, HOSTNAME, size);
  1697.     return NOERR;
  1698. #else
  1699.     *host = 0;
  1700.     if ((r = gethostname(host, size)) == 0) {
  1701.         oldv = verbose;
  1702.         verbose = V_QUIET;
  1703.         argv[0] = "lookup";
  1704.         (void) sprintf(line, "lookup %s", host);
  1705.         (void) makeargv();
  1706.         if (lookup(margc, margv) == 0 && lasthostname[0]) {
  1707.             (void) _Strncpy(host, lasthostname, size);
  1708. #ifdef HAS_DOMAINNAME
  1709.             if (index(host, '.') == NULL) {
  1710.                 if (getdomainname(domain + 1, sizeof(domain) - 1) == 0) {
  1711.                     domain[0] = '.';
  1712.                     (void) _Strncat(host, domain, size);
  1713.                 }
  1714.             }
  1715. #endif
  1716.         }
  1717.         verbose = oldv;
  1718.     }
  1719.     return r;
  1720. #endif
  1721. }    /* getlocalhostname */
  1722.  
  1723.  
  1724.  
  1725.  
  1726. /*
  1727.  * show status on remote machine
  1728.  */
  1729. int rmtstatus(int argc, char **argv)
  1730. {
  1731.     string str;
  1732.  
  1733.     if (argc > 1) {
  1734.         (void) sprintf(str, "STAT %s" , argv[1]);
  1735.         (void) verbose_command(str);
  1736.     } else (void) verbose_command("STAT");
  1737.     return NOERR;
  1738. }    /* rmtstatus */
  1739.  
  1740.  
  1741.  
  1742.  
  1743. /*
  1744.  * create an empty file on remote machine.
  1745.  */
  1746. int create(int argc, char **argv)
  1747. {
  1748.     string            str;
  1749.     FILE            *ftemp;
  1750.  
  1751.     if (argc < 2)
  1752.         argv = re_makeargv("(remote-file) ", &argc);
  1753.     if (argc < 2) {
  1754.         return USAGE;
  1755.     }
  1756.     (void) tmp_name(str);
  1757.     ftemp = fopen(str, "w");
  1758.     /* (void) fputc('x', ftemp); */
  1759.     (void) fclose(ftemp);
  1760.     creating = 1;
  1761.     (void) sendrequest("STOR", str, argv[1]);
  1762.     creating = 0;
  1763.     (void) unlink(str);
  1764.     return NOERR;
  1765. }    /* create */
  1766.  
  1767.  
  1768.  
  1769.  
  1770. /* show version info */
  1771. /*ARGSUSED*/
  1772. int show_version(int argc, char **argv)
  1773. {
  1774.     char    *DStrs[48];
  1775.     int        nDStrs = 0, i, j;
  1776.  
  1777.     (void) printf("%-30s %s\n", "NcFTP Version:", version);
  1778.     (void) printf("%-30s %s\n", "Author:",
  1779.         "Mike Gleason, NCEMRSoft (mgleason@@cse.unl.edu).");
  1780.  
  1781. /* Now entering CPP hell... */
  1782. #ifdef __DATE__
  1783.     (void) printf("%-30s %s\n", "Compile Date:", __DATE__);
  1784. #endif
  1785.     (void) printf("%-30s %s (%s)\n", "Operating System:",
  1786. #ifdef System
  1787.     System,
  1788. #else
  1789. #    ifdef unix
  1790.     "UNIX",
  1791. #    else
  1792.     "??",
  1793. #    endif
  1794. #endif
  1795. #ifdef SYSV
  1796.         "SYSV");
  1797. #else
  1798. #    ifdef BSD
  1799.             "BSD");
  1800. #    else
  1801.             "neither BSD nor SYSV?");
  1802. #    endif
  1803. #endif
  1804.  
  1805.     /* Show which CPP symbols were used in compilation. */
  1806. #ifdef __GNUC__
  1807.     DStrs[nDStrs++] = "__GNUC__";
  1808. #endif
  1809. #ifdef RINDEX
  1810.     DStrs[nDStrs++] = "RINDEX";
  1811. #endif
  1812. #ifdef CURSES
  1813.     DStrs[nDStrs++] = "CURSES";
  1814. #endif
  1815. #ifdef HERROR
  1816.     DStrs[nDStrs++] = "HERROR";
  1817. #endif
  1818. #ifdef U_WAIT
  1819.     DStrs[nDStrs++] = "U_WAIT";
  1820. #endif
  1821. #if !defined(HAS_CONST)
  1822. #if defined(NO_CONST) || defined(const)
  1823.     DStrs[nDStrs++] = "NO_CONST";
  1824. #endif
  1825. #endif
  1826. #ifdef GETPASS
  1827.     DStrs[nDStrs++] = "GETPASS";
  1828. #endif
  1829. #ifdef GETCWDSIZET
  1830.     DStrs[nDStrs++] = "GETCWDSIZET";
  1831. #endif
  1832. #ifdef HOSTNAME
  1833.     DStrs[nDStrs++] = "HOSTNAME";
  1834. #endif
  1835. #ifdef SYSDIRH
  1836.     DStrs[nDStrs++] = "SYSDIRH";
  1837. #endif
  1838. #ifdef SYSSELECTH
  1839.     DStrs[nDStrs++] = "SYSSELECTH";
  1840. #endif
  1841. #ifdef TERMH
  1842.     DStrs[nDStrs++] = "TERMH";
  1843. #endif
  1844. #ifdef NO_UNISTDH 
  1845.     DStrs[nDStrs++] = "NO_UNISTDH";
  1846. #endif
  1847. #ifdef NO_STDLIBH
  1848.     DStrs[nDStrs++] = "NO_STDLIBH";
  1849. #endif
  1850. #ifdef SYSLOG 
  1851.     DStrs[nDStrs++] = "SYSLOG";
  1852. #endif
  1853. #ifdef BAD_INETADDR
  1854.     DStrs[nDStrs++] = "BAD_INETADDR";
  1855. #endif
  1856. #ifdef SGTTYB
  1857.     DStrs[nDStrs++] = "SGTTYB";
  1858. #endif
  1859. #ifdef TERMIOS
  1860.     DStrs[nDStrs++] = "TERMIOS";
  1861. #endif
  1862. #ifdef STRICT_PROTOS
  1863.     DStrs[nDStrs++] = "STRICT_PROTOS";
  1864. #endif
  1865. #ifdef dFTP_PORT
  1866.     DStrs[nDStrs++] = "dFTP_PORT";
  1867. #endif
  1868. #ifdef BROKEN_MEMCPY
  1869.     DStrs[nDStrs++] = "BROKEN_MEMCPY";
  1870. #endif
  1871. #ifdef READLINE
  1872.     DStrs[nDStrs++] = "READLINE";
  1873. #endif
  1874. #ifdef GETLINE 
  1875.     DStrs[nDStrs++] = "GETLINE";
  1876. #endif
  1877. #ifdef _POSIX_SOURCE
  1878.     DStrs[nDStrs++] = "_POSIX_SOURCE";
  1879. #endif
  1880. #ifdef NO_TIPS
  1881.     DStrs[nDStrs++] = "NO_TIPS";
  1882. #endif
  1883. #ifdef GZCAT
  1884.     DStrs[nDStrs++] = "GZCAT";
  1885. #endif
  1886. #ifdef NO_UTIMEH 
  1887.     DStrs[nDStrs++] = "NO_UTIMEH";
  1888. #endif
  1889. #ifdef DB_ERRS
  1890.     DStrs[nDStrs++] = "DB_ERRS";
  1891. #endif
  1892. #ifdef NO_VARARGS 
  1893.     DStrs[nDStrs++] = "NO_VARARGS";
  1894. #endif
  1895. #ifdef NO_MKTIME
  1896.     DStrs[nDStrs++] = "NO_MKTIME";
  1897. #endif
  1898. #ifdef NO_STRSTR
  1899.     DStrs[nDStrs++] = "NO_STRSTR";
  1900. #endif
  1901. #ifdef NO_STRFTIME
  1902.     DStrs[nDStrs++] = "NO_STRFTIME";
  1903. #endif
  1904. #ifdef NO_RENAME
  1905.     DStrs[nDStrs++] = "NO_RENAME";
  1906. #endif
  1907. #ifdef TRY_ABOR
  1908.     DStrs[nDStrs++] = "TRY_ABOR";
  1909. #endif
  1910. #ifdef GATEWAY
  1911.     DStrs[nDStrs++] = "GATEWAY";
  1912. #endif
  1913. #ifdef SOCKS
  1914.     DStrs[nDStrs++] = "SOCKS";
  1915. #endif
  1916. #ifdef NO_FORK
  1917.     DStrs[nDStrs++] = "NO_FORK";
  1918. #endif
  1919. #ifdef NO_POPEN
  1920.     DStrs[nDStrs++] = "NO_POPEN";
  1921. #endif
  1922. #ifdef NO_PWSTUFF
  1923.     DStrs[nDStrs++] = "NO_PWSTUFF";
  1924. #endif
  1925. #ifdef NO_GETPID
  1926.     DStrs[nDStrs++] = "NO_GETPID";
  1927. #endif
  1928. #ifdef NO_UTIME
  1929.     DStrs[nDStrs++] = "NO_UTIME";
  1930. #endif
  1931. #ifdef USE_TMPNAM
  1932.     DStrs[nDStrs++] = "USE_TMPNAM";
  1933. #endif
  1934. #ifdef USE_GETCWD
  1935.     DStrs[nDStrs++] = "USE_GETCWD";
  1936. #endif
  1937.  
  1938. /* DONE with #ifdefs for now! */
  1939.  
  1940.     (void) printf ("\nCompile Options:\n");
  1941.     for (i=j=0; i<nDStrs; i++) {
  1942.         if (j == 0)
  1943.             (void) printf("    ");
  1944.         (void) printf("%-15s", DStrs[i]);
  1945.         if (++j == 4) {
  1946.             j = 0;
  1947.             (void) putchar('\n');
  1948.         }
  1949.     }
  1950.     if (j != 0)
  1951.         (void) putchar('\n');
  1952.  
  1953. #ifdef MK
  1954.     (void) printf("\nMK: %s\n", MK);
  1955. #endif /* MK */
  1956.  
  1957.     (void) printf("\nDefaults:\n");
  1958.     (void) printf("\
  1959.     Xfer Buf Size: %8d   Debug: %d   MPrompt: %d   Verbosity: %d\n\
  1960.     Prompt: %s   Pager: %s  ZCat: %s\n\
  1961.     Logname: %s   Logging: %d   Type: %s   Cmd Len: %d\n\
  1962.     Recv Line Len: %d   #Macros: %d   Macbuf: %d  Auto-Binary: %d\n\
  1963.     Recent File: %s   Recent On: %d   nRecents: %d\n\
  1964.     Redial Delay: %d  Anon Open: %d  New Mail Message: \"%s\"\n",
  1965.         MAX_XFER_BUFSIZE, dDEBUG, dMPROMPT, dVERBOSE,
  1966.         dPROMPT, dPAGER, ZCAT,
  1967.         dLOGNAME, dLOGGING, dTYPESTR, CMDLINELEN,
  1968.         RECEIVEDLINELEN, MAXMACROS, MACBUFLEN, dAUTOBINARY,
  1969.         dRECENTF, dRECENT_ON, dMAXRECENTS,
  1970.         dREDIALDELAY, dANONOPEN, NEWMAILMESSAGE
  1971.     );
  1972. #ifdef GATEWAY
  1973.     (void) printf("\
  1974.     Gateway Login: %s\n", dGATEWAY_LOGIN);
  1975. #endif
  1976.     return NOERR;
  1977. }    /* show_version */
  1978.  
  1979.  
  1980.  
  1981. void PurgeLineBuffer(void)
  1982. {
  1983.     register struct lslist *a, *b;
  1984.          
  1985.     for (a = lshead; a != NULL; ) {
  1986.         b = a->next;
  1987.         if (a->string)
  1988.             free(a->string);    /* free string */
  1989.         Free(a);         /* free node */
  1990.         a = b;
  1991.     }
  1992.     lshead = lstail = NULL;
  1993. }    /* PurgeLineBuffer */
  1994.  
  1995.  
  1996.  
  1997.  
  1998. /*ARGSUSED*/
  1999. int ShowLineBuffer(int argc, char **argv)
  2000. {
  2001.     register struct lslist *a = lshead;
  2002.     int pagemode;
  2003.     FILE *fp;
  2004.     Sig_t oldintp;
  2005.  
  2006.     if (a == NULL)
  2007.         return CMDERR;
  2008.     pagemode= (**argv) == 'p' && pager[0] == '|';
  2009. #ifndef NO_POPEN
  2010.     if (pagemode) {
  2011.         fp = popen(pager + 1, "w");
  2012.         if (!fp) {
  2013.             PERROR("ShowLineBuffer", pager + 1);
  2014.             return CMDERR;
  2015.         }
  2016.     } else
  2017. #endif
  2018.         fp = stdout;
  2019.     oldintp = Signal(SIGPIPE, SIG_IGN);
  2020.     while (a) {
  2021.         if (a->string)
  2022.             (void) fprintf(fp, "%s\n", a->string);
  2023.         a = a->next;
  2024.     }
  2025. #ifndef NO_POPEN
  2026.     if (pagemode)
  2027.         (void) pclose(fp);
  2028. #endif
  2029.     if (oldintp)
  2030.         (void) Signal(SIGPIPE, oldintp);
  2031.     return NOERR;
  2032. }    /* ShowLineBuffer */
  2033.  
  2034.  
  2035.  
  2036.  
  2037. /*ARGSUSED*/
  2038. int unimpl(int argc, char **argv)
  2039. {
  2040.     if (!parsing_rc)
  2041.         (void) printf("%s: command not supported. (and probably won't ever be).\n", argv[0]);
  2042.     return (NOERR);
  2043. }    /* unimpl */
  2044.  
  2045. /* eof cmds.c */
  2046. @
  2047.  
  2048.  
  2049. 14020.14
  2050. log
  2051. @checked in with -k by alph at 1993/10/10 19:59:56
  2052. @
  2053. text
  2054. @d4 2
  2055. a5 2
  2056.  *  $Revision: 14020.14 $
  2057.  *  $Date: 93/07/09 11:31:53 $
  2058. d976 1
  2059. d1021 5
  2060. d1424 2
  2061. d1427 6
  2062. d1745 1
  2063. a1745 1
  2064.     char    *DStrs[40];
  2065. d1792 1
  2066. d1796 1
  2067. d1887 21
  2068. d1980 1
  2069. d1988 1
  2070. d1996 1
  2071. d1999 1
  2072. @
  2073.