diff options
author | Eduardo Chappa <chappa@washington.edu> | 2013-11-02 02:51:18 -0600 |
---|---|---|
committer | Eduardo Chappa <chappa@washington.edu> | 2013-11-02 02:51:18 -0600 |
commit | 7fe712882b909931088a318c08041b0e7974a000 (patch) | |
tree | 2770f9b084e2efc7fc55e96e9bf4352cf2ff33a3 /imap/src/osdep/unix/tcp_unix.c | |
parent | bdfc834badee92ceeb2befe02f1d065ced5b9ddf (diff) | |
download | alpine-7fe712882b909931088a318c08041b0e7974a000.tar.xz |
* Update to version 2.19.1
* Upgrade UW-IMAP to Panda IMAP from https://github.com/jonabbey/panda-imap.
* Replace tabs by spaces in From and Subject fields to control for size in
screen of these fields. Change only in index screen display.
Diffstat (limited to 'imap/src/osdep/unix/tcp_unix.c')
-rw-r--r-- | imap/src/osdep/unix/tcp_unix.c | 119 |
1 files changed, 72 insertions, 47 deletions
diff --git a/imap/src/osdep/unix/tcp_unix.c b/imap/src/osdep/unix/tcp_unix.c index 127cf2ae..652f1250 100644 --- a/imap/src/osdep/unix/tcp_unix.c +++ b/imap/src/osdep/unix/tcp_unix.c @@ -1,13 +1,5 @@ /* ======================================================================== - * Copyright 1988-2008 University of Washington - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * + * Copyright 2008-2011 Mark Crispin * ======================================================================== */ @@ -15,20 +7,30 @@ * Program: UNIX TCP/IP routines * * Author: Mark Crispin - * Networks and Distributed Computing - * Computing & Communications - * University of Washington - * Administration Building, AG-44 - * Seattle, WA 98195 - * Internet: MRC@CAC.Washington.EDU * * Date: 1 August 1988 - * Last Edited: 13 January 2008 + * Last Edited: 29 August 2011 + * + * Previous versions of this file were + * + * Copyright 1988-2008 University of Washington + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * */ #include "ip_unix.c" #undef write /* don't use redefined write() */ + +#ifndef NI_MAXHOST +#define NI_MAXHOST 1025 +#endif + static tcptimeout_t tmoh = NIL; /* TCP timeout handler routine */ static long ttmo_open = 0; /* TCP timeouts, in seconds */ @@ -155,9 +157,11 @@ TCPSTREAM *tcp_open (char *host,char *service,unsigned long port) int ctr = 0; int silent = (port & NET_SILENT) ? T : NIL; int *ctrp = (port & NET_NOOPENTIMEOUT) ? NIL : &ctr; - char *s,*hostname,tmp[MAILTMPLEN]; + char *s,tmp[MAILTMPLEN]; + char *hostname = NIL; void *adr; size_t adrlen; + void *cleanup = NIL; struct servent *sv = NIL; blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); void *data,*next; @@ -175,7 +179,8 @@ TCPSTREAM *tcp_open (char *host,char *service,unsigned long port) if (adr = ip_stringtoaddr (tmp,&adrlen,&family)) { (*bn) (BLOCK_TCPOPEN,NIL); /* get an open socket for this system */ - sock = tcp_socket_open (family,adr,adrlen,port,tmp,ctrp,hostname = host); + sock = tcp_socket_open (family,adr,adrlen,port,tmp,ctrp, + hostname = cpystr(host)); (*bn) (BLOCK_NONE,NIL); fs_give ((void **) &adr); } @@ -189,7 +194,7 @@ TCPSTREAM *tcp_open (char *host,char *service,unsigned long port) } (*bn) (BLOCK_DNSLOOKUP,NIL);/* quell alarms */ data = (*bn) (BLOCK_SENSITIVE,NIL); - if (!(s = ip_nametoaddr (host,&adrlen,&family,&hostname,&next))) + if (!(s = ip_nametoaddr (host,&adrlen,&family,&hostname,&next,&cleanup))) sprintf (tmp,"No such host as %.80s",host); (*bn) (BLOCK_NONSENSITIVE,data); (*bn) (BLOCK_NONE,NIL); @@ -199,13 +204,19 @@ TCPSTREAM *tcp_open (char *host,char *service,unsigned long port) (*bn) (BLOCK_TCPOPEN,NIL); if (((sock = tcp_socket_open (family,s,adrlen,port,tmp,ctrp, hostname)) < 0) && - (s = ip_nametoaddr (NIL,&adrlen,&family,&hostname,&next)) && - !silent) mm_log (tmp,WARN); + (s = ip_nametoaddr (NIL,&adrlen,&family,&hostname,&next, + &cleanup)) && !silent) + mm_log (tmp,WARN); (*bn) (BLOCK_NONE,NIL); } while ((sock < 0) && s);/* repeat until success or no more addreses */ } + ip_nametoaddr (NIL,NIL,NIL,NIL,NIL,&cleanup); + } + if (sock < 0) { /* lost? */ + if (!silent) mm_log (tmp,ERROR); + if (hostname) fs_give ((void **) &hostname); } - if (sock >= 0) { /* won */ + else { /* won */ stream = (TCPSTREAM *) memset (fs_get (sizeof (TCPSTREAM)),0, sizeof (TCPSTREAM)); stream->port = port; /* port number */ @@ -213,11 +224,9 @@ TCPSTREAM *tcp_open (char *host,char *service,unsigned long port) stream->tcpsi = stream->tcpso = sock; /* stash in the snuck-in byte */ if (stream->ictr = ctr) *(stream->iptr = stream->ibuf) = tmp[0]; - /* copy official host name */ - stream->host = cpystr (hostname); + stream->host = hostname; /* copy official host name */ if (tcpdebug) mm_log ("Stream open and ready for read",TCPDEBUG); } - else if (!silent) mm_log (tmp,ERROR); return stream; /* return success */ } @@ -238,17 +247,17 @@ int tcp_socket_open (int family,void *adr,size_t adrlen,unsigned short port, int i,ti,sock,flgs; size_t len; time_t now; - struct protoent *pt = getprotobyname ("tcp"); - fd_set fds,efds; + fd_set rfds,wfds,efds; + char buf[NI_MAXHOST]; struct timeval tmo; struct sockaddr *sadr = ip_sockaddr (family,adr,adrlen,port,&len); blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); /* fetid Solaris */ void *data = (*bn) (BLOCK_SENSITIVE,NIL); - sprintf (tmp,"Trying IP address [%s]",ip_sockaddrtostring (sadr)); + sprintf (tmp,"Trying IP address [%s]",ip_sockaddrtostring (sadr,buf)); mm_log (tmp,NIL); /* make a socket */ - if ((sock = socket (sadr->sa_family,SOCK_STREAM,pt ? pt->p_proto : 0)) < 0) { + if ((sock = socket (sadr->sa_family,SOCK_STREAM,0)) < 0) { sprintf (tmp,"Unable to create TCP socket: %s",strerror (errno)); (*bn) (BLOCK_NONSENSITIVE,data); } @@ -285,13 +294,15 @@ int tcp_socket_open (int family,void *adr,size_t adrlen,unsigned short port, now = time (0); /* open timeout */ ti = ttmo_open ? now + ttmo_open : 0; tmo.tv_usec = 0; - FD_ZERO (&fds); /* initialize selection vector */ + FD_ZERO (&rfds); /* initialize selection vector */ + FD_ZERO (&wfds); FD_ZERO (&efds); /* handle errors too */ - FD_SET (sock,&fds); /* block for error or readable */ + FD_SET (sock,&rfds); /* block for readable, writeable, or error */ + FD_SET (sock,&wfds); FD_SET (sock,&efds); do { /* block under timeout */ tmo.tv_sec = ti ? ti - now : 0; - i = select (sock+1,&fds,NIL,&efds,ti ? &tmo : NIL); + i = select (sock+1,&rfds,&wfds,&efds,ti ? &tmo : NIL); now = time (0); /* fake timeout if interrupt & time expired */ if ((i < 0) && (errno == EINTR) && ti && (ti <= now)) i = 0; } while ((i < 0) && (errno == EINTR)); @@ -300,7 +311,8 @@ int tcp_socket_open (int family,void *adr,size_t adrlen,unsigned short port, fcntl (sock,F_SETFL,flgs); /* This used to be a zero-byte read(), but that crashes Solaris */ /* get socket status */ - while (((i = *ctr = read (sock,tmp,1)) < 0) && (errno == EINTR)); + if(FD_ISSET(sock,&rfds)) + while (((i = *ctr = read (sock,tmp,1)) < 0) && (errno == EINTR)); } if (i <= 0) { /* timeout or error? */ i = i ? errno : ETIMEDOUT;/* determine error code */ @@ -366,7 +378,10 @@ TCPSTREAM *tcp_aopen (NETMBX *mb,char *service,char *usrbuf) return NIL; } } - else strcpy (host,tcp_canonical (mb->host)); + else { + strcpy (host,r = tcp_canonical (mb->host)); + fs_give((void **) &r); + } if (*service == '*') /* build ssh command */ sprintf (tmp,sshcommand,sshpath,host, @@ -765,7 +780,8 @@ long tcp_abort (TCPSTREAM *stream) char *tcp_host (TCPSTREAM *stream) { - return stream->host; /* use tcp_remotehost() if want guarantees */ + /* use tcp_remotehost() if want guarantees */ + return stream ? stream->host : "UNKNOWN"; } @@ -825,12 +841,13 @@ char *tcp_localhost (TCPSTREAM *stream) char *tcp_clientaddr () { if (!myClientAddr) { + char buf[NI_MAXHOST]; size_t sadrlen; struct sockaddr *sadr = ip_newsockaddr (&sadrlen); if (getpeername (0,sadr,(void *) &sadrlen)) myClientAddr = cpystr ("UNKNOWN"); else { /* get stdin's peer name */ - myClientAddr = cpystr (ip_sockaddrtostring (sadr)); + myClientAddr = cpystr (ip_sockaddrtostring (sadr,buf)); if (myClientPort < 0) myClientPort = ip_sockaddrtoport (sadr); } fs_give ((void **) &sadr); @@ -846,6 +863,7 @@ char *tcp_clientaddr () char *tcp_clienthost () { if (!myClientHost) { + char buf[NI_MAXHOST]; size_t sadrlen; struct sockaddr *sadr = ip_newsockaddr (&sadrlen); if (getpeername (0,sadr,(void *) &sadrlen)) { @@ -861,7 +879,7 @@ char *tcp_clienthost () } else { /* get stdin's peer name */ myClientHost = tcp_name (sadr,T); - if (!myClientAddr) myClientAddr = cpystr (ip_sockaddrtostring (sadr)); + if (!myClientAddr) myClientAddr = cpystr (ip_sockaddrtostring(sadr,buf)); if (myClientPort < 0) myClientPort = ip_sockaddrtoport (sadr); } fs_give ((void **) &sadr); @@ -887,12 +905,13 @@ long tcp_clientport () char *tcp_serveraddr () { if (!myServerAddr) { + char buf[NI_MAXHOST]; size_t sadrlen; struct sockaddr *sadr = ip_newsockaddr (&sadrlen); if (getsockname (0,sadr,(void *) &sadrlen)) myServerAddr = cpystr ("UNKNOWN"); else { /* get stdin's name */ - myServerAddr = cpystr (ip_sockaddrtostring (sadr)); + myServerAddr = cpystr (ip_sockaddrtostring (sadr,buf)); if (myServerPort < 0) myServerPort = ip_sockaddrtoport (sadr); } fs_give ((void **) &sadr); @@ -908,6 +927,7 @@ char *tcp_serveraddr () char *tcp_serverhost () { if (!myServerHost) { /* once-only */ + char buf[NI_MAXHOST]; size_t sadrlen; struct sockaddr *sadr = ip_newsockaddr (&sadrlen); /* get stdin's name */ @@ -915,7 +935,7 @@ char *tcp_serverhost () myServerHost = cpystr (mylocalhost ()); else { /* get stdin's name */ myServerHost = tcp_name (sadr,NIL); - if (!myServerAddr) myServerAddr = cpystr (ip_sockaddrtostring (sadr)); + if (!myServerAddr) myServerAddr = cpystr (ip_sockaddrtostring(sadr,buf)); if (myServerPort < 0) myServerPort = ip_sockaddrtoport (sadr); } fs_give ((void **) &sadr); @@ -953,7 +973,7 @@ char *tcp_canonical (char *name) mm_log (host,TCPDEBUG); } /* get canonical name */ - if (!ip_nametoaddr (name,NIL,NIL,&ret,NIL)) ret = name; + if (!ip_nametoaddr (name,NIL,NIL,&ret,NIL,NIL)) ret = cpystr (name); (*bn) (BLOCK_NONSENSITIVE,data); (*bn) (BLOCK_NONE,NIL); /* alarms OK now */ if (tcpdebug) mm_log ("DNS canonicalization done",TCPDEBUG); @@ -968,8 +988,8 @@ char *tcp_canonical (char *name) char *tcp_name (struct sockaddr *sadr,long flag) { - char *ret,*t,adr[MAILTMPLEN],tmp[MAILTMPLEN]; - sprintf (ret = adr,"[%.80s]",ip_sockaddrtostring (sadr)); + char *ret,*t,adr[MAILTMPLEN],tmp[MAILTMPLEN],buf[NI_MAXHOST]; + sprintf (ret = adr,"[%.80s]",ip_sockaddrtostring (sadr,buf)); if (allowreversedns) { blocknotify_t bn = (blocknotify_t)mail_parameters(NIL,GET_BLOCKNOTIFY,NIL); void *data; @@ -980,7 +1000,7 @@ char *tcp_name (struct sockaddr *sadr,long flag) (*bn) (BLOCK_DNSLOOKUP,NIL);/* quell alarms */ data = (*bn) (BLOCK_SENSITIVE,NIL); /* translate address to name */ - if (t = tcp_name_valid (ip_sockaddrtoname (sadr))) { + if (t = tcp_name_valid (ip_sockaddrtoname (sadr,buf))) { /* produce verbose form if needed */ if (flag) sprintf (ret = tmp,"%s %s",t,adr); else ret = t; @@ -1023,18 +1043,23 @@ long tcp_isclienthost (char *host) int family; size_t adrlen,sadrlen,len; void *adr,*next; + char buf[NI_MAXHOST]; struct sockaddr *sadr; + void *cleanup = NIL; long ret = NIL; /* make sure that myClientAddr is set */ - if (tcp_clienthost () && myClientAddr) + if (tcp_clienthost () && myClientAddr) { /* get sockaddr of client */ - for (adr = ip_nametoaddr (host,&adrlen,&family,NIL,&next); adr && !ret; - adr = ip_nametoaddr (NIL,&adrlen,&family,NIL,&next)) { + for (adr = ip_nametoaddr (host,&adrlen,&family,NIL,&next,&cleanup); + adr && !ret; + adr = ip_nametoaddr (NIL,&adrlen,&family,NIL,&next,&cleanup)) { /* build sockaddr of given address */ sadr = ip_sockaddr (family,adr,adrlen,1,&len); - if (!strcmp (myClientAddr,ip_sockaddrtostring (sadr))) ret = LONGT; + if (!strcmp (myClientAddr,ip_sockaddrtostring (sadr,buf))) ret = LONGT; fs_give ((void **) &sadr); /* done with client sockaddr */ } + ip_nametoaddr (NIL,NIL,NIL,NIL,NIL,&cleanup); + } return ret; } |