~ubuntu-branches/ubuntu/quantal/sudo/quantal

« back to all changes in this revision

Viewing changes to common/lbuf.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2011-11-20 12:07:45 UTC
  • mfrom: (1.3.17 sid)
  • Revision ID: package-import@ubuntu.com-20111120120745-o3qpklobmygytndc
Tags: 1.8.3p1-1ubuntu1
* Merge from debian/testing, remaining changes:
  - debian/patches/keep_home_by_default.patch:
    + Set HOME in initial_keepenv_table. (rebased for 1.8.3p1)
  - debian/patches/enable_badpass.patch: turn on "mail_badpass" by default:
    + attempting sudo without knowing a login password is as bad as not
      being listed in the sudoers file, especially if getting the password
      wrong means doing the access-check-email-notification never happens
      (rebased for 1.8.3p1)
  - debian/rules:
    + compile with --without-lecture --with-tty-tickets (Ubuntu specific)
    + install man/man8/sudo_root.8 (Ubuntu specific)
    + install apport hooks
    + The ubuntu-sudo-as-admin-successful.patch was taken upstream by
      Debian however it requires a --enable-admin-flag configure flag to
      actually enable it.
  - debian/sudoers: 
    + grant admin group sudo access
  - debian/sudo-ldap.dirs, debian/sudo.dirs: 
    + add usr/share/apport/package-hooks
  - debian/sudo.preinst:
    + avoid conffile prompt by checking for known default /etc/sudoers
      and if found installing the correct default /etc/sudoers file

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2007-2011 Todd C. Miller <Todd.Miller@courtesan.com>
 
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 <stdio.h>
 
24
#ifdef STDC_HEADERS
 
25
# include <stdlib.h>
 
26
# include <stddef.h>
 
27
#else
 
28
# ifdef HAVE_STDLIB_H
 
29
#  include <stdlib.h>
 
30
# endif
 
31
#endif /* STDC_HEADERS */
 
32
#ifdef HAVE_STRING_H
 
33
# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
 
34
#  include <memory.h>
 
35
# endif
 
36
# include <string.h>
 
37
#endif /* HAVE_STRING_H */
 
38
#ifdef HAVE_STRINGS_H
 
39
# include <strings.h>
 
40
#endif /* HAVE_STRINGS_H */
 
41
#ifdef HAVE_UNISTD_H
 
42
# include <unistd.h>
 
43
#endif /* HAVE_UNISTD_H */
 
44
#include <ctype.h>
 
45
 
 
46
#include "missing.h"
 
47
#include "alloc.h"
 
48
#include "error.h"
 
49
#include "lbuf.h"
 
50
 
 
51
void
 
52
lbuf_init(struct lbuf *lbuf, int (*output)(const char *),
 
53
    int indent, const char *continuation, int cols)
 
54
{
 
55
    lbuf->output = output;
 
56
    lbuf->continuation = continuation;
 
57
    lbuf->indent = indent;
 
58
    lbuf->cols = cols;
 
59
    lbuf->len = 0;
 
60
    lbuf->size = 0;
 
61
    lbuf->buf = NULL;
 
62
}
 
63
 
 
64
void
 
65
lbuf_destroy(struct lbuf *lbuf)
 
66
{
 
67
    efree(lbuf->buf);
 
68
    lbuf->buf = NULL;
 
69
}
 
70
 
 
71
/*
 
72
 * Parse the format and append strings, only %s and %% escapes are supported.
 
73
 * Any characters in set are quoted with a backslash.
 
74
 */
 
75
void
 
76
lbuf_append_quoted(struct lbuf *lbuf, const char *set, const char *fmt, ...)
 
77
{
 
78
    va_list ap;
 
79
    int len;
 
80
    char *cp, *s = NULL;
 
81
 
 
82
    va_start(ap, fmt);
 
83
    while (*fmt != '\0') {
 
84
        len = 1;
 
85
        if (fmt[0] == '%' && fmt[1] == 's') {
 
86
            s = va_arg(ap, char *);
 
87
            len = strlen(s);
 
88
        }
 
89
        /* Assume worst case that all chars must be escaped. */
 
90
        if (lbuf->len + (len * 2) + 1 >= lbuf->size) {
 
91
            do {
 
92
                lbuf->size += 256;
 
93
            } while (lbuf->len + len + 1 >= lbuf->size);
 
94
            lbuf->buf = erealloc(lbuf->buf, lbuf->size);
 
95
        }
 
96
        if (*fmt == '%') {
 
97
            if (*(++fmt) == 's') {
 
98
                while ((cp = strpbrk(s, set)) != NULL) {
 
99
                    len = (int)(cp - s);
 
100
                    memcpy(lbuf->buf + lbuf->len, s, len);
 
101
                    lbuf->len += len;
 
102
                    lbuf->buf[lbuf->len++] = '\\';
 
103
                    lbuf->buf[lbuf->len++] = *cp;
 
104
                    s = cp + 1;
 
105
                }
 
106
                if (*s != '\0') {
 
107
                    len = strlen(s);
 
108
                    memcpy(lbuf->buf + lbuf->len, s, len);
 
109
                    lbuf->len += len;
 
110
                }
 
111
                fmt++;
 
112
                continue;
 
113
            }
 
114
        }
 
115
        if (strchr(set, *fmt) != NULL)
 
116
            lbuf->buf[lbuf->len++] = '\\';
 
117
        lbuf->buf[lbuf->len++] = *fmt++;
 
118
    }
 
119
    lbuf->buf[lbuf->len] = '\0';
 
120
    va_end(ap);
 
121
}
 
122
 
 
123
/*
 
124
 * Parse the format and append strings, only %s and %% escapes are supported.
 
125
 */
 
126
void
 
127
lbuf_append(struct lbuf *lbuf, const char *fmt, ...)
 
128
{
 
129
    va_list ap;
 
130
    int len;
 
131
    char *s = NULL;
 
132
 
 
133
    va_start(ap, fmt);
 
134
    while (*fmt != '\0') {
 
135
        len = 1;
 
136
        if (fmt[0] == '%' && fmt[1] == 's') {
 
137
            s = va_arg(ap, char *);
 
138
            len = strlen(s);
 
139
        }
 
140
        if (lbuf->len + len + 1 >= lbuf->size) {
 
141
            do {
 
142
                lbuf->size += 256;
 
143
            } while (lbuf->len + len + 1 >= lbuf->size);
 
144
            lbuf->buf = erealloc(lbuf->buf, lbuf->size);
 
145
        }
 
146
        if (*fmt == '%') {
 
147
            if (*(++fmt) == 's') {
 
148
                memcpy(lbuf->buf + lbuf->len, s, len);
 
149
                lbuf->len += len;
 
150
                fmt++;
 
151
                continue;
 
152
            }
 
153
        }
 
154
        lbuf->buf[lbuf->len++] = *fmt++;
 
155
    }
 
156
    lbuf->buf[lbuf->len] = '\0';
 
157
    va_end(ap);
 
158
}
 
159
 
 
160
static void
 
161
lbuf_println(struct lbuf *lbuf, char *line, int len)
 
162
{
 
163
    char *cp, save;
 
164
    int i, have, contlen;
 
165
 
 
166
    contlen = lbuf->continuation ? strlen(lbuf->continuation) : 0;
 
167
 
 
168
    /*
 
169
     * Print the buffer, splitting the line as needed on a word
 
170
     * boundary.
 
171
     */
 
172
    cp = line;
 
173
    have = lbuf->cols;
 
174
    while (cp != NULL && *cp != '\0') {
 
175
        char *ep = NULL;
 
176
        int need = len - (int)(cp - line);
 
177
 
 
178
        if (need > have) {
 
179
            have -= contlen;            /* subtract for continuation char */
 
180
            if ((ep = memrchr(cp, ' ', have)) == NULL)
 
181
                ep = memchr(cp + have, ' ', need - have);
 
182
            if (ep != NULL)
 
183
                need = (int)(ep - cp);
 
184
        }
 
185
        if (cp != line) {
 
186
            /* indent continued lines */
 
187
            /* XXX - build up string instead? */
 
188
            for (i = 0; i < lbuf->indent; i++)
 
189
                lbuf->output(" ");
 
190
        }
 
191
        /* NUL-terminate cp for the output function and restore afterwards */
 
192
        save = cp[need];
 
193
        cp[need] = '\0';
 
194
        lbuf->output(cp);
 
195
        cp[need] = save;
 
196
        cp = ep;
 
197
 
 
198
        /*
 
199
         * If there is more to print, reset have, incremement cp past
 
200
         * the whitespace, and print a line continuaton char if needed.
 
201
         */
 
202
        if (cp != NULL) {
 
203
            have = lbuf->cols - lbuf->indent;
 
204
            ep = line + len;
 
205
            while (cp < ep && isblank((unsigned char)*cp)) {
 
206
                cp++;
 
207
            }
 
208
            if (contlen)
 
209
                lbuf->output(lbuf->continuation);
 
210
        }
 
211
        lbuf->output("\n");
 
212
    }
 
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(struct lbuf *lbuf)
 
221
{
 
222
    char *cp, *ep;
 
223
    int len;
 
224
 
 
225
    if (lbuf->buf == NULL || lbuf->len == 0)
 
226
        goto done;
 
227
 
 
228
    /* For very small widths just give up... */
 
229
    len = lbuf->continuation ? strlen(lbuf->continuation) : 0;
 
230
    if (lbuf->cols <= lbuf->indent + len + 20) {
 
231
        lbuf->buf[lbuf->len] = '\0';
 
232
        lbuf->output(lbuf->buf);
 
233
        goto done;
 
234
    }
 
235
 
 
236
    /* Print each line in the buffer */
 
237
    for (cp = lbuf->buf; cp != NULL && *cp != '\0'; ) {
 
238
        if (*cp == '\n') {
 
239
            lbuf->output("\n");
 
240
            cp++;
 
241
        } else {
 
242
            len = lbuf->len - (cp - lbuf->buf);
 
243
            if ((ep = memchr(cp, '\n', len)) != NULL)
 
244
                len = (int)(ep - cp);
 
245
            if (len)
 
246
                lbuf_println(lbuf, cp, len);
 
247
            cp = ep ? ep + 1 : NULL;
 
248
        }
 
249
    }
 
250
 
 
251
done:
 
252
    lbuf->len = 0;              /* reset the buffer for re-use. */
 
253
}