Watt-32 tcp/ip  2.2 dev-rel.10
printk.c
Go to the documentation of this file.
1 
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <stdarg.h>
39 #include <string.h>
40 #include <signal.h>
41 #include <ctype.h>
42 #include <errno.h>
43 #include <time.h>
44 
45 #include "wattcp.h"
46 #include "strings.h"
47 #include "misc.h"
48 #include "run.h"
49 #include "netaddr.h"
50 #include "pcconfig.h"
51 #include "printk.h"
52 
53 #if defined(USE_BSD_API) || defined(USE_DEBUG) || (DOSX & (DOS4GW|X32VM))
54 
55 int _printk_safe = 1; /* must be set to 0 in intr-handlers */
56 
57 #if defined(WIN32)
58  FILE *_printk_file = NULL;
59 #else
60  FILE *_printk_file = stderr;
61 #endif
62 
63 static char *printk_ptr = NULL;
64 static char *printk_buf = NULL;
65 static char *printk_end = NULL;
66 
67 static const char *str_signal (int sig);
68 
69 /*
70  * _snprintk - format a message into a buffer. Like sprintf except we
71  * also specify the length of the output buffer, and we handle
72  * %m (error message), %t (current time) and %I (IPv4 address) formats.
73  * Returns the number of chars put into buf.
74  *
75  * NB! Doesn't do floating-point formats and long modifiers.
76  * (e.g. "%lu").
77  */
78 int MS_CDECL _snprintk (char *buf, int buflen, const char *fmt, ...)
79 {
80  int len;
81  va_list args;
82 
83  va_start (args, fmt);
84  len = _vsnprintk (buf, buflen, fmt, args);
85  va_end (args);
86  return (len);
87 }
88 
89 int MS_CDECL _printk (const char *fmt, ...)
90 {
91  int left = (int)(printk_end - printk_ptr);
92  int len = -1;
93 
94  if (_printk_file && fmt && left > 0)
95  {
96  va_list args;
97  va_start (args, fmt);
98  len = _vsnprintk (printk_ptr, left, fmt, args);
99  printk_ptr += len;
100  _printk_flush();
101  va_end (args);
102  }
103  return (len);
104 }
105 
106 /*
107  * Return 0 if okay, else -1
108  */
109 int _fputsk (const char *buf, FILE *stream)
110 {
111  int rc = -1;
112 
113  if (stream && _printk_safe)
114  rc = fwrite (buf, strlen(buf), 1, stream);
115  return (rc == 1 ? 0 : -1);
116 }
117 
118 void _printk_flush (void)
119 {
120  int len = printk_ptr - printk_buf;
121 
122  if (_printk_safe && _printk_file && len > 0)
123  {
124  fwrite (printk_buf, len, 1, _printk_file);
125  printk_ptr = printk_buf;
126  }
127 }
128 
129 static void printk_exit (void)
130 {
131  _printk_flush();
132  if (_printk_file && _printk_file != stderr && _printk_file != stdout)
133  fclose (_printk_file);
134  _printk_file = NULL;
135 
136  if (printk_buf)
137  free (printk_buf); /* Reclaim memory allocated in _printk_init() */
138  printk_buf = NULL;
139 }
140 
141 /*
142  * Called from openlog() to allocate print-buffer and
143  * optionally open a file. If file == NULL, print to stderr.
144  */
145 int _printk_init (int size, const char *file)
146 {
147  if (!printk_buf)
148  {
149  printk_ptr = printk_buf = malloc (size);
150  if (!printk_ptr)
151  {
152  fprintf (stderr, "_printk_init: allocation failed\n");
153  return (0);
154  }
155  }
156 
157 #if defined(WIN32)
158  _printk_file = stderr;
159 #endif
160 
161  if (file && (_printk_file = fopen(file,"wt")) == NULL)
162  {
163  fprintf (stderr, "_printk_init: cannot open `%s'\n", file);
164  return (0);
165  }
166  printk_end = printk_ptr + size;
167  RUNDOWN_ADD (printk_exit, 301);
168  return (1);
169 }
170 
171 
172 /*
173  * _vsnprintk - like _snprintk, takes a va_list instead of a list of args.
174  */
175 #define OUTCHAR(c) (void) (buflen > 0 ? (--buflen, *buf++ = (c)) : 0)
176 
177 int _vsnprintk (char *buf, int buflen, const char *fmt, va_list args)
178 {
179  int c, n, width, prec, fillch;
180  int base, len, neg, quoted, upper;
181  long i;
182  BOOL right_pad, is_long;
183  BYTE *p;
184  char *str, *f, *buf0 = buf, *_fmt = (char*)fmt;
185  char num[32], ct_buf[30];
186  time_t t;
187  DWORD_PTR val = 0L;
188 
189  if (--buflen < 0)
190  return (-1);
191 
192  while (buflen > 0)
193  {
194  for (f = _fmt; *f != '%' && *f != '\0'; ++f)
195  ;
196  if (f > _fmt)
197  {
198  len = f - _fmt;
199  if (len > buflen)
200  len = buflen;
201  memcpy (buf, _fmt, len);
202  buf += len;
203  buflen -= len;
204  _fmt = f;
205  }
206  if (*_fmt == '\0')
207  break;
208 
209  is_long = FALSE;
210 next:
211  c = *(++_fmt);
212  width = prec = 0;
213  right_pad = FALSE;
214  fillch = ' ';
215  if (c == '0')
216  {
217  fillch = '0';
218  c = *(++_fmt);
219  }
220  if (c == '*')
221  {
222  width = va_arg (args, int);
223  c = *(++_fmt);
224  }
225  else
226  {
227  if (c == '-')
228  {
229  right_pad = TRUE;
230  c = *(++fmt);
231  }
232  while (isdigit(c))
233  {
234  width = width * 10 + c - '0';
235  c = *(++_fmt);
236  }
237  }
238 
239  if (c == '.')
240  {
241  c = *(++_fmt);
242  if (c == '*')
243  {
244  prec = va_arg (args, int);
245  c = *(++_fmt);
246  }
247  else
248  {
249  while (isdigit(c))
250  {
251  prec = prec * 10 + c - '0';
252  c = *(++_fmt);
253  }
254  }
255  }
256  str = NULL;
257  base = 0;
258  neg = 0;
259  upper = 0;
260  ++_fmt;
261 
262  switch (c)
263  {
264  case 'l':
265  is_long = 1;
266  goto next;
267 
268  case 'd':
269  i = is_long ? va_arg (args, long) : va_arg (args, int);
270  if (i < 0)
271  {
272  neg = 1;
273  val = -i;
274  }
275  else
276  val = i;
277  base = 10;
278  break;
279 
280  case 'u':
281  val = is_long ? va_arg (args, DWORD) : va_arg (args, unsigned);
282  base = 10;
283  break;
284 
285  case 'o':
286  val = is_long ? va_arg (args, unsigned long) :
287  va_arg (args, unsigned int);
288  base = 8;
289  break;
290 
291  case 'X':
292  upper = 1;
293  /* fall through */
294  case 'x':
295  val = is_long ? va_arg (args, unsigned long) :
296  va_arg (args, unsigned int);
297  base = 16;
298  break;
299 
300  case 'p':
301  val = (DWORD_PTR) va_arg (args, void*);
302  base = 16;
303  neg = 2;
304  upper = 1;
305  break;
306 
307  case 's':
308  str = va_arg (args, char*);
309  break;
310 
311  case 'S':
312  str = (char*) str_signal (va_arg(args, int));
313  break;
314 
315  case 'c':
316  num[0] = va_arg (args, int);
317  num[1] = '\0';
318  str = num;
319  break;
320 
321  case 'm':
322  str = rip (strerror(errno));
323  break;
324 
325  case 'I':
326  str = _inet_ntoa (num, ntohl(va_arg(args,DWORD)));
327  break;
328 
329  case 't':
330  str = (char*) "??";
331  if (!_printk_safe)
332  break;
333  time (&t);
334  str = ctime_r (&t, ct_buf);
335  str += 4; /* chop off the day name */
336  str[15] = '\0'; /* chop off year and newline */
337  break;
338 
339  case 'v': /* "visible" string */
340  case 'q': /* quoted string */
341  quoted = c == 'q';
342  p = va_arg (args, BYTE*);
343  if (fillch == '0' && prec > 0)
344  n = prec;
345  else
346  {
347  n = strlen ((char*)p);
348  if (prec > 0 && prec < n)
349  n = prec;
350  }
351  while (n > 0 && buflen > 0)
352  {
353  c = *p++;
354  --n;
355  if (!quoted && c >= 0x80)
356  {
357  OUTCHAR ('M');
358  OUTCHAR ('-');
359  c -= 0x80;
360  }
361  if (quoted && (c == '"' || c == '\\'))
362  OUTCHAR ('\\');
363  if (c < 0x20 || (0x7F <= c && c < 0xA0))
364  {
365  if (quoted)
366  {
367  OUTCHAR ('\\');
368  switch (c)
369  {
370  case '\t':
371  OUTCHAR ('t');
372  break;
373  case '\n':
374  OUTCHAR ('n');
375  break;
376  case '\b':
377  OUTCHAR ('b');
378  break;
379  case '\f':
380  OUTCHAR ('f');
381  break;
382  default:
383  OUTCHAR ('x');
384  OUTCHAR (hex_chars_lower[c >> 4]);
385  OUTCHAR (hex_chars_lower[c & 0xF]);
386  }
387  }
388  else
389  {
390  if (c == '\t')
391  OUTCHAR (c);
392  else
393  {
394  OUTCHAR ('^');
395  OUTCHAR (c ^ 0x40);
396  }
397  }
398  }
399  else
400  OUTCHAR (c);
401  }
402  continue;
403 
404  default:
405  *buf++ = '%';
406  if (c != '%')
407  --_fmt; /* so %z outputs %z etc. */
408  --buflen;
409  continue;
410  }
411 
412  if (base)
413  {
414  str = num + sizeof(num);
415  *(--str) = '\0';
416  while (str > num + neg)
417  {
418  int idx = val % base;
419 
420  *(--str) = upper ? hex_chars_upper[idx] :
421  hex_chars_lower[idx];
422  val = val / base;
423  if (--prec <= 0 && val == 0)
424  break;
425  }
426  switch (neg)
427  {
428  case 1: *(--str) = '-';
429  break;
430  case 2: *(--str) = 'x';
431  *(--str) = '0';
432  break;
433  }
434  len = num + sizeof(num) - 1 - str;
435  }
436  else
437  {
438  len = strlen (str);
439  if (prec > 0 && len > prec)
440  len = prec;
441  }
442  if (right_pad && width > 0)
443  {
444  if (width > buflen)
445  width = buflen;
446  if ((n = width - len) > 0)
447  {
448  buflen -= n;
449  for (; n > 0; --n)
450  *buf++ = fillch;
451  }
452  }
453  if (len > buflen)
454  len = buflen;
455  memcpy (buf, str, len);
456  buf += len;
457  buflen -= len;
458 
459  if (right_pad && width > 0)
460  {
461  if (width > buflen)
462  width = buflen;
463  if ((n = width - len) > 0)
464  {
465  buflen -= n;
466  for (; n > 0; --n)
467  *buf++ = fillch;
468  }
469  }
470  }
471  *buf = '\0';
472  return (buf - buf0);
473 }
474 
475 
476 /*
477  * Return name for signal 'sig'
478  */
479 #ifdef __HIGHC__
480 #undef SIGABRT /* = SIGIOT */
481 #endif
482 
483 static const char *str_signal (int sig)
484 {
485  static char buf[20];
486 
487  switch (sig)
488  {
489  case 0:
490  return ("None");
491 #ifdef SIGINT
492  case SIGINT:
493  return ("SIGINT");
494 #endif
495 #ifdef SIGABRT
496  case SIGABRT:
497  return ("SIGABRT");
498 #endif
499 #ifdef SIGFPE
500  case SIGFPE:
501  return ("SIGFPE");
502 #endif
503 #ifdef SIGILL
504  case SIGILL:
505  return ("SIGILL");
506 #endif
507 #ifdef SIGSEGV
508  case SIGSEGV:
509  return ("SIGSEGV");
510 #endif
511 #ifdef SIGTERM
512  case SIGTERM:
513  return ("SIGTERM");
514 #endif
515 #ifdef SIGALRM
516  case SIGALRM:
517  return ("SIGALRM");
518 #endif
519 #ifdef SIGHUP
520  case SIGHUP:
521  return ("SIGHUP");
522 #endif
523 #ifdef SIGKILL
524  case SIGKILL:
525  return ("SIGKILL");
526 #endif
527 #ifdef SIGPIPE
528  case SIGPIPE:
529  return ("SIGPIPE");
530 #endif
531 #ifdef SIGQUIT
532  case SIGQUIT:
533  return ("SIGQUIT");
534 #endif
535 #ifdef SIGUSR1
536  case SIGUSR1:
537  return ("SIGUSR1");
538 #endif
539 #ifdef SIGUSR2
540  case SIGUSR2:
541  return ("SIGUSR2");
542 #endif
543 #ifdef SIGUSR3
544  case SIGUSR3:
545  return ("SIGUSR3");
546 #endif
547 #ifdef SIGNOFP
548  case SIGNOFP:
549  return ("SIGNOFP");
550 #endif
551 #ifdef SIGTRAP
552  case SIGTRAP:
553  return ("SIGTRAP");
554 #endif
555 #ifdef SIGTIMR
556  case SIGTIMR:
557  return ("SIGTIMR");
558 #endif
559 #ifdef SIGPROF
560  case SIGPROF:
561  return ("SIGPROF");
562 #endif
563 #ifdef SIGSTAK
564  case SIGSTAK:
565  return ("SIGSTAK");
566 #endif
567 #ifdef SIGBRK
568  case SIGBRK:
569  return ("SIGBRK");
570 #endif
571 #ifdef SIGBUS
572  case SIGBUS:
573  return ("SIGBUS");
574 #endif
575 #ifdef SIGIOT
576  case SIGIOT:
577  return ("SIGIOT");
578 #endif
579 #ifdef SIGEMT
580  case SIGEMT:
581  return ("SIGEMT");
582 #endif
583 #ifdef SIGSYS
584  case SIGSYS:
585  return ("SIGSYS");
586 #endif
587 #ifdef SIGCHLD
588  case SIGCHLD:
589  return ("SIGCHLD");
590 #endif
591 #ifdef SIGWINCH
592  case SIGWINCH:
593  return ("SIGWINCH");
594 #endif
595 #ifdef SIGPOLL
596  case SIGPOLL:
597  return ("SIGPOLL");
598 #endif
599 #ifdef SIGCONT
600  case SIGCONT:
601  return ("SIGCONT");
602 #endif
603 #ifdef SIGSTOP
604  case SIGSTOP:
605  return ("SIGSTOP");
606 #endif
607 #ifdef SIGTSTP
608  case SIGTSTP:
609  return ("SIGTSTP");
610 #endif
611 #ifdef SIGTTIN
612  case SIGTTIN:
613  return ("SIGTTIN");
614 #endif
615 #ifdef SIGTTOU
616  case SIGTTOU:
617  return ("SIGTTOU");
618 #endif
619 #ifdef SIGURG
620  case SIGURG:
621  return ("SIGURG");
622 #endif
623 #ifdef SIGLOST
624  case SIGLOST:
625  return ("SIGLOST");
626 #endif
627 #ifdef SIGDIL
628  case SIGDIL:
629  return ("SIGDIL");
630 #endif
631 #ifdef SIGXCPU
632  case SIGXCPU:
633  return ("SIGXCPU");
634 #endif
635 #ifdef SIGXFSZ
636  case SIGXFSZ:
637  return ("SIGXFSZ");
638 #endif
639  }
640  strcpy (buf, "Unknown ");
641  itoa (sig, buf+8, 10);
642  return (buf);
643 }
644 
645 #endif /* USE_BSD_API || USE_DEBUG || (DOSX & (DOS4GW|X32VM)) */
int _printk_safe
Definition: printk.c:55
Core definitions.
FILE * _printk_file
Definition: printk.c:58
char * ctime_r(const time_t *t, char *res)
A reentrant ctime().
Definition: misc.c:878
char *W32_CALL _inet_ntoa(char *s, DWORD ip)
Convert an IP-address 'ip' into a string.
Definition: netaddr.c:43
char *W32_CALL rip(char *s)
Removes end-of-line termination from a string.
Definition: strings.c:180