source: trunk/coreutils/src/uptime.c@ 2603

Last change on this file since 2603 was 2554, checked in by bird, 20 years ago

coretuils-5.94

File size: 5.9 KB
Line 
1/* GNU's uptime.
2 Copyright (C) 1992-2002, 2004, 2005 Free Software Foundation, Inc.
3
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.
8
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.
13
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18/* Created by hacking who.c by Kaveh Ghazi [email protected]. */
19
20#include <config.h>
21#include <getopt.h>
22#include <stdio.h>
23
24#include <sys/types.h>
25#include "system.h"
26
27#if HAVE_SYSCTL && HAVE_SYS_SYSCTL_H
28# include <sys/sysctl.h>
29#endif
30
31#include "c-strtod.h"
32#include "error.h"
33#include "long-options.h"
34#include "quote.h"
35#include "readutmp.h"
36
37/* The official name of this program (e.g., no `g' prefix). */
38#define PROGRAM_NAME "uptime"
39
40#define AUTHORS "Joseph Arceneaux", "David MacKenzie", "Kaveh Ghazi"
41
42int getloadavg ();
43
44/* The name this program was run with. */
45char *program_name;
46
47static void
48print_uptime (size_t n, const STRUCT_UTMP *this)
49{
50 size_t entries = 0;
51 time_t boot_time = 0;
52 time_t time_now;
53 time_t uptime = 0;
54 long int updays;
55 int uphours;
56 int upmins;
57 struct tm *tmn;
58 double avg[3];
59 int loads;
60#ifdef HAVE_PROC_UPTIME
61 FILE *fp;
62 double upsecs;
63
64 fp = fopen ("/proc/uptime", "r");
65 if (fp != NULL)
66 {
67 char buf[BUFSIZ];
68 char *b = fgets (buf, BUFSIZ, fp);
69 if (b == buf)
70 {
71 char *end_ptr;
72 upsecs = c_strtod (buf, &end_ptr);
73 if (buf != end_ptr)
74 uptime = (0 <= upsecs && upsecs < TYPE_MAXIMUM (time_t)
75 ? upsecs : -1);
76 }
77
78 fclose (fp);
79 }
80#endif /* HAVE_PROC_UPTIME */
81
82#if HAVE_SYSCTL && defined CTL_KERN && defined KERN_BOOTTIME
83 {
84 /* FreeBSD specific: fetch sysctl "kern.boottime". */
85 static int request[2] = { CTL_KERN, KERN_BOOTTIME };
86 struct timeval result;
87 size_t result_len = sizeof result;
88
89 if (sysctl (request, 2, &result, &result_len, NULL, 0) >= 0)
90 boot_time = result.tv_sec;
91 }
92#endif
93
94 /* Loop through all the utmp entries we just read and count up the valid
95 ones, also in the process possibly gleaning boottime. */
96 while (n--)
97 {
98 entries += IS_USER_PROCESS (this);
99 if (UT_TYPE_BOOT_TIME (this))
100 boot_time = UT_TIME_MEMBER (this);
101 ++this;
102 }
103 time_now = time (NULL);
104#if defined HAVE_PROC_UPTIME
105 if (uptime == 0)
106#endif
107 {
108 if (boot_time == 0)
109 error (EXIT_FAILURE, errno, _("couldn't get boot time"));
110 uptime = time_now - boot_time;
111 }
112 updays = uptime / 86400;
113 uphours = (uptime - (updays * 86400)) / 3600;
114 upmins = (uptime - (updays * 86400) - (uphours * 3600)) / 60;
115 tmn = localtime (&time_now);
116 if (tmn)
117 printf (_(" %2d:%02d%s up "),
118 ((tmn->tm_hour % 12) == 0 ? 12 : tmn->tm_hour % 12),
119 /* FIXME: use strftime, not am, pm. Uli reports that
120 the german translation is meaningless. */
121 tmn->tm_min, (tmn->tm_hour < 12 ? _("am") : _("pm")));
122 else
123 printf (_(" ??:???? up "));
124 if (uptime == (time_t) -1)
125 printf (_("???? days ??:??, "));
126 else
127 {
128 if (0 < updays)
129 printf (ngettext ("%ld day", "%ld days", updays), updays);
130 printf (" %2d:%02d, ", uphours, upmins);
131 }
132 printf (ngettext ("%lu user", "%lu users", entries),
133 (unsigned long int) entries);
134
135#if defined HAVE_GETLOADAVG || defined C_GETLOADAVG
136 loads = getloadavg (avg, 3);
137#else
138 loads = -1;
139#endif
140
141 if (loads == -1)
142 putchar ('\n');
143 else
144 {
145 if (loads > 0)
146 printf (_(", load average: %.2f"), avg[0]);
147 if (loads > 1)
148 printf (", %.2f", avg[1]);
149 if (loads > 2)
150 printf (", %.2f", avg[2]);
151 if (loads > 0)
152 putchar ('\n');
153 }
154}
155
156/* Display the system uptime and the number of users on the system,
157 according to utmp file FILENAME. Use read_utmp OPTIONS to read the
158 utmp file. */
159
160static void
161uptime (const char *filename, int options)
162{
163 size_t n_users;
164 STRUCT_UTMP *utmp_buf;
165
166 if (read_utmp (filename, &n_users, &utmp_buf, options) != 0)
167 error (EXIT_FAILURE, errno, "%s", filename);
168
169 print_uptime (n_users, utmp_buf);
170}
171
172void
173usage (int status)
174{
175 if (status != EXIT_SUCCESS)
176 fprintf (stderr, _("Try `%s --help' for more information.\n"),
177 program_name);
178 else
179 {
180 printf (_("Usage: %s [OPTION]... [ FILE ]\n"), program_name);
181 printf (_("\
182Print the current time, the length of time the system has been up,\n\
183the number of users on the system, and the average number of jobs\n\
184in the run queue over the last 1, 5 and 15 minutes.\n\
185If FILE is not specified, use %s. %s as FILE is common.\n\
186\n\
187"),
188 UTMP_FILE, WTMP_FILE);
189 fputs (HELP_OPTION_DESCRIPTION, stdout);
190 fputs (VERSION_OPTION_DESCRIPTION, stdout);
191 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
192 }
193 exit (status);
194}
195
196int
197main (int argc, char **argv)
198{
199 initialize_main (&argc, &argv);
200 program_name = argv[0];
201 setlocale (LC_ALL, "");
202 bindtextdomain (PACKAGE, LOCALEDIR);
203 textdomain (PACKAGE);
204
205 atexit (close_stdout);
206
207 parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
208 usage, AUTHORS, (char const *) NULL);