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

1.1       misho       1: /* print.c
                      2: 
                      3:    Turn data structures into printable text. */
                      4: 
                      5: /*
1.1.1.1 ! misho       6:  * Copyright (c) 2009-2012 by Internet Systems Consortium, Inc. ("ISC")
1.1       misho       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;
1.1.1.1 ! misho     482:        char *s;
1.1       misho     483: 
                    484:        s = &dq_buf [0];
                    485:        
                    486:        i = 0;
                    487: 
                    488:        /* %Audit% Loop bounds checks to 21 bytes. %2004.06.17,Safe%
                    489:         * The sprintf can't exceed 18 bytes, and since the loop enforces
                    490:         * 21 bytes of space per iteration at no time can we exit the
                    491:         * loop without at least 3 bytes spare.
                    492:         */
                    493:        do {
                    494:                sprintf (s, "%u.%u.%u.%u, ",
                    495:                         data [i], data [i + 1], data [i + 2], data [i + 3]);
                    496:                s += strlen (s);
                    497:                i += 4;
                    498:        } while ((s - &dq_buf [0] > DQLEN - 21) &&
                    499:                 i + 3 < len);
                    500:        if (i == len)
                    501:                s [-2] = 0;
                    502:        else
                    503:                strcpy (s, "...");
                    504:        return dq_buf;
                    505: }
                    506: 
                    507: char *print_dec_1 (val)
                    508:        unsigned long val;
                    509: {
                    510:        static char vbuf [32];
                    511:        sprintf (vbuf, "%lu", val);
                    512:        return vbuf;
                    513: }
                    514: 
                    515: char *print_dec_2 (val)
                    516:        unsigned long val;
                    517: {
                    518:        static char vbuf [32];
                    519:        sprintf (vbuf, "%lu", val);
                    520:        return vbuf;
                    521: }
                    522: 
                    523: static unsigned print_subexpression (struct expression *, char *, unsigned);
                    524: 
                    525: static unsigned print_subexpression (expr, buf, len)
                    526:        struct expression *expr;
                    527:        char *buf;
                    528:        unsigned len;
                    529: {
                    530:        unsigned rv, left;
                    531:        const char *s;
                    532: 
                    533:        switch (expr -> op) {
                    534:              case expr_none:
                    535:                if (len > 3) {
                    536:                        strcpy (buf, "nil");
                    537:                        return 3;
                    538:                }
                    539:                break;
                    540:                  
                    541:              case expr_match:
                    542:                if (len > 7) {
                    543:                        strcpy (buf, "(match)");
                    544:                        return 7;
                    545:                }
                    546:                break;
                    547: 
                    548:              case expr_check:
                    549:                rv = 10 + strlen (expr -> data.check -> name);
                    550:                if (len > rv) {
                    551:                        sprintf (buf, "(check %s)",
                    552:                                 expr -> data.check -> name);
                    553:                        return rv;
                    554:                }
                    555:                break;
                    556: 
                    557:              case expr_equal:
                    558:                if (len > 6) {
                    559:                        rv = 4;
                    560:                        strcpy (buf, "(eq ");
                    561:                        rv += print_subexpression (expr -> data.equal [0],
                    562:                                                   buf + rv, len - rv - 2);
                    563:                        buf [rv++] = ' ';
                    564:                        rv += print_subexpression (expr -> data.equal [1],
                    565:                                                   buf + rv, len - rv - 1);
                    566:                        buf [rv++] = ')';
                    567:                        buf [rv] = 0;
                    568:                        return rv;
                    569:                }
                    570:                break;
                    571: 
                    572:              case expr_not_equal:
                    573:                if (len > 7) {
                    574:                        rv = 5;
                    575:                        strcpy (buf, "(neq ");
                    576:                        rv += print_subexpression (expr -> data.equal [0],
                    577:                                                   buf + rv, len - rv - 2);
                    578:                        buf [rv++] = ' ';
                    579:                        rv += print_subexpression (expr -> data.equal [1],
                    580:                                                   buf + rv, len - rv - 1);
                    581:                        buf [rv++] = ')';
                    582:                        buf [rv] = 0;
                    583:                        return rv;
                    584:                }
                    585:                break;
                    586: 
                    587:              case expr_regex_match:
                    588:                if (len > 10) {
                    589:                        rv = 4;
                    590:                        strcpy(buf, "(regex ");
                    591:                        rv += print_subexpression(expr->data.equal[0],
                    592:                                                  buf + rv, len - rv - 2);
                    593:                        buf[rv++] = ' ';
                    594:                        rv += print_subexpression(expr->data.equal[1],
                    595:                                                  buf + rv, len - rv - 1);
                    596:                        buf[rv++] = ')';
                    597:                        buf[rv] = 0;
                    598:                        return rv;
                    599:                }
                    600:                break;
                    601: 
                    602:              case expr_substring:
                    603:                if (len > 11) {
                    604:                        rv = 8;
                    605:                        strcpy (buf, "(substr ");
                    606:                        rv += print_subexpression (expr -> data.substring.expr,
                    607:                                                   buf + rv, len - rv - 3);
                    608:                        buf [rv++] = ' ';
                    609:                        rv += print_subexpression
                    610:                                (expr -> data.substring.offset,
                    611:                                 buf + rv, len - rv - 2);
                    612:                        buf [rv++] = ' ';
                    613:                        rv += print_subexpression (expr -> data.substring.len,
                    614:                                                   buf + rv, len - rv - 1);
                    615:                        buf [rv++] = ')';
                    616:                        buf [rv] = 0;
                    617:                        return rv;
                    618:                }
                    619:                break;
                    620: 
                    621:              case expr_suffix:
                    622:                if (len > 10) {
                    623:                        rv = 8;
                    624:                        strcpy (buf, "(suffix ");
                    625:                        rv += print_subexpression (expr -> data.suffix.expr,
                    626:                                                   buf + rv, len - rv - 2);
                    627:                        if (len > rv)
                    628:                                buf [rv++] = ' ';
                    629:                        rv += print_subexpression (expr -> data.suffix.len,
                    630:                                                   buf + rv, len - rv - 1);
                    631:                        if (len > rv)
                    632:                                buf [rv++] = ')';
                    633:                        buf [rv] = 0;
                    634:                        return rv;
                    635:                }
                    636:                break;
                    637: 
                    638:              case expr_lcase:
                    639:                if (len > 9) {
                    640:                        rv = 7;
                    641:                        strcpy(buf, "(lcase ");
                    642:                        rv += print_subexpression(expr->data.lcase,
                    643:                                                  buf + rv, len - rv - 1);
                    644:                        buf[rv++] = ')';
                    645:                        buf[rv] = 0;
                    646:                        return rv;
                    647:                }
                    648:                break;
                    649: 
                    650:              case expr_ucase:
                    651:                if (len > 9) {
                    652:                        rv = 7;
                    653:                        strcpy(buf, "(ucase ");
                    654:                        rv += print_subexpression(expr->data.ucase,
                    655:                                                  buf + rv, len - rv - 1);
                    656:                        buf[rv++] = ')';
                    657:                        buf[rv] = 0;
                    658:                        return rv;
                    659:                }
                    660:                break;
                    661: 
                    662:              case expr_concat:
                    663:                if (len > 10) {
                    664:                        rv = 8;
                    665:                        strcpy (buf, "(concat ");
                    666:                        rv += print_subexpression (expr -> data.concat [0],
                    667:                                                   buf + rv, len - rv - 2);
                    668:                        buf [rv++] = ' ';
                    669:                        rv += print_subexpression (expr -> data.concat [1],
                    670:                                                   buf + rv, len - rv - 1);
                    671:                        buf [rv++] = ')';
                    672:                        buf [rv] = 0;
                    673:                        return rv;
                    674:                }
                    675:                break;
                    676: 
                    677:              case expr_pick_first_value:
                    678:                if (len > 8) {
                    679:                        rv = 6;
                    680:                        strcpy (buf, "(pick1st ");
                    681:                        rv += print_subexpression
                    682:                                (expr -> data.pick_first_value.car,
                    683:                                 buf + rv, len - rv - 2);
                    684:                        buf [rv++] = ' ';
                    685:                        rv += print_subexpression
                    686:                                (expr -> data.pick_first_value.cdr,
                    687:                                 buf + rv, len - rv - 1);
                    688:                        buf [rv++] = ')';
                    689:                        buf [rv] = 0;
                    690:                        return rv;
                    691:                }
                    692:                break;
                    693: 
                    694:              case expr_host_lookup:
                    695:                rv = 15 + strlen (expr -> data.host_lookup -> hostname);
                    696:                if (len > rv) {
                    697:                        sprintf (buf, "(dns-lookup %s)",
                    698:                                 expr -> data.host_lookup -> hostname);
                    699:                        return rv;
                    700:                }
                    701:                break;
                    702: 
                    703:              case expr_and:
                    704:                s = "and";
                    705:              binop:
                    706:                rv = strlen (s);
                    707:                if (len > rv + 4) {
                    708:                        buf [0] = '(';
                    709:                        strcpy (&buf [1], s);
                    710:                        rv += 1;
                    711:                        buf [rv++] = ' ';
                    712:                        rv += print_subexpression (expr -> data.and [0],
                    713:                                                buf + rv, len - rv - 2);
                    714:                        buf [rv++] = ' ';
                    715:                        rv += print_subexpression (expr -> data.and [1],
                    716:                                                   buf + rv, len - rv - 1);
                    717:                        buf [rv++] = ')';
                    718:                        buf [rv] = 0;
                    719:                        return rv;
                    720:                }
                    721:                break;
                    722: 
                    723:              case expr_or:
                    724:                s = "or";
                    725:                goto binop;
                    726: 
                    727:              case expr_add:
                    728:                s = "+";
                    729:                goto binop;
                    730: 
                    731:              case expr_subtract:
                    732:                s = "-";
                    733:                goto binop;
                    734: 
                    735:              case expr_multiply:
                    736:                s = "*";
                    737:                goto binop;
                    738: 
                    739:              case expr_divide:
                    740:                s = "/";
                    741:                goto binop;
                    742: 
                    743:              case expr_remainder:
                    744:                s = "%";
                    745:                goto binop;
                    746: 
                    747:              case expr_binary_and:
                    748:                s = "&";
                    749:                goto binop;
                    750: 
                    751:              case expr_binary_or:
                    752:                s = "|";
                    753:                goto binop;
                    754: 
                    755:              case expr_binary_xor:
                    756:                s = "^";
                    757:                goto binop;
                    758:                
                    759:              case expr_not:
                    760:                if (len > 6) {
                    761:                        rv = 5;
                    762:                        strcpy (buf, "(not ");
                    763:                        rv += print_subexpression (expr -> data.not,
                    764:                                                   buf + rv, len - rv - 1);
                    765:                        buf [rv++] = ')';
                    766:                        buf [rv] = 0;
                    767:                        return rv;
                    768:                }
                    769:                break;
                    770: 
                    771:              case expr_config_option:
                    772:                s = "cfg-option";
                    773:                goto dooption;
                    774: 
                    775:              case expr_option:
                    776:                s = "option";
                    777:              dooption:
                    778:                rv = strlen (s) + 2 + (strlen (expr -> data.option -> name) +
                    779:                           strlen (expr -> data.option -> universe -> name));
                    780:                if (len > rv) {
                    781:                        sprintf (buf, "(option %s.%s)",
                    782:                                 expr -> data.option -> universe -> name,
                    783:                                 expr -> data.option -> name);
                    784:                        return rv;
                    785:                }
                    786:                break;
                    787: 
                    788:              case expr_hardware:
                    789:                if (len > 10) {
                    790:                        strcpy (buf, "(hardware)");
                    791:                        return 10;
                    792:                }
                    793:                break;
                    794: 
                    795:              case expr_packet:
                    796:                if (len > 10) {
                    797:                        rv = 8;
                    798:                        strcpy (buf, "(substr ");
                    799:                        rv += print_subexpression (expr -> data.packet.offset,
                    800:                                                   buf + rv, len - rv - 2);
                    801:                        buf [rv++] = ' ';
                    802:                        rv += print_subexpression (expr -> data.packet.len,
                    803:                                                   buf + rv, len - rv - 1);
                    804:                        buf [rv++] = ')';
                    805:                        buf [rv] = 0;
                    806:                        return rv;
                    807:                }
                    808:                break;
                    809: 
                    810:              case expr_const_data:
                    811:                s = print_hex_1 (expr -> data.const_data.len,
                    812:                                 expr -> data.const_data.data, len);
                    813:                rv = strlen (s);
                    814:                if (rv >= len)
                    815:                        rv = len - 1;
                    816:                strncpy (buf, s, rv);
                    817:                buf [rv] = 0;
                    818:                return rv;
                    819: 
                    820:              case expr_encapsulate:
                    821:                rv = 13;
                    822:                strcpy (buf, "(encapsulate ");
                    823:                rv += expr -> data.encapsulate.len;
                    824:                if (rv + 2 > len)
                    825:                        rv = len - 2;
                    826:                strncpy (buf,
                    827:                         (const char *)expr -> data.encapsulate.data, rv - 13);
                    828:                buf [rv++] = ')';
                    829:                buf [rv++] = 0;
                    830:                break;
                    831: 
                    832:              case expr_extract_int8:
                    833:                if (len > 7) {
                    834:                        rv = 6;
                    835:                        strcpy (buf, "(int8 ");
                    836:                        rv += print_subexpression (expr -> data.extract_int,
                    837:                                                   buf + rv, len - rv - 1);
                    838:                        buf [rv++] = ')';
                    839:                        buf [rv] = 0;
                    840:                        return rv;
                    841:                }
                    842:                break;
                    843: 
                    844:              case expr_extract_int16:
                    845:                if (len > 8) {
                    846:                        rv = 7;
                    847:                        strcpy (buf, "(int16 ");
                    848:                        rv += print_subexpression (expr -> data.extract_int,
                    849:                                                   buf + rv, len - rv - 1);
                    850:                        buf [rv++] = ')';
                    851:                        buf [rv] = 0;
                    852:                        return rv;
                    853:                }
                    854:                break;
                    855: 
                    856:              case expr_extract_int32:
                    857:                if (len > 8) {
                    858:                        rv = 7;
                    859:                        strcpy (buf, "(int32 ");
                    860:                        rv += print_subexpression (expr -> data.extract_int,
                    861:                                                   buf + rv, len - rv - 1);
                    862:                        buf [rv++] = ')';
                    863:                        buf [rv] = 0;
                    864:                        return rv;
                    865:                }
                    866:                break;
                    867: 
                    868:              case expr_encode_int8:
                    869:                if (len > 7) {
                    870:                        rv = 6;
                    871:                        strcpy (buf, "(to-int8 ");
                    872:                        rv += print_subexpression (expr -> data.encode_int,
                    873:                                                   buf + rv, len - rv - 1);
                    874:                        buf [rv++] = ')';
                    875:                        buf [rv] = 0;
                    876:                        return rv;
                    877:                }
                    878:                break;
                    879: 
                    880:              case expr_encode_int16:
                    881:                if (len > 8) {
                    882:                        rv = 7;
                    883:                        strcpy (buf, "(to-int16 ");
                    884:                        rv += print_subexpression (expr -> data.encode_int,
                    885:                                                   buf + rv, len - rv - 1);
                    886:                        buf [rv++] = ')';
                    887:                        buf [rv] = 0;
                    888:                        return rv;
                    889:                }
                    890:                break;
                    891: 
                    892:              case expr_encode_int32:
                    893:                if (len > 8) {
                    894:                        rv = 7;
                    895:                        strcpy (buf, "(to-int32 ");
                    896:                        rv += print_subexpression (expr -> data.encode_int,
                    897:                                                   buf + rv, len - rv - 1);
                    898:                        buf [rv++] = ')';
                    899:                        buf [rv] = 0;
                    900:                        return rv;
                    901:                }
                    902:                break;
                    903: 
                    904:              case expr_const_int:
                    905:                s = print_dec_1 (expr -> data.const_int);
                    906:                rv = strlen (s);
                    907:                if (len > rv) {
                    908:                        strcpy (buf, s);
                    909:                        return rv;
                    910:                }
                    911:                break;
                    912: 
                    913:              case expr_exists:
                    914:                rv = 10 + (strlen (expr -> data.option -> name) +
                    915:                           strlen (expr -> data.option -> universe -> name));
                    916:                if (len > rv) {
                    917:                        sprintf (buf, "(exists %s.%s)",
                    918:                                 expr -> data.option -> universe -> name,
                    919:                                 expr -> data.option -> name);
                    920:                        return rv;
                    921:                }
                    922:                break;
                    923: 
                    924:              case expr_variable_exists:
                    925:                rv = 10 + strlen (expr -> data.variable);
                    926:                if (len > rv) {
                    927:                        sprintf (buf, "(defined %s)", expr -> data.variable);
                    928:                        return rv;
                    929:                }
                    930:                break;
                    931: 
                    932:              case expr_variable_reference:
                    933:                rv = strlen (expr -> data.variable);
                    934:                if (len > rv) {
                    935:                        sprintf (buf, "%s", expr -> data.variable);
                    936:                        return rv;
                    937:                }
                    938:                break;
                    939: 
                    940:              case expr_known:
                    941:                s = "known";
                    942:              astring:
                    943:                rv = strlen (s);
                    944:                if (len > rv) {
                    945:                        strcpy (buf, s);
                    946:                        return rv;
                    947:                }
                    948:                break;
                    949: 
                    950:              case expr_leased_address:
                    951:                s = "leased-address";
                    952:                goto astring;
                    953: 
                    954:              case expr_client_state:
                    955:                s = "client-state";
                    956:                goto astring;
                    957: 
                    958:              case expr_host_decl_name:
                    959:                s = "host-decl-name";
                    960:                goto astring;
                    961: 
                    962:              case expr_lease_time:
                    963:                s = "lease-time";
                    964:                goto astring;
                    965: 
                    966:              case expr_static:
                    967:                s = "static";
                    968:                goto astring;
                    969: 
                    970:              case expr_filename:
                    971:                s = "filename";
                    972:                goto astring;
                    973: 
                    974:              case expr_sname:
                    975:                s = "server-name";
                    976:                goto astring;
                    977: 
                    978:              case expr_reverse:
                    979:                if (len > 11) {
                    980:                        rv = 13;
                    981:                        strcpy (buf, "(reverse ");
                    982:                        rv += print_subexpression (expr -> data.reverse.width,
                    983:                                                   buf + rv, len - rv - 2);
                    984:                        buf [rv++] = ' ';
                    985:                        rv += print_subexpression (expr -> data.reverse.buffer,
                    986:                                                   buf + rv, len - rv - 1);
                    987:                        buf [rv++] = ')';
                    988:                        buf [rv] = 0;
                    989:                        return rv;
                    990:                }
                    991:                break;
                    992: 
                    993:              case expr_binary_to_ascii:
                    994:                if (len > 5) {
                    995:                        rv = 9;
                    996:                        strcpy (buf, "(b2a ");
                    997:                        rv += print_subexpression (expr -> data.b2a.base,
                    998:                                                   buf + rv, len - rv - 4);
                    999:                        buf [rv++] = ' ';
                   1000:                        rv += print_subexpression (expr -> data.b2a.width,
                   1001:                                                   buf + rv, len - rv - 3);
                   1002:                        buf [rv++] = ' ';
                   1003:                        rv += print_subexpression (expr -> data.b2a.separator,
                   1004:                                                   buf + rv, len - rv - 2);
                   1005:                        buf [rv++] = ' ';
                   1006:                        rv += print_subexpression (expr -> data.b2a.buffer,
                   1007:                                                   buf + rv, len - rv - 1);
                   1008:                        buf [rv++] = ')';
                   1009:                        buf [rv] = 0;
                   1010:                        return rv;
                   1011:                }
                   1012:                break;
                   1013: 
                   1014:              case expr_dns_transaction:
                   1015:                rv = 10;
                   1016:                if (len < rv + 2) {
                   1017:                        buf [0] = '(';
                   1018:                        strcpy (&buf [1], "ns-update ");
                   1019:                        while (len < rv + 2) {
                   1020:                                rv += print_subexpression
                   1021:                                        (expr -> data.dns_transaction.car,
                   1022:                                         buf + rv, len - rv - 2);
                   1023:                                buf [rv++] = ' ';
                   1024:                                expr = expr -> data.dns_transaction.cdr;
                   1025:                        }
                   1026:                        buf [rv - 1] = ')';
                   1027:                        buf [rv] = 0;
                   1028:                        return rv;
                   1029:                }
                   1030:                return 0;
                   1031: 
                   1032:              case expr_ns_delete:
                   1033:                s = "delete";
                   1034:                left = 4;
                   1035:                goto dodnsupd;
                   1036:              case expr_ns_exists:
                   1037:                s = "exists";
                   1038:                left = 4;
                   1039:                goto dodnsupd;
                   1040:              case expr_ns_not_exists:
                   1041:                s = "not_exists";
                   1042:                left = 4;
                   1043:                goto dodnsupd;
                   1044:              case expr_ns_add:
                   1045:                s = "update";
                   1046:                left = 5;
                   1047:              dodnsupd:
                   1048:                rv = strlen (s);
                   1049:                if (len > strlen (s) + 1) {
                   1050:                        buf [0] = '(';
                   1051:                        strcpy (buf + 1, s);
                   1052:                        rv++;
                   1053:                        buf [rv++] = ' ';
                   1054:                        s = print_dec_1 (expr -> data.ns_add.rrclass);
                   1055:                        if (len > rv + strlen (s) + left) {
                   1056:                                strcpy (&buf [rv], s);
                   1057:                                rv += strlen (&buf [rv]);
                   1058:                        }
                   1059:                        buf [rv++] = ' ';
                   1060:                        left--;
                   1061:                        s = print_dec_1 (expr -> data.ns_add.rrtype);
                   1062:                        if (len > rv + strlen (s) + left) {
                   1063:                                strcpy (&buf [rv], s);
                   1064:                                rv += strlen (&buf [rv]);
                   1065:                        }
                   1066:                        buf [rv++] = ' ';
                   1067:                        left--;
                   1068:                        rv += print_subexpression
                   1069:                                (expr -> data.ns_add.rrname,
                   1070:                                 buf + rv, len - rv - left);
                   1071:                        buf [rv++] = ' ';
                   1072:                        left--;
                   1073:                        rv += print_subexpression
                   1074:                                (expr -> data.ns_add.rrdata,
                   1075:                                 buf + rv, len - rv - left);
                   1076:                        buf [rv++] = ' ';
                   1077:                        left--;
                   1078:                        rv += print_subexpression
                   1079:                                (expr -> data.ns_add.ttl,
                   1080:                                 buf + rv, len - rv - left);
                   1081:                        buf [rv++] = ')';
                   1082:                        buf [rv] = 0;
                   1083:                        return rv;
                   1084:                }
                   1085:                break;
                   1086: 
                   1087:              case expr_null:
                   1088:                if (len > 6) {
                   1089:                        strcpy (buf, "(null)");
                   1090:                        return 6;
                   1091:                }
                   1092:                break;
                   1093:              case expr_funcall:
                   1094:                rv = 12 + strlen (expr -> data.funcall.name);
                   1095:                if (len > rv + 1) {
                   1096:                        strcpy (buf, "(funcall  ");
                   1097:                        strcpy (buf + 9, expr -> data.funcall.name);
                   1098:                        buf [rv++] = ' ';
                   1099:                        rv += print_subexpression
                   1100:                                (expr -> data.funcall.arglist, buf + rv,
                   1101:                                 len - rv - 1);
                   1102:                        buf [rv++] = ')';
                   1103:                        buf [rv] = 0;
                   1104:                        return rv;
                   1105:                }
                   1106:                break;
                   1107: 
                   1108:              case expr_arg:
                   1109:                rv = print_subexpression (expr -> data.arg.val, buf, len);
                   1110:                if (expr -> data.arg.next && rv + 2 < len) {
                   1111:                        buf [rv++] = ' ';
                   1112:                        rv += print_subexpression (expr -> data.arg.next,
                   1113:                                                   buf, len);
                   1114:                        if (rv + 1 < len)
                   1115:                                buf [rv++] = 0;
                   1116:                        return rv;
                   1117:                }
                   1118:                break;
                   1119: 
                   1120:              case expr_function:
                   1121:                rv = 9;
                   1122:                if (len > rv + 1) {
                   1123:                        struct string_list *foo;
                   1124:                        strcpy (buf, "(function");
                   1125:                        for (foo = expr -> data.func -> args;
                   1126:                             foo; foo = foo -> next) {
                   1127:                                if (len > rv + 2 + strlen (foo -> string)) {
                   1128:                                        buf [rv - 1] = ' ';
                   1129:                                        strcpy (&buf [rv], foo -> string);
                   1130:                                        rv += strlen (foo -> string);
                   1131:                                }
                   1132:                        }
                   1133:                        buf [rv++] = ')';
                   1134:                        buf [rv] = 0;
                   1135:                        return rv;
                   1136:                }
                   1137: 
                   1138:              default:
                   1139:                log_fatal("Impossible case at %s:%d (undefined expression "
                   1140:                          "%d).", MDL, expr->op);
                   1141:                break;
                   1142:        }
                   1143:        return 0;
                   1144: }
                   1145: 
                   1146: void print_expression (name, expr)
                   1147:        const char *name;
                   1148:        struct expression *expr;
                   1149: {
                   1150:        char buf [1024];
                   1151: 
                   1152:        print_subexpression (expr, buf, sizeof buf);
                   1153:        log_info ("%s: %s", name, buf);
                   1154: }
                   1155: 
                   1156: int token_print_indent_concat (FILE *file, int col,  int indent,
                   1157:                               const char *prefix, 
                   1158:                               const char *suffix, ...)
                   1159: {
                   1160:        va_list list;
                   1161:        unsigned len;
                   1162:        char *s, *t, *u;
                   1163: 
                   1164:        va_start (list, suffix);
                   1165:        s = va_arg (list, char *);
                   1166:        len = 0;
                   1167:        while (s) {
                   1168:                len += strlen (s);
                   1169:                s = va_arg (list, char *);
                   1170:        }
                   1171:        va_end (list);
                   1172: 
                   1173:        t = dmalloc (len + 1, MDL);
                   1174:        if (!t)
                   1175:                log_fatal ("token_print_indent: no memory for copy buffer");
                   1176: 
                   1177:        va_start (list, suffix);
                   1178:        s = va_arg (list, char *);
                   1179:        u = t;
                   1180:        while (s) {
                   1181:                len = strlen (s);
                   1182:                strcpy (u, s);
                   1183:                u += len;
                   1184:                s = va_arg (list, char *);
                   1185:        }
                   1186:        va_end (list);
                   1187:        
                   1188:        len = token_print_indent (file, col, indent,
                   1189:                                  prefix, suffix, t);
                   1190:        dfree (t, MDL);
                   1191:        return col;
                   1192: }
                   1193: 
                   1194: int token_indent_data_string (FILE *file, int col, int indent,
                   1195:                              const char *prefix, const char *suffix,
                   1196:                              struct data_string *data)
                   1197: {
                   1198:        int i;
                   1199:        char *buf;
                   1200:        char obuf [3];
                   1201: 
                   1202:        /* See if this is just ASCII. */
                   1203:        for (i = 0; i < data -> len; i++)
                   1204:                if (!isascii (data -> data [i]) ||
                   1205:                    !isprint (data -> data [i]))
                   1206:                        break;
                   1207: 
                   1208:        /* If we have a purely ASCII string, output it as text. */
                   1209:        if (i == data -> len) {
                   1210:                buf = dmalloc (data -> len + 3, MDL);
                   1211:                if (buf) {
                   1212:                        buf [0] = '"';
                   1213:                        memcpy (buf + 1, data -> data, data -> len);
                   1214:                        buf [data -> len + 1] = '"';
                   1215:                        buf [data -> len + 2] = 0;
                   1216:                        i = token_print_indent (file, col, indent,
                   1217:                                                prefix, suffix, buf);
                   1218:                        dfree (buf, MDL);
                   1219:                        return i;
                   1220:                }
                   1221:        }
                   1222: 
                   1223:        for (i = 0; i < data -> len; i++) {
                   1224:                sprintf (obuf, "%2.2x", data -> data [i]);
                   1225:                col = token_print_indent (file, col, indent,
                   1226:                                          i == 0 ? prefix : "",
                   1227:                                          (i + 1 == data -> len
                   1228:                                           ? suffix
                   1229:                                           : ""), obuf);
                   1230:                if (i + 1 != data -> len)
                   1231:                        col = token_print_indent (file, col, indent,
                   1232:                                                  prefix, suffix, ":");
                   1233:        }
                   1234:        return col;
                   1235: }
                   1236: 
                   1237: int token_print_indent (FILE *file, int col, int indent,
                   1238:                        const char *prefix,
                   1239:                        const char *suffix, const char *buf)
                   1240: {
                   1241:        int len = strlen (buf) + strlen (prefix);
                   1242:        if (col + len > 79) {
                   1243:                if (indent + len < 79) {
                   1244:                        indent_spaces (file, indent);
                   1245:                        col = indent;
                   1246:                } else {
                   1247:                        indent_spaces (file, col);
                   1248:                        col = len > 79 ? 0 : 79 - len - 1;
                   1249:                }
                   1250:        } else if (prefix && *prefix) {
                   1251:                fputs (prefix, file);
                   1252:                col += strlen (prefix);
                   1253:        }
                   1254:        fputs (buf, file);
                   1255:        col += len;
                   1256:        if (suffix && *suffix) {
                   1257:                if (col + strlen (suffix) > 79) {
                   1258:                        indent_spaces (file, indent);
                   1259:                        col = indent;
                   1260:                } else {
                   1261:                        fputs (suffix, file);
                   1262:                        col += strlen (suffix);
                   1263:                }
                   1264:        }
                   1265:        return col;
                   1266: }
                   1267: 
                   1268: void indent_spaces (FILE *file, int indent)
                   1269: {
                   1270:        int i;
                   1271:        fputc ('\n', file);
                   1272:        for (i = 0; i < indent; i++)
                   1273:                fputc (' ', file);
                   1274: }
                   1275: 
                   1276: #if defined (NSUPDATE)
                   1277: void print_dns_status (int status, ns_updque *uq)
                   1278: {
                   1279:        char obuf [1024];
                   1280:        char *s = &obuf [0], *end = &obuf [1022];
                   1281:        ns_updrec *u;
                   1282:        int position;
                   1283:        int ttlp;
                   1284:        const char *predicate = "if", *en, *op;
                   1285:        int errorp;
                   1286: 
                   1287:        for (u = ISC_LIST_HEAD (*uq); u; u = ISC_LIST_NEXT (u, r_link)) {
                   1288:                ttlp = 0;
                   1289: 
                   1290:                switch (u -> r_opcode)
                   1291:                {
                   1292:                      case NXRRSET:
                   1293:                        op = "rrset doesn't exist";
                   1294:                        position = 1;
                   1295:                        break;
                   1296:                      case YXRRSET:
                   1297:                        op = "rrset exists";
                   1298:                        position = 1;
                   1299:                        break;
                   1300:                      case NXDOMAIN:
                   1301:                        op = "domain doesn't exist";
                   1302:                        position = 1;
                   1303:                        break;
                   1304:                      case YXDOMAIN:
                   1305:                        op = "domain exists";
                   1306:                        position = 1;
                   1307:                        break;
                   1308:                      case ADD:
                   1309:                        op = "add";
                   1310:                        position = 0;
                   1311:                        ttlp = 1;
                   1312:                        break;
                   1313:                      case DELETE:
                   1314:                        op = "delete";
                   1315:                        position = 0;
                   1316:                        break;
                   1317:                      default:
                   1318:                        op = "unknown";
                   1319:                        position = 0;
                   1320:                        break;
                   1321:                }
                   1322:                if (!position) {
                   1323:                        if (s != &obuf [0] && s + 1 < end)
                   1324:                                *s++ = ' ';
                   1325:                        if (s + strlen (op) < end) {
                   1326:                                strcpy (s, op);
                   1327:                                s += strlen (s);
                   1328:                        }
                   1329:                } else {
                   1330:                        if (s != &obuf [0] && s + 1 < end)
                   1331:                                *s++ = ' ';
                   1332:                        if (s + strlen (predicate) < end) {
                   1333:                                strcpy (s, predicate);
                   1334:                                s += strlen (s);
                   1335:                        }
                   1336:                        predicate = "and";
                   1337:                }
                   1338:                if (u -> r_dname) {
                   1339:                        if (s + 1 < end)
                   1340:                                *s++ = ' ';
                   1341:                        if (s + strlen (u -> r_dname) < end) {
                   1342:                                strcpy (s, u -> r_dname);
                   1343:                                s += strlen (s);
                   1344:                        }
                   1345:                }
                   1346:                if (ttlp) {
                   1347:                        if (s + 1 < end)
                   1348:                                *s++ = ' ';
                   1349:                        /* 27 is as big as a ttl can get. */
                   1350:                        if (s + 27 < end) {
                   1351:                                sprintf (s, "%lu",
                   1352:                                         (unsigned long)(u -> r_ttl));
                   1353:                                s += strlen (s);
                   1354:                        }
                   1355:                }
                   1356:                switch (u -> r_class) {
                   1357:                      case C_IN:
                   1358:                        en = "IN";
                   1359:                        break;
                   1360:                      case C_CHAOS:
                   1361:                        en = "CHAOS";
                   1362:                        break;
                   1363:                      case C_HS:
                   1364:                        en = "HS";
                   1365:                        break;
                   1366:                      default:
                   1367:                        en = "UNKNOWN";
                   1368:                        break;
                   1369:                }
                   1370:                if (s + strlen (en) < end) {
                   1371:                        if (s + 1 < end)
                   1372:                                *s++ = ' ';
                   1373:                        strcpy (s, en);
                   1374:                        s += strlen (en);
                   1375:                }
                   1376:                switch (u -> r_type) {
                   1377:                      case T_A:
                   1378:                        en = "A";
                   1379:                        break;
                   1380:                      case T_AAAA:
                   1381:                        en = "AAAA";
                   1382:                        break;
                   1383:                      case T_PTR:
                   1384:                        en = "PTR";
                   1385:                        break;
                   1386:                      case T_MX:
                   1387:                        en = "MX";
                   1388:                        break;
                   1389:                      case T_TXT:
                   1390:                        en = "TXT";
                   1391:                        break;
                   1392:                      case T_KEY:
                   1393:                        en = "KEY";
                   1394:                        break;
                   1395:                      case T_CNAME:
                   1396:                        en = "CNAME";
                   1397:                        break;
                   1398:                      default:
                   1399:                        en = "UNKNOWN";
                   1400:                        break;
                   1401:                }
                   1402:                if (s + strlen (en) < end) {
                   1403:                        if (s + 1 < end)
                   1404:                                *s++ = ' ';
                   1405:                        strcpy (s, en);
                   1406:                        s += strlen (en);
                   1407:                }
                   1408:                if (u -> r_data) {
                   1409:                        if (s + 1 < end)
                   1410:                                *s++ = ' ';
                   1411:                        if (u -> r_type == T_TXT) {
                   1412:                                if (s + 1 < end)
                   1413:                                        *s++ = '"';
                   1414:                        }
                   1415:                        if(u->r_type == T_KEY) {
                   1416:                          strcat(s, "<keydata>");
                   1417:                          s+=strlen("<keydata>");
                   1418:                        }
                   1419:                        else {  
                   1420:                          if (s + u -> r_size < end) {
                   1421:                            memcpy (s, u -> r_data, u -> r_size);
                   1422:                            s += u -> r_size;
                   1423:                            if (u -> r_type == T_TXT) {
                   1424:                              if (s + 1 < end)
                   1425:                                *s++ = '"';
                   1426:                            }
                   1427:                          }
                   1428:                        }
                   1429:                }
                   1430:                if (position) {
                   1431:                        if (s + 1 < end)
                   1432:                                *s++ = ' ';
                   1433:                        if (s + strlen (op) < end) {
                   1434:                                strcpy (s, op);
                   1435:                                s += strlen (s);
                   1436:                        }
                   1437:                }
                   1438:                if (u == ISC_LIST_TAIL (*uq))
                   1439:                        break;
                   1440:        }
                   1441:        if (s == &obuf [0]) {
                   1442:                strcpy (s, "empty update");
                   1443:                s += strlen (s);
                   1444:        }
                   1445:        if (status == NOERROR)
                   1446:                errorp = 0;
                   1447:        else
                   1448:                errorp = 1;
                   1449:        en = isc_result_totext (status);
                   1450: #if 0
                   1451:        switch (status) {
                   1452:              case -1:
                   1453:                en = "resolver failed";
                   1454:                break;
                   1455: 
                   1456:              case FORMERR:
                   1457:                en = "format error";
                   1458:                break;
                   1459: 
                   1460:              case NOERROR:
                   1461:                en = "succeeded";
                   1462:                errorp = 0;
                   1463:                break;
                   1464: 
                   1465:              case NOTAUTH:
                   1466:                en = "not authorized";
                   1467:                break;
                   1468: 
                   1469:              case NOTIMP:
                   1470:                en = "not implemented";
                   1471:                break;
                   1472: 
                   1473:              case NOTZONE:
                   1474:                en = "not a single valid zone";
                   1475:                break;
                   1476: 
                   1477:              case NXDOMAIN:
                   1478:                en = "no such domain";
                   1479:                break;
                   1480: 
                   1481:              case NXRRSET:
                   1482:                en = "no such record";
                   1483:                break;
                   1484: 
                   1485:              case REFUSED:
                   1486:                en = "refused";
                   1487:                break;
                   1488: 
                   1489:              case SERVFAIL:
                   1490:                en = "server failed";
                   1491:                break;
                   1492: 
                   1493:              case YXDOMAIN:
                   1494:                en = "domain exists";
                   1495:                break;
                   1496: 
                   1497:              case YXRRSET:
                   1498:                en = "record exists";
                   1499:                break;
                   1500: 
                   1501:              default:
                   1502:                en = "unknown error";
                   1503:                break;
                   1504:        }
                   1505: #endif
                   1506: 
                   1507:        if (s + 2 < end) {
                   1508:                *s++ = ':';
                   1509:                *s++ = ' ';
                   1510:        }
                   1511:        if (s + strlen (en) < end) {
                   1512:                strcpy (s, en);
                   1513:                s += strlen (en);
                   1514:        }
                   1515:        if (s + 1 < end)
                   1516:                *s++ = '.';
                   1517:        *s++ = 0;
                   1518:        if (errorp)
                   1519:                log_error ("%s", obuf);
                   1520:        else
                   1521:                log_info ("%s", obuf);
                   1522: }
                   1523: #endif /* NSUPDATE */
                   1524: 
                   1525: /* Format the given time as "A; # B", where A is the format
                   1526:  * used by the parser, and B is the local time, for humans.
                   1527:  */
                   1528: const char *
                   1529: print_time(TIME t)
                   1530: {
                   1531:        static char buf[sizeof("epoch 9223372036854775807; "
                   1532:                               "# Wed Jun 30 21:49:08 2147483647")];
                   1533:        static char buf1[sizeof("# Wed Jun 30 21:49:08 2147483647")];
                   1534:        time_t since_epoch;
                   1535:        /* The string:         "6 2147483647/12/31 23:59:60;"
                   1536:         * is smaller than the other, used to declare the buffer size, so
                   1537:         * we can use one buffer for both.
                   1538:         */
                   1539: 
                   1540:        if (t == MAX_TIME)
                   1541:                return "never;";
                   1542: 
                   1543:        if (t < 0)
                   1544:                return NULL;
                   1545: 
                   1546:        /* For those lucky enough to have a 128-bit time_t, ensure that
                   1547:         * whatever (corrupt) value we're given doesn't exceed the static
                   1548:         * buffer.
                   1549:         */
                   1550: #if (MAX_TIME > 0x7fffffffffffffff)
                   1551:        if (t > 0x7fffffffffffffff)
                   1552:                return NULL;
                   1553: #endif
                   1554: 
                   1555:        if (db_time_format == LOCAL_TIME_FORMAT) {
                   1556:                since_epoch = mktime(localtime(&t));
                   1557:                if ((strftime(buf1, sizeof(buf1),
                   1558:                              "# %a %b %d %H:%M:%S %Y",
                   1559:                              localtime(&t)) == 0) ||
                   1560:                    (snprintf(buf, sizeof(buf), "epoch %lu; %s",
                   1561:                              (unsigned long)since_epoch, buf1) >= sizeof(buf)))
                   1562:                        return NULL;
                   1563: 
                   1564:        } else {
                   1565:                /* No bounds check for the year is necessary - in this case,
                   1566:                 * strftime() will run out of space and assert an error.
                   1567:                 */
                   1568:                if (strftime(buf, sizeof(buf), "%w %Y/%m/%d %H:%M:%S;",
                   1569:                             gmtime(&t)) == 0)
                   1570:                        return NULL;
                   1571:        }
                   1572: 
                   1573:        return buf;
                   1574: }

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