Annotation of embedaddon/dhcp/common/print.c, revision 1.1

1.1     ! misho       1: /* print.c
        !             2: 
        !             3:    Turn data structures into printable text. */
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 2009-2011 by Internet Systems Consortium, Inc. ("ISC")
        !             7:  * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
        !             8:  * Copyright (c) 1995-2003 by Internet Software Consortium
        !             9:  *
        !            10:  * Permission to use, copy, modify, and distribute this software for any
        !            11:  * purpose with or without fee is hereby granted, provided that the above
        !            12:  * copyright notice and this permission notice appear in all copies.
        !            13:  *
        !            14:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
        !            15:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            16:  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
        !            17:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            18:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            19:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
        !            20:  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            21:  *
        !            22:  *   Internet Systems Consortium, Inc.
        !            23:  *   950 Charter Street
        !            24:  *   Redwood City, CA 94063
        !            25:  *   <info@isc.org>
        !            26:  *   https://www.isc.org/
        !            27:  *
        !            28:  * This software has been written for Internet Systems Consortium
        !            29:  * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
        !            30:  * To learn more about Internet Systems Consortium, see
        !            31:  * ``https://www.isc.org/''.  To learn more about Vixie Enterprises,
        !            32:  * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
        !            33:  * ``http://www.nominum.com''.
        !            34:  */
        !            35: 
        !            36: #include "dhcpd.h"
        !            37: 
        !            38: int db_time_format = DEFAULT_TIME_FORMAT;
        !            39: 
        !            40: char *quotify_string (const char *s, const char *file, int line)
        !            41: {
        !            42:        unsigned len = 0;
        !            43:        const char *sp;
        !            44:        char *buf, *nsp;
        !            45: 
        !            46:        for (sp = s; sp && *sp; sp++) {
        !            47:                if (*sp == ' ')
        !            48:                        len++;
        !            49:                else if (!isascii ((int)*sp) || !isprint ((int)*sp))
        !            50:                        len += 4;
        !            51:                else if (*sp == '"' || *sp == '\\')
        !            52:                        len += 2;
        !            53:                else
        !            54:                        len++;
        !            55:        }
        !            56: 
        !            57:        buf = dmalloc (len + 1, file, line);
        !            58:        if (buf) {
        !            59:                nsp = buf;
        !            60:                for (sp = s; sp && *sp; sp++) {
        !            61:                        if (*sp == ' ')
        !            62:                                *nsp++ = ' ';
        !            63:                        else if (!isascii ((int)*sp) || !isprint ((int)*sp)) {
        !            64:                                sprintf (nsp, "\\%03o",
        !            65:                                         *(const unsigned char *)sp);
        !            66:                                nsp += 4;
        !            67:                        } else if (*sp == '"' || *sp == '\\') {
        !            68:                                *nsp++ = '\\';
        !            69:                                *nsp++ = *sp;
        !            70:                        } else
        !            71:                                *nsp++ = *sp;
        !            72:                }
        !            73:                *nsp++ = 0;
        !            74:        }
        !            75:        return buf;
        !            76: }
        !            77: 
        !            78: char *quotify_buf (const unsigned char *s, unsigned len,
        !            79:                   const char *file, int line)
        !            80: {
        !            81:        unsigned nulen = 0;
        !            82:        char *buf, *nsp;
        !            83:        int i;
        !            84: 
        !            85:        for (i = 0; i < len; i++) {
        !            86:                if (s [i] == ' ')
        !            87:                        nulen++;
        !            88:                else if (!isascii (s [i]) || !isprint (s [i]))
        !            89:                        nulen += 4;
        !            90:                else if (s [i] == '"' || s [i] == '\\')
        !            91:                        nulen += 2;
        !            92:                else
        !            93:                        nulen++;
        !            94:        }
        !            95: 
        !            96:        buf = dmalloc (nulen + 1, MDL);
        !            97:        if (buf) {
        !            98:                nsp = buf;
        !            99:                for (i = 0; i < len; i++) {
        !           100:                        if (s [i] == ' ')
        !           101:                                *nsp++ = ' ';
        !           102:                        else if (!isascii (s [i]) || !isprint (s [i])) {
        !           103:                                sprintf (nsp, "\\%03o", s [i]);
        !           104:                                nsp += 4;
        !           105:                        } else if (s [i] == '"' || s [i] == '\\') {
        !           106:                                *nsp++ = '\\';
        !           107:                                *nsp++ = s [i];
        !           108:                        } else
        !           109:                                *nsp++ = s [i];
        !           110:                }
        !           111:                *nsp++ = 0;
        !           112:        }
        !           113:        return buf;
        !           114: }
        !           115: 
        !           116: char *print_base64 (const unsigned char *buf, unsigned len,
        !           117:                    const char *file, int line)
        !           118: {
        !           119:        char *s, *b;
        !           120:        unsigned bl;
        !           121:        int i;
        !           122:        unsigned val, extra;
        !           123:        static char to64 [] =
        !           124:           "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        !           125: 
        !           126:        bl = ((len * 4 + 2) / 3) + 1;
        !           127:        b = dmalloc (bl + 1, file, line);
        !           128:        if (!b)
        !           129:                return (char *)0;
        !           130:        
        !           131:        i = 0;
        !           132:        s = b;
        !           133:        while (i != len) {
        !           134:                val = buf [i++];
        !           135:                extra = val & 3;
        !           136:                val = val >> 2;
        !           137:                *s++ = to64 [val];
        !           138:                if (i == len) {
        !           139:                        *s++ = to64 [extra << 4];
        !           140:                        *s++ = '=';
        !           141:                        break;
        !           142:                }
        !           143:                val = (extra << 8) + buf [i++];
        !           144:                extra = val & 15;
        !           145:                val = val >> 4;
        !           146:                *s++ = to64 [val];
        !           147:                if (i == len) {
        !           148:                        *s++ = to64 [extra << 2];
        !           149:                        *s++ = '=';
        !           150:                        break;
        !           151:                }
        !           152:                val = (extra << 8) + buf [i++];
        !           153:                extra = val & 0x3f;
        !           154:                val = val >> 6;
        !           155:                *s++ = to64 [val];
        !           156:                *s++ = to64 [extra];
        !           157:        }
        !           158:        if (!len)
        !           159:                *s++ = '=';
        !           160:        *s++ = 0;
        !           161:        if (s > b + bl + 1)
        !           162:                abort ();
        !           163:        return b;
        !           164: }
        !           165: 
        !           166: char *print_hw_addr (htype, hlen, data)
        !           167:        int htype;
        !           168:        int hlen;
        !           169:        unsigned char *data;
        !           170: {
        !           171:        static char habuf [49];
        !           172:        char *s;
        !           173:        int i;
        !           174: 
        !           175:        if (hlen <= 0)
        !           176:                habuf [0] = 0;
        !           177:        else {
        !           178:                s = habuf;
        !           179:                for (i = 0; i < hlen; i++) {
        !           180:                        sprintf (s, "%02x", data [i]);
        !           181:                        s += strlen (s);
        !           182:                        *s++ = ':';
        !           183:                }
        !           184:                *--s = 0;
        !           185:        }
        !           186:        return habuf;
        !           187: }
        !           188: 
        !           189: void print_lease (lease)
        !           190:        struct lease *lease;
        !           191: {
        !           192:        struct tm *t;
        !           193:        char tbuf [32];
        !           194: 
        !           195:        log_debug ("  Lease %s",
        !           196:               piaddr (lease -> ip_addr));
        !           197:        
        !           198:        t = gmtime (&lease -> starts);
        !           199:        strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t);
        !           200:        log_debug ("  start %s", tbuf);
        !           201:        
        !           202:        t = gmtime (&lease -> ends);
        !           203:        strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t);
        !           204:        log_debug ("  end %s", tbuf);
        !           205:        
        !           206:        if (lease -> hardware_addr.hlen)
        !           207:                log_debug ("    hardware addr = %s",
        !           208:                           print_hw_addr (lease -> hardware_addr.hbuf [0],
        !           209:                                          lease -> hardware_addr.hlen - 1,
        !           210:                                          &lease -> hardware_addr.hbuf [1]));
        !           211:        log_debug ("  host %s  ",
        !           212:               lease -> host ? lease -> host -> name : "<none>");
        !           213: }      
        !           214: 
        !           215: #if defined (DEBUG_PACKET)
        !           216: void dump_packet_option (struct option_cache *oc,
        !           217:                         struct packet *packet,
        !           218:                         struct lease *lease,
        !           219:                         struct client_state *client,
        !           220:                         struct option_state *in_options,
        !           221:                         struct option_state *cfg_options,
        !           222:                         struct binding_scope **scope,
        !           223:                         struct universe *u, void *foo)
        !           224: {
        !           225:        const char *name, *dot;
        !           226:        struct data_string ds;
        !           227:        memset (&ds, 0, sizeof ds);
        !           228: 
        !           229:        if (u != &dhcp_universe) {
        !           230:                name = u -> name;
        !           231:                dot = ".";
        !           232:        } else {
        !           233:                name = "";
        !           234:                dot = "";
        !           235:        }
        !           236:        if (evaluate_option_cache (&ds, packet, lease, client,
        !           237:                                   in_options, cfg_options, scope, oc, MDL)) {
        !           238:                log_debug ("  option %s%s%s %s;\n",
        !           239:                           name, dot, oc -> option -> name,
        !           240:                           pretty_print_option (oc -> option,
        !           241:                                                ds.data, ds.len, 1, 1));
        !           242:                data_string_forget (&ds, MDL);
        !           243:        }
        !           244: }
        !           245: 
        !           246: void dump_packet (tp)
        !           247:        struct packet *tp;
        !           248: {
        !           249:        struct dhcp_packet *tdp = tp -> raw;
        !           250: 
        !           251:        log_debug ("packet length %d", tp -> packet_length);
        !           252:        log_debug ("op = %d  htype = %d  hlen = %d  hops = %d",
        !           253:               tdp -> op, tdp -> htype, tdp -> hlen, tdp -> hops);
        !           254:        log_debug ("xid = %x  secs = %ld  flags = %x",
        !           255:               tdp -> xid, (unsigned long)tdp -> secs, tdp -> flags);
        !           256:        log_debug ("ciaddr = %s", inet_ntoa (tdp -> ciaddr));
        !           257:        log_debug ("yiaddr = %s", inet_ntoa (tdp -> yiaddr));
        !           258:        log_debug ("siaddr = %s", inet_ntoa (tdp -> siaddr));
        !           259:        log_debug ("giaddr = %s", inet_ntoa (tdp -> giaddr));
        !           260:        log_debug ("chaddr = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
        !           261:               ((unsigned char *)(tdp -> chaddr)) [0],
        !           262:               ((unsigned char *)(tdp -> chaddr)) [1],
        !           263:               ((unsigned char *)(tdp -> chaddr)) [2],
        !           264:               ((unsigned char *)(tdp -> chaddr)) [3],
        !           265:               ((unsigned char *)(tdp -> chaddr)) [4],
        !           266:               ((unsigned char *)(tdp -> chaddr)) [5]);
        !           267:        log_debug ("filename = %s", tdp -> file);
        !           268:        log_debug ("server_name = %s", tdp -> sname);
        !           269:        if (tp -> options_valid) {
        !           270:                int i;
        !           271: 
        !           272:                for (i = 0; i < tp -> options -> universe_count; i++) {
        !           273:                        if (tp -> options -> universes [i]) {
        !           274:                                option_space_foreach (tp, (struct lease *)0,
        !           275:                                                      (struct client_state *)0,
        !           276:                                                      (struct option_state *)0,
        !           277:                                                      tp -> options,
        !           278:                                                      &global_scope,
        !           279:                                                      universes [i], 0,
        !           280:                                                      dump_packet_option);
        !           281:                        }
        !           282:                }
        !           283:        }
        !           284:        log_debug ("%s", "");
        !           285: }
        !           286: #endif
        !           287: 
        !           288: void dump_raw (buf, len)
        !           289:        const unsigned char *buf;
        !           290:        unsigned len;
        !           291: {
        !           292:        int i;
        !           293:        char lbuf [80];
        !           294:        int lbix = 0;
        !           295: 
        !           296: /*
        !           297:           1         2         3         4         5         6         7
        !           298: 01234567890123456789012345678901234567890123456789012345678901234567890123
        !           299: 280: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   .................  
        !           300: */
        !           301: 
        !           302:        memset(lbuf, ' ', 79);
        !           303:        lbuf [79] = 0;
        !           304: 
        !           305:        for (i = 0; i < len; i++) {
        !           306:                if ((i & 15) == 0) {
        !           307:                  if (lbix) {
        !           308:                        lbuf[53]=' ';
        !           309:                        lbuf[54]=' ';
        !           310:                        lbuf[55]=' ';
        !           311:                        lbuf[73]='\0';
        !           312:                        log_info ("%s", lbuf);
        !           313:                  }
        !           314:                  memset(lbuf, ' ', 79);
        !           315:                  lbuf [79] = 0;
        !           316:                  sprintf (lbuf, "%03x:", i);
        !           317:                  lbix = 4;
        !           318:                } else if ((i & 7) == 0)
        !           319:                        lbuf [lbix++] = ' ';
        !           320: 
        !           321:                if(isprint(buf[i])) {
        !           322:                  lbuf[56+(i%16)]=buf[i];
        !           323:                } else {
        !           324:                  lbuf[56+(i%16)]='.';
        !           325:                }
        !           326: 
        !           327:                sprintf (&lbuf [lbix], " %02x", buf [i]);
        !           328:                lbix += 3;
        !           329:                lbuf[lbix]=' ';
        !           330: 
        !           331:        }
        !           332:        lbuf[53]=' ';
        !           333:        lbuf[54]=' ';
        !           334:        lbuf[55]=' ';
        !           335:        lbuf[73]='\0';
        !           336:        log_info ("%s", lbuf);
        !           337: }
        !           338: 
        !           339: void hash_dump (table)
        !           340:        struct hash_table *table;
        !           341: {
        !           342:        int i;
        !           343:        struct hash_bucket *bp;
        !           344: 
        !           345:        if (!table)
        !           346:                return;
        !           347: 
        !           348:        for (i = 0; i < table -> hash_count; i++) {
        !           349:                if (!table -> buckets [i])
        !           350:                        continue;
        !           351:                log_info ("hash bucket %d:", i);
        !           352:                for (bp = table -> buckets [i]; bp; bp = bp -> next) {
        !           353:                        if (bp -> len)
        !           354:                                dump_raw (bp -> name, bp -> len);
        !           355:                        else
        !           356:                                log_info ("%s", (const char *)bp -> name);
        !           357:                }
        !           358:        }
        !           359: }
        !           360: 
        !           361: /*
        !           362:  * print a string as hex.  This only outputs
        !           363:  * colon separated hex list no matter what
        !           364:  * the input looks like.  See print_hex
        !           365:  * for a function that prints either cshl
        !           366:  * or a string if all bytes are printible
        !           367:  * It only uses limit characters from buf
        !           368:  * and doesn't do anything if buf == NULL
        !           369:  *
        !           370:  * len - length of data
        !           371:  * data - input data
        !           372:  * limit - length of buf to use
        !           373:  * buf - output buffer
        !           374:  */
        !           375: void print_hex_only (len, data, limit, buf)
        !           376:        unsigned len;
        !           377:        const u_int8_t *data;
        !           378:        unsigned limit;
        !           379:        char *buf;
        !           380: {
        !           381:        unsigned i;
        !           382: 
        !           383:        if ((buf == NULL) || (limit < 3))
        !           384:                return;
        !           385: 
        !           386:        for (i = 0; (i < limit / 3) && (i < len); i++) {
        !           387:                sprintf(&buf[i*3], "%02x:", data[i]);
        !           388:        }
        !           389:        buf[(i * 3) - 1] = 0;
        !           390:        return;
        !           391: }
        !           392: 
        !           393: /*
        !           394:  * print a string as either text if all the characters
        !           395:  * are printable or colon separated hex if they aren't
        !           396:  *
        !           397:  * len - length of data
        !           398:  * data - input data
        !           399:  * limit - length of buf to use
        !           400:  * buf - output buffer
        !           401:  */
        !           402: void print_hex_or_string (len, data, limit, buf)
        !           403:        unsigned len;
        !           404:        const u_int8_t *data;
        !           405:        unsigned limit;
        !           406:        char *buf;
        !           407: {
        !           408:        unsigned i;
        !           409:        if ((buf == NULL) || (limit < 3))
        !           410:                return;
        !           411: 
        !           412:        for (i = 0; (i < (limit - 3)) && (i < len); i++) {
        !           413:                if (!isascii(data[i]) || !isprint(data[i])) {
        !           414:                        print_hex_only(len, data, limit, buf);
        !           415:                        return;
        !           416:                }
        !           417:        }
        !           418: 
        !           419:        buf[0] = '"';
        !           420:        i = len;
        !           421:        if (i > (limit - 3))
        !           422:                i = limit - 3;
        !           423:        memcpy(&buf[1], data, i);
        !           424:        buf[i + 1] = '"';
        !           425:        buf[i + 2] = 0;
        !           426:        return;
        !           427: }
        !           428: 
        !           429: /*
        !           430:  * print a string as either hex or text
        !           431:  * using static buffers to hold the output
        !           432:  * 
        !           433:  * len - length of data
        !           434:  * data - input data
        !           435:  * limit - length of buf
        !           436:  * buf_num - the output buffer to use
        !           437:  */
        !           438: #define HBLEN 1024
        !           439: char *print_hex(len, data, limit, buf_num)
        !           440:        unsigned len;
        !           441:        const u_int8_t *data;
        !           442:        unsigned limit;
        !           443:        unsigned buf_num;
        !           444: {
        !           445:        static char hex_buf_1[HBLEN + 1];
        !           446:        static char hex_buf_2[HBLEN + 1];
        !           447:        static char hex_buf_3[HBLEN + 1];
        !           448:        char *hex_buf;
        !           449: 
        !           450:        switch(buf_num) {
        !           451:          case 0:
        !           452:                hex_buf = hex_buf_1;
        !           453:                if (limit >= sizeof(hex_buf_1))
        !           454:                        limit = sizeof(hex_buf_1);
        !           455:                break;
        !           456:          case 1:
        !           457:                hex_buf = hex_buf_2;
        !           458:                if (limit >= sizeof(hex_buf_2))
        !           459:                        limit = sizeof(hex_buf_2);
        !           460:                break;
        !           461:          case 2:
        !           462:                hex_buf = hex_buf_3;
        !           463:                if (limit >= sizeof(hex_buf_3))
        !           464:                        limit = sizeof(hex_buf_3);
        !           465:                break;
        !           466:          default:
        !           467:                return(NULL);
        !           468:        }
        !           469: 
        !           470:        print_hex_or_string(len, data, limit, hex_buf);
        !           471:        return(hex_buf);
        !           472: }
        !           473: 
        !           474: #define DQLEN  80
        !           475: 
        !           476: char *print_dotted_quads (len, data)
        !           477:        unsigned len;
        !           478:        const u_int8_t *data;
        !           479: {
        !           480:        static char dq_buf [DQLEN + 1];
        !           481:        int i;
        !           482:        char *s, *last;
        !           483: 
        !           484:        s = &dq_buf [0];
        !           485:        last = s;
        !           486:        
        !           487:        i = 0;
        !           488: 
        !           489:        /* %Audit% Loop bounds checks to 21 bytes. %2004.06.17,Safe%
        !           490:         * The sprintf can't exceed 18 bytes, and since the loop enforces
        !           491:         * 21 bytes of space per iteration at no time can we exit the
        !           492:         * loop without at least 3 bytes spare.
        !           493:         */
        !           494:        do {
        !           495:                sprintf (s, "%u.%u.%u.%u, ",
        !           496:                         data [i], data [i + 1], data [i + 2], data [i + 3]);
        !           497:                s += strlen (s);
        !           498:                i += 4;
        !           499:        } while ((s - &dq_buf [0] > DQLEN - 21) &&
        !           500:                 i + 3 < len);
        !           501:        if (i == len)
        !           502:                s [-2] = 0;
        !           503:        else
        !           504:                strcpy (s, "...");
        !           505:        return dq_buf;
        !           506: }
        !           507: 
        !           508: char *print_dec_1 (val)
        !           509:        unsigned long val;
        !           510: {
        !           511:        static char vbuf [32];
        !           512:        sprintf (vbuf, "%lu", val);
        !           513:        return vbuf;
        !           514: }
        !           515: 
        !           516: char *print_dec_2 (val)
        !           517:        unsigned long val;
        !           518: {
        !           519:        static char vbuf [32];
        !           520:        sprintf (vbuf, "%lu", val);
        !           521:        return vbuf;
        !           522: }
        !           523: 
        !           524: static unsigned print_subexpression (struct expression *, char *, unsigned);
        !           525: 
        !           526: static unsigned print_subexpression (expr, buf, len)
        !           527:        struct expression *expr;
        !           528:        char *buf;
        !           529:        unsigned len;
        !           530: {
        !           531:        unsigned rv, left;
        !           532:        const char *s;
        !           533: 
        !           534:        switch (expr -> op) {
        !           535:              case expr_none:
        !           536:                if (len > 3) {
        !           537:                        strcpy (buf, "nil");
        !           538:                        return 3;
        !           539:                }
        !           540:                break;
        !           541:                  
        !           542:              case expr_match:
        !           543:                if (len > 7) {
        !           544:                        strcpy (buf, "(match)");
        !           545:                        return 7;
        !           546:                }
        !           547:                break;
        !           548: 
        !           549:              case expr_check:
        !           550:                rv = 10 + strlen (expr -> data.check -> name);
        !           551:                if (len > rv) {
        !           552:                        sprintf (buf, "(check %s)",
        !           553:                                 expr -> data.check -> name);
        !           554:                        return rv;
        !           555:                }
        !           556:                break;
        !           557: 
        !           558:              case expr_equal:
        !           559:                if (len > 6) {
        !           560:                        rv = 4;
        !           561:                        strcpy (buf, "(eq ");
        !           562:                        rv += print_subexpression (expr -> data.equal [0],
        !           563:                                                   buf + rv, len - rv - 2);
        !           564:                        buf [rv++] = ' ';
        !           565:                        rv += print_subexpression (expr -> data.equal [1],
        !           566:                                                   buf + rv, len - rv - 1);
        !           567:                        buf [rv++] = ')';
        !           568:                        buf [rv] = 0;
        !           569:                        return rv;
        !           570:                }
        !           571:                break;
        !           572: 
        !           573:              case expr_not_equal:
        !           574:                if (len > 7) {
        !           575:                        rv = 5;
        !           576:                        strcpy (buf, "(neq ");
        !           577:                        rv += print_subexpression (expr -> data.equal [0],
        !           578:                                                   buf + rv, len - rv - 2);
        !           579:                        buf [rv++] = ' ';
        !           580:                        rv += print_subexpression (expr -> data.equal [1],
        !           581:                                                   buf + rv, len - rv - 1);
        !           582:                        buf [rv++] = ')';
        !           583:                        buf [rv] = 0;
        !           584:                        return rv;
        !           585:                }
        !           586:                break;
        !           587: 
        !           588:              case expr_regex_match:
        !           589:                if (len > 10) {
        !           590:                        rv = 4;
        !           591:                        strcpy(buf, "(regex ");
        !           592:                        rv += print_subexpression(expr->data.equal[0],
        !           593:                                                  buf + rv, len - rv - 2);
        !           594:                        buf[rv++] = ' ';
        !           595:                        rv += print_subexpression(expr->data.equal[1],
        !           596:                                                  buf + rv, len - rv - 1);
        !           597:                        buf[rv++] = ')';
        !           598:                        buf[rv] = 0;
        !           599:                        return rv;
        !           600:                }
        !           601:                break;
        !           602: 
        !           603:              case expr_substring:
        !           604:                if (len > 11) {
        !           605:                        rv = 8;
        !           606:                        strcpy (buf, "(substr ");
        !           607:                        rv += print_subexpression (expr -> data.substring.expr,
        !           608:                                                   buf + rv, len - rv - 3);
        !           609:                        buf [rv++] = ' ';
        !           610:                        rv += print_subexpression
        !           611:                                (expr -> data.substring.offset,
        !           612:                                 buf + rv, len - rv - 2);
        !           613:                        buf [rv++] = ' ';
        !           614:                        rv += print_subexpression (expr -> data.substring.len,
        !           615:                                                   buf + rv, len - rv - 1);
        !           616:                        buf [rv++] = ')';
        !           617:                        buf [rv] = 0;
        !           618:                        return rv;
        !           619:                }
        !           620:                break;
        !           621: 
        !           622:              case expr_suffix:
        !           623:                if (len > 10) {
        !           624:                        rv = 8;
        !           625:                        strcpy (buf, "(suffix ");
        !           626:                        rv += print_subexpression (expr -> data.suffix.expr,
        !           627:                                                   buf + rv, len - rv - 2);
        !           628:                        if (len > rv)
        !           629:                                buf [rv++] = ' ';
        !           630:                        rv += print_subexpression (expr -> data.suffix.len,
        !           631:                                                   buf + rv, len - rv - 1);
        !           632:                        if (len > rv)
        !           633:                                buf [rv++] = ')';
        !           634:                        buf [rv] = 0;
        !           635:                        return rv;
        !           636:                }
        !           637:                break;
        !           638: 
        !           639:              case expr_lcase:
        !           640:                if (len > 9) {
        !           641:                        rv = 7;
        !           642:                        strcpy(buf, "(lcase ");
        !           643:                        rv += print_subexpression(expr->data.lcase,
        !           644:                                                  buf + rv, len - rv - 1);
        !           645:                        buf[rv++] = ')';
        !           646:                        buf[rv] = 0;
        !           647:                        return rv;
        !           648:                }
        !           649:                break;
        !           650: 
        !           651:              case expr_ucase:
        !           652:                if (len > 9) {
        !           653:                        rv = 7;
        !           654:                        strcpy(buf, "(ucase ");
        !           655:                        rv += print_subexpression(expr->data.ucase,
        !           656:                                                  buf + rv, len - rv - 1);
        !           657:                        buf[rv++] = ')';
        !           658:                        buf[rv] = 0;
        !           659:                        return rv;
        !           660:                }
        !           661:                break;
        !           662: 
        !           663:              case expr_concat:
        !           664:                if (len > 10) {
        !           665:                        rv = 8;
        !           666:                        strcpy (buf, "(concat ");
        !           667:                        rv += print_subexpression (expr -> data.concat [0],
        !           668:                                                   buf + rv, len - rv - 2);
        !           669:                        buf [rv++] = ' ';
        !           670:                        rv += print_subexpression (expr -> data.concat [1],
        !           671:                                                   buf + rv, len - rv - 1);
        !           672:                        buf [rv++] = ')';
        !           673:                        buf [rv] = 0;
        !           674:                        return rv;
        !           675:                }
        !           676:                break;
        !           677: 
        !           678:              case expr_pick_first_value:
        !           679:                if (len > 8) {
        !           680:                        rv = 6;
        !           681:                        strcpy (buf, "(pick1st ");
        !           682:                        rv += print_subexpression
        !           683:                                (expr -> data.pick_first_value.car,
        !           684:                                 buf + rv, len - rv - 2);
        !           685:                        buf [rv++] = ' ';
        !           686:                        rv += print_subexpression
        !           687:                                (expr -> data.pick_first_value.cdr,
        !           688:                                 buf + rv, len - rv - 1);
        !           689:                        buf [rv++] = ')';
        !           690:                        buf [rv] = 0;
        !           691:                        return rv;
        !           692:                }
        !           693:                break;
        !           694: 
        !           695:              case expr_host_lookup:
        !           696:                rv = 15 + strlen (expr -> data.host_lookup -> hostname);
        !           697:                if (len > rv) {
        !           698:                        sprintf (buf, "(dns-lookup %s)",
        !           699:                                 expr -> data.host_lookup -> hostname);
        !           700:                        return rv;
        !           701:                }
        !           702:                break;
        !           703: 
        !           704:              case expr_and:
        !           705:                s = "and";
        !           706:              binop:
        !           707:                rv = strlen (s);
        !           708:                if (len > rv + 4) {
        !           709:                        buf [0] = '(';
        !           710:                        strcpy (&buf [1], s);
        !           711:                        rv += 1;
        !           712:                        buf [rv++] = ' ';
        !           713:                        rv += print_subexpression (expr -> data.and [0],
        !           714:                                                buf + rv, len - rv - 2);
        !           715:                        buf [rv++] = ' ';
        !           716:                        rv += print_subexpression (expr -> data.and [1],
        !           717:                                                   buf + rv, len - rv - 1);
        !           718:                        buf [rv++] = ')';
        !           719:                        buf [rv] = 0;
        !           720:                        return rv;
        !           721:                }
        !           722:                break;
        !           723: 
        !           724:              case expr_or:
        !           725:                s = "or";
        !           726:                goto binop;
        !           727: 
        !           728:              case expr_add:
        !           729:                s = "+";
        !           730:                goto binop;
        !           731: 
        !           732:              case expr_subtract:
        !           733:                s = "-";
        !           734:                goto binop;
        !           735: 
        !           736:              case expr_multiply:
        !           737:                s = "*";
        !           738:                goto binop;
        !           739: 
        !           740:              case expr_divide:
        !           741:                s = "/";
        !           742:                goto binop;
        !           743: 
        !           744:              case expr_remainder:
        !           745:                s = "%";
        !           746:                goto binop;
        !           747: 
        !           748:              case expr_binary_and:
        !           749:                s = "&";
        !           750:                goto binop;
        !           751: 
        !           752:              case expr_binary_or:
        !           753:                s = "|";
        !           754:                goto binop;
        !           755: 
        !           756:              case expr_binary_xor:
        !           757:                s = "^";
        !           758:                goto binop;
        !           759:                
        !           760:              case expr_not:
        !           761:                if (len > 6) {
        !           762:                        rv = 5;
        !           763:                        strcpy (buf, "(not ");
        !           764:                        rv += print_subexpression (expr -> data.not,
        !           765:                                                   buf + rv, len - rv - 1);
        !           766:                        buf [rv++] = ')';
        !           767:                        buf [rv] = 0;
        !           768:                        return rv;
        !           769:                }
        !           770:                break;
        !           771: 
        !           772:              case expr_config_option:
        !           773:                s = "cfg-option";
        !           774:                goto dooption;
        !           775: 
        !           776:              case expr_option:
        !           777:                s = "option";
        !           778:              dooption:
        !           779:                rv = strlen (s) + 2 + (strlen (expr -> data.option -> name) +
        !           780:                           strlen (expr -> data.option -> universe -> name));
        !           781:                if (len > rv) {
        !           782:                        sprintf (buf, "(option %s.%s)",
        !           783:                                 expr -> data.option -> universe -> name,
        !           784:                                 expr -> data.option -> name);
        !           785:                        return rv;
        !           786:                }
        !           787:                break;
        !           788: 
        !           789:              case expr_hardware:
        !           790:                if (len > 10) {
        !           791:                        strcpy (buf, "(hardware)");
        !           792:                        return 10;
        !           793:                }
        !           794:                break;
        !           795: 
        !           796:              case expr_packet:
        !           797:                if (len > 10) {
        !           798:                        rv = 8;
        !           799:                        strcpy (buf, "(substr ");
        !           800:                        rv += print_subexpression (expr -> data.packet.offset,
        !           801:                                                   buf + rv, len - rv - 2);
        !           802:                        buf [rv++] = ' ';
        !           803:                        rv += print_subexpression (expr -> data.packet.len,
        !           804:                                                   buf + rv, len - rv - 1);
        !           805:                        buf [rv++] = ')';
        !           806:                        buf [rv] = 0;
        !           807:                        return rv;
        !           808:                }
        !           809:                break;
        !           810: 
        !           811:              case expr_const_data:
        !           812:                s = print_hex_1 (expr -> data.const_data.len,
        !           813:                                 expr -> data.const_data.data, len);
        !           814:                rv = strlen (s);
        !           815:                if (rv >= len)
        !           816:                        rv = len - 1;
        !           817:                strncpy (buf, s, rv);
        !           818:                buf [rv] = 0;
        !           819:                return rv;
        !           820: 
        !           821:              case expr_encapsulate:
        !           822:                rv = 13;
        !           823:                strcpy (buf, "(encapsulate ");
        !           824:                rv += expr -> data.encapsulate.len;
        !           825:                if (rv + 2 > len)
        !           826:                        rv = len - 2;
        !           827:                strncpy (buf,
        !           828:                         (const char *)expr -> data.encapsulate.data, rv - 13);
        !           829:                buf [rv++] = ')';
        !           830:                buf [rv++] = 0;
        !           831:                break;
        !           832: 
        !           833:              case expr_extract_int8:
        !           834:                if (len > 7) {
        !           835:                        rv = 6;
        !           836:                        strcpy (buf, "(int8 ");
        !           837:                        rv += print_subexpression (expr -> data.extract_int,
        !           838:                                                   buf + rv, len - rv - 1);
        !           839:                        buf [rv++] = ')';
        !           840:                        buf [rv] = 0;
        !           841:                        return rv;
        !           842:                }
        !           843:                break;
        !           844: 
        !           845:              case expr_extract_int16:
        !           846:                if (len > 8) {
        !           847:                        rv = 7;
        !           848:                        strcpy (buf, "(int16 ");
        !           849:                        rv += print_subexpression (expr -> data.extract_int,
        !           850:                                                   buf + rv, len - rv - 1);
        !           851:                        buf [rv++] = ')';
        !           852:                        buf [rv] = 0;
        !           853:                        return rv;
        !           854:                }
        !           855:                break;
        !           856: 
        !           857:              case expr_extract_int32:
        !           858:                if (len > 8) {
        !           859:                        rv = 7;
        !           860:                        strcpy (buf, "(int32 ");
        !           861:                        rv += print_subexpression (expr -> data.extract_int,
        !           862:                                                   buf + rv, len - rv - 1);
        !           863:                        buf [rv++] = ')';
        !           864:                        buf [rv] = 0;
        !           865:                        return rv;
        !           866:                }
        !           867:                break;
        !           868: 
        !           869:              case expr_encode_int8:
        !           870:                if (len > 7) {
        !           871:                        rv = 6;
        !           872:                        strcpy (buf, "(to-int8 ");
        !           873:                        rv += print_subexpression (expr -> data.encode_int,
        !           874:                                                   buf + rv, len - rv - 1);
        !           875:                        buf [rv++] = ')';
        !           876:                        buf [rv] = 0;
        !           877:                        return rv;
        !           878:                }
        !           879:                break;
        !           880: 
        !           881:              case expr_encode_int16:
        !           882:                if (len > 8) {
        !           883:                        rv = 7;
        !           884:                        strcpy (buf, "(to-int16 ");
        !           885:                        rv += print_subexpression (expr -> data.encode_int,
        !           886:                                                   buf + rv, len - rv - 1);
        !           887:                        buf [rv++] = ')';
        !           888:                        buf [rv] = 0;
        !           889:                        return rv;
        !           890:                }
        !           891:                break;
        !           892: 
        !           893:              case expr_encode_int32:
        !           894:                if (len > 8) {
        !           895:                        rv = 7;
        !           896:                        strcpy (buf, "(to-int32 ");
        !           897:                        rv += print_subexpression (expr -> data.encode_int,
        !           898:                                                   buf + rv, len - rv - 1);
        !           899:                        buf [rv++] = ')';
        !           900:                        buf [rv] = 0;
        !           901:                        return rv;
        !           902:                }
        !           903:                break;
        !           904: 
        !           905:              case expr_const_int:
        !           906:                s = print_dec_1 (expr -> data.const_int);
        !           907:                rv = strlen (s);
        !           908:                if (len > rv) {
        !           909:                        strcpy (buf, s);
        !           910:                        return rv;
        !           911:                }
        !           912:                break;
        !           913: 
        !           914:              case expr_exists:
        !           915:                rv = 10 + (strlen (expr -> data.option -> name) +
        !           916:                           strlen (expr -> data.option -> universe -> name));
        !           917:                if (len > rv) {
        !           918:                        sprintf (buf, "(exists %s.%s)",
        !           919:                                 expr -> data.option -> universe -> name,
        !           920:                                 expr -> data.option -> name);
        !           921:                        return rv;
        !           922:                }
        !           923:                break;
        !           924: 
        !           925:              case expr_variable_exists:
        !           926:                rv = 10 + strlen (expr -> data.variable);
        !           927:                if (len > rv) {
        !           928:                        sprintf (buf, "(defined %s)", expr -> data.variable);
        !           929:                        return rv;
        !           930:                }
        !           931:                break;
        !           932: 
        !           933:              case expr_variable_reference:
        !           934:                rv = strlen (expr -> data.variable);
        !           935:                if (len > rv) {
        !           936:                        sprintf (buf, "%s", expr -> data.variable);
        !           937:                        return rv;
        !           938:                }
        !           939:                break;
        !           940: 
        !           941:              case expr_known:
        !           942:                s = "known";
        !           943:              astring:
        !           944:                rv = strlen (s);
        !           945:                if (len > rv) {
        !           946:                        strcpy (buf, s);
        !           947:                        return rv;
        !           948:                }
        !           949:                break;
        !           950: 
        !           951:              case expr_leased_address:
        !           952:                s = "leased-address";
        !           953:                goto astring;
        !           954: 
        !           955:              case expr_client_state:
        !           956:                s = "client-state";
        !           957:                goto astring;
        !           958: 
        !           959:              case expr_host_decl_name:
        !           960:                s = "host-decl-name";
        !           961:                goto astring;
        !           962: 
        !           963:              case expr_lease_time:
        !           964:                s = "lease-time";
        !           965:                goto astring;
        !           966: 
        !           967:              case expr_static:
        !           968:                s = "static";
        !           969:                goto astring;
        !           970: 
        !           971:              case expr_filename:
        !           972:                s = "filename";
        !           973:                goto astring;
        !           974: 
        !           975:              case expr_sname:
        !           976:                s = "server-name";
        !           977:                goto astring;
        !           978: 
        !           979:              case expr_reverse:
        !           980:                if (len > 11) {
        !           981:                        rv = 13;
        !           982:                        strcpy (buf, "(reverse ");
        !           983:                        rv += print_subexpression (expr -> data.reverse.width,
        !           984:                                                   buf + rv, len - rv - 2);
        !           985:                        buf [rv++] = ' ';
        !           986:                        rv += print_subexpression (expr -> data.reverse.buffer,
        !           987:                                                   buf + rv, len - rv - 1);
        !           988:                        buf [rv++] = ')';
        !           989:                        buf [rv] = 0;
        !           990:                        return rv;
        !           991:                }
        !           992:                break;
        !           993: 
        !           994:              case expr_binary_to_ascii:
        !           995:                if (len > 5) {
        !           996:                        rv = 9;
        !           997:                        strcpy (buf, "(b2a ");
        !           998:                        rv += print_subexpression (expr -> data.b2a.base,
        !           999:                                                   buf + rv, len - rv - 4);
        !          1000:                        buf [rv++] = ' ';
        !          1001:                        rv += print_subexpression (expr -> data.b2a.width,
        !          1002:                                                   buf + rv, len - rv - 3);
        !          1003:                        buf [rv++] = ' ';
        !          1004:                        rv += print_subexpression (expr -> data.b2a.separator,
        !          1005:                                                   buf + rv, len - rv - 2);
        !          1006:                        buf [rv++] = ' ';
        !          1007:                        rv += print_subexpression (expr -> data.b2a.buffer,
        !          1008:                                                   buf + rv, len - rv - 1);
        !          1009:                        buf [rv++] = ')';
        !          1010:                        buf [rv] = 0;
        !          1011:                        return rv;
        !          1012:                }
        !          1013:                break;
        !          1014: 
        !          1015:              case expr_dns_transaction:
        !          1016:                rv = 10;
        !          1017:                if (len < rv + 2) {
        !          1018:                        buf [0] = '(';
        !          1019:                        strcpy (&buf [1], "ns-update ");
        !          1020:                        while (len < rv + 2) {
        !          1021:                                rv += print_subexpression
        !          1022:                                        (expr -> data.dns_transaction.car,
        !          1023:                                         buf + rv, len - rv - 2);
        !          1024:                                buf [rv++] = ' ';
        !          1025:                                expr = expr -> data.dns_transaction.cdr;
        !          1026:                        }
        !          1027:                        buf [rv - 1] = ')';
        !          1028:                        buf [rv] = 0;
        !          1029:                        return rv;
        !          1030:                }
        !          1031:                return 0;
        !          1032: 
        !          1033:              case expr_ns_delete:
        !          1034:                s = "delete";
        !          1035:                left = 4;
        !          1036:                goto dodnsupd;
        !          1037:              case expr_ns_exists:
        !          1038:                s = "exists";
        !          1039:                left = 4;
        !          1040:                goto dodnsupd;
        !          1041:              case expr_ns_not_exists:
        !          1042:                s = "not_exists";
        !          1043:                left = 4;
        !          1044:                goto dodnsupd;
        !          1045:              case expr_ns_add:
        !          1046:                s = "update";
        !          1047:                left = 5;
        !          1048:              dodnsupd:
        !          1049:                rv = strlen (s);
        !          1050:                if (len > strlen (s) + 1) {
        !          1051:                        buf [0] = '(';
        !          1052:                        strcpy (buf + 1, s);
        !          1053:                        rv++;
        !          1054:                        buf [rv++] = ' ';
        !          1055:                        s = print_dec_1 (expr -> data.ns_add.rrclass);
        !          1056:                        if (len > rv + strlen (s) + left) {
        !          1057:                                strcpy (&buf [rv], s);
        !          1058:                                rv += strlen (&buf [rv]);
        !          1059:                        }
        !          1060:                        buf [rv++] = ' ';
        !          1061:                        left--;
        !          1062:                        s = print_dec_1 (expr -> data.ns_add.rrtype);
        !          1063:                        if (len > rv + strlen (s) + left) {
        !          1064:                                strcpy (&buf [rv], s);
        !          1065:                                rv += strlen (&buf [rv]);
        !          1066:                        }
        !          1067:                        buf [rv++] = ' ';
        !          1068:                        left--;
        !          1069:                        rv += print_subexpression
        !          1070:                                (expr -> data.ns_add.rrname,
        !          1071:                                 buf + rv, len - rv - left);
        !          1072:                        buf [rv++] = ' ';
        !          1073:                        left--;
        !          1074:                        rv += print_subexpression
        !          1075:                                (expr -> data.ns_add.rrdata,
        !          1076:                                 buf + rv, len - rv - left);
        !          1077:                        buf [rv++] = ' ';
        !          1078:                        left--;
        !          1079:                        rv += print_subexpression
        !          1080:                                (expr -> data.ns_add.ttl,
        !          1081:                                 buf + rv, len - rv - left);
        !          1082:                        buf [rv++] = ')';
        !          1083:                        buf [rv] = 0;
        !          1084:                        return rv;
        !          1085:                }
        !          1086:                break;
        !          1087: 
        !          1088:              case expr_null:
        !          1089:                if (len > 6) {
        !          1090:                        strcpy (buf, "(null)");
        !          1091:                        return 6;
        !          1092:                }
        !          1093:                break;
        !          1094:              case expr_funcall:
        !          1095:                rv = 12 + strlen (expr -> data.funcall.name);
        !          1096:                if (len > rv + 1) {
        !          1097:                        strcpy (buf, "(funcall  ");
        !          1098:                        strcpy (buf + 9, expr -> data.funcall.name);
        !          1099:                        buf [rv++] = ' ';
        !          1100:                        rv += print_subexpression
        !          1101:                                (expr -> data.funcall.arglist, buf + rv,
        !          1102:                                 len - rv - 1);
        !          1103:                        buf [rv++] = ')';
        !          1104:                        buf [rv] = 0;
        !          1105:                        return rv;
        !          1106:                }
        !          1107:                break;
        !          1108: 
        !          1109:              case expr_arg:
        !          1110:                rv = print_subexpression (expr -> data.arg.val, buf, len);
        !          1111:                if (expr -> data.arg.next && rv + 2 < len) {
        !          1112:                        buf [rv++] = ' ';
        !          1113:                        rv += print_subexpression (expr -> data.arg.next,
        !          1114:                                                   buf, len);
        !          1115:                        if (rv + 1 < len)
        !          1116:                                buf [rv++] = 0;
        !          1117:                        return rv;
        !          1118:                }
        !          1119:                break;
        !          1120: 
        !          1121:              case expr_function:
        !          1122:                rv = 9;
        !          1123:                if (len > rv + 1) {
        !          1124:                        struct string_list *foo;
        !          1125:                        strcpy (buf, "(function");
        !          1126:                        for (foo = expr -> data.func -> args;
        !          1127:                             foo; foo = foo -> next) {
        !          1128:                                if (len > rv + 2 + strlen (foo -> string)) {
        !          1129:                                        buf [rv - 1] = ' ';
        !          1130:                                        strcpy (&buf [rv], foo -> string);
        !          1131:                                        rv += strlen (foo -> string);
        !          1132:                                }
        !          1133:                        }
        !          1134:                        buf [rv++] = ')';
        !          1135:                        buf [rv] = 0;
        !          1136:                        return rv;
        !          1137:                }
        !          1138: 
        !          1139:              default:
        !          1140:                log_fatal("Impossible case at %s:%d (undefined expression "
        !          1141:                          "%d).", MDL, expr->op);
        !          1142:                break;
        !          1143:        }
        !          1144:        return 0;
        !          1145: }
        !          1146: 
        !          1147: void print_expression (name, expr)
        !          1148:        const char *name;
        !          1149:        struct expression *expr;
        !          1150: {
        !          1151:        char buf [1024];
        !          1152: 
        !          1153:        print_subexpression (expr, buf, sizeof buf);
        !          1154:        log_info ("%s: %s", name, buf);
        !          1155: }
        !          1156: 
        !          1157: int token_print_indent_concat (FILE *file, int col,  int indent,
        !          1158:                               const char *prefix, 
        !          1159:                               const char *suffix, ...)
        !          1160: {
        !          1161:        va_list list;
        !          1162:        unsigned len;
        !          1163:        char *s, *t, *u;
        !          1164: 
        !          1165:        va_start (list, suffix);
        !          1166:        s = va_arg (list, char *);
        !          1167:        len = 0;
        !          1168:        while (s) {
        !          1169:                len += strlen (s);
        !          1170:                s = va_arg (list, char *);
        !          1171:        }
        !          1172:        va_end (list);
        !          1173: 
        !          1174:        t = dmalloc (len + 1, MDL);
        !          1175:        if (!t)
        !          1176:                log_fatal ("token_print_indent: no memory for copy buffer");
        !          1177: 
        !          1178:        va_start (list, suffix);
        !          1179:        s = va_arg (list, char *);
        !          1180:        u = t;
        !          1181:        while (s) {
        !          1182:                len = strlen (s);
        !          1183:                strcpy (u, s);
        !          1184:                u += len;
        !          1185:                s = va_arg (list, char *);
        !          1186:        }
        !          1187:        va_end (list);
        !          1188:        
        !          1189:        len = token_print_indent (file, col, indent,
        !          1190:                                  prefix, suffix, t);
        !          1191:        dfree (t, MDL);
        !          1192:        return col;
        !          1193: }
        !          1194: 
        !          1195: int token_indent_data_string (FILE *file, int col, int indent,
        !          1196:                              const char *prefix, const char *suffix,
        !          1197:                              struct data_string *data)
        !          1198: {
        !          1199:        int i;
        !          1200:        char *buf;
        !          1201:        char obuf [3];
        !          1202: 
        !          1203:        /* See if this is just ASCII. */
        !          1204:        for (i = 0; i < data -> len; i++)
        !          1205:                if (!isascii (data -> data [i]) ||
        !          1206:                    !isprint (data -> data [i]))
        !          1207:                        break;
        !          1208: 
        !          1209:        /* If we have a purely ASCII string, output it as text. */
        !          1210:        if (i == data -> len) {
        !          1211:                buf = dmalloc (data -> len + 3, MDL);
        !          1212:                if (buf) {
        !          1213:                        buf [0] = '"';
        !          1214:                        memcpy (buf + 1, data -> data, data -> len);
        !          1215:                        buf [data -> len + 1] = '"';
        !          1216:                        buf [data -> len + 2] = 0;
        !          1217:                        i = token_print_indent (file, col, indent,
        !          1218:                                                prefix, suffix, buf);
        !          1219:                        dfree (buf, MDL);
        !          1220:                        return i;
        !          1221:                }
        !          1222:        }
        !          1223: 
        !          1224:        for (i = 0; i < data -> len; i++) {
        !          1225:                sprintf (obuf, "%2.2x", data -> data [i]);
        !          1226:                col = token_print_indent (file, col, indent,
        !          1227:                                          i == 0 ? prefix : "",
        !          1228:                                          (i + 1 == data -> len
        !          1229:                                           ? suffix
        !          1230:                                           : ""), obuf);
        !          1231:                if (i + 1 != data -> len)
        !          1232:                        col = token_print_indent (file, col, indent,
        !          1233:                                                  prefix, suffix, ":");
        !          1234:        }
        !          1235:        return col;
        !          1236: }
        !          1237: 
        !          1238: int token_print_indent (FILE *file, int col, int indent,
        !          1239:                        const char *prefix,
        !          1240:                        const char *suffix, const char *buf)
        !          1241: {
        !          1242:        int len = strlen (buf) + strlen (prefix);
        !          1243:        if (col + len > 79) {
        !          1244:                if (indent + len < 79) {
        !          1245:                        indent_spaces (file, indent);
        !          1246:                        col = indent;
        !          1247:                } else {
        !          1248:                        indent_spaces (file, col);
        !          1249:                        col = len > 79 ? 0 : 79 - len - 1;
        !          1250:                }
        !          1251:        } else if (prefix && *prefix) {
        !          1252:                fputs (prefix, file);
        !          1253:                col += strlen (prefix);
        !          1254:        }
        !          1255:        fputs (buf, file);
        !          1256:        col += len;
        !          1257:        if (suffix && *suffix) {
        !          1258:                if (col + strlen (suffix) > 79) {
        !          1259:                        indent_spaces (file, indent);
        !          1260:                        col = indent;
        !          1261:                } else {
        !          1262:                        fputs (suffix, file);
        !          1263:                        col += strlen (suffix);
        !          1264:                }
        !          1265:        }
        !          1266:        return col;
        !          1267: }
        !          1268: 
        !          1269: void indent_spaces (FILE *file, int indent)
        !          1270: {
        !          1271:        int i;
        !          1272:        fputc ('\n', file);
        !          1273:        for (i = 0; i < indent; i++)
        !          1274:                fputc (' ', file);
        !          1275: }
        !          1276: 
        !          1277: #if defined (NSUPDATE)
        !          1278: void print_dns_status (int status, ns_updque *uq)
        !          1279: {
        !          1280:        char obuf [1024];
        !          1281:        char *s = &obuf [0], *end = &obuf [1022];
        !          1282:        ns_updrec *u;
        !          1283:        int position;
        !          1284:        int ttlp;
        !          1285:        const char *predicate = "if", *en, *op;
        !          1286:        int errorp;
        !          1287: 
        !          1288:        for (u = ISC_LIST_HEAD (*uq); u; u = ISC_LIST_NEXT (u, r_link)) {
        !          1289:                ttlp = 0;
        !          1290: 
        !          1291:                switch (u -> r_opcode)
        !          1292:                {
        !          1293:                      case NXRRSET:
        !          1294:                        op = "rrset doesn't exist";
        !          1295:                        position = 1;
        !          1296:                        break;
        !          1297:                      case YXRRSET:
        !          1298:                        op = "rrset exists";
        !          1299:                        position = 1;
        !          1300:                        break;
        !          1301:                      case NXDOMAIN:
        !          1302:                        op = "domain doesn't exist";
        !          1303:                        position = 1;
        !          1304:                        break;
        !          1305:                      case YXDOMAIN:
        !          1306:                        op = "domain exists";
        !          1307:                        position = 1;
        !          1308:                        break;
        !          1309:                      case ADD:
        !          1310:                        op = "add";
        !          1311:                        position = 0;
        !          1312:                        ttlp = 1;
        !          1313:                        break;
        !          1314:                      case DELETE:
        !          1315:                        op = "delete";
        !          1316:                        position = 0;
        !          1317:                        break;
        !          1318:                      default:
        !          1319:                        op = "unknown";
        !          1320:                        position = 0;
        !          1321:                        break;
        !          1322:                }
        !          1323:                if (!position) {
        !          1324:                        if (s != &obuf [0] && s + 1 < end)
        !          1325:                                *s++ = ' ';
        !          1326:                        if (s + strlen (op) < end) {
        !          1327:                                strcpy (s, op);
        !          1328:                                s += strlen (s);
        !          1329:                        }
        !          1330:                } else {
        !          1331:                        if (s != &obuf [0] && s + 1 < end)
        !          1332:                                *s++ = ' ';
        !          1333:                        if (s + strlen (predicate) < end) {
        !          1334:                                strcpy (s, predicate);
        !          1335:                                s += strlen (s);
        !          1336:                        }
        !          1337:                        predicate = "and";
        !          1338:                }
        !          1339:                if (u -> r_dname) {
        !          1340:                        if (s + 1 < end)
        !          1341:                                *s++ = ' ';
        !          1342:                        if (s + strlen (u -> r_dname) < end) {
        !          1343:                                strcpy (s, u -> r_dname);
        !          1344:                                s += strlen (s);
        !          1345:                        }
        !          1346:                }
        !          1347:                if (ttlp) {
        !          1348:                        if (s + 1 < end)
        !          1349:                                *s++ = ' ';
        !          1350:                        /* 27 is as big as a ttl can get. */
        !          1351:                        if (s + 27 < end) {
        !          1352:                                sprintf (s, "%lu",
        !          1353:                                         (unsigned long)(u -> r_ttl));
        !          1354:                                s += strlen (s);
        !          1355:                        }
        !          1356:                }
        !          1357:                switch (u -> r_class) {
        !          1358:                      case C_IN:
        !          1359:                        en = "IN";
        !          1360:                        break;
        !          1361:                      case C_CHAOS:
        !          1362:                        en = "CHAOS";
        !          1363:                        break;
        !          1364:                      case C_HS:
        !          1365:                        en = "HS";
        !          1366:                        break;
        !          1367:                      default:
        !          1368:                        en = "UNKNOWN";
        !          1369:                        break;
        !          1370:                }
        !          1371:                if (s + strlen (en) < end) {
        !          1372:                        if (s + 1 < end)
        !          1373:                                *s++ = ' ';
        !          1374:                        strcpy (s, en);
        !          1375:                        s += strlen (en);
        !          1376:                }
        !          1377:                switch (u -> r_type) {
        !          1378:                      case T_A:
        !          1379:                        en = "A";
        !          1380:                        break;
        !          1381:                      case T_AAAA:
        !          1382:                        en = "AAAA";
        !          1383:                        break;
        !          1384:                      case T_PTR:
        !          1385:                        en = "PTR";
        !          1386:                        break;
        !          1387:                      case T_MX:
        !          1388:                        en = "MX";
        !          1389:                        break;
        !          1390:                      case T_TXT:
        !          1391:                        en = "TXT";
        !          1392:                        break;
        !          1393:                      case T_KEY:
        !          1394:                        en = "KEY";
        !          1395:                        break;
        !          1396:                      case T_CNAME:
        !          1397:                        en = "CNAME";
        !          1398:                        break;
        !          1399:                      default:
        !          1400:                        en = "UNKNOWN";
        !          1401:                        break;
        !          1402:                }
        !          1403:                if (s + strlen (en) < end) {
        !          1404:                        if (s + 1 < end)
        !          1405:                                *s++ = ' ';
        !          1406:                        strcpy (s, en);
        !          1407:                        s += strlen (en);
        !          1408:                }
        !          1409:                if (u -> r_data) {
        !          1410:                        if (s + 1 < end)
        !          1411:                                *s++ = ' ';
        !          1412:                        if (u -> r_type == T_TXT) {
        !          1413:                                if (s + 1 < end)
        !          1414:                                        *s++ = '"';
        !          1415:                        }
        !          1416:                        if(u->r_type == T_KEY) {
        !          1417:                          strcat(s, "<keydata>");
        !          1418:                          s+=strlen("<keydata>");
        !          1419:                        }
        !          1420:                        else {  
        !          1421:                          if (s + u -> r_size < end) {
        !          1422:                            memcpy (s, u -> r_data, u -> r_size);
        !          1423:                            s += u -> r_size;
        !          1424:                            if (u -> r_type == T_TXT) {
        !          1425:                              if (s + 1 < end)
        !          1426:                                *s++ = '"';
        !          1427:                            }
        !          1428:                          }
        !          1429:                        }
        !          1430:                }
        !          1431:                if (position) {
        !          1432:                        if (s + 1 < end)
        !          1433:                                *s++ = ' ';
        !          1434:                        if (s + strlen (op) < end) {
        !          1435:                                strcpy (s, op);
        !          1436:                                s += strlen (s);
        !          1437:                        }
        !          1438:                }
        !          1439:                if (u == ISC_LIST_TAIL (*uq))
        !          1440:                        break;
        !          1441:        }
        !          1442:        if (s == &obuf [0]) {
        !          1443:                strcpy (s, "empty update");
        !          1444:                s += strlen (s);
        !          1445:        }
        !          1446:        if (status == NOERROR)
        !          1447:                errorp = 0;
        !          1448:        else
        !          1449:                errorp = 1;
        !          1450:        en = isc_result_totext (status);
        !          1451: #if 0
        !          1452:        switch (status) {
        !          1453:              case -1:
        !          1454:                en = "resolver failed";
        !          1455:                break;
        !          1456: 
        !          1457:              case FORMERR:
        !          1458:                en = "format error";
        !          1459:                break;
        !          1460: 
        !          1461:              case NOERROR:
        !          1462:                en = "succeeded";
        !          1463:                errorp = 0;
        !          1464:                break;
        !          1465: 
        !          1466:              case NOTAUTH:
        !          1467:                en = "not authorized";
        !          1468:                break;
        !          1469: 
        !          1470:              case NOTIMP:
        !          1471:                en = "not implemented";
        !          1472:                break;
        !          1473: 
        !          1474:              case NOTZONE:
        !          1475:                en = "not a single valid zone";
        !          1476:                break;
        !          1477: 
        !          1478:              case NXDOMAIN:
        !          1479:                en = "no such domain";
        !          1480:                break;
        !          1481: 
        !          1482:              case NXRRSET:
        !          1483:                en = "no such record";
        !          1484:                break;
        !          1485: 
        !          1486:              case REFUSED:
        !          1487:                en = "refused";
        !          1488:                break;
        !          1489: 
        !          1490:              case SERVFAIL:
        !          1491:                en = "server failed";
        !          1492:                break;
        !          1493: 
        !          1494:              case YXDOMAIN:
        !          1495:                en = "domain exists";
        !          1496:                break;
        !          1497: 
        !          1498:              case YXRRSET:
        !          1499:                en = "record exists";
        !          1500:                break;
        !          1501: 
        !          1502:              default:
        !          1503:                en = "unknown error";
        !          1504:                break;
        !          1505:        }
        !          1506: #endif
        !          1507: 
        !          1508:        if (s + 2 < end) {
        !          1509:                *s++ = ':';
        !          1510:                *s++ = ' ';
        !          1511:        }
        !          1512:        if (s + strlen (en) < end) {
        !          1513:                strcpy (s, en);
        !          1514:                s += strlen (en);
        !          1515:        }
        !          1516:        if (s + 1 < end)
        !          1517:                *s++ = '.';
        !          1518:        *s++ = 0;
        !          1519:        if (errorp)
        !          1520:                log_error ("%s", obuf);
        !          1521:        else
        !          1522:                log_info ("%s", obuf);
        !          1523: }
        !          1524: #endif /* NSUPDATE */
        !          1525: 
        !          1526: /* Format the given time as "A; # B", where A is the format
        !          1527:  * used by the parser, and B is the local time, for humans.
        !          1528:  */
        !          1529: const char *
        !          1530: print_time(TIME t)
        !          1531: {
        !          1532:        static char buf[sizeof("epoch 9223372036854775807; "
        !          1533:                               "# Wed Jun 30 21:49:08 2147483647")];
        !          1534:        static char buf1[sizeof("# Wed Jun 30 21:49:08 2147483647")];
        !          1535:        time_t since_epoch;
        !          1536:        /* The string:         "6 2147483647/12/31 23:59:60;"
        !          1537:         * is smaller than the other, used to declare the buffer size, so
        !          1538:         * we can use one buffer for both.
        !          1539:         */
        !          1540: 
        !          1541:        if (t == MAX_TIME)
        !          1542:                return "never;";
        !          1543: 
        !          1544:        if (t < 0)
        !          1545:                return NULL;
        !          1546: 
        !          1547:        /* For those lucky enough to have a 128-bit time_t, ensure that
        !          1548:         * whatever (corrupt) value we're given doesn't exceed the static
        !          1549:         * buffer.
        !          1550:         */
        !          1551: #if (MAX_TIME > 0x7fffffffffffffff)
        !          1552:        if (t > 0x7fffffffffffffff)
        !          1553:                return NULL;
        !          1554: #endif
        !          1555: 
        !          1556:        if (db_time_format == LOCAL_TIME_FORMAT) {
        !          1557:                since_epoch = mktime(localtime(&t));
        !          1558:                if ((strftime(buf1, sizeof(buf1),
        !          1559:                              "# %a %b %d %H:%M:%S %Y",
        !          1560:                              localtime(&t)) == 0) ||
        !          1561:                    (snprintf(buf, sizeof(buf), "epoch %lu; %s",
        !          1562:                              (unsigned long)since_epoch, buf1) >= sizeof(buf)))
        !          1563:                        return NULL;
        !          1564: 
        !          1565:        } else {
        !          1566:                /* No bounds check for the year is necessary - in this case,
        !          1567:                 * strftime() will run out of space and assert an error.
        !          1568:                 */
        !          1569:                if (strftime(buf, sizeof(buf), "%w %Y/%m/%d %H:%M:%S;",
        !          1570:                             gmtime(&t)) == 0)
        !          1571:                        return NULL;
        !          1572:        }
        !          1573: 
        !          1574:        return buf;
        !          1575: }

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