.
[coreutils.git] / src / uptime.c
blob3c746f57b24a63387af4fd68bf801f9bcb2d0a8b
1 /* GNU's uptime.
2 Copyright (C) 1992-2002, 2004 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"
35 /* The official name of this program (e.g., no `g' prefix). */
36 #define PROGRAM_NAME "uptime"
38 #define AUTHORS "Joseph Arceneaux", "David MacKenzie", "Kaveh Ghazi"
40 int getloadavg ();
42 /* The name this program was run with. */
43 char *program_name;
45 static struct option const longopts[] =
47 {NULL, 0, NULL, 0}
50 static void
51 print_uptime (int n, const STRUCT_UTMP *this)
53 register int entries = 0;
54 time_t boot_time = 0;
55 time_t time_now;
56 time_t uptime = 0;
57 int updays;
58 int uphours;
59 int upmins;
60 struct tm *tmn;
61 double avg[3];
62 int loads;
63 #ifdef HAVE_PROC_UPTIME
64 FILE *fp;
65 double upsecs;
67 fp = fopen ("/proc/uptime", "r");
68 if (fp != NULL)
70 char buf[BUFSIZ];
71 int res;
72 char *b = fgets (buf, BUFSIZ, fp);
73 if (b == buf)
75 /* The following sscanf must use the C locale. */
76 setlocale (LC_NUMERIC, "C");
77 res = sscanf (buf, "%lf", &upsecs);
78 setlocale (LC_NUMERIC, "");
79 if (res == 1)
80 uptime = (time_t) upsecs;
83 fclose (fp);
85 #endif /* HAVE_PROC_UPTIME */
87 #if HAVE_SYSCTL && defined CTL_KERN && defined KERN_BOOTTIME
89 /* FreeBSD specific: fetch sysctl "kern.boottime". */
90 static int request[2] = { CTL_KERN, KERN_BOOTTIME };
91 struct timeval result;
92 size_t result_len = sizeof result;
94 if (sysctl (request, 2, &result, &result_len, NULL, 0) >= 0)
95 boot_time = result.tv_sec;
97 #endif
99 /* Loop through all the utmp entries we just read and count up the valid
100 ones, also in the process possibly gleaning boottime. */
101 while (n--)
103 if (UT_USER (this) [0]
104 #ifdef USER_PROCESS
105 && this->ut_type == USER_PROCESS
106 #endif
109 ++entries;
111 /* If BOOT_MSG is defined, we can get boottime from utmp. This avoids
112 possibly needing special privs to read /dev/kmem. */
113 #ifdef BOOT_MSG
114 # if HAVE_PROC_UPTIME
115 if (uptime == 0)
116 # endif /* HAVE_PROC_UPTIME */
117 if (STREQ (this->ut_line, BOOT_MSG))
118 boot_time = UT_TIME_MEMBER (this);
119 #endif /* BOOT_MSG */
120 ++this;
122 time_now = time (0);
123 #if defined HAVE_PROC_UPTIME
124 if (uptime == 0)
125 #endif
127 if (boot_time == 0)
128 error (EXIT_FAILURE, errno, _("couldn't get boot time"));
129 uptime = time_now - boot_time;
131 updays = uptime / 86400;
132 uphours = (uptime - (updays * 86400)) / 3600;
133 upmins = (uptime - (updays * 86400) - (uphours * 3600)) / 60;
134 tmn = localtime (&time_now);
135 if (tmn)
136 printf (_(" %2d:%02d%s up "),
137 ((tmn->tm_hour % 12) == 0 ? 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 else
142 printf (_(" ??:???? up "));
143 if (updays > 0)
144 printf (ngettext("%d day", "%d days", updays), updays);
145 printf (" %2d:%02d, ", uphours, upmins);
146 printf (ngettext ("%d user", "%d users", entries), entries);
148 #if defined (HAVE_GETLOADAVG) || defined (C_GETLOADAVG)
149 loads = getloadavg (avg, 3);
150 #else
151 loads = -1;
152 #endif
154 if (loads == -1)
155 putchar ('\n');
156 else
158 if (loads > 0)
159 printf (_(", load average: %.2f"), avg[0]);
160 if (loads > 1)
161 printf (", %.2f", avg[1]);
162 if (loads > 2)
163 printf (", %.2f", avg[2]);
164 if (loads > 0)
165 putchar ('\n');
169 /* Display the system uptime and the number of users on the system,
170 according to utmp file FILENAME. */
172 static void
173 uptime (const char *filename)
175 int n_users;
176 STRUCT_UTMP *utmp_buf;
177 int fail = read_utmp (filename, &n_users, &utmp_buf);
179 if (fail)
180 error (EXIT_FAILURE, errno, "%s", filename);
182 print_uptime (n_users, utmp_buf);
185 void
186 usage (int status)
188 if (status != EXIT_SUCCESS)
189 fprintf (stderr, _("Try `%s --help' for more information.\n"),
190 program_name);
191 else
193 printf (_("Usage: %s [OPTION]... [ FILE ]\n"), program_name);
194 printf (_("\
195 Print the current time, the length of time the system has been up,\n\
196 the number of users on the system, and the average number of jobs\n\
197 in the run queue over the last 1, 5 and 15 minutes.\n\
198 If FILE is not specified, use %s. %s as FILE is common.\n\
201 UTMP_FILE, WTMP_FILE);
202 fputs (HELP_OPTION_DESCRIPTION, stdout);
203 fputs (VERSION_OPTION_DESCRIPTION, stdout);
204 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
206 exit (status);
210 main (int argc, char **argv)
212 int optc, longind;
213 initialize_main (&argc, &argv);
214 program_name = argv[0];
215 setlocale (LC_ALL, "");
216 bindtextdomain (PACKAGE, LOCALEDIR);
217 textdomain (PACKAGE);
219 atexit (close_stdout);
221 parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
222 usage, AUTHORS, (char const *) NULL);
224 while ((optc = getopt_long (argc, argv, "", longopts, &longind)) != -1)
226 switch (optc)
228 case 0:
229 break;
231 default:
232 usage (EXIT_FAILURE);
236 switch (argc - optind)
238 case 0: /* uptime */
239 uptime (UTMP_FILE);
240 break;
242 case 1: /* uptime <utmp file> */
243 uptime (argv[optind]);
244 break;
246 default: /* lose */
247 error (0, 0, _("too many arguments"));
248 usage (EXIT_FAILURE);
251 exit (EXIT_SUCCESS);