home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume34 / ncftp / part01 next >
Text File  |  1992-12-08  |  55KB  |  2,492 lines

  1. Newsgroups: comp.sources.misc
  2. From: mgleason@cse.unl.edu (Mike Gleason)
  3. Subject:  v34i014:  ncftp - Alternative User Interface for FTP, Part01/03
  4. Message-ID: <csm-v34i014=ncftp.150928@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: 9ee3036605bd11603fa19c3d17f5fe55
  6. Date: Mon, 7 Dec 1992 21:10:05 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: mgleason@cse.unl.edu (Mike Gleason)
  10. Posting-number: Volume 34, Issue 14
  11. Archive-name: ncftp/part01
  12. Environment: UNIX, ANSI-C, getopt
  13.  
  14. ncftp - Alternative user interface for FTP
  15. version 1.0 by Mike Gleason, NCEMRSoft.
  16.  
  17. ncftp was created out of disgust with using the regular 'ftp'
  18. command found on many brands of Unix.  People who spend a lot
  19. of time in ftp will want to install ncftp.
  20.  
  21. Features:
  22.  
  23.  * No more typing 'anonymous' and your email address every time
  24.    you want to ftp anonymously.  You don't need to have the
  25.    site in your .netrc.
  26.    
  27.  * No more typing complete site names.  Sites in your .netrc
  28.    can be abbreviated.  Type 'o wuar' to call wuarchive.wustl.edu.
  29.  
  30.  * Use your pager (like 'more') to read remote files (and also
  31.    compressed files).
  32.  
  33.  * Use your pager to view remote directory listings.
  34.  
  35.  * Transfers feature a progress meter.
  36.  
  37.  * Implicit cd.
  38.  
  39.  * Fancy prompts.
  40.  
  41.  * You can keep a log of your actions.  See what the path was of
  42.    that file you downloaded yesterday so you don't have to
  43.    look for it today.
  44.  
  45.  * Built-in mini-nslookup.
  46.  
  47.  * The 'ls' command is ls -CF.  Some ftp's ls was identical to 'dir.'
  48.  
  49.  * You can 'redial' a remote host until you connect.
  50.  
  51.  * Don't need to 'close' a site, just open a new one.
  52.  
  53.  * Don't feel like typing a long filename?  Use a wildcard in single
  54.    file commands like get and page.
  55.  
  56.  * You can create empty remote files.
  57.  
  58.  * Supports 'colon mode', so you can type 'ncftp cse.unl.edu:/pub/foo',
  59.    to copy foo into your current directory.
  60.  
  61.  * You can re-display the last directory listing without getting it
  62.    across the network.
  63.  
  64.  * Detects when new mail arrives.
  65.  
  66.  * ncftp is quieter by default -- who cares if the PORT command was
  67.    successful (if you do, turn verbose on :-).
  68. ------
  69. #! /bin/sh
  70. # This is a shell archive.  Remove anything before this line, then feed it
  71. # into a shell via "sh file" or similar.  To overwrite existing files,
  72. # type "sh file -c".
  73. # Contents:  cmds.c ftpdefs.h sys.h
  74. # Wrapped by kent@sparky on Mon Dec  7 15:06:54 1992
  75. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  76. echo If this archive is complete, you will see the following message:
  77. echo '          "shar: End of archive 1 (of 3)."'
  78. if test -f 'cmds.c' -a "${1}" != "-c" ; then 
  79.   echo shar: Will not clobber existing file \"'cmds.c'\"
  80. else
  81.   echo shar: Extracting \"'cmds.c'\" \(44217 characters\)
  82.   sed "s/^X//" >'cmds.c' <<'END_OF_FILE'
  83. X/* cmds.c */
  84. X
  85. X#include "sys.h"
  86. X#include <sys/types.h>
  87. X#include <sys/param.h>
  88. X
  89. X#ifdef SCO324
  90. X#    include <net/sys/wait.h>
  91. X#else
  92. X#    include <sys/wait.h>
  93. X#endif /* SCO324 */
  94. X
  95. X#include <sys/stat.h>
  96. X#include <sys/socket.h>
  97. X#include <arpa/ftp.h>
  98. X#include <setjmp.h>
  99. X#include <signal.h>
  100. X#include <stdio.h>
  101. X#include <string.h>
  102. X#include <stdlib.h>
  103. X#include <errno.h>
  104. X#include <netdb.h>
  105. X#include <netinet/in.h>
  106. X#include <ctype.h>
  107. X#include <sys/time.h>
  108. X#include <time.h>
  109. X#include <unistd.h>
  110. X#include <termio.h>
  111. X/* #include <sys/ioctl.h> */
  112. X#include "ftpdefs.h"
  113. X#include "defaults.h"
  114. X#include "cmds.h"
  115. X#include "main.h"
  116. X#include "ftp.h"
  117. X#include "ftprc.h"
  118. X#include "glob.h"
  119. X#include "copyright.h"
  120. X
  121. X/* cmds.c globals */
  122. Xint                    curtype;            /* file transfer type */
  123. Xstr32                curtypename;        /* name of file transfer type */
  124. Xint                    verbose;            /* print messages coming back from server */
  125. Xint                    mprompt;            /* interactively prompt on m* cmds */
  126. Xint                    debug;                /* debugging level */
  127. Xint                    options;            /* used during socket creation */
  128. Xint                    macnum;                /* number of defined macros */
  129. Xint                    paging = 0;
  130. Xint                    creating = 0;
  131. Xstruct macel        macros[16];
  132. Xchar                *macbuf;            /* holds ALL macros */
  133. Xjmp_buf                jabort;
  134. Xchar                *mname;                /* name of current m* command */
  135. Xint                    activemcmd;            /* flag: if != 0, then active multi command */
  136. Xstring                cwd;                /* current remote directory */
  137. Xstring                lcwd;                /* current local directory */
  138. Xchar                lasthostname[64];    /* name of last host w/ lookup(). */
  139. Xint                    remote_is_unix;        /* TRUE if remote host is unix. */
  140. Xint                    auto_binary = dAUTOBINARY;    /* If TRUE, set binary each connection. */
  141. X
  142. X#ifdef REDIR
  143. Xint                            is_ls = 0;        /* are we doing an ls?  if so, then buffer */
  144. Xstruct lslist               *lshead = NULL;    /* hold last output from host */
  145. Xstruct lslist               *lstail = NULL;
  146. X#endif
  147. X
  148. X/* cmds.c externs */
  149. Xextern char                    *globerr, *home, *reply_string;
  150. Xextern int                    code, margc, connected, ansi_escapes;
  151. Xextern int                    connected, fromatty, data, want_progress;
  152. Xextern char                    *altarg, *line, *margv[];
  153. Xextern char                    *globchars;
  154. Xextern string                hostname, progname, pager, anon_password;
  155. Xextern string                prompt, logfname, version;
  156. Xextern long                    logsize, eventnumber;
  157. Xextern size_t                xferbufsize;
  158. Xextern struct servent        *sp;
  159. Xextern struct cmd            cmdtab[];
  160. Xextern struct userinfo        uinfo;
  161. Xextern FILE                    *cin, *cout, *logf;
  162. Xextern int                    optind;
  163. Xextern char                    *optarg;
  164. X
  165. Xstruct var vars[] = {
  166. X    { "anon-password",        STR,    0,    anon_password,    (setvarproc) 0    },
  167. X    { "ansi-escapes",        INT,    0,    &ansi_escapes,    (setvarproc) 0    },
  168. X    { "auto-binary",        INT,    0,    &auto_binary,    (setvarproc) 0    },
  169. X    { "debug",                INT,    0,    &debug,            (setvarproc) 0    },
  170. X    { "local-dir",            STR,    0,    lcwd,            set_ldir         },
  171. X    { "logfile",            STR,    0,    logfname,        set_log            },
  172. X    { "logsize",            LONG,    0,    &logsize,        (setvarproc) 0    },
  173. X    { "mprompt",            INT,    0,    &mprompt,        (setvarproc) 0    },
  174. X    { "pager",                STR,    0,    pager + 1,        set_pager        },
  175. X    { "prompt",                STR,    0,    prompt,            set_prompt        },
  176. X    { "progress-reports",    INT,    0,    &want_progress,    (setvarproc) 0    },
  177. X    { "remote-is-unix",        INT,    1,    &remote_is_unix,(setvarproc) 0    },
  178. X    { "type",                STR,    1,    curtypename,    set_type        },
  179. X    { "verbose",            INT,    0,    &verbose,        (setvarproc) 0    }
  180. X};
  181. X
  182. Xstruct types types[] = {
  183. X    { "ascii",  "A",    TYPE_A, 0 },
  184. X    { "binary", "I",    TYPE_I, 0 },
  185. X    { "image",  "I",    TYPE_I, 0 },
  186. X    { "ebcdic", "E",    TYPE_E, 0 },
  187. X    { "tenex",  "L",    TYPE_L, "8" },
  188. X    0
  189. X};
  190. X
  191. X
  192. Xchar **re_makeargv(char *promptstr, int *argc)
  193. X{
  194. X    (void) strcat(line, " ");
  195. X    (void) printf(promptstr);
  196. X    (void) gets(&line[strlen(line)]);
  197. X    (void) makeargv();
  198. X    *argc = margc;
  199. X    return (margv);
  200. X}    /* re_makeargv */
  201. X
  202. X
  203. X
  204. Xchar *get_cwd(char *buf, int size)
  205. X{
  206. X#ifdef SYSV
  207. X    extern char *getcwd(char *, int);
  208. X    return (getcwd(buf, size - 1));
  209. X#else
  210. X    extern char *getwd(char *);
  211. X    return (getwd(buf));
  212. X#endif
  213. X}   /* get_cwd */
  214. X
  215. X/*
  216. X * Connect to peer server and
  217. X * auto-login, if possible.
  218. X */
  219. X
  220. Xint setpeer(int argc, char **argv)
  221. X{
  222. X    char                *path;
  223. X    unsigned int        port;
  224. X    time_t                now;
  225. X    int                    openmode = 1, tmpverbose, opt, hErr;
  226. X    int                    redial_delay = dREDIALDELAY;
  227. X    int                    ignore_rc = 0, dials, max_dials = 1;
  228. X    string                pathname, newhost;
  229. X    char                *cmdname = argv[0];
  230. X
  231. X    port = sp->s_port;
  232. X    optind = 1;
  233. X    while ((opt = getopt(argc, argv, "aiup:rd:g:")) >= 0) {
  234. X        switch (opt) {
  235. X            case 'a': openmode = OPEN_A; break;
  236. X            case 'u': openmode = OPEN_U; break;
  237. X            case 'i': ignore_rc = 1; break;
  238. X            case 'p':
  239. X                port = atoi(optarg);
  240. X                if (port <= 0) {
  241. X                    (void) printf("%s: bad port number (%s).\n", cmdname, optarg);
  242. X                    goto usage;
  243. X                }
  244. X                port = htons(port);
  245. X                break;
  246. X            case 'd': redial_delay = atoi(optarg); break;
  247. X            case 'g': max_dials = atoi(optarg);  break;
  248. X            case 'r': max_dials = -1; break;
  249. X            default:
  250. X            usage:
  251. X                (void) printf("usage: %s [-a | -u] [-i] [-p N] [-r [-d N] [-g N]] hostname[:pathname]\n\
  252. X    -a     : Open anonymously (this is the default).\n\
  253. X    -u     : Open, specify user/password.\n\
  254. X    -i     : Ignore machine entry in your .netrc.\n\
  255. X    -p N   : Use port #N for connection.\n\
  256. X    -r     : \"Redial\" until connected.\n\
  257. X    -d N   : Redial, pausing N seconds between tries.\n\
  258. X    -g N   : Redial, giving up after N tries.\n\
  259. X    :path  : Open site, then retrieve file \"path.\"\n", cmdname);
  260. X                code = -1;
  261. X                return;
  262. X        }
  263. X    }
  264. X
  265. X    if (argv[optind] == NULL)
  266. X        goto usage;
  267. X    (void) Strncpy(newhost, argv[optind]);
  268. X    if (connected) {
  269. X        if (NOT_VQUIET && hostname != NULL)
  270. X            (void) printf("Closing %s...\n", hostname);
  271. X        (void) disconnect(0, NULL);
  272. X    }
  273. X
  274. X    /*
  275. X     *    If we are given something like wuarchive.wustl.edu:/pub/foo,
  276. X     *    try to connect to the site then first try to cd to /pub/foo,
  277. X     *    or if that fails, assume it is a file then try to fetch
  278. X     *    /pub/foo and write foo in the current local directory.
  279. X     */
  280. X    if ((path = index(newhost, ':')) != NULL) {
  281. X        *path++ = 0;
  282. X        (void) Strncpy(pathname, path);
  283. X    }
  284. X
  285. X    GetFullSiteName(newhost);
  286. X    for (dials = 0; max_dials < 0 || dials < max_dials; dials++) {
  287. X        if (dials > 0) {
  288. X            (void) sleep(redial_delay);
  289. X            (void) fprintf(stderr, "Retry Number: %d\n", dials + 1);
  290. X        }
  291. X        hErr = hookup(newhost, port);
  292. X        if (hErr == -2)        /* Recoverable, so we can try again. */
  293. X            continue;
  294. X        else if (hErr == 0) {
  295. X            connected = 1;
  296. X            tmpverbose = verbose;
  297. X            if (debug == 0)
  298. X                verbose = V_QUIET;
  299. X            remote_is_unix = 1;
  300. X            if (command("SYST") == COMPLETE) {
  301. X                if (tmpverbose) {
  302. X                    register char *cp, c;
  303. X                    cp = index(reply_string+4, ' ');
  304. X                    if (cp == NULL)
  305. X                        cp = index(reply_string+4, '\r');
  306. X                    if (cp) {
  307. X                        if (cp[-1] == '.')
  308. X                            cp--;
  309. X                        c = *cp;
  310. X                        *cp = '\0';
  311. X                    }
  312. X    
  313. X                    (void) printf("Remote system type is %s.\n",
  314. X                        reply_string+4);
  315. X                    if (cp)
  316. X                        *cp = c;
  317. X                }
  318. X                remote_is_unix = !strncmp(reply_string + 4, "UNIX", (size_t) 4);
  319. X            }
  320. X    
  321. X            if (auto_binary || path || !strncmp(reply_string, "215 UNIX Type: L8", (size_t) 17)) {
  322. X                _settype("binary");
  323. X                if (tmpverbose > V_TERSE)
  324. X                    (void) printf("Using %s mode to transfer files.\n", curtypename);
  325. X            }
  326. X            if (tmpverbose >= V_ERRS && 
  327. X                !strncmp(reply_string, "215 TOPS20", (size_t) 10)) {
  328. X                (void) printf(
  329. X    "Remember to set tenex mode when transfering _binary_ files from this machine.\n");
  330. X            }
  331. X            verbose = tmpverbose;
  332. X
  333. X            if (!login(newhost, openmode, ignore_rc) || cout == NULL)
  334. X                goto nextdial;        /* error! */
  335. X            if (logf != NULL) {
  336. X                (void) time(&now);
  337. X                (void) fprintf(logf, "%s opened at %s",
  338. X                    hostname,
  339. X                    ctime(&now));
  340. X            }
  341. X
  342. X            /* Freshen 'cwd' variable for the prompt. */
  343. X            (void) _cd(NULL);
  344. X            if (path != NULL) {
  345. X                if (! _cd(pathname)) {
  346. X                    /* Couldn't cd to this path, must be a file then. */
  347. X                    (void) sprintf(line, "get %s", pathname);
  348. X                    makeargv();
  349. X                    (void) get(margc, margv);
  350. X                    /* If we were invoked from the command line, quit
  351. X                     * after we got this file.
  352. X                     */
  353. X                    if (eventnumber == 0L) {
  354. X                        (void) quit(0, NULL);
  355. X                    }
  356. X                }
  357. X            }
  358. X            break;
  359. X            /* end if we are connected */
  360. X        } else {
  361. X            /* Irrecoverable error, so don't bother redialing. */
  362. X            break;
  363. X        }
  364. Xnextdial: continue;
  365. X    }
  366. X}    /* setpeer */
  367. X
  368. X
  369. X/*
  370. X * Set transfer type.
  371. X */
  372. Xint settype(int argc, char **argv)
  373. X{
  374. X    if (argc > 2) {
  375. X        (void) printf("usage: %s [ ascii | binary | ebcdic | image | tenex ]\n", argv[0]);
  376. X        code = -1;
  377. X        return;
  378. X    }
  379. X    code = 0;
  380. X    if (argc < 2) {
  381. Xxx:        (void) printf("Using %s mode to transfer files.\n", curtypename);
  382. X        return;
  383. X    }
  384. X    _settype(argv[1]);
  385. X    if (IS_VVERBOSE)
  386. X        goto xx;
  387. X}    /* settype */
  388. X
  389. X
  390. X
  391. X
  392. Xvoid _settype(char *typename)
  393. X{
  394. X    register struct types    *p;
  395. X    int                        comret, i;
  396. X    string                    cmd;
  397. X
  398. X    switch (tolower(*typename)) {
  399. X        case 'a': i = 0; break;
  400. X        case 'b': i = 1; break;
  401. X        case 'i': i = 2; break;
  402. X        case 'e': i = 3; break;
  403. X        case 't': i = 4;
  404. X            (void) strcpy(cmd, "TYPE L 8");
  405. X            goto xx;
  406. X        default:
  407. X            (void) printf("%s: unknown type\n", typename);
  408. X            code = -1;
  409. X            return;
  410. X    }
  411. X    p = &types[i];
  412. X    (void) sprintf(cmd, "TYPE %s", p->t_mode);
  413. Xxx:    comret = command(cmd);
  414. X    if (comret == COMPLETE) {
  415. X        (void) Strncpy(curtypename, p->t_name);
  416. X        curtype = p->t_type;
  417. X    }
  418. X}    /* _settype */
  419. X
  420. X
  421. X
  422. X
  423. X/*ARGSUSED*/
  424. Xint setbinary(int argc, char **argv) {    _settype("binary");    }
  425. X/*ARGSUSED*/
  426. Xint setascii(int argc, char **argv) {    _settype("ascii");    }
  427. X
  428. X
  429. X
  430. Xvoid set_prompt(char *new, int unset)
  431. X{
  432. X    (void) Strncpy(prompt, (unset || !new || !*new) ? dPROMPT : new);
  433. X    init_prompt();
  434. X}    /* set_prompt */
  435. X
  436. X
  437. X
  438. X
  439. Xvoid set_log(char *fname, int unset)
  440. X{
  441. X    if (logf) {
  442. X        (void) fclose(logf);
  443. X        logf = NULL;
  444. X    }
  445. X    if (!unset && fname && *fname) {
  446. X        (void) Strncpy(logfname, fname);
  447. X        logf = fopen (logfname, "a");
  448. X    }
  449. X}    /* set_log */
  450. X
  451. X
  452. X
  453. X
  454. Xvoid set_pager(char *new, int unset)
  455. X{
  456. X    if (unset)
  457. X        (void) strcpy(pager, "-");
  458. X    else {
  459. X        if (!new)
  460. X            new = dPAGER;
  461. X        if (!*new)
  462. X            (void) strcpy(pager, "-");
  463. X        else if (*new != '-')
  464. X            (void) sprintf(pager, "|%s", (*new == '|' ? new + 1 : new));
  465. X    }
  466. X}    /* set_pager */
  467. X
  468. X
  469. X
  470. X
  471. Xvoid set_type(char *newtype, int unset)
  472. X{
  473. X    int t = verbose;
  474. X    verbose = V_QUIET;
  475. X    if (!connected && t > V_QUIET)
  476. X        (void) printf("Not connected.\n");
  477. X    else
  478. X        _settype(newtype && !unset ? newtype : "image");
  479. X    verbose = t;
  480. X}    /* set_type */
  481. X
  482. X
  483. X
  484. X
  485. Xvoid set_ldir(char *ldir, int unset)
  486. X{
  487. X    int t = verbose;
  488. X    char *argv[2];
  489. X
  490. X    if (ldir && !unset) {
  491. X        verbose = V_QUIET;
  492. X        argv[1] = ldir;
  493. X        lcd(2, argv);
  494. X        verbose = t;
  495. X    }
  496. X}    /* set_ldir */
  497. X
  498. X
  499. X
  500. X
  501. Xint set(int argc, char **argv)
  502. X{
  503. X    int unset, i, c;
  504. X    struct var *v;
  505. X    char *var, *val = NULL;
  506. X
  507. X    if (argc < 2) {
  508. X        /* Show all variables. */
  509. X        for (i=0; i<sizeof(vars)/sizeof(struct var); i++) {
  510. X            (void) printf("%-20s= ", vars[i].name);
  511. X            c = vars[i].type;
  512. X            if (c < 0) c = -c;
  513. X            if (vars[i].conn_required && !connected)
  514. X                (void) printf("(not connected)\n");
  515. X            else switch (c) {
  516. X                case INT:
  517. X                    (void) printf("%d\n", *(int *)vars[i].var); break;
  518. X                case LONG:
  519. X                    (void) printf("%ld\n", *(long *)vars[i].var); break;
  520. X                case STR:
  521. X                    (void) printf("%s\n", (char *) vars[i].var); break;
  522. X            }
  523. X        }
  524. X    } else {
  525. X        unset = argv[0][0] == 'u';
  526. X        var = argv[1];
  527. X        if (argc == 2)
  528. X            val = NULL;
  529. X        else if (argc > 2) {
  530. X            /* could be =, value or just value. */
  531. X            if (*argv[2] == '=') {
  532. X                if (argc > 3)
  533. X                    val = argv[3];
  534. X                else return;    /* can't do 'set var =' */
  535. X            } else
  536. X                val = argv[2];
  537. X        }
  538. X        for (i=0, v=NULL; i<sizeof(vars)/sizeof(struct var); i++) {
  539. X            if (strncmp(vars[i].name, var, sizeof(vars[i].name)) == 0) {
  540. X                v = &vars[i];
  541. X                break;
  542. X            }
  543. X        }
  544. X        if (v == NULL) 
  545. X            (void) fprintf(stderr, "%s: unknown variable.\n", var);
  546. X        else {
  547. X            if (v->conn_required && !connected)
  548. X                (void) fprintf(stderr, "%s: must be connected.\n", var);
  549. X            else if (v->type < 0)    
  550. X                (void) fprintf(stderr, "%s: read-only variable.\n", var);
  551. X            else if (v->proc != (setvarproc) 0)
  552. X                (*v->proc)(val, unset);        /* a custom set proc. */
  553. X            else if (unset) switch(v->type) {
  554. X                case INT:
  555. X                    *(int *) v->var = 0; break;
  556. X                case LONG:
  557. X                    *(long *) v->var = 0; break;
  558. X                case STR:
  559. X                    *(char *) v->var = 0; break;
  560. X            } else {
  561. X                if (val == NULL) switch(v->type) {
  562. X                    /* User just said "set varname" */
  563. X                    case INT:
  564. X                        *(int *) v->var = 1; break;
  565. X                    case LONG:
  566. X                        *(long *) v->var = 1; break;
  567. X                    case STR:
  568. X                        *(char *) v->var = 0; break;
  569. X                } else {
  570. X                    /* User said "set varname = value" */
  571. X                    switch (v->type) {
  572. X                        case INT:
  573. X                            (void) sscanf(val, "%d", (int *) v->var); break;
  574. X                        case LONG:
  575. X                            (void) sscanf(val, "%ld", (long *) v->var); break;
  576. X                        case STR:
  577. X                            (void) strcpy(v->var, val); break;
  578. X                    }
  579. X                }
  580. X            }
  581. X        }
  582. X    }
  583. X}    /* set */
  584. X
  585. X
  586. X
  587. X
  588. X/*
  589. X * Send a single file.
  590. X */
  591. Xint put(int argc, char **argv)
  592. X{
  593. X    char *cmd;
  594. X    char *oldargv1;
  595. X
  596. X    if (argc == 2) {
  597. X        argc++;
  598. X        argv[2] = argv[1];
  599. X    }
  600. X    if (argc < 2)
  601. X        argv = re_makeargv("(local-file) ", &argc);
  602. X    if (argc < 2) {
  603. Xusage:
  604. X        (void) printf("usage:%s local-file remote-file\n", argv[0]);
  605. X        code = -1;
  606. X        return;
  607. X    }
  608. X    if (argc < 3)
  609. X        argv = re_makeargv("(remote-file) ", &argc);
  610. X    if (argc < 3) 
  611. X        goto usage;
  612. X    oldargv1 = argv[1];
  613. X    if (!globulize(&argv[1])) {
  614. X        code = -1;
  615. X        return;
  616. X    }
  617. X    /*
  618. X     * If "globulize" modifies argv[1], and argv[2] is a copy of
  619. X     * the old argv[1], make it a copy of the new argv[1].
  620. X     */
  621. X    if (argv[1] != oldargv1 && argv[2] == oldargv1) {
  622. X        argv[2] = argv[1];
  623. X    }
  624. X    cmd = (argv[0][0] == 'a') ? "APPE" : "STOR";
  625. X    sendrequest(cmd, argv[1], argv[2]);
  626. X}    /* put */
  627. X
  628. X
  629. X
  630. X
  631. X/*
  632. X * Send multiple files.
  633. X */
  634. Xint mput(int argc, char **argv)
  635. X{
  636. X    register int i;
  637. X    void (*oldintr)(int);
  638. X    char *tp;
  639. X
  640. X    if (argc < 2)
  641. X        argv = re_makeargv("(local-files) ", &argc);
  642. X    if (argc < 2) {
  643. X        (void) printf("usage:%s local-files\n", argv[0]);
  644. X        code = -1;
  645. X        return;
  646. X    }
  647. X    mname = argv[0];
  648. X    activemcmd = 1;
  649. X    oldintr = signal(SIGINT, (void (*)(int)) mabort);
  650. X    (void) setjmp(jabort);
  651. X    for (i = 1; i < argc; i++) {
  652. X        register char **cpp, **gargs;
  653. X
  654. X        gargs = glob(argv[i]);
  655. X        if (globerr != NULL) {
  656. X            (void) printf("%s\n", globerr);
  657. X            if (gargs) {
  658. X                blkfree(gargs);
  659. X                free(gargs);
  660. X            }
  661. X            continue;
  662. X        }
  663. X        for (cpp = gargs; cpp && *cpp != NULL; cpp++) {
  664. X            if (activemcmd && confirm(argv[0], *cpp)) {
  665. X                tp = *cpp;
  666. X                sendrequest("STOR", *cpp, tp);
  667. X                if (!activemcmd && fromatty) {
  668. X                    if (confirm("Continue with","mput")) {
  669. X                        activemcmd++;
  670. X                    }
  671. X                }
  672. X            }
  673. X        }
  674. X        if (gargs != NULL) {
  675. X            blkfree(gargs);
  676. X            free(gargs);
  677. X        }
  678. X    }
  679. X    (void) signal(SIGINT, oldintr);
  680. X    activemcmd = 0;
  681. X}    /* mput */
  682. X
  683. X
  684. X
  685. Xint tmp_name(char *str)
  686. X{
  687. X    (void) strcpy(str, "/tmp/ncftpXXXXXX");
  688. X    return (mktemp(str) == NULL);
  689. X}    /* tmp_name */
  690. X
  691. X
  692. X
  693. X
  694. Xint rem_glob_one(char *pattern)
  695. X{
  696. X    int            oldverbose, result = 0;
  697. X    char        *cp;
  698. X    string        str, tname;
  699. X    FILE        *ftemp;
  700. X
  701. X    /* Check for wildcard characters. */
  702. X    if (*pattern == '|' || strpbrk(pattern, globchars) == NULL)
  703. X        return 0;
  704. X
  705. X    (void) tmp_name(tname);
  706. X    oldverbose = verbose;
  707. X    verbose = V_QUIET;
  708. X    recvrequest ("NLST", tname, pattern, "w");
  709. X    verbose = oldverbose;
  710. X    ftemp = fopen(tname, "r");
  711. X    if (ftemp == NULL || FGets(str, ftemp) == NULL) {
  712. X        if (NOT_VQUIET)
  713. X            (void) printf("%s: no match.\n", pattern);
  714. X        result = -1;
  715. X        goto done;
  716. X    }
  717. X    if ((cp = index(str, '\n')) != NULL)
  718. X        *cp = '\0';
  719. X    (void) strcpy(pattern, str);
  720. X    cp = FGets(str, ftemp);
  721. X    /* It is an error if the pattern matched more than one file. */
  722. X    if (cp != NULL) {
  723. X        if (NOT_VQUIET)
  724. X            (void) printf("?Ambiguous remote file name.\n");
  725. X        result = -2;
  726. X    }
  727. Xdone:
  728. X    if (ftemp != NULL)
  729. X        (void) fclose(ftemp);
  730. X    (void) unlink(tname);
  731. X    return (result);
  732. X}    /* rem_glob_one */
  733. X
  734. X
  735. X
  736. X
  737. X/*
  738. X * Receive (and maybe page) one file.
  739. X */
  740. Xint get(int argc, char **argv)
  741. X{
  742. X    string local_file;
  743. X    string remote_file;
  744. X
  745. X    /* paging mode is set if the command name is 'page' or 'more.' */
  746. X    paging = (**argv != 'g');
  747. X
  748. X    if (argc < 2)
  749. X        argv = re_makeargv("(remote-file) ", &argc);
  750. X
  751. X    if (argc < 2) {
  752. X        if (paging)
  753. X            (void) printf("usage: %s remote-file\n", argv[0]);
  754. X        else {
  755. Xgetusage:
  756. X                (void) printf("usage: %s remote-file [local-file]\n", argv[0]);
  757. X        }
  758. X        return;
  759. X    }
  760. X    argv[1] = Strncpy(remote_file, argv[1]);
  761. X    if (rem_glob_one(argv[1]) < 0)
  762. X        return;
  763. X
  764. X    if (paging) {
  765. X        size_t len = strlen(remote_file);
  766. X
  767. X        /* Run compressed remote files through zcat, then the pager. */
  768. X        if (remote_file[len - 1] == 'Z' && remote_file[len - 2] == '.') {
  769. X            _settype("b");
  770. X            (void) sprintf(local_file, "|%s", ZCAT);
  771. X            argv[2] = Strncat(local_file, pager);
  772. X        } else
  773. X            argv[2] = pager;
  774. X    } else {
  775. X        /* normal get */
  776. X        if (argc == 2) {
  777. X            (void) Strncpy(local_file, argv[1]);
  778. X            argv[2] = local_file;
  779. X        } else {
  780. X            if (argc < 3)
  781. X                argv = re_makeargv("(local-file) ", &argc);
  782. X            if (argc < 3) 
  783. X                goto getusage;
  784. X            if (!globulize(&argv[2])) {
  785. X                code = -1;
  786. X                return;
  787. X            }
  788. X        }
  789. X    }
  790. X    recvrequest("RETR", argv[2], argv[1], "w");
  791. X    paging = 0;
  792. X}    /* get */
  793. X
  794. X
  795. X
  796. X/*ARGSUSED*/
  797. Xvoid mabort(int unused)
  798. X{
  799. X    (void) printf("\n");
  800. X    (void) fflush(stdout);
  801. X    if (activemcmd && fromatty) {
  802. X        if (confirm("Continue with", mname)) {
  803. X            longjmp(jabort,0);
  804. X        }
  805. X    }
  806. X    activemcmd = 0;
  807. X    longjmp(jabort,0);
  808. X}    /* mabort */
  809. X
  810. X
  811. X
  812. X
  813. X/*
  814. X * Get multiple files.
  815. X */
  816. Xint mget(int argc, char **argv)
  817. X{
  818. X    char *cp, *tp;
  819. X    void (*oldintr)(int);
  820. X
  821. X    if (argc < 2)
  822. X        argv = re_makeargv("(remote-files) ", &argc);
  823. X    if (argc < 2) {
  824. X        (void) printf("usage:%s remote-files\n", argv[0]);
  825. X        code = -1;
  826. X        return;
  827. X    }
  828. X    mname = argv[0];
  829. X    activemcmd = 1;
  830. X    oldintr = signal(SIGINT,mabort);
  831. X    (void) setjmp(jabort);
  832. X    while ((cp = remglob(argv)) != NULL) {
  833. X        if (*cp == '\0') {
  834. X            activemcmd = 0;
  835. X            continue;
  836. X        }
  837. X        if (activemcmd && confirm(argv[0], cp)) {
  838. X            tp = cp;
  839. X            recvrequest("RETR", tp, cp, "w");
  840. X            if (!activemcmd && fromatty) {
  841. X                if (confirm("Continue with","mget")) {
  842. X                    activemcmd++;
  843. X                }
  844. X            }
  845. X        }
  846. X    }
  847. X    (void) signal(SIGINT,oldintr);
  848. X    activemcmd = 0;
  849. X}    /* mget */
  850. X
  851. X
  852. X
  853. X
  854. Xchar *remglob(char *argv[])
  855. X{
  856. X    static FILE            *ftemp = NULL;
  857. X    int                    oldverbose;
  858. X    char                *cp, *mode;
  859. X    static string        tmpname, str;
  860. X
  861. X    if (!activemcmd) {
  862. Xxx:
  863. X        if (ftemp) {
  864. X            (void) fclose(ftemp);
  865. X            ftemp = NULL;
  866. X            (void) unlink(tmpname);
  867. X        }
  868. X        return(NULL);
  869. X    }
  870. X    if (ftemp == NULL) {
  871. X        (void) tmp_name(tmpname);
  872. X        oldverbose = verbose, verbose = V_QUIET;
  873. X        for (mode = "w"; *++argv != NULL; mode = "a")
  874. X            recvrequest ("NLST", tmpname, *argv, mode);
  875. X        verbose = oldverbose;
  876. X        ftemp = fopen(tmpname, "r");
  877. X        if (ftemp == NULL) {
  878. X            (void) printf("Can't find list of remote files (%s), oops.\n", tmpname);
  879. X            return (NULL);
  880. X        }
  881. X    }
  882. X    if (FGets(str, ftemp) == NULL) 
  883. X        goto xx;
  884. X    if ((cp = index(str, '\n')) != NULL)
  885. X        *cp = '\0';
  886. X    return (str);
  887. X}    /* remglob */
  888. X
  889. X
  890. X
  891. X
  892. Xchar *
  893. Xonoff(int bool)
  894. X{
  895. X    return (bool ? "on" : "off");
  896. X}   /* onoff */
  897. X
  898. X
  899. X
  900. X
  901. Xint
  902. XStrToBool(char *s)
  903. X{
  904. X    register char c;
  905. X
  906. X    c = *s | 32;            /* lcase(*value) */
  907. X    switch (c) {
  908. X        case 'f':           /* false */
  909. X            return (0);
  910. X        case 'o':           /* test for "off" and "on" */
  911. X            c = s[1] | 32;
  912. X            return(c == 'f' ? 0 : 1);
  913. X        case 't':           /* true */
  914. X            return (1);
  915. X        default:            /* 1, 0, -1, other number? */
  916. X            return (atoi(s));
  917. X    }
  918. X}   /* StrToBool */
  919. X
  920. X
  921. X/*
  922. X * Turn on/off printing of server echo's, messages, and statistics.
  923. X */
  924. Xint setverbose(int argc, char **argv)
  925. X{
  926. X    if (argc > 1)
  927. X        verbose = StrToBool(argv[1]);
  928. X    else verbose = !verbose;
  929. X    /* if (verbose > 0) */
  930. X        (void) printf("Verbose mode %s.\n", onoff(verbose));
  931. X    code = verbose;
  932. X}    /* setverbose */
  933. X
  934. X
  935. X
  936. X/*
  937. X * Toggle interactive prompting
  938. X * during mget, mput, and mdelete.
  939. X */
  940. Xint setprompt(int argc, char **argv)
  941. X{
  942. X    if (argc > 1)
  943. X        mprompt = StrToBool(argv[1]);
  944. X    else mprompt = !mprompt;
  945. X    if (IS_VVERBOSE)
  946. X        (void) printf("Interactive prompting for m* commmands %s.\n", onoff(mprompt));
  947. X    code = mprompt;
  948. X}    /* setprompt */
  949. X
  950. X
  951. X/*
  952. X * Set debugging mode on/off and/or
  953. X * set level of debugging.
  954. X */
  955. Xint setdebug(int argc, char **argv)
  956. X{
  957. X    int val;
  958. X
  959. X    if (argc > 1) {
  960. X        val = StrToBool(argv[1]);
  961. X        if (val < 0) {
  962. X            (void) printf("%s: bad debugging value.\n", argv[1]);
  963. X            code = -1;
  964. X            return;
  965. X        }
  966. X    } else
  967. X        val = !debug;
  968. X    debug = val;
  969. X    fix_options();
  970. X    if (IS_VVERBOSE)
  971. X        (void) printf("Debugging %s (debug=%d).\n", onoff(debug), debug);
  972. X    code = debug > 0;
  973. X}    /* debug */
  974. X
  975. X
  976. X
  977. Xvoid fix_options(void)
  978. X{
  979. X    if (debug)
  980. X        options |= SO_DEBUG;
  981. X    else
  982. X        options &= ~SO_DEBUG;
  983. X}    /* fix_options */
  984. X
  985. X
  986. X
  987. X/*
  988. X * Set current working directory
  989. X * on remote machine.
  990. X */
  991. Xint cd(int argc, char **argv)
  992. X{
  993. X    if (argc < 2)
  994. X        argv = re_makeargv("(remote-directory) ", &argc);
  995. X    if (argc < 2) {
  996. X        (void) printf("usage:%s remote-directory\n", argv[0]);
  997. X        code = -1;
  998. X        return;
  999. X    }
  1000. X    (void) _cd(argv[1]);
  1001. X}    /* cd */
  1002. X
  1003. X
  1004. X
  1005. X
  1006. Xint implicit_cd(char *dir)
  1007. X{
  1008. X    int i, j = 0;
  1009. X    
  1010. X    if (connected) {
  1011. X        i = verbose;
  1012. X        verbose = V_QUIET;
  1013. X        j = _cd(dir);
  1014. X        verbose = i;
  1015. X    }
  1016. X    return j;
  1017. X}    /* implicit_cd */
  1018. X
  1019. X
  1020. X
  1021. X
  1022. Xint _cd(char *dir)
  1023. X{
  1024. X    register char *cp;
  1025. X    int result = 0, tmpverbose;
  1026. X    string str;
  1027. X
  1028. X    if (dir == NULL)
  1029. X        goto getrwd;
  1030. X    if (result = rem_glob_one(dir) < 0)
  1031. X        return result;
  1032. X    if (strncmp(dir, "CDUP", (size_t) 4) == 0)
  1033. X        (void) Strncpy(str, dir);
  1034. X    else
  1035. X        (void) sprintf(str, "CWD %s", dir);
  1036. X    if (command(str) != 5) {
  1037. Xgetrwd:
  1038. X        /* (void) Strncpy(cwd, dir); */
  1039. X        tmpverbose = verbose; verbose = V_QUIET;
  1040. X        (void) command("PWD");
  1041. X        verbose = tmpverbose;
  1042. X        cp = rindex(reply_string, '\"');
  1043. X        if (cp != NULL) {
  1044. X            result = 1;
  1045. X            *cp = '\0';
  1046. X            cp = index(reply_string, '\"');
  1047. X            if (cp != NULL)
  1048. X                (void) Strncpy(cwd, ++cp);
  1049. X        }
  1050. X    }
  1051. X    if (debug > 0)
  1052. X        (void) printf("---> Current remote directory is \"%s\"\n", cwd);
  1053. X    return (result);
  1054. X}    /* _cd */
  1055. X
  1056. X
  1057. X
  1058. X
  1059. X/*
  1060. X * Set current working directory
  1061. X * on local machine.
  1062. X */
  1063. Xint lcd(int argc, char **argv)
  1064. X{
  1065. X    if (argc < 2)
  1066. X        argc++, argv[1] = home;
  1067. X    if (argc != 2) {
  1068. X        (void) printf("usage:%s local-directory\n", argv[0]);
  1069. X        code = -1;
  1070. X        return;
  1071. X    }
  1072. X    if (!globulize(&argv[1])) {
  1073. X        code = -1;
  1074. X        return;
  1075. X    }
  1076. X    if (chdir(argv[1]) < 0) {
  1077. X        Perror(argv[1]);
  1078. X        code = -1;
  1079. X        return;
  1080. X    }
  1081. X    (void) get_cwd(lcwd, (int) sizeof(lcwd));
  1082. X    if (IS_VVERBOSE) 
  1083. X        (void) printf("Local directory now %s\n", lcwd);
  1084. X    code = 0;
  1085. X}    /* lcd */
  1086. X
  1087. X
  1088. X
  1089. X
  1090. X/*
  1091. X * Delete a single file.
  1092. X */
  1093. Xint do_delete(int argc, char **argv)
  1094. X{
  1095. X    string str;
  1096. X
  1097. X    if (argc < 2)
  1098. X        argv = re_makeargv("(remote file to delete) ", &argc);
  1099. X    if (argc < 2) {
  1100. X        (void) printf("usage:%s remote-file\n", argv[0]);
  1101. X        code = -1;
  1102. X        return;
  1103. X    }
  1104. X    if (rem_glob_one(argv[1]) == 0) {
  1105. X        (void) sprintf(str, "DELE %s", argv[1]);
  1106. X        (void) command(str);
  1107. X    }
  1108. X}    /* do_delete */
  1109. X
  1110. X
  1111. X
  1112. X
  1113. X/*
  1114. X * Delete multiple files.
  1115. X */
  1116. Xint mdelete(int argc, char **argv)
  1117. X{
  1118. X    char *cp;
  1119. X    void (*oldintr)(int);
  1120. X    string str;
  1121. X
  1122. X    if (argc < 2)
  1123. X        argv = re_makeargv("(remote-files) ", &argc);
  1124. X    if (argc < 2) {
  1125. X        (void) printf("usage:%s remote-files\n", argv[0]);
  1126. X        code = -1;
  1127. X        return;
  1128. X    }
  1129. X    mname = argv[0];
  1130. X    activemcmd = 1;
  1131. X    oldintr = signal(SIGINT, mabort);
  1132. X    (void) setjmp(jabort);
  1133. X    while ((cp = remglob(argv)) != NULL) {
  1134. X        if (*cp == '\0') {
  1135. X            activemcmd = 0;
  1136. X            continue;
  1137. X        }
  1138. X        if (activemcmd && confirm(argv[0], cp)) {
  1139. X            (void) sprintf(str, "DELE %s", cp);
  1140. X            (void) command(str);
  1141. X            if (!activemcmd && fromatty) {
  1142. X                if (confirm("Continue with", "mdelete")) {
  1143. X                    activemcmd++;
  1144. X                }
  1145. X            }
  1146. X        }
  1147. X    }
  1148. X    (void) signal(SIGINT, oldintr);
  1149. X    activemcmd = 0;
  1150. X}    /* mdelete */
  1151. X
  1152. X
  1153. X
  1154. X
  1155. X/*
  1156. X * Rename a remote file.
  1157. X */
  1158. Xint renamefile(int argc, char **argv)
  1159. X{
  1160. X    string str;
  1161. X
  1162. X    if (argc < 2)
  1163. X        argv = re_makeargv("(from-name) ", &argc);
  1164. X    if (argc < 2) {
  1165. Xusage:
  1166. X        (void) printf("%s from-name to-name\n", argv[0]);
  1167. X        code = -1;
  1168. X        return;
  1169. X    }
  1170. X    if (argc < 3)
  1171. X        argv = re_makeargv("(to-name) ", &argc);
  1172. X    if (argc < 3)
  1173. X        goto usage;
  1174. X    if (rem_glob_one(argv[1]) < 0)
  1175. X        return;
  1176. X    (void) sprintf(str, "RNFR %s", argv[1]);
  1177. X    if (command(str) == CONTINUE) {
  1178. X        (void) sprintf(str, "RNTO %s", argv[1]);
  1179. X        (void) command(str);
  1180. X    }
  1181. X}    /* renamefile */
  1182. X
  1183. X
  1184. X
  1185. X/*
  1186. X * Get a directory listing
  1187. X * of remote files.
  1188. X */
  1189. Xint ls(int argc, char **argv)
  1190. X{
  1191. X    char        *whichcmd, *remote, *local, *cp;
  1192. X    str32        lsflags;
  1193. X    string        zpager;
  1194. X    int            listmode, pagemode, defltFlags;
  1195. X
  1196. X#ifdef REDIR
  1197. X    register struct lslist *a, *b;
  1198. X    for (a = lshead; a != NULL; ) {
  1199. X        b = a->next;
  1200. X        if (a->string)
  1201. X            free(a->string);    /* free string */
  1202. X        free(a);                  /* free node */
  1203. X        a = b;
  1204. X    }
  1205. X    lshead = lstail = NULL;
  1206. X#endif
  1207. X
  1208. X    pagemode = 0;
  1209. X    switch (**argv) {
  1210. X        case 'p':                            /* pls, pdir, pnlist */
  1211. X            pagemode = 1;
  1212. X            listmode = argv[0][1] == 'd';
  1213. X            break;
  1214. X        case 'd':                            /* dir */
  1215. X            listmode = 1;
  1216. X            break;
  1217. X        default:                            /* ls, nlist */
  1218. X            listmode = 0;
  1219. X    }
  1220. X    remote = NULL;
  1221. X    if (listmode) {        /* dir */
  1222. X        whichcmd = "LIST";
  1223. X    } else {                    /* ls or nlist */
  1224. X        whichcmd = "NLST";
  1225. X        if (remote_is_unix) {
  1226. X            remote = "-CF";
  1227. X            defltFlags = 1;
  1228. X        } else {
  1229. X            defltFlags = 0;
  1230. X        }    
  1231. X    }
  1232. X
  1233. X    if (pagemode) {
  1234. X        size_t len = strlen(remote);
  1235. X        if (remote[len - 1] == 'Z' && remote[len - 2] == '.') {
  1236. X            /* run uncompress first, then pipe through pager. */
  1237. X            (void) Strncpy(zpager, "|uncompress ");
  1238. X            (void) Strncat(zpager, pager);
  1239. X            local = zpager;
  1240. X        } else 
  1241. X            local = pager;
  1242. X    } else
  1243. X        local = "-";
  1244. X    
  1245. X    /* Possible scenarios:
  1246. X        1.    ls
  1247. X        2.    ls -flags
  1248. X        3.    ls directory
  1249. X        4.  ls -flags >outfile
  1250. X        5.    ls directory >outfile */
  1251. X            
  1252. X    if (argc > 1) {
  1253. X        remote = argv[1];
  1254. X        defltFlags = 0;
  1255. X    }
  1256. X    if (argc > 2)
  1257. X        local = argv[2];
  1258. X    if (argc > 3) {
  1259. X        (void) printf("usage: %s [remote-directory | flags] [local-file]\n", argv[0]);
  1260. X        code = -1;
  1261. X        return;
  1262. X    }
  1263. X
  1264. X    /*
  1265. X     *    If we are given an ls with some flags, make sure we use 
  1266. X     *    columnized output (-C) unless one column output (-1) is
  1267. X     *    specified.
  1268. X     */
  1269. X    if (!listmode && !defltFlags && remote != NULL && *remote == '-')  {
  1270. X        for (cp = remote + 1; *cp; cp++)
  1271. X            if (*cp == '1')
  1272. X                goto aa;
  1273. X        (void) sprintf(lsflags, "-CF%s", remote + 1);
  1274. X        remote = lsflags;
  1275. X    }
  1276. Xaa:    if (strcmp(local, "-") != 0 && !globulize(&local)) {
  1277. X        /* if #2 is not stdout, but there was a glob error, barf. */
  1278. X        code = -1;
  1279. X        return;
  1280. X    }
  1281. X    if (strcmp(local, "-") != 0 && *local != '|')
  1282. X        if (!globulize(&local) || !confirm("output to local-file:", local)) {
  1283. X            code = -1;
  1284. X            return;
  1285. X    }
  1286. X#ifdef REDIR
  1287. X    is_ls=1; /* tells getreply() to buffer output on a lshead list */
  1288. X#endif
  1289. X    recvrequest(whichcmd, local, remote, "w");
  1290. X#ifdef REDIR
  1291. X    is_ls=0;
  1292. X#endif
  1293. X}    /* ls */
  1294. X
  1295. X
  1296. X
  1297. X
  1298. X/*
  1299. X * Get a directory listing
  1300. X * of multiple remote files.
  1301. X */
  1302. Xint mls(int argc, char **argv)
  1303. X{
  1304. X    char *cmd, mode[1], *dest;
  1305. X    int i;
  1306. X    void (*oldintr)(int);
  1307. X
  1308. X    if (argc < 2)
  1309. X        argv = re_makeargv("(remote-files) ", &argc);
  1310. X    if (argc < 3)
  1311. X        argv = re_makeargv("(local-file) ", &argc);
  1312. X    if (argc < 3) {
  1313. X        (void) printf("usage:%s remote-files local-file\n", argv[0]);
  1314. X        code = -1;
  1315. X        return;
  1316. X    }
  1317. X    dest = argv[argc - 1];
  1318. X    argv[argc - 1] = NULL;
  1319. X    if (strcmp(dest, "-") && *dest != '|')
  1320. X        if (!globulize(&dest) || !confirm("output to local-file:", dest)) {
  1321. X            code = -1;
  1322. X            return;
  1323. X    }
  1324. X    cmd = argv[0][1] != 'd' ? "NLST" : "LIST";
  1325. X    mname = argv[0];
  1326. X    activemcmd = 1;
  1327. X    oldintr = signal(SIGINT, mabort);
  1328. X    (void) setjmp(jabort);
  1329. X    for (i = 1; activemcmd && i < argc-1; ++i) {
  1330. X        *mode = (i == 1) ? 'w' : 'a';
  1331. X        recvrequest(cmd, dest, argv[i], mode);
  1332. X        if (!activemcmd && fromatty) {
  1333. X            if (confirm("Continue with", argv[0])) {
  1334. X                activemcmd++;
  1335. X            }
  1336. X        }
  1337. X    }
  1338. X    (void) signal(SIGINT, oldintr);
  1339. X    activemcmd = 0;
  1340. X}    /* mls */
  1341. X
  1342. X
  1343. X
  1344. X
  1345. X/*
  1346. X * Do a shell escape
  1347. X */
  1348. X/*ARGSUSED*/
  1349. Xint shell(int argc, char **argv)
  1350. X{
  1351. X    int                pid;
  1352. X    void            (*old1)(int), (*old2)(int);
  1353. X    char            *theShell, *namep;
  1354. X#ifndef U_WAIT
  1355. X    long            Status;
  1356. X#else
  1357. X    union wait        Status;
  1358. X#endif
  1359. X    string            str;
  1360. X
  1361. X    old1 = signal (SIGINT, SIG_IGN);
  1362. X    old2 = signal (SIGQUIT, SIG_IGN);
  1363. X    if ((pid = fork()) == 0) {
  1364. X        for (pid = 3; pid < 20; pid++)
  1365. X            (void) close(pid);
  1366. X        (void) signal(SIGINT, SIG_DFL);
  1367. X        (void) signal(SIGQUIT, SIG_DFL);
  1368. X        if ((theShell = getenv("SHELL")) == NULL)
  1369. X            theShell = uinfo.shell;
  1370. X        if (theShell == NULL)
  1371. X            theShell = "/bin/sh";
  1372. X        namep = rindex(theShell, '/');
  1373. X        if (namep == NULL)
  1374. X            namep = theShell;
  1375. X        (void) strcpy(str, "-");
  1376. X        (void) strcat(str, ++namep);
  1377. X        if (strcmp(namep, "sh") != 0)
  1378. X            str[0] = '+';
  1379. X        if (debug) {
  1380. X            (void) printf ("%s\n", theShell);
  1381. X            (void) fflush (stdout);
  1382. X        }
  1383. X        if (argc > 1)
  1384. X            (void) execl(theShell, str, "-c", altarg, (char *)0);
  1385. X        else
  1386. X            (void) execl(theShell, str, (char *)0);
  1387. X        Perror(theShell);
  1388. X        code = -1;
  1389. X        exit(1);
  1390. X        }
  1391. X    if (pid > 0)
  1392. X        while (wait((void *) &Status) != pid)
  1393. X            ;
  1394. X    (void) signal(SIGINT, old1);
  1395. X    (void) signal(SIGQUIT, old2);
  1396. X    if (pid == -1) {
  1397. X        Perror("Try again later");
  1398. X        code = -1;
  1399. X    } else code = 0;
  1400. X    return (0);
  1401. X}    /* shell */
  1402. X
  1403. X
  1404. X
  1405. X
  1406. X/*
  1407. X * Send new user information (re-login)
  1408. X */
  1409. Xint do_user(int argc, char **argv)
  1410. X{
  1411. X    char            acct[80];
  1412. X    int                n, aflag = 0;
  1413. X    string            str;
  1414. X
  1415. X    if (argc < 2)
  1416. X        argv = re_makeargv("(username) ", &argc);
  1417. X    if (argc > 4) {
  1418. X        (void) printf("usage: %s username [password] [account]\n", argv[0]);
  1419. X        code = -1;
  1420. X        return (0);
  1421. X    }
  1422. X    (void) sprintf(str, "USER %s", argv[1]);
  1423. X    n = command(str);
  1424. X    if (n == CONTINUE) {
  1425. X        if (argc < 3 )
  1426. X            argv[2] = getpass2("Password: "), argc++;
  1427. X        (void) sprintf(str, "PASS %s", argv[2]);
  1428. X        n = command(str);
  1429. X    }
  1430. X    if (n == CONTINUE) {
  1431. X        if (argc < 4) {
  1432. X            (void) printf("Account: "); (void) fflush(stdout);
  1433. X            (void) FGets(acct, stdin);
  1434. X            acct[strlen(acct) - 1] = '\0';
  1435. X            argv[3] = acct; argc++;
  1436. X        }
  1437. X        (void) sprintf(str, "ACCT %s", argv[3]);
  1438. X        n = command(str);
  1439. X        aflag++;
  1440. X    }
  1441. X    if (n != COMPLETE) {
  1442. X        (void) fprintf(stdout, "Login failed.\n");
  1443. X        return (0);
  1444. X    }
  1445. X    if (!aflag && argc == 4) {
  1446. X        (void) sprintf(str, "ACCT %s", argv[3]);
  1447. X        (void) command(str);
  1448. X    }
  1449. X    return (1);
  1450. X}    /* user */
  1451. X
  1452. X
  1453. X
  1454. X
  1455. X/*
  1456. X * Print working directory.
  1457. X */
  1458. X/*ARGSUSED*/
  1459. Xint pwd(int argc, char **argv)
  1460. X{
  1461. X    int tmpverbose = verbose;
  1462. X    verbose = V_VERBOSE;
  1463. X    (void) command("PWD");
  1464. X    verbose = tmpverbose;
  1465. X}    /* pwd */
  1466. X
  1467. X
  1468. X
  1469. X
  1470. X/*
  1471. X * Make a directory.
  1472. X */
  1473. Xint makedir(int argc, char **argv)
  1474. X{
  1475. X    string str;
  1476. X
  1477. X    if (argc < 2)
  1478. X        argv = re_makeargv("(directory-name) ", &argc);
  1479. X    if (argc < 2) {
  1480. X        (void) printf("usage: %s directory-name\n", argv[0]);
  1481. X        code = -1;
  1482. X        return;
  1483. X    }
  1484. X    (void) sprintf(str, "MKD %s", argv[1]);
  1485. X    (void) command(str);
  1486. X}    /* makedir */
  1487. X
  1488. X
  1489. X
  1490. X
  1491. X/*
  1492. X * Remove a directory.
  1493. X */
  1494. Xint removedir(int argc, char **argv)
  1495. X{
  1496. X    string str;
  1497. X    if (argc < 2)
  1498. X        argv = re_makeargv("(directory-name) ", &argc);
  1499. X    if (argc < 2) {
  1500. X        (void) printf("usage: %s directory-name\n", argv[0]);
  1501. X        code = -1;
  1502. X        return;
  1503. X    }
  1504. X    if (rem_glob_one(argv[1]) == 0) {
  1505. X        (void) sprintf(str, "RMD %s", argv[1]);
  1506. X        (void) command(str);
  1507. X    }
  1508. X}    /* removedir */
  1509. X
  1510. X
  1511. X
  1512. X
  1513. X/*
  1514. X * Send a line, verbatim, to the remote machine.
  1515. X */
  1516. Xint quote(int argc, char **argv)
  1517. X{
  1518. X    int i;
  1519. X    string str;
  1520. X
  1521. X    if (argc < 2)
  1522. X        argv = re_makeargv("(command line to send) ", &argc);
  1523. X    if (argc < 2) {
  1524. X        (void) printf("usage: %s line-to-send\n", argv[0]);
  1525. X        code = -1;
  1526. X        return;
  1527. X    }
  1528. X    (void) Strncpy(str, argv[1]);
  1529. X    for (i = 2; i < argc; i++) {
  1530. X        (void) Strncat(str, " ");
  1531. X        (void) Strncat(str, argv[i]);
  1532. X    }
  1533. X    if (command(str) == PRELIM) {
  1534. X        while (getreply(0) == PRELIM);
  1535. X    }
  1536. X}    /* quote */
  1537. X
  1538. X
  1539. X
  1540. X
  1541. X/*
  1542. X * Ask the other side for help.
  1543. X */
  1544. Xint rmthelp(int argc, char **argv)
  1545. X{
  1546. X    int oldverbose = verbose;
  1547. X    string str;
  1548. X
  1549. X    verbose = V_VERBOSE;
  1550. X    if (argc == 1) (void) command("HELP");
  1551. X    else {
  1552. X        (void) sprintf(str, "HELP %s", argv[1]);
  1553. X        (void) command(str);
  1554. X    }
  1555. X    verbose = oldverbose;
  1556. X}    /* rmthelp */
  1557. X
  1558. X
  1559. X
  1560. X
  1561. X/*
  1562. X * Terminate session and exit.
  1563. X */
  1564. X/*ARGSUSED*/
  1565. Xint quit(int argc, char **argv)
  1566. X{
  1567. X    close_up_shop();
  1568. X    trim_log();
  1569. X    exit(0);
  1570. X}    /* quit */
  1571. X
  1572. X
  1573. X
  1574. Xvoid close_streams(int wantShutDown)
  1575. X{
  1576. X    if (cout != NULL) {
  1577. X        if (wantShutDown)
  1578. X            (void) shutdown(fileno(cout), 1+1);
  1579. X        (void) fclose(cout);
  1580. X        cout = NULL;
  1581. X    }
  1582. X    if (cin != NULL) {
  1583. X        if (wantShutDown)
  1584. X            (void) shutdown(fileno(cin), 1+1);
  1585. X        (void) fclose(cin);
  1586. X        cin = NULL;
  1587. X    }
  1588. X}    /* close_streams */
  1589. X
  1590. X
  1591. X
  1592. X
  1593. X/*
  1594. X * Terminate session, but don't exit.
  1595. X */
  1596. X/*ARGSUSED*/
  1597. Xint disconnect(int argc, char **argv)
  1598. X{
  1599. X    (void) command("QUIT");
  1600. X    close_streams(0);
  1601. X    hostname[0] = cwd[0] = 0;
  1602. X    connected = 0;
  1603. X    data = -1;
  1604. X    macnum = 0;
  1605. X}    /* disconnect */
  1606. X
  1607. X
  1608. X
  1609. X
  1610. Xint confirm(char *cmd, char *file)
  1611. X{
  1612. X    str32 str;
  1613. X
  1614. X    if (!fromatty || (activemcmd && !mprompt))
  1615. X        return 1;
  1616. X    (void) printf("%s %s? ", cmd, file);
  1617. X    (void) fflush(stdout);
  1618. X    (void) gets(str);
  1619. X    return (*str != 'n' && *str != 'N');
  1620. X}    /* confirm */
  1621. X
  1622. X
  1623. X
  1624. Xvoid
  1625. Xfatal(char *msg)
  1626. X{
  1627. X    (void) fprintf(stderr, "%s: %s\n", progname, msg);
  1628. X    close_up_shop();
  1629. X    exit(1);
  1630. X}    /* fatal */
  1631. X
  1632. X
  1633. X
  1634. Xvoid
  1635. Xclose_up_shop(void)
  1636. X{
  1637. X    static int only_once = 0;
  1638. X    if (only_once++ > 0)
  1639. X        return;
  1640. X    if (connected)
  1641. X        disconnect(0, NULL);
  1642. X    if (logf != NULL) {
  1643. X        (void) fclose(logf);
  1644. X        logf = NULL;
  1645. X    }
  1646. X}    /* close_up_shop */
  1647. X
  1648. X
  1649. X
  1650. X
  1651. X/*
  1652. X * Glob a local file name specification with
  1653. X * the expectation of a single return value.
  1654. X * Can't control multiple values being expanded
  1655. X * from the expression, we return only the first.
  1656. X */
  1657. Xint globulize(char **cpp)
  1658. X{
  1659. X    char **globbed;
  1660. X
  1661. X    globbed = glob(*cpp);
  1662. X    if (globerr != NULL) {
  1663. X        (void) printf("%s: %s\n", *cpp, globerr);
  1664. X        if (globbed) {
  1665. X            blkfree(globbed);
  1666. X            free(globbed);
  1667. X        }
  1668. X        return (0);
  1669. X    }
  1670. X    if (globbed) {
  1671. X        *cpp = *globbed++;
  1672. X        /* don't waste too much memory */
  1673. X        if (*globbed) {
  1674. X            blkfree(globbed);
  1675. X            free(globbed);
  1676. X        }
  1677. X    }
  1678. X    return (1);
  1679. X}    /* globulize */
  1680. X
  1681. X
  1682. X
  1683. X/* change directory to perent directory */
  1684. X/*ARGSUSED*/
  1685. Xint cdup(int argc, char **argv)
  1686. X{
  1687. X    (void) _cd("CDUP");
  1688. X}
  1689. X
  1690. X
  1691. X/* show remote system type */
  1692. X/*ARGSUSED*/
  1693. Xint syst(int argc, char **argv)
  1694. X{
  1695. X    (void) command("SYST");
  1696. X}
  1697. X
  1698. X
  1699. X
  1700. X
  1701. Xint make_macro(char *name, FILE *fp)
  1702. X{
  1703. X    char            *tmp;
  1704. X    char            *cp;
  1705. X    string            str;
  1706. X    size_t            len;
  1707. X
  1708. X    if (macnum == MAXMACROS) {
  1709. X        (void) fprintf(stderr, "Limit of %d macros have already been defined.\n", MAXMACROS);
  1710. X        return -1;
  1711. X    }
  1712. X    (void) strncpy(macros[macnum].mac_name, name, (size_t)8);
  1713. X    if (macnum == 0)
  1714. X        macros[macnum].mac_start = macbuf;
  1715. X    else
  1716. X        macros[macnum].mac_start = macros[macnum - 1].mac_end + 1;
  1717. X    tmp = macros[macnum].mac_start;
  1718. X    while (1) {
  1719. X        cp = fgets(str, sizeof(str) - 1, fp);
  1720. X        if (cp == NULL) {
  1721. X            /*
  1722. X             * If we had started a macro, we will say it is
  1723. X             * okay to skip the blank line delimiter if we
  1724. X             * are at the EOF.
  1725. X             */
  1726. X            if (tmp > macros[macnum].mac_start)
  1727. X                goto endmac;
  1728. X            (void) fprintf(stderr, "No text supplied for macro \"%s.\"\n", name);
  1729. X        }
  1730. X        /* see if we have a 'blank' line: just whitespace. */
  1731. X        while (*cp && isspace(*cp)) ++cp;
  1732. X        if (*cp == '\0') {
  1733. X            /* Blank line; end this macro. */
  1734. Xendmac:
  1735. X            macros[macnum++].mac_end = tmp;
  1736. X            return 0;
  1737. X        }
  1738. X        len = strlen(cp) + 1;    /* we need the \0 too. */
  1739. X        if (tmp + len >= macbuf + MACBUFLEN) {
  1740. X            (void) fprintf(stderr, "Macro \"%s\" not defined -- %d byte buffer exceeded.\n", name, MACBUFLEN);
  1741. X            return -1;
  1742. X        }
  1743. X        (void) strcpy(tmp, cp);
  1744. X        tmp += len;
  1745. X    }
  1746. X}    /* make_macro */
  1747. X
  1748. X
  1749. X
  1750. X
  1751. Xint macdef(int argc, char **argv)
  1752. X{
  1753. X    if (argc < 2)
  1754. X        argv = re_makeargv("(macro name) ", &argc);
  1755. X    if (argc != 2) {
  1756. X        (void) printf("Usage: %s macro_name\n", argv[0]);
  1757. X        code = -1;
  1758. X        return;
  1759. X    }
  1760. X    (void) printf("Enter macro line by line, terminating it with a blank line\n");
  1761. X    code = make_macro(argv[0], stdin);
  1762. X}    /* macdef */
  1763. X
  1764. X
  1765. X
  1766. X
  1767. Xint domacro(int argc, char **argv)
  1768. X{
  1769. X    register int            i, j;
  1770. X    register char            *cp1, *cp2;
  1771. X    int                        count = 2, loopflg = 0;
  1772. X    string                    str;
  1773. X    struct cmd                *c;
  1774. X
  1775. X    if (argc < 2) {
  1776. X        /* print macros. */
  1777. X        if (macnum == 0)
  1778. X            (void) printf("No macros defined.\n");
  1779. X        else
  1780. X        for (i = 0; i < macnum; ++i) {
  1781. X            (void) printf("%s:\n", macros[i].mac_name);
  1782. X            cp1 = macros[i].mac_start;
  1783. X            cp2 = macros[i].mac_end;
  1784. X            while (cp1 < cp2) {
  1785. X                (void) printf("   > ");
  1786. X                while (cp1 < cp2 && *cp1)
  1787. X                    putchar(*cp1++);
  1788. X                ++cp1;
  1789. X                /* putchar('\n'); */
  1790. X            }
  1791. X        }
  1792. X        argv = re_makeargv("(macro to run) ", &argc);
  1793. X    }            
  1794. X    if (argc < 2) {
  1795. X        (void) printf("Usage: %s macro_name.\n", argv[0]);
  1796. X        code = -1;
  1797. X        return;
  1798. X    }
  1799. X    for (i = 0; i < macnum; ++i) {
  1800. X        if (!strncmp(argv[1], macros[i].mac_name, (size_t) 9)) {
  1801. X            break;
  1802. X        }
  1803. X    }
  1804. X    if (i == macnum) {
  1805. X        (void) printf("'%s' macro not found.\n", argv[1]);
  1806. X        code = -1;
  1807. X        return;
  1808. X    }
  1809. X    (void) Strncpy(str, line);
  1810. XTOP:
  1811. X    cp1 = macros[i].mac_start;
  1812. X    while (cp1 != macros[i].mac_end) {
  1813. X        while (isspace(*cp1)) {
  1814. X            cp1++;
  1815. X        }
  1816. X        cp2 = line;
  1817. X        while (*cp1 != '\0') {
  1818. X              switch(*cp1) {
  1819. X                   case '\\':
  1820. X                 *cp2++ = *++cp1;
  1821. X                 break;
  1822. X                case '$':
  1823. X                 if (isdigit(*(cp1+1))) {
  1824. X                    j = 0;
  1825. X                    while (isdigit(*++cp1)) {
  1826. X                      j = 10*j +  *cp1 - '0';
  1827. X                    }
  1828. X                    cp1--;
  1829. X                    if (argc - 2 >= j) {
  1830. X                    (void) strcpy(cp2, argv[j+1]);
  1831. X                    cp2 += strlen(argv[j+1]);
  1832. X                    }
  1833. X                    break;
  1834. X                 }
  1835. X                 if (*(cp1+1) == 'i') {
  1836. X                    loopflg = 1;
  1837. X                    cp1++;
  1838. X                    if (count < argc) {
  1839. X                       (void) strcpy(cp2, argv[count]);
  1840. X                       cp2 += strlen(argv[count]);
  1841. X                    }
  1842. X                    break;
  1843. X                }
  1844. X                /* intentional drop through */
  1845. X                default:
  1846. X                *cp2++ = *cp1;
  1847. X                break;
  1848. X              }
  1849. X              if (*cp1 != '\0') {
  1850. X                    cp1++;
  1851. X              }
  1852. X        }
  1853. X        *cp2 = '\0';
  1854. X        makeargv();
  1855. X        c = getcmd(margv[0]);
  1856. X        if (c == (struct cmd *)-1) {
  1857. X            (void) printf("?Ambiguous command\n");
  1858. X            code = -1;
  1859. X        }
  1860. X        else if (c == 0) {
  1861. X            (void) printf("?Invalid command\n");
  1862. X            code = -1;
  1863. X        } else if (c->c_conn && !connected) {
  1864. X            (void) printf("Not connected.\n");
  1865. X            code = -1;
  1866. X        } else {
  1867. X            if (IS_VVERBOSE)
  1868. X                (void) printf("%s\n",line);
  1869. X            (*c->c_handler)(margc, margv);
  1870. X            (void) strcpy(line, str);
  1871. X            makeargv();
  1872. X            argc = margc;
  1873. X            argv = margv;
  1874. X        }
  1875. X        if (cp1 != macros[i].mac_end) {
  1876. X            cp1++;
  1877. X        }
  1878. X    }
  1879. X    if (loopflg && ++count < argc) {
  1880. X        goto TOP;
  1881. X    }
  1882. X}    /* domacro */
  1883. X
  1884. X
  1885. X
  1886. X/*
  1887. X * get size of file on remote machine
  1888. X */
  1889. Xint sizecmd(int argc, char **argv)
  1890. X{
  1891. X    string str;
  1892. X
  1893. X    if (argc < 2)
  1894. X        argv = re_makeargv("(remote-file) ", &argc);
  1895. X    if (argc < 2) {
  1896. X        (void) printf("usage:%s filename\n", argv[0]);
  1897. X        code = -1;
  1898. X        return;
  1899. X    }
  1900. X    if (rem_glob_one(argv[1]) == 0) {
  1901. X        (void) sprintf(str, "SIZE %s", argv[1]);
  1902. X        (void) command(str);
  1903. X    }
  1904. X}    /* sizecmd */
  1905. X
  1906. X
  1907. X
  1908. X
  1909. X/*
  1910. X * get last modification time of file on remote machine
  1911. X */
  1912. Xint modtime(int argc, char **argv)
  1913. X{
  1914. X    int overbose;
  1915. X    string str;
  1916. X
  1917. X    if (argc < 2)
  1918. X        argv = re_makeargv("(remote-file) ", &argc);
  1919. X    if (argc < 2) {
  1920. X        (void) printf("usage:%s filename\n", argv[0]);
  1921. X        code = -1;
  1922. X        return;
  1923. X    }
  1924. X    if (rem_glob_one(argv[1]) == 0) {
  1925. X        overbose = verbose;
  1926. X        if (debug == 0)
  1927. X            verbose = V_QUIET;
  1928. X        (void) sprintf(str, "MDTM %s", argv[1]);
  1929. X        if (command(str) == COMPLETE) {
  1930. X            int yy, mo, day, hour, min, sec;
  1931. X            (void) sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo,
  1932. X                &day, &hour, &min, &sec);
  1933. X            /* might want to print this in local time */
  1934. X            (void) printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1],
  1935. X                mo, day, yy, hour, min, sec);
  1936. X        } else
  1937. X            (void) fputs(reply_string, stdout);
  1938. X        verbose = overbose;
  1939. X    }
  1940. X}    /* modtime */
  1941. X
  1942. X
  1943. X
  1944. Xint lookup(int argc, char **argv)
  1945. X{
  1946. X    int i, j, by_name, result = 0;
  1947. X    unsigned long addr;            /* address in host order */
  1948. X    struct hostent *host;        /* structure returned by gethostbyaddr() */
  1949. X    extern int h_errno;
  1950. X
  1951. X    if (argc < 2)
  1952. X        argv = re_makeargv("(sitename) ", &argc);
  1953. X    if (argc < 2) {
  1954. X        (void) printf("usages:\n\t%s <sitenames>\n\t%s <ip numbers>\n",
  1955. X            argv[0], argv[0]);
  1956. X    }
  1957. X
  1958. X     lasthostname[0] = 0;
  1959. X    for (i=1; i<argc; i++) {
  1960. X        /* does the argument look like an address? */
  1961. X        if (4 == sscanf (argv[i], "%d.%d.%d.%d", &j, &j, &j, &j)) {
  1962. X            /* ip */
  1963. X              if ((addr = inet_addr (argv[i])) == 0xffffffff) {
  1964. X                 (void) fprintf(stderr, "## could not convert \"%s\" into a valid IP address.\n", argv[i]);
  1965. X                 continue;
  1966. X             }
  1967. X            host = gethostbyaddr ((char *) &addr, 4, AF_INET);
  1968. X            by_name = 0;
  1969. X        } else {
  1970. X            /* name */
  1971. X            host = gethostbyname (argv[i]);
  1972. X            by_name = 1;
  1973. X        }
  1974. X        if (host == NULL) {
  1975. X            if (NOT_VQUIET) {
  1976. X                /* gethostxxx error */                
  1977. X                result = h_errno;
  1978. X                if (h_errno == HOST_NOT_FOUND) {
  1979. X                     (void) printf("%s: lookup error (%d).\n",
  1980. X                         argv[i], h_errno);
  1981. X                     result = h_errno;
  1982. X                 } else {
  1983. X                     (void) printf("%s \"%s\"\n",
  1984. X                         (by_name==0 ? "unknown address" : "unknown host"),
  1985. X                         argv[i]);
  1986. X                     result = 
  1987. X                         h_errno != 0 ? h_errno :
  1988. X                         -1;
  1989. X                }
  1990. X            }
  1991. X         } else {
  1992. X             if (*host->h_name)
  1993. X                 Strncpy(lasthostname, host->h_name);
  1994. X            if (NOT_VQUIET) {
  1995. X                (void) printf("%-32s  ", *host->h_name ? host->h_name : "???");
  1996. X                if (*host->h_addr_list) {
  1997. X                    unsigned long horder;
  1998. X    
  1999. X                    horder = ntohl (*(unsigned long *) *(char **)host->h_addr_list);
  2000. X                    (void) printf ("%lu.%lu.%lu.%lu\n",
  2001. X                        (horder >> 24),
  2002. X                        (horder >> 16) & 0xff,
  2003. X                        (horder >> 8) & 0xff,
  2004. X                        horder & 0xff);
  2005. X                }
  2006. X                else (void) printf("???\n");
  2007. X            }
  2008. X        }
  2009. X    }    /* loop thru all sites */
  2010. X    return result;
  2011. X}    /* lookup */
  2012. X
  2013. X
  2014. X
  2015. X
  2016. Xint getlocalhostname(char *host, size_t size)
  2017. X{
  2018. X    int oldv, r;
  2019. X    char *argv[2];
  2020. X
  2021. X#ifdef HOSTNAME
  2022. X    (void) strncpy(host, HOSTNAME, size);
  2023. X    return 0;
  2024. X#else
  2025. X    *host = 0;
  2026. X    if ((r = gethostname(host, size)) == 0) {
  2027. X        oldv = verbose;
  2028. X        verbose = V_QUIET;
  2029. X        argv[0] = "lookup";
  2030. X        (void) sprintf(line, "lookup %s", host);
  2031. X        (void) makeargv();
  2032. X        if (lookup(margc, margv) == 0 && lasthostname[0])
  2033. X            (void) strncpy(host, lasthostname, size);
  2034. X        verbose = oldv;
  2035. X    }
  2036. X    return r;
  2037. X#endif
  2038. X}    /* getlocalhostname */
  2039. X
  2040. X
  2041. X
  2042. X
  2043. X/*
  2044. X * show status on remote machine
  2045. X */
  2046. Xint rmtstatus(int argc, char **argv)
  2047. X{
  2048. X    string str;
  2049. X    if (argc > 1) {
  2050. X        (void) sprintf(str, "STAT %s" , argv[1]);
  2051. X        (void) command(str);
  2052. X    } else (void) command("STAT");
  2053. X}    /* rmtstatus */
  2054. X
  2055. X
  2056. X
  2057. X
  2058. X/*
  2059. X * create an empty file on remote machine.
  2060. X */
  2061. Xint create(int argc, char **argv)
  2062. X{
  2063. X    string            str;
  2064. X    FILE            *ftemp;
  2065. X
  2066. X    if (argc < 2)
  2067. X        argv = re_makeargv("(remote-file) ", &argc);
  2068. X    if (argc < 2) {
  2069. X        (void) printf("usage:%s filename\n", argv[0]);
  2070. X        code = -1;
  2071. X        return;
  2072. X    }
  2073. X    (void) tmp_name(str);
  2074. X    ftemp = fopen(str, "w");
  2075. X    /* (void) fputc('x', ftemp); */
  2076. X    (void) fclose(ftemp);
  2077. X    creating = 1;
  2078. X    sendrequest("STOR", str, argv[1]);
  2079. X    creating = 0;
  2080. X    (void) unlink(str);
  2081. X}    /* create */
  2082. X
  2083. X
  2084. X/* Peter Jaspers-Fayer    pjf@osiris.cs.uoguelph.ca    Nov'92 */
  2085. Xchar *getpass2(char *promptstr)
  2086. X{
  2087. X    static char pass[80];               /* That should be enough! */
  2088. X
  2089. X    struct termio t, s;
  2090. X
  2091. X    (void) printf("%s", promptstr);
  2092. X    if (0 > ioctl(0, TCGETA, &t))
  2093. X        Perror("termio failed");
  2094. X    s.c_lflag = t.c_lflag;               /* -- save */
  2095. X
  2096. X    t.c_lflag &= ~ECHO;                   /* disable echo */
  2097. X    if (0 > ioctl(0, TCSETA, &t))
  2098. X        Perror("termio failed");
  2099. X
  2100. X    (void) gets(pass);
  2101. X
  2102. X    t.c_lflag = s.c_lflag;               /* -- restore */
  2103. X    if (0 > ioctl(0, TCSETA, &t))
  2104. X        Perror("termio failed");
  2105. X
  2106. X    (void) printf("\n");               /* Only because the original did */
  2107. X    return (pass);
  2108. X}                                       /* getpass2 */
  2109. X
  2110. X
  2111. X/* show version info */
  2112. X/*ARGSUSED*/
  2113. Xint show_version(int argc, char **argv)
  2114. X{
  2115. X    char    *DStrs[20];
  2116. X    int        nDStrs = 0, i, j;
  2117. X
  2118. X    (void) printf("%s\n%-30s %s\n", version, "Author:",
  2119. X        "Mike Gleason, NCEMRSoft (mgleason@cse.unl.edu).");
  2120. X
  2121. X/* Now entering CPP hell... */
  2122. X#ifdef __DATE__
  2123. X    (void) printf("%-30s %s\n", "Compile Date:", __DATE__);
  2124. X#endif
  2125. X    (void) printf("%-30s %s (%s)\n", "Operating System:",
  2126. X#ifdef System
  2127. X    System,
  2128. X#else
  2129. X#    ifdef unix
  2130. X    "UNIX",
  2131. X#    else
  2132. X    "??",
  2133. X#    endif
  2134. X#endif
  2135. X#ifdef SYSV
  2136. X        "SYSV");
  2137. X#else
  2138. X#    ifdef BSD
  2139. X            "BSD");
  2140. X#    else
  2141. X            "??");
  2142. X#    endif
  2143. X#endif
  2144. X
  2145. X#ifdef RINDEX
  2146. X    DStrs[nDStrs++] = "RINDEX";
  2147. X#endif
  2148. X#ifdef HERROR
  2149. X    DStrs[nDStrs++] = "HERROR";
  2150. X#endif
  2151. X#ifdef U_WAIT
  2152. X    DStrs[nDStrs++] = "U_WAIT";
  2153. X#endif
  2154. X#ifdef const
  2155. X    DStrs[nDStrs++] = "const";
  2156. X#endif
  2157. X#ifdef HOSTNAME
  2158. X    DStrs[nDStrs++] = "HOSTNAME";
  2159. X#endif
  2160. X#ifdef SYSDIRH
  2161. X    DStrs[nDStrs++] = "SYSDIRH";
  2162. X#endif
  2163. X#ifdef SYSSELECTH
  2164. X    DStrs[nDStrs++] = "SYSSELECTH";
  2165. X#endif
  2166. X#ifdef REDIR
  2167. X    DStrs[nDStrs++] = "REDIR";
  2168. X#endif
  2169. X
  2170. X    (void) printf ("\nCompile Options:\n");
  2171. X    for (i=j=0; i<nDStrs; i++) {
  2172. X        if (j == 0)
  2173. X            (void) printf("    ");
  2174. X        (void) printf("%-15s", DStrs[i]);
  2175. X        if (++j == 4) {
  2176. X            j = 0;
  2177. X            (void) putchar('\n');
  2178. X        }
  2179. X    }
  2180. X    if (j != 0)
  2181. X        (void) putchar('\n');
  2182. X    
  2183. X    (void) printf("\nDefaults:\n");
  2184. X    (void) printf("\
  2185. X    Xfer Buf Size: %8d   Debug: %d   MPrompt: %d   Verbosity: %d\n\
  2186. X    Prompt: %s   Pager: %s  ZCat: %s\n\
  2187. X    Logname: %s   Logging: %d   Type: %s   Cmd Len: %d\n\
  2188. X    Recv Line Len: %d   #Macros: %d   Macbuf: %d  Auto-Binary: %d\n\
  2189. X    Redial Delay: %d  New Mail Message: \"%s\"\n",
  2190. X        MAX_XFER_BUFSIZE, dDEBUG, dMPROMPT, dVERBOSE,
  2191. X        dPROMPT, dPAGER, ZCAT,
  2192. X        dLOGNAME, dLOGGING, dTYPESTR, CMDLINELEN,
  2193. X        RECEIVEDLINELEN, MAXMACROS, MACBUFLEN, dAUTOBINARY,
  2194. X        dREDIALDELAY, NEWMAILMESSAGE
  2195. X    );
  2196. X}    /* show_version */
  2197. X
  2198. X
  2199. X
  2200. Xvoid Perror(char *s)
  2201. X{
  2202. X    extern int errno;
  2203. X
  2204. X    if (NOT_VQUIET) {
  2205. X        if (s != NULL)
  2206. X            (void) fprintf(stderr, "NcFTP: %s (%d): ", s, errno);
  2207. X        perror(NULL);
  2208. X    }
  2209. X}    /* Perror */
  2210. X
  2211. X
  2212. X
  2213. X#ifdef REDIR
  2214. X/*ARGSUSED*/
  2215. Xint showlsbuffer(int argc, char **argv)
  2216. X{
  2217. X    register struct lslist *a = lshead;
  2218. X    int pagemode;
  2219. X    FILE *fp;
  2220. X    void (*oldintp)(int);
  2221. X
  2222. X    if (a == NULL)
  2223. X        return;
  2224. X    pagemode= (**argv) == 'p' && pager[0] == '|';
  2225. X    if (pagemode) {
  2226. X        fp = popen(pager + 1, "w");
  2227. X        if (!fp) {
  2228. X            Perror(pager + 1);
  2229. X            return;
  2230. X        }
  2231. X    } else
  2232. X        fp = stdout;
  2233. X    oldintp = signal(SIGPIPE, SIG_IGN);
  2234. X    while (a) {
  2235. X        if (a->string)
  2236. X            (void) fprintf(fp, "%s\n", a->string);
  2237. X        a = a->next;
  2238. X    }
  2239. X    if (pagemode)
  2240. X        (void) pclose(fp);
  2241. X    if (oldintp)
  2242. X        signal(SIGPIPE, oldintp);
  2243. X}    /* showlsbuffer */
  2244. X#endif
  2245. X
  2246. X/* eof cmds.c */
  2247. END_OF_FILE
  2248.   if test 44217 -ne `wc -c <'cmds.c'`; then
  2249.     echo shar: \"'cmds.c'\" unpacked with wrong size!
  2250.   fi
  2251.   # end of 'cmds.c'
  2252. fi
  2253. if test -f 'ftpdefs.h' -a "${1}" != "-c" ; then 
  2254.   echo shar: Will not clobber existing file \"'ftpdefs.h'\"
  2255. else
  2256.   echo shar: Extracting \"'ftpdefs.h'\" \(644 characters\)
  2257.   sed "s/^X//" >'ftpdefs.h' <<'END_OF_FILE'
  2258. X/* ftpdefs.h */
  2259. X
  2260. X#ifndef _ftpdefs_h_
  2261. X#define _ftpdefs_h_
  2262. X
  2263. X#define FTP_VERSION "NcFTP 1.0 (6 Dec 92)"
  2264. X
  2265. Xtypedef char string[128], str32[32];
  2266. X
  2267. Xstruct userinfo {
  2268. X    str32   username;
  2269. X    string  homedir;
  2270. X    string  shell;
  2271. X    string  hostname;
  2272. X    int        uid;
  2273. X};
  2274. X
  2275. X/* Your compiler may not like the 'const' directives.  If it chokes
  2276. X * here, add -Dconst to your SDEFS line in the Makefile, or delete the word
  2277. X * const here.
  2278. X */
  2279. X#define Strncpy(a,b) strncpy((a), (const char *) (b), (size_t) sizeof (a))
  2280. X#define Strncat(a,b) strncat((a), (const char *) (b), (size_t) sizeof (a))
  2281. X#define FGets(a,b) fgets((a), sizeof(a) - 1, (b))
  2282. X
  2283. X#endif /* _ftpdefs_h_ */
  2284. X/* eof */
  2285. END_OF_FILE
  2286.   if test 644 -ne `wc -c <'ftpdefs.h'`; then
  2287.     echo shar: \"'ftpdefs.h'\" unpacked with wrong size!
  2288.   fi
  2289.   # end of 'ftpdefs.h'
  2290. fi
  2291. if test -f 'sys.h' -a "${1}" != "-c" ; then 
  2292.   echo shar: Will not clobber existing file \"'sys.h'\"
  2293. else
  2294.   echo shar: Extracting \"'sys.h'\" \(4116 characters\)
  2295.   sed "s/^X//" >'sys.h' <<'END_OF_FILE'
  2296. X/* sys.h */
  2297. X
  2298. X/*
  2299. X * ncftp may need work arounds for some things due to the differences
  2300. X * in implementations of unix.  The following systems are taken care
  2301. X * of automatically:
  2302. X *
  2303. X *    SunOS/Solaris (but use gcc)
  2304. X *    Silicon Graphics IRIX
  2305. X *    AIX
  2306. X *    SINIX
  2307. X *
  2308. X * For those systems, you should be able to 'make' ncftp without any
  2309. X * problems.  Otherwise you will have to configure ncftp manually.
  2310. X * You will need to add these things to the SDEFS line in the Makefile
  2311. X * as applicable.
  2312. X *
  2313. X * For these systems, some things are taken care of automatically, but
  2314. X * you still need to add something to CFLAGS or SDEFS:
  2315. X *
  2316. X *     Hewlett-Packard HP-UX:  If you have 7.0, you'll need to find
  2317. X *       a copy of <ftp.h> from somewhere (8.0 has it though). Then
  2318. X *       set CFLAGS= -Aa.  You may also need to use gcc if your
  2319. X *       compiler is non-ANSI.
  2320. X *
  2321. X *     SCO Unix:  Add -DSCO324 to SDEFS.
  2322. X *
  2323. X *     Bull DPX/2: Add -DBULL to SDEFS, add -linet to MORELIBS, and
  2324. X *       use gcc.
  2325. X *
  2326. X * Is your system closer to System V or BSD?  Your SDEFS line should have
  2327. X * either -DBSD or -DSYSV.  If you don't know, try leaving it blank first;
  2328. X * some compilers automatically define it for you.  So far, defining
  2329. X * SYSV just defines a couple of macros for similar functions in BSD.
  2330. X *
  2331. X * You may need to add -DRINDEX if your system uses strrchr instead.
  2332. X * If SYSV is defined, RINDEX is defined automatically because System V
  2333. X * uses strrchr.
  2334. X *
  2335. X * Add -Dconst if your compiler chokes on the const directive.
  2336. X *
  2337. X * Add -DSYSSELECTH if you need <sys/select.h> included for definitions
  2338. X * of fd_set, etc.
  2339. X *
  2340. X * (Optional) Add -DHERROR if you know you have the herror() system
  2341. X * call.
  2342. X *
  2343. X * (Optional) Add -DU_WAIT if you know your wait system call takes
  2344. X * a pointer to a 'union wait.'  Defined automatically if you define
  2345. X * BSD.
  2346. X *
  2347. X * (Optional) Add -DHOSTNAME=\"machine.domain.nam\" if your system
  2348. X * doesn't generate it's own hostname.  To check this, compile ncftp
  2349. X * then run it and type 'set.'  Look at the variable anon-password.
  2350. X * If the hostname is wrong, recompile it with HOSTNAME set to your
  2351. X * machine's address.
  2352. X */
  2353. X
  2354. X#ifdef sun
  2355. X#    define System "SunOS"
  2356. X#    ifndef RINDEX
  2357. X#        define RINDEX 1
  2358. X#    endif
  2359. X#endif /* sun */
  2360. X
  2361. X#ifdef sgi
  2362. X#    define System "IRIX"
  2363. X#    ifndef SYSV
  2364. X#        define SYSV 1
  2365. X#    endif
  2366. X#    ifndef HERROR
  2367. X#        define HERROR 1
  2368. X#    endif
  2369. X#    ifndef U_WAIT
  2370. X#        define U_WAIT 1
  2371. X#    endif
  2372. X#endif /* sgi */
  2373. X
  2374. X#ifdef _AIX
  2375. X#    define System "AIX"
  2376. X#    define SYSSELECTH 1
  2377. X#endif    /* _AIX */
  2378. X
  2379. X#ifdef SCO324
  2380. X#    define System "SCO Unix"
  2381. X#    ifndef SYSV
  2382. X#        define SYSV 1
  2383. X#    endif
  2384. X#endif    /* SCO */
  2385. X
  2386. X#if defined(__hpux) || defined(HPUX)
  2387. X#    define System "HP-UX"
  2388. X#    ifndef _HPUX_SOURCE
  2389. X#        define _HPUX_SOURCE 1
  2390. X#    endif
  2391. X#    define SYSV 1
  2392. X#endif    /* HPUX */
  2393. X
  2394. X#ifdef SINIX
  2395. X#    define System "SINIX"
  2396. X#    ifndef SYSV
  2397. X#        define SYSV 1
  2398. X#    endif
  2399. X/* You may need to add -lresolv, -lport, -lcurses to MORELIBS in Makefile. */
  2400. X#endif
  2401. X
  2402. X#ifdef BULL          /* added 23nov92 for Bull DPX/2 */
  2403. X#    define _POSIX_SOURCE
  2404. X#    define _XOPEN_SOURCE
  2405. X#    define _BULL_SOURCE
  2406. X#    ifndef SYSV
  2407. X#        define SYSV 1
  2408. X#    endif
  2409. X#    define bull
  2410. X#    define System "Bull DPX/2 BOS"
  2411. X#    include <sys/types.h>
  2412. X#    define SYSSELECTH
  2413. X#endif  /* BULL */   /* added 23nov92 for Bull DPX/2 */
  2414. X
  2415. X/* -------------------------------------------------------------------- */
  2416. X
  2417. X#ifdef _SYSV
  2418. X#    ifndef SYSV
  2419. X#        define SYSV 1
  2420. X#    endif
  2421. X#endif
  2422. X
  2423. X#ifdef USG
  2424. X#    ifndef SYSV
  2425. X#        define SYSV 1
  2426. X#    endif
  2427. X#endif
  2428. X
  2429. X#ifdef _BSD
  2430. X#    ifndef BSD
  2431. X#        define BSD 1
  2432. X#    endif
  2433. X#    ifndef SYSDIRH
  2434. X#        define SYSDIRH 1
  2435. X#    endif
  2436. X#endif
  2437. X
  2438. X#ifdef SYSV
  2439. X#    ifndef RINDEX
  2440. X#        define RINDEX 1
  2441. X#    endif
  2442. X#    define unlink remove
  2443. X#    define bcopy(s,d,l) memcpy((d),(s),(l))
  2444. X#    define bzero(cp,l) memset((cp),0,(l))
  2445. X#endif
  2446. X
  2447. X#ifdef BSD
  2448. X#    ifndef U_WAIT
  2449. X#        define U_WAIT 1 /* Use a 'union wait' parameter with wait(). */
  2450. X#    endif
  2451. X#endif
  2452. X
  2453. X/*
  2454. X * Some systems besides System V don't use rindex/index (like SunOS).
  2455. X * Add -DRINDEX to your SDEFS line if you need to.
  2456. X */
  2457. X#ifdef RINDEX
  2458. X    /* or #include <strings.h> if you have it. */
  2459. X#    define rindex strrchr
  2460. X#    define index strchr
  2461. X#endif /* RINDEX */
  2462. X
  2463. X/* Turn on the redir command. */
  2464. X#ifndef REDIR
  2465. X#    define REDIR 1
  2466. X#endif
  2467. X
  2468. X/* eof sys.h */
  2469. END_OF_FILE
  2470.   if test 4116 -ne `wc -c <'sys.h'`; then
  2471.     echo shar: \"'sys.h'\" unpacked with wrong size!
  2472.   fi
  2473.   # end of 'sys.h'
  2474. fi
  2475. echo shar: End of archive 1 \(of 3\).
  2476. cp /dev/null ark1isdone
  2477. MISSING=""
  2478. for I in 1 2 3 ; do
  2479.     if test ! -f ark${I}isdone ; then
  2480.     MISSING="${MISSING} ${I}"
  2481.     fi
  2482. done
  2483. if test "${MISSING}" = "" ; then
  2484.     echo You have unpacked all 3 archives.
  2485.     rm -f ark[1-9]isdone
  2486. else
  2487.     echo You still must unpack the following archives:
  2488.     echo "        " ${MISSING}
  2489. fi
  2490. exit 0
  2491. exit 0 # Just in case...
  2492.