1 /**************************************************************************** 2 * Copyright 2018,2020 Thomas E. Dickey * 3 * Copyright 1998-2016,2017 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 32 * and: Eric S. Raymond <esr@snark.thyrsus.com> * 33 * and: Thomas E. Dickey 1996-on * 34 * and: Juergen Pfeifer * 35 ****************************************************************************/ 36 37 /* 38 ** lib_data.c 39 ** 40 ** Common data that may/may not be allocated, but is referenced globally 41 ** 42 */ 43 44 #include <curses.priv.h> 45 46 MODULE_ID("$Id: lib_data.c,v 1.80 2020/02/02 23:34:34 tom Exp $") 47 48 /* 49 * OS/2's native linker complains if we don't initialize public data when 50 * constructing a dll (reported by J.J.G.Ripoll). 51 */ 52 #if USE_REENTRANT 53 NCURSES_EXPORT(WINDOW *) 54 NCURSES_PUBLIC_VAR(stdscr) (void) 55 { 56 return CURRENT_SCREEN ? StdScreen(CURRENT_SCREEN) : 0; 57 } 58 NCURSES_EXPORT(WINDOW *) 59 NCURSES_PUBLIC_VAR(curscr) (void) 60 { 61 return CURRENT_SCREEN ? CurScreen(CURRENT_SCREEN) : 0; 62 } 63 NCURSES_EXPORT(WINDOW *) 64 NCURSES_PUBLIC_VAR(newscr) (void) 65 { 66 return CURRENT_SCREEN ? NewScreen(CURRENT_SCREEN) : 0; 67 } 68 #else 69 NCURSES_EXPORT_VAR(WINDOW *) stdscr = 0; 70 NCURSES_EXPORT_VAR(WINDOW *) curscr = 0; 71 NCURSES_EXPORT_VAR(WINDOW *) newscr = 0; 72 #endif 73 74 NCURSES_EXPORT_VAR(SCREEN *) _nc_screen_chain = 0; 75 76 /* 77 * The variable 'SP' will be defined as a function on systems that cannot link 78 * data-only modules, since it is used in a lot of places within ncurses and we 79 * cannot guarantee that any application will use any particular function. We 80 * put the WINDOW variables in this module, because it appears that any 81 * application that uses them will also use 'SP'. 82 * 83 * This module intentionally does not reference other ncurses modules, to avoid 84 * module coupling that increases the size of the executable. 85 */ 86 #if BROKEN_LINKER 87 static SCREEN *my_screen; 88 89 NCURSES_EXPORT(SCREEN *) 90 _nc_screen(void) 91 { 92 return my_screen; 93 } 94 95 NCURSES_EXPORT(int) 96 _nc_alloc_screen(void) 97 { 98 my_screen = _nc_alloc_screen_sp(); 99 T(("_nc_alloc_screen_sp %p", my_screen)); 100 return (my_screen != 0); 101 } 102 103 NCURSES_EXPORT(void) 104 _nc_set_screen(SCREEN *sp) 105 { 106 my_screen = sp; 107 } 108 109 #else 110 111 NCURSES_EXPORT_VAR(SCREEN *) SP = NULL; /* Some linkers require initialized data... */ 112 #endif 113 /* *INDENT-OFF* */ 114 #define CHARS_0s { '\0' } 115 116 #define TGETENT_0 { 0L, FALSE, NULL, NULL, NULL } 117 #define TGETENT_0s { TGETENT_0, TGETENT_0, TGETENT_0, TGETENT_0 } 118 119 NCURSES_EXPORT_VAR(NCURSES_GLOBALS) _nc_globals = { 120 0, /* have_sigtstp */ 121 0, /* have_sigwinch */ 122 0, /* cleanup_nested */ 123 124 FALSE, /* init_signals */ 125 FALSE, /* init_screen */ 126 127 NULL, /* comp_sourcename */ 128 NULL, /* comp_termtype */ 129 130 FALSE, /* have_tic_directory */ 131 FALSE, /* keep_tic_directory */ 132 0, /* tic_directory */ 133 134 NULL, /* dbi_list */ 135 0, /* dbi_size */ 136 137 NULL, /* first_name */ 138 NULL, /* keyname_table */ 139 0, /* init_keyname */ 140 141 0, /* slk_format */ 142 143 2048, /* getstr_limit */ 144 145 NULL, /* safeprint_buf */ 146 0, /* safeprint_used */ 147 148 TGETENT_0s, /* tgetent_cache */ 149 0, /* tgetent_index */ 150 0, /* tgetent_sequence */ 151 152 0, /* dbd_blob */ 153 0, /* dbd_list */ 154 0, /* dbd_size */ 155 0, /* dbd_time */ 156 { { 0, 0 } }, /* dbd_vars */ 157 158 #ifdef USE_TERM_DRIVER 159 0, /* term_driver */ 160 #endif 161 162 #ifndef USE_SP_WINDOWLIST 163 0, /* _nc_windowlist */ 164 #endif 165 166 #if USE_HOME_TERMINFO 167 NULL, /* home_terminfo */ 168 #endif 169 170 #if !USE_SAFE_SPRINTF 171 0, /* safeprint_cols */ 172 0, /* safeprint_rows */ 173 #endif 174 175 #ifdef USE_PTHREADS 176 PTHREAD_MUTEX_INITIALIZER, /* mutex_curses */ 177 PTHREAD_MUTEX_INITIALIZER, /* mutex_prescreen */ 178 PTHREAD_MUTEX_INITIALIZER, /* mutex_screen */ 179 PTHREAD_MUTEX_INITIALIZER, /* mutex_update */ 180 PTHREAD_MUTEX_INITIALIZER, /* mutex_tst_tracef */ 181 PTHREAD_MUTEX_INITIALIZER, /* mutex_tracef */ 182 0, /* nested_tracef */ 183 0, /* use_pthreads */ 184 #if USE_PTHREADS_EINTR 185 0, /* read_thread */ 186 #endif 187 #endif 188 #if USE_WIDEC_SUPPORT 189 CHARS_0s, /* key_name */ 190 #endif 191 #ifdef TRACE 192 FALSE, /* trace_opened */ 193 CHARS_0s, /* trace_fname */ 194 0, /* trace_level */ 195 NULL, /* trace_fp */ 196 -1, /* trace_fd */ 197 198 NULL, /* tracearg_buf */ 199 0, /* tracearg_used */ 200 201 NULL, /* tracebuf_ptr */ 202 0, /* tracebuf_used */ 203 204 CHARS_0s, /* tracechr_buf */ 205 206 NULL, /* tracedmp_buf */ 207 0, /* tracedmp_used */ 208 209 NULL, /* tracetry_buf */ 210 0, /* tracetry_used */ 211 212 { CHARS_0s, CHARS_0s }, /* traceatr_color_buf */ 213 0, /* traceatr_color_sel */ 214 -1, /* traceatr_color_last */ 215 #if !defined(USE_PTHREADS) && USE_REENTRANT 216 0, /* nested_tracef */ 217 #endif 218 #endif /* TRACE */ 219 #if NO_LEAKS 220 FALSE, /* leak_checking */ 221 #endif 222 }; 223 224 #define STACK_FRAME_0 { { 0 }, 0 } 225 #define STACK_FRAME_0s { STACK_FRAME_0 } 226 #define NUM_VARS_0s { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } 227 228 #define RIPOFF_0 { 0,0,0 } 229 #define RIPOFF_0s { RIPOFF_0 } 230 231 NCURSES_EXPORT_VAR(NCURSES_PRESCREEN) _nc_prescreen = { 232 NULL, /* allocated */ 233 TRUE, /* use_env */ 234 FALSE, /* filter_mode */ 235 A_NORMAL, /* previous_attr */ 236 { /* tparm_state */ 237 NULL, /* tparam_base */ 238 239 STACK_FRAME_0s, /* stack */ 240 0, /* stack_ptr */ 241 242 NULL, /* out_buff */ 243 0, /* out_size */ 244 0, /* out_used */ 245 246 NULL, /* fmt_buff */ 247 0, /* fmt_size */ 248 249 NUM_VARS_0s, /* dynamic_var */ 250 NUM_VARS_0s, /* static_vars */ 251 #ifdef TRACE 252 NULL, /* tname */ 253 #endif 254 }, 255 NULL, /* saved_tty */ 256 FALSE, /* use_tioctl */ 257 0, /* _outch */ 258 #ifndef USE_SP_RIPOFF 259 RIPOFF_0s, /* ripoff */ 260 NULL, /* rsp */ 261 #endif 262 #if NCURSES_NO_PADDING 263 FALSE, /* flag to set if padding disabled */ 264 #endif 265 #if BROKEN_LINKER || USE_REENTRANT 266 NULL, /* real_acs_map */ 267 0, /* LINES */ 268 0, /* COLS */ 269 8, /* TABSIZE */ 270 1000, /* ESCDELAY */ 271 0, /* cur_term */ 272 #endif 273 #ifdef TRACE 274 #if BROKEN_LINKER || USE_REENTRANT 275 0L, /* _outchars */ 276 NULL, /* _tputs_trace */ 277 #endif 278 #endif 279 }; 280 /* *INDENT-ON* */ 281 282 /* 283 * wgetch() and other functions with a WINDOW* parameter may use a SCREEN* 284 * internally, and it is useful to allow those to be invoked without switching 285 * SCREEN's, e.g., for multi-threaded applications. 286 */ 287 NCURSES_EXPORT(SCREEN *) 288 _nc_screen_of(WINDOW *win) 289 { 290 SCREEN *sp = 0; 291 292 if (win != 0) { 293 sp = WINDOW_EXT(win, screen); 294 } 295 return (sp); 296 } 297 298 /******************************************************************************/ 299 #ifdef USE_PTHREADS 300 static void 301 init_global_mutexes(void) 302 { 303 static bool initialized = FALSE; 304 305 if (!initialized) { 306 initialized = TRUE; 307 _nc_mutex_init(&_nc_globals.mutex_curses); 308 _nc_mutex_init(&_nc_globals.mutex_prescreen); 309 _nc_mutex_init(&_nc_globals.mutex_screen); 310 _nc_mutex_init(&_nc_globals.mutex_update); 311 _nc_mutex_init(&_nc_globals.mutex_tst_tracef); 312 _nc_mutex_init(&_nc_globals.mutex_tracef); 313 } 314 } 315 316 NCURSES_EXPORT(void) 317 _nc_init_pthreads(void) 318 { 319 if (_nc_use_pthreads) 320 return; 321 # if USE_WEAK_SYMBOLS 322 if ((pthread_mutex_init) == 0) 323 return; 324 if ((pthread_mutex_lock) == 0) 325 return; 326 if ((pthread_mutex_unlock) == 0) 327 return; 328 if ((pthread_mutex_trylock) == 0) 329 return; 330 if ((pthread_mutexattr_settype) == 0) 331 return; 332 # endif 333 _nc_use_pthreads = 1; 334 init_global_mutexes(); 335 } 336 337 /* 338 * Use recursive mutexes if we have them - they're part of Unix98. 339 * For the cases where we do not, _nc_mutex_trylock() is used to avoid a 340 * deadlock, at the expense of memory leaks and unexpected failures that 341 * may not be handled by typical clients. 342 * 343 * FIXME - need configure check for PTHREAD_MUTEX_RECURSIVE, define it to 344 * PTHREAD_MUTEX_NORMAL if not supported. 345 */ 346 NCURSES_EXPORT(void) 347 _nc_mutex_init(pthread_mutex_t * obj) 348 { 349 pthread_mutexattr_t recattr; 350 351 if (_nc_use_pthreads) { 352 pthread_mutexattr_init(&recattr); 353 pthread_mutexattr_settype(&recattr, PTHREAD_MUTEX_RECURSIVE); 354 pthread_mutex_init(obj, &recattr); 355 } 356 } 357 358 NCURSES_EXPORT(int) 359 _nc_mutex_lock(pthread_mutex_t * obj) 360 { 361 if (_nc_use_pthreads == 0) 362 return 0; 363 return pthread_mutex_lock(obj); 364 } 365 366 NCURSES_EXPORT(int) 367 _nc_mutex_trylock(pthread_mutex_t * obj) 368 { 369 if (_nc_use_pthreads == 0) 370 return 0; 371 return pthread_mutex_trylock(obj); 372 } 373 374 NCURSES_EXPORT(int) 375 _nc_mutex_unlock(pthread_mutex_t * obj) 376 { 377 if (_nc_use_pthreads == 0) 378 return 0; 379 return pthread_mutex_unlock(obj); 380 } 381 #endif /* USE_PTHREADS */ 382 383 #if defined(USE_PTHREADS) || USE_PTHREADS_EINTR 384 #if USE_WEAK_SYMBOLS 385 /* 386 * NB: sigprocmask(2) is global but pthread_sigmask(3p) 387 * only for the calling thread. 388 */ 389 NCURSES_EXPORT(int) 390 _nc_sigprocmask(int how, const sigset_t * newmask, sigset_t * oldmask) 391 { 392 if ((pthread_sigmask)) 393 return pthread_sigmask(how, newmask, oldmask); 394 else 395 return (sigprocmask) (how, newmask, oldmask); 396 } 397 #endif 398 #endif /* USE_PTHREADS */ 399