home *** CD-ROM | disk | FTP | other *** search
- RCS_ID_C="$Id: subr_prf.c,v 1.33 1994/02/16 06:07:33 jraja Exp $";
- /*
- * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>,
- * Helsinki University of Technology, Finland.
- * All rights reserved.
- *
- * HISTORY
- * $Log: subr_prf.c,v $
- * Revision 1.33 1994/02/16 06:07:33 jraja
- * Replaced RawDoFmt() calls with vcsprintf(), which now does the formatting
- * itself. Changed stuffchar() to cs_putchar(), added csprintn() to print
- * out numbers.
- * Changed vlog() to return the number of characters written, changed
- * printf() to use vlog() (wheir code was identical).
- *
- * Revision 1.32 1994/01/05 10:27:30 jraja
- * Added IntuitionBase opening and closing to the panic().
- * Note: using a local library base variable might not work in GCC?
- *
- * Revision 1.31 1993/12/21 22:06:48 jraja
- * Changed implicit structure member (s_sec) to explicit (tv_secs) on timeval.
- *
- * Revision 1.30 1993/11/06 23:51:22 ppessi
- * Added csprintf(), sprintf function using CSource.
- * Added vsprintf() and vcsprintf() as well.
- *
- * Revision 1.29 1993/10/07 22:41:34 ppessi
- * Added time to the log message.
- *
- * Revision 1.28 1993/05/16 00:11:12 jraja
- * Removed redundant volatile keyword.
- *
- * Revision 1.27 93/05/14 15:54:17 15:54:17 ppessi (Pekka Pessi)
- * Minor prototype fixes.
- *
- * Revision 1.26 93/05/05 16:10:15 16:10:15 puhuri (Markus Peuhkuri)
- * Fixes for final demo.
- *
- * Revision 1.25 93/05/04 12:40:07 12:40:07 puhuri (Markus Peuhkuri)
- * Fixed PANICBUFFER (SASC didnt like implicit alloca())
- * Now log takes care of keeping level on right range.
- *
- * Revision 1.24 93/04/29 22:02:44 22:02:44 puhuri (Markus Peuhkuri)
- * fixed variable names to use configuration structure.
- *
- * Revision 1.23 93/04/28 12:59:05 12:59:05 puhuri (Markus Peuhkuri)
- * Fixed stdargs.h to stdarg.h
- *
- * Revision 1.22 93/04/27 10:23:19 10:23:19 puhuri (Markus Peuhkuri)
- * Add vlog-function for calling log from API. log() calls now vlog().
- *
- * Revision 1.21 93/04/26 18:55:08 18:55:08 puhuri (Markus Peuhkuri)
- * Moved contents of closelog to log_deinit() and removed closelog.
- *
- * Revision 1.20 93/04/26 11:54:46 11:54:46 too (Tomi Ollila)
- * Changed include paths of amiga_api.h, amiga_libcallentry.h and amiga_raf.h
- * from kern to api
- *
- * Revision 1.19 93/04/23 02:28:38 02:28:38 ppessi (Pekka Pessi)
- * Number and length of logging messages made configureable.
- *
- * Revision 1.18 93/04/21 19:08:46 19:08:46 puhuri (Markus Peuhkuri)
- * Now checks if process run into panic() was AmiTCP.
- * Now uses new structure to log_msg. (Printing of priority is in
- * NETTRACE)
- *
- * Revision 1.17 93/04/06 15:15:55 15:15:55 jraja (Jarno Tapio Rajahalme)
- * Changed spl function return value storage to spl_t,
- * changed bcopys and bzeros to aligned and/or const when possible,
- * added inclusion of conf.h to every .c file.
- *
- * Revision 1.16 93/03/20 07:06:38 07:06:38 ppessi (Pekka Pessi)
- * Fixed memory leak caused by task_remove()
- *
- * Revision 1.15 93/03/19 14:14:54 14:14:54 too (Tomi Ollila)
- * Code changes at night 17-18 March 1993
- *
- * Revision 1.14 93/03/15 09:12:42 09:12:42 jraja (Jarno Tapio Rajahalme)
- * Checkin' mods made by ppessi.
- *
- * Revision 1.13 93/03/13 00:05:31 00:05:31 ppessi (Pekka Pessi)
- * Quick'n'dirty fix for PANICBUFFER; some prototypes fixed.
- *
- * Revision 1.12 93/03/10 17:14:12 17:14:12 puhuri (Markus Peuhkuri)
- * Fixed documentation. Now (s)printf returns number of printed chars.
- *
- * Revision 1.11 93/03/09 13:33:11 13:33:11 puhuri (Markus Peuhkuri)
- * See messages for amiga_log.c/1.10.
- * Now uses new function to get log message.
- * Fixed a bug in closing of log (caused a read from low memory, 0x14)
- *
- * Revision 1.10 93/03/05 21:11:17 21:11:17 jraja (Jarno Tapio Rajahalme)
- * Fixed includes (again).
- *
- * Revision 1.9 93/03/05 12:32:33 12:32:33 jraja (Jarno Tapio Rajahalme)
- * Removed #include <kern/amiga_api_protos.h>.
- *
- * Revision 1.8 93/03/05 03:26:17 03:26:17 ppessi (Pekka Pessi)
- * Compiles with SASC. Initial test version.
- *
- * Revision 1.7 93/03/02 18:25:12 18:25:12 puhuri (Markus Peuhkuri)
- * Add sprintf() and fixed documentation
- *
- * Revision 1.6 93/03/02 16:10:35 16:10:35 puhuri (Markus Peuhkuri)
- * Removed amiga.lib functions, fixed memory managment
- *
- * Revision 1.5 93/02/26 19:44:35 19:44:35 puhuri (Markus Peuhkuri)
- * Modified to use MsgPort as list of free messages,
- * made log() and printf() re-entrant, removed kprintf (replaced w/
- * exec/RawDoFmt()), kernputchar, ksprintn() and logpri.
- * As every BSD/Mach code was removed so was copyright.
- *
- * Revision 1.4 93/02/25 19:39:25 19:39:25 puhuri (Markus Peuhkuri)
- * Includes fixed, compatible with both GCC and SAS,
- * function declarations fixed, calls from panic() fixed,
- * checks for various places.
- *
- * Revision 1.3 93/02/24 17:32:17 17:32:17 puhuri (Markus Peuhkuri)
- * Add printf (for printing to log)
- *
- * Revision 1.2 93/02/24 17:22:23 17:22:23 puhuri (Markus Peuhkuri)
- * Made program to work much cleanier, still uses Amiga.lib
- *
- * Revision 1.1 92/12/17 18:19:42 puhuri
- * Initial revision
- *
- */
-
- #include <conf.h>
-
- #include <sys/param.h>
- #include <sys/systm.h>
- #include <sys/syslog.h>
- #include <sys/time.h>
-
- #include <kern/amiga_includes.h>
- #include <api/amiga_api.h>
- #include <api/amiga_libcallentry.h>
- #include <kern/amiga_log.h>
- #include <stdarg.h>
- #include <intuition/intuition.h>
-
- #if __GNUC__
- #include <inline/intuition.h>
- #elif __SASC
- #include <proto/intuition.h>
- #endif
-
- #include <kern/amiga_main_protos.h>
- #include <dos/rdargs.h> /* CSource */
-
- extern void exit(int);
-
- void
- cs_putchar(unsigned char ch, struct CSource * cs)
- {
- if (cs->CS_CurChr < cs->CS_Length
- && (cs->CS_Buffer[cs->CS_CurChr] = ch))
- cs->CS_CurChr++;
- }
-
- /****i* bsdsocket.library/panic ******************************************
- *
- * NAME
- * panic -- Inform user from serious failure.
- *
- * SYNOPSIS
- * panic(Message, Arguments...)
- *
- * void panic( STRPTR, ... )
- *
- * FUNCTION
- * Calls api_setfunctions() with no arguments to stop programs using
- * AmiTCP. Writes message to log file. Sets up User Requester to
- * inform user about situation. Avoids self-loops.
- *
- *
- * INPUTS
- * Messagestring - A pointer to string containing message to show
- * to user and to write to log. It should describe problem so
- * that user can take correcting action if it is failure with
- * his configuration or is able to write bug report if it is
- * a bug withn program.
- *
- * Arguments - as in c-library printf()
- *
- * RESULT
- * This function does not return.
- *
- * EXAMPLE
- * if(Everything==WRONG)
- * panic("Everything is wrong\nGoto sleep");
- *
- * NOTES
- * As panic does not return, it should be used only in extreme
- * cases
- *
- * BUGS
- *
- * SEE ALSO
- * log()
- *
- ******************************************************************************
- *
- */
-
- #define PANICBUFFERSIZE 512
-
- void
- panic(const char *fmt,...)
- {
- struct EasyStruct panicES = {
- sizeof( struct EasyStruct),
- NULL,
- "AmiTCP PANIC",
- "panic: %s" ,
- "Exit AmiTCP"
- };
- static in_panic = 0;
- struct CSource cs;
- char buffer[PANICBUFFERSIZE];
- va_list ap;
- struct Library *IntuitionBase = NULL; /* local intuitionbase */
- extern struct Task *AmiTCP_Task;
-
- if (!in_panic){
- /* If we're called previously.. */
- in_panic++; /* We're in panic now */
- api_setfunctions(); /* Set libraries to return error code */
-
- cs.CS_Buffer = buffer;
- cs.CS_CurChr = 0;
- cs.CS_Length = PANICBUFFERSIZE;
-
- va_start(ap, fmt);
- vcsprintf(&cs, fmt, ap);
- va_end(ap);
-
- log(LOG_EMERG, "panic: %s", buffer); /* Write to log */
- }
- in_panic--;
-
- /*
- * Inform user (if log system has failed...)
- * by opening a requester to the default public screen.
- *
- * Open a local IntuitionBase for the EasyRequestArgs()
- */
- if ((IntuitionBase = OpenLibrary("intuition.library", 37L)) != NULL) {
- EasyRequestArgs(NULL, &panicES, NULL, (char *)&buffer);
- CloseLibrary(IntuitionBase);
- IntuitionBase = NULL;
- }
-
- /*
- * If the caller is not the AmiTCP task, sleep forever.
- * This should go to API or where ever we came in AmiTCP code
- */
- if (FindTask(NULL) != AmiTCP_Task)
- Wait(0);
-
- Wait(SIGBREAKF_CTRL_F); /* AmiTCP/IP waits here */
-
- /*
- * Following code is not safe. Probably we should wait infinetely long too...
- */
- deinit_all(); /* This returns !! */
- exit(20); /* This should be safe... */
- }
-
- /****i* bsdsockets.library/log ******************************************
- *
- * NAME
- * log -- Write log message to log and/or console.
- *
- * SYNOPSIS
- * log(Level, FormatString, arguments...)
- *
- * void log( ULONG, STRPTR, ...)
- *
- * FUNCTION
- * Writes message given as format string and arguments
- * (printf-style) to both log and console (except if level is
- * LOG_EMERG, LOG_EMERG is generated only by panic and it is
- * written only to the log file as panic() generates an User
- * Requester informing user.
- *
- * This function can be called from interrupts.
- *
- * INPUTS
- * Level - indicates type of logged message. These levels are
- * defined in sys/syslog.h.
- * FormatString - This is a printf-style format string with some
- * restrictions (notably the floats are not handled).
- * arguments - as in printf()
- *
- * RESULT
- * Returns no value.
- *
- * EXAMPLE
- * log(LOG_ERR,
- * "arp: ether address is broadcast for IP address %x!\n",
- * ntohl(isaddr.s_addr));
- * fail=TRUE;
- * break;
- *
- * NOTES
- *
- * BUGS
- *
- * SEE ALSO
- * Your C-compilers printf() documentation.
- *
- ******************************************************************************
- *
- */
-
- void
- log(unsigned long level, const char *fmt, ...)
- {
- va_list ap;
-
- va_start(ap, fmt);
- vlog(level, fmt, ap); /* Call actual function */
- va_end(ap);
- }
-
- ULONG
- vlog(unsigned long level, const char *fmt, va_list ap)
- {
- struct log_msg *msg;
- struct timeval now;
- if (msg = (struct log_msg *)GetLogMsg(logReplyPort)) {
- ULONG ret;
- struct CSource cs;
- cs.CS_Buffer = msg->string;
- cs.CS_Length = log_cnf.log_buf_len;
- cs.CS_CurChr = 0;
-
- GetSysTime(&now);
-
- vcsprintf(&cs, fmt, ap);
- msg->level = level & (LOG_FACMASK | LOG_PRIMASK); /* Level of message */
- ret = msg->chars = cs.CS_CurChr;
- msg->time = now.tv_secs;
- PutMsg(logPort, (struct Message *)msg);
- return ret;
- }
- return 0;
- }
-
- /****i* bsdsockets.library/printf ******************************************
- *
- * NAME
- * printf -- print to log
- *
- * SYNOPSIS
- * printf(FormatString, Arguments...)
- *
- * ULONG printf( const char *, ...)
- *
- * FUNCTION
- * Prints messages to log
- * As log, also this is callable from interrupts.
- *
- * Specially for debugging prints.
- *
- * INPUTS
- * FormatString - This is a printf-style format string as for vcsprintf().
- * Arguments - as in C-librarys printf()
- *
- * RESULT
- * Number of characters printed.
- *
- * EXAMPLE
- *
- * printf("line=%d, val=%x\n",
- * __LINE__, very.interesting->value);
- *
- * NOTES
- *
- * BUGS
- *
- * SEE ALSO
- * vcsprintf(), vlog()
- *
- ******************************************************************************
- *
- */
- ULONG
- printf(const char *fmt, ...)
- {
- #if 1
- ULONG ret;
- va_list ap;
-
- va_start(ap, fmt);
- ret = vlog(LOG_INFO, fmt, ap);
- va_end(ap);
-
- return ret;
- #else
- va_list ap;
- struct log_msg *msg;
- struct timeval now;
-
- if (msg = GetLogMsg(logReplyPort)) { /* Get next free message */
- struct CSource cs;
-
- GetSysTime(&now);
-
- cs.CS_Buffer = msg->string;
- cs.CS_Length = log_cnf.log_buf_len;
- cs.CS_CurChr = 0;
-
- va_start(ap, fmt);
- vcsprintf(&cs, fmt, ap);
- va_end(ap);
-
- msg->level = LOG_INFO;
- msg->chars = cs.CS_CurChr;
- msg->time = now.tv_secs;
- PutMsg(logPort,(struct Message *)msg);
-
- return (ULONG)cs.CS_CurChr;
- } else
- return 0;
- #endif
- }
-
- /****i* bsdsockets.library/sprintf ******************************************
- *
- * NAME
- * sprintf -- print to buffer
- *
- * SYNOPSIS
- * len = sprintf(Buffer, FormatString, Arguments...)
- * len = csprintf(cs, FormatString, Arguments...)
- *
- * ULONG sprintf(STRPTR, const char*, ...)
- * ULONG csprintf(struct CSource *, const char*, ...)
- *
- * FUNCTION
- * Prints to a simple buffer or to a CSource buffer. These functions
- * are similar to C-library sprintf() with restricted formatting.
- *
- * INPUTS
- * Buffer - Pointer to buffer.
- * FormatString - This is a printf()-style format string with some
- * restrictions. Numbers are being taken as 'long' by
- * default, however.
- * Arguments - as in printf() .
- * cs - Pointer to CSource structure.
- *
- * RESULT
- * Number of characters printed.
- *
- * EXAMPLE
- * sprintf(mybuf, "line=%d, val=%x\n",
- * __LINE__, very.interesting->value);
- *
- * BUGS
- * Function sprintf() assumes that no print is longer than 1024 chars.
- * It does not check for buffer owerflow (there no way to check, the
- * definition of sprintf misses it).
- *
- * sprintf strings are truncated to maximum of 1024 chars (including
- * final NUL)
- *
- * SEE ALSO
- * vcsprintf()
- *
- ******************************************************************************
- *
- */
-
- ULONG
- vcsprintf(struct CSource *cs, const char *fmt, va_list ap)
- {
- ULONG start = cs->CS_CurChr;
- char *p, ch, padc;
- u_long ul;
- int n, base, lflag, tmp, width, precision, leftjustify;
- char buf[sizeof(long) * NBBY / 3 + 2]; /* A long in base 8, plus '\0'. */
-
- if (cs->CS_Length && cs->CS_CurChr < cs->CS_Length) {
-
- for (;;) {
- padc = ' ';
- width = 0;
- precision = -1;
- leftjustify = FALSE;
- while ((ch = *fmt++) != '%') {
- if (ch == '\0') {
- goto end;
- }
- cs_putchar(ch, cs);
- }
- lflag = 0;
- reswitch:
- switch (ch = *fmt++) {
- case '-':
- leftjustify = TRUE;
- goto reswitch;
- case '0':
- padc = '0';
- goto reswitch;
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- for (width = 0;; ++fmt) {
- width = width * 10 + ch - '0';
- ch = *fmt;
- if (ch < '0' || ch > '9')
- break;
- }
- goto reswitch;
- case '.': /* precision */
- for (precision = 0; (ch = *fmt) >= '0' && ch <= '9'; ++fmt) {
- precision = precision * 10 + ch - '0';
- }
- goto reswitch;
- case 'l':
- lflag = 1;
- goto reswitch;
- case 'b':
- {
- char *tp;
-
- ul = va_arg(ap, int);
- p = va_arg(ap, char *);
- for (tp = csprintn(ul, *p++, buf, sizeof(buf)); ch = *tp++;)
- cs_putchar(ch, cs);
-
- if (!ul)
- break;
-
- for (tmp = 0; n = *p++;) {
- if (ul & (1 << (n - 1))) {
- cs_putchar(tmp ? ',' : '<', cs);
- for (; (n = *p) > ' '; ++p)
- cs_putchar(n, cs);
- tmp = 1;
- } else
- for (; *p > ' '; ++p)
- ;
- }
- if (tmp)
- cs_putchar('>', cs);
- }
- break;
- case 'r':
- p = va_arg(ap, char *);
- vcsprintf(cs, p, va_arg(ap, va_list));
- break;
- case 'c':
- *buf = va_arg(ap, int);
- buf[1] = '\0';
- p = buf;
- goto textout;
- case 's':
- p = va_arg(ap, char *);
- textout:
- /*
- * Set width to the maximum width, if maximum width is set, and
- * width exceeds it.
- */
- if (precision > 0 && width > precision)
- width = precision;
- /*
- * spit out necessary pad characters to fill on left, if necessary
- */
- if (width > 0 && !leftjustify && (width -= strlen(p)) > 0)
- while (width--)
- cs_putchar(padc, cs);
- /* take a copy of the original pointer */
- ul = (u_long)p;
- /*
- * Copy the characters, pay attention to the fact that precision
- * may not be exceeded.
- */
- while ((ch = *p++) && precision-- != 0)
- cs_putchar(ch, cs);
- /*
- * spit out necessary pad characters to fill on right, if necessary
- */
- if (width > 0 && leftjustify && (width -= ((u_long)p - ul - 1)) > 0)
- while (width--)
- cs_putchar(' ', cs);
- break;
- case 'd':
- case 'i':
- ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
- if ((long)ul < 0) {
- cs_putchar('-', cs);
- ul = -(long)ul;
- }
- base = 10;
- goto number;
- case 'o':
- ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
- base = 8;
- goto number;
- case 'u':
- ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
- base = 10;
- goto number;
- case 'p': /* pointers */
- case 'P':
- width = 8;
- padc = '0';
- /* FALLTHROUGH */
- case 'x':
- case 'X':
- ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
- base = 16;
- number:
- p = csprintn(ul, base, buf, sizeof(buf));
- tmp = (buf + sizeof(buf) - 1) - p; /* length */
- if (width > 0 && !leftjustify && (width -= tmp) > 0)
- while (width--)
- cs_putchar(padc, cs);
- while (ch = *p++)
- cs_putchar(ch, cs);
- if (width > 0 && leftjustify && (width -= tmp) > 0)
- while (width--)
- cs_putchar(' ', cs);
- break;
- default:
- cs_putchar('%', cs);
- if (lflag)
- cs_putchar('l', cs);
- /* FALLTHROUGH */
- case '%':
- cs_putchar(ch, cs);
- }
- }
-
- end:
-
- if (cs->CS_CurChr == cs->CS_Length) {
- cs->CS_CurChr--; /* must NUL terminate */
- }
- cs->CS_Buffer[cs->CS_CurChr] = '\0';
-
- return cs->CS_CurChr - start;
- } else {
- /* A pathological case */
- return 0;
- }
- }
-
- ULONG csprintf(struct CSource *cs, const char *fmt, ...)
- {
- va_list ap;
- ULONG len;
-
- va_start(ap, fmt);
- len = vcsprintf(cs, fmt, ap);
- va_end(ap);
- return len;
- }
-
- ULONG vsprintf(char *buf, const char *fmt, va_list ap)
- {
- struct CSource cs;
-
- cs.CS_Buffer = buf;
- cs.CS_CurChr = 0;
- cs.CS_Length = 1024; /* This is not probably the cleanest way :-) */
-
- return vcsprintf(&cs, fmt, ap);
- }
-
- ULONG sprintf(char *buf, const char *fmt, ...)
- {
- va_list ap;
- ULONG len;
-
- va_start(ap, fmt);
- len = vsprintf(buf, fmt, ap);
- va_end(ap);
- return len;
- }
-
- char *
- csprintn(u_long n, int base, char *buf, int buflen)
- {
- register char *cp = buf + buflen - 1;
-
- *cp = 0;
- do {
- cp--;
- *cp = "0123456789abcdef"[n % base];
- } while (n /= base);
- return (cp);
- }
-