2 * dhcpcd - DHCP client daemon
3 * Copyright (c) 2006-2009 Roy Marples <roy@marples.name>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
28 /* Needed define to get at getline for glibc and FreeBSD */
31 #include <sys/cdefs.h>
34 # include <mach/mach_time.h>
35 # include <mach/kern_return.h>
38 #include <sys/param.h>
58 # define _PATH_DEVNULL "/dev/null"
63 static size_t lbuf_len
;
77 /* Handy routine to read very long lines in text files.
78 * This means we read the whole line and avoid any nasty buffer overflows.
79 * We strip leading space and avoid comment lines, making the code that calls
81 * As we don't use threads, this API is clean too. */
83 get_line(FILE * __restrict fp
)
96 bytes
= getline(&lbuf
, &lbuf_len
, fp
);
99 for (p
= lbuf
; *p
== ' ' || *p
== '\t'; p
++)
101 } while (*p
== '\0' || *p
== '\n' || *p
== '#' || *p
== ';');
102 if (lbuf
[--bytes
] == '\n')
112 if ((flags
= fcntl(fd
, F_GETFD
, 0)) == -1 ||
113 fcntl(fd
, F_SETFD
, flags
| FD_CLOEXEC
) == -1)
115 syslog(LOG_ERR
, "fcntl: %m");
126 if ((flags
= fcntl(fd
, F_GETFL
, 0)) == -1 ||
127 fcntl(fd
, F_SETFL
, flags
| O_NONBLOCK
) == -1)
129 syslog(LOG_ERR
, "fcntl: %m");
135 /* Handy function to get the time.
136 * We only care about time advancements, not the actual time itself
137 * Which is why we use CLOCK_MONOTONIC, but it is not available on all
140 #define NO_MONOTONIC "host does not support a monotonic clock - timing can skew"
142 get_monotonic(struct timeval
*tp
)
144 static int posix_clock_set
= 0;
145 #if defined(_POSIX_MONOTONIC_CLOCK) && defined(CLOCK_MONOTONIC)
147 static clockid_t posix_clock
;
149 if (!posix_clock_set
) {
150 if (clock_gettime(CLOCK_MONOTONIC
, &ts
) == 0) {
151 posix_clock
= CLOCK_MONOTONIC
;
152 clock_monotonic
= posix_clock_set
= 1;
156 if (clock_monotonic
) {
157 if (clock_gettime(posix_clock
, &ts
) == 0) {
158 tp
->tv_sec
= ts
.tv_sec
;
159 tp
->tv_usec
= ts
.tv_nsec
/ 1000;
163 #elif defined(__APPLE__)
164 #define NSEC_PER_SEC 1000000000
165 /* We can use mach kernel functions here.
166 * This is crap though - why can't they implement clock_gettime?*/
167 static struct mach_timebase_info info
= { 0, 0 };
168 static double factor
= 0.0;
172 if (!posix_clock_set
) {
173 if (mach_timebase_info(&info
) == KERN_SUCCESS
) {
174 factor
= (double)info
.numer
/ (double)info
.denom
;
175 clock_monotonic
= posix_clock_set
= 1;
178 if (clock_monotonic
) {
179 nano
= mach_absolute_time();
180 if ((info
.denom
!= 1 || info
.numer
!= 1) && factor
!= 0.0)
182 tp
->tv_sec
= nano
/ NSEC_PER_SEC
;
183 rem
= nano
% NSEC_PER_SEC
;
188 tp
->tv_usec
= rem
/ 1000;
193 /* Something above failed, so fall back to gettimeofday */
194 if (!posix_clock_set
) {
195 syslog(LOG_WARNING
, NO_MONOTONIC
);
198 return gettimeofday(tp
, NULL
);
206 if (get_monotonic(&tv
) == -1)
212 writepid(int fd
, pid_t pid
)
217 if (ftruncate(fd
, (off_t
)0) == -1)
219 snprintf(spid
, sizeof(spid
), "%u\n", pid
);
220 len
= pwrite(fd
, spid
, strlen(spid
), (off_t
)0);
221 if (len
!= (ssize_t
)strlen(spid
))
229 void *value
= malloc(s
);
233 syslog(LOG_ERR
, "memory exhausted (xalloc %zu bytes)", s
);
241 void *value
= xmalloc(s
);
248 xrealloc(void *ptr
, size_t s
)
250 void *value
= realloc(ptr
, s
);
254 syslog(LOG_ERR
, "memory exhausted (xrealloc %zu bytes)", s
);
260 xstrdup(const char *str
)
267 if ((value
= strdup(str
)) != NULL
)
270 syslog(LOG_ERR
, "memory exhausted (xstrdup)");