1/*
2 * zftp.c - builtin FTP client
3 *
4 * This file is part of zsh, the Z shell.
5 *
6 * Copyright (c) 1998 Peter Stephenson
7 * All rights reserved.
8 *
9 * Permission is hereby granted, without written agreement and without
10 * license or royalty fees, to use, copy, modify, and distribute this
11 * software and to distribute modified versions of this software for any
12 * purpose, provided that the above copyright notice and the following
13 * two paragraphs appear in all copies of this software.
14 *
15 * In no event shall Peter Stephenson or the Zsh Development Group be liable
16 * to any party for direct, indirect, special, incidental, or consequential
17 * damages arising out of the use of this software and its documentation,
18 * even if Peter Stephenson and the Zsh Development Group have been advised of
19 * the possibility of such damage.
20 *
21 * Peter Stephenson and the Zsh Development Group specifically disclaim any
22 * warranties, including, but not limited to, the implied warranties of
23 * merchantability and fitness for a particular purpose.  The software
24 * provided hereunder is on an "as is" basis, and Peter Stephenson and the
25 * Zsh Development Group have no obligation to provide maintenance,
26 * support, updates, enhancements, or modifications.
27 *
28 */
29
30/*
31 * TODO:
32 *   should be eight-bit clean, but isn't.
33 *   tracking of logical rather than physical directories, like nochaselinks
34 *     (usually PWD returns physical directory).
35 *   can signal handling be improved?
36 *   maybe we should block CTRL-c on some more operations,
37 *     otherwise you can get the connection closed prematurely.
38 *   some way of turning off progress reports when backgrounded
39 *     would be nice, but the shell doesn't make it easy to find that out.
40 *   proxy/gateway connections if i knew what to do
41 *   options to specify e.g. a non-standard port
42 */
43
44/* needed in prototypes for statics */
45struct hostent;
46struct in_addr;
47struct sockaddr_in;
48struct sockaddr_in6;
49struct zftp_session;
50typedef struct zftp_session *Zftp_session;
51
52#include "tcp.h"
53#include "tcp.mdh"
54#include "zftp.mdh"
55#include "zftp.pro"
56
57/* it's a TELNET based protocol, but don't think I like doing this */
58#include <arpa/telnet.h>
59
60/*
61 * We use poll() in preference to select because some subset of manuals says
62 * that's the thing to do, plus it's a bit less fiddly.  I don't actually
63 * have access to a system with poll but not select, however, though
64 * both bits of the code have been tested on a machine with both.
65 */
66#ifdef HAVE_POLL_H
67# include <poll.h>
68#endif
69#if defined(HAVE_POLL) && !defined(POLLIN) && !defined(POLLNORM)
70# undef HAVE_POLL
71#endif
72
73
74#ifdef USE_LOCAL_H_ERRNO
75int h_errno;
76#endif
77
78union zftp_sockaddr {
79    struct sockaddr a;
80    struct sockaddr_in in;
81#ifdef SUPPORT_IPV6
82    struct sockaddr_in6 in6;
83#endif
84};
85
86#ifdef USE_LOCAL_H_ERRNO
87int h_errno;
88#endif
89
90/*
91 * For FTP block mode
92 *
93 * The server on our AIX machine here happily accepts block mode, takes the
94 * first connection, then at the second complains that it's got nowhere
95 * to send data.  The same problem happens with ncftp, it's not just
96 * me.  And a lot of servers don't even support block mode. So I'm not sure
97 * how widespread the supposed ability to leave open the data fd between
98 * transfers.  Therefore, I've closed all connections after the transfer.
99 * But then what's the point in block mode?  I only implemented it because
100 * it says in RFC959 that you need it to be able to restart transfers
101 * later in the file.  However, it turns out that's not true for
102 * most servers --- but our AIX machine happily accepts the REST
103 * command and then dumps the whole file onto you.  Sigh.
104 *
105 * Note on block sizes:
106 * Not quite sure how to optimize this:  in principle
107 * we should handle blocks up to 65535 bytes, which
108 * is pretty big, and should presumably send blocks
109 * which are smaller to be on the safe side.
110 * Currently we send 32768 and use that also as
111 * the maximum to receive.  No-one's complained yet.  Of course,
112 * no-one's *used* it yet apart from me, but even so.
113 */
114
115struct zfheader {
116    char flags;
117    unsigned char bytes[2];
118};
119
120enum {
121    ZFHD_MARK = 16,		/* restart marker */
122    ZFHD_ERRS = 32,		/* suspected errors in block */
123    ZFHD_EOFB = 64,		/* block is end of record */
124    ZFHD_EORB = 128		/* block is end of file */
125};
126
127typedef int (*readwrite_t)(int, char *, off_t, int);
128
129struct zftpcmd {
130    const char *nam;
131    int (*fun) _((char *, char **, int));
132    int min, max, flags;
133};
134
135enum {
136    ZFTP_CONN  = 0x0001,	/* must be connected */
137    ZFTP_LOGI  = 0x0002,	/* must be logged in */
138    ZFTP_TBIN  = 0x0004,	/* set transfer type image */
139    ZFTP_TASC  = 0x0008,	/* set transfer type ASCII */
140    ZFTP_NLST  = 0x0010,	/* use NLST rather than LIST */
141    ZFTP_DELE  = 0x0020,	/* a delete rather than a make */
142    ZFTP_SITE  = 0x0040,	/* a site rather than a quote */
143    ZFTP_APPE  = 0x0080,	/* append rather than overwrite */
144    ZFTP_HERE  = 0x0100,	/* here rather than over there */
145    ZFTP_CDUP  = 0x0200,	/* CDUP rather than CWD */
146    ZFTP_REST  = 0x0400,	/* restart: set point in remote file */
147    ZFTP_RECV  = 0x0800,	/* receive rather than send */
148    ZFTP_TEST  = 0x1000,	/* test command, don't test */
149    ZFTP_SESS  = 0x2000		/* session command, don't need status */
150};
151
152typedef struct zftpcmd *Zftpcmd;
153
154static struct zftpcmd zftpcmdtab[] = {
155    { "open", zftp_open, 0, 4, 0 },
156    { "params", zftp_params, 0, 4, 0 },
157    { "login", zftp_login, 0, 3, ZFTP_CONN },
158    { "user", zftp_login, 0, 3, ZFTP_CONN },
159    { "test", zftp_test, 0, 0, ZFTP_TEST },
160    { "cd", zftp_cd, 1, 1, ZFTP_CONN|ZFTP_LOGI },
161    { "cdup", zftp_cd, 0, 0, ZFTP_CONN|ZFTP_LOGI|ZFTP_CDUP },
162    { "dir", zftp_dir, 0, -1, ZFTP_CONN|ZFTP_LOGI },
163    { "ls", zftp_dir, 0, -1, ZFTP_CONN|ZFTP_LOGI|ZFTP_NLST },
164    { "type", zftp_type, 0, 1, ZFTP_CONN|ZFTP_LOGI },
165    { "ascii", zftp_type, 0, 0, ZFTP_CONN|ZFTP_LOGI|ZFTP_TASC },
166    { "binary", zftp_type, 0, 0, ZFTP_CONN|ZFTP_LOGI|ZFTP_TBIN },
167    { "mode", zftp_mode, 0, 1, ZFTP_CONN|ZFTP_LOGI },
168    { "local", zftp_local, 0, -1, ZFTP_HERE },
169    { "remote", zftp_local, 1, -1, ZFTP_CONN|ZFTP_LOGI },
170    { "get", zftp_getput, 1, -1, ZFTP_CONN|ZFTP_LOGI|ZFTP_RECV },
171    { "getat", zftp_getput, 2, 2, ZFTP_CONN|ZFTP_LOGI|ZFTP_RECV|ZFTP_REST },
172    { "put", zftp_getput, 1, -1, ZFTP_CONN|ZFTP_LOGI },
173    { "putat", zftp_getput, 2, 2, ZFTP_CONN|ZFTP_LOGI|ZFTP_REST },
174    { "append", zftp_getput, 1, -1, ZFTP_CONN|ZFTP_LOGI|ZFTP_APPE },
175    { "appendat", zftp_getput, 2, 2, ZFTP_CONN|ZFTP_LOGI|ZFTP_APPE|ZFTP_REST },
176    { "delete", zftp_delete, 1, -1, ZFTP_CONN|ZFTP_LOGI },
177    { "mkdir", zftp_mkdir, 1, 1, ZFTP_CONN|ZFTP_LOGI },
178    { "rmdir", zftp_mkdir, 1, 1, ZFTP_CONN|ZFTP_LOGI|ZFTP_DELE },
179    { "rename", zftp_rename, 2, 2, ZFTP_CONN|ZFTP_LOGI },
180    { "quote", zftp_quote, 1, -1, ZFTP_CONN },
181    { "site", zftp_quote, 1, -1, ZFTP_CONN|ZFTP_SITE },
182    { "close", zftp_close, 0, 0, ZFTP_CONN },
183    { "quit", zftp_close, 0, 0, ZFTP_CONN },
184    { "session", zftp_session, 0, 1, ZFTP_SESS },
185    { "rmsession", zftp_rmsession, 0, 1, ZFTP_SESS },
186    { 0, 0, 0, 0, 0 }
187};
188
189static struct builtin bintab[] = {
190    BUILTIN("zftp", 0, bin_zftp, 1, -1, 0, NULL, NULL),
191};
192
193/*
194 * these are the non-special params to unset when a connection
195 * closes.  any special params are handled, well, specially.
196 * currently there aren't any, which is the way I like it.
197 */
198static char *zfparams[] = {
199    "ZFTP_HOST", "ZFTP_PORT", "ZFTP_IP", "ZFTP_SYSTEM", "ZFTP_USER",
200    "ZFTP_ACCOUNT", "ZFTP_PWD", "ZFTP_TYPE", "ZFTP_MODE", NULL
201};
202
203/* flags for zfsetparam */
204
205enum {
206    ZFPM_READONLY = 0x01,	/* make parameter readonly */
207    ZFPM_IFUNSET  = 0x02,	/* only set if not already set */
208    ZFPM_INTEGER  = 0x04	/* passed pointer to off_t */
209};
210
211/* Number of connections actually open */
212static int zfnopen;
213
214/*
215 * zcfinish = 0 keep going
216 *            1 line finished, alles klar
217 *            2 EOF
218 */
219static int zcfinish;
220/* zfclosing is set if zftp_close() is active */
221static int zfclosing;
222
223/*
224 * Stuff about last message:  last line of message and status code.
225 * The reply is also stored in $ZFTP_REPLY; we keep these separate
226 * for convenience.
227 */
228static char *lastmsg, lastcodestr[4];
229static int lastcode;
230
231/* remote system has size, mdtm commands */
232enum {
233    ZFCP_UNKN = 0,		/* dunno if it works on this server */
234    ZFCP_YUPP = 1,		/* it does */
235    ZFCP_NOPE = 2		/* it doesn't */
236};
237
238/*
239 * We keep an fd open for communication between the main shell
240 * and forked off bits and pieces.  This allows us to know
241 * if something happend in a subshell:  mode changed, type changed,
242 * connection was closed.  If something too substantial happened
243 * in a subshell --- connection opened, ZFTP_USER and ZFTP_PWD changed
244 * --- we don't try to track it because it's too complicated.
245 */
246enum {
247    ZFST_ASCI = 0x0000,		/* type for next transfer is ASCII */
248    ZFST_IMAG = 0x0001,		/* type for next transfer is image */
249
250    ZFST_TMSK = 0x0001,		/* mask for type flags */
251    ZFST_TBIT = 0x0001,		/* number of bits in type flags */
252
253    ZFST_CASC = 0x0000,		/* current type is ASCII - default */
254    ZFST_CIMA = 0x0002,		/* current type is image */
255
256    ZFST_STRE = 0x0000,		/* stream mode - default */
257    ZFST_BLOC = 0x0004,		/* block mode */
258
259    ZFST_MMSK = 0x0004,		/* mask for mode flags */
260
261    ZFST_LOGI = 0x0008,		/* user logged in */
262    ZFST_SYST = 0x0010,		/* done system type check */
263    ZFST_NOPS = 0x0020,		/* server doesn't understand PASV */
264    ZFST_NOSZ = 0x0040,		/* server doesn't send `(XXXX bytes)' reply */
265    ZFST_TRSZ = 0x0080,		/* tried getting 'size' from reply */
266    ZFST_CLOS = 0x0100		/* connection closed */
267};
268#define ZFST_TYPE(x) (x & ZFST_TMSK)
269/*
270 * shift current type flags to match type flags: should be by
271 * the number of bits in the type flags
272 */
273#define ZFST_CTYP(x) ((x >> ZFST_TBIT) & ZFST_TMSK)
274#define ZFST_MODE(x) (x & ZFST_MMSK)
275
276/* fd containing status for all sessions and array for internal use */
277static int zfstatfd = -1, *zfstatusp;
278
279/* Preferences, read in from the `zftp_prefs' array variable */
280enum {
281    ZFPF_SNDP = 0x01,		/* Use send port mode */
282    ZFPF_PASV = 0x02,		/* Try using passive mode */
283    ZFPF_DUMB = 0x04		/* Don't do clever things with variables */
284};
285
286/* The flags as stored internally. */
287static int zfprefs;
288
289/*
290 * Data node for linked list of sessions.
291 *
292 * Memory management notes:
293 *   name is permanently allocated and remains for the life of the node.
294 *   userparams is set directly by zftp_params and also freed with the node.
295 *   params and its data are allocated when we need
296 *     to save an existing session, and are freed when we switch back
297 *     to that session.
298 *   The node itself is deleted when we remove it from the list.
299 */
300struct zftp_session {
301    char *name;			/* name of session */
302    char **params;		/* parameters ordered as in zfparams */
303    char **userparams;		/* user parameters set by zftp_params */
304    FILE *cin;			/* control input file */
305    Tcp_session control;	/* the control connection */
306    int dfd;			/* data connection */
307    int has_size;		/* understands SIZE? */
308    int has_mdtm;		/* understands MDTM? */
309};
310
311/* List of active sessions */
312static LinkList zfsessions;
313
314/* Current session */
315static Zftp_session zfsess;
316
317/* Number of current session, corresponding to position in list */
318static int zfsessno;
319
320/* Total number of sessions */
321static int zfsesscnt;
322
323/*
324 * Bits and pieces for dealing with SIGALRM (and SIGPIPE, but that's
325 * easier).  The complication is that SIGALRM may already be handled
326 * by the user setting TMOUT and possibly setting their own trap --- in
327 * fact, it's always handled by the shell when it's interactive.  It's
328 * too difficult to use zsh's own signal handler --- either it would
329 * need rewriting to use a C function as a trap, or we would need a
330 * hack to make it callback via a hidden builtin from a function --- so
331 * just install our own, and use settrap() to restore the behaviour
332 * afterwards if necessary.  However, the more that could be done by
333 * the main shell code, the better I would like it.
334 *
335 * Since we don't want to go through the palaver of changing between
336 * the main zsh signal handler and ours every time we start or stop the
337 * alarm, we keep the flag zfalarmed set to 1 while zftp is rigged to
338 * handle alarms.  This is tested at the end of bin_zftp(), which is
339 * the entry point for all functions, and that restores the original
340 * handler for SIGALRM.  To turn off the alarm temporarily in the zftp
341 * code we then just call alarm(0).
342 *
343 * If we could rely on having select() or some replacement, we would
344 * only need the alarm during zftp_open().
345 */
346
347/* flags for alarm set, alarm gone off */
348int zfalarmed, zfdrrrring;
349/* remember old alarm status */
350time_t oaltime;
351unsigned int oalremain;
352
353/*
354 * Where to jump to when the alarm goes off.  This is much
355 * easier than fiddling with error flags at every turn.
356 * Since we don't expect too many alarm's, the simple setjmp()
357 * mechanism should be good enough.
358 *
359 * gcc -O gives apparently spurious `may be clobbered by longjmp' warnings.
360 */
361jmp_buf zfalrmbuf;
362
363/* The signal handler itself */
364
365/**/
366static RETSIGTYPE
367zfhandler(int sig)
368{
369    if (sig == SIGALRM) {
370	zfdrrrring = 1;
371#ifdef ETIMEDOUT		/* just in case */
372	errno = ETIMEDOUT;
373#else
374	errno = EIO;
375#endif
376	longjmp(zfalrmbuf, 1);
377    }
378    DPUTS(1, "zfhandler caught incorrect signal");
379}
380
381/* Set up for an alarm call */
382
383/**/
384static void
385zfalarm(int tmout)
386{
387    zfdrrrring = 0;
388    /*
389     * We need to do this even if tmout is zero, since there may
390     * be a non-zero timeout set in the main shell which we don't
391     * want to go off.  This could be argued the other way, since
392     * if we don't get that it's probably harmless.  But this looks safer.
393     */
394    if (zfalarmed) {
395	alarm(tmout);
396	return;
397    }
398    signal(SIGALRM, zfhandler);
399    oalremain = alarm(tmout);
400    if (oalremain)
401	oaltime = time(NULL);
402    /*
403     * We'll leave sigtrapped, sigfuncs and TRAPXXX as they are; since the
404     * shell's handler doesn't get the signal, they don't matter.
405     */
406    zfalarmed = 1;
407}
408
409/* Set up for a broken pipe */
410
411/**/
412static void
413zfpipe()
414{
415    /* Just ignore SIGPIPE and rely on getting EPIPE from the write. */
416    signal(SIGPIPE, SIG_IGN);
417}
418
419/* Unset the alarm, see above */
420
421/**/
422static void
423zfunalarm(void)
424{
425    if (oalremain) {
426	/*
427	 * The alarm was previously set, so set it back, adjusting
428	 * for the time used.  Mostly the alarm was set to zero
429	 * beforehand, so it would probably be best to reinstall
430	 * the proper signal handler before resetting the alarm.
431	 *
432	 * I love the way alarm() uses unsigned int while time_t
433	 * is probably something completely different.
434	 */
435	unsigned int tdiff = time(NULL) - oaltime;
436	alarm(oalremain < tdiff ? 1 : oalremain - tdiff);
437    } else
438	alarm(0);
439    if (sigtrapped[SIGALRM] || interact) {
440	if (siglists[SIGALRM] || !sigtrapped[SIGALRM] ||
441	    (sigtrapped[SIGALRM] & ZSIG_FUNC))
442	    install_handler(SIGALRM);
443	else
444	    signal_ignore(SIGALRM);
445    } else
446	signal_default(SIGALRM);
447    zfalarmed = 0;
448}
449
450/* Restore SIGPIPE handling to its usual status */
451
452/**/
453static void
454zfunpipe()
455{
456    if (sigtrapped[SIGPIPE]) {
457	if (siglists[SIGPIPE] || (sigtrapped[SIGPIPE] & ZSIG_FUNC))
458	    install_handler(SIGPIPE);
459	else
460	    signal_ignore(SIGPIPE);
461    } else
462	signal_default(SIGPIPE);
463}
464
465/*
466 * Same as movefd(), but don't mark the fd in the zsh tables,
467 * because we only want it closed by zftp.  However, we still
468 * need to shift the fd's out of the way of the user-visible 0-9.
469 */
470
471/**/
472static int
473zfmovefd(int fd)
474{
475    if (fd != -1 && fd < 10) {
476#ifdef F_DUPFD
477	int fe = fcntl(fd, F_DUPFD, 10);
478#else
479	int fe = zfmovefd(dup(fd));
480#endif
481	close(fd);
482	fd = fe;
483    }
484    return fd;
485}
486
487/*
488 * set a non-special parameter.
489 * if ZFPM_IFUNSET, don't set if it already exists.
490 * if ZFPM_READONLY, make it readonly, but only when creating it.
491 * if ZFPM_INTEGER, val pointer is to off_t (NB not int), don't free.
492 */
493/**/
494static void
495zfsetparam(char *name, void *val, int flags)
496{
497    Param pm = NULL;
498    int type = (flags & ZFPM_INTEGER) ? PM_INTEGER : PM_SCALAR;
499
500    if (!(pm = (Param) paramtab->getnode(paramtab, name))
501	|| (pm->node.flags & PM_UNSET)) {
502	/*
503	 * just make it readonly when creating, in case user
504	 * *really* knows what they're doing
505	 */
506	if ((pm = createparam(name, type)) && (flags & ZFPM_READONLY))
507	    pm->node.flags |= PM_READONLY;
508    } else if (flags & ZFPM_IFUNSET) {
509	pm = NULL;
510    }
511    if (!pm || PM_TYPE(pm->node.flags) != type) {
512	/* parameters are funny, you just never know */
513	if (type == PM_SCALAR)
514	    zsfree((char *)val);
515	return;
516    }
517    if (type == PM_INTEGER)
518	pm->gsu.i->setfn(pm, *(off_t *)val);
519    else
520	pm->gsu.s->setfn(pm, (char *)val);
521}
522
523/*
524 * Unset a ZFTP parameter when the connection is closed.
525 * We only do this with connection-specific parameters.
526 */
527
528/**/
529static void
530zfunsetparam(char *name)
531{
532    Param pm;
533
534    if ((pm = (Param) paramtab->getnode(paramtab, name))) {
535	pm->node.flags &= ~PM_READONLY;
536	unsetparam_pm(pm, 0, 1);
537    }
538}
539
540/*
541 * Join command and arguments to make a proper TELNET command line.
542 * New line is in permanent storage.
543 */
544
545/**/
546static char *
547zfargstring(char *cmd, char **args)
548{
549    int clen = strlen(cmd) + 3;
550    char *line, **aptr;
551
552    for (aptr = args; *aptr; aptr++)
553	clen += strlen(*aptr) + 1;
554    line = zalloc(clen);
555    strcpy(line, cmd);
556    for (aptr = args; *aptr; aptr++) {
557	strcat(line, " ");
558	strcat(line, *aptr);
559    }
560    strcat(line, "\r\n");
561
562    return line;
563}
564
565/*
566 * get a line on the control connection according to TELNET rules
567 * Return status is first digit of FTP reply code
568 */
569
570/**/
571static int
572zfgetline(char *ln, int lnsize, int tmout)
573{
574    int ch, added = 0;
575    /* current line point */
576    char *pcur = ln, cmdbuf[3];
577
578    zcfinish = 0;
579    /* leave room for null byte */
580    lnsize--;
581    /* in case we return unexpectedly before getting anything */
582    ln[0] = '\0';
583
584    if (setjmp(zfalrmbuf)) {
585	alarm(0);
586	zwarnnam("zftp", "timeout getting response");
587	return 6;
588    }
589    zfalarm(tmout);
590
591    /*
592     * We need to be more careful about errors here; we
593     * should do the stuff with errflag and so forth.
594     * We should probably holdintr() here, since if we don't
595     * get the message, the connection is going to be messed up.
596     * But then we get `frustrated user syndrome'.
597     */
598    for (;;) {
599	ch = fgetc(zfsess->cin);
600
601	switch(ch) {
602	case EOF:
603	    if (ferror(zfsess->cin) && errno == EINTR) {
604		clearerr(zfsess->cin);
605		continue;
606	    }
607	    zcfinish = 2;
608	    break;
609
610	case '\r':
611	    /* always precedes something else */
612	    ch = fgetc(zfsess->cin);
613	    if (ch == EOF) {
614		zcfinish = 2;
615		break;
616	    }
617	    if (ch == '\n') {
618		zcfinish = 1;
619		break;
620	    }
621	    if (ch == '\0') {
622		ch = '\r';
623		break;
624	    }
625	    /* not supposed to get here */
626	    ch = '\r';
627	    break;
628
629	case '\n':
630	    /* not supposed to get here */
631	    zcfinish = 1;
632	    break;
633
634	case IAC:
635	    /*
636	     * oh great, now it's sending TELNET commands.  try
637	     * to persuade it not to.
638	     */
639	    ch = fgetc(zfsess->cin);
640	    switch (ch) {
641	    case WILL:
642	    case WONT:
643		ch = fgetc(zfsess->cin);
644		/* whatever it wants to do, stop it. */
645		cmdbuf[0] = (char)IAC;
646		cmdbuf[1] = (char)DONT;
647		cmdbuf[2] = ch;
648		write_loop(zfsess->control->fd, cmdbuf, 3);
649		continue;
650
651	    case DO:
652	    case DONT:
653		ch = fgetc(zfsess->cin);
654		/* well, tough, we're not going to. */
655		cmdbuf[0] = (char)IAC;
656		cmdbuf[1] = (char)WONT;
657		cmdbuf[2] = ch;
658		write_loop(zfsess->control->fd, cmdbuf, 3);
659		continue;
660
661	    case EOF:
662		/* strange machine. */
663		zcfinish = 2;
664		break;
665
666	    default:
667		break;
668	    }
669	    break;
670	}
671
672	if (zcfinish)
673	    break;
674	if (added < lnsize) {
675	    *pcur++ = ch;
676	    added++;
677	}
678	/* junk it if we don't have room, but go on reading */
679    }
680
681    alarm(0);
682
683    *pcur = '\0';
684    /* if zcfinish == 2, at EOF, return that, else 0 */
685    return (zcfinish & 2);
686}
687
688/*
689 * Get a whole message from the server.  A dash after
690 * the first line code means keep reading until we get
691 * a line with the same code followed by a space.
692 *
693 * Note that this returns an FTP status code, the first
694 * digit of the reply.  There is also a pseudocode, 6, which
695 * means `there's no point trying anything, just yet'.
696 * We return it either if the connection is closed, or if
697 * we got a 530 (user not logged in), in which case whatever
698 * you're trying to do isn't going to work.
699 */
700
701/**/
702static int
703zfgetmsg(void)
704{
705    char line[256], *ptr, *verbose;
706    int stopit, printing = 0, tmout;
707
708    if (!zfsess->control)
709	return 6;
710    zsfree(lastmsg);
711    lastmsg = NULL;
712
713    tmout = getiparam("ZFTP_TMOUT");
714
715    zfgetline(line, 256, tmout);
716    ptr = line;
717    if (zfdrrrring || !idigit(*ptr) || !idigit(ptr[1]) || !idigit(ptr[2])) {
718	/* timeout, or not talking FTP.  not really interested. */
719	zcfinish = 2;
720	if (!zfclosing)
721	    zfclose(0);
722	lastmsg = ztrdup("");
723	strcpy(lastcodestr, "000");
724	zfsetparam("ZFTP_REPLY", ztrdup(lastmsg), ZFPM_READONLY);
725	return 6;
726    }
727    strncpy(lastcodestr, ptr, 3);
728    ptr += 3;
729    lastcodestr[3] = '\0';
730    lastcode = atoi(lastcodestr);
731    zfsetparam("ZFTP_CODE", ztrdup(lastcodestr), ZFPM_READONLY);
732    stopit = (*ptr++ != '-');
733
734    queue_signals();
735    if (!(verbose = getsparam("ZFTP_VERBOSE")))
736	verbose = "";
737    if (strchr(verbose, lastcodestr[0])) {
738	/* print the whole thing verbatim */
739	printing = 1;
740	fputs(line, stderr);
741    }  else if (strchr(verbose, '0') && !stopit) {
742	/* print multiline parts with the code stripped */
743	printing = 2;
744	fputs(ptr, stderr);
745    }
746    unqueue_signals();
747    if (printing)
748	fputc('\n', stderr);
749
750    while (zcfinish != 2 && !stopit) {
751	zfgetline(line, 256, tmout);
752	ptr = line;
753	if (zfdrrrring) {
754	    line[0] = '\0';
755	    break;
756	}
757
758	if (!strncmp(lastcodestr, line, 3)) {
759	    if (line[3] == ' ') {
760		stopit = 1;
761		ptr += 4;
762	    } else if (line[3] == '-')
763		ptr += 4;
764	} else if (!strncmp("    ", line, 4))
765	    ptr += 4;
766
767	if (printing == 2) {
768	    if (!stopit) {
769		fputs(ptr, stderr);
770		fputc('\n', stderr);
771	    }
772	} else if (printing) {
773	    fputs(line, stderr);
774	    fputc('\n', stderr);
775	}
776    }
777
778    if (printing)
779	fflush(stderr);
780
781    /* The internal message is just the text. */
782    lastmsg = ztrdup(ptr);
783    /*
784     * The parameter is the whole thing, including the code.
785     */
786    zfsetparam("ZFTP_REPLY", ztrdup(line), ZFPM_READONLY);
787    /*
788     * close the connection here if zcfinish == 2, i.e. EOF,
789     * or if we get a 421 (service not available, closing connection),
790     * but don't do it if it's expected (zfclosing set).
791     */
792    if ((zcfinish == 2 || lastcode == 421) && !zfclosing) {
793	zcfinish = 2;		/* don't need to tell server */
794	zfclose(0);
795	/* unexpected, so tell user */
796	zwarnnam("zftp", "remote server has closed connection");
797	return 6;
798    }
799    if (lastcode == 530) {
800	/* user not logged in */
801	return 6;
802    }
803    /*
804     * May as well handle this here, though it's pretty uncommon.
805     * A 120 is something like "service ready in nnn minutes".
806     * It means we just hang around waiting for another reply.
807     */
808    if (lastcode == 120) {
809	zwarnnam("zftp", "delay expected, waiting: %s", lastmsg);
810	return zfgetmsg();
811    }
812
813    /* first digit of code determines success, failure, not in the mood... */
814    return lastcodestr[0] - '0';
815}
816
817
818/*
819 * Send a command and get the reply.
820 * The command is expected to have the \r\n already tacked on.
821 * Returns the status code for the reply.
822 */
823
824/**/
825static int
826zfsendcmd(char *cmd)
827{
828    /*
829     * We use the fd directly; there's no point even using
830     * stdio with line buffering, since we always send the
831     * complete line in one string anyway.
832     */
833    int ret, tmout;
834
835    if (!zfsess->control)
836	return 6;
837    tmout = getiparam("ZFTP_TMOUT");
838    if (setjmp(zfalrmbuf)) {
839	alarm(0);
840	zwarnnam("zftp", "timeout sending message");
841	return 6;
842    }
843    zfalarm(tmout);
844    ret = write(zfsess->control->fd, cmd, strlen(cmd));
845    alarm(0);
846
847    if (ret <= 0) {
848	zwarnnam("zftp send", "failure sending control message: %e", errno);
849	return 6;
850    }
851
852    return zfgetmsg();
853}
854
855
856/* Set up a data connection, return 1 for failure, 0 for success */
857
858/**/
859static int
860zfopendata(char *name, union tcp_sockaddr *zdsockp, int *is_passivep)
861{
862    if (!(zfprefs & (ZFPF_SNDP|ZFPF_PASV))) {
863	zwarnnam(name, "Must set preference S or P to transfer data");
864	return 1;
865    }
866    zfsess->dfd = socket(zfsess->control->peer.a.sa_family, SOCK_STREAM, 0);
867    if (zfsess->dfd < 0) {
868	zwarnnam(name, "can't get data socket: %e", errno);
869	return 1;
870    }
871
872    if (!(zfstatusp[zfsessno] & ZFST_NOPS) && (zfprefs & ZFPF_PASV)) {
873	char *psv_cmd;
874	int err, salen;
875
876#ifdef SUPPORT_IPV6
877	if(zfsess->control->peer.a.sa_family == AF_INET6)
878	    psv_cmd = "EPSV\r\n";
879	else
880#endif /* SUPPORT_IPV6 */
881	    psv_cmd = "PASV\r\n";
882	if (zfsendcmd(psv_cmd) == 6)
883	    return 1;
884	else if (lastcode >= 500 && lastcode <= 504) {
885	    /*
886	     * Fall back to send port mode.  That will
887	     * test the preferences for whether that's OK.
888	     */
889	    zfstatusp[zfsessno] |= ZFST_NOPS;
890	    zfclosedata();
891	    return zfopendata(name, zdsockp, is_passivep);
892	}
893	zdsockp->a.sa_family = zfsess->control->peer.a.sa_family;
894#ifdef SUPPORT_IPV6
895	if(zfsess->control->peer.a.sa_family == AF_INET6) {
896	    /* see RFC 2428 for explanation */
897	    char const *ptr, *end;
898	    char delim, portbuf[6], *pbp;
899	    unsigned long portnum;
900	    ptr = strchr(lastmsg, '(');
901	    if(!ptr) {
902	    bad_epsv:
903		zwarnnam(name, "bad response to EPSV: %s", lastmsg);
904		zfclosedata();
905		return 1;
906	    }
907	    delim = ptr[1];
908	    if(delim < 33 || delim > 126 || ptr[2] != delim || ptr[3] != delim)
909		goto bad_epsv;
910	    ptr += 4;
911	    end = strchr(ptr, delim);
912	    if(!end || end[1] != ')')
913		goto bad_epsv;
914	    while(ptr != end && *ptr == '0')
915		ptr++;
916	    if(ptr == end || (end-ptr) > 5 || !idigit(*ptr))
917		goto bad_epsv;
918	    memcpy(portbuf, ptr, (end-ptr));
919	    portbuf[end-ptr] = 0;
920	    portnum = strtoul(portbuf, &pbp, 10);
921	    if(*pbp || portnum > 65535UL)
922		goto bad_epsv;
923	    *zdsockp = zfsess->control->peer;
924	    zdsockp->in6.sin6_port = htons((unsigned)portnum);
925	    salen = sizeof(struct sockaddr_in6);
926	} else
927#endif /* SUPPORT_IPV6 */
928	{
929	    char *ptr;
930	    int i, nums[6];
931	    unsigned char iaddr[4], iport[2];
932
933	    /*
934	     * OK, now we need to know what port we're looking at,
935	     * which is cunningly concealed in the reply.
936	     * lastmsg already has the reply code expunged.
937	     */
938	    for (ptr = lastmsg; *ptr; ptr++)
939		if (idigit(*ptr))
940		    break;
941	    if (sscanf(ptr, "%d,%d,%d,%d,%d,%d",
942		       nums, nums+1, nums+2, nums+3, nums+4, nums+5) != 6) {
943		zwarnnam(name, "bad response to PASV: %s", lastmsg);
944		zfclosedata();
945		return 1;
946	    }
947	    for (i = 0; i < 4; i++)
948		iaddr[i] = STOUC(nums[i]);
949	    iport[0] = STOUC(nums[4]);
950	    iport[1] = STOUC(nums[5]);
951
952	    memcpy(&zdsockp->in.sin_addr, iaddr, sizeof(iaddr));
953	    memcpy(&zdsockp->in.sin_port, iport, sizeof(iport));
954	    salen = sizeof(struct sockaddr_in);
955	}
956
957	/* we should timeout this connect */
958	do {
959	    err = connect(zfsess->dfd, (struct sockaddr *)zdsockp, salen);
960	} while (err && errno == EINTR && !errflag);
961
962	if (err) {
963	    zwarnnam(name, "connect failed: %e", errno);
964	    zfclosedata();
965	    return 1;
966	}
967
968	*is_passivep = 1;
969    } else {
970#ifdef SUPPORT_IPV6
971	char portcmd[8+INET6_ADDRSTRLEN+9];
972#else
973	char portcmd[40];
974#endif
975	ZSOCKLEN_T len;
976	int ret;
977
978	if (!(zfprefs & ZFPF_SNDP)) {
979	    zwarnnam(name, "only sendport mode available for data");
980	    return 1;
981	}
982
983	*zdsockp = zfsess->control->sock;
984#ifdef SUPPORT_IPV6
985	if(zdsockp->a.sa_family == AF_INET6) {
986	    zdsockp->in6.sin6_port = 0;	/* to be set by bind() */
987	    len = sizeof(struct sockaddr_in6);
988	} else
989#endif /* SUPPORT_IPV6 */
990	{
991	    zdsockp->in.sin_port = 0;	/* to be set by bind() */
992	    len = sizeof(struct sockaddr_in);
993	}
994	/* need to do timeout stuff and probably handle EINTR here */
995	if (bind(zfsess->dfd, (struct sockaddr *)zdsockp, len) < 0)
996	    ret = 1;
997	else if (getsockname(zfsess->dfd, (struct sockaddr *)zdsockp,
998			     &len) < 0)
999	    ret = 2;
1000	else if (listen(zfsess->dfd, 1) < 0)
1001	    ret = 3;
1002	else
1003	    ret = 0;
1004
1005	if (ret) {
1006	    zwarnnam(name, "failure on data socket: %s: %e",
1007		     ret == 3 ? "listen" : ret == 2 ? "getsockname" : "bind",
1008		     errno);
1009	    zfclosedata();
1010	    return 1;
1011	}
1012
1013#ifdef SUPPORT_IPV6
1014	if(zdsockp->a.sa_family == AF_INET6) {
1015	    /* see RFC 2428 for explanation */
1016	    strcpy(portcmd, "EPRT |2|");
1017	    zsh_inet_ntop(AF_INET6, &zdsockp->in6.sin6_addr,
1018			  portcmd+8, INET6_ADDRSTRLEN);
1019	    sprintf(strchr(portcmd, 0), "|%u|\r\n",
1020		    (unsigned)ntohs(zdsockp->in6.sin6_port));
1021	} else
1022#endif /* SUPPORT_IPV6 */
1023	{
1024	    unsigned char *addr = (unsigned char *) &zdsockp->in.sin_addr;
1025	    unsigned char *port = (unsigned char *) &zdsockp->in.sin_port;
1026	    sprintf(portcmd, "PORT %d,%d,%d,%d,%d,%d\r\n",
1027		    addr[0],addr[1],addr[2],addr[3],port[0],port[1]);
1028	}
1029	if (zfsendcmd(portcmd) >= 5) {
1030	    zwarnnam(name, "port command failed");
1031	    zfclosedata();
1032	    return 1;
1033	}
1034	*is_passivep = 0;
1035    }
1036
1037    return 0;
1038}
1039
1040/* Close the data connection. */
1041
1042/**/
1043static void
1044zfclosedata(void)
1045{
1046    if (zfsess->dfd == -1)
1047	return;
1048    close(zfsess->dfd);
1049    zfsess->dfd = -1;
1050}
1051
1052/*
1053 * Set up a data connection and use cmd to initiate a transfer.
1054 * The actual data fd will be zfsess->dfd; the calling routine
1055 * must handle the data itself.
1056 * rest is a REST command to specify starting somewhere other
1057 * then the start of the remote file.
1058 * getsize is non-zero if we want to try to find the number
1059 * of bytes in the reply to a RETR command.
1060 *
1061 * Return 0 on success, 1 on failure.
1062 */
1063
1064/**/
1065static int
1066zfgetdata(char *name, char *rest, char *cmd, int getsize)
1067{
1068    ZSOCKLEN_T len;
1069    int newfd, is_passive;
1070    union tcp_sockaddr zdsock;
1071
1072    if (zfopendata(name, &zdsock, &is_passive))
1073	return 1;
1074
1075    /*
1076     * Set position in remote file for get/put.
1077     * According to RFC959, the restart command needs something
1078     * called a marker which has previously been put into the data.
1079     * Luckily for the real world, UNIX machines just interpret this
1080     * as an offset into the byte stream.
1081     *
1082     * This has to be sent immediately before the data transfer, i.e.
1083     * after all mucking around with types and sizes and so on.
1084     */
1085    if (rest && zfsendcmd(rest) > 3) {
1086	zfclosedata();
1087	return 1;
1088    }
1089
1090    if (zfsendcmd(cmd) > 2) {
1091	zfclosedata();
1092	return 1;
1093    }
1094    if (getsize || (!(zfstatusp[zfsessno] & ZFST_TRSZ) &&
1095		    !strncmp(cmd, "RETR", 4))) {
1096	/*
1097	 * See if we got something like:
1098	 *   Opening data connection for nortypix.gif (1234567 bytes).
1099	 * On the first RETR, always see if this works,  Then we
1100	 * can avoid sending a special SIZE command beforehand.
1101	 */
1102	char *ptr = strstr(lastmsg, "bytes");
1103	zfstatusp[zfsessno] |= ZFST_NOSZ|ZFST_TRSZ;
1104	if (ptr) {
1105	    while (ptr > lastmsg && !idigit(*ptr))
1106		ptr--;
1107	    while (ptr > lastmsg && idigit(ptr[-1]))
1108		ptr--;
1109	    if (idigit(*ptr)) {
1110		zfstatusp[zfsessno] &= ~ZFST_NOSZ;
1111		if (getsize) {
1112		    off_t sz = zstrtol(ptr, NULL, 10);
1113		    zfsetparam("ZFTP_SIZE", &sz, ZFPM_READONLY|ZFPM_INTEGER);
1114		}
1115	    }
1116	}
1117    }
1118
1119    if (!is_passive) {
1120	/*
1121	 * the current zfsess->dfd is the socket we opened, but we need
1122	 * to let the server set up a different fd for reading/writing.
1123	 * then we can close the fd we were listening for a connection on.
1124	 * don't expect me to understand this, i'm only the programmer.
1125	 */
1126
1127	/* accept the connection */
1128	len = sizeof(zdsock);
1129	newfd = zfmovefd(accept(zfsess->dfd, (struct sockaddr *)&zdsock,
1130				&len));
1131	if (newfd < 0)
1132	    zwarnnam(name, "unable to accept data: %e", errno);
1133	zfclosedata();
1134	if (newfd < 0)
1135	    return 1;
1136	zfsess->dfd = newfd;	/* this is now the actual data fd */
1137    } else {
1138	/*
1139	 * We avoided dup'ing zfsess->dfd up to this point, to try to keep
1140	 * things simple, so we now need to move it out of the way
1141	 * of the user-visible fd's.
1142	 */
1143	zfsess->dfd = zfmovefd(zfsess->dfd);
1144    }
1145
1146
1147    /* more options, just to look professional */
1148#ifdef SO_LINGER
1149    /*
1150     * Since data can take arbitrary amounts of time to arrive,
1151     * the socket can be made to hang around until it doesn't think
1152     * anything is arriving.
1153     *
1154     * In BSD 4.3, you could only linger for infinity.  Don't
1155     * know if this has changed.
1156     */
1157    {
1158	struct linger li;
1159
1160	li.l_onoff = 1;
1161	li.l_linger = 120;
1162	setsockopt(zfsess->dfd, SOL_SOCKET, SO_LINGER,
1163		   (char *)&li, sizeof(li));
1164    }
1165#endif
1166#if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
1167    /* try to get high throughput, snigger */
1168    {
1169	int arg = IPTOS_THROUGHPUT;
1170	setsockopt(zfsess->dfd, IPPROTO_IP, IP_TOS, (char *)&arg, sizeof(arg));
1171    }
1172#endif
1173#if defined(F_SETFD) && defined(FD_CLOEXEC)
1174    /* If the shell execs a program, we don't want this fd left open. */
1175    fcntl(zfsess->dfd, F_SETFD, FD_CLOEXEC);
1176#endif
1177
1178    return 0;
1179}
1180
1181/*
1182 * Find out about a local or remote file and pass back the information.
1183 *
1184 * We could jigger this to use ls like ncftp does as a backup.
1185 * But if the server is non-standard enough not to have SIZE and MDTM,
1186 * there's a very good chance ls -l isn't going to do great things.
1187 *
1188 * if fd is >= 0, it is used for an fstat when remote is zero:
1189 * this is because on a put we are taking input from fd 0.
1190 */
1191
1192/**/
1193static int
1194zfstats(char *fnam, int remote, off_t *retsize, char **retmdtm, int fd)
1195{
1196    off_t sz = -1;
1197    char *mt = NULL;
1198    int ret;
1199
1200    if (retsize)
1201	*retsize = -1;
1202    if (retmdtm)
1203	*retmdtm = NULL;
1204    if (remote) {
1205	char *cmd;
1206	if ((zfsess->has_size == ZFCP_NOPE && retsize) ||
1207	    (zfsess->has_mdtm == ZFCP_NOPE && retmdtm))
1208	    return 2;
1209
1210	/*
1211	 * File is coming from over there.
1212	 * Make sure we get the type right.
1213	 */
1214	zfsettype(ZFST_TYPE(zfstatusp[zfsessno]));
1215	if (retsize) {
1216	    cmd = tricat("SIZE ", fnam, "\r\n");
1217	    ret = zfsendcmd(cmd);
1218	    zsfree(cmd);
1219	    if (ret == 6)
1220		return 1;
1221	    else if (lastcode < 300) {
1222		sz = zstrtol(lastmsg, 0, 10);
1223		zfsess->has_size = ZFCP_YUPP;
1224	    } else if (lastcode >= 500 && lastcode <= 504) {
1225		zfsess->has_size = ZFCP_NOPE;
1226		return 2;
1227	    } else if (lastcode == 550)
1228		return 1;
1229	    /* if we got a 550 from SIZE, the file doesn't exist */
1230	}
1231
1232	if (retmdtm) {
1233	    cmd = tricat("MDTM ", fnam, "\r\n");
1234	    ret = zfsendcmd(cmd);
1235	    zsfree(cmd);
1236	    if (ret == 6)
1237		return 1;
1238	    else if (lastcode < 300) {
1239		mt = ztrdup(lastmsg);
1240		zfsess->has_mdtm = ZFCP_YUPP;
1241	    } else if (lastcode >= 500 && lastcode <= 504) {
1242		zfsess->has_mdtm = ZFCP_NOPE;
1243		return 2;
1244	    } else if (lastcode == 550)
1245		return 1;
1246	}
1247    } else {
1248	/* File is over here */
1249	struct stat statbuf;
1250	struct tm *tm;
1251	char tmbuf[20];
1252
1253	if ((fd == -1 ? stat(fnam, &statbuf) : fstat(fd, &statbuf)) < 0)
1254	    return 1;
1255	/* make sure it's off_t, since this has to be a pointer */
1256	sz = statbuf.st_size;
1257
1258	if (retmdtm) {
1259	    /* use gmtime() rather than localtime() for consistency */
1260	    tm = gmtime(&statbuf.st_mtime);
1261	    /*
1262	     * FTP format for data is YYYYMMDDHHMMSS
1263	     * Using tm directly is easier than worrying about
1264	     * incompatible strftime()'s.
1265	     */
1266	    sprintf(tmbuf, "%04d%02d%02d%02d%02d%02d",
1267		    tm->tm_year + 1900, tm->tm_mon+1, tm->tm_mday,
1268		    tm->tm_hour, tm->tm_min, tm->tm_sec);
1269	    mt = ztrdup(tmbuf);
1270	}
1271    }
1272    if (retsize)
1273	*retsize = sz;
1274    if (retmdtm)
1275	*retmdtm = mt;
1276    return 0;
1277}
1278
1279/* Set parameters to say what's coming */
1280
1281/**/
1282static void
1283zfstarttrans(char *nam, int recv, off_t sz)
1284{
1285    off_t cnt = 0;
1286    /*
1287     * sz = -1 signifies error getting size.  don't set ZFTP_SIZE if sz is
1288     * zero, either: it probably came from an fstat() on a pipe, so it
1289     * means we don't know and shouldn't tell the user porkies.
1290     */
1291    if (sz > 0)
1292	zfsetparam("ZFTP_SIZE", &sz, ZFPM_READONLY|ZFPM_INTEGER);
1293    zfsetparam("ZFTP_FILE", ztrdup(nam), ZFPM_READONLY);
1294    zfsetparam("ZFTP_TRANSFER", ztrdup(recv ? "G" : "P"), ZFPM_READONLY);
1295    zfsetparam("ZFTP_COUNT", &cnt, ZFPM_READONLY|ZFPM_INTEGER);
1296}
1297
1298/* Tidy up afterwards */
1299
1300/**/
1301static void
1302zfendtrans()
1303{
1304    zfunsetparam("ZFTP_SIZE");
1305    zfunsetparam("ZFTP_FILE");
1306    zfunsetparam("ZFTP_TRANSFER");
1307    zfunsetparam("ZFTP_COUNT");
1308}
1309
1310/* Read with timeout if recv is set. */
1311
1312/**/
1313static int
1314zfread(int fd, char *bf, off_t sz, int tmout)
1315{
1316    int ret;
1317
1318    if (!tmout)
1319	return read(fd, bf, sz);
1320
1321    if (setjmp(zfalrmbuf)) {
1322	alarm(0);
1323	zwarnnam("zftp", "timeout on network read");
1324	return -1;
1325    }
1326    zfalarm(tmout);
1327
1328    ret = read(fd, bf, sz);
1329
1330    /* we don't bother turning off the whole alarm mechanism here */
1331    alarm(0);
1332    return ret;
1333}
1334
1335/* Write with timeout if recv is not set. */
1336
1337/**/
1338static int
1339zfwrite(int fd, char *bf, off_t sz, int tmout)
1340{
1341    int ret;
1342
1343    if (!tmout)
1344	return write(fd, bf, sz);
1345
1346    if (setjmp(zfalrmbuf)) {
1347	alarm(0);
1348	zwarnnam("zftp", "timeout on network write");
1349	return -1;
1350    }
1351    zfalarm(tmout);
1352
1353    ret = write(fd, bf, sz);
1354
1355    /* we don't bother turning off the whole alarm mechanism here */
1356    alarm(0);
1357    return ret;
1358}
1359
1360static int zfread_eof;
1361
1362/* Version of zfread when we need to read in block mode. */
1363
1364/**/
1365static int
1366zfread_block(int fd, char *bf, off_t sz, int tmout)
1367{
1368    int n;
1369    struct zfheader hdr;
1370    off_t blksz, cnt;
1371    char *bfptr;
1372    do {
1373	/* we need the header */
1374	do {
1375	    n = zfread(fd, (char *)&hdr, sizeof(hdr), tmout);
1376	} while (n < 0 && errno == EINTR);
1377	if (n != 3 && !zfdrrrring) {
1378	    zwarnnam("zftp", "failure reading FTP block header");
1379	    return n;
1380	}
1381	/* size is stored in network byte order */
1382	if (hdr.flags & ZFHD_EOFB)
1383	    zfread_eof = 1;
1384	blksz = (hdr.bytes[0] << 8) | hdr.bytes[1];
1385	if (blksz > sz) {
1386	    /*
1387	     * See comments in file headers
1388	     */
1389	    zwarnnam("zftp", "block too large to handle");
1390	    errno = EIO;
1391	    return -1;
1392	}
1393	bfptr = bf;
1394	cnt = blksz;
1395	while (cnt) {
1396	    n = zfread(fd, bfptr, cnt, tmout);
1397	    if (n > 0) {
1398		bfptr += n;
1399		cnt -= n;
1400	    } else if (n < 0 && (errflag || zfdrrrring || errno != EINTR))
1401		return n;
1402	    else
1403		break;
1404	}
1405	if (cnt) {
1406	    zwarnnam("zftp", "short data block");
1407	    errno = EIO;
1408	    return -1;
1409	}
1410    } while ((hdr.flags & ZFHD_MARK) && !zfread_eof);
1411    return (hdr.flags & ZFHD_MARK) ? 0 : blksz;
1412}
1413
1414/* Version of zfwrite when we need to write in block mode. */
1415
1416/**/
1417static int
1418zfwrite_block(int fd, char *bf, off_t sz, int tmout)
1419{
1420    int n;
1421    struct zfheader hdr;
1422    off_t cnt;
1423    char *bfptr;
1424    /* we need the header */
1425    do {
1426	hdr.bytes[0] = (sz & 0xff00) >> 8;
1427	hdr.bytes[1] = sz & 0xff;
1428	hdr.flags = sz ? 0 : ZFHD_EOFB;
1429	n = zfwrite(fd, (char *)&hdr, sizeof(hdr), tmout);
1430    } while (n < 0 && errno == EINTR);
1431    if (n != 3 && !zfdrrrring) {
1432	zwarnnam("zftp", "failure writing FTP block header");
1433	return n;
1434    }
1435    bfptr = bf;
1436    cnt = sz;
1437    while (cnt) {
1438	n = zfwrite(fd, bfptr, cnt, tmout);
1439	if (n > 0) {
1440	    bfptr += n;
1441	    cnt -= n;
1442	} else if (n < 0 && (errflag || zfdrrrring || errno != EINTR))
1443	    return n;
1444    }
1445
1446    return sz;
1447}
1448
1449/*
1450 * Move stuff from fdin to fdout, tidying up the data connection
1451 * when finished.  The data connection could be either input or output:
1452 * recv is 1 for receiving a file, 0 for sending.
1453 *
1454 * progress is 1 to use a progress meter.
1455 * startat says how far in we're starting with a REST command.
1456 *
1457 * Since we're doing some buffering here anyway, we don't bother
1458 * with a stdio layer.
1459 */
1460
1461/**/
1462static int
1463zfsenddata(char *name, int recv, int progress, off_t startat)
1464{
1465#define ZF_BUFSIZE 32768
1466#define ZF_ASCSIZE (ZF_BUFSIZE/2)
1467    /* ret = 2 signals the local read/write failed, so send abort */
1468    int n, ret = 0, gotack = 0, fdin, fdout, fromasc = 0, toasc = 0;
1469    int rtmout = 0, wtmout = 0;
1470    char lsbuf[ZF_BUFSIZE], *ascbuf = NULL, *optr;
1471    off_t sofar = 0, last_sofar = 0;
1472    readwrite_t read_ptr = zfread, write_ptr = zfwrite;
1473    Shfunc shfunc;
1474
1475    if (progress && (shfunc = getshfunc("zftp_progress"))) {
1476	/*
1477	 * progress to set up:  ZFTP_COUNT is zero.
1478	 * We do this here in case we needed to wait for a RETR
1479	 * command to tell us how many bytes are coming.
1480	 */
1481	int osc = sfcontext;
1482
1483	sfcontext = SFC_HOOK;
1484	doshfunc(shfunc, NULL, 1);
1485	sfcontext = osc;
1486	/* Now add in the bit of the file we've got/sent already */
1487	sofar = last_sofar = startat;
1488    }
1489    if (recv) {
1490	fdin = zfsess->dfd;
1491	fdout = 1;
1492	rtmout = getiparam("ZFTP_TMOUT");
1493	if (ZFST_CTYP(zfstatusp[zfsessno]) == ZFST_ASCI)
1494	    fromasc = 1;
1495	if (ZFST_MODE(zfstatusp[zfsessno]) == ZFST_BLOC)
1496	    read_ptr = zfread_block;
1497    } else {
1498	fdin = 0;
1499	fdout = zfsess->dfd;
1500	wtmout = getiparam("ZFTP_TMOUT");
1501	if (ZFST_CTYP(zfstatusp[zfsessno]) == ZFST_ASCI)
1502	    toasc = 1;
1503	if (ZFST_MODE(zfstatusp[zfsessno]) == ZFST_BLOC)
1504	    write_ptr = zfwrite_block;
1505    }
1506
1507    if (toasc)
1508	ascbuf = zalloc(ZF_ASCSIZE);
1509    zfpipe();
1510    zfread_eof = 0;
1511    while (!ret && !zfread_eof) {
1512	n = (toasc) ? read_ptr(fdin, ascbuf, ZF_ASCSIZE, rtmout)
1513	    : read_ptr(fdin, lsbuf, ZF_BUFSIZE, rtmout);
1514	if (n > 0) {
1515	    char *iptr;
1516	    if (toasc) {
1517		/* \n -> \r\n it shouldn't happen to a dog. */
1518		char *iptr = ascbuf, *optr = lsbuf;
1519		int cnt = n;
1520		while (cnt--) {
1521		    if (*iptr == '\n') {
1522			*optr++ = '\r';
1523			n++;
1524		    }
1525		    *optr++ = *iptr++;
1526		}
1527	    }
1528	    if (fromasc && (iptr = memchr(lsbuf, '\r', n))) {
1529		/* \r\n -> \n */
1530		char *optr = iptr;
1531		int cnt = n - (iptr - lsbuf);
1532		while (cnt--) {
1533		    if (*iptr != '\r' || iptr[1] != '\n') {
1534			*optr++ = *iptr;
1535		    } else
1536			n--;
1537		    iptr++;
1538		}
1539	    }
1540	    optr = lsbuf;
1541
1542	    sofar += n;
1543
1544	    for (;;) {
1545		/*
1546		 * in principle, write can be interrupted after
1547		 * safely writing some bytes, and will return the
1548		 * number already written, which may not be the
1549		 * complete buffer.  so make this robust.  they call me
1550		 * `robustness stephenson'.  in my dreams.
1551		 */
1552		int newn = write_ptr(fdout, optr, n, wtmout);
1553		if (newn == n)
1554		    break;
1555		if (newn < 0) {
1556		    /*
1557		     * The somewhat contorted test here (for write)
1558		     * and below (for read) means:
1559		     * real error if
1560		     *  - errno is set and it's not just an interrupt, or
1561		     *  - errflag is set, probably due to CTRL-c, or
1562		     *  - zfdrrrring is set, due to the alarm going off.
1563		     * print an error message if
1564		     *  - not a timeout, since that was reported, and
1565		     *    either
1566		     *    - a non-interactive shell, where we don't
1567		     *      know what happened otherwise
1568		     *    - or both of
1569		     *      - not errflag, i.e. CTRL-c or what have you,
1570		     *        since the user probably knows about that, and
1571		     *      - not a SIGPIPE, since usually people are
1572		     *        silent about those when going to pagers
1573		     *        (if you quit less or more in the middle
1574		     *        and see an error message you think `I
1575		     *        shouldn't have done that').
1576		     *
1577		     * If we didn't print an error message here,
1578		     * and were going to do an abort (ret == 2)
1579		     * because the error happened on the local end
1580		     * of the connection, set ret to 3 and don't print
1581		     * the 'aborting...' either.
1582		     *
1583		     * There must be a better way of doing this.
1584		     */
1585		    if (errno != EINTR || errflag || zfdrrrring) {
1586			if (!zfdrrrring &&
1587			    (!interact || (!errflag && errno != EPIPE))) {
1588			    ret = recv ? 2 : 1;
1589			    zwarnnam(name, "write failed: %e", errno);
1590			} else
1591			    ret = recv ? 3 : 1;
1592			break;
1593		    }
1594		    continue;
1595		}
1596		optr += newn;
1597		n -= newn;
1598	    }
1599	} else if (n < 0) {
1600	    if (errno != EINTR || errflag || zfdrrrring) {
1601		if (!zfdrrrring &&
1602		    (!interact || (!errflag && errno != EPIPE))) {
1603		    ret = recv ? 1 : 2;
1604		    zwarnnam(name, "read failed: %e", errno);
1605		} else
1606		    ret = recv ? 1 : 3;
1607		break;
1608	    }
1609	} else
1610	    break;
1611	if (!ret && sofar != last_sofar && progress &&
1612	    (shfunc = getshfunc("zftp_progress"))) {
1613	    int osc = sfcontext;
1614
1615	    zfsetparam("ZFTP_COUNT", &sofar, ZFPM_READONLY|ZFPM_INTEGER);
1616	    sfcontext = SFC_HOOK;
1617	    doshfunc(shfunc, NULL, 1);
1618	    sfcontext = osc;
1619	    last_sofar = sofar;
1620	}
1621    }
1622    zfunpipe();
1623    /*
1624     * At this point any timeout was on the data connection,
1625     * so we don't need to force the control connection to close.
1626     */
1627    zfdrrrring = 0;
1628    if (!errflag && !ret && !recv &&
1629	ZFST_MODE(zfstatusp[zfsessno]) == ZFST_BLOC) {
1630	/* send an end-of-file marker block */
1631	ret = (zfwrite_block(fdout, lsbuf, 0, wtmout) < 0);
1632    }
1633    if (errflag || ret > 1) {
1634	/*
1635	 * some error occurred, maybe a keyboard interrupt, or
1636	 * a local file/pipe handling problem.
1637	 * send an abort.
1638	 *
1639	 * safest to block all signals here?  can get frustrating if
1640	 * we're waiting for an abort.  don't I know.  let's start
1641	 * off just by blocking SIGINT's.
1642	 *
1643	 * maybe the timeout for the abort should be shorter than
1644	 * for normal commands.  and what about aborting after
1645	 * we had a timeout on the data connection, is that
1646	 * really a good idea?
1647	 */
1648	/* RFC 959 says this is what to send */
1649	unsigned char msg[4] = { IAC, IP, IAC, SYNCH };
1650
1651	if (ret == 2)
1652	    zwarnnam(name, "aborting data transfer...");
1653
1654	holdintr();
1655
1656	/* the following is black magic, as far as I'm concerned. */
1657	/* what are we going to do if it fails?  not a lot, actually. */
1658	send(zfsess->control->fd, (char *)msg, 3, 0);
1659	send(zfsess->control->fd, (char *)msg+3, 1, MSG_OOB);
1660
1661	zfsendcmd("ABOR\r\n");
1662	if (lastcode == 226) {
1663	    /*
1664	     * 226 is supposed to mean the transfer got sent OK after
1665	     * all, and the abort got ignored, at least that's what
1666	     * rfc959 seems to be saying.  but in fact what can happen
1667	     * is the transfer finishes (at least as far as the
1668	     * server's concerned) and it's response is waiting, then
1669	     * the abort gets sent, and we need to mop up a response to
1670	     * that.  so actually in most cases we get two replies
1671	     * anyway.  we could test if we had select() on all hosts.
1672	     */
1673	    /* gotack = 1; */
1674	    /*
1675	     * we'd better leave errflag, since we don't know
1676	     * where it came from.  maybe the user wants to abort
1677	     * a whole script or function.
1678	     */
1679	} else
1680	    ret = 1;
1681
1682	noholdintr();
1683    }
1684
1685    if (toasc)
1686	zfree(ascbuf, ZF_ASCSIZE);
1687    zfclosedata();
1688    if (!gotack && zfgetmsg() > 2)
1689	ret = 1;
1690    return ret != 0;
1691}
1692
1693/* Open a new control connection, i.e. start a new FTP session */
1694
1695/**/
1696static int
1697zftp_open(char *name, char **args, int flags)
1698{
1699    struct protoent *zprotop;
1700    struct servent *zservp;
1701    struct hostent *zhostp;
1702    char **addrp, *fname, *tmpptr, *portnam = "ftp";
1703    char *hostnam, *hostsuffix;
1704    int err, tmout, port = -1;
1705    ZSOCKLEN_T  len;
1706    int herrno, af, hlen;
1707
1708    if (!*args) {
1709	if (zfsess->userparams)
1710	    args = zfsess->userparams;
1711	else {
1712	    zwarnnam(name, "no host specified");
1713	    return 1;
1714	}
1715    }
1716
1717    /*
1718     * Close the existing connection if any.
1719     * Probably this is the safest thing to do.  It's possible
1720     * a `QUIT' will hang, though.
1721     */
1722    if (zfsess->control)
1723	zfclose(0);
1724
1725    hostnam = dupstring(args[0]);
1726    /*
1727     * Check for IPv6 address in square brackets (RFC2732).
1728     * We are more lenient and allow any form for the host here.
1729     */
1730    if (hostnam[0] == '[') {
1731	hostnam++;
1732	hostsuffix = strchr(hostnam, ']');
1733	if (!hostsuffix || (hostsuffix[1] && hostsuffix[1] != ':')) {
1734	    zwarnnam(name, "Invalid host format: %s", hostnam);
1735	    return 1;
1736	}
1737	*hostsuffix++ = '\0';
1738    }
1739    else
1740	hostsuffix = hostnam;
1741
1742    if ((tmpptr = strchr(hostsuffix, ':'))) {
1743	char *endptr;
1744
1745	*tmpptr++ = '\0';
1746	port = (int)zstrtol(tmpptr, &endptr, 10);
1747	/*
1748	 * If the port is not numeric, look it up by name below.
1749	 */
1750	if (*endptr) {
1751	    portnam = tmpptr;
1752	    port = -1;
1753	}
1754#if defined(HAVE_NTOHS) && defined(HAVE_HTONS)
1755	else {
1756	    port = (int)htons((unsigned short)port);
1757	}
1758#endif
1759    }
1760
1761    /* this is going to give 0.  why bother? */
1762    zprotop = getprotobyname("tcp");
1763    if (!zprotop) {
1764	zwarnnam(name, "Can't find protocol TCP (is your network functional)?");
1765	return 1;
1766    }
1767    if (port < 0)
1768	zservp = getservbyname(portnam, "tcp");
1769    else
1770	zservp = getservbyport(port, "tcp");
1771
1772    if (!zprotop || !zservp) {
1773	zwarnnam(name, "Can't find port for service `%s'", portnam);
1774	return 1;
1775    }
1776
1777    /* don't try talking to server yet */
1778    zcfinish = 2;
1779
1780    /*
1781     * This sets an alarm for the whole process, getting the host name
1782     * as well as connecting.  Arguably you could time them out separately.
1783     */
1784    tmout = getiparam("ZFTP_TMOUT");
1785    if (setjmp(zfalrmbuf)) {
1786	char *hname;
1787	alarm(0);
1788	queue_signals();
1789	if ((hname = getsparam("ZFTP_HOST")) && *hname)
1790	    zwarnnam(name, "timeout connecting to %s", hname);
1791	else
1792	    zwarnnam(name, "timeout on host name lookup");
1793	unqueue_signals();
1794	zfclose(0);
1795	return 1;
1796    }
1797    zfalarm(tmout);
1798
1799#ifdef SUPPORT_IPV6
1800    for(af=AF_INET6; 1; af = AF_INET)
1801# define SUCCEEDED() break
1802# define FAILED() if(af == AF_INET) { } else continue
1803#else
1804	af = AF_INET;
1805# define SUCCEEDED() do { } while(0)
1806# define FAILED() do { } while(0)
1807#endif
1808    {
1809	off_t tcp_port;
1810
1811	zhostp = zsh_getipnodebyname(hostnam, af, 0, &herrno);
1812	if (!zhostp || errflag) {
1813	    /* should use herror() here if available, but maybe
1814	     * needs configure test. on AIX it's present but not
1815	     * in headers.
1816	     *
1817	     * on the other hand, herror() is obsolete
1818	     */
1819	    FAILED();
1820	    zwarnnam(name, "host not found: %s", hostnam);
1821	    alarm(0);
1822	    return 1;
1823	}
1824	zfsetparam("ZFTP_HOST", ztrdup(zhostp->h_name), ZFPM_READONLY);
1825	/* careful with pointer types */
1826#if defined(HAVE_NTOHS) && defined(HAVE_HTONS)
1827	tcp_port = (off_t)ntohs((unsigned short)zservp->s_port);
1828#else
1829	tcp_port = (off_t)zservp->s_port;
1830#endif
1831	zfsetparam("ZFTP_PORT", &tcp_port, ZFPM_READONLY|ZFPM_INTEGER);
1832
1833#ifdef SUPPORT_IPV6
1834	if(af == AF_INET6) {
1835	    hlen = 16;
1836	} else
1837#endif /* SUPPORT_IPV6 */
1838	{
1839	    hlen = 4;
1840	}
1841
1842	zfsess->control = tcp_socket(af, SOCK_STREAM, 0, ZTCP_ZFTP);
1843
1844	if (!(zfsess->control) || (zfsess->control->fd < 0)) {
1845	    if (zfsess->control) {
1846		tcp_close(zfsess->control);
1847		zfsess->control = NULL;
1848	    }
1849	    freehostent(zhostp);
1850	    zfunsetparam("ZFTP_HOST");
1851	    zfunsetparam("ZFTP_PORT");
1852	    FAILED();
1853	    zwarnnam(name, "socket failed: %e", errno);
1854	    alarm(0);
1855	    return 1;
1856	}
1857	/* counts as `open' so long as it's not negative */
1858	zfnopen++;
1859
1860	/*
1861	 * now connect the socket.  manual pages all say things like `this is
1862	 * all explained oh-so-wonderfully in some other manual page'.  not.
1863	 */
1864
1865	err = 1;
1866
1867	/* try all possible IP's */
1868	for (addrp = zhostp->h_addr_list; err && *addrp; addrp++) {
1869	    if(hlen != zhostp->h_length)
1870		zwarnnam(name, "address length mismatch");
1871	    do {
1872		err = tcp_connect(zfsess->control, *addrp, zhostp, zservp->s_port);
1873	    } while (err && errno == EINTR && !errflag);
1874	    /* you can check whether it's worth retrying here */
1875	}
1876
1877	if (err) {
1878	    freehostent(zhostp);
1879	    zfclose(0);
1880	    FAILED();
1881	    zwarnnam(name, "connect failed: %e", errno);
1882	    alarm(0);
1883	    return 1;
1884	}
1885
1886	SUCCEEDED();
1887    }
1888    alarm(0);
1889    {
1890#ifdef SUPPORT_IPV6
1891	char pbuf[INET6_ADDRSTRLEN];
1892#else
1893	char pbuf[INET_ADDRSTRLEN];
1894#endif
1895	addrp--;
1896	zsh_inet_ntop(af, *addrp, pbuf, sizeof(pbuf));
1897	zfsetparam("ZFTP_IP", ztrdup(pbuf), ZFPM_READONLY);
1898    }
1899    freehostent(zhostp);
1900    /* now we can talk to the control connection */
1901    zcfinish = 0;
1902
1903    /*
1904     * Move the fd out of the user-visible range.  We need to do
1905     * this after the connect() on some systems.
1906     */
1907    zfsess->control->fd = zfmovefd(zfsess->control->fd);
1908
1909#if defined(F_SETFD) && defined(FD_CLOEXEC)
1910    /* If the shell execs a program, we don't want this fd left open. */
1911    fcntl(zfsess->control->fd, F_SETFD, FD_CLOEXEC);
1912#endif
1913
1914    len = sizeof(zfsess->control->sock);
1915    if (getsockname(zfsess->control->fd, (struct sockaddr *)&zfsess->control->sock, &len) < 0) {
1916	zwarnnam(name, "getsockname failed: %e", errno);
1917	zfclose(0);
1918	return 1;
1919    }
1920    /* nice to get some options right, ignore if they don't work */
1921#ifdef SO_OOBINLINE
1922    /*
1923     * this says we want messages in line.  maybe sophisticated people
1924     * do clever things with SIGURG.
1925     */
1926    len = 1;
1927    setsockopt(zfsess->control->fd, SOL_SOCKET, SO_OOBINLINE,
1928	       (char *)&len, sizeof(len));
1929#endif
1930#if defined(IP_TOS) && defined(IPTOS_LOWDELAY)
1931    /* for control connection we want low delay.  please don't laugh. */
1932    len = IPTOS_LOWDELAY;
1933    setsockopt(zfsess->control->fd, IPPROTO_IP, IP_TOS, (char *)&len, sizeof(len));
1934#endif
1935
1936    /*
1937     * We use stdio with line buffering for convenience on input.
1938     * On output, we can just dump a complete message to the fd via write().
1939     */
1940    zfsess->cin = fdopen(zfsess->control->fd, "r");
1941
1942    if (!zfsess->cin) {
1943	zwarnnam(name, "file handling error");
1944	zfclose(0);
1945	return 1;
1946    }
1947
1948#ifdef _IONBF
1949    setvbuf(zfsess->cin, NULL, _IONBF, 0);
1950#else
1951    setlinebuf(zfsess->cin);
1952#endif
1953
1954    /*
1955     * now see what the remote server has to say about that.
1956     */
1957    if (zfgetmsg() >= 4) {
1958	zfclose(0);
1959	return 1;
1960    }
1961
1962    zfsess->has_size = zfsess->has_mdtm = ZFCP_UNKN;
1963    zfsess->dfd = -1;
1964    /* initial status: open, ASCII data, stream mode 'n' stuff */
1965    zfstatusp[zfsessno] = 0;
1966
1967    /*
1968     * Open file for saving the current status.
1969     * We keep this open at the end of the session because
1970     * it is used to store the status for all sessions.
1971     * However, it is closed whenever there are no connections open.
1972     */
1973    if (zfstatfd == -1) {
1974	zfstatfd = gettempfile(NULL, 1, &fname);
1975	DPUTS(zfstatfd == -1, "zfstatfd not created");
1976#if defined(F_SETFD) && defined(FD_CLOEXEC)
1977	/* If the shell execs a program, we don't want this fd left open. */
1978	fcntl(zfstatfd, F_SETFD, FD_CLOEXEC);
1979#endif
1980	unlink(fname);
1981    }
1982
1983    if (zfsess->control->fd == -1) {
1984	/* final paranoid check */
1985	tcp_close(zfsess->control);
1986	zfsess->control = NULL;
1987	zfnopen--;
1988    } else {
1989	zfsetparam("ZFTP_MODE", ztrdup("S"), ZFPM_READONLY);
1990	/* if remaining arguments, use them to log in. */
1991	if (*++args)
1992	    return zftp_login(name, args, flags);
1993    }
1994    /* if something wayward happened, connection was already closed */
1995    return !zfsess->control;
1996}
1997
1998/*
1999 * Read a parameter string, with a prompt if reading from stdin.
2000 * The returned string is on the heap.
2001 * If noecho, turn off ECHO mode while reading.
2002 */
2003
2004/**/
2005static char *
2006zfgetinfo(char *prompt, int noecho)
2007{
2008    int resettty = 0;
2009    /* 256 characters should be enough, hardly worth allocating
2010     * a password string byte by byte
2011     */
2012    char instr[256], *strret;
2013    int len;
2014
2015    /*
2016     * Only print the prompt if getting info from a tty.  Of
2017     * course, we don't know if stderr has been redirected, but
2018     * that seems a minor point.
2019     */
2020    if (isatty(0)) {
2021	if (noecho) {
2022	    /* hmmm... all this great big shell and we have to read
2023	     * something with no echo by ourselves.
2024	     * bin_read() is far to complicated for our needs.
2025	     * we could use zread(), but that relies on static
2026	     * variables, so someone doesn't want that to happen.
2027	     *
2028	     * this is modified from setcbreak() in utils.c,
2029	     * except I don't see any point in using cbreak mode
2030	     */
2031	    struct ttyinfo ti;
2032
2033	    ti = shttyinfo;
2034#ifdef HAS_TIO
2035	    ti.tio.c_lflag &= ~ECHO;
2036#else
2037	    ti.sgttyb.sg_flags &= ~ECHO;
2038#endif
2039	    settyinfo(&ti);
2040	    resettty = 1;
2041	}
2042	fflush(stdin);
2043	fputs(prompt, stderr);
2044	fflush(stderr);
2045    }
2046
2047    if (fgets(instr, 256, stdin) == NULL)
2048	instr[len = 0] = '\0';
2049    else if (instr[len = strlen(instr)-1] == '\n')
2050	instr[len] = '\0';
2051
2052    strret = dupstring(instr);
2053
2054    if (resettty) {
2055	/* '\n' didn't get echoed */
2056	fputc('\n', stdout);
2057	fflush(stdout);
2058	settyinfo(&shttyinfo);
2059    }
2060
2061    return strret;
2062}
2063
2064/*
2065 * set params for an open with no arguments.
2066 * this allows easy re-opens.
2067 */
2068
2069/**/
2070static int
2071zftp_params(UNUSED(char *name), char **args, UNUSED(int flags))
2072{
2073    char *prompts[] = { "Host: ", "User: ", "Password: ", "Account: " };
2074    char **aptr, **newarr;
2075    int i, j, len;
2076
2077    if (!*args) {
2078	if (zfsess->userparams) {
2079	    for (aptr = zfsess->userparams, i = 0; *aptr; aptr++, i++) {
2080		if (i == 2) {
2081		    len = strlen(*aptr);
2082		    for (j = 0; j < len; j++)
2083			fputc('*', stdout);
2084		    fputc('\n', stdout);
2085		} else
2086		    fprintf(stdout, "%s\n", *aptr);
2087	    }
2088	    return 0;
2089	} else
2090	    return 1;
2091    }
2092    if (!strcmp(*args, "-")) {
2093	if (zfsess->userparams)
2094	    freearray(zfsess->userparams);
2095	zfsess->userparams = 0;
2096	return 0;
2097    }
2098    len = arrlen(args);
2099    newarr = (char **)zshcalloc((len+1)*sizeof(char *));
2100    for (aptr = args, i = 0; *aptr && !errflag; aptr++, i++) {
2101	char *str;
2102	if (**aptr == '?')
2103	    str = zfgetinfo((*aptr)[1] ? (*aptr+1) : prompts[i], i == 2);
2104	else
2105	    str = (**aptr == '\\') ? *aptr+1 : *aptr;
2106	newarr[i] = ztrdup(str);
2107    }
2108    if (errflag) {
2109	/* maybe user CTRL-c'd in the middle somewhere */
2110	for (aptr = newarr; *aptr; aptr++)
2111	    zsfree(*aptr);
2112	zfree(newarr, len+1);
2113	return 1;
2114    }
2115    if (zfsess->userparams)
2116	freearray(zfsess->userparams);
2117    zfsess->userparams = newarr;
2118    return 0;
2119}
2120
2121/* login a user:  often called as part of the open sequence */
2122
2123/**/
2124static int
2125zftp_login(char *name, char **args, UNUSED(int flags))
2126{
2127    char *ucmd, *passwd = NULL, *acct = NULL;
2128    char *user, tbuf[2] = "X";
2129    int stopit;
2130
2131    if ((zfstatusp[zfsessno] & ZFST_LOGI) && zfsendcmd("REIN\r\n") >= 4)
2132	return 1;
2133
2134    zfstatusp[zfsessno] &= ~ZFST_LOGI;
2135    if (*args) {
2136	user = *args++;
2137    } else {
2138	user = zfgetinfo("User: ", 0);
2139    }
2140
2141    ucmd = tricat("USER ", user, "\r\n");
2142    stopit = 0;
2143
2144    if (zfsendcmd(ucmd) == 6)
2145	stopit = 2;
2146
2147    while (!stopit && !errflag) {
2148	switch (lastcode) {
2149	case 230: /* user logged in */
2150	case 202: /* command not implemented, don't care */
2151	    stopit = 1;
2152	    break;
2153
2154	case 331: /* need password */
2155	    if (*args)
2156		passwd = *args++;
2157	    else
2158		passwd = zfgetinfo("Password: ", 1);
2159	    zsfree(ucmd);
2160	    ucmd = tricat("PASS ", passwd, "\r\n");
2161	    if (zfsendcmd(ucmd) == 6)
2162		stopit = 2;
2163	    break;
2164
2165	case 332: /* need account */
2166	case 532:
2167	    if (*args)
2168		acct = *args++;
2169	    else
2170		acct = zfgetinfo("Account: ", 0);
2171	    zsfree(ucmd);
2172	    ucmd = tricat("ACCT ", acct, "\r\n");
2173	    if (zfsendcmd(ucmd) == 6)
2174		stopit = 2;
2175	    break;
2176
2177	case 421: /* service not available, so closed anyway */
2178	case 501: /* syntax error */
2179	case 503: /* bad commands */
2180	case 530: /* not logged in */
2181	case 550: /* random can't-do-that */
2182	default:  /* whatever, should flag this as bad karma */
2183	    /* need more diagnostics here */
2184	    stopit = 2;
2185	    break;
2186	}
2187    }
2188
2189    zsfree(ucmd);
2190    if (!zfsess->control)
2191	return 1;
2192    if (stopit == 2 || (lastcode != 230 && lastcode != 202)) {
2193	zwarnnam(name, "login failed");
2194	return 1;
2195    }
2196
2197    if (*args) {
2198	int cnt;
2199	for (cnt = 0; *args; args++)
2200	    cnt++;
2201	zwarnnam(name, "warning: %d command arguments not used\n", cnt);
2202    }
2203    zfstatusp[zfsessno] |= ZFST_LOGI;
2204    zfsetparam("ZFTP_USER", ztrdup(user), ZFPM_READONLY);
2205    if (acct)
2206	zfsetparam("ZFTP_ACCOUNT", ztrdup(acct), ZFPM_READONLY);
2207
2208    /*
2209     * Now find out what system we're connected to. Some systems
2210     * won't let us do this until we're logged in; it's fairly safe
2211     * to delay it here for all systems.
2212     */
2213    if (!(zfprefs & ZFPF_DUMB) && !(zfstatusp[zfsessno] & ZFST_SYST)) {
2214	if (zfsendcmd("SYST\r\n") == 2) {
2215	    char *ptr = lastmsg, *eptr, *systype;
2216	    for (eptr = ptr; *eptr; eptr++)
2217		;
2218	    systype = ztrduppfx(ptr, eptr-ptr);
2219	    if (!strncmp(systype, "UNIX Type: L8", 13)) {
2220		/*
2221		 * Use binary for transfers.  This simple test saves much
2222		 * hassle for all concerned, particularly me.
2223		 *
2224		 * We could set this based just on the UNIX part,
2225		 * but I don't really know the consequences of that.
2226		 */
2227		zfstatusp[zfsessno] |= ZFST_IMAG;
2228	    }
2229	    zfsetparam("ZFTP_SYSTEM", systype, ZFPM_READONLY);
2230	}
2231	zfstatusp[zfsessno] |= ZFST_SYST;
2232    }
2233    tbuf[0] = (ZFST_TYPE(zfstatusp[zfsessno]) == ZFST_ASCI) ? 'A' : 'I';
2234    zfsetparam("ZFTP_TYPE", ztrdup(tbuf), ZFPM_READONLY);
2235
2236    /*
2237     * Get the directory.  This is possibly an unnecessary overhead, of
2238     * course, but when you're being driven by shell functions there's
2239     * just no way of telling.
2240     */
2241    return zfgetcwd();
2242}
2243
2244/*
2245 * See if the server wants to tell us something.  On a timeout, we usually
2246 * have a `421 Timeout' or something such waiting for us, so we read
2247 * it here.  As well as being called explicitly by the user
2248 * (precmd is a very good place for this, it's cheap since it has
2249 * no network overhead), we call it in the bin_zftp front end if we
2250 * have a connection and weren't going to call it anyway.
2251 *
2252 * Poll-free and select-free systems are few and far between these days,
2253 * but I'm willing to consider suggestions.
2254 */
2255
2256/**/
2257static int
2258zftp_test(UNUSED(char *name), UNUSED(char **args), UNUSED(int flags))
2259{
2260#if defined(HAVE_POLL) || defined(HAVE_SELECT)
2261    int ret;
2262# ifdef HAVE_POLL
2263    struct pollfd pfd;
2264# else
2265    fd_set f;
2266    struct timeval tv;
2267# endif /* HAVE_POLL */
2268
2269    if (!zfsess->control)
2270	return 1;
2271
2272# ifdef HAVE_POLL
2273#  ifndef POLLIN
2274    /* safety first, though I think POLLIN is more common */
2275#   define POLLIN POLLNORM
2276#  endif /* HAVE_POLL */
2277    pfd.fd = zfsess->control->fd;
2278    pfd.events = POLLIN;
2279    if ((ret = poll(&pfd, 1, 0)) < 0 && errno != EINTR && errno != EAGAIN)
2280	zfclose(0);
2281    else if (ret > 0 && pfd.revents) {
2282	/* handles 421 (maybe a bit noisily?) */
2283	zfgetmsg();
2284    }
2285# else
2286    FD_ZERO(&f);
2287    FD_SET(zfsess->control->fd, &f);
2288    tv.tv_sec = 0;
2289    tv.tv_usec = 0;
2290    if ((ret = select(zfsess->control->fd +1, (SELECT_ARG_2_T) &f,
2291		      NULL, NULL, &tv)) < 0
2292	&& errno != EINTR)
2293	zfclose(0);
2294    else if (ret > 0) {
2295	/* handles 421 */
2296	zfgetmsg();
2297    }
2298# endif /* HAVE_POLL */
2299    /* if we have no zfsess->control, then we've just been dumped out. */
2300    return zfsess->control ? 0 : 2;
2301#else
2302    zfwarnnam(name, "not supported on this system.");
2303    return 3;
2304#endif /* defined(HAVE_POLL) || defined(HAVE_SELECT) */
2305}
2306
2307
2308/* do ls or dir on the remote directory */
2309
2310/**/
2311static int
2312zftp_dir(char *name, char **args, int flags)
2313{
2314    /* maybe should be cleverer about handling arguments */
2315    char *cmd;
2316    int ret;
2317
2318    /*
2319     * RFC959 says this must be ASCII or EBCDIC, not image format.
2320     * I rather suspect on a UNIX server we get away handsomely
2321     * with doing everything, including this, as image.
2322     */
2323    zfsettype(ZFST_ASCI);
2324
2325    cmd = zfargstring((flags & ZFTP_NLST) ? "NLST" : "LIST", args);
2326    ret = zfgetdata(name, NULL, cmd, 0);
2327    zsfree(cmd);
2328    if (ret)
2329	return 1;
2330
2331    fflush(stdout);		/* since we're now using fd 1 */
2332    return zfsenddata(name, 1, 0, 0);
2333}
2334
2335/* change the remote directory */
2336
2337/**/
2338static int
2339zftp_cd(UNUSED(char *name), char **args, int flags)
2340{
2341    /* change directory --- enhance to allow 'zftp cdup' */
2342    int ret;
2343
2344    if ((flags & ZFTP_CDUP) || !strcmp(*args, "..") ||
2345	!strcmp(*args, "../")) {
2346	ret = zfsendcmd("CDUP\r\n");
2347    } else {
2348	char *cmd = tricat("CWD ", *args, "\r\n");
2349	ret = zfsendcmd(cmd);
2350	zsfree(cmd);
2351    }
2352    if (ret > 2)
2353	return 1;
2354    /* sometimes the directory may be in the response. usually not. */
2355    if (zfgetcwd())
2356	return 1;
2357
2358    return 0;
2359}
2360
2361/* get the remote directory */
2362
2363/**/
2364static int
2365zfgetcwd(void)
2366{
2367    char *ptr, *eptr;
2368    int endc;
2369    Shfunc shfunc;
2370
2371    if (zfprefs & ZFPF_DUMB)
2372	return 1;
2373    if (zfsendcmd("PWD\r\n") > 2) {
2374	zfunsetparam("ZFTP_PWD");
2375	return 1;
2376    }
2377    ptr = lastmsg;
2378    while (*ptr == ' ')
2379	ptr++;
2380    if (!*ptr)			/* ultra safe */
2381	return 1;
2382    if (*ptr == '"') {
2383	ptr++;
2384	endc = '"';
2385    } else
2386	endc = ' ';
2387    for (eptr = ptr; *eptr && *eptr != endc; eptr++)
2388	;
2389    zfsetparam("ZFTP_PWD", ztrduppfx(ptr, eptr-ptr), ZFPM_READONLY);
2390
2391    /*
2392     * This isn't so necessary if we're going to have a shell function
2393     * front end.  By putting it here, and in close when ZFTP_PWD is unset,
2394     * we at least cover the bases.
2395     */
2396    if ((shfunc = getshfunc("zftp_chpwd"))) {
2397	int osc = sfcontext;
2398
2399	sfcontext = SFC_HOOK;
2400	doshfunc(shfunc, NULL, 1);
2401	sfcontext = osc;
2402    }
2403    return 0;
2404}
2405
2406/*
2407 * Set the type for the next transfer, usually image (binary) or ASCII.
2408 */
2409
2410/**/
2411static int
2412zfsettype(int type)
2413{
2414    char buf[] = "TYPE X\r\n";
2415    if (ZFST_TYPE(type) == ZFST_CTYP(zfstatusp[zfsessno]))
2416	return 0;
2417    buf[5] = (ZFST_TYPE(type) == ZFST_ASCI) ? 'A' : 'I';
2418    if (zfsendcmd(buf) > 2)
2419	return 1;
2420    zfstatusp[zfsessno] &= ~(ZFST_TMSK << ZFST_TBIT);
2421    /* shift the type left to set the current type bits */;
2422    zfstatusp[zfsessno] |= type << ZFST_TBIT;
2423    return 0;
2424}
2425
2426/*
2427 * Print or get a new type for the transfer.
2428 * We don't actually set the type at this point.
2429 */
2430
2431/**/
2432static int
2433zftp_type(char *name, char **args, int flags)
2434{
2435    char *str, nt, tbuf[2] = "A";
2436    if (flags & (ZFTP_TBIN|ZFTP_TASC)) {
2437	nt = (flags & ZFTP_TBIN) ? 'I' : 'A';
2438    } else if (!(str = *args)) {
2439	/*
2440	 * Since this is supposed to be a low-level basis for
2441	 * an FTP system, just print the single code letter.
2442	 */
2443	printf("%c\n", (ZFST_TYPE(zfstatusp[zfsessno]) == ZFST_ASCI) ?
2444	       'A' : 'I');
2445	fflush(stdout);
2446	return 0;
2447    } else {
2448	nt = toupper(STOUC(*str));
2449	/*
2450	 * RFC959 specifies other types, but these are the only
2451	 * ones we know what to do with.
2452	 */
2453	if (str[1] || (nt != 'A' && nt != 'B' && nt != 'I')) {
2454	    zwarnnam(name, "transfer type %s not recognised", str);
2455	    return 1;
2456	}
2457
2458	if (nt == 'B')		/* binary = image */
2459	    nt = 'I';
2460    }
2461
2462    zfstatusp[zfsessno] &= ~ZFST_TMSK;
2463    zfstatusp[zfsessno] |= (nt == 'I') ? ZFST_IMAG : ZFST_ASCI;
2464    tbuf[0] = nt;
2465    zfsetparam("ZFTP_TYPE", ztrdup(tbuf), ZFPM_READONLY);
2466    return 0;
2467}
2468
2469/**/
2470static int
2471zftp_mode(char *name, char **args, UNUSED(int flags))
2472{
2473    char *str, cmd[] = "MODE X\r\n";
2474    int nt;
2475
2476    if (!(str = *args)) {
2477	printf("%c\n", (ZFST_MODE(zfstatusp[zfsessno]) == ZFST_STRE) ?
2478	       'S' : 'B');
2479	fflush(stdout);
2480	return 0;
2481    }
2482    nt = str[0] = toupper(STOUC(*str));
2483    if (str[1] || (nt != 'S' && nt != 'B')) {
2484	zwarnnam(name, "transfer mode %s not recognised", str);
2485	return 1;
2486    }
2487    cmd[5] = (char) nt;
2488    if (zfsendcmd(cmd) > 2)
2489	return 1;
2490    zfstatusp[zfsessno] &= ZFST_MMSK;
2491    zfstatusp[zfsessno] |= (nt == 'S') ? ZFST_STRE : ZFST_BLOC;
2492    zfsetparam("ZFTP_MODE", ztrdup(str), ZFPM_READONLY);
2493    return 0;
2494}
2495
2496/**/
2497static int
2498zftp_local(UNUSED(char *name), char **args, int flags)
2499{
2500    int more = !!args[1], ret = 0, dofd = !*args;
2501    while (*args || dofd) {
2502	off_t sz;
2503	char *mt;
2504	int newret = zfstats(*args, !(flags & ZFTP_HERE), &sz, &mt,
2505			     dofd ? 0 : -1);
2506	if (newret == 2)	/* at least one is not implemented */
2507	    return 2;
2508	else if (newret) {
2509	    ret = 1;
2510	    if (mt)
2511		zsfree(mt);
2512	    args++;
2513	    continue;
2514	}
2515	if (more) {
2516	    fputs(*args, stdout);
2517	    fputc(' ', stdout);
2518	}
2519#ifdef OFF_T_IS_64_BIT
2520	printf("%s %s\n", output64(sz), mt);
2521#else
2522	DPUTS(sizeof(sz) > 4, "Shell compiled with wrong off_t size");
2523	printf("%ld %s\n", (long)sz, mt);
2524#endif
2525	zsfree(mt);
2526	if (dofd)
2527	    break;
2528	args++;
2529    }
2530    fflush(stdout);
2531
2532    return ret;
2533}
2534
2535/*
2536 * Generic transfer for get, put and append.
2537 *
2538 * Get sends all files to stdout, i.e. this is basically cat. It's up to a
2539 * shell function driver to turn this into standard FTP-like commands.
2540 *
2541 * Put/append sends everything from stdin down the drai^H^H^Hata connection.
2542 * Slightly weird with multiple files in that it tries to read
2543 * a separate complete file from stdin each time, which is
2544 * only even potentially useful interactively.  But the only
2545 * real alternative is just to allow one file at a time.
2546 */
2547
2548/**/
2549static int
2550zftp_getput(char *name, char **args, int flags)
2551{
2552    int ret = 0, recv = (flags & ZFTP_RECV), getsize = 0, progress = 1;
2553    char *cmd = recv ? "RETR " : (flags & ZFTP_APPE) ? "APPE " : "STOR ";
2554    Shfunc shfunc;
2555
2556    /*
2557     * At this point I'd like to set progress to 0 if we're
2558     * backgrounded, since it's hard for the user to find out.
2559     * It turns out it's hard enough for us to find out.
2560     * The problem is that zsh clears it's job table, so we
2561     * just don't know if we're some forked shell in a pipeline
2562     * somewhere or in the background.  This seems to me a problem.
2563     */
2564
2565    zfsettype(ZFST_TYPE(zfstatusp[zfsessno]));
2566
2567    if (recv)
2568	fflush(stdout);		/* since we may be using fd 1 */
2569    for (; *args; args++) {
2570	char *ln, *rest = NULL;
2571	off_t startat = 0;
2572	if (progress && (shfunc = getshfunc("zftp_progress"))) {
2573	    off_t sz = -1;
2574	    /*
2575	     * This calls the SIZE command to get the size for remote
2576	     * files.  Some servers send the size with the reply to
2577	     * the transfer command (i.e. RETR), in which
2578	     * case we note the fact and don't call this
2579	     * next time.  For that reason, the first call
2580	     * of zftp_progress is delayed until zfsenddata().
2581	     */
2582	    if ((!(zfprefs & ZFPF_DUMB) &&
2583		 (zfstatusp[zfsessno] & (ZFST_NOSZ|ZFST_TRSZ)) != ZFST_TRSZ)
2584		|| !recv) {
2585		/* the final 0 is a local fd to fstat if recv is zero */
2586		zfstats(*args, recv, &sz, NULL, 0);
2587		/* even if it doesn't support SIZE, it may tell us */
2588		if (recv && sz == -1)
2589		    getsize = 1;
2590	    } else
2591		getsize = 1;
2592	    zfstarttrans(*args, recv, sz);
2593	}
2594
2595	if (flags & ZFTP_REST) {
2596	    startat = zstrtol(args[1], NULL, 10);
2597	    rest = tricat("REST ", args[1], "\r\n");
2598	}
2599
2600	ln = tricat(cmd, *args, "\r\n");
2601	/* note zfsess->dfd doesn't exist till zfgetdata() creates it */
2602	if (zfgetdata(name, rest, ln, getsize))
2603	    ret = 2;
2604	else if (zfsenddata(name, recv, progress, startat))
2605	    ret = 1;
2606	zsfree(ln);
2607	/*
2608	 * The progress report isn't started till zfsenddata(), where
2609	 * it's the first item.  Hence we send a final progress report
2610	 * if and only if we called zfsenddata();
2611	 */
2612	if (progress && ret != 2 &&
2613	    (shfunc = getshfunc("zftp_progress"))) {
2614	    /* progress to finish: ZFTP_TRANSFER set to GF or PF */
2615	    int osc = sfcontext;
2616
2617	    zfsetparam("ZFTP_TRANSFER", ztrdup(recv ? "GF" : "PF"),
2618		       ZFPM_READONLY);
2619	    sfcontext = SFC_HOOK;
2620	    doshfunc(shfunc, NULL, 1);
2621	    sfcontext = osc;
2622	}
2623	if (rest) {
2624	    zsfree(rest);
2625	    args++;
2626	}
2627	if (errflag)
2628	    break;
2629    }
2630    zfendtrans();
2631    return ret != 0;
2632}
2633
2634/*
2635 * Delete a list of files on the server.  We allow a list by analogy with
2636 * `rm'.
2637 */
2638
2639/**/
2640static int
2641zftp_delete(UNUSED(char *name), char **args, UNUSED(int flags))
2642{
2643    int ret = 0;
2644    char *cmd, **aptr;
2645    for (aptr = args; *aptr; aptr++) {
2646	cmd = tricat("DELE ", *aptr, "\r\n");
2647	if (zfsendcmd(cmd) > 2)
2648	    ret = 1;
2649	zsfree(cmd);
2650    }
2651    return ret;
2652}
2653
2654/* Create or remove a directory on the server */
2655
2656/**/
2657static int
2658zftp_mkdir(UNUSED(char *name), char **args, int flags)
2659{
2660    int ret;
2661    char *cmd = tricat((flags & ZFTP_DELE) ? "RMD " : "MKD ",
2662		       *args, "\r\n");
2663    ret = (zfsendcmd(cmd) > 2);
2664    zsfree(cmd);
2665    return ret;
2666}
2667
2668/* Rename a file on the server */
2669
2670/**/
2671static int
2672zftp_rename(UNUSED(char *name), char **args, UNUSED(int flags))
2673{
2674    int ret;
2675    char *cmd;
2676
2677    cmd = tricat("RNFR ", args[0], "\r\n");
2678    ret = 1;
2679    if (zfsendcmd(cmd) == 3) {
2680	zsfree(cmd);
2681	cmd = tricat("RNTO ", args[1], "\r\n");
2682	if (zfsendcmd(cmd) == 2)
2683	    ret = 0;
2684    }
2685    zsfree(cmd);
2686    return ret;
2687}
2688
2689/*
2690 * Send random commands, either with SITE or literal.
2691 * In the second case, the user better know what they're doing.
2692 */
2693
2694/**/
2695static int
2696zftp_quote(UNUSED(char *name), char **args, int flags)
2697{
2698    int ret = 0;
2699    char *cmd;
2700
2701    cmd = (flags & ZFTP_SITE) ? zfargstring("SITE", args)
2702	: zfargstring(args[0], args+1);
2703    ret = (zfsendcmd(cmd) > 2);
2704    zsfree(cmd);
2705
2706    return ret;
2707}
2708
2709/*
2710 * Close the connection, ending the session.  With leaveparams,
2711 * don't do anything to the external status (parameters, zftp_chpwd),
2712 * probably because this isn't the current session.
2713 */
2714
2715/**/
2716static void
2717zfclose(int leaveparams)
2718{
2719    char **aptr;
2720    Shfunc shfunc;
2721
2722    if (!zfsess->control)
2723	return;
2724
2725    zfclosing = 1;
2726    if (zcfinish != 2) {
2727	/*
2728	 * haven't had EOF from server, so send a QUIT and get the response.
2729	 * maybe we should set a shorter timeout for this to avoid
2730	 * CTRL-c rage.
2731	 */
2732	zfsendcmd("QUIT\r\n");
2733    }
2734    if (zfsess->cin) {
2735	/*
2736	 * We fdopen'd the TCP control fd; since we can't fdclose it,
2737	 * we need to perform a full fclose, which invalidates the
2738	 * TCP fd.  We need to do this before closing the FILE, since
2739	 * it's not usable afterwards.
2740	 */
2741	if (fileno(zfsess->cin) == zfsess->control->fd)
2742	    zfsess->control->fd = -1;
2743	fclose(zfsess->cin);
2744	zfsess->cin = NULL;
2745    }
2746    if (zfsess->control) {
2747	zfnopen--;
2748	tcp_close(zfsess->control);
2749	/* We leak if the above failed */
2750	zfsess->control = NULL;
2751    }
2752
2753    if (zfstatfd != -1) {
2754	zfstatusp[zfsessno] |= ZFST_CLOS;
2755	if (!zfnopen) {
2756	    /* Write the final status in case this is a subshell */
2757	    lseek(zfstatfd, zfsessno*sizeof(int), 0);
2758	    write_loop(zfstatfd, (char *)zfstatusp+zfsessno, sizeof(int));
2759
2760	    close(zfstatfd);
2761	    zfstatfd = -1;
2762	}
2763    }
2764
2765    if (!leaveparams) {
2766	/* Unset the non-special parameters */
2767	for (aptr = zfparams; *aptr; aptr++)
2768	    zfunsetparam(*aptr);
2769
2770	/* Now ZFTP_PWD is unset.  It's up to zftp_chpwd to notice. */
2771	if ((shfunc = getshfunc("zftp_chpwd"))) {
2772	    int osc = sfcontext;
2773
2774	    sfcontext = SFC_HOOK;
2775	    doshfunc(shfunc, NULL, 1);
2776	    sfcontext = osc;
2777	}
2778    }
2779
2780    /* tidy up status variables, because mess is bad */
2781    zfclosing = zfdrrrring = 0;
2782}
2783
2784/* Safe front end to zftp_close() from within the package */
2785
2786/**/
2787static int
2788zftp_close(UNUSED(char *name), UNUSED(char **args), UNUSED(int flags))
2789{
2790    zfclose(0);
2791    return 0;
2792}
2793
2794
2795/*
2796 * Session management routines.  A session consists of various
2797 * internal variables describing the connection, the set of shell
2798 * parameters --- the same set which is unset by closing a connection ---
2799 * and the set of host/user parameters if set by zftp params.
2800 */
2801
2802/*
2803 * Switch to a new session, creating it if necessary.
2804 * Sets zfsessno, zfsess and $ZFTP_SESSION; updates zfsesscnt and zfstatusp.
2805 */
2806
2807/**/
2808static void
2809newsession(char *nm)
2810{
2811    LinkNode nptr;
2812
2813    for (zfsessno = 0, nptr = firstnode(zfsessions);
2814	 nptr; zfsessno++, incnode(nptr)) {
2815	zfsess = (Zftp_session) nptr->dat;
2816	if (!strcmp(zfsess->name, nm))
2817	    break;
2818    }
2819
2820    if (!nptr) {
2821	zfsess = (Zftp_session) zshcalloc(sizeof(struct zftp_session));
2822	zfsess->name = ztrdup(nm);
2823	zfsess->dfd = -1;
2824	zfsess->params = (char **) zshcalloc(sizeof(zfparams));
2825	zaddlinknode(zfsessions, zfsess);
2826
2827	zfsesscnt++;
2828	zfstatusp = (int *)zrealloc(zfstatusp, sizeof(int)*zfsesscnt);
2829	zfstatusp[zfsessno] = 0;
2830    }
2831
2832    zfsetparam("ZFTP_SESSION", ztrdup(zfsess->name), ZFPM_READONLY);
2833}
2834
2835/* Save the existing session: this just means saving the parameters. */
2836
2837static void
2838savesession()
2839{
2840    char **ps, **pd, *val;
2841
2842    for (ps = zfparams, pd = zfsess->params; *ps; ps++, pd++) {
2843	if (*pd)
2844	    zsfree(*pd);
2845	queue_signals();
2846	if ((val = getsparam(*ps)))
2847	    *pd = ztrdup(val);
2848	else
2849	    *pd = NULL;
2850	unqueue_signals();
2851    }
2852    *pd = NULL;
2853}
2854
2855/*
2856 * Switch to session nm, creating it if necessary.
2857 * Just call newsession, then set up the session-specific parameters.
2858 */
2859
2860/**/
2861static void
2862switchsession(char *nm)
2863{
2864    char **ps, **pd;
2865
2866    newsession(nm);
2867
2868    for (ps = zfparams, pd = zfsess->params; *ps; ps++, pd++) {
2869	if (*pd) {
2870	    /* Use the permanently allocated string for the parameter */
2871	    zfsetparam(*ps, *pd, ZFPM_READONLY);
2872	    *pd = NULL;
2873	} else
2874	    zfunsetparam(*ps);
2875    }
2876}
2877
2878/**/
2879static void
2880freesession(Zftp_session sptr)
2881{
2882    char **ps, **pd;
2883    zsfree(sptr->name);
2884    for (ps = zfparams, pd = zfsess->params; *ps; ps++, pd++)
2885	if (*pd)
2886	    zsfree(*pd);
2887    zfree(zfsess->params, sizeof(zfparams));
2888    if (sptr->userparams)
2889	freearray(sptr->userparams);
2890    zfree(sptr, sizeof(struct zftp_session));
2891}
2892
2893/**/
2894static int
2895zftp_session(UNUSED(char *name), char **args, UNUSED(int flags))
2896{
2897    if (!*args) {
2898	LinkNode nptr;
2899
2900	for (nptr = firstnode(zfsessions); nptr; incnode(nptr))
2901	    printf("%s\n", ((Zftp_session)nptr->dat)->name);
2902	return 0;
2903    }
2904
2905    /*
2906     * Check if we are already in the required session: if so,
2907     * it's a no-op, not an error.
2908     */
2909    if (!strcmp(*args, zfsess->name))
2910	return 0;
2911
2912    savesession();
2913    switchsession(*args);
2914    return 0;
2915}
2916
2917/* Remove a session and free it */
2918
2919/**/
2920static int
2921zftp_rmsession(UNUSED(char *name), char **args, UNUSED(int flags))
2922{
2923    int no;
2924    LinkNode nptr;
2925    Zftp_session sptr = NULL;
2926    char *newsess = NULL;
2927
2928    /* Find the session in the list: either the current one, or by name */
2929    for (no = 0, nptr = firstnode(zfsessions); nptr; no++, incnode(nptr)) {
2930	sptr = (Zftp_session) nptr->dat;
2931	if ((!*args && sptr == zfsess) ||
2932	    (*args && !strcmp(sptr->name, *args)))
2933	    break;
2934    }
2935    if (!nptr)
2936	return 1;
2937
2938    if (sptr == zfsess) {
2939	/* Freeing current session: make sure it's closed */
2940	zfclosedata();
2941	zfclose(0);
2942
2943	/*
2944	 * Choose new session to switch to if any: first in list
2945	 * excluding the one just freed.
2946	 */
2947	if (zfsesscnt > 1) {
2948	    LinkNode newn = firstnode(zfsessions);
2949	    if (newn == nptr)
2950		incnode(newn);
2951	    newsess = ((Zftp_session)newn->dat)->name;
2952	}
2953    } else {
2954	Zftp_session oldsess = zfsess;
2955	zfsess = sptr;
2956	/*
2957	 * Freeing another session: don't need to switch, just
2958	 * tell zfclose() not to delete parameters etc.
2959	 */
2960	zfclosedata();
2961	zfclose(1);
2962	zfsess = oldsess;
2963    }
2964    remnode(zfsessions, nptr);
2965    freesession(sptr);
2966
2967    /*
2968     * Fix up array of status pointers.
2969     */
2970    if (--zfsesscnt) {
2971	/*
2972	 * Some remaining, so just shift up
2973	 */
2974	int *newstatusp = (int *)zalloc(sizeof(int)*zfsesscnt);
2975	int *src, *dst, i;
2976	for (i = 0, src = zfstatusp, dst = newstatusp; i < zfsesscnt;
2977	     i++, src++, dst++) {
2978	    if (i == no)
2979		src++;
2980	    *dst = *src;
2981	}
2982	zfree(zfstatusp, sizeof(int)*(zfsesscnt+1));
2983	zfstatusp = newstatusp;
2984
2985	/*
2986	 * Maybe we need to switch to one of the remaining sessions.
2987	 */
2988	if (newsess)
2989	    switchsession(newsess);
2990    } else {
2991	zfree(zfstatusp, sizeof(int));
2992	zfstatusp = NULL;
2993
2994	/*
2995	 * We've just deleted the last session, so we need to
2996	 * start again from scratch.
2997	 */
2998	newsession("default");
2999    }
3000
3001    return 0;
3002}
3003
3004/* The builtin command frontend to the rest of the package */
3005
3006/**/
3007static int
3008bin_zftp(char *name, char **args, UNUSED(Options ops), UNUSED(int func))
3009{
3010    char fullname[20] = "zftp ";
3011    char *cnam = *args++, *prefs, *ptr;
3012    Zftpcmd zptr;
3013    int n, ret = 0;
3014
3015    for (zptr = zftpcmdtab; zptr->nam; zptr++)
3016	if (!strcmp(zptr->nam, cnam))
3017	    break;
3018
3019    if (!zptr->nam) {
3020	zwarnnam(name, "no such subcommand: %s", cnam);
3021	return 1;
3022    }
3023
3024    /* check number of arguments */
3025    for (n = 0; args[n]; n++)
3026	;
3027    if (n < zptr->min || (zptr->max != -1 && n > zptr->max)) {
3028	zwarnnam(name, "wrong no. of arguments for %s", cnam);
3029	return 1;
3030    }
3031
3032    strcat(fullname, cnam);
3033    if (zfstatfd != -1 && !(zptr->flags & ZFTP_SESS)) {
3034	/* Get the status in case it was set by a forked process */
3035	int oldstatus = zfstatusp[zfsessno];
3036	lseek(zfstatfd, 0, 0);
3037	read_loop(zfstatfd, (char *)zfstatusp, sizeof(int)*zfsesscnt);
3038	if (zfsess->control && (zfstatusp[zfsessno] & ZFST_CLOS)) {
3039	    /* got closed in subshell without us knowing */
3040	    zcfinish = 2;
3041	    zfclose(0);
3042	} else {
3043	    /*
3044	     * fix up status types: unfortunately they may already
3045	     * have been looked at between being changed in the subshell
3046	     * and now, but we can't help that.
3047	     */
3048	    if (ZFST_TYPE(oldstatus) != ZFST_TYPE(zfstatusp[zfsessno]))
3049		zfsetparam("ZFTP_TYPE",
3050			   ztrdup(ZFST_TYPE(zfstatusp[zfsessno]) == ZFST_ASCI ?
3051				  "A" : "I"), ZFPM_READONLY);
3052	    if (ZFST_MODE(oldstatus) != ZFST_MODE(zfstatusp[zfsessno]))
3053		zfsetparam("ZFTP_MODE",
3054			   ztrdup(ZFST_MODE(zfstatusp[zfsessno]) == ZFST_BLOC ?
3055				  "B" : "S"), ZFPM_READONLY);
3056	}
3057    }
3058#if defined(HAVE_SELECT) || defined (HAVE_POLL)
3059    if (zfsess->control && !(zptr->flags & (ZFTP_TEST|ZFTP_SESS))) {
3060	/*
3061	 * Test the connection for a bad fd or incoming message, but
3062	 * only if the connection was last heard of open, and
3063	 * if we are not about to call the test command anyway.
3064	 * Not worth it unless we have select() or poll().
3065	 */
3066	ret = zftp_test("zftp test", NULL, 0);
3067    }
3068#endif
3069    if ((zptr->flags & ZFTP_CONN) && !zfsess->control) {
3070	if (ret != 2) {
3071	    /*
3072	     * with ret == 2, we just got dumped out in the test,
3073	     * so enough messages already.
3074	     */
3075	    zwarnnam(fullname, "not connected.");
3076	}
3077	return 1;
3078    }
3079
3080    queue_signals();
3081    if ((prefs = getsparam("ZFTP_PREFS"))) {
3082	zfprefs = 0;
3083	for (ptr = prefs; *ptr; ptr++) {
3084	    switch (toupper(STOUC(*ptr))) {
3085	    case 'S':
3086		/* sendport */
3087		zfprefs |= ZFPF_SNDP;
3088		break;
3089
3090	    case 'P':
3091		/*
3092		 * passive
3093		 * If we have already been told to use sendport mode,
3094		 * we're never going to use passive mode.
3095		 */
3096		if (!(zfprefs & ZFPF_SNDP))
3097		    zfprefs |= ZFPF_PASV;
3098		break;
3099
3100	    case 'D':
3101		/* dumb */
3102		zfprefs |= ZFPF_DUMB;
3103		break;
3104
3105	    default:
3106		zwarnnam(name, "preference %c not recognized", *ptr);
3107		break;
3108	    }
3109	}
3110    }
3111    unqueue_signals();
3112
3113    ret = (*zptr->fun)(fullname, args, zptr->flags);
3114
3115    if (zfalarmed)
3116	zfunalarm();
3117    if (zfdrrrring) {
3118	/* had a timeout, close the connection */
3119	zcfinish = 2;		/* don't try sending QUIT */
3120	zfclose(0);
3121    }
3122    if (zfstatfd != -1) {
3123	/*
3124	 * Set the status in case another process needs to know,
3125	 * but only for the active session.
3126	 */
3127	lseek(zfstatfd, zfsessno*sizeof(int), 0);
3128	write_loop(zfstatfd, (char *)zfstatusp+zfsessno, sizeof(int));
3129    }
3130    return ret;
3131}
3132
3133static void
3134zftp_cleanup(void)
3135{
3136    /*
3137     * There are various parameters hanging around, but they're
3138     * all non-special so are entirely non-life-threatening.
3139     */
3140    LinkNode nptr;
3141    Zftp_session cursess = zfsess;
3142    for (zfsessno = 0, nptr = firstnode(zfsessions); nptr;
3143	 zfsessno++, incnode(nptr)) {
3144	zfsess = (Zftp_session)nptr->dat;
3145	zfclosedata();
3146	/*
3147	 * When closing the current session, do the usual unsetting,
3148	 * otherwise don't.
3149	 */
3150	zfclose(zfsess != cursess);
3151    }
3152    zsfree(lastmsg);
3153    zfunsetparam("ZFTP_SESSION");
3154    freelinklist(zfsessions, (FreeFunc) freesession);
3155    zfree(zfstatusp, sizeof(int)*zfsesscnt);
3156}
3157
3158static int
3159zftpexithook(UNUSED(Hookdef d), UNUSED(void *dummy))
3160{
3161    zftp_cleanup();
3162    return 0;
3163}
3164
3165static struct features module_features = {
3166    bintab, sizeof(bintab)/sizeof(*bintab),
3167    NULL, 0,
3168    NULL, 0,
3169    NULL, 0,
3170    0
3171};
3172
3173/* The load/unload routines required by the zsh library interface */
3174
3175/**/
3176int
3177setup_(UNUSED(Module m))
3178{
3179    return (require_module("zsh/net/tcp", NULL) == 1);
3180}
3181
3182/**/
3183int
3184features_(Module m, char ***features)
3185{
3186    *features = featuresarray(m, &module_features);
3187    return 0;
3188}
3189
3190/**/
3191int
3192enables_(Module m, int **enables)
3193{
3194    return handlefeatures(m, &module_features, enables);
3195}
3196
3197/**/
3198int
3199boot_(UNUSED(Module m))
3200{
3201    /*
3202     * Set some default parameters.
3203     * These aren't special, so aren't associated with features.
3204     */
3205    off_t tmout_def = 60;
3206    zfsetparam("ZFTP_VERBOSE", ztrdup("450"), ZFPM_IFUNSET);
3207    zfsetparam("ZFTP_TMOUT", &tmout_def, ZFPM_IFUNSET|ZFPM_INTEGER);
3208    zfsetparam("ZFTP_PREFS", ztrdup("PS"), ZFPM_IFUNSET);
3209    /* default preferences if user deletes variable */
3210    zfprefs = ZFPF_SNDP|ZFPF_PASV;
3211
3212    zfsessions = znewlinklist();
3213    newsession("default");
3214
3215    addhookfunc("exit", zftpexithook);
3216
3217    return 0;
3218}
3219
3220/**/
3221int
3222cleanup_(Module m)
3223{
3224    deletehookfunc("exit", zftpexithook);
3225    zftp_cleanup();
3226    return setfeatureenables(m, &module_features, NULL);
3227}
3228
3229/**/
3230int
3231finish_(UNUSED(Module m))
3232{
3233    return 0;
3234}
3235