Esempio n. 1
0
TCPSTREAM *tcp_open (char *host,char *service,unsigned long port)
{
  TCPSTREAM *stream = NIL;
  int family;
  int sock = -1;
  int ctr = 0;
  int silent = (port & NET_SILENT) ? T : NIL;
  int *ctrp = (port & NET_NOOPENTIMEOUT) ? NIL : &ctr;
  char *s,*hostname,tmp[MAILTMPLEN];
  void *adr;
  size_t adrlen;
  struct servent *sv = NIL;
  blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL);
  void *data,*next;
  port &= 0xffff;		/* erase flags */
				/* lookup service */
  if (service && (sv = getservbyname (service,"tcp")))
    port = ntohs (sv->s_port);
  /* The domain literal form is used (rather than simply the dotted decimal
     as with other Unix programs) because it has to be a valid "host name"
     in mailsystem terminology. */
				/* look like domain literal? */
  if (host[0] == '[' && host[(strlen (host))-1] == ']') {
    strcpy (tmp,host+1);	/* yes, copy number part */
    tmp[(strlen (tmp))-1] = '\0';
    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);
      (*bn) (BLOCK_NONE,NIL);
      fs_give ((void **) &adr);
    }
    else sprintf (tmp,"Bad format domain-literal: %.80s",host);
  }

  else {			/* lookup host name */
    if (tcpdebug) {
      sprintf (tmp,"DNS resolution %.80s",host);
      mm_log (tmp,TCPDEBUG);
    }
    (*bn) (BLOCK_DNSLOOKUP,NIL);/* quell alarms */
    data = (*bn) (BLOCK_SENSITIVE,NIL);
    if (!(s = ip_nametoaddr (host,&adrlen,&family,&hostname,&next)))
      sprintf (tmp,"No such host as %.80s",host);
    (*bn) (BLOCK_NONSENSITIVE,data);
    (*bn) (BLOCK_NONE,NIL);
    if (s) {			/* DNS resolution won? */
      if (tcpdebug) mm_log ("DNS resolution done",TCPDEBUG);
      do {
	(*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);
	(*bn) (BLOCK_NONE,NIL);
      } while ((sock < 0) && s);/* repeat until success or no more addreses */
    }
  }
  if (sock >= 0)  {		/* won */
    stream = (TCPSTREAM *) memset (fs_get (sizeof (TCPSTREAM)),0,
				   sizeof (TCPSTREAM));
    stream->port = port;	/* port number */
				/* init sockets */
    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);
    if (tcpdebug) mm_log ("Stream open and ready for read",TCPDEBUG);
  }
  else if (!silent) mm_log (tmp,ERROR);
  return stream;		/* return success */
}
Esempio n. 2
0
TCPSTREAM *tcp_aopen (NETMBX *mb,char *service,char *usrbuf)
{
  TCPSTREAM *stream = NIL;
  void *adr;
  char host[MAILTMPLEN],tmp[MAILTMPLEN],*path,*argv[MAXARGV+1],*r;
  int i,ti,pipei[2],pipeo[2];
  size_t len;
  time_t now;
  struct timeval tmo;
  fd_set fds,efds;
  blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL);
#ifdef SSHPATH			/* ssh path defined yet? */
  if (!sshpath) sshpath = cpystr (SSHPATH);
#endif
#ifdef RSHPATH			/* rsh path defined yet? */
  if (!rshpath) rshpath = cpystr (RSHPATH);
#endif
  if (*service == '*') {	/* want ssh? */
				/* return immediately if ssh disabled */
    if (!(sshpath && (ti = sshtimeout))) return NIL;
				/* ssh command prototype defined yet? */
    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 */
}
Esempio n. 3
0
TCPSTREAM *tcp_open (char *host,char *service,unsigned long port)
{
  TCPSTREAM *stream = NIL;
  int i,family;
  SOCKET sock = INVALID_SOCKET;
  int silent = (port & NET_SILENT) ? T : NIL;
  char *s,*hostname,tmp[MAILTMPLEN];
  void *adr,*next;
  size_t adrlen;
  struct servent *sv = NIL;
  blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL);
  if (!wsa_initted++) {		/* init Windows Sockets */
    WSADATA wsock;
    if (i = (int) WSAStartup (WINSOCK_VERSION,&wsock)) {
      wsa_initted = 0;		/* in case we try again */
      sprintf (tmp,"Unable to start Windows Sockets (%d)",i);
      mm_log (tmp,ERROR);
      return NIL;
    }
  }
  port &= 0xffff;		/* erase flags */
				/* lookup service */
  if (service && (sv = getservbyname (service,"tcp")))
    port = ntohs (sv->s_port);
  /* The domain literal form is used (rather than simply the dotted decimal
     as with other Windows programs) because it has to be a valid "host name"
     in mailsystem terminology. */
				/* look like domain literal? */
  if (host[0] == '[' && host[(strlen (host))-1] == ']') {
    strcpy (tmp,host+1);	/* yes, copy number part */
    tmp[strlen (tmp)-1] = '\0';
    if (adr = ip_stringtoaddr (tmp,&adrlen,&family)) {
      (*bn) (BLOCK_TCPOPEN,NIL);
      sock = tcp_socket_open (family,adr,adrlen,(unsigned short) port,tmp,
			      hostname = host);
      (*bn) (BLOCK_NONE,NIL);
      fs_give ((void **) &adr);
    }
    else sprintf (tmp,"Bad format domain-literal: %.80s",host);
  }

  else {			/* lookup host name */
    if (tcpdebug) {
      sprintf (tmp,"DNS resolution %.80s",host);
      mm_log (tmp,TCPDEBUG);
    }
    (*bn) (BLOCK_DNSLOOKUP,NIL);/* look up name */
    if (!(s = ip_nametoaddr (host,&adrlen,&family,&hostname,&next)))
      sprintf (tmp,"Host not found (#%d): %s",WSAGetLastError (),host);
    (*bn) (BLOCK_NONE,NIL);
    if (s) {			/* DNS resolution won? */
      if (tcpdebug) mm_log ("DNS resolution done",TCPDEBUG);
      wsa_sock_open++;		/* prevent tcp_abort() from freeing in loop */
      do {
	(*bn) (BLOCK_TCPOPEN,NIL);
	if (((sock = tcp_socket_open (family,s,adrlen,(unsigned short) port,
				      tmp,hostname)) == INVALID_SOCKET) &&
	    (s = ip_nametoaddr (NIL,&adrlen,&family,&hostname,&next)) &&
	    !silent) mm_log (tmp,WARN);
	(*bn) (BLOCK_NONE,NIL);
      } while ((sock == INVALID_SOCKET) && s);
      wsa_sock_open--;		/* undo protection */
    }
  }
  if (sock == INVALID_SOCKET) {	/* do possible cleanup action */
    if (!silent) mm_log (tmp,ERROR);
    tcp_abort (&sock);	
  }
  else {			/* got a socket, create TCP/IP stream */
    stream = (TCPSTREAM *) memset (fs_get (sizeof (TCPSTREAM)),0,
				   sizeof (TCPSTREAM));
    stream->port = port;	/* port number */
				/* init socket */
    stream->tcpsi = stream->tcpso = sock;
    stream->ictr = 0;		/* init input counter */
				/* copy official host name */
    stream->host = cpystr (hostname);
    if (tcpdebug) mm_log ("Stream open and ready for read",TCPDEBUG);
  }
  return stream;		/* return success */
}