]> granicus.if.org Git - procps-ng/commitdiff
Add -p|--pretty option to uptime(1) for pretty output.
authorDavid Cantrell <david.l.cantrell@gmail.com>
Wed, 22 Feb 2012 15:35:12 +0000 (10:35 -0500)
committerDavid Cantrell <david.l.cantrell@gmail.com>
Wed, 22 Feb 2012 15:35:12 +0000 (10:35 -0500)
This patch adds the -p option to the uptime(1) command, which changes
the uptime displayed from something like:

 10:35:52 up  2:33,  1 user,  load average: 1.69, 1.65, 1.63

to:

 up 2 hours, 33 minutes

I originally implemented this as the up(1) program about 14 years ago.
In 2008 or 2009, I created a patch for procps to add this functionality
to uptime and submitted it to the project.  Never heard from the
project and no new releases of procps had been made.  Then I found out
about this project and decided to port my patch to it.  So here it is.

This is really just for fun.  There is no real technical reason to
have this functionality.  But even now, 14 years later, I still get
emails asking where the source code for up is.  So I thought it would
be nice for the uptime command on Linux to sport the up functionality
by default.

AUTHORS
proc/whattime.c
proc/whattime.h
top/top.c
uptime.1
uptime.c
w.c

diff --git a/AUTHORS b/AUTHORS
index 1ad27195b26e20a3169d029028057c4d70890855..70680cf4c3ec45c59e1d16c646cb6773f00a1355 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -43,6 +43,7 @@ George Bonser <george@captech.com>
 uptime:
 Larry Greenfield <greenfie@gauss.rutgers.edu>
 Michael K. Johnson <johnsonm@sunsite.unc.edu>
+David Cantrell <david.l.cantrell@gmail.com>
 
 vmstat:
 Henry Ware <al172@yfn.ysu.edu>.
index d2785a82d0a896e1ead9b69ab16cd2585dfc4bf3..5064cec81b04115c14f81ca45e4cf46b42435cce 100644 (file)
 static char buf[128];
 static double av[3];
 
-char *sprint_uptime(void) {
+char *sprint_uptime(int human_readable) {
   struct utmp *utmpstruct;
-  int upminutes, uphours, updays;
+  int upminutes, uphours, updays, upweeks, upyears, updecades;
   int pos;
+  int comma;
   struct tm *realtime;
   time_t realseconds;
   int numuser;
@@ -38,50 +39,107 @@ char *sprint_uptime(void) {
 
 /* first get the current time */
 
-  time(&realseconds);
-  realtime = localtime(&realseconds);
-  pos = sprintf(buf, " %02d:%02d:%02d ",
-    realtime->tm_hour, realtime->tm_min, realtime->tm_sec);
+  if (!human_readable) {
+    time(&realseconds);
+    realtime = localtime(&realseconds);
+    pos = sprintf(buf, " %02d:%02d:%02d ",
+      realtime->tm_hour, realtime->tm_min, realtime->tm_sec);
+  }
 
 /* read and calculate the amount of uptime */
 
   uptime(&uptime_secs, &idle_secs);
 
-  updays = (int) uptime_secs / (60*60*24);
+  if (human_readable) {
+    updecades = (int) uptime_secs / (60*60*24*365*10);
+    upyears = ((int) uptime_secs / (60*60*24*365)) % 10;
+    upweeks = ((int) uptime_secs / (60*60*24*7)) % 52;
+    updays = ((int) uptime_secs / (60*60*24)) % 7;
+  }
+  else
+    updays = (int) uptime_secs / (60*60*24);
+
   strcat (buf, "up ");
   pos += 3;
-  if (updays)
-    pos += sprintf(buf + pos, "%d day%s, ", updays, (updays != 1) ? "s" : "");
+
+  if (!human_readable) {
+    if (updays)
+      pos += sprintf(buf + pos, "%d day%s, ", updays, (updays != 1) ? "s" : "");
+  }
+
   upminutes = (int) uptime_secs / 60;
   uphours = upminutes / 60;
   uphours = uphours % 24;
   upminutes = upminutes % 60;
-  if(uphours)
-    pos += sprintf(buf + pos, "%2d:%02d, ", uphours, upminutes);
-  else
-    pos += sprintf(buf + pos, "%d min, ", upminutes);
+
+  if (!human_readable) {
+    if(uphours)
+      pos += sprintf(buf + pos, "%2d:%02d, ", uphours, upminutes);
+    else
+      pos += sprintf(buf + pos, "%d min, ", upminutes);
 
 /* count the number of users */
 
-  numuser = 0;
-  setutent();
-  while ((utmpstruct = getutent())) {
-    if ((utmpstruct->ut_type == USER_PROCESS) &&
-       (utmpstruct->ut_name[0] != '\0'))
-      numuser++;
+    numuser = 0;
+    setutent();
+    while ((utmpstruct = getutent())) {
+      if ((utmpstruct->ut_type == USER_PROCESS) &&
+         (utmpstruct->ut_name[0] != '\0'))
+        numuser++;
+    }
+    endutent();
+
+    pos += sprintf(buf + pos, "%2d user%s, ", numuser, numuser == 1 ? "" : "s");
+
+    loadavg(&av[0], &av[1], &av[2]);
+
+    pos += sprintf(buf + pos, " load average: %.2f, %.2f, %.2f",
+                  av[0], av[1], av[2]);
   }
-  endutent();
 
-  pos += sprintf(buf + pos, "%2d user%s, ", numuser, numuser == 1 ? "" : "s");
+  if (human_readable) {
+    comma = 0;
+
+    if (updecades) {
+      pos += sprintf(buf + pos, "%d %s", updecades,
+                     updecades > 1 ? "decades" : "decade");
+      comma += 1;
+    }
 
-  loadavg(&av[0], &av[1], &av[2]);
+    if (upyears) {
+      pos += sprintf(buf + pos, "%s%d %s", comma > 0 ? ", " : "", upyears,
+                     upyears > 1 ? "years" : "year");
+      comma += 1;
+    }
 
-  pos += sprintf(buf + pos, " load average: %.2f, %.2f, %.2f",
-                av[0], av[1], av[2]);
+    if (upweeks) {
+      pos += sprintf(buf + pos, "%s%d %s", comma > 0 ? ", " : "", upweeks,
+                     upweeks > 1 ? "weeks" : "week");
+      comma += 1;
+    }
+
+    if (updays) {
+      pos += sprintf(buf + pos, "%s%d %s", comma > 0 ? ", " : "", updays,
+                     updays > 1 ? "days" : "day");
+      comma += 1;
+    }
+
+    if (uphours) {
+      pos += sprintf(buf + pos, "%s%d %s", comma > 0 ? ", " : "", uphours,
+                     uphours > 1 ? "hours" : "hour");
+      comma += 1;
+    }
+
+    if (upminutes) {
+      pos += sprintf(buf + pos, "%s%d %s", comma > 0 ? ", " : "", upminutes,
+                     upminutes > 1 ? "minutes" : "minute");
+      comma += 1;
+    }
+  }
 
   return buf;
 }
 
-void print_uptime(void) {
-  printf("%s\n", sprint_uptime());
+void print_uptime(int human_readable) {
+  printf("%s\n", sprint_uptime(human_readable));
 }
index 891ccd35c89d436dbe50cffc3473a1c9cf74411a..5ac5850176eee9004a594c0e9e3b4c7eb1801a76 100644 (file)
@@ -5,8 +5,8 @@
 
 EXTERN_C_BEGIN
 
-extern void print_uptime(void);
-extern char *sprint_uptime(void);
+extern void print_uptime(int human_readable);
+extern char *sprint_uptime(int human_readable);
 
 EXTERN_C_END
 
index 853a64eb32b137849f1c301faf4e4d3bcbe247d3..73aa2827738cb7a7027074ccdf7a72dcfd126859 100644 (file)
--- a/top/top.c
+++ b/top/top.c
@@ -3388,10 +3388,10 @@ static void summary_show (void) {
    // Display Uptime and Loadavg
    if (isROOM(View_LOADAV, 1)) {
       if (!Rc.mode_altscr)
-         show_special(0, fmtmk(LOADAV_line, Myname, sprint_uptime()));
+         show_special(0, fmtmk(LOADAV_line, Myname, sprint_uptime(0)));
       else
          show_special(0, fmtmk(CHKw(w, Show_TASKON)? LOADAV_line_alt : LOADAV_line
-            , w->grpname, sprint_uptime()));
+            , w->grpname, sprint_uptime(0)));
       Msg_row += 1;
    }
 
index e5fac2eea1724038028cbebaaacb4af09f5a8a77..9b5dd0cd70bf64670dd5f1e31e24b0c7b7de0240 100644 (file)
--- a/uptime.1
+++ b/uptime.1
@@ -25,6 +25,9 @@ is loaded all the time while on a 4 CPU system it means it was idle 75% of
 the time.
 .SH OPTIONS
 .TP
+\fB\-p\fR, \fB\-\-pretty\fR
+show uptime in pretty format
+.TP
 \fB\-h\fR, \fB\-\-help\fR
 display this help text
 .TP
index 8957ce14c683e5ef1d37313f7bdf805a57496ac4..557b08ced132866b16bbf688ede9142a189d8234 100644 (file)
--- a/uptime.c
+++ b/uptime.c
@@ -13,6 +13,7 @@ static void __attribute__ ((__noreturn__)) usage(FILE * out)
        fputs(USAGE_HEADER, out);
        fprintf(out, _(" %s [options]\n"), program_invocation_short_name);
        fputs(USAGE_OPTIONS, out);
+       fputs(_(" -p, --pretty   show uptime in pretty format\n"), out);
        fputs(USAGE_HELP, out);
        fputs(USAGE_VERSION, out);
        fprintf(out, USAGE_MAN_TAIL("uptime(1)"));
@@ -22,9 +23,10 @@ static void __attribute__ ((__noreturn__)) usage(FILE * out)
 
 int main(int argc, char **argv)
 {
-       int c;
+       int c, p = 0;
 
        static const struct option longopts[] = {
+               {"pretty", no_argument, NULL, 'p'},
                {"help", no_argument, NULL, 'h'},
                {"version", no_argument, NULL, 'V'},
                {NULL, 0, NULL, 0}
@@ -35,8 +37,11 @@ int main(int argc, char **argv)
        bindtextdomain(PACKAGE, LOCALEDIR);
        textdomain(PACKAGE);
 
-       while ((c = getopt_long(argc, argv, "hV", longopts, NULL)) != -1)
+       while ((c = getopt_long(argc, argv, "phV", longopts, NULL)) != -1)
                switch (c) {
+               case 'p':
+                       p = 1;
+                       break;
                case 'h':
                        usage(stdout);
                case 'V':
@@ -46,6 +51,6 @@ int main(int argc, char **argv)
                        usage(stderr);
                }
 
-       print_uptime();
+       print_uptime(p);
        return EXIT_SUCCESS;
 }
diff --git a/w.c b/w.c
index cded1623b7211bb94502fb10ab41d8261ef25661..0dbe33396ac15afaec3cac7fa9a6ee666097f08e 100644 (file)
--- a/w.c
+++ b/w.c
@@ -424,7 +424,7 @@ int main(int argc, char **argv)
 
        if (header) {
                /* print uptime and headers */
-               print_uptime();
+               print_uptime(0);
                /* Translation Hint: Following five uppercase messages are
                 * headers. Try to keep alignment intact.  */
                printf(_("%-*s TTY      "), userlen, _("USER"));