blob: 8165a14e9ce7250af7bc95bf2f848332bde24093 [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>
Michal Vasko5aa44c02020-06-29 11:47:02 +020022#include <stdarg.h>
23#include <stdio.h>
24#include <stdlib.h>
Michal Vasko69730152020-10-09 16:30:07 +020025#include <string.h>
Michal Vasko5aa44c02020-06-29 11:47:02 +020026#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}
Radek Krejci0f969882020-08-21 16:56:47 +020042
Michal Vasko5aa44c02020-06-29 11:47:02 +020043#endif
44
45#ifndef HAVE_ASPRINTF
46int
47asprintf(char **strp, const char *fmt, ...)
48{
49 int ret;
50 va_list ap;
51
52 va_start(ap, fmt);
53 ret = vasprintf(strp, fmt, ap);
54 va_end(ap);
55 return ret;
56}
Radek Krejci0f969882020-08-21 16:56:47 +020057
Michal Vasko5aa44c02020-06-29 11:47:02 +020058#endif
59
60#ifndef HAVE_VASPRINTF
61int
62vasprintf(char **strp, const char *fmt, va_list ap)
63{
64 va_list ap2;
Michal Vasko69730152020-10-09 16:30:07 +020065
Michal Vasko5aa44c02020-06-29 11:47:02 +020066 va_copy(ap2, ap);
67 int l = vsnprintf(0, 0, fmt, ap2);
Michal Vasko69730152020-10-09 16:30:07 +020068
Michal Vasko5aa44c02020-06-29 11:47:02 +020069 va_end(ap2);
70
Michal Vasko69730152020-10-09 16:30:07 +020071 if ((l < 0) || !(*strp = malloc(l + 1U))) {
Michal Vasko5aa44c02020-06-29 11:47:02 +020072 return -1;
73 }
74
75 return vsnprintf(*strp, l + 1U, fmt, ap);
76}
Radek Krejci0f969882020-08-21 16:56:47 +020077
Michal Vasko5aa44c02020-06-29 11:47:02 +020078#endif
79
80#ifndef HAVE_STRNDUP
81char *
82strndup(const char *s, size_t n)
83{
84 char *buf;
85 size_t len = 0;
86
87 /* strnlen */
Michal Vaskod989ba02020-08-24 10:59:24 +020088 for ( ; (len < n) && (s[len] != '\0'); ++len) {}
Michal Vasko5aa44c02020-06-29 11:47:02 +020089
90 if (!(buf = malloc(len + 1U))) {
91 return NULL;
92 }
93
94 memcpy(buf, s, len);
95 buf[len] = '\0';
96 return buf;
97}
Radek Krejci0f969882020-08-21 16:56:47 +020098
Michal Vasko5aa44c02020-06-29 11:47:02 +020099#endif
100
101#ifndef HAVE_STRNSTR
102char *
103strnstr(const char *s, const char *find, size_t slen)
104{
105 char c, sc;
106 size_t len;
107
108 if ((c = *find++) != '\0') {
109 len = strlen(find);
110 do {
111 do {
112 if ((slen-- < 1) || ((sc = *s++) == '\0')) {
113 return NULL;
114 }
115 } while (sc != c);
116 if (len > slen) {
117 return NULL;
118 }
119 } while (strncmp(s, find, len));
120 s--;
121 }
122 return (char *)s;
123}
Radek Krejci0f969882020-08-21 16:56:47 +0200124
Michal Vasko5aa44c02020-06-29 11:47:02 +0200125#endif
126
127#ifndef HAVE_GETLINE
128ssize_t
129getline(char **lineptr, size_t *n, FILE *stream)
130{
131 static char line[256];
132 char *ptr;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200133 ssize_t len;
Michal Vasko5aa44c02020-06-29 11:47:02 +0200134
135 if (!lineptr || !n) {
136 errno = EINVAL;
137 return -1;
138 }
139
140 if (ferror(stream) || feof(stream)) {
141 return -1;
142 }
143
144 if (!fgets(line, 256, stream)) {
145 return -1;
146 }
147
148 ptr = strchr(line, '\n');
149 if (ptr) {
150 *ptr = '\0';
151 }
152
153 len = strlen(line);
154
155 if (len + 1 < 256) {
156 ptr = realloc(*lineptr, 256);
157 if (!ptr) {
158 return -1;
159 }
160 *lineptr = ptr;
161 *n = 256;
162 }
163
164 strcpy(*lineptr, line);
165 return len;
166}
Radek Krejci0f969882020-08-21 16:56:47 +0200167
Michal Vasko5aa44c02020-06-29 11:47:02 +0200168#endif
169
170#ifndef HAVE_GET_CURRENT_DIR_NAME
171char *
172get_current_dir_name(void)
173{
174 char tmp[_POSIX_PATH_MAX];
175 char *retval = NULL;
176
177 if (getcwd(tmp, sizeof(tmp))) {
178 retval = strdup(tmp);
179 if (!retval) {
180 errno = ENOMEM;
181 }
182 }
183
184 return retval;
185}
Radek Krejci0f969882020-08-21 16:56:47 +0200186
Michal Vasko5aa44c02020-06-29 11:47:02 +0200187#endif