Esempio n. 1
0
//
// Clear the Info fields
//
void DecodeDlg::InfoClear()
{

	Info1((const char *) NULL);
	Info2(NULL);

}
Esempio n. 2
0
File: sycls.c Progetto: erluko/socat
int Dup(int oldfd) {
   int newfd, _errno;
   Debug1("dup(%d)", oldfd);
   newfd = dup(oldfd);
   _errno = errno;
   Info2("dup(%d) -> %d", oldfd, newfd);
   errno = _errno;
   return newfd;
}
Esempio n. 3
0
File: sycls.c Progetto: erluko/socat
int Shutdown(int fd, int how) {
   int retval, _errno;
   Info2("shutdown(%d, %d)", fd, how);
   retval = shutdown(fd, how);
   _errno = errno;
   Debug1("shutdown()  -> %d", retval);
   errno = _errno;
   return retval;
}
Esempio n. 4
0
File: User.cpp Progetto: wuwm/keshe
Accountant::Accountant()										//Accountant的构造函数
{
	fstream Info2("info2.dat",ios::in);							//对象创建时自动读入用户名和密码
	if(!Info2)
	{
		cout<<"打开用户名文件失败"<<endl;
	}
	Info2>>uname>>pass;
	Info2.close();
}
Esempio n. 5
0
File: User.cpp Progetto: wuwm/keshe
void Accountant::edit(){										//修改User类的用户名和密码
	string name,pass;
	cout<<"请输入新用户名和密码,用空格隔开"<<endl;
	cin>>name>>pass;
	fstream Info2("info2.dat",ios::out);						//打开用户名和密码文件准备进行修改
	if(!Info2){
		cout<<"打开用户名文件失败"<<endl;
	}
	Info2<<name<<"\t"<<pass;
	Info2.close();												//关闭文件
}
Esempio n. 6
0
void DecodeDlg::DecodeGoDone(int rc)
{

	HourGlass(false);

	m_DecodeOut.ModifyStyle(LVS_SHOWSELALWAYS, 0);

	if (rc < 0)
	{
		SetState(MS_GO, true);		// Force back to Go state
		Info1(IDS_CANCEL);
	}
	else								// Not cancelled, set to DONE, etc.
	{
		int r = m_DecodeOut.GetItemCount() - 1;

		m_DecodeOut.SetImage(r, 
			DecIcon(m_DecodeOut.GetItemData(r), NULL));	// Update the last icon

		SetState(MS_DONE);

		Info1("Done decoding.");

		if (rc != 0)
		{
			CString wrk;

			wrk.Format("%d errors found.", rc);

			Info2(wrk);
		}
		else
			Info2("No errors.");
	}

	if (SHOW_DEBUG)
		deBox.Ready();

}
Esempio n. 7
0
/* return 0 if socket is not responsible for deadchild */
static int xio_checkchild(xiofile_t *socket, int socknum, pid_t deadchild) {
   int retval;
   if (socket != NULL) {
      if (socket->tag != XIO_TAG_DUAL) {
	 if (socket->stream.child.pid == deadchild) {
	    Info2("exec'd process %d on socket %d terminated",
		  socket->stream.child.pid, socknum);
	    sigchld_stream(&socket->stream);
	    return 1;
	 }
      } else {
	 if (retval = xio_checkchild((xiofile_t *)socket->dual.stream[0], socknum, deadchild))
	    return retval;
	 else
	    return xio_checkchild((xiofile_t *)socket->dual.stream[1], socknum, deadchild);
      }
   }
   return 0;
}
Esempio n. 8
0
/* we expect the form: port */
int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
			   int xioflags, xiofile_t *fd,
			  unsigned groups, int pf, int ipproto,
			  int protname) {
   const char *portname = argv[1];
   union sockaddr_union us;
   union sockaddr_union themunion;
   union sockaddr_union *them = &themunion;
   int socktype = SOCK_DGRAM;
   struct pollfd readfd;
   bool dofork = false;
   pid_t pid;
   char *rangename;
   char infobuff[256];
   unsigned char buff1[1];
   socklen_t uslen;
   socklen_t themlen;
   int result;

   if (argc != 2) {
      Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
   }

   if (pf == PF_UNSPEC) {
#if WITH_IP4 && WITH_IP6
      pf = xioopts.default_ip=='6'?PF_INET6:PF_INET;
#elif WITH_IP6
      pf = PF_INET6;
#else
      pf = PF_INET;
#endif
   }

   retropt_socket_pf(opts, &pf);

   if (applyopts_single(&fd->stream, opts, PH_INIT) < 0)  return -1;
   applyopts(-1, opts, PH_INIT);

   uslen = socket_init(pf, &us);
   retropt_bind(opts, pf, socktype, IPPROTO_UDP,
		(struct sockaddr *)&us, &uslen, 1,
		fd->stream.para.socket.ip.res_opts[1],
		fd->stream.para.socket.ip.res_opts[0]);

   if (false) {
      ;
#if WITH_IP4
   } else if (pf == PF_INET) {
      us.ip4.sin_port = parseport(portname, ipproto);
#endif
#if WITH_IP6
   } else if (pf == PF_INET6) {
      us.ip6.sin6_port = parseport(portname, ipproto);
#endif
   } else {
      Error1("xioopen_ipdgram_listen(): unknown address family %d", pf);
   }

   retropt_bool(opts, OPT_FORK, &dofork);

   if (dofork) {
      if (!(xioflags & XIO_MAYFORK)) {
	 Error("option fork not allowed here");
	 return STAT_NORETRY;
      }
   }

#if WITH_IP4 /*|| WITH_IP6*/
   if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
      if (xioparserange(rangename, pf, &fd->stream.para.socket.range) < 0) {
	 free(rangename);
	 return STAT_NORETRY;
      }
      free(rangename);
      fd->stream.para.socket.dorange = true;
   }
#endif

#if WITH_LIBWRAP
   xio_retropt_tcpwrap(&fd->stream, opts);
#endif /* WITH_LIBWRAP */

   if (retropt_ushort(opts, OPT_SOURCEPORT, &fd->stream.para.socket.ip.sourceport)
       >= 0) {
      fd->stream.para.socket.ip.dosourceport = true;
   }
   retropt_bool(opts, OPT_LOWPORT, &fd->stream.para.socket.ip.lowport);

   if (dofork) {
      xiosetchilddied();	/* set SIGCHLD handler */
   }

   while (true) {	/* we loop with fork or prohibited packets */
      /* now wait for some packet on this datagram socket, get its sender
	 address, connect there, and return */
      int one = 1;
      char infobuff[256];
      union sockaddr_union _sockname;
      union sockaddr_union *la = &_sockname;	/* local address */

      if ((fd->stream.fd = xiosocket(opts, pf, socktype, ipproto, E_ERROR)) < 0) {
	 return STAT_RETRYLATER;
      }
      applyopts(fd->stream.fd, opts, PH_PASTSOCKET);
      if (Setsockopt(fd->stream.fd, opt_so_reuseaddr.major,
		     opt_so_reuseaddr.minor, &one, sizeof(one)) < 0) {
	 Warn6("setsockopt(%d, %d, %d, {%d}, "F_Zd"): %s",
	       fd->stream.fd, opt_so_reuseaddr.major,
	       opt_so_reuseaddr.minor, one, sizeof(one), strerror(errno));
      }
      applyopts_cloexec(fd->stream.fd, opts);
      applyopts(fd->stream.fd, opts, PH_PREBIND);
      applyopts(fd->stream.fd, opts, PH_BIND);
      if (Bind(fd->stream.fd, &us.soa, uslen) < 0) {
	 Error4("bind(%d, {%s}, "F_Zd"): %s", fd->stream.fd,
		sockaddr_info(&us.soa, uslen, infobuff, sizeof(infobuff)),
		uslen, strerror(errno));
	 return STAT_RETRYLATER;
      }
      /* under some circumstances bind() fills sockaddr with interesting info. */
      if (Getsockname(fd->stream.fd, &us.soa, &uslen) < 0) {
	 Error4("getsockname(%d, %p, {%d}): %s",
		fd->stream.fd, &us.soa, uslen, strerror(errno));
      }
      applyopts(fd->stream.fd, opts, PH_PASTBIND);

      Notice1("listening on UDP %s",
	      sockaddr_info(&us.soa, uslen, infobuff, sizeof(infobuff)));
      readfd.fd = fd->stream.fd;
      readfd.events = POLLIN|POLLERR;
      while (xiopoll(&readfd, 1, NULL) < 0) {
	 if (errno != EINTR)  break;
      }

      themlen = socket_init(pf, them);
      do {
	 result = Recvfrom(fd->stream.fd, buff1, 1, MSG_PEEK,
			     &them->soa, &themlen);
      } while (result < 0 && errno == EINTR);
      if (result < 0) {
	 Error5("recvfrom(%d, %p, 1, MSG_PEEK, {%s}, {"F_Zu"}): %s",
		fd->stream.fd, buff1,
		sockaddr_info(&them->soa, themlen, infobuff, sizeof(infobuff)),
		themlen, strerror(errno));
	 return STAT_RETRYLATER;
      }

      Notice1("accepting UDP connection from %s",
	      sockaddr_info(&them->soa, themlen, infobuff, sizeof(infobuff)));

      if (xiocheckpeer(&fd->stream, them, la) < 0) {
	 /* drop packet */
	 char buff[512];
	 Recv(fd->stream.fd, buff, sizeof(buff), 0);	/* drop packet */
	 Close(fd->stream.fd);
	 continue;
      }
      Info1("permitting UDP connection from %s",
	    sockaddr_info(&them->soa, themlen, infobuff, sizeof(infobuff)));

      if (dofork) {
	 pid = xio_fork(false, E_ERROR);
	 if (pid < 0) {
	    return STAT_RETRYLATER;
	 }

	 if (pid == 0) {	/* child */
	    break;
	 }

	 /* server: continue loop with socket()+recvfrom() */
	 /* when we dont close this we get awkward behaviour on Linux 2.4:
	    recvfrom gives 0 bytes with invalid socket address */
	 if (Close(fd->stream.fd) < 0) {
	    Info2("close(%d): %s", fd->stream.fd, strerror(errno));
	 }
	 Sleep(1);	/*! give child a chance to consume the old packet */

	 continue;
      }
      break;
   }

   applyopts(fd->stream.fd, opts, PH_CONNECT);
   if ((result = Connect(fd->stream.fd, &them->soa, themlen)) < 0) {
      Error4("connect(%d, {%s}, "F_Zd"): %s",
	     fd->stream.fd,
	     sockaddr_info(&them->soa, themlen, infobuff, sizeof(infobuff)),
	     themlen, strerror(errno));
      return STAT_RETRYLATER;
   }

   /* set the env vars describing the local and remote sockets */
   if (Getsockname(fd->stream.fd, &us.soa, &uslen) < 0) {
      Warn4("getsockname(%d, %p, {%d}): %s",
	    fd->stream.fd, &us.soa, uslen, strerror(errno));
   }
   xiosetsockaddrenv("SOCK", &us,  uslen,   IPPROTO_UDP);
   xiosetsockaddrenv("PEER", them, themlen, IPPROTO_UDP);

   fd->stream.howtoend = END_SHUTDOWN;
   applyopts_fchown(fd->stream.fd, opts);
   applyopts(fd->stream.fd, opts, PH_LATE);

   if ((result = _xio_openlate(&fd->stream, opts)) < 0)
      return result;

   return 0;
}
Esempio n. 9
0
/* creates the listening socket, bind, applies options; waits for incoming
   connection, checks its source address and port. Depending on fork option, it
   may fork a subprocess.
   pf specifies the syntax expected for range option. In the case of generic
   socket it is 0 (expecting raw binary data), and the real pf can be obtained
   from us->af_family; for other socket types pf == us->af_family
   Returns 0 if a connection was accepted; with fork option, this is always in
   a subprocess!
   Other return values indicate a problem; this can happen in the master
   process or in a subprocess.
   This function does not retry. If you need retries, handle this in a
   loop in the calling function (and always provide the options...)
   After fork, we set the forever/retry of the child process to 0
   applies and consumes the following option:
   PH_INIT, PH_PASTSOCKET, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_EARLY,
   PH_PREOPEN, PH_FD, PH_CONNECTED, PH_LATE, PH_LATE2
   OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_BACKLOG, OPT_RANGE, tcpwrap,
   OPT_SOURCEPORT, OPT_LOWPORT, cloexec
 */
int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, socklen_t uslen,
		 struct opt *opts, int pf, int socktype, int proto, int level) {
   struct sockaddr sa;
   socklen_t salen;
   int backlog = 5;	/* why? 1 seems to cause problems under some load */
   char *rangename;
   bool dofork = false;
   int maxchildren = 0;
   char infobuff[256];
   char lisname[256];
   union sockaddr_union _peername;
   union sockaddr_union _sockname;
   union sockaddr_union *pa = &_peername;	/* peer address */
   union sockaddr_union *la = &_sockname;	/* local address */
   socklen_t pas = sizeof(_peername);	/* peer address size */
   socklen_t las = sizeof(_sockname);	/* local address size */
   int result;

   retropt_bool(opts, OPT_FORK, &dofork);

   if (dofork) {
      if (!(xioflags & XIO_MAYFORK)) {
	 Error("option fork not allowed here");
	 return STAT_NORETRY;
      }
      xfd->flags |= XIO_DOESFORK;
   }

   retropt_int(opts, OPT_MAX_CHILDREN, &maxchildren);

   if (! dofork && maxchildren) {
       Error("option max-children not allowed without option fork");
       return STAT_NORETRY;
   }

   if (applyopts_single(xfd, opts, PH_INIT) < 0)  return -1;

   if (dofork) {
      xiosetchilddied();	/* set SIGCHLD handler */
   }

   if ((xfd->fd = xiosocket(opts, us->sa_family, socktype, proto, level)) < 0) {
      return STAT_RETRYLATER;
   }

   applyopts_cloexec(xfd->fd, opts);

   applyopts(xfd->fd, opts, PH_PREBIND);
   applyopts(xfd->fd, opts, PH_BIND);
   if (Bind(xfd->fd, (struct sockaddr *)us, uslen) < 0) {
      Msg4(level, "bind(%d, {%s}, "F_socklen"): %s", xfd->fd,
	   sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen,
	   strerror(errno));
      Close(xfd->fd);
      return STAT_RETRYLATER;
   }

#if WITH_UNIX
   if (us->sa_family == AF_UNIX) {
      applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_FD);
   }
#endif
   /* under some circumstances (e.g., TCP listen on port 0) bind() fills empty
      fields that we want to know. */
   salen = sizeof(sa);
   if (Getsockname(xfd->fd, us, &uslen) < 0) {
      Warn4("getsockname(%d, %p, {%d}): %s",
	    xfd->fd, &us, uslen, strerror(errno));
   }

   applyopts(xfd->fd, opts, PH_PASTBIND);
#if WITH_UNIX
   if (us->sa_family == AF_UNIX) {
      /*applyopts_early(((struct sockaddr_un *)us)->sun_path, opts);*/
      applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_EARLY);
      applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_PREOPEN);
   }
#endif /* WITH_UNIX */

#if WITH_IP4 /*|| WITH_IP6*/
   if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
      if (xioparserange(rangename, pf, &xfd->para.socket.range)
	  < 0) {
	 free(rangename);
	 return STAT_NORETRY;
      }
      free(rangename);
      xfd->para.socket.dorange = true;
   }
#endif

#if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP
   xio_retropt_tcpwrap(xfd, opts);
#endif /* && (WITH_TCP || WITH_UDP) && WITH_LIBWRAP */

#if WITH_TCP || WITH_UDP
   if (retropt_ushort(opts, OPT_SOURCEPORT, &xfd->para.socket.ip.sourceport) >= 0) {
      xfd->para.socket.ip.dosourceport = true;
   }
   retropt_bool(opts, OPT_LOWPORT, &xfd->para.socket.ip.lowport);
#endif /* WITH_TCP || WITH_UDP */

   applyopts(xfd->fd, opts, PH_PRELISTEN);
   retropt_int(opts, OPT_BACKLOG, &backlog);
   if (Listen(xfd->fd, backlog) < 0) {
      Error3("listen(%d, %d): %s", xfd->fd, backlog, strerror(errno));
      return STAT_RETRYLATER;
   }

   if (xioopts.logopt == 'm') {
      Info("starting accept loop, switching to syslog");
      diag_set('y', xioopts.syslogfac);  xioopts.logopt = 'y';
   } else {
      Info("starting accept loop");
   }
   while (true) {	/* but we only loop if fork option is set */
      char peername[256];
      char sockname[256];
      int ps;		/* peer socket */

      pa = &_peername;
      la = &_sockname;
      salen = sizeof(struct sockaddr);
      do {
	 /*? int level = E_ERROR;*/
	 Notice1("listening on %s", sockaddr_info(us, uslen, lisname, sizeof(lisname)));
	 ps = Accept(xfd->fd, (struct sockaddr *)&sa, &salen);
	 if (ps >= 0) {
	    /*0 Info4("accept(%d, %p, {"F_Zu"}) -> %d", xfd->fd, &sa, salen, ps);*/
	    break;	/* success, break out of loop */
	 }
	 if (errno == EINTR) {
	    continue;
	 }
	 if (errno == ECONNABORTED) {
	    Notice4("accept(%d, %p, {"F_socklen"}): %s",
		    xfd->fd, &sa, salen, strerror(errno));
	    continue;
	 }
	 Msg4(level, "accept(%d, %p, {"F_socklen"}): %s",
	      xfd->fd, &sa, salen, strerror(errno));
	 Close(xfd->fd);
	 return STAT_RETRYLATER;
      } while (true);
      applyopts_cloexec(ps, opts);
      if (Getpeername(ps, &pa->soa, &pas) < 0) {
	 Warn4("getpeername(%d, %p, {"F_socklen"}): %s",
	       ps, pa, pas, strerror(errno));
	 pa = NULL;
      }
      if (Getsockname(ps, &la->soa, &las) < 0) {
	 Warn4("getsockname(%d, %p, {"F_socklen"}): %s",
	       ps, la, las, strerror(errno));
	 la = NULL;
      }
      Notice2("accepting connection from %s on %s",
	      pa?
	      sockaddr_info(&pa->soa, pas, peername, sizeof(peername)):"NULL",
	      la?
	      sockaddr_info(&la->soa, las, sockname, sizeof(sockname)):"NULL");

      if (pa != NULL && la != NULL && xiocheckpeer(xfd, pa, la) < 0) {
	 if (Shutdown(ps, 2) < 0) {
	    Info2("shutdown(%d, 2): %s", ps, strerror(errno));
	 }
	 Close(ps);
	 continue;
      }

      if (pa != NULL)
	 Info1("permitting connection from %s",
	       sockaddr_info((struct sockaddr *)pa, pas,
			     infobuff, sizeof(infobuff)));

      if (dofork) {
	 pid_t pid;	/* mostly int; only used with fork */
         sigset_t mask_sigchld;

         /* we must prevent that the current packet triggers another fork;
            therefore we wait for a signal from the recent child: USR1
            indicates that is has consumed the last packet; CHLD means it has
            terminated */
         /* block SIGCHLD and SIGUSR1 until parent is ready to react */
         sigemptyset(&mask_sigchld);
         sigaddset(&mask_sigchld, SIGCHLD);
         Sigprocmask(SIG_BLOCK, &mask_sigchld, NULL);

	 if ((pid = xio_fork(false, level==E_ERROR?level:E_WARN)) < 0) {
	    Close(xfd->fd);
	    Sigprocmask(SIG_UNBLOCK, &mask_sigchld, NULL);
	    return STAT_RETRYLATER;
	 }
	 if (pid == 0) {	/* child */
	    pid_t cpid = Getpid();
	    Sigprocmask(SIG_UNBLOCK, &mask_sigchld, NULL);

	    Info1("just born: child process "F_pid, cpid);
	    xiosetenvulong("PID", cpid, 1);

	    if (Close(xfd->fd) < 0) {
	       Info2("close(%d): %s", xfd->fd, strerror(errno));
	    }
	    xfd->fd = ps;

#if WITH_RETRY
	    /* !? */
	    xfd->forever = false;  xfd->retry = 0;
	    level = E_ERROR;
#endif /* WITH_RETRY */

	    break;
	 }

	 /* server: continue loop with listen */
	 /* shutdown() closes the socket even for the child process, but
	    close() does what we want */
	 if (Close(ps) < 0) {
	    Info2("close(%d): %s", ps, strerror(errno));
	 }

         /* now we are ready to handle signals */
         Sigprocmask(SIG_UNBLOCK, &mask_sigchld, NULL);

	 while (maxchildren) {
	    if (num_child < maxchildren) break;
	    Notice("maxchildren are active, waiting");
	    /* UINT_MAX would even be nicer, but Openindiana works only
	       with 31 bits */
	    while (!Sleep(INT_MAX)) ;	/* any signal lets us continue */
	 }
	 Info("still listening");
      } else {
	 if (Close(xfd->fd) < 0) {
	    Info2("close(%d): %s", xfd->fd, strerror(errno));
	 }
	 xfd->fd = ps;
	break;
      }
   }

   applyopts(xfd->fd, opts, PH_FD);
   applyopts(xfd->fd, opts, PH_PASTSOCKET);
   applyopts(xfd->fd, opts, PH_CONNECTED);
   if ((result = _xio_openlate(xfd, opts)) < 0)
      return result;

   /* set the env vars describing the local and remote sockets */
   if (la != NULL)  xiosetsockaddrenv("SOCK", la, las, proto);
   if (pa != NULL)  xiosetsockaddrenv("PEER", pa, pas, proto);

   return 0;
}
Esempio n. 10
0
void DecodeDlg::DecodePreviewDone(int rc)
{
	bool clmode = ((CUud32App *) AfxGetApp())->GetCLMode();

	if (SHOW_DEBUG)
	{
		deBox.Ready();					// OK to interact with debug box
		decoder->UD.SetLastMessage("");			// Messages already retrieved
	}

	if (rc == CUud32acxCtrl::uudRetCancel)		// Cancel.
	{
		HourGlass(false);
		m_DecodeGo.SetLabel(IDS_PREVIEW);
		Info1(IDS_CANCEL);
		return;
	}
	else if (rc != CUud32acxCtrl::uudRetOK)
	{
		CString emsg(decoder->UD.GetLastMessage());

		CString lfn;

		int row = m_DecodeList.GetFirstSel();

		if (row >= 0)
			m_DecodeList.GetText(row, lfn);
		else
			lfn = "(Unknown?)";

		if (ArgMessageBox("Load Encoded Files", MB_OKCANCEL | MB_ICONQUESTION,
				"Error loading file:\r\n%s\r\nCode: %d [%s]\r\nContinue?",
				(const char *) lfn, rc, (const char *) emsg) == IDOK)
			decoder->PostThreadMessage(ENG_LOAD, 0, 0);		// Restart the engine with next file
		else
		{
			HourGlass(false);
			Info1(IDS_CANCEL);
			m_DecodeGo.SetLabel(IDS_PREVIEW);
		}

		return;
	}

	Info1("Done loading.");
	CString lfn(decoder->UD.GetLastMessage());
	Info2(lfn);			// Messages already routed

	m_DecodeList.SetSel(-1, FALSE);			// Clear all selections
	m_DecodeList.SetCaretIndex(0, FALSE);	// Scroll list back to top

	int row, rmax = decoder->UD.GetDFCount();					// Read maximum file count
	CString cpath(CurrentOutput());

	if (rmax == 0) 
	{
		Info1(IDS_NOTHING_DECODE);

		if (!clmode)
		{
			CString msg;
			msg.LoadString(IDS_NOFIND_DECODE);
			MessageBox(msg, "Decode",
				MB_ICONEXCLAMATION | MB_OK);
		}

		m_DecodeGo.SetLabel(IDS_PREVIEW);
		HourGlass(false);
		SetState(MS_PREVIEW);
		return;
	}

	m_DecodeOut.SetRedraw(FALSE);

	m_DecodeOut.SetItemCount(rmax + 1);		// Maximum items to add...

	for (row=0; row < rmax; row++)
		if (!(decoder->UD.GetDFileFlags(row) & CUud32acxCtrl::uudFileNoData)) 
		{
			lfn = decoder->UD.GetDFile(row);
			lfn = decoder->UD.FileFilter(lfn);
			if (!options[OPT_PCASE])		// Preserve case on output
				lfn.MakeLower();
			m_DecodeOut.InsertItem(LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM, 0, lfn, 0, 0, DecIcon(row, cpath + lfn), row);
		}

	m_DecodeOut.SetRedraw(TRUE);

	HourGlass(false);

	if (m_DecodeOut.GetItemCount() == 0)
	{
		Info1(IDS_NOTHING_DECODE);

		CString msg;
		msg.LoadString(IDS_NOTHING_DECODE);

		m_DecodeGo.SetLabel(IDS_PREVIEW);

		if (!clmode)
			MessageBox(msg, "Decode",
				MB_ICONEXCLAMATION | MB_OK);

		SetState(MS_PREVIEW);
		return;
	}

	DupCheck();
	SetState(MS_GO);

	if (options[OPT_DNOPROMPT])		// Decode without prompting
	{
		CWnd *go = GetDlgItem(IDC_DECODEGO);

		ASSERT(go != NULL);

		if (!clmode && go != NULL)			// Not command line mode
			PostMessage(WM_COMMAND, IDC_DECODEGO, (LPARAM) go->m_hWnd);
	}

}
Esempio n. 11
0
/* the current socat/xio implementation knows two kinds of children:
   exec/system addresses perform a fork: their children are registered and
   their death's influence the parents' flow;
   listen-socket with fork children: these children are "anonymous" and their
   death does not affect the parent process (now; maybe we have a child
   process counter later) */
void childdied(int signum
#if HAVE_SIGACTION
	       , siginfo_t *siginfo, void *context
#endif /* HAVE_SIGACTION */
	       ) {
   pid_t pid;
   int _errno;
   int status = 0;
   bool wassig = false;
   int i;
   struct _xiosigchld_child *entry;

   _errno = errno;	/* save current value; e.g., select() on Cygwin seems
			   to set it to EINTR _before_ handling the signal, and
			   then passes the value left by the signal handler to
			   the caller of select(), accept() etc. */
   /* is not thread/signal save, but confused messages in rare cases are better
      than no messages at all */
   Info1("childdied(signum=%d)", signum);
   do {
      pid = Waitpid(-1, &status, WNOHANG);
      if (pid == 0) {
	 Msg(wassig?E_INFO:E_WARN,
	     "waitpid(-1, {}, WNOHANG): no child has exited");
	 Info("childdied() finished");
	 errno = _errno;
	 return;
      } else if (pid < 0 && errno == ECHILD) {
	 Msg1(wassig?E_INFO:E_WARN,
	      "waitpid(-1, {}, WNOHANG): %s", strerror(errno));
	 Info("childdied() finished");
	 errno = _errno;
	 return;
      }
      wassig = true;
      if (pid < 0) {
	 Warn2("waitpid(-1, {%d}, WNOHANG): %s", status, strerror(errno));
	 Info("childdied() finished");
	 errno = _errno;
	 return;
      }
#if 0
   /*! indent */
   /* check if it was a registered child process */
   i = 0;
   while (i < XIO_MAXSOCK) {
      if (xio_checkchild(sock[i], i, pid))  break;
      ++i;
   }
   if (i == XIO_MAXSOCK) {
	 Info2("childdied(%d): cannot identify child %d", signum, pid);
	 if (diedunknown1 == 0) {
	    diedunknown1 = pid;
	    Debug("saving pid in diedunknown1");
	 } else if (diedunknown2 == 0) {
	    diedunknown2 = pid;
	    Debug("saving pid in diedunknown2");
	 } else if (diedunknown3 == 0) {
	     diedunknown3 = pid;
	    Debug("saving pid in diedunknown3");
	 } else {
	    diedunknown4 = pid;
	    Debug("saving pid in diedunknown4");
	 }
      }
#else
   entry = _xiosigchld_find(pid);
   if (entry == NULL) {
      Info("dead child "F_pid" died unknown");
   } else {
      (*entry->sigaction)(signum, siginfo, entry->context);
      xiosigchld_unregister(pid);
   }
#endif

   if (WIFEXITED(status)) {
      if (WEXITSTATUS(status) == 0) {
	 Info2("waitpid(): child %d exited with status %d",
	       pid, WEXITSTATUS(status));
      } else {
	 Warn2("waitpid(): child %d exited with status %d",
	       pid, WEXITSTATUS(status));
      }
   } else if (WIFSIGNALED(status)) {
      Info2("waitpid(): child %d exited on signal %d",
	    pid, WTERMSIG(status));
   } else if (WIFSTOPPED(status)) {
      Info2("waitpid(): child %d stopped on signal %d",
	    pid, WSTOPSIG(status));
   } else {
      Warn1("waitpid(): cannot determine status of child %d", pid);
   }

#if !HAVE_SIGACTION
   /* we might need to re-register our handler */
   if (Signal(SIGCHLD, childdied) == SIG_ERR) {
      Warn2("signal(SIGCHLD, %p): %s", childdied, strerror(errno));
   }
#endif /* !HAVE_SIGACTION */
  } while (1);
   Info("childdied() finished");
   errno = _errno;
}
Esempio n. 12
0
/* perform socks4 client dialog on existing FD.
   Called within fork/retry loop, after connect() */
int _xioopen_socks4_connect(struct single *xfd,
                            struct socks4 *sockhead,
                            size_t headlen,
                            int level) {
    ssize_t bytes;
    int result;
    unsigned char buff[SIZEOF_STRUCT_SOCKS4];
    struct socks4 *replyhead = (struct socks4 *)buff;
    char *destdomname = NULL;

    /* send socks header (target addr+port, +auth) */
#if WITH_MSGLEVEL <= E_INFO
    if (ntohl(sockhead->dest) <= 0x000000ff) {
        destdomname = strchr(sockhead->userid, '\0')+1;
    }
    Info11("sending socks4%s request VN=%d DC=%d DSTPORT=%d DSTIP=%d.%d.%d.%d USERID=%s%s%s",
           destdomname?"a":"",
           sockhead->version, sockhead->action, ntohs(sockhead->port),
           ((unsigned char *)&sockhead->dest)[0],
           ((unsigned char *)&sockhead->dest)[1],
           ((unsigned char *)&sockhead->dest)[2],
           ((unsigned char *)&sockhead->dest)[3],
           sockhead->userid,
           destdomname?" DESTNAME=":"",
           destdomname?destdomname:"");
#endif /* WITH_MSGLEVEL <= E_INFO */
#if WITH_MSGLEVEL <= E_DEBUG
    {
        char *msgbuff;
        if ((msgbuff = Malloc(3*headlen)) != NULL) {
            xiohexdump((const unsigned char *)sockhead, headlen, msgbuff);
            Debug1("sending socks4(a) request data %s", msgbuff);
        }
    }
#endif /* WITH_MSGLEVEL <= E_DEBUG */
    if (writefull(xfd->fd, sockhead, headlen) < 0) {
        Msg4(level, "write(%d, %p, "F_Zu"): %s",
             xfd->fd, sockhead, headlen, strerror(errno));
        if (Close(xfd->fd) < 0) {
            Info2("close(%d): %s", xfd->fd, strerror(errno));
        }
        return STAT_RETRYLATER;	/* retry complete open cycle */
    }

    bytes = 0;
    Info("waiting for socks reply");
    while (bytes >= 0) {	/* loop over answer chunks until complete or error */
        /* receive socks answer */
        do {
            result = Read(xfd->fd, buff+bytes, SIZEOF_STRUCT_SOCKS4-bytes);
        } while (result < 0 && errno == EINTR);
        if (result < 0) {
            Msg4(level, "read(%d, %p, "F_Zu"): %s",
                 xfd->fd, buff+bytes, SIZEOF_STRUCT_SOCKS4-bytes,
                 strerror(errno));
            if (Close(xfd->fd) < 0) {
                Info2("close(%d): %s", xfd->fd, strerror(errno));
            }
        }
        if (result == 0) {
            Msg(level, "read(): EOF during read of socks reply, peer might not be a socks4 server");
            if (Close(xfd->fd) < 0) {
                Info2("close(%d): %s", xfd->fd, strerror(errno));
            }
            return STAT_RETRYLATER;
        }
#if WITH_MSGLEVEL <= E_DEBUG
        {
            char msgbuff[3*SIZEOF_STRUCT_SOCKS4];
            * xiohexdump((const unsigned char *)replyhead+bytes, result, msgbuff)
                = '\0';
            Debug2("received socks4 reply data (offset "F_Zd"): %s", bytes, msgbuff);
        }
#endif /* WITH_MSGLEVEL <= E_DEBUG */
        bytes += result;
        if (bytes == SIZEOF_STRUCT_SOCKS4) {
            Debug1("received all "F_Zd" bytes", bytes);
            break;
        }
        Debug2("received %d bytes, waiting for "F_Zu" more bytes",
               result, SIZEOF_STRUCT_SOCKS4-bytes);
    }
    if (result <= 0) {	/* we had a problem while reading socks answer */
        return STAT_RETRYLATER;	/* retry complete open cycle */
    }

    Info7("received socks reply VN=%u CD=%u DSTPORT=%u DSTIP=%u.%u.%u.%u",
          replyhead->version, replyhead->action, ntohs(replyhead->port),
          ((uint8_t *)&replyhead->dest)[0],
          ((uint8_t *)&replyhead->dest)[1],
          ((uint8_t *)&replyhead->dest)[2],
          ((uint8_t *)&replyhead->dest)[3]);
    if (replyhead->version != 0) {
        Warn1("socks: reply code version is not 0 (%d)",
              replyhead->version);
    }

    switch (replyhead->action) {
    case SOCKS_CD_GRANTED:
        /* Notice("socks: connect request succeeded"); */
#if 0
        if (Getsockname(xfd->fd, (struct sockaddr *)&us, &uslen) < 0) {
            Warn4("getsockname(%d, %p, {%d}): %s",
                  xfd->fd, &us, uslen, strerror(errno));
        }
        Notice1("successfully connected from %s via socks4",
                sockaddr_info((struct sockaddr *)&us, infobuff, sizeof(infobuff)));
#else
        Notice("successfully connected via socks4");
#endif
        break;

    case SOCKS_CD_FAILED:
        Msg(level, "socks: connect request rejected or failed");
        return STAT_RETRYLATER;

    case SOCKS_CD_NOIDENT:
        Msg(level, "socks: ident refused by client");
        return STAT_RETRYLATER;

    case SOCKS_CD_IDENTFAILED:
        Msg(level, "socks: ident failed");
        return STAT_RETRYLATER;

    default:
        Msg1(level, "socks: undefined status %u", replyhead->action);
    }

    return STAT_OK;
}
Esempio n. 13
0
int xioshutdown(xiofile_t *sock, int how) {
   int result = 0;

   if (sock->tag == XIO_TAG_INVALID) {
      Error("xioshutdown(): invalid file descriptor");
      errno = EINVAL;
      return -1;
   }

   if (sock->tag == XIO_TAG_DUAL) {
      if ((how+1)&1) {
	 result = xioshutdown((xiofile_t *)sock->dual.stream[0], 0);
      }
      if ((how+1)&2) {
	 result |= xioshutdown((xiofile_t *)sock->dual.stream[1], 1);
      }
      return result;
   }

   switch (sock->stream.howtoshut) {
      char writenull;
   case XIOSHUT_NONE:
      return 0;
   case XIOSHUT_CLOSE:
      if (Close(sock->stream.fd) < 0) {
	 Info2("close(%d): %s",
	       sock->stream.fd, strerror(errno));
      }
      return 0;
   case XIOSHUT_DOWN:
      if ((result = Shutdown(sock->stream.fd, how)) < 0) {
	 Info3("shutdown(%d, %d): %s",
	       sock->stream.fd, how, strerror(errno));
      }
      return 0;
#if _WITH_SOCKET
   case XIOSHUT_NULL:
      /* send an empty packet; only useful on datagram sockets? */
      xiowrite(sock, &writenull, 0);
      return 0;
#endif /* _WITH_SOCKET */
   default: ;
   }

   if (false) {
      ;
#if WITH_OPENSSL
   } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_OPENSSL) {
      sycSSL_shutdown (sock->stream.para.openssl.ssl);
      /*! what about half/full close? */
#endif /* WITH_OPENSSL */

   } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_PIPE) {
      if ((how+1)&1) {
	 if (Close(sock->stream.fd) < 0) {
	    Info2("close(%d): %s",
		  sock->stream.fd, strerror(errno));
	 }
      }
      if ((how+1)&2) {
	 if (Close(sock->stream.para.bipipe.fdout) < 0) {
	    Info2("close(%d): %s",
		  sock->stream.para.bipipe.fdout, strerror(errno));
	 } 
      }
      
   } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_2PIPE) {
      if ((how+1)&1) {
	 if (Close(sock->stream.fd) < 0) {
	    Info2("close(%d): %s",
		  sock->stream.fd, strerror(errno));
	 }
      }
      if ((how+1)&2) {
	 if (Close(sock->stream.para.exec.fdout) < 0) {
	    Info2("close(%d): %s",
		  sock->stream.para.exec.fdout, strerror(errno));
	 } 
      }
#if _WITH_SOCKET
   } else if (sock->stream.howtoend == END_SHUTDOWN) {
      if ((result = Shutdown(sock->stream.fd, how)) < 0) {
	 Info3("shutdown(%d, %d): %s",
	       sock->stream.fd, how, strerror(errno));
      }
   } else if (sock->stream.howtoend == END_SHUTDOWN_KILL) {
      if ((result = Shutdown(sock->stream.fd, how)) < 0) {
	 Info3("shutdown(%d, %d): %s",
	       sock->stream.fd, how, strerror(errno));
      }
      if ((sock->stream.flags&XIO_ACCMODE) == XIO_WRONLY) {
	 /* the child process might want to flush some data before terminating
	    */
	 int status = 0;

	 /* we wait for the child process to die, but to prevent timeout
	    we raise an alarm after some time.
	    NOTE: the alarm does not terminate waitpid() on Linux/glibc (BUG?),
	    therefore we have to do the kill in the signal handler */
	 {
	    struct sigaction act;
	    sigfillset(&act.sa_mask);
	    act.sa_flags = 0;
	    act.sa_handler = signal_kill_pid;
	    Sigaction(SIGALRM, &act, NULL);
	 }
	 socat_kill_pid = sock->stream.para.exec.pid;
#if HAVE_SETITIMER
	 /*! with next feature release, we get usec resolution and an option */
#else
	 Alarm(1 /*! sock->stream.para.exec.waitdie */);
#endif /* !HAVE_SETITIMER */
	 if (Waitpid(sock->stream.para.exec.pid, &status, 0) < 0) {
	    Warn3("waitpid("F_pid", %p, 0): %s",
		  sock->stream.para.exec.pid, &status, strerror(errno));
	 }
	 Alarm(0);
      }
   } else if ((sock->stream.dtype & XIODATA_MASK) ==
	      (XIODATA_RECVFROM & XIODATA_MASK)) {
      if (how >= 1) {
	 if (Close(sock->stream.fd) < 0) {
	    Info2("close(%d): %s",
		  sock->stream.fd, strerror(errno));
	 }
	 sock->stream.eof = 2;
	 sock->stream.fd = -1;
      }
#endif /* _WITH_SOCKET */
#if 0
   } else {
      Error1("xioshutdown(): bad data type specification %d", sock->stream.dtype);
      return -1;
#endif

   }
#if 0
   else if (sock->stream.howtoend == END_CLOSE &&
Esempio n. 14
0
int _xioopen_proxy_connect(struct single *xfd,
			   struct proxyvars *proxyvars,
			   int level) {
   size_t offset;
   char request[CONNLEN];
   char buff[BUFLEN+1];
#if CONNLEN > BUFLEN
#error not enough buffer space 
#endif
   char textbuff[2*BUFLEN+1];	/* just for sanitizing print data */
   char *eol = buff;
   int state;
   ssize_t sresult;

   /* generate proxy request header - points to final target */
   sprintf(request, "CONNECT %s:%u HTTP/1.0\r\n",
	   proxyvars->targetaddr, proxyvars->targetport);

   /* send proxy CONNECT request (target addr+port) */
   * xiosanitize(request, strlen(request), textbuff) = '\0';
   Info1("sending \"%s\"", textbuff);
   /* write errors are assumed to always be hard errors, no retry */
   do {
      sresult = Write(xfd->wfd, request, strlen(request));
   } while (sresult < 0 && errno == EINTR);
   if (sresult < 0) {
      Msg4(level, "write(%d, %p, "F_Zu"): %s",
	   xfd->wfd, request, strlen(request), strerror(errno));
      if (Close(xfd->wfd) < 0) {
	 Info2("close(%d): %s", xfd->wfd, strerror(errno));
      }
      return STAT_RETRYLATER;
   }

   if (proxyvars->authstring) {
      /* send proxy authentication header */
#     define XIOAUTHHEAD "Proxy-authorization: Basic "
#     define XIOAUTHLEN  27
      static const char *authhead = XIOAUTHHEAD;
#     define HEADLEN 256
      char *header, *next;

      /* ...\r\n\0 */
      if ((header =
	   Malloc(XIOAUTHLEN+((strlen(proxyvars->authstring)+2)/3)*4+3))
	  == NULL) {
	 return -1;
      }
      strcpy(header, authhead);
      next = xiob64encodeline(proxyvars->authstring,
			      strlen(proxyvars->authstring),
			      strchr(header, '\0'));
      *next = '\0';
      Info1("sending \"%s\\r\\n\"", header);
      *next++ = '\r';  *next++ = '\n'; *next++ = '\0';
      do {
	 sresult = Write(xfd->wfd, header, strlen(header));
      } while (sresult < 0 && errno == EINTR);
      if (sresult < 0) {
	 Msg4(level, "write(%d, %p, "F_Zu"): %s",
	      xfd->wfd, header, strlen(header), strerror(errno));
	 if (Close(xfd->wfd/*!*/) < 0) {
	    Info2("close(%d): %s", xfd->wfd, strerror(errno));
	 }
	 return STAT_RETRYLATER;
      }

      free(header);
   }

   Info("sending \"\\r\\n\"");
   do {
      sresult = Write(xfd->wfd, "\r\n", 2);
   } while (sresult < 0 && errno == EINTR);
   /*! */

   /* request is kept for later error messages */
   *strstr(request, " HTTP") = '\0';

   /* receive proxy answer; looks like "HTTP/1.0 200 .*\r\nHeaders..\r\n\r\n" */
   /* socat version 1 depends on a valid fd for data transfer; address
      therefore cannot buffer data. So, to prevent reading beyond the end of
      the answer headers, only single bytes are read. puh. */
   state = XIOSTATE_HTTP1;
   offset = 0;	/* up to where the buffer is filled (relative) */
   /*eol;*/	/* points to the first lineterm of the current line */
   do {
      sresult = xioproxy_recvbytes(xfd, buff+offset, 1, level);
      if (sresult <= 0) {
	 state = XIOSTATE_ERROR;
	 break;	/* leave read cycles */
      }
      
      switch (state) {

      case XIOSTATE_HTTP1:
	 /* 0 or more bytes of first line received, no '\r' yet */
	 if (*(buff+offset) == '\r') {
	    eol = buff+offset;
	    state = XIOSTATE_HTTP2;
	    break;
	 }
	 if (proxyvars->ignorecr && *(buff+offset) == '\n') {
	    eol = buff+offset;
	    state = XIOSTATE_HTTP3;
	    break;
	 }
	 break;

      case XIOSTATE_HTTP2:
	 /* first line received including '\r' */
	 if (*(buff+offset) != '\n') {
	    state = XIOSTATE_HTTP1;
	    break;
	 }
	 state = XIOSTATE_HTTP3;
	 break;

      case XIOSTATE_HTTP3:
	 /* received status (first line) and "\r\n" */
	 if (*(buff+offset) == '\r') {
	    state = XIOSTATE_HTTP7;
	    break;
	 }
	 if (proxyvars->ignorecr && *(buff+offset) == '\n') {
	    state = XIOSTATE_HTTP8;
	    break;
	 }
	 state = XIOSTATE_HTTP4;
	 break;
	 
      case XIOSTATE_HTTP4:
	 /* within header */
	 if (*(buff+offset) == '\r') {
	    eol = buff+offset;
	    state = XIOSTATE_HTTP5;
	    break;
	 }
	 if (proxyvars->ignorecr && *(buff+offset) == '\n') {
	    eol = buff+offset;
	    state = XIOSTATE_HTTP6;
	    break;
	 }
	 break;

      case XIOSTATE_HTTP5:
	 /* within header, '\r' received */
	 if (*(buff+offset) != '\n') {
	    state = XIOSTATE_HTTP4;
	    break;
	 }
	 state = XIOSTATE_HTTP6;
	 break;

      case XIOSTATE_HTTP6:
	 /* received status (first line) and 1 or more headers, "\r\n" */
	 if (*(buff+offset) == '\r') {
	    state = XIOSTATE_HTTP7;
	    break;
	 }
	 if (proxyvars->ignorecr && *(buff+offset) == '\n') {
	    state = XIOSTATE_HTTP8;
	    break;
	 }
	 state = XIOSTATE_HTTP4;
	 break;

      case XIOSTATE_HTTP7:
	 /* received status (first line), 0 or more headers, "\r\n\r" */
	 if (*(buff+offset) == '\n') {
	    state = XIOSTATE_HTTP8;
	    break;
	 }
	 if (*(buff+offset) == '\r') {
	    if (proxyvars->ignorecr) {
	       break;	/* ignore it, keep waiting for '\n' */
	    } else {
	       state = XIOSTATE_HTTP5;
	    }
	    break;
	 }
	 state = XIOSTATE_HTTP4;
	 break;

      }
      ++offset;

      /* end of status line reached */
      if (state == XIOSTATE_HTTP3) {
	 char *ptr;
	 /* set a terminating null - on or after CRLF? */
	 *(buff+offset) = '\0';

	 * xiosanitize(buff, Min(offset, (sizeof(textbuff)-1)>>1), textbuff)
	    = '\0';
	 Info1("proxy_connect: received answer \"%s\"", textbuff);
	 *eol = '\0';
	 * xiosanitize(buff, Min(strlen(buff), (sizeof(textbuff)-1)>>1),
		       textbuff) = '\0';
	 if (strncmp(buff, "HTTP/1.0 ", 9) &&
	     strncmp(buff, "HTTP/1.1 ", 9)) {
	    /* invalid answer */
	    Msg1(level, "proxy: invalid answer \"%s\"", textbuff);
	    return STAT_RETRYLATER;
	 }
	 ptr = buff+9;

	 /* skip multiple spaces */
	 while (*ptr == ' ')  ++ptr;

	 /* HTTP answer */
	 if (strncmp(ptr, "200", 3)) {
	    /* not ok */
	    /* CERN:
	       "HTTP/1.0 200 Connection established"
	       "HTTP/1.0 400 Invalid request "CONNECT 10.244.9.3:8080 HTTP/1.0" (unknown method)"
	       "HTTP/1.0 403 Forbidden - by rule"
	       "HTTP/1.0 407 Proxy Authentication Required"
	       Proxy-Authenticate: Basic realm="Squid proxy-caching web server"
>  50 72 6f 78 79 2d 61 75 74 68 6f 72 69 7a 61 74  Proxy-authorizat
>  69 6f 6e 3a 20 42 61 73 69 63 20 61 57 4e 6f 63  ion: Basic aWNoc
>  32 56 73 59 6e 4e 30 4f 6e 4e 30 63 6d 56 75 5a  2VsYnN0OnN0cmVuZ
>  32 64 6c 61 47 56 70 62 51 3d 3d 0d 0a           2dlaGVpbQ==..
                b64encode("username:password")
	       "HTTP/1.0 500 Can't connect to host"
	    */
	    /* Squid:
	       "HTTP/1.0 400 Bad Request"
	       "HTTP/1.0 403 Forbidden"
	       "HTTP/1.0 503 Service Unavailable"
	       interesting header: "X-Squid-Error: ERR_CONNECT_FAIL 111" */
	    /* Apache:
	       "HTTP/1.0 400 Bad Request"
	       "HTTP/1.1 405 Method Not Allowed"
	    */
	    /* WTE:
	       "HTTP/1.1 200 Connection established"
	       "HTTP/1.1 404 Host not found or not responding, errno:  79"
	       "HTTP/1.1 404 Host not found or not responding, errno:  32"
	       "HTTP/1.1 404 Host not found or not responding, errno:  13"
	    */
	    /* IIS:
	       "HTTP/1.1 404 Object Not Found"
	    */
	    ptr += 3;
	    while (*ptr == ' ')  ++ptr;
	    
	    Msg2(level, "%s: %s", request, ptr);
	    return STAT_RETRYLATER;
	 }

	 /* ok!! */
	 /* "HTTP/1.0 200 Connection established" */
	 /*Info1("proxy: \"%s\"", textbuff+13);*/
	 offset = 0;

      } else if (state == XIOSTATE_HTTP6) {
      /* end of a header line reached */
	 char *endp;

	 /* set a terminating null */
	 *(buff+offset) = '\0';

	 endp =
	    xiosanitize(buff, Min(offset, (sizeof(textbuff)-1)>>1),
			textbuff);
	 *endp = '\0';
	 Info1("proxy_connect: received header \"%s\"", textbuff);
	 offset = 0;
      }
Esempio n. 15
0
/* fork for exec/system, but return before exec'ing.
   return=0: is child process
   return>0: is parent process
   return<0: error occurred, assume parent process and no child exists !!!
   function formerly known as _xioopen_foxec()
 */
int _xioopen_progcall(int xioflags,	/* XIO_RDONLY etc. */
		       struct single *xfd,
		       unsigned groups,
		       struct opt **copts, /* in: opts; out: opts for child */
		       int *duptostderr,
		       bool inter,	/* is interaddr, not endpoint */
		       int form		/* with interaddr: =2: FDs 1,0--4,3
					   =1: FDs 1--0 */
		) {
   struct single *fd = xfd;
   struct opt *popts;	/* parent process options */
   int numleft;
   int sv[2], rdpip[2], wrpip[2];
   int saverfd = -1, savewfd = -1;	/* with inter addr, save assigned right fds */
   int rw = (xioflags & XIO_ACCMODE);
   char *commname;
   int commtype = XIOCOMM_SOCKETPAIRS;
   bool usepipes = false;
#if HAVE_PTY
   int ptyfd = -1, ttyfd = -1;
   bool usebestpty = false;	/* use the best available way to open pty */
#if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)
   bool useptmx = false;	/* use /dev/ptmx or equivalent */
#endif
#if HAVE_OPENPTY
   bool useopenpty = false;	/* try only openpty */
#endif	/* HAVE_OPENPTY */
   bool usepty = false;		/* any of the pty options is selected */
   char ptyname[MAXPTYNAMELEN];
#endif /* HAVE_PTY */
   pid_t pid = 0;	/* mostly int */
   int leftfd[2] = { 0, 1 };
#  define fdi (leftfd[0])
#  define fdo (leftfd[1])
   int rightfd[2] = { 3, 4 };
#  define rightin (rightfd[0])
#  define rightout (rightfd[1])
   short result;
   bool withstderr = false;
   bool nofork = false;
   bool withfork;

   popts = moveopts(*copts, GROUP_ALL);
   if (applyopts_single(fd, popts, PH_INIT) < 0)  return -1;
   applyopts2(-1, popts, PH_INIT, PH_EARLY);

   retropt_bool(popts, OPT_NOFORK, &nofork);
   withfork = !nofork;

   if ((retropt_string(popts, OPT_COMMTYPE, &commname)) >= 0) {
      if ((commtype = getcommtype(commname)) < 0) {
	 Error1("bad communication type \"%s\"", commname);
	 commtype = XIOCOMM_SOCKETPAIRS;
      }
   }

   retropt_bool(popts, OPT_PIPES, &usepipes);
#if HAVE_PTY
   retropt_bool(popts, OPT_PTY, &usebestpty);
#if HAVE_OPENPTY
   retropt_bool(popts, OPT_OPENPTY, &useopenpty);
#endif
#if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)
   retropt_bool(popts, OPT_PTMX, &useptmx);
#endif
   usepty = (usebestpty
#if HAVE_OPENPTY
	     || useopenpty
#endif
#if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)
	     || useptmx
#endif
	     );
   if (usepipes && usepty) {
      Warn("_xioopen_foxec(): options \"pipes\" and \"pty\" must not be specified together; ignoring \"pipes\"");
      usepipes = false;
   }
#endif /* HAVE_PTY */

   if (usepty) {
      commtype = XIOCOMM_PTY;
   } else if (usepipes) {
      commtype = XIOCOMM_PIPES;
   }

   /*------------------------------------------------------------------------*/
   /* retrieve options regarding file descriptors */
   if (!retropt_int(popts, OPT_LEFTFD,  &fdi)) {
      fdo = fdi;
   }
   retropt_int(popts, OPT_LEFTINFD,  &fdi);
   retropt_int(popts, OPT_LEFTOUTFD, &fdo);

   if (!retropt_int(popts, OPT_RIGHTFD,  &rightin)) {
      rightout = rightin;
   }
   retropt_int(popts, OPT_RIGHTINFD,  &rightin);
   retropt_int(popts, OPT_RIGHTOUTFD, &rightout);
   /* when the superordinate communication type provides two distinct fds we
      cannot pass just one fd to the program */
   if (rw == XIO_RDWR && rightin==rightout) {
      struct stat rstat, wstat;
      if (Fstat(xfd->rfd, &rstat) < 0)
	 Error2("fstat(%d, ...): %s", xfd->rfd, strerror(errno));
      if (Fstat(xfd->wfd, &wstat) < 0)
	 Error2("fstat(%d, ...): %s", xfd->wfd, strerror(errno));
      if (memcmp(&rstat, &wstat, sizeof(rstat))) {
	 Error("exec/system: your rightfd options require the same FD for both directions but the communication environment provides two different FDs");
      }
   }

   /*------------------------------------------------------------------------*/
   if (rw == XIO_WRONLY) {
      if (fd->howtoclose == XIOCLOSE_UNSPEC) {
	 fd->howtoclose = XIOCLOSE_SLEEP_SIGTERM;
      }
   }
   if (withfork) {
      const char *typename;
      if (!(xioflags&XIO_MAYCHILD)) {
	 Error("fork for exec not allowed in this context");
	 /*!! free something */
	 return -1;
      }
      fd->flags |= XIO_DOESCHILD;

      switch (commtype) {
      case XIOCOMM_PIPES:       typename = "pipes"; break;
#if HAVE_PTY
      case XIOCOMM_PTY:         typename = "pty"; break;
      case XIOCOMM_PTYS:        typename = "two pty's"; break;
#endif /* HAVE_PTY */
      case XIOCOMM_SOCKETPAIR:  typename = "socketpair"; break;
      case XIOCOMM_SOCKETPAIRS: typename = "two socketpairs"; break;
#if _WITH_TCP
      case XIOCOMM_TCP:         typename = "TCP socket pair"; break;
      case XIOCOMM_TCP4:        typename = "TCP4 socket pair"; break;
      case XIOCOMM_TCP4_LISTEN: typename = "TCP4 listen socket pair"; break;
#endif
      default:			typename = NULL; break;
      }
      Notice2("forking off child, using %s for %s",
	      typename, ddirection[rw]);
   }
   applyopts(-1, popts, PH_PREBIGEN);

   if (inter) {
      saverfd = xfd->rfd;
      savewfd = xfd->wfd;
      xfd->howtoshut = XIOSHUT_UNSPEC;
      xfd->howtoclose = XIOCLOSE_UNSPEC;
   }

   if (!withfork) {
      /*0 struct single *stream1, *stream2;*/

      free(*copts);
      *copts = moveopts(popts, GROUP_ALL);
      /* what if WE are sock1 ? */
#if 1
      if (!(xioflags & XIO_MAYEXEC /* means exec+nofork */)) {
	 Error("nofork option is not allowed here");
	 /*!! free something */
	 return -1;
      }
      fd->flags |= XIO_DOESEXEC;
#else      /*!! */
      if (sock1 == NULL) {
	 Fatal("nofork option must no be applied to first socat address");
      }
#endif
      if (fd->howtoclose == XIOCLOSE_UNSPEC) {
	 fd->howtoclose = XIOCLOSE_CLOSE;
      }

#if 0 /*!! */
      if (sock1->tag == XIO_TAG_DUAL) {
	 stream1 = &sock1->dual.stream[0]->stream;
	 stream2 = &sock1->dual.stream[1]->stream;
      } else {
	 stream1 = &sock1->stream;
	 stream2 = &sock1->stream;
      }
      if (stream1->dtype == DATA_READLINE || stream2->dtype == DATA_READLINE ||
	  stream1->dtype == DATA_OPENSSL  || stream2->dtype == DATA_OPENSSL
	  ) {
	 Error("with option nofork, openssl and readline in address1 do not work");
      }
      if (stream1->lineterm != LINETERM_RAW ||
	  stream2->lineterm != LINETERM_RAW ||
	  stream1->ignoreeof || stream2->ignoreeof) {
	 Warn("due to option nofork, address1 options for lineterm and igoreeof do not apply");
      }
#endif

      /*! problem: when fdi==WRFD(sock[0]) or fdo==RDFD(sock[0]) */
      if (rw != XIO_WRONLY) {
	 if (XIO_GETRDFD(sock[0]/*!!!*/) == fdi) {
	    if (Fcntl_l(fdi, F_SETFD, 0) < 0) {
	       Warn2("fcntl(%d, F_SETFD, 0): %s", fdi, strerror(errno));
	    }
	    if (Dup2(XIO_GETRDFD(sock[0]), fdi) < 0) {
	       Error3("dup2(%d, %d): %s",
		      XIO_GETRDFD(sock[0]), fdi, strerror(errno));
	    }
	    /*0 Info2("dup2(%d, %d)", XIO_GETRDFD(sock[0]), fdi);*/
	 } else {
	    if (Dup2(XIO_GETRDFD(sock[0]), fdi) < 0) {
	       Error3("dup2(%d, %d): %s",
		      XIO_GETRDFD(sock[0]), fdi, strerror(errno));
	    }
	    /*0 Info2("dup2(%d, %d)", XIO_GETRDFD(sock[0]), fdi);*/
	 }
      }
      if (rw != XIO_RDONLY) {
	 if (XIO_GETWRFD(sock[0]) == fdo) {
	    if (Fcntl_l(fdo, F_SETFD, 0) < 0) {
	       Warn2("fcntl(%d, F_SETFD, 0): %s", fdo, strerror(errno));
	    }
	    if (Dup2(XIO_GETWRFD(sock[0]), fdo) < 0) {
	       Error3("dup2(%d, %d): %s)",
		      XIO_GETWRFD(sock[0]), fdo, strerror(errno));
	    }
	    /*0 Info2("dup2(%d, %d)", XIO_GETWRFD(sock[0]), fdo);*/
	 } else {
	    if (Dup2(XIO_GETWRFD(sock[0]), fdo) < 0) {
	       Error3("dup2(%d, %d): %s)",
		      XIO_GETWRFD(sock[0]), fdo, strerror(errno));
	    }
	    /*0 Info2("dup2(%d, %d)", XIO_GETWRFD(sock[0]), fdo);*/
	 }
      }
   } else /* withfork */
      /* create fd pair(s), set related xfd parameters, and apply options */
      switch (commtype) {

#if HAVE_PTY
      case XIOCOMM_PTY:
	 /*!indent*/
#if defined(HAVE_DEV_PTMX)
#  define PTMX "/dev/ptmx"	/* Linux */
#elif HAVE_DEV_PTC
#  define PTMX "/dev/ptc"	/* AIX 4.3.3 */
#endif
      fd->dtype = XIODATA_PTY;
#if 0
      if (fd->howtoshut == XIOSHUT_UNSPEC) {
	 fd->howtoshut = XIOSHUTRD_SIGTERM|XIOSHUTWR_SIGHUP;
      }
      if (fd->howtoclose == XIOCLOSE_UNSPEC) {
	 fd->howtoclose = XIOCLOSE_CLOSE_SIGTERM;
      }
#endif

      if (xiopty(usebestpty||useptmx, &ttyfd, &ptyfd) < 0) {
	 return -1;
      }

      free(*copts);
      if ((*copts = moveopts(popts, GROUP_TERMIOS|GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) {
	 return -1;
      }
      applyopts_cloexec(ptyfd, popts);/*!*/

      /* exec:...,pty did not kill child process under some circumstances */
      if (fd->howtoshut == XIOSHUT_UNSPEC) {
	 fd->howtoshut = XIOSHUTRD_SIGTERM|XIOSHUTWR_SIGHUP;
      }
      if (fd->howtoclose == XIOCLOSE_UNSPEC) {
	 fd->howtoclose = XIOCLOSE_CLOSE_SIGTERM;
      }

      /* this for parent, was after fork */
      applyopts(ptyfd, popts, PH_FD);
      applyopts(ptyfd, popts, PH_LATE);
      if (applyopts_single(fd, popts, PH_LATE) < 0)  return -1;

      if (XIOWITHRD(rw))  fd->rfd = ptyfd;
      if (XIOWITHWR(rw))  fd->wfd = ptyfd;

      /* this for child, was after fork */
      applyopts(ttyfd, *copts, PH_FD);

      break;
#endif /* HAVE_PTY */

      case XIOCOMM_PIPES: {
	 /*!indent*/
      struct opt *popts2, *copts2;

      if (rw == XIO_RDWR) {
	 fd->dtype = XIODATA_2PIPE;
      }
      if (fd->howtoshut == XIOSHUT_UNSPEC || fd->howtoshut == XIOSHUT_DOWN) {
	 fd->howtoshut = XIOSHUT_CLOSE;
      }
      if (fd->howtoclose == XIOCLOSE_UNSPEC) {
	 fd->howtoclose = XIOCLOSE_CLOSE;
      }

      if (rw != XIO_WRONLY) {
	 if (Pipe(rdpip) < 0) {
	    Error2("pipe(%p): %s", rdpip, strerror(errno));
	    return -1;
	 }
      }
      /*0 Info2("pipe({%d,%d})", rdpip[0], rdpip[1]);*/
      /* rdpip[0]: read by socat; rdpip[1]: write by child */
      free(*copts);
      if ((*copts = moveopts(popts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS))
	  == NULL) {
	 return -1;
      }

      popts2 = copyopts(popts, GROUP_ALL);
      copts2 = copyopts(*copts, GROUP_ALL);

      if (rw != XIO_WRONLY) {
	 applyopts_cloexec(rdpip[0], popts);
	 applyopts(rdpip[0], popts, PH_FD);
	 applyopts(rdpip[1], *copts, PH_FD);
      }

      if (rw != XIO_RDONLY) {
	 if (Pipe(wrpip) < 0) {
	    Error2("pipe(%p): %s", wrpip, strerror(errno));
	    return -1;
	 }
      }
      /*0 Info2("pipe({%d,%d})", wrpip[0], wrpip[1]);*/

      /* wrpip[1]: write by socat; wrpip[0]: read by child */
      if (rw != XIO_RDONLY) {
	 applyopts_cloexec(wrpip[1], popts2);
	 applyopts(wrpip[1], popts2, PH_FD);
	 applyopts(wrpip[0], copts2, PH_FD);
      }

      /* this for parent, was after fork */
      if (XIOWITHRD(rw))  fd->rfd = rdpip[0];
      if (XIOWITHWR(rw))  fd->wfd = wrpip[1];
      applyopts(fd->rfd, popts, PH_FD);
      applyopts(fd->rfd, popts, PH_LATE);
      if (applyopts_single(fd, popts, PH_LATE) < 0)  return -1;
      break;
      }

      case XIOCOMM_SOCKETPAIR: {
	 /*!indent*/
      int pf = AF_UNIX;
      retropt_int(popts, OPT_PROTOCOL_FAMILY, &pf);
      result = xiosocketpair(popts, pf, SOCK_STREAM, 0, sv);
      if (result < 0) {
	 return -1;
      }

      if (xfd->howtoshut == XIOSHUT_UNSPEC) {
	 xfd->howtoshut = XIOSHUT_DOWN;
      }
      if (xfd->howtoclose == XIOCLOSE_UNSPEC) {
	 xfd->howtoclose = XIOCLOSE_CLOSE;
      }

      /*0 Info5("socketpair(%d, %d, %d, {%d,%d})",
	d, type, protocol, sv[0], sv[1]);*/
      free(*copts);
      if ((*copts = moveopts(popts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) {
	 return -1;
      }
      applyopts(sv[0], *copts, PH_PASTSOCKET);
      applyopts(sv[1], popts, PH_PASTSOCKET);

      applyopts_cloexec(sv[0], *copts);
      applyopts(sv[0], *copts, PH_FD);
      applyopts(sv[1], popts, PH_FD);

      applyopts(sv[0], *copts, PH_PREBIND);
      applyopts(sv[0], *copts, PH_BIND);
      applyopts(sv[0], *copts, PH_PASTBIND);
      applyopts(sv[1], popts, PH_PREBIND);
      applyopts(sv[1], popts, PH_BIND);
      applyopts(sv[1], popts, PH_PASTBIND);

Warn1("xio-progcall.c: fd->howtoshut == %d", fd->howtoshut);
      if (inter || fd->howtoshut == XIOSHUT_UNSPEC) {
	 fd->howtoshut = XIOSHUT_DOWN;
      }
      if (fd->howtoclose == XIOCLOSE_UNSPEC) {
	 fd->howtoclose = XIOCLOSE_SIGTERM;
      }

      /* this for parent, was after fork */
   /*!!!*/ Warn2("2: fd->rfd==%d, fd->wfd==%d", fd->rfd, fd->wfd);
      if (XIOWITHRD(rw))  fd->rfd = sv[0];
      if (XIOWITHWR(rw))  fd->wfd = sv[0];
   /*!!!*/ Warn2("3: fd->rfd==%d, fd->wfd==%d", fd->rfd, fd->wfd);
      applyopts(fd->rfd, popts, PH_FD);
      applyopts(fd->rfd, popts, PH_LATE);
      if (applyopts_single(fd, popts, PH_LATE) < 0)  return -1;
      }
	 break;

      case XIOCOMM_TCP:
      case XIOCOMM_TCP4: {
	 /*!indent*/
	 int pf = AF_INET;
	 xiofd_t socatfd, execfd;
	 retropt_int(popts, OPT_PROTOCOL_FAMILY, &pf);
	 if (xiocommpair(commtype, XIOWITHWR(rw), XIOWITHRD(rw),
			 0, &socatfd, &execfd) < 0) {
	    return -1;
	 }
      free(*copts);
      if ((*copts = moveopts(popts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) {
	 return -1;
      }
      sv[0] = socatfd.rfd;	/*!!! r/w */
      sv[1] = execfd.wfd;
      applyopts(socatfd.rfd, *copts, PH_PASTSOCKET);
      applyopts(execfd.rfd, popts, PH_PASTSOCKET);

      applyopts_cloexec(sv[0], *copts);
      applyopts(sv[0], *copts, PH_FD);
      applyopts(sv[1], popts, PH_FD);

      applyopts(sv[0], *copts, PH_PREBIND);
      applyopts(sv[0], *copts, PH_BIND);
      applyopts(sv[0], *copts, PH_PASTBIND);
      applyopts(sv[1], popts, PH_PREBIND);
      applyopts(sv[1], popts, PH_BIND);
      applyopts(sv[1], popts, PH_PASTBIND);

Warn1("xio-progcall.c: fd->howtoshut == %d", fd->howtoshut);
      if (inter || fd->howtoshut == XIOSHUT_UNSPEC) {
	 fd->howtoshut = XIOSHUT_DOWN;
      }
      if (fd->howtoclose == XIOCLOSE_UNSPEC) {
	 fd->howtoclose = XIOCLOSE_SIGTERM;
      }

      /* this for parent, was after fork */
      if (XIOWITHRD(rw))  fd->rfd = sv[0];
      if (XIOWITHWR(rw))  fd->wfd = sv[0];
      applyopts(fd->rfd, popts, PH_FD);
      applyopts(fd->rfd, popts, PH_LATE);
      if (applyopts_single(fd, popts, PH_LATE) < 0)  return -1;
      }
	 break;

#if LATER
      case XIOCOMM_TCP4_LISTEN: {
	 /*!indent*/
	 int pf = AF_INET;
	 xiofd_t socatfd, execfd;
	 retropt_int(popts, OPT_PROTOCOL_FAMILY, &pf);
	 if (xiocommpair(commtype, XIOWITHWR(rw), XIOWITHRD(rw),
			 0, &socatfd, &execfd) < 0) {
	    return -1;
	 }

	 free(*copts);
	 if ((*copts = moveopts(popts, GROUP_TERMIOS|GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) {
	    return -1;
	 }
	 applyopts_cloexec(ptyfd, popts);/*!*/
      }
	 break;
#endif /* LATER */

      case XIOCOMM_SOCKETPAIRS:
      case XIOCOMM_PTYS: {
	 xiofd_t socatfd, execfd;
	 struct termios andmask, ormask;
	 switch (commtype) {
	 case XIOCOMM_SOCKETPAIRS:
	    if (xiocommpair(commtype, XIOWITHWR(rw), XIOWITHRD(rw),
			    0, &socatfd, &execfd, PF_UNIX, SOCK_STREAM, 0) < 0)
	       return -1;
	    break;
	 case XIOCOMM_PTYS:
	    if (xiocommpair(commtype, XIOWITHWR(rw), XIOWITHRD(rw),
			    0, &socatfd, &execfd, &andmask, &ormask) < 0)
	       return -1;
	    break;
	 }

	 free(*copts);
	 if ((*copts = copyopts(popts, GROUP_TERMIOS|GROUP_FORK)) == NULL) {
	    return -1;
	 }
	 if (socatfd.rfd >= 0) {
	    applyopts_cloexec(socatfd.rfd, *copts);/*!*/
	    applyopts(socatfd.rfd, *copts, PH_FD);
	    applyopts(socatfd.rfd, *copts, PH_LATE);
	 }
	 if (applyopts_single(xfd, *copts, PH_LATE) < 0)  return -1;

	 free(*copts);
	 if ((*copts = moveopts(popts, GROUP_TERMIOS|GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) {
	    return -1;
	 }
	 if (socatfd.wfd >= 0) {
	    applyopts_cloexec(socatfd.wfd, *copts);/*!*/
	    applyopts(socatfd.wfd, *copts, PH_FD);
	    applyopts(socatfd.wfd, *copts, PH_LATE);
	 }
	 if (applyopts_single(xfd, *copts, PH_LATE) < 0)  return -1;

	 if (XIOWITHRD(rw))  xfd->rfd = socatfd.rfd;
	 if (XIOWITHWR(rw))  xfd->wfd = socatfd.wfd;
	 xfd->dtype      = socatfd.dtype;
	 if (xfd->howtoshut == XIOSHUT_UNSPEC)
	    xfd->howtoshut  = socatfd.howtoshut;
	 if (fd->howtoclose == XIOCLOSE_UNSPEC) {
	    fd->howtoclose = XIOWITHRD(rw)?XIOCLOSE_CLOSE_SIGTERM:XIOCLOSE_SLEEP_SIGTERM;
	 }
	 wrpip[0] = execfd.rfd;
	 rdpip[1] = execfd.wfd;
	 rdpip[0] = socatfd.rfd;
	 wrpip[1] = socatfd.wfd;
      }
	 break;

	 default:
	    Error1("_xioopen_progcall() internal: commtype %d not handled",
		   commtype);
	    break;
      }

   /*0   if ((optpr = copyopts(*copts, GROUP_PROCESS)) == NULL)
     return -1;*/
   retropt_bool(*copts, OPT_STDERR, &withstderr);

   xiosetchilddied();	/* set SIGCHLD handler */

   xiosetchilddied();	/* set SIGCHLD handler */

   if (withfork) {
      sigset_t set, oldset;

      sigemptyset(&set);
      sigaddset(&set, SIGCHLD);
      Sigprocmask(SIG_BLOCK, &set, &oldset);	/* disable SIGCHLD */
      pid = xio_fork(true, E_ERROR);
      if (pid < 0) {
	 Sigprocmask(SIG_SETMASK, &oldset, NULL);
	 Error1("fork(): %s", strerror(errno));
	 return -1;
      }

      if (pid > 0) {
	 /* for parent (this is our socat process) */
	 xiosigchld_register(pid, xiosigaction_child, fd);
	 Sigprocmask(SIG_SETMASK, &oldset, NULL);	/* enable SIGCHLD */
      }

      if (pid == 0) {	/* child */
	 /* drop parents locks, reset FIPS... */
	 if (xio_forked_inchild() != 0) {
	    Exit(1);
	 }
	 Sigprocmask(SIG_SETMASK, &oldset, NULL);	/* enable SIGCHLD */
      }
   }
   if (!withfork || pid == 0) {	/* child */
      uid_t user;
      gid_t group;

      if (withfork) {
	 if (Signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
	    Warn1("signal(SIGCHLD, SIG_IGN): %s", strerror(errno));
	 }

	 /* dup2() the fds to desired values, close old fds, and apply late 
	    options */
	 switch (commtype) {
#if HAVE_PTY
	 case XIOCOMM_PTY:
	    if (rw != XIO_RDONLY && fdi != ttyfd) {
	       if (Dup2(ttyfd, fdi) < 0) {
		  Error3("dup2(%d, %d): %s", ttyfd, fdi, strerror(errno));
		  return -1; }
	       /*0 Info2("dup2(%d, %d)", ttyfd, fdi);*/
	    }
	    if (rw != XIO_WRONLY && fdo != ttyfd) {
	       if (Dup2(ttyfd, fdo) < 0) {
		  Error3("dup2(%d, %d): %s", ttyfd, fdo, strerror(errno));
		  return -1; }
	       /*0 Info2("dup2(%d, %d)", ttyfd, fdo);*/
	    }
	    if ((rw == XIO_RDONLY || fdi != ttyfd) &&
		(rw == XIO_WRONLY || fdo != ttyfd)) {
	       applyopts_cloexec(ttyfd, *copts);
	    }

	    applyopts(ttyfd, *copts, PH_LATE);
	    applyopts(ttyfd, *copts, PH_LATE2);
	    break;
#endif /* HAVE_PTY */

	 case XIOCOMM_PIPES:
	 case XIOCOMM_SOCKETPAIRS:
	 case XIOCOMM_PTYS:
	    {
	    /*!indent*/
	       /* we might have a temporary conflict between what FDs are
		  currently allocated, and which are to be used. We try to find
		  a graceful solution via temporary descriptors */
	       int tmpi, tmpo;

	       /* needed with system() (not with exec()) */
	       if (XIOWITHRD(rw))  Close(rdpip[0]);
	       if (XIOWITHWR(rw))  Close(wrpip[1]);
#if 0
	       /*! might not be needed */
	       if (XIOWITHRD(rw))  Close(rdpip[0]);
	       if (XIOWITHWR(rw))  Close(wrpip[1]);

	       if (fdi == rdpip[1]) {	/* a conflict here */
		  if ((tmpi = Dup(wrpip[0])) < 0) {
		     Error2("dup(%d): %s", wrpip[0], strerror(errno));
		     return -1;
		  }
		  /*0 Info2("dup(%d) -> %d", wrpip[0], tmpi);*/
		  rdpip[1] = tmpi;
	       }
	       if (fdo == wrpip[0]) {	/* a conflict here */
		  if ((tmpo = Dup(rdpip[1])) < 0) {
		     Error2("dup(%d): %s", rdpip[1], strerror(errno));
		     return -1;
		  }
		  /*0 Info2("dup(%d) -> %d", rdpip[1], tmpo);*/
		  wrpip[0] = tmpo;
	       }
	       
	       if (rw != XIO_WRONLY && rdpip[1] != fdo) {
		  if (Dup2(rdpip[1], fdo) < 0) {
		     Error3("dup2(%d, %d): %s", rdpip[1], fdo, strerror(errno));
		     return -1;
		  }
		  Close(rdpip[1]);
		  /*0 Info2("dup2(%d, %d)", rdpip[1], fdo);*/
		  /*0 applyopts_cloexec(fdo, *copts);*/
	       }
	       if (rw != XIO_RDONLY && wrpip[0] != fdi) {
		  if (Dup2(wrpip[0], fdi) < 0) {
		     Error3("dup2(%d, %d): %s", wrpip[0], fdi, strerror(errno));
		     return -1;
		  }
		  Close(wrpip[0]);
		  /*0 Info2("dup2(%d, %d)", wrpip[0], fdi);*/
		  /*0 applyopts_cloexec(wrpip[0], *copts);*/	/* option is already consumed! */
		  /* applyopts_cloexec(fdi, *copts);*/	/* option is already consumed! */
	       }
#else
	       result = reassignfds(XIOWITHWR(rw)?wrpip[0]:-1,
				    XIOWITHRD(rw)?rdpip[1]:-1,
				    fdi, fdo);
	       if (result < 0)  return result;
#endif
	       applyopts(fdi, *copts, PH_LATE);
	       applyopts(fdo, *copts, PH_LATE);
	       applyopts(fdi, *copts, PH_LATE2);
	       applyopts(fdo, *copts, PH_LATE2);
	       break;
	 }
	 case XIOCOMM_SOCKETPAIR:
	 case XIOCOMM_TCP:
	 case XIOCOMM_TCP4:
	 case XIOCOMM_TCP4_LISTEN:
	    /*!indent*/
	       if (rw != XIO_RDONLY && fdi != sv[1]) {
		  if (Dup2(sv[1], fdi) < 0) {
		     Error3("dup2(%d, %d): %s", sv[1], fdi, strerror(errno));
		     return -1; }
		  /*0 Info2("dup2(%d, %d)", sv[1], fdi);*/
	       }
	       if (rw != XIO_WRONLY && fdo != sv[1]) {
		  if (Dup2(sv[1], fdo) < 0) {
		     Error3("dup2(%d, %d): %s", sv[1], fdo, strerror(errno));
		     return -1; }
		  /*0 Info2("dup2(%d, %d)", sv[1], fdo);*/
	       }
	       if (fdi != sv[1] && fdo != sv[1]) {
		  applyopts_cloexec(sv[1], *copts);
		  Close(sv[1]);
	       }

	       applyopts(fdi, *copts, PH_LATE);
	       applyopts(fdi, *copts, PH_LATE2);
	       Close(sv[1]);
	       break;

	 default:
	    Error1("_xioopen_progcall() internal: commtype %d not handled",
		   commtype);
	    break;

	 }

	 /* in case of an inter address, assign the right side FDs (e.g. 3 and 4) */
	 if (inter) {
	    Info2("preparing the right side FDs %d and %d for exec process",
		  rightin, rightout);
	    result = reassignfds(XIOWITHRD(rw)?saverfd:-1,
				 XIOWITHWR(rw)?savewfd:-1,
				 rightin, form==2?rightout:STDOUT_FILENO);
	    if (result < 0)  return result;
	    if (form == 2) {
	       Fcntl_l(rightin, F_SETFD, 0);
	       Fcntl_l(rightout, F_SETFD, 0);
	    }
	 }

      } /* withfork */
      else /* !withfork */ {
	 applyopts(-1, *copts, PH_LATE);
	 applyopts(-1, *copts, PH_LATE2);
      }
      _xioopen_setdelayeduser();
      /* set group before user - maybe you are not permitted afterwards */
      if (retropt_gidt(*copts, OPT_SETGID, &group) >= 0) {
	 Setgid(group);
      }
      if (retropt_uidt(*copts, OPT_SETUID, &user) >= 0) {
	 Setuid(user);
      }
      if (withstderr) {
	 *duptostderr = fdo;
      } else {
	 *duptostderr = -1;
      }

      return 0;	/* indicate child process */
   }

   /* for parent (this is our socat process) */
   Notice1("forked off child process "F_pid, pid);

#if 0
   if ((popts = copyopts(*copts,
			 GROUP_FD|GROUP_TERMIOS|GROUP_FORK|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_FIFO)) == NULL)
      return STAT_RETRYLATER;
#endif

   /* in parent: close fds that are only needed in child */
   switch (commtype) {
#if HAVE_PTY
   case XIOCOMM_PTY:
      if (Close(ttyfd) < 0) {
	 Info2("close(%d): %s", ttyfd, strerror(errno));
      }
      break;
#endif /* HAVE_PTY */
   case XIOCOMM_SOCKETPAIR:
   case XIOCOMM_TCP:
   case XIOCOMM_TCP4:
   case XIOCOMM_TCP4_LISTEN:
      Close(sv[1]);
      break;
   case XIOCOMM_PIPES:
   default:
      if (XIOWITHWR(rw))  Close(wrpip[0]);
      if (XIOWITHRD(rw))  Close(rdpip[1]);
      break;
   }

   fd->child.pid = pid;

   if (applyopts_single(fd, popts, PH_LATE) < 0)  return -1;
   applyopts_signal(fd, popts);
   if ((numleft = leftopts(popts)) > 0) {
      Error1("%d option(s) could not be used", numleft);
      showleft(popts);
      return STAT_NORETRY;
   }

   if (inter) {
      if (XIOWITHRD(rw))  Close(saverfd);
      if (XIOWITHWR(rw))  Close(savewfd);
   }

   return pid;	/* indicate parent (main) process */
}