1/* sockerror.c --- convert WinSock error number to string
2   Vince Del Vecchio <vdelvecc@spd.analog.com>
3
4   This file is part of GNU CVS.
5
6   GNU CVS is free software; you can redistribute it and/or modify it
7   under the terms of the GNU General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.  */
15
16#include <stdio.h>
17#include <winsock.h>
18
19struct err_strs {
20    char **strs;
21    int first;
22    int last;
23};
24
25static char *errs1[] = {
26    /* EINTR		*/ "Interrupted system call"
27};
28
29static char *errs2[] = {
30    /* EBADF		*/ "Bad file descriptor"
31};
32
33static char *errs3[] = {
34    /* EACCES		*/ "Permission denied",
35    /* EFAULT		*/ "Bad address"
36};
37
38static char *errs4[] = {
39    /* EINVAL		*/ "Invalid argument"
40};
41
42static char *errs5[] = {
43    /* EMFILE		*/ "Too many open files",
44};
45
46static char *errs6[] = {
47    /* EWOULDBLOCK	*/ "Resource temporarily unavailable",
48    /* EINPROGRESS	*/ "Operation now in progress",
49    /* EALREADY		*/ "Operation already in progress",
50    /* ENOTSOCK		*/ "Socket operation on non-socket",
51    /* EDESTADDRREQ	*/ "Destination address required",
52    /* EMSGSIZE		*/ "Message too long",
53    /* EPROTOTYPE	*/ "Protocol wrong type for socket",
54    /* ENOPROTOOPT	*/ "Protocol not available",
55    /* EPROTONOSUPPORT	*/ "Protocol not supported",
56    /* ESOCKTNOSUPPORT	*/ "Socket type not supported",
57    /* EOPNOTSUPP	*/ "Operation not supported on socket",
58    /* EPFNOSUPPORT	*/ "Protocol family not supported",
59    /* EAFNOSUPPORT	*/ "Address family not supported by protocol",
60    /* EADDRINUSE	*/ "Address already in use",
61    /* EADDRNOTAVAIL	*/ "Can't assign requested address",
62    /* ENETDOWN		*/ "Network is down",
63    /* ENETUNREACH	*/ "Network is unreachable",
64    /* ENETRESET	*/ "Network connection dropped on reset",
65    /* ECONNABORTED	*/ "Software caused connection abort",
66    /* ECONNRESET	*/ "Connection reset by peer",
67    /* ENOBUFS		*/ "No buffer space available",
68    /* EISCONN		*/ "Socket is already connected",
69    /* ENOTCONN		*/ "Socket is not connected",
70    /* ESHUTDOWN	*/ "Can't send after socket shutdown",
71    /* ETOOMANYREFS	*/ "Too many references: can't splice",
72    /* ETIMEDOUT	*/ "Connection timed out",
73    /* ECONNREFUSED	*/ "Connection refused",
74    /* ELOOP		*/ "Too many levels of symbolic links",
75    /* ENAMETOOLONG	*/ "File name too long",
76    /* EHOSTDOWN	*/ "Host is down",
77    /* EHOSTUNREACH	*/ "No route to host",
78    /* ENOTEMPTY	*/ "Directory not empty",
79    /* EPROCLIM		*/ "Too many processes",
80    /* EUSERS		*/ "Too many users",
81    /* EDQUOT		*/ "Disc quota exceeded",
82    /* ESTALE		*/ "Stale NFS file handle",
83    /* EREMOTE		*/ "Object is remote"
84};
85
86static char *errs7[] = {
87    /* SYSNOTREADY	*/ "Network subsystem unavailable",
88    /* VERNOTSUPPORTED	*/ "Requested WinSock version not supported",
89    /* NOTINITIALISED	*/ "WinSock was not initialized"
90};
91
92#ifdef WSAEDISCON
93static char *errs8[] = {
94    /* EDISCON		*/ "Graceful shutdown in progress"
95};
96#endif
97
98static char *errs9[] = {
99    /* HOST_NOT_FOUND	*/ "Unknown host",
100    /* TRY_AGAIN	*/ "Host name lookup failure",
101    /* NO_RECOVERY	*/ "Unknown server error",
102    /* NO_DATA		*/ "No address associated with name",
103};
104
105/* Some of these errors are defined in the winsock.h header file I have,
106   but not in the Winsock 1.1 spec.  I include them some of them anyway,
107   where it is not too hard to avoid referencing the symbolic constant. */
108
109static struct err_strs sock_errlist[] = {
110    { errs1,	WSAEINTR,	WSAEINTR },
111    { errs2,	WSAEBADF,	WSAEBADF },
112    { errs3,	WSAEACCES,	WSAEFAULT },
113    { errs4,	WSAEINVAL,	WSAEINVAL },
114    { errs5,	WSAEMFILE,	WSAEMFILE },
115    { errs6,	WSAEWOULDBLOCK, WSAEHOSTUNREACH + 6 },
116    { errs7,	WSASYSNOTREADY,	WSANOTINITIALISED },
117#ifdef WSAEDISCON
118    { errs8,	WSAEDISCON,	WSAEDISCON },
119#endif
120    { errs9,	WSAHOST_NOT_FOUND, WSANO_DATA }
121};
122
123char *
124sock_strerror (int errnum)
125{
126    static char buf[40];
127    int i;
128
129    for (i = 0; i < (sizeof sock_errlist / sizeof *sock_errlist); i++)
130    {
131	if (errnum >= sock_errlist[i].first && errnum <= sock_errlist[i].last)
132	    return sock_errlist[i].strs[errnum - sock_errlist[i].first];
133    }
134    sprintf(buf, "Unknown socket error: %d", errnum);
135    return buf;
136}
137