Error.c revision 0568f49b
1/*********************************************************** 2Copyright (c) 1993, Oracle and/or its affiliates. All rights reserved. 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#if GLOBALERRORS 88static XrmDatabase errorDB = NULL; 89static Boolean error_inited = FALSE; 90void _XtDefaultErrorMsg(String, String, String, String, String*, Cardinal*); 91void _XtDefaultWarningMsg(String, String, String, String, String*, Cardinal*); 92void _XtDefaultError(String) _X_NORETURN; 93void _XtDefaultWarning(String); 94static XtErrorMsgHandler errorMsgHandler = _XtDefaultErrorMsg; 95static XtErrorMsgHandler warningMsgHandler = _XtDefaultWarningMsg; 96static XtErrorHandler errorHandler _X_NORETURN = _XtDefaultError; 97static XtErrorHandler warningHandler = _XtDefaultWarning; 98#endif /* GLOBALERRORS */ 99 100XrmDatabase *XtGetErrorDatabase(void) 101{ 102 XrmDatabase* retval; 103#if GLOBALERRORS 104 LOCK_PROCESS; 105 retval = &errorDB; 106 UNLOCK_PROCESS; 107#else 108 retval = XtAppGetErrorDatabase(_XtDefaultAppContext()); 109#endif /* GLOBALERRORS */ 110 return retval; 111} 112 113XrmDatabase *XtAppGetErrorDatabase( 114 XtAppContext app) 115{ 116 XrmDatabase* retval; 117#if GLOBALERRORS 118 LOCK_PROCESS; 119 retval = &errorDB; 120 UNLOCK_PROCESS; 121#else 122 LOCK_APP(app); 123 retval= &app->errorDB; 124 UNLOCK_APP(app); 125#endif /* GLOBALERRORS */ 126 return retval; 127} 128 129void XtGetErrorDatabaseText( 130 register _Xconst char* name, 131 register _Xconst char* type, 132 register _Xconst char* class, 133 _Xconst char* defaultp, 134 _XtString buffer, 135 int nbytes) 136{ 137#if GLOBALERRORS 138 XtAppGetErrorDatabaseText(NULL, 139 name,type,class,defaultp, buffer, nbytes, NULL); 140#else 141 XtAppGetErrorDatabaseText(_XtDefaultAppContext(), 142 name,type,class,defaultp, buffer, nbytes, NULL); 143#endif /* GLOBALERRORS */ 144} 145 146void XtAppGetErrorDatabaseText( 147 XtAppContext app, 148 register _Xconst char* name, 149 register _Xconst char* type, 150 register _Xconst char* class, 151 _Xconst char* defaultp, 152 _XtString buffer, 153 int nbytes, 154 XrmDatabase db) 155{ 156 String str_class; 157 _XtString type_str; 158 XrmValue result; 159 char *str_name = NULL; 160 char *temp = NULL; 161 162#if GLOBALERRORS 163 LOCK_PROCESS; 164 if (error_inited == FALSE) { 165 InitErrorHandling (&errorDB); 166 error_inited = TRUE; 167 } 168#else 169 LOCK_APP(app); 170 if (app->error_inited == FALSE) { 171 InitErrorHandling (&app->errorDB); 172 app->error_inited = TRUE; 173 } 174#endif /* GLOBALERRORS */ 175 if (!(str_name = ALLOCATE_LOCAL(strlen(name) + strlen(type) + 2))) 176 _XtAllocError(NULL); 177 (void) sprintf(str_name, "%s.%s", name, type); 178 /* XrmGetResource requires the name and class to be fully qualified 179 * and to have the same number of components. */ 180 str_class = (char *)class; 181 if (! strchr(class, '.')) { 182 if (!(temp = ALLOCATE_LOCAL(2 * strlen(class) + 2))) 183 _XtAllocError(NULL); 184 (void) sprintf(temp, "%s.%s", class, class); 185 str_class = temp; 186 } 187 if (db == NULL) { 188#if GLOBALERRORS 189 (void) XrmGetResource(errorDB, str_name, str_class, &type_str, 190 &result); 191#else 192 (void) XrmGetResource(app->errorDB, str_name, str_class, &type_str, 193 &result); 194#endif /* GLOBALERRORS */ 195 } else (void) XrmGetResource(db, str_name, str_class, &type_str, &result); 196 if (result.addr) { 197 (void) strncpy (buffer, result.addr, (size_t) nbytes); 198 if (result.size > (unsigned) nbytes) buffer[nbytes-1] = 0; 199 } else { 200 int len = (int) strlen(defaultp); 201 if (len >= nbytes) len = nbytes-1; 202 (void) memmove(buffer, defaultp, (size_t) len); 203 buffer[len] = '\0'; 204 } 205 if (str_name) 206 DEALLOCATE_LOCAL(str_name); 207 if (temp) 208 DEALLOCATE_LOCAL(temp); 209#if GLOBALERRORS 210 UNLOCK_PROCESS; 211#else 212 UNLOCK_APP(app); 213#endif 214} 215 216static void InitErrorHandling ( 217 XrmDatabase *db) 218{ 219 XrmDatabase errordb; 220 221 errordb = XrmGetFileDatabase(ERRORDB); 222 XrmMergeDatabases(errordb, db); 223} 224 225static void DefaultMsg ( 226 String name, 227 String type, 228 String class, 229 String defaultp, 230 String* params, 231 Cardinal* num_params, 232 Bool error, 233 void (*fn)(_Xconst _XtString)) 234{ 235#define BIGBUF 1024 236 char buffer[BIGBUF]; 237 char* message; 238 XtGetErrorDatabaseText(name,type,class,defaultp, buffer, BIGBUF); 239/*need better solution here, perhaps use lower level printf primitives? */ 240 if (params == NULL || num_params == NULL || *num_params == 0) 241 (*fn)(buffer); 242#ifndef WIN32 /* and OS/2 */ 243 else if ((getuid () != geteuid ()) || getuid() == 0) { 244 if ((error && errorHandler == _XtDefaultError) || 245 (!error && warningHandler == _XtDefaultWarning)) { 246 /* 247 * if it's just going to go to stderr anyway, then we'll 248 * fprintf to stderr ourselves and skip the insecure sprintf. 249 */ 250 Cardinal i = *num_params; 251 String par[10]; 252 if (i > 10) i = 10; 253 (void) memmove((char*)par, (char*)params, i * sizeof(String) ); 254 memset( &par[i], 0, (10-i) * sizeof(String) ); 255 (void) fprintf (stderr, "%s%s", 256 error ? XTERROR_PREFIX : XTWARNING_PREFIX, 257 error ? "Error: " : "Warning: "); 258 (void) fprintf (stderr, buffer, 259 par[0], par[1], par[2], par[3], par[4], 260 par[5], par[6], par[7], par[8], par[9]); 261 (void) fprintf (stderr, "%c", '\n'); 262 if (i != *num_params) 263 (*fn) ( "Some arguments in previous message were lost" ); 264 else if (error) exit (1); 265 } else { 266 /* 267 * can't tell what it might do, so we'll play it safe 268 */ 269 XtWarning ("\ 270This program is an suid-root program or is being run by the root user.\n\ 271The full text of the error or warning message cannot be safely formatted\n\ 272in this environment. You may get a more descriptive message by running the\n\ 273program as a non-root user or by removing the suid bit on the executable."); 274 (*fn)(buffer); /* if *fn is an ErrorHandler it should exit */ 275 } 276 } 277#endif 278 else { 279 /* 280 * If you have snprintf the worst thing that could happen is you'd 281 * lose some information. Without snprintf you're probably going to 282 * scramble your heap and perhaps SEGV -- sooner or later. 283 * If it hurts when you go like this then don't go like this! :-) 284 */ 285 Cardinal i = *num_params; 286 String par[10]; 287 if (i > 10) i = 10; 288 (void) memmove((char*)par, (char*)params, i * sizeof(String) ); 289 memset( &par[i], 0, (10-i) * sizeof(String) ); 290 if (i != *num_params) 291 XtWarning( "Some arguments in following message were lost" ); 292 /* 293 * resist any temptation you might have to make `message' a 294 * local buffer on the stack. Doing so is a security hole 295 * in programs executing as root. Error and Warning 296 * messages shouldn't be called frequently enough for this 297 * to be a performance issue. 298 */ 299 if ((message = __XtMalloc (BIGBUF))) { 300 (void) snprintf (message, BIGBUF, buffer, 301 par[0], par[1], par[2], par[3], par[4], 302 par[5], par[6], par[7], par[8], par[9]); 303 (*fn)(message); 304 XtFree(message); 305 } else { 306 XtWarning ("Memory allocation failed, arguments in the following message were lost"); 307 (*fn)(buffer); 308 } 309 } 310} 311 312void _XtDefaultErrorMsg ( 313 String name, 314 String type, 315 String class, 316 String defaultp, 317 String* params, 318 Cardinal* num_params) 319{ 320 DefaultMsg (name,type,class,defaultp,params,num_params,True,XtError); 321} 322 323void _XtDefaultWarningMsg ( 324 String name, 325 String type, 326 String class, 327 String defaultp, 328 String* params, 329 Cardinal* num_params) 330{ 331 DefaultMsg (name,type,class,defaultp,params,num_params,False,XtWarning); 332} 333 334void XtErrorMsg( 335 _Xconst char* name, 336 _Xconst char* type, 337 _Xconst char* class, 338 _Xconst char* defaultp, 339 String* params, 340 Cardinal* num_params) 341{ 342#if GLOBALERRORS 343 LOCK_PROCESS; 344 (*errorMsgHandler)((String)name,(String)type,(String)class, 345 (String)defaultp,params,num_params); 346 UNLOCK_PROCESS; 347 exit(1); 348#else 349 XtAppErrorMsg(_XtDefaultAppContext(),name,type,class, 350 defaultp,params,num_params); 351#endif /* GLOBALERRORS */ 352} 353 354void XtAppErrorMsg( 355 XtAppContext app, 356 _Xconst char* name, 357 _Xconst char* type, 358 _Xconst char* class, 359 _Xconst char* defaultp, 360 String* params, 361 Cardinal* num_params) 362{ 363#if GLOBALERRORS 364 LOCK_PROCESS; 365 (*errorMsgHandler)((String)name,(String)type,(String)class, 366 (String)defaultp,params,num_params); 367 UNLOCK_PROCESS; 368 exit(1); 369#else 370 LOCK_APP(app); 371 (*app->errorMsgHandler)(name,type,class,defaultp,params,num_params); 372 UNLOCK_APP(app); 373#endif /* GLOBALERRORS */ 374} 375 376void XtWarningMsg( 377 _Xconst char* name, 378 _Xconst char* type, 379 _Xconst char* class, 380 _Xconst char* defaultp, 381 String* params, 382 Cardinal* num_params) 383{ 384#if GLOBALERRORS 385 LOCK_PROCESS; 386 (*warningMsgHandler)((String)name,(String)type,(String)class, 387 (String)defaultp,params,num_params); 388 UNLOCK_PROCESS; 389#else 390 XtAppWarningMsg(_XtDefaultAppContext(),name,type,class, 391 defaultp,params,num_params); 392#endif /* GLOBALERRORS */ 393} 394 395void XtAppWarningMsg( 396 XtAppContext app, 397 _Xconst char* name, 398 _Xconst char* type, 399 _Xconst char* class, 400 _Xconst char* defaultp, 401 String* params, 402 Cardinal* num_params) 403{ 404#if GLOBALERRORS 405 LOCK_PROCESS; 406 (*warningMsgHandler)((String)name,(String)type,(String)class, 407 (String)defaultp,params,num_params); 408 UNLOCK_PROCESS; 409#else 410 LOCK_APP(app); 411 (*app->warningMsgHandler)(name,type,class,defaultp,params,num_params); 412 UNLOCK_APP(app); 413#endif /* GLOBALERRORS */ 414} 415 416void XtSetErrorMsgHandler( 417 XtErrorMsgHandler handler _X_NORETURN) 418{ 419#if GLOBALERRORS 420 LOCK_PROCESS; 421 if (handler != NULL) errorMsgHandler = handler; 422 else errorMsgHandler = _XtDefaultErrorMsg; 423 UNLOCK_PROCESS; 424#else 425 XtAppSetErrorMsgHandler(_XtDefaultAppContext(), handler); 426#endif /* GLOBALERRORS */ 427} 428 429XtErrorMsgHandler XtAppSetErrorMsgHandler( 430 XtAppContext app, 431 XtErrorMsgHandler handler _X_NORETURN) 432{ 433 XtErrorMsgHandler old; 434#if GLOBALERRORS 435 LOCK_PROCESS; 436 old = errorMsgHandler; 437 if (handler != NULL) errorMsgHandler = handler; 438 else errorMsgHandler = _XtDefaultErrorMsg; 439 UNLOCK_PROCESS; 440#else 441 LOCK_APP(app); 442 old = app->errorMsgHandler; 443 if (handler != NULL) app->errorMsgHandler = handler; 444 else app->errorMsgHandler = _XtDefaultErrorMsg; 445 UNLOCK_APP(app); 446#endif /* GLOBALERRORS */ 447 return old; 448} 449 450void XtSetWarningMsgHandler( 451 XtErrorMsgHandler handler) 452{ 453#if GLOBALERRORS 454 LOCK_PROCESS; 455 if (handler != NULL) warningMsgHandler = handler; 456 else warningMsgHandler = _XtDefaultWarningMsg; 457 UNLOCK_PROCESS; 458#else 459 XtAppSetWarningMsgHandler(_XtDefaultAppContext(),handler); 460#endif /* GLOBALERRORS */ 461} 462 463XtErrorMsgHandler XtAppSetWarningMsgHandler( 464 XtAppContext app, 465 XtErrorMsgHandler handler) 466{ 467 XtErrorMsgHandler old; 468#if GLOBALERRORS 469 LOCK_PROCESS; 470 old = warningMsgHandler; 471 if (handler != NULL) warningMsgHandler = handler; 472 else warningMsgHandler = _XtDefaultWarningMsg; 473 UNLOCK_PROCESS; 474#else 475 LOCK_APP(app); 476 old = app->warningMsgHandler; 477 if (handler != NULL) app->warningMsgHandler = handler; 478 else app->warningMsgHandler = _XtDefaultWarningMsg; 479 UNLOCK_APP(app); 480#endif /* GLOBALERRORS */ 481 return old; 482} 483 484void _XtDefaultError(String message) 485{ 486 if (message && *message) 487 (void)fprintf(stderr, "%sError: %s\n", XTERROR_PREFIX, message); 488 exit(1); 489} 490 491void _XtDefaultWarning(String message) 492{ 493 if (message && *message) 494 (void)fprintf(stderr, "%sWarning: %s\n", XTWARNING_PREFIX, message); 495 return; 496} 497 498void XtError( 499 _Xconst char* message) 500{ 501#if GLOBALERRORS 502 LOCK_PROCESS; 503 (*errorHandler)((String)message); 504 UNLOCK_PROCESS; 505#else 506 XtAppError(_XtDefaultAppContext(),message); 507#endif /* GLOBALERRORS */ 508} 509 510void XtAppError( 511 XtAppContext app, 512 _Xconst char* message) 513{ 514#if GLOBALERRORS 515 LOCK_PROCESS; 516 (*errorHandler)((String)message); 517 UNLOCK_PROCESS; 518#else 519 LOCK_APP(app); 520 (*app->errorHandler)(message); 521 UNLOCK_APP(app); 522#endif /* GLOBALERRORS */ 523} 524 525void XtWarning( 526 _Xconst char* message) 527{ 528#if GLOBALERRORS 529 LOCK_PROCESS; 530 (*warningHandler)((String)message); 531 UNLOCK_PROCESS; 532#else 533 XtAppWarning(_XtDefaultAppContext(),message); 534#endif /* GLOBALERRORS */ 535} 536 537void XtAppWarning( 538 XtAppContext app, 539 _Xconst char* message) 540{ 541#if GLOBALERRORS 542 LOCK_PROCESS; 543 (*warningHandler)((String)message); 544 UNLOCK_PROCESS; 545#else 546 LOCK_APP(app); 547 (*app->warningHandler)(message); 548 UNLOCK_APP(app); 549#endif /* GLOBALERRORS */ 550} 551 552void XtSetErrorHandler(XtErrorHandler handler _X_NORETURN) 553{ 554#if GLOBALERRORS 555 LOCK_PROCESS; 556 if (handler != NULL) errorHandler = handler; 557 else errorHandler = _XtDefaultError; 558 UNLOCK_PROCESS; 559#else 560 XtAppSetErrorHandler(_XtDefaultAppContext(),handler); 561#endif /* GLOBALERRORS */ 562} 563 564XtErrorHandler XtAppSetErrorHandler( 565 XtAppContext app, 566 XtErrorHandler handler _X_NORETURN) 567{ 568 XtErrorHandler old; 569#if GLOBALERRORS 570 LOCK_PROCESS; 571 old = errorHandler; 572 if (handler != NULL) errorHandler = handler; 573 else errorHandler = _XtDefaultError; 574 UNLOCK_PROCESS; 575#else 576 LOCK_APP(app); 577 old = app->errorHandler; 578 if (handler != NULL) app->errorHandler = handler; 579 else app->errorHandler = _XtDefaultError; 580 UNLOCK_APP(app); 581#endif /* GLOBALERRORS */ 582 return old; 583} 584 585void XtSetWarningHandler(XtErrorHandler handler) 586{ 587#if GLOBALERRORS 588 LOCK_PROCESS; 589 if (handler != NULL) warningHandler = handler; 590 else warningHandler = _XtDefaultWarning; 591 UNLOCK_PROCESS; 592#else 593 XtAppSetWarningHandler(_XtDefaultAppContext(),handler); 594#endif /* GLOBALERRORS */ 595} 596 597XtErrorHandler XtAppSetWarningHandler( 598 XtAppContext app, 599 XtErrorHandler handler) 600{ 601 XtErrorHandler old; 602#if GLOBALERRORS 603 LOCK_PROCESS; 604 old = warningHandler; 605 if (handler != NULL) warningHandler = handler; 606 else warningHandler = _XtDefaultWarning; 607 UNLOCK_PROCESS; 608#else 609 LOCK_APP(app); 610 old = app->warningHandler; 611 if (handler != NULL) app->warningHandler = handler; 612 else app->warningHandler = _XtDefaultWarning; 613 UNLOCK_APP(app); 614#endif /* GLOBALERRORS */ 615 return old; 616} 617 618void _XtSetDefaultErrorHandlers( 619 XtErrorMsgHandler *errMsg, 620 XtErrorMsgHandler *warnMsg, 621 XtErrorHandler *err, 622 XtErrorHandler *warn) 623{ 624#ifndef GLOBALERRORS 625 LOCK_PROCESS; 626 *errMsg = _XtDefaultErrorMsg; 627 *warnMsg = _XtDefaultWarningMsg; 628 *err = _XtDefaultError; 629 *warn = _XtDefaultWarning; 630 UNLOCK_PROCESS; 631#endif /* GLOBALERRORS */ 632} 633