⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcp_unix.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 3 页
字号:
    if (!sshcommand) sshcommand = cpystr ("%s %s -l %s exec /etc/r%sd");  }				/* want rsh? */  else if (rshpath && (ti = rshtimeout)) {				/* rsh command prototype defined yet? */    if (!rshcommand) rshcommand = cpystr ("%s %s -l %s exec /etc/r%sd");  }  else return NIL;		/* rsh disabled */				/* look like domain literal? */  if (mb->host[0] == '[' && mb->host[i = (strlen (mb->host))-1] == ']') {    strcpy (host,mb->host+1);	/* yes, copy without brackets */    host[i-1] = '\0';				/* validate domain literal */    if (adr = ip_stringtoaddr (host,&len,&i)) fs_give ((void **) &adr);    else {      sprintf (tmp,"Bad format domain-literal: %.80s",host);      mm_log (tmp,ERROR);      return NIL;    }  }  else strcpy (host,tcp_canonical (mb->host));  if (*service == '*')		/* build ssh command */    sprintf (tmp,sshcommand,sshpath,host,	     mb->user[0] ? mb->user : myusername (),service + 1);  else sprintf (tmp,rshcommand,rshpath,host,		mb->user[0] ? mb->user : myusername (),service);  if (tcpdebug) {    char msg[MAILTMPLEN];    sprintf (msg,"Trying %.100s",tmp);    mm_log (msg,TCPDEBUG);  }				/* parse command into argv */  for (i = 1,path = argv[0] = strtok_r (tmp," ",&r);       (i < MAXARGV) && (argv[i] = strtok_r (NIL," ",&r)); i++);  argv[i] = NIL;		/* make sure argv tied off */				/* make command pipes */  if (pipe (pipei) < 0) return NIL;  if ((pipei[0] >= FD_SETSIZE) || (pipei[1] >= FD_SETSIZE) ||      (pipe (pipeo) < 0)) {    close (pipei[0]); close (pipei[1]);    return NIL;  }  (*bn) (BLOCK_TCPOPEN,NIL);	/* quell alarm up here for NeXT */  if ((pipeo[0] >= FD_SETSIZE) || (pipeo[1] >= FD_SETSIZE) ||      ((i = fork ()) < 0)) {	/* make inferior process */    close (pipei[0]); close (pipei[1]);    close (pipeo[0]); close (pipeo[1]);    (*bn) (BLOCK_NONE,NIL);    return NIL;  }  if (!i) {			/* if child */    alarm (0);			/* never have alarms in children */    if (!fork ()) {		/* make grandchild so it's inherited by init */      int cf;			/* don't alter parent vars in case vfork() */      int maxfd = max (20,max (max(pipei[0],pipei[1]),max(pipeo[0],pipeo[1])));      dup2 (pipei[1],1);	/* parent's input is my output */      dup2 (pipei[1],2);	/* parent's input is my error output too */      dup2 (pipeo[0],0);	/* parent's output is my input */				/* close all unnecessary descriptors */      for (cf = 3; cf <= maxfd; cf++) close (cf);      setpgrp (0,getpid ());	/* be our own process group */      _exit (execv (path,argv));/* now run it */    }    _exit (1);			/* child is done */  }  grim_pid_reap (i,NIL);	/* reap child; grandchild now owned by init */  close (pipei[1]);		/* close child's side of the pipes */  close (pipeo[0]);				/* create TCP/IP stream */  stream = (TCPSTREAM *) memset (fs_get (sizeof (TCPSTREAM)),0,				 sizeof (TCPSTREAM));				/* copy remote host name from argument */  stream->remotehost = cpystr (stream->host = cpystr (host));  stream->tcpsi = pipei[0];	/* init sockets */  stream->tcpso = pipeo[1];  stream->ictr = 0;		/* init input counter */  stream->port = 0xffffffff;	/* no port number */  ti += now = time (0);		/* open timeout */  tmo.tv_usec = 0;		/* initialize usec timeout */  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,NIL,&efds,&tmo);    now = time (0);		/* fake timeout if interrupt & time expired */    if ((i < 0) && (errno == EINTR) && ti && (ti <= now)) i = 0;  } while ((i < 0) && (errno == EINTR));  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 receive line * Accepts: TCP stream * Returns: text line string or NIL if failure */char *tcp_getline (TCPSTREAM *stream){  unsigned long n,contd;  char *ret = tcp_getline_work (stream,&n,&contd);  if (ret && contd) {		/* got a line needing continuation? */    STRINGLIST *stl = mail_newstringlist ();    STRINGLIST *stc = stl;    do {			/* collect additional lines */      stc->text.data = (unsigned char *) ret;      stc->text.size = n;      stc = stc->next = mail_newstringlist ();      ret = tcp_getline_work (stream,&n,&contd);    } while (ret && contd);    if (ret) {			/* stash final part of line on list */      stc->text.data = (unsigned char *) ret;      stc->text.size = n;				/* determine how large a buffer we need */      for (n = 0, stc = stl; stc; stc = stc->next) n += stc->text.size;      ret = fs_get (n + 1);	/* copy parts into buffer */      for (n = 0, stc = stl; stc; n += stc->text.size, stc = stc->next)	memcpy (ret + n,stc->text.data,stc->text.size);      ret[n] = '\0';    }    mail_free_stringlist (&stl);/* either way, done with list */  }  return ret;}/* TCP receive line or partial line * Accepts: TCP stream *	    pointer to return size *	    pointer to return continuation flag * Returns: text line string, size and continuation flag, or NIL if failure */static char *tcp_getline_work (TCPSTREAM *stream,unsigned long *size,			       long *contd){  unsigned long n;  char *s,*ret,c,d;  *contd = NIL;			/* assume no continuation */				/* make sure have data */  if (!tcp_getdata (stream)) return NIL;  for (s = stream->iptr, n = 0, c = '\0'; stream->ictr--; n++, c = d) {    d = *stream->iptr++;	/* slurp another character */    if ((c == '\015') && (d == '\012')) {      ret = (char *) fs_get (n--);      memcpy (ret,s,*size = n);	/* copy into a free storage string */      ret[n] = '\0';		/* tie off string with null */      return ret;    }  }				/* copy partial string from buffer */  memcpy ((ret = (char *) fs_get (n)),s,*size = 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[*size = --n] = '\0';	/* tie off string with null */  }  else *contd = LONGT;		/* continuation needed */  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;      time_t ti = ttmo_read ? now + ttmo_read : 0;      if (tcpdebug) mm_log ("Reading TCP buffer",TCPDEBUG);      tmo.tv_usec = 0;      FD_ZERO (&fds);		/* initialize selection vector */      FD_ZERO (&efds);		/* handle errors too */				/* set bit in selection vectors */      FD_SET (stream->tcpsi,&fds);      FD_SET (stream->tcpsi,&efds);      errno = NIL;		/* initially no error */      do {			/* block under timeout */	tmo.tv_sec = ti ? ti - now : 0;	i = select (stream->tcpsi+1,&fds,NIL,&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));      if (i) {			/* non-timeout result from select? */	if (i > 0)		/* read what we can */	  while (((i = read (stream->tcpsi,s,(int) min (maxposint,size))) < 0)		 && (errno == EINTR));	if (i <= 0) {		/* error seen? */	  if (tcpdebug) {	    char tmp[MAILTMPLEN];	    if (i) sprintf (s = tmp,"TCP buffer read I/O error %d",errno);	    else s = "TCP buffer read end of file";	    mm_log (s,TCPDEBUG);	  }	  return tcp_abort (stream);	}	s += i;			/* success, point at new place to write */	size -= i;		/* reduce byte count */	if (tcpdebug) mm_log ("Successfully read TCP buffer",TCPDEBUG);      }				/* timeout, punt unless told not to */      else if (!tmoh || !(*tmoh) (now - t,now - tl)) {	if (tcpdebug) mm_log ("TCP buffer read timeout",TCPDEBUG);	return tcp_abort (stream);      }    }    (*bn) (BLOCK_NONE,NIL);  }  *s = '\0';			/* tie off string */  return LONGT;}/* 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;    time_t ti = ttmo_read ? now + ttmo_read : 0;    if (tcpdebug) mm_log ("Reading TCP data",TCPDEBUG);    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 vectors */    FD_SET (stream->tcpsi,&efds);    errno = NIL;		/* initially no error */    do {			/* block under timeout */      tmo.tv_sec = ti ? ti - now : 0;      i = select (stream->tcpsi+1,&fds,NIL,&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));    if (i) {			/* non-timeout result from select? */				/* read what we can */      if (i > 0) while (((i = read (stream->tcpsi,stream->ibuf,BUFLEN)) < 0) &&			(errno == EINTR));      if (i <= 0) {		/* error seen? */	if (tcpdebug) {	  char *s,tmp[MAILTMPLEN];	  if (i) sprintf (s = tmp,"TCP data read I/O error %d",errno);	  else s = "TCP data read end of file";	  mm_log (s,TCPDEBUG);	}	return tcp_abort (stream);      }      stream->ictr = i;		/* success, set new count and pointer */      stream->iptr = stream->ibuf;      if (tcpdebug) mm_log ("Successfully read TCP data",TCPDEBUG);    }				/* timeout, punt unless told not to */    else if (!tmoh || !(*tmoh) (now - t,now - tl)) {      if (tcpdebug) mm_log ("TCP data read timeout",TCPDEBUG);      return tcp_abort (stream);/* error or timeout no-continue */    }  }  (*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;    time_t ti = ttmo_write ? now + ttmo_write : 0;    if (tcpdebug) mm_log ("Writing to TCP",TCPDEBUG);    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 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -