/*==============================================================================

FICHIER     : [systools.c]

DATE        : 2005/12/0005 21:58:43

CREATEUR    : [Linux!jef]

COMMENTAIRE :
		Released under GPL license, see gnu.org
================================================================================

==============================================================================*/
#define __USE_LARGEFILE64
#define _LARGEFILE64_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>

char ** environ;
#define	SH_PATH	"/bin/sh"
#define	SH_NAME	"sh"

/* Structure describing a popen child.  */
struct child
{
	int fd;
	int pid;
} Child;

#define PATHCHR		':'
#define SEPCHAR		'/'

/*------------------------------------------------------------------------------
	MKFIFO-
Linux!jef 2005/12/05 21:59:11
------------------------------------------------------------------------------*/

int MkFifo( fifoName )
char * fifoName;
{
	return( mknod( fifoName, S_IFIFO | 0666, 0 ) ? -1 : 0 );
}
/*------------------------------------------------------------------------------
	DELFIFO-
Linux!jef 2005/12/05 22:00:27
------------------------------------------------------------------------------*/

int DelFifo( fifoName )
char * fifoName;
{
	unlink( fifoName );
	return( 0 );
}

/*------------------------------------------------------------------------------
	FILESTAT64-
Linux!jef 2005/12/16 21:19:35
------------------------------------------------------------------------------*/

long long FileSize64( char * fileName )
{
	struct stat64 bstat;
	int res;

	res = stat64( fileName, &bstat );
	if( res < 0 )	return( 0LL );
// fprintf(stderr,"sizeof(bstat.st_size)=%d := %lld\n", sizeof(bstat.st_size), bstat.st_size );
	return( (long long)bstat.st_size );
}

/*------------------------------------------------------------------------------
	LLSIZE2GIGA-
Linux!jef 2005/12/16 22:22:31
------------------------------------------------------------------------------*/

char * LLSize2Giga( long long size )
{
	static char string[200];
	double g;

// fprintf(stderr,"Size: %lld\n", size );

	g = (double)size / ( 1024.0 * 1024.0 * 1024.0 );
	if( g >= 1.0 ) {
		sprintf( string,(char*)("%.2f gigas"), g );
	}
	else {
		g = (double)size / ( 1024.0 * 1024.0 );
		if( g >= 1.0 ) {
			sprintf( string,(char*)("%.2f megas"), g );
		}
		else {
			g = (double)size / ( 1024.0 );
			sprintf( string,(char*)("%.2f kilos"), g );
		}
	}
	return( string );
}

/*------------------------------------------------------------------------------
	FLOOK-
JEF!jef 95/02/02 15:17:26
------------------------------------------------------------------------------*/
int flook( fname )
char *fname;
{
	char *path;	/* environmental PATH variable */
	char *sp;	/* pointer into path spec */
	char fspec[512];	/* full path spec to search */


	if( *fname == '/' ) {
		if( access( fname, 1 ) == 0 )	return( 1 );
// fprintf(stderr,"%s: is regular file !\n", fname );
		return( 0 );
	}
	/* get the PATH variable */
	path = getenv("PATH");
	if( path ) {
		while (*path) {

			/* build next possible file spec */
			sp = fspec;
			while (*path && (*path != PATHCHR))
				*sp++ = *path++;

			/* add a terminating dir separator if we need it */
			if (sp[-1] != SEPCHAR)
				*sp++ = SEPCHAR;

			*sp = 0;
			strcat(fspec, fname);
// fprintf(stderr,"Trying: (%s)\n",fspec);
			/* and try it out */
			if( access( fspec, 1 ) == 0 )
				return(1);
			if (*path == PATHCHR)
				++path;
		}
	}
	return(0);	/* no such luck */
}
/*------------------------------------------------------------------------------
	FSFREE-
Linux!jef 2005/12/19 20:57:02
------------------------------------------------------------------------------*/

long long FsFree( char * fsName )
{
	struct statfs b;
	int res;
	long long freeSize;

	res = statfs( fsName, &b );
	if( res < 0 )	return( 0LL );
	freeSize = ((long long)b.f_bavail * (long long)b.f_bsize);
	return( freeSize );
}
/*------------------------------------------------------------------------------
	DIREXIST-
Linux!jef 2006/01/31 20:46:19
------------------------------------------------------------------------------*/

int DirExist( char * dirName )
{
	struct stat bStat;
	int res;

	res = stat( dirName, &bStat );
// fprintf(stderr,"%s: res=%d\n", dirName, res );
	if( res )	return( 0 );
	if( S_ISDIR( bStat.st_mode ) )	return( 1 );
	return( -1 );
}
/*------------------------------------------------------------------------------
	FILEEXIST-
Linux!jef 2006/01/31 21:02:35
------------------------------------------------------------------------------*/

int FileExist( char * fileName )
{
	struct stat64 bStat;
	int res;

	res = stat64( fileName, &bStat );
// fprintf(stderr,"%s(%s) = %d errno: %d\n", __FUNCTION__,fileName, res, errno );
	if( res )	return( 0 );
	if( S_ISREG( bStat.st_mode ) )	return( 1 );
	if( S_ISBLK( bStat.st_mode ) )	return( 2 );
	return( -1 );
}


/*------------------------------------------------------------------------------
	MY_POPEN-
JEF!jef 95/09/26 14:29:09
	Open a new stream that is a one-way pipe to a
	child process running the given shell command. 
------------------------------------------------------------------------------*/
FILE * my_popen( command, mode)
char * command;
char * mode;
{
	int pid;
	int pipedes[2];
	FILE * stream;

	if (command == NULL || mode == NULL || (*mode != 'r' && *mode != 'w'))
	{
		errno = EINVAL;
		return NULL;
	}

  /* Create the pipe.  */
	if( pipe(pipedes) < 0)
		return NULL;

  /* Fork off the child.  */
	pid = fork();
	if( pid == -1)
	{
/* The fork failed.  */
		close(pipedes[0]);
		close(pipedes[1]);
		return( NULL );
	}
	else {
		if( !pid )
		{
			char *new_argv[4];
			int res;

			signal( SIGHUP, SIG_DFL );
			signal( SIGTERM, SIG_DFL );
			signal( SIGINT, SIG_DFL );
			signal( SIGQUIT, SIG_DFL );
			if( *mode == 'w' ) {
				res = dup2( pipedes[0] , 0 );
			}
			else {
				res = dup2( pipedes[1] , 1 );
/* Ajout Stderr */
				res |= dup2( pipedes[1] , 2 );
			}
			if( res < 0 )	_exit( 127 );

      /* Close the pipe descriptors.  */
			close(pipedes[0]);
			close(pipedes[1]);

      /* Exec the shell.  */
			new_argv[0] = SH_NAME;
			new_argv[1] = "-c";
			new_argv[2] = command;
			new_argv[3] = NULL;
			(void) execve(	SH_PATH,
					(char **) new_argv,
					(char **)environ);
			/* Die if it failed.  */
			_exit(127);
		}
	}
  /* We are the parent side.  */

  /* Close the irrelevant side of the pipe and open the relevant side as a
     new stream.  Mark our side of the pipe to close on exec, so new children
     won't see it.  */
	if( *mode == 'r')
	{
		close(pipedes[1]);
		fcntl( pipedes[0], F_SETFD, FD_CLOEXEC);
		stream = fdopen(pipedes[0], mode);
	}
	else {
		close(pipedes[0]);
		fcntl( pipedes[1], F_SETFD, FD_CLOEXEC);
		stream = fdopen(1, mode);
	}

	if( !stream )
		goto error;

	memset( &Child , 0 , sizeof( Child ));
	Child.fd = fileno(stream);
	Child.pid = pid;
	setvbuf( stream , NULL,_IOFBF,0 );
	return( stream );

error:;
	{
		int save = errno;

		kill(pid, SIGKILL);
		if( !stream )
			close(pipedes[*mode == 'r' ? 1 : 0]);
		else
			fclose(stream);
		{
			int dead;
			do
				dead = wait ((int *) NULL);
			while (dead > 0 && dead != pid);
		}
		errno = save;
		return NULL;
	}
}

/* Close a stream opened by popen and return its status.
   Returns -1 if the stream was not opened by popen.  */
int my_pclose( stream )
register FILE *stream;
{
	int pid, dead;
	int status;
	pid = Child.pid;

// fprintf(stderr,"killing: %d\n", pid );

	status = kill( pid, SIGHUP );
	if( fclose(stream) )
		return( -1 );
	do
		dead = wait (&status);
	while (dead > 0 && dead != pid);
	if (dead != pid)
		status = -1;
	return( status );
}

