/src/gpsd/gpsd-3.26.2~dev/libgps/os_compat.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * This file contains functions to deal with compatibility issues across OSes. |
3 | | * |
4 | | * The initial version of this file is a near-verbatim concatenation of the |
5 | | * following three source files: |
6 | | * clock_gettime.c |
7 | | * daemon.c |
8 | | * strl.c |
9 | | * History of this code prior to the creation of this file can be found |
10 | | * in the histories of those files. |
11 | | * |
12 | | * This file is Copyright by the GPSD project |
13 | | * SPDX-License-Identifier: BSD-2-clause |
14 | | */ |
15 | | |
16 | | #include "../include/gpsd_config.h" // must be before all includes |
17 | | |
18 | | #include "../include/os_compat.h" |
19 | | |
20 | | // export gpsd version so FFI can check it |
21 | | const char *gpsd_version = VERSION; |
22 | | |
23 | | #ifndef HAVE_CLOCK_GETTIME |
24 | | |
25 | | // Simulate ANSI/POSIX clock_gettime() on platforms that don't have it |
26 | | |
27 | | #include <time.h> |
28 | | #include <sys/time.h> |
29 | | |
30 | | /* |
31 | | * Note that previous versions of this code made use of clock_get_time() |
32 | | * on OSX, as a way to get time of day with nanosecond resolution. But |
33 | | * it turns out that clock_get_time() only has microsecond resolution, |
34 | | * in spite of the data format, and it's also substantially slower than |
35 | | * gettimeofday(). Thus, it makes no sense to do anything special for OSX. |
36 | | */ |
37 | | |
38 | | int clock_gettime(clockid_t clk_id, struct timespec *ts) |
39 | | { |
40 | | (void) clk_id; |
41 | | struct timeval tv; |
42 | | if (0 > gettimeofday(&tv, NULL)) { |
43 | | return -1; |
44 | | } |
45 | | ts->tv_sec = tv.tv_sec; |
46 | | ts->tv_nsec = tv.tv_usec * 1000; |
47 | | return 0; |
48 | | } |
49 | | #endif // HAVE_CLOCK_GETTIME |
50 | | |
51 | | // End of clock_gettime section |
52 | | |
53 | | #ifndef HAVE_DAEMON |
54 | | // Simulate Linux/BSD daemon() on platforms that don't have it |
55 | | |
56 | | #include <stdlib.h> |
57 | | #include <sys/types.h> |
58 | | #include <sys/stat.h> |
59 | | #include <fcntl.h> |
60 | | #include <unistd.h> |
61 | | |
62 | | #if defined (HAVE_PATH_H) |
63 | | #include <paths.h> |
64 | | #elif !defined (_PATH_DEVNULL) |
65 | | #define _PATH_DEVNULL "/dev/null" |
66 | | #endif |
67 | | |
68 | | // compatible with the daemon(3) found on Linuxes and BSDs |
69 | | int os_daemon(int nochdir, int noclose) |
70 | | { |
71 | | int fd; |
72 | | |
73 | | switch (fork()) { |
74 | | case -1: |
75 | | return -1; |
76 | | case 0: // child side |
77 | | break; |
78 | | default: // parent side |
79 | | exit(EXIT_SUCCESS); |
80 | | } |
81 | | |
82 | | if (-1 == setsid()) { |
83 | | return -1; |
84 | | } |
85 | | if ((0 == nochdir) && |
86 | | (-1 == chdir("/"))) { |
87 | | return -1; |
88 | | } |
89 | | if (0 == noclose && |
90 | | -1 != (fd = open(_PATH_DEVNULL, O_RDWR, 0))) { |
91 | | (void)dup2(fd, STDIN_FILENO); |
92 | | (void)dup2(fd, STDOUT_FILENO); |
93 | | (void)dup2(fd, STDERR_FILENO); |
94 | | if (2 < fd) { |
95 | | (void)close(fd); |
96 | | } |
97 | | } |
98 | | // coverity[leaked_handle] Intentional handle duplication |
99 | | return 0; |
100 | | } |
101 | | |
102 | | #else // HAVE_DAEMON |
103 | | |
104 | | #if defined (__linux__) || defined (__GLIBC__) |
105 | | |
106 | | #include <unistd.h> // for daemon() |
107 | | |
108 | | #elif defined(__APPLE__) // !__linux__ |
109 | | |
110 | | /* |
111 | | * Avoid the OSX deprecation warning. |
112 | | * |
113 | | * Note that on OSX, real daemons like gpsd should run via launchd rather than |
114 | | * self-daemonizing, but we use daemon() for other tools as well. |
115 | | * |
116 | | * There doesn't seem to be an easy way to avoid the warning other than by |
117 | | * providing our own declaration to override the deprecation-flagged version. |
118 | | * Fortunately, the function signature is pretty well frozen at this point. |
119 | | * |
120 | | * Until we fix the kludge where all this code has to be additionally compiled |
121 | | * as C++ for the Qt library, we need this to be compilable as C++ as well. |
122 | | */ |
123 | | #ifdef __cplusplus |
124 | | extern "C" { |
125 | | #endif |
126 | | |
127 | | int daemon(int nochdir, int noclose); |
128 | | |
129 | | #ifdef __cplusplus |
130 | | } |
131 | | #endif |
132 | | |
133 | | #else // !__linux__ && !__APPLE__ |
134 | | |
135 | | #include <stdlib.h> |
136 | | |
137 | | #endif // !__linux__ && !__APPLE__ |
138 | | |
139 | | int os_daemon(int nochdir, int noclose) |
140 | 0 | { |
141 | 0 | return daemon(nochdir, noclose); |
142 | 0 | } |
143 | | |
144 | | #endif // HAVE_DAEMON |
145 | | |
146 | | // End of daemon section |
147 | | |
148 | | // Provide syslog() on platforms that don't have it |
149 | | |
150 | | #ifndef HAVE_SYSLOG_H |
151 | | #include "../include/compiler.h" |
152 | | #include <stdarg.h> |
153 | | #include <stdio.h> |
154 | | /* |
155 | | * Minimal syslog() fallback to print to stderr |
156 | | * |
157 | | */ |
158 | | PRINTF_FUNC(2, 3) void syslog(int priority UNUSED, const char *format, ...) |
159 | | { |
160 | | // ATM ignore priority (i.e. don't even both prepending to output) |
161 | | char buf[BUFSIZ]; |
162 | | va_list ap; |
163 | | va_start(ap, format); |
164 | | // Always append a new line to the message |
165 | | (void)vsnprintf(buf, sizeof(buf) - 2, format, ap); |
166 | | (void)fprintf(stderr, "%s\n", buf); |
167 | | va_end(ap); |
168 | | } |
169 | | |
170 | | void openlog (const char *__ident UNUSED, int __option UNUSED, int __facility UNUSED) |
171 | | { |
172 | | (void)fprintf(stderr, "Warning openlog() not available\n"); |
173 | | } |
174 | | |
175 | | void closelog (void) |
176 | | { |
177 | | } |
178 | | #endif // !HAVE_SYSLOG_H |
179 | | |
180 | | // End of syslog section |
181 | | |
182 | | /* |
183 | | * Provide BSD strlcat()/strlcpy() on platforms that don't have it |
184 | | * |
185 | | * These versions use memcpy and strlen() because they are often |
186 | | * heavily optimized down to assembler level. Thus, likely to be |
187 | | * faster even with the function call overhead. |
188 | | */ |
189 | | |
190 | | #ifndef HAVE_STRLCAT |
191 | | |
192 | | #include <string.h> |
193 | | |
194 | | /* |
195 | | * Appends src to string dst of size siz (unlike strncat, siz is the |
196 | | * full size of dst, not space left). At most siz-1 characters |
197 | | * will be copied. Always NUL terminates (unless siz <= strlen(dst)). |
198 | | * Returns strlen(src) + MIN(siz, strlen(initial dst)). |
199 | | * If retval >= siz, truncation occurred. |
200 | | */ |
201 | | size_t strlcat(char *dst, const char *src, size_t siz) |
202 | 0 | { |
203 | 0 | size_t slen = strlen(src); |
204 | 0 | size_t dlen = strlen(dst); |
205 | 0 | if (0 != siz) { |
206 | 0 | if (dlen + slen < siz) { |
207 | 0 | memcpy(dst + dlen, src, slen + 1); |
208 | 0 | } else { |
209 | 0 | memcpy(dst + dlen, src, siz - dlen - 1); |
210 | 0 | dst[siz - 1] = '\0'; |
211 | 0 | } |
212 | 0 | } |
213 | 0 | return dlen + slen; |
214 | 0 | } |
215 | | |
216 | | #ifdef __UNUSED__ |
217 | | // $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ |
218 | | |
219 | | /* |
220 | | * Copyright 1998 Todd C. Miller <Todd.Miller@courtesan.com> |
221 | | * |
222 | | * Permission to use, copy, modify, and distribute this software for any |
223 | | * purpose with or without fee is hereby granted, provided that the above |
224 | | * copyright notice and this permission notice appear in all copies. |
225 | | * |
226 | | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
227 | | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
228 | | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
229 | | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
230 | | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
231 | | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
232 | | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
233 | | */ |
234 | | |
235 | | size_t strlcat(char *dst, const char *src, size_t siz) |
236 | | { |
237 | | char *d = dst; |
238 | | const char *s = src; |
239 | | size_t n = siz; |
240 | | size_t dlen; |
241 | | |
242 | | // Find the end of dst and adjust bytes left but don't go past end |
243 | | while (n-- != 0 && *d != '\0') |
244 | | d++; |
245 | | dlen = (size_t) (d - dst); |
246 | | n = siz - dlen; |
247 | | |
248 | | if (0 == n) { |
249 | | return (dlen + strlen(s)); |
250 | | } |
251 | | while ('\0'* != s) { |
252 | | if (1 != n) { |
253 | | *d++ = *s; |
254 | | n--; |
255 | | } |
256 | | s++; |
257 | | } |
258 | | *d = '\0'; |
259 | | |
260 | | return (dlen + (s - src)); // count does not include NUL |
261 | | } |
262 | | #endif // __UNUSED__ |
263 | | #endif // !HAVE_STRLCAT |
264 | | |
265 | | #ifndef HAVE_STRLCPY |
266 | | |
267 | | #include <string.h> |
268 | | |
269 | | /* |
270 | | * Copy src to string dst of size siz. At most siz-1 characters |
271 | | * will be copied. Always NUL terminates (unless siz == 0). |
272 | | * Returns strlen(src); if retval >= siz, truncation occurred. |
273 | | */ |
274 | | size_t strlcpy(char *dst, const char *src, size_t siz) |
275 | 1.06k | { |
276 | 1.06k | size_t len = strlen(src); |
277 | 1.06k | if (0!= siz ) { |
278 | 1.06k | if (len >= siz) { |
279 | 194 | memcpy(dst, src, siz - 1); |
280 | 194 | dst[siz - 1] = '\0'; |
281 | 872 | } else { |
282 | 872 | memcpy(dst, src, len + 1); |
283 | 872 | } |
284 | 1.06k | } |
285 | 1.06k | return len; |
286 | 1.06k | } |
287 | | |
288 | | #endif // !HAVE_STRLCPY |
289 | | |
290 | | // End of strlcat()/strlcpy() section |
291 | | |
292 | | /* |
293 | | * Provide sincos() on platforms that don't have it. |
294 | | * Getting scons to test for sincos() and pass -Werror not possible. |
295 | | * This just uses the usual sin() and cos(), with no speed benefit. |
296 | | * It doesn't worry about the corner case where the +-infinity argument |
297 | | * may raise the "invalid" exception before storing both NaN results. |
298 | | */ |
299 | | |
300 | | #include <math.h> |
301 | | |
302 | | void gpsd_sincos(double x, double *sinp, double *cosp) |
303 | 0 | { |
304 | 0 | *sinp = sin(x); |
305 | 0 | *cosp = cos(x); |
306 | 0 | } |
307 | | |
308 | | // End of sincos() section. |
309 | | // vim: set expandtab shiftwidth=4 |