revert between 56095 -> 55830 in arch
[AROS.git] / workbench / network / stacks / AROSTCP / bsdsocket / kern / subr_prf.c
blob5b5803044359ed30bd9c1d8762d0999c7f0c5644
1 /*
2 * Copyright (C) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
3 * Helsinki University of Technology, Finland.
4 * All rights reserved.
5 * Copyright (C) 2005 - 2007 The AROS Dev Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19 * MA 02111-1307, USA.
23 #define USE_INLINE_STDARG
25 #include <conf.h>
27 #include <sys/param.h>
28 #include <sys/systm.h>
29 #include <syslog.h>
30 #include <sys/time.h>
32 #include <kern/amiga_includes.h>
33 #include <api/amiga_api.h>
34 #include <api/amiga_libcallentry.h>
35 #include <kern/amiga_log.h>
36 #include <stdarg.h>
37 #include <intuition/intuition.h>
39 #include <proto/intuition.h>
41 #include <kern/amiga_main_protos.h>
42 #include <dos/rdargs.h> /* CSource */
44 extern void exit(int);
46 void
47 cs_putchar(unsigned char ch, struct CSource * cs)
49 if (cs->CS_CurChr < cs->CS_Length
50 && (cs->CS_Buffer[cs->CS_CurChr] = ch))
51 cs->CS_CurChr++;
54 /****i* bsdsocket.library/panic ******************************************
56 * NAME
57 * panic -- Inform user from serious failure.
59 * SYNOPSIS
60 * panic(Message, Arguments...)
62 * void panic( STRPTR, ... )
64 * FUNCTION
65 * Calls api_setfunctions() with no arguments to stop programs using
66 * AmiTCP. Writes message to log file. Sets up User Requester to
67 * inform user about situation. Avoids self-loops.
70 * INPUTS
71 * Messagestring - A pointer to string containing message to show
72 * to user and to write to log. It should describe problem so
73 * that user can take correcting action if it is failure with
74 * his configuration or is able to write bug report if it is
75 * a bug withn program.
77 * Arguments - as in c-library printf()
79 * RESULT
80 * This function does not return.
82 * EXAMPLE
83 * if(Everything==WRONG)
84 * panic("Everything is wrong\nGoto sleep");
86 * NOTES
87 * As panic does not return, it should be used only in extreme
88 * cases
90 * BUGS
92 * SEE ALSO
93 * log()
95 ******************************************************************************
99 #define PANICBUFFERSIZE 512
101 void
102 panic(const char *fmt,...)
104 struct EasyStruct panicES = {
105 sizeof( struct EasyStruct),
107 "TCP/IP PANIC",
108 "panic: %s" ,
109 "Shut Down TCP/IP"
111 static int in_panic = 0;
112 struct CSource cs;
113 char buffer[PANICBUFFERSIZE];
114 va_list ap;
115 struct Library *IntuitionBase = NULL; /* local intuitionbase */
116 extern struct Task *AROSTCP_Task;
118 if (!in_panic){
119 /* If we're called previously.. */
120 in_panic++; /* We're in panic now */
121 api_setfunctions(); /* Set libraries to return error code */
123 cs.CS_Buffer = buffer;
124 cs.CS_CurChr = 0;
125 cs.CS_Length = PANICBUFFERSIZE;
127 va_start(ap, fmt);
128 vcsprintf(&cs, fmt, ap);
129 va_end(ap);
131 __log(LOG_EMERG, "panic: %s", buffer); /* Write to log */
133 in_panic--;
136 * Inform user (if log system has failed...)
137 * by opening a requester to the default public screen.
139 * Open a local IntuitionBase for the EasyRequest()
141 if ((IntuitionBase = OpenLibrary("intuition.library", 37L)) != NULL) {
142 EasyRequest(NULL, &panicES, NULL, (IPTR)buffer);
143 CloseLibrary(IntuitionBase);
144 IntuitionBase = NULL;
148 * If the caller is not the AmiTCP task, sleep forever.
149 * This should go to API or where ever we came in AmiTCP code
151 if (FindTask(NULL) != AROSTCP_Task)
152 Wait(0);
154 Wait(SIGBREAKF_CTRL_F); /* AmiTCP/IP waits here */
157 * Following code is not safe. Probably we should wait infinetely long too...
159 deinit_all(); /* This returns !! */
160 exit(20); /* This should be safe... */
163 /****i* bsdsockets.library/log ******************************************
165 * NAME
166 * log -- Write log message to log and/or console.
168 * SYNOPSIS
169 * log(Level, FormatString, arguments...)
171 * void log( ULONG, STRPTR, ...)
173 * FUNCTION
174 * Writes message given as format string and arguments
175 * (printf-style) to both log and console (except if level is
176 * LOG_EMERG, LOG_EMERG is generated only by panic and it is
177 * written only to the log file as panic() generates an User
178 * Requester informing user.
180 * This function can be called from interrupts.
182 * INPUTS
183 * Level - indicates type of logged message. These levels are
184 * defined in sys/syslog.h.
185 * FormatString - This is a printf-style format string with some
186 * restrictions (notably the floats are not handled).
187 * arguments - as in printf()
189 * RESULT
190 * Returns no value.
192 * EXAMPLE
193 * log(LOG_ERR,
194 * "arp: ether address is broadcast for IP address %x!\n",
195 * ntohl(isaddr.s_addr));
196 * fail=TRUE;
197 * break;
199 * NOTES
201 * BUGS
203 * SEE ALSO
204 * Your C-compilers printf() documentation.
206 ******************************************************************************
210 #ifdef __AROS__
211 #undef __log
212 #endif
213 void
214 __log(unsigned long level, const char *fmt, ...)
216 va_list ap;
218 va_start(ap, fmt);
219 vlog(level, "kernel", fmt, ap); /* Call actual function */
220 va_end(ap);
224 vlog(unsigned long level, const char *tag, const char *fmt, va_list ap)
226 struct SysLogPacket *msg;
227 struct timeval now;
229 msg = (struct SysLogPacket *)GetLogMsg(&logReplyPort);
230 if (msg) {
231 ULONG ret;
232 struct CSource cs;
233 if (tag) {
234 cs.CS_Length = log_cnf.log_buf_len-strlen(tag)-1;
235 msg->Tag = &msg->String[cs.CS_Length];
236 strcpy(msg->Tag, tag);
237 } else {
238 cs.CS_Length = log_cnf.log_buf_len;
239 msg->Tag = NULL;
241 cs.CS_Buffer = msg->String;
242 cs.CS_CurChr = 0;
244 GetSysTime(&now);
246 vcsprintf(&cs, fmt, ap);
247 msg->Level = level & (LOG_FACMASK | LOG_PRIMASK); /* Level of message */
248 ret = cs.CS_CurChr;
249 msg->Time = now.tv_secs;
250 DSYSLOG(KPrintF("Putting message = 0x%08x, tag: %s, text: %s\n",msg, msg->Tag, msg->String );)
251 PutMsg(logPort, (struct Message *)msg);
252 return ret;
254 return 0;
257 /****i* bsdsockets.library/printf ******************************************
259 * NAME
260 * printf -- print to log
262 * SYNOPSIS
263 * printf(FormatString, Arguments...)
265 * ULONG printf( const char *, ...)
267 * FUNCTION
268 * Prints messages to log
269 * As log, also this is callable from interrupts.
271 * Specially for debugging prints.
273 * INPUTS
274 * FormatString - This is a printf-style format string as for vcsprintf().
275 * Arguments - as in C-librarys printf()
277 * RESULT
278 * Number of characters printed.
280 * EXAMPLE
282 * printf("line=%d, val=%x\n",
283 * __LINE__, very.interesting->value);
285 * NOTES
287 * BUGS
289 * SEE ALSO
290 * vcsprintf(), vlog()
292 ******************************************************************************
295 #ifndef __AROS__
296 int
297 printf(const char *fmt, ...)
299 #if 1
300 ULONG ret;
301 va_list ap;
303 va_start(ap, fmt);
304 ret = vlog(LOG_INFO, "kernel", fmt, ap);
305 va_end(ap);
307 return ret;
308 #else
309 va_list ap;
310 struct SysLogPacket *msg;
311 struct timeval now;
313 if (msg = GetLogMsg(&logReplyPort)) { /* Get next free message */
314 struct CSource cs;
316 GetSysTime(&now);
318 cs.CS_Buffer = msg->String;
319 cs.CS_Length = log_cnf.log_buf_len;
320 cs.CS_CurChr = 0;
322 va_start(ap, fmt);
323 vcsprintf(&cs, fmt, ap);
324 va_end(ap);
326 msg->Level = LOG_INFO;
327 msg->chars = cs.CS_CurChr;
328 msg->Time = now.tv_secs;
329 PutMsg(logPort,(struct Message *)msg);
331 return (ULONG)cs.CS_CurChr;
332 } else
333 return 0;
334 #endif
336 #endif
338 /****i* bsdsocket.library/sprintf ******************************************
340 * NAME
341 * sprintf -- print to buffer
343 * SYNOPSIS
344 * len = sprintf(Buffer, FormatString, Arguments...)
345 * len = csprintf(cs, FormatString, Arguments...)
347 * ULONG sprintf(STRPTR, const char*, ...)
348 * ULONG csprintf(struct CSource *, const char*, ...)
350 * FUNCTION
351 * Prints to a simple buffer or to a CSource buffer. These functions
352 * are similar to C-library sprintf() with restricted formatting.
354 * INPUTS
355 * Buffer - Pointer to buffer.
356 * FormatString - This is a printf()-style format string with some
357 * restrictions. Numbers are being taken as 'long' by
358 * default, however.
359 * Arguments - as in printf() .
360 * cs - Pointer to CSource structure.
362 * RESULT
363 * Number of characters printed.
365 * EXAMPLE
366 * sprintf(mybuf, "line=%d, val=%x\n",
367 * __LINE__, very.interesting->value);
369 * BUGS
370 * Function sprintf() assumes that no print is longer than 1024 chars.
371 * It does not check for buffer owerflow (there no way to check, the
372 * definition of sprintf misses it).
374 * sprintf strings are truncated to maximum of 1024 chars (including
375 * final NUL)
377 * SEE ALSO
378 * vcsprintf()
380 ****************************************************************************
384 int
385 vcsprintf(struct CSource *cs, const char *fmt, va_list ap)
387 ULONG start = cs->CS_CurChr;
388 char *p, ch, padc;
389 u_long ul;
390 int n, base, lflag, tmp, width, precision, leftjustify;
391 char buf[sizeof(long) * NBBY / 3 + 2]; /* A long in base 8, plus '\0'. */
393 if (cs->CS_Length && cs->CS_CurChr < cs->CS_Length) {
395 for (;;) {
396 padc = ' ';
397 width = 0;
398 precision = -1;
399 leftjustify = FALSE;
400 while ((ch = *fmt++) != '%') {
401 if (ch == '\0') {
402 goto end;
404 cs_putchar(ch, cs);
406 lflag = 0;
407 reswitch:
408 switch (ch = *fmt++) {
409 case '-':
410 leftjustify = TRUE;
411 goto reswitch;
412 case '0':
413 padc = '0';
414 goto reswitch;
415 case '1': case '2': case '3': case '4':
416 case '5': case '6': case '7': case '8': case '9':
417 for (width = 0;; ++fmt) {
418 width = width * 10 + ch - '0';
419 ch = *fmt;
420 if (ch < '0' || ch > '9')
421 break;
423 goto reswitch;
424 case '.': /* precision */
425 for (precision = 0; (ch = *fmt) >= '0' && ch <= '9'; ++fmt) {
426 precision = precision * 10 + ch - '0';
428 goto reswitch;
429 case 'l':
430 lflag = 1;
431 goto reswitch;
432 case 'b':
434 char *tp;
436 ul = va_arg(ap, int);
437 p = va_arg(ap, char *);
438 for (tp = csprintn(ul, *p++, buf, sizeof(buf)); ch = *tp++;)
439 cs_putchar(ch, cs);
441 if (!ul)
442 break;
444 for (tmp = 0; n = *p++;) {
445 if (ul & (1 << (n - 1))) {
446 cs_putchar(tmp ? ',' : '<', cs);
447 for (; (n = *p) > ' '; ++p)
448 cs_putchar(n, cs);
449 tmp = 1;
450 } else
451 for (; *p > ' '; ++p)
454 if (tmp)
455 cs_putchar('>', cs);
457 break;
458 case 'r':
459 p = va_arg(ap, char *);
460 #ifdef __arm__
461 vcsprintf(cs, p, va_arg(ap, va_list));
462 #else
463 vcsprintf(cs, p, va_arg(ap, void *));
464 #endif
465 /* vcsprintf(cs, p, va_arg(ap, va_list));*/
466 break;
467 case 'c':
468 *buf = va_arg(ap, int);
469 buf[1] = '\0';
470 p = buf;
471 goto textout;
472 case 's':
473 p = va_arg(ap, char *);
474 textout:
476 * Set width to the maximum width, if maximum width is set, and
477 * width exceeds it.
479 if (precision > 0 && width > precision)
480 width = precision;
482 * spit out necessary pad characters to fill on left, if necessary
484 if (width > 0 && !leftjustify && (width -= strlen(p)) > 0)
485 while (width--)
486 cs_putchar(padc, cs);
487 /* take a copy of the original pointer */
488 ul = (u_long)p;
490 * Copy the characters, pay attention to the fact that precision
491 * may not be exceeded.
493 while ((ch = *p++) && precision-- != 0)
494 cs_putchar(ch, cs);
496 * spit out necessary pad characters to fill on right, if necessary
498 if (width > 0 && leftjustify && (width -= ((u_long)p - ul - 1)) > 0)
499 while (width--)
500 cs_putchar(' ', cs);
501 break;
502 case 'd':
503 case 'i':
504 ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
505 if ((long)ul < 0) {
506 cs_putchar('-', cs);
507 ul = -(long)ul;
509 base = 10;
510 goto number;
511 case 'o':
512 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
513 base = 8;
514 goto number;
515 case 'u':
516 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
517 base = 10;
518 goto number;
519 case 'p': /* pointers */
520 case 'P':
521 width = 8;
522 padc = '0';
523 /* FALLTHROUGH */
524 case 'x':
525 case 'X':
526 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
527 base = 16;
528 number:
529 p = csprintn(ul, base, buf, sizeof(buf));
530 tmp = (buf + sizeof(buf) - 1) - p; /* length */
531 if (width > 0 && !leftjustify && (width -= tmp) > 0)
532 while (width--)
533 cs_putchar(padc, cs);
534 while (ch = *p++)
535 cs_putchar(ch, cs);
536 if (width > 0 && leftjustify && (width -= tmp) > 0)
537 while (width--)
538 cs_putchar(' ', cs);
539 break;
540 default:
541 cs_putchar('%', cs);
542 if (lflag)
543 cs_putchar('l', cs);
544 /* FALLTHROUGH */
545 case '%':
546 cs_putchar(ch, cs);
550 end:
552 if (cs->CS_CurChr == cs->CS_Length) {
553 cs->CS_CurChr--; /* must NUL terminate */
555 cs->CS_Buffer[cs->CS_CurChr] = '\0';
557 return cs->CS_CurChr - start;
558 } else {
559 /* A pathological case */
560 return 0;
564 int csprintf(struct CSource *cs, const char *fmt, ...)
566 va_list ap;
567 ULONG len;
569 va_start(ap, fmt);
570 len = vcsprintf(cs, fmt, ap);
571 va_end(ap);
572 return len;
575 #ifndef __AROS__
576 int vsprintf(char *buf, const char *fmt, va_list ap)
578 struct CSource cs;
580 cs.CS_Buffer = buf;
581 cs.CS_CurChr = 0;
582 cs.CS_Length = 1024; /* This is not probably the cleanest way :-) */
584 return vcsprintf(&cs, fmt, ap);
587 int sprintf(char *buf, const char *fmt, ...)
589 va_list ap;
590 ULONG len;
592 va_start(ap, fmt);
593 len = vsprintf(buf, fmt, ap);
594 va_end(ap);
595 return len;
597 #endif
599 char *
600 csprintn(u_long n, int base, char *buf, int buflen)
602 register char *cp = buf + buflen - 1;
604 *cp = 0;
605 do {
606 cp--;
607 *cp = "0123456789abcdef"[n % base];
608 } while (n /= base);
609 return (cp);