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