mirror of
git://git.code.sf.net/p/zsh/code
synced 2024-09-22 03:40:47 +02:00
15762: introduce ztcp builtin
This commit is contained in:
parent
199bccab75
commit
b554563ece
@ -1,3 +1,9 @@
|
||||
2001-09-08 Clint Adams <clint@zsh.org>
|
||||
|
||||
* 15762: Src/Modules/tcp.c, Src/Modules/tcp.h,
|
||||
Src/Modules/tcp.mdd, Src/Modules/zftp.c:
|
||||
introduce ztcp builtin.
|
||||
|
||||
2001-09-06 Clint Adams <clint@zsh.org>
|
||||
|
||||
* 15740: Completion/compaudit: don't whine about
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* tcp.c - builtin FTP client
|
||||
* tcp.c - TCP module
|
||||
*
|
||||
* This file is part of zsh, the Z shell.
|
||||
*
|
||||
@ -89,16 +89,16 @@ int h_errno;
|
||||
mod_export char const *
|
||||
zsh_inet_ntop(int af, void const *cp, char *buf, size_t len)
|
||||
{
|
||||
if(af != AF_INET) {
|
||||
errno = EAFNOSUPPORT;
|
||||
return NULL;
|
||||
}
|
||||
if(len < INET_ADDRSTRLEN) {
|
||||
errno = ENOSPC;
|
||||
return NULL;
|
||||
}
|
||||
strcpy(buf, inet_ntoa(*(struct in_addr *)cp));
|
||||
return buf;
|
||||
if(af != AF_INET) {
|
||||
errno = EAFNOSUPPORT;
|
||||
return NULL;
|
||||
}
|
||||
if(len < INET_ADDRSTRLEN) {
|
||||
errno = ENOSPC;
|
||||
return NULL;
|
||||
}
|
||||
strcpy(buf, inet_ntoa(*(struct in_addr *)cp));
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**/
|
||||
@ -139,11 +139,11 @@ mod_export int zsh_inet_aton(char const *src, struct in_addr *dst)
|
||||
mod_export int
|
||||
zsh_inet_pton(int af, char const *src, void *dst)
|
||||
{
|
||||
if(af != AF_INET) {
|
||||
errno = EAFNOSUPPORT;
|
||||
return -1;
|
||||
}
|
||||
return !!zsh_inet_aton(src, dst);
|
||||
if(af != AF_INET) {
|
||||
errno = EAFNOSUPPORT;
|
||||
return -1;
|
||||
}
|
||||
return !!zsh_inet_aton(src, dst);
|
||||
}
|
||||
|
||||
#else /* !HAVE_INET_PTON */
|
||||
@ -163,11 +163,11 @@ zsh_inet_pton(int af, char const *src, void *dst)
|
||||
mod_export struct hostent *
|
||||
zsh_gethostbyname2(char const *name, int af)
|
||||
{
|
||||
if(af != AF_INET) {
|
||||
h_errno = NO_RECOVERY;
|
||||
return NULL;
|
||||
}
|
||||
return gethostbyname(name);
|
||||
if(af != AF_INET) {
|
||||
h_errno = NO_RECOVERY;
|
||||
return NULL;
|
||||
}
|
||||
return gethostbyname(name);
|
||||
}
|
||||
|
||||
/**/
|
||||
@ -187,28 +187,28 @@ zsh_gethostbyname2(char const *name, int af)
|
||||
mod_export struct hostent *
|
||||
zsh_getipnodebyname(char const *name, int af, int flags, int *errorp)
|
||||
{
|
||||
static struct hostent ahe;
|
||||
static char nbuf[16];
|
||||
static char *addrlist[] = { nbuf, NULL };
|
||||
static struct hostent ahe;
|
||||
static char nbuf[16];
|
||||
static char *addrlist[] = { nbuf, NULL };
|
||||
# ifdef SUPPORT_IPV6
|
||||
static char pbuf[INET6_ADDRSTRLEN];
|
||||
static char pbuf[INET6_ADDRSTRLEN];
|
||||
# else
|
||||
static char pbuf[INET_ADDRSTRLEN];
|
||||
static char pbuf[INET_ADDRSTRLEN];
|
||||
# endif
|
||||
struct hostent *he;
|
||||
if(zsh_inet_pton(af, name, nbuf) == 1) {
|
||||
zsh_inet_ntop(af, nbuf, pbuf, sizeof(pbuf));
|
||||
ahe.h_name = pbuf;
|
||||
ahe.h_aliases = addrlist+1;
|
||||
ahe.h_addrtype = af;
|
||||
ahe.h_length = (af == AF_INET) ? 4 : 16;
|
||||
ahe.h_addr_list = addrlist;
|
||||
return &ahe;
|
||||
}
|
||||
he = zsh_gethostbyname2(name, af);
|
||||
if(!he)
|
||||
*errorp = h_errno;
|
||||
return he;
|
||||
struct hostent *he;
|
||||
if(zsh_inet_pton(af, name, nbuf) == 1) {
|
||||
zsh_inet_ntop(af, nbuf, pbuf, sizeof(pbuf));
|
||||
ahe.h_name = pbuf;
|
||||
ahe.h_aliases = addrlist+1;
|
||||
ahe.h_addrtype = af;
|
||||
ahe.h_length = (af == AF_INET) ? 4 : 16;
|
||||
ahe.h_addr_list = addrlist;
|
||||
return &ahe;
|
||||
}
|
||||
he = zsh_gethostbyname2(name, af);
|
||||
if(!he)
|
||||
*errorp = h_errno;
|
||||
return he;
|
||||
}
|
||||
|
||||
/**/
|
||||
@ -226,29 +226,130 @@ freehostent(struct hostent *ptr)
|
||||
/**/
|
||||
#endif /* !HAVE_GETIPNODEBYNAME */
|
||||
|
||||
/**/
|
||||
mod_export int
|
||||
tcp_socket(int domain, int type, int protocol, Tcp_session sess)
|
||||
Tcp_session ztcp_head = NULL, ztcp_tail = NULL;
|
||||
|
||||
static Tcp_session
|
||||
zts_head(void)
|
||||
{
|
||||
return ztcp_head;
|
||||
}
|
||||
|
||||
static Tcp_session
|
||||
zts_next(Tcp_session cur)
|
||||
{
|
||||
return cur ? cur->next : NULL;
|
||||
}
|
||||
|
||||
/* "allocate" a tcp_session */
|
||||
static Tcp_session
|
||||
zts_alloc(int ztflags)
|
||||
{
|
||||
Tcp_session sess;
|
||||
|
||||
sess = (Tcp_session)zcalloc(sizeof(struct tcp_session));
|
||||
if(!sess) return NULL;
|
||||
sess->fd=-1;
|
||||
sess->next=NULL;
|
||||
sess->flags=ztflags;
|
||||
|
||||
if(!zts_head()) {
|
||||
ztcp_head = ztcp_tail = sess;
|
||||
}
|
||||
else {
|
||||
ztcp_tail->next = sess;
|
||||
}
|
||||
return sess;
|
||||
}
|
||||
|
||||
/**/
|
||||
mod_export Tcp_session
|
||||
tcp_socket(int domain, int type, int protocol, int ztflags)
|
||||
{
|
||||
Tcp_session sess;
|
||||
|
||||
sess = zts_alloc(ztflags);
|
||||
if(!sess) return NULL;
|
||||
|
||||
sess->fd = socket(domain, type, protocol);
|
||||
return sess->fd;
|
||||
return sess;
|
||||
}
|
||||
|
||||
static int
|
||||
zts_delete(Tcp_session sess)
|
||||
{
|
||||
Tcp_session tsess;
|
||||
|
||||
tsess = zts_head();
|
||||
|
||||
if(tsess == sess)
|
||||
{
|
||||
ztcp_head = sess->next;
|
||||
free(sess);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while((tsess->next != sess) && (tsess->next))
|
||||
{
|
||||
tsess = zts_next(tsess);
|
||||
}
|
||||
|
||||
if(!tsess->next) return 1;
|
||||
|
||||
tsess->next = tsess->next->next;
|
||||
free(tsess->next);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static Tcp_session
|
||||
zts_byfd(int fd)
|
||||
{
|
||||
Tcp_session tsess;
|
||||
|
||||
tsess = zts_head();
|
||||
|
||||
do {
|
||||
if(tsess->fd == fd)
|
||||
return tsess;
|
||||
|
||||
tsess = zts_next(tsess);
|
||||
}
|
||||
while(tsess != NULL);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
tcp_cleanup(void)
|
||||
{
|
||||
Tcp_session sess, prev;
|
||||
|
||||
for(sess = zts_head(); sess != NULL; sess = zts_next(prev))
|
||||
{
|
||||
prev = sess;
|
||||
tcp_close(sess);
|
||||
zts_delete(sess);
|
||||
}
|
||||
}
|
||||
|
||||
/**/
|
||||
mod_export int
|
||||
tcp_close(Tcp_session sess)
|
||||
{
|
||||
if(!close(sess->fd))
|
||||
{
|
||||
sess->fd = -1;
|
||||
int err;
|
||||
|
||||
if(sess->fd != -1)
|
||||
{
|
||||
err = close(sess->fd);
|
||||
if(err)
|
||||
{
|
||||
zwarn("connection close failed: %e", NULL, errno);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else return -1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**/
|
||||
@ -270,12 +371,122 @@ tcp_connect(Tcp_session sess, char *addrp, struct hostent *zhost, int d_port)
|
||||
{
|
||||
memcpy(&(sess->peer.in.sin_addr), addrp, zhost->h_length);
|
||||
sess->peer.in.sin_port = d_port;
|
||||
sess->peer.a.sa_family = zhost->h_addrtype;
|
||||
salen = sizeof(struct sockaddr_in);
|
||||
}
|
||||
|
||||
return connect(sess->fd, (struct sockaddr *)&(sess->peer), salen);
|
||||
}
|
||||
|
||||
static int
|
||||
bin_ztcp(char *nam, char **args, char *ops, int func)
|
||||
{
|
||||
int herrno, err=1, destport, force=0, len;
|
||||
char **addrp, *desthost;
|
||||
struct hostent *zthost = NULL;
|
||||
Tcp_session sess;
|
||||
|
||||
if (ops['f'])
|
||||
force=1;
|
||||
|
||||
if (ops['c']) {
|
||||
if (!args[0]) {
|
||||
tcp_cleanup();
|
||||
}
|
||||
else {
|
||||
int targetfd = atoi(args[0]);
|
||||
sess = zts_byfd(targetfd);
|
||||
|
||||
if(sess)
|
||||
{
|
||||
if((sess->flags & ZTCP_ZFTP) && !force)
|
||||
{
|
||||
zwarnnam(nam, "use -f to force closure of a zftp control connection", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
tcp_close(sess);
|
||||
zts_delete(sess);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
zwarnnam(nam, "fd not found in tcp table", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if (!args[0]) {
|
||||
for(sess = zts_head(); sess != NULL; sess = zts_next(sess))
|
||||
{
|
||||
if(sess->fd != -1)
|
||||
{
|
||||
zthost = gethostbyaddr(&(sess->peer.in.sin_addr), sizeof(struct sockaddr_in), AF_INET);
|
||||
if(zthost) fprintf(shout, "%s:%d is on fd %d%s\n", zthost->h_name, ntohs(sess->peer.in.sin_port), sess->fd, (sess->flags & ZTCP_ZFTP) ? " ZFTP" : "");
|
||||
else fprintf(shout, "%s:%d is on fd %d%s\n", "UNKNOWN", sess->peer.in.sin_port, sess->fd, (sess->flags & ZTCP_ZFTP) ? " ZFTP" : "");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (!args[1]) {
|
||||
destport = 23;
|
||||
}
|
||||
else {
|
||||
destport = atoi(args[1]);
|
||||
}
|
||||
|
||||
desthost = ztrdup(args[0]);
|
||||
|
||||
zthost = zsh_getipnodebyname(desthost, AF_INET, 0, &herrno);
|
||||
if (!zthost || errflag) {
|
||||
zwarnnam(nam, "host resolution failure: %s", desthost, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
sess = tcp_socket(PF_INET, SOCK_STREAM, 0, 0);
|
||||
#ifdef SO_OOBINLINE
|
||||
len = 1;
|
||||
setsockopt(sess->fd, SOL_SOCKET, SO_OOBINLINE, (char *)&len, sizeof(len));
|
||||
#endif
|
||||
|
||||
if(!sess) {
|
||||
zwarnnam(nam, "unable to allocate a TCP session slot", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
if (sess->fd < 0) {
|
||||
zwarnnam(nam, "socket creation failed: %e", NULL, errno);
|
||||
zsfree(desthost);
|
||||
zts_delete(sess);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (addrp = zthost->h_addr_list; err && *addrp; addrp++) {
|
||||
if(zthost->h_length != 4)
|
||||
zwarnnam(nam, "address length mismatch", NULL, 0);
|
||||
do {
|
||||
err = tcp_connect(sess, *addrp, zthost, htons(destport));
|
||||
} while (err && errno == EINTR && !errflag);
|
||||
}
|
||||
|
||||
if(err)
|
||||
zwarnnam(nam, "connection failed: %e", NULL, errno);
|
||||
else
|
||||
{
|
||||
fprintf(shout, "%s:%d is now on fd %d\n", desthost, destport, sess->fd);
|
||||
}
|
||||
|
||||
zsfree(desthost);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static struct builtin bintab[] = {
|
||||
BUILTIN("ztcp", 0, bin_ztcp, 0, 2, 0, "c", NULL),
|
||||
};
|
||||
|
||||
/* The load/unload routines required by the zsh library interface */
|
||||
|
||||
/**/
|
||||
@ -289,9 +500,10 @@ setup_(Module m)
|
||||
int
|
||||
boot_(Module m)
|
||||
{
|
||||
return 0;
|
||||
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||
}
|
||||
|
||||
|
||||
/**/
|
||||
int
|
||||
cleanup_(Module m)
|
||||
|
@ -63,21 +63,25 @@
|
||||
#endif
|
||||
|
||||
union tcp_sockaddr {
|
||||
struct sockaddr a;
|
||||
struct sockaddr_in in;
|
||||
struct sockaddr a;
|
||||
struct sockaddr_in in;
|
||||
#ifdef SUPPORT_IPV6
|
||||
struct sockaddr_in6 in6;
|
||||
struct sockaddr_in6 in6;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct tcp_session {
|
||||
int fd; /* file descriptor */
|
||||
union tcp_sockaddr sock; /* local address */
|
||||
union tcp_sockaddr peer; /* remote address */
|
||||
};
|
||||
|
||||
typedef struct tcp_session *Tcp_session;
|
||||
|
||||
#define ZTCP_ZFTP 16
|
||||
|
||||
struct tcp_session {
|
||||
int fd; /* file descriptor */
|
||||
union tcp_sockaddr sock; /* local address */
|
||||
union tcp_sockaddr peer; /* remote address */
|
||||
Tcp_session next;
|
||||
int flags;
|
||||
};
|
||||
|
||||
#include "tcp.mdh"
|
||||
#include "tcp.pro"
|
||||
|
||||
|
@ -3,3 +3,4 @@ link=dynamic
|
||||
load=no
|
||||
|
||||
objects="tcp.o"
|
||||
autobins="ztcp"
|
||||
|
@ -75,10 +75,10 @@ int h_errno;
|
||||
#endif
|
||||
|
||||
union zftp_sockaddr {
|
||||
struct sockaddr a;
|
||||
struct sockaddr_in in;
|
||||
struct sockaddr a;
|
||||
struct sockaddr_in in;
|
||||
#ifdef SUPPORT_IPV6
|
||||
struct sockaddr_in6 in6;
|
||||
struct sockaddr_in6 in6;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -301,7 +301,7 @@ struct zftp_session {
|
||||
char **params; /* parameters ordered as in zfparams */
|
||||
char **userparams; /* user parameters set by zftp_params */
|
||||
FILE *cin; /* control input file */
|
||||
struct tcp_session control; /* the control connection */
|
||||
Tcp_session control; /* the control connection */
|
||||
int dfd; /* data connection */
|
||||
int has_size; /* understands SIZE? */
|
||||
int has_mdtm; /* understands MDTM? */
|
||||
@ -643,7 +643,7 @@ zfgetline(char *ln, int lnsize, int tmout)
|
||||
cmdbuf[0] = (char)IAC;
|
||||
cmdbuf[1] = (char)DONT;
|
||||
cmdbuf[2] = ch;
|
||||
write(zfsess->control.fd, cmdbuf, 3);
|
||||
write(zfsess->control->fd, cmdbuf, 3);
|
||||
continue;
|
||||
|
||||
case DO:
|
||||
@ -653,7 +653,7 @@ zfgetline(char *ln, int lnsize, int tmout)
|
||||
cmdbuf[0] = (char)IAC;
|
||||
cmdbuf[1] = (char)WONT;
|
||||
cmdbuf[2] = ch;
|
||||
write(zfsess->control.fd, cmdbuf, 3);
|
||||
write(zfsess->control->fd, cmdbuf, 3);
|
||||
continue;
|
||||
|
||||
case EOF:
|
||||
@ -703,7 +703,7 @@ zfgetmsg(void)
|
||||
char line[256], *ptr, *verbose;
|
||||
int stopit, printing = 0, tmout;
|
||||
|
||||
if (zfsess->control.fd == -1)
|
||||
if ((zfsess->control && zfsess->control->fd == -1))
|
||||
return 6;
|
||||
zsfree(lastmsg);
|
||||
lastmsg = NULL;
|
||||
@ -831,7 +831,7 @@ zfsendcmd(char *cmd)
|
||||
*/
|
||||
int ret, tmout;
|
||||
|
||||
if (zfsess->control.fd == -1)
|
||||
if ((zfsess->control && zfsess->control->fd == -1))
|
||||
return 6;
|
||||
tmout = getiparam("ZFTP_TMOUT");
|
||||
if (setjmp(zfalrmbuf)) {
|
||||
@ -840,7 +840,7 @@ zfsendcmd(char *cmd)
|
||||
return 6;
|
||||
}
|
||||
zfalarm(tmout);
|
||||
ret = write(zfsess->control.fd, cmd, strlen(cmd));
|
||||
ret = write(zfsess->control->fd, cmd, strlen(cmd));
|
||||
alarm(0);
|
||||
|
||||
if (ret <= 0) {
|
||||
@ -874,7 +874,7 @@ zfopendata(char *name, union tcp_sockaddr *zdsockp, int *is_passivep)
|
||||
int err, salen;
|
||||
|
||||
#ifdef SUPPORT_IPV6
|
||||
if(zfsess->control.peer.a.sa_family == AF_INET6)
|
||||
if(zfsess->control->peer.a.sa_family == AF_INET6)
|
||||
psv_cmd = "EPSV\r\n";
|
||||
else
|
||||
#endif /* SUPPORT_IPV6 */
|
||||
@ -890,9 +890,9 @@ zfopendata(char *name, union tcp_sockaddr *zdsockp, int *is_passivep)
|
||||
zfclosedata();
|
||||
return zfopendata(name, zdsockp, is_passivep);
|
||||
}
|
||||
zdsockp->a.sa_family = zfsess->control.peer.a.sa_family;
|
||||
zdsockp->a.sa_family = zfsess->control->peer.a.sa_family;
|
||||
#ifdef SUPPORT_IPV6
|
||||
if(zfsess->control.peer.a.sa_family == AF_INET6) {
|
||||
if(zfsess->control->peer.a.sa_family == AF_INET6) {
|
||||
/* see RFC 2428 for explanation */
|
||||
char const *ptr, *end;
|
||||
char delim, portbuf[6], *pbp;
|
||||
@ -920,7 +920,7 @@ zfopendata(char *name, union tcp_sockaddr *zdsockp, int *is_passivep)
|
||||
portnum = strtoul(portbuf, &pbp, 10);
|
||||
if(*pbp || portnum > 65535UL)
|
||||
goto bad_epsv;
|
||||
*zdsockp = zfsess->control.peer;
|
||||
*zdsockp = zfsess->control->peer;
|
||||
zdsockp->in6.sin6_port = htons((unsigned)portnum);
|
||||
salen = sizeof(struct sockaddr_in6);
|
||||
} else
|
||||
@ -980,7 +980,7 @@ zfopendata(char *name, union tcp_sockaddr *zdsockp, int *is_passivep)
|
||||
return 1;
|
||||
}
|
||||
|
||||
*zdsockp = zfsess->control.sock;
|
||||
*zdsockp = zfsess->control->sock;
|
||||
#ifdef SUPPORT_IPV6
|
||||
if(zdsockp->a.sa_family == AF_INET6) {
|
||||
zdsockp->in6.sin6_port = 0; /* to be set by bind() */
|
||||
@ -1015,9 +1015,9 @@ zfopendata(char *name, union tcp_sockaddr *zdsockp, int *is_passivep)
|
||||
/* see RFC 2428 for explanation */
|
||||
strcpy(portcmd, "EPRT |2|");
|
||||
zsh_inet_ntop(AF_INET6, &zdsockp->in6.sin6_addr,
|
||||
portcmd+8, INET6_ADDRSTRLEN);
|
||||
portcmd+8, INET6_ADDRSTRLEN);
|
||||
sprintf(strchr(portcmd, 0), "|%u|\r\n",
|
||||
(unsigned)ntohs(zdsockp->in6.sin6_port));
|
||||
(unsigned)ntohs(zdsockp->in6.sin6_port));
|
||||
} else
|
||||
#endif /* SUPPORT_IPV6 */
|
||||
{
|
||||
@ -1171,8 +1171,8 @@ zfgetdata(char *name, char *rest, char *cmd, int getsize)
|
||||
}
|
||||
#endif
|
||||
#if defined(F_SETFD) && defined(FD_CLOEXEC)
|
||||
/* If the shell execs a program, we don't want this fd left open. */
|
||||
fcntl(zfsess->dfd, F_SETFD, FD_CLOEXEC);
|
||||
/* If the shell execs a program, we don't want this fd left open. */
|
||||
fcntl(zfsess->dfd, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
@ -1655,8 +1655,8 @@ zfsenddata(char *name, int recv, int progress, off_t startat)
|
||||
|
||||
/* the following is black magic, as far as I'm concerned. */
|
||||
/* what are we going to do if it fails? not a lot, actually. */
|
||||
send(zfsess->control.fd, (char *)msg, 3, 0);
|
||||
send(zfsess->control.fd, (char *)msg+3, 1, MSG_OOB);
|
||||
send(zfsess->control->fd, (char *)msg, 3, 0);
|
||||
send(zfsess->control->fd, (char *)msg+3, 1, MSG_OOB);
|
||||
|
||||
zfsendcmd("ABOR\r\n");
|
||||
if (lastcode == 226) {
|
||||
@ -1718,7 +1718,7 @@ zftp_open(char *name, char **args, int flags)
|
||||
* Probably this is the safest thing to do. It's possible
|
||||
* a `QUIT' will hang, though.
|
||||
*/
|
||||
if (zfsess->control.fd != -1)
|
||||
if ((zfsess->control && zfsess->control->fd != -1))
|
||||
zfclose(0);
|
||||
|
||||
/* this is going to give 0. why bother? */
|
||||
@ -1757,12 +1757,12 @@ zftp_open(char *name, char **args, int flags)
|
||||
# define SUCCEEDED() break
|
||||
# define FAILED() if(af == AF_INET) { } else continue
|
||||
#else
|
||||
af = AF_INET;
|
||||
af = AF_INET;
|
||||
# define SUCCEEDED() do { } while(0)
|
||||
# define FAILED() do { } while(0)
|
||||
#endif
|
||||
{
|
||||
zhostp = zsh_getipnodebyname(args[0], af, 0, &herrno);
|
||||
zhostp = zsh_getipnodebyname(args[0], af, 0, &herrno);
|
||||
if (!zhostp || errflag) {
|
||||
/* should use herror() here if available, but maybe
|
||||
* needs configure test. on AIX it's present but not
|
||||
@ -1777,7 +1777,6 @@ zftp_open(char *name, char **args, int flags)
|
||||
}
|
||||
zfsetparam("ZFTP_HOST", ztrdup(zhostp->h_name), ZFPM_READONLY);
|
||||
|
||||
zfsess->control.peer.a.sa_family = af;
|
||||
#ifdef SUPPORT_IPV6
|
||||
if(af == AF_INET6) {
|
||||
hlen = 16;
|
||||
@ -1787,8 +1786,9 @@ zftp_open(char *name, char **args, int flags)
|
||||
hlen = 4;
|
||||
}
|
||||
|
||||
tcp_socket(af, SOCK_STREAM, 0, &(zfsess->control));
|
||||
if (zfsess->control.fd < 0) {
|
||||
zfsess->control = tcp_socket(af, SOCK_STREAM, 0, ZTCP_ZFTP);
|
||||
|
||||
if (!(zfsess->control) || (zfsess->control->fd < 0)) {
|
||||
freehostent(zhostp);
|
||||
zfunsetparam("ZFTP_HOST");
|
||||
FAILED();
|
||||
@ -1811,7 +1811,7 @@ zftp_open(char *name, char **args, int flags)
|
||||
if(hlen != zhostp->h_length)
|
||||
zwarnnam(name, "address length mismatch", NULL, 0);
|
||||
do {
|
||||
err = tcp_connect(&(zfsess->control), *addrp, zhostp, zservp->s_port);
|
||||
err = tcp_connect(zfsess->control, *addrp, zhostp, zservp->s_port);
|
||||
} while (err && errno == EINTR && !errflag);
|
||||
/* you can check whether it's worth retrying here */
|
||||
}
|
||||
@ -1846,15 +1846,15 @@ zftp_open(char *name, char **args, int flags)
|
||||
* Move the fd out of the user-visible range. We need to do
|
||||
* this after the connect() on some systems.
|
||||
*/
|
||||
zfsess->control.fd = zfmovefd(zfsess->control.fd);
|
||||
zfsess->control->fd = zfmovefd(zfsess->control->fd);
|
||||
|
||||
#if defined(F_SETFD) && defined(FD_CLOEXEC)
|
||||
/* If the shell execs a program, we don't want this fd left open. */
|
||||
fcntl(zfsess->control.fd, F_SETFD, FD_CLOEXEC);
|
||||
fcntl(zfsess->control->fd, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
len = sizeof(zfsess->control.sock);
|
||||
if (getsockname(zfsess->control.fd, (struct sockaddr *)&zfsess->control.sock, &len) < 0) {
|
||||
len = sizeof(zfsess->control->sock);
|
||||
if (getsockname(zfsess->control->fd, (struct sockaddr *)&zfsess->control->sock, &len) < 0) {
|
||||
zwarnnam(name, "getsockname failed: %e", NULL, errno);
|
||||
zfclose(0);
|
||||
return 1;
|
||||
@ -1866,20 +1866,20 @@ zftp_open(char *name, char **args, int flags)
|
||||
* do clever things with SIGURG.
|
||||
*/
|
||||
len = 1;
|
||||
setsockopt(zfsess->control.fd, SOL_SOCKET, SO_OOBINLINE,
|
||||
setsockopt(zfsess->control->fd, SOL_SOCKET, SO_OOBINLINE,
|
||||
(char *)&len, sizeof(len));
|
||||
#endif
|
||||
#if defined(IP_TOS) && defined(IPTOS_LOWDELAY)
|
||||
/* for control connection we want low delay. please don't laugh. */
|
||||
len = IPTOS_LOWDELAY;
|
||||
setsockopt(zfsess->control.fd, IPPROTO_IP, IP_TOS, (char *)&len, sizeof(len));
|
||||
setsockopt(zfsess->control->fd, IPPROTO_IP, IP_TOS, (char *)&len, sizeof(len));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We use stdio with line buffering for convenience on input.
|
||||
* On output, we can just dump a complete message to the fd via write().
|
||||
*/
|
||||
zfsess->cin = fdopen(zfsess->control.fd, "r");
|
||||
zfsess->cin = fdopen(zfsess->control->fd, "r");
|
||||
|
||||
if (!zfsess->cin) {
|
||||
zwarnnam(name, "file handling error", NULL, 0);
|
||||
@ -1923,17 +1923,17 @@ zftp_open(char *name, char **args, int flags)
|
||||
unlink(fname);
|
||||
}
|
||||
|
||||
if (zfsess->control.fd == -1) {
|
||||
if (zfsess->control->fd == -1) {
|
||||
/* final paranoid check */
|
||||
return 1;
|
||||
}
|
||||
|
||||
zfsetparam("ZFTP_MODE", ztrdup("S"), ZFPM_READONLY);
|
||||
/* if remaining arguments, use them to log in. */
|
||||
if (zfsess->control.fd > -1 && *++args)
|
||||
if (zfsess->control->fd > -1 && *++args)
|
||||
return zftp_login(name, args, flags);
|
||||
/* if something wayward happened, connection was already closed */
|
||||
return zfsess->control.fd == -1;
|
||||
return zfsess->control->fd == -1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1995,7 +1995,7 @@ zfgetinfo(char *prompt, int noecho)
|
||||
/* '\n' didn't get echoed */
|
||||
fputc('\n', stdout);
|
||||
fflush(stdout);
|
||||
settyinfo(&shttyinfo);
|
||||
settyinfo(&shttyinfo);
|
||||
}
|
||||
|
||||
return strret;
|
||||
@ -2127,7 +2127,7 @@ zftp_login(char *name, char **args, int flags)
|
||||
}
|
||||
|
||||
zsfree(ucmd);
|
||||
if (zfsess->control.fd == -1)
|
||||
if (zfsess->control->fd == -1)
|
||||
return 1;
|
||||
if (stopit == 2 || (lastcode != 230 && lastcode != 202)) {
|
||||
zwarnnam(name, "login failed", NULL, 0);
|
||||
@ -2206,7 +2206,7 @@ zftp_test(char *name, char **args, int flags)
|
||||
struct timeval tv;
|
||||
# endif /* HAVE_POLL */
|
||||
|
||||
if (zfsess->control.fd == -1)
|
||||
if (zfsess->control->fd == -1)
|
||||
return 1;
|
||||
|
||||
# ifdef HAVE_POLL
|
||||
@ -2214,7 +2214,7 @@ zftp_test(char *name, char **args, int flags)
|
||||
/* safety first, though I think POLLIN is more common */
|
||||
# define POLLIN POLLNORM
|
||||
# endif /* HAVE_POLL */
|
||||
pfd.fd = zfsess->control.fd;
|
||||
pfd.fd = zfsess->control->fd;
|
||||
pfd.events = POLLIN;
|
||||
if ((ret = poll(&pfd, 1, 0)) < 0 && errno != EINTR && errno != EAGAIN)
|
||||
zfclose(0);
|
||||
@ -2224,10 +2224,10 @@ zftp_test(char *name, char **args, int flags)
|
||||
}
|
||||
# else
|
||||
FD_ZERO(&f);
|
||||
FD_SET(zfsess->control.fd, &f);
|
||||
FD_SET(zfsess->control->fd, &f);
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
if ((ret = select(zfsess->control.fd +1, (SELECT_ARG_2_T) &f,
|
||||
if ((ret = select(zfsess->control->fd +1, (SELECT_ARG_2_T) &f,
|
||||
NULL, NULL, &tv)) < 0
|
||||
&& errno != EINTR)
|
||||
zfclose(0);
|
||||
@ -2236,8 +2236,8 @@ zftp_test(char *name, char **args, int flags)
|
||||
zfgetmsg();
|
||||
}
|
||||
# endif /* HAVE_POLL */
|
||||
/* if we now have zfsess->control.fd == -1, then we've just been dumped out. */
|
||||
return (zfsess->control.fd == -1) ? 2 : 0;
|
||||
/* if we now have zfsess->control->fd == -1, then we've just been dumped out. */
|
||||
return (zfsess->control->fd == -1) ? 2 : 0;
|
||||
#else
|
||||
zfwarnnam(name, "not supported on this system.", NULL, 0);
|
||||
return 3;
|
||||
@ -2659,7 +2659,7 @@ zfclose(int leaveparams)
|
||||
char **aptr;
|
||||
Eprog prog;
|
||||
|
||||
if (zfsess->control.fd == -1)
|
||||
if (zfsess->control->fd == -1)
|
||||
return;
|
||||
|
||||
zfclosing = 1;
|
||||
@ -2675,9 +2675,9 @@ zfclose(int leaveparams)
|
||||
fclose(zfsess->cin);
|
||||
zfsess->cin = NULL;
|
||||
}
|
||||
if (zfsess->control.fd != -1) {
|
||||
if (zfsess->control->fd != -1) {
|
||||
zfnopen--;
|
||||
tcp_close(&(zfsess->control));
|
||||
tcp_close(zfsess->control);
|
||||
}
|
||||
|
||||
if (zfstatfd != -1) {
|
||||
@ -2750,7 +2750,7 @@ newsession(char *nm)
|
||||
if (!nptr) {
|
||||
zfsess = (Zftp_session) zcalloc(sizeof(struct zftp_session));
|
||||
zfsess->name = ztrdup(nm);
|
||||
zfsess->control.fd = zfsess->dfd = -1;
|
||||
zfsess->dfd = -1;
|
||||
zfsess->params = (char **) zcalloc(sizeof(zfparams));
|
||||
zaddlinknode(zfsessions, zfsess);
|
||||
|
||||
@ -2965,7 +2965,7 @@ bin_zftp(char *name, char **args, char *ops, int func)
|
||||
int oldstatus = zfstatusp[zfsessno];
|
||||
lseek(zfstatfd, 0, 0);
|
||||
read(zfstatfd, (char *)zfstatusp, sizeof(int)*zfsesscnt);
|
||||
if (zfsess->control.fd != -1 && (zfstatusp[zfsessno] & ZFST_CLOS)) {
|
||||
if ((zfsess->control && zfsess->control->fd != -1) && (zfstatusp[zfsessno] & ZFST_CLOS)) {
|
||||
/* got closed in subshell without us knowing */
|
||||
zcfinish = 2;
|
||||
zfclose(0);
|
||||
@ -2986,7 +2986,7 @@ bin_zftp(char *name, char **args, char *ops, int func)
|
||||
}
|
||||
}
|
||||
#if defined(HAVE_SELECT) || defined (HAVE_POLL)
|
||||
if (zfsess->control.fd != -1 && !(zptr->flags & (ZFTP_TEST|ZFTP_SESS))) {
|
||||
if ((zfsess->control && zfsess->control->fd != -1) && !(zptr->flags & (ZFTP_TEST|ZFTP_SESS))) {
|
||||
/*
|
||||
* Test the connection for a bad fd or incoming message, but
|
||||
* only if the connection was last heard of open, and
|
||||
@ -2996,7 +2996,7 @@ bin_zftp(char *name, char **args, char *ops, int func)
|
||||
ret = zftp_test("zftp test", NULL, 0);
|
||||
}
|
||||
#endif
|
||||
if ((zptr->flags & ZFTP_CONN) && zfsess->control.fd == -1) {
|
||||
if ((zptr->flags & ZFTP_CONN) && (zfsess->control && zfsess->control->fd == -1)) {
|
||||
if (ret != 2) {
|
||||
/*
|
||||
* with ret == 2, we just got dumped out in the test,
|
||||
|
Loading…
Reference in New Issue
Block a user