]> sjero.net Git - wget/blob - src/mswindows.c
[svn] Fixes to support out of the box compilation on various Windows compilers.
[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 /* Defined in log.c.  */
61 void log_request_redirect_output PARAMS ((const char *));
62
63 static int windows_nt_p;
64
65
66 #ifndef HAVE_SLEEP
67 /* Emulation of Unix sleep.  */
68
69 unsigned int
70 sleep (unsigned seconds)
71 {
72   return SleepEx (1000 * seconds, TRUE) ? 0U : 1000 * seconds;
73 }
74 #endif
75
76 #ifndef HAVE_USLEEP
77 /* Emulation of Unix usleep().  This has a granularity of
78    milliseconds, but that's ok because:
79
80    a) Wget is only using it with milliseconds [not anymore, but b)
81       still applies];
82
83    b) You can't rely on usleep's granularity anyway.  If a caller
84    expects usleep to respect every microsecond, he's in for a
85    surprise.  */
86
87 int
88 usleep (unsigned long usec)
89 {
90   SleepEx (usec / 1000, TRUE);
91   return 0;
92 }
93 #endif  /* HAVE_USLEEP */
94
95 static char *
96 read_registry (HKEY hkey, char *subkey, char *valuename, char *buf, int *len)
97 {
98   HKEY result;
99   DWORD size = *len;
100   DWORD type = REG_SZ;
101   if (RegOpenKeyEx (hkey, subkey, 0, KEY_READ, &result) != ERROR_SUCCESS)
102     return NULL;
103   if (RegQueryValueEx (result, valuename, NULL, &type, (LPBYTE)buf, &size) != ERROR_SUCCESS)
104     buf = NULL;
105   *len = size;
106   RegCloseKey (result);
107   return buf;
108 }
109
110 void
111 windows_main_junk (int *argc, char **argv, char **exec_name)
112 {
113   char *p;
114
115   /* Remove .EXE from filename if it has one.  */
116   *exec_name = xstrdup (*exec_name);
117   p = strrchr (*exec_name, '.');
118   if (p)
119     *p = '\0';
120 }
121 \f
122 /* Winsock stuff. */
123
124 static void
125 ws_cleanup (void)
126 {
127   WSACleanup ();
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       WSACleanup ();
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   SetConsoleCtrlHandler (ws_handler, TRUE);
270 }
271
272 /* Replacement utime function for buggy Borland C++Builder 5.5 compiler.
273    (The Borland utime function only works on Windows NT.)  */
274
275 #ifdef HACK_BCC_UTIME_BUG
276 int borland_utime(const char *path, const struct utimbuf *times)
277 {
278   int fd;
279   int res;
280   struct ftime ft;
281   struct tm *ptr_tm;
282
283   if ((fd = open (path, O_RDWR)) < 0)
284     return -1;
285
286   ptr_tm = localtime (&times->modtime);
287   ft.ft_tsec = ptr_tm->tm_sec >> 1;
288   ft.ft_min = ptr_tm->tm_min;
289   ft.ft_hour = ptr_tm->tm_hour;
290   ft.ft_day = ptr_tm->tm_mday;
291   ft.ft_month = ptr_tm->tm_mon + 1;
292   ft.ft_year = ptr_tm->tm_year - 80;
293   res = setftime (fd, &ft);
294   close (fd);
295   return res;
296 }
297 #endif