Tizen 2.0 Release
[external/tizen-coreutils.git] / src / uptime.c
1 /* GNU's uptime.
2    Copyright (C) 1992-2002, 2004, 2005, 2006 Free Software Foundation, Inc.
3
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.
8
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.
13
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.  */
17
18 /* Created by hacking who.c by Kaveh Ghazi ghazi@caip.rutgers.edu.  */
19
20 #include <config.h>
21 #include <getopt.h>
22 #include <stdio.h>
23
24 #include <sys/types.h>
25 #include "system.h"
26
27 #if HAVE_SYSCTL && HAVE_SYS_SYSCTL_H
28 # include <sys/sysctl.h>
29 #endif
30
31 #if HAVE_OS_H
32 # include <OS.h>
33 #endif
34
35 #include "c-strtod.h"
36 #include "error.h"
37 #include "long-options.h"
38 #include "quote.h"
39 #include "readutmp.h"
40
41 /* The official name of this program (e.g., no `g' prefix).  */
42 #define PROGRAM_NAME "uptime"
43
44 #define AUTHORS "Joseph Arceneaux", "David MacKenzie", "Kaveh Ghazi"
45
46 int getloadavg ();
47
48 /* The name this program was run with. */
49 char *program_name;
50
51 static void
52 print_uptime (size_t n, const STRUCT_UTMP *this)
53 {
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;
66
67   fp = fopen ("/proc/uptime", "r");
68   if (fp != NULL)
69     {
70       char buf[BUFSIZ];
71       char *b = fgets (buf, BUFSIZ, fp);
72       if (b == buf)
73         {
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);
79         }
80
81       fclose (fp);
82     }
83 #endif /* HAVE_PROC_UPTIME */
84
85 #if HAVE_SYSCTL && defined CTL_KERN && defined KERN_BOOTTIME
86   {
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;
91
92     if (sysctl (request, 2, &result, &result_len, NULL, 0) >= 0)
93       boot_time = result.tv_sec;
94   }
95 #endif
96
97 #if HAVE_OS_H /* BeOS */
98   {
99     system_info si;
100
101     get_system_info (&si);
102     boot_time = si.boot_time / 1000000;
103   }
104 #endif
105
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--)
110     {
111       entries += IS_USER_PROCESS (this);
112       if (UT_TYPE_BOOT_TIME (this))
113         boot_time = UT_TIME_MEMBER (this);
114       ++this;
115     }
116 #endif
117   time_now = time (NULL);
118 #if defined HAVE_PROC_UPTIME
119   if (uptime == 0)
120 #endif
121     {
122       if (boot_time == 0)
123         error (EXIT_FAILURE, errno, _("couldn't get boot time"));
124       uptime = time_now - boot_time;
125     }
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
141     {
142       if (0 < updays)
143         printf (ngettext ("%ld day", "%ld days", select_plural (updays)),
144                 updays);
145       printf (" %2d:%02d,  ", uphours, upmins);
146     }
147   printf (ngettext ("%lu user", "%lu users", entries),
148           (unsigned long int) entries);
149
150 #if defined HAVE_GETLOADAVG || defined C_GETLOADAVG
151   loads = getloadavg (avg, 3);
152 #else
153   loads = -1;
154 #endif
155
156   if (loads == -1)
157     putchar ('\n');
158   else
159     {
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');
168     }
169 }
170
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.  */
174
175 static void
176 uptime (const char *filename, int options)
177 {
178   size_t n_users;
179   STRUCT_UTMP *utmp_buf;
180
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
185
186   print_uptime (n_users, utmp_buf);
187 }
188
189 void
190 usage (int status)
191 {
192   if (status != EXIT_SUCCESS)
193     fprintf (stderr, _("Try `%s --help' for more information.\n"),
194              program_name);
195   else
196     {
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\
203 \n\
204 "),
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);
209     }
210   exit (status);
211 }
212
213 int
214 main (int argc, char **argv)
215 {
216   initialize_main (&argc, &argv);
217   program_name = argv[0];
218   setlocale (LC_ALL, "");
219   bindtextdomain (PACKAGE, LOCALEDIR);
220   textdomain (PACKAGE);
221
222   atexit (close_stdout);
223
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);
228
229   switch (argc - optind)
230     {
231     case 0:                     /* uptime */
232       uptime (UTMP_FILE, READ_UTMP_CHECK_PIDS);
233       break;
234
235     case 1:                     /* uptime <utmp file> */
236       uptime (argv[optind], 0);
237       break;
238
239     default:                    /* lose */
240       error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));
241       usage (EXIT_FAILURE);
242     }
243
244   exit (EXIT_SUCCESS);
245 }