source: rtems/cpukit/libnetworking/libc/ns_print.c @ cb2f320

4.104.114.84.9
Last change on this file since cb2f320 was cb2f320, checked in by Joel Sherrill <joel.sherrill@…>, on Mar 5, 2004 at 6:02:41 PM

2004-03-05 Joel Sherrill <joel@…>

  • libblock/src/bdbuf.c, libblock/src/ramdisk.c, libcsupport/src/newlibc.c, libcsupport/src/sync.c, libmisc/cpuuse/cpuuse.c, libmisc/monitor/mon-symbols.c, libmisc/shell/cmds.c, libmisc/shell/shell.c, libnetworking/kern/kern_sysctl.c, libnetworking/lib/ftpfs.c, libnetworking/lib/tftpDriver.c, libnetworking/libc/gethostbydns.c, libnetworking/libc/gethostbyht.c, libnetworking/libc/gethostnamadr.c, libnetworking/libc/getnetbyht.c, libnetworking/libc/getnetnamadr.c, libnetworking/libc/inet_addr.c, libnetworking/libc/linkaddr.c, libnetworking/libc/map_v4v6.c, libnetworking/libc/ns_print.c, libnetworking/libc/ns_ttl.c, libnetworking/libc/nsap_addr.c, libnetworking/libc/rcmd.c, libnetworking/libc/res_debug.c, libnetworking/libc/res_mkupdate.c, libnetworking/libc/res_query.c, libnetworking/libc/res_send.c, libnetworking/libc/res_update.c, libnetworking/net/radix.c, libnetworking/rtems/mkrootfs.c, librpc/src/rpc/clnt_perror.c, librpc/src/rpc/svc.c, score/macros/rtems/score/chain.inl, score/src/objectidtoname.c: Too much was accidentally committed -- revert.
  • Property mode set to 100644
File size: 17.1 KB
Line 
1/*
2 * Copyright (c) 1996, 1998 by Internet Software Consortium.
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
9 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
10 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
11 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
13 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
14 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
15 * SOFTWARE.
16 */
17
18#if !defined(__rtems__)
19#if !defined(LINT) && !defined(CODECENTER)
20static char rcsid[] = "$Id$";
21#endif /* not lint */
22#endif /* not rtems */
23
24/* Import. */
25
26#include <sys/types.h>
27#include <sys/socket.h>
28
29#include <netinet/in.h>
30#include <arpa/nameser.h>
31#include <arpa/inet.h>
32
33#include <assert.h>
34#include <errno.h>
35#include <resolv.h>
36#include <string.h>
37#include <ctype.h>
38
39#define SPRINTF(x) ((size_t)sprintf x)
40
41/* Forward. */
42
43static size_t   prune_origin(const char *name, const char *origin);
44static int      charstr(const u_char *rdata, const u_char *edata,
45                        char **buf, size_t *buflen);
46static int      addname(const u_char *msg, size_t msglen,
47                        const u_char **p, const char *origin,
48                        char **buf, size_t *buflen);
49static void     addlen(size_t len, char **buf, size_t *buflen);
50static int      addstr(const char *src, size_t len,
51                       char **buf, size_t *buflen);
52static int      addtab(size_t len, size_t target, int spaced,
53                       char **buf, size_t *buflen);
54
55/* Macros. */
56
57#define T(x) \
58        do { \
59                if ((x) < 0) \
60                        return (-1); \
61        } while (0)
62
63/* Public. */
64
65/*
66 * int
67 * ns_sprintrr(handle, rr, name_ctx, origin, buf, buflen)
68 *      Convert an RR to presentation format.
69 * return:
70 *      Number of characters written to buf, or -1 (check errno).
71 */
72int
73ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
74            const char *name_ctx, const char *origin,
75            char *buf, size_t buflen)
76{
77        int n;
78
79        n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),
80                         ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),
81                         ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),
82                         name_ctx, origin, buf, buflen);
83        return (n);
84}
85
86/*
87 * int
88 * ns_sprintrrf(msg, msglen, name, class, type, ttl, rdata, rdlen,
89 *             name_ctx, origin, buf, buflen)
90 *      Convert the fields of an RR into presentation format.
91 * return:
92 *      Number of characters written to buf, or -1 (check errno).
93 */
94int
95ns_sprintrrf(const u_char *msg, size_t msglen,
96            const char *name, ns_class class, ns_type type,
97            u_long ttl, const u_char *rdata, size_t rdlen,
98            const char *name_ctx, const char *origin,
99            char *buf, size_t buflen)
100{
101        const char *obuf = buf;
102        const u_char *edata = rdata + rdlen;
103        int spaced = 0;
104
105        const char *comment;
106        char tmp[100];
107        int len, x;
108
109        /*
110         * Owner.
111         */
112        if (name_ctx != NULL && strcasecmp(name_ctx, name) == 0) {
113                T(addstr("\t\t\t", 3, &buf, &buflen));
114        } else {
115                len = prune_origin(name, origin);
116                if (len == 0) {
117                        T(addstr("@\t\t\t", 4, &buf, &buflen));
118                } else {
119                        T(addstr(name, len, &buf, &buflen));
120                        /* Origin not used and no trailing dot? */
121                        if ((!origin || !origin[0] || name[len] == '\0') &&
122                            name[len - 1] != '.') {
123                                T(addstr(".", 1, &buf, &buflen));
124                                len++;
125                        }
126                        T(spaced = addtab(len, 24, spaced, &buf, &buflen));
127                }
128        }
129
130        /*
131         * TTL, Class, Type.
132         */
133        T(x = ns_format_ttl(ttl, buf, buflen));
134        addlen(x, &buf, &buflen);
135        len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type)));
136        T(addstr(tmp, len, &buf, &buflen));
137        T(spaced = addtab(x + len, 16, spaced, &buf, &buflen));
138
139        /*
140         * RData.
141         */
142        switch (type) {
143        case ns_t_a:
144                if (rdlen != NS_INADDRSZ)
145                        goto formerr;
146                (void) inet_ntop(AF_INET, rdata, buf, buflen);
147                addlen(strlen(buf), &buf, &buflen);
148                break;
149
150        case ns_t_cname:
151        case ns_t_mb:
152        case ns_t_mg:
153        case ns_t_mr:
154        case ns_t_ns:
155        case ns_t_ptr:
156                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
157                break;
158
159        case ns_t_hinfo:
160        case ns_t_isdn:
161                /* First word. */
162                T(len = charstr(rdata, edata, &buf, &buflen));
163                if (len == 0)
164                        goto formerr;
165                rdata += len;
166                T(addstr(" ", 1, &buf, &buflen));
167
168                /* Second word. */
169                T(len = charstr(rdata, edata, &buf, &buflen));
170                if (len == 0)
171                        goto formerr;
172                rdata += len;
173                break;
174
175        case ns_t_soa: {
176                u_long t;
177
178                /* Server name. */
179                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
180                T(addstr(" ", 1, &buf, &buflen));
181
182                /* Administrator name. */
183                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
184                T(addstr(" (\n", 3, &buf, &buflen));
185                spaced = 0;
186
187                if ((edata - rdata) != 5*NS_INT32SZ)
188                        goto formerr;
189
190                /* Serial number. */
191                t = ns_get32(rdata);  rdata += NS_INT32SZ;
192                T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
193                len = SPRINTF((tmp, "%lu", t));
194                T(addstr(tmp, len, &buf, &buflen));
195                T(spaced = addtab(len, 16, spaced, &buf, &buflen));
196                T(addstr("; serial\n", 9, &buf, &buflen));
197                spaced = 0;
198
199                /* Refresh interval. */
200                t = ns_get32(rdata);  rdata += NS_INT32SZ;
201                T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
202                T(len = ns_format_ttl(t, buf, buflen));
203                addlen(len, &buf, &buflen);
204                T(spaced = addtab(len, 16, spaced, &buf, &buflen));
205                T(addstr("; refresh\n", 10, &buf, &buflen));
206                spaced = 0;
207
208                /* Retry interval. */
209                t = ns_get32(rdata);  rdata += NS_INT32SZ;
210                T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
211                T(len = ns_format_ttl(t, buf, buflen));
212                addlen(len, &buf, &buflen);
213                T(spaced = addtab(len, 16, spaced, &buf, &buflen));
214                T(addstr("; retry\n", 8, &buf, &buflen));
215                spaced = 0;
216
217                /* Expiry. */
218                t = ns_get32(rdata);  rdata += NS_INT32SZ;
219                T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
220                T(len = ns_format_ttl(t, buf, buflen));
221                addlen(len, &buf, &buflen);
222                T(spaced = addtab(len, 16, spaced, &buf, &buflen));
223                T(addstr("; expiry\n", 9, &buf, &buflen));
224                spaced = 0;
225
226                /* Minimum TTL. */
227                t = ns_get32(rdata);  rdata += NS_INT32SZ;
228                T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
229                T(len = ns_format_ttl(t, buf, buflen));
230                addlen(len, &buf, &buflen);
231                T(addstr(" )", 2, &buf, &buflen));
232                T(spaced = addtab(len, 16, spaced, &buf, &buflen));
233                T(addstr("; minimum\n", 10, &buf, &buflen));
234
235                break;
236            }
237
238        case ns_t_mx:
239        case ns_t_afsdb:
240        case ns_t_rt: {
241                u_int t;
242
243                if (rdlen < NS_INT16SZ)
244                        goto formerr;
245
246                /* Priority. */
247                t = ns_get16(rdata);
248                rdata += NS_INT16SZ;
249                len = SPRINTF((tmp, "%u ", t));
250                T(addstr(tmp, len, &buf, &buflen));
251
252                /* Target. */
253                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
254
255                break;
256            }
257
258        case ns_t_px: {
259                u_int t;
260
261                if (rdlen < NS_INT16SZ)
262                        goto formerr;
263
264                /* Priority. */
265                t = ns_get16(rdata);
266                rdata += NS_INT16SZ;
267                len = SPRINTF((tmp, "%u ", t));
268                T(addstr(tmp, len, &buf, &buflen));
269
270                /* Name1. */
271                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
272                T(addstr(" ", 1, &buf, &buflen));
273
274                /* Name2. */
275                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
276
277                break;
278            }
279
280        case ns_t_x25:
281                T(len = charstr(rdata, edata, &buf, &buflen));
282                if (len == 0)
283                        goto formerr;
284                rdata += len;
285                break;
286
287        case ns_t_txt:
288                while (rdata < edata) {
289                        T(len = charstr(rdata, edata, &buf, &buflen));
290                        if (len == 0)
291                                goto formerr;
292                        rdata += len;
293                        if (rdata < edata)
294                                T(addstr(" ", 1, &buf, &buflen));
295                }
296                break;
297
298        case ns_t_nsap: {
299                char t[255*3];
300
301                (void) inet_nsap_ntoa(rdlen, rdata, t);
302                T(addstr(t, strlen(t), &buf, &buflen));
303                break;
304            }
305
306        case ns_t_aaaa:
307                if (rdlen != NS_IN6ADDRSZ)
308                        goto formerr;
309                (void) inet_ntop(AF_INET6, rdata, buf, buflen);
310                addlen(strlen(buf), &buf, &buflen);
311                break;
312
313        case ns_t_loc: {
314                char t[255];
315
316                /* XXX protocol format checking? */
317                (void) loc_ntoa(rdata, t);
318                T(addstr(t, strlen(t), &buf, &buflen));
319                break;
320            }
321
322        case ns_t_naptr: {
323                u_int order, preference;
324                char t[50];
325
326                if (rdlen < 2*NS_INT16SZ)
327                        goto formerr;
328
329                /* Order, Precedence. */
330                order = ns_get16(rdata);        rdata += NS_INT16SZ;
331                preference = ns_get16(rdata);   rdata += NS_INT16SZ;
332                len = SPRINTF((t, "%u %u ", order, preference));
333                T(addstr(t, len, &buf, &buflen));
334
335                /* Flags. */
336                T(len = charstr(rdata, edata, &buf, &buflen));
337                if (len == 0)
338                        goto formerr;
339                rdata += len;
340                T(addstr(" ", 1, &buf, &buflen));
341
342                /* Service. */
343                T(len = charstr(rdata, edata, &buf, &buflen));
344                if (len == 0)
345                        goto formerr;
346                rdata += len;
347                T(addstr(" ", 1, &buf, &buflen));
348
349                /* Regexp. */
350                T(len = charstr(rdata, edata, &buf, &buflen));
351                if (len < 0)
352                        return (-1);
353                if (len == 0)
354                        goto formerr;
355                rdata += len;
356                T(addstr(" ", 1, &buf, &buflen));
357
358                /* Server. */
359                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
360                break;
361            }
362
363        case ns_t_srv: {
364                u_int priority, weight, port;
365                char t[50];
366
367                if (rdlen < NS_INT16SZ*3)
368                        goto formerr;
369
370                /* Priority, Weight, Port. */
371                priority = ns_get16(rdata);  rdata += NS_INT16SZ;
372                weight   = ns_get16(rdata);  rdata += NS_INT16SZ;
373                port     = ns_get16(rdata);  rdata += NS_INT16SZ;
374                len = SPRINTF((t, "%u %u %u ", priority, weight, port));
375                T(addstr(t, len, &buf, &buflen));
376
377                /* Server. */
378                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
379                break;
380            }
381
382        case ns_t_minfo:
383        case ns_t_rp:
384                /* Name1. */
385                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
386                T(addstr(" ", 1, &buf, &buflen));
387
388                /* Name2. */
389                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
390
391                break;
392
393        case ns_t_wks: {
394                int n, lcnt;
395
396                if (rdlen < NS_INT32SZ + 1)
397                        goto formerr;
398
399                /* Address. */
400                (void) inet_ntop(AF_INET, rdata, buf, buflen);
401                addlen(strlen(buf), &buf, &buflen);
402                rdata += NS_INADDRSZ;
403
404                /* Protocol. */
405                len = SPRINTF((tmp, " %u ( ", *rdata));
406                T(addstr(tmp, len, &buf, &buflen));
407                rdata += NS_INT8SZ;
408
409                /* Bit map. */
410                n = 0;
411                lcnt = 0;
412                while (rdata < edata) {
413                        u_int c = *rdata++;
414                        do {
415                                if (c & 0200) {
416                                        if (lcnt == 0) {
417                                                T(addstr("\n\t\t\t\t", 5,
418                                                         &buf, &buflen));
419                                                lcnt = 10;
420                                                spaced = 0;
421                                        }
422                                        len = SPRINTF((tmp, "%d ", n));
423                                        T(addstr(tmp, len, &buf, &buflen));
424                                        lcnt--;
425                                }
426                                c <<= 1;
427                        } while (++n & 07);
428                }
429                T(addstr(")", 1, &buf, &buflen));
430
431                break;
432            }
433
434        case ns_t_key: {
435                char base64_key[NS_MD5RSA_MAX_BASE64];
436                u_int keyflags, protocol, algorithm;
437                const char *leader;
438                int n;
439
440                if (rdlen < NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
441                        goto formerr;
442
443                /* Key flags, Protocol, Algorithm. */
444                keyflags = ns_get16(rdata);  rdata += NS_INT16SZ;
445                protocol = *rdata++;
446                algorithm = *rdata++;
447                len = SPRINTF((tmp, "0x%04x %u %u",
448                               keyflags, protocol, algorithm));
449                T(addstr(tmp, len, &buf, &buflen));
450
451                /* Public key data. */
452                len = b64_ntop(rdata, edata - rdata,
453                               base64_key, sizeof base64_key);
454                if (len < 0)
455                        goto formerr;
456                if (len > 15) {
457                        T(addstr(" (", 2, &buf, &buflen));
458                        leader = "\n\t\t";
459                        spaced = 0;
460                } else
461                        leader = " ";
462                for (n = 0; n < len; n += 48) {
463                        T(addstr(leader, strlen(leader), &buf, &buflen));
464                        T(addstr(base64_key + n, MIN(len - n, 48),
465                                 &buf, &buflen));
466                }
467                if (len > 15)
468                        T(addstr(" )", 2, &buf, &buflen));
469
470                break;
471            }
472
473        case ns_t_sig: {
474                char base64_key[NS_MD5RSA_MAX_BASE64];
475                u_int type, algorithm, labels, footprint;
476                const char *leader;
477                u_long t;
478                int n;
479
480                if (rdlen < 22)
481                        goto formerr;
482
483                /* Type covered, Algorithm, Label count, Original TTL. */
484                type = ns_get16(rdata);  rdata += NS_INT16SZ;
485                algorithm = *rdata++;
486                labels = *rdata++;
487                t = ns_get32(rdata);  rdata += NS_INT32SZ;
488                len = SPRINTF((tmp, " %s %d %lu ",
489                               p_type(type), algorithm, t));
490                T(addstr(tmp, len, &buf, &buflen));
491                if (labels != (u_int)dn_count_labels(name))
492                        goto formerr;
493
494                /* Signature expiry. */
495                t = ns_get32(rdata);  rdata += NS_INT32SZ;
496                len = SPRINTF((tmp, "%s ", p_secstodate(t)));
497                T(addstr(tmp, len, &buf, &buflen));
498
499                /* Time signed. */
500                t = ns_get32(rdata);  rdata += NS_INT32SZ;
501                len = SPRINTF((tmp, "%s ", p_secstodate(t)));
502                T(addstr(tmp, len, &buf, &buflen));
503
504                /* Signature Footprint. */
505                footprint = ns_get16(rdata);  rdata += NS_INT16SZ;
506                len = SPRINTF((tmp, "%u ", footprint));
507                T(addstr(tmp, len, &buf, &buflen));
508
509                /* Signer's name. */
510                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
511
512                /* Signature. */
513                len = b64_ntop(rdata, edata - rdata,
514                               base64_key, sizeof base64_key);
515                if (len > 15) {
516                        T(addstr(" (", 2, &buf, &buflen));
517                        leader = "\n\t\t";
518                        spaced = 0;
519                } else
520                        leader = " ";
521                if (len < 0)
522                        goto formerr;
523                for (n = 0; n < len; n += 48) {
524                        T(addstr(leader, strlen(leader), &buf, &buflen));
525                        T(addstr(base64_key + n, MIN(len - n, 48),
526                                 &buf, &buflen));
527                }
528                if (len > 15)
529                        T(addstr(" )", 2, &buf, &buflen));
530
531                break;
532            }
533
534        case ns_t_nxt: {
535                int n, c;
536
537                /* Next domain name. */
538                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
539
540                /* Type bit map. */
541                n = edata - rdata;
542                for (c = 0; c < n*8; c++)
543                        if (NS_NXT_BIT_ISSET(c, rdata)) {
544                                len = SPRINTF((tmp, " %s", p_type(c)));
545                                T(addstr(tmp, len, &buf, &buflen));
546                        }
547                break;
548            }
549
550        default:
551                comment = "unknown RR type";
552                goto hexify;
553        }
554        return (buf - obuf);
555 formerr:
556        comment = "RR format error";
557 hexify: {
558        int n, m;
559        char *p;
560
561        len = SPRINTF((tmp, "\\#(\t\t; %s", comment));
562        T(addstr(tmp, len, &buf, &buflen));
563        while (rdata < edata) {
564                p = tmp;
565                p += SPRINTF((p, "\n\t"));
566                spaced = 0;
567                n = MIN(16, edata - rdata);
568                for (m = 0; m < n; m++)
569                        p += SPRINTF((p, "%02x ", rdata[m]));
570                T(addstr(tmp, p - tmp, &buf, &buflen));
571                if (n < 16) {
572                        T(addstr(")", 1, &buf, &buflen));
573                        T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen));
574                }
575                p = tmp;
576                p += SPRINTF((p, "; "));
577                for (m = 0; m < n; m++)
578                        *p++ = (isascii(rdata[m]) && isprint(rdata[m]))
579                                ? rdata[m]
580                                : '.';
581                T(addstr(tmp, p - tmp, &buf, &buflen));
582                rdata += n;
583        }
584        return (buf - obuf);
585    }
586}
587
588/* Private. */
589
590/*
591 * size_t
592 * prune_origin(name, origin)
593 *      Find out if the name is at or under the current origin.
594 * return:
595 *      Number of characters in name before start of origin,
596 *      or length of name if origin does not match.
597 * notes:
598 *      This function should share code with samedomain().
599 */
600static size_t
601prune_origin(const char *name, const char *origin) {
602        const char *oname = name;
603
604        while (*name != '\0') {
605                if (origin != NULL && strcasecmp(name, origin) == 0)
606                        return (name - oname - (name > oname));
607                while (*name != '\0') {
608                        if (*name == '\\') {
609                                name++;
610                                /* XXX need to handle \nnn form. */
611                                if (*name == '\0')
612                                        break;
613                        } else if (*name == '.') {
614                                name++;
615                                break;
616                        }
617                        name++;
618                }
619        }
620        return (name - oname);
621}
622
623/*
624 * int
625 * charstr(rdata, edata, buf, buflen)
626 *      Format a <character-string> into the presentation buffer.
627 * return:
628 *      Number of rdata octets consumed
629 *      0 for protocol format error
630 *      -1 for output buffer error
631 * side effects:
632 *      buffer is advanced on success.
633 */
634static int
635charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) {
636        const u_char *odata = rdata;
637        size_t save_buflen = *buflen;
638        char *save_buf = *buf;
639
640        if (addstr("\"", 1, buf, buflen) < 0)
641                goto enospc;
642        if (rdata < edata) {
643                int n = *rdata;
644
645                if (rdata + 1 + n <= edata) {
646                        rdata++;
647                        while (n-- > 0) {
648                                if (strchr("\n\"\\", *rdata) != NULL)
649                                        if (addstr("\\", 1, buf, buflen) < 0)
650                                                goto enospc;
651                                if (addstr((const char *)rdata, 1,
652                                           buf, buflen) < 0)
653                                        goto enospc;
654                                rdata++;
655                        }
656                }
657        }
658        if (addstr("\"", 1, buf, buflen) < 0)
659                goto enospc;
660        return (rdata - odata);
661 enospc:
662        errno = ENOSPC;
663        *buf = save_buf;
664        *buflen = save_buflen;
665        return (-1);
666}
667
668static int
669addname(const u_char *msg, size_t msglen,
670        const u_char **pp, const char *origin,
671        char **buf, size_t *buflen)
672{
673        size_t newlen, save_buflen = *buflen;
674        char *save_buf = *buf;
675        int n;
676
677        n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen);
678        if (n < 0)
679                goto enospc;    /* Guess. */
680        newlen = prune_origin(*buf, origin);
681        if ((origin == NULL || origin[0] == '\0' || (*buf)[newlen] == '\0') &&
682            (newlen == 0 || (*buf)[newlen - 1] != '.')) {
683                /* No trailing dot. */
684                if (newlen + 2 > *buflen)
685                        goto enospc;    /* No room for ".\0". */
686                (*buf)[newlen++] = '.';
687                (*buf)[newlen] = '\0';
688        }
689        if (newlen == 0) {
690                /* Use "@" instead of name. */
691                if (newlen + 2 > *buflen)
692                        goto enospc;        /* No room for "@\0". */
693                (*buf)[newlen++] = '@';
694                (*buf)[newlen] = '\0';
695        }
696        *pp += n;
697        addlen(newlen, buf, buflen);
698        **buf = '\0';
699        return (newlen);
700 enospc:
701        errno = ENOSPC;
702        *buf = save_buf;
703        *buflen = save_buflen;
704        return (-1);
705}
706
707static void
708addlen(size_t len, char **buf, size_t *buflen) {
709        assert(len <= *buflen);
710        *buf += len;
711        *buflen -= len;
712}
713
714static int
715addstr(const char *src, size_t len, char **buf, size_t *buflen) {
716        if (len > *buflen) {
717                errno = ENOSPC;
718                return (-1);
719        }
720        memcpy(*buf, src, len);
721        addlen(len, buf, buflen);
722        **buf = '\0';
723        return (0);
724}
725
726static int
727addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
728        size_t save_buflen = *buflen;
729        char *save_buf = *buf;
730        int t;
731
732        if (spaced || len >= target - 1) {
733                T(addstr("  ", 2, buf, buflen));
734                spaced = 1;
735        } else {
736                for (t = (target - len - 1) / 8; t >= 0; t--)
737                        if (addstr("\t", 1, buf, buflen) < 0) {
738                                *buflen = save_buflen;
739                                *buf = save_buf;
740                                return (-1);
741                        }
742                spaced = 0;
743        }
744        return (spaced);
745}
Note: See TracBrowser for help on using the repository browser.