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