/****************************************************************************
- * Copyright (c) 2013-2016,2020 Free Software Foundation, Inc. *
+ * Copyright 2020,2023 Thomas E. Dickey *
+ * Copyright 2013-2014,2016 Free Software Foundation, Inc. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the *
#include <curses.priv.h>
-MODULE_ID("$Id: obsolete.c,v 1.5 2020/01/18 17:02:38 tom Exp $")
+MODULE_ID("$Id: obsolete.c,v 1.11 2023/10/21 15:38:47 tom Exp $")
/*
* Obsolete entrypoint retained for binary compatibility.
#undef CH
}
#endif /* EXP_XTERM_1005 */
+
+#ifdef EXP_OOM_TESTING
+/*
+ * Out-of-memory testing, suitable for checking if initialization (and limited
+ * running) recovers from errors due to insufficient memory. In practice, this
+ * is unlikely except with artificially constructed tests (or poorly behaved
+ * applications).
+ */
+#undef malloc
+#undef calloc
+#undef realloc
+#undef free
+#undef strdup
+
+#define TR_OOM(stmt) T(stmt)
+
+static long oom_limit = -1;
+static long oom_count = 0;
+
+static bool
+oom_check(void)
+{
+ static bool initialized = FALSE;
+ static bool triggered = FALSE;
+ bool result = FALSE;
+
+ if (!initialized) {
+ char *env = getenv("NCURSES_OOM_TESTING");
+ initialized = TRUE;
+ if (env != NULL) {
+ char *check;
+ oom_limit = strtol(env, &check, 0);
+ if (check != NULL && *check != '\0')
+ oom_limit = 0;
+ }
+ }
+ ++oom_count;
+ if (oom_limit >= 0) {
+ result = (oom_count > oom_limit);
+ if (result && !triggered) {
+ triggered = TRUE;
+ TR_OOM(("out-of-memory"));
+ }
+ }
+ return result;
+}
+
+NCURSES_EXPORT(void *)
+_nc_oom_malloc(size_t size)
+{
+ char *result = (oom_check()
+ ? NULL
+ : malloc(size));
+ TR_OOM(("oom #%ld malloc(%ld) %p", oom_count, size, result));
+ return result;
+}
+
+NCURSES_EXPORT(void *)
+_nc_oom_calloc(size_t nmemb, size_t size)
+{
+ char *result = (oom_check()
+ ? NULL
+ : calloc(nmemb, size));
+ TR_OOM(("oom #%ld calloc(%ld, %ld) %p", oom_count, nmemb, size, result));
+ return result;
+}
+
+NCURSES_EXPORT(void *)
+_nc_oom_realloc(void *ptr, size_t size)
+{
+ char *result = (oom_check()
+ ? NULL
+ : realloc(ptr, size));
+ TR_OOM(("oom #%ld realloc(%p, %ld) %p", oom_count, ptr, size, result));
+ return result;
+}
+
+NCURSES_EXPORT(void)
+_nc_oom_free(void *ptr)
+{
+ ++oom_count;
+ TR_OOM(("oom #%ld free(%p)", oom_count, ptr));
+ free(ptr);
+}
+
+NCURSES_EXPORT(char *)
+_nc_oom_strdup(const char *ptr)
+{
+ char *result = (oom_check()
+ ? NULL
+ : strdup(ptr));
+ TR_OOM(("oom #%ld strdup(%p) %p", oom_count, ptr, result));
+ return result;
+}
+#endif /* EXP_OOM_TESTING */