os_compat.c 8.0 KB

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