1/*
2 * Copyright (c) 2009-2010 Todd C. Miller <Todd.Miller@courtesan.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include <config.h>
18
19#include <sys/param.h>
20#include <sys/types.h>
21#include <sys/time.h>
22
23#include <stdio.h>
24#ifdef STDC_HEADERS
25# include <stdlib.h>
26# include <stddef.h>
27#else
28# ifdef HAVE_STDLIB_H
29#  include <stdlib.h>
30# endif
31#endif /* STDC_HEADERS */
32#ifdef HAVE_STRING_H
33# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
34#  include <memory.h>
35# endif
36# include <string.h>
37#endif /* HAVE_STRING_H */
38#ifdef HAVE_STRINGS_H
39# include <strings.h>
40#endif /* HAVE_STRINGS_H */
41#include <limits.h>
42#if TIME_WITH_SYS_TIME
43# include <time.h>
44#endif
45#ifdef HAVE_GETUTXID
46# include <utmpx.h>
47#endif
48#ifdef HAVE_GETUTID
49# include <utmp.h>
50#endif
51#ifdef HAVE_SYSCTL
52# include <sys/sysctl.h>
53#endif
54
55#include "missing.h"
56
57/*
58 * Fill in a struct timeval with the time the system booted.
59 * Returns 1 on success and 0 on failure.
60 */
61
62#if defined(__linux__)
63int
64get_boottime(tv)
65    struct timeval *tv;
66{
67    char *line = NULL;
68    size_t linesize = 0;
69    ssize_t len;
70    FILE * fp;
71
72    /* read btime from /proc/stat */
73    fp = fopen("/proc/stat", "r");
74    if (fp != NULL) {
75	while ((len = getline(&line, &linesize, fp)) != -1) {
76	    if (strncmp(line, "btime ", 6) == 0) {
77		tv->tv_sec = atoi(line + 6);
78		tv->tv_usec = 0;
79		return 1;
80	    }
81	}
82	fclose(fp);
83	free(line);
84    }
85
86    return 0;
87}
88
89#elif defined(HAVE_SYSCTL) && defined(KERN_BOOTTIME)
90
91int
92get_boottime(tv)
93    struct timeval *tv;
94{
95    size_t size;
96    int mib[2];
97
98    mib[0] = CTL_KERN;
99    mib[1] = KERN_BOOTTIME;
100    size = sizeof(*tv);
101    if (sysctl(mib, 2, tv, &size, NULL, 0) != -1)
102	return 1;
103
104    return 0;
105}
106
107#elif defined(HAVE_GETUTXID)
108
109int
110get_boottime(tv)
111    struct timeval *tv;
112{
113    struct utmpx *ut, key;
114
115    memset(&key, 0, sizeof(key));
116    key.ut_type = BOOT_TIME;
117    if ((ut = getutxid(&key)) != NULL) {
118	tv->tv_sec = ut->ut_tv.tv_sec;
119	tv->tv_usec = ut->ut_tv.tv_usec;
120	endutxent();
121    }
122    return ut != NULL;
123}
124
125#elif defined(HAVE_GETUTID)
126
127int
128get_boottime(tv)
129    struct timeval *tv;
130{
131    struct utmp *ut, key;
132
133    memset(&key, 0, sizeof(key));
134    key.ut_type = BOOT_TIME;
135    if ((ut = getutid(&key)) != NULL) {
136	tv->tv_sec = ut->ut_time;
137	tv->tv_usec = 0;
138	endutent();
139    }
140    return ut != NULL;
141}
142
143#else
144
145int
146get_boottime(tv)
147    struct timeval *tv;
148{
149    return 0;
150}
151#endif
152