terror.c - vaccinewars - be a doctor and try to vaccinate the world
HTML git clone git://src.adamsgaard.dk/vaccinewars
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
terror.c (7177B)
---
1 /************************************************************************
2 * error.c Error-handling routines for dopewars *
3 * Copyright (C) 1998-2021 Ben Webb *
4 * Email: benwebb@users.sf.net *
5 * WWW: https://dopewars.sourceforge.io/ *
6 * *
7 * This program is free software; you can redistribute it and/or *
8 * modify it under the terms of the GNU General Public License *
9 * as published by the Free Software Foundation; either version 2 *
10 * of the License, or (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, *
20 * MA 02111-1307, USA. *
21 ************************************************************************/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <glib.h> /* For GString functions */
28 #include <string.h> /* For strerror */
29
30 #ifdef CYGWIN
31 #include <winsock2.h> /* For WSAxxx constants */
32 #include <windows.h> /* For FormatMessage() etc. */
33 #else
34 #include <netdb.h> /* For h_errno error codes */
35 #endif
36
37 #include "error.h"
38 #include "nls.h"
39
40 static gboolean err_utf8_encoding = FALSE;
41
42 /*
43 * If "want" is TRUE, we want all error texts (via. strerror) in UTF8,
44 * even if the locale's charset is not UTF8.
45 */
46 void WantUTF8Errors(gboolean want)
47 {
48 err_utf8_encoding = want;
49 }
50
51 /*
52 * Returns the strerror() error string for the given error code,
53 * possibly translated to UTF8. N.B. Unlike strerror(), this string
54 * must be g_free'd by the caller when no longer needed.
55 */
56 gchar *ErrStrFromErrno(int errcode)
57 {
58 gchar *untran = strerror(errcode);
59
60 if (err_utf8_encoding) {
61 gchar *utf8str;
62
63 utf8str = g_locale_to_utf8(untran, strlen(untran), NULL, NULL, NULL);
64 if (utf8str) {
65 return utf8str;
66 } else {
67 return g_strdup(_("(Error cannot be displayed in UTF-8)"));
68 }
69 } else {
70 return g_strdup(untran);
71 }
72 }
73
74 void FreeError(LastError *error)
75 {
76 if (!error)
77 return;
78 if (error->type && error->type->FreeErrorData) {
79 (*error->type->FreeErrorData)(error);
80 } else {
81 g_free(error->data);
82 }
83 g_free(error);
84 }
85
86 LastError *NewError(ErrorType *type, gint code, gpointer data)
87 {
88 LastError *error;
89
90 error = g_new0(LastError, 1);
91
92 error->type = type;
93 error->code = code;
94 error->data = data;
95
96 return error;
97 }
98
99 void SetError(LastError **error, ErrorType *type, gint code, gpointer data)
100 {
101 if (!error)
102 return;
103 if (*error)
104 FreeError(*error);
105 *error = NewError(type, code, data);
106 }
107
108 void LookupErrorCode(GString *str, gint code, ErrTable *table,
109 gchar *fallbackstr)
110 {
111 for (; table && table->string; table++) {
112 if (code == table->code) {
113 g_string_append(str, _(table->string));
114 return;
115 }
116 }
117 g_string_append_printf(str, fallbackstr, code);
118 }
119
120 /* "Custom" error handling */
121 static ErrTable CustomErrStr[] = {
122 {E_FULLBUF, N_("Connection dropped due to full buffer")},
123 {0, NULL}
124 };
125
126 void CustomAppendError(GString *str, LastError *error)
127 {
128 LookupErrorCode(str, error->code, CustomErrStr,
129 _("Internal error code %d"));
130 }
131
132 static ErrorType ETCustom = { CustomAppendError, NULL };
133 ErrorType *ET_CUSTOM = &ETCustom;
134
135 /*
136 * "errno" error handling
137 */
138 void ErrnoAppendError(GString *str, LastError *error)
139 {
140 gchar *errstr = ErrStrFromErrno(error->code);
141 g_string_append(str, errstr);
142 g_free(errstr);
143 }
144
145 static ErrorType ETErrno = { ErrnoAppendError, NULL };
146 ErrorType *ET_ERRNO = &ETErrno;
147
148 #ifdef CYGWIN
149
150 /* Winsock error handling */
151 static ErrTable WSAErrStr[] = {
152 /* These are the explanations of the various
153 Windows Sockets error codes */
154 {WSANOTINITIALISED, N_("WinSock has not been properly initialized")},
155 {WSASYSNOTREADY, N_("Network subsystem is not ready")},
156 {WSAVERNOTSUPPORTED, N_("WinSock version not supported")},
157 {WSAENETDOWN, N_("The network subsystem has failed")},
158 {WSAEADDRINUSE, N_("Address already in use")},
159 {WSAENETDOWN, N_("Cannot reach the network")},
160 {WSAETIMEDOUT, N_("The connection timed out")},
161 {WSAEMFILE, N_("Out of file descriptors")},
162 {WSAENOBUFS, N_("Out of buffer space")},
163 {WSAEOPNOTSUPP, N_("Operation not supported")},
164 {WSAECONNABORTED, N_("Connection aborted due to failure")},
165 {WSAECONNRESET, N_("Connection reset by remote host")},
166 {WSAECONNREFUSED, N_("Connection refused")},
167 {WSAEAFNOSUPPORT, N_("Address family not supported")},
168 {WSAEPROTONOSUPPORT, N_("Protocol not supported")},
169 {WSAESOCKTNOSUPPORT, N_("Socket type not supported")},
170 {WSAHOST_NOT_FOUND, N_("Host not found")},
171 {WSATRY_AGAIN, N_("Temporary name server error - try again later")},
172 {WSANO_RECOVERY, N_("Failed to contact nameserver")},
173 {WSANO_DATA, N_("Valid name, but no DNS data record present")},
174 {0, NULL}
175 };
176
177 void WinsockAppendError(GString *str, LastError *error)
178 {
179 LookupErrorCode(str, error->code, WSAErrStr, _("Network error code %d"));
180 }
181
182 static ErrorType ETWinsock = { WinsockAppendError, NULL };
183 ErrorType *ET_WINSOCK = &ETWinsock;
184
185 /*
186 * Standard Win32 "GetLastError" handling
187 */
188 void Win32AppendError(GString *str, LastError *error)
189 {
190 LPTSTR lpMsgBuf;
191
192 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
193 FORMAT_MESSAGE_FROM_SYSTEM, NULL, error->code,
194 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
195 (LPTSTR) & lpMsgBuf, 0, NULL);
196 g_string_append(str, lpMsgBuf);
197 LocalFree(lpMsgBuf);
198 }
199
200 static ErrorType ETWin32 = { Win32AppendError, NULL };
201 ErrorType *ET_WIN32 = &ETWin32;
202
203 #else
204
205 /* h_errno error handling */
206 static ErrTable DNSErrStr[] = {
207 /* These are the explanations of the various name server error codes */
208 {HOST_NOT_FOUND, N_("Host not found")},
209 {TRY_AGAIN, N_("Temporary name server error - try again later")},
210 {0, NULL}
211 };
212
213 void HErrnoAppendError(GString *str, LastError *error)
214 {
215 LookupErrorCode(str, error->code, DNSErrStr,
216 _("Name server error code %d"));
217 }
218
219 static ErrorType ETHErrno = { HErrnoAppendError, NULL };
220 ErrorType *ET_HERRNO = ÐErrno;
221
222 #endif /* CYGWIN */
223
224 void g_string_assign_error(GString *str, LastError *error)
225 {
226 g_string_truncate(str, 0);
227 g_string_append_error(str, error);
228 }
229
230 void g_string_append_error(GString *str, LastError *error)
231 {
232 if (!error || !error->type)
233 return;
234 (*error->type->AppendErrorString) (str, error);
235 }