ls: --color now highlights files with capabilities, too
[coreutils.git] / src / uptime.c
blob9e3384fc8aca4a4088e68a30119a22afdfe86c64
1 /* GNU's uptime.
2 Copyright (C) 1992-2002, 2004-2008 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 3 of the License, or
7 (at your option) 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, see <http://www.gnu.org/licenses/>. */
17 /* Created by hacking who.c by Kaveh Ghazi ghazi@caip.rutgers.edu. */
19 #include <config.h>
20 #include <getopt.h>
21 #include <stdio.h>
23 #include <sys/types.h>
24 #include "system.h"
26 #if HAVE_SYSCTL && HAVE_SYS_SYSCTL_H
27 # include <sys/sysctl.h>
28 #endif
30 #if HAVE_OS_H
31 # include <OS.h>
32 #endif
34 #include "c-strtod.h"
35 #include "error.h"
36 #include "long-options.h"
37 #include "quote.h"
38 #include "readutmp.h"
40 /* The official name of this program (e.g., no `g' prefix). */
41 #define PROGRAM_NAME "uptime"
43 #define AUTHORS \
44 proper_name ("Joseph Arceneaux"), \
45 proper_name ("David MacKenzie"), \
46 proper_name ("Kaveh Ghazi")
48 int getloadavg ();
50 static void
51 print_uptime (size_t n, const STRUCT_UTMP *this)
53 size_t entries = 0;
54 time_t boot_time = 0;
55 time_t time_now;
56 time_t uptime = 0;
57 long 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;
66 fp = fopen ("/proc/uptime", "r");
67 if (fp != NULL)
69 char buf[BUFSIZ];
70 char *b = fgets (buf, BUFSIZ, fp);
71 if (b == buf)
73 char *end_ptr;
74 double upsecs = c_strtod (buf, &end_ptr);
75 if (buf != end_ptr)
76 uptime = (0 <= upsecs && upsecs < TYPE_MAXIMUM (time_t)
77 ? upsecs : -1);
80 fclose (fp);
82 #endif /* HAVE_PROC_UPTIME */
84 #if HAVE_SYSCTL && defined CTL_KERN && defined KERN_BOOTTIME
86 /* FreeBSD specific: fetch sysctl "kern.boottime". */
87 static int request[2] = { CTL_KERN, KERN_BOOTTIME };
88 struct timeval result;
89 size_t result_len = sizeof result;
91 if (sysctl (request, 2, &result, &result_len, NULL, 0) >= 0)
92 boot_time = result.tv_sec;
94 #endif
96 #if HAVE_OS_H /* BeOS */
98 system_info si;
100 get_system_info (&si);
101 boot_time = si.boot_time / 1000000;
103 #endif
105 #if HAVE_UTMPX_H || HAVE_UTMP_H
106 /* Loop through all the utmp entries we just read and count up the valid
107 ones, also in the process possibly gleaning boottime. */
108 while (n--)
110 entries += IS_USER_PROCESS (this);
111 if (UT_TYPE_BOOT_TIME (this))
112 boot_time = UT_TIME_MEMBER (this);
113 ++this;
115 #endif
116 time_now = time (NULL);
117 #if defined HAVE_PROC_UPTIME
118 if (uptime == 0)
119 #endif
121 if (boot_time == 0)
122 error (EXIT_FAILURE, errno, _("couldn't get boot time"));
123 uptime = time_now - boot_time;
125 updays = uptime / 86400;
126 uphours = (uptime - (updays * 86400)) / 3600;
127 upmins = (uptime - (updays * 86400) - (uphours * 3600)) / 60;
128 tmn = localtime (&time_now);
129 if (tmn)
130 printf (_(" %2d:%02d%s up "),
131 ((tmn->tm_hour % 12) == 0 ? 12 : tmn->tm_hour % 12),
132 /* FIXME: use strftime, not am, pm. Uli reports that
133 the german translation is meaningless. */
134 tmn->tm_min, (tmn->tm_hour < 12 ? _("am") : _("pm")));
135 else
136 printf (_(" ??:???? up "));
137 if (uptime == (time_t) -1)
138 printf (_("???? days ??:??, "));
139 else
141 if (0 < updays)
142 printf (ngettext ("%ld day", "%ld days", select_plural (updays)),
143 updays);
144 printf (" %2d:%02d, ", uphours, upmins);
146 printf (ngettext ("%lu user", "%lu users", entries),
147 (unsigned long int) entries);
149 #if defined HAVE_GETLOADAVG || defined C_GETLOADAVG
150 loads = getloadavg (avg, 3);
151 #else
152 loads = -1;
153 #endif
155 if (loads == -1)
156 putchar ('\n');
157 else
159 if (loads > 0)
160 printf (_(", load average: %.2f"), avg[0]);
161 if (loads > 1)
162 printf (", %.2f", avg[1]);
163 if (loads > 2)
164 printf (", %.2f", avg[2]);
165 if (loads > 0)
166 putchar ('\n');
170 /* Display the system uptime and the number of users on the system,
171 according to utmp file FILENAME. Use read_utmp OPTIONS to read the
172 utmp file. */
174 static void
175 uptime (const char *filename, int options)
177 size_t n_users;
178 STRUCT_UTMP *utmp_buf;
180 #if HAVE_UTMPX_H || HAVE_UTMP_H
181 if (read_utmp (filename, &n_users, &utmp_buf, options) != 0)
182 error (EXIT_FAILURE, errno, "%s", filename);
183 #endif
185 print_uptime (n_users, utmp_buf);
188 void
189 usage (int status)
191 if (status != EXIT_SUCCESS)
192 fprintf (stderr, _("Try `%s --help' for more information.\n"),
193 program_name);
194 else
196 printf (_("Usage: %s [OPTION]... [ FILE ]\n"), program_name);
197 printf (_("\
198 Print the current time, the length of time the system has been up,\n\
199 the number of users on the system, and the average number of jobs\n\
200 in the run queue over the last 1, 5 and 15 minutes.\n\
201 If FILE is not specified, use %s. %s as FILE is common.\n\
204 UTMP_FILE, WTMP_FILE);
205 fputs (HELP_OPTION_DESCRIPTION, stdout);
206 fputs (VERSION_OPTION_DESCRIPTION, stdout);
207 emit_bug_reporting_address ();
209 exit (status);
213 main (int argc, char **argv)
215 initialize_main (&argc, &argv);
216 set_program_name (argv[0]);
217 setlocale (LC_ALL, "");
218 bindtextdomain (PACKAGE, LOCALEDIR);
219 textdomain (PACKAGE);
221 atexit (close_stdout);
223 parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, VERSION,
224 usage, AUTHORS, (char const *) NULL);
225 if (getopt_long (argc, argv, "", NULL, NULL) != -1)
226 usage (EXIT_FAILURE);
228 switch (argc - optind)
230 case 0: /* uptime */
231 uptime (UTMP_FILE, READ_UTMP_CHECK_PIDS);
232 break;
234 case 1: /* uptime <utmp file> */
235 uptime (argv[optind], 0);
236 break;
238 default: /* lose */
239 error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));
240 usage (EXIT_FAILURE);
243 exit (EXIT_SUCCESS);