/* 	$Id: info_hpux.cpp,v 1.15 2000/06/22 19:01:28 bieker Exp $
	
	!!!!! this file will be included by info.cpp !!!!!
	
	Mostly written 1998-1999 by Helge Deller (deller@gmx.de),
	with some pieces of code from Aubert Pierre.

	Last modified:	done:
	1999-06-21	added more models to the lookup-table (deller)
	1999-06-18	added support for 64-Bit HP-UX in CPU-detection(deller)
	1999-05-04	added audio(alib)-support (deller)
	1999-04-27	[tested with HP-UX 10.20 (HP9000/715/64-EISA)]
			added support for nearly all categories 
			    (means: not finished!)
	1998-11-01	first, nearly empty version (deller)
			with a little source for CPU from Aubert Pierre
*/

#include <unistd.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/pstat.h>
#include <sys/utsname.h>
#include <sys/statvfs.h>
#include <sys/vfs.h>
#include <fstab.h>
#include <stdlib.h>
#include <qfile.h>
#include <qfontmetrics.h>
#include <qtextstream.h>


#define INFO_CPU_AVAILABLE
#	define INFO_CPU_MODEL		"/bin/model" 	// as pipe !!

#define INFO_IRQ_AVAILABLE

#define INFO_DMA_AVAILABLE

#define INFO_PCI_AVAILABLE
#	define INFO_PCI			""	// Please, who know it ????
#	define INFO_PCI_EISA		"/etc/eisa/system.sci" // File !

#define INFO_IOPORTS_AVAILABLE
#	define INFO_IOPORTS_1		"/etc/dmesg"		// as pipe !
#	define INFO_IOPORTS_2		"/usr/sbin/dmesg"	// as pipe !

#define INFO_SOUND_AVAILABLE

#define INFO_DEVICES_AVAILABLE
#	define INFO_DEVICES		"/etc/ioscan" 	// as pipe !!

#define INFO_SCSI_AVAILABLE

#define INFO_PARTITIONS_AVAILABLE
#	define INFO_PARTITIONS_1 	FSTAB	// = "/etc/fstab" (in fstab.h)
#	define INFO_PARTITIONS_2 	"/etc/checklist"

#define INFO_XSERVER_AVAILABLE



/*	The following table is from an HP-UX 10.20 System
	build out of the files
	    "/usr/lib/sched.models" 
		    or
	    "/opt/langtools/lib/sched.models"
	If you have more entries, then please add them or send them to me!
*/

// entries for PA_REVISION[]
enum V_ENTRIES
    {	V_1x0,  
	V_1x1, V_1x1a, V_1x1b, V_1x1c, V_1x1d, V_1x1e, 
	V_2x0, 
	V_LAST };

static const char PA_REVISION[V_LAST][7]
    = { "1.0", 
        "1.1", "1.1a", "1.1b", "1.1c", "1.1d", "1.1e",
	"2.0" };

// entries for PA_NAME[]
enum PA_ENTRIES 
    {	PA7000,
	PA7100, PA7100LC, PA7200, PA7300,
	PA8000, PA8200,   PA8500,
	PARISC_PA_LAST };
			
static const char PA_NAME[PARISC_PA_LAST][11]
    = { "PA7000",
	"PA7100", "PA7100LC", "PA7200", "PA7300",
	"PA8000", "PA8200",   "PA8500" };

struct _type_LOOKUPTABLE {
	 char 		Name[8]; 
	 unsigned short	parisc_rev;	// = enum V_ENTRIES 
	 unsigned short	parisc_name;	// = enum PA_ENTRIES 
};
	 

static const struct _type_LOOKUPTABLE PA_LOOKUPTABLE[] = {	
/* 			VERSION A.00.07    
    (there seems to exist several different files with same version-number !)*/
{ "600"		,V_1x0	,PA7000		},
{ "635"		,V_1x0	,PA7000		},
{ "645"		,V_1x0	,PA7000		},
{ "700"		,V_1x1	,PA7000		},
{ "705"		,V_1x1a	,PA7000		},
{ "710"		,V_1x1a	,PA7000		},
{ "712"		,V_1x1c	,PA7100LC	},
{ "715"		,V_1x1c	,PA7100LC	},
{ "720"		,V_1x1a	,PA7000		},
{ "722"		,V_1x1c	,PA7100LC	},
{ "725"		,V_1x1c	,PA7100LC	},
{ "728"		,V_1x1d	,PA7200		},
{ "730"		,V_1x1a	,PA7000		},
{ "735"		,V_1x1b	,PA7100		},
{ "742"		,V_1x1b	,PA7100		},
{ "743"		,V_1x1b	,PA7100		},	// or a 1.1c,PA7100LC !!
{ "744"		,V_1x1e	,PA7300		},
{ "745"		,V_1x1b	,PA7100		},
{ "747"		,V_1x1b	,PA7100		},
{ "750"		,V_1x1a	,PA7000		},
{ "755"		,V_1x1b	,PA7100		},
{ "770"		,V_1x1d	,PA7200		},
{ "777"		,V_1x1d	,PA7200		},
{ "778"		,V_1x1e	,PA7300		},
{ "779"		,V_1x1e	,PA7300		},
{ "780"		,V_2x0	,PA8000		},
{ "781"		,V_2x0	,PA8000		},
{ "782"		,V_2x0	,PA8200		},
{ "783"		,V_2x0	,PA8500		},
{ "785"		,V_2x0	,PA8500		},
{ "800"		,V_1x0	,PA7000		},	// and one with: 2.0 / PA8000
{ "801"		,V_1x1c	,PA7100LC	},
{ "802"		,V_2x0	,PA8000		},
{ "803"		,V_1x1e	,PA7300		},
{ "804"		,V_2x0	,PA8000		},
{ "806"		,V_1x1c	,PA7100LC	},
{ "807"		,V_1x1a	,PA7000		},
{ "808"		,V_1x0	,PA7000		},
{ "809"		,V_1x1d	,PA7200		},
{ "810"		,V_2x0	,PA8000		},
{ "811"		,V_1x1c	,PA7100LC	},
{ "813"		,V_1x1e	,PA7300		},
{ "815"		,V_1x0	,PA7000		},
{ "816"		,V_1x1c	,PA7100LC	},
{ "817"		,V_1x1a	,PA7000		},
{ "819"		,V_1x1d	,PA7200		},
{ "820"		,V_2x0	,PA8000		},
{ "821"		,V_1x1d	,PA7200		},
{ "822"		,V_1x0	,PA7000		},
{ "825"		,V_1x0	,PA7000		},
{ "826"		,V_1x1c	,PA7100LC	},
{ "827"		,V_1x1a	,PA7000		},
{ "829"		,V_1x1d	,PA7200		},
{ "831"		,V_1x1d	,PA7200		},
{ "832"		,V_1x0	,PA7000		},
{ "834"		,V_1x0	,PA7000		},
{ "835"		,V_1x0	,PA7000		},
{ "837"		,V_1x1a	,PA7000		},
{ "839"		,V_1x1d	,PA7200		},
{ "840"		,V_1x0	,PA7000		},
{ "841"		,V_1x1d	,PA7200		},
{ "842"		,V_1x0	,PA7000		},
{ "845"		,V_1x0	,PA7000		},
{ "847"		,V_1x1a	,PA7000		},
{ "849"		,V_1x1d	,PA7200		},
{ "850"		,V_1x0	,PA7000		},
{ "851"		,V_1x1d	,PA7200		},
{ "852"		,V_1x0	,PA7000		},
{ "855"		,V_1x0	,PA7000		},
{ "856"		,V_1x1c	,PA7100LC	},
{ "857"		,V_1x1a	,PA7000		},
{ "859"		,V_1x1d	,PA7200		},
{ "860"		,V_1x0	,PA7000		},
{ "861"		,V_2x0	,PA8000		},
{ "865"		,V_1x0	,PA7000		},
{ "869"		,V_1x1d	,PA7200		},
{ "870"		,V_1x0	,PA7000		},
{ "871"		,V_2x0	,PA8000		},
{ "877"		,V_1x1a	,PA7000		},
{ "879"		,V_2x0	,PA8000		},
{ "887"		,V_1x1b	,PA7100		},
{ "889"		,V_2x0	,PA8000		},
{ "890"		,V_1x0	,PA7000		},
{ "891"		,V_1x1b	,PA7100		},
{ "892"		,V_1x1b	,PA7100		},
{ "893"		,V_2x0	,PA8000		},
{ "895"		,V_2x0	,PA8000		},
{ "896"		,V_2x0	,PA8000		},
{ "897"		,V_1x1b	,PA7100		},
{ "898"		,V_2x0	,PA8200		},
{ "899"		,V_2x0	,PA8200		},
{ "900"		,V_1x0	,PA7000		},
{ "B115"	,V_1x1e	,PA7300		},
{ "B120"	,V_1x1e	,PA7300		},
{ "B132L"	,V_1x1e	,PA7300		},
{ "B160L"	,V_1x1e	,PA7300		},
{ "B180L"	,V_1x1e	,PA7300		},
{ "C100"	,V_1x1d	,PA7200		},
{ "C110"	,V_1x1d	,PA7200		},
{ "C115"	,V_1x1e	,PA7300		},
{ "C120"	,V_1x1e	,PA7300		},
{ "C130"	,V_2x0	,PA8000		},
{ "C140"	,V_2x0	,PA8000		},
{ "C160L"	,V_1x1e	,PA7300		},
{ "C160"	,V_2x0	,PA8000		},
{ "C180L"	,V_1x1e	,PA7300		},
{ "C180-XP"	,V_2x0	,PA8000		},
{ "C180"	,V_2x0	,PA8000		},
{ "C200+"	,V_2x0	,PA8200		},
{ "C230+"	,V_2x0	,PA8200		},
{ "C240+"	,V_2x0	,PA8200		},
{ "CB260"	,V_2x0	,PA8200		},
{ "D200"	,V_1x1d	,PA7200		}, // or: 1.1c, PA7100LC
{ "D210"	,V_1x1d	,PA7200		}, // or: 1.1c, PA7100LC
{ "D220"	,V_1x1e	,PA7300		},
{ "D230"	,V_1x1e	,PA7300		},
{ "D250"	,V_1x1d	,PA7200		},
{ "D260"	,V_1x1d	,PA7200		},
{ "D270"	,V_2x0	,PA8000		},
{ "D280"	,V_2x0	,PA8000		},
{ "D310"	,V_1x1c	,PA7100LC	},
{ "D320"	,V_1x1e	,PA7300		},
{ "D330"	,V_1x1e	,PA7300		},
{ "D350"	,V_1x1d	,PA7200		},
{ "D360"	,V_1x1d	,PA7200		},
{ "D370"	,V_2x0	,PA8000		},
{ "D380"	,V_2x0	,PA8000		},
{ "D400"	,V_1x1d	,PA7200		},
{ "D410"	,V_1x1d	,PA7200		},
{ "D650"	,V_2x0	,PA8000		},
{ "DX0"		,V_1x1c	,PA7100LC	},
{ "DX5"		,V_1x1c	,PA7100LC	},
{ "DXO"		,V_1x1c	,PA7100LC	},
{ "E25"		,V_1x1c	,PA7100LC	},
{ "E35"		,V_1x1c	,PA7100LC	},
{ "E45"		,V_1x1c	,PA7100LC	},
{ "E55"		,V_1x1c	,PA7100LC	},
{ "F10"		,V_1x1a	,PA7000		},
{ "F20"		,V_1x1a	,PA7000		},
{ "F30"		,V_1x1a	,PA7000		},
{ "G30"		,V_1x1a	,PA7000		},
{ "G40"		,V_1x1a	,PA7000		},
{ "G50"		,V_1x1b	,PA7100		},
{ "G60"		,V_1x1b	,PA7100		},
{ "G70"		,V_1x1b	,PA7100		},
{ "H20"		,V_1x1a	,PA7000		},
{ "H30"		,V_1x1a	,PA7000		},
{ "H40"		,V_1x1a	,PA7000		},
{ "H50"		,V_1x1b	,PA7100		},
{ "H60"		,V_1x1b	,PA7100		},
{ "H70"		,V_1x1b	,PA7100		},
{ "I30"		,V_1x1a	,PA7000		},
{ "I40"		,V_1x1a	,PA7000		},
{ "I50"		,V_1x1b	,PA7100		},
{ "I60"		,V_1x1b	,PA7100		},
{ "I70"		,V_1x1b	,PA7100		},
{ "J200"	,V_1x1d	,PA7200		},
{ "J210XC"	,V_1x1d	,PA7200		},
{ "J210"	,V_1x1d	,PA7200		},
{ "J220"	,V_2x0	,PA8000		},
{ "J2240"	,V_2x0	,PA8200		},
{ "J280"	,V_2x0	,PA8000		},
{ "J282"	,V_2x0	,PA8000		},
{ "J400"	,V_2x0	,PA8000		},
{ "J410"	,V_2x0	,PA8000		},
{ "K100"	,V_1x1d	,PA7200		},
{ "K200"	,V_1x1d	,PA7200		},
{ "K210"	,V_1x1d	,PA7200		},
{ "K230"	,V_1x1d	,PA7200		},
{ "K250"	,V_2x0	,PA8000		},
{ "K260"	,V_2x0	,PA8000		},
{ "K370"	,V_2x0	,PA8200		},
{ "K380"	,V_2x0	,PA8200		},
{ "K400"	,V_1x1d	,PA7200		},
{ "K410"	,V_1x1d	,PA7200		},
{ "K420"	,V_1x1d	,PA7200		},
{ "K430"	,V_1x1d	,PA7200		},
{ "K450"	,V_2x0	,PA8000		},
{ "K460"	,V_2x0	,PA8000		},
{ "K470"	,V_2x0	,PA8200		},
{ "K570"	,V_2x0	,PA8200		},
{ "K580"	,V_2x0	,PA8200		},
{ "S700i"	,V_1x1e	,PA7300		},
{ "S715"	,V_1x1e	,PA7300		},
{ "S744"	,V_1x1e	,PA7300		},
{ "S760"	,V_1x1e	,PA7300		},
{ "T500"	,V_1x1c	,PA7100LC	}, // or: 1.1b, PA7100
{ "T520"	,V_1x1b	,PA7100 	},
{ "T540"	,V_2x0	,PA8000		},
{ "T600"	,V_2x0	,PA8000		},
{ "V2000"	,V_2x0	,PA8000		},
{ "V2200"	,V_2x0	,PA8200		},
{ "V2250"	,V_2x0	,PA8200		},
{ "V2500"	,V_2x0	,PA8500		},

{ ""		,0	,0		}  /* Last Entry has to be empty. */
};



/* Helper-Functions */

// Value() is defined in info.cpp !!!

static bool Find_in_LOOKUPTABLE( QListView *lBox, char *machine )
{	char *Machine;
	int  len;
	const struct _type_LOOKUPTABLE *Entry = PA_LOOKUPTABLE;
	QString str;
    QListViewItem* olditem = 0;
    
	
	Machine = machine;	// machine is like: "9000/715/D"
	while ((*Machine) && (*Machine!='/'))
        ++Machine;
    
	if (*Machine)
        ++Machine;
    else
        Machine=machine;
    
	len = strlen(Machine);
	
	while (Entry->Name[0])
	{	if (strncmp(Entry->Name,Machine,len)==0)
		{
            olditem = new QListViewItem(lBox, olditem, i18n("PA-RISC Processor"),
                                        QString(PA_NAME[Entry->parisc_name]));
            olditem = new QListViewItem(lBox, olditem, i18n("PA-RISC Revision"),
                                        QString("PA-RISC ") + QString(PA_REVISION[Entry->parisc_rev]));
		    return true;
		}
		else
		    ++Entry;	// next Entry !
	}
	
	return false;
}


/*  all following functions should return true, when the Information 
    was filled into the lBox-Widget.
    returning false indicates, that information was not available.
*/


bool GetInfo_CPU( QListView *lBox )
{
  FILE *pipe;
  QFile *model;
     
  struct pst_dynamic	psd;
  struct pst_static	pst;
  struct pst_processor	pro;
  struct utsname	info;
  QString str,str2;
  QListViewItem* olditem = 0;
  int	maxwidth,i;
			
  if((pstat_getstatic(&pst, sizeof(pst), (size_t)1, 0) == -1) ||
     (pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0)== -1)) {
     *GetInfo_ErrorString = i18n("Could not get Information!"); /* Error */
     return false;
  }

  maxwidth = 0;
  lBox->addColumn(i18n("Information") );
  lBox->addColumn(i18n("Value") );
  
  uname(&info);
  
  olditem = new QListViewItem(lBox, olditem, i18n("Machine"), info.machine);
  
  model = new QFile(INFO_CPU_MODEL);  
  if (model->exists()) 
  {	if ((pipe = popen(INFO_CPU_MODEL, "r"))) 
	{	QTextStream *t = new QTextStream(pipe, IO_ReadOnly);
		str = t->readLine();
        olditem = new QListViewItem(lBox, olditem, i18n("Model"), str);
		delete t;
	}
	delete pipe;
  }
  delete model;
  
  olditem = new QListViewItem(lBox, olditem, i18n("Machine Identification Number"),
                              strlen(info.__idnumber) ? QString(info.__idnumber) : i18n("(none)") );    

  if (psd.psd_proc_cnt<=0)
      psd.psd_proc_cnt=1; // Minimum one CPU !
  
  olditem = new QListViewItem(lBox, olditem, i18n("Number of active Processors"),
                              Value(psd.psd_proc_cnt));
  
  pstat_getprocessor( &pro, sizeof(pro), 1, 0 );
  olditem = new QListViewItem(lBox, olditem, i18n("CPU Clock"),
                              Value(pro.psp_iticksperclktick/10000) + " " + i18n("MHz"));
  
  switch(sysconf(_SC_CPU_VERSION))
  {	case CPU_HP_MC68020:	str2 = "Motorola 68020";	break;
	case CPU_HP_MC68030:	str2 = "Motorola 68030";	break;
	case CPU_HP_MC68040:	str2 = "Motorola 68040";	break;
	case CPU_PA_RISC1_0:	str2 = "PA-RISC 1.0";		break;
	case CPU_PA_RISC1_1:	str2 = "PA-RISC 1.1";		break;
	case CPU_PA_RISC1_2:	str2 = "PA-RISC 1.2";		break;
	case CPU_PA_RISC2_0:	
#if defined(_SC_KERNEL_BITS)
              	switch (sysconf(_SC_KERNEL_BITS)) {
              	    case 64: str2 = "PA-RISC 2.0w (64 bit)";	break;
              	    case 32: str2 = "PA-RISC 2.0n (32 bit)";	break;
              	    default: str2 = "PA-RISC 2.0"; 		break;
              	};						break;
#else  /* !defined(_SC_KERNEL_BITS) */
				str2 = "PA-RISC 2.0";		break;
#endif
	default:		str2 = i18n("(unknown)"); 	break;
  }

  olditem = new QListViewItem(lBox, olditem, i18n("CPU Architecture"), str2);
  
  Find_in_LOOKUPTABLE( lBox, info.machine );// try to get extended Information.

  for (i=PS_PA83_FPU; i<=PS_PA89_FPU; ++i) {
      if ((1<<(i-1)) & pro.psp_coprocessor.psc_present) {
          str = QString( (i==PS_PA83_FPU) ? "PS_PA83_FPU":"PS_PA89_FPU" )
              + QString(" (")
              + QString(((1<<(i-1))&pro.psp_coprocessor.psc_enabled) ? 
                        i18n("enabled") : i18n("disabled")	)
              + QString(")");

          olditem = new QListViewItem(lBox, olditem, i18n("Numerical Coprocessor (FPU)"), str);
      }
  }// for(coprocessor..)
  
  str = Value(((pst.physical_memory*pst.page_size)/1024/1024)) 
      + QString(" ")
      + i18n("MB");	// Mega-Byte
  olditem = new QListViewItem(lBox, olditem, i18n("Total Physical Memory"), str);

  str = Value(pst.page_size) + QString(" ") + i18n("Bytes");
  olditem = new QListViewItem(lBox, olditem, i18n("Size of one Page"), str);
  
  return true;
}

bool GetInfo_ReadfromFile( QListView *lBox, const char *Name )
{
  char buf[2048];

  QFile *file = new QFile(Name);
  QListViewItem* olditem = 0;

  if(!file->open(IO_ReadOnly)) {
    delete file; 
    return false;
  }
  
  while (file->readLine(buf,sizeof(buf)-1) >= 0) 
  {	if (strlen(buf))
      olditem = new QListViewItem(lBox, olditem, buf);
  }
  
  file->close();
  delete file;
  return (lBox->childCount());
}


static bool GetInfo_ReadfromPipe( QListView *lBox, const char *FileName )
{
    FILE *pipe;
    QFile *devices = new QFile(FileName);
    QTextStream *t;
    QListViewItem* olditem = 0;
    QString s;
  
    if (!devices->exists()) 
    {	delete devices;
	return false;
    }
  
    if ((pipe = popen(FileName, "r")) == NULL) 
    {   delete devices;
	pclose(pipe);
	return false;
    }

    t = new QTextStream(pipe, IO_ReadOnly);

    while (!t->eof())
	if ((s=t->readLine())!="")
        olditem = new QListViewItem(lBox, olditem, s);
  
    delete t; 
    delete devices; 
    pclose(pipe);
  
    return (lBox->childCount());
}


bool GetInfo_IRQ( QListView * )
{
	return false;
}

bool GetInfo_DMA( QListView * )
{
	return false;
}

bool GetInfo_PCI( QListView *lBox )
{	
    return(	GetInfo_ReadfromFile(lBox,INFO_PCI)    + 
		GetInfo_ReadfromFile(lBox,INFO_PCI_EISA) );
}

bool GetInfo_IO_Ports( QListView *lBox )
{
	if (GetInfo_ReadfromPipe( lBox, INFO_IOPORTS_1 ))
	    return true;
	else
	    return GetInfo_ReadfromPipe( lBox, INFO_IOPORTS_2 );
}


bool GetInfo_Devices( QListView *lBox )
{
	return GetInfo_ReadfromPipe( lBox, INFO_DEVICES );
}

bool GetInfo_SCSI( QListView *lBox )
{	
    return GetInfo_Devices( lBox );
}
/* Parts taken from fsusage.c from the Midnight Commander (mc)

   Copyright (C) 1991, 1992 Free Software Foundation, In

   Return the number of TOSIZE-byte blocks used by
   BLOCKS FROMSIZE-byte blocks, rounding away from zero.
   TOSIZE must be positive.  Return -1 if FROMSIZE is not positive.  */

static long fs_adjust_blocks(long blocks, int fromsize, int tosize)
{
    if (tosize <= 0)
	abort ();
    if (fromsize <= 0)
	return -1;

    if (fromsize == tosize)	/* E.g., from 512 to 512.  */
	return blocks;
    else if (fromsize > tosize)	/* E.g., from 2048 to 512.  */
	return blocks * (fromsize / tosize);
    else			/* E.g., from 256 to 512.  */
	return (blocks + (blocks < 0 ? -1 : 1)) / (tosize / fromsize);
}

/* Fill in the fields of FSP with information about space usage for
   the filesystem on which PATH resides.
   Return 0 if successful, -1 if not. */

#define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_bsize, 512)

static int get_fs_usage (char *path, long *l_total, long *l_avail)
{   struct statfs fsd;    /* 4.3BSD, SunOS 4, HP-UX, AIX.  */
    unsigned long fsu_blocks,fsu_bfree,fsu_bavail;

   *l_total = *l_avail = 0;
    if (statfs (path, &fsd) < 0)
	return -1;

    fsu_blocks = CONVERT_BLOCKS (fsd.f_blocks);
    fsu_bfree = CONVERT_BLOCKS (fsd.f_bfree);
    fsu_bavail = CONVERT_BLOCKS (fsd.f_bavail);

    *l_avail = getuid () ? fsu_bavail/2 : fsu_bfree/2;
    *l_total = fsu_blocks/2;

    return 0;
}


// Some Ideas taken from garbazo from his source in info_fbsd.cpp

bool GetInfo_Partitions (QListView *lbox)
{
	#define NUMCOLS 5
	QString Title[NUMCOLS];
	int n;
	
	struct fstab *fstab_ent;
	struct statvfs svfs;
	long total,avail;
	QString str;
	QString MB(i18n("MB")+ "  ");	// International Text for MB=Mega-Byte

	if (setfsent() != 1) // Try to open fstab 
	    return false;

	Title[0] = i18n("Device");
	Title[1] = i18n("Mount Point");
	Title[2] = i18n("FS Type");
	Title[3] = i18n("Total Size");
	Title[4] = i18n("Free Size");

	for (n=0; n<NUMCOLS; ++n) {
        lbox->addColumn(Title[n] );
	}

	while ((fstab_ent=getfsent())!=NULL) {
		/* fstab_ent->fs_type holds only "rw","xx","ro"... */
		memset(&svfs,0,sizeof(svfs)); 
		statvfs(fstab_ent->fs_file,&svfs);
		get_fs_usage(fstab_ent->fs_file, &total, &avail);
		
		if (!strcmp(fstab_ent->fs_type,FSTAB_XX))  // valid drive ?
			svfs.f_basetype[0] = 0;

        if(svfs.f_basetype[0]) {
            new QListViewItem(lbox, QString(fstab_ent->fs_spec),
                              QString(fstab_ent->fs_file) + QString("  "),
                              (svfs.f_basetype[0] ? QString(svfs.f_basetype) : i18n("n/a")),
                              Value((total+512)/1024,6) + MB,
                              Value((avail+512)/1024,6) + MB);
        }
        else {
            new QListViewItem(lbox, QString(fstab_ent->fs_spec),
                              QString(fstab_ent->fs_file) + QString("  "),
                              (svfs.f_basetype[0] ? QString(svfs.f_basetype) : i18n("n/a")));
        }

	}
	endfsent(); 
	    
	return true;
}


bool GetInfo_XServer_and_Video( QListView *lBox )
{	
    lBox = lBox;
    return GetInfo_XServer_Generic( lBox );
}





#ifndef HAVE_ALIB_H

bool GetInfo_Sound( QListView *lBox )
{	lBox = lBox;
	*GetInfo_ErrorString = i18n("Sorry, Audio-Support (Alib) was disabled during configuration and compile-time!");
	return false;
}

#else // defined(HAVE_ALIB_H)

#include "Alib.h"

static const char formatNames[6][15] = {  
    "ADFUnknown",	"ADFMuLaw",	"ADFALaw",
    "ADFLin16",  	"ADFLin8",  	"ADFLin8Offset" };

/* handle typo in 1st release of Alib.h */
#ifndef ARightOutputChMask
#define ARightOutputChMask ARighOutputChMask
#endif


bool GetInfo_Sound( QListView *lBox )
{	
    Audio	*audio;
    long	status;
    char	server[80];
    int		i;

    QString 	str,str2;
    QListViewItem* olditem = 0;

    // server = Hostname....
    server[0] = 0;    
    audio = AOpenAudio( server, &status );
    if( status ) {
        *GetInfo_ErrorString = i18n("Unable to open Audio-Server (Alib)!");
        return false;
    }
    
    lBox->addColumn(i18n("Information") );
    lBox->addColumn(i18n("Value") );

    olditem = new QListViewItem(lBox, olditem, i18n("Audio Name"), QString(audio->audio_name));
    olditem = new QListViewItem(lBox, olditem, i18n("Vendor"), QString(audio->vendor));
    olditem = new QListViewItem(lBox, olditem, i18n("Alib Version"),     
                                Value(audio->alib_major_version) + QString(".") +
                                Value(audio->alib_minor_version));

    olditem = new QListViewItem(lBox, olditem, i18n("Protocol Revision"), 
                                Value(audio->proto_major_version) + QString(".") +
                                Value(audio->proto_minor_version));

    olditem = new QListViewItem(lBox, olditem, i18n("Vendor Number"), 
                                Value(audio->vnumber));

    olditem = new QListViewItem(lBox, olditem, i18n("Release"),
                                Value(audio->release));

    olditem = new QListViewItem(lBox, olditem, i18n("Byte Order"),
                                QString((audio->byte_order==ALSBFirst)? i18n("ALSBFirst (LSB)"):
                                        ((audio->byte_order==AMSBFirst)? i18n("AMSBFirst (MSB)"):
                                         i18n("Invalid Byteorder!")) ));
    
    olditem = new QListViewItem(lBox, olditem, i18n("Bit Order"),
                                QString((audio->sound_bit_order==ALeastSignificant)? 
                                        i18n("ALeastSignificant (LSB)") :
                                        ((audio->sound_bit_order==AMostSignificant) ? 
                                         i18n("AMostSignificant (MSB)"):i18n("Invalid Bitorder!")) ));

    olditem = new QListViewItem(lBox, olditem, i18n("Data Formats"));
    for ( i = 0;  i < audio->n_data_format; i++ ) {
        if (audio->data_format_list[i] <= ADFLin8Offset)
            new QListViewItem(olditem, QString(formatNames[audio->data_format_list[i]]));
    }
    olditem->setOpen(true);

    olditem = new QListViewItem(lBox, olditem, i18n("Sampling Rates"));
    for ( i = 0;  i < audio->n_sampling_rate; i++ ) {
        new QListViewItem(olditem, Value(audio->sampling_rate_list[i]));
    }
    olditem->setOpen(true);

    olditem = new QListViewItem(lBox, olditem, i18n("Input Sources"));
    if ( audio->input_sources & AMonoMicrophoneMask )
        new QListViewItem(olditem, i18n("Mono-Microphone"));
    if ( audio->input_sources & AMonoAuxiliaryMask )
        new QListViewItem(olditem, i18n("Mono-Auxiliary"));
    if ( audio->input_sources & ALeftMicrophoneMask )
        new QListViewItem(olditem, i18n("Left-Microphone"));
    if ( audio->input_sources & ARightMicrophoneMask )
        new QListViewItem(olditem, i18n("Right-Microphone"));
    if ( audio->input_sources & ALeftAuxiliaryMask )
        new QListViewItem(olditem, i18n("Left-Auxiliary"));
    if ( audio->input_sources & ARightAuxiliaryMask )
        new QListViewItem(olditem, i18n("Right-Auxiliary"));
    olditem->setOpen(true);

    olditem = new QListViewItem(lBox, olditem,i18n("Input Channels"));
    if ( audio->input_channels & AMonoInputChMask )
        new QListViewItem(olditem, i18n("Mono-Channel"));
    if ( audio->input_channels & ALeftInputChMask )
        new QListViewItem(olditem, i18n("Left-Channel"));
    if ( audio->input_channels & ARightInputChMask )
        new QListViewItem(olditem, i18n("Right-Channel"));
    olditem->setOpen(true);

    olditem = new QListViewItem(lBox, olditem, i18n("Output Destinations"));
    if ( audio->output_destinations & AMonoIntSpeakerMask )
        new QListViewItem(olditem, i18n("Mono-InternalSpeaker"));
    if ( audio->output_destinations & AMonoJackMask )
        new QListViewItem(olditem, i18n("Mono-Jack"));
    if ( audio->output_destinations & ALeftIntSpeakerMask )
        new QListViewItem(olditem, i18n("Left-InternalSpeaker"));
    if ( audio->output_destinations & ARightIntSpeakerMask )
        new QListViewItem(olditem, i18n("Right-InternalSpeaker"));
    if ( audio->output_destinations & ALeftJackMask )
        new QListViewItem(olditem, i18n("Left-Jack"));
    if ( audio->output_destinations & ARightJackMask )
        new QListViewItem(olditem, i18n("Right-Jack"));
    olditem->setOpen(true);

    olditem = new QListViewItem(lBox, olditem, i18n("Output Channels"));
    if ( audio->output_channels & AMonoOutputChMask )
        new QListViewItem(olditem, i18n("Mono-Channel")); 
    if ( audio->output_channels & ALeftOutputChMask )
        new QListViewItem(olditem, i18n("Left-Channel"));
    if ( audio->output_channels & ARightOutputChMask )
        new QListViewItem(olditem, i18n("Right-Channel"));
    olditem->setOpen(true);


    olditem = new QListViewItem(lBox, olditem, i18n("Gain"));
    new QListViewItem(olditem, i18n("Input Gain Limits"), 
                                Value(audio->max_input_gain));
    new QListViewItem(olditem,i18n("Output Gain Limits"),
                                Value(audio->min_output_gain) + QString(" ") 
                                + Value(audio->max_output_gain));
    new QListViewItem(olditem, i18n("Monitor Gain Limits"),
                                Value(audio->min_monitor_gain) + QString(" ")
                                + Value(audio->max_monitor_gain));
    new QListViewItem(olditem, i18n("Gain Restricted"),    
                                Value(audio->gm_gain_restricted));
    olditem->setOpen(true);
    

    olditem = new QListViewItem(lBox, olditem,i18n("Lock"),
                                Value(audio->lock));
    olditem = new QListViewItem(lBox, olditem, i18n("Queue Length"),
                                Value(audio->qlen));
    olditem = new QListViewItem(lBox, olditem, i18n("Block Size"),
                                Value(audio->block_size));
    olditem = new QListViewItem(lBox, olditem, i18n("Stream Port (decimal)"),
                                Value(audio->stream_port));
    olditem = new QListViewItem(lBox, olditem, i18n("Ev Buffer Size"),
                                Value(audio->ev_buf_size));
    olditem = new QListViewItem(lBox, olditem, i18n("Ext Number"),
                                Value(audio->ext_number));

    ACloseAudio( audio, &status );
   
    return true;
}

#endif // defined(HAVE_ALIB_H)
