ls: --color now highlights hard linked files, too
[coreutils/bo.git] / src / uptime.c
blob95fea4b91bdcdca5b4486ef50f9ff824de284caa
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"
39 #include "fprintftime.h"
41 /* The official name of this program (e.g., no `g' prefix). */
42 #define PROGRAM_NAME "uptime"
44 #define AUTHORS \
45 proper_name ("Joseph Arceneaux"), \
46 proper_name ("David MacKenzie"), \
47 proper_name ("Kaveh Ghazi")
49 static void
50 print_uptime (size_t n, const STRUCT_UTMP *this)
52 size_t entries = 0;
53 time_t boot_time = 0;
54 time_t time_now;
55 time_t uptime = 0;
56 long int updays;
57 int uphours;
58 int upmins;
59 struct tm *tmn;
60 double avg[3];
61 int loads;
62 #ifdef HAVE_PROC_UPTIME
63 FILE *fp;
65 fp = fopen ("/proc/uptime", "r");
66 if (fp != NULL)
68 char buf[BUFSIZ];
69 char *b = fgets (buf, BUFSIZ, fp);
70 if (b == buf)
72 char *end_ptr;
73 double upsecs = c_strtod (buf, &end_ptr);
74 if (buf != end_ptr)
75 uptime = (0 <= upsecs && upsecs < TYPE_MAXIMUM (time_t)
76 ? upsecs : -1);
79 fclose (fp);
81 #endif /* HAVE_PROC_UPTIME */
83 #if HAVE_SYSCTL && defined CTL_KERN && defined KERN_BOOTTIME
85 /* FreeBSD specific: fetch sysctl "kern.boottime". */
86 static int request[2] = { CTL_KERN, KERN_BOOTTIME };
87 struct timeval result;
88 size_t result_len = sizeof result;
90 if (sysctl (request, 2, &result, &result_len, NULL, 0) >= 0)
91 boot_time = result.tv_sec;
93 #endif
95 #if HAVE_OS_H /* BeOS */
97 system_info si;
99 get_system_info (&si);
100 boot_time = si.boot_time / 1000000;
102 #endif
104 #if HAVE_UTMPX_H || HAVE_UTMP_H
105 /* Loop through all the utmp entries we just read and count up the valid
106 ones, also in the process possibly gleaning boottime. */
107 while (n--)
109 entries += IS_USER_PROCESS (this);
110 if (UT_TYPE_BOOT_TIME (this))
111 boot_time = UT_TIME_MEMBER (this);
112 ++this;
114 #endif
115 time_now = time (NULL);
116 #if defined HAVE_PROC_UPTIME
117 if (uptime == 0)
118 #endif
120 if (boot_time == 0)
121 error (EXIT_FAILURE, errno, _("couldn't get boot time"));
122 uptime = time_now - boot_time;
124 updays = uptime / 86400;
125 uphours = (uptime - (updays * 86400)) / 3600;
126 upmins = (uptime - (updays * 86400) - (uphours * 3600)) / 60;
127 tmn = localtime (&time_now);
128 /* procps' version of uptime also prints the seconds field, but
129 previous versions of coreutils don't. */
130 if (tmn)
131 /* TRANSLATORS: This prints the current clock time. */
132 fprintftime (stdout, _(" %H:%M%P "), tmn, 0, 0);
133 else
134 printf (_(" ??:???? "));
135 if (uptime == (time_t) -1)
136 printf (_("up ???? days ??:??, "));
137 else
139 if (0 < updays)
140 printf (ngettext ("up %ld day %2d:%02d, ",
141 "up %ld days %2d:%02d, ",
142 select_plural (updays)),
143 updays, uphours, upmins);
144 else
145 printf ("up %2d:%02d, ", uphours, upmins);
147 printf (ngettext ("%lu user", "%lu users", entries),
148 (unsigned long int) entries);
150 #if defined HAVE_GETLOADAVG || defined C_GETLOADAVG
151 loads = getloadavg (avg, 3);
152 #else
153 loads = -1;
154 #endif
156 if (loads == -1)
157 putchar ('\n');
158 else
160 if (loads > 0)
161 printf (_(", load average: %.2f"), avg[0]);
162 if (loads > 1)
163 printf (", %.2f", avg[1]);
164 if (loads > 2)
165 printf (", %.2f", avg[2]);
166 if (loads > 0)
167 putchar ('\n');
171 /* Display the system uptime and the number of users on the system,
172 according to utmp file FILENAME. Use read_utmp OPTIONS to read the
173 utmp file. */
175 static void
176 uptime (const char *filename, int options)
178 size_t n_users;
179 STRUCT_UTMP *utmp_buf;
181 #if HAVE_UTMPX_H || HAVE_UTMP_H
182 if (read_utmp (filename, &n_users, &utmp_buf, options) != 0)
183 error (EXIT_FAILURE, errno, "%s", filename);
184 #endif
186 print_uptime (n_users, utmp_buf);
189 void
190 usage (int status)
192 if (status != EXIT_SUCCESS)
193 fprintf (stderr, _("Try `%s --help' for more information.\n"),
194 program_name);
195 else
197 printf (_("Usage: %s [OPTION]... [FILE]\n"), program_name);
198 printf (_("\
199 Print the current time, the length of time the system has been up,\n\
200 the number of users on the system, and the average number of jobs\n\
201 in the run queue over the last 1, 5 and 15 minutes."));
202 #ifdef __linux__
203 /* It would be better to introduce a configure test for this,
204 but such a test is hard to write. For the moment then, we
205 have a hack which depends on the preprocessor used at compile
206 time to tell us what the running kernel is. Ugh. */
207 printf(_(" \
208 Processes in\n\
209 an uninterruptible sleep state also contribute to the load average.\n"));
210 #else
211 printf(_("\n"));
212 #endif
213 printf (_("\
214 If FILE is not specified, use %s. %s as FILE is common.\n\
215 \n"),
216 UTMP_FILE, WTMP_FILE);
217 fputs (HELP_OPTION_DESCRIPTION, stdout);
218 fputs (VERSION_OPTION_DESCRIPTION, stdout);
219 emit_bug_reporting_address ();
221 exit (status);
225 main (int argc, char **argv)
227 initialize_main (&argc, &argv);
228 set_program_name (argv[0]);
229 setlocale (LC_ALL, "");
230 bindtextdomain (PACKAGE, LOCALEDIR);
231 textdomain (PACKAGE);
233 atexit (close_stdout);
235 parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,
236 usage, AUTHORS, (char const *) NULL);
237 if (getopt_long (argc, argv, "", NULL, NULL) != -1)
238 usage (EXIT_FAILURE);
240 switch (argc - optind)
242 case 0: /* uptime */
243 uptime (UTMP_FILE, READ_UTMP_CHECK_PIDS);
244 break;
246 case 1: /* uptime <utmp file> */
247 uptime (argv[optind], 0);
248 break;
250 default: /* lose */
251 error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));
252 usage (EXIT_FAILURE);
255 exit (EXIT_SUCCESS);