dd: synchronize output after write errors
[coreutils.git] / src / uptime.c
blobb620885f784c554234f65049da63e93e08868060
1 /* GNU's uptime.
2 Copyright (C) 1992-2022 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 <stdio.h>
22 #include <sys/types.h>
23 #include "system.h"
25 #if HAVE_SYSCTL && HAVE_SYS_SYSCTL_H && ! defined __GLIBC__
26 # include <sys/sysctl.h>
27 #endif
29 #if HAVE_OS_H
30 # include <OS.h>
31 #endif
33 #include "c-strtod.h"
34 #include "die.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 __GLIBC__ \
84 && 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 #else
116 (void) n;
117 (void) this;
118 #endif
120 time_now = time (NULL);
121 #if defined HAVE_PROC_UPTIME
122 if (uptime == 0)
123 #endif
125 if (boot_time == 0)
126 die (EXIT_FAILURE, errno, _("couldn't get boot time"));
127 uptime = time_now - boot_time;
129 updays = uptime / 86400;
130 uphours = (uptime - (updays * 86400)) / 3600;
131 upmins = (uptime - (updays * 86400) - (uphours * 3600)) / 60;
132 tmn = localtime (&time_now);
133 /* procps' version of uptime also prints the seconds field, but
134 previous versions of coreutils don't. */
135 if (tmn)
136 /* TRANSLATORS: This prints the current clock time. */
137 fprintftime (stdout, _(" %H:%M:%S "), tmn, 0, 0);
138 else
139 printf (_(" ??:???? "));
140 if (uptime == (time_t) -1)
141 printf (_("up ???? days ??:??, "));
142 else
144 if (0 < updays)
145 printf (ngettext ("up %ld day %2d:%02d, ",
146 "up %ld days %2d:%02d, ",
147 select_plural (updays)),
148 updays, uphours, upmins);
149 else
150 printf (_("up %2d:%02d, "), uphours, upmins);
152 printf (ngettext ("%lu user", "%lu users", select_plural (entries)),
153 (unsigned long int) entries);
155 loads = getloadavg (avg, 3);
157 if (loads == -1)
158 putchar ('\n');
159 else
161 if (loads > 0)
162 printf (_(", load average: %.2f"), avg[0]);
163 if (loads > 1)
164 printf (", %.2f", avg[1]);
165 if (loads > 2)
166 printf (", %.2f", avg[2]);
167 if (loads > 0)
168 putchar ('\n');
172 /* Display the system uptime and the number of users on the system,
173 according to utmp file FILENAME. Use read_utmp OPTIONS to read the
174 utmp file. */
176 static void
177 uptime (char const *filename, int options)
179 size_t n_users;
180 STRUCT_UTMP *utmp_buf = NULL;
182 #if HAVE_UTMPX_H || HAVE_UTMP_H
183 if (read_utmp (filename, &n_users, &utmp_buf, options) != 0)
184 die (EXIT_FAILURE, errno, "%s", quotef (filename));
185 #endif
187 print_uptime (n_users, utmp_buf);
189 IF_LINT (free (utmp_buf));
192 void
193 usage (int status)
195 if (status != EXIT_SUCCESS)
196 emit_try_help ();
197 else
199 printf (_("Usage: %s [OPTION]... [FILE]\n"), program_name);
200 printf (_("\
201 Print the current time, the length of time the system has been up,\n\
202 the number of users on the system, and the average number of jobs\n\
203 in the run queue over the last 1, 5 and 15 minutes."));
204 #ifdef __linux__
205 /* It would be better to introduce a configure test for this,
206 but such a test is hard to write. For the moment then, we
207 have a hack which depends on the preprocessor used at compile
208 time to tell us what the running kernel is. Ugh. */
209 printf (_(" \
210 Processes in\n\
211 an uninterruptible sleep state also contribute to the load average.\n"));
212 #else
213 printf (_("\n"));
214 #endif
215 printf (_("\
216 If FILE is not specified, use %s. %s as FILE is common.\n\
217 \n"),
218 UTMP_FILE, WTMP_FILE);
219 fputs (HELP_OPTION_DESCRIPTION, stdout);
220 fputs (VERSION_OPTION_DESCRIPTION, stdout);
221 emit_ancillary_info (PROGRAM_NAME);
223 exit (status);
227 main (int argc, char **argv)
229 initialize_main (&argc, &argv);
230 set_program_name (argv[0]);
231 setlocale (LC_ALL, "");
232 bindtextdomain (PACKAGE, LOCALEDIR);
233 textdomain (PACKAGE);
235 atexit (close_stdout);
237 parse_gnu_standard_options_only (argc, argv, PROGRAM_NAME, PACKAGE_NAME,
238 Version, true, usage, AUTHORS,
239 (char const *) NULL);
241 switch (argc - optind)
243 case 0: /* uptime */
244 uptime (UTMP_FILE, READ_UTMP_CHECK_PIDS);
245 break;
247 case 1: /* uptime <utmp file> */
248 uptime (argv[optind], 0);
249 break;
251 default: /* lose */
252 error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));
253 usage (EXIT_FAILURE);
256 return EXIT_SUCCESS;