1/* 2 * dhcpcd - DHCP client daemon 3 * Copyright (c) 2006-2009 Roy Marples <roy@marples.name> 4 * All rights reserved 5 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28/* Needed define to get at getline for glibc and FreeBSD */ 29#ifndef _GNU_SOURCE 30# define _GNU_SOURCE 31#endif 32 33#include <sys/cdefs.h> 34 35#ifdef __APPLE__ 36# include <mach/mach_time.h> 37# include <mach/kern_return.h> 38#endif 39 40#include <sys/param.h> 41#include <sys/time.h> 42 43#include <errno.h> 44#include <fcntl.h> 45#include <limits.h> 46#ifdef BSD 47# include <paths.h> 48#endif 49#include <stdint.h> 50#include <stdio.h> 51#include <stdlib.h> 52#include <string.h> 53#include <time.h> 54#include <unistd.h> 55 56#include "common.h" 57 58#ifndef _PATH_DEVNULL 59# define _PATH_DEVNULL "/dev/null" 60#endif 61 62int clock_monotonic; 63#ifdef DEBUG_MEMORY 64static char lbuf_set; 65#endif 66 67#ifdef DEBUG_MEMORY 68static void 69free_lbuf(void) 70{ 71 free(lbuf); 72 lbuf = NULL; 73} 74#endif 75 76/* Handy function to get the time. 77 * We only care about time advancements, not the actual time itself 78 * Which is why we use CLOCK_MONOTONIC, but it is not available on all 79 * platforms. 80 */ 81#define NO_MONOTONIC "host does not support a monotonic clock - timing can skew" 82int 83get_monotonic(struct timeval *tp) 84{ 85 static int posix_clock_set = 0; 86#if defined(_POSIX_MONOTONIC_CLOCK) && defined(CLOCK_MONOTONIC) 87 struct timespec ts; 88 static clockid_t posix_clock; 89 90 if (!posix_clock_set) { 91 if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { 92 posix_clock = CLOCK_MONOTONIC; 93 clock_monotonic = posix_clock_set = 1; 94 } 95 } 96 97 if (clock_monotonic) { 98 if (clock_gettime(posix_clock, &ts) == 0) { 99 tp->tv_sec = ts.tv_sec; 100 tp->tv_usec = ts.tv_nsec / 1000; 101 return 0; 102 } 103 } 104#elif defined(__APPLE__) 105#define NSEC_PER_SEC 1000000000 106 /* We can use mach kernel functions here. 107 * This is crap though - why can't they implement clock_gettime?*/ 108 static struct mach_timebase_info info = { 0, 0 }; 109 static double factor = 0.0; 110 uint64_t nano; 111 long rem; 112 113 if (!posix_clock_set) { 114 if (mach_timebase_info(&info) == KERN_SUCCESS) { 115 factor = (double)info.numer / (double)info.denom; 116 clock_monotonic = posix_clock_set = 1; 117 } 118 } 119 if (clock_monotonic) { 120 nano = mach_absolute_time(); 121 if ((info.denom != 1 || info.numer != 1) && factor != 0.0) 122 nano *= factor; 123 tp->tv_sec = nano / NSEC_PER_SEC; 124 rem = nano % NSEC_PER_SEC; 125 if (rem < 0) { 126 tp->tv_sec--; 127 rem += NSEC_PER_SEC; 128 } 129 tp->tv_usec = rem / 1000; 130 return 0; 131 } 132#endif 133 134 /* Something above failed, so fall back to gettimeofday */ 135 if (!posix_clock_set) { 136 posix_clock_set = 1; 137 } 138 return gettimeofday(tp, NULL); 139} 140 141time_t 142uptime(void) 143{ 144 struct timeval tv; 145 146 if (get_monotonic(&tv) == -1) 147 return -1; 148 return tv.tv_sec; 149} 150 151void * 152xmalloc(size_t s) 153{ 154 void *value = malloc(s); 155 156 if (value != NULL) 157 return value; 158 abort(); 159 /* NOTREACHED */ 160} 161 162void * 163xzalloc(size_t s) 164{ 165 void *value = xmalloc(s); 166 167 memset(value, 0, s); 168 return value; 169} 170 171void * 172xrealloc(void *ptr, size_t s) 173{ 174 void *value = realloc(ptr, s); 175 176 if (value != NULL) 177 return value; 178 abort(); 179 /* NOTREACHED */ 180} 181 182char * 183xstrdup(const char *str) 184{ 185 char *value; 186 187 if (str == NULL) 188 return NULL; 189 190 if ((value = strdup(str)) != NULL) 191 return value; 192 193 abort(); 194 /* NOTREACHED */ 195} 196