📄 tcp_unix.c
字号:
FD_ZERO (&fds); /* initialize selection vector */ FD_ZERO (&efds); /* handle errors too */ FD_SET (stream->tcpsi,&fds); /* set bit in selection vector */ FD_SET (stream->tcpsi,&efds); /* set bit in error selection vector */ FD_SET (stream->tcpso,&efds); /* set bit in error selection vector */ do { /* block under timeout */ tmo.tv_sec = ti - now; i = select (max (stream->tcpsi,stream->tcpso)+1,&fds,0,&efds,&tmo); now = time (0); } while (((i < 0) && (errno == EINTR)) || (ti && !i && (ti > now))); if (i <= 0) { /* timeout or error? */ sprintf (tmp,i ? "error in %s to IMAP server" : "%s to IMAP server timed out",(*service == '*') ? "ssh" : "rsh"); mm_log (tmp,WARN); tcp_close (stream); /* punt stream */ stream = NIL; } (*bn) (BLOCK_NONE,NIL); /* return user name */ strcpy (usrbuf,mb->user[0] ? mb->user : myusername ()); return stream; /* return success */}/* TCP/IP receive line * Accepts: TCP/IP stream * Returns: text line string or NIL if failure */char *tcp_getline (TCPSTREAM *stream){ int n,m; char *st,*ret,*stp; char c = '\0'; char d; /* make sure have data */ if (!tcp_getdata (stream)) return NIL; st = stream->iptr; /* save start of string */ n = 0; /* init string count */ while (stream->ictr--) { /* look for end of line */ d = *stream->iptr++; /* slurp another character */ if ((c == '\015') && (d == '\012')) { ret = (char *) fs_get (n--); memcpy (ret,st,n); /* copy into a free storage string */ ret[n] = '\0'; /* tie off string with null */ return ret; } n++; /* count another character searched */ c = d; /* remember previous character */ } /* copy partial string from buffer */ memcpy ((ret = stp = (char *) fs_get (n)),st,n); /* get more data from the net */ if (!tcp_getdata (stream)) fs_give ((void **) &ret); /* special case of newline broken by buffer */ else if ((c == '\015') && (*stream->iptr == '\012')) { stream->iptr++; /* eat the line feed */ stream->ictr--; ret[n - 1] = '\0'; /* tie off string with null */ } /* else recurse to get remainder */ else if (st = tcp_getline (stream)) { ret = (char *) fs_get (n + 1 + (m = strlen (st))); memcpy (ret,stp,n); /* copy first part */ memcpy (ret + n,st,m); /* and second part */ fs_give ((void **) &stp); /* flush first part */ fs_give ((void **) &st); /* flush second part */ ret[n + m] = '\0'; /* tie off string with null */ } return ret;}/* TCP/IP receive buffer * Accepts: TCP/IP stream * size in bytes * buffer to read into * Returns: T if success, NIL otherwise */long tcp_getbuffer (TCPSTREAM *stream,unsigned long size,char *s){ unsigned long n; /* make sure socket still alive */ if (stream->tcpsi < 0) return NIL; /* can transfer bytes from buffer? */ if (n = min (size,stream->ictr)) { memcpy (s,stream->iptr,n); /* yes, slurp as much as we can from it */ s += n; /* update pointer */ stream->iptr +=n; size -= n; /* update # of bytes to do */ stream->ictr -=n; } if (size) { int i; fd_set fds,efds; struct timeval tmo; time_t t = time (0); blocknotify_t bn=(blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); (*bn) (BLOCK_TCPREAD,NIL); while (size > 0) { /* until request satisfied */ time_t tl = time (0); time_t now = tl; int ti = ttmo_read ? now + ttmo_read : 0; tmo.tv_usec = 0; FD_ZERO (&fds); /* initialize selection vector */ FD_ZERO (&efds); /* handle errors too */ FD_SET (stream->tcpsi,&fds); FD_SET (stream->tcpsi,&efds); errno = NIL; /* block and read */ do { /* block under timeout */ tmo.tv_sec = ti ? ti - now : 0; i = select (stream->tcpsi+1,&fds,0,&efds,ti ? &tmo : 0); now = time (0); } while (((i < 0) && (errno == EINTR)) || (ti && !i && (ti > now))); if (i > 0) { /* select says there's data to read? */ while (((i = read (stream->tcpsi,s,(int) min (maxposint,size))) < 0) && (errno == EINTR)); if (i < 1) return tcp_abort (stream); s += i; /* point at new place to write */ size -= i; /* reduce byte count */ } else if (i || !tmoh || !(*tmoh) (now - t,now - tl)) return tcp_abort (stream); } (*bn) (BLOCK_NONE,NIL); } *s = '\0'; /* tie off string */ return T;}/* TCP/IP receive data * Accepts: TCP/IP stream * Returns: T if success, NIL otherwise */long tcp_getdata (TCPSTREAM *stream){ int i; fd_set fds,efds; struct timeval tmo; time_t t = time (0); blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); if (stream->tcpsi < 0) return NIL; (*bn) (BLOCK_TCPREAD,NIL); while (stream->ictr < 1) { /* if nothing in the buffer */ time_t tl = time (0); /* start of request */ time_t now = tl; int ti = ttmo_read ? now + ttmo_read : 0; tmo.tv_usec = 0; FD_ZERO (&fds); /* initialize selection vector */ FD_ZERO (&efds); /* handle errors too */ FD_SET (stream->tcpsi,&fds);/* set bit in selection vector */ FD_SET(stream->tcpsi,&efds);/* set bit in error selection vector */ errno = NIL; /* block and read */ do { /* block under timeout */ tmo.tv_sec = ti ? ti - now : 0; i = select (stream->tcpsi+1,&fds,0,&efds,ti ? &tmo : 0); now = time (0); } while (((i < 0) && (errno == EINTR)) || (ti && !i && (ti > now))); if (!i) { /* timeout? */ if (tmoh && ((*tmoh) (now - t,now - tl))) continue; else return tcp_abort (stream); } else if (i < 0) return tcp_abort (stream); while (((i = read (stream->tcpsi,stream->ibuf,BUFLEN)) < 0) && (errno == EINTR)); if (i < 1) return tcp_abort (stream); stream->iptr = stream->ibuf;/* point at TCP buffer */ stream->ictr = i; /* set new byte count */ } (*bn) (BLOCK_NONE,NIL); return T;}/* TCP/IP send string as record * Accepts: TCP/IP stream * string pointer * Returns: T if success else NIL */long tcp_soutr (TCPSTREAM *stream,char *string){ return tcp_sout (stream,string,(unsigned long) strlen (string));}/* TCP/IP send string * Accepts: TCP/IP stream * string pointer * byte count * Returns: T if success else NIL */long tcp_sout (TCPSTREAM *stream,char *string,unsigned long size){ int i; fd_set fds,efds; struct timeval tmo; time_t t = time (0); blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); if (stream->tcpso < 0) return NIL; (*bn) (BLOCK_TCPWRITE,NIL); while (size > 0) { /* until request satisfied */ time_t tl = time (0); /* start of request */ time_t now = tl; int ti = ttmo_write ? now + ttmo_write : 0; tmo.tv_usec = 0; FD_ZERO (&fds); /* initialize selection vector */ FD_ZERO (&efds); /* handle errors too */ FD_SET (stream->tcpso,&fds);/* set bit in selection vector */ FD_SET(stream->tcpso,&efds);/* set bit in error selection vector */ errno = NIL; /* block and write */ do { /* block under timeout */ tmo.tv_sec = ti ? ti - now : 0; i = select (stream->tcpso+1,0,&fds,&efds,ti ? &tmo : 0); now = time (0); } while (((i < 0) && (errno == EINTR)) || (ti && !i && (ti > now))); if (!i) { /* timeout? */ if (tmoh && ((*tmoh) (now - t,now - tl))) continue; else return tcp_abort (stream); } else if (i < 0) return tcp_abort (stream); while (((i = write (stream->tcpso,string,size)) < 0) && (errno == EINTR)); if (i < 0) return tcp_abort (stream); size -= i; /* how much we sent */ string += i; } (*bn) (BLOCK_NONE,NIL); return T; /* all done */}/* TCP/IP close * Accepts: TCP/IP stream */void tcp_close (TCPSTREAM *stream){ tcp_abort (stream); /* nuke the stream */ /* flush host names */ if (stream->host) fs_give ((void **) &stream->host); if (stream->remotehost) fs_give ((void **) &stream->remotehost); if (stream->localhost) fs_give ((void **) &stream->localhost); fs_give ((void **) &stream); /* flush the stream */}/* TCP/IP abort stream * Accepts: TCP/IP stream * Returns: NIL always */long tcp_abort (TCPSTREAM *stream){ blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); if (stream->tcpsi >= 0) { /* no-op if no socket */ (*bn) (BLOCK_TCPCLOSE,NIL); close (stream->tcpsi); /* nuke the socket */ if (stream->tcpsi != stream->tcpso) close (stream->tcpso); stream->tcpsi = stream->tcpso = -1; } (*bn) (BLOCK_NONE,NIL); return NIL;}/* TCP/IP get host name * Accepts: TCP/IP stream * Returns: host name for this stream */char *tcp_host (TCPSTREAM *stream){ return stream->host; /* use tcp_remotehost() if want guarantees */}/* TCP/IP get remote host name * Accepts: TCP/IP stream * Returns: host name for this stream */char *tcp_remotehost (TCPSTREAM *stream){ if (!stream->remotehost) { struct sockaddr_in sin; int sinlen = sizeof (struct sockaddr_in); stream->remotehost = /* get socket's peer name */ getpeername (stream->tcpsi,(struct sockaddr *) &sin,(void *) &sinlen) ? cpystr (stream->host) : tcp_name (&sin,NIL); } return stream->remotehost;}/* TCP/IP return port for this stream * Accepts: TCP/IP stream * Returns: port number for this stream */unsigned long tcp_port (TCPSTREAM *stream){ return stream->port; /* return port number */}/* TCP/IP get local host name * Accepts: TCP/IP stream * Returns: local host name */char *tcp_localhost (TCPSTREAM *stream){ if (!stream->localhost) { struct sockaddr_in sin; int sinlen = sizeof (struct sockaddr_in); stream->localhost = /* get socket's name */ ((stream->port & 0xffff000) || getsockname (stream->tcpsi,(struct sockaddr *) &sin,(void *) &sinlen)) ? cpystr (mylocalhost ()) : tcp_name (&sin,NIL); } return stream->localhost; /* return local host name */}/* TCP/IP get client host name (server calls only) * Returns: client host name */static char *myClientHost = NIL;char *tcp_clienthost (){ if (!myClientHost) { struct sockaddr_in sin; int sinlen = sizeof (struct sockaddr_in); /* get stdin's peer name */ myClientHost = getpeername (0,(struct sockaddr *) &sin,(void *) &sinlen) ? cpystr ("UNKNOWN") : tcp_name (&sin,T); } return myClientHost;}/* TCP/IP get server host name (server calls only) * Returns: server host name */static char *myServerHost = NIL;static long myServerPort = -1;char *tcp_serverhost (){ if (!myServerHost) { struct sockaddr_in sin; int sinlen = sizeof (struct sockaddr_in); /* get stdin's name */ if (getsockname (0,(struct sockaddr *) &sin,(void *) &sinlen)) myServerHost = cpystr (mylocalhost ()); else { myServerHost = tcp_name (&sin,NIL); myServerPort = ntohs (sin.sin_port); } } return myServerHost;}/* TCP/IP get server port number (server calls only) * Returns: server port number */long tcp_serverport (){ if (!myServerHost) tcp_serverhost (); return myServerPort;}/* TCP/IP return canonical form of host name * Accepts: host name * Returns: canonical form of host name */char *tcp_canonical (char *name){ char *ret,host[MAILTMPLEN]; struct hostent *he; blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); void *data; /* look like domain literal? */ if (name[0] == '[' && name[strlen (name) - 1] == ']') return name; (*bn) (BLOCK_DNSLOOKUP,NIL); /* quell alarms */ data = (*bn) (BLOCK_SENSITIVE,NIL); /* note that Unix requires lowercase! */ ret = (he = gethostbyname (lcase (strcpy (host,name)))) ? he->h_name : name; (*bn) (BLOCK_NONSENSITIVE,data); (*bn) (BLOCK_NONE,NIL); /* alarms OK now */ return ret;}/* TCP/IP return name from socket * Accepts: socket * verbose flag * Returns: cpystr name */char *tcp_name (struct sockaddr_in *sin,long flag){ char *s,tmp[MAILTMPLEN]; if (allowreversedns) { struct hostent *he; blocknotify_t bn = (blocknotify_t)mail_parameters(NIL,GET_BLOCKNOTIFY,NIL); void *data; (*bn) (BLOCK_DNSLOOKUP,NIL); /* quell alarms */ data = (*bn) (BLOCK_SENSITIVE,NIL); /* translate address to name */ if (!(he = gethostbyaddr ((char *) &sin->sin_addr, sizeof (struct in_addr),sin->sin_family))) sprintf (s = tmp,"[%s]",inet_ntoa (sin->sin_addr)); else if (flag) sprintf (s = tmp,"%s [%s]",he->h_name, inet_ntoa (sin->sin_addr)); else s = he->h_name; (*bn) (BLOCK_NONSENSITIVE,data); (*bn) (BLOCK_NONE,NIL); /* alarms OK now */ } else sprintf (s = tmp,"[%s]",inet_ntoa (sin->sin_addr)); return cpystr (s);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -