/***************************************************************************
                          myexec.cpp  -  description
                             -------------------
    begin                : Fri May 10 2002
    copyright            : (C) 2002 by Argo Vessmann (ARTEC Design)
    email                : 
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <stdlib.h>

#include "myexec.h"

#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <unistd.h>

#include <qtextstream.h>
#include <qfile.h>

#include <iostream.h>


MyExec::MyExec()
{
}

MyExec::MyExec( QString c, bool autorun = TRUE )
{
	command = c;
	if ( autorun )
		run();
}

MyExec::~MyExec()
{
}

int MyExec::run()
{
	int pid = iofork();
	if ( pid == -1 ) {
		retvalue = -1;
		return -1;
	}
	readIos();
	int status;
	if ( wait4( pid, &status, 0, NULL )  == -1 ) {
		retvalue = -1;
		return -1;
	}
	if ( WIFEXITED( status ) )
		retvalue = WEXITSTATUS( status );
	else
		retvalue = -1;
	return retvalue;
}

int MyExec::iofork()
{
	int ifd[2], ofd[2], efd[2];

	if ( pipe( ifd ) == -1 )
		return -1;
	if ( pipe( ofd ) == -1 ) {
		close( ifd[0] ); close( ifd[1] );
		return -1;
	}
	if ( pipe( efd ) == -1 ) {
		close( ifd[0] ); close( ifd[1] );
		close( ofd[0] ); close( ofd[1] );
		return -1;
	}
	inputfd = ifd[1];
	outputfd = ofd[0];
	errorfd = efd[0];

	pid_t ret = fork();
	if ( ret == -1 ) {
		close( ifd[0]); close( ifd[1] );
		close( ofd[0]); close( ofd[1] );
		close( efd[0]); close( efd[1] );
		return -1;
	}
	if ( ret ) { //I am the parent
		close( ifd[0] ); close( ofd[1] ); close( efd[1] );
		return ret;
	}

	setpgrp();

	char buf[BUFSIZ];
	sprintf( buf, "%s", (const char *)command );
	char *const argv[4] = { "/bin/sh", "-c", buf, 0 };
/*	argv[0] = "/bin/sh";
	argv[1] = "-c";
	argv[2] = buf;
	argv[3] = 0; */

	close( STDIN_FILENO );
	dup2( ifd[0], STDIN_FILENO );
	close( STDOUT_FILENO );
	dup2( ofd[1], STDOUT_FILENO );
	close( STDERR_FILENO );
	dup2( efd[1], STDERR_FILENO );
	close( ifd[1] ); close( ofd[0] ); close( efd[0] );

	execve( "/bin/sh", argv, 0 );
	exit( 127 );
}

void MyExec::readIos()
{
	istring = "";
	ostring = "";
	estring = "";

//	FILE *ifb = fdopen( inputfd, "w" );
	FILE *fb = fdopen( outputfd, "r" );
	QTextStream stream( fb, IO_ReadOnly );
	QString all = stream.read();
	stream.unsetDevice();
	fclose( fb );
	outputlist = QStringList::split( QChar( '\n' ), all, TRUE );

	fb = fdopen( errorfd, "r" );
	QFile f;
	f.open( IO_ReadOnly, fb );
	stream.setDevice( &f );
	all = stream.read();
	stream.unsetDevice();
	f.close();
	fclose( fb );
	errorlist = QStringList::split( QChar( '\n' ), all, TRUE );

	close( inputfd );

}

QStringList MyExec::stdOutput()
{
	return outputlist;
}

QStringList MyExec::stdError()
{
	return errorlist;
}

int MyExec::returnValue()
{
	return retvalue;
}
