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

5
Last change on this file since cb68253 was cb68253, checked in by Sebastian Huber <sebastian.huber@…>, on 09/07/18 at 04:19:02

network: Use kernel/user space header files

Add and use <machine/rtems-bsd-kernel-space.h> and
<machine/rtems-bsd-user-space.h> similar to the libbsd to avoid command
line defines and defines scattered throught the code base.

Simplify cpukit/libnetworking/Makefile.am.

Update #3375.

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