config(8): use sbuf to manage line buffers

PR:	245476
Reported by:	kevans
Reviewed by:	imp, kevans
MFC after:	1 week
Differential Revision:	https://reviews.freebsd.org/D24373
This commit is contained in:
Jason A. Harmening 2020-04-12 02:42:42 +00:00
parent e3e7c612f3
commit 31de6cad17
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=359815

View File

@ -113,6 +113,8 @@ struct hdr_list {
struct hdr_list *h_next; struct hdr_list *h_next;
} *htab; } *htab;
static struct sbuf *line_buf = NULL;
/* /*
* Config builds a set of files for building a UNIX * Config builds a set of files for building a UNIX
* system given a description of the desired system. * system given a description of the desired system.
@ -313,6 +315,29 @@ usage(void)
exit(EX_USAGE); exit(EX_USAGE);
} }
static void
init_line_buf(void)
{
if (line_buf == NULL) {
line_buf = sbuf_new(NULL, NULL, 80, SBUF_AUTOEXTEND);
if (line_buf == NULL) {
errx(EXIT_FAILURE, "failed to allocate line buffer");
}
} else {
sbuf_clear(line_buf);
}
}
static char *
get_line_buf(void)
{
if (sbuf_finish(line_buf) != 0) {
errx(EXIT_FAILURE, "failed to generate line buffer, "
"partial line = %s", sbuf_data(line_buf));
}
return sbuf_data(line_buf);
}
/* /*
* get_word * get_word
* returns EOF on end of file * returns EOF on end of file
@ -322,11 +347,10 @@ usage(void)
char * char *
get_word(FILE *fp) get_word(FILE *fp)
{ {
static char line[160];
int ch; int ch;
char *cp;
int escaped_nl = 0; int escaped_nl = 0;
init_line_buf();
begin: begin:
while ((ch = getc(fp)) != EOF) while ((ch = getc(fp)) != EOF)
if (ch != ' ' && ch != '\t') if (ch != ' ' && ch != '\t')
@ -345,29 +369,20 @@ get_word(FILE *fp)
else else
return (NULL); return (NULL);
} }
cp = line; sbuf_putc(line_buf, ch);
*cp++ = ch;
/* Negation operator is a word by itself. */ /* Negation operator is a word by itself. */
if (ch == '!') { if (ch == '!') {
*cp = 0; return get_line_buf();
return (line);
} }
while ((ch = getc(fp)) != EOF && cp < line + sizeof(line)) { while ((ch = getc(fp)) != EOF) {
if (isspace(ch)) if (isspace(ch))
break; break;
*cp++ = ch; sbuf_putc(line_buf, ch);
} }
if (cp >= line + sizeof(line)) {
line[sizeof(line) - 1] = '\0';
fprintf(stderr, "config: attempted overflow, partial line: `%s'",
line);
exit(2);
}
*cp = 0;
if (ch == EOF) if (ch == EOF)
return ((char *)EOF); return ((char *)EOF);
(void) ungetc(ch, fp); (void) ungetc(ch, fp);
return (line); return (get_line_buf());
} }
/* /*
@ -378,11 +393,10 @@ get_word(FILE *fp)
char * char *
get_quoted_word(FILE *fp) get_quoted_word(FILE *fp)
{ {
static char line[512];
int ch; int ch;
char *cp;
int escaped_nl = 0; int escaped_nl = 0;
init_line_buf();
begin: begin:
while ((ch = getc(fp)) != EOF) while ((ch = getc(fp)) != EOF)
if (ch != ' ' && ch != '\t') if (ch != ' ' && ch != '\t')
@ -401,7 +415,6 @@ get_quoted_word(FILE *fp)
else else
return (NULL); return (NULL);
} }
cp = line;
if (ch == '"' || ch == '\'') { if (ch == '"' || ch == '\'') {
int quote = ch; int quote = ch;
@ -410,9 +423,8 @@ get_quoted_word(FILE *fp)
if (ch == quote && !escaped_nl) if (ch == quote && !escaped_nl)
break; break;
if (ch == '\n' && !escaped_nl) { if (ch == '\n' && !escaped_nl) {
*cp = 0;
printf("config: missing quote reading `%s'\n", printf("config: missing quote reading `%s'\n",
line); get_line_buf());
exit(2); exit(2);
} }
if (ch == '\\' && !escaped_nl) { if (ch == '\\' && !escaped_nl) {
@ -420,38 +432,23 @@ get_quoted_word(FILE *fp)
continue; continue;
} }
if (ch != quote && escaped_nl) if (ch != quote && escaped_nl)
*cp++ = '\\'; sbuf_putc(line_buf, '\\');
if (cp >= line + sizeof(line)) { sbuf_putc(line_buf, ch);
line[sizeof(line) - 1] = '\0';
printf(
"config: line buffer overflow reading partial line `%s'\n",
line);
exit(2);
}
*cp++ = ch;
escaped_nl = 0; escaped_nl = 0;
} }
} else { } else {
*cp++ = ch; sbuf_putc(line_buf, ch);
while ((ch = getc(fp)) != EOF && cp < line + sizeof(line)) { while ((ch = getc(fp)) != EOF) {
if (isspace(ch)) if (isspace(ch))
break; break;
*cp++ = ch; sbuf_putc(line_buf, ch);
}
if (cp >= line + sizeof(line)) {
line[sizeof(line) - 1] = '\0';
printf(
"config: line buffer overflow reading partial line `%s'\n",
line);
exit(2);
} }
if (ch != EOF) if (ch != EOF)
(void) ungetc(ch, fp); (void) ungetc(ch, fp);
} }
*cp = 0;
if (ch == EOF) if (ch == EOF)
return ((char *)EOF); return ((char *)EOF);
return (line); return (get_line_buf());
} }
/* /*