Watt-32 tcp/ip  2.2 dev-rel.10
bsddbug.c
Go to the documentation of this file.
1 
5 /* BSD sockets functionality for Watt-32 TCP/IP
6  *
7  * Copyright (c) 1997-2002 Gisle Vanem <gvanem@yahoo.no>
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  * must display the following acknowledgement:
19  * This product includes software developed by Gisle Vanem
20  * Bergen, Norway.
21  *
22  * THIS SOFTWARE IS PROVIDED BY ME (Gisle Vanem) AND CONTRIBUTORS ``AS IS''
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL I OR CONTRIBUTORS BE LIABLE FOR ANY
26  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Version
34  *
35  * 0.5 : Dec 18, 1997 : G. Vanem - created
36  * Debug functions moved from socket.c
37  */
38 
39 #include "socket.h"
40 #include "run.h"
41 #include "get_xby.h"
42 
43 #if defined(USE_DEBUG) && defined(USE_BSD_API) /* Whole file */
44 
45 #define USE_PRINTK 0
46 #define SCOPE_INDENT 2 /* How much to indent printout at each new scope */
47 
48 static int sk_scope = 0;
50 static void (W32_CALL *prev_hook) (const char*, const char*);
51 
52 static BOOL dbg_use_ods = FALSE;
53 static FILE *dbg_file = NULL;
54 static char dbg_omode[5] = "w+"; /* max "w+tc" */
55 static char dbg_fname[MAX_PATHLEN+1] = "";
56 
57 static void bsddbug_exit (void);
58 static void bsddbug_close (void);
59 
60 #if defined(WIN32)
61 static int ods_printf (const char *fmt, va_list arg);
62 #endif
63 
64 int MS_CDECL _sock_debugf (const char *fmt, ...)
65 {
66  int len = 0, rc = 0;
67  char buf[256];
68  va_list arg;
69  int err, errno_save = errno;
70 
71  if (!debug_xmit || !fmt) /* dbug_init() not called */
72  return (0);
73 
74 #if defined(WIN32)
75  if (dbg_use_ods)
76  {
77  va_start (arg, fmt);
78  rc = ods_printf (fmt, arg);
79  va_end (arg);
80  return (rc);
81  }
82 #endif
83 
84  if (!dbg_file)
85  return (rc);
86 
87  va_start (arg, fmt);
88 
89  if (*fmt == '\n')
90  {
91 #if (USE_PRINTK)
92  len = _printk ("\n%9s: ", elapsed_str(set_timeout(0)));
93  if (sk_scope > 0)
94  len += _printk ("%*s", SCOPE_INDENT*sk_scope, "");
95 #else
96  len = fprintf (dbg_file, "\n%9s: ", elapsed_str(set_timeout(0)));
97  if (sk_scope > 0)
98  len += fprintf (dbg_file, "%*s", SCOPE_INDENT*sk_scope, "");
99 #endif
100  fmt++;
101  if (*fmt == '\0')
102  return (len);
103  }
104 
105 #if (USE_PRINTK)
106  _vsnprintk (buf, sizeof(buf), fmt, arg);
107  rc = _fputsk (buf, dbg_file);
108 #else
109  vsprintf (buf, fmt, arg);
110  rc = fputs (buf, dbg_file);
111 #endif
112 
113  err = errno;
114  _sock_dbug_flush();
115 
116  if (rc == EOF)
117  {
118  TCP_CONSOLE_MSG (1, ("%s (%d): write failed; %s\n",
119  __FILE__, __LINE__, strerror(err)));
120  bsddbug_close();
121  }
122  else
123  len += rc;
124 
125  errno = errno_save;
126  va_end (arg);
127  return (len);
128 }
129 
130 BOOL _sock_dbug_active (void)
131 {
132  return (dbg_file != NULL || dbg_use_ods);
133 }
134 
135 void _sock_dbug_flush (void)
136 {
137  if (!dbg_file)
138  return;
139 
140 #if (USE_PRINTK)
141  _printk_safe = TRUE;
142  _printk_flush();
143 #else
144  fflush (dbg_file);
145 #endif
146 }
147 
148 /*
149  * Called from sock_ini.c if 'debug_xmit' != NULL.
150  */
151 void _sock_dbug_open (void)
152 {
153  if (dbg_file == stdout || dbg_file == stderr || dbg_use_ods)
154  return;
155 
156 #if (USE_PRINTK)
157  if (_printk_init(2000, dbg_fname))
158  {
159  dbg_file = _printk_file;
160  RUNDOWN_ADD (bsddbug_exit, 150);
161  }
162 #else
163  if (!dbg_fname[0])
164  return;
165 
166  errno = 0;
167  dbg_file = fopen_excl (dbg_fname, dbg_omode);
168  if (dbg_file)
169  {
170 #if !defined(__BORLANDC__) /* buggy output with this */
171  static char buf [1024];
172  setvbuf (dbg_file, buf, _IOLBF, sizeof(buf));
173 #endif
174  RUNDOWN_ADD (bsddbug_exit, 150);
175  }
176 #endif /* USE_PRINTK */
177 
178  TCP_CONSOLE_MSG (2, ("%s (%d): dbg_file `%s', handle %d, errno %d\n",
179  __FILE__, __LINE__, dbg_fname,
180  dbg_file ? fileno(dbg_file) : -1, errno));
181 }
182 
183 /*
184  * Callbacks for config-table parser.
185  */
186 static void set_dbg_fname (const char *value)
187 {
188  _strlcpy (dbg_fname, value, sizeof(dbg_fname));
189 
190  if (!stricmp(dbg_fname,"stderr"))
191  dbg_file = stderr;
192  if (!stricmp(dbg_fname,"stdout") || !stricmp(dbg_fname,"con"))
193  dbg_file = stdout;
194 #if defined(WIN32)
195  if (!stricmp(dbg_fname,"$ods"))
196  dbg_use_ods = TRUE;
197 #endif
198 }
199 
200 static void set_dbg_openmode (const char *value)
201 {
202  _strlcpy (dbg_omode, value, sizeof(dbg_omode));
203 }
204 
205 /*
206  * Config-file hook routine called from parser.
207  * (set_values() in pcconfig.c and via ourinit() in pcdbug.c)
208  *
209  * Parses keywords:
210  * SK_DEBUG.DEVICE = <file>
211  * SK_DEBUG.OPENMODE = <mode>
212  */
213 static void W32_CALL dbug_parse (const char *name, const char *value)
214 {
215  static const struct config_table cfg[] = {
216  { "DEVICE", ARG_FUNC, (void*)set_dbg_fname },
217  { "OPENMODE", ARG_FUNC, (void*)set_dbg_openmode },
218  { NULL, 0, NULL }
219  };
220 
221  if (!parse_config_table(&cfg[0], "SK_DEBUG.", name, value) && prev_hook)
222  (*prev_hook) (name, value);
223 }
224 
225 /*
226  * Normally called from dbug_init() (in pcdbug.c) if USE_DEBUG is defined.
227  * Must be called before watt_sock_init() and any other socket functions.
228  */
229 void _sock_dbug_init (void)
230 {
231  prev_hook = usr_init;
232  usr_init = dbug_parse;
233 }
234 
235 static void show_local_ports_inuse (void)
236 {
237  WORD port, num = 0;
238 
239  if (!dbg_file)
240  return;
241 
242 #if (USE_PRINTK)
243  _printk ("\nLocal ports still in use:\n");
244 #else
245  fprintf (dbg_file, "\nLocal ports still in use:\n");
246 #endif
247 
248  for (port = 1025; port < USHRT_MAX; port++)
249  {
250  int rc = reuse_localport (port);
251 
252  if (rc < 0)
253  break;
254  if (rc > 0)
255  {
256  num++;
257 #if (USE_PRINTK)
258  _printk ("%5u%c", port, num % 12 ? ',' : '\n');
259 #else
260  fprintf (dbg_file, "%5u%c", port, (num % 12) ? ',' : '\n');
261 #endif
262  }
263  }
264 }
265 
266 void bsd_fortify_print (const char *buf)
267 {
268  if (dbg_file)
269  {
270 #if (USE_PRINTK)
271  _fputsk (buf, dbg_file);
272 #else
273  fputs (buf, dbg_file);
274 #endif
275  }
276 }
277 
278 #if defined(WIN32)
279 
282 static int ods_printf (const char *fmt, va_list arg)
283 {
284  char buf1[300];
285  char buf2[400];
286  char *p1 = buf1;
287  char *p2 = buf2;
288  size_t left = sizeof(buf1);
289 
290  if (*fmt == '\n')
291  {
292  p1 += SNPRINTF (p1, left, "\n%9s: ", elapsed_str(set_timeout(0)));
293  left -= p1 - buf1;
294  fmt++;
295  if (sk_scope > 0)
296  {
297  p1 += SNPRINTF (p1, left, "%*s", SCOPE_INDENT*sk_scope, "");
298  left -= p1 - buf1;
299  }
300  }
301 
302  VSNPRINTF (p1, left, fmt, arg);
303 
304  for (p1 = buf1, p2 = buf2; *p1 && p2 < buf2 + sizeof(buf2); p1++, p2++)
305  {
306  if (p1[0] == '\n' && p1[-1] != '\r')
307  *p2++ = '\r';
308  *p2 = *p1;
309  }
310 
311 #if 0
312  if (p2[-2] != '\r' || p2[-1] != '\n')
313  strcpy (p2, "\r\n"), p2 += 2;
314 #endif
315 
316  *p2++ = '\0';
317  OutputDebugStringA (buf2);
318  return (p2 - buf2);
319 }
320 #endif /* WIN32 */
321 
322 
323 #include "nochkstk.h"
324 
325 static void bsddbug_close (void)
326 {
327 #if (USE_PRINTK == 0)
328  if (dbg_file && dbg_file != stdout && dbg_file != stderr)
329  FCLOSE (dbg_file);
330 #endif
331  dbg_file = NULL;
332 }
333 
334 static void bsddbug_exit (void)
335 {
336  if (!_watt_fatal_error && dbg_file)
337  {
338  DumpEthersCache();
339  DumpHostsCache();
340 #if defined(USE_IPV6)
341  DumpHosts6Cache();
342 #endif
343  show_local_ports_inuse();
344  _sock_dbug_flush();
345  }
346  bsddbug_close();
347  set_dbg_openmode ("at"); /* append next time we open it */
348 }
349 
350 /*
351  * These two functions are meant to increase/decrease the suspension
352  * depth of a "task". I.e. _sock_enter_scope() should awake other
353  * sleeping "tasks" waiting to be signalled. Ref. sk_block in socket.c.
354  * Now they're only used to make the sock-trace prettier.
355  */
356 void _sock_enter_scope (void)
357 {
358  if (sk_scope < INT_MAX)
359  sk_scope++;
360 }
361 
362 void _sock_leave_scope (void)
363 {
364  if (sk_scope > 0)
365  sk_scope--;
366 }
367 #endif /* USE_DEBUG && USE_BSD_API */
368 
int W32_CALL parse_config_table(const struct config_table *tab, const char *section, const char *name, const char *value)
Parse the config-table and if a match is found for ('section'+'.
Definition: pcconfig.c:379
call convertion function
Definition: tcp.h:434
int _printk_safe
Definition: printk.c:55
char * _strlcpy(char *dst, const char *src, size_t len)
Similar to strncpy(), but always returns 'dst' with 0-termination.
Definition: strings.c:226
FILE * fopen_excl(const char *file, const char *mode)
WIN32: Open an existing file (or create) in share-mode but deny other processes to write to the file...
Definition: misc.c:439
DWORD W32_CALL set_timeout(DWORD msec)
Return time for when given timeout (msec) expires.
Definition: timer.c:503
FILE * _printk_file
Definition: printk.c:58
static int ods_printf(const char *fmt, va_list arg)
Definition: bsddbug.c:282
static int sk_scope
Definition: bsddbug.c:48
BOOL _watt_fatal_error
Definition: misc.c:60