blob: a9594470b9fc07ebb6cfbad86c7bdb59b23762e0 [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}
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;
65 va_copy(ap2, ap);
66 int l = vsnprintf(0, 0, fmt, ap2);
67 va_end(ap2);
68
69 if (l < 0 || !(*strp = malloc(l + 1U))) {
70 return -1;
71 }
72
73 return vsnprintf(*strp, l + 1U, fmt, ap);
74}
Radek Krejci0f969882020-08-21 16:56:47 +020075
Michal Vasko5aa44c02020-06-29 11:47:02 +020076#endif
77
78#ifndef HAVE_STRNDUP
79char *
80strndup(const char *s, size_t n)
81{
82 char *buf;
83 size_t len = 0;
84
85 /* strnlen */
Radek Krejci1e008d22020-08-17 11:37:37 +020086 for (; (len < n) && (s[len] != '\0'); ++len) {}
Michal Vasko5aa44c02020-06-29 11:47:02 +020087
88 if (!(buf = malloc(len + 1U))) {
89 return NULL;
90 }
91
92 memcpy(buf, s, len);
93 buf[len] = '\0';
94 return buf;
95}
Radek Krejci0f969882020-08-21 16:56:47 +020096
Michal Vasko5aa44c02020-06-29 11:47:02 +020097#endif
98
99#ifndef HAVE_STRNSTR
100char *
101strnstr(const char *s, const char *find, size_t slen)
102{
103 char c, sc;
104 size_t len;
105
106 if ((c = *find++) != '\0') {
107 len = strlen(find);
108 do {
109 do {
110 if ((slen-- < 1) || ((sc = *s++) == '\0')) {
111 return NULL;
112 }
113 } while (sc != c);
114 if (len > slen) {
115 return NULL;
116 }
117 } while (strncmp(s, find, len));
118 s--;
119 }
120 return (char *)s;
121}
Radek Krejci0f969882020-08-21 16:56:47 +0200122
Michal Vasko5aa44c02020-06-29 11:47:02 +0200123#endif
124
125#ifndef HAVE_GETLINE
126ssize_t
127getline(char **lineptr, size_t *n, FILE *stream)
128{
129 static char line[256];
130 char *ptr;
131 unsigned int len;
132
133 if (!lineptr || !n) {
134 errno = EINVAL;
135 return -1;
136 }
137
138 if (ferror(stream) || feof(stream)) {
139 return -1;
140 }
141
142 if (!fgets(line, 256, stream)) {
143 return -1;
144 }
145
146 ptr = strchr(line, '\n');
147 if (ptr) {
148 *ptr = '\0';
149 }
150
151 len = strlen(line);
152
153 if (len + 1 < 256) {
154 ptr = realloc(*lineptr, 256);
155 if (!ptr) {
156 return -1;
157 }
158 *lineptr = ptr;
159 *n = 256;
160 }
161
162 strcpy(*lineptr, line);
163 return len;
164}
Radek Krejci0f969882020-08-21 16:56:47 +0200165
Michal Vasko5aa44c02020-06-29 11:47:02 +0200166#endif
167
168#ifndef HAVE_GET_CURRENT_DIR_NAME
169char *
170get_current_dir_name(void)
171{
172 char tmp[_POSIX_PATH_MAX];
173 char *retval = NULL;
174
175 if (getcwd(tmp, sizeof(tmp))) {
176 retval = strdup(tmp);
177 if (!retval) {
178 errno = ENOMEM;
179 }
180 }
181
182 return retval;
183}
Radek Krejci0f969882020-08-21 16:56:47 +0200184
Michal Vasko5aa44c02020-06-29 11:47:02 +0200185#endif