build: ensure sys/select.h is included
[coreutils.git] / src / uptime.c
blobff1e8796a9d11f483ff321f8da5e45cce1087073
1 /* GNU's uptime.
2 Copyright (C) 1992-2019 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 <https://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 "die.h"
36 #include "error.h"
37 #include "long-options.h"
38 #include "quote.h"
39 #include "readutmp.h"
40 #include "fprintftime.h"
42 /* The official name of this program (e.g., no 'g' prefix). */
43 #define PROGRAM_NAME "uptime"
45 #define AUTHORS \
46 proper_name ("Joseph Arceneaux"), \
47 proper_name ("David MacKenzie"), \
48 proper_name ("Kaveh Ghazi")
50 static struct option const long_options[] =
52 {NULL, 0, NULL, 0}
55 static void
56 print_uptime (size_t n, const STRUCT_UTMP *this)
58 size_t entries = 0;
59 time_t boot_time = 0;
60 time_t time_now;
61 time_t uptime = 0;
62 long int updays;
63 int uphours;
64 int upmins;
65 struct tm *tmn;
66 double avg[3];
67 int loads;
68 #ifdef HAVE_PROC_UPTIME
69 FILE *fp;
71 fp = fopen ("/proc/uptime", "r");
72 if (fp != NULL)
74 char buf[BUFSIZ];
75 char *b = fgets (buf, BUFSIZ, fp);
76 if (b == buf)
78 char *end_ptr;
79 double upsecs = c_strtod (buf, &end_ptr);
80 if (buf != end_ptr)
81 uptime = (0 <= upsecs && upsecs < TYPE_MAXIMUM (time_t)
82 ? upsecs : -1);
85 fclose (fp);
87 #endif /* HAVE_PROC_UPTIME */
89 #if HAVE_SYSCTL && defined CTL_KERN && defined KERN_BOOTTIME
91 /* FreeBSD specific: fetch sysctl "kern.boottime". */
92 static int request[2] = { CTL_KERN, KERN_BOOTTIME };
93 struct timeval result;
94 size_t result_len = sizeof result;
96 if (sysctl (request, 2, &result, &result_len, NULL, 0) >= 0)
97 boot_time = result.tv_sec;
99 #endif
101 #if HAVE_OS_H /* BeOS */
103 system_info si;
105 get_system_info (&si);
106 boot_time = si.boot_time / 1000000;
108 #endif
110 #if HAVE_UTMPX_H || HAVE_UTMP_H
111 /* Loop through all the utmp entries we just read and count up the valid
112 ones, also in the process possibly gleaning boottime. */
113 while (n--)
115 entries += IS_USER_PROCESS (this);
116 if (UT_TYPE_BOOT_TIME (this))
117 boot_time = UT_TIME_MEMBER (this);
118 ++this;
120 #else
121 (void) n;
122 (void) this;
123 #endif
125 time_now = time (NULL);
126 #if defined HAVE_PROC_UPTIME
127 if (uptime == 0)
128 #endif
130 if (boot_time == 0)
131 die (EXIT_FAILURE, errno, _("couldn't get boot time"));
132 uptime = time_now - boot_time;
134 updays = uptime / 86400;
135 uphours = (uptime - (updays * 86400)) / 3600;
136 upmins = (uptime - (updays * 86400) - (uphours * 3600)) / 60;
137 tmn = localtime (&time_now);
138 /* procps' version of uptime also prints the seconds field, but
139 previous versions of coreutils don't. */
140 if (tmn)
141 /* TRANSLATORS: This prints the current clock time. */
142 fprintftime (stdout, _(" %H:%M:%S "), tmn, 0, 0);
143 else
144 printf (_(" ??:???? "));
145 if (uptime == (time_t) -1)
146 printf (_("up ???? days ??:??, "));
147 else
149 if (0 < updays)
150 printf (ngettext ("up %ld day %2d:%02d, ",
151 "up %ld days %2d:%02d, ",
152 select_plural (updays)),
153 updays, uphours, upmins);
154 else
155 printf (_("up %2d:%02d, "), uphours, upmins);
157 printf (ngettext ("%lu user", "%lu users", select_plural (entries)),
158 (unsigned long int) entries);
160 loads = getloadavg (avg, 3);
162 if (loads == -1)
163 putchar ('\n');
164 else
166 if (loads > 0)
167 printf (_(", load average: %.2f"), avg[0]);
168 if (loads > 1)
169 printf (", %.2f", avg[1]);
170 if (loads > 2)
171 printf (", %.2f", avg[2]);
172 if (loads > 0)
173 putchar ('\n');
177 /* Display the system uptime and the number of users on the system,
178 according to utmp file FILENAME. Use read_utmp OPTIONS to read the
179 utmp file. */
181 static void
182 uptime (const char *filename, int options)
184 size_t n_users;
185 STRUCT_UTMP *utmp_buf = NULL;
187 #if HAVE_UTMPX_H || HAVE_UTMP_H
188 if (read_utmp (filename, &n_users, &utmp_buf, options) != 0)
189 die (EXIT_FAILURE, errno, "%s", quotef (filename));
190 #endif
192 print_uptime (n_users, utmp_buf);
194 IF_LINT (free (utmp_buf));
197 void
198 usage (int status)
200 if (status != EXIT_SUCCESS)
201 emit_try_help ();
202 else
204 printf (_("Usage: %s [OPTION]... [FILE]\n"), program_name);
205 printf (_("\
206 Print the current time, the length of time the system has been up,\n\
207 the number of users on the system, and the average number of jobs\n\
208 in the run queue over the last 1, 5 and 15 minutes."));
209 #ifdef __linux__
210 /* It would be better to introduce a configure test for this,
211 but such a test is hard to write. For the moment then, we
212 have a hack which depends on the preprocessor used at compile
213 time to tell us what the running kernel is. Ugh. */
214 printf (_(" \
215 Processes in\n\
216 an uninterruptible sleep state also contribute to the load average.\n"));
217 #else
218 printf (_("\n"));
219 #endif
220 printf (_("\
221 If FILE is not specified, use %s. %s as FILE is common.\n\
222 \n"),
223 UTMP_FILE, WTMP_FILE);
224 fputs (HELP_OPTION_DESCRIPTION, stdout);
225 fputs (VERSION_OPTION_DESCRIPTION, stdout);
226 emit_ancillary_info (PROGRAM_NAME);
228 exit (status);
232 main (int argc, char **argv)
234 initialize_main (&argc, &argv);
235 set_program_name (argv[0]);
236 setlocale (LC_ALL, "");
237 bindtextdomain (PACKAGE, LOCALEDIR);
238 textdomain (PACKAGE);
240 atexit (close_stdout);
242 parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,
243 usage, AUTHORS, (char const *) NULL);
244 if (getopt_long (argc, argv, "", long_options, NULL) != -1)
245 usage (EXIT_FAILURE);
247 switch (argc - optind)
249 case 0: /* uptime */
250 uptime (UTMP_FILE, READ_UTMP_CHECK_PIDS);
251 break;
253 case 1: /* uptime <utmp file> */
254 uptime (argv[optind], 0);
255 break;
257 default: /* lose */
258 error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));
259 usage (EXIT_FAILURE);
262 return EXIT_SUCCESS;