/*

 OBJETIVO:

 Programa intermediario entre named.exe y named-xfer.exe que permite obtener el exitcode
 del named-xfer.exe y pasarlo a named.exe.

 FUNCIONAMIENTO

 Solo debe ser ejecutado por named.exe (Bind 824). Si es ejcutado manualmente, un mensaje
 de atencion saldra por la pantalla.
 Named.exe llama a este programa de la forma: "xferldr.exe \PIPE\NAMED\numero" donde
 "\PIPE\NAMED\numero" es un pipe supuestamente ya creado por el propio named.exe.

 El proceso es:

  1) Abre \PIPE\NAMED\numero
  2) Envia a named.exe la cadena "HOLA" por el pipe
  3) Recibe de named.exe una serie de datos que representan los argumentos a pasar a
     named-xfer.exe.
  4) Ejecuta named-xfer.exe con los argumentos pasados por named.exe.
  5) Espera a que termine la ejecucion de named-xfer.exe y pasa a named.exe (via pipe)
     el valor del exitcode del named-xfer.exe.
  6) Fin.

*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#define INCL_DOSERRORS
#include <os2emx.h>
#include <process.h>
#include <signal.h>
#include "xferldr.h"

/* Contendra los argumentos a pasar al named-xfer.exe */
char *namedxfer_argv[20] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
                            NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,};

void usage(void);

int main(int argc, char *argv[]) {

	int rc,i,j,finished;
	ULONG action, nbytes;
	TUBO tubo;
	struct _AVAILDATA bytes_avail;

	/* Debe llamarse como: "xferldr.exe UsE_oS2_XfErLdR \PIPE\BIND824\numero" */
	if (argc != 3) {
		usage();  /* Para los curiosos que ejecutan el programa */
		return XFER_FAIL;
		} else if (!((strcmp(argv[1],"UsE_oS2_XfErLdR") == 0 ) &&
		             (strstr(argv[2],"\\PIPE\\NAMED\\") != NULL))) return XFER_FAIL;

	/* sleep(1); Esperamos a que el server tenga tiempo de hacer un DosConnectPipe */

	/* Abrimos el pipe */
	strcpy(tubo.Name,argv[2]);
	rc = DosOpen(tubo.Name,&tubo.Hdl,&action,0,0, FILE_OPEN,
	             OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE,0);
	if (rc) {
		if (rc == ERROR_PIPE_BUSY) {
			rc = DosWaitNPipe(tubo.Name,0);
			if (rc) return (XFER_FAIL); else rc = DosOpen(tubo.Name,&tubo.Hdl,
			        &action,0,0,FILE_OPEN,OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE,0);
		} else return (XFER_FAIL);
	}

	tubo.WriteBuff = calloc(1,WRITEBUFFSIZE);
	tubo.ReadBuff  = calloc(1,READBUFFSIZE);

	/* Hablamos al server */
	strcpy(tubo.WriteBuff,"HOLA");
	DosWrite(tubo.Hdl,tubo.WriteBuff,5, &nbytes);

	/* Recibimos del server los argumentos a pasar a named-xfer.exe */
	DosRead(tubo.Hdl,tubo.ReadBuff,READBUFFSIZE, &nbytes);

	/* Creamos namedxfer_argv[] */
	j=1;
	namedxfer_argv[0]=tubo.ReadBuff;
	for(i=0;i < nbytes;i++) if ((tubo.ReadBuff[i] == 0) &&
	(tubo.ReadBuff[i+1] != 0)) namedxfer_argv[j++]=(char*)(&tubo.ReadBuff[i+1]);

	/* Llamamos a named-xfer.exe */
	j=spawnvp(P_NOWAIT | P_WINDOWED | P_MINIMIZE ,namedxfer_argv[0],namedxfer_argv);
	/* rc=wait(&i); */

	/* Esperamos a que el hijo termine mientras verificamos que named.exe aun esta vivo */
	finished=FALSE;
	do {
	 rc=waitpid(j,&i,WNOHANG);
	 action=0;
	 if (rc) {
	 	if (!(WIFEXITED(i))) rc = -1;
	 	finished=TRUE;
	 	} else {
	 	/* Verificamos que el pipe (named.exe) esta aun operativo */
	 	rc=DosPeekNPipe(tubo.Hdl,NULL,0,&nbytes,&bytes_avail,&action);
	 	if (rc) { /* Error grave, abortamos todo */
	 	   kill(j,SIGKILL);
	 	   finished=TRUE;
	 	   } else { /* esta Named.exe muerto? */
	 	   if ((action == NP_STATE_DISCONNECTED) || (action == NP_STATE_CLOSING)) {
	 	       kill(j,SIGKILL); /* pipe roto !!!, matamos al hijo */
	 	       finished=TRUE;
	 	       }
	 	   }
	 	}
	 _sleep2(200);
	} while (!finished);

	if (!action) {
		if (rc == -1) rc = XFER_FAIL << 8; else rc = i;
		_itoa(rc,tubo.WriteBuff,10);
		DosWrite(tubo.Hdl,tubo.WriteBuff,strlen(tubo.ReadBuff)+1, &nbytes);
		}

	free(tubo.ReadBuff);
	free(tubo.WriteBuff);
	DosClose(tubo.Hdl);

	return 0;
}

void usage(void) {
	printf("This program is required by named.exe (Bind 8.2.4 for OS/2) and it must be\n");
	printf("located in your %%PATH%% directory. Tony Sanmarti <warper@ansaro.com>.\n");
}


