]> sjero.net Git - wget/blob - src/mswindows.c
[svn] Windows fixes by Gisle Vanem.
[wget] / src / mswindows.c
1 /* mswindows.c -- Windows-specific support
2    Copyright (C) 1995, 1996, 1997, 1998  Free Software Foundation, Inc.
3
4 This file is part of GNU Wget.
5
6 GNU Wget is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 GNU Wget 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 You should have received a copy of the GNU General Public License
17 along with Wget; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20 In addition, as a special exception, the Free Software Foundation
21 gives permission to link the code of its release of Wget with the
22 OpenSSL project's "OpenSSL" library (or with modified versions of it
23 that use the same license as the "OpenSSL" library), and distribute
24 the linked executables.  You must obey the GNU General Public License
25 in all respects for all of the code used other than "OpenSSL".  If you
26 modify this file, you may extend this exception to your version of the
27 file, but you are not obligated to do so.  If you do not wish to do
28 so, delete this exception statement from your version.  */
29
30 /* #### Someone please document what these functions do!  */
31
32 #include <config.h>
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <winsock.h>
37 #include <string.h>
38 #include <assert.h>
39 #include <errno.h>
40
41 #ifdef HACK_BCC_UTIME_BUG
42 # include <io.h>
43 # include <fcntl.h>
44 # ifdef HAVE_UTIME_H
45 #  include <utime.h>
46 # endif
47 # ifdef HAVE_SYS_UTIME_H
48 #  include <sys/utime.h>
49 # endif
50 #endif
51
52 #include "wget.h"
53 #include "utils.h"
54 #include "url.h"
55
56 #ifndef errno
57 extern int errno;
58 #endif
59
60 #ifndef ES_SYSTEM_REQUIRED
61 #define ES_SYSTEM_REQUIRED  0x00000001
62 #endif
63
64 #ifndef ES_CONTINUOUS
65 #define ES_CONTINUOUS       0x80000000
66 #endif
67
68
69 /* Defined in log.c.  */
70 void log_request_redirect_output PARAMS ((const char *));
71
72 static DWORD set_sleep_mode (DWORD mode);
73
74 static DWORD pwr_mode = 0;
75 static int windows_nt_p;
76
77 #ifndef HAVE_SLEEP
78
79 /* Emulation of Unix sleep.  */
80
81 unsigned int
82 sleep (unsigned seconds)
83 {
84   return SleepEx (1000 * seconds, TRUE) ? 0U : 1000 * seconds;
85 }
86 #endif
87
88 #ifndef HAVE_USLEEP
89 /* Emulation of Unix usleep().  This has a granularity of
90    milliseconds, but that's ok because:
91
92    a) Wget is only using it with milliseconds [not anymore, but b)
93       still applies];
94
95    b) You can't rely on usleep's granularity anyway.  If a caller
96    expects usleep to respect every microsecond, he's in for a
97    surprise.  */
98
99 int
100 usleep (unsigned long usec)
101 {
102   SleepEx (usec / 1000, TRUE);
103   return 0;
104 }
105 #endif  /* HAVE_USLEEP */
106
107 void
108 windows_main_junk (int *argc, char **argv, char **exec_name)
109 {
110   char *p;
111
112   /* Remove .EXE from filename if it has one.  */
113   *exec_name = xstrdup (*exec_name);
114   p = strrchr (*exec_name, '.');
115   if (p)
116     *p = '\0';
117 }
118 \f
119 /* Winsock stuff. */
120
121 static void
122 ws_cleanup (void)
123 {
124   WSACleanup ();
125   if (pwr_mode)
126      set_sleep_mode (pwr_mode);
127   pwr_mode = 0;
128 }
129
130 static void
131 ws_hangup (void)
132 {
133   log_request_redirect_output ("CTRL+Break");
134 }
135
136 void
137 fork_to_background (void)
138 {
139   /* Whether we arrange our own version of opt.lfilename here.  */
140   int changedp = 0;
141
142   if (!opt.lfilename)
143     {
144       opt.lfilename = unique_name (DEFAULT_LOGFILE, 0);
145       changedp = 1;
146     }
147   printf (_("Continuing in background.\n"));
148   if (changedp)
149     printf (_("Output will be written to `%s'.\n"), opt.lfilename);
150
151   ws_hangup ();
152   if (!windows_nt_p)
153     FreeConsole ();
154 }
155
156 static BOOL WINAPI
157 ws_handler (DWORD dwEvent)
158 {
159   switch (dwEvent)
160     {
161 #ifdef CTRLC_BACKGND
162     case CTRL_C_EVENT:
163 #endif
164 #ifdef CTRLBREAK_BACKGND
165     case CTRL_BREAK_EVENT:
166 #endif
167       fork_to_background ();
168       break;
169     case CTRL_SHUTDOWN_EVENT:
170     case CTRL_CLOSE_EVENT:
171     case CTRL_LOGOFF_EVENT:
172     default:
173       ws_cleanup ();
174       return FALSE;
175     }
176   return TRUE;
177 }
178
179 void
180 ws_changetitle (char *url, int nurl)
181 {
182   char *title_buf;
183   if (!nurl)
184     return;
185
186   title_buf = (char *)alloca (strlen (url) + 20);
187   sprintf (title_buf, "Wget %s%s", url, nurl == 1 ? "" : " ...");
188   SetConsoleTitle (title_buf);
189 }
190
191 char *
192 ws_mypath (void)
193 {
194   static char *wspathsave;
195   char buffer[MAX_PATH];
196   char *ptr;
197
198   if (wspathsave)
199     {
200       return wspathsave;
201     }
202
203   GetModuleFileName (NULL, buffer, MAX_PATH);
204
205   ptr = strrchr (buffer, '\\');
206   if (ptr)
207     {
208       *(ptr + 1) = '\0';
209       wspathsave = (char*) xmalloc (strlen (buffer) + 1);
210       strcpy (wspathsave, buffer);
211     }
212   else
213     wspathsave = NULL;
214   return wspathsave;
215 }
216
217 void
218 ws_help (const char *name)
219 {
220   char *mypath = ws_mypath ();
221
222   if (mypath)
223     {
224       struct stat sbuf;
225       char *buf = (char *)alloca (strlen (mypath) + strlen (name) + 4 + 1);
226       sprintf (buf, "%s%s.HLP", mypath, name);
227       if (stat (buf, &sbuf) == 0) 
228         {
229           printf (_("Starting WinHelp %s\n"), buf);
230           WinHelp (NULL, buf, HELP_INDEX, NULL);
231         }
232       else
233         {
234           printf ("%s: %s\n", buf, strerror (errno));
235         }
236     }
237 }
238
239 void
240 ws_startup (void)
241 {
242   WORD requested;
243   WSADATA data;
244   int err;
245   OSVERSIONINFO os;
246
247   if (GetVersionEx (&os) == TRUE
248       && os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
249     windows_nt_p = 1;
250
251   requested = MAKEWORD (1, 1);
252   err = WSAStartup (requested, &data);
253
254   if (err != 0)
255     {
256       fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
257                exec_name);
258       exit (1);
259     }
260
261   if (data.wVersion < requested)
262     {
263       fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
264                exec_name);
265       WSACleanup ();
266       exit (1);
267     }
268   atexit (ws_cleanup);
269   pwr_mode = set_sleep_mode (0);
270   SetConsoleCtrlHandler (ws_handler, TRUE);
271 }
272
273 /* Replacement utime function for buggy Borland C++Builder 5.5 compiler.
274    (The Borland utime function only works on Windows NT.)  */
275
276 #ifdef HACK_BCC_UTIME_BUG
277 int borland_utime(const char *path, const struct utimbuf *times)
278 {
279   int fd;
280   int res;
281   struct ftime ft;
282   struct tm *ptr_tm;
283
284   if ((fd = open (path, O_RDWR)) < 0)
285     return -1;
286
287   ptr_tm = localtime (&times->modtime);
288   ft.ft_tsec = ptr_tm->tm_sec >> 1;
289   ft.ft_min = ptr_tm->tm_min;
290   ft.ft_hour = ptr_tm->tm_hour;
291   ft.ft_day = ptr_tm->tm_mday;
292   ft.ft_month = ptr_tm->tm_mon + 1;
293   ft.ft_year = ptr_tm->tm_year - 80;
294   res = setftime (fd, &ft);
295   close (fd);
296   return res;
297 }
298 #endif
299
300 /*
301  * Prevent Windows entering sleep/hibernation-mode while wget is doing a lengthy transfer.
302  * Windows does by default not consider network activity in console-programs as activity !
303  * Works on Win-98/ME/2K and up.
304  */
305 static
306 DWORD set_sleep_mode (DWORD mode)
307 {
308   HMODULE mod = LoadLibrary ("kernel32.dll");
309   DWORD (*_SetThreadExecutionState) (DWORD) = NULL;
310   DWORD rc = (DWORD)-1;
311
312   if (mod)
313      (void*)_SetThreadExecutionState = GetProcAddress ((HINSTANCE)mod, "SetThreadExecutionState");
314
315   if (_SetThreadExecutionState)
316     {
317       if (mode == 0)  /* first time */
318          mode = (ES_SYSTEM_REQUIRED | ES_CONTINUOUS);
319       rc = (*_SetThreadExecutionState) (mode);
320     }
321   if (mod)
322      FreeLibrary (mod);
323   DEBUGP (("set_sleep_mode(): mode 0x%08lX, rc 0x%08lX\n", mode, rc));
324   return (rc);
325 }
326