1/*********************************************************** 2Copyright (c) 1993, Oracle and/or its affiliates. 3 4Permission is hereby granted, free of charge, to any person obtaining a 5copy of this software and associated documentation files (the "Software"), 6to deal in the Software without restriction, including without limitation 7the rights to use, copy, modify, merge, publish, distribute, sublicense, 8and/or sell copies of the Software, and to permit persons to whom the 9Software is furnished to do so, subject to the following conditions: 10 11The above copyright notice and this permission notice (including the next 12paragraph) shall be included in all copies or substantial portions of the 13Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21DEALINGS IN THE SOFTWARE. 22 23Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. 24 25 All Rights Reserved 26 27Permission to use, copy, modify, and distribute this software and its 28documentation for any purpose and without fee is hereby granted, 29provided that the above copyright notice appear in all copies and that 30both that copyright notice and this permission notice appear in 31supporting documentation, and that the name of Digital not be 32used in advertising or publicity pertaining to distribution of the 33software without specific, written prior permission. 34 35DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 36ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 37DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 38ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 39WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 40ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 41SOFTWARE. 42 43******************************************************************/ 44 45/* 46 47Copyright 1987, 1988, 1998 The Open Group 48 49Permission to use, copy, modify, distribute, and sell this software and its 50documentation for any purpose is hereby granted without fee, provided that 51the above copyright notice appear in all copies and that both that 52copyright notice and this permission notice appear in supporting 53documentation. 54 55The above copyright notice and this permission notice shall be included in 56all copies or substantial portions of the Software. 57 58THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 59IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 60FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 61OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 62AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 63CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 64 65Except as contained in this notice, the name of The Open Group shall not be 66used in advertising or otherwise to promote the sale, use or other dealings 67in this Software without prior written authorization from The Open Group. 68 69*/ 70 71#ifdef HAVE_CONFIG_H 72#include <config.h> 73#endif 74#include "IntrinsicI.h" 75#include <stdio.h> 76#include <stdlib.h> 77 78/* The error handlers in the application context aren't used since we can't 79 come up with a uniform way of using them. If you can, define 80 GLOBALERRORS to be FALSE (or 0). */ 81 82#ifndef GLOBALERRORS 83#define GLOBALERRORS 1 84#endif 85 86static void InitErrorHandling(XrmDatabase *); 87 88#if GLOBALERRORS 89static XrmDatabase errorDB = NULL; 90static Boolean error_inited = FALSE; 91void _XtDefaultErrorMsg(String, String, String, String, String *, Cardinal *); 92void _XtDefaultWarningMsg(String, String, String, String, String *, Cardinal *); 93void 94_XtDefaultError(String) 95 _X_NORETURN; 96void 97_XtDefaultWarning(String); 98static XtErrorMsgHandler errorMsgHandler = _XtDefaultErrorMsg; 99static XtErrorMsgHandler warningMsgHandler = _XtDefaultWarningMsg; 100static XtErrorHandler errorHandler _X_NORETURN = _XtDefaultError; 101static XtErrorHandler warningHandler = _XtDefaultWarning; 102#endif /* GLOBALERRORS */ 103 104XrmDatabase * 105XtGetErrorDatabase(void) 106{ 107 XrmDatabase *retval; 108 109#if GLOBALERRORS 110 LOCK_PROCESS; 111 retval = &errorDB; 112 UNLOCK_PROCESS; 113#else 114 retval = XtAppGetErrorDatabase(_XtDefaultAppContext()); 115#endif /* GLOBALERRORS */ 116 return retval; 117} 118 119XrmDatabase * 120XtAppGetErrorDatabase(XtAppContext app _X_UNUSED) 121{ 122 XrmDatabase *retval; 123 124#if GLOBALERRORS 125 LOCK_PROCESS; 126 retval = &errorDB; 127 UNLOCK_PROCESS; 128#else 129 LOCK_APP(app); 130 retval = &app->errorDB; 131 UNLOCK_APP(app); 132#endif /* GLOBALERRORS */ 133 return retval; 134} 135 136void 137XtGetErrorDatabaseText(register _Xconst char *name, 138 register _Xconst char *type, 139 register _Xconst char *class, 140 _Xconst char *defaultp, 141 _XtString buffer, int nbytes) 142{ 143#if GLOBALERRORS 144 XtAppGetErrorDatabaseText(NULL, 145 name, type, class, defaultp, buffer, nbytes, 146 NULL); 147#else 148 XtAppGetErrorDatabaseText(_XtDefaultAppContext(), 149 name, type, class, defaultp, buffer, nbytes, 150 NULL); 151#endif /* GLOBALERRORS */ 152} 153 154void 155XtAppGetErrorDatabaseText(XtAppContext app _X_UNUSED, 156 register _Xconst char *name, 157 register _Xconst char *type, 158 register _Xconst char *class, 159 _Xconst char *defaultp, 160 _XtString buffer, 161 int nbytes, 162 XrmDatabase db) 163{ 164 String str_class; 165 _XtString type_str; 166 XrmValue result; 167 char *str_name = NULL; 168 char *temp = NULL; 169 170#if GLOBALERRORS 171 LOCK_PROCESS; 172 if (error_inited == FALSE) { 173 InitErrorHandling(&errorDB); 174 error_inited = TRUE; 175 } 176#else 177 LOCK_APP(app); 178 if (app->error_inited == FALSE) { 179 InitErrorHandling(&app->errorDB); 180 app->error_inited = TRUE; 181 } 182#endif /* GLOBALERRORS */ 183 if (!(str_name = ALLOCATE_LOCAL(strlen(name) + strlen(type) + 2))) 184 _XtAllocError(NULL); 185 (void) sprintf(str_name, "%s.%s", name, type); 186 /* XrmGetResource requires the name and class to be fully qualified 187 * and to have the same number of components. */ 188 str_class = (String) class; 189 if (!strchr(class, '.')) { 190 if (!(temp = ALLOCATE_LOCAL(2 * strlen(class) + 2))) 191 _XtAllocError(NULL); 192 (void) sprintf(temp, "%s.%s", class, class); 193 str_class = temp; 194 } 195 if (db == NULL) { 196#if GLOBALERRORS 197 (void) XrmGetResource(errorDB, str_name, str_class, &type_str, &result); 198#else 199 (void) XrmGetResource(app->errorDB, str_name, str_class, &type_str, 200 &result); 201#endif /* GLOBALERRORS */ 202 } 203 else 204 (void) XrmGetResource(db, str_name, str_class, &type_str, &result); 205 if (result.addr) { 206 (void) strncpy(buffer, result.addr, (size_t) nbytes); 207 if (result.size > (unsigned) nbytes) 208 buffer[nbytes - 1] = 0; 209 } 210 else { 211 int len = (int) strlen(defaultp); 212 213 if (len >= nbytes) 214 len = nbytes - 1; 215 (void) memmove(buffer, defaultp, (size_t) len); 216 buffer[len] = '\0'; 217 } 218 if (str_name) 219 DEALLOCATE_LOCAL(str_name); 220 if (temp) 221 DEALLOCATE_LOCAL(temp); 222#if GLOBALERRORS 223 UNLOCK_PROCESS; 224#else 225 UNLOCK_APP(app); 226#endif 227} 228 229static void 230InitErrorHandling(XrmDatabase *db) 231{ 232 XrmDatabase errordb; 233 234 errordb = XrmGetFileDatabase(ERRORDB); 235 XrmMergeDatabases(errordb, db); 236} 237 238static void 239DefaultMsg(String name, 240 String type, 241 String class, 242 String defaultp, 243 String *params, 244 const Cardinal *num_params, 245 Bool error, 246 void (*fn) (_Xconst _XtString)) 247{ 248#define BIGBUF 1024 249 char buffer[BIGBUF]; 250 char *message; 251 252 XtGetErrorDatabaseText(name, type, class, defaultp, buffer, BIGBUF); 253/*need better solution here, perhaps use lower level printf primitives? */ 254 if (params == NULL || num_params == NULL || *num_params == 0) 255 (*fn) (buffer); 256#ifndef WIN32 /* and OS/2 */ 257 else if ((getuid() != geteuid()) || getuid() == 0) { 258 if ((error && errorHandler == _XtDefaultError) || 259 (!error && warningHandler == _XtDefaultWarning)) { 260 /* 261 * if it's just going to go to stderr anyway, then we'll 262 * fprintf to stderr ourselves and skip the insecure sprintf. 263 */ 264 Cardinal i = *num_params; 265 String par[10]; 266 267 if (i > 10) 268 i = 10; 269 (void) memcpy(par, params, i * sizeof(String)); 270 memset(&par[i], 0, (10 - i) * sizeof(String)); 271 (void) fprintf(stderr, "%s%s", 272 error ? XTERROR_PREFIX : XTWARNING_PREFIX, 273 error ? "Error: " : "Warning: "); 274 (void) fprintf(stderr, buffer, 275 par[0], par[1], par[2], par[3], par[4], 276 par[5], par[6], par[7], par[8], par[9]); 277 (void) fprintf(stderr, "%c", '\n'); 278 if (i != *num_params) 279 (*fn) ("Some arguments in previous message were lost"); 280 else if (error) 281 exit(1); 282 } 283 else { 284 /* 285 * can't tell what it might do, so we'll play it safe 286 */ 287 XtWarning("\ 288This program is an suid-root program or is being run by the root user.\n\ 289The full text of the error or warning message cannot be safely formatted\n\ 290in this environment. You may get a more descriptive message by running the\n\ 291program as a non-root user or by removing the suid bit on the executable."); 292 (*fn) (buffer); /* if *fn is an ErrorHandler it should exit */ 293 } 294 } 295#endif 296 else { 297 /* 298 * If you have snprintf the worst thing that could happen is you'd 299 * lose some information. Without snprintf you're probably going to 300 * scramble your heap and perhaps SEGV -- sooner or later. 301 * If it hurts when you go like this then don't go like this! :-) 302 */ 303 Cardinal i = *num_params; 304 String par[10]; 305 306 if (i > 10) 307 i = 10; 308 (void) memcpy(par, params, i * sizeof(String)); 309 memset(&par[i], 0, (10 - i) * sizeof(String)); 310 if (i != *num_params) 311 XtWarning("Some arguments in following message were lost"); 312 /* 313 * resist any temptation you might have to make `message' a 314 * local buffer on the stack. Doing so is a security hole 315 * in programs executing as root. Error and Warning 316 * messages shouldn't be called frequently enough for this 317 * to be a performance issue. 318 */ 319 if ((message = __XtMalloc(BIGBUF))) { 320 (void) snprintf(message, BIGBUF, buffer, 321 par[0], par[1], par[2], par[3], par[4], 322 par[5], par[6], par[7], par[8], par[9]); 323 (*fn) (message); 324 XtFree(message); 325 } 326 else { 327 XtWarning 328 ("Memory allocation failed, arguments in the following message were lost"); 329 (*fn) (buffer); 330 } 331 } 332} 333 334void 335_XtDefaultErrorMsg(String name, 336 String type, 337 String class, 338 String defaultp, 339 String *params, 340 Cardinal *num_params) 341{ 342 DefaultMsg(name, type, class, defaultp, params, num_params, True, XtError); 343} 344 345void 346_XtDefaultWarningMsg(String name, 347 String type, 348 String class, 349 String defaultp, 350 String *params, 351 Cardinal *num_params) 352{ 353 DefaultMsg(name, type, class, defaultp, params, num_params, False, 354 XtWarning); 355} 356 357void 358XtErrorMsg(_Xconst char *name, 359 _Xconst char *type, 360 _Xconst char *class, 361 _Xconst char *defaultp, 362 String *params, 363 Cardinal *num_params) 364{ 365#if GLOBALERRORS 366 LOCK_PROCESS; 367 (*errorMsgHandler) ((String) name, (String) type, (String) class, 368 (String) defaultp, params, num_params); 369 UNLOCK_PROCESS; 370 exit(1); 371#else 372 XtAppErrorMsg(_XtDefaultAppContext(), name, type, class, 373 defaultp, params, num_params); 374#endif /* GLOBALERRORS */ 375} 376 377void 378XtAppErrorMsg(XtAppContext app _X_UNUSED, 379 _Xconst char *name, 380 _Xconst char *type, 381 _Xconst char *class, 382 _Xconst char *defaultp, 383 String *params, 384 Cardinal *num_params) 385{ 386#if GLOBALERRORS 387 LOCK_PROCESS; 388 (*errorMsgHandler) ((String) name, (String) type, (String) class, 389 (String) defaultp, params, num_params); 390 UNLOCK_PROCESS; 391 exit(1); 392#else 393 LOCK_APP(app); 394 (*app->errorMsgHandler) (name, type, class, defaultp, params, num_params); 395 UNLOCK_APP(app); 396#endif /* GLOBALERRORS */ 397} 398 399void 400XtWarningMsg(_Xconst char *name, 401 _Xconst char *type, 402 _Xconst char *class, 403 _Xconst char *defaultp, 404 String *params, 405 Cardinal *num_params) 406{ 407#if GLOBALERRORS 408 LOCK_PROCESS; 409 (*warningMsgHandler) ((String) name, (String) type, (String) class, 410 (String) defaultp, params, num_params); 411 UNLOCK_PROCESS; 412#else 413 XtAppWarningMsg(_XtDefaultAppContext(), name, type, class, 414 defaultp, params, num_params); 415#endif /* GLOBALERRORS */ 416} 417 418void 419XtAppWarningMsg(XtAppContext app _X_UNUSED, 420 _Xconst char *name, 421 _Xconst char *type, 422 _Xconst char *class, 423 _Xconst char *defaultp, 424 String *params, 425 Cardinal *num_params) 426{ 427#if GLOBALERRORS 428 LOCK_PROCESS; 429 (*warningMsgHandler) ((String) name, (String) type, (String) class, 430 (String) defaultp, params, num_params); 431 UNLOCK_PROCESS; 432#else 433 LOCK_APP(app); 434 (*app->warningMsgHandler) (name, type, class, defaultp, params, num_params); 435 UNLOCK_APP(app); 436#endif /* GLOBALERRORS */ 437} 438 439void 440XtSetErrorMsgHandler(XtErrorMsgHandler handler _X_NORETURN) 441{ 442#if GLOBALERRORS 443 LOCK_PROCESS; 444 if (handler != NULL) 445 errorMsgHandler = handler; 446 else 447 errorMsgHandler = _XtDefaultErrorMsg; 448 UNLOCK_PROCESS; 449#else 450 XtAppSetErrorMsgHandler(_XtDefaultAppContext(), handler); 451#endif /* GLOBALERRORS */ 452} 453 454XtErrorMsgHandler 455XtAppSetErrorMsgHandler(XtAppContext app _X_UNUSED, 456 XtErrorMsgHandler handler _X_NORETURN) 457{ 458 XtErrorMsgHandler old; 459 460#if GLOBALERRORS 461 LOCK_PROCESS; 462 old = errorMsgHandler; 463 if (handler != NULL) 464 errorMsgHandler = handler; 465 else 466 errorMsgHandler = _XtDefaultErrorMsg; 467 UNLOCK_PROCESS; 468#else 469 LOCK_APP(app); 470 old = app->errorMsgHandler; 471 if (handler != NULL) 472 app->errorMsgHandler = handler; 473 else 474 app->errorMsgHandler = _XtDefaultErrorMsg; 475 UNLOCK_APP(app); 476#endif /* GLOBALERRORS */ 477 return old; 478} 479 480void 481XtSetWarningMsgHandler(XtErrorMsgHandler handler) 482{ 483#if GLOBALERRORS 484 LOCK_PROCESS; 485 if (handler != NULL) 486 warningMsgHandler = handler; 487 else 488 warningMsgHandler = _XtDefaultWarningMsg; 489 UNLOCK_PROCESS; 490#else 491 XtAppSetWarningMsgHandler(_XtDefaultAppContext(), handler); 492#endif /* GLOBALERRORS */ 493} 494 495XtErrorMsgHandler 496XtAppSetWarningMsgHandler(XtAppContext app _X_UNUSED, XtErrorMsgHandler handler) 497{ 498 XtErrorMsgHandler old; 499 500#if GLOBALERRORS 501 LOCK_PROCESS; 502 old = warningMsgHandler; 503 if (handler != NULL) 504 warningMsgHandler = handler; 505 else 506 warningMsgHandler = _XtDefaultWarningMsg; 507 UNLOCK_PROCESS; 508#else 509 LOCK_APP(app); 510 old = app->warningMsgHandler; 511 if (handler != NULL) 512 app->warningMsgHandler = handler; 513 else 514 app->warningMsgHandler = _XtDefaultWarningMsg; 515 UNLOCK_APP(app); 516#endif /* GLOBALERRORS */ 517 return old; 518} 519 520void 521_XtDefaultError(String message) 522{ 523 if (message && *message) 524 (void) fprintf(stderr, "%sError: %s\n", XTERROR_PREFIX, message); 525 exit(1); 526} 527 528void 529_XtDefaultWarning(String message) 530{ 531 if (message && *message) 532 (void) fprintf(stderr, "%sWarning: %s\n", XTWARNING_PREFIX, message); 533 return; 534} 535 536void 537XtError(_Xconst char *message) 538{ 539#if GLOBALERRORS 540 LOCK_PROCESS; 541 (*errorHandler) ((String) message); 542 UNLOCK_PROCESS; 543#else 544 XtAppError(_XtDefaultAppContext(), message); 545#endif /* GLOBALERRORS */ 546} 547 548void 549XtAppError(XtAppContext app _X_UNUSED, _Xconst char *message) 550{ 551#if GLOBALERRORS 552 LOCK_PROCESS; 553 (*errorHandler) ((String) message); 554 UNLOCK_PROCESS; 555#else 556 LOCK_APP(app); 557 (*app->errorHandler) (message); 558 UNLOCK_APP(app); 559#endif /* GLOBALERRORS */ 560} 561 562void 563XtWarning(_Xconst char *message) 564{ 565#if GLOBALERRORS 566 LOCK_PROCESS; 567 (*warningHandler) ((String) message); 568 UNLOCK_PROCESS; 569#else 570 XtAppWarning(_XtDefaultAppContext(), message); 571#endif /* GLOBALERRORS */ 572} 573 574void 575XtAppWarning(XtAppContext app _X_UNUSED, _Xconst char *message) 576{ 577#if GLOBALERRORS 578 LOCK_PROCESS; 579 (*warningHandler) ((String) message); 580 UNLOCK_PROCESS; 581#else 582 LOCK_APP(app); 583 (*app->warningHandler) (message); 584 UNLOCK_APP(app); 585#endif /* GLOBALERRORS */ 586} 587 588void 589XtSetErrorHandler(XtErrorHandler handler _X_NORETURN) 590{ 591#if GLOBALERRORS 592 LOCK_PROCESS; 593 if (handler != NULL) 594 errorHandler = handler; 595 else 596 errorHandler = _XtDefaultError; 597 UNLOCK_PROCESS; 598#else 599 XtAppSetErrorHandler(_XtDefaultAppContext(), handler); 600#endif /* GLOBALERRORS */ 601} 602 603XtErrorHandler 604XtAppSetErrorHandler(XtAppContext app _X_UNUSED, 605 XtErrorHandler handler _X_NORETURN) 606{ 607 XtErrorHandler old; 608 609#if GLOBALERRORS 610 LOCK_PROCESS; 611 old = errorHandler; 612 if (handler != NULL) 613 errorHandler = handler; 614 else 615 errorHandler = _XtDefaultError; 616 UNLOCK_PROCESS; 617#else 618 LOCK_APP(app); 619 old = app->errorHandler; 620 if (handler != NULL) 621 app->errorHandler = handler; 622 else 623 app->errorHandler = _XtDefaultError; 624 UNLOCK_APP(app); 625#endif /* GLOBALERRORS */ 626 return old; 627} 628 629void 630XtSetWarningHandler(XtErrorHandler handler) 631{ 632#if GLOBALERRORS 633 LOCK_PROCESS; 634 if (handler != NULL) 635 warningHandler = handler; 636 else 637 warningHandler = _XtDefaultWarning; 638 UNLOCK_PROCESS; 639#else 640 XtAppSetWarningHandler(_XtDefaultAppContext(), handler); 641#endif /* GLOBALERRORS */ 642} 643 644XtErrorHandler 645XtAppSetWarningHandler(XtAppContext app _X_UNUSED, XtErrorHandler handler) 646{ 647 XtErrorHandler old; 648 649#if GLOBALERRORS 650 LOCK_PROCESS; 651 old = warningHandler; 652 if (handler != NULL) 653 warningHandler = handler; 654 else 655 warningHandler = _XtDefaultWarning; 656 UNLOCK_PROCESS; 657#else 658 LOCK_APP(app); 659 old = app->warningHandler; 660 if (handler != NULL) 661 app->warningHandler = handler; 662 else 663 app->warningHandler = _XtDefaultWarning; 664 UNLOCK_APP(app); 665#endif /* GLOBALERRORS */ 666 return old; 667} 668 669void 670_XtSetDefaultErrorHandlers(XtErrorMsgHandler *errMsg _X_UNUSED, 671 XtErrorMsgHandler *warnMsg _X_UNUSED, 672 XtErrorHandler *err _X_UNUSED, 673 XtErrorHandler *warn _X_UNUSED) 674{ 675#ifndef GLOBALERRORS 676 LOCK_PROCESS; 677 *errMsg = _XtDefaultErrorMsg; 678 *warnMsg = _XtDefaultWarningMsg; 679 *err = _XtDefaultError; 680 *warn = _XtDefaultWarning; 681 UNLOCK_PROCESS; 682#endif /* GLOBALERRORS */ 683} 684