xref: /openbsd/lib/libcurses/tinfo/obsolete.c (revision c7ef0cfc)
1 /****************************************************************************
2  * Copyright 2020,2023 Thomas E. Dickey                                     *
3  * Copyright 2013-2014,2016 Free Software Foundation, Inc.                  *
4  *                                                                          *
5  * Permission is hereby granted, free of charge, to any person obtaining a  *
6  * copy of this software and associated documentation files (the            *
7  * "Software"), to deal in the Software without restriction, including      *
8  * without limitation the rights to use, copy, modify, merge, publish,      *
9  * distribute, distribute with modifications, sublicense, and/or sell       *
10  * copies of the Software, and to permit persons to whom the Software is    *
11  * furnished to do so, subject to the following conditions:                 *
12  *                                                                          *
13  * The above copyright notice and this permission notice shall be included  *
14  * in all copies or substantial portions of the Software.                   *
15  *                                                                          *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
19  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
20  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
21  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
23  *                                                                          *
24  * Except as contained in this notice, the name(s) of the above copyright   *
25  * holders shall not be used in advertising or otherwise to promote the     *
26  * sale, use or other dealings in this Software without prior written       *
27  * authorization.                                                           *
28  ****************************************************************************/
29 
30 /****************************************************************************
31  *  Author: Thomas E. Dickey                        2013-on                 *
32  ****************************************************************************/
33 
34 /*
35 **	Support for obsolete/unusual features.
36 */
37 
38 #include <curses.priv.h>
39 
40 MODULE_ID("$Id: obsolete.c,v 1.1 2023/10/17 09:52:09 nicm Exp $")
41 
42 /*
43  * Obsolete entrypoint retained for binary compatibility.
44  */
NCURSES_EXPORT(void)45 NCURSES_EXPORT(void)
46 NCURSES_SP_NAME(_nc_set_buffer) (NCURSES_SP_DCLx FILE *ofp, int buffered)
47 {
48 #if NCURSES_SP_FUNCS
49     (void) SP_PARM;
50 #endif
51     (void) ofp;
52     (void) buffered;
53 }
54 
55 #if NCURSES_SP_FUNCS
56 NCURSES_EXPORT(void)
_nc_set_buffer(FILE * ofp,int buffered)57 _nc_set_buffer(FILE *ofp, int buffered)
58 {
59     NCURSES_SP_NAME(_nc_set_buffer) (CURRENT_SCREEN, ofp, buffered);
60 }
61 #endif
62 
63 #if !HAVE_STRDUP
64 NCURSES_EXPORT(char *)
_nc_strdup(const char * s)65 _nc_strdup(const char *s)
66 {
67     char *result = 0;
68     if (s != 0) {
69 	size_t need = strlen(s);
70 	result = malloc(need + 1);
71 	if (result != 0) {
72 	    _nc_STRCPY(result, s, need);
73 	}
74     }
75     return result;
76 }
77 #endif
78 
79 #if USE_MY_MEMMOVE
80 #define DST ((char *)s1)
81 #define SRC ((const char *)s2)
82 NCURSES_EXPORT(void *)
_nc_memmove(void * s1,const void * s2,size_t n)83 _nc_memmove(void *s1, const void *s2, size_t n)
84 {
85     if (n != 0) {
86 	if ((DST + n > SRC) && (SRC + n > DST)) {
87 	    static char *bfr;
88 	    static size_t length;
89 	    register size_t j;
90 	    if (length < n) {
91 		length = (n * 3) / 2;
92 		bfr = typeRealloc(char, length, bfr);
93 	    }
94 	    for (j = 0; j < n; j++)
95 		bfr[j] = SRC[j];
96 	    s2 = bfr;
97 	}
98 	while (n-- != 0)
99 	    DST[n] = SRC[n];
100     }
101     return s1;
102 }
103 #endif /* USE_MY_MEMMOVE */
104 
105 #ifdef EXP_XTERM_1005
106 NCURSES_EXPORT(int)
_nc_conv_to_utf8(unsigned char * target,unsigned source,unsigned limit)107 _nc_conv_to_utf8(unsigned char *target, unsigned source, unsigned limit)
108 {
109 #define CH(n) UChar((source) >> ((n) * 8))
110     int rc = 0;
111 
112     if (source <= 0x0000007f)
113 	rc = 1;
114     else if (source <= 0x000007ff)
115 	rc = 2;
116     else if (source <= 0x0000ffff)
117 	rc = 3;
118     else if (source <= 0x001fffff)
119 	rc = 4;
120     else if (source <= 0x03ffffff)
121 	rc = 5;
122     else			/* (source <= 0x7fffffff) */
123 	rc = 6;
124 
125     if ((unsigned) rc > limit) {	/* whatever it is, we cannot decode it */
126 	rc = 0;
127     }
128 
129     if (target != 0) {
130 	switch (rc) {
131 	case 1:
132 	    target[0] = CH(0);
133 	    break;
134 
135 	case 2:
136 	    target[1] = UChar(0x80 | (CH(0) & 0x3f));
137 	    target[0] = UChar(0xc0 | (CH(0) >> 6) | ((CH(1) & 0x07) << 2));
138 	    break;
139 
140 	case 3:
141 	    target[2] = UChar(0x80 | (CH(0) & 0x3f));
142 	    target[1] = UChar(0x80 | (CH(0) >> 6) | ((CH(1) & 0x0f) << 2));
143 	    target[0] = UChar(0xe0 | ((int) (CH(1) & 0xf0) >> 4));
144 	    break;
145 
146 	case 4:
147 	    target[3] = UChar(0x80 | (CH(0) & 0x3f));
148 	    target[2] = UChar(0x80 | (CH(0) >> 6) | ((CH(1) & 0x0f) << 2));
149 	    target[1] = UChar(0x80 |
150 			      ((int) (CH(1) & 0xf0) >> 4) |
151 			      ((int) (CH(2) & 0x03) << 4));
152 	    target[0] = UChar(0xf0 | ((int) (CH(2) & 0x1f) >> 2));
153 	    break;
154 
155 	case 5:
156 	    target[4] = UChar(0x80 | (CH(0) & 0x3f));
157 	    target[3] = UChar(0x80 | (CH(0) >> 6) | ((CH(1) & 0x0f) << 2));
158 	    target[2] = UChar(0x80 |
159 			      ((int) (CH(1) & 0xf0) >> 4) |
160 			      ((int) (CH(2) & 0x03) << 4));
161 	    target[1] = UChar(0x80 | (CH(2) >> 2));
162 	    target[0] = UChar(0xf8 | (CH(3) & 0x03));
163 	    break;
164 
165 	case 6:
166 	    target[5] = UChar(0x80 | (CH(0) & 0x3f));
167 	    target[4] = UChar(0x80 | (CH(0) >> 6) | ((CH(1) & 0x0f) << 2));
168 	    target[3] = UChar(0x80 | (CH(1) >> 4) | ((CH(2) & 0x03) << 4));
169 	    target[2] = UChar(0x80 | (CH(2) >> 2));
170 	    target[1] = UChar(0x80 | (CH(3) & 0x3f));
171 	    target[0] = UChar(0xfc | ((int) (CH(3) & 0x40) >> 6));
172 	    break;
173 	}
174     }
175 
176     return rc;			/* number of bytes needed in target */
177 #undef CH
178 }
179 
180 NCURSES_EXPORT(int)
_nc_conv_to_utf32(unsigned * target,const char * source,unsigned limit)181 _nc_conv_to_utf32(unsigned *target, const char *source, unsigned limit)
182 {
183 #define CH(n) UChar((*target) >> ((n) * 8))
184     int rc = 0;
185     int j;
186     unsigned mask = 0;
187 
188     /*
189      * Find the number of bytes we will need from the source.
190      */
191     if ((*source & 0x80) == 0) {
192 	rc = 1;
193 	mask = (unsigned) *source;
194     } else if ((*source & 0xe0) == 0xc0) {
195 	rc = 2;
196 	mask = (unsigned) (*source & 0x1f);
197     } else if ((*source & 0xf0) == 0xe0) {
198 	rc = 3;
199 	mask = (unsigned) (*source & 0x0f);
200     } else if ((*source & 0xf8) == 0xf0) {
201 	rc = 4;
202 	mask = (unsigned) (*source & 0x07);
203     } else if ((*source & 0xfc) == 0xf8) {
204 	rc = 5;
205 	mask = (unsigned) (*source & 0x03);
206     } else if ((*source & 0xfe) == 0xfc) {
207 	rc = 6;
208 	mask = (unsigned) (*source & 0x01);
209     }
210 
211     if ((unsigned) rc > limit) {	/* whatever it is, we cannot decode it */
212 	rc = 0;
213     }
214 
215     /*
216      * sanity-check.
217      */
218     if (rc > 1) {
219 	for (j = 1; j < rc; j++) {
220 	    if ((source[j] & 0xc0) != 0x80)
221 		break;
222 	}
223 	if (j != rc) {
224 	    rc = 0;
225 	}
226     }
227 
228     if (target != 0) {
229 	int shift = 0;
230 	*target = 0;
231 	for (j = 1; j < rc; j++) {
232 	    *target |= (unsigned) (source[rc - j] & 0x3f) << shift;
233 	    shift += 6;
234 	}
235 	*target |= mask << shift;
236     }
237     return rc;
238 #undef CH
239 }
240 #endif /* EXP_XTERM_1005 */
241 
242 #ifdef EXP_OOM_TESTING
243 /*
244  * Out-of-memory testing, suitable for checking if initialization (and limited
245  * running) recovers from errors due to insufficient memory.  In practice, this
246  * is unlikely except with artifically constructed tests (or poorly behaved
247  * applications).
248  */
249 #undef malloc
250 #undef calloc
251 #undef realloc
252 #undef free
253 #undef strdup
254 
255 #define TR_OOM(stmt) T(stmt)
256 
257 static long oom_limit = -1;
258 static long oom_count = 0;
259 
260 static bool
oom_check(void)261 oom_check(void)
262 {
263     static bool initialized = FALSE;
264     static bool triggered = FALSE;
265     bool result = FALSE;
266 
267     if (!initialized) {
268 	char *env = getenv("NCURSES_OOM_TESTING");
269 	initialized = TRUE;
270 	if (env != NULL) {
271 	    char *check;
272 	    oom_limit = strtol(env, &check, 0);
273 	    if (check != NULL && *check != '\0')
274 		oom_limit = 0;
275 	}
276     }
277     ++oom_count;
278     if (oom_limit >= 0) {
279 	result = (oom_count > oom_limit);
280 	if (result && !triggered) {
281 	    triggered = TRUE;
282 	    TR_OOM(("out-of-memory"));
283 	}
284     }
285     return result;
286 }
287 
288 NCURSES_EXPORT(void *)
_nc_oom_malloc(size_t size)289 _nc_oom_malloc(size_t size)
290 {
291     char *result = (oom_check()
292 		    ? NULL
293 		    : malloc(size));
294     TR_OOM(("oom #%ld malloc(%ld) %p", oom_count, size, result));
295     return result;
296 }
297 
298 NCURSES_EXPORT(void *)
_nc_oom_calloc(size_t nmemb,size_t size)299 _nc_oom_calloc(size_t nmemb, size_t size)
300 {
301     char *result = (oom_check()
302 		    ? NULL
303 		    : calloc(nmemb, size));
304     TR_OOM(("oom #%ld calloc(%ld, %ld) %p", oom_count, nmemb, size, result));
305     return result;
306 }
307 
308 NCURSES_EXPORT(void *)
_nc_oom_realloc(void * ptr,size_t size)309 _nc_oom_realloc(void *ptr, size_t size)
310 {
311     char *result = (oom_check()
312 		    ? NULL
313 		    : realloc(ptr, size));
314     TR_OOM(("oom #%ld realloc(%p, %ld) %p", oom_count, ptr, size, result));
315     return result;
316 }
317 
318 NCURSES_EXPORT(void)
_nc_oom_free(void * ptr)319 _nc_oom_free(void *ptr)
320 {
321     ++oom_count;
322     TR_OOM(("oom #%ld free(%p)", oom_count, ptr));
323     free(ptr);
324 }
325 
326 NCURSES_EXPORT(char *)
_nc_oom_strdup(const char * ptr)327 _nc_oom_strdup(const char *ptr)
328 {
329     char *result = (oom_check()
330 		    ? NULL
331 		    : strdup(ptr));
332     TR_OOM(("oom #%ld strdup(%p) %p", oom_count, ptr, result));
333     return result;
334 }
335 #endif /* EXP_OOM_TESTING */
336