/* * Copyright (c) 2009-2013 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif /* STDC_HEADERS */ #ifdef HAVE_STRING_H # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS) # include # endif # include #endif /* HAVE_STRING_H */ #ifdef HAVE_STRINGS_H # include #endif /* HAVE_STRINGS_H */ #include #if TIME_WITH_SYS_TIME # include #endif #ifndef __linux__ # if defined(HAVE_SYSCTL) && defined(KERN_BOOTTIME) # include # elif defined(HAVE_GETUTXID) # include # elif defined(HAVE_GETUTID) # include # endif #endif /* !__linux__ */ #include "missing.h" #include "sudo_debug.h" /* * Fill in a struct timeval with the time the system booted. * Returns 1 on success and 0 on failure. */ #if defined(__linux__) int get_boottime(struct timeval *tv) { char *ep, *line = NULL; size_t linesize = 0; ssize_t len; FILE * fp; debug_decl(get_boottime, SUDO_DEBUG_UTIL) /* read btime from /proc/stat */ fp = fopen("/proc/stat", "r"); if (fp != NULL) { while ((len = getline(&line, &linesize, fp)) != -1) { if (strncmp(line, "btime ", 6) == 0) { #ifdef HAVE_STRTOLL long long llval = strtoll(line + 6, &ep, 10); if (line[6] != '\0' && *ep == '\0' && (time_t)llval == llval) { tv->tv_sec = (time_t)llval; tv->tv_usec = 0; debug_return_bool(1); } #else long lval = strtol(line + 6, &ep, 10); if (line[6] != '\0' && *ep == '\0' && (time_t)lval == lval) { tv->tv_sec = (time_t)llval; tv->tv_usec = 0; debug_return_bool(1); } #endif } } fclose(fp); free(line); } debug_return_bool(0); } #elif defined(HAVE_SYSCTL) && defined(KERN_BOOTTIME) int get_boottime(struct timeval *tv) { size_t size; int mib[2]; debug_decl(get_boottime, SUDO_DEBUG_UTIL) mib[0] = CTL_KERN; mib[1] = KERN_BOOTTIME; size = sizeof(*tv); if (sysctl(mib, 2, tv, &size, NULL, 0) != -1) debug_return_bool(1); debug_return_bool(0); } #elif defined(HAVE_GETUTXID) int get_boottime(struct timeval *tv) { struct utmpx *ut, key; debug_decl(get_boottime, SUDO_DEBUG_UTIL) memset(&key, 0, sizeof(key)); key.ut_type = BOOT_TIME; setutxent(); if ((ut = getutxid(&key)) != NULL) { tv->tv_sec = ut->ut_tv.tv_sec; tv->tv_usec = ut->ut_tv.tv_usec; } endutxent(); debug_return_bool(ut != NULL); } #elif defined(HAVE_GETUTID) int get_boottime(struct timeval *tv) { struct utmp *ut, key; debug_decl(get_boottime, SUDO_DEBUG_UTIL) memset(&key, 0, sizeof(key)); key.ut_type = BOOT_TIME; setutent(); if ((ut = getutid(&key)) != NULL) { tv->tv_sec = ut->ut_time; tv->tv_usec = 0; } endutent(); debug_return_bool(ut != NULL); } #else int get_boottime(struct timeval *tv) { debug_decl(get_boottime, SUDO_DEBUG_UTIL) debug_return_bool(0); } #endif