]>
Commit | Line | Data |
---|---|---|
3839e657 TT |
1 | /* |
2 | * $Header$ | |
3 | * $Source$ | |
4 | * $Locker$ | |
5 | * | |
6 | * Copyright 1987 by the Student Information Processing Board | |
7 | * of the Massachusetts Institute of Technology | |
8 | * | |
06cefee5 TT |
9 | * Permission to use, copy, modify, and distribute this software and |
10 | * its documentation for any purpose is hereby granted, provided that | |
11 | * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in | |
12 | * advertising or publicity pertaining to distribution of the software | |
13 | * without specific, written prior permission. M.I.T. and the | |
14 | * M.I.T. S.I.P.B. make no representations about the suitability of | |
15 | * this software for any purpose. It is provided "as is" without | |
16 | * express or implied warranty. | |
3839e657 TT |
17 | */ |
18 | ||
19 | #include <stdio.h> | |
91835c15 | 20 | #include <stdlib.h> |
3839e657 | 21 | #include <string.h> |
f3db3566 | 22 | #include <errno.h> |
ec84b746 TT |
23 | #ifdef HAVE_SYS_PRCTL_H |
24 | #include <sys/prctl.h> | |
25 | #else | |
26 | #define PR_GET_DUMPABLE 3 | |
27 | #endif | |
28 | #if (!defined(HAVE_PRCTL) && defined(linux)) | |
29 | #include <sys/syscall.h> | |
30 | #endif | |
de8f3a76 AD |
31 | #if HAVE_UNISTD_H |
32 | #include <unistd.h> | |
33 | #endif | |
34 | #if HAVE_SYS_TYPES_H | |
35 | #include <sys/types.h> | |
36 | #endif | |
f3db3566 | 37 | #include "com_err.h" |
3839e657 | 38 | #include "error_table.h" |
3839e657 TT |
39 | #include "internal.h" |
40 | ||
3839e657 TT |
41 | static char buffer[25]; |
42 | ||
43 | struct et_list * _et_list = (struct et_list *) NULL; | |
d51b819e | 44 | struct et_list * _et_dynamic_list = (struct et_list *) NULL; |
3839e657 | 45 | |
f3db3566 | 46 | |
f3db3566 | 47 | const char * error_message (errcode_t code) |
3839e657 TT |
48 | { |
49 | int offset; | |
50 | struct et_list *et; | |
a47b66ee | 51 | errcode_t table_num; |
3839e657 TT |
52 | int started = 0; |
53 | char *cp; | |
54 | ||
a47b66ee | 55 | offset = (int) (code & ((1<<ERRCODE_RANGE)-1)); |
3839e657 TT |
56 | table_num = code - offset; |
57 | if (!table_num) { | |
f3db3566 | 58 | #ifdef HAS_SYS_ERRLIST |
3839e657 TT |
59 | if (offset < sys_nerr) |
60 | return(sys_errlist[offset]); | |
61 | else | |
62 | goto oops; | |
f3db3566 TT |
63 | #else |
64 | cp = strerror(offset); | |
65 | if (cp) | |
66 | return(cp); | |
67 | else | |
68 | goto oops; | |
69 | #endif | |
3839e657 TT |
70 | } |
71 | for (et = _et_list; et; et = et->next) { | |
72 | if (et->table->base == table_num) { | |
73 | /* This is the right table */ | |
74 | if (et->table->n_msgs <= offset) | |
75 | goto oops; | |
76 | return(et->table->msgs[offset]); | |
77 | } | |
78 | } | |
d51b819e TT |
79 | for (et = _et_dynamic_list; et; et = et->next) { |
80 | if (et->table->base == table_num) { | |
81 | /* This is the right table */ | |
82 | if (et->table->n_msgs <= offset) | |
83 | goto oops; | |
84 | return(et->table->msgs[offset]); | |
85 | } | |
86 | } | |
3839e657 TT |
87 | oops: |
88 | strcpy (buffer, "Unknown code "); | |
89 | if (table_num) { | |
90 | strcat (buffer, error_table_name (table_num)); | |
91 | strcat (buffer, " "); | |
92 | } | |
93 | for (cp = buffer; *cp; cp++) | |
94 | ; | |
95 | if (offset >= 100) { | |
96 | *cp++ = '0' + offset / 100; | |
97 | offset %= 100; | |
98 | started++; | |
99 | } | |
100 | if (started || offset >= 10) { | |
101 | *cp++ = '0' + offset / 10; | |
102 | offset %= 10; | |
103 | } | |
104 | *cp++ = '0' + offset; | |
105 | *cp = '\0'; | |
106 | return(buffer); | |
107 | } | |
00aba967 | 108 | |
ec84b746 TT |
109 | /* |
110 | * This routine will only return a value if the we are not running as | |
111 | * a privileged process. | |
112 | */ | |
113 | static char *safe_getenv(const char *arg) | |
114 | { | |
115 | if ((getuid() != geteuid()) || (getgid() != getegid())) | |
116 | return NULL; | |
117 | #if HAVE_PRCTL | |
118 | if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) | |
119 | return NULL; | |
120 | #else | |
121 | #if (defined(linux) && defined(SYS_prctl)) | |
122 | if (syscall(SYS_prctl, PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) | |
123 | return NULL; | |
124 | #endif | |
125 | #endif | |
126 | ||
127 | #ifdef HAVE___SECURE_GETENV | |
128 | return __secure_getenv(arg); | |
129 | #else | |
130 | return getenv(arg); | |
131 | #endif | |
132 | } | |
133 | ||
134 | #define DEBUG_INIT 0x8000 | |
135 | #define DEBUG_ADDREMOVE 0x0001 | |
136 | ||
137 | static int debug_mask = 0; | |
138 | static FILE *debug_f = 0; | |
139 | ||
140 | static void init_debug(void) | |
141 | { | |
142 | char *dstr; | |
143 | char *fn; | |
144 | ||
145 | if (debug_mask & DEBUG_INIT) | |
146 | return; | |
147 | ||
148 | dstr = getenv("COMERR_DEBUG"); | |
149 | if (dstr) | |
150 | debug_mask = strtoul(dstr, 0, 0); | |
151 | ||
152 | fn = safe_getenv("COMERR_DEBUG_FILE"); | |
153 | if (fn) | |
154 | debug_f = fopen(fn, "a"); | |
155 | if (!debug_f) | |
156 | debug_f = fopen("/dev/tty", "a"); | |
157 | if (!debug_f) | |
158 | debug_mask = 0; | |
159 | ||
160 | debug_mask |= DEBUG_INIT; | |
161 | } | |
162 | ||
00aba967 TT |
163 | /* |
164 | * New interface provided by krb5's com_err library | |
165 | */ | |
91835c15 | 166 | errcode_t add_error_table(const struct error_table * et) |
00aba967 | 167 | { |
d51b819e | 168 | struct et_list *el; |
00aba967 TT |
169 | |
170 | if (!(el = (struct et_list *) malloc(sizeof(struct et_list)))) | |
171 | return ENOMEM; | |
172 | ||
173 | el->table = et; | |
d51b819e TT |
174 | el->next = _et_dynamic_list; |
175 | _et_dynamic_list = el; | |
00aba967 | 176 | |
ec84b746 TT |
177 | init_debug(); |
178 | if (debug_mask & DEBUG_ADDREMOVE) | |
179 | fprintf(debug_f, "add_error_table: %s (0x%p)\n", | |
180 | error_table_name(et->base), | |
181 | (const void *) et); | |
182 | ||
00aba967 TT |
183 | return 0; |
184 | } | |
185 | ||
186 | /* | |
187 | * New interface provided by krb5's com_err library | |
188 | */ | |
91835c15 | 189 | errcode_t remove_error_table(const struct error_table * et) |
00aba967 | 190 | { |
d51b819e | 191 | struct et_list *el = _et_dynamic_list; |
00aba967 TT |
192 | struct et_list *el2 = 0; |
193 | ||
ec84b746 | 194 | init_debug(); |
00aba967 TT |
195 | while (el) { |
196 | if (el->table->base == et->base) { | |
197 | if (el2) /* Not the beginning of the list */ | |
198 | el2->next = el->next; | |
199 | else | |
d51b819e | 200 | _et_dynamic_list = el->next; |
00aba967 | 201 | (void) free(el); |
ec84b746 TT |
202 | if (debug_mask & DEBUG_ADDREMOVE) |
203 | fprintf(debug_f, | |
204 | "remove_error_table: %s (0x%p)\n", | |
205 | error_table_name(et->base), | |
206 | (const void *) et); | |
00aba967 TT |
207 | return 0; |
208 | } | |
209 | el2 = el; | |
210 | el = el->next; | |
211 | } | |
ec84b746 TT |
212 | if (debug_mask & DEBUG_ADDREMOVE) |
213 | fprintf(debug_f, "remove_error_table FAILED: %s (0x%p)\n", | |
214 | error_table_name(et->base), | |
215 | (const void *) et); | |
00aba967 TT |
216 | return ENOENT; |
217 | } | |
218 | ||
219 | /* | |
220 | * Variant of the interface provided by Heimdal's com_err library | |
221 | */ | |
222 | void | |
223 | add_to_error_table(struct et_list *new_table) | |
224 | { | |
225 | add_error_table(new_table->table); | |
226 | } |