/*
 * This file is part of DesktopBSD, see the README file.
 *
 * Author: Peter Hofer <ph@desktopbsd.net>
 *			(C) 2004, 2005
 *
 * Copyright: BSD, see the COPYING file included in this distribution
 *
 */

#include "executor.h"

#include <cstdio>

#include <qstring.h>
#include <qprocess.h>
#include <qstringlist.h>

#define  MAXLINESIZE  8192

/** Executes a command and returns the
  * exit status when finished.
  */
int  Executor::exec(const char  *cmd) {
	qDebug("Executor::exec <%s>.", cmd);

	return	system(cmd);
}


/** @sa cstrFromCmd() */
QString  Executor::strFromCmd(const char  *cmd) {
	qDebug("Executor::strFromCmd <%s>.", cmd);

	return	QString(cstrFromCmd(cmd));
}


/** Executes a command and reads every output line.
  * @note If a line is longer than MAXLINESIZE characters,
  *		 it will be split into two or more strings
  *		 in the QStringList.
  *
  * @return All lines of output.
  */
QStringList  Executor::strlistFromCmd(const char  *cmd) {
	qDebug("Executor::strlistFromCmd <%s>.", cmd);

	FILE *p = popen(cmd, "r");
	if(p == NULL)
		return  QStringList();

	QStringList lst;
	char buffer[MAXLINESIZE];
	while(fgets(buffer, sizeof(buffer), p) != NULL)
		lst.append(QString(buffer).remove('\n'));

	pclose(p);
	return  lst;
}


/** Executes a command and returns the first
  * line of output in a QCString object or
  * the first MAXLINESIZE characters if it
  * it's longer than MAXLINESIZE characters.
  */
QCString  Executor::cstrFromCmd(const char *cmd) {
	qDebug("Executor::cstrFromCmd <%s>", cmd);

	FILE  *p = popen(cmd, "r");
	if(p == NULL)
		return (char *) NULL;

	char  buffer[MAXLINESIZE];
	if(fgets(buffer, sizeof(buffer), p) == NULL) {
		pclose(p);
		return (char *) NULL;
	}

	char  *newl = strrchr(buffer, '\n');
	if(newl != NULL)
		*newl = '\0';

	pclose(p);
	return  QCString(buffer);
}


/** Executes a command and uses fscanf() to
  * read an integer from the first line of
  * output.
  *
  * @returns The read integer or -1 if popen() failed
  *			 or fscanf() couldn't read an integer.
  *
  * @warning Error checking is very limited because
  *			 the invocated program could also print -1.
  */
int  Executor::intFromCmd(const char *cmd) {
	qDebug("Executor::intFromCmd <%s>.", cmd);

	FILE  *p = popen(cmd, "r");
	if(p == NULL)  return -1;

	int  value;
	if(fscanf(p, "%i", &value) != 1)
		value = -1;

	pclose(p);
	return  value;
}

