2 * Copyright (C) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
3 * Helsinki University of Technology, Finland.
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,
23 #define USE_INLINE_STDARG
27 #include <sys/param.h>
28 #include <sys/systm.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>
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);
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
))
54 /****i* bsdsocket.library/panic ******************************************
57 * panic -- Inform user from serious failure.
60 * panic(Message, Arguments...)
62 * void panic( STRPTR, ... )
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.
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()
80 * This function does not return.
83 * if(Everything==WRONG)
84 * panic("Everything is wrong\nGoto sleep");
87 * As panic does not return, it should be used only in extreme
95 ******************************************************************************
99 #define PANICBUFFERSIZE 512
102 panic(const char *fmt
,...)
104 struct EasyStruct panicES
= {
105 sizeof( struct EasyStruct
),
111 static int in_panic
= 0;
113 char buffer
[PANICBUFFERSIZE
];
115 struct Library
*IntuitionBase
= NULL
; /* local intuitionbase */
116 extern struct Task
*AROSTCP_Task
;
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
;
125 cs
.CS_Length
= PANICBUFFERSIZE
;
128 vcsprintf(&cs
, fmt
, ap
);
131 __log(LOG_EMERG
, "panic: %s", buffer
); /* Write to log */
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
)
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 ******************************************
166 * log -- Write log message to log and/or console.
169 * log(Level, FormatString, arguments...)
171 * void log( ULONG, STRPTR, ...)
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.
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()
194 * "arp: ether address is broadcast for IP address %x!\n",
195 * ntohl(isaddr.s_addr));
204 * Your C-compilers printf() documentation.
206 ******************************************************************************
214 __log(unsigned long level
, const char *fmt
, ...)
219 vlog(level
, "kernel", fmt
, ap
); /* Call actual function */
224 vlog(unsigned long level
, const char *tag
, const char *fmt
, va_list ap
)
226 struct SysLogPacket
*msg
;
229 msg
= (struct SysLogPacket
*)GetLogMsg(&logReplyPort
);
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
);
238 cs
.CS_Length
= log_cnf
.log_buf_len
;
241 cs
.CS_Buffer
= msg
->String
;
246 vcsprintf(&cs
, fmt
, ap
);
247 msg
->Level
= level
& (LOG_FACMASK
| LOG_PRIMASK
); /* Level of message */
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
);
257 /****i* bsdsockets.library/printf ******************************************
260 * printf -- print to log
263 * printf(FormatString, Arguments...)
265 * ULONG printf( const char *, ...)
268 * Prints messages to log
269 * As log, also this is callable from interrupts.
271 * Specially for debugging prints.
274 * FormatString - This is a printf-style format string as for vcsprintf().
275 * Arguments - as in C-librarys printf()
278 * Number of characters printed.
282 * printf("line=%d, val=%x\n",
283 * __LINE__, very.interesting->value);
290 * vcsprintf(), vlog()
292 ******************************************************************************
297 printf(const char *fmt
, ...)
304 ret
= vlog(LOG_INFO
, "kernel", fmt
, ap
);
310 struct SysLogPacket
*msg
;
313 if (msg
= GetLogMsg(&logReplyPort
)) { /* Get next free message */
318 cs
.CS_Buffer
= msg
->String
;
319 cs
.CS_Length
= log_cnf
.log_buf_len
;
323 vcsprintf(&cs
, fmt
, 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
;
338 /****i* bsdsocket.library/sprintf ******************************************
341 * sprintf -- print to buffer
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*, ...)
351 * Prints to a simple buffer or to a CSource buffer. These functions
352 * are similar to C-library sprintf() with restricted formatting.
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
359 * Arguments - as in printf() .
360 * cs - Pointer to CSource structure.
363 * Number of characters printed.
366 * sprintf(mybuf, "line=%d, val=%x\n",
367 * __LINE__, very.interesting->value);
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
380 ****************************************************************************
385 vcsprintf(struct CSource
*cs
, const char *fmt
, va_list ap
)
387 ULONG start
= cs
->CS_CurChr
;
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
) {
400 while ((ch
= *fmt
++) != '%') {
408 switch (ch
= *fmt
++) {
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';
420 if (ch
< '0' || ch
> '9')
424 case '.': /* precision */
425 for (precision
= 0; (ch
= *fmt
) >= '0' && ch
<= '9'; ++fmt
) {
426 precision
= precision
* 10 + ch
- '0';
436 ul
= va_arg(ap
, int);
437 p
= va_arg(ap
, char *);
438 for (tp
= csprintn(ul
, *p
++, buf
, sizeof(buf
)); ch
= *tp
++;)
444 for (tmp
= 0; n
= *p
++;) {
445 if (ul
& (1 << (n
- 1))) {
446 cs_putchar(tmp
? ',' : '<', cs
);
447 for (; (n
= *p
) > ' '; ++p
)
451 for (; *p
> ' '; ++p
)
459 p
= va_arg(ap
, char *);
461 vcsprintf(cs
, p
, va_arg(ap
, va_list));
463 vcsprintf(cs
, p
, va_arg(ap
, void *));
465 /* vcsprintf(cs, p, va_arg(ap, va_list));*/
468 *buf
= va_arg(ap
, int);
473 p
= va_arg(ap
, char *);
476 * Set width to the maximum width, if maximum width is set, and
479 if (precision
> 0 && width
> precision
)
482 * spit out necessary pad characters to fill on left, if necessary
484 if (width
> 0 && !leftjustify
&& (width
-= strlen(p
)) > 0)
486 cs_putchar(padc
, cs
);
487 /* take a copy of the original pointer */
490 * Copy the characters, pay attention to the fact that precision
491 * may not be exceeded.
493 while ((ch
= *p
++) && precision
-- != 0)
496 * spit out necessary pad characters to fill on right, if necessary
498 if (width
> 0 && leftjustify
&& (width
-= ((u_long
)p
- ul
- 1)) > 0)
504 ul
= lflag
? va_arg(ap
, long) : va_arg(ap
, int);
512 ul
= lflag
? va_arg(ap
, u_long
) : va_arg(ap
, u_int
);
516 ul
= lflag
? va_arg(ap
, u_long
) : va_arg(ap
, u_int
);
519 case 'p': /* pointers */
526 ul
= lflag
? va_arg(ap
, u_long
) : va_arg(ap
, u_int
);
529 p
= csprintn(ul
, base
, buf
, sizeof(buf
));
530 tmp
= (buf
+ sizeof(buf
) - 1) - p
; /* length */
531 if (width
> 0 && !leftjustify
&& (width
-= tmp
) > 0)
533 cs_putchar(padc
, cs
);
536 if (width
> 0 && leftjustify
&& (width
-= tmp
) > 0)
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
;
559 /* A pathological case */
564 int csprintf(struct CSource
*cs
, const char *fmt
, ...)
570 len
= vcsprintf(cs
, fmt
, ap
);
576 int vsprintf(char *buf
, const char *fmt
, va_list ap
)
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
, ...)
593 len
= vsprintf(buf
, fmt
, ap
);
600 csprintn(u_long n
, int base
, char *buf
, int buflen
)
602 register char *cp
= buf
+ buflen
- 1;
607 *cp
= "0123456789abcdef"[n
% base
];