*** empty log message ***
[coreutils.git] / src / uptime.c
blob5c644c4c09f70307b484f609fc8c3356e57cd29b
1 /* GNU's uptime.
2 Copyright (C) 1992-2002 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Created by hacking who.c by Kaveh Ghazi ghazi@caip.rutgers.edu. */
20 #include <config.h>
21 #include <getopt.h>
22 #include <stdio.h>
24 #include <sys/types.h>
25 #include "system.h"
27 #if HAVE_SYSCTL && HAVE_SYS_SYSCTL_H
28 # include <sys/sysctl.h>
29 #endif
31 #include "error.h"
32 #include "long-options.h"
33 #include "readutmp.h"
34 #include "closeout.h"
36 /* The official name of this program (e.g., no `g' prefix). */
37 #define PROGRAM_NAME "uptime"
39 #define AUTHORS N_ ("Joseph Arceneaux, David MacKenzie, and Kaveh Ghazi")
41 int getloadavg ();
43 /* The name this program was run with. */
44 char *program_name;
46 static struct option const longopts[] =
48 {NULL, 0, NULL, 0}
51 static void
52 print_uptime (int n, const STRUCT_UTMP *this)
54 register int entries = 0;
55 time_t boot_time = 0;
56 time_t time_now;
57 time_t uptime = 0;
58 int updays;
59 int uphours;
60 int upmins;
61 struct tm *tmn;
62 double avg[3];
63 int loads;
64 #ifdef HAVE_PROC_UPTIME
65 FILE *fp;
66 double upsecs;
68 fp = fopen ("/proc/uptime", "r");
69 if (fp != NULL)
71 char buf[BUFSIZ];
72 int res;
73 char *b = fgets (buf, BUFSIZ, fp);
74 if (b == buf)
76 /* The following sscanf must use the C locale. */
77 setlocale (LC_NUMERIC, "C");
78 res = sscanf (buf, "%lf", &upsecs);
79 setlocale (LC_NUMERIC, "");
80 if (res == 1)
81 uptime = (time_t) upsecs;
84 fclose (fp);
86 #endif /* HAVE_PROC_UPTIME */
88 #if HAVE_SYSCTL && defined CTL_KERN && defined KERN_BOOTTIME
90 /* FreeBSD specific: fetch sysctl "kern.boottime". */
91 static int request[2] = { CTL_KERN, KERN_BOOTTIME };
92 struct timeval result;
93 size_t result_len = sizeof result;
95 if (sysctl (request, 2, &result, &result_len, NULL, 0) >= 0)
96 boot_time = result.tv_sec;
98 #endif
100 /* Loop through all the utmp entries we just read and count up the valid
101 ones, also in the process possibly gleaning boottime. */
102 while (n--)
104 if (UT_USER (this) [0]
105 #ifdef USER_PROCESS
106 && this->ut_type == USER_PROCESS
107 #endif
110 ++entries;
112 /* If BOOT_MSG is defined, we can get boottime from utmp. This avoids
113 possibly needing special privs to read /dev/kmem. */
114 #ifdef BOOT_MSG
115 # if HAVE_PROC_UPTIME
116 if (uptime == 0)
117 # endif /* HAVE_PROC_UPTIME */
118 if (STREQ (this->ut_line, BOOT_MSG))
119 boot_time = UT_TIME_MEMBER (this);
120 #endif /* BOOT_MSG */
121 ++this;
123 time_now = time (0);
124 #if defined HAVE_PROC_UPTIME
125 if (uptime == 0)
126 #endif
128 if (boot_time == 0)
129 error (1, errno, _("couldn't get boot time"));
130 uptime = time_now - boot_time;
132 updays = uptime / 86400;
133 uphours = (uptime - (updays * 86400)) / 3600;
134 upmins = (uptime - (updays * 86400) - (uphours * 3600)) / 60;
135 tmn = localtime (&time_now);
136 printf (_(" %2d:%02d%s up "), ((tmn->tm_hour % 12) == 0
137 ? 12 : tmn->tm_hour % 12),
138 /* FIXME: use strftime, not am, pm. Uli reports that
139 the german translation is meaningless. */
140 tmn->tm_min, (tmn->tm_hour < 12 ? _("am") : _("pm")));
141 if (updays > 0)
142 printf (ngettext("%d day", "%d days", updays), updays);
143 printf (" %2d:%02d, ", uphours, upmins);
144 printf (ngettext ("%d user", "%d users", entries), entries);
146 #if defined (HAVE_GETLOADAVG) || defined (C_GETLOADAVG)
147 loads = getloadavg (avg, 3);
148 #else
149 loads = -1;
150 #endif
152 if (loads == -1)
153 putchar ('\n');
154 else
156 if (loads > 0)
157 printf (_(", load average: %.2f"), avg[0]);
158 if (loads > 1)
159 printf (", %.2f", avg[1]);
160 if (loads > 2)
161 printf (", %.2f", avg[2]);
162 if (loads > 0)
163 putchar ('\n');
167 /* Display the system uptime and the number of users on the system,
168 according to utmp file FILENAME. */
170 static void
171 uptime (const char *filename)
173 int n_users;
174 STRUCT_UTMP *utmp_buf;
175 int fail = read_utmp (filename, &n_users, &utmp_buf);
177 if (fail)
178 error (1, errno, "%s", filename);
180 print_uptime (n_users, utmp_buf);
183 void
184 usage (int status)
186 if (status != 0)
187 fprintf (stderr, _("Try `%s --help' for more information.\n"),
188 program_name);
189 else
191 printf (_("Usage: %s [OPTION]... [ FILE ]\n"), program_name);
192 printf (_("\
193 Print the current time, the length of time the system has been up,\n\
194 the number of users on the system, and the average number of jobs\n\
195 in the run queue over the last 1, 5 and 15 minutes.\n\
196 If FILE is not specified, use %s. %s as FILE is common.\n\
199 UTMP_FILE, WTMP_FILE);
200 fputs (HELP_OPTION_DESCRIPTION, stdout);
201 fputs (VERSION_OPTION_DESCRIPTION, stdout);
202 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
204 exit (status);
208 main (int argc, char **argv)
210 int optc, longind;
211 program_name = argv[0];
212 setlocale (LC_ALL, "");
213 bindtextdomain (PACKAGE, LOCALEDIR);
214 textdomain (PACKAGE);
216 atexit (close_stdout);
218 parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
219 AUTHORS, usage);
221 while ((optc = getopt_long (argc, argv, "", longopts, &longind)) != -1)
223 switch (optc)
225 case 0:
226 break;
228 default:
229 usage (1);
233 switch (argc - optind)
235 case 0: /* uptime */
236 uptime (UTMP_FILE);
237 break;
239 case 1: /* uptime <utmp file> */
240 uptime (argv[optind]);
241 break;
243 default: /* lose */
244 error (0, 0, _("too many arguments"));
245 usage (1);
248 exit (0);