xref: /php-src/main/reentrancy.c (revision 2b30f187)
1 /*
2    +----------------------------------------------------------------------+
3    | Copyright (c) The PHP Group                                          |
4    +----------------------------------------------------------------------+
5    | This source file is subject to version 3.01 of the PHP license,      |
6    | that is bundled with this package in the file LICENSE, and is        |
7    | available through the world-wide-web at the following url:           |
8    | https://www.php.net/license/3_01.txt                                 |
9    | If you did not receive a copy of the PHP license and are unable to   |
10    | obtain it through the world-wide-web, please send a note to          |
11    | license@php.net so we can mail you a copy immediately.               |
12    +----------------------------------------------------------------------+
13    | Author: Sascha Schumann <sascha@schumann.cx>                         |
14    +----------------------------------------------------------------------+
15  */
16 
17 #include <sys/types.h>
18 #include <string.h>
19 #include <errno.h>
20 #ifdef HAVE_DIRENT_H
21 #include <dirent.h>
22 #endif
23 
24 #include "php_reentrancy.h"
25 
26 enum {
27 	LOCALTIME_R,
28 	CTIME_R,
29 	ASCTIME_R,
30 	GMTIME_R,
31 	NUMBER_OF_LOCKS
32 };
33 
34 #if defined(PHP_NEED_REENTRANCY)
35 
36 #include <TSRM.h>
37 
38 static MUTEX_T reentrant_locks[NUMBER_OF_LOCKS];
39 
40 #define local_lock(x) tsrm_mutex_lock(reentrant_locks[x])
41 #define local_unlock(x) tsrm_mutex_unlock(reentrant_locks[x])
42 
43 #else
44 
45 #define local_lock(x)
46 #define local_unlock(x)
47 
48 #endif
49 
50 #if defined(PHP_IRIX_TIME_R)
51 
52 #define HAVE_CTIME_R 1
53 #define HAVE_ASCTIME_R 1
54 
php_ctime_r(const time_t * clock,char * buf)55 PHPAPI char *php_ctime_r(const time_t *clock, char *buf)
56 {
57 	if (ctime_r(clock, buf) == buf)
58 		return (buf);
59 	return (NULL);
60 }
61 
php_asctime_r(const struct tm * tm,char * buf)62 PHPAPI char *php_asctime_r(const struct tm *tm, char *buf)
63 {
64 	if (asctime_r(tm, buf) == buf)
65 		return (buf);
66 	return (NULL);
67 }
68 
69 #endif
70 
71 #if defined(PHP_HPUX_TIME_R)
72 
73 #define HAVE_LOCALTIME_R 1
74 #define HAVE_CTIME_R 1
75 #define HAVE_ASCTIME_R 1
76 #define HAVE_GMTIME_R 1
77 
php_localtime_r(const time_t * const timep,struct tm * p_tm)78 PHPAPI struct tm *php_localtime_r(const time_t *const timep, struct tm *p_tm)
79 {
80 	if (localtime_r(timep, p_tm) == 0)
81 		return (p_tm);
82 	return (NULL);
83 }
84 
php_ctime_r(const time_t * clock,char * buf)85 PHPAPI char *php_ctime_r(const time_t *clock, char *buf)
86 {
87 	if (ctime_r(clock, buf, 26) != -1)
88 		return (buf);
89 	return (NULL);
90 }
91 
php_asctime_r(const struct tm * tm,char * buf)92 PHPAPI char *php_asctime_r(const struct tm *tm, char *buf)
93 {
94 	if (asctime_r(tm, buf, 26) != -1)
95 		return (buf);
96 	return (NULL);
97 }
98 
php_gmtime_r(const time_t * const timep,struct tm * p_tm)99 PHPAPI struct tm *php_gmtime_r(const time_t *const timep, struct tm *p_tm)
100 {
101 	if (gmtime_r(timep, p_tm) == 0)
102 		return (p_tm);
103 	return (NULL);
104 }
105 
106 #endif
107 
108 #if !defined(HAVE_LOCALTIME_R) && defined(HAVE_LOCALTIME)
109 
php_localtime_r(const time_t * const timep,struct tm * p_tm)110 PHPAPI struct tm *php_localtime_r(const time_t *const timep, struct tm *p_tm)
111 {
112 	struct tm *tmp;
113 
114 	local_lock(LOCALTIME_R);
115 
116 	tmp = localtime(timep);
117 	if (tmp) {
118 		memcpy(p_tm, tmp, sizeof(struct tm));
119 		tmp = p_tm;
120 	}
121 
122 	local_unlock(LOCALTIME_R);
123 
124 	return tmp;
125 }
126 
127 #endif
128 
129 #if !defined(HAVE_CTIME_R) && defined(HAVE_CTIME)
130 
php_ctime_r(const time_t * clock,char * buf)131 PHPAPI char *php_ctime_r(const time_t *clock, char *buf)
132 {
133 	char *tmp;
134 
135 	local_lock(CTIME_R);
136 
137 	tmp = ctime(clock);
138 	if (tmp) {
139 		strcpy(buf, tmp);
140 		tmp = buf;
141 	}
142 
143 	local_unlock(CTIME_R);
144 
145 	return tmp;
146 }
147 
148 #endif
149 
150 #if !defined(HAVE_ASCTIME_R) && defined(HAVE_ASCTIME)
151 
php_asctime_r(const struct tm * tm,char * buf)152 PHPAPI char *php_asctime_r(const struct tm *tm, char *buf)
153 {
154 	char *tmp;
155 
156 	local_lock(ASCTIME_R);
157 
158 	tmp = asctime(tm);
159 	if (tmp) {
160 		strcpy(buf, tmp);
161 		tmp = buf;
162 	}
163 
164 	local_unlock(ASCTIME_R);
165 
166 	return tmp;
167 }
168 
169 #endif
170 
171 #if !defined(HAVE_GMTIME_R) && defined(HAVE_GMTIME)
172 
php_gmtime_r(const time_t * const timep,struct tm * p_tm)173 PHPAPI struct tm *php_gmtime_r(const time_t *const timep, struct tm *p_tm)
174 {
175 	struct tm *tmp;
176 
177 	local_lock(GMTIME_R);
178 
179 	tmp = gmtime(timep);
180 	if (tmp) {
181 		memcpy(p_tm, tmp, sizeof(struct tm));
182 		tmp = p_tm;
183 	}
184 
185 	local_unlock(GMTIME_R);
186 
187 	return tmp;
188 }
189 
190 #endif
191 
192 #if defined(PHP_NEED_REENTRANCY)
193 
reentrancy_startup(void)194 void reentrancy_startup(void)
195 {
196 	int i;
197 
198 	for (i = 0; i < NUMBER_OF_LOCKS; i++) {
199 		reentrant_locks[i] = tsrm_mutex_alloc();
200 	}
201 }
202 
reentrancy_shutdown(void)203 void reentrancy_shutdown(void)
204 {
205 	int i;
206 
207 	for (i = 0; i < NUMBER_OF_LOCKS; i++) {
208 		tsrm_mutex_free(reentrant_locks[i]);
209 	}
210 }
211 
212 #endif
213 
214 
215 #ifndef HAVE_STRTOK_R
216 
217 /*
218  * Copyright (c) 1998 Softweyr LLC.  All rights reserved.
219  *
220  * strtok_r, from Berkeley strtok
221  * Oct 13, 1998 by Wes Peters <wes@softweyr.com>
222  *
223  * Copyright (c) 1988, 1993
224  *	The Regents of the University of California.  All rights reserved.
225  *
226  * Redistribution and use in source and binary forms, with or without
227  * modification, are permitted provided that the following conditions
228  * are met:
229  *
230  * 1. Redistributions of source code must retain the above copyright
231  *    notices, this list of conditions and the following disclaimer.
232  *
233  * 2. Redistributions in binary form must reproduce the above copyright
234  *    notices, this list of conditions and the following disclaimer in the
235  *    documentation and/or other materials provided with the distribution.
236  *
237  * 3. All advertising materials mentioning features or use of this software
238  *    must display the following acknowledgement:
239  *
240  *	This product includes software developed by Softweyr LLC, the
241  *      University of California, Berkeley, and its contributors.
242  *
243  * 4. Neither the name of the University nor the names of its contributors
244  *    may be used to endorse or promote products derived from this software
245  *    without specific prior written permission.
246  *
247  * THIS SOFTWARE IS PROVIDED BY SOFTWEYR LLC, THE REGENTS AND CONTRIBUTORS
248  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
249  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
250  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL SOFTWEYR LLC, THE
251  * REGENTS, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
252  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
253  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
254  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
255  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
256  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
257  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
258  */
259 
260 #include <stddef.h>
261 
262 PHPAPI char *
php_strtok_r(char * s,const char * delim,char ** last)263 php_strtok_r(char *s, const char *delim, char **last)
264 {
265     char *spanp;
266     int c, sc;
267     char *tok;
268 
269     if (s == NULL && (s = *last) == NULL)
270     {
271 	return NULL;
272     }
273 
274     /*
275      * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
276      */
277 cont:
278     c = *s++;
279     for (spanp = (char *)delim; (sc = *spanp++) != 0; )
280     {
281 	if (c == sc)
282 	{
283 	    goto cont;
284 	}
285     }
286 
287     if (c == 0)		/* no non-delimiter characters */
288     {
289 	*last = NULL;
290 	return NULL;
291     }
292     tok = s - 1;
293 
294     /*
295      * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
296      * Note that delim must have one NUL; we stop if we see that, too.
297      */
298     for (;;)
299     {
300 	c = *s++;
301 	spanp = (char *)delim;
302 	do
303 	{
304 	    if ((sc = *spanp++) == c)
305 	    {
306 		if (c == 0)
307 		{
308 		    s = NULL;
309 		}
310 		else
311 		{
312 		    char *w = s - 1;
313 		    *w = '\0';
314 		}
315 		*last = s;
316 		return tok;
317 	    }
318 	}
319 	while (sc != 0);
320     }
321     /* NOTREACHED */
322 }
323 
324 #endif
325