mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-15 22:30:43 +00:00
Merge pull request #1982 from qlyoung/fixup-vtysh-read
vtysh: fixup incorrect read logic
This commit is contained in:
commit
aa2fc55b20
@ -141,21 +141,22 @@ static int vtysh_client_run(struct vtysh_client *vclient, const char *line,
|
|||||||
|
|
||||||
bufvalid += nread;
|
bufvalid += nread;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We expect string output from daemons, so instead of looking
|
||||||
|
* for the full 3 null bytes of the terminator, we check for
|
||||||
|
* just one instead and assume it is the first byte of the
|
||||||
|
* terminator. The presence of the full terminator is checked
|
||||||
|
* later.
|
||||||
|
*/
|
||||||
if (bufvalid - buf >= 4)
|
if (bufvalid - buf >= 4)
|
||||||
end = memmem(bufvalid - 4, 4, terminator,
|
end = memmem(bufvalid - 4, 4, "\0", 1);
|
||||||
sizeof(terminator));
|
|
||||||
|
|
||||||
if (end && end + sizeof(terminator) + 1 > bufvalid)
|
|
||||||
/* found \0\0\0 but return code hasn't been read yet */
|
|
||||||
end = NULL;
|
|
||||||
if (end)
|
|
||||||
ret = end[sizeof(terminator)];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* calculate # bytes we have, up to & not including the
|
* calculate # bytes we have, up to & not including the
|
||||||
* terminator if present
|
* terminator if present
|
||||||
*/
|
*/
|
||||||
size_t textlen = (end ? end : bufvalid) - buf;
|
size_t textlen = (end ? end : bufvalid) - buf;
|
||||||
|
bool b = false;
|
||||||
|
|
||||||
/* feed line processing callback if present */
|
/* feed line processing callback if present */
|
||||||
while (callback && bufvalid > buf && (end > buf || !end)) {
|
while (callback && bufvalid > buf && (end > buf || !end)) {
|
||||||
@ -165,16 +166,38 @@ static int vtysh_client_run(struct vtysh_client *vclient, const char *line,
|
|||||||
/* line break */
|
/* line break */
|
||||||
*eol++ = '\0';
|
*eol++ = '\0';
|
||||||
else if (end == buf)
|
else if (end == buf)
|
||||||
/* no line break, end of input, no text left
|
/*
|
||||||
* before end
|
* no line break, end of input, no text left
|
||||||
* => don't insert an empty line at the end */
|
* before end; nothing to write
|
||||||
break;
|
*/
|
||||||
|
b = true;
|
||||||
else if (end)
|
else if (end)
|
||||||
/* no line break, end of input, but some text
|
/* no nl, end of input, but some text left */
|
||||||
* left */
|
|
||||||
eol = end;
|
eol = end;
|
||||||
else
|
else if (bufvalid == buf + bufsz) {
|
||||||
/* continue reading */
|
/*
|
||||||
|
* no nl, no end of input, no buffer space;
|
||||||
|
* realloc
|
||||||
|
*/
|
||||||
|
char *new;
|
||||||
|
|
||||||
|
bufsz *= 2;
|
||||||
|
if (buf == stackbuf) {
|
||||||
|
new = XMALLOC(MTYPE_TMP, bufsz);
|
||||||
|
memcpy(new, stackbuf, sizeof(stackbuf));
|
||||||
|
} else
|
||||||
|
new = XREALLOC(MTYPE_TMP, buf, bufsz);
|
||||||
|
|
||||||
|
bufvalid = bufvalid - buf + new;
|
||||||
|
buf = new;
|
||||||
|
/* if end != NULL, we won't be reading more
|
||||||
|
* data... */
|
||||||
|
assert(end == NULL);
|
||||||
|
b = true;
|
||||||
|
} else
|
||||||
|
b = true;
|
||||||
|
|
||||||
|
if (b)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* eol is at line end now, either \n => \0 or \0\0\0 */
|
/* eol is at line end now, either \n => \0 or \0\0\0 */
|
||||||
@ -187,10 +210,7 @@ static int vtysh_client_run(struct vtysh_client *vclient, const char *line,
|
|||||||
if (callback)
|
if (callback)
|
||||||
callback(cbarg, buf);
|
callback(cbarg, buf);
|
||||||
|
|
||||||
if (eol == end)
|
/* shift back data and adjust bufvalid */
|
||||||
/* \n\0\0\0 */
|
|
||||||
break;
|
|
||||||
|
|
||||||
memmove(buf, eol, bufvalid - eol);
|
memmove(buf, eol, bufvalid - eol);
|
||||||
bufvalid -= eol - buf;
|
bufvalid -= eol - buf;
|
||||||
if (end)
|
if (end)
|
||||||
@ -203,23 +223,28 @@ static int vtysh_client_run(struct vtysh_client *vclient, const char *line,
|
|||||||
fwrite(buf, 1, textlen, fp);
|
fwrite(buf, 1, textlen, fp);
|
||||||
memmove(buf, buf + textlen, bufvalid - buf - textlen);
|
memmove(buf, buf + textlen, bufvalid - buf - textlen);
|
||||||
bufvalid -= textlen;
|
bufvalid -= textlen;
|
||||||
|
if (end)
|
||||||
|
end -= textlen;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------
|
||||||
|
* At this point `buf` should be in one of two states:
|
||||||
|
* - Empty (i.e. buf == bufvalid)
|
||||||
|
* - Contains up to 4 bytes of the terminator
|
||||||
|
* ----------------------------------------------------
|
||||||
|
*/
|
||||||
|
assert(((buf == bufvalid)
|
||||||
|
|| (bufvalid - buf <= 4 && buf[0] == 0x00)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bufvalid == buf + bufsz) {
|
/* if we have the terminator, break */
|
||||||
char *new;
|
if (end && bufvalid - buf == 4) {
|
||||||
bufsz *= 2;
|
assert(!memcmp(buf, terminator, 3));
|
||||||
if (buf == stackbuf) {
|
ret = buf[3];
|
||||||
new = XMALLOC(MTYPE_TMP, bufsz);
|
break;
|
||||||
memcpy(new, stackbuf, sizeof(stackbuf));
|
|
||||||
} else
|
|
||||||
new = XREALLOC(MTYPE_TMP, buf, bufsz);
|
|
||||||
|
|
||||||
bufvalid = bufvalid - buf + new;
|
|
||||||
buf = new;
|
|
||||||
/* if end != NULL, we won't be reading more data... */
|
|
||||||
assert(end == NULL);
|
|
||||||
}
|
}
|
||||||
} while (!end);
|
|
||||||
|
} while (true);
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
out_err:
|
out_err:
|
||||||
|
Loading…
Reference in New Issue
Block a user