summaryrefslogtreecommitdiff
path: root/src/uptime.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/uptime.c')
-rw-r--r--src/uptime.c245
1 files changed, 245 insertions, 0 deletions
diff --git a/src/uptime.c b/src/uptime.c
new file mode 100644
index 0000000..6b2a724
--- /dev/null
+++ b/src/uptime.c
@@ -0,0 +1,245 @@
+/* GNU's uptime.
+ Copyright (C) 1992-2002, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+ 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, 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 Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Created by hacking who.c by Kaveh Ghazi ghazi@caip.rutgers.edu. */
+
+#include <config.h>
+#include <getopt.h>
+#include <stdio.h>
+
+#include <sys/types.h>
+#include "system.h"
+
+#if HAVE_SYSCTL && HAVE_SYS_SYSCTL_H
+# include <sys/sysctl.h>
+#endif
+
+#if HAVE_OS_H
+# include <OS.h>
+#endif
+
+#include "c-strtod.h"
+#include "error.h"
+#include "long-options.h"
+#include "quote.h"
+#include "readutmp.h"
+
+/* The official name of this program (e.g., no `g' prefix). */
+#define PROGRAM_NAME "uptime"
+
+#define AUTHORS "Joseph Arceneaux", "David MacKenzie", "Kaveh Ghazi"
+
+int getloadavg ();
+
+/* The name this program was run with. */
+char *program_name;
+
+static void
+print_uptime (size_t n, const STRUCT_UTMP *this)
+{
+ size_t entries = 0;
+ time_t boot_time = 0;
+ time_t time_now;
+ time_t uptime = 0;
+ long int updays;
+ int uphours;
+ int upmins;
+ struct tm *tmn;
+ double avg[3];
+ int loads;
+#ifdef HAVE_PROC_UPTIME
+ FILE *fp;
+
+ fp = fopen ("/proc/uptime", "r");
+ if (fp != NULL)
+ {
+ char buf[BUFSIZ];
+ char *b = fgets (buf, BUFSIZ, fp);
+ if (b == buf)
+ {
+ char *end_ptr;
+ double upsecs = c_strtod (buf, &end_ptr);
+ if (buf != end_ptr)
+ uptime = (0 <= upsecs && upsecs < TYPE_MAXIMUM (time_t)
+ ? upsecs : -1);
+ }
+
+ fclose (fp);
+ }
+#endif /* HAVE_PROC_UPTIME */
+
+#if HAVE_SYSCTL && defined CTL_KERN && defined KERN_BOOTTIME
+ {
+ /* FreeBSD specific: fetch sysctl "kern.boottime". */
+ static int request[2] = { CTL_KERN, KERN_BOOTTIME };
+ struct timeval result;
+ size_t result_len = sizeof result;
+
+ if (sysctl (request, 2, &result, &result_len, NULL, 0) >= 0)
+ boot_time = result.tv_sec;
+ }
+#endif
+
+#if HAVE_OS_H /* BeOS */
+ {
+ system_info si;
+
+ get_system_info (&si);
+ boot_time = si.boot_time / 1000000;
+ }
+#endif
+
+#if HAVE_UTMPX_H || HAVE_UTMP_H
+ /* Loop through all the utmp entries we just read and count up the valid
+ ones, also in the process possibly gleaning boottime. */
+ while (n--)
+ {
+ entries += IS_USER_PROCESS (this);
+ if (UT_TYPE_BOOT_TIME (this))
+ boot_time = UT_TIME_MEMBER (this);
+ ++this;
+ }
+#endif
+ time_now = time (NULL);
+#if defined HAVE_PROC_UPTIME
+ if (uptime == 0)
+#endif
+ {
+ if (boot_time == 0)
+ error (EXIT_FAILURE, errno, _("couldn't get boot time"));
+ uptime = time_now - boot_time;
+ }
+ updays = uptime / 86400;
+ uphours = (uptime - (updays * 86400)) / 3600;
+ upmins = (uptime - (updays * 86400) - (uphours * 3600)) / 60;
+ tmn = localtime (&time_now);
+ if (tmn)
+ printf (_(" %2d:%02d%s up "),
+ ((tmn->tm_hour % 12) == 0 ? 12 : tmn->tm_hour % 12),
+ /* FIXME: use strftime, not am, pm. Uli reports that
+ the german translation is meaningless. */
+ tmn->tm_min, (tmn->tm_hour < 12 ? _("am") : _("pm")));
+ else
+ printf (_(" ??:???? up "));
+ if (uptime == (time_t) -1)
+ printf (_("???? days ??:??, "));
+ else
+ {
+ if (0 < updays)
+ printf (ngettext ("%ld day", "%ld days", select_plural (updays)),
+ updays);
+ printf (" %2d:%02d, ", uphours, upmins);
+ }
+ printf (ngettext ("%lu user", "%lu users", entries),
+ (unsigned long int) entries);
+
+#if defined HAVE_GETLOADAVG || defined C_GETLOADAVG
+ loads = getloadavg (avg, 3);
+#else
+ loads = -1;
+#endif
+
+ if (loads == -1)
+ putchar ('\n');
+ else
+ {
+ if (loads > 0)
+ printf (_(", load average: %.2f"), avg[0]);
+ if (loads > 1)
+ printf (", %.2f", avg[1]);
+ if (loads > 2)
+ printf (", %.2f", avg[2]);
+ if (loads > 0)
+ putchar ('\n');
+ }
+}
+
+/* Display the system uptime and the number of users on the system,
+ according to utmp file FILENAME. Use read_utmp OPTIONS to read the
+ utmp file. */
+
+static void
+uptime (const char *filename, int options)
+{
+ size_t n_users;
+ STRUCT_UTMP *utmp_buf;
+
+#if HAVE_UTMPX_H || HAVE_UTMP_H
+ if (read_utmp (filename, &n_users, &utmp_buf, options) != 0)
+ error (EXIT_FAILURE, errno, "%s", filename);
+#endif
+
+ print_uptime (n_users, utmp_buf);
+}
+
+void
+usage (int status)
+{
+ if (status != EXIT_SUCCESS)
+ fprintf (stderr, _("Try `%s --help' for more information.\n"),
+ program_name);
+ else
+ {
+ printf (_("Usage: %s [OPTION]... [ FILE ]\n"), program_name);
+ printf (_("\
+Print the current time, the length of time the system has been up,\n\
+the number of users on the system, and the average number of jobs\n\
+in the run queue over the last 1, 5 and 15 minutes.\n\
+If FILE is not specified, use %s. %s as FILE is common.\n\
+\n\
+"),
+ UTMP_FILE, WTMP_FILE);
+ fputs (HELP_OPTION_DESCRIPTION, stdout);
+ fputs (VERSION_OPTION_DESCRIPTION, stdout);
+ printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
+ }
+ exit (status);
+}
+
+int
+main (int argc, char **argv)
+{
+ initialize_main (&argc, &argv);
+ program_name = argv[0];
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+
+ atexit (close_stdout);
+
+ parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
+ usage, AUTHORS, (char const *) NULL);
+ if (getopt_long (argc, argv, "", NULL, NULL) != -1)
+ usage (EXIT_FAILURE);
+
+ switch (argc - optind)
+ {
+ case 0: /* uptime */
+ uptime (UTMP_FILE, READ_UTMP_CHECK_PIDS);
+ break;
+
+ case 1: /* uptime <utmp file> */
+ uptime (argv[optind], 0);
+ break;
+
+ default: /* lose */
+ error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));
+ usage (EXIT_FAILURE);
+ }
+
+ exit (EXIT_SUCCESS);
+}