]> sjero.net Git - wget/blob - src/mswindows.c
[svn] Fix for Borland's broken (on Win9X) `utime' function.
[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 /* #### Someone please document what these functions do!  */
21
22 #include <config.h>
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <winsock.h>
27 #include <string.h>
28 #include <assert.h>
29 #include <errno.h>
30
31 #ifdef HACK_BCC_UTIME_BUG
32 # include <io.h>
33 # include <fcntl.h>
34 # ifdef HAVE_UTIME_H
35 #  include <utime.h>
36 # endif
37 # ifdef HAVE_SYS_UTIME_H
38 #  include <sys/utime.h>
39 # endif
40 #endif
41
42 #include "wget.h"
43 #include "utils.h"
44 #include "url.h"
45
46 #ifndef errno
47 extern int errno;
48 #endif
49
50 /* Defined in log.c.  */
51 void log_request_redirect_output PARAMS ((const char *));
52
53 static int windows_nt_p;
54
55
56 /* Emulation of Unix sleep.  */
57
58 unsigned int
59 sleep (unsigned seconds)
60 {
61   return SleepEx (1000 * seconds, TRUE) ? 0U : 1000 * seconds;
62 }
63
64 /* Emulation of Unix usleep().  This has a granularity of
65    milliseconds, but that's ok because:
66
67    a) Wget is only using it with milliseconds;
68
69    b) You can't rely on usleep's granularity anyway.  If a caller
70    expects usleep to respect every microsecond, he's in for a
71    surprise.  */
72
73 int
74 usleep (unsigned long usec)
75 {
76   SleepEx (usec / 1000, TRUE);
77   return 0;
78 }
79
80 static char *
81 read_registry (HKEY hkey, char *subkey, char *valuename, char *buf, int *len)
82 {
83   HKEY result;
84   DWORD size = *len;
85   DWORD type = REG_SZ;
86   if (RegOpenKeyEx (hkey, subkey, NULL, KEY_READ, &result) != ERROR_SUCCESS)
87     return NULL;
88   if (RegQueryValueEx (result, valuename, NULL, &type, buf, &size) != ERROR_SUCCESS)
89     buf = NULL;
90   *len = size;
91   RegCloseKey (result);
92   return buf;
93 }
94
95 void
96 windows_main_junk (int *argc, char **argv, char **exec_name)
97 {
98   char *p;
99
100   /* Remove .EXE from filename if it has one.  */
101   *exec_name = xstrdup (*exec_name);
102   p = strrchr (*exec_name, '.');
103   if (p)
104     *p = '\0';
105 }
106 \f
107 /* Winsock stuff. */
108
109 static void
110 ws_cleanup (void)
111 {
112   WSACleanup ();
113 }
114
115 static void
116 ws_hangup (void)
117 {
118   log_request_redirect_output ("CTRL+Break");
119 }
120
121 void
122 fork_to_background (void)
123 {
124   /* Whether we arrange our own version of opt.lfilename here.  */
125   int changedp = 0;
126
127   if (!opt.lfilename)
128     {
129       opt.lfilename = unique_name (DEFAULT_LOGFILE);
130       changedp = 1;
131     }
132   printf (_("Continuing in background.\n"));
133   if (changedp)
134     printf (_("Output will be written to `%s'.\n"), opt.lfilename);
135
136   ws_hangup ();
137   if (!windows_nt_p)
138     FreeConsole ();
139 }
140
141 static BOOL WINAPI
142 ws_handler (DWORD dwEvent)
143 {
144   switch (dwEvent)
145     {
146 #ifdef CTRLC_BACKGND
147     case CTRL_C_EVENT:
148 #endif
149 #ifdef CTRLBREAK_BACKGND
150     case CTRL_BREAK_EVENT:
151 #endif
152       fork_to_background ();
153       break;
154     case CTRL_SHUTDOWN_EVENT:
155     case CTRL_CLOSE_EVENT:
156     case CTRL_LOGOFF_EVENT:
157     default:
158       WSACleanup ();
159       return FALSE;
160     }
161   return TRUE;
162 }
163
164 void
165 ws_changetitle (char *url, int nurl)
166 {
167   char *title_buf;
168   if (!nurl)
169     return;
170
171   title_buf = (char *)alloca (strlen (url) + 20);
172   sprintf (title_buf, "Wget %s%s", url, nurl == 1 ? "" : " ...");
173   SetConsoleTitle (title_buf);
174 }
175
176 char *
177 ws_mypath (void)
178 {
179   static char *wspathsave;
180   char buffer[MAX_PATH];
181   char *ptr;
182
183   if (wspathsave)
184     {
185       return wspathsave;
186     }
187
188   GetModuleFileName (NULL, buffer, MAX_PATH);
189
190   ptr = strrchr (buffer, '\\');
191   if (ptr)
192     {
193       *(ptr + 1) = '\0';
194       wspathsave = (char*) xmalloc (strlen (buffer) + 1);
195       strcpy (wspathsave, buffer);
196     }
197   else
198     wspathsave = NULL;
199   return wspathsave;
200 }
201
202 void
203 ws_help (const char *name)
204 {
205   char *mypath = ws_mypath ();
206
207   if (mypath)
208     {
209       struct stat sbuf;
210       char *buf = (char *)alloca (strlen (mypath) + strlen (name) + 4 + 1);
211       sprintf (buf, "%s%s.HLP", mypath, name);
212       if (stat (buf, &sbuf) == 0) 
213         {
214           printf (_("Starting WinHelp %s\n"), buf);
215           WinHelp (NULL, buf, HELP_INDEX, NULL);
216         }
217       else
218         {
219           printf ("%s: %s\n", buf, strerror (errno));
220         }
221     }
222 }
223
224 void
225 ws_startup (void)
226 {
227   WORD requested;
228   WSADATA data;
229   int err;
230   OSVERSIONINFO os;
231
232   if (GetVersionEx (&os) == TRUE
233       && os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
234     windows_nt_p = 1;
235
236   requested = MAKEWORD (1, 1);
237   err = WSAStartup (requested, &data);
238
239   if (err != 0)
240     {
241       fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
242                exec_name);
243       exit (1);
244     }
245
246   if (data.wVersion < requested)
247     {
248       fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
249                exec_name);
250       WSACleanup ();
251       exit (1);
252     }
253   atexit (ws_cleanup);
254   SetConsoleCtrlHandler (ws_handler, TRUE);
255 }
256
257 /* Replacement utime function for buggy Borland C++Builder 5.5 compiler.
258    (The Borland utime function only works on Windows NT.)  */
259
260 #ifdef HACK_BCC_UTIME_BUG
261 int borland_utime(const char *path, const struct utimbuf *times)
262 {
263   int fd;
264   int res;
265   struct ftime ft;
266   struct tm *ptr_tm;
267
268   if ((fd = open (path, O_RDWR)) < 0)
269     return -1;
270
271   ptr_tm = localtime (&times->modtime);
272   ft.ft_tsec = ptr_tm->tm_sec >> 1;
273   ft.ft_min = ptr_tm->tm_min;
274   ft.ft_hour = ptr_tm->tm_hour;
275   ft.ft_day = ptr_tm->tm_mday;
276   ft.ft_month = ptr_tm->tm_mon + 1;
277   ft.ft_year = ptr_tm->tm_year - 80;
278   res = setftime (fd, &ft);
279   close (fd);
280   return res;
281 }
282 #endif