blob: 7a06d5892a418a00286d5c69c01c9a0fa7a70472 [file] [log] [blame]
Michal Vasko5aa44c02020-06-29 11:47:02 +02001/**
2 * @file compat.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief compatibility functions
5 *
6 * Copyright (c) 2020 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14#include "compat.h"
15
16#define _POSIX_C_SOURCE 1 /* fdopen, _POSIX_PATH_MAX */
17#define _ISOC99_SOURCE /* vsnprintf */
18#define _XOPEN_SOURCE 500 /* strdup */
19
20#include <errno.h>
21#include <limits.h>
22#include <string.h>
23#include <stdarg.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <unistd.h>
27
28#ifndef HAVE_VDPRINTF
29int
30vdprintf(int fd, const char *format, va_list ap)
31{
32 FILE *stream;
33 int count;
34
35 stream = fdopen(dup(fd), "a+");
36 if (stream) {
37 count = vfprintf(stream, format, ap);
38 fclose(stream);
39 }
40 return count;
41}
42#endif
43
44#ifndef HAVE_ASPRINTF
45int
46asprintf(char **strp, const char *fmt, ...)
47{
48 int ret;
49 va_list ap;
50
51 va_start(ap, fmt);
52 ret = vasprintf(strp, fmt, ap);
53 va_end(ap);
54 return ret;
55}
56#endif
57
58#ifndef HAVE_VASPRINTF
59int
60vasprintf(char **strp, const char *fmt, va_list ap)
61{
62 va_list ap2;
63 va_copy(ap2, ap);
64 int l = vsnprintf(0, 0, fmt, ap2);
65 va_end(ap2);
66
67 if (l < 0 || !(*strp = malloc(l + 1U))) {
68 return -1;
69 }
70
71 return vsnprintf(*strp, l + 1U, fmt, ap);
72}
73#endif
74
75#ifndef HAVE_STRNDUP
76char *
77strndup(const char *s, size_t n)
78{
79 char *buf;
80 size_t len = 0;
81
82 /* strnlen */
Radek Krejci1e008d22020-08-17 11:37:37 +020083 for (; (len < n) && (s[len] != '\0'); ++len) {}
Michal Vasko5aa44c02020-06-29 11:47:02 +020084
85 if (!(buf = malloc(len + 1U))) {
86 return NULL;
87 }
88
89 memcpy(buf, s, len);
90 buf[len] = '\0';
91 return buf;
92}
93#endif
94
95#ifndef HAVE_STRNSTR
96char *
97strnstr(const char *s, const char *find, size_t slen)
98{
99 char c, sc;
100 size_t len;
101
102 if ((c = *find++) != '\0') {
103 len = strlen(find);
104 do {
105 do {
106 if ((slen-- < 1) || ((sc = *s++) == '\0')) {
107 return NULL;
108 }
109 } while (sc != c);
110 if (len > slen) {
111 return NULL;
112 }
113 } while (strncmp(s, find, len));
114 s--;
115 }
116 return (char *)s;
117}
118#endif
119
120#ifndef HAVE_GETLINE
121ssize_t
122getline(char **lineptr, size_t *n, FILE *stream)
123{
124 static char line[256];
125 char *ptr;
126 unsigned int len;
127
128 if (!lineptr || !n) {
129 errno = EINVAL;
130 return -1;
131 }
132
133 if (ferror(stream) || feof(stream)) {
134 return -1;
135 }
136
137 if (!fgets(line, 256, stream)) {
138 return -1;
139 }
140
141 ptr = strchr(line, '\n');
142 if (ptr) {
143 *ptr = '\0';
144 }
145
146 len = strlen(line);
147
148 if (len + 1 < 256) {
149 ptr = realloc(*lineptr, 256);
150 if (!ptr) {
151 return -1;
152 }
153 *lineptr = ptr;
154 *n = 256;
155 }
156
157 strcpy(*lineptr, line);
158 return len;
159}
160#endif
161
162#ifndef HAVE_GET_CURRENT_DIR_NAME
163char *
164get_current_dir_name(void)
165{
166 char tmp[_POSIX_PATH_MAX];
167 char *retval = NULL;
168
169 if (getcwd(tmp, sizeof(tmp))) {
170 retval = strdup(tmp);
171 if (!retval) {
172 errno = ENOMEM;
173 }
174 }
175
176 return retval;
177}
178#endif