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