/ lib / com_err / com_err.c
com_err.c
  1  /*
  2   * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan
  3   * (Royal Institute of Technology, Stockholm, Sweden).
  4   * All rights reserved.
  5   *
  6   * Redistribution and use in source and binary forms, with or without
  7   * modification, are permitted provided that the following conditions
  8   * are met:
  9   *
 10   * 1. Redistributions of source code must retain the above copyright
 11   *    notice, this list of conditions and the following disclaimer.
 12   *
 13   * 2. Redistributions in binary form must reproduce the above copyright
 14   *    notice, this list of conditions and the following disclaimer in the
 15   *    documentation and/or other materials provided with the distribution.
 16   *
 17   * 3. Neither the name of the Institute nor the names of its contributors
 18   *    may be used to endorse or promote products derived from this software
 19   *    without specific prior written permission.
 20   *
 21   * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 22   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 23   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 24   * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 25   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 26   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 27   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 28   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 29   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 30   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 31   * SUCH DAMAGE.
 32   */
 33  
 34  
 35  #include <config.h>
 36  
 37  #include <stdio.h>
 38  #include <stdlib.h>
 39  #include <string.h>
 40  #include <roken.h>
 41  #include "com_err.h"
 42  
 43  struct et_list *_et_list = NULL;
 44  
 45  
 46  KRB5_LIB_FUNCTION const char * KRB5_LIB_CALL
 47  error_message (long code)
 48  {
 49      static char msg[128];
 50      const char *p = com_right(_et_list, code);
 51      if (p == NULL) {
 52  	if (code < 0)
 53  	    snprintf(msg, sizeof(msg), "Unknown error %ld", code);
 54  	else
 55  	    p = strerror((int)code);
 56      }
 57      if (p != NULL && *p != '\0') {
 58  	strlcpy(msg, p, sizeof(msg));
 59      } else
 60  	snprintf(msg, sizeof(msg), "Unknown error %ld", code);
 61      return msg;
 62  }
 63  
 64  KRB5_LIB_FUNCTION int KRB5_LIB_CALL
 65  init_error_table(const char **msgs, long base, int count)
 66  {
 67      initialize_error_table_r(&_et_list, msgs, count, base);
 68      return 0;
 69  }
 70  
 71  static void KRB5_CALLCONV
 72  default_proc (const char *whoami, long code, const char *fmt, va_list args)
 73      __attribute__((__format__(__printf__, 3, 0)));
 74  
 75  static void KRB5_CALLCONV
 76  default_proc (const char *whoami, long code, const char *fmt, va_list args)
 77  {
 78      if (whoami)
 79        fprintf(stderr, "%s: ", whoami);
 80      if (code)
 81        fprintf(stderr, "%s ", error_message(code));
 82      if (fmt)
 83        vfprintf(stderr, fmt, args);
 84      fprintf(stderr, "\r\n");	/* ??? */
 85  }
 86  
 87  static errf com_err_hook = default_proc;
 88  
 89  KRB5_LIB_FUNCTION void KRB5_LIB_CALL
 90  com_err_va (const char *whoami,
 91  	    long code,
 92  	    const char *fmt,
 93  	    va_list args)
 94  {
 95      (*com_err_hook) (whoami, code, fmt, args);
 96  }
 97  
 98  KRB5_LIB_FUNCTION void KRB5_LIB_CALL
 99  com_err (const char *whoami,
100  	 long code,
101  	 const char *fmt,
102  	 ...)
103  {
104      va_list ap;
105      va_start(ap, fmt);
106      com_err_va (whoami, code, fmt, ap);
107      va_end(ap);
108  }
109  
110  KRB5_LIB_FUNCTION errf KRB5_LIB_CALL
111  set_com_err_hook (errf new)
112  {
113      errf old = com_err_hook;
114  
115      if (new)
116  	com_err_hook = new;
117      else
118  	com_err_hook = default_proc;
119  
120      return old;
121  }
122  
123  KRB5_LIB_FUNCTION errf KRB5_LIB_CALL
124  reset_com_err_hook (void)
125  {
126      return set_com_err_hook(NULL);
127  }
128  
129  #define ERRCODE_RANGE   8       /* # of bits to shift table number */
130  #define BITS_PER_CHAR   6       /* # bits to shift per character in name */
131  
132  static const char char_set[] =
133          "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
134  
135  static char buf[6];
136  
137  KRB5_LIB_FUNCTION const char * KRB5_LIB_CALL
138  error_table_name(int num)
139  {
140      int ch;
141      int i;
142      char *p;
143  
144      /* num = aa aaa abb bbb bcc ccc cdd ddd d?? ??? ??? */
145      p = buf;
146      num >>= ERRCODE_RANGE;
147      /* num = ?? ??? ??? aaa aaa bbb bbb ccc ccc ddd ddd */
148      num &= 077777777;
149      /* num = 00 000 000 aaa aaa bbb bbb ccc ccc ddd ddd */
150      for (i = 4; i >= 0; i--) {
151          ch = (num >> BITS_PER_CHAR * i) & ((1 << BITS_PER_CHAR) - 1);
152          if (ch != 0)
153              *p++ = char_set[ch-1];
154      }
155      *p = '\0';
156      return(buf);
157  }
158  
159  KRB5_LIB_FUNCTION void KRB5_LIB_CALL
160  add_to_error_table(struct et_list *new_table)
161  {
162      struct et_list *et;
163  
164      for (et = _et_list; et; et = et->next) {
165  	if (et->table->base == new_table->table->base)
166  	    return;
167      }
168  
169      new_table->next = _et_list;
170      _et_list = new_table;
171  }