// * $Id: ipc.c,v 1.28 2002/04/04 23:59:25 hno Exp $
// * DEBUG: section 54    Interprocess Communication

#include "squid.h"

#ifdef _SQUID_OS2_
#define OLD_SRC 0

 #define INCL_DOSPROCESS
 #include <os2.h>


static const char *hello_string = "hi there\n";
#define HELLO_BUF_SZ 32
static char hello_buf[HELLO_BUF_SZ];


int mainTST(void);

static int
ipcCloseAllFD(int prfd, int pwfd, int crfd, int cwfd)
{
    if (prfd >= 0)
       comm_close(prfd);
    if (prfd != pwfd)
       if (pwfd >= 0)
           comm_close(pwfd);
    if (crfd >= 0)
       comm_close(crfd);
    if (crfd != cwfd)
       if (cwfd >= 0)
           comm_close(cwfd);
    return -1;
}

/*EK - type still ignore */
int
ipcCreate(int type, const char *prog, const char *const args[],
          const char *name, int *rfd, int *wfd)
{
    int crfd = -1;
    int prfd = -1;
    int cwfd = -1;
    int pwfd = -1;
    int pwfdR = -1;
    int pwfd_socket;
    int pwfd_socketR;
    int p2c[2], rc;
    int c2p[2];
    int x;

    struct sockaddr_un PS, PSR;
    char IPCName[] = "\\socket\\squid_pinger";
    char IPCNameR[] = "\\socket\\squid_pingerW";

    int stdinMy, stdoutMy;
    int index_fd_ipc[8];

    if (rfd)
       *rfd = -1;
    if (wfd)
       *wfd = -1;
/* для ICMP - pinger'а */
    if (type == IPC_UDP_SOCKET)
    {
       memset(&PS, 0, sizeof(PS));
      PS.sun_family = AF_UNIX;
      strncpy(PS.sun_path, IPCName, sizeof(PS.sun_path));
      pwfd_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
 debug(91, 6)
     ("ipcCreate socket %d\n",pwfd_socket);

      rc = squid_fd_table.open(pwfd ,pwfd_socket, FD_SOCKET, name);
      prfd = pwfd;

      if (prfd < 0) {
          debug(54, 0) ("ipcCreate: Failed to create server FD.\n");
          return -1;
      }
//      if (bind(pwfd_socket, (struct sockaddr *) &PS, sizeof(PS)) < 0) {
//          debug(54, 0) ("ipcCreate: Cannot bind socket FD %d: %s\n", prfd,  xstrerror_type(FD_SOCKET));
//          return -1;
//      }
//      if (connect(pwfd_socket, (struct sockaddr *) &PS, sizeof(PS)) < 0) {
//          debug(54, 0) ("ipcCreate: Cannot connect socket FD %d: %s\n", prfd,  xstrerror_type(FD_SOCKET));
//          return -1;
//      }
      memset(&PSR, 0, sizeof(PSR));
      PSR.sun_family = AF_UNIX;
      strncpy(PSR.sun_path, IPCNameR, sizeof(PSR.sun_path));
      pwfd_socketR = socket(AF_UNIX, SOCK_DGRAM, 0);
 debug(91, 6)
     ("ipcCreate socketR %d\n",pwfd_socketR);

      rc = squid_fd_table.open(pwfdR , pwfd_socketR, FD_SOCKET, name);
      if (pwfdR < 0) {
          debug(54, 0) ("ipcCreate: Failed to create serverR FD.\n");
          return -1;
      }
      if (bind(pwfd_socketR, (struct sockaddr *) &PSR, sizeof(PSR)) < 0) {
          debug(54, 0) ("ipcCreate: Cannot bind socketR FD %d: %s\n", pwfdR,  xstrerror_type(FD_SOCKET));
          return -1;
      }

      if (connect(pwfd_socketR, (struct sockaddr *) &PSR, sizeof(PSR)) < 0) {
          debug(54, 0) ("ipcCreate: Cannot connect socketR FD %d: %s\n", pwfdR,  xstrerror_type(FD_SOCKET));
          return -1;
      }


/* на всякий случАй */
      logsFlush();
/* пущаем клиента */
     // Let started program inherit handles from parent
    rc = _spawnvp(P_NOWAIT,(char *)prog, (char * *) args);
/* на будущее - тут можно разрешить вывод сквида в stdin/out */
    if(rc < 0)
         debug(54, 0) ("WARNING: ipcCreate: _spawnvp error %s, %s\n", prog,xstdio_strerror() );
    else
    {     debug(54, 1) ("ipcCreate: _spawnvp Ok, %s pid=%i\n",prog,rc );
          squid_fd_table.AddChild(rc, (char *)prog);
    }

        x = recv(pwfd_socketR, hello_buf, strlen(hello_string)+1, 0);
        if(x < 0)
        {    debug(54,1)("WARNING:ipcCreate: IPC_UDP_SOCKET hello recv() failed %s\n",
                          xstrerror_type(FD_SOCKET) );
           return -1;
        } else if (strcmp(hello_buf, hello_string)) {
           debug(54, 0) ("WARNING:ipcCreate:  hello read test failed\n");
           debug(54, 0) ("--> read returned %d\n", x);
           debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf));
           return -1;
        }
  
      if (connect(pwfd_socket, (struct sockaddr *) &PS, sizeof(PS)) < 0) {
          debug(54, 0) ("ipcCreate: Cannot connect socket FD %d: %s\n", prfd,  xstrerror_type(FD_SOCKET));
          return -1;
      }

        strcpy(hello_buf,"ipc work ok");
        x = send(pwfd_socket,(char *)hello_buf , strlen(hello_buf)+1, 0);
        if(x < 0)
        {  debug(54,1)("WARNING:ipcCreate: send failed %s\n",
                          xstrerror_type(FD_SOCKET) );
        }
         commSetTimeout(pwfd, -1,  NULL, NULL);
         commSetNonBlocking(pwfd);
         *rfd = pwfd;
         *wfd = pwfd;

        return 0;
/*********************************/
    } else {  /* IPC_UDP_SOCKET */
/*********************************/

   rc = pipe(p2c); /* ReadHandle, WriteHandle */
   if (rc < 0) {
          debug(54, 0) ("ipcCreate: Create pipe(1) error,rc=%d\n",-rc );
          return -1;
   }

   rc = pipe(c2p); /* ReadHandle, WriteHandle */
   if (rc < 0) {
          debug(54, 0) ("ipcCreate: Create pipe(2) error,rc=%d\n",-rc );
          return -1;
   }

/* flush or else we get dup data if unbuffered_logs is set */
/* на всякий случАй */
    logsFlush();

/* дублируем stdin/stdout */
    stdinMy  = dup(0);
    stdoutMy = dup(1);
/* дупим fh И fh2*/

     dup2(p2c[0],0);
     dup2(c2p[1],1);

/* На будущее - желательно прекратить на это время вывод сквида в stdin/stdout */
/* пущаем клиента */
     // Let started program inherit handles from parent
    rc = _spawnvp(P_NOWAIT,(char *)prog, (char * *) args);
/* вертаем взад stdin и stdout */
    dup2(stdinMy,0);
    dup2(stdoutMy,1);
/* на будущее - тут можно разрешить вывод сквида в stdin/out */
    if(rc < 0)
         debug(54, 0) ("WARNING: ipcCreate: _spawnvp error %s, %s\n", prog,xstdio_strerror() );
    else
    {     debug(54, 1) ("ipcCreate: _spawnvp Ok, %s pid=%i\n",prog,rc );
          squid_fd_table.AddChild(rc, (char *)prog);
    }
    rc = squid_fd_table.open(index_fd_ipc[0],c2p[0], FD_PIPE_READ, "IPC FIFO Child Read");
    rc = squid_fd_table.open(index_fd_ipc[1],p2c[1], FD_PIPE_WRITE, "IPC FIFO Child Write");
       if (index_fd_ipc[0])
           *rfd = index_fd_ipc[0];
       if (index_fd_ipc[1])
           *wfd = index_fd_ipc[1];

   squid_fd_table.fd_table[index_fd_ipc[0]].flags.ipc = 1;
   squid_fd_table.fd_table[index_fd_ipc[1]].flags.ipc = 1;

   return index_fd_ipc[1];
/*********************************/
    }  /* endif  IPC_UDP_SOCKET */

/* test */
//   { char str[256], buf[256];
//       strcpy(str,"http://ad2.rambler.ru/ban.ban?pg=931 127.0.0.1/- - GET\n");
//       rc = write(p2c[1],str,strlen(str));
//       rc = read(c2p[0],buf,sizeof(buf));
//       if(rc >= 0) buf[rc]=0;
//       printf("{%s}",buf);
//   }

/************/

}

#if  OLD_SRC
/*EK - type still ignore */
int
ipcCreate(int type, const char *prog, const char *const args[],
          const char *name, int *rfd, int *wfd)
{
    int crfd = -1;
    int prfd = -1;
    int cwfd = -1;
    int pwfd = -1;
    int pwfd_socket;
    int p2c[2], rc;
    int c2p[2];

    struct sockaddr_un PS;
    char IPCName[] = "\\socket\\squid\\pinger";

    int stdinMy, stdoutMy;
    int index_fd_ipc[8];

    if (rfd)
       *rfd = -1;
    if (wfd)
       *wfd = -1;
/* для ICMP - pinger'а */
    if (type == IPC_UDP_SOCKET)
    {
       memset(&PS, 0, sizeof(PS));
      PS.sun_family = AF_UNIX;
      strncpy(PS.sun_path, IPCName, sizeof(PS.sun_path));
      pwfd_socket = socket(AF_UNIX, SOCK_DGRAM, 0);

      rc = squid_fd_table.open(pwfd ,pwfd_socket, FD_SOCKET, name);
      prfd = pwfd;

      if (prfd < 0) {
          debug(54, 0) ("ipcCreate: Failed to create server FD.\n");
          return -1;
      }
      if (bind(pwfd_socket, (struct sockaddr *) &PS, sizeof(PS)) < 0) {
          debug(54, 0) ("ipcCreate: Cannot bind socket FD %d: %s\n", prfd,  xstrerror_type(FD_SOCKET));
          return -1;
      }
      if (connect(pwfd_socket, (struct sockaddr *) &PS, sizeof(PS)) < 0) {
          debug(54, 0) ("ipcCreate: Cannot connect socket FD %d: %s\n", prfd,  xstrerror_type(FD_SOCKET));
          return -1;
      }
    }

   rc = pipe(p2c); /* ReadHandle, WriteHandle */
   if (rc < 0) {
          debug(54, 0) ("ipcCreate: Create pipe(1) error,rc=%d\n",-rc );
          return -1;
   }

   rc = pipe(c2p); /* ReadHandle, WriteHandle */
   if (rc < 0) {
          debug(54, 0) ("ipcCreate: Create pipe(2) error,rc=%d\n",-rc );
          return -1;
   }


/* flush or else we get dup data if unbuffered_logs is set */
/* на всякий случАй */
    logsFlush();

/* дублируем stdin/stdout */
    stdinMy  = dup(0);
    stdoutMy = dup(1);
/* дупим fh И fh2*/

     dup2(p2c[0],0);
     dup2(c2p[1],1);


/* На будущее - желательно прекратить на это время вывод сквида в stdin/stdout */
/* пущаем клиента */
     // Let started program inherit handles from parent
    rc = _spawnvp(P_NOWAIT,(char *)prog, (char * *) args);
/* вертаем взад stdin и stdout */
    dup2(stdinMy,0);
    dup2(stdoutMy,1);

/* на будущее - тут можно разрешить вывод сквида в stdin/out */
    if(rc < 0)
         debug(54, 0) ("WARNING: ipcCreate: _spawnvp error %s, %s\n", prog,xstdio_strerror() );
    else
    {     debug(54, 1) ("ipcCreate: _spawnvp Ok, %s pid=%i\n",prog,rc );
          squid_fd_table.AddChild(rc, (char *)prog);
    }
/* test */
//   { char str[256], buf[256];
//       strcpy(str,"http://ad2.rambler.ru/ban.ban?pg=931 127.0.0.1/- - GET\n");
//       rc = write(p2c[1],str,strlen(str));
//       rc = read(c2p[0],buf,sizeof(buf));
//       if(rc >= 0) buf[rc]=0;
//       printf("{%s}",buf);
//   }

/************/
    rc = squid_fd_table.open(index_fd_ipc[0],c2p[0], FD_PIPE_READ, "IPC FIFO Child Read");
    rc = squid_fd_table.open(index_fd_ipc[1],p2c[1], FD_PIPE_WRITE, "IPC FIFO Child Write");

    if(type == IPC_UDP_SOCKET)
    {
       char buf[10];
       int x;
        x = recv(pwfd_socket, buf, 9, 0);
        if(x < 0)
                debug(54,1)("ipcCreate: recv() failed\n");
         commSetTimeout(pwfd, -1,  NULL, NULL);
         commSetNonBlocking(pwfd);
         *rfd = pwfd;
         *wfd = pwfd;
    } else {
       if (index_fd_ipc[0])
           *rfd = index_fd_ipc[0];
       if (index_fd_ipc[1])
           *wfd = index_fd_ipc[1];
    }
   squid_fd_table.fd_table[index_fd_ipc[0]].flags.ipc = 1;
   squid_fd_table.fd_table[index_fd_ipc[1]].flags.ipc = 1;

   return index_fd_ipc[1];

}


#endif //OLD_SRC
#endif
  //_SQUID_OS2_

