# endif
#endif
+#define INHIBIT_WRAP /* avoid wrapping of socket, bind, ... */
+
#include "wget.h"
#include "utils.h"
#include "url.h"
-#ifndef errno
-extern int errno;
-#endif
-
#ifndef ES_SYSTEM_REQUIRED
#define ES_SYSTEM_REQUIRED 0x00000001
#endif
/* Defined in log.c. */
-void log_request_redirect_output PARAMS ((const char *));
+void log_request_redirect_output (const char *);
/* Windows version of xsleep in utils.c. */
}
usleep (seconds * 1000000L);
#else /* not HAVE_USLEEP */
- SleepEx (seconds * 1000, FALSE);
+ SleepEx ((DWORD) (seconds * 1000 + .5), FALSE);
#endif /* not HAVE_USLEEP */
}
-#if defined(_MSC_VER) && _MSC_VER < 1300
+#if defined(__BORLANDC__) || (defined(_MSC_VER) && _MSC_VER < 1300)
static inline int
char_value (char c, int base)
__int64
str_to_int64 (const char *nptr, char **endptr, int base)
{
-#define OVERFLOW 9223372036854775807I64
-#define UNDERFLOW (-OVERFLOW - 1)
+#define INT64_OVERFLOW 9223372036854775807I64
+#define INT64_UNDERFLOW (-INT64_OVERFLOW - 1)
__int64 result = 0;
int negative;
__int64 newresult = base * result + val;
if (newresult < result)
{
- result = OVERFLOW;
+ result = INT64_OVERFLOW;
errno = ERANGE;
break;
}
__int64 newresult = base * result - val;
if (newresult > result)
{
- result = UNDERFLOW;
+ result = INT64_UNDERFLOW;
errno = ERANGE;
break;
}
return result;
}
-#else /* !defined(_MSC_VER) || _MSC_VER >= 1300 */
+#else /* !defined(__BORLANDC__) && (!defined(_MSC_VER) || _MSC_VER >= 1300) */
__int64
str_to_int64 (const char *nptr, char **endptr, int base)
#endif
}
-#endif /* !defined(_MSC_VER) || _MSC_VER >= 1300 */
-
-/* A simple clone of ftello. The normal ftell doesn't work for large
- files, so this is needed, and used by file_size(), which is itself
- used for the --post-file option.
-
- This function uses fgetpos incorrectly and should be considered a
- hack until a better way to tell the stream position is found. */
-
-__int64
-wget_ftello (FILE *fp)
-{
- fpos_t pos;
- if (fgetpos (fp, &pos) != 0)
- return -1;
- else
- return pos;
-}
+#endif /* !defined(__BORLANDC__) && (!defined(_MSC_VER) || _MSC_VER >= 1300) */
void
-windows_main_junk (int *argc, char **argv, char **exec_name)
+windows_main (int *argc, char **argv, char **exec_name)
{
char *p;
static void
ws_hangup (const char *reason)
{
- /* Whether we arrange our own version of opt.lfilename here. */
- int changedp = 0;
-
- if (!opt.lfilename)
- {
- opt.lfilename = unique_name (DEFAULT_LOGFILE, 0);
- changedp = 1;
- }
- printf (_("Continuing in background.\n"));
- if (changedp)
- printf (_("Output will be written to `%s'.\n"), opt.lfilename);
-
+ fprintf (stderr, _("Continuing in background.\n"));
log_request_redirect_output (reason);
/* Detach process from the current console. Under Windows 9x, if we
struct fake_fork_info
{
HANDLE event;
- int changedp;
+ int logfile_changed;
char lfilename[MAX_PATH + 1];
};
event = info->event;
+ info->logfile_changed = 0;
if (!opt.lfilename)
{
- opt.lfilename = unique_name (DEFAULT_LOGFILE, 0);
- info->changedp = 1;
- strncpy (info->lfilename, opt.lfilename, sizeof (info->lfilename));
- info->lfilename[sizeof (info->lfilename) - 1] = '\0';
+ /* See utils:fork_to_background for explanation. */
+ FILE *new_log_fp = unique_create (DEFAULT_LOGFILE, 0, &opt.lfilename);
+ if (new_log_fp)
+ {
+ info->logfile_changed = 1;
+ strncpy (info->lfilename, opt.lfilename, sizeof (info->lfilename));
+ info->lfilename[sizeof (info->lfilename) - 1] = '\0';
+ fclose (new_log_fp);
+ }
}
- else
- info->changedp = 0;
UnmapViewOfFile (info);
CloseHandle (section);
char *name;
BOOL rv;
- event = section = pi.hProcess = pi.hThread = NULL;
+ section = pi.hProcess = pi.hThread = NULL;
/* Get the fully qualified name of our executable. This is more reliable
than using argv[0]. */
/* Create the child process detached form the current console and in a
suspended state. */
- memset (&si, 0, sizeof (si));
+ xzero (si);
si.cb = sizeof (si);
rv = CreateProcess (exe, GetCommandLine (), NULL, NULL, TRUE,
CREATE_SUSPENDED | DETACHED_PROCESS,
}
/* Ensure string is properly terminated. */
- if (info->changedp &&
+ if (info->logfile_changed &&
!memchr (info->lfilename, '\0', sizeof (info->lfilename)))
{
rv = FALSE;
}
printf (_("Continuing in background, pid %lu.\n"), pi.dwProcessId);
- if (info->changedp)
+ if (info->logfile_changed)
printf (_("Output will be written to `%s'.\n"), info->lfilename);
UnmapViewOfFile (info);
void
ws_startup (void)
{
- WORD requested;
WSADATA data;
- int err;
-
- requested = MAKEWORD (1, 1);
- err = WSAStartup (requested, &data);
+ WORD requested = MAKEWORD (1, 1);
+ int err = WSAStartup (requested, &data);
if (err != 0)
{
fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
static HANDLE thread_hnd = NULL;
struct thread_data thread_arg;
DWORD thread_id;
- int rc = 0;
+ int rc;
DEBUGP (("seconds %.2f, ", seconds));
thread_hnd = NULL;
return rc;
}
+\f
+/* Wget expects network calls such as connect, recv, send, etc., to set
+ errno on failure. To achieve that, Winsock calls are wrapped with code
+ that, in case of error, sets errno to the value of WSAGetLastError().
+ In addition, we provide a wrapper around strerror, which recognizes
+ Winsock errors and prints the appropriate error message. */
+
+/* Define a macro that creates a function definition that wraps FUN into
+ a function that sets errno the way the rest of the code expects. */
+
+#define WRAP(fun, decl, call) int wrapped_##fun decl { \
+ int retval = fun call; \
+ if (retval < 0) \
+ errno = WSAGetLastError (); \
+ return retval; \
+}
+
+WRAP (socket, (int domain, int type, int protocol), (domain, type, protocol))
+WRAP (bind, (int s, struct sockaddr *a, int alen), (s, a, alen))
+WRAP (connect, (int s, const struct sockaddr *a, int alen), (s, a, alen))
+WRAP (recv, (int s, void *buf, int len, int flags), (s, buf, len, flags))
+WRAP (send, (int s, const void *buf, int len, int flags), (s, buf, len, flags))
+WRAP (select, (int n, fd_set *r, fd_set *w, fd_set *e, const struct timeval *tm),
+ (n, r, w, e, tm))
+WRAP (getsockname, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
+WRAP (getpeername, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
+WRAP (setsockopt, (int s, int level, int opt, const void *val, int len),
+ (s, level, opt, val, len))
+WRAP (closesocket, (int s), (s))
+
+/* Return the text of the error message for Winsock error WSERR. */
+
+static const char *
+get_winsock_error (int wserr)
+{
+ switch (wserr) {
+ case WSAEINTR: return "Interrupted system call";
+ case WSAEBADF: return "Bad file number";
+ case WSAEACCES: return "Permission denied";
+ case WSAEFAULT: return "Bad address";
+ case WSAEINVAL: return "Invalid argument";
+ case WSAEMFILE: return "Too many open files";
+ case WSAEWOULDBLOCK: return "Resource temporarily unavailable";
+ case WSAEINPROGRESS: return "Operation now in progress";
+ case WSAEALREADY: return "Operation already in progress";
+ case WSAENOTSOCK: return "Socket operation on nonsocket";
+ case WSAEDESTADDRREQ: return "Destination address required";
+ case WSAEMSGSIZE: return "Message too long";
+ case WSAEPROTOTYPE: return "Protocol wrong type for socket";
+ case WSAENOPROTOOPT: return "Bad protocol option";
+ case WSAEPROTONOSUPPORT: return "Protocol not supported";
+ case WSAESOCKTNOSUPPORT: return "Socket type not supported";
+ case WSAEOPNOTSUPP: return "Operation not supported";
+ case WSAEPFNOSUPPORT: return "Protocol family not supported";
+ case WSAEAFNOSUPPORT: return "Address family not supported by protocol family";
+ case WSAEADDRINUSE: return "Address already in use";
+ case WSAEADDRNOTAVAIL: return "Cannot assign requested address";
+ case WSAENETDOWN: return "Network is down";
+ case WSAENETUNREACH: return "Network is unreachable";
+ case WSAENETRESET: return "Network dropped connection on reset";
+ case WSAECONNABORTED: return "Software caused connection abort";
+ case WSAECONNRESET: return "Connection reset by peer";
+ case WSAENOBUFS: return "No buffer space available";
+ case WSAEISCONN: return "Socket is already connected";
+ case WSAENOTCONN: return "Socket is not connected";
+ case WSAESHUTDOWN: return "Cannot send after socket shutdown";
+ case WSAETOOMANYREFS: return "Too many references";
+ case WSAETIMEDOUT: return "Connection timed out";
+ case WSAECONNREFUSED: return "Connection refused";
+ case WSAELOOP: return "Too many levels of symbolic links";
+ case WSAENAMETOOLONG: return "File name too long";
+ case WSAEHOSTDOWN: return "Host is down";
+ case WSAEHOSTUNREACH: return "No route to host";
+ case WSAENOTEMPTY: return "Not empty";
+ case WSAEPROCLIM: return "Too many processes";
+ case WSAEUSERS: return "Too many users";
+ case WSAEDQUOT: return "Bad quota";
+ case WSAESTALE: return "Something is stale";
+ case WSAEREMOTE: return "Remote error";
+ case WSAEDISCON: return "Disconnected";
+
+ /* Extended Winsock errors */
+ case WSASYSNOTREADY: return "Winsock library is not ready";
+ case WSANOTINITIALISED: return "Winsock library not initalised";
+ case WSAVERNOTSUPPORTED: return "Winsock version not supported";
+
+ case WSAHOST_NOT_FOUND: return "Host not found";
+ case WSATRY_AGAIN: return "Host not found, try again";
+ case WSANO_RECOVERY: return "Unrecoverable error in call to nameserver";
+ case WSANO_DATA: return "No data record of requested type";
+
+ default:
+ return NULL;
+ }
+}
+
+/* Return the error message corresponding to ERR. This is different
+ from Windows libc strerror() in that it handles Winsock errors
+ correctly. */
+
+const char *
+windows_strerror (int err)
+{
+ const char *p;
+ if (err >= 0 && err < sys_nerr)
+ return strerror (err);
+ else if ((p = get_winsock_error (err)) != NULL)
+ return p;
+ else
+ {
+ static char buf[32];
+ snprintf (buf, sizeof (buf), "Unknown error %d (%#x)", err, err);
+ return buf;
+ }
+}