afsconfig-and-rcsid-all-around-20010705
[openafs.git] / src / comerr / error_msg.c
1 /*
2  * $Locker$
3  *
4  * Copyright 1987 by the Student Information Processing Board
5  * of the Massachusetts Institute of Technology
6  *
7  * For copyright info, see "mit-sipb-cr.h".
8  */
9
10 #include <afs/param.h>
11 #include <afsconfig.h>
12
13 RCSID("$Header$");
14
15 #include "internal.h"
16 #include <stdio.h>
17 #include "error_table.h"
18 #include "mit-sipb-cr.h"
19 #include <afs/errors.h>
20 #include <string.h>
21
22 static const char copyright[] =
23     "Copyright 1986, 1987, 1988 by the Student Information Processing Board\nand the department of Information Systems\nof the Massachusetts Institute of Technology";
24
25 static char buffer[64];
26
27 static struct et_list * _et_list = (struct et_list *) NULL;
28
29 #ifdef AFS_PTHREAD_ENV
30 #include <pthread.h>
31 #include <assert.h>
32
33 /*
34  * This mutex protects the following variables:
35  * _et_list
36  */
37
38 static pthread_mutex_t et_list_mutex;
39 static int et_list_done = 0;
40 static pthread_once_t et_list_once = PTHREAD_ONCE_INIT;
41
42 /*
43  * Function to initialize the et_list_mutex
44  */
45
46 void et_mutex_once(void) {
47     assert(!pthread_mutex_init(&et_list_mutex, (const pthread_mutexattr_t*)0));
48     et_list_done = 1;
49 }
50 #define LOCK_ET_LIST \
51         (et_list_done || pthread_once(&et_list_once, et_mutex_once)); \
52         assert(pthread_mutex_lock(&et_list_mutex)==0);
53 #define UNLOCK_ET_LIST assert(pthread_mutex_unlock(&et_list_mutex)==0);
54 #else
55 #define LOCK_ET_LIST
56 #define UNLOCK_ET_LIST
57 #endif /* AFS_PTHREAD_ENV */
58
59
60 static char *vmsgs[] = {
61     "volume needs to be salvaged",      /* 101, in Pittsburghese */
62     "no such entry (vnode)",    /* 102 */
63     "volume does not exist / did not salvage",  /* 103 */
64     "volume already exists",    /* 104 */
65     "volume out of service",    /* 105 */
66     "volume offline (utility running)", /* 106 */
67     "volume already online",    /* 107 */
68     "unknown volume error 108", /* 108 */
69     "unknown volume error 109", /* 109 */
70     "volume temporarily busy",  /* 110 */
71     "volume moved",             /* 111 */
72     (char *) 0
73 };
74
75 static char *negative_message(code)
76 int code; {
77     if (code == -1)
78         return "server or network not responding";
79     else if (code == -2)
80         return "invalid RPC (RX) operation";
81     else if (code == -3)
82         return "server not responding promptly";
83     else if (code == -7)
84         return "port address already in use";
85     else if (code <= -450 && code > -500) {
86         sprintf(buffer, "RPC interface mismatch (%d)", code);
87         return buffer;
88     }
89     else {
90         sprintf(buffer, "unknown RPC error (%d)", code);
91         return buffer;
92     }
93 }
94
95 static char *volume_message(code)
96 int code; {
97       if (code >= 101 && code <= 111)
98           return vmsgs[code-101];
99       else
100           return "unknown volume error";
101 }
102
103 const char * error_message (code)
104   int code;
105 {
106     int offset;
107     struct et_list *et;
108     int table_num;
109     int started = 0;
110     char *cp;
111     char *err_msg;
112
113     /* check for rpc errors first */
114     if (code < 0) return negative_message(code);
115
116     offset = code & ((1<<ERRCODE_RANGE)-1);
117     table_num = code - offset;
118     if (!table_num) {
119         if ( (err_msg = strerror(offset)) != NULL) 
120             return(err_msg);
121         else if (offset < 140)
122             return volume_message(code);
123         else
124             goto oops;
125     }
126     LOCK_ET_LIST
127     for (et = _et_list; et; et = et->next) {
128         if (et->table->base == table_num) {
129             /* This is the right table */
130             if (et->table->n_msgs <= offset)
131                 goto oops;
132             UNLOCK_ET_LIST
133             return(et->table->msgs[offset]);
134         }
135     }
136 oops:
137     UNLOCK_ET_LIST
138     strcpy (buffer, "Unknown code ");
139     if (table_num) {
140         strcat (buffer, error_table_name (table_num));
141         strcat (buffer, " ");
142     }
143     for (cp = buffer; *cp; cp++)
144         ;
145     if (offset >= 100) {
146         *cp++ = '0' + offset / 100;
147         offset %= 100;
148         started++;
149     }
150     if (started || offset >= 10) {
151         *cp++ = '0' + offset / 10;
152         offset %= 10;
153     }
154     *cp++ = '0' + offset;
155     if (code > -10000) sprintf (cp, " (%d)", code);
156     else *cp = '\0';
157     return(buffer);
158 }
159
160 void add_to_error_table(struct et_list *new_table) {
161     struct et_list *et;
162
163     LOCK_ET_LIST
164     /*
165      * Protect against adding the same error table twice
166      */
167
168     for (et = _et_list; et; et = et->next) {
169         if (et->table->base == new_table->table->base) {
170             UNLOCK_ET_LIST
171             return;
172         }
173     }
174
175     new_table->next = _et_list;
176     _et_list = new_table;
177     UNLOCK_ET_LIST
178 }