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