uptime.c
changeset 8 af9ebb57baf6
parent 7 6524d7d3061b
child 9 c1f0277182a3
--- a/uptime.c	Thu Nov 11 22:42:45 2010 +0100
+++ b/uptime.c	Sat Nov 13 17:51:20 2010 +0100
@@ -54,15 +54,72 @@
 	.next        = &info_uptime_experimental,
 };
 
+guint hz = 0;
+long long unsigned int mstime = 0;
 time_t starttime = 0;
+gboolean proc_used = FALSE;
+
+static int sys_uptime (void)
+{
+	GString *line = g_string_new (NULL);
+	GError     *error   = NULL;
+	GIOStatus ret;
+	int sec, ssec;
+	GIOChannel *channel = g_io_channel_new_file ("/proc/uptime", "r", &error);
+	if (!channel) {
+		g_string_free (line, TRUE);
+		scr_log_print (LPRINT_LOGNORM,
+				"Cannot open system uptime for reading.");
+		return 0;
+	}
+	g_io_channel_set_close_on_unref (channel, TRUE);
+
+	ret = g_io_channel_read_line_string (channel, line, NULL, &error);
+	if (ret != G_IO_STATUS_NORMAL) {
+		if (error) {
+			scr_log_print (LPRINT_LOGNORM,
+					"uptime: System uptime reading error: %s.",
+					error -> message);
+			g_error_free (error);
+		}
+		g_io_channel_unref (channel);
+		g_string_free (line, TRUE);
+		return 0;
+	}
+	g_io_channel_unref (channel);
+	if (sscanf (line -> str, "%d.%ds", &sec, &ssec) != 2) {
+		scr_log_print (LPRINT_LOGNORM,
+				"Unable to parse system uptime.");
+		g_string_free (line, TRUE);
+		return 0;
+	}
+	return (sec * hz) + (ssec * hz)/100;
+}
 
 void do_uptime (char *arg)
 {
 	GString *line = g_string_new (NULL);
-	guint seconds = time (NULL) - starttime;
-	guint minutes = seconds / 60;
-	guint hours   = minutes / 60;
-	guint days    = hours   / 24;
+	guint seconds;
+	guint minutes;
+	guint hours;
+	guint days;
+	time_t now = time (NULL);
+
+	if (proc_used && settings_opt_get_int ("uptime_use_proc")) {
+		int sysup = sys_uptime();
+		if (!sysup) {
+			g_string_free (line, TRUE);
+			scr_log_print (LPRINT_NORMAL, "Uptime not available :-(");
+			return;
+		}
+		seconds = (sysup - mstime) / hz;
+	} else {
+		seconds = now - starttime;
+	}
+
+	minutes = seconds / 60;
+	hours   = minutes / 60;
+	days    = hours   / 24;
 	seconds %= 60;
 	minutes %= 60;
 	hours   %= 24;
@@ -83,9 +140,10 @@
 
 gchar *g_module_check_init (GModule *module)
 {
+	starttime = time (NULL);
+
 	if (settings_opt_get_int ("uptime_use_proc")) {
-		long long unsigned int mstime = 0;
-		long long unsigned int kbtime = 0;
+		//long long unsigned int kbtime = 0;
 		GError     *error   = NULL;
 		GString    *line;
 		GIOChannel *channel = g_io_channel_new_file ("/proc/self/stat", "r", &error);
@@ -97,7 +155,7 @@
 		line = g_string_new (NULL);
 		if (g_io_channel_read_line_string (channel, line, NULL, &error) != G_IO_STATUS_NORMAL) {
 			if (error) {
-				scr_log_print (LPRINT_DEBUG, "uptime: Own stats reading error: %s.", error -> message);
+				scr_log_print (LPRINT_LOGNORM, "uptime: Own stats reading error: %s.", error -> message);
 				g_error_free (error);
 			}
 			g_io_channel_unref (channel);
@@ -110,6 +168,7 @@
 			g_string_free (line, TRUE);
 			return "Missing ) in own stats";
 		}
+		p++;
 		while (*p && isspace (*p)) p++;
 		while (*p && isalpha (*p)) p++; // state (%c)
 		while (*p && isspace (*p)) p++;
@@ -160,36 +219,12 @@
 			g_string_free (line, TRUE);
 			return "Malformed own start time.";
 		}
-
-		channel = g_io_channel_new_file ("/proc/stat", "r", &error);
-		if (!channel) {
-			g_string_free (line, TRUE);
-			return "Cannot open system stats for reading";
-		}
-		g_io_channel_set_close_on_unref (channel, TRUE);
-
-		while (TRUE) {
-			GIOStatus ret = g_io_channel_read_line_string (channel, line, NULL, &error);
-			if (ret != G_IO_STATUS_NORMAL) {
-				if (error) {
-					scr_log_print (LPRINT_DEBUG, "uptime: System stats reading error: %s.", error -> message);
-					g_error_free (error);
-				}
-				g_io_channel_unref (channel);
-				g_string_free (line, TRUE);
-				return "Error reading system stats.";
-			}
-			if (sscanf (line -> str, "btime %llu", &kbtime))
-				break;
-		}
-		g_io_channel_unref (channel);
-
 		g_string_free (line, TRUE);
 
-		guint hz = sysconf(_SC_CLK_TCK);
-		starttime = kbtime + (mstime / hz);
-	} else
-		starttime = time (NULL);
+		hz = sysconf(_SC_CLK_TCK);
+		if (hz && mstime)
+			proc_used = TRUE;
+	}
 
 	cmd_add ("uptime", "", 0, 0, do_uptime, NULL);
 	return NULL;