]> sjero.net Git - wget/blob - src/mswindows.c
[svn] Display percentage in title bar.
[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 #include <math.h>
41
42 #ifdef HACK_BCC_UTIME_BUG
43 # include <io.h>
44 # include <fcntl.h>
45 # ifdef HAVE_UTIME_H
46 #  include <utime.h>
47 # endif
48 # ifdef HAVE_SYS_UTIME_H
49 #  include <sys/utime.h>
50 # endif
51 #endif
52
53 #include "wget.h"
54 #include "utils.h"
55 #include "url.h"
56
57 #ifndef errno
58 extern int errno;
59 #endif
60
61 #ifndef ES_SYSTEM_REQUIRED
62 #define ES_SYSTEM_REQUIRED  0x00000001
63 #endif
64
65 #ifndef ES_CONTINUOUS
66 #define ES_CONTINUOUS       0x80000000
67 #endif
68
69
70 /* Defined in log.c.  */
71 void log_request_redirect_output PARAMS ((const char *));
72
73 static DWORD set_sleep_mode (DWORD mode);
74
75 static DWORD pwr_mode = 0;
76 static int windows_nt_p;
77
78 #ifndef HAVE_SLEEP
79
80 /* Emulation of Unix sleep.  */
81
82 unsigned int
83 sleep (unsigned seconds)
84 {
85   return SleepEx (1000 * seconds, TRUE) ? 0U : 1000 * seconds;
86 }
87 #endif
88
89 #ifndef HAVE_USLEEP
90 /* Emulation of Unix usleep().  This has a granularity of
91    milliseconds, but that's ok because:
92
93    a) Wget is only using it with milliseconds [not anymore, but b)
94       still applies];
95
96    b) You can't rely on usleep's granularity anyway.  If a caller
97    expects usleep to respect every microsecond, he's in for a
98    surprise.  */
99
100 int
101 usleep (unsigned long usec)
102 {
103   SleepEx (usec / 1000, TRUE);
104   return 0;
105 }
106 #endif  /* HAVE_USLEEP */
107
108 void
109 windows_main_junk (int *argc, char **argv, char **exec_name)
110 {
111   char *p;
112
113   /* Remove .EXE from filename if it has one.  */
114   *exec_name = xstrdup (*exec_name);
115   p = strrchr (*exec_name, '.');
116   if (p)
117     *p = '\0';
118 }
119 \f
120 /* Winsock stuff. */
121
122 static void
123 ws_cleanup (void)
124 {
125   WSACleanup ();
126   if (pwr_mode)
127      set_sleep_mode (pwr_mode);
128   pwr_mode = 0;
129 }
130
131 static void
132 ws_hangup (void)
133 {
134   log_request_redirect_output ("CTRL+Break");
135 }
136
137 void
138 fork_to_background (void)
139 {
140   /* Whether we arrange our own version of opt.lfilename here.  */
141   int changedp = 0;
142
143   if (!opt.lfilename)
144     {
145       opt.lfilename = unique_name (DEFAULT_LOGFILE, 0);
146       changedp = 1;
147     }
148   printf (_("Continuing in background.\n"));
149   if (changedp)
150     printf (_("Output will be written to `%s'.\n"), opt.lfilename);
151
152   ws_hangup ();
153   if (!windows_nt_p)
154     FreeConsole ();
155 }
156
157 static BOOL WINAPI
158 ws_handler (DWORD dwEvent)
159 {
160   switch (dwEvent)
161     {
162 #ifdef CTRLC_BACKGND
163     case CTRL_C_EVENT:
164 #endif
165 #ifdef CTRLBREAK_BACKGND
166     case CTRL_BREAK_EVENT:
167 #endif
168       fork_to_background ();
169       break;
170     case CTRL_SHUTDOWN_EVENT:
171     case CTRL_CLOSE_EVENT:
172     case CTRL_LOGOFF_EVENT:
173     default:
174       ws_cleanup ();
175       return FALSE;
176     }
177   return TRUE;
178 }
179
180 static char *title_buf = NULL;
181 static char *curr_url  = NULL;
182 static int   num_urls  = 0;
183
184 void
185 ws_changetitle (const char *url, int nurl)
186 {
187   if (!nurl)
188     return;
189
190   num_urls = nurl;
191   if (title_buf)
192      xfree(title_buf);
193   if (curr_url)
194      xfree(curr_url);
195   title_buf = (char *)xmalloc (strlen (url) + 20);
196   curr_url = xstrdup(url);
197   sprintf(title_buf, "Wget %s%s", url, nurl == 1 ? "" : " ...");
198   SetConsoleTitle(title_buf);
199 }
200
201 void
202 ws_percenttitle (double percent)
203 {
204   if (num_urls == 1 && title_buf && curr_url && fabs(percent) <= 100.0)
205     {
206       sprintf (title_buf, "Wget [%.1f%%] %s", percent, curr_url);
207       SetConsoleTitle (title_buf);
208     }
209 }
210
211 char *
212 ws_mypath (void)
213 {
214   static char *wspathsave = NULL;
215   char buffer[MAX_PATH];
216   char *ptr;
217
218   if (wspathsave)
219     {
220       return wspathsave;
221     }
222
223   if (GetModuleFileName (NULL, buffer, MAX_PATH) &&
224       (ptr = strrchr (buffer, PATH_SEPARATOR)) != NULL)
225     {
226       *(ptr + 1) = '\0';
227       wspathsave = xstrdup (buffer);
228     }
229   else
230     wspathsave = NULL;
231   return wspathsave;
232 }
233
234 void
235 ws_help (const char *name)
236 {
237   char *mypath = ws_mypath ();
238
239   if (mypath)
240     {
241       struct stat sbuf;
242       char *buf = (char *)alloca (strlen (mypath) + strlen (name) + 4 + 1);
243       sprintf (buf, "%s%s.HLP", mypath, name);
244       if (stat (buf, &sbuf) == 0) 
245         {
246           printf (_("Starting WinHelp %s\n"), buf);
247           WinHelp (NULL, buf, HELP_INDEX, NULL);
248         }
249       else
250         {
251           printf ("%s: %s\n", buf, strerror (errno));
252         }
253     }
254 }
255
256 void
257 ws_startup (void)
258 {
259   WORD requested;
260   WSADATA data;
261   int err;
262   OSVERSIONINFO os;
263
264   if (GetVersionEx (&os) == TRUE
265       && os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
266     windows_nt_p = 1;
267
268   requested = MAKEWORD (1, 1);
269   err = WSAStartup (requested, &data);
270
271   if (err != 0)
272     {
273       fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
274                exec_name);
275       exit (1);
276     }
277
278   if (data.wVersion < requested)
279     {
280       fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
281                exec_name);
282       WSACleanup ();
283       exit (1);
284     }
285   atexit (ws_cleanup);
286   pwr_mode = set_sleep_mode (0);
287   SetConsoleCtrlHandler (ws_handler, TRUE);
288 }
289
290 /* Replacement utime function for buggy Borland C++Builder 5.5 compiler.
291    (The Borland utime function only works on Windows NT.)  */
292
293 #ifdef HACK_BCC_UTIME_BUG
294 int borland_utime(const char *path, const struct utimbuf *times)
295 {
296   int fd;
297   int res;
298   struct ftime ft;
299   struct tm *ptr_tm;
300
301   if ((fd = open (path, O_RDWR)) < 0)
302     return -1;
303
304   ptr_tm = localtime (&times->modtime);
305   ft.ft_tsec = ptr_tm->tm_sec >> 1;
306   ft.ft_min = ptr_tm->tm_min;
307   ft.ft_hour = ptr_tm->tm_hour;
308   ft.ft_day = ptr_tm->tm_mday;
309   ft.ft_month = ptr_tm->tm_mon + 1;
310   ft.ft_year = ptr_tm->tm_year - 80;
311   res = setftime (fd, &ft);
312   close (fd);
313   return res;
314 }
315 #endif
316
317 /*
318  * Prevent Windows entering sleep/hibernation-mode while wget is doing a lengthy transfer.
319  * Windows does by default not consider network activity in console-programs as activity !
320  * Works on Win-98/ME/2K and up.
321  */
322 static
323 DWORD set_sleep_mode (DWORD mode)
324 {
325   HMODULE mod = LoadLibrary ("kernel32.dll");
326   DWORD (*_SetThreadExecutionState) (DWORD) = NULL;
327   DWORD rc = (DWORD)-1;
328
329   if (mod)
330      (void*)_SetThreadExecutionState = GetProcAddress ((HINSTANCE)mod, "SetThreadExecutionState");
331
332   if (_SetThreadExecutionState)
333     {
334       if (mode == 0)  /* first time */
335          mode = (ES_SYSTEM_REQUIRED | ES_CONTINUOUS);
336       rc = (*_SetThreadExecutionState) (mode);
337     }
338   if (mod)
339      FreeLibrary (mod);
340   DEBUGP (("set_sleep_mode(): mode 0x%08lX, rc 0x%08lX\n", mode, rc));
341   return (rc);
342 }
343