Browse code

freshclam builds

aCaB authored on 2009/10/15 09:39:29
Showing 12 changed files
... ...
@@ -166,8 +166,9 @@ static int download(const struct optstruct *opts, const char *datadir, const cha
166 166
     } else {
167 167
 	while(opt) {
168 168
 	    ret = downloadmanager(opts, opt->strarg, datadir, try == maxattempts - 1);
169
+#ifndef _WIN32
169 170
 	    alarm(0);
170
-
171
+#endif
171 172
 	    if(ret == 52 || ret == 54 || ret == 58 || ret == 59) {
172 173
 		if(try < maxattempts - 1) {
173 174
 		    logg("Trying again in 5 secs...\n");
... ...
@@ -199,7 +200,7 @@ int main(int argc, char **argv)
199 199
 	char *pt;
200 200
 	struct optstruct *opts;
201 201
 	const struct optstruct *opt;
202
-#ifndef	C_WINDOWS
202
+#ifndef	_WIN32
203 203
 	struct sigaction sigact;
204 204
 	struct sigaction oldact;
205 205
 #endif
... ...
@@ -297,7 +298,7 @@ int main(int argc, char **argv)
297 297
 	    return 61;
298 298
 	}
299 299
     }
300
-#endif
300
+#endif /* HAVE_PWD_H */
301 301
 
302 302
     /* initialize some important variables */
303 303
 
... ...
@@ -373,7 +374,7 @@ int main(int argc, char **argv)
373 373
 
374 374
     if(optget(opts, "daemon")->enabled) {
375 375
 	    int bigsleep, checks;
376
-#ifndef	C_WINDOWS
376
+#ifndef	_WIN32
377 377
 	    time_t now, wakeup;
378 378
 
379 379
 	memset(&sigact, 0, sizeof(struct sigaction));
... ...
@@ -211,7 +211,7 @@ static int wwwconnect(const char *server, const char *proxy, int pport, char *ip
211 211
 		else
212 212
 			port = 8080;
213 213
 
214
-#ifndef	C_WINDOWS
214
+#ifndef	_WIN32
215 215
 		endservent();
216 216
 #endif
217 217
 	}
... ...
@@ -16,6 +16,9 @@ EndProject
16 16
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libclamunrar", "libclamunrar.vcproj", "{41B2E193-92E3-429C-8DAC-9B287E3D7182}"
17 17
 EndProject
18 18
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "freshclam", "freshclam.vcproj", "{CEA52DD8-0418-42AD-B640-F33CC7C600CE}"
19
+	ProjectSection(ProjectDependencies) = postProject
20
+		{3AD5B16C-340A-40AC-96AD-6017B941A316} = {3AD5B16C-340A-40AC-96AD-6017B941A316}
21
+	EndProjectSection
19 22
 EndProject
20 23
 Global
21 24
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
... ...
@@ -40,6 +43,7 @@ Global
40 40
 		{41B2E193-92E3-429C-8DAC-9B287E3D7182}.Release|Win32.ActiveCfg = Release|Win32
41 41
 		{41B2E193-92E3-429C-8DAC-9B287E3D7182}.Release|Win32.Build.0 = Release|Win32
42 42
 		{CEA52DD8-0418-42AD-B640-F33CC7C600CE}.Debug|Win32.ActiveCfg = Debug|Win32
43
+		{CEA52DD8-0418-42AD-B640-F33CC7C600CE}.Debug|Win32.Build.0 = Debug|Win32
43 44
 		{CEA52DD8-0418-42AD-B640-F33CC7C600CE}.Release|Win32.ActiveCfg = Release|Win32
44 45
 		{CEA52DD8-0418-42AD-B640-F33CC7C600CE}.Release|Win32.Build.0 = Release|Win32
45 46
 	EndGlobalSection
... ...
@@ -188,20 +188,11 @@
188 188
 /* have getaddrinfo() */
189 189
 #define HAVE_GETADDRINFO 1
190 190
 
191
-/* gethostbyname_r takes 3 arguments */
192
-/* #undef HAVE_GETHOSTBYNAME_R_3 */
193
-
194
-/* gethostbyname_r takes 5 arguments */
195
-/* #undef HAVE_GETHOSTBYNAME_R_5 */
196
-
197
-/* gethostbyname_r takes 6 arguments */
198
-#define HAVE_GETHOSTBYNAME_R_6 1
199
-
200 191
 /* Define to 1 if getpagesize() is available */
201 192
 #define HAVE_GETPAGESIZE 1
202 193
 
203 194
 /* Define to 1 if you have the <grp.h> header file. */
204
-#define HAVE_GRP_H 1
195
+/* #undef HAVE_GRP_H */
205 196
 
206 197
 /* iconv() available */
207 198
 /* #undef HAVE_ICONV 1 */
... ...
@@ -313,7 +304,7 @@
313 313
 #define HAVE_RECVMSG 1
314 314
 
315 315
 /* have resolv.h */
316
-#define HAVE_RESOLV_H 1
316
+/* #undef HAVE_RESOLV_H */
317 317
 
318 318
 /* Define signed right shift implementation */
319 319
 #define HAVE_SAR 1
320 320
new file mode 100644
... ...
@@ -0,0 +1,32 @@
0
+/* just a draft for now */
1
+
2
+#if HAVE_CONFIG_H
3
+#include "clamav-config.h"
4
+#endif
5
+
6
+#include "pthread.h"
7
+
8
+BOOL APIENTRY DllMain(HMODULE hm, DWORD why, LPVOID rsrv) {
9
+    WSADATA wsa;
10
+    switch (why) {
11
+    case DLL_PROCESS_ATTACH:
12
+	if(WSAStartup(MAKEWORD(2,2), &wsa))
13
+	    return FALSE;
14
+	return pthread_win32_process_attach_np();
15
+	break;
16
+
17
+    case DLL_THREAD_ATTACH:
18
+	return pthread_win32_thread_attach_np ();
19
+	break;
20
+
21
+    case DLL_THREAD_DETACH:
22
+	return pthread_win32_thread_detach_np ();
23
+	break;
24
+
25
+    case DLL_PROCESS_DETACH:
26
+	WSACleanup();
27
+	pthread_win32_thread_detach_np ();
28
+	return pthread_win32_process_detach_np ();
29
+	break;
30
+    }
31
+}
... ...
@@ -1,4 +1,6 @@
1 1
 #include <winsock2.h>
2
+#include <Ws2tcpip.h>
3
+#include "net.h"
2 4
 #include "w32_errno.h"
3 5
 
4 6
 static void wsock2errno() {
... ...
@@ -187,36 +189,100 @@ static void wsock2errno() {
187 187
     }
188 188
 }
189 189
 
190
-int w32_send(int sockfd, const void *buf, size_t len, int flags) {
191
-    int ret;
192
-    if(WSASend((SOCKET)sockfd, (LPWSABUF)buf, (DWORD)len, (LPDWORD)&ret, (DWORD)flags, NULL, NULL)) {
190
+int w32_socket(int domain, int type, int protocol) {
191
+    SOCKET s = socket(domain, type, protocol);
192
+    if(s == INVALID_SOCKET) {
193 193
 	wsock2errno();
194 194
 	return -1;
195 195
     }
196
-    return ret;
196
+    return (int)s;
197 197
 }
198 198
 
199
-/*
200
-int w32_gethostbyname(const char *name) {
201
-    struct hostent *h = gethostbyname(name);
202
-    h_errno = 0;
203
-    if(!h) {
204
-	switch(WSAGetLastError()) {
205
-	    case WSAHOST_NOT_FOUND:
206
-		*h_errno = HOST_NOT_FOUND;
207
-		break;
208
-	    case WSATRY_AGAIN:
209
-		*h_errno = TRY_AGAIN;
210
-		break;
211
-	    case WSANO_RECOVERY:
212
-		*h_errno = NO_RECOVERY;
213
-		break;
214
-	    case WSANO_DATA:
215
-		*h_errno = NO_DATA;
216
-		break;
217
-	}
199
+int w32_getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen) {
200
+    if(getsockopt((SOCKET)sockfd, level, optname, (char *)optval, optlen) == SOCKET_ERROR) {
201
+	wsock2errno();
202
+	return -1;
203
+    }
204
+    return 0;
205
+}
206
+
207
+int w32_setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) {
208
+    if(setsockopt((SOCKET)sockfd, level, optname, (const char*)optval, optlen) == SOCKET_ERROR) {
209
+	wsock2errno();
210
+	return -1;
211
+    }
212
+    return 0;
213
+}
214
+
215
+int w32_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
216
+    if(bind((SOCKET)sockfd, addr, addrlen) == SOCKET_ERROR) {
217
+	wsock2errno();
218
+	return -1;
218 219
     }
219
-    return h;
220
+    return 0;
220 221
 }
221 222
 
222
-*/
223 223
\ No newline at end of file
224
+int w32_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
225
+    if(connect((SOCKET)sockfd, addr, addrlen)) {
226
+	wsock2errno();
227
+	return -1;
228
+    }
229
+    return 0;
230
+}
231
+
232
+ssize_t w32_send(int sockfd, const void *buf, size_t len, int flags) {
233
+    int ret = recv((SOCKET)sockfd, (const char *)buf, (int)len, flags);
234
+    if(ret == SOCKET_ERROR) {
235
+	wsock2errno();
236
+	return -1;
237
+    }
238
+    return (ssize_t)ret;
239
+}
240
+
241
+ssize_t w32_recv(int sockfd, void *buf, size_t len, int flags) {
242
+    int ret = recv((SOCKET)sockfd, (char *)buf, len, flags);
243
+    if(ret == SOCKET_ERROR) {
244
+	wsock2errno();
245
+	return -1;
246
+    }
247
+    return (ssize_t)ret;
248
+}
249
+
250
+int w32_closesocket(int sockfd) {
251
+    if(closesocket((SOCKET)sockfd) == SOCKET_ERROR) {
252
+	wsock2errno();
253
+	return -1;
254
+    }
255
+    return 0;
256
+}
257
+
258
+struct servent *w32_getservbyname(const char *name, const char *proto) {
259
+    return getservbyname(name, proto);
260
+}
261
+
262
+int w32_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) {
263
+    return getaddrinfo(node, service, hints, res);
264
+}
265
+
266
+void w32_freeaddrinfo(struct addrinfo *res) {
267
+    freeaddrinfo(res);
268
+}
269
+
270
+const char *w32_inet_ntop(int af, const void *src, char *dst, socklen_t size) {
271
+    const char *ret = inet_ntoa(*(struct in_addr *)src);
272
+    if(!ret) wsock2errno();
273
+    return ret;
274
+}
275
+
276
+struct hostent *w32_gethostbyname(const char *name) {
277
+    return gethostbyname(name);
278
+}
279
+
280
+int w32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) {
281
+    int ret = select(nfds, readfds, writefds, exceptfds, timeout);
282
+    if(ret == SOCKET_ERROR) {
283
+	wsock2errno();
284
+	return -1;
285
+    }
286
+    return ret;
287
+}
... ...
@@ -21,6 +21,22 @@
21 21
 #ifndef __NET_H
22 22
 #define __NET_H
23 23
 
24
-int w32_send(int sockfd, const void *buf, size_t len, int flags);
24
+typedef int socklen_t;
25
+typedef int ssize_t;
26
+
27
+int w32_socket(int domain, int type, int protocol);
28
+int w32_getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
29
+int w32_setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
30
+int w32_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
31
+int w32_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
32
+ssize_t w32_send(int sockfd, const void *buf, size_t len, int flags);
33
+ssize_t w32_recv(int sockfd, void *buf, size_t len, int flags);
34
+int w32_closesocket(int sockfd);
35
+struct servent *w32_getservbyname(const char *name, const char *proto);
36
+int w32_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);
37
+void w32_freeaddrinfo(struct addrinfo *res);
38
+const char *w32_inet_ntop(int af, const void *src, char *dst, socklen_t size);
39
+struct hostent *w32_gethostbyname(const char *name);
40
+int w32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
25 41
 
26 42
 #endif
27 43
new file mode 100644
... ...
@@ -0,0 +1,1149 @@
0
+/* Copyright (C) 2002, 2004, 2005, 2007 Free Software Foundation, Inc.
1
+   This file is part of the GNU C Library.
2
+
3
+   This program is free software; you can redistribute it and/or modify
4
+   it under the terms of the GNU General Public License as published by
5
+   the Free Software Foundation; either version 2, or (at your option)
6
+   any later version.
7
+
8
+   This program is distributed in the hope that it will be useful,
9
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
+   GNU General Public License for more details.
12
+
13
+   You should have received a copy of the GNU General Public License along
14
+   with this program; if not, write to the Free Software Foundation,
15
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
16
+
17
+
18
+/* Minor modifications by acab@clamav.net */
19
+
20
+#define strncasecmp strnicmp
21
+#ifndef _LIBC
22
+//# include <config.h>
23
+#endif
24
+
25
+#include <time.h>
26
+
27
+#include <assert.h>
28
+#include <ctype.h>
29
+#ifdef _LIBC
30
+# include <langinfo.h>
31
+#endif
32
+#include <limits.h>
33
+#include <string.h>
34
+//#include <stdbool.h>
35
+
36
+#ifdef _LIBC
37
+# include "../locale/localeinfo.h"
38
+#endif
39
+
40
+#ifndef _LIBC
41
+enum ptime_locale_status { not, loc, raw };
42
+#endif
43
+
44
+struct tm *localtime_r(time_t const *t, struct tm *tp) {
45
+    struct tm *copy = localtime(t);
46
+    if(!copy) return NULL;
47
+    memcpy(tp, copy, sizeof(*tp));
48
+    return tp;
49
+}
50
+
51
+typedef int bool;
52
+
53
+#define match_char(ch1, ch2) if (ch1 != ch2) return NULL
54
+#if defined _LIBC && defined __GNUC__ && __GNUC__ >= 2
55
+# define match_string(cs1, s2) \
56
+  ({ size_t len = strlen (cs1);						      \
57
+     int result = __strncasecmp_l ((cs1), (s2), len, locale) == 0;	      \
58
+     if (result) (s2) += len;						      \
59
+     result; })
60
+#else
61
+/* Oh come on.  Get a reasonable compiler.  */
62
+# define match_string(cs1, s2) \
63
+  (strncasecmp ((cs1), (s2), strlen (cs1)) ? 0 : ((s2) += strlen (cs1), 1))
64
+#endif
65
+/* We intentionally do not use isdigit() for testing because this will
66
+   lead to problems with the wide character version.  */
67
+#define get_number(from, to, n) \
68
+  do {									      \
69
+    int __n = n;							      \
70
+    val = 0;								      \
71
+    while (*rp == ' ')							      \
72
+      ++rp;								      \
73
+    if (*rp < '0' || *rp > '9')						      \
74
+      return NULL;							      \
75
+    do {								      \
76
+      val *= 10;							      \
77
+      val += *rp++ - '0';						      \
78
+    } while (--__n > 0 && val * 10 <= to && *rp >= '0' && *rp <= '9');	      \
79
+    if (val < from || val > to)						      \
80
+      return NULL;							      \
81
+  } while (0)
82
+#ifdef _NL_CURRENT
83
+# define get_alt_number(from, to, n) \
84
+  ({									      \
85
+     __label__ do_normal;						      \
86
+									      \
87
+     if (*decided != raw)						      \
88
+       {								      \
89
+	 val = _nl_parse_alt_digit (&rp HELPER_LOCALE_ARG);		      \
90
+	 if (val == -1 && *decided != loc)				      \
91
+	   {								      \
92
+	     *decided = loc;						      \
93
+	     goto do_normal;						      \
94
+	   }								      \
95
+	if (val < from || val > to)					      \
96
+	  return NULL;							      \
97
+       }								      \
98
+     else								      \
99
+       {								      \
100
+       do_normal:							      \
101
+	 get_number (from, to, n);					      \
102
+       }								      \
103
+    0;									      \
104
+  })
105
+#else
106
+# define get_alt_number(from, to, n) \
107
+  /* We don't have the alternate representation.  */			      \
108
+  get_number(from, to, n)
109
+#endif
110
+#define recursive(new_fmt) \
111
+  (*(new_fmt) != '\0'							      \
112
+   && (rp = __strptime_internal (rp, (new_fmt), tm,			      \
113
+				 decided, era_cnt LOCALE_ARG)) != NULL)
114
+
115
+
116
+#ifdef _LIBC
117
+/* This is defined in locale/C-time.c in the GNU libc.  */
118
+extern const struct locale_data _nl_C_LC_TIME attribute_hidden;
119
+
120
+# define weekday_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (DAY_1)].string)
121
+# define ab_weekday_name \
122
+  (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)].string)
123
+# define month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (MON_1)].string)
124
+# define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string)
125
+# define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string)
126
+# define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_FMT)].string)
127
+# define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string)
128
+# define HERE_PM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (PM_STR)].string)
129
+# define HERE_T_FMT_AMPM \
130
+  (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT_AMPM)].string)
131
+# define HERE_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT)].string)
132
+
133
+# define strncasecmp(s1, s2, n) __strncasecmp (s1, s2, n)
134
+#else
135
+static char const weekday_name[][10] =
136
+  {
137
+    "Sunday", "Monday", "Tuesday", "Wednesday",
138
+    "Thursday", "Friday", "Saturday"
139
+  };
140
+static char const ab_weekday_name[][4] =
141
+  {
142
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
143
+  };
144
+static char const month_name[][10] =
145
+  {
146
+    "January", "February", "March", "April", "May", "June",
147
+    "July", "August", "September", "October", "November", "December"
148
+  };
149
+static char const ab_month_name[][4] =
150
+  {
151
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
152
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
153
+  };
154
+# define HERE_D_T_FMT "%a %b %e %H:%M:%S %Y"
155
+# define HERE_D_FMT "%m/%d/%y"
156
+# define HERE_AM_STR "AM"
157
+# define HERE_PM_STR "PM"
158
+# define HERE_T_FMT_AMPM "%I:%M:%S %p"
159
+# define HERE_T_FMT "%H:%M:%S"
160
+
161
+static const unsigned short int __mon_yday[2][13] =
162
+  {
163
+    /* Normal years.  */
164
+    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
165
+    /* Leap years.  */
166
+    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
167
+  };
168
+#endif
169
+
170
+#if defined _LIBC
171
+/* We use this code also for the extended locale handling where the
172
+   function gets as an additional argument the locale which has to be
173
+   used.  To access the values we have to redefine the _NL_CURRENT
174
+   macro.  */
175
+# define strptime		__strptime_l
176
+# undef _NL_CURRENT
177
+# define _NL_CURRENT(category, item) \
178
+  (current->values[_NL_ITEM_INDEX (item)].string)
179
+# undef _NL_CURRENT_WORD
180
+# define _NL_CURRENT_WORD(category, item) \
181
+  (current->values[_NL_ITEM_INDEX (item)].word)
182
+# define LOCALE_PARAM , locale
183
+# define LOCALE_ARG , locale
184
+# define LOCALE_PARAM_PROTO , __locale_t locale
185
+# define LOCALE_PARAM_DECL __locale_t locale;
186
+# define HELPER_LOCALE_ARG , current
187
+# define ISSPACE(Ch) __isspace_l (Ch, locale)
188
+#else
189
+# define LOCALE_PARAM
190
+# define LOCALE_ARG
191
+# define LOCALE_PARAM_DECL
192
+# define LOCALE_PARAM_PROTO
193
+# define HELPER_LOCALE_ARG
194
+# define ISSPACE(Ch) isspace (Ch)
195
+#endif
196
+
197
+
198
+
199
+
200
+#ifndef __isleap
201
+/* Nonzero if YEAR is a leap year (every 4 years,
202
+   except every 100th isn't, and every 400th is).  */
203
+# define __isleap(year)	\
204
+  ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
205
+#endif
206
+
207
+/* Compute the day of the week.  */
208
+static void
209
+day_of_the_week (struct tm *tm)
210
+{
211
+  /* We know that January 1st 1970 was a Thursday (= 4).  Compute the
212
+     the difference between this data in the one on TM and so determine
213
+     the weekday.  */
214
+  int corr_year = 1900 + tm->tm_year - (tm->tm_mon < 2);
215
+  int wday = (-473
216
+	      + (365 * (tm->tm_year - 70))
217
+	      + (corr_year / 4)
218
+	      - ((corr_year / 4) / 25) + ((corr_year / 4) % 25 < 0)
219
+	      + (((corr_year / 4) / 25) / 4)
220
+	      + __mon_yday[0][tm->tm_mon]
221
+	      + tm->tm_mday - 1);
222
+  tm->tm_wday = ((wday % 7) + 7) % 7;
223
+}
224
+
225
+/* Compute the day of the year.  */
226
+static void
227
+day_of_the_year (struct tm *tm)
228
+{
229
+  tm->tm_yday = (__mon_yday[__isleap (1900 + tm->tm_year)][tm->tm_mon]
230
+		 + (tm->tm_mday - 1));
231
+}
232
+
233
+
234
+#ifdef _LIBC
235
+char *
236
+internal_function
237
+#else
238
+static char *
239
+#endif
240
+__strptime_internal (rp, fmt, tm, decided, era_cnt LOCALE_PARAM)
241
+     const char *rp;
242
+     const char *fmt;
243
+     struct tm *tm;
244
+     enum ptime_locale_status *decided;
245
+     int era_cnt;
246
+     LOCALE_PARAM_DECL
247
+{
248
+#ifdef _LIBC
249
+  struct locale_data *const current = locale->__locales[LC_TIME];
250
+#endif
251
+
252
+  const char *rp_backup;
253
+  int cnt;
254
+  size_t val;
255
+  int have_I, is_pm;
256
+  int century, want_century;
257
+  int want_era;
258
+  int have_wday, want_xday;
259
+  int have_yday;
260
+  int have_mon, have_mday;
261
+  int have_uweek, have_wweek;
262
+  int week_no;
263
+  size_t num_eras;
264
+  struct era_entry *era;
265
+
266
+  have_I = is_pm = 0;
267
+  century = -1;
268
+  want_century = 0;
269
+  want_era = 0;
270
+  era = NULL;
271
+  week_no = 0;
272
+
273
+  have_wday = want_xday = have_yday = have_mon = have_mday = have_uweek = 0;
274
+  have_wweek = 0;
275
+
276
+  while (*fmt != '\0')
277
+    {
278
+      /* A white space in the format string matches 0 more or white
279
+	 space in the input string.  */
280
+      if (ISSPACE (*fmt))
281
+	{
282
+	  while (ISSPACE (*rp))
283
+	    ++rp;
284
+	  ++fmt;
285
+	  continue;
286
+	}
287
+
288
+      /* Any character but `%' must be matched by the same character
289
+	 in the iput string.  */
290
+      if (*fmt != '%')
291
+	{
292
+	  match_char (*fmt++, *rp++);
293
+	  continue;
294
+	}
295
+
296
+      ++fmt;
297
+#ifndef _NL_CURRENT
298
+      /* We need this for handling the `E' modifier.  */
299
+    start_over:
300
+#endif
301
+
302
+      /* Make back up of current processing pointer.  */
303
+      rp_backup = rp;
304
+
305
+      switch (*fmt++)
306
+	{
307
+	case '%':
308
+	  /* Match the `%' character itself.  */
309
+	  match_char ('%', *rp++);
310
+	  break;
311
+	case 'a':
312
+	case 'A':
313
+	  /* Match day of week.  */
314
+	  for (cnt = 0; cnt < 7; ++cnt)
315
+	    {
316
+#ifdef _NL_CURRENT
317
+	      if (*decided !=raw)
318
+		{
319
+		  if (match_string (_NL_CURRENT (LC_TIME, DAY_1 + cnt), rp))
320
+		    {
321
+		      if (*decided == not
322
+			  && strcmp (_NL_CURRENT (LC_TIME, DAY_1 + cnt),
323
+				     weekday_name[cnt]))
324
+			*decided = loc;
325
+		      break;
326
+		    }
327
+		  if (match_string (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), rp))
328
+		    {
329
+		      if (*decided == not
330
+			  && strcmp (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt),
331
+				     ab_weekday_name[cnt]))
332
+			*decided = loc;
333
+		      break;
334
+		    }
335
+		}
336
+#endif
337
+	      if (*decided != loc
338
+		  && (match_string (weekday_name[cnt], rp)
339
+		      || match_string (ab_weekday_name[cnt], rp)))
340
+		{
341
+		  *decided = raw;
342
+		  break;
343
+		}
344
+	    }
345
+	  if (cnt == 7)
346
+	    /* Does not match a weekday name.  */
347
+	    return NULL;
348
+	  tm->tm_wday = cnt;
349
+	  have_wday = 1;
350
+	  break;
351
+	case 'b':
352
+	case 'B':
353
+	case 'h':
354
+	  /* Match month name.  */
355
+	  for (cnt = 0; cnt < 12; ++cnt)
356
+	    {
357
+#ifdef _NL_CURRENT
358
+	      if (*decided !=raw)
359
+		{
360
+		  if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), rp))
361
+		    {
362
+		      if (*decided == not
363
+			  && strcmp (_NL_CURRENT (LC_TIME, MON_1 + cnt),
364
+				     month_name[cnt]))
365
+			*decided = loc;
366
+		      break;
367
+		    }
368
+		  if (match_string (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), rp))
369
+		    {
370
+		      if (*decided == not
371
+			  && strcmp (_NL_CURRENT (LC_TIME, ABMON_1 + cnt),
372
+				     ab_month_name[cnt]))
373
+			*decided = loc;
374
+		      break;
375
+		    }
376
+		}
377
+#endif
378
+	      if (match_string (month_name[cnt], rp)
379
+		  || match_string (ab_month_name[cnt], rp))
380
+		{
381
+		  *decided = raw;
382
+		  break;
383
+		}
384
+	    }
385
+	  if (cnt == 12)
386
+	    /* Does not match a month name.  */
387
+	    return NULL;
388
+	  tm->tm_mon = cnt;
389
+	  want_xday = 1;
390
+	  break;
391
+	case 'c':
392
+	  /* Match locale's date and time format.  */
393
+#ifdef _NL_CURRENT
394
+	  if (*decided != raw)
395
+	    {
396
+	      if (!recursive (_NL_CURRENT (LC_TIME, D_T_FMT)))
397
+		{
398
+		  if (*decided == loc)
399
+		    return NULL;
400
+		  else
401
+		    rp = rp_backup;
402
+		}
403
+	      else
404
+		{
405
+		  if (*decided == not &&
406
+		      strcmp (_NL_CURRENT (LC_TIME, D_T_FMT), HERE_D_T_FMT))
407
+		    *decided = loc;
408
+		  want_xday = 1;
409
+		  break;
410
+		}
411
+	      *decided = raw;
412
+	    }
413
+#endif
414
+	  if (!recursive (HERE_D_T_FMT))
415
+	    return NULL;
416
+	  want_xday = 1;
417
+	  break;
418
+	case 'C':
419
+	  /* Match century number.  */
420
+	match_century:
421
+	  get_number (0, 99, 2);
422
+	  century = val;
423
+	  want_xday = 1;
424
+	  break;
425
+	case 'd':
426
+	case 'e':
427
+	  /* Match day of month.  */
428
+	  get_number (1, 31, 2);
429
+	  tm->tm_mday = val;
430
+	  have_mday = 1;
431
+	  want_xday = 1;
432
+	  break;
433
+	case 'F':
434
+	  if (!recursive ("%Y-%m-%d"))
435
+	    return NULL;
436
+	  want_xday = 1;
437
+	  break;
438
+	case 'x':
439
+#ifdef _NL_CURRENT
440
+	  if (*decided != raw)
441
+	    {
442
+	      if (!recursive (_NL_CURRENT (LC_TIME, D_FMT)))
443
+		{
444
+		  if (*decided == loc)
445
+		    return NULL;
446
+		  else
447
+		    rp = rp_backup;
448
+		}
449
+	      else
450
+		{
451
+		  if (*decided == not
452
+		      && strcmp (_NL_CURRENT (LC_TIME, D_FMT), HERE_D_FMT))
453
+		    *decided = loc;
454
+		  want_xday = 1;
455
+		  break;
456
+		}
457
+	      *decided = raw;
458
+	    }
459
+#endif
460
+	  /* Fall through.  */
461
+	case 'D':
462
+	  /* Match standard day format.  */
463
+	  if (!recursive (HERE_D_FMT))
464
+	    return NULL;
465
+	  want_xday = 1;
466
+	  break;
467
+	case 'k':
468
+	case 'H':
469
+	  /* Match hour in 24-hour clock.  */
470
+	  get_number (0, 23, 2);
471
+	  tm->tm_hour = val;
472
+	  have_I = 0;
473
+	  break;
474
+	case 'l':
475
+	  /* Match hour in 12-hour clock.  GNU extension.  */
476
+	case 'I':
477
+	  /* Match hour in 12-hour clock.  */
478
+	  get_number (1, 12, 2);
479
+	  tm->tm_hour = val % 12;
480
+	  have_I = 1;
481
+	  break;
482
+	case 'j':
483
+	  /* Match day number of year.  */
484
+	  get_number (1, 366, 3);
485
+	  tm->tm_yday = val - 1;
486
+	  have_yday = 1;
487
+	  break;
488
+	case 'm':
489
+	  /* Match number of month.  */
490
+	  get_number (1, 12, 2);
491
+	  tm->tm_mon = val - 1;
492
+	  have_mon = 1;
493
+	  want_xday = 1;
494
+	  break;
495
+	case 'M':
496
+	  /* Match minute.  */
497
+	  get_number (0, 59, 2);
498
+	  tm->tm_min = val;
499
+	  break;
500
+	case 'n':
501
+	case 't':
502
+	  /* Match any white space.  */
503
+	  while (ISSPACE (*rp))
504
+	    ++rp;
505
+	  break;
506
+	case 'p':
507
+	  /* Match locale's equivalent of AM/PM.  */
508
+#ifdef _NL_CURRENT
509
+	  if (*decided != raw)
510
+	    {
511
+	      if (match_string (_NL_CURRENT (LC_TIME, AM_STR), rp))
512
+		{
513
+		  if (strcmp (_NL_CURRENT (LC_TIME, AM_STR), HERE_AM_STR))
514
+		    *decided = loc;
515
+		  break;
516
+		}
517
+	      if (match_string (_NL_CURRENT (LC_TIME, PM_STR), rp))
518
+		{
519
+		  if (strcmp (_NL_CURRENT (LC_TIME, PM_STR), HERE_PM_STR))
520
+		    *decided = loc;
521
+		  is_pm = 1;
522
+		  break;
523
+		}
524
+	      *decided = raw;
525
+	    }
526
+#endif
527
+	  if (!match_string (HERE_AM_STR, rp))
528
+	    {
529
+	      if (match_string (HERE_PM_STR, rp))
530
+		is_pm = 1;
531
+	      else
532
+		return NULL;
533
+	    }
534
+	  break;
535
+	case 'r':
536
+#ifdef _NL_CURRENT
537
+	  if (*decided != raw)
538
+	    {
539
+	      if (!recursive (_NL_CURRENT (LC_TIME, T_FMT_AMPM)))
540
+		{
541
+		  if (*decided == loc)
542
+		    return NULL;
543
+		  else
544
+		    rp = rp_backup;
545
+		}
546
+	      else
547
+		{
548
+		  if (*decided == not &&
549
+		      strcmp (_NL_CURRENT (LC_TIME, T_FMT_AMPM),
550
+			      HERE_T_FMT_AMPM))
551
+		    *decided = loc;
552
+		  break;
553
+		}
554
+	      *decided = raw;
555
+	    }
556
+#endif
557
+	  if (!recursive (HERE_T_FMT_AMPM))
558
+	    return NULL;
559
+	  break;
560
+	case 'R':
561
+	  if (!recursive ("%H:%M"))
562
+	    return NULL;
563
+	  break;
564
+	case 's':
565
+	  {
566
+	    /* The number of seconds may be very high so we cannot use
567
+	       the `get_number' macro.  Instead read the number
568
+	       character for character and construct the result while
569
+	       doing this.  */
570
+	    time_t secs = 0;
571
+	    if (*rp < '0' || *rp > '9')
572
+	      /* We need at least one digit.  */
573
+	      return NULL;
574
+
575
+	    do
576
+	      {
577
+		secs *= 10;
578
+		secs += *rp++ - '0';
579
+	      }
580
+	    while (*rp >= '0' && *rp <= '9');
581
+
582
+	    if (localtime_r (&secs, tm) == NULL)
583
+	      /* Error in function.  */
584
+	      return NULL;
585
+	  }
586
+	  break;
587
+	case 'S':
588
+	  get_number (0, 61, 2);
589
+	  tm->tm_sec = val;
590
+	  break;
591
+	case 'X':
592
+#ifdef _NL_CURRENT
593
+	  if (*decided != raw)
594
+	    {
595
+	      if (!recursive (_NL_CURRENT (LC_TIME, T_FMT)))
596
+		{
597
+		  if (*decided == loc)
598
+		    return NULL;
599
+		  else
600
+		    rp = rp_backup;
601
+		}
602
+	      else
603
+		{
604
+		  if (strcmp (_NL_CURRENT (LC_TIME, T_FMT), HERE_T_FMT))
605
+		    *decided = loc;
606
+		  break;
607
+		}
608
+	      *decided = raw;
609
+	    }
610
+#endif
611
+	  /* Fall through.  */
612
+	case 'T':
613
+	  if (!recursive (HERE_T_FMT))
614
+	    return NULL;
615
+	  break;
616
+	case 'u':
617
+	  get_number (1, 7, 1);
618
+	  tm->tm_wday = val % 7;
619
+	  have_wday = 1;
620
+	  break;
621
+	case 'g':
622
+	  get_number (0, 99, 2);
623
+	  /* XXX This cannot determine any field in TM.  */
624
+	  break;
625
+	case 'G':
626
+	  if (*rp < '0' || *rp > '9')
627
+	    return NULL;
628
+	  /* XXX Ignore the number since we would need some more
629
+	     information to compute a real date.  */
630
+	  do
631
+	    ++rp;
632
+	  while (*rp >= '0' && *rp <= '9');
633
+	  break;
634
+	case 'U':
635
+	  get_number (0, 53, 2);
636
+	  week_no = val;
637
+	  have_uweek = 1;
638
+	  break;
639
+	case 'W':
640
+	  get_number (0, 53, 2);
641
+	  week_no = val;
642
+	  have_wweek = 1;
643
+	  break;
644
+	case 'V':
645
+	  get_number (0, 53, 2);
646
+	  /* XXX This cannot determine any field in TM without some
647
+	     information.  */
648
+	  break;
649
+	case 'w':
650
+	  /* Match number of weekday.  */
651
+	  get_number (0, 6, 1);
652
+	  tm->tm_wday = val;
653
+	  have_wday = 1;
654
+	  break;
655
+	case 'y':
656
+	match_year_in_century:
657
+	  /* Match year within century.  */
658
+	  get_number (0, 99, 2);
659
+	  /* The "Year 2000: The Millennium Rollover" paper suggests that
660
+	     values in the range 69-99 refer to the twentieth century.  */
661
+	  tm->tm_year = val >= 69 ? val : val + 100;
662
+	  /* Indicate that we want to use the century, if specified.  */
663
+	  want_century = 1;
664
+	  want_xday = 1;
665
+	  break;
666
+	case 'Y':
667
+	  /* Match year including century number.  */
668
+	  get_number (0, 9999, 4);
669
+	  tm->tm_year = val - 1900;
670
+	  want_century = 0;
671
+	  want_xday = 1;
672
+	  break;
673
+	case 'Z':
674
+	  /* XXX How to handle this?  */
675
+	  break;
676
+	case 'z':
677
+	  /* We recognize two formats: if two digits are given, these
678
+	     specify hours.  If fours digits are used, minutes are
679
+	     also specified.  */
680
+	  {
681
+	    bool neg;
682
+	    int n;
683
+
684
+	    val = 0;
685
+	    while (*rp == ' ')
686
+	      ++rp;
687
+	    if (*rp != '+' && *rp != '-')
688
+	      return NULL;
689
+	    neg = *rp++ == '-';
690
+	    n = 0;
691
+	    while (n < 4 && *rp >= '0' && *rp <= '9')
692
+	      {
693
+		val = val * 10 + *rp++ - '0';
694
+		++n;
695
+	      }
696
+	    if (n == 2)
697
+	      val *= 100;
698
+	    else if (n != 4)
699
+	      /* Only two or four digits recognized.  */
700
+	      return NULL;
701
+	    else
702
+	      {
703
+		/* We have to convert the minutes into decimal.  */
704
+		if (val % 100 >= 60)
705
+		  return NULL;
706
+		val = (val / 100) * 100 + ((val % 100) * 50) / 30;
707
+	      }
708
+	    if (val > 1200)
709
+	      return NULL;
710
+#if defined _LIBC || HAVE_TM_GMTOFF
711
+	    tm->tm_gmtoff = (val * 3600) / 100;
712
+	    if (neg)
713
+	      tm->tm_gmtoff = -tm->tm_gmtoff;
714
+#endif
715
+	  }
716
+	  break;
717
+	case 'E':
718
+#ifdef _NL_CURRENT
719
+	  switch (*fmt++)
720
+	    {
721
+	    case 'c':
722
+	      /* Match locale's alternate date and time format.  */
723
+	      if (*decided != raw)
724
+		{
725
+		  const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT);
726
+
727
+		  if (*fmt == '\0')
728
+		    fmt = _NL_CURRENT (LC_TIME, D_T_FMT);
729
+
730
+		  if (!recursive (fmt))
731
+		    {
732
+		      if (*decided == loc)
733
+			return NULL;
734
+		      else
735
+			rp = rp_backup;
736
+		    }
737
+		  else
738
+		    {
739
+		      if (strcmp (fmt, HERE_D_T_FMT))
740
+			*decided = loc;
741
+		      want_xday = 1;
742
+		      break;
743
+		    }
744
+		  *decided = raw;
745
+		}
746
+	      /* The C locale has no era information, so use the
747
+		 normal representation.  */
748
+	      if (!recursive (HERE_D_T_FMT))
749
+		return NULL;
750
+	      want_xday = 1;
751
+	      break;
752
+	    case 'C':
753
+	      if (*decided != raw)
754
+		{
755
+		  if (era_cnt >= 0)
756
+		    {
757
+		      era = _nl_select_era_entry (era_cnt HELPER_LOCALE_ARG);
758
+		      if (era != NULL && match_string (era->era_name, rp))
759
+			{
760
+			  *decided = loc;
761
+			  break;
762
+			}
763
+		      else
764
+			return NULL;
765
+		    }
766
+
767
+		  num_eras = _NL_CURRENT_WORD (LC_TIME,
768
+					       _NL_TIME_ERA_NUM_ENTRIES);
769
+		  for (era_cnt = 0; era_cnt < (int) num_eras;
770
+		       ++era_cnt, rp = rp_backup)
771
+		    {
772
+		      era = _nl_select_era_entry (era_cnt
773
+						  HELPER_LOCALE_ARG);
774
+		      if (era != NULL && match_string (era->era_name, rp))
775
+			{
776
+			  *decided = loc;
777
+			  break;
778
+			}
779
+		    }
780
+		  if (era_cnt != (int) num_eras)
781
+		    break;
782
+
783
+		  era_cnt = -1;
784
+		  if (*decided == loc)
785
+		    return NULL;
786
+
787
+		  *decided = raw;
788
+		}
789
+	      /* The C locale has no era information, so use the
790
+		 normal representation.  */
791
+	      goto match_century;
792
+ 	    case 'y':
793
+	      if (*decided != raw)
794
+		{
795
+		  get_number(0, 9999, 4);
796
+		  tm->tm_year = val;
797
+		  want_era = 1;
798
+		  want_xday = 1;
799
+		  want_century = 1;
800
+
801
+		  if (era_cnt >= 0)
802
+		    {
803
+		      assert (*decided == loc);
804
+
805
+		      era = _nl_select_era_entry (era_cnt HELPER_LOCALE_ARG);
806
+		      bool match = false;
807
+		      if (era != NULL)
808
+			{
809
+			  int delta = ((tm->tm_year - era->offset)
810
+				       * era->absolute_direction);
811
+			  match = (delta >= 0
812
+				   && delta < (((int64_t) era->stop_date[0]
813
+						- (int64_t) era->start_date[0])
814
+					       * era->absolute_direction));
815
+			}
816
+		      if (! match)
817
+			return NULL;
818
+
819
+		      break;
820
+		    }
821
+
822
+		  num_eras = _NL_CURRENT_WORD (LC_TIME,
823
+					       _NL_TIME_ERA_NUM_ENTRIES);
824
+		  for (era_cnt = 0; era_cnt < (int) num_eras; ++era_cnt)
825
+		    {
826
+		      era = _nl_select_era_entry (era_cnt
827
+						  HELPER_LOCALE_ARG);
828
+		      if (era != NULL)
829
+			{
830
+			  int delta = ((tm->tm_year - era->offset)
831
+				       * era->absolute_direction);
832
+			  if (delta >= 0
833
+			      && delta < (((int64_t) era->stop_date[0]
834
+					   - (int64_t) era->start_date[0])
835
+					  * era->absolute_direction))
836
+			    {
837
+			      *decided = loc;
838
+			      break;
839
+			    }
840
+			}
841
+		    }
842
+		  if (era_cnt != (int) num_eras)
843
+		    break;
844
+
845
+		  era_cnt = -1;
846
+		  if (*decided == loc)
847
+		    return NULL;
848
+
849
+		  *decided = raw;
850
+		}
851
+
852
+	      goto match_year_in_century;
853
+	    case 'Y':
854
+	      if (*decided != raw)
855
+		{
856
+		  num_eras = _NL_CURRENT_WORD (LC_TIME,
857
+					       _NL_TIME_ERA_NUM_ENTRIES);
858
+		  for (era_cnt = 0; era_cnt < (int) num_eras;
859
+		       ++era_cnt, rp = rp_backup)
860
+		    {
861
+		      era = _nl_select_era_entry (era_cnt HELPER_LOCALE_ARG);
862
+		      if (era != NULL && recursive (era->era_format))
863
+			break;
864
+		    }
865
+		  if (era_cnt == (int) num_eras)
866
+		    {
867
+		      era_cnt = -1;
868
+		      if (*decided == loc)
869
+			return NULL;
870
+		      else
871
+			rp = rp_backup;
872
+		    }
873
+		  else
874
+		    {
875
+		      *decided = loc;
876
+		      era_cnt = -1;
877
+		      break;
878
+		    }
879
+
880
+		  *decided = raw;
881
+		}
882
+	      get_number (0, 9999, 4);
883
+	      tm->tm_year = val - 1900;
884
+	      want_century = 0;
885
+	      want_xday = 1;
886
+	      break;
887
+	    case 'x':
888
+	      if (*decided != raw)
889
+		{
890
+		  const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_FMT);
891
+
892
+		  if (*fmt == '\0')
893
+		    fmt = _NL_CURRENT (LC_TIME, D_FMT);
894
+
895
+		  if (!recursive (fmt))
896
+		    {
897
+		      if (*decided == loc)
898
+			return NULL;
899
+		      else
900
+			rp = rp_backup;
901
+		    }
902
+		  else
903
+		    {
904
+		      if (strcmp (fmt, HERE_D_FMT))
905
+			*decided = loc;
906
+		      break;
907
+		    }
908
+		  *decided = raw;
909
+		}
910
+	      if (!recursive (HERE_D_FMT))
911
+		return NULL;
912
+	      break;
913
+	    case 'X':
914
+	      if (*decided != raw)
915
+		{
916
+		  const char *fmt = _NL_CURRENT (LC_TIME, ERA_T_FMT);
917
+
918
+		  if (*fmt == '\0')
919
+		    fmt = _NL_CURRENT (LC_TIME, T_FMT);
920
+
921
+		  if (!recursive (fmt))
922
+		    {
923
+		      if (*decided == loc)
924
+			return NULL;
925
+		      else
926
+			rp = rp_backup;
927
+		    }
928
+		  else
929
+		    {
930
+		      if (strcmp (fmt, HERE_T_FMT))
931
+			*decided = loc;
932
+		      break;
933
+		    }
934
+		  *decided = raw;
935
+		}
936
+	      if (!recursive (HERE_T_FMT))
937
+		return NULL;
938
+	      break;
939
+	    default:
940
+	      return NULL;
941
+	    }
942
+	  break;
943
+#else
944
+	  /* We have no information about the era format.  Just use
945
+	     the normal format.  */
946
+	  if (*fmt != 'c' && *fmt != 'C' && *fmt != 'y' && *fmt != 'Y'
947
+	      && *fmt != 'x' && *fmt != 'X')
948
+	    /* This is an illegal format.  */
949
+	    return NULL;
950
+
951
+	  goto start_over;
952
+#endif
953
+	case 'O':
954
+	  switch (*fmt++)
955
+	    {
956
+	    case 'd':
957
+	    case 'e':
958
+	      /* Match day of month using alternate numeric symbols.  */
959
+	      get_alt_number (1, 31, 2);
960
+	      tm->tm_mday = val;
961
+	      have_mday = 1;
962
+	      want_xday = 1;
963
+	      break;
964
+	    case 'H':
965
+	      /* Match hour in 24-hour clock using alternate numeric
966
+		 symbols.  */
967
+	      get_alt_number (0, 23, 2);
968
+	      tm->tm_hour = val;
969
+	      have_I = 0;
970
+	      break;
971
+	    case 'I':
972
+	      /* Match hour in 12-hour clock using alternate numeric
973
+		 symbols.  */
974
+	      get_alt_number (1, 12, 2);
975
+	      tm->tm_hour = val % 12;
976
+	      have_I = 1;
977
+	      break;
978
+	    case 'm':
979
+	      /* Match month using alternate numeric symbols.  */
980
+	      get_alt_number (1, 12, 2);
981
+	      tm->tm_mon = val - 1;
982
+	      have_mon = 1;
983
+	      want_xday = 1;
984
+	      break;
985
+	    case 'M':
986
+	      /* Match minutes using alternate numeric symbols.  */
987
+	      get_alt_number (0, 59, 2);
988
+	      tm->tm_min = val;
989
+	      break;
990
+	    case 'S':
991
+	      /* Match seconds using alternate numeric symbols.  */
992
+	      get_alt_number (0, 61, 2);
993
+	      tm->tm_sec = val;
994
+	      break;
995
+	    case 'U':
996
+	      get_alt_number (0, 53, 2);
997
+	      week_no = val;
998
+	      have_uweek = 1;
999
+	      break;
1000
+	    case 'W':
1001
+	      get_alt_number (0, 53, 2);
1002
+	      week_no = val;
1003
+	      have_wweek = 1;
1004
+	      break;
1005
+	    case 'V':
1006
+	      get_alt_number (0, 53, 2);
1007
+	      /* XXX This cannot determine any field in TM without
1008
+		 further information.  */
1009
+	      break;
1010
+	    case 'w':
1011
+	      /* Match number of weekday using alternate numeric symbols.  */
1012
+	      get_alt_number (0, 6, 1);
1013
+	      tm->tm_wday = val;
1014
+	      have_wday = 1;
1015
+	      break;
1016
+	    case 'y':
1017
+	      /* Match year within century using alternate numeric symbols.  */
1018
+	      get_alt_number (0, 99, 2);
1019
+	      tm->tm_year = val >= 69 ? val : val + 100;
1020
+	      want_xday = 1;
1021
+	      break;
1022
+	    default:
1023
+	      return NULL;
1024
+	    }
1025
+	  break;
1026
+	default:
1027
+	  return NULL;
1028
+	}
1029
+    }
1030
+
1031
+  if (have_I && is_pm)
1032
+    tm->tm_hour += 12;
1033
+
1034
+  if (century != -1)
1035
+    {
1036
+      if (want_century)
1037
+	tm->tm_year = tm->tm_year % 100 + (century - 19) * 100;
1038
+      else
1039
+	/* Only the century, but not the year.  Strange, but so be it.  */
1040
+	tm->tm_year = (century - 19) * 100;
1041
+    }
1042
+
1043
+  if (era_cnt != -1)
1044
+    {
1045
+#ifdef _NL_CURRENT
1046
+      era = _nl_select_era_entry (era_cnt HELPER_LOCALE_ARG);
1047
+      if (era == NULL)
1048
+	return NULL;
1049
+      if (want_era)
1050
+	tm->tm_year = (era->start_date[0]
1051
+		       + ((tm->tm_year - era->offset)
1052
+			  * era->absolute_direction));
1053
+      else
1054
+	/* Era start year assumed.  */
1055
+	tm->tm_year = era->start_date[0];
1056
+#endif
1057
+    }
1058
+  else
1059
+    if (want_era)
1060
+      {
1061
+	/* No era found but we have seen an E modifier.  Rectify some
1062
+	   values.  */
1063
+	if (want_century && century == -1 && tm->tm_year < 69)
1064
+	  tm->tm_year += 100;
1065
+      }
1066
+
1067
+  if (want_xday && !have_wday)
1068
+    {
1069
+      if ( !(have_mon && have_mday) && have_yday)
1070
+	{
1071
+	  /* We don't have tm_mon and/or tm_mday, compute them.  */
1072
+	  int t_mon = 0;
1073
+	  while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon] <= tm->tm_yday)
1074
+	      t_mon++;
1075
+	  if (!have_mon)
1076
+	      tm->tm_mon = t_mon - 1;
1077
+	  if (!have_mday)
1078
+	      tm->tm_mday =
1079
+		(tm->tm_yday
1080
+		 - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1);
1081
+	}
1082
+      day_of_the_week (tm);
1083
+    }
1084
+
1085
+  if (want_xday && !have_yday)
1086
+    day_of_the_year (tm);
1087
+
1088
+  if ((have_uweek || have_wweek) && have_wday)
1089
+    {
1090
+      int save_wday = tm->tm_wday;
1091
+      int save_mday = tm->tm_mday;
1092
+      int save_mon = tm->tm_mon;
1093
+      int w_offset = have_uweek ? 0 : 1;
1094
+
1095
+      tm->tm_mday = 1;
1096
+      tm->tm_mon = 0;
1097
+      day_of_the_week (tm);
1098
+      if (have_mday)
1099
+	tm->tm_mday = save_mday;
1100
+      if (have_mon)
1101
+	tm->tm_mon = save_mon;
1102
+
1103
+      if (!have_yday)
1104
+	tm->tm_yday = ((7 - (tm->tm_wday - w_offset)) % 7
1105
+		       + (week_no - 1) *7
1106
+		       + save_wday - w_offset);
1107
+
1108
+      if (!have_mday || !have_mon)
1109
+	{
1110
+	  int t_mon = 0;
1111
+	  while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon]
1112
+		 <= tm->tm_yday)
1113
+	    t_mon++;
1114
+	  if (!have_mon)
1115
+	    tm->tm_mon = t_mon - 1;
1116
+	  if (!have_mday)
1117
+	      tm->tm_mday =
1118
+		(tm->tm_yday
1119
+		 - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1);
1120
+	}
1121
+
1122
+      tm->tm_wday = save_wday;
1123
+    }
1124
+
1125
+  return (char *) rp;
1126
+}
1127
+
1128
+
1129
+char *
1130
+strptime (buf, format, tm LOCALE_PARAM)
1131
+     const char *buf;
1132
+     const char *format;
1133
+     struct tm *tm;
1134
+     LOCALE_PARAM_DECL
1135
+{
1136
+  enum ptime_locale_status decided;
1137
+
1138
+#ifdef _NL_CURRENT
1139
+  decided = not;
1140
+#else
1141
+  decided = raw;
1142
+#endif
1143
+  return __strptime_internal (buf, format, tm, &decided, -1 LOCALE_ARG);
1144
+}
1145
+
1146
+#ifdef _LIBC
1147
+weak_alias (__strptime_l, strptime_l)
1148
+#endif
... ...
@@ -205,6 +205,42 @@
205 205
 				RelativePath="..\freshclam\notify.c"
206 206
 				>
207 207
 			</File>
208
+			<Filter
209
+				Name="shared"
210
+				>
211
+				<File
212
+					RelativePath="..\shared\cdiff.c"
213
+					>
214
+				</File>
215
+				<File
216
+					RelativePath="..\shared\getopt.c"
217
+					>
218
+				</File>
219
+				<File
220
+					RelativePath="..\shared\misc.c"
221
+					>
222
+				</File>
223
+				<File
224
+					RelativePath="..\shared\optparser.c"
225
+					>
226
+				</File>
227
+				<File
228
+					RelativePath="..\shared\output.c"
229
+					>
230
+				</File>
231
+				<File
232
+					RelativePath="..\shared\tar.c"
233
+					>
234
+				</File>
235
+			</Filter>
236
+			<Filter
237
+				Name="compat"
238
+				>
239
+				<File
240
+					RelativePath=".\compat\strptime.c"
241
+					>
242
+				</File>
243
+			</Filter>
208 244
 		</Filter>
209 245
 		<Filter
210 246
 			Name="Header Files"
... ...
@@ -14,6 +14,9 @@ EXPORTS cl_scandesc
14 14
 EXPORTS cl_scanfile
15 15
 EXPORTS cl_cvdfree
16 16
 EXPORTS cl_cvdhead
17
+EXPORTS cl_retflevel
18
+EXPORTS cl_cvdparse
19
+EXPORTS cl_cvdverify
17 20
 
18 21
 ; cli_stuff - should be mangled or exported by ordinal only
19 22
 EXPORTS cli_gentemp
... ...
@@ -22,17 +25,49 @@ EXPORTS cli_regcomp
22 22
 EXPORTS cli_regexec
23 23
 EXPORTS cli_regfree
24 24
 EXPORTS cli_ctime
25
+EXPORTS cli_rmdirs
26
+EXPORTS cli_isnumber
27
+EXPORTS cli_strtok
28
+EXPORTS cli_cvdunpack
29
+EXPORTS cli_decodesig
30
+EXPORTS cli_chomp
25 31
 
26 32
 ; shared stuff - to be either double compiled into the tools or treated like cli_xxx
27
-EXPORTS gettimeofday
28 33
 EXPORTS opendir
29 34
 EXPORTS readdir
30 35
 EXPORTS closedir
31 36
 EXPORTS snprintf
37
+EXPORTS mp_init
38
+EXPORTS mp_read_radix
39
+EXPORTS mp_clear
40
+EXPORTS sha256_init
41
+EXPORTS sha256_update
42
+EXPORTS sha256_final
43
+EXPORTS gzopen
44
+EXPORTS gzgets
45
+EXPORTS gzdopen
46
+EXPORTS gzclose
47
+EXPORTS gzwrite
32 48
 
33 49
 ; winsock - bridging for now
34 50
 EXPORTS htonl
35 51
 EXPORTS htons
36
-EXPORTS w32_send
37
-EXPORTS select
38
-EXPORTS gethostbyname
52
+EXPORTS ntohs
53
+EXPORTS gettimeofday
54
+EXPORTS pthread_mutex_lock
55
+EXPORTS pthread_mutex_unlock
56
+
57
+EXPORTS w32_socket
58
+EXPORTS w32_getsockopt
59
+EXPORTS w32_setsockopt
60
+EXPORTS w32_bind
61
+EXPORTS w32_connect
62
+EXPORTS w32_send
63
+EXPORTS w32_recv
64
+EXPORTS w32_closesocket
65
+EXPORTS w32_getservbyname
66
+EXPORTS w32_getaddrinfo
67
+EXPORTS w32_freeaddrinfo
68
+EXPORTS w32_inet_ntop
69
+EXPORTS w32_gethostbyname
70
+EXPORTS w32_select
... ...
@@ -42,7 +42,7 @@
42 42
 				Name="VCCLCompilerTool"
43 43
 				Optimization="0"
44 44
 				AdditionalIncludeDirectories="&quot;$(SolutionDir)&quot;;&quot;$(SolutionDir)..\libclamav&quot;;&quot;$(SolutionDir)compat&quot;;&quot;$(SolutionDir)3rdparty\zlib&quot;;&quot;$(SolutionDir)3rdparty\pthreads&quot;;&quot;$(SolutionDir)3rdparty\bzip2&quot;;&quot;$(SolutionDir)..&quot;"
45
-				PreprocessorDefinitions="WIN32_LEAN_AND_MEAN;HAVE_CONFIG_H"
45
+				PreprocessorDefinitions="WIN32_LEAN_AND_MEAN;HAVE_CONFIG_H;PTW32_STATIC_LIB"
46 46
 				MinimalRebuild="true"
47 47
 				BasicRuntimeChecks="3"
48 48
 				RuntimeLibrary="3"
... ...
@@ -121,7 +121,7 @@
121 121
 				Optimization="2"
122 122
 				EnableIntrinsicFunctions="true"
123 123
 				AdditionalIncludeDirectories="&quot;$(SolutionDir)&quot;;&quot;$(SolutionDir)..\libclamav&quot;;&quot;$(SolutionDir)compat&quot;;&quot;$(SolutionDir)3rdparty\zlib&quot;;&quot;$(SolutionDir)3rdparty\pthreads&quot;;&quot;$(SolutionDir)3rdparty\bzip2&quot;;&quot;$(SolutionDir)..&quot;"
124
-				PreprocessorDefinitions="WIN32_LEAN_AND_MEAN;HAVE_CONFIG_H"
124
+				PreprocessorDefinitions="WIN32_LEAN_AND_MEAN;HAVE_CONFIG_H;PTW32_STATIC_LIB"
125 125
 				RuntimeLibrary="2"
126 126
 				BufferSecurityCheck="false"
127 127
 				EnableFunctionLevelLinking="true"
... ...
@@ -776,6 +776,10 @@
776 776
 					>
777 777
 				</File>
778 778
 				<File
779
+					RelativePath=".\compat\libclamav_main.c"
780
+					>
781
+				</File>
782
+				<File
779 783
 					RelativePath=".\compat\ltdl.c"
780 784
 					>
781 785
 				</File>
... ...
@@ -8,26 +8,41 @@
8 8
 #include <io.h>
9 9
 #include <direct.h>
10 10
 #include <Ws2tcpip.h>
11
+#include <process.h>
11 12
 
12 13
 #include "gettimeofday.h"
13 14
 #include "snprintf.h"
14 15
 #include "net.h"
16
+#include "w32_errno.h"
15 17
 
16
-typedef int ssize_t;
17 18
 typedef unsigned short mode_t;
19
+
18 20
 #define strcasecmp lstrcmpi
19 21
 #define strncasecmp strnicmp
20 22
 #define mkdir(path, mode) mkdir(path)
21 23
 #define lstat stat
24
+#define sleep(sex) Sleep(sex)
25
+#define getuid() 0
26
+#define getgid() 0
27
+
28
+char *strptime(const char *s, const char *format, struct tm *tm);
22 29
 
23 30
 #define socket w32_socket
31
+#define getsockopt w32_getsockopt
32
+#define setsockopt w32_setsockopt
33
+#define bind w32_bind
24 34
 #define connect w32_connect
25 35
 #define send w32_send
26
-//#define getsockopt(sock, lvl, name, val, len) getsockopt(sock, lvl, name, (char *)(val), len)
36
+#define recv w32_recv
37
+#define closesocket w32_closesocket
38
+#define getservbyname w32_getservbyname
39
+#define getaddrinfo w32_getaddrinfo
40
+#define freeaddrinfo w32_freeaddrinfo
41
+#define inet_ntop w32_inet_ntop
42
+#define gethostbyname w32_gethostbyname
43
+#define select w32_select
27 44
 
28
-/* FIXME: need to wrap all win32 and winsock functions and map
29
-    (WSA)GetLastError to errno */
30
-#define EWOULDBLOCK EAGAIN
45
+#define getpid GetCurrentProcessId
31 46
 
32 47
 #define PATH_MAX 32767
33 48