aboutsummaryrefslogtreecommitdiff
path: root/libbb/platform.c
blob: 7913353e215cda9156e0576a7af02ffcf547d52f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/*
 * Replacements for common but usually nonstandard functions that aren't
 * supplied by all platforms.
 *
 * Copyright (C) 2009 by Dan Fandrich <dan@coneharvesters.com>, et. al.
 *
 * Licensed under GPLv2, see file LICENSE in this source tree.
 */
#include "libbb.h"

#ifndef HAVE_STRCHRNUL
char* FAST_FUNC strchrnul(const char *s, int c)
{
	while (*s != '\0' && *s != c)
		s++;
	return (char*)s;
}
#endif

#ifndef HAVE_USLEEP
int FAST_FUNC usleep(unsigned usec)
{
	struct timespec ts;
	ts.tv_sec = usec / 1000000u;
	ts.tv_nsec = (usec % 1000000u) * 1000u;
	/*
	 * If a signal has non-default handler, nanosleep returns early.
	 * Our version of usleep doesn't return early
	 * if interrupted by such signals:
	 */
	while (nanosleep(&ts, &ts) != 0)
		continue;
	return 0;
}
#endif

#ifndef HAVE_VASPRINTF
int FAST_FUNC vasprintf(char **string_ptr, const char *format, va_list p)
{
	int r;
	va_list p2;
	char buf[128];

	va_copy(p2, p);
	r = vsnprintf(buf, 128, format, p);
	va_end(p);

	/* Note: can't use xstrdup/xmalloc, they call vasprintf (us) on failure! */

	if (r < 128) {
		va_end(p2);
		*string_ptr = strdup(buf);
		return (*string_ptr ? r : -1);
	}

	*string_ptr = malloc(r+1);
	r = (*string_ptr ? vsnprintf(*string_ptr, r+1, format, p2) : -1);
	va_end(p2);

	return r;
}
#endif

#ifndef HAVE_DPRINTF
/* dprintf is now part of POSIX.1, but was only added in 2008 */
int dprintf(int fd, const char *format, ...)
{
	va_list p;
	int r;
	char *string_ptr;

	va_start(p, format);
	r = vasprintf(&string_ptr, format, p);
	va_end(p);
	if (r >= 0) {
		r = full_write(fd, string_ptr, r);
		free(string_ptr);
	}
	return r;
}
#endif

#ifndef HAVE_MEMRCHR
/* Copyright (C) 2005 Free Software Foundation, Inc.
 * memrchr() is a GNU function that might not be available everywhere.
 * It's basically the inverse of memchr() - search backwards in a
 * memory block for a particular character.
 */
void* FAST_FUNC memrchr(const void *s, int c, size_t n)
{
	const char *start = s, *end = s;

	end += n - 1;

	while (end >= start) {
		if (*end == (char)c)
			return (void *) end;
		end--;
	}

	return NULL;
}
#endif

#ifndef HAVE_MKDTEMP
/* This is now actually part of POSIX.1, but was only added in 2008 */
char* FAST_FUNC mkdtemp(char *template)
{
	/* NB: on error, mktemp returns an empty string, not NULL */
	if (mktemp(template)[0] == '\0' || mkdir(template, 0700) != 0)
		return NULL;
	return template;
}
#endif

#ifndef HAVE_STRCASESTR
/* Copyright (c) 1999, 2000 The ht://Dig Group */
char* FAST_FUNC strcasestr(const char *s, const char *pattern)
{
	int length = strlen(pattern);

	while (*s) {
		if (strncasecmp(s, pattern, length) == 0)
			return (char *)s;
		s++;
	}
	return 0;
}
#endif

#ifndef HAVE_STRSEP
/* Copyright (C) 2004 Free Software Foundation, Inc. */
char* FAST_FUNC strsep(char **stringp, const char *delim)
{
	char *start = *stringp;
	char *ptr;

	if (!start)
		return NULL;

	if (!*delim)
		ptr = start + strlen(start);
	else {
		ptr = strpbrk(start, delim);
		if (!ptr) {
			*stringp = NULL;
			return start;
		}
	}

	*ptr = '\0';
	*stringp = ptr + 1;

	return start;
}
#endif

#ifndef HAVE_STPCPY
char* FAST_FUNC stpcpy(char *p, const char *to_add)
{
	while ((*p = *to_add) != '\0') {
		p++;
		to_add++;
	}
	return p;
}
#endif

#ifndef HAVE_STPNCPY
char* FAST_FUNC stpncpy(char *p, const char *to_add, size_t n)
{
	while (n != 0 && (*p = *to_add) != '\0') {
		p++;
		to_add++;
		n--;
	}
	return p;
}
#endif

#ifndef HAVE_GETLINE
ssize_t FAST_FUNC getline(char **lineptr, size_t *n, FILE *stream)
{
	int ch;
	char *line = *lineptr;
	size_t alloced = *n;
	size_t len = 0;

	do {
		ch = fgetc(stream);
		if (ch == EOF)
			break;
		if (len + 1 >= alloced) {
			alloced += alloced/4 + 64;
			line = xrealloc(line, alloced);
		}
		line[len++] = ch;
	} while (ch != '\n');

	if (len == 0)
		return -1;

	line[len] = '\0';
	*lineptr = line;
	*n = alloced;
	return len;
}
#endif

#ifndef HAVE_TTYNAME_R
int ttyname_r(int fd, char *buf, size_t buflen)
{
	int r;
	char path[sizeof("/proc/self/fd/%d") + sizeof(int)*3];

	if (!isatty(fd))
		return errno == EINVAL ? ENOTTY : errno;
	sprintf(path, "/proc/self/fd/%d", fd);
	r = readlink(path, buf, buflen);
	if (r < 0)
		return errno;
	if (r >= buflen)
		return ERANGE;
	buf[r] = '\0';
	return 0;
}
#endif