ngspice/src/frontend/com_sysinfo.c

478 lines
11 KiB
C
Raw Normal View History

2009-10-01 00:22:36 +02:00
/* Provide system information
LINUX: /proc file system
Windows: GlobalMemoryStatusEx, GetSystemInfo, GetVersionExA, RegQueryValueExA
Authors: Holger Vogt, Hendrik Vogt
$Id$
*/
#include "config.h"
#include "ngspice.h"
#include "cpdefs.h"
/* We might compile for Windows, but only as a console application (e.g. tcl) */
#if defined(HAS_WINDOWS) || defined(__MINGW32__) || defined(_MSC_VER)
#define HAVE_WIN32
#endif
#ifdef HAVE_WIN32
#define WIN32_LEAN_AND_MEAN
#ifdef __MINGW32__ /* access to GlobalMemoryStatusEx in winbase.h:1558 */
#define WINVER 0x0500
#endif
#undef BOOLEAN
#include "windows.h"
#if defined(__MINGW32__) || (_MSC_VER > 1200) /* Exclude VC++ 6.0 from using the psapi */
#include <psapi.h>
#endif
#endif
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#define tInt int
#define TesError int
#define TES_FAIL 1
#define TES_SUCCESS 0
2009-10-01 00:52:52 +02:00
#define TES_INVALID_PARAMS 1
2009-10-01 00:22:36 +02:00
/* system info */
typedef struct TSI {
char* cpuModelName;
int numPhysicalProcessors;
int numLogicalProcessors;
char* osName;
} TesSystemInfo;
/* memory info */
struct sys_memory {
unsigned long int size_m; /* Total memory size */
unsigned long int free_m; /* Free memory */
2009-10-01 00:22:36 +02:00
unsigned long int swap_t; /* Swap total */
unsigned long int swap_f; /* Swap free */
};
static struct sys_memory mem_t_act;
TesError tesCreateSystemInfo(TesSystemInfo *info);
static size_t get_sysmem(struct sys_memory *memall);
/* Print to stream the given memory size in a human friendly format */
static void
fprintmem(FILE* stream, unsigned long int memory) {
if (memory > 1048576)
fprintf(stream, "%8.6f MB", memory/1048576.);
else if (memory > 1024)
fprintf(stream, "%5.3f kB", memory/1024.);
else
fprintf(stream, "%lu bytes", memory);
}
static void tesFreeSystemInfo(TesSystemInfo *info) {
if(info != NULL) {
free(info->cpuModelName);
free(info->osName);
}
}
/* print system info */
void com_sysinfo()
2009-10-01 00:22:36 +02:00
{
int errorcode;
TesSystemInfo* info;
info = (TesSystemInfo*)tmalloc(sizeof(TesSystemInfo));
errorcode = tesCreateSystemInfo(info);
if (errorcode)
fprintf(cp_err, "No system info available! \n");
else {
fprintf(cp_out, "\nOS: %s\n", info->osName);
fprintf(cp_out, "CPU: %s\n", info->cpuModelName);
if (info->numPhysicalProcessors > 0)
fprintf(cp_out, "Physical processors: %d, ", info->numPhysicalProcessors);
fprintf(cp_out, "Logical processors: %d\n",
info->numLogicalProcessors);
}
#if defined(HAVE_WIN32) || defined(HAVE__PROC_MEMINFO)
get_sysmem(&mem_t_act);
/* get_sysmem returns bytes */
fprintf(cp_out, "Total DRAM available = ");
fprintmem(cp_out, mem_t_act.size_m);
2009-10-01 00:22:36 +02:00
fprintf(cp_out, ".\n");
fprintf(cp_out, "DRAM currently available = ");
fprintmem(cp_out, mem_t_act.free_m);
2009-10-01 00:22:36 +02:00
fprintf(cp_out, ".\n\n");
#endif
tesFreeSystemInfo(info);
tfree(info);
}
#ifdef HAVE__PROC_MEMINFO
/* Get memory information */
static size_t get_sysmem(struct sys_memory *memall) {
FILE *fp;
char buffer[2048];
size_t bytes_read;
char *match;
long mem_got;
if((fp = fopen("/proc/meminfo", "r")) == NULL) {
perror("fopen(\"/proc/meminfo\")");
return 0;
}
bytes_read = fread (buffer, 1, sizeof (buffer), fp);
fclose (fp);
if (bytes_read == 0 || bytes_read == sizeof (buffer))
return 0;
buffer[bytes_read] = '\0';
/* Search for string "MemTotal" */
match = strstr (buffer, "MemTotal");
if (match == NULL) /* not found */
return 0;
sscanf (match, "MemTotal: %ld", &mem_got);
memall->size_m = mem_got*1024; /* 1MB = 1024KB */
2009-10-01 00:22:36 +02:00
/* Search for string "MemFree" */
match = strstr (buffer, "MemFree");
if (match == NULL) /* not found */
return 0;
sscanf (match, "MemFree: %ld", &mem_got);
memall->free_m = mem_got*1024; /* 1MB = 1024KB */
2009-10-01 00:22:36 +02:00
/* Search for string "SwapTotal" */
match = strstr (buffer, "SwapTotal");
if (match == NULL) /* not found */
return 0;
sscanf (match, "SwapTotal: %ld", &mem_got);
memall->swap_t = mem_got*1024; /* 1MB = 1024KB */
/* Search for string "SwapFree" */
match = strstr (buffer, "SwapFree");
if (match == NULL) /* not found */
return 0;
sscanf (match, "SwapFree: %ld", &mem_got);
memall->swap_f = mem_got*1024; /* 1MB = 1024KB */
return 1;
}
/* Return length of first line in a string */
tInt getLineLength(const char *str) {
tInt length = strlen(str);
char c = str[0];
tInt index = 0;
while((c != '\n') && (index < length)) {
index++;
c = str[index];
}
return index;
}
/* Checks if number 'match' is found in a vector 'set' of size 'size'
Returns 1 if yes, otherwise, 0 */
tInt searchInSet(const tInt *set, tInt size, tInt match) {
tInt index;
for(index = 0; index < size; index++) {
if(match == set[index]) {
return 1;
}
}
return 0;
}
/* Get system information */
2009-10-01 00:52:52 +02:00
TesError tesCreateSystemInfo(TesSystemInfo *info) {
2009-10-01 00:22:36 +02:00
FILE *file;
TesError error = TES_SUCCESS;
if(info == NULL)
return TES_INVALID_PARAMS;
info->cpuModelName = NULL;
info->osName = NULL;
info->numLogicalProcessors = info->numPhysicalProcessors = 0;
/* get kernel version string */
file = fopen("/proc/version", "rb");
if(file != NULL) {
tInt size = 0;
char buf;
/* read bytes and find end of file */
buf = fgetc(file);
while(buf != EOF) {
size++;
buf = fgetc(file);
}
info->osName = malloc((size) * sizeof(char));
rewind(file);
fread(info->osName, sizeof(char), size, file);
fclose(file);
info->osName[size-1] = '\0';
}
else {
error = TES_FAIL;
}
/* get cpu information */
file = fopen("/proc/cpuinfo", "rb");
if(file != NULL) {
tInt size = 0;
char buf, *inStr;
/* read bytes and find end of file */
buf = fgetc(file);
while(buf != EOF) {
size++;
buf = fgetc(file);
}
/* get complete string */
inStr = malloc((size+1) * sizeof(char));
rewind(file);
fread(inStr, sizeof(char), size, file);
inStr[size] = '\0';
{
const char *matchStr = "model name";
/* pointer to first occurrence of model name*/
const char *modelStr = strstr(inStr, matchStr);
if(modelStr != NULL) {
/* search for ':' */
const char *modelPtr = strchr(modelStr, ':');
if(modelPtr != NULL) {
/*length of string from ':' till end of line */
tInt numToEOL = getLineLength(modelPtr);
if(numToEOL > 2) {
/* skip ": "*/
numToEOL-=2;
info->cpuModelName = malloc(numToEOL+1);
memcpy(info->cpuModelName, modelPtr+2, numToEOL);
info->cpuModelName[numToEOL] = '\0';
}
}
else {
error = TES_FAIL;
}
}
else {
error = TES_FAIL;
}
}
{
const char *matchStrProc = "processor";
const char *matchStrPhys = "physical id";
char *strPtr = inStr;
tInt numProcs = 0;
tInt *physIDs;
/* get number of logical processors */
while((strPtr = strstr(strPtr, matchStrProc)) != NULL) {
2009-10-04 17:57:10 +02:00
// numProcs++;
2009-10-01 00:22:36 +02:00
strPtr += strlen(matchStrProc);
2009-10-04 17:57:10 +02:00
if isblank(*strPtr) numProcs++;
2009-10-01 00:22:36 +02:00
}
info->numLogicalProcessors = numProcs;
physIDs = malloc(numProcs * sizeof(tInt));
/* get number of physical CPUs */
numProcs = 0;
strPtr = inStr;
while((strPtr = strstr(strPtr, matchStrProc)) != NULL) {
/* search for first occurrence of physical id */
strPtr = strstr(strPtr, matchStrPhys);
if(strPtr != NULL) {
/* go to ';' */
strPtr = strchr(strPtr, ':');
if(strPtr != NULL) {
tInt buffer = 0;
/* skip ": " */
strPtr += 2;
/* get number */
sscanf(strPtr, "%d", &buffer);
/* If this physical id is unique,
we have another physically available CPU */
if(searchInSet(physIDs, numProcs, buffer) == 0) {
physIDs[numProcs] = buffer;
numProcs++;
}
}
else {
// error = TES_FAIL;
break;
}
}
else {
// error = TES_FAIL;
break;
}
}
info->numPhysicalProcessors = numProcs;
free(physIDs);
}
2009-10-04 17:57:10 +02:00
/* another test to get number of logical processors
2009-10-01 00:52:52 +02:00
if (info->numLogicalProcessors == 0) {
2009-10-01 00:22:36 +02:00
char* token;
char* cpustr = copy(inStr);
2009-10-04 17:57:10 +02:00
while ((cpustr) && !*cpustr)
2009-10-01 00:52:52 +02:00
if (cieq(gettok(&cpustr), "processor")) {
2009-10-01 00:22:36 +02:00
gettok(&cpustr);
token = gettok(&cpustr);
}
info->numLogicalProcessors = atoi(token) + 1;
2009-10-01 00:52:52 +02:00
tfree(cpustr);
2009-10-04 17:57:10 +02:00
}*/
2009-10-01 00:22:36 +02:00
free(inStr);
fclose(file);
}
else {
error = TES_FAIL;
}
return error;
}
#elif HAS_WINDOWS
/* get memory information */
static size_t get_sysmem(struct sys_memory *memall) {
#if ( _WIN32_WINNT >= 0x0500)
MEMORYSTATUSEX ms;
ms.dwLength = sizeof(MEMORYSTATUSEX);
GlobalMemoryStatusEx( &ms);
memall->size_m = ms.ullTotalPhys;
memall->free_m = ms.ullAvailPhys;
2009-10-01 00:22:36 +02:00
memall->swap_t = ms.ullTotalPageFile;
memall->swap_f = ms.ullAvailPageFile;
#else
MEMORYSTATUS ms;
ms.dwLength = sizeof(MEMORYSTATUS);
GlobalMemoryStatus( &ms);
memall->size_m = ms.dwTotalPhys;
memall->free_m = ms.dwAvailPhys;
2009-10-01 00:22:36 +02:00
memall->swap_t = ms.dwTotalPageFile;
memall->swap_f = ms.dwAvailPageFile;
#endif /*_WIN32_WINNT 0x0500*/
return 1;
}
/* get system information */
TesError tesCreateSystemInfo(TesSystemInfo *info) {
OSVERSIONINFOA version;
char *versionStr = NULL, *procStr, *freeStr;
tInt major, minor;
DWORD dwLen;
HKEY hkBaseCPU;
LONG lResult;
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
info->numPhysicalProcessors = 0;
info->numLogicalProcessors = sysinfo.dwNumberOfProcessors; //atoi(getenv("NUMBER_OF_PROCESSORS"));
info->osName = NULL;
version.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
if(GetVersionExA(&version) == 0) {
return TES_FAIL;
}
major = version.dwMajorVersion;
minor = version.dwMinorVersion;
switch(major) {
case 4:
if(minor == 0) {
versionStr = "Windows 95/NT4.0";
}
else if(minor == 10) {
versionStr = "Windows 98";
}
else if (minor == 90) {
versionStr = "Windows ME";
}
break;
case 5:
if(minor == 0) {
versionStr = "Windows 2000";
}
else if(minor == 1) {
versionStr = "Windows XP";
}
else if(minor == 2) {
versionStr = "Windows Server 2003";
}
break;
case 6:
if(minor == 0) {
versionStr = "Windows Vista";
}
2009-10-04 17:57:10 +02:00
else if(minor == 1) {
versionStr = "Windows 7";
}
2009-10-01 00:22:36 +02:00
break;
default:
break;
}
if(versionStr != NULL) {
tInt lengthCSD = strlen(version.szCSDVersion);
tInt lengthVer = strlen(versionStr);
info->osName = malloc(lengthVer + lengthCSD + 2);
memcpy(info->osName, versionStr, lengthVer);
memcpy(info->osName + lengthVer + 1, version.szCSDVersion, lengthCSD);
info->osName[lengthVer] = ' ';
info->osName[lengthVer + lengthCSD + 1] = '\0';
}
lResult = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
0,KEY_READ,&hkBaseCPU);
if(lResult != ERROR_SUCCESS) {
info->cpuModelName = NULL;
return TES_FAIL;
}
RegQueryValueExA(hkBaseCPU,"ProcessorNameString",0,0,NULL,&dwLen);
freeStr = procStr = tmalloc(dwLen+1);
RegQueryValueExA(hkBaseCPU,"ProcessorNameString",0,0,(LPBYTE)procStr,&dwLen);
procStr[dwLen] = '\0';
while (*procStr == ' ') procStr++;
info->cpuModelName = copy(procStr);
tfree(freeStr);
RegCloseKey(hkBaseCPU);
return TES_SUCCESS;
}
#else
/* no Windows OS, no proc info file system */
TesError tesCreateSystemInfo(TesSystemInfo *info) {
return 1;
}
#endif