summary refs log tree commit diff stats
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/sysinfo/Makefile.am14
-rw-r--r--plugins/sysinfo/format.c95
-rw-r--r--plugins/sysinfo/format.h28
-rw-r--r--plugins/sysinfo/match.c228
-rw-r--r--plugins/sysinfo/osx/backend.m263
-rw-r--r--plugins/sysinfo/shared/df.c53
-rw-r--r--plugins/sysinfo/shared/df.h23
-rw-r--r--plugins/sysinfo/sysinfo-backend.h33
-rw-r--r--plugins/sysinfo/sysinfo.c674
-rw-r--r--plugins/sysinfo/sysinfo.h (renamed from plugins/sysinfo/xsys.h)15
-rw-r--r--plugins/sysinfo/sysinfo.vcxproj11
-rw-r--r--plugins/sysinfo/sysinfo.vcxproj.filters20
-rw-r--r--plugins/sysinfo/unix/backend.c170
-rw-r--r--plugins/sysinfo/unix/match.c98
-rw-r--r--plugins/sysinfo/unix/match.h (renamed from plugins/sysinfo/match.h)6
-rw-r--r--plugins/sysinfo/unix/parse.c (renamed from plugins/sysinfo/parse.c)222
-rw-r--r--plugins/sysinfo/unix/parse.h (renamed from plugins/sysinfo/parse.h)7
-rw-r--r--plugins/sysinfo/unix/pci.c (renamed from plugins/sysinfo/pci.c)141
-rw-r--r--plugins/sysinfo/unix/pci.h (renamed from plugins/sysinfo/pci.h)0
-rw-r--r--plugins/sysinfo/win32/backend.c493
-rw-r--r--plugins/sysinfo/xsys-changelog116
-rw-r--r--plugins/sysinfo/xsys-install15
-rw-r--r--plugins/sysinfo/xsys-makefile38
-rw-r--r--plugins/sysinfo/xsys-readme105
-rw-r--r--plugins/sysinfo/xsys.c927
25 files changed, 1615 insertions, 2180 deletions
diff --git a/plugins/sysinfo/Makefile.am b/plugins/sysinfo/Makefile.am
index 4ac9c016..bd44a19d 100644
--- a/plugins/sysinfo/Makefile.am
+++ b/plugins/sysinfo/Makefile.am
@@ -1,7 +1,17 @@
 libdir = $(hexchatlibdir)
 
+sources = sysinfo.c format.c shared/df.c
+
+if PLATFORM_OSX
+sources += osx/backend.m
+else
+sources += unix/backend.c unix/match.c unix/parse.c unix/pci.c
+endif
+
+EXTRA_DIST = osx unix win32 shared format.h sysinfo.h sysinfo-backend.h
+
 lib_LTLIBRARIES = sysinfo.la
-sysinfo_la_SOURCES = match.c parse.c pci.c xsys.c
+sysinfo_la_SOURCES = $(sources)
 sysinfo_la_LDFLAGS = $(PLUGIN_LDFLAGS) -module
 sysinfo_la_LIBADD = $(LIBPCI_LIBS) $(GLIB_LIBS)
-sysinfo_la_CFLAGS = $(LIBPCI_CFLAGS) $(GLIB_CFLAGS) -I$(srcdir)/../../src/common
+AM_CPPFLAGS = $(LIBPCI_CFLAGS) $(GLIB_CFLAGS) -I$(top_srcdir)/src/common -I$(srcdir)/shared
diff --git a/plugins/sysinfo/format.c b/plugins/sysinfo/format.c
new file mode 100644
index 00000000..f0b0effd
--- /dev/null
+++ b/plugins/sysinfo/format.c
@@ -0,0 +1,95 @@
+/*
+ * SysInfo - sysinfo plugin for HexChat
+ * Copyright (c) 2015 Patrick Griffis.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <glib.h>
+
+char *
+sysinfo_format_uptime (gint64 uptime)
+{
+	char buffer[128];
+	int weeks;
+	int days;
+	int hours;
+	int minutes;
+	int seconds;
+
+	seconds = uptime%60;
+	minutes = (uptime/60)%60;
+	hours   = (uptime/3600)%24;
+	days    = (uptime/86400)%7;
+	weeks   = uptime/604800;
+
+	if (minutes != 0 || hours != 0 || days != 0 || weeks != 0)
+	{
+		if (hours != 0 || days != 0 || weeks != 0)
+		{
+			if (days !=0 || weeks != 0)
+			{
+				if (weeks != 0)
+					g_snprintf (buffer, sizeof(buffer), "%dw %dd %dh %dm %ds", weeks, days, hours, minutes, seconds);
+				else
+					g_snprintf (buffer, sizeof(buffer), "%dd %dh %dm %ds", days, hours, minutes, seconds);
+			}
+			else
+			{
+				g_snprintf (buffer, sizeof(buffer), "%dh %dm %ds", hours, minutes, seconds);
+			}
+		}
+		else
+		{
+			g_snprintf (buffer, sizeof(buffer), "%dm %ds", minutes, seconds);
+		}
+	}
+	return g_strdup (buffer);
+}
+
+char *
+sysinfo_format_memory (guint64 totalmem, guint64 freemem)
+{
+	char *total_fmt, *free_fmt, *ret;
+
+	total_fmt = g_format_size_full (totalmem, G_FORMAT_SIZE_IEC_UNITS);
+	free_fmt = g_format_size_full (freemem, G_FORMAT_SIZE_IEC_UNITS);
+	ret = g_strdup_printf ("%s Total (%s Free)", total_fmt, free_fmt);
+
+	g_free (total_fmt);
+	g_free (free_fmt);
+	return ret;
+}
+
+char *
+sysinfo_format_disk (guint64 total, guint64 free)
+{
+	char *total_fmt, *free_fmt, *used_fmt, *ret;
+	GFormatSizeFlags format_flags = G_FORMAT_SIZE_DEFAULT;
+
+#ifdef WIN32 /* Windows uses IEC size (with SI format) */
+	format_flags = G_FORMAT_SIZE_IEC_UNITS;
+#endif
+
+	total_fmt = g_format_size_full (total, format_flags);
+	free_fmt = g_format_size_full (free, format_flags);
+	used_fmt = g_format_size_full (total - free, format_flags);
+	ret = g_strdup_printf ("%s / %s (%s Free)", used_fmt, total_fmt, free_fmt);
+
+	g_free (total_fmt);
+	g_free (free_fmt);
+	g_free (used_fmt);
+	return ret;
+}
diff --git a/plugins/sysinfo/format.h b/plugins/sysinfo/format.h
new file mode 100644
index 00000000..5fe209be
--- /dev/null
+++ b/plugins/sysinfo/format.h
@@ -0,0 +1,28 @@
+/*
+ * SysInfo - sysinfo plugin for HexChat
+ * Copyright (c) 2015 Patrick Griffis.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+
+#ifndef FORMAT_H
+#define FORMAT_H
+
+char *sysinfo_format_uptime(gint64 uptime);
+char *sysinfo_format_memory(guint64 totalmem, guint64 freemem);
+char *sysinfo_format_disk(guint64 total, guint64 free);
+
+#endif
diff --git a/plugins/sysinfo/match.c b/plugins/sysinfo/match.c
deleted file mode 100644
index cfd66e37..00000000
--- a/plugins/sysinfo/match.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * match.c - matching functions for X-Sys
- * Copyright (C) 2005, 2006, 2007 Tony Vroon
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <glib.h>
-#include "xsys.h"
-
-float percentage(unsigned long long *free, unsigned long long *total)
-{
-        unsigned long long result = (*free) * (unsigned long long)1000 / (*total);
-        return result / 10.0;
-}
-
-char *pretty_freespace(const char *desc, unsigned long long *free_k, unsigned long long *total_k)
-{
-	char *quantities[] = { "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", 0 };
-	char *result, **quantity;
-	double free_space, total_space;
-	free_space = *free_k;
-	total_space = *total_k;
-	result = g_new(char, bsize);
-	if (total_space == 0)
-	{
-		g_snprintf(result, bsize, "%s: none", desc);
-		return result;
-	}
-	quantity = quantities;
-	while (total_space > 1023 && *(quantity + 1))
-	{
-		quantity++;
-		free_space = free_space / 1024;
-		total_space = total_space / 1024;
-	}
-	if (sysinfo_get_percent () != 0)
-		g_snprintf(result, bsize, "%s: %.1f%s, %.1f%% free",
-		desc, total_space, *quantity,
-		percentage(free_k, total_k));
-	else
-		g_snprintf(result, bsize, "%s: %.1f%s/%.1f%s free",
-		desc, free_space, *quantity, total_space, *quantity);
-        return result;
-}
-
-
-void remove_leading_whitespace(char *buffer)
-{
-	char *p;
-
-	if (buffer == NULL)
-		return;
-
-	for (p = buffer; *p && isspace (*p); p++)
-	;
-
-	memmove (buffer, p, strlen (p) + 1);
-}
-
-char *decruft_filename(char *buffer)
-{
-	char *match, *match_end;
-
-	while ((match = strstr(buffer, "%20")))
-	{
-		match_end = match + 3;
-		*match++ = ' ';
-		while (*match_end)
-			*match++ = *match_end++;
-		*match = 0;
-	}
-	return buffer;
-}
-
-void find_match_char(char *buffer, char *match, char *result)
-{
-	char *position;
-	remove_leading_whitespace(buffer);
-	if(strstr(buffer, match) == strstr(buffer, buffer))
-		{
-			position = strpbrk(buffer, delims);
-			if (position != NULL) {
-				position += 1;
-				strcpy(result, position);
-				position = strstr(result, "\n");
-				*(position) = '\0';
-				remove_leading_whitespace(result);
-				}
-			else
-				strcpy(result, "\0");
-		}
-}
-
-void find_match_double(char *buffer, char *match, double *result)
-{
-	char *position;
-	remove_leading_whitespace(buffer);
-	if(strstr(buffer, match) == strstr(buffer, buffer))
-		{
-			position = strpbrk(buffer, delims);
-			if (position != NULL) {
-                        	position += 1;
-                        	*result = strtod(position, NULL);
-				}
-			else
-				*result = 0;
-		}
-}
-
-void find_match_double_hex(char *buffer, char *match, double *result)
-{
-	char *position;
-	remove_leading_whitespace(buffer);
-	if(strstr(buffer, match) == strstr(buffer, buffer))
-		{
-			position = strpbrk(buffer, delims);
-			if (position != NULL) {
-				memcpy(position,"0x",2);
-				*result = strtod(position,NULL);
-				}
-			else
-				*result = 0;
-		}
-}
-
-void find_match_int(char *buffer, char *match, unsigned int *result)
-{
-	char *position;
-	remove_leading_whitespace(buffer);
-	if(strstr(buffer, match) == strstr(buffer, buffer))
-		{
-			position = strpbrk(buffer, delims);
-			if (position != NULL) {
-                        	position += 1;
-                        	*result = atoi(position);
-				}
-			else
-				*result = 0;
-		}
-}
-
-void find_match_ll(char *buffer, char *match, unsigned long long *result)
-{
-	char *position;
-	remove_leading_whitespace(buffer);
-	if(strstr(buffer, match) == strstr(buffer, buffer))
-		{
-			position = strpbrk(buffer, delims);
-			if (position != NULL) {
-		               	position += 1;
-		               	*result = strtoll(position, NULL, 10);
-				}
-			else
-				*result = 0;
-		}
-}
-
-void format_output(const char *arg, char *string, char *format)
-{
-        char *pos1, *pos2, buffer[bsize];
-        pos1 = &format[0];
-        strncpy(buffer, string, bsize);
-        string[0] = '\0';
-
-        while((pos2 = strstr(pos1, "%")) != NULL)
-        {
-                strncat(string, pos1, (size_t)(pos2-pos1));
-                if(*(pos2+1) == '1')
-                        strcat(string, arg);
-                else if(*(pos2+1) == '2')
-                        strcat(string, buffer);
-                else if(*(pos2+1) == 'C' || *(pos2+1) == 'c')
-                        strcat(string, "\003");
-                else if(*(pos2+1) == 'B' || *(pos2+1) == 'b')
-                        strcat(string, "\002");
-                else if(*(pos2+1) == 'R' || *(pos2+1) == 'r')
-                        strcat(string, "\026");
-                else if(*(pos2+1) == 'O' || *(pos2+1) == 'o')
-                        strcat(string, "\017");
-                else if(*(pos2+1) == 'U' || *(pos2+1) == 'u')
-                        strcat(string, "\037");
-                else if(*(pos2+1) == '%')
-                        strcat(string, "%");
-                pos1=pos2+2;
-        }
-
-        strcat(string, pos1);
-}
-
-void flat_format_output(const char *arg, char *string, char *format)
-{
-        char *pos1, *pos2, buffer[bsize];
-        pos1 = &format[0];
-        strncpy(buffer, string, bsize);
-        string[0] = '\0';
-
-        while((pos2 = strstr(pos1, "%")) != NULL)
-        {
-                strncat(string, pos1, (size_t)(pos2-pos1));
-                if(*(pos2+1) == '1')
-                        strcat(string, arg);
-                else if(*(pos2+1) == '2')
-                        strcat(string, buffer);
-                else if(*(pos2+1) == '%')
-                        strcat(string, "%");
-                pos1=pos2+2;
-        }
-
-        strcat(string, pos1);
-}
diff --git a/plugins/sysinfo/osx/backend.m b/plugins/sysinfo/osx/backend.m
new file mode 100644
index 00000000..450a557a
--- /dev/null
+++ b/plugins/sysinfo/osx/backend.m
@@ -0,0 +1,263 @@
+/*
+ * SysInfo - sysinfo plugin for HexChat
+ * Copyright (c) 2015 Patrick Griffis.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+ /*
+	* Some snippets based upon Textual's System Profiler plugin.
+	* https://github.com/Codeux-Software/Textual
+	*/
+
+#import <Cocoa/Cocoa.h>
+
+#include <sys/sysctl.h>
+#include <mach/mach.h>
+#include <mach/mach_host.h>
+#include <mach/host_info.h>
+#include <mach/mach_vm.h>
+
+#include <glib.h>
+
+#include "format.h"
+#include "df.h"
+
+static char *
+get_os (void)
+{
+	NSDictionary *systemversion = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"];
+	NSString *build = [systemversion objectForKey:@"ProductBuildVersion"];
+	if (!build)
+		return NULL;
+	NSString *version = [systemversion objectForKey:@"ProductUserVisibleVersion"];
+	if (!version)
+	{
+		[build release];
+		return NULL;
+	}
+
+	NSDictionary *profiler = [NSDictionary dictionaryWithContentsOfFile:[@"~/Library/Preferences/com.apple.SystemProfiler.plist" stringByExpandingTildeInPath]];
+	NSDictionary *names = [profiler objectForKey:@"OS Names"];
+	NSString *os_name = nil;
+
+	for (NSString *name in names)
+	{
+		if ([name hasPrefix:build])
+		{
+			os_name = [names objectForKey:name];
+			break;
+		}
+	}
+	[build release];
+
+	if (!os_name)
+	{
+		[version release];
+		return NULL;
+	}
+
+	char *ret = g_strdup_printf ("%s %s", [os_name UTF8String], [version UTF8String]);
+	[version release];
+
+	return ret;
+}
+
+static char *
+get_os_fallback (void)
+{
+	NSProcessInfo *info = [NSProcessInfo processInfo];
+	NSOperatingSystemVersion version = [info operatingSystemVersion];
+
+	return g_strdup_printf ("OS X %ld.%ld.%ld", version.majorVersion, version.minorVersion, version.patchVersion);
+}
+char *
+sysinfo_backend_get_os(void)
+{
+	static char *os_str = NULL;
+	if (!os_str)
+	{
+		os_str = get_os();
+		if (!os_str)
+			os_str = get_os_fallback();
+	}
+	return g_strdup (os_str);
+}
+
+char *
+sysinfo_backend_get_disk(void)
+{
+	gint64 total, free_space;
+
+	if (xs_parse_df (&total, &free_space))
+	{
+		return NULL;
+	}
+
+	return sysinfo_format_disk (total, free_space);
+}
+
+static guint64
+get_free_memory (void)
+{
+	mach_msg_type_number_t infoCount = (sizeof(vm_statistics_data_t) / sizeof(natural_t));
+
+	vm_size_t pagesize;
+	vm_statistics_data_t vm_stat;
+
+	host_page_size(mach_host_self(), &pagesize);
+
+	if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_stat, &infoCount) == KERN_SUCCESS)
+		return ((vm_stat.inactive_count + vm_stat.free_count) * pagesize);
+
+	return 0;
+}
+
+char *
+sysinfo_backend_get_memory(void)
+{
+	NSProcessInfo *info = [NSProcessInfo processInfo];
+	guint64 totalmem, freemem;
+
+	totalmem = [info physicalMemory];
+
+	if ((freemem = get_free_memory()) == 0)
+		return NULL;
+
+	return sysinfo_format_memory (totalmem, freemem);
+}
+
+char *
+sysinfo_backend_get_cpu(void)
+{
+	guint64 cpu_clock_uint = 0;
+	double cpu_clock;
+	char cpu_string[256];
+	gsize len;
+	gboolean giga = FALSE;
+
+	len = sizeof(cpu_string);
+	if (sysctlbyname ("machdep.cpu.brand_string", cpu_string, &len, NULL, 0) != 0)
+		return NULL;
+	cpu_string[sizeof(cpu_string) - 1] = '\0';
+
+	len = sizeof(cpu_clock_uint);
+	if (sysctlbyname("hw.cpufrequency", &cpu_clock_uint, &len, NULL, 0) < 0)
+		return NULL;
+
+	cpu_clock = cpu_clock_uint / 1000000;
+	if (cpu_clock > 1000)
+	{
+		cpu_clock /= 1000;
+		giga = TRUE;
+	}
+
+	if (giga)
+		return g_strdup_printf ("%s (%.2fGHz)", cpu_string, cpu_clock);
+	else
+		return g_strdup_printf ("%s (%.0fMHz)", cpu_string, cpu_clock);
+}
+
+static char *
+get_gpu(void)
+{
+	CFMutableDictionaryRef pciDevices = IOServiceMatching("IOPCIDevice");
+	io_iterator_t entry_iterator, serviceObject;
+
+	if (IOServiceGetMatchingServices(kIOMasterPortDefault, pciDevices, &entry_iterator) != kIOReturnSuccess)
+		return NULL;
+
+	GString *gpu_list = g_string_new(NULL);
+	while ((serviceObject = IOIteratorNext(entry_iterator)))
+	{
+		CFMutableDictionaryRef serviceDictionary;
+
+		kern_return_t status = IORegistryEntryCreateCFProperties(serviceObject, &serviceDictionary,
+														 kCFAllocatorDefault, kNilOptions);
+
+		if (status != kIOReturnSuccess)
+		{
+			IOObjectRelease(serviceObject);
+			continue;
+		}
+
+		const void *class = CFDictionaryGetValue(serviceDictionary, @"class-code");
+		if (!class || *(guint32*)CFDataGetBytePtr(class) != 0x30000) /* DISPLAY_VGA */
+		{
+			CFRelease(serviceDictionary);
+			continue;
+		}
+
+		const void *model = CFDictionaryGetValue(serviceDictionary, @"model");
+		if (model)
+		{
+			if (CFGetTypeID(model) == CFDataGetTypeID() && CFDataGetLength(model) > 1)
+			{
+				if (gpu_list->len != 0)
+						g_string_append (gpu_list, ", ");
+				g_string_append_len (gpu_list, (const char*)CFDataGetBytePtr(model), CFDataGetLength(model) - 1);
+			}
+		}
+
+		CFRelease(serviceDictionary);
+	}
+
+	if (gpu_list->len == 0)
+	{
+		g_string_free (gpu_list, TRUE);
+		return NULL;
+	}
+
+	/* The string may contain nul-chars we must replace */
+	int i;
+	for (i = 0; i < gpu_list->len; i++)
+	{
+		if (gpu_list->str[i] == '\0')
+			gpu_list->str[i] = ' ';
+	}
+
+	return g_string_free (gpu_list, FALSE);
+}
+
+char *
+sysinfo_backend_get_gpu(void)
+{
+	static char *gpu_str = NULL;
+	if (!gpu_str)
+		gpu_str = get_gpu();
+
+	return g_strdup (gpu_str);
+}
+
+char *
+sysinfo_backend_get_sound(void)
+{
+	return NULL;
+}
+
+char *
+sysinfo_backend_get_uptime(void)
+{
+	NSProcessInfo *info = [NSProcessInfo processInfo];
+	double uptime = [info systemUptime];
+
+	return sysinfo_format_uptime ((gint64)uptime);
+}
+
+char *
+sysinfo_backend_get_network(void)
+{
+	return NULL;
+}
diff --git a/plugins/sysinfo/shared/df.c b/plugins/sysinfo/shared/df.c
new file mode 100644
index 00000000..2ef75689
--- /dev/null
+++ b/plugins/sysinfo/shared/df.c
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+
+#include "sysinfo.h"
+
+int xs_parse_df(gint64 *out_total, gint64 *out_free)
+{
+	FILE *pipe;
+	char buffer[bsize];
+	
+	pipe = popen("df -k -l -P", "r");
+	if(pipe==NULL)
+		return 1;
+
+	*out_total = *out_free = 0;
+
+	while(fgets(buffer, bsize, pipe) != NULL)
+	{
+		long long int avail, total;
+
+		/* Filesystem 1024-blocks Used Available Capacity Mounted-on */
+		if (sscanf (buffer, "%*s %lld %*lld %lld %*s %*s", &total, &avail) == 2)
+		{
+			*out_total += total;
+			*out_free += avail;
+		}
+	}
+
+	/* Convert to bytes */
+	*out_total *= 1000;
+	*out_free *= 1000;
+
+	pclose(pipe);
+	return 0;
+}
diff --git a/plugins/sysinfo/shared/df.h b/plugins/sysinfo/shared/df.h
new file mode 100644
index 00000000..5f7f3296
--- /dev/null
+++ b/plugins/sysinfo/shared/df.h
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+
+#ifndef SYSINFO_SHARED_H
+#define SYSINFO_SHARED_H
+
+int xs_parse_df(gint64 *total_bytes, gint64 *free_bytes);
+
+#endif
diff --git a/plugins/sysinfo/sysinfo-backend.h b/plugins/sysinfo/sysinfo-backend.h
new file mode 100644
index 00000000..c69a0853
--- /dev/null
+++ b/plugins/sysinfo/sysinfo-backend.h
@@ -0,0 +1,33 @@
+/*
+ * SysInfo - sysinfo plugin for HexChat
+ * Copyright (c) 2015 Patrick Griffis.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+
+#ifndef SYSINFO_BACKEND_H
+#define SYSINFO_BACKEND_H
+
+char *sysinfo_backend_get_os(void);
+char *sysinfo_backend_get_disk(void);
+char *sysinfo_backend_get_memory(void);
+char *sysinfo_backend_get_cpu(void);
+char *sysinfo_backend_get_gpu(void);
+char *sysinfo_backend_get_sound(void);
+char *sysinfo_backend_get_uptime(void);
+char *sysinfo_backend_get_network(void);
+
+#endif
diff --git a/plugins/sysinfo/sysinfo.c b/plugins/sysinfo/sysinfo.c
index c243de42..10c9d796 100644
--- a/plugins/sysinfo/sysinfo.c
+++ b/plugins/sysinfo/sysinfo.c
@@ -1,567 +1,277 @@
-/* HexChat
- * Copyright (c) 2011-2012 Berke Viktor.
+/*
+ * SysInfo - sysinfo plugin for HexChat
+ * Copyright (c) 2012 Berke Viktor.
  *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
+ * xsys.c - main functions for X-Sys 2
+ * by mikeshoup
+ * Copyright (C) 2003, 2004, 2005 Michael Shoup
+ * Copyright (C) 2005, 2006, 2007 Tony Vroon
  *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
+ * 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.
  *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include <stdio.h>
-#include <windows.h>
-#include <wbemidl.h>
+#include "config.h"
 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <glib.h>
 
 #include "hexchat-plugin.h"
+#include "sysinfo-backend.h"
+#include "sysinfo.h"
 
-static hexchat_plugin *ph;   /* plugin handle */
+#define _(x) hexchat_gettext(ph,x)
+#define DEFAULT_ANNOUNCE TRUE
 
-static char name[] = "SysInfo";
-static char desc[] = "Display info about your hardware and OS";
-static char version[] = "1.1";
-static char helptext[] = "USAGE: /SYSINFO - Sends info about your hardware and OS to current channel.";
-
-/* Cache the info for subsequent invocations of /SYSINFO */
-static int cpu_arch = 0;
-static char *os_name = NULL;
-static char *cpu_info = NULL;
-static char *vga_name = NULL;
+static hexchat_plugin *ph;
 
-static int command_callback (char *word[], char *word_eol[], void *user_data);
+static char name[] = "Sysinfo";
+static char desc[] = "Display info about your hardware and OS";
+static char version[] = "1.0";
+static char sysinfo_help[] = "SysInfo Usage:\n  /SYSINFO [-e|-o] [CLIENT|OS|CPU|RAM|DISK|VGA|SOUND|ETHERNET|UPTIME], print various details about your system or print a summary without arguments\n  /SYSINFO SET <variable>\n";
 
-typedef enum
+typedef struct
 {
-	QUERY_WMI_OS,
-	QUERY_WMI_CPU,
-	QUERY_WMI_VGA,
-	QUERY_WMI_HDD,
-} QueryWmiType;
-
-void print_info (void);
-int get_cpu_arch (void);
-char *query_wmi (QueryWmiType mode);
-char *read_os_name (IWbemClassObject *object);
-char *read_cpu_info (IWbemClassObject *object);
-char *read_vga_name (IWbemClassObject *object);
-
-guint64 hdd_capacity;
-guint64 hdd_free_space;
-char *read_hdd_info (IWbemClassObject *object);
-
-char *get_memory_info (void);
-char *bstr_to_utf8 (BSTR bstr);
-guint64 variant_to_uint64 (VARIANT *variant);
-
-int hexchat_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg)
+	const char *name; /* Lower case name used for prefs */
+	const char *title; /* Used for the end formatting */
+	char *(*callback) (void);
+	gboolean def; /* Hide by default? */
+} hwinfo;
+
+static char *
+get_client (void)
 {
-	ph = plugin_handle;
-
-	*plugin_name = name;
-	*plugin_desc = desc;
-	*plugin_version = version;
-
-	hexchat_hook_command (ph, "SYSINFO", HEXCHAT_PRI_NORM, command_callback, helptext, NULL);
-	hexchat_command (ph, "MENU -ishare\\system.png ADD \"Window/Send System Info\" \"SYSINFO\"");
-
-	hexchat_printf (ph, "%s plugin loaded\n", name);
-
-	return 1;
+	return g_strdup_printf ("HexChat %s", hexchat_get_info(ph, "version"));
 }
 
-int hexchat_plugin_deinit (void)
+static hwinfo hwinfos[] = {
+	{"client", "Client", get_client},
+	{"os", "OS", sysinfo_backend_get_os},
+	{"cpu", "CPU", sysinfo_backend_get_cpu},
+	{"memory", "Memory", sysinfo_backend_get_memory},
+	{"storage", "Storage", sysinfo_backend_get_disk},
+	{"vga", "VGA", sysinfo_backend_get_gpu},
+	{"sound", "Sound", sysinfo_backend_get_sound, TRUE},
+	{"ethernet", "Ethernet", sysinfo_backend_get_network, TRUE},
+	{"uptime", "Uptime", sysinfo_backend_get_uptime},
+	{NULL, NULL},
+};
+
+static gboolean sysinfo_get_bool_pref (const char *pref, gboolean def);
+
+static gboolean
+should_show_info (hwinfo info)
 {
-	g_free (os_name);
-	g_free (cpu_info);
-	g_free (vga_name);
+	char hide_pref[32];
 
-	hexchat_command (ph, "MENU DEL \"Window/Display System Info\"");
-	hexchat_printf (ph, "%s plugin unloaded\n", name);
-
-	return 1;
+	g_snprintf (hide_pref, sizeof(hide_pref), "hide_%s", info.name);
+	return !sysinfo_get_bool_pref (hide_pref, info.def);
 }
 
-static int command_callback (char *word[], char *word_eol[], void *user_data)
+static void
+print_summary (gboolean announce)
 {
-	print_info ();
-
-	return HEXCHAT_EAT_HEXCHAT;
-}
-
-static void print_info (void)
-{
-	char *memory_info;
-	char *hdd_info;
-	int channel_type;
-
-#ifdef _WIN64
-	const char *build_arch = "x64";
-#else
-	const char *build_arch = "x86";
-#endif
+	char **strings = g_new0 (char*, G_N_ELEMENTS(hwinfos));
+	int i, x;
+	char *output;
 
-	/* Load information if not already loaded */
-
-	if (cpu_arch == 0)
-	{
-		cpu_arch = get_cpu_arch ();
-	}
-
-	if (os_name == NULL)
-	{
-		os_name = query_wmi (QUERY_WMI_OS);
-		if (os_name == NULL)
-		{
-			hexchat_printf (ph, "%s - Error while getting OS info.\n", name);
-			os_name = g_strdup ("Unknown");
-		}
-	}
-
-	if (cpu_info == NULL)
+	for (i = 0, x = 0; hwinfos[i].name != NULL; i++)
 	{
-		cpu_info = query_wmi (QUERY_WMI_CPU);
-		if (cpu_info == NULL)
+		if (should_show_info (hwinfos[i]))
 		{
-			hexchat_printf (ph, "%s - Error while getting CPU info.\n", name);
-			cpu_info = g_strdup ("Unknown");
-		}
-	}
-
-	if (vga_name == NULL)
-	{
-		vga_name = query_wmi (QUERY_WMI_VGA);
-		if (vga_name == NULL)
-		{
-			hexchat_printf (ph, "%s - Error while getting VGA info.\n", name);
-			vga_name = g_strdup ("Unknown");
+			char *str = hwinfos[i].callback();
+			if (str)
+			{
+				strings[x++] = g_strdup_printf ("\002%s\002: %s", hwinfos[i].title, str);
+				g_free (str);
+			}
 		}
 	}
 
-	/* Memory information is always loaded dynamically since it includes the current amount of free memory */
-	memory_info = get_memory_info ();
-	if (memory_info == NULL)
-	{
-		hexchat_printf (ph, "%s - Error while getting memory info.\n", name);
-		memory_info = g_strdup ("Unknown");
-	}
-
-	/* HDD information is always loaded dynamically since it includes the current amount of free space */
-	hdd_capacity = 0;
-	hdd_free_space = 0;
-	hdd_info = query_wmi (QUERY_WMI_HDD);
-	if (hdd_info == NULL)
-	{
-		hexchat_printf (ph, "%s - Error while getting disk info.\n", name);
-		hdd_info = g_strdup ("Unknown");
-	}
-	else
-	{
-		gfloat total_gb = hdd_capacity / 1000.f / 1000.f / 1000.f;
-		gfloat used_gb = (hdd_capacity - hdd_free_space) / 1000.f / 1000.f / 1000.f;
-		gfloat free_gb = hdd_free_space / 1000.f / 1000.f / 1000.f;
-		hdd_info = g_strdup_printf ("%.2f GB / %.2f GB (%.2f GB Free)", used_gb, total_gb, free_gb);
-	}
-
-	channel_type = hexchat_list_int (ph, NULL, "type");
-	if (channel_type == 2 /* SESS_CHANNEL */ || channel_type == 3 /* SESS_DIALOG */)
-	{
-		hexchat_commandf (
-			ph,
-			"ME ** SysInfo ** Client: HexChat %s (%s) ** OS: %s (x%d) ** CPU: %s ** RAM: %s ** VGA: %s ** HDD: %s ** Uptime: %.2f Hours **",
-			hexchat_get_info (ph, "version"), build_arch,
-			os_name, cpu_arch,
-			cpu_info,
-			memory_info,
-			vga_name,
-			hdd_info,
-			(float) GetTickCount64 () / 1000 / 60 / 60);
-	}
-	else
-	{
-		hexchat_printf (ph, " * Client:  HexChat %s (%s)\n", hexchat_get_info (ph, "version"), build_arch);
-		hexchat_printf (ph, " * OS:      %s (x%d)\n", os_name, cpu_arch);
-		hexchat_printf (ph, " * CPU:     %s\n", cpu_info);
-		hexchat_printf (ph, " * RAM:     %s\n", memory_info);
-		hexchat_printf (ph, " * VGA:     %s\n", vga_name);
-		hexchat_printf (ph, " * HDD:     %s\n", hdd_info);
-		hexchat_printf (ph, " * Uptime:  %.2f Hours\n", (float) GetTickCount64 () / 1000 / 60 / 60);
-	}
+	output = g_strjoinv (" \002\342\200\242\002 ", strings);
+	hexchat_commandf (ph, "%s %s", announce ? "SAY" : "ECHO", output);
 
-	g_free (memory_info);
+	g_strfreev (strings);
+	g_free (output);
 }
 
-static int get_cpu_arch (void)
+static void
+print_info (char *info, gboolean announce)
 {
-	SYSTEM_INFO si;
-
-	GetNativeSystemInfo (&si);
-
-	if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
-	{
-		return 64;
-	}
-	else
-	{
-		return 86;
-	}
-}
-
-/* http://msdn.microsoft.com/en-us/site/aa390423 */
-static char *query_wmi (QueryWmiType type)
-{
-	GString *result = NULL;
-	HRESULT hr;
-
-	IWbemLocator *locator = NULL;
-	BSTR namespaceName = NULL;
-	BSTR queryLanguageName = NULL;
-	BSTR query = NULL;
-	IWbemServices *namespace = NULL;
-	IUnknown *namespaceUnknown = NULL;
-	IEnumWbemClassObject *enumerator = NULL;
 	int i;
-	gboolean atleast_one_appended = FALSE;
-
-	hr = CoCreateInstance (&CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, &IID_IWbemLocator, (LPVOID *) &locator);
-	if (FAILED (hr))
-	{
-		goto exit;
-	}
-
-	namespaceName = SysAllocString (L"root\\CIMV2");
-
-	hr = locator->lpVtbl->ConnectServer (locator, namespaceName, NULL, NULL, NULL, 0, NULL, NULL, &namespace);
-	if (FAILED (hr))
-	{
-		goto release_locator;
-	}
-
-	hr = namespace->lpVtbl->QueryInterface (namespace, &IID_IUnknown, &namespaceUnknown);
-	if (FAILED (hr))
-	{
-		goto release_namespace;
-	}
-
-	hr = CoSetProxyBlanket (namespaceUnknown, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
-	if (FAILED (hr))
-	{
-		goto release_namespaceUnknown;
-	}
-
-	queryLanguageName = SysAllocString (L"WQL");
-
-	switch (type)
-	{
-	case QUERY_WMI_OS:
-		query = SysAllocString (L"SELECT Caption FROM Win32_OperatingSystem");
-		break;
-	case QUERY_WMI_CPU:
-		query = SysAllocString (L"SELECT Name, MaxClockSpeed FROM Win32_Processor");
-		break;
-	case QUERY_WMI_VGA:
-		query = SysAllocString (L"SELECT Name FROM Win32_VideoController");
-		break;
-	case QUERY_WMI_HDD:
-		query = SysAllocString (L"SELECT Name, Capacity, FreeSpace FROM Win32_Volume");
-		break;
-	default:
-		goto release_queryLanguageName;
-	}
 
-	hr = namespace->lpVtbl->ExecQuery (namespace, queryLanguageName, query, WBEM_FLAG_FORWARD_ONLY, NULL, &enumerator);
-	if (FAILED (hr))
+	for (i = 0; hwinfos[i].name != NULL; i++)
 	{
-		goto release_query;
-	}
-
-	result = g_string_new ("");
-
-	for (i = 0;; i++)
-	{
-		ULONG numReturned = 0;
-		IWbemClassObject *object;
-		char *line;
-
-		hr = enumerator->lpVtbl->Next (enumerator, WBEM_INFINITE, 1, &object, &numReturned);
-		if (FAILED (hr) || numReturned == 0)
-		{
-			break;
-		}
-
-		switch (type)
-		{
-			case QUERY_WMI_OS:
-				line = read_os_name (object);
-				break;
-
-			case QUERY_WMI_CPU:
-				line = read_cpu_info (object);
-				break;
-
-			case QUERY_WMI_VGA:
-				line = read_vga_name (object);
-				break;
-
-			case QUERY_WMI_HDD:
-				line = read_hdd_info (object);
-				break;
-
-			default:
-				break;
-		}
-
-		object->lpVtbl->Release (object);
-
-		if (line != NULL)
+		if (!g_ascii_strcasecmp (info, hwinfos[i].name))
 		{
-			if (atleast_one_appended)
+			char *str = hwinfos[i].callback();
+			if (str)
 			{
-				g_string_append (result, ", ");
+				hexchat_commandf (ph, "%s \002%s\002: %s", announce ? "SAY" : "ECHO",
+									hwinfos[i].title, str);
+				g_free (str);
 			}
-
-			g_string_append (result, line);
-
-			g_free (line);
-
-			atleast_one_appended = TRUE;
+			else
+				hexchat_print (ph, _("Sysinfo: Failed to get info. Either not supported or error."));
+			return;
 		}
 	}
 
-	enumerator->lpVtbl->Release (enumerator);
-
-release_query:
-	SysFreeString (query);
-
-release_queryLanguageName:
-	SysFreeString (queryLanguageName);
-
-release_namespaceUnknown:
-	namespaceUnknown->lpVtbl->Release (namespaceUnknown);
-
-release_namespace:
-	namespace->lpVtbl->Release (namespace);
-
-release_locator:
-	locator->lpVtbl->Release (locator);
-	SysFreeString (namespaceName);
-
-exit:
-	if (result == NULL)
-	{
-		return NULL;
-	}
-
-	return g_string_free (result, FALSE);
+	hexchat_print (ph, _("Sysinfo: No info by that name\n"));
 }
 
-static char *read_os_name (IWbemClassObject *object)
+/*
+ * Simple wrapper for backend specific options.
+ * Ensure dest >= 512.
+ */
+int
+sysinfo_get_str_pref (const char *pref, char *dest)
 {
-	HRESULT hr;
-	VARIANT caption_variant;
-	char *caption_utf8;
-
-	hr = object->lpVtbl->Get (object, L"Caption", 0, &caption_variant, NULL, NULL);
-	if (FAILED (hr))
-	{
-		return NULL;
-	}
-
-	caption_utf8 = bstr_to_utf8 (caption_variant.bstrVal);
-
-	VariantClear(&caption_variant);
-
-	if (caption_utf8 == NULL)
-	{
-		return NULL;
-	}
-
-	g_strchomp (caption_utf8);
-
-	return caption_utf8;
+	return hexchat_pluginpref_get_str (ph, pref, dest);
 }
 
-static char *read_cpu_info (IWbemClassObject *object)
+static gboolean
+sysinfo_get_bool_pref (const char *pref, gboolean def)
 {
-	HRESULT hr;
-	VARIANT name_variant;
-	char *name_utf8;
-	VARIANT max_clock_speed_variant;
-	guint cpu_freq_mhz;
-	char *result;
-
-	hr = object->lpVtbl->Get (object, L"Name", 0, &name_variant, NULL, NULL);
-	if (FAILED (hr))
-	{
-		return NULL;
-	}
-
-	name_utf8 = bstr_to_utf8 (name_variant.bstrVal);
-
-	VariantClear (&name_variant);
+	int value = hexchat_pluginpref_get_int (ph, pref);
 
-	if (name_utf8 == NULL)
-	{
-		return NULL;
-	}
+	if (value != -1)
+		return value;
 
-	hr = object->lpVtbl->Get (object, L"MaxClockSpeed", 0, &max_clock_speed_variant, NULL, NULL);
-	if (FAILED (hr))
-	{
-		g_free (name_utf8);
-
-		return NULL;
-	}
-
-	cpu_freq_mhz = max_clock_speed_variant.uintVal;
-
-	VariantClear (&max_clock_speed_variant);
+	return def;
+}
 
-	if (cpu_freq_mhz > 1000)
+static void
+sysinfo_set_pref_real (const char *pref, char *value, gboolean def)
+{
+	if (value && value[0])
 	{
-		result = g_strdup_printf ("%s (%.2f GHz)", name_utf8, cpu_freq_mhz / 1000.f);
+		guint64 i = g_ascii_strtoull (value, NULL, 0);
+		hexchat_pluginpref_set_int (ph, pref, i != 0);
+		hexchat_printf (ph, _("Sysinfo: %s is set to: %d\n"), pref, i != 0);
 	}
 	else
 	{
-		result = g_strdup_printf ("%s (%" G_GUINT32_FORMAT " MHz)", name_utf8, cpu_freq_mhz);
+		hexchat_printf (ph, _("Sysinfo: %s is set to: %d\n"), pref,
+						sysinfo_get_bool_pref(pref, def));
 	}
-
-	g_free (name_utf8);
-
-	return result;
 }
 
-static char *read_vga_name (IWbemClassObject *object)
+static void
+sysinfo_set_pref (char *key, char *value)
 {
-	HRESULT hr;
-	VARIANT name_variant;
-	char *name_utf8;
-
-	hr = object->lpVtbl->Get (object, L"Name", 0, &name_variant, NULL, NULL);
-	if (FAILED (hr))
-	{
-		return NULL;
-	}
-
-	name_utf8 = bstr_to_utf8 (name_variant.bstrVal);
-
-	VariantClear (&name_variant);
-
-	if (name_utf8 == NULL)
+	if (!key || !key[0])
 	{
-		return NULL;
+		hexchat_print (ph, _("Sysinfo: Valid settings are: announce and hide_* for each piece of information. e.g. hide_os. Without a value it will show current (or default) setting.\n"));
+		return;
 	}
 
-	return name_utf8;
-}
-
-static char *read_hdd_info (IWbemClassObject *object)
-{
-	HRESULT hr;
-	VARIANT name_variant;
-	BSTR name_bstr;
-	gsize name_len;
-	VARIANT capacity_variant;
-	guint64 capacity;
-	VARIANT free_space_variant;
-	guint64 free_space;
-
-	hr = object->lpVtbl->Get (object, L"Name", 0, &name_variant, NULL, NULL);
-	if (FAILED (hr))
+	if (!strcmp (key, "announce"))
 	{
-		return NULL;
+		sysinfo_set_pref_real (key, value, DEFAULT_ANNOUNCE);
+		return;
 	}
-
-	name_bstr = name_variant.bstrVal;
-	name_len = SysStringLen (name_variant.bstrVal);
-
-	if (name_len >= 4 && name_bstr[0] == L'\\' && name_bstr[1] == L'\\' && name_bstr[2] == L'?' && name_bstr[3] == L'\\')
+#ifdef HAVE_LIBPCI
+	else if (!strcmp (key, "pciids"))
 	{
-		// This is not a named volume. Skip it.
-		VariantClear (&name_variant);
-
-		return NULL;
+		if (value && value[0])
+		{
+			hexchat_pluginpref_set_str (ph, "pciids", value);
+			hexchat_printf (ph, _("Sysinfo: pciids is set to: %s\n"), value);
+		}
+		else
+		{
+			char buf[512];
+			if (hexchat_pluginpref_get_str (ph, "pciids", buf) == 0)
+				strcpy (buf, DEFAULT_PCIIDS);
+			hexchat_printf (ph, _("Sysinfo: pciids is set to: %s\n"), buf);
+		}
+		return;
 	}
-
-	VariantClear (&name_variant);
-
-	hr = object->lpVtbl->Get (object, L"Capacity", 0, &capacity_variant, NULL, NULL);
-	if (FAILED (hr))
+#endif
+	else if (g_str_has_prefix (key, "hide_"))
 	{
-		return NULL;
+		int i;
+		for (i = 0; hwinfos[i].name != NULL; i++)
+		{
+			if (!strcmp (key + 5, hwinfos[i].name))
+			{
+				sysinfo_set_pref_real (key, value, hwinfos[i].def);
+				return;
+			}
+		}
 	}
 
-	capacity = variant_to_uint64 (&capacity_variant);
-
-	VariantClear (&capacity_variant);
+	hexchat_print (ph, _("Sysinfo: Invalid variable name\n"));
+}
 
-	if (capacity == 0)
-	{
-		return NULL;
-	}
+static int
+sysinfo_cb (char *word[], char *word_eol[], void *userdata)
+{
+	gboolean announce = sysinfo_get_bool_pref("announce", DEFAULT_ANNOUNCE);
+	int offset = 0, channel_type;
+	char *cmd;
 
-	hr = object->lpVtbl->Get (object, L"FreeSpace", 0, &free_space_variant, NULL, NULL);
-	if (FAILED (hr))
+	/* Allow overriding global announce setting */
+	if (!strcmp ("-e", word[2]))
 	{
-		return NULL;
+		announce = FALSE;
+		offset++;
 	}
-
-	free_space = variant_to_uint64 (&free_space_variant);
-
-	VariantClear (&free_space_variant);
-
-	if (free_space == 0)
+	else if (!strcmp ("-o", word[2]))
 	{
-		return NULL;
+		announce = TRUE;
+		offset++;
 	}
 
-	hdd_capacity += capacity;
-	hdd_free_space += free_space;
+	/* Cannot send to server tab */
+	channel_type = hexchat_list_int (ph, NULL, "type");
+	if (channel_type != 2 /* SESS_CHANNEL */ && channel_type != 3 /* SESS_DIALOG */)
+		announce = FALSE;
+
+	cmd = word[2+offset];
+	if (!g_ascii_strcasecmp ("SET", cmd))
+		sysinfo_set_pref (word[3+offset], word_eol[4+offset]);
+	else if (!cmd || !cmd[0])
+		print_summary (announce);
+	else
+		print_info (cmd, announce);
 
-	return NULL;
+	return HEXCHAT_EAT_ALL;
 }
 
-static char *get_memory_info (void)
+int
+hexchat_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg)
 {
-	MEMORYSTATUSEX meminfo = { 0 };
-	meminfo.dwLength = sizeof (meminfo);
-
-	if (!GlobalMemoryStatusEx (&meminfo))
-	{
-		return NULL;
-	}
+	ph = plugin_handle;
+	*plugin_name = name;
+	*plugin_desc = desc;
+	*plugin_version = version;
 
-	return g_strdup_printf ("%" G_GUINT64_FORMAT " MB Total (%" G_GUINT64_FORMAT " MB Free)", meminfo.ullTotalPhys / 1024 / 1024, meminfo.ullAvailPhys / 1024 / 1024);
-}
+	hexchat_hook_command (ph, "SYSINFO", HEXCHAT_PRI_NORM, sysinfo_cb, sysinfo_help, NULL);
 
-static char *bstr_to_utf8 (BSTR bstr)
-{
-	return g_utf16_to_utf8 (bstr, SysStringLen (bstr), NULL, NULL, NULL);
+	hexchat_command (ph, "MENU ADD \"Window/Send System Info\" \"SYSINFO\"");
+	hexchat_printf (ph, _("%s plugin loaded\n"), name);
+	return 1;
 }
 
-static guint64 variant_to_uint64 (VARIANT *variant)
+int
+hexchat_plugin_deinit (void)
 {
-	switch (V_VT (variant))
-	{
-	case VT_UI8:
-		return variant->ullVal;
-
-	case VT_BSTR:
-		return wcstoull (variant->bstrVal, NULL, 10);
-
-	default:
-		return 0;
-	}
+	hexchat_command (ph, "MENU DEL \"Window/Display System Info\"");
+	hexchat_printf (ph, _("%s plugin unloaded\n"), name);
+	return 1;
 }
diff --git a/plugins/sysinfo/xsys.h b/plugins/sysinfo/sysinfo.h
index 4daf8545..cfde8408 100644
--- a/plugins/sysinfo/xsys.h
+++ b/plugins/sysinfo/sysinfo.h
@@ -1,7 +1,6 @@
 /*
- * xsys.h - X-Sys general parameters header
- * Copyright (C) 2005 Gustavo Zacarias
- * Copyright (C) 2006, 2007 Tony Vroon
+ * SysInfo - sysinfo plugin for HexChat
+ * Copyright (c) 2015 Patrick Griffis.
  *
  * 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
@@ -19,14 +18,12 @@
  */
 
 
-#ifndef _XSYS_H_
-#define _XSYS_H_
+#ifndef SYSINFO_H
+#define SYSINFO_H
 
 #define bsize 1024
-#define delims ":="
+#define DEFAULT_PCIIDS "/usr/share/hwdata/pci.ids"
 
-int sysinfo_get_percent ();
-void sysinfo_get_pciids (char *dest);
-void sysinfo_print_error (const char* msg);
+int sysinfo_get_str_pref (const char *name, char *dest);
 
 #endif
diff --git a/plugins/sysinfo/sysinfo.vcxproj b/plugins/sysinfo/sysinfo.vcxproj
index fe3530e7..3d429295 100644
--- a/plugins/sysinfo/sysinfo.vcxproj
+++ b/plugins/sysinfo/sysinfo.vcxproj
@@ -31,7 +31,7 @@
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

     <ClCompile>

       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;SYSINFO_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>..\..\src\common;$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <AdditionalIncludeDirectories>..\..\src\common;$(DepsRoot)\include;$(Glib);$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

       <TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>

     </ClCompile>

     <Link>

@@ -44,7 +44,7 @@
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

     <ClCompile>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;SYSINFO_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>..\..\src\common;$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <AdditionalIncludeDirectories>..\..\src\common;$(DepsRoot)\include;$(Glib);$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

       <TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>

     </ClCompile>

     <Link>

@@ -58,7 +58,14 @@
     <None Include="sysinfo.def" />

   </ItemGroup>

   <ItemGroup>

+    <ClCompile Include="format.c" />

     <ClCompile Include="sysinfo.c" />

+    <ClCompile Include="win32\backend.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ClInclude Include="format.h" />

+    <ClInclude Include="sysinfo-backend.h" />

+    <ClInclude Include="sysinfo.h" />

   </ItemGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

 </Project>

diff --git a/plugins/sysinfo/sysinfo.vcxproj.filters b/plugins/sysinfo/sysinfo.vcxproj.filters
index 04831e5f..aa173bb5 100644
--- a/plugins/sysinfo/sysinfo.vcxproj.filters
+++ b/plugins/sysinfo/sysinfo.vcxproj.filters
@@ -9,6 +9,9 @@
       <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>

       <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>

     </Filter>

+    <Filter Include="Header Files">

+      <UniqueIdentifier>{c873eb6b-aca6-434d-8ec9-199838b80838}</UniqueIdentifier>

+    </Filter>

   </ItemGroup>

   <ItemGroup>

     <None Include="sysinfo.def">

@@ -19,5 +22,22 @@
     <ClCompile Include="sysinfo.c">

       <Filter>Source Files</Filter>

     </ClCompile>

+    <ClCompile Include="win32\backend.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="format.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+  </ItemGroup>

+  <ItemGroup>

+    <ClInclude Include="sysinfo.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="sysinfo-backend.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="format.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

   </ItemGroup>

 </Project>
\ No newline at end of file
diff --git a/plugins/sysinfo/unix/backend.c b/plugins/sysinfo/unix/backend.c
new file mode 100644
index 00000000..76a6f70f
--- /dev/null
+++ b/plugins/sysinfo/unix/backend.c
@@ -0,0 +1,170 @@
+/*
+ * SysInfo - sysinfo plugin for HexChat
+ * Copyright (c) 2015 Patrick Griffis.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <glib.h>
+#include "parse.h"
+#include "match.h"
+#include "sysinfo.h"
+#include "format.h"
+#include "df.h"
+
+char *sysinfo_backend_get_os(void)
+{
+	char name[bsize];
+
+	if (xs_parse_distro (name) != 0)
+	{
+		return NULL;
+	}
+
+	return g_strdup(name);
+}
+
+char *sysinfo_backend_get_disk(void)
+{
+	gint64 total, free;
+
+	if (xs_parse_df (&total, &free))
+	{
+		return NULL;
+	}
+
+	return sysinfo_format_disk (total, free);
+}
+
+char *sysinfo_backend_get_memory(void)
+{
+	unsigned long long mem_total;
+	unsigned long long mem_free;
+	unsigned long long swap_total;
+	unsigned long long swap_free;
+	char *swap_fmt = NULL, *mem_fmt, *ret;
+
+	if (xs_parse_meminfo (&mem_total, &mem_free, 0) == 1)
+	{
+		return NULL;
+	}
+	if (xs_parse_meminfo (&swap_total, &swap_free, 1) != 1)
+	{
+		swap_fmt = sysinfo_format_memory (swap_total, swap_free);
+	}
+
+	mem_fmt = sysinfo_format_memory (mem_total, mem_free);
+
+	if (swap_fmt)
+	{
+		ret = g_strdup_printf ("Physical: %s Swap: %s", mem_fmt, swap_fmt);
+		g_free (mem_fmt);
+		g_free (swap_fmt);
+	}
+	else
+		ret = mem_fmt;
+
+	return ret;
+}
+
+char *sysinfo_backend_get_cpu(void)
+{
+	char model[bsize];
+	char vendor[bsize];
+	char buffer[bsize];
+	double freq;
+	int giga = 0;
+
+	if (xs_parse_cpu (model, vendor, &freq) != 0)
+	{
+		return NULL;
+	}
+
+	if (freq > 1000)
+	{
+		freq /= 1000;
+		giga = 1;
+	}
+
+	if (giga)
+	{
+		g_snprintf (buffer, bsize, "%s (%.2fGHz)", model, freq);
+	}
+	else
+	{
+		g_snprintf (buffer, bsize, "%s (%.0fMHz)", model, freq);
+	}
+	
+	return g_strdup (buffer);
+}
+
+char *sysinfo_backend_get_gpu(void)
+{
+	char vid_card[bsize];
+	char agp_bridge[bsize];
+	char buffer[bsize];
+	int ret;
+
+	if ((ret = xs_parse_video (vid_card)) != 0)
+	{
+		return NULL;
+	}
+
+	if (xs_parse_agpbridge (agp_bridge) != 0)
+	{
+		g_snprintf (buffer, bsize, "%s", vid_card);
+	}
+	else
+	{
+		g_snprintf (buffer, bsize, "%s @ %s", vid_card, agp_bridge);
+	}
+
+	return g_strdup (buffer);
+}
+
+char *sysinfo_backend_get_sound(void)
+{
+	char sound[bsize];
+
+	if (xs_parse_sound (sound) != 0)
+	{
+		return NULL;
+	}
+	return g_strdup (sound);
+}
+
+char *sysinfo_backend_get_uptime(void)
+{
+	guint64 uptime;
+
+	if ((uptime = xs_parse_uptime ()) == 0)
+	{
+		return NULL;
+	}
+
+	return sysinfo_format_uptime (uptime);
+}
+
+char *sysinfo_backend_get_network(void)
+{
+	char ethernet_card[bsize];
+
+	if (xs_parse_ether (ethernet_card))
+	{
+		g_strlcpy (ethernet_card, "None found", bsize);
+	}
+	
+	return g_strdup (ethernet_card);
+}
diff --git a/plugins/sysinfo/unix/match.c b/plugins/sysinfo/unix/match.c
new file mode 100644
index 00000000..2ef51f3f
--- /dev/null
+++ b/plugins/sysinfo/unix/match.c
@@ -0,0 +1,98 @@
+/*
+ * match.c - matching functions for X-Sys
+ * Copyright (C) 2005, 2006, 2007 Tony Vroon
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include "sysinfo.h"
+
+#define delims ":="
+
+void find_match_char(char *buffer, char *match, char *result)
+{
+	char *position;
+	g_strchug(buffer);
+	if(strstr(buffer, match) == strstr(buffer, buffer))
+	{
+		position = strpbrk(buffer, delims);
+		if (position != NULL)
+		{
+			position += 1;
+			strcpy(result, position);
+			position = strstr(result, "\n");
+			*(position) = '\0';
+			g_strchug(result);
+		}
+		else
+			strcpy(result, "\0");
+	}
+}
+
+void find_match_double(char *buffer, char *match, double *result)
+{
+	char *position;
+	g_strchug(buffer);
+	if(strstr(buffer, match) == strstr(buffer, buffer))
+	{
+		position = strpbrk(buffer, delims);
+		if (position != NULL)
+		{
+        	position += 1;
+        	*result = strtod(position, NULL);
+		}
+		else
+			*result = 0;
+	}
+}
+
+void find_match_double_hex(char *buffer, char *match, double *result)
+{
+	char *position;
+	g_strchug(buffer);
+	if(strstr(buffer, match) == strstr(buffer, buffer))
+	{
+		position = strpbrk(buffer, delims);
+		if (position != NULL)
+		{
+			memcpy(position,"0x",2);
+			*result = strtod(position,NULL);
+		}
+		else
+			*result = 0;
+	}
+}
+
+void find_match_ll(char *buffer, char *match, unsigned long long *result)
+{
+	char *position;
+	g_strchug(buffer);
+	if(strstr(buffer, match) == strstr(buffer, buffer))
+	{
+		position = strpbrk(buffer, delims);
+		if (position != NULL)
+		{
+			position += 1;
+			*result = strtoll(position, NULL, 10);
+		}
+		else
+			*result = 0;
+	}
+}
+
diff --git a/plugins/sysinfo/match.h b/plugins/sysinfo/unix/match.h
index 61811e4a..16999fa2 100644
--- a/plugins/sysinfo/match.h
+++ b/plugins/sysinfo/unix/match.h
@@ -23,13 +23,7 @@
 void find_match_char(char *buffer, char *match, char *result);
 void find_match_double(char *buffer, char *match, double *result);
 void find_match_double_hex(char *buffer, char *match, double *result);
-void find_match_int(char *buffer, char *match, unsigned int *result);
 void find_match_ll(char *buffer, char *match, unsigned long long *result);
-void format_output(const char *arg, char *string, char *format);
-void flat_format_output(const char *arg, char *string, char *format);
-float percentage(unsigned long long *free, unsigned long long *total);
-char *pretty_freespace(const char *desc, unsigned long long *free_k, unsigned long long *total_k);
 void remove_leading_whitespace(char *buffer);
-char *decruft_filename(char *buffer);
 
 #endif
diff --git a/plugins/sysinfo/parse.c b/plugins/sysinfo/unix/parse.c
index 3b210022..9f03533d 100644
--- a/plugins/sysinfo/parse.c
+++ b/plugins/sysinfo/unix/parse.c
@@ -23,20 +23,19 @@
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
-#include <sys/utsname.h>
-#include <unistd.h>
-#include <time.h>
-#include <dirent.h>
-#include <sys/types.h>
 #include <pci/header.h>
 #include <glib.h>
 
+#ifdef __sparc__
+#include <dirent.h>
+#endif
+
 #include "pci.h"
 #include "match.h"
-#include "xsys.h"
 #include "parse.h"
+#include "sysinfo.h"
 
-int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned int *count)
+int xs_parse_cpu(char *model, char *vendor, double *freq)
 {
 #if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || defined(__alpha__) || defined(__ia64__) || defined(__parisc__) || defined(__sparc__)
 	char buffer[bsize];
@@ -47,9 +46,6 @@ int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned
 	FILE *fp = fopen("/proc/cpuinfo", "r");
 	if(fp == NULL)
 		return 1;
-
-	*count = 0;
-	strcpy(cache,"unknown\0");
 	
 	#if defined(__i386__) || defined(__x86_64__)
 	while(fgets(buffer, bsize, fp) != NULL)
@@ -57,10 +53,7 @@ int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned
 		find_match_char(buffer, "model name", model);
 		find_match_char(buffer, "vendor_id", vendor);
 		find_match_double(buffer, "cpu MHz", freq);
-		find_match_char(buffer, "cache size", cache);
-		find_match_int(buffer, "processor", count);
 	}
-	*count = *count + 1;
 	#endif
 	#ifdef __powerpc__
 	while(fgets(buffer, bsize, fp) != NULL)
@@ -68,10 +61,7 @@ int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned
 		find_match_char(buffer, "cpu", model);
 		find_match_char(buffer, "machine", vendor);
 		find_match_double(buffer, "clock", freq);
-		find_match_char(buffer, "L2 cache", cache);
-		find_match_int(buffer, "processor", count);
 	}
-	*count = *count + 1;
 	pos = strstr(model, ",");
 	if (pos != NULL) *pos = '\0';
 	#endif
@@ -81,8 +71,6 @@ int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned
 		find_match_char(buffer, "cpu model", model);
 		find_match_char(buffer, "system type", vendor);
 		find_match_double(buffer, "cycle frequency [Hz]", freq);
-		find_match_char(buffer, "L2 cache", cache);
-		find_match_int(buffer, "cpus detected", count);
 	}
 	*freq = *freq / 1000000;
 	#endif
@@ -92,20 +80,15 @@ int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned
 		find_match_char(buffer, "model", model);
 		find_match_char(buffer, "vendor", vendor);
 		find_match_double(buffer, "cpu MHz", freq);
-		find_match_int(buffer, "processor", count);
 	}
-	*count = *count + 1;
 	#endif
 	#ifdef __parisc__
 	while(fgets(buffer, bsize, fp) != NULL)
 	{
 		find_match_char(buffer, "cpu  ", model);
 		find_match_char(buffer, "cpu family", vendor);
-		find_match_char(buffer, "D-cache", cache);
 		find_match_double(buffer, "cpu MHz", freq);
-		find_match_int(buffer, "processor", count);
 	}
-	*count = *count + 1;
 	#endif
 	#ifdef __sparc__
 	DIR *dir;
@@ -115,22 +98,8 @@ int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned
 	{
 		find_match_char(buffer, "cpu	", model);
 		find_match_char(buffer, "type	", vendor);
-		find_match_int(buffer, "ncpus active", count);
 		find_match_double_hex(buffer, "Cpu0ClkTck", freq);
 	}
-	/* Cache is tricky, only implemented for sparc64 */
-	if ((dir = opendir("/proc/openprom")) != NULL)
-		while ((entry = readdir(dir)) != NULL)
-			if (strncmp(entry->d_name,"SUNW,UltraSPARC",15) == 0)
-			{
-				g_snprintf(buffer,bsize,"/proc/openprom/%s/ecache-size",entry->d_name);
-				fp2 = fopen(buffer, "r");
-				if (fp2 == NULL) break;
-				fscanf(fp2,"%16s",cache);
-				fclose(fp2);
-				sprintf(buffer,"0x%s",cache);
-				sprintf(cache,"%0.0f KB",strtod(buffer,NULL)/1024);
-			}
 	*freq = *freq / 1000000;
 	#endif
 	fclose(fp);
@@ -138,43 +107,20 @@ int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned
 	return 0;
 }
 
-int xs_parse_uptime(int *weeks, int *days, int *hours, int *minutes, int *seconds)
+guint64 xs_parse_uptime(void)
 {
 	char buffer[bsize];
-	long long uptime = 0;
+	guint64 uptime = 0;
 	FILE *fp = fopen("/proc/uptime", "r");
 	if(fp == NULL)
-		return 1;
+		return 0;
 
 	if(fgets(buffer, bsize, fp) != NULL)
 		uptime = strtol(buffer, NULL, 0);
 	
-	*seconds = uptime%60;
-	*minutes = (uptime/60)%60;
-	*hours   = (uptime/3600)%24;
-	*days    = (uptime/86400)%7;
-	*weeks   = uptime/604800;
-	
 	fclose(fp);
 	
-	return 0;
-}
-
-int xs_parse_os(char *user, char *host, char *kernel)
-{
-	struct utsname osinfo;
-	char hostn[bsize], *usern = getenv("USER");
-	
-	if(uname(&osinfo)<0)
-		return 1;	
-	if(gethostname(hostn, bsize)<0)
-		return 1;
-	
-	strncpy(user, usern, bsize);
-	strcpy(host, hostn);
-	g_snprintf(kernel, bsize, "%s %s %s", osinfo.sysname, osinfo.release, osinfo.machine);
-	
-	return 0;
+	return uptime;
 }
 
 int xs_parse_sound(char *snd_card)
@@ -183,12 +129,13 @@ int xs_parse_sound(char *snd_card)
 	u16 class = PCI_CLASS_MULTIMEDIA_AUDIO;
 
 	FILE *fp = NULL;
-	if((fp = fopen("/proc/asound/cards", "r"))== NULL) {
+	if((fp = fopen("/proc/asound/cards", "r"))== NULL)
+	{
 		if (pci_find_by_class(&class, vendor, device) == 0) 
-			{
-				pci_find_fullname(snd_card, vendor, device);
-				return 0;
-			}
+		{
+			pci_find_fullname(snd_card, vendor, device);
+			return 0;
+		}
 		else
 			return 1;
 	}
@@ -251,129 +198,42 @@ int xs_parse_agpbridge(char *agp_bridge)
 	return 0;
 }
 
-int xs_parse_netdev(const char *device, unsigned long long *bytes_recv, unsigned long long *bytes_sent)
-{
-	FILE *fp;
-	char buffer[bsize], *pos;
-	int i;
-	
-	fp=fopen("/proc/net/dev", "r");
-	if(fp==NULL)
-		return 1;
-	
-	while(fgets(buffer, bsize, fp) != NULL)
-	{
-		for(i=0; isspace(buffer[i]); i++);
-		if(strncmp(device, &buffer[i], strlen(device)) == 0) break;
-	}
-	fclose(fp);
-	pos = strstr(buffer, ":");
-	pos++;
-	*bytes_recv = g_ascii_strtoull (pos, &pos, 0);
-
-	for(i=0;i<7;i++) g_ascii_strtoull (pos, &pos, 0);
-	
-	*bytes_sent = g_ascii_strtoull (pos, NULL, 0);
-
-	return 0;
-}
-
-int xs_parse_df(const char *mount_point, char *result)
-{
-	FILE *pipe;
-	char buffer[bsize], *pos;
-	unsigned long long total_k=0, free_k=0;
-	int i=0;
-	
-	pipe = popen("df -k -l -P", "r");
-	if(pipe==NULL)
-		return 1;
-	
-	while(fgets(buffer, bsize, pipe) != NULL)
-	{
-		/* Skip over pseudo-filesystems and description line */
-		if(isalpha(buffer[0]))
-			continue;
-		
-		for(pos=buffer; !isspace(*pos); pos++);
-		for(;isspace(*pos);pos++);
-		if(mount_point == NULL)
-		{
-			total_k += g_ascii_strtoull (pos, &pos, 0);
-			g_ascii_strtoull(pos, &pos, 0);
-			free_k += g_ascii_strtoull (pos, &pos, 0);
-			continue;
-		}
-		total_k = g_ascii_strtoull (pos, &pos, 0);
-		g_ascii_strtoull(pos, &pos, 0);
-		free_k = g_ascii_strtoull (pos, &pos, 0);
-		g_ascii_strtoull (pos, &pos, 0);
-		for(;isspace(*pos);pos++);
-		for(;*pos!='/';pos++);
-		for(i=0;*(buffer+i)!='\n';i++);
-		*(buffer+i)='\0';
-		
-		if(strncasecmp(mount_point, "ALL", 3)==0)
-		{
-			char *tmp_buf = pretty_freespace(pos, &free_k, &total_k);
-			strcat(tmp_buf, " | ");
-			strcat(result, tmp_buf);
-			g_free(tmp_buf);
-		}
-		else if(strncmp(mount_point, pos, strlen(mount_point)) == 0)
-		{
-			char *tmp_buf = pretty_freespace(mount_point, &free_k, &total_k);
-			strncpy(result, tmp_buf, bsize);
-			g_free(tmp_buf);
-			break;
-		}
-		else g_snprintf(result, bsize, "Mount point %s not found!", mount_point);
-	}
-	
-	if(mount_point != NULL && strncasecmp(mount_point, "ALL", 3)==0)
-		*(result+strlen(result)-3) = '\0';
-	
-	if(mount_point == NULL)
-	{
-		char *tmp_buf = pretty_freespace("Total", &free_k, &total_k);
-		strncpy(result, tmp_buf, bsize);
-		g_free(tmp_buf);
-	}
-	pclose(pipe);
-	return 0;
-}
-
 int xs_parse_meminfo(unsigned long long *mem_tot, unsigned long long *mem_free, int swap)
 {
 	FILE *fp;
-        char buffer[bsize];
+	char buffer[bsize];
 	unsigned long long freemem = 0, buffers = 0, cache = 0;
-        *mem_tot = 0;
-        *mem_free = 0;
+	*mem_tot = 0;
+	*mem_free = 0;
 
-        if((fp = fopen("/proc/meminfo", "r")) == NULL)
-                return 1;
+	if((fp = fopen("/proc/meminfo", "r")) == NULL)
+		return 1;
 
-        while(fgets(buffer, bsize, fp) != NULL)
-        {
-                if(!swap)
-                {
+	while(fgets(buffer, bsize, fp) != NULL)
+	{
+		if(!swap)
+		{
 			find_match_ll(buffer, "MemTotal:", mem_tot);
 			find_match_ll(buffer, "MemFree:", &freemem);
 			find_match_ll(buffer, "Buffers:", &buffers);
 			find_match_ll(buffer, "Cached:", &cache);
-                }
-                else
-                {
+		}
+		else
+		{
 			find_match_ll(buffer, "SwapTotal:", mem_tot);
 			find_match_ll(buffer, "SwapFree:", mem_free);
-                }
-        }
-	if (!swap) {
+		}
+	}
+	if (!swap)
+	{
 		*mem_free = freemem + buffers + cache;
 	}
-        fclose(fp);
-        return 0;
+	fclose(fp);
+
+	/* Convert to bytes */
+	*mem_free *= 1000;
+	*mem_tot *= 1000;
+	return 0;
 }
 
 int xs_parse_distro(char *name)
@@ -429,10 +289,12 @@ int xs_parse_distro(char *name)
 	}
 	else
 		g_snprintf(buffer, bsize, "Unknown Distro");
-	if(fp != NULL) fclose(fp);
+	if(fp != NULL)
+		fclose(fp);
 	
 	pos=strchr(buffer, '\n');
-	if(pos != NULL) *pos = '\0';
+	if(pos != NULL)
+		*pos = '\0';
 	strcpy(name, buffer);
 	return 0;
 }
diff --git a/plugins/sysinfo/parse.h b/plugins/sysinfo/unix/parse.h
index 600793de..89f1299c 100644
--- a/plugins/sysinfo/parse.h
+++ b/plugins/sysinfo/unix/parse.h
@@ -23,12 +23,9 @@
 #ifndef _PARSE_H_
 #define _PARSE_H_
 
-int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned int *count);
-int xs_parse_uptime(int *weeks, int *days, int *hours, int *minutes, int *seconds);
-int xs_parse_os(char *user, char *host, char *kernel);
+int xs_parse_cpu(char *model, char *vendor, double *freq);
+guint64 xs_parse_uptime(void);
 int xs_parse_sound(char *snd_card);
-int xs_parse_netdev(const char *device, unsigned long long *bytes_recv, unsigned long long *bytes_sent);
-int xs_parse_df(const char *mount_point, char *string);
 int xs_parse_meminfo(unsigned long long *mem_tot, unsigned long long *mem_free, int swap);
 int xs_parse_video(char *vid_card);
 int xs_parse_agpbridge(char *agp_bridge);
diff --git a/plugins/sysinfo/pci.c b/plugins/sysinfo/unix/pci.c
index bda4888b..71b085fe 100644
--- a/plugins/sysinfo/pci.c
+++ b/plugins/sysinfo/unix/pci.c
@@ -23,64 +23,67 @@
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
-#include <unistd.h>
 #include <pci/pci.h>
 #include <glib.h>
 
-#include "xsys.h"
+#include "sysinfo.h"
 
 static struct pci_filter filter;       /* Device filter */
 static struct pci_access *pacc;
 int bus, dev, func; /* Location of the card */
 
 struct device {
-  	struct device *next;
-  	struct pci_dev *dev;
-  	unsigned int config_cnt;
-  	u8 config[256];
+	struct device *next;
+	struct pci_dev *dev;
+	unsigned int config_cnt;
+	u8 config[256];
 };
 
 static struct device *first_dev;
 
 static struct device *scan_device(struct pci_dev *p)
 {
-  	int how_much = 64;
-  	struct device *d;
-
-  	if (!pci_filter_match(&filter, p))
-    		return NULL;
-  	d = g_new0 (struct device, 1);
-  	d->dev = p;
-  	if (!pci_read_block(p, 0, d->config, how_much))
-    		exit(1);
-  	if (how_much < 128 && (d->config[PCI_HEADER_TYPE] & 0x7f) == PCI_HEADER_TYPE_CARDBUS) {
-      		/* For cardbus bridges, we need to fetch 64 bytes more to get the full standard header... */
-      		if (!pci_read_block(p, 64, d->config+64, 64))
-        		exit(1);
-      		how_much = 128;
-    	}
-  	d->config_cnt = how_much;
-  	pci_setup_cache(p, d->config, d->config_cnt);
-  	pci_fill_info(p, PCI_FILL_IDENT);
-  	return d;
+	int how_much = 64;
+	struct device *d;
+
+	if (!pci_filter_match(&filter, p))
+		return NULL;
+	d = g_new0 (struct device, 1);
+	d->dev = p;
+	if (!pci_read_block(p, 0, d->config, how_much))
+		exit(1);
+	if (how_much < 128 && (d->config[PCI_HEADER_TYPE] & 0x7f) == PCI_HEADER_TYPE_CARDBUS)
+	{
+		/* For cardbus bridges, we need to fetch 64 bytes more to get the full standard header... */
+		if (!pci_read_block(p, 64, d->config+64, 64))
+			exit(1);
+		how_much = 128;
+	}
+	d->config_cnt = how_much;
+	pci_setup_cache(p, d->config, d->config_cnt);
+	pci_fill_info(p, PCI_FILL_IDENT);
+	return d;
 }
 
 static void scan_devices(void)
 {
-  	struct device *d;
-  	struct pci_dev *p;
-
-  	pci_scan_bus(pacc);
-  	for(p=pacc->devices; p; p=p->next)
-    	if ((d = scan_device(p))) {
-        	d->next = first_dev;
-        	first_dev = d;
-      	}
+	struct device *d;
+	struct pci_dev *p;
+
+	pci_scan_bus(pacc);
+	for(p=pacc->devices; p; p=p->next)
+	{
+		if ((d = scan_device(p)))
+		{
+			d->next = first_dev;
+			first_dev = d;
+		}
+	}
 }
 
 static u16 get_conf_word(struct device *d, unsigned int pos)
 {
-  	return d->config[pos] | (d->config[pos+1] << 8);
+	  return d->config[pos] | (d->config[pos+1] << 8);
 }
 
 int pci_find_by_class(u16 *class, char *vendor, char *device)
@@ -94,19 +97,21 @@ int pci_find_by_class(u16 *class, char *vendor, char *device)
 	pci_init(pacc);
 	scan_devices();
 
-	for(d=first_dev; d; d=d->next) {
-    		p = d->dev;
-    		/* Acquire vendor & device ID if the class matches */
-    		if(get_conf_word(d, PCI_CLASS_DEVICE) == *class) {
-      			nomatch = 0;
+	for(d=first_dev; d; d=d->next)
+	{
+		p = d->dev;
+		/* Acquire vendor & device ID if the class matches */
+		if(get_conf_word(d, PCI_CLASS_DEVICE) == *class)
+		{
+			nomatch = 0;
 			g_snprintf(vendor,7,"%04x",p->vendor_id);
 			g_snprintf(device,7,"%04x",p->device_id);
-      			break;
-    		}
-  	}
+			break;
+		}
+	  }
 
-  	pci_cleanup(pacc);
-  	return nomatch;
+	  pci_cleanup(pacc);
+	  return nomatch;
 }
 
 void pci_find_fullname(char *fullname, char *vendor, char *device)
@@ -117,38 +122,44 @@ void pci_find_fullname(char *fullname, char *vendor, char *device)
 	char *position;
 	int cardfound = 0;
 	FILE *fp;
+	
+	if (!sysinfo_get_str_pref ("pciids", buffer))
+		strcpy (buffer, DEFAULT_PCIIDS);
 
-	sysinfo_get_pciids (buffer);
 	fp = fopen (buffer, "r");
-
-	if(fp == NULL) {
+	if(fp == NULL)
+	{
 		g_snprintf(fullname, bsize, "%s:%s", vendor, device);
-		sysinfo_print_error ("pci.ids file not found! You might want to adjust your pciids setting with /SYSINFO SET pciids (you can query its current value with /SYSINFO LIST).\n");
+		//sysinfo_print_error ("pci.ids file not found! You might want to adjust your pciids setting with /SYSINFO SET pciids (you can query its current value with /SYSINFO LIST).\n");
 		return;
 	}
 
-	while(fgets(buffer, bsize, fp) != NULL)	{
-		if (!isspace(buffer[0]) && strstr(buffer, vendor) != NULL) {
-                       	position = strstr(buffer, vendor);
-                       	position += 6;
-                       	strncpy(vendorname, position, bsize/2);
-                       	position = strstr(vendorname, "\n");
-                       	*(position) = '\0';
+	while(fgets(buffer, bsize, fp) != NULL)
+	{
+		if (!isspace(buffer[0]) && strstr(buffer, vendor) != NULL)
+		{
+			position = strstr(buffer, vendor);
+			position += 6;
+			strncpy(vendorname, position, bsize/2);
+			position = strstr(vendorname, "\n");
+			*(position) = '\0';
 			break;
-                }
+		}
 	}
-	while(fgets(buffer, bsize, fp) != NULL) {
-		if(strstr(buffer, device) != NULL) {
-                        position = strstr(buffer, device);
-                        position += 6;
-                        strncpy(devicename, position, bsize/2);
+	while(fgets(buffer, bsize, fp) != NULL)
+	{
+		if(strstr(buffer, device) != NULL)
+		{
+			position = strstr(buffer, device);
+			position += 6;
+			strncpy(devicename, position, bsize/2);
 			position = strstr(devicename, " (");
 			if (position == NULL)
-                        	position = strstr(devicename, "\n");
-                        *(position) = '\0';
+				position = strstr(devicename, "\n");
+			*(position) = '\0';
 			cardfound = 1;
 			break;
- 		}
+		 }
 	}
 	if (cardfound == 1)
 		g_snprintf(fullname, bsize, "%s %s", vendorname, devicename);
diff --git a/plugins/sysinfo/pci.h b/plugins/sysinfo/unix/pci.h
index 673f0a0a..673f0a0a 100644
--- a/plugins/sysinfo/pci.h
+++ b/plugins/sysinfo/unix/pci.h
diff --git a/plugins/sysinfo/win32/backend.c b/plugins/sysinfo/win32/backend.c
new file mode 100644
index 00000000..26779961
--- /dev/null
+++ b/plugins/sysinfo/win32/backend.c
@@ -0,0 +1,493 @@
+/* HexChat
+ * Copyright (c) 2011-2012 Berke Viktor.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <windows.h>
+#include <wbemidl.h>
+
+#include <glib.h>
+
+#include "../format.h"
+
+/* Cache the info for subsequent invocations of /SYSINFO */
+static int cpu_arch = 0;
+static char *os_name = NULL;
+static char *cpu_info = NULL;
+static char *vga_name = NULL;
+
+static int command_callback (char *word[], char *word_eol[], void *user_data);
+
+typedef enum
+{
+	QUERY_WMI_OS,
+	QUERY_WMI_CPU,
+	QUERY_WMI_VGA,
+	QUERY_WMI_HDD,
+} QueryWmiType;
+
+void print_info (void);
+int get_cpu_arch (void);
+char *query_wmi (QueryWmiType mode);
+char *read_os_name (IWbemClassObject *object);
+char *read_cpu_info (IWbemClassObject *object);
+char *read_vga_name (IWbemClassObject *object);
+
+guint64 hdd_capacity;
+guint64 hdd_free_space;
+char *read_hdd_info (IWbemClassObject *object);
+
+char *get_memory_info (void);
+char *bstr_to_utf8 (BSTR bstr);
+guint64 variant_to_uint64 (VARIANT *variant);
+
+char *
+sysinfo_backend_get_sound (void)
+{
+	return NULL;
+}
+
+char *
+sysinfo_backend_get_network (void)
+{
+	return NULL;
+}
+
+char *
+sysinfo_backend_get_uptime (void)
+{
+	return sysinfo_format_uptime (GetTickCount64 () / 1000);
+}
+
+char *
+sysinfo_backend_get_disk (void)
+{
+	char *hdd_info;
+
+	/* HDD information is always loaded dynamically since it includes the current amount of free space */
+	hdd_capacity = 0;
+	hdd_free_space = 0;
+	hdd_info = query_wmi (QUERY_WMI_HDD);
+	if (hdd_info)
+		return sysinfo_format_disk (hdd_capacity, hdd_free_space);
+
+	return NULL;
+}
+
+char *
+sysinfo_backend_get_cpu (void)
+{
+	if (cpu_info == NULL)
+		cpu_info = query_wmi (QUERY_WMI_CPU);
+
+	return g_strdup (cpu_info);
+}
+
+char *
+sysinfo_backend_get_memory (void)
+{
+	/* Memory information is always loaded dynamically since it includes the current amount of free memory */
+	return get_memory_info ();
+}
+
+char *
+sysinfo_backend_get_gpu (void)
+{
+	if (vga_name == NULL)
+		vga_name = query_wmi (QUERY_WMI_VGA);
+
+	return g_strdup (vga_name);
+}
+
+char *
+sysinfo_backend_get_os (void)
+{
+	if (os_name == NULL)
+		os_name = query_wmi (QUERY_WMI_OS);
+
+	if (cpu_arch == 0)
+		cpu_arch = get_cpu_arch ();
+
+	return g_strdup_printf ("%s (x%d)", os_name, cpu_arch);
+}
+
+static int get_cpu_arch (void)
+{
+	SYSTEM_INFO si;
+
+	GetNativeSystemInfo (&si);
+
+	if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
+	{
+		return 64;
+	}
+	else
+	{
+		return 86;
+	}
+}
+
+/* http://msdn.microsoft.com/en-us/site/aa390423 */
+static char *query_wmi (QueryWmiType type)
+{
+	GString *result = NULL;
+	HRESULT hr;
+
+	IWbemLocator *locator = NULL;
+	BSTR namespaceName = NULL;
+	BSTR queryLanguageName = NULL;
+	BSTR query = NULL;
+	IWbemServices *namespace = NULL;
+	IUnknown *namespaceUnknown = NULL;
+	IEnumWbemClassObject *enumerator = NULL;
+	int i;
+	gboolean atleast_one_appended = FALSE;
+
+	hr = CoCreateInstance (&CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, &IID_IWbemLocator, (LPVOID *) &locator);
+	if (FAILED (hr))
+	{
+		goto exit;
+	}
+
+	namespaceName = SysAllocString (L"root\\CIMV2");
+
+	hr = locator->lpVtbl->ConnectServer (locator, namespaceName, NULL, NULL, NULL, 0, NULL, NULL, &namespace);
+	if (FAILED (hr))
+	{
+		goto release_locator;
+	}
+
+	hr = namespace->lpVtbl->QueryInterface (namespace, &IID_IUnknown, &namespaceUnknown);
+	if (FAILED (hr))
+	{
+		goto release_namespace;
+	}
+
+	hr = CoSetProxyBlanket (namespaceUnknown, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
+	if (FAILED (hr))
+	{
+		goto release_namespaceUnknown;
+	}
+
+	queryLanguageName = SysAllocString (L"WQL");
+
+	switch (type)
+	{
+	case QUERY_WMI_OS:
+		query = SysAllocString (L"SELECT Caption FROM Win32_OperatingSystem");
+		break;
+	case QUERY_WMI_CPU:
+		query = SysAllocString (L"SELECT Name, MaxClockSpeed FROM Win32_Processor");
+		break;
+	case QUERY_WMI_VGA:
+		query = SysAllocString (L"SELECT Name FROM Win32_VideoController");
+		break;
+	case QUERY_WMI_HDD:
+		query = SysAllocString (L"SELECT Name, Capacity, FreeSpace FROM Win32_Volume");
+		break;
+	default:
+		goto release_queryLanguageName;
+	}
+
+	hr = namespace->lpVtbl->ExecQuery (namespace, queryLanguageName, query, WBEM_FLAG_FORWARD_ONLY, NULL, &enumerator);
+	if (FAILED (hr))
+	{
+		goto release_query;
+	}
+
+	result = g_string_new ("");
+
+	for (i = 0;; i++)
+	{
+		ULONG numReturned = 0;
+		IWbemClassObject *object;
+		char *line;
+
+		hr = enumerator->lpVtbl->Next (enumerator, WBEM_INFINITE, 1, &object, &numReturned);
+		if (FAILED (hr) || numReturned == 0)
+		{
+			break;
+		}
+
+		switch (type)
+		{
+			case QUERY_WMI_OS:
+				line = read_os_name (object);
+				break;
+
+			case QUERY_WMI_CPU:
+				line = read_cpu_info (object);
+				break;
+
+			case QUERY_WMI_VGA:
+				line = read_vga_name (object);
+				break;
+
+			case QUERY_WMI_HDD:
+				line = read_hdd_info (object);
+				break;
+
+			default:
+				break;
+		}
+
+		object->lpVtbl->Release (object);
+
+		if (line != NULL)
+		{
+			if (atleast_one_appended)
+			{
+				g_string_append (result, ", ");
+			}
+
+			g_string_append (result, line);
+
+			g_free (line);
+
+			atleast_one_appended = TRUE;
+		}
+	}
+
+	enumerator->lpVtbl->Release (enumerator);
+
+release_query:
+	SysFreeString (query);
+
+release_queryLanguageName:
+	SysFreeString (queryLanguageName);
+
+release_namespaceUnknown:
+	namespaceUnknown->lpVtbl->Release (namespaceUnknown);
+
+release_namespace:
+	namespace->lpVtbl->Release (namespace);
+
+release_locator:
+	locator->lpVtbl->Release (locator);
+	SysFreeString (namespaceName);
+
+exit:
+	if (result == NULL)
+	{
+		return NULL;
+	}
+
+	return g_string_free (result, FALSE);
+}
+
+static char *read_os_name (IWbemClassObject *object)
+{
+	HRESULT hr;
+	VARIANT caption_variant;
+	char *caption_utf8;
+
+	hr = object->lpVtbl->Get (object, L"Caption", 0, &caption_variant, NULL, NULL);
+	if (FAILED (hr))
+	{
+		return NULL;
+	}
+
+	caption_utf8 = bstr_to_utf8 (caption_variant.bstrVal);
+
+	VariantClear(&caption_variant);
+
+	if (caption_utf8 == NULL)
+	{
+		return NULL;
+	}
+
+	g_strchomp (caption_utf8);
+
+	return caption_utf8;
+}
+
+static char *read_cpu_info (IWbemClassObject *object)
+{
+	HRESULT hr;
+	VARIANT name_variant;
+	char *name_utf8;
+	VARIANT max_clock_speed_variant;
+	guint cpu_freq_mhz;
+	char *result;
+
+	hr = object->lpVtbl->Get (object, L"Name", 0, &name_variant, NULL, NULL);
+	if (FAILED (hr))
+	{
+		return NULL;
+	}
+
+	name_utf8 = bstr_to_utf8 (name_variant.bstrVal);
+
+	VariantClear (&name_variant);
+
+	if (name_utf8 == NULL)
+	{
+		return NULL;
+	}
+
+	hr = object->lpVtbl->Get (object, L"MaxClockSpeed", 0, &max_clock_speed_variant, NULL, NULL);
+	if (FAILED (hr))
+	{
+		g_free (name_utf8);
+
+		return NULL;
+	}
+
+	cpu_freq_mhz = max_clock_speed_variant.uintVal;
+
+	VariantClear (&max_clock_speed_variant);
+
+	if (cpu_freq_mhz > 1000)
+	{
+		result = g_strdup_printf ("%s (%.2fGHz)", name_utf8, cpu_freq_mhz / 1000.f);
+	}
+	else
+	{
+		result = g_strdup_printf ("%s (%" G_GUINT32_FORMAT "MHz)", name_utf8, cpu_freq_mhz);
+	}
+
+	g_free (name_utf8);
+
+	return result;
+}
+
+static char *read_vga_name (IWbemClassObject *object)
+{
+	HRESULT hr;
+	VARIANT name_variant;
+	char *name_utf8;
+
+	hr = object->lpVtbl->Get (object, L"Name", 0, &name_variant, NULL, NULL);
+	if (FAILED (hr))
+	{
+		return NULL;
+	}
+
+	name_utf8 = bstr_to_utf8 (name_variant.bstrVal);
+
+	VariantClear (&name_variant);
+
+	if (name_utf8 == NULL)
+	{
+		return NULL;
+	}
+
+	return name_utf8;
+}
+
+static char *read_hdd_info (IWbemClassObject *object)
+{
+	HRESULT hr;
+	VARIANT name_variant;
+	BSTR name_bstr;
+	gsize name_len;
+	VARIANT capacity_variant;
+	guint64 capacity;
+	VARIANT free_space_variant;
+	guint64 free_space;
+
+	hr = object->lpVtbl->Get (object, L"Name", 0, &name_variant, NULL, NULL);
+	if (FAILED (hr))
+	{
+		return NULL;
+	}
+
+	name_bstr = name_variant.bstrVal;
+	name_len = SysStringLen (name_variant.bstrVal);
+
+	if (name_len >= 4 && name_bstr[0] == L'\\' && name_bstr[1] == L'\\' && name_bstr[2] == L'?' && name_bstr[3] == L'\\')
+	{
+		// This is not a named volume. Skip it.
+		VariantClear (&name_variant);
+
+		return NULL;
+	}
+
+	VariantClear (&name_variant);
+
+	hr = object->lpVtbl->Get (object, L"Capacity", 0, &capacity_variant, NULL, NULL);
+	if (FAILED (hr))
+	{
+		return NULL;
+	}
+
+	capacity = variant_to_uint64 (&capacity_variant);
+
+	VariantClear (&capacity_variant);
+
+	if (capacity == 0)
+	{
+		return NULL;
+	}
+
+	hr = object->lpVtbl->Get (object, L"FreeSpace", 0, &free_space_variant, NULL, NULL);
+	if (FAILED (hr))
+	{
+		return NULL;
+	}
+
+	free_space = variant_to_uint64 (&free_space_variant);
+
+	VariantClear (&free_space_variant);
+
+	if (free_space == 0)
+	{
+		return NULL;
+	}
+
+	hdd_capacity += capacity;
+	hdd_free_space += free_space;
+
+	return NULL;
+}
+
+static char *get_memory_info (void)
+{
+	MEMORYSTATUSEX meminfo = { 0 };
+	meminfo.dwLength = sizeof (meminfo);
+
+	if (!GlobalMemoryStatusEx (&meminfo))
+	{
+		return NULL;
+	}
+
+	return sysinfo_format_memory (meminfo.ullTotalPhys, meminfo.ullAvailPhys);
+}
+
+static char *bstr_to_utf8 (BSTR bstr)
+{
+	return g_utf16_to_utf8 (bstr, SysStringLen (bstr), NULL, NULL, NULL);
+}
+
+static guint64 variant_to_uint64 (VARIANT *variant)
+{
+	switch (V_VT (variant))
+	{
+	case VT_UI8:
+		return variant->ullVal;
+
+	case VT_BSTR:
+		return wcstoull (variant->bstrVal, NULL, 10);
+
+	default:
+		return 0;
+	}
+}
diff --git a/plugins/sysinfo/xsys-changelog b/plugins/sysinfo/xsys-changelog
deleted file mode 100644
index 9ea20727..00000000
--- a/plugins/sysinfo/xsys-changelog
+++ /dev/null
@@ -1,116 +0,0 @@
-v2.2.0
-	* (Thomas Cort) Report L2 cache info for Alpha CPUs
-	* (Tony Vroon) Drop XMMS, port audacious features to D-Bus, make dependency mandatory
-	* (Tony Vroon) Use pretty_freespace for memory & swap reporting as well as disk space
-	* (Tony Vroon) Make pretty_freespace report none if total_size is 0, thanks to Emopig <andrew@nelless.net> for the report
-	* (Tony Vroon) Make pretty_freespace aware of terabytes, petabytes, exabytes, zettabytes & yottabytes
-	* (Tony Vroon) Remove xchatdirfs workaround
-
-v2.1.0
-	Removals & pending removal:
-	* (Tony Vroon) Remove support for BMP, it is an abandoned project. Suggested upgrade path: audacious
-	* (Tony Vroon) Remove /uname & /euname; the OS part of sysinfo displays similar info without requiring a process pipe
-	* (Tony Vroon) Added a note that the xchatdirfs workaround is due for removal as X-Chat Gnome has fixed the bug
-
-	Bugfixes:
-	* (Tony Vroon) Actually show the vendor that we retrieve in cpuinfo
-	* (Tony Vroon) Display Gentoo Linux as stable or ~arch, the baselayout version doesn't really interest anyone
-	* (Tony Vroon) Match framework: Make remove_leading_whitespace actually work
-	* (Tony Vroon) Match framework: Do not assume that a delimiter is always followed by a space
-
-	Code improvements:
-	* (Tony Vroon) PCI framework: We were requesting more info then we actually return to the caller
-	* (Tony Vroon) Match framework: Consolidate delimiters in a single define & use 1 strpbrk instead of 2 strstr's
-	* (Tony Vroon) Display the machine string instead of the pmac-generation as vendor info for PPC machines
-
-	New features
-	* (Tony Vroon) Show memory capacity in gigabytes instead of in megabytes when appropriate
-	* (Tony Vroon) Cut cpu name at comma (so overly long other info such as "altivec supported" is no longer displayed)
-	* (Tony Vroon) Now Playing: Report time played as well as the song length
-	* (Tony Vroon) Now Playing: Support reporting as an action; configurable at runtime
-	* (Tony Vroon) Check LSB release data, prefer above all others; based on a code sample submitted by Thomas Winwood
-
-v2.0.9
-	* (Tony Vroon) Protect the matching framework against spurious matches (bug reported by Harm Geerts)
-	* (Tony Vroon) Unexporting unnecessary symbols for PCI framework
-	* (Tony Vroon) Deal with incompatible header changes in pciutils
-	* (Tony Vroon) Begin implementing hardware monitoring support, not yet activated
-	* (Tony Vroon) Add support for Audacious, a BMP fork
-
-v2.0.8
-	* (Tony Vroon) Make XMMS interface actually work, thanks to a patch from Morten Cools
-	* (Tony Vroon) Use percentages for df information as well
-	* (Gustavo Zacarias) Add support for Sparc architecture, cache size detection on sparc64 only
-	* (Gustavo Zacarias) Consolidate buffer sizes into a single define
-
-v2.0.7
-	* (Tony Vroon) Have df parser ignore pseudo-filesystems; deal with other locales more gracefully
-	* (Tony Vroon) Change default formatstring not to use mIRC color codes
-	* (Tony Vroon) Add fallback to ~/.xchat2 for xchat-gnome which does not report xchatdirfs properly
-	* (Tony Vroon) Revert to beepctrl.h style calls as infopipe is too unreliable
-
-v2.0.6
-	* (Tony Vroon) Rewrote PCI framework, no longer depends on sysfs, kernel 2.4 and lower will work now
-	* (Tony Vroon) Made percentages configurable, can be set at runtime (feature request by Halcy0n)
-	* (Tony Vroon) Abstract out all pointer voodoo from xsys.c
-	* (Tony Vroon) Do not return XCHAT_EAT_NONE, causes spurious "unknown command" errors
-	* (Tony Vroon) Deal more gracefully with a missing soundcard or unknown linux distribution
-	* (Tony Vroon) Add error handling to the matching framework
-
-v2.0.5
-	* (Tony Vroon) Added support for parisc/hppa & ia64 architectures
-	* (Tony Vroon) Proper report of L2 cache as "unknown" instead of showing bits of unitialized memory
-	* (Tony Vroon) Upped PCI parser yield for ppc64 architecture, has high bus number for AGP card
-	* (Tony Vroon) Use percentages in memory/swap information
-
-v2.0.4
-	* (Tony Vroon) /sound uses ALSA if possible, PCI now fallback (false positives reported with PCI code)
-	* (Tony Vroon) Remove 0 prefix from first ALSA card; 1: and up will be shown for extra cards
-	* (Tony Vroon) Matching code rewritten and separated out from other code
-	* (Tony Vroon) Use new matching framework where possible
-	* (Tony Vroon) Added support for Alpha architecture, thanks to Bert (bert@ev6.net)
-
-v2.0.3
-	* (Tony Vroon) Fix buttons, XMMS -> NP
-	* (Tony Vroon) PCI functions separated out from other code; fully rewritten
-	* (Tony Vroon) Use new PCI framework for sound detection; ALSA is now fallback
-	* (Tony Vroon) Implement /ether
-	* (Tony Vroon) /video now reports video card @ AGP bridge; resolution info dropped
-
-v2.0.2
-	* (Tony Vroon) XMMS/BMP: Delete XMMS/BMP detection; it just got obsoleted by a BMP bugfix
-	* (Tony Vroon) XMMS/BMP: Change to /np & /enp as commands (np -> now playing)
-	* (Tony Vroon) Allow customization of now_playing with /playing
-	* (Tony Vroon) Separate out the length field for now_playing
-	* (Tony Vroon) Better configuration file handling
-	* (Tony Vroon) Set homepage to http://dev.gentoo.org/~chainsaw/xsys
-	* (Tony Vroon) Make channel buttons optional, not everyone appreciates them
-	* (Tony Vroon) Fix cpuinfo parsing on x86_64, a necessary define was missing
-
-v2.0.1
-	* (Tony Vroon) XMMS/BMP: Report "stream" if song length is -1
-	* (Tony Vroon) XMMS/BMP: Determine whether XMMS or BMP is playing
-	* (Tony Vroon) Better errorhandling if pci.ids parsing fails; at least mention raw PCI ID of card
-	* (Tony Vroon) Remove AGP from video card messages; we detect plain PCI cards too
-	* (Tony Vroon) Fix Debian release detector
-
-v2.0.0
-	* (mikeshoup)  Clean up of code for 2.0.0 release
-	* (Tony Vroon) Added PowerPC /proc/cpuinfo support
-	* (Tony Vroon) Changed LSPCI to SYSFS
-
-v1.9.3
-	* (mikeshoup) Introduced distro function
-	* (mikeshoup, Tony Vroon's suggestion) Removed bitrate from /XMMS
-
-v1.9.2
-	* 2005/01/14 (mikeshoup) Put in the userlist buttons
-	* 2005/01/10 (mikeshoup) Added XMMS/BMP Support
-
-v1.9.1
-	* 2004/12/20 (mikeshoup) Added a dynamic formatting scheme
-	* 2004/12/19 (mikeshoup) Changed some commands
-	* 2004/12/18 (mikeshoup) Reintroducted /VIDEO
-
-v1.9.0
-	* 2004/12/17 (mikeshoup) Initial Release
diff --git a/plugins/sysinfo/xsys-install b/plugins/sysinfo/xsys-install
deleted file mode 100644
index 8f148569..00000000
--- a/plugins/sysinfo/xsys-install
+++ /dev/null
@@ -1,15 +0,0 @@
-INSTALLATION
-============
-Installation is straightforward. You need Audacious 1.4 or higher and D-Bus.
-Open up the Makefile, check to make sure PCIIDS points to your pci.ids file.
-	(Symptom if you get it wrong: raw PCI ID's (XXXX:XXXX) emitted by /VIDEO and friends).
-
-Run: make
-Run: make install
-
-Voila!
-
-NOTES:
-`make install' copies the compiled library (something like xsys-v.v.v.so) to
-$HOME/.xchat2/xsys-plugin.so for autoloading. If $HOME/.xchat2/xsys-plugin.so
-exists, it is removed first.
diff --git a/plugins/sysinfo/xsys-makefile b/plugins/sysinfo/xsys-makefile
deleted file mode 100644
index 8b51a53d..00000000
--- a/plugins/sysinfo/xsys-makefile
+++ /dev/null
@@ -1,38 +0,0 @@
-#### SET THIS VALUE TO THE LOCATION OF THE `pci.ids` file ####
-PCIIDS = /usr/share/misc/pci.ids
-
-#### UNCOMMENT THIS IF YOU WANT THE BUTTONS ####
-#BUTTON = -Dbuttonbar
-
-#### SHOULD NOT NEED TO EDIT BELOW THIS LINE ####
-VER_MAJOR = 2
-VER_MINOR = 2
-VER_PATCH = 0
-CC = gcc
-CFLAGS += -O2 -Wall -fPIC
-CFLAGS += -DVER_MINOR=$(VER_MINOR) -DVER_MAJOR=$(VER_MAJOR) -DVER_PATCH=$(VER_PATCH) \
-          -DVER_STRING=\"$(VER_MAJOR).$(VER_MINOR).$(VER_PATCH)\" -DPCIIDS=\"$(PCIIDS)\" $(BUTTON)
-LDFLAGS = $(CFLAGS) -shared
-LIBRARY = xsys-$(VER_MAJOR).$(VER_MINOR).$(VER_PATCH).so
-OBJECTS = xsys.o parse.o pci.o match.o hwmon.o
-
-ALL : $(LIBRARY)
-
-$(LIBRARY) : $(OBJECTS)
-	$(CC) $(LDFLAGS) -o $(LIBRARY) $(OBJECTS) -lpci
-
-xsys.o : xsys.c
-parse.o : parse.c
-pci.o : pci.c
-match.o : match.c
-hwmon.o : hwmon.c
-
-.PHONY : clean
-clean :
-	rm -rf *.o *.so *~
-
-.PHONY : install
-install : $(LIBRARY)
-	rm -f $(HOME)/.xchat2/xsys-plugin.so
-	cp ./$(LIBRARY) $(HOME)/.xchat2/xsys-plugin.so
-
diff --git a/plugins/sysinfo/xsys-readme b/plugins/sysinfo/xsys-readme
deleted file mode 100644
index 6226e725..00000000
--- a/plugins/sysinfo/xsys-readme
+++ /dev/null
@@ -1,105 +0,0 @@
-X-Sys README
-============
-What is X-Sys?
-
-X-Sys is a plugin for X-Chat that allows you to display your current system statistics in
-a channel, private conversation or just in an echo to yourself for testing purposes.
-It is supported on Linux, running on various architectures. Right now x86, ppc, ppc64, sparc,
-sparc64 and alpha are supported, with parisc and ia64 implemented but awaiting testing.
-
----------------
-Who wrote this?
-
-X-Sys is originally a Mike Shoup creation, from the very first alpha releases to the open-source
-version 1 releases. But then, things stalled. For a few months (more like a year almost)
-Mike didn't work on X-Sys. The last version that had been written was 1.0.5.
-The website was gone, and I (Tony) couldn't find Mike. So, I took over and improved it to my liking. 
-It turned out that Mike was still around, though, he contacted me and started development again,
-now called version 2, a complete rewrite. Various 1.9 betas came out that I contributed patches to,
-and starting with version 2.0.0 I'm maintaining xchat-xsys again, this time with Mike's blessing.
-
----------------
-What do I need?
-
-- X-Chat (regular or Gnome version)
-- Audacious 1.4 or higher
-- D-Bus (for communication with Audacious)
-- a working toolchain (compiler, binutils, etc).
-
-------------------------------------------------
-What if I get errors about u8 not being defined?
-
-Sorry to hear that, it appears your linux distribution neglected to install essential headers on your 
-system. On Debian & Ubuntu, apt-get install pciutils-dev should make it happy.
-
-========
-COMMANDS
-
-X-Sys 2 has the following implemented commands:
-/XSYS & /EXSYS - Output current version, either to channel or echoed on screen.
-/CPUINFO & /ECPUINFO - Echoes or says current cpu statistics
-/SYSUPTIME & /ESYSUPTIME - Echoes or says current uptime
-/OSINFO & /EOSINFO - Echoes or says various OS statistics
-/SOUND & /ESOUND - Echoes or says the current sound card, as determined by ALSA
-/NETDATA & /ENETDATA - Echoes or says total amount transferred through a network
-	interface. Use like: `/netdata eth0' (where eth0 is a network interface)
-/NETSTREAM & /ENETSTREAM - Echoes or says amount of bandwidth being used.
-	Use like: `/netstream eth0' (where eth0 is a network interface)
-/DISKINFO & /EDISKINFO - Echoes or says free space on partitions. The DISK command has a
-	few arguments as follows:
-	ALL - Displays every partitions
-	/mount - Displays free space for that specific mount point
-	No arguments just displays total free space
-/MEMINFO & /EMEMINFO - Echoes or says memory information.
-/VIDEO & /EVIDEO - Echoes or says the current video card on the PCI bus
-/ETHER & /EETHER - Echoes or says the current network card on the PCI bus
-/DISTRO & /EDISTRO - Echoes or says which distro you're running
-	If this doesn't work for your distro, look for a *-release file or similar in /etc
-	E-mail this to chainsaw@gentoo.org
-
-and the big one:
-/SYSINFO & /ESYSINFO - Complete system information!
-
-Two output control commands:
-/XSYS2FORMAT , No arguments, it will print just the current formatting string.
-   It will take any arguments to it as the formatting string.
-   The formatting string can consist of any letter/numbers, and is used to format
-   the output. The following special symbols can be used:
-   
-   %B      : Bold
-   %Cnn    : Foreground Color, where nn is a number corresponding to a mIRC color
-   %Cnn,nn : Foreground,Background Color
-   %R      : Reverse Foreground/Background Colors
-   %O      : Reset Color and Format (thats an 'oh' not a 'zero (0)')
-   %C      : Reset Color
-   %U      : Underline 
-
-/PLAYING will either print or allow you to set the text for /np.
-The default is now_playing, but you can set this to whatever text you prefer.
-
-/PERCENTAGES will allow you to set whether to use percentages in plugin output or not.
-Percentages are enabled  by default. Use a zero value to disable, and a non-zero value
-to enable. If unsure, use 1.
-
-/NP & /ENP - Reports what's currently playing in Audacious.
-
-====
-BUGS
-(none known)
-
-E-mail me your bug reports at chainsaw@gentoo.org
-Please include the following information:
-- what architecture you are using (amd64, ia64, parisc, ppc, ppc64, sparc, sparc64 or x86)
-- what linux distribution you are using (Gentoo 2007.1, Fedora Core 8, etc)
-- what compiler you have used to compile X-Sys, i.e. gcc (GCC) 4.1.2 (Gentoo 4.1.2)
-- what version of X-Sys you are using
-
-=======
-Thanks!
-Remember, everything here is:
-(C) 2003, 2004, 2005 by Michael Shoup
-(C) 2005, 2006, 2007 by Tony Vroon
-All Rights Reserved.
-Visit http://dev.gentoo.org/~chainsaw/xsys/ for release information.
-
-Feel free to e-mail me for feature requests, or see if I'm online on irc.freenode.net
diff --git a/plugins/sysinfo/xsys.c b/plugins/sysinfo/xsys.c
deleted file mode 100644
index be38b379..00000000
--- a/plugins/sysinfo/xsys.c
+++ /dev/null
@@ -1,927 +0,0 @@
-/*
- * SysInfo - sysinfo plugin for HexChat
- * Copyright (c) 2012 Berke Viktor.
- *
- * xsys.c - main functions for X-Sys 2
- * by mikeshoup
- * Copyright (C) 2003, 2004, 2005 Michael Shoup
- * Copyright (C) 2005, 2006, 2007 Tony Vroon
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-
-#include "hexchat-plugin.h"
-#include "parse.h"
-#include "match.h"
-#include "xsys.h"
-
-#define DEFAULT_FORMAT "%B%1:%B %2 **"
-#define DEFAULT_PERCENT 1
-#define DEFAULT_ANNOUNCE 1
-#define DEFAULT_PCIIDS "/usr/share/hwdata/pci.ids"
-
-static hexchat_plugin *ph;	/* plugin handle */
-static int error_printed = 0;	/* semaphore, make sure not to print the same error more than once during one execution */
-
-static char name[] = "SysInfo";
-static char desc[] = "Display info about your hardware and OS";
-static char version[] = "3.0";
-static char sysinfo_help[] = "SysInfo Usage:\n  /SYSINFO [-e|-o] [OS|DISTRO|CPU|RAM|DISK|VGA|SOUND|ETHERNET|UPTIME], print various details about your system or print a summary without arguments\n  /SYSINFO LIST, print current settings\n  /SYSINFO SET <variable>, update given setting\n  /SYSINFO RESET, reset settings to defaults\n  /NETDATA <iface>, show transmitted data on given interface\n  /NETSTREAM <iface>, show current bandwidth on given interface\n";
-
-void
-sysinfo_get_pciids (char* dest)
-{
-	hexchat_pluginpref_get_str (ph, "pciids", dest);
-}
-
-int
-sysinfo_get_percent ()
-{
-	return hexchat_pluginpref_get_int (ph, "percent");
-}
-
-int
-sysinfo_get_announce ()
-{
-	return hexchat_pluginpref_get_int (ph, "announce");
-}
-
-void
-sysinfo_print_error (const char* msg)
-{
-	if (!error_printed)
-	{
-		hexchat_printf (ph, "%s\t%s", name, msg);
-	}
-	error_printed++;
-	
-}
-
-static int
-print_summary (int announce, char* format)
-{
-	char sysinfo[bsize];
-	char buffer[bsize];
-	char cpu_model[bsize];
-	char cpu_cache[bsize];
-	char cpu_vendor[bsize];
-	char os_host[bsize];
-	char os_user[bsize];
-	char os_kernel[bsize];
-	char *free_space;
-	unsigned long long mem_total;
-	unsigned long long mem_free;
-	unsigned int count;
-	double cpu_freq;
-	int giga = 0;
-	int weeks;
-	int days;
-	int hours;
-	int minutes;
-	int seconds;
-	sysinfo[0] = '\0';
-
-	g_snprintf (buffer, bsize, "%s", hexchat_get_info (ph, "version"));
-	format_output ("HexChat", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (sysinfo));
-
-	/* BEGIN OS PARSING */
-	if (xs_parse_os (os_user, os_host, os_kernel) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_os()", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	g_snprintf (buffer, bsize, "%s", os_kernel);
-	format_output ("OS", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (sysinfo));
-
-	/* BEGIN DISTRO PARSING */
-        if (xs_parse_distro (buffer) != 0)
-        {
-		strncpy (buffer, "Unknown", bsize);
-	}
-
-	format_output ("Distro", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (sysinfo));	
-
-	/* BEGIN CPU PARSING */
-	if (xs_parse_cpu (cpu_model, cpu_vendor, &cpu_freq, cpu_cache, &count) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_cpu()", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	if (cpu_freq > 1000)
-	{
-		cpu_freq /= 1000;
-		giga = 1;
-	}
-
-	if (giga)
-	{
-		g_snprintf (buffer, bsize, "%u x %s (%s) @ %.2fGHz", count, cpu_model, cpu_vendor, cpu_freq);
-	}
-	else
-	{
-		g_snprintf (buffer, bsize, "%u x %s (%s) @ %.0fMHz", count, cpu_model, cpu_vendor, cpu_freq);
-	}
-
-	format_output ("CPU", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (sysinfo));
-
-	/* BEGIN MEMORY PARSING */
-	if (xs_parse_meminfo (&mem_total, &mem_free, 0) == 1)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_meminfo!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	free_space = pretty_freespace ("Physical", &mem_free, &mem_total);
-	g_snprintf (buffer, bsize, "%s", free_space);
-	g_free (free_space);
-	format_output ("RAM", buffer, format);	
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (sysinfo));
-
-	/* BEGIN DISK PARSING */
-	if (xs_parse_df (NULL, buffer))
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_df", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	format_output ("Disk", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (buffer));
-
-	/* BEGIN VIDEO PARSING */
-	if (xs_parse_video (buffer))
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_video", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	format_output ("VGA", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (buffer));
-
-	/* BEGIN SOUND PARSING */
-	if (xs_parse_sound (buffer))
-	{
-		strncpy (buffer, "Not present", bsize);
-	}
-
-	format_output ("Sound", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (buffer));
-
-	/* BEGIN ETHERNET PARSING */
-	if (xs_parse_ether (buffer))
-	{
-		strncpy (buffer, "None found", bsize);
-	}
-
-	format_output ("Ethernet", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (buffer));
-
-	/* BEGIN UPTIME PARSING */
-	if (xs_parse_uptime (&weeks, &days, &hours, &minutes, &seconds))
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_uptime()", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	if (minutes != 0 || hours != 0 || days != 0 || weeks != 0)
-	{
-		if (hours != 0 || days != 0 || weeks != 0)
-		{
-			if (days  !=0 || weeks != 0)
-			{
-				if (weeks != 0)
-				{
-					g_snprintf (buffer, bsize, "%dw %dd %dh %dm %ds", weeks, days, hours, minutes, seconds);
-				}
-				else
-				{
-					g_snprintf (buffer, bsize, "%dd %dh %dm %ds", days, hours, minutes, seconds);
-				}
-			}
-			else
-			{
-				g_snprintf (buffer, bsize, "%dh %dm %ds", hours, minutes, seconds);
-			}
-		}
-		else
-		{
-			g_snprintf (buffer, bsize, "%dm %ds", minutes, seconds);
-		}
-	}
-
-        format_output ("Uptime", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (buffer));
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", sysinfo);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", sysinfo);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_os (int announce, char* format)
-{
-	char buffer[bsize];
-	char user[bsize];
-	char host[bsize];
-	char kernel[bsize];
-
-	if (xs_parse_os (user, host, kernel) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_os()", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	g_snprintf (buffer, bsize, "%s@%s, %s", user, host, kernel);
-	format_output ("OS", buffer, format);
-	
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", buffer);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", buffer);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_distro (int announce, char* format)
-{
-	char name[bsize];
-
-	if (xs_parse_distro (name) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_distro()!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	format_output("Distro", name, format);
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", name);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", name);
-	}
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_cpu (int announce, char* format)
-{
-	char model[bsize];
-	char vendor[bsize];
-	char cache[bsize];
-	char buffer[bsize];
-	unsigned int count;
-	double freq;
-	int giga = 0;
-
-	if (xs_parse_cpu (model, vendor, &freq, cache, &count) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_cpu()", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	if (freq > 1000)
-	{
-		freq /= 1000;
-		giga = 1;
-	}
-
-	if (giga)
-	{
-		g_snprintf (buffer, bsize, "%u x %s (%s) @ %.2fGHz w/ %s L2 Cache", count, model, vendor, freq, cache);
-	}
-	else
-	{
-		g_snprintf (buffer, bsize, "%u x %s (%s) @ %.0fMHz w/ %s L2 Cache", count, model, vendor, freq, cache);
-	}
-
-	format_output ("CPU", buffer, format);
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", buffer);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", buffer);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_ram (int announce, char* format)
-{
-	unsigned long long mem_total;
-	unsigned long long mem_free;
-	unsigned long long swap_total;
-	unsigned long long swap_free;
-	char string[bsize];
-
-	if (xs_parse_meminfo (&mem_total, &mem_free, 0) == 1)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_meminfo!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-	if (xs_parse_meminfo (&swap_total, &swap_free, 1) == 1)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_meminfo!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	g_snprintf (string, bsize, "%s - %s", pretty_freespace ("Physical", &mem_free, &mem_total), pretty_freespace ("Swap", &swap_free, &swap_total));
-	format_output ("RAM", string, format);
-	
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", string);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", string);
-	}
-	
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_disk (int announce, char* format)
-{
-	char string[bsize] = {0,};
-
-#if 0
-	if (*word == '\0')
-	{
-		if (xs_parse_df (NULL, string))
-		{
-			hexchat_printf (ph, "ERROR in parse_df");
-			return HEXCHAT_EAT_ALL;
-		}
-	}
-	else
-	{
-		if (xs_parse_df (*word, string))
-		{
-			hexchat_printf (ph, "ERROR in parse_df");
-			return HEXCHAT_EAT_ALL;
-		}
-	}
-#endif
-
-	if (xs_parse_df (NULL, string))
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_df", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	format_output ("Disk", string, format);
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", string);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", string);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_vga (int announce, char* format)
-{
-	char vid_card[bsize];
-	char agp_bridge[bsize];
-	char buffer[bsize];
-	int ret;
-
-	if ((ret = xs_parse_video (vid_card)) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_video! %d", name, ret);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	if (xs_parse_agpbridge (agp_bridge) != 0)
-	{
-		g_snprintf (buffer, bsize, "%s", vid_card);
-	}
-	else
-	{
-		g_snprintf (buffer, bsize, "%s @ %s", vid_card, agp_bridge);
-	}
-
-	format_output ("VGA", buffer, format);
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", buffer);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", buffer);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_sound (int announce, char* format)
-{
-	char sound[bsize];
-
-	if (xs_parse_sound (sound) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_asound()!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	format_output ("Sound", sound, format);
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", sound);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", sound);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-
-static int
-print_ethernet (int announce, char* format)
-{
-	char ethernet_card[bsize];
-
-	if (xs_parse_ether (ethernet_card))
-	{
-		strncpy (ethernet_card, "None found", bsize);
-	}
-
-	format_output ("Ethernet", ethernet_card, format);
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", ethernet_card);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", ethernet_card);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_uptime (int announce, char* format)
-{
-	char buffer[bsize];
-	int weeks;
-	int days;
-	int hours;
-	int minutes;
-	int seconds;
-
-	if (xs_parse_uptime (&weeks, &days, &hours, &minutes, &seconds))
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_uptime()", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	if (minutes != 0 || hours != 0 || days != 0 || weeks != 0)
-	{
-		if (hours != 0 || days != 0 || weeks != 0)
-		{
-			if (days  !=0 || weeks != 0)
-			{
-				if (weeks != 0)
-				{
-					g_snprintf (buffer, bsize, "%dw %dd %dh %dm %ds", weeks, days, hours, minutes, seconds);
-				}
-				else
-				{
-					g_snprintf (buffer, bsize, "%dd %dh %dm %ds", days, hours, minutes, seconds);
-				}
-			}
-			else
-			{
-				g_snprintf (buffer, bsize, "%dh %dm %ds", hours, minutes, seconds);
-			}
-		}
-		else
-		{
-			g_snprintf (buffer, bsize, "%dm %ds", minutes, seconds);
-		}
-	}
-
-	format_output ("Uptime", buffer, format);
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", buffer);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", buffer);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-netdata_cb (char *word[], char *word_eol[], void *userdata)
-{
-	char netdata[bsize];
-	char format[bsize];
-	unsigned long long bytes_recv;
-	unsigned long long bytes_sent;
-	
-	if (*word[2] == '\0')
-	{
-		hexchat_printf (ph, "%s\tYou must specify a network device (e.g. /NETDATA eth0)!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	if (xs_parse_netdev (word[2], &bytes_recv, &bytes_sent) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_netdev", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	bytes_recv /= 1024;
-	bytes_sent /= 1024;
-	
-	g_snprintf (netdata, bsize, "%s: %.1f MB Received, %.1f MB Sent", word[2], (double)bytes_recv/1024.0, (double)bytes_sent/1024.0);
-	hexchat_pluginpref_get_str (ph, "format", format);
-	format_output ("Netdata", netdata, format);
-
-	if (hexchat_list_int (ph, NULL, "type") >= 2)
-	{
-		hexchat_commandf (ph, "SAY %s", netdata);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", netdata);
-	}
-	
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-netstream_cb (char *word[], char *word_eol[], void *userdata)
-{
-	char netstream[bsize];
-	char mag_r[5];
-	char mag_s[5];
-	char format[bsize];
-	unsigned long long bytes_recv;
-	unsigned long long bytes_sent;
-	unsigned long long bytes_recv_p;
-	unsigned long long bytes_sent_p;
-
-	struct timespec ts = {1, 0};
-
-	if (*word[2] == '\0')
-	{
-		hexchat_printf (ph, "%s\tYou must specify a network device (e.g. /NETSTREAM eth0)!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	if (xs_parse_netdev(word[2], &bytes_recv, &bytes_sent) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_netdev", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	while (nanosleep (&ts, &ts) < 0);
-
-	if (xs_parse_netdev(word[2], &bytes_recv_p, &bytes_sent_p) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_netdev", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	bytes_recv = (bytes_recv_p - bytes_recv);
-	bytes_sent = (bytes_sent_p - bytes_sent);
-
-	if (bytes_recv > 1024)
-	{
-		bytes_recv /= 1024;
-		g_snprintf (mag_r, 5, "KB/s");
-	}
-	else
-	{
-		g_snprintf (mag_r, 5, "B/s");
-	}
-
-	if (bytes_sent > 1024)
-	{
-		bytes_sent /= 1024;
-		g_snprintf (mag_s, 5, "KB/s");
-	}
-	else
-	{
-		g_snprintf (mag_s, 5, "B/s");
-	}
-
-	g_snprintf (netstream, bsize, "%s: Receiving %llu %s, Sending %llu %s", word[2], bytes_recv, mag_r, bytes_sent, mag_s);
-	hexchat_pluginpref_get_str (ph, "format", format);
-	format_output ("Netstream", netstream, format);
-
-	if (hexchat_list_int (ph, NULL, "type") >= 2)
-	{
-		hexchat_commandf (ph, "SAY %s", netstream);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", netstream);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static void
-list_settings ()
-{
-	char list[512];
-	char buffer[512];
-	char* token;
-
-	hexchat_pluginpref_list (ph, list);
-	hexchat_printf (ph, "%s\tCurrent Settings:", name);
-	token = strtok (list, ",");
-
-	while (token != NULL)
-	{
-		hexchat_pluginpref_get_str (ph, token, buffer);
-		hexchat_printf (ph, "%s\t%s: %s\n", name, token, buffer);
-		token = strtok (NULL, ",");
-	}
-}
-
-static void
-reset_settings ()
-{
-	hexchat_pluginpref_set_str (ph, "pciids", DEFAULT_PCIIDS);
-	hexchat_pluginpref_set_str (ph, "format", DEFAULT_FORMAT);
-	hexchat_pluginpref_set_int (ph, "percent", DEFAULT_PERCENT);
-	hexchat_pluginpref_set_int (ph, "announce", DEFAULT_ANNOUNCE);
-}
-
-static int
-sysinfo_cb (char *word[], char *word_eol[], void *userdata)
-{
-	error_printed = 0;
-	int announce = sysinfo_get_announce ();
-	int offset = 0;
-	int buffer;
-	char format[bsize];
-
-	if (!hexchat_pluginpref_get_str (ph, "format", format))
-	{
-		hexchat_printf (ph, "%s\tError reading config file!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	/* Cannot send to server tab */
-	if (hexchat_list_int (ph, NULL, "type") == 1)
-	{
-		announce = 0;
-	}
-
-	/* Allow overriding global announce setting */
-	if (!strcmp ("-e", word[2]))
-	{
-		announce = 0;
-		offset++;
-	}
-	else if (!strcmp ("-o", word[2]))
-	{
-		announce = 1;
-		offset++;
-	}
-
-	if (!g_ascii_strcasecmp ("HELP", word[2+offset]))
-	{
-		hexchat_printf (ph, "%s", sysinfo_help);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("LIST", word[2+offset]))
-	{
-		list_settings ();
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("SET", word[2+offset]))
-	{
-		if (!g_ascii_strcasecmp ("", word_eol[4+offset]))
-		{
-			hexchat_printf (ph, "%s\tEnter a value!\n", name);
-			return HEXCHAT_EAT_ALL;
-		}
-		if (!g_ascii_strcasecmp ("format", word[3+offset]))
-		{
-			hexchat_pluginpref_set_str (ph, "format", word_eol[4+offset]);
-			hexchat_printf (ph, "%s\tformat is set to: %s\n", name, word_eol[4+offset]);
-		}
-		else if (!g_ascii_strcasecmp ("percent", word[3+offset]))
-		{
-			buffer = atoi (word[4+offset]);	/* don't use word_eol, numbers must not contain spaces */
-
-			if (buffer > 0 && buffer < INT_MAX)
-			{
-				hexchat_pluginpref_set_int (ph, "percent", buffer);
-				hexchat_printf (ph, "%s\tpercent is set to: %d\n", name, buffer);
-			}
-			else
-			{
-				hexchat_printf (ph, "%s\tInvalid input!\n", name);
-			}
-		}
-		else if (!g_ascii_strcasecmp ("announce", word[3+offset]))
-		{
-			buffer = atoi (word[4+offset]);	/* don't use word_eol, numbers must not contain spaces */
-
-			if (buffer > 0)
-			{
-				hexchat_pluginpref_set_int (ph, "announce", 1);
-				hexchat_printf (ph, "%s\tannounce is set to: On\n", name);
-			}
-			else
-			{
-				hexchat_pluginpref_set_int (ph, "announce", 0);
-				hexchat_printf (ph, "%s\tannounce is set to: Off\n", name);
-			}
-		}
-		else if (!g_ascii_strcasecmp ("pciids", word[3+offset]))
-		{
-			hexchat_pluginpref_set_str (ph, "pciids", word_eol[4+offset]);
-			hexchat_printf (ph, "%s\tpciids is set to: %s\n", name, word_eol[4+offset]);
-		}
-		else
-		{
-			hexchat_printf (ph, "%s\tInvalid variable name! Use 'pciids', 'format' or 'percent'!\n", name);
-			return HEXCHAT_EAT_ALL;
-		}
-
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("RESET", word[2+offset]))
-	{
-		reset_settings ();
-		hexchat_printf (ph, "%s\tSettings have been restored to defaults.\n", name);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("OS", word[2+offset]))
-	{
-		print_os (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("DISTRO", word[2+offset]))
-	{
-		print_distro (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("CPU", word[2+offset]))
-	{
-		print_cpu (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("RAM", word[2+offset]))
-	{
-		print_ram (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("DISK", word[2+offset]))
-	{
-		print_disk (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("VGA", word[2+offset]))
-	{
-		print_vga (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("SOUND", word[2+offset]))
-	{
-		print_sound (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("ETHERNET", word[2+offset]))
-	{
-		print_ethernet (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("UPTIME", word[2+offset]))
-	{
-		print_uptime (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("", word[2+offset]))
-	{
-		print_summary (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", sysinfo_help);
-		return HEXCHAT_EAT_ALL;
-	}
-}
-
-int
-hexchat_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg)
-{
-	char buffer[bsize];
-	ph = plugin_handle;
-	*plugin_name    = name;
-	*plugin_desc    = desc;
-	*plugin_version = version;
-
-	hexchat_hook_command (ph, "SYSINFO",	HEXCHAT_PRI_NORM,	sysinfo_cb,	sysinfo_help, NULL);
-	hexchat_hook_command (ph, "NETDATA",	HEXCHAT_PRI_NORM,	netdata_cb,	NULL, NULL);
-	hexchat_hook_command (ph, "NETSTREAM",	HEXCHAT_PRI_NORM,	netstream_cb,	NULL, NULL);
-
-	/* this is required for the very first run */
-	if (hexchat_pluginpref_get_str (ph, "pciids", buffer) == 0)
-	{
-		hexchat_pluginpref_set_str (ph, "pciids", DEFAULT_PCIIDS);
-	}
-
-	if (hexchat_pluginpref_get_str (ph, "format", buffer) == 0)
-	{
-		hexchat_pluginpref_set_str (ph, "format", DEFAULT_FORMAT);
-	}
-
-	if (hexchat_pluginpref_get_int (ph, "percent") == -1)
-	{
-		hexchat_pluginpref_set_int (ph, "percent", DEFAULT_PERCENT);
-	}
-
-	if (hexchat_pluginpref_get_int (ph, "announce") == -1)
-	{
-		hexchat_pluginpref_set_int (ph, "announce", DEFAULT_ANNOUNCE);
-	}
-
-	hexchat_command (ph, "MENU ADD \"Window/Send System Info\" \"SYSINFO\"");
-	hexchat_printf (ph, "%s plugin loaded\n", name);
-	return 1;
-}
-
-int
-hexchat_plugin_deinit (void)
-{
-	hexchat_command (ph, "MENU DEL \"Window/Display System Info\"");
-	hexchat_printf (ph, "%s plugin unloaded\n", name);
-	return 1;
-}