Annotation of embedaddon/ntp/ElectricFence/print.c, revision 1.1.1.1

1.1       misho       1: #include "efence.h"
                      2: #include <stdlib.h>
                      3: #include <unistd.h>
                      4: #include <stdarg.h>
                      5: #include <string.h>
                      6: #include <signal.h>
                      7: 
                      8: /*
                      9:  * These routines do their printing without using stdio. Stdio can't
                     10:  * be used because it calls malloc(). Internal routines of a malloc()
                     11:  * debugger should not re-enter malloc(), so stdio is out.
                     12:  */
                     13: 
                     14: /*
                     15:  * NUMBER_BUFFER_SIZE is the longest character string that could be needed
                     16:  * to represent an unsigned integer, assuming we might print in base 2.
                     17:  */
                     18: #define        NUMBER_BUFFER_SIZE      (sizeof(ef_number) * NBBY)
                     19: 
                     20: static void
                     21: printNumber(ef_number number, ef_number base)
                     22: {
                     23:        char            buffer[NUMBER_BUFFER_SIZE];
                     24:        char *          s = &buffer[NUMBER_BUFFER_SIZE];
                     25:        int             size;
                     26:        
                     27:        do {
                     28:                ef_number       digit;
                     29: 
                     30:                if ( --s == buffer )
                     31:                        EF_Abort("Internal error printing number.");
                     32: 
                     33:                digit = number % base;
                     34: 
                     35:                if ( digit < 10 )
                     36:                        *s = '0' + digit;
                     37:                else
                     38:                        *s = 'a' + digit - 10;
                     39: 
                     40:        } while ( (number /= base) > 0 );
                     41: 
                     42:        size = &buffer[NUMBER_BUFFER_SIZE] - s;
                     43: 
                     44:        if ( size > 0 )
                     45:                write(2, s, size);
                     46: }
                     47: 
                     48: static void
                     49: vprint(const char * pattern, va_list args)
                     50: {
                     51:        static const char       bad_pattern[] =
                     52:         "\nBad pattern specifier %%%c in EF_Print().\n";
                     53:        const char *    s = pattern;
                     54:        char            c;
                     55: 
                     56:        while ( (c = *s++) != '\0' ) {
                     57:                if ( c == '%' ) {
                     58:                        c = *s++;
                     59:                        switch ( c ) {
                     60:                        case '%':
                     61:                                (void) write(2, &c, 1);
                     62:                                break;
                     63:                        case 'a':
                     64:                                /*
                     65:                                 * Print an address passed as a void pointer.
                     66:                                 * The type of ef_number must be set so that
                     67:                                 * it is large enough to contain all of the
                     68:                                 * bits of a void pointer.
                     69:                                 */
                     70:                                printNumber(
                     71:                                 (ef_number)va_arg(args, void *)
                     72:                                ,0x10);
                     73:                                break;
                     74:                        case 's':
                     75:                                {
                     76:                                        const char *    string;
                     77:                                        size_t          length;
                     78: 
                     79:                                        string = va_arg(args, char *);
                     80:                                        length = strlen(string);
                     81: 
                     82:                                        (void) write(2, string, length);
                     83:                                }
                     84:                                break;
                     85:                        case 'd':
                     86:                                {
                     87:                                        int     n = va_arg(args, int);
                     88: 
                     89:                                        if ( n < 0 ) {
                     90:                                                char    c = '-';
                     91:                                                write(2, &c, 1);
                     92:                                                n = -n;
                     93:                                        }
                     94:                                        printNumber(n, 10);
                     95:                                }
                     96:                                break;
                     97:                        case 'x':
                     98:                                printNumber(va_arg(args, u_int), 0x10);
                     99:                                break;
                    100:                        case 'c':
                    101:                                {
                    102:                                        char    c = va_arg(args, char);
                    103:                                        
                    104:                                        (void) write(2, &c, 1);
                    105:                                }
                    106:                                break;
                    107:                        default:
                    108:                                {
                    109:                                        EF_Print(bad_pattern, c);
                    110:                                }
                    111:                
                    112:                        }
                    113:                }
                    114:                else
                    115:                        (void) write(2, &c, 1);
                    116:        }
                    117: }
                    118: 
                    119: void
                    120: EF_Abort(const char * pattern, ...)
                    121: {
                    122:        va_list args;
                    123: 
                    124:        va_start(args, pattern);
                    125: 
                    126:        EF_Print("\nElectricFence Aborting: ");
                    127:        vprint(pattern, args);
                    128:        EF_Print("\n");
                    129: 
                    130:        va_end(args);
                    131: 
                    132:        /*
                    133:         * I use kill(getpid(), SIGILL) instead of abort() because some
                    134:         * mis-guided implementations of abort() flush stdio, which can
                    135:         * cause malloc() or free() to be called.
                    136:         */
                    137:        kill(getpid(), SIGILL);
                    138:        /* Just in case something handles SIGILL and returns, exit here. */
                    139:        _exit(-1);
                    140: }
                    141: 
                    142: void
                    143: EF_Exit(const char * pattern, ...)
                    144: {
                    145:        va_list args;
                    146: 
                    147:        va_start(args, pattern);
                    148: 
                    149:        EF_Print("\nElectricFence Exiting: ");
                    150:        vprint(pattern, args);
                    151:        EF_Print("\n");
                    152: 
                    153:        va_end(args);
                    154: 
                    155:        /*
                    156:         * I use _exit() because the regular exit() flushes stdio,
                    157:         * which may cause malloc() or free() to be called.
                    158:         */
                    159:        _exit(-1);
                    160: }
                    161: 
                    162: void
                    163: EF_Print(const char * pattern, ...)
                    164: {
                    165:        va_list args;
                    166: 
                    167:        va_start(args, pattern);
                    168:        vprint(pattern, args);
                    169:        va_end(args);
                    170: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>