1/*
2 * Copyright (c) 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
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 * 2.  Redistributions in binary form must reproduce the above copyright
13 *     notice, this list of conditions and the following disclaimer in the
14 *     documentation and/or other materials provided with the distribution.
15 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
16 *     contributors may be used to endorse or promote products derived from
17 *     this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Portions of this software have been released under the following terms:
31 *
32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC.
33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY
34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION
35 *
36 * To anyone who acknowledges that this file is provided "AS IS"
37 * without any express or implied warranty:
38 * permission to use, copy, modify, and distribute this file for any
39 * purpose is hereby granted without fee, provided that the above
40 * copyright notices and this notice appears in all source code copies,
41 * and that none of the names of Open Software Foundation, Inc., Hewlett-
42 * Packard Company or Digital Equipment Corporation be used
43 * in advertising or publicity pertaining to distribution of the software
44 * without specific, written prior permission.  Neither Open Software
45 * Foundation, Inc., Hewlett-Packard Company nor Digital
46 * Equipment Corporation makes any representations about the suitability
47 * of this software for any purpose.
48 *
49 * Copyright (c) 2007, Novell, Inc. All rights reserved.
50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions
52 * are met:
53 *
54 * 1.  Redistributions of source code must retain the above copyright
55 *     notice, this list of conditions and the following disclaimer.
56 * 2.  Redistributions in binary form must reproduce the above copyright
57 *     notice, this list of conditions and the following disclaimer in the
58 *     documentation and/or other materials provided with the distribution.
59 * 3.  Neither the name of Novell Inc. nor the names of its contributors
60 *     may be used to endorse or promote products derived from this
61 *     this software without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY
67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 *
74 * @APPLE_LICENSE_HEADER_END@
75 */
76
77/*
78 *  OSF DCE Version 1.0
79 */
80/*
81**
82**  NAME
83**
84**      dce_error.c
85**
86**  FACILITY:
87**
88**      Distributed Computing Environment (DCE)
89**
90**  ABSTRACT:
91**
92**  Error status management routines.
93**
94**
95*/
96
97#if HAVE_CONFIG_H
98#include <config.h>
99#endif
100
101#include <stdio.h>
102#include <stdarg.h>
103#include <string.h>
104#ifdef HAVE_NL_TYPES_H
105#include <nl_types.h>       /* public types for NLS (I18N) routines */
106#else
107#warning Message catalog support disabled
108#endif /* HAVE_NL_TYPES_H */
109
110#include <dce/dce_error.h>
111
112#define FACILITY_CODE_MASK          0xF0000000
113#define FACILITY_CODE_SHIFT         28
114
115#define COMPONENT_CODE_MASK         0x0FFFF000
116#define COMPONENT_CODE_SHIFT        12
117
118#define STATUS_CODE_MASK            0x00000FFF
119#define STATUS_CODE_SHIFT           0
120
121#define NO_MESSAGE                  "THIS IS NOT A MESSAGE"
122
123/*
124 * The system-dependant location for the catalog files is defined in sysconf.h
125 */
126
127#ifndef RPC_DEFAULT_NLSPATH
128#define RPC_DEFAULT_NLSPATH "/usr/lib/nls/msg/en_US.ISO8859-1/%s.cat"
129/* #error Define RPC_DEFAULT_NLSPATH in your sysconf.h file. */
130#endif
131
132#ifndef RPC_NLS_FORMAT
133#define RPC_NLS_FORMAT "%s.cat"
134#endif
135
136#ifndef MAXPATHLEN
137#define MAXPATHLEN 1024
138#endif
139
140
141/*
142**++
143**
144**  ROUTINE NAME:       dce_error_inq_text
145**
146**  SCOPE:              PUBLIC - declared in dce_error.h
147**
148**  DESCRIPTION:
149**
150**  Returns a text string in a user provided buffer associated with a given
151**  error status code. In the case of errors a text string will also be
152**  returned indicating the nature of the error.
153**
154**  INPUTS:
155**
156**      status_to_convert   A DCE error status code to be converted to
157**                          text form.
158**
159**  INPUTS/OUTPUTS:         None.
160**
161**  OUTPUTS:
162**
163**      error_text          A user provided buffer to hold the text
164**                          equivalent of status_to_convert or
165**                          a message indicating what error occurred.
166**
167**
168**      status              The result of the operation. One of:
169**                           0  -  success
170**                          -1  -  failure
171**
172**  IMPLICIT INPUTS:    none
173**
174**  IMPLICIT OUTPUTS:   none
175**
176**  FUNCTION VALUE:     none
177**
178**  SIDE EFFECTS:       none
179**
180**--
181**/
182
183static void dce_get_msg(
184	unsigned long   status_to_convert,
185	char			*error_text,
186	size_t			error_text_len,
187	char			*fname,
188	char			*cname,
189	int             *status)
190{
191    unsigned short  facility_code;
192    unsigned short  component_code;
193    unsigned short  status_code;
194#ifdef HAVE_NL_TYPES_H
195    nl_catd     catd;
196#endif
197    char        component_name[4];
198    const char  *facility_name;
199    char        filename_prefix[7];
200    char        nls_filename[MAXPATHLEN];
201    char        alt_filename[MAXPATHLEN];
202    char        *message;
203    static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz_0123456789-+@";
204    static const char *facility_names[] = {
205        "dce",
206        "dfs"
207    };
208
209    /*
210     * set up output status for future error returns
211     */
212    if (status != NULL)
213    {
214        *status = -1;
215    }
216
217    /*
218     * check for ok input status
219     */
220    if (status_to_convert == 0)
221    {
222        if (status != NULL)
223        {
224            *status = 0;
225        }
226        strlcpy ((char *)error_text, "successful completion", error_text_len);
227        return;
228    }
229
230    /*
231     * extract the component, facility and status codes
232     */
233    facility_code = (status_to_convert & FACILITY_CODE_MASK)
234        >> FACILITY_CODE_SHIFT;
235
236    component_code = (status_to_convert & COMPONENT_CODE_MASK)
237        >> COMPONENT_CODE_SHIFT;
238
239    status_code = (status_to_convert & STATUS_CODE_MASK)
240        >> STATUS_CODE_SHIFT;
241
242    /*
243     * see if this is a recognized facility
244     */
245    if (facility_code == 0 || facility_code > sizeof (facility_names) / sizeof (char *))
246    {
247        sprintf ((char *) error_text, "status %08lx (unknown facility)", status_to_convert);
248        return;
249    }
250
251    facility_name = facility_names[facility_code - 1];
252
253    /*
254     * Convert component name from RAD-50 component code.  (Mapping is:
255     * 0 => 'a', ..., 25 => 'z', 26 => '{', 27 => '0', ..., 36 => '9'.)
256     */
257
258    component_name[3] = 0;
259    component_name[2] = alphabet[component_code % 40];
260    component_code /= 40;
261    component_name[1] = alphabet[component_code % 40];
262    component_name[0] = alphabet[component_code / 40];
263
264    if (fname != NULL)
265        sprintf ((char*) fname, "%3s", facility_name);
266    if (cname != NULL)
267        sprintf ((char*) cname, "%3s", component_name);
268
269    sprintf ((char*) filename_prefix, "%3s%3s", facility_name, component_name);
270
271#if defined(CATALOG_DIR)
272    sprintf ((char*) nls_filename,
273	    CATALOG_DIR "/" RPC_NLS_FORMAT, filename_prefix);
274#else
275    sprintf ((char*) nls_filename, RPC_NLS_FORMAT, filename_prefix);
276#endif
277
278    /*
279     * Open the message file
280     */
281#ifdef HAVE_NL_TYPES_H
282    catd = (nl_catd) catopen (nls_filename, 0);
283    if (catd == (nl_catd) -1)
284    {
285        /*
286         * If we did not succeed in opening message file using NLSPATH,
287         * try to open the message file in a well-known default area
288         */
289
290        sprintf (alt_filename,
291                 RPC_DEFAULT_NLSPATH,
292                 filename_prefix);
293        catd = (nl_catd) catopen (alt_filename, 0);
294
295        if (catd == (nl_catd) -1)
296        {
297            sprintf ((char *) error_text, "status %08lx", status_to_convert);
298            return;
299        }
300    }
301
302    /*
303     * try to get the specified message from the file
304     */
305    message = (char *) catgets (catd, 1, status_code, NO_MESSAGE);
306
307    /*
308     * if everything went well, return the resulting message
309     */
310    if (strcmp (message, NO_MESSAGE) != 0)
311    {
312        sprintf ((char *) error_text, "%s", message);
313        if (status != NULL)
314        {
315            *status = 0;
316        }
317    }
318    else
319    {
320        sprintf ((char *) error_text, "status %08lx", status_to_convert);
321    }
322
323    catclose (catd);
324#else
325    sprintf ((char *) error_text, "status %08lx", status_to_convert);
326#endif
327}
328void dce_error_inq_text (
329unsigned long           status_to_convert,
330dce_error_string_t      error_text,
331int                     *status
332)
333{
334    char        cname[4];
335    char        fname[4];
336
337    /*
338     * check for ok input status
339     */
340    if (status_to_convert == 0)
341    {
342        if (status != NULL)
343        {
344            *status = 0;
345        }
346        strlcpy ((char *)error_text, "successful completion", dce_c_error_string_len);
347        return;
348    }
349
350    dce_get_msg (status_to_convert, (char *)error_text, dce_c_error_string_len, fname, cname, status);
351    strlcat ((char*) error_text, " (", dce_c_error_string_len);
352    strlcat ((char*) error_text, fname, dce_c_error_string_len);
353    strlcat ((char*) error_text, " / ", dce_c_error_string_len);
354    strlcat ((char*) error_text, cname, dce_c_error_string_len);
355    strlcat ((char*) error_text, ")", dce_c_error_string_len);
356}
357
358#if 0
359/* unused functions */
360int dce_fprintf(FILE *f, unsigned long index, ...)
361{
362    va_list ap;
363    int st;
364    int i;
365    char format[1024];
366
367    dce_get_msg(index, format, sizeof (format), NULL, NULL, &st);
368    if (st != 0) return EOF;
369
370    va_start(ap, index);
371    i = vfprintf(f, format, ap);
372    va_end(ap);
373    return i;
374}
375int dce_printf(unsigned long index, ...)
376{
377    va_list ap;
378    int st;
379    int i;
380    char format[1024];
381
382    dce_get_msg(index, format, sizeof (format), NULL, NULL, &st);
383    if (st != 0) return EOF;
384
385    va_start(ap, index);
386    i = vfprintf(stdout, format, ap);
387    va_end(ap);
388    return i;
389}
390#endif
391
392#ifdef BUILD_STCODE
393main(int argc, char **argv)
394{
395    long code;
396    int i;
397    int _;
398    dce_error_string_t message;
399
400    if (argc <= 1) {
401        printf("Usage:  stcode {0x<hex status code> | <decimal status code>}\n");
402        exit(1);
403    }
404
405    for (i=1; i < argc; i++) {
406        if(strncmp(argv[i], "0x", 2) == 0)
407                sscanf(argv[i], "%x", &code);
408        else
409                sscanf(argv[i], "%d", &code);
410        dce_error_inq_text(code, message, &_);
411        printf("%d (decimal), %x (hex): %s\n", code, code, message);
412    }
413}
414#endif
415