06f3ce10de483126e29d80212a8d2ca03609fbd9
[platform/upstream/curl.git] / tests / server / util.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2013, 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 http://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       sprintf(optr, "%%%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
171     WSACleanup();
172     perror("Winsock init failed");
173     logmsg("No suitable winsock.dll found -- aborting");
174     exit(1);
175   }
176 }
177
178 void win32_cleanup(void)
179 {
180   WSACleanup();
181 }
182 #endif  /* USE_WINSOCK */
183
184 /* set by the main code to point to where the test dir is */
185 const char *path=".";
186
187 char *test2file(long testno)
188 {
189   static char filename[256];
190   snprintf(filename, sizeof(filename), TEST_DATA_PATH, path, testno);
191   return filename;
192 }
193
194 /*
195  * Portable function used for waiting a specific amount of ms.
196  * Waiting indefinitely with this function is not allowed, a
197  * zero or negative timeout value will return immediately.
198  *
199  * Return values:
200  *   -1 = system call error, or invalid timeout value
201  *    0 = specified timeout has elapsed
202  */
203 int wait_ms(int timeout_ms)
204 {
205 #if !defined(MSDOS) && !defined(USE_WINSOCK)
206 #ifndef HAVE_POLL_FINE
207   struct timeval pending_tv;
208 #endif
209   struct timeval initial_tv;
210   int pending_ms;
211   int error;
212 #endif
213   int r = 0;
214
215   if(!timeout_ms)
216     return 0;
217   if(timeout_ms < 0) {
218     errno = EINVAL;
219     return -1;
220   }
221 #if defined(MSDOS)
222   delay(timeout_ms);
223 #elif defined(USE_WINSOCK)
224   Sleep(timeout_ms);
225 #else
226   pending_ms = timeout_ms;
227   initial_tv = curlx_tvnow();
228   do {
229 #if defined(HAVE_POLL_FINE)
230     r = poll(NULL, 0, pending_ms);
231 #else
232     pending_tv.tv_sec = pending_ms / 1000;
233     pending_tv.tv_usec = (pending_ms % 1000) * 1000;
234     r = select(0, NULL, NULL, NULL, &pending_tv);
235 #endif /* HAVE_POLL_FINE */
236     if(r != -1)
237       break;
238     error = errno;
239     if(error && (error != EINTR))
240       break;
241     pending_ms = timeout_ms - (int)curlx_tvdiff(curlx_tvnow(), initial_tv);
242     if(pending_ms <= 0)
243       break;
244   } while(r == -1);
245 #endif /* USE_WINSOCK */
246   if(r)
247     r = -1;
248   return r;
249 }
250
251 int write_pidfile(const char *filename)
252 {
253   FILE *pidfile;
254   long pid;
255
256   pid = (long)getpid();
257   pidfile = fopen(filename, "wb");
258   if(!pidfile) {
259     logmsg("Couldn't write pid file: %s %s", filename, strerror(errno));
260     return 0; /* fail */
261   }
262   fprintf(pidfile, "%ld\n", pid);
263   fclose(pidfile);
264   logmsg("Wrote pid %ld to %s", pid, filename);
265   return 1; /* success */
266 }
267
268 void set_advisor_read_lock(const char *filename)
269 {
270   FILE *lockfile;
271   int error = 0;
272   int res;
273
274   do {
275     lockfile = fopen(filename, "wb");
276   } while((lockfile == NULL) && ((error = errno) == EINTR));
277   if(lockfile == NULL) {
278     logmsg("Error creating lock file %s error: %d %s",
279            filename, error, strerror(error));
280     return;
281   }
282
283   do {
284     res = fclose(lockfile);
285   } while(res && ((error = errno) == EINTR));
286   if(res)
287     logmsg("Error closing lock file %s error: %d %s",
288            filename, error, strerror(error));
289 }
290
291 void clear_advisor_read_lock(const char *filename)
292 {
293   int error = 0;
294   int res;
295
296   /*
297   ** Log all removal failures. Even those due to file not existing.
298   ** This allows to detect if unexpectedly the file has already been
299   ** removed by a process different than the one that should do this.
300   */
301
302   do {
303     res = unlink(filename);
304   } while(res && ((error = errno) == EINTR));
305   if(res)
306     logmsg("Error removing lock file %s error: %d %s",
307            filename, error, strerror(error));
308 }