[BACK]Return to lbuf.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / sudo

Annotation of src/usr.bin/sudo/lbuf.c, Revision 1.5

1.1       millert     1: /*
1.3       millert     2:  * Copyright (c) 2007-2009 Todd C. Miller <Todd.Miller@courtesan.com>
1.1       millert     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 THE AUTHOR DISCLAIMS ALL WARRANTIES
                      9:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     10:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     11:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     12:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     13:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     14:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     15:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
                     16:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     17:  */
                     18:
                     19: #include <config.h>
                     20:
                     21: #include <sys/types.h>
                     22: #include <sys/param.h>
                     23: #include <sys/ioctl.h>
                     24: #include <stdio.h>
                     25: #ifdef STDC_HEADERS
                     26: # include <stdlib.h>
                     27: # include <stddef.h>
                     28: #else
                     29: # ifdef HAVE_STDLIB_H
                     30: #  include <stdlib.h>
                     31: # endif
                     32: #endif /* STDC_HEADERS */
                     33: #ifdef HAVE_STRING_H
                     34: # include <string.h>
                     35: #else
                     36: # ifdef HAVE_STRINGS_H
                     37: #  include <strings.h>
                     38: # endif
                     39: #endif /* HAVE_STRING_H */
                     40: #ifdef HAVE_UNISTD_H
                     41: # include <unistd.h>
                     42: #endif /* HAVE_UNISTD_H */
                     43: #include <ctype.h>
1.3       millert    44: #ifdef HAVE_TERMIOS_H
                     45: # include <termios.h>
                     46: #else
                     47: # ifdef HAVE_TERMIO_H
                     48: #  include <termio.h>
                     49: # endif
                     50: #endif
1.1       millert    51:
                     52: #include "sudo.h"
                     53: #include "lbuf.h"
                     54:
1.5     ! naddy      55: #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
        !            56: # define TIOCGWINSZ    TIOCGSIZE
        !            57: # define winsize       ttysize
        !            58: # define ws_col                ts_cols
1.1       millert    59: #endif
                     60:
                     61: int
                     62: get_ttycols()
                     63: {
                     64:     char *p;
                     65:     int cols;
                     66: #ifdef TIOCGSIZE
1.5     ! naddy      67:     struct winsize win;
1.1       millert    68:
1.5     ! naddy      69:     if (ioctl(STDERR_FILENO, TIOCGWINSZ, &win) == 0 && win.ws_col != 0)
        !            70:        return((int)win.ws_col);
1.1       millert    71: #endif
                     72:
                     73:     /* Fall back on $COLUMNS. */
                     74:     if ((p = getenv("COLUMNS")) == NULL || (cols = atoi(p)) <= 0)
                     75:        cols = 80;
                     76:     return(cols);
                     77: }
                     78:
                     79: /*
                     80:  * TODO: add support for embedded newlines in lbufs
                     81:  */
                     82:
                     83: void
                     84: lbuf_init(lbuf, buf, indent, continuation)
                     85:     struct lbuf *lbuf;
                     86:     char *buf;
                     87:     int indent;
                     88:     int continuation;
                     89: {
                     90:     lbuf->continuation = continuation;
                     91:     lbuf->indent = indent;
                     92:     lbuf->len = 0;
                     93:     lbuf->size = 0;
                     94:     lbuf->buf = NULL;
                     95: }
                     96:
                     97: void
                     98: lbuf_destroy(lbuf)
                     99:     struct lbuf *lbuf;
                    100: {
                    101:     efree(lbuf->buf);
                    102:     lbuf->buf = NULL;
                    103: }
                    104:
                    105: /*
                    106:  * Append strings to the buffer, expanding it as needed.
                    107:  */
                    108: void
                    109: #ifdef __STDC__
                    110: lbuf_append_quoted(struct lbuf *lbuf, const char *set, ...)
                    111: #else
1.2       millert   112: lbuf_append_quoted(lbuf, set, va_alist)
1.1       millert   113:        struct lbuf *lbuf;
                    114:        const char *set;
                    115:        va_dcl
                    116: #endif
                    117: {
                    118:     va_list ap;
                    119:     int len = 0;
                    120:     char *cp, *s;
                    121:
                    122: #ifdef __STDC__
                    123:     va_start(ap, set);
                    124: #else
                    125:     va_start(ap);
                    126: #endif
                    127:     while ((s = va_arg(ap, char *)) != NULL) {
                    128:        len += strlen(s);
                    129:        for (cp = s; (cp = strpbrk(cp, set)) != NULL; cp++)
                    130:            len++;
                    131:     }
                    132:     va_end(ap);
                    133:
                    134:     /* Expand buffer as needed. */
                    135:     if (lbuf->len + len >= lbuf->size) {
                    136:        do {
                    137:            lbuf->size += 256;
                    138:        } while (lbuf->len + len >= lbuf->size);
                    139:        lbuf->buf = erealloc(lbuf->buf, lbuf->size);
                    140:     }
                    141:
                    142: #ifdef __STDC__
                    143:     va_start(ap, set);
                    144: #else
                    145:     va_start(ap);
                    146: #endif
                    147:     /* Append each string. */
                    148:     while ((s = va_arg(ap, char *)) != NULL) {
                    149:        while ((cp = strpbrk(s, set)) != NULL) {
                    150:            len = (int)(cp - s);
                    151:            memcpy(lbuf->buf + lbuf->len, s, len);
                    152:            lbuf->len += len;
                    153:            lbuf->buf[lbuf->len++] = '\\';
                    154:            lbuf->buf[lbuf->len++] = *cp;
                    155:            s = cp + 1;
                    156:        }
                    157:        if (*s != '\0') {
                    158:            len = strlen(s);
                    159:            memcpy(lbuf->buf + lbuf->len, s, len);
                    160:            lbuf->len += len;
                    161:        }
                    162:     }
                    163:     lbuf->buf[lbuf->len] = '\0';
                    164:     va_end(ap);
                    165: }
                    166:
                    167: /*
                    168:  * Append strings to the buffer, expanding it as needed.
                    169:  */
                    170: void
                    171: #ifdef __STDC__
                    172: lbuf_append(struct lbuf *lbuf, ...)
                    173: #else
                    174: lbuf_append(lbuf, va_alist)
                    175:        struct lbuf *lbuf;
                    176:        va_dcl
                    177: #endif
                    178: {
                    179:     va_list ap;
                    180:     int len = 0;
                    181:     char *s;
                    182:
                    183: #ifdef __STDC__
                    184:     va_start(ap, lbuf);
                    185: #else
                    186:     va_start(ap);
                    187: #endif
                    188:     while ((s = va_arg(ap, char *)) != NULL)
                    189:        len += strlen(s);
                    190:     va_end(ap);
                    191:
                    192:     /* Expand buffer as needed. */
                    193:     if (lbuf->len + len >= lbuf->size) {
                    194:        do {
                    195:            lbuf->size += 256;
                    196:        } while (lbuf->len + len >= lbuf->size);
                    197:        lbuf->buf = erealloc(lbuf->buf, lbuf->size);
                    198:     }
                    199:
                    200: #ifdef __STDC__
                    201:     va_start(ap, lbuf);
                    202: #else
                    203:     va_start(ap);
                    204: #endif
                    205:     /* Append each string. */
                    206:     while ((s = va_arg(ap, char *)) != NULL) {
                    207:        len = strlen(s);
                    208:        memcpy(lbuf->buf + lbuf->len, s, len);
                    209:        lbuf->len += len;
                    210:     }
                    211:     lbuf->buf[lbuf->len] = '\0';
                    212:     va_end(ap);
                    213: }
                    214:
                    215: /*
                    216:  * Print the buffer with word wrap based on the tty width.
                    217:  * The lbuf is reset on return.
                    218:  */
                    219: void
                    220: lbuf_print(lbuf)
                    221:     struct lbuf *lbuf;
                    222: {
                    223:     char *cp;
                    224:     int i, have, contlen;
                    225:     static int cols = -1;
                    226:
                    227:     if (cols == -1)
                    228:        cols = get_ttycols();
                    229:     contlen = lbuf->continuation ? 2 : 0;
                    230:
                    231:     /* For very small widths just give up... */
                    232:     if (cols <= lbuf->indent + contlen + 20) {
                    233:        puts(lbuf->buf);
                    234:        goto done;
                    235:     }
                    236:
                    237:     /*
                    238:      * Print the buffer, splitting the line as needed on a word
                    239:      * boundary.
                    240:      */
                    241:     cp = lbuf->buf;
                    242:     have = cols;
                    243:     while (cp != NULL && *cp != '\0') {
                    244:        char *ep = NULL;
                    245:        int need = lbuf->len - (int)(cp - lbuf->buf);
                    246:
                    247:        if (need > have) {
                    248:            have -= contlen;            /* subtract for continuation char */
                    249:            if ((ep = memrchr(cp, ' ', have)) == NULL)
                    250:                ep = memchr(cp + have, ' ', need - have);
                    251:            if (ep != NULL)
                    252:                need = (int)(ep - cp);
                    253:        }
                    254:        if (cp != lbuf->buf) {
                    255:            /* indent continued lines */
                    256:            for (i = 0; i < lbuf->indent; i++)
                    257:                putchar(' ');
                    258:        }
                    259:        fwrite(cp, need, 1, stdout);
                    260:        cp = ep;
                    261:
                    262:        /*
                    263:         * If there is more to print, reset have, incremement cp past
                    264:         * the whitespace, and print a line continuaton char if needed.
                    265:         */
                    266:        if (cp != NULL) {
                    267:            have = cols - lbuf->indent;
                    268:            do {
                    269:                cp++;
                    270:            } while (isspace((unsigned char)*cp));
                    271:            if (lbuf->continuation) {
                    272:                putchar(' ');
                    273:                putchar(lbuf->continuation);
                    274:            }
                    275:        }
                    276:        putchar('\n');
                    277:     }
                    278:
                    279: done:
                    280:     lbuf->len = 0;             /* reset the buffer for re-use. */
                    281: }