8465cd9c3ff6f4c0032743106c5643a0c66d8588
[platform/upstream/curl.git] / tests / server / util.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22 #include "server_setup.h"
23
24 #ifdef HAVE_SIGNAL_H
25 #include <signal.h>
26 #endif
27 #ifdef HAVE_NETINET_IN_H
28 #include <netinet/in.h>
29 #endif
30 #ifdef _XOPEN_SOURCE_EXTENDED
31 /* This define is "almost" required to build on HPUX 11 */
32 #include <arpa/inet.h>
33 #endif
34 #ifdef HAVE_NETDB_H
35 #include <netdb.h>
36 #endif
37 #ifdef HAVE_SYS_POLL_H
38 #include <sys/poll.h>
39 #elif defined(HAVE_POLL_H)
40 #include <poll.h>
41 #endif
42
43 #define ENABLE_CURLX_PRINTF
44 /* make the curlx header define all printf() functions to use the curlx_*
45    versions instead */
46 #include "curlx.h" /* from the private lib dir */
47 #include "getpart.h"
48 #include "util.h"
49 #include "timeval.h"
50
51 #ifdef USE_WINSOCK
52 #undef  EINTR
53 #define EINTR    4 /* errno.h value */
54 #undef  EINVAL
55 #define EINVAL  22 /* errno.h value */
56 #endif
57
58 #if defined(ENABLE_IPV6) && defined(__MINGW32__)
59 const struct in6_addr in6addr_any = {{ IN6ADDR_ANY_INIT }};
60 #endif
61
62 /* This function returns a pointer to STATIC memory. It converts the given
63  * binary lump to a hex formatted string usable for output in logs or
64  * whatever.
65  */
66 char *data_to_hex(char *data, size_t len)
67 {
68   static char buf[256*3];
69   size_t i;
70   char *optr = buf;
71   char *iptr = data;
72
73   if(len > 255)
74     len = 255;
75
76   for(i=0; i < len; i++) {
77     if((data[i] >= 0x20) && (data[i] < 0x7f))
78       *optr++ = *iptr++;
79     else {
80       snprintf(optr, 4, "%%%02x", *iptr++);
81       optr+=3;
82     }
83   }
84   *optr=0; /* in case no sprintf was used */
85
86   return buf;
87 }
88
89 void logmsg(const char *msg, ...)
90 {
91   va_list ap;
92   char buffer[2048 + 1];
93   FILE *logfp;
94   int error;
95   struct timeval tv;
96   time_t sec;
97   struct tm *now;
98   char timebuf[20];
99   static time_t epoch_offset;
100   static int    known_offset;
101
102   if(!serverlogfile) {
103     fprintf(stderr, "Error: serverlogfile not set\n");
104     return;
105   }
106
107   tv = curlx_tvnow();
108   if(!known_offset) {
109     epoch_offset = time(NULL) - tv.tv_sec;
110     known_offset = 1;
111   }
112   sec = epoch_offset + tv.tv_sec;
113   now = localtime(&sec); /* not thread safe but we don't care */
114
115   snprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld",
116     (int)now->tm_hour, (int)now->tm_min, (int)now->tm_sec, (long)tv.tv_usec);
117
118   va_start(ap, msg);
119   vsnprintf(buffer, sizeof(buffer), msg, ap);
120   va_end(ap);
121
122   logfp = fopen(serverlogfile, "ab");
123   if(logfp) {
124     fprintf(logfp, "%s %s\n", timebuf, buffer);
125     fclose(logfp);
126   }
127   else {
128     error = errno;
129     fprintf(stderr, "fopen() failed with error: %d %s\n",
130             error, strerror(error));
131     fprintf(stderr, "Error opening file: %s\n", serverlogfile);
132     fprintf(stderr, "Msg not logged: %s %s\n", timebuf, buffer);
133   }
134 }
135
136 #ifdef WIN32
137 /* use instead of perror() on generic windows */
138 void win32_perror(const char *msg)
139 {
140   char buf[512];
141   DWORD err = SOCKERRNO;
142
143   if(!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
144                     LANG_NEUTRAL, buf, sizeof(buf), NULL))
145      snprintf(buf, sizeof(buf), "Unknown error %lu (%#lx)", err, err);
146   if(msg)
147     fprintf(stderr, "%s: ", msg);
148   fprintf(stderr, "%s\n", buf);
149 }
150 #endif  /* WIN32 */
151
152 #ifdef USE_WINSOCK
153 void win32_init(void)
154 {
155   WORD wVersionRequested;
156   WSADATA wsaData;
157   int err;
158   wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
159
160   err = WSAStartup(wVersionRequested, &wsaData);
161
162   if(err != 0) {
163     perror("Winsock init failed");
164     logmsg("Error initialising winsock -- aborting");
165     exit(1);
166   }
167
168   if(LOBYTE(wsaData.wVersion) != USE_WINSOCK ||
169      HIBYTE(wsaData.wVersion) != USE_WINSOCK) {
170     WSACleanup();
171     perror("Winsock init failed");
172     logmsg("No suitable winsock.dll found -- aborting");
173     exit(1);
174   }
175 }
176
177 void win32_cleanup(void)
178 {
179   WSACleanup();
180 }
181 #endif  /* USE_WINSOCK */
182
183 /* set by the main code to point to where the test dir is */
184 const char *path=".";
185
186 char *test2file(long testno)
187 {
188   static char filename[256];
189   snprintf(filename, sizeof(filename), TEST_DATA_PATH, path, testno);
190   return filename;
191 }
192
193 /*
194  * Portable function used for waiting a specific amount of ms.
195  * Waiting indefinitely with this function is not allowed, a
196  * zero or negative timeout value will return immediately.
197  *
198  * Return values:
199  *   -1 = system call error, or invalid timeout value
200  *    0 = specified timeout has elapsed
201  */
202 int wait_ms(int timeout_ms)
203 {
204 #if !defined(MSDOS) && !defined(USE_WINSOCK)
205 #ifndef HAVE_POLL_FINE
206   struct timeval pending_tv;
207 #endif
208   struct timeval initial_tv;
209   int pending_ms;
210   int error;
211 #endif
212   int r = 0;
213
214   if(!timeout_ms)
215     return 0;
216   if(timeout_ms < 0) {
217     errno = EINVAL;
218     return -1;
219   }
220 #if defined(MSDOS)
221   delay(timeout_ms);
222 #elif defined(USE_WINSOCK)
223   Sleep(timeout_ms);
224 #else
225   pending_ms = timeout_ms;
226   initial_tv = curlx_tvnow();
227   do {
228 #if defined(HAVE_POLL_FINE)
229     r = poll(NULL, 0, pending_ms);
230 #else
231     pending_tv.tv_sec = pending_ms / 1000;
232     pending_tv.tv_usec = (pending_ms % 1000) * 1000;
233     r = select(0, NULL, NULL, NULL, &pending_tv);
234 #endif /* HAVE_POLL_FINE */
235     if(r != -1)
236       break;
237     error = errno;
238     if(error && (error != EINTR))
239       break;
240     pending_ms = timeout_ms - (int)curlx_tvdiff(curlx_tvnow(), initial_tv);
241     if(pending_ms <= 0)
242       break;
243   } while(r == -1);
244 #endif /* USE_WINSOCK */
245   if(r)
246     r = -1;
247   return r;
248 }
249
250 int write_pidfile(const char *filename)
251 {
252   FILE *pidfile;
253   long pid;
254
255   pid = (long)getpid();
256   pidfile = fopen(filename, "wb");
257   if(!pidfile) {
258     logmsg("Couldn't write pid file: %s %s", filename, strerror(errno));
259     return 0; /* fail */
260   }
261   fprintf(pidfile, "%ld\n", pid);
262   fclose(pidfile);
263   logmsg("Wrote pid %ld to %s", pid, filename);
264   return 1; /* success */
265 }
266
267 void set_advisor_read_lock(const char *filename)
268 {
269   FILE *lockfile;
270   int error = 0;
271   int res;
272
273   do {
274     lockfile = fopen(filename, "wb");
275   } while((lockfile == NULL) && ((error = errno) == EINTR));
276   if(lockfile == NULL) {
277     logmsg("Error creating lock file %s error: %d %s",
278            filename, error, strerror(error));
279     return;
280   }
281
282   do {
283     res = fclose(lockfile);
284   } while(res && ((error = errno) == EINTR));
285   if(res)
286     logmsg("Error closing lock file %s error: %d %s",
287            filename, error, strerror(error));
288 }
289
290 void clear_advisor_read_lock(const char *filename)
291 {
292   int error = 0;
293   int res;
294
295   /*
296   ** Log all removal failures. Even those due to file not existing.
297   ** This allows to detect if unexpectedly the file has already been
298   ** removed by a process different than the one that should do this.
299   */
300
301   do {
302     res = unlink(filename);
303   } while(res && ((error = errno) == EINTR));
304   if(res)
305     logmsg("Error removing lock file %s error: %d %s",
306            filename, error, strerror(error));
307 }
308
309
310 /* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because
311    its behavior is altered by the current locale. */
312 static char raw_toupper(char in)
313 {
314 #if !defined(CURL_DOES_CONVERSIONS)
315   if(in >= 'a' && in <= 'z')
316     return (char)('A' + in - 'a');
317 #else
318   switch(in) {
319   case 'a':
320     return 'A';
321   case 'b':
322     return 'B';
323   case 'c':
324     return 'C';
325   case 'd':
326     return 'D';
327   case 'e':
328     return 'E';
329   case 'f':
330     return 'F';
331   case 'g':
332     return 'G';
333   case 'h':
334     return 'H';
335   case 'i':
336     return 'I';
337   case 'j':
338     return 'J';
339   case 'k':
340     return 'K';
341   case 'l':
342     return 'L';
343   case 'm':
344     return 'M';
345   case 'n':
346     return 'N';
347   case 'o':
348     return 'O';
349   case 'p':
350     return 'P';
351   case 'q':
352     return 'Q';
353   case 'r':
354     return 'R';
355   case 's':
356     return 'S';
357   case 't':
358     return 'T';
359   case 'u':
360     return 'U';
361   case 'v':
362     return 'V';
363   case 'w':
364     return 'W';
365   case 'x':
366     return 'X';
367   case 'y':
368     return 'Y';
369   case 'z':
370     return 'Z';
371   }
372 #endif
373
374   return in;
375 }
376
377 int strncasecompare(const char *first, const char *second, size_t max)
378 {
379   while(*first && *second && max) {
380     if(raw_toupper(*first) != raw_toupper(*second)) {
381       break;
382     }
383     max--;
384     first++;
385     second++;
386   }
387   if(0 == max)
388     return 1; /* they are equal this far */
389
390   return raw_toupper(*first) == raw_toupper(*second);
391 }