Annotation of embedaddon/ntp/ElectricFence/print.c, revision 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>