blob: 5fcd448cc593204fe4133797033198193f294064
1 | /* |
2 | * Replacements for common but usually nonstandard functions that aren't |
3 | * supplied by all platforms. |
4 | * |
5 | * Copyright (C) 2009 by Dan Fandrich <dan@coneharvesters.com>, et. al. |
6 | * |
7 | * Licensed under GPLv2, see file LICENSE in this source tree. |
8 | */ |
9 | #include "libbb.h" |
10 | |
11 | #ifndef HAVE_STRCHRNUL |
12 | char* FAST_FUNC strchrnul(const char *s, int c) |
13 | { |
14 | while (*s != '\0' && *s != c) |
15 | s++; |
16 | return (char*)s; |
17 | } |
18 | #endif |
19 | |
20 | #ifndef HAVE_VASPRINTF |
21 | int FAST_FUNC vasprintf(char **string_ptr, const char *format, va_list p) |
22 | { |
23 | int r; |
24 | va_list p2; |
25 | char buf[128]; |
26 | |
27 | va_copy(p2, p); |
28 | r = vsnprintf(buf, 128, format, p); |
29 | va_end(p); |
30 | |
31 | /* Note: can't use xstrdup/xmalloc, they call vasprintf (us) on failure! */ |
32 | |
33 | if (r < 128) { |
34 | va_end(p2); |
35 | *string_ptr = strdup(buf); |
36 | return (*string_ptr ? r : -1); |
37 | } |
38 | |
39 | *string_ptr = malloc(r+1); |
40 | r = (*string_ptr ? vsnprintf(*string_ptr, r+1, format, p2) : -1); |
41 | va_end(p2); |
42 | |
43 | return r; |
44 | } |
45 | #endif |
46 | |
47 | #ifndef HAVE_DPRINTF |
48 | /* dprintf is now part of POSIX.1, but was only added in 2008 */ |
49 | int dprintf(int fd, const char *format, ...) |
50 | { |
51 | va_list p; |
52 | int r; |
53 | char *string_ptr; |
54 | |
55 | va_start(p, format); |
56 | r = vasprintf(&string_ptr, format, p); |
57 | va_end(p); |
58 | if (r >= 0) { |
59 | r = full_write(fd, string_ptr, r); |
60 | free(string_ptr); |
61 | } |
62 | return r; |
63 | } |
64 | #endif |
65 | |
66 | #ifndef HAVE_MEMRCHR |
67 | /* Copyright (C) 2005 Free Software Foundation, Inc. |
68 | * memrchr() is a GNU function that might not be available everywhere. |
69 | * It's basically the inverse of memchr() - search backwards in a |
70 | * memory block for a particular character. |
71 | */ |
72 | void* FAST_FUNC memrchr(const void *s, int c, size_t n) |
73 | { |
74 | const char *start = s, *end = s; |
75 | |
76 | end += n - 1; |
77 | |
78 | while (end >= start) { |
79 | if (*end == (char)c) |
80 | return (void *) end; |
81 | end--; |
82 | } |
83 | |
84 | return NULL; |
85 | } |
86 | #endif |
87 | |
88 | #ifndef HAVE_MKDTEMP |
89 | #ifdef __BIONIC__ |
90 | #define mktemp(s) bb_mktemp(s) |
91 | #endif |
92 | /* This is now actually part of POSIX.1, but was only added in 2008 */ |
93 | char* FAST_FUNC mkdtemp(char *template) |
94 | { |
95 | if (mktemp(template) == NULL || mkdir(template, 0700) != 0) |
96 | return NULL; |
97 | return template; |
98 | } |
99 | #endif |
100 | |
101 | #ifndef HAVE_STRCASESTR |
102 | /* Copyright (c) 1999, 2000 The ht://Dig Group */ |
103 | char* FAST_FUNC strcasestr(const char *s, const char *pattern) |
104 | { |
105 | int length = strlen(pattern); |
106 | |
107 | while (*s) { |
108 | if (strncasecmp(s, pattern, length) == 0) |
109 | return (char *)s; |
110 | s++; |
111 | } |
112 | return 0; |
113 | } |
114 | #endif |
115 | |
116 | #ifndef HAVE_STRSEP |
117 | /* Copyright (C) 2004 Free Software Foundation, Inc. */ |
118 | char* FAST_FUNC strsep(char **stringp, const char *delim) |
119 | { |
120 | char *start = *stringp; |
121 | char *ptr; |
122 | |
123 | if (!start) |
124 | return NULL; |
125 | |
126 | if (!*delim) |
127 | ptr = start + strlen(start); |
128 | else { |
129 | ptr = strpbrk(start, delim); |
130 | if (!ptr) { |
131 | *stringp = NULL; |
132 | return start; |
133 | } |
134 | } |
135 | |
136 | *ptr = '\0'; |
137 | *stringp = ptr + 1; |
138 | |
139 | return start; |
140 | } |
141 | #endif |
142 | |
143 | #ifndef HAVE_STPCPY |
144 | char* FAST_FUNC stpcpy(char *p, const char *to_add) |
145 | { |
146 | while ((*p = *to_add) != '\0') { |
147 | p++; |
148 | to_add++; |
149 | } |
150 | return p; |
151 | } |
152 | #endif |
153 | |
154 | #ifndef HAVE_GETLINE |
155 | ssize_t FAST_FUNC getline(char **lineptr, size_t *n, FILE *stream) |
156 | { |
157 | int ch; |
158 | char *line = *lineptr; |
159 | size_t alloced = *n; |
160 | size_t len = 0; |
161 | |
162 | do { |
163 | ch = fgetc(stream); |
164 | if (ch == EOF) |
165 | break; |
166 | if (len + 1 >= alloced) { |
167 | alloced += alloced/4 + 64; |
168 | line = xrealloc(line, alloced); |
169 | } |
170 | line[len++] = ch; |
171 | } while (ch != '\n'); |
172 | |
173 | if (len == 0) |
174 | return -1; |
175 | |
176 | line[len] = '\0'; |
177 | *lineptr = line; |
178 | *n = alloced; |
179 | return len; |
180 | } |
181 | #endif |
182 |