summary refs log tree commit diff stats
path: root/plugins/sysinfo
diff options
context:
space:
mode:
authorBerke Viktor <bviktor@hexchat.org>2012-10-21 06:44:29 +0200
committerBerke Viktor <bviktor@hexchat.org>2012-10-21 06:44:29 +0200
commit187351fa61e0ec9e8fe396de7a1d72a3a67d328f (patch)
tree46c15ce40d623ab8398073fe15c7af74eeb49f93 /plugins/sysinfo
parentcb891a9732d77dde425052b6d11dc8024492e80a (diff)
Add vanilla X-Sys sources
Diffstat (limited to 'plugins/sysinfo')
-rw-r--r--plugins/sysinfo/hwmon.c61
-rw-r--r--plugins/sysinfo/hwmon.h28
-rw-r--r--plugins/sysinfo/match.c229
-rw-r--r--plugins/sysinfo/match.h35
-rw-r--r--plugins/sysinfo/parse.c451
-rw-r--r--plugins/sysinfo/parse.h41
-rw-r--r--plugins/sysinfo/pci.c149
-rw-r--r--plugins/sysinfo/pci.h28
-rw-r--r--plugins/sysinfo/xsys-changelog116
-rw-r--r--plugins/sysinfo/xsys-install15
-rw-r--r--plugins/sysinfo/xsys-makefile39
-rw-r--r--plugins/sysinfo/xsys-readme105
-rw-r--r--plugins/sysinfo/xsys.c734
-rw-r--r--plugins/sysinfo/xsys.h28
14 files changed, 2059 insertions, 0 deletions
diff --git a/plugins/sysinfo/hwmon.c b/plugins/sysinfo/hwmon.c
new file mode 100644
index 00000000..d7616b47
--- /dev/null
+++ b/plugins/sysinfo/hwmon.c
@@ -0,0 +1,61 @@
+/*
+ * hwmon.c - Hardware monitoring functions for X-Sys
+ * Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include "xsys.h"
+
+int hwmon_chip_present()
+{
+	FILE *fp = fopen("/sys/class/hwmon/hwmon0/device/name", "r");
+	if(fp != NULL) {
+		fclose(fp);
+		return 1;
+	}
+	return 0;
+}
+
+void get_hwmon_chip_name(char *name)
+{
+	char *position, buffer[bsize];
+	FILE *fp = fopen("/sys/class/hwmon/hwmon0/device/name", "r");
+	if(fp != NULL) {
+		if(fgets(buffer, bsize, fp) != NULL) {
+			position = strstr(buffer, "\n");
+                        *(position) = '\0';
+			snprintf(name, sizeof(name), "%s", buffer);
+		}
+		fclose(fp);
+	}
+}
+
+void get_hwmon_temp(unsigned int *value, unsigned int *sensor)
+{
+	char buffer[bsize];
+	snprintf(buffer, bsize, "/sys/class/hwmon/hwmon0/device/temp%i_input", *sensor);
+	FILE *fp = fopen(buffer, "r");
+	if(fp != NULL) {
+		if(fgets(buffer, bsize, fp) != NULL)
+			*value = atoi(buffer);
+		fclose(fp);
+	}
+}
diff --git a/plugins/sysinfo/hwmon.h b/plugins/sysinfo/hwmon.h
new file mode 100644
index 00000000..020111f9
--- /dev/null
+++ b/plugins/sysinfo/hwmon.h
@@ -0,0 +1,28 @@
+/*
+ * hwmon.h - Hardware monitoring header for X-Sys
+ * Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _HWMON_H_
+#define _HWMON_H_
+
+int hwmon_chip_present();
+void get_hwmon_chip_name(char *name);
+void get_hwmon_temp(unsigned int *value, unsigned int *sensor);
+
+#endif
diff --git a/plugins/sysinfo/match.c b/plugins/sysinfo/match.c
new file mode 100644
index 00000000..64d7a062
--- /dev/null
+++ b/plugins/sysinfo/match.c
@@ -0,0 +1,229 @@
+/*
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include "xsys.h"
+
+extern int percentages;
+
+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 *result, *bytesize;
+	double free_space, total_space;
+	free_space = *free_k;
+	total_space = *total_k;
+        result = malloc(bsize * sizeof(char));
+        bytesize = malloc(3 * sizeof(char));
+	const char *quantities = "KB\0MB\0GB\0TB\0PB\0EB\0ZB\0YB\0";
+	int i=0;
+	if (total_space == 0)
+	{
+		snprintf(result, bsize, "%s: none", desc);
+		return result;
+	}
+	while (total_space > 1023 && i <= 14)
+	{
+		i=i+3;
+		*bytesize=*(quantities+i);
+		*(bytesize+1)=*(quantities+i+1);
+		*(bytesize+2)=*(quantities+i+2);
+		free_space = free_space / 1024;
+		total_space = total_space / 1024;
+	}
+	if (percentages != 0)
+		snprintf(result, bsize, "%s: %.1f%s, %.1f%% free",
+		desc, total_space, bytesize,
+		percentage(free_k, total_k));
+	else
+		snprintf(result, bsize, "%s: %.1f%s/%.1f%s free",
+		desc, free_space, bytesize, total_space, bytesize);
+        return result;
+}
+
+void remove_leading_whitespace(char *buffer)
+{
+	char *pos;
+        while((pos = memchr(buffer, 0x20, 1)))
+	{
+		pos += 1;
+		strcpy(buffer, pos);
+	}
+}
+
+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/match.h b/plugins/sysinfo/match.h
new file mode 100644
index 00000000..b8846527
--- /dev/null
+++ b/plugins/sysinfo/match.h
@@ -0,0 +1,35 @@
+/*
+ * match.h - matching header for X-Sys
+ * Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _MATCH_H_
+#define _MATCH_H_
+
+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/parse.c
new file mode 100644
index 00000000..d55142a1
--- /dev/null
+++ b/plugins/sysinfo/parse.c
@@ -0,0 +1,451 @@
+/*
+ * parse.c - parsing functions for X-Sys
+ * by mike9010
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdio.h>
+#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 "pci.h"
+#include "match.h"
+#include "hwmon.h"
+#include "xsys.h"
+
+int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned int *count)
+{
+	char buffer[bsize], *pos;
+	FILE *fp = fopen("/proc/cpuinfo", "r");
+	pos = NULL;
+	if(fp == NULL)
+		return 1;
+	if(count != NULL) *count = 0;
+	strcpy(cache,"unknown\0");
+	
+	#if defined(__i386__) || defined(__x86_64__)
+	while(fgets(buffer, bsize, fp) != NULL)
+	{
+		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)
+	{
+		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
+	#ifdef __alpha__
+	while(fgets(buffer, bsize, fp) != NULL)
+	{
+		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
+	#ifdef __ia64__
+	while(fgets(buffer, bsize, fp) != NULL)
+	{
+		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;
+	struct dirent *entry;
+	FILE *fp2;
+	while(fgets(buffer, bsize, fp) != NULL)
+	{
+		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)
+			{
+				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);
+	
+	return 0;
+}
+
+int xs_parse_uptime(int *weeks, int *days, int *hours, int *minutes, int *seconds)
+{
+	char buffer[bsize];
+	long long uptime = 0;
+	FILE *fp = fopen("/proc/uptime", "r");
+	if(fp == NULL)
+		return 1;
+
+	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);
+	snprintf(kernel, bsize, "%s %s %s", osinfo.sysname, osinfo.release, osinfo.machine);
+	
+	return 0;
+}
+
+int xs_parse_sound(char *snd_card)
+{
+	char buffer[bsize], cards[bsize] = "\0", vendor[7] = "\0", device[7] = "\0", *pos;
+	u16 class = PCI_CLASS_MULTIMEDIA_AUDIO;
+
+	FILE *fp = 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;
+			}
+		else
+			return 1;
+	}
+	
+	
+	while(fgets(buffer, bsize, fp) != NULL)
+	{
+		if(isdigit(buffer[0]) || isdigit(buffer[1]))
+		{
+			char card_buf[bsize];
+			long card_id = 0;
+			pos = strstr(buffer, ":");
+			card_id = strtoll(buffer, NULL, 0);
+			if (card_id == 0)
+				snprintf(card_buf, bsize, "%s", pos+2);
+			else
+				snprintf(card_buf, bsize, "%ld: %s", card_id, pos+2);
+			pos = strstr(card_buf, "\n");
+			*pos = '\0';
+			strcat(cards, card_buf);
+		}
+	}
+
+	strcpy(snd_card, cards);
+	
+	fclose(fp);
+	return 0;
+}
+
+int xs_parse_video(char *vid_card)
+{
+	char vendor[7] = "\0", device[7] = "\0";
+	u16 class = PCI_CLASS_DISPLAY_VGA;
+	if (pci_find_by_class(&class, vendor, device))
+		return 1;
+	else
+		pci_find_fullname(vid_card, vendor, device);
+	return 0;
+}
+
+int xs_parse_ether(char *ethernet_card)
+{
+	char vendor[7] = "\0", device[7] = "\0";
+	u16 class = PCI_CLASS_NETWORK_ETHERNET;
+	if (pci_find_by_class(&class, vendor, device))
+		return 1;
+	else
+		pci_find_fullname(ethernet_card, vendor, device);
+	return 0;
+}
+
+int xs_parse_agpbridge(char *agp_bridge)
+{
+	char vendor[7] = "\0", device[7] = "\0";
+	u16 class = PCI_CLASS_BRIDGE_HOST;
+	if (pci_find_by_class(&class, vendor, device))
+		return 1;
+	else
+		pci_find_fullname(agp_bridge, vendor, device);
+	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 = strtoull(pos, &pos, 0);
+
+	for(i=0;i<7;i++) strtoull(pos, &pos, 0);
+	
+	*bytes_sent = 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 += strtoull(pos, &pos, 0);
+			strtoull(pos, &pos, 0);
+			free_k += strtoull(pos, &pos, 0);
+			continue;
+		}
+		total_k = strtoull(pos, &pos, 0);
+		strtoull(pos, &pos, 0);
+		free_k = strtoull(pos, &pos, 0);
+		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);
+			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);
+			free(tmp_buf);
+			break;
+		}
+		else 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);
+		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];
+	unsigned long long freemem = 0, buffers = 0, cache = 0;
+        *mem_tot = 0;
+        *mem_free = 0;
+
+        if((fp = fopen("/proc/meminfo", "r")) == NULL)
+                return 1;
+
+        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
+                {
+			find_match_ll(buffer, "SwapTotal:", mem_tot);
+			find_match_ll(buffer, "SwapFree:", mem_free);
+                }
+        }
+	if (!swap) {
+		*mem_free = freemem + buffers + cache;
+	}
+        fclose(fp);
+        return 0;
+}
+
+int xs_parse_distro(char *name)
+{
+	FILE *fp = NULL;
+	char buffer[bsize], *pos = NULL;
+	
+	if((fp = fopen("/etc/lsb_release", "r")) != NULL)
+	{
+		char id[bsize], codename[bsize], release[bsize];
+		strcpy(id, "?");
+		strcpy(codename, "?");
+		strcpy(release, "?");
+		while(fgets(buffer, bsize, fp) != NULL)
+		{
+			find_match_char(buffer, "DISTRIB_ID", id);
+			find_match_char(buffer, "DISTRIB_CODENAME", codename);
+			find_match_char(buffer, "DISTRIB_RELEASE", release);
+		}
+		snprintf(buffer, bsize, "%s \"%s\" %s", id, codename, release);
+	}
+	else if((fp = fopen("/etc/make.conf", "r")) != NULL)
+	{
+		char keywords[bsize];
+		while(fgets(buffer, bsize, fp) != NULL)
+			find_match_char(buffer, "ACCEPT_KEYWORDS", keywords);
+		if (strstr(keywords, "\"") == NULL)
+			snprintf(buffer, bsize, "Gentoo Linux (stable)");
+		else
+			snprintf(buffer, bsize, "Gentoo Linux %s", keywords);
+	}		
+	else if((fp = fopen("/etc/redhat-release", "r")) != NULL)
+		fgets(buffer, bsize, fp);
+	else if((fp = fopen("/etc/slackware-version", "r")) != NULL)
+		fgets(buffer, bsize, fp);
+	else if((fp = fopen("/etc/mandrake-release", "r")) != NULL)
+		fgets(buffer, bsize, fp);
+	else if((fp = fopen("/etc/debian_version", "r")) != NULL)
+	{
+		char release[bsize];
+		fgets(release, bsize, fp);
+		snprintf(buffer, bsize, "Debian %s", release);
+	}
+	else if((fp = fopen("/etc/SuSE-release", "r")) != NULL)
+		fgets(buffer, bsize, fp);
+	else if((fp = fopen("/etc/turbolinux-release", "r")) != NULL)
+		fgets(buffer, bsize, fp);
+	else
+		snprintf(buffer, bsize, "Unknown Distro");
+	if(fp != NULL) fclose(fp);
+	
+	pos=strchr(buffer, '\n');
+	if(pos != NULL) *pos = '\0';
+	strcpy(name, buffer);
+	return 0;
+}
+
+int xs_parse_hwmon_chip(char *chip)
+{
+	if (!hwmon_chip_present())
+		return 1;
+	else
+		get_hwmon_chip_name(chip);
+	return 0;
+}
+
+int xs_parse_hwmon_temp(char *temp, unsigned int *sensor)
+{
+	unsigned int *value;
+	float celsius;
+        value = malloc(sizeof(int));
+
+	if (!hwmon_chip_present())
+		return 1;
+	else
+		get_hwmon_temp(value, sensor);
+		celsius = (float)*value;
+		snprintf(temp, bsize, "%.1fC", celsius/1000.0);
+		free(value);
+	return 0;
+}
diff --git a/plugins/sysinfo/parse.h b/plugins/sysinfo/parse.h
new file mode 100644
index 00000000..154fa8c4
--- /dev/null
+++ b/plugins/sysinfo/parse.h
@@ -0,0 +1,41 @@
+/*
+ * parse.h - parsing header for X-Sys
+ * by mikeshoup
+ * Copyright (C) 2003, 2004, 2005 Michael Shoup
+ * Copyright (C) 2005, 2006 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#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_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);
+int xs_parse_ether(char *ethernet_card);
+int xs_parse_xmms_info(char **title, unsigned int *songtime, unsigned int *playtime);
+int xs_parse_distro(char *name);
+int xs_parse_hwmon_chip(char *chip);
+int xs_parse_hwmon_temp(char *temp, unsigned int *sensor);
+
+#endif
diff --git a/plugins/sysinfo/pci.c b/plugins/sysinfo/pci.c
new file mode 100644
index 00000000..21f23c3e
--- /dev/null
+++ b/plugins/sysinfo/pci.c
@@ -0,0 +1,149 @@
+/*
+ * pci.c - PCI functions for X-Sys
+ * Copyright (C) 1997-1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz> [PCI routines from lspci]
+ * Copyright (C) 2000 Tom Rini <trini@kernel.crashing.org> [XorgAutoConfig pci.c, based on lspci]
+ * Copyright (C) 2005, 2006 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <pci/pci.h>
+#include "xsys.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];
+};
+
+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 = malloc(sizeof(struct device));
+  	bzero(d, sizeof(*d));
+  	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;
+      	}
+}
+
+static u16 get_conf_word(struct device *d, unsigned int pos)
+{
+  	return d->config[pos] | (d->config[pos+1] << 8);
+}
+
+int pci_find_by_class(u16 *class, char *vendor, char *device)
+{
+	struct device *d;
+	struct pci_dev *p;
+	int nomatch = 1;
+
+	pacc = pci_alloc();
+	pci_filter_init(pacc, &filter);
+	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;
+			snprintf(vendor,7,"%04x",p->vendor_id);
+			snprintf(device,7,"%04x",p->device_id);
+      			break;
+    		}
+  	}
+
+  	pci_cleanup(pacc);
+  	return nomatch;
+}
+
+void pci_find_fullname(char *fullname, char *vendor, char *device)
+{
+	char buffer[bsize], vendorname[bsize/2] = "", devicename[bsize/2] = "", *position;
+	int cardfound = 0;
+	FILE *fp = fopen(PCIIDS, "r");
+	if(fp == NULL) {
+		snprintf(fullname, bsize, "%s:%s", vendor, device);	
+		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';
+			break;
+                }
+	}
+	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';
+			cardfound = 1;
+			break;
+ 		}
+	}
+	if (cardfound == 1)
+		snprintf(fullname, bsize, "%s %s", vendorname, devicename);
+	else
+		snprintf(fullname, bsize, "%s:%s", vendor, device);	
+	fclose(fp);
+}
diff --git a/plugins/sysinfo/pci.h b/plugins/sysinfo/pci.h
new file mode 100644
index 00000000..b7afb1fc
--- /dev/null
+++ b/plugins/sysinfo/pci.h
@@ -0,0 +1,28 @@
+/*
+ * pci.h - PCI header for X-Sys
+ * Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PCI_H_
+#define _PCI_H_
+
+#include <pci/pci.h>
+void pci_find_fullname(char *fullname, char *vendor, char *device);
+int  pci_find_by_class(u16 *class, char *vendor, char *device);
+
+#endif
diff --git a/plugins/sysinfo/xsys-changelog b/plugins/sysinfo/xsys-changelog
new file mode 100644
index 00000000..9ea20727
--- /dev/null
+++ b/plugins/sysinfo/xsys-changelog
@@ -0,0 +1,116 @@
+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
new file mode 100644
index 00000000..8f148569
--- /dev/null
+++ b/plugins/sysinfo/xsys-install
@@ -0,0 +1,15 @@
+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
new file mode 100644
index 00000000..aeb28a99
--- /dev/null
+++ b/plugins/sysinfo/xsys-makefile
@@ -0,0 +1,39 @@
+#### 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 += $(shell pkg-config dbus-1 --cflags) $(shell pkg-config glib-2.0 --cflags)
+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 $(shell pkg-config dbus-1 --libs) $(shell pkg-config glib-2.0 --libs) -laudclient
+
+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
new file mode 100644
index 00000000..6226e725
--- /dev/null
+++ b/plugins/sysinfo/xsys-readme
@@ -0,0 +1,105 @@
+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
new file mode 100644
index 00000000..933ab7a6
--- /dev/null
+++ b/plugins/sysinfo/xsys.c
@@ -0,0 +1,734 @@
+/*
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xchat-plugin.h"
+#include "parse.h"
+#include "match.h"
+#include "xsys.h"
+#include <audacious/dbus.h>
+#include <audacious/audctrl.h>
+
+static xchat_plugin *ph;
+
+static char format[bsize] = "%B%1%B[%2]";
+static char playing[42] = "now_playing";
+unsigned int percentages = 1;
+static unsigned int action = 0;
+
+static void load_config();
+static void save_config();
+static gboolean dbus_init(void);
+
+static int format_cb		(char *word[], char *word_eol[], void *userdata);
+static int playing_cb		(char *word[], char *word_eol[], void *userdata);
+static int percentages_cb	(char *word[], char *word_eol[], void *userdata);
+static int action_cb		(char *word[], char *word_eol[], void *userdata);
+static int sysinfo_cb		(char *word[], char *word_eol[], void *userdata);
+static int xsys_cb		(char *word[], char *word_eol[], void *userdata);
+static int cpuinfo_cb		(char *word[], char *word_eol[], void *userdata);
+static int uptime_cb		(char *word[], char *word_eol[], void *userdata);
+static int osinfo_cb		(char *word[], char *word_eol[], void *userdata);
+static int sound_cb		(char *word[], char *word_eol[], void *userdata);
+static int netdata_cb		(char *word[], char *word_eol[], void *userdata);
+static int netstream_cb		(char *word[], char *word_eol[], void *userdata);
+static int disk_cb		(char *word[], char *word_eol[], void *userdata);
+static int mem_cb		(char *word[], char *word_eol[], void *userdata);
+static int video_cb		(char *word[], char *word_eol[], void *userdata);
+static int ether_cb		(char *word[], char *word_eol[], void *userdata);
+static int distro_cb		(char *word[], char *word_eol[], void *userdata);
+#if 0
+static int hwmon_cb		(char *word[], char *word_eol[], void *userdata);
+#endif
+static int np_cb		(char *word[], char *word_eol[], void *userdata);
+static DBusGProxy *dbus_proxy = NULL;
+static DBusGConnection *connection = NULL;
+
+int xchat_plugin_init(xchat_plugin *plugin_handle, char **plugin_name,
+                      char **plugin_desc, char **plugin_version, char *arg)
+{
+	ph = plugin_handle;
+	*plugin_name    = "X-Sys_2";
+	*plugin_desc    = "A sysinfo/audacious plugin";
+	*plugin_version = VER_STRING;
+
+	xchat_hook_command(ph, "XSYS2FORMAT",XCHAT_PRI_NORM, format_cb,    NULL, NULL);
+	xchat_hook_command(ph, "PLAYING",    XCHAT_PRI_NORM, playing_cb,   NULL, NULL);
+	xchat_hook_command(ph, "PERCENTAGES",XCHAT_PRI_NORM, percentages_cb,   NULL, NULL);
+	xchat_hook_command(ph, "NPACTION",   XCHAT_PRI_NORM, action_cb,    NULL, NULL);
+	xchat_hook_command(ph, "SYSINFO",    XCHAT_PRI_NORM, sysinfo_cb,   NULL, (void *) 0);
+	xchat_hook_command(ph, "ESYSINFO",   XCHAT_PRI_NORM, sysinfo_cb,   NULL, (void *) 1);
+	xchat_hook_command(ph, "XSYS",       XCHAT_PRI_NORM, xsys_cb,      NULL, (void *) 0);
+	xchat_hook_command(ph, "EXSYS",      XCHAT_PRI_NORM, xsys_cb,      NULL, (void *) 1);
+	xchat_hook_command(ph, "CPUINFO",    XCHAT_PRI_NORM, cpuinfo_cb,   NULL, (void *) 0);
+	xchat_hook_command(ph, "ECPUINFO",   XCHAT_PRI_NORM, cpuinfo_cb,   NULL, (void *) 1);
+	xchat_hook_command(ph, "SYSUPTIME",  XCHAT_PRI_NORM, uptime_cb,    NULL, (void *) 0);
+	xchat_hook_command(ph, "ESYSUPTIME", XCHAT_PRI_NORM, uptime_cb,    NULL, (void *) 1);
+	xchat_hook_command(ph, "OSINFO",     XCHAT_PRI_NORM, osinfo_cb,    NULL, (void *) 0);
+	xchat_hook_command(ph, "EOSINFO",    XCHAT_PRI_NORM, osinfo_cb,    NULL, (void *) 1);
+	xchat_hook_command(ph, "SOUND",      XCHAT_PRI_NORM, sound_cb,     NULL, (void *) 0);
+	xchat_hook_command(ph, "ESOUND",     XCHAT_PRI_NORM, sound_cb,     NULL, (void *) 1);
+	xchat_hook_command(ph, "NETDATA",    XCHAT_PRI_NORM, netdata_cb,   NULL, (void *) 0);
+	xchat_hook_command(ph, "ENETDATA",   XCHAT_PRI_NORM, netdata_cb,   NULL, (void *) 1);
+	xchat_hook_command(ph, "NETSTREAM",  XCHAT_PRI_NORM, netstream_cb, NULL, (void *) 0);
+	xchat_hook_command(ph, "ENETSTREAM", XCHAT_PRI_NORM, netstream_cb, NULL, (void *) 1);
+	xchat_hook_command(ph, "DISKINFO",   XCHAT_PRI_NORM, disk_cb,      NULL, (void *) 0);
+	xchat_hook_command(ph, "EDISKINFO",  XCHAT_PRI_NORM, disk_cb,      NULL, (void *) 1);
+	xchat_hook_command(ph, "MEMINFO",    XCHAT_PRI_NORM, mem_cb,       NULL, (void *) 0);
+	xchat_hook_command(ph, "EMEMINFO",   XCHAT_PRI_NORM, mem_cb,       NULL, (void *) 1);
+	xchat_hook_command(ph, "VIDEO",      XCHAT_PRI_NORM, video_cb,     NULL, (void *) 0);
+	xchat_hook_command(ph, "EVIDEO",     XCHAT_PRI_NORM, video_cb,     NULL, (void *) 1);
+	xchat_hook_command(ph, "ETHER",      XCHAT_PRI_NORM, ether_cb,     NULL, (void *) 0);
+	xchat_hook_command(ph, "EETHER",     XCHAT_PRI_NORM, ether_cb,     NULL, (void *) 1);
+	xchat_hook_command(ph, "DISTRO",     XCHAT_PRI_NORM, distro_cb,    NULL, (void *) 0);
+	xchat_hook_command(ph, "EDISTRO",    XCHAT_PRI_NORM, distro_cb,    NULL, (void *) 1);
+#if 0
+	xchat_hook_command(ph, "HWMON",      XCHAT_PRI_NORM, hwmon_cb,     NULL, (void *) 0);
+	xchat_hook_command(ph, "EHWMON",     XCHAT_PRI_NORM, hwmon_cb,     NULL, (void *) 1);
+#endif
+	if (dbus_init())
+	{
+		xchat_hook_command(ph, "NP",         XCHAT_PRI_NORM, np_cb,        NULL, (void *) 0);
+		xchat_hook_command(ph, "ENP",        XCHAT_PRI_NORM, np_cb,        NULL, (void *) 1);
+		xchat_printf(ph, "D-Bus MPRIS support initialized", VER_STRING);
+	}
+	
+	load_config();
+
+	xchat_printf(ph, "X-Sys %s Loaded Succesfully", VER_STRING);
+	
+	return 1;
+}
+
+static void xchat_plugin_deinit()
+{
+	/* blahblahblah */
+}
+
+static void save_config()
+{
+	FILE *fp;
+	char buffer[bsize];
+	snprintf(buffer, bsize, "%s/xsys2.conf", xchat_get_info(ph, "xchatdirfs"));
+	fp = fopen(buffer, "w");
+	if(fp == NULL)
+	{
+		printf("ERROR writing xsys2.conf");
+		return;
+	}
+	fprintf(fp, "format: %s\n", format);
+	fprintf(fp, "playing: %s\n", playing);
+	fprintf(fp, "percentages: %i\n", percentages);
+	fprintf(fp, "action: %i\n", action);
+	fclose(fp);
+	return;
+}
+
+static void load_config()
+{
+	FILE *fp;
+	char buffer[bsize];
+	snprintf(buffer, bsize, "%s/xsys2.conf", xchat_get_info(ph, "xchatdirfs"));
+	fp = fopen(buffer, "r");
+	if(fp == NULL)
+		save_config();
+	
+	while(fgets(buffer, bsize, fp) != NULL)
+	{
+		find_match_char(buffer, "format", format);
+		find_match_char(buffer, "playing", playing);
+		find_match_int(buffer, "percentages", &percentages);
+		find_match_int(buffer, "action", &action);
+	}
+	fclose(fp);
+}
+
+static gboolean dbus_init(void)
+{
+        GError *error = NULL;
+
+        connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+        if (connection == NULL)
+                return FALSE;
+
+        dbus_proxy = dbus_g_proxy_new_for_name(connection, AUDACIOUS_DBUS_SERVICE,
+                                                           AUDACIOUS_DBUS_PATH,
+                                                           AUDACIOUS_DBUS_INTERFACE);
+        if (dbus_proxy == NULL)
+                return FALSE;
+
+        return TRUE;
+}
+
+static int format_cb(char *word[], char *word_eol[], void *userdata)
+{
+	if(*(word[2]) == '\0')
+		xchat_printf(ph, "Current format string:\n%s", format);
+	else
+	{
+		strncpy(format, word_eol[2], bsize);
+		save_config();
+	}
+	return XCHAT_EAT_ALL;
+}
+
+static int playing_cb(char *word[], char *word_eol[], void *userdata)
+{
+	if(*(word[2]) == '\0')
+		xchat_printf(ph, "Current playing string:\n%s", playing);
+	else
+	{
+		strncpy(playing, word_eol[2], 42);
+		save_config();
+	}
+	return XCHAT_EAT_ALL;
+}
+
+static int percentages_cb(char *word[], char *word_eol[], void *userdata)
+{
+	if(*(word[2]) == '\0')
+		if (percentages != 0)
+			xchat_printf(ph, "Percentages currently enabled");
+		else
+			xchat_printf(ph, "Percentages currently disabled");		
+	else
+	{
+		percentages = atoi(word[2]);
+		save_config();
+	}
+	return XCHAT_EAT_ALL;
+}
+
+static int action_cb(char *word[], char *word_eol[], void *userdata)
+{
+	if(*(word[2]) == '\0')
+		if (action != 0)
+			xchat_printf(ph, "Now playing action currently enabled");
+		else
+			xchat_printf(ph, "Now playing action currently disabled");		
+	else
+	{
+		action = atoi(word[2]);
+		save_config();
+	}
+	return XCHAT_EAT_ALL;
+}
+
+static int sysinfo_cb(char *word[], char *word_eol[], void *userdata)
+{
+	char sysinfo[bsize], buffer[bsize], cpu_model[bsize], cpu_cache[bsize], cpu_vendor[bsize];
+	char os_host[bsize], os_user[bsize], os_kernel[bsize];
+	unsigned long long mem_total, mem_free;
+	unsigned int count;
+	double cpu_freq;
+	int giga = 0;
+	sysinfo[0] = '\0';
+
+// BEGIN OS PARSING
+	if(xs_parse_os(os_user, os_host, os_kernel) != 0)
+	{
+		xchat_printf(ph, "ERROR in parse_os()");
+		return XCHAT_EAT_ALL;
+	}
+
+	snprintf(buffer, bsize, "%s", os_kernel);
+	format_output("os", buffer, format);
+	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)
+	{
+		xchat_printf(ph, "ERROR in parse_cpu()");
+		return XCHAT_EAT_ALL;
+	}
+	
+	if(cpu_freq > 1000)
+	{
+		cpu_freq /= 1000;
+		giga = 1;
+	}
+	
+	if(giga) snprintf(buffer, bsize, "%d x %s (%s) @ %.2fGHz", count, cpu_model, cpu_vendor, cpu_freq);
+	else snprintf(buffer, bsize, "%d 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)
+	{
+		xchat_printf(ph, "ERROR in parse_meminfo!");
+		return XCHAT_EAT_ALL;
+	}
+	snprintf(buffer, bsize, "%s", pretty_freespace("Physical", &mem_free, &mem_total));
+	format_output("mem", buffer, format);	
+	strcat(sysinfo, "\017 ");
+	strncat(sysinfo, buffer, bsize-strlen(sysinfo));
+	
+// BEGIN DISK PARSING
+	if(xs_parse_df(NULL, buffer))
+	{
+		xchat_printf(ph, "ERROR in parse_df");
+		return XCHAT_EAT_ALL;
+	}
+	format_output("disk", buffer, format);
+	strcat(sysinfo, "\017 ");
+	strncat(sysinfo, buffer, bsize-strlen(buffer));
+	
+//BEGIN VIDEO PARSING
+	if(xs_parse_video(buffer))
+	{
+		xchat_printf(ph, "ERROR in parse_video");
+		return XCHAT_EAT_ALL;
+	}
+	format_output("video", 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));
+	
+	if((long)userdata)
+		xchat_printf(ph, "%s", sysinfo);
+	else
+		xchat_commandf(ph, "say %s", sysinfo);	
+	
+	return XCHAT_EAT_ALL;
+}
+
+static int xsys_cb(char *word[], char *word_eol[], void *userdata)
+{
+	if((long)userdata)
+		xchat_printf(ph, "You are using X-Sys v%s (http://dev.gentoo.org/~chainsaw/xsys)", VER_STRING);
+	else
+		xchat_commandf(ph, "me is using X-Sys v%s (http://dev.gentoo.org/~chainsaw/xsys)", VER_STRING);
+	
+	return XCHAT_EAT_ALL;
+}
+
+static int cpuinfo_cb(char *word[], char *word_eol[], void *userdata)
+{
+	char model[bsize], vendor[bsize], cache[bsize], buffer[bsize];
+	unsigned int count;
+	double freq;
+	int giga = 0;
+	
+	if(xs_parse_cpu(model, vendor, &freq, cache, &count) != 0)
+	{
+		xchat_printf(ph, "ERROR in parse_cpu()");
+		return XCHAT_EAT_ALL;
+	}
+	
+	if(freq > 1000)
+	{
+		freq /= 1000;
+		giga = 1;
+	}
+	
+	if(giga) snprintf(buffer, bsize, "%d x %s (%s) @ %.2fGHz w/ %s L2 Cache", count, model, vendor, freq, cache);
+	else snprintf(buffer, bsize, "%d x %s (%s) @ %.0fMHz w/ %s L2 Cache", count, model, vendor, freq, cache);
+	
+	format_output("cpu", buffer, format);
+	
+	if((long)userdata)
+		xchat_printf(ph, "%s", buffer);
+	else
+		xchat_commandf(ph, "say %s", buffer);
+	
+	return XCHAT_EAT_ALL;
+}
+
+static int uptime_cb(char *word[], char *word_eol[], void *userdata)
+{
+	char buffer[bsize];
+	int weeks, days, hours, minutes, seconds;
+	
+	if(xs_parse_uptime(&weeks, &days, &hours, &minutes, &seconds))
+	{
+		xchat_printf(ph, "ERROR in parse_uptime()");
+		return XCHAT_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 )
+                                {
+                                        snprintf( buffer, bsize, "%dw %dd %dh %dm %ds",
+                                                  weeks, days, hours, minutes, seconds );
+                                }
+                                else
+                                {
+                                        snprintf( buffer, bsize, "%dd %dh %dm %ds",
+                                                  days, hours, minutes, seconds );
+                                }
+                        }
+                        else
+                        {
+                                snprintf( buffer, bsize, "%dh %dm %ds",
+                                          hours, minutes, seconds );
+                        }
+                }
+                else
+                {
+                        snprintf( buffer, bsize, "%dm %ds", minutes, seconds );
+                }
+        }
+
+	format_output("uptime", buffer, format);
+	
+	if((long)userdata)
+		xchat_printf(ph, "%s", buffer);
+	else
+		xchat_commandf(ph, "say %s", buffer);
+	
+	return XCHAT_EAT_ALL;
+}
+
+static int osinfo_cb(char *word[], char *word_eol[], void *userdata)
+{
+	char buffer[bsize], user[bsize], host[bsize], kernel[bsize];
+	
+	if(xs_parse_os(user, host, kernel) != 0)
+	{
+		xchat_printf(ph, "ERROR in parse_os()");
+		return XCHAT_EAT_ALL;
+	}
+
+	snprintf(buffer, bsize, "%s@%s, %s", user, host, kernel);
+	format_output("os", buffer, format);
+	
+	if((long)userdata)
+		xchat_printf(ph, "%s", buffer);
+	else
+		xchat_commandf(ph, "say %s", buffer);
+	
+	return XCHAT_EAT_ALL;
+}
+
+static int sound_cb(char *word[], char *world_eol[], void *userdata)
+{
+	char sound[bsize];
+	if(xs_parse_sound(sound) != 0)
+	{
+		xchat_printf(ph, "ERROR in parse_asound()!");
+		return XCHAT_EAT_ALL;
+	}
+	
+	format_output("sound", sound, format);
+	
+	if((long)userdata)
+		xchat_printf(ph, "%s", sound);
+	else
+		xchat_commandf(ph, "say %s", sound);
+	
+	return XCHAT_EAT_ALL;
+}
+
+static int distro_cb(char *word[], char *word_eol[], void *userdata)
+{
+	char name[bsize];
+	if(xs_parse_distro(name) != 0)
+	{
+		xchat_printf(ph, "ERROR in parse_distro()!");
+		return XCHAT_EAT_ALL;
+	}
+	
+	format_output("distro", name, format);
+	if((long)userdata)
+		xchat_printf(ph, "%s", name);
+	else
+		xchat_commandf(ph, "say %s", name);
+	return XCHAT_EAT_ALL;
+}	
+
+static int netdata_cb(char *word[], char *word_eol[], void *userdata)
+{
+	char netdata[bsize];
+	unsigned long long bytes_recv, bytes_sent;
+	
+	if(*word[2] == '\0')
+	{
+		xchat_printf(ph, "You must specify a network device! (eg.: /netdata eth0)");
+		return XCHAT_EAT_ALL;
+	}
+	
+	if(xs_parse_netdev(word[2], &bytes_recv, &bytes_sent) != 0)
+	{
+		xchat_printf(ph, "ERROR in parse_netdev");
+		return XCHAT_EAT_ALL;
+	}
+	
+	bytes_recv /= 1024;
+	bytes_sent /= 1024;
+	
+	snprintf(netdata, bsize, "%s: %.1f MB Recieved, %.1f MB Sent", word[2], (double)bytes_recv/1024.0, (double)bytes_sent/1024.0);
+	format_output("netdata", netdata, format);
+	if((long)userdata)
+		xchat_printf(ph, "%s", netdata);
+	else
+		xchat_commandf(ph, "say %s", netdata);
+		
+	return XCHAT_EAT_ALL;
+}
+
+static int netstream_cb(char *word[], char *word_eol[], void *userdata)
+{
+	char netstream[bsize], mag_r[3], mag_s[5];
+	unsigned long long bytes_recv, bytes_sent, bytes_recv_p, bytes_sent_p;
+	struct timespec ts = {1, 0};
+	
+
+	if(*word[2] == '\0')
+	{
+		xchat_printf(ph, "You must specify a network device! (eg.: /netstream eth0)");
+		return XCHAT_EAT_ALL;
+	}
+	
+	if(xs_parse_netdev(word[2], &bytes_recv, &bytes_sent) != 0)
+	{
+		xchat_printf(ph, "ERROR in parse_netdev");
+		return XCHAT_EAT_ALL;
+	}
+	
+	while(nanosleep(&ts, &ts) < 0);
+	
+	if(xs_parse_netdev(word[2], &bytes_recv_p, &bytes_sent_p) != 0)
+	{
+		xchat_printf(ph, "ERROR in parse_netdev");
+		return XCHAT_EAT_ALL;
+	}
+	
+	bytes_recv = (bytes_recv_p - bytes_recv);
+	bytes_sent = (bytes_sent_p - bytes_sent);
+	
+	if(bytes_recv>1024)
+	{
+		bytes_recv /= 1024;
+		snprintf(mag_r, 5, "KB/s");
+	}
+	else snprintf(mag_r, 5, "B/s");
+	
+	if(bytes_sent>1024)
+	{
+		bytes_sent /= 1024;
+		snprintf(mag_s, 5, "KB/s");
+	}
+	else snprintf(mag_s, 5, "B/s");
+	
+	snprintf(netstream, bsize, "%s: Receiving %llu %s, Sending %llu %s", word[2], bytes_recv, mag_r, bytes_sent, mag_s);
+	format_output("netstream", netstream, format);
+	if((long)userdata)
+		xchat_printf(ph, "%s", netstream);
+	else
+		xchat_commandf(ph, "say %s", netstream);
+	
+	return XCHAT_EAT_ALL;
+}
+
+static int disk_cb(char *word[], char *word_eol[], void *userdata)
+{
+	char string[bsize] = {0,};
+	
+	if(*word[2] == '\0')
+	{
+		if(xs_parse_df(NULL, string))
+		{
+			xchat_printf(ph, "ERROR in parse_df");
+			return XCHAT_EAT_ALL;
+		}
+	}
+	else
+	{
+		if(xs_parse_df(word[2], string))
+		{
+			xchat_printf(ph, "ERROR in parse_df");
+			return XCHAT_EAT_ALL;
+		}
+	}
+	
+	format_output("disk", string, format);
+	
+	if((long)userdata)
+		xchat_printf(ph, "%s", string);
+	else
+		xchat_commandf(ph, "say %s", string);
+	
+	return XCHAT_EAT_ALL;
+}
+
+static int mem_cb(char *word[], char *word_eol[], void *userdata)
+{
+	unsigned long long mem_total, mem_free, swap_total, swap_free;
+	char string[bsize];
+	
+	if(xs_parse_meminfo(&mem_total, &mem_free, 0) == 1)
+	{
+		xchat_printf(ph, "ERROR in parse_meminfo!");
+		return XCHAT_EAT_ALL;
+	}
+	if(xs_parse_meminfo(&swap_total, &swap_free, 1) == 1)
+	{
+		xchat_printf(ph, "ERROR in parse_meminfo!");
+		return XCHAT_EAT_ALL;
+	}
+
+	snprintf(string, bsize, "%s - %s", pretty_freespace("Physical", &mem_free, &mem_total),
+		 pretty_freespace("Swap", &swap_free, &swap_total));
+	format_output("mem", string, format);
+	
+	if((long)userdata)
+		xchat_printf(ph, "%s", string);
+	else
+		xchat_commandf(ph, "say %s", string);
+	
+	return XCHAT_EAT_ALL;
+}
+
+static int video_cb(char *word[], char *word_eol[], void *userdata)
+{
+	char vid_card[bsize], agp_bridge[bsize], buffer[bsize];
+	int ret;
+	if((ret = xs_parse_video(vid_card)) != 0)
+	{
+		xchat_printf(ph, "ERROR in parse_video! %d", ret);
+		return XCHAT_EAT_ALL;
+	}
+	
+	if(xs_parse_agpbridge(agp_bridge) != 0)
+		snprintf(buffer, bsize, "%s", vid_card);
+	else
+		snprintf(buffer, bsize, "%s @ %s", vid_card, agp_bridge);
+	
+	format_output("video", buffer, format);
+	if((long)userdata)
+		xchat_printf(ph, "%s", buffer);
+	else
+		xchat_commandf(ph, "say %s", buffer);
+	
+	return XCHAT_EAT_ALL;
+}
+
+static int ether_cb(char *word[], char *word_eol[], void *userdata)
+{
+	char ethernet_card[bsize];
+	if(xs_parse_ether(ethernet_card))
+		strncpy(ethernet_card, "None found", bsize);
+	format_output("ether", ethernet_card, format);
+	if((long)userdata)
+		xchat_printf(ph, "%s", ethernet_card);
+	else
+		xchat_commandf(ph, "say %s", ethernet_card);
+	
+	return XCHAT_EAT_ALL;
+}
+
+#if 0
+static int hwmon_cb(char *word[], char *word_eol[], void *userdata)
+{
+	char chip[bsize], buffer[bsize];
+	
+	if(xs_parse_hwmon_chip(chip))
+	{
+		xchat_printf(ph, "ERROR No hardware monitoring support found");
+		return XCHAT_EAT_ALL;
+	}
+	format_output("sensor", chip, format);
+	strcat(chip, "\017 ");
+
+	xs_parse_hwmon_temp(buffer, 1);
+	format_output("temp1", buffer, format);
+	strncat(chip, buffer, bsize);
+	
+	if((long)userdata)
+		xchat_printf(ph, "%s", chip);
+	else
+		xchat_commandf(ph, "say %s", chip);
+	
+	return XCHAT_EAT_ALL;
+}
+#endif
+
+static int np_cb(char *word[], char *word_eol[], void *userdata)
+{
+	char *buffer = NULL, title[bsize], length[42];
+	int pos, len, p = audacious_remote_get_playlist_pos(dbus_proxy);
+
+	if (!audacious_remote_is_running(dbus_proxy))
+	{
+		xchat_printf(ph, "Audacious is not currently running");
+		return XCHAT_EAT_ALL;
+        }
+
+	pos = audacious_remote_get_output_time(dbus_proxy);
+	len = audacious_remote_get_playlist_time(dbus_proxy, p);
+	buffer = decruft_filename(audacious_remote_get_playlist_title(dbus_proxy, p));
+
+	strncpy(title, buffer, bsize);
+	
+	if (action != 0)
+		flat_format_output(playing, title, format);
+	else
+		format_output(playing, title, format);
+	strcat(title, "\017 ");
+
+	if(len == -1)
+		snprintf(length, 42, "%d:%02d/stream",
+		 ((pos/1000)-((pos/1000)%60))/60, (pos/1000)%60);
+	else 
+		snprintf(length, 42, "%d:%02d/%d:%02d",
+		 ((pos/1000)-((pos/1000)%60))/60, (pos/1000)%60,
+		 ((len/1000)-((len/1000)%60))/60, (len/1000)%60);
+	
+	if (action != 0)
+		flat_format_output("length", length, format);
+	else
+		format_output("length", length, format);
+	strncat(title, length, bsize);
+	
+	if ((action != 0) && (long)userdata)
+		xchat_printf(ph, "You are %s", title);
+	else if (action != 0)
+		xchat_commandf(ph, "me is %s", title);
+	else if ((long)userdata)
+		xchat_printf(ph, "%s", title);
+	else
+		xchat_commandf(ph, "say %s", title);
+	
+	return XCHAT_EAT_ALL;
+}
diff --git a/plugins/sysinfo/xsys.h b/plugins/sysinfo/xsys.h
new file mode 100644
index 00000000..19a77ede
--- /dev/null
+++ b/plugins/sysinfo/xsys.h
@@ -0,0 +1,28 @@
+/*
+ * xsys.h - X-Sys general parameters header
+ * Copyright (C) 2005 Gustavo Zacarias
+ * Copyright (C) 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _XSYS_H_
+#define _XSYS_H_
+
+#define bsize 1024
+#define delims ":="
+
+#endif