/* source: xioinitialize.c */
/* Copyright Gerhard Rieger 2001-2008 */
/* Published under the GNU General Public License V.2, see file COPYING */

/* this file contains the source for the initialize function */

#include "xiosysincludes.h"

#include "xiostatic.h"
#include "xioopen.h"
#include "xiolockfile.h"
#include "xiosigchld.h"

#include "xio-openssl.h"	/* xio_reset_fips_mode() */

static int xioinitialized;
xiofile_t *sock[XIO_MAXSOCK];
int (*xiohook_newchild)(void);	/* xio calls this function in every new child
				   process */


/* call this function before calling any other xio function.
   With xioflags, you have to set the features that xio can make use of.
   Use XIO_MAYALL for unrestricted use. */
/* returns 0 on success or != if an error occurred */
int xioinitialize(int xioflags) {
   int xio_flags;
   if (xioinitialized)  return 0;

   /* configure and .h's cannot guarantee this */
   assert(sizeof(uint8_t)==1);
   assert(sizeof(uint16_t)==2);
   assert(sizeof(uint32_t)==4);

   /* assertions regarding O_ flags - important for XIO_READABLE() etc. */
   assert(O_RDONLY==0);
   assert(O_WRONLY==1);
   assert(O_RDWR==2);

   assert(SHUT_RD==0);
   assert(SHUT_WR==1);
   assert(SHUT_RDWR==2);

   /* some assertions about termios */
#if WITH_TERMIOS
#if defined(CRDLY) && CRDLY_SHIFT >= 0
   assert(3 << opt_crdly.arg3  == CRDLY);
#endif
#if defined(TABDLY) && TABDLY_SHIFT >= 0
   assert(3 << opt_tabdly.arg3 == TABDLY);
#endif
#if CSIZE_SHIFT >= 0
   assert(3 << opt_csize.arg3  == CSIZE);
#endif
   {
      union {
	 struct termios termarg;
	 tcflag_t flags[4];
#if HAVE_TERMIOS_ISPEED
	 speed_t speeds[sizeof(struct termios)/sizeof(speed_t)];
#endif
      } tdata;
      tdata.termarg.c_iflag = 0x12345678;
      tdata.termarg.c_oflag = 0x23456789;
      tdata.termarg.c_cflag = 0x3456789a;
      tdata.termarg.c_lflag = 0x456789ab;
      assert(tdata.termarg.c_iflag == tdata.flags[0]);
      assert(tdata.termarg.c_oflag == tdata.flags[1]);
      assert(tdata.termarg.c_cflag == tdata.flags[2]);
      assert(tdata.termarg.c_lflag == tdata.flags[3]);
#if HAVE_TERMIOS_ISPEED
      tdata.termarg.c_ispeed = 0x56789abc;
      tdata.termarg.c_ospeed = 0x6789abcd;
      assert(tdata.termarg.c_ispeed == tdata.speeds[ISPEED_OFFSET]);
      assert(tdata.termarg.c_ospeed == tdata.speeds[OSPEED_OFFSET]);
#endif
   }
#endif /* WITH_TERMIOS */

   /* these dependencies required in applyopts() for OFUNC_FCNTL */
   assert(F_GETFD == F_SETFD-1);
   assert(F_GETFL == F_SETFL-1);

   {
      const char *default_ip;
      default_ip = getenv("SOCAT_DEFAULT_LISTEN_IP");
      if (default_ip != NULL) {
	 switch (default_ip[0]) {
	 case '4':
	 case '6':
	    xioopts.default_ip = default_ip[0]; break;
	 }
      }
   }
   {
      const char *preferred_ip;
      preferred_ip = getenv("SOCAT_PREFERRED_RESOLVE_IP");
      if (preferred_ip != NULL) {
	 switch (preferred_ip[0]) {
	 case '4':
	 case '6':
	    xioopts.preferred_ip = preferred_ip[0]; break;
	 default:
	    xioopts.preferred_ip = '0'; break;
	 }
      }
   }

   if (Atexit(xioexit) < 0) {
      Error("atexit(xioexit) failed");
      return -1;
   }

   xio_flags = xioflags;

   if ((xio_flags|XIO_MAYFORK) || (xio_flags|XIO_MAYCHILD) ||
       (xio_flags|XIO_MAYCHAIN)) {
      
#if HAVE_SIGACTION
      struct sigaction act;
      memset(&act, 0, sizeof(struct sigaction));
      act.sa_flags   = SA_NOCLDSTOP|SA_RESTART|SA_SIGINFO
#ifdef SA_NOMASK
	 |SA_NOMASK
#endif
	 ;
      act.sa_sigaction = childdied;
      if (Sigaction(SIGCHLD, &act, NULL) < 0) {
	 /*! Linux man does not explicitely say that errno is defined */
	 Warn2("sigaction(SIGCHLD, %p, NULL): %s", childdied, strerror(errno));
      }
#else /* !HAVE_SIGACTION */
      act.sa_handler = childdied;
      if (Signal(SIGCHLD, childdied) == SIG_ERR) {
	 Warn2("signal(SIGCHLD, %p): %s", childdied, strerror(errno));
      }
#endif /* !HAVE_SIGACTION */
   }

   xioinitialized = 1;
   return 0;
}

/* call this function when option -lp (reset program name) has been applied */
int xioinitialize2(void) {
   pid_t pid = Getpid();
   xiosetenvulong("PID", pid, 1);
   xiosetenvulong("PPID", pid, 1);
   return 0;
}


/* well, this function is not for initialization, but I could not find a better
   source file for it
   it is called in the child process after fork
   it drops the lock references of the xiofile's so only the parent owns them
 */
void xiodroplocks(void) {
   int i;

   for (i = 0; i < XIO_MAXSOCK; ++i) {
      if (sock[i] != NULL && sock[i]->tag != XIO_TAG_INVALID) {
	 xiofiledroplock(sock[i]);
      }
   }
}


#if 0
/* consider an invokation like this:
   socat -u exec:'some program that accepts data' tcp-l:...,fork
   we do not want the program to be killed by the first tcp-l sub process, it's
   better if it survives all sub processes. Thus, it must not be killed when
   the sub process delivers EOF. Also, a socket that is reused in sub processes
   should not be shut down (affects the connection), but closed (affects only
   sub processes copy of file descriptor) */
static int xio_nokill(xiofile_t *sock) {
   int result = 0;
   switch (sock->tag) {
   case XIO_TAG_INVALID:
   default:
      return -1;
   case XIO_TAG_DUAL:
      if ((result = xio_nokill((xiofile_t *)sock->dual.stream[0])) != 0)
	 return result;
      result = xio_nokill((xiofile_t *)sock->dual.stream[1]);
      break;
   case XIO_TAG_RDONLY:
   case XIO_TAG_WRONLY:
   case XIO_TAG_RDWR:
      /* here is the core of this function */
      switch (sock->stream.howtoclose) {
      case END_SHUTDOWN_KILL: sock->stream.howtoclose = END_CLOSE; break;
      case END_CLOSE_KILL:    sock->stream.howtoclose = END_CLOSE; break;
      case END_SHUTDOWN:      sock->stream.howtoclose = END_CLOSE; break;
      default: break;
      }
      break;
   }
   return result;
}
#endif /* 0 */

/* call this function immediately after fork() in child process */
/* it performs some neccessary actions
   returns 0 on success or != 0 if an error occurred */
int xio_forked_inchild(void) {
   int result = 0;

   xiodroplocks();
#if WITH_FIPS
   if (xio_reset_fips_mode() != 0) {
      result = 1;
   }
#endif /* WITH_FIPS */
   /* some locks belong to parent process, so "drop" them now */
   if (xiohook_newchild) {
      if ((*xiohook_newchild)() != 0) {
	 Exit(1);
      }
   }

#if 0
   /* change XIO_SHUTDOWN_KILL to XIO_SHUTDOWN */
   if (sock1 != NULL) {
      int result2;
      result2 = xio_nokill(sock1);
      if (result2 < 0)  Exit(1);
      result |= result2;
   }
#endif

   return result;
}

/* subchild != 0 means that the current process is already a child process of
   the master process and thus the new sub child process should not set the
   SOCAT_PID variable */
pid_t xio_fork(bool subchild, int level) {
   pid_t pid;
   const char *forkwaitstring;
   int forkwaitsecs = 0;

   if ((pid = Fork()) < 0) {
      Msg1(level, "fork(): %s", strerror(errno));
      return pid;
   }

   if (pid == 0) {	/* child process */
      pid_t cpid = Getpid();

      Info1("just born: client process "F_pid, cpid);
      if (!subchild) {
	 /* set SOCAT_PID to new value */
	 xiosetenvulong("PID", pid, 1);
      }
      /* gdb recommends to have env controlled sleep after fork */
      if (forkwaitstring = getenv("SOCAT_FORK_WAIT")) {
	 forkwaitsecs = atoi(forkwaitstring);
	 Sleep(forkwaitsecs);
      }
      if (xio_forked_inchild() != 0) {
	 Exit(1);
      }
      return 0;
   }

   /* parent process */
   Notice1("forked off child process "F_pid, pid);
   /* gdb recommends to have env controlled sleep after fork */
   if (forkwaitstring = getenv("SOCAT_FORK_WAIT")) {
      forkwaitsecs = atoi(forkwaitstring);
      Sleep(forkwaitsecs);
   }
   return pid;
}
