URI:
       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 = &ETHErrno;
          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 }