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