error_message.c revision ec84b746f553f150935f82dd8d487517fcad745b
15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * $Header$ 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * $Source$ 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * $Locker$ 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Copyright 1987 by the Student Information Processing Board 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of the Massachusetts Institute of Technology 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission to use, copy, modify, and distribute this software and 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * its documentation for any purpose is hereby granted, provided that 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * advertising or publicity pertaining to distribution of the software 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * without specific, written prior permission. M.I.T. and the 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * M.I.T. S.I.P.B. make no representations about the suitability of 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this software for any purpose. It is provided "as is" without 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * express or implied warranty. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_SYS_PRCTL_H 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/prctl.h> 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PR_GET_DUMPABLE 3 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if (!defined(HAVE_PRCTL) && defined(linux)) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/syscall.h> 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "com_err.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "error_table.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "internal.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static char buffer[25]; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct et_list * _et_list = (struct et_list *) NULL; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct et_list * _et_dynamic_list = (struct et_list *) NULL; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char * error_message (errcode_t code) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int offset; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct et_list *et; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errcode_t table_num; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int started = 0; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *cp; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offset = (int) (code & ((1<<ERRCODE_RANGE)-1)); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) table_num = code - offset; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!table_num) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAS_SYS_ERRLIST 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (offset < sys_nerr) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return(sys_errlist[offset]); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto oops; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cp = strerror(offset); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cp) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return(cp); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto oops; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (et = _et_list; et; et = et->next) { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (et->table->base == table_num) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* This is the right table */ 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (et->table->n_msgs <= offset) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto oops; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return(et->table->msgs[offset]); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (et = _et_dynamic_list; et; et = et->next) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (et->table->base == table_num) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* This is the right table */ 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (et->table->n_msgs <= offset) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto oops; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return(et->table->msgs[offset]); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)oops: 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strcpy (buffer, "Unknown code "); 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (table_num) { 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) strcat (buffer, error_table_name (table_num)); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strcat (buffer, " "); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (cp = buffer; *cp; cp++) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (offset >= 100) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *cp++ = '0' + offset / 100; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offset %= 100; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) started++; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (started || offset >= 10) { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *cp++ = '0' + offset / 10; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offset %= 10; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *cp++ = '0' + offset; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *cp = '\0'; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return(buffer); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This routine will only return a value if the we are not running as 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * a privileged process. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static char *safe_getenv(const char *arg) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((getuid() != geteuid()) || (getgid() != getegid())) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if HAVE_PRCTL 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if (defined(linux) && defined(SYS_prctl)) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (syscall(SYS_prctl, PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE___SECURE_GETENV 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return __secure_getenv(arg); 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#else 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return getenv(arg); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEBUG_INIT 0x8000 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEBUG_ADDREMOVE 0x0001 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int debug_mask = 0; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static FILE *debug_f = 0; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void init_debug(void) 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *dstr; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *fn; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (debug_mask & DEBUG_INIT) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dstr = getenv("COMERR_DEBUG"); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dstr) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) debug_mask = strtoul(dstr, 0, 0); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fn = safe_getenv("COMERR_DEBUG_FILE"); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fn) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) debug_f = fopen(fn, "a"); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!debug_f) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) debug_f = fopen("/dev/tty", "a"); 1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!debug_f) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) debug_mask = 0; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) debug_mask |= DEBUG_INIT; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * New interface provided by krb5's com_err library 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)errcode_t add_error_table(const struct error_table * et) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct et_list *el; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(el = (struct et_list *) malloc(sizeof(struct et_list)))) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ENOMEM; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) el->table = et; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) el->next = _et_dynamic_list; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _et_dynamic_list = el; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) init_debug(); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (debug_mask & DEBUG_ADDREMOVE) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(debug_f, "add_error_table: %s (0x%p)\n", 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_table_name(et->base), 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (const void *) et); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * New interface provided by krb5's com_err library 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)errcode_t remove_error_table(const struct error_table * et) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct et_list *el = _et_dynamic_list; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct et_list *el2 = 0; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) init_debug(); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (el) { 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (el->table->base == et->base) { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (el2) /* Not the beginning of the list */ 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) el2->next = el->next; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _et_dynamic_list = el->next; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) free(el); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (debug_mask & DEBUG_ADDREMOVE) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(debug_f, 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "remove_error_table: %s (0x%p)\n", 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_table_name(et->base), 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (const void *) et); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) el2 = el; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) el = el->next; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (debug_mask & DEBUG_ADDREMOVE) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(debug_f, "remove_error_table FAILED: %s (0x%p)\n", 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_table_name(et->base), 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (const void *) et); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ENOENT; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Variant of the interface provided by Heimdal's com_err library 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)add_to_error_table(struct et_list *new_table) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) add_error_table(new_table->table); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)