* src/dd.c (flags): noatime and nofollow now depend on
[coreutils/bo.git] / src / uptime.c
blob6b2a7240a4efb079356e3f0cf727298d9e26a01d
1 /* GNU's uptime.
2 Copyright (C) 1992-2002, 2004, 2005, 2006 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 2, or (at your option)
7 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, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18 /* Created by hacking who.c by Kaveh Ghazi ghazi@caip.rutgers.edu. */
20 #include <config.h>
21 #include <getopt.h>
22 #include <stdio.h>
24 #include <sys/types.h>
25 #include "system.h"
27 #if HAVE_SYSCTL && HAVE_SYS_SYSCTL_H
28 # include <sys/sysctl.h>
29 #endif
31 #if HAVE_OS_H
32 # include <OS.h>
33 #endif
35 #include "c-strtod.h"
36 #include "error.h"
37 #include "long-options.h"
38 #include "quote.h"
39 #include "readutmp.h"
41 /* The official name of this program (e.g., no `g' prefix). */
42 #define PROGRAM_NAME "uptime"
44 #define AUTHORS "Joseph Arceneaux", "David MacKenzie", "Kaveh Ghazi"
46 int getloadavg ();
48 /* The name this program was run with. */
49 char *program_name;
51 static void
52 print_uptime (size_t n, const STRUCT_UTMP *this)
54 size_t entries = 0;
55 time_t boot_time = 0;
56 time_t time_now;
57 time_t uptime = 0;
58 long int updays;
59 int uphours;
60 int upmins;
61 struct tm *tmn;
62 double avg[3];
63 int loads;
64 #ifdef HAVE_PROC_UPTIME
65 FILE *fp;
67 fp = fopen ("/proc/uptime", "r");
68 if (fp != NULL)
70 char buf[BUFSIZ];
71 char *b = fgets (buf, BUFSIZ, fp);
72 if (b == buf)
74 char *end_ptr;
75 double upsecs = c_strtod (buf, &end_ptr);
76 if (buf != end_ptr)
77 uptime = (0 <= upsecs && upsecs < TYPE_MAXIMUM (time_t)
78 ? upsecs : -1);
81 fclose (fp);
83 #endif /* HAVE_PROC_UPTIME */
85 #if HAVE_SYSCTL && defined CTL_KERN && defined KERN_BOOTTIME
87 /* FreeBSD specific: fetch sysctl "kern.boottime". */
88 static int request[2] = { CTL_KERN, KERN_BOOTTIME };
89 struct timeval result;
90 size_t result_len = sizeof result;
92 if (sysctl (request, 2, &result, &result_len, NULL, 0) >= 0)
93 boot_time = result.tv_sec;
95 #endif
97 #if HAVE_OS_H /* BeOS */
99 system_info si;
101 get_system_info (&si);
102 boot_time = si.boot_time / 1000000;
104 #endif
106 #if HAVE_UTMPX_H || HAVE_UTMP_H
107 /* Loop through all the utmp entries we just read and count up the valid
108 ones, also in the process possibly gleaning boottime. */
109 while (n--)
111 entries += IS_USER_PROCESS (this);
112 if (UT_TYPE_BOOT_TIME (this))
113 boot_time = UT_TIME_MEMBER (this);
114 ++this;
116 #endif
117 time_now = time (NULL);
118 #if defined HAVE_PROC_UPTIME
119 if (uptime == 0)
120 #endif
122 if (boot_time == 0)
123 error (EXIT_FAILURE, errno, _("couldn't get boot time"));
124 uptime = time_now - boot_time;
126 updays = uptime / 86400;
127 uphours = (uptime - (updays * 86400)) / 3600;
128 upmins = (uptime - (updays * 86400) - (uphours * 3600)) / 60;
129 tmn = localtime (&time_now);
130 if (tmn)
131 printf (_(" %2d:%02d%s up "),
132 ((tmn->tm_hour % 12) == 0 ? 12 : tmn->tm_hour % 12),
133 /* FIXME: use strftime, not am, pm. Uli reports that
134 the german translation is meaningless. */
135 tmn->tm_min, (tmn->tm_hour < 12 ? _("am") : _("pm")));
136 else
137 printf (_(" ??:???? up "));
138 if (uptime == (time_t) -1)
139 printf (_("???? days ??:??, "));
140 else
142 if (0 < updays)
143 printf (ngettext ("%ld day", "%ld days", select_plural (updays)),
144 updays);
145 printf (" %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.\n\
202 If FILE is not specified, use %s. %s as FILE is common.\n\
205 UTMP_FILE, WTMP_FILE);
206 fputs (HELP_OPTION_DESCRIPTION, stdout);
207 fputs (VERSION_OPTION_DESCRIPTION, stdout);
208 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
210 exit (status);
214 main (int argc, char **argv)
216 initialize_main (&argc, &argv);
217 program_name = argv[0];
218 setlocale (LC_ALL, "");
219 bindtextdomain (PACKAGE, LOCALEDIR);
220 textdomain (PACKAGE);
222 atexit (close_stdout);
224 parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
225 usage, AUTHORS, (char const *) NULL);
226 if (getopt_long (argc, argv, "", NULL, NULL) != -1)
227 usage (EXIT_FAILURE);
229 switch (argc - optind)
231 case 0: /* uptime */
232 uptime (UTMP_FILE, READ_UTMP_CHECK_PIDS);
233 break;
235 case 1: /* uptime <utmp file> */
236 uptime (argv[optind], 0);
237 break;
239 default: /* lose */
240 error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));
241 usage (EXIT_FAILURE);
244 exit (EXIT_SUCCESS);