source: rtems-libbsd/dhcpcd/common.c @ 2017a6d

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 2017a6d was f2ed769, checked in by Sebastian Huber <sebastian.huber@…>, on 01/30/14 at 12:29:46

DHCPCD(8): Import

Import DHCPCD(8) from:

http://roy.marples.name/projects/dhcpcd/

The upstream sources can be obtained via:

fossil clone http://roy.marples.name/projects/dhcpcd

The imported version is 2014-01-29 19:46:44 [6b209507bb].

  • Property mode set to 100644
File size: 6.4 KB
Line 
1/*
2 * dhcpcd - DHCP client daemon
3 * Copyright (c) 2006-2012 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 <syslog.h>
54#include <time.h>
55#include <unistd.h>
56
57#include "common.h"
58
59#ifndef _PATH_DEVNULL
60#  define _PATH_DEVNULL "/dev/null"
61#endif
62
63static char hostname_buffer[HOSTNAME_MAX_LEN + 1];
64int clock_monotonic;
65static char *lbuf;
66static size_t lbuf_len;
67#ifdef DEBUG_MEMORY
68static char lbuf_set;
69#endif
70
71#ifdef DEBUG_MEMORY
72static void
73free_lbuf(void)
74{
75        free(lbuf);
76        lbuf = NULL;
77}
78#endif
79
80/* Handy routine to read very long lines in text files.
81 * This means we read the whole line and avoid any nasty buffer overflows.
82 * We strip leading space and avoid comment lines, making the code that calls
83 * us smaller.
84 * As we don't use threads, this API is clean too. */
85char *
86get_line(FILE * __restrict fp)
87{
88        char *p;
89        ssize_t bytes;
90
91#ifdef DEBUG_MEMORY
92        if (lbuf_set == 0) {
93                atexit(free_lbuf);
94                lbuf_set = 1;
95        }
96#endif
97
98        do {
99                bytes = getline(&lbuf, &lbuf_len, fp);
100                if (bytes == -1)
101                        return NULL;
102                for (p = lbuf; *p == ' ' || *p == '\t'; p++)
103                        ;
104        } while (*p == '\0' || *p == '\n' || *p == '#' || *p == ';');
105        if (lbuf[--bytes] == '\n')
106                lbuf[bytes] = '\0';
107        return p;
108}
109
110int
111set_cloexec(int fd)
112{
113        int flags;
114
115        if ((flags = fcntl(fd, F_GETFD, 0)) == -1 ||
116            fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
117        {
118                syslog(LOG_ERR, "fcntl: %m");
119                return -1;
120        }
121        return 0;
122}
123
124int
125set_nonblock(int fd)
126{
127        int flags;
128
129        if ((flags = fcntl(fd, F_GETFL, 0)) == -1 ||
130            fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
131        {
132                syslog(LOG_ERR, "fcntl: %m");
133                return -1;
134        }
135        return 0;
136}
137
138const char *
139get_hostname(int short_hostname)
140{
141        char *p;
142
143        gethostname(hostname_buffer, sizeof(hostname_buffer));
144        hostname_buffer[sizeof(hostname_buffer) - 1] = '\0';
145        if (strcmp(hostname_buffer, "(none)") == 0 ||
146            strcmp(hostname_buffer, "localhost") == 0 ||
147            strncmp(hostname_buffer, "localhost.", strlen("localhost.")) == 0 ||
148            hostname_buffer[0] == '.')
149                return NULL;
150
151        if (short_hostname) {
152                p = strchr(hostname_buffer, '.');
153                if (p)
154                        *p = '\0';
155        }
156
157        return hostname_buffer;
158}
159
160/* Handy function to get the time.
161 * We only care about time advancements, not the actual time itself
162 * Which is why we use CLOCK_MONOTONIC, but it is not available on all
163 * platforms.
164 */
165#define NO_MONOTONIC "host does not support a monotonic clock - timing can skew"
166int
167get_monotonic(struct timeval *tp)
168{
169        static int posix_clock_set = 0;
170#if defined(_POSIX_MONOTONIC_CLOCK) && defined(CLOCK_MONOTONIC)
171        struct timespec ts;
172        static clockid_t posix_clock;
173
174        if (!posix_clock_set) {
175                if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
176                        posix_clock = CLOCK_MONOTONIC;
177                        clock_monotonic = posix_clock_set = 1;
178                }
179        }
180
181        if (clock_monotonic) {
182                if (clock_gettime(posix_clock, &ts) == 0) {
183                        tp->tv_sec = ts.tv_sec;
184                        tp->tv_usec = ts.tv_nsec / 1000;
185                        return 0;
186                }
187        }
188#elif defined(__APPLE__)
189#define NSEC_PER_SEC 1000000000
190        /* We can use mach kernel functions here.
191         * This is crap though - why can't they implement clock_gettime?*/
192        static struct mach_timebase_info info = { 0, 0 };
193        static double factor = 0.0;
194        uint64_t nano;
195        long rem;
196
197        if (!posix_clock_set) {
198                if (mach_timebase_info(&info) == KERN_SUCCESS) {
199                        factor = (double)info.numer / (double)info.denom;
200                        clock_monotonic = posix_clock_set = 1;
201                }
202        }
203        if (clock_monotonic) {
204                nano = mach_absolute_time();
205                if ((info.denom != 1 || info.numer != 1) && factor != 0.0)
206                        nano *= factor;
207                tp->tv_sec = nano / NSEC_PER_SEC;
208                rem = nano % NSEC_PER_SEC;
209                if (rem < 0) {
210                        tp->tv_sec--;
211                        rem += NSEC_PER_SEC;
212                }
213                tp->tv_usec = rem / 1000;
214                return 0;
215        }
216#endif
217
218        /* Something above failed, so fall back to gettimeofday */
219        if (!posix_clock_set) {
220                syslog(LOG_WARNING, NO_MONOTONIC);
221                posix_clock_set = 1;
222        }
223        return gettimeofday(tp, NULL);
224}
225
226ssize_t
227setvar(char ***e, const char *prefix, const char *var, const char *value)
228{
229        size_t len = strlen(var) + strlen(value) + 3;
230
231        if (prefix)
232                len += strlen(prefix) + 1;
233        **e = malloc(len);
234        if (**e == NULL) {
235                syslog(LOG_ERR, "%s: %m", __func__);
236                return -1;
237        }
238        if (prefix)
239                snprintf(**e, len, "%s_%s=%s", prefix, var, value);
240        else
241                snprintf(**e, len, "%s=%s", var, value);
242        (*e)++;
243        return len;
244}
245
246ssize_t
247setvard(char ***e, const char *prefix, const char *var, int value)
248{
249        char buffer[32];
250
251        snprintf(buffer, sizeof(buffer), "%d", value);
252        return setvar(e, prefix, var, buffer);
253}
254
255
256time_t
257uptime(void)
258{
259        struct timeval tv;
260
261        if (get_monotonic(&tv) == -1)
262                return -1;
263        return tv.tv_sec;
264}
265
266int
267writepid(int fd, pid_t pid)
268{
269        char spid[16];
270        ssize_t len;
271
272        if (ftruncate(fd, (off_t)0) == -1)
273                return -1;
274        snprintf(spid, sizeof(spid), "%u\n", pid);
275        len = pwrite(fd, spid, strlen(spid), (off_t)0);
276        if (len != (ssize_t)strlen(spid))
277                return -1;
278        return 0;
279}
Note: See TracBrowser for help on using the repository browser.