home *** CD-ROM | disk | FTP | other *** search
/ ftp.ncftp.com / ftp.ncftp.com.zip / ftp.ncftp.com / ncftp / ncftp-1.9.5.tar.gz / ncftp-1.9.5.tar / ncftp-1.9.5 / cmds.c < prev    next >
C/C++ Source or Header  |  1995-10-01  |  47KB  |  2,224 lines

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