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