*sigh* this code is interesting: assume you want to output via shf to
a string buffer whose window size is currently 32 (initial), your data is 96 bytes, this routine used to resize the buffer to 64, append your first 64 bytes to it (no matter if there's already something in it) and then writes the remaining bytes to stdio fd instead of the string… if it doesn’t SIGABRT before discovered by wbx@ – thanks – bug inherited from pdksh 5.2.14 (AD 1999)
This commit is contained in:
parent
f10186fedd
commit
c6eedad976
4
check.t
4
check.t
@ -1,4 +1,4 @@
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.382 2010/07/17 22:09:30 tg Exp $
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.383 2010/07/19 22:41:01 tg Exp $
|
||||
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
|
||||
# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
|
||||
# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
|
||||
@ -25,7 +25,7 @@
|
||||
# http://www.research.att.com/~gsf/public/ifs.sh
|
||||
|
||||
expected-stdout:
|
||||
@(#)MIRBSD KSH R39 2010/07/17
|
||||
@(#)MIRBSD KSH R39 2010/07/19
|
||||
description:
|
||||
Check version of shell.
|
||||
stdin:
|
||||
|
4
sh.h
4
sh.h
@ -150,9 +150,9 @@
|
||||
#endif
|
||||
|
||||
#ifdef EXTERN
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.398 2010/07/17 22:09:38 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.399 2010/07/19 22:41:03 tg Exp $");
|
||||
#endif
|
||||
#define MKSH_VERSION "R39 2010/07/17"
|
||||
#define MKSH_VERSION "R39 2010/07/19"
|
||||
|
||||
#ifndef MKSH_INCLUDES_ONLY
|
||||
|
||||
|
57
shf.c
57
shf.c
@ -22,7 +22,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.35 2009/11/28 14:28:03 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.36 2010/07/19 22:41:04 tg Exp $");
|
||||
|
||||
/* flags to shf_emptybuf() */
|
||||
#define EB_READSW 0x01 /* about to switch to reading */
|
||||
@ -636,32 +636,45 @@ shf_write(const char *buf, int nbytes, struct shf *shf)
|
||||
shf->wnleft -= ncopy;
|
||||
}
|
||||
if (nbytes > 0) {
|
||||
/* Flush deals with strings and sticky errors */
|
||||
if (shf_emptybuf(shf, EB_GROW) == EOF)
|
||||
return (EOF);
|
||||
if (nbytes > shf->wbsize) {
|
||||
ncopy = nbytes;
|
||||
if (shf->wbsize)
|
||||
ncopy -= nbytes % shf->wbsize;
|
||||
nbytes -= ncopy;
|
||||
while (ncopy > 0) {
|
||||
n = write(shf->fd, buf, ncopy);
|
||||
if (n < 0) {
|
||||
if (errno == EINTR &&
|
||||
!(shf->flags & SHF_INTERRUPT))
|
||||
continue;
|
||||
shf->flags |= SHF_ERROR;
|
||||
shf->errno_ = errno;
|
||||
shf->wnleft = 0;
|
||||
/* Note: fwrite(3S) returns 0 for
|
||||
* errors - this doesn't */
|
||||
if (shf->flags & SHF_STRING) {
|
||||
/* resize buffer until there's enough space left */
|
||||
while (nbytes > shf->wnleft)
|
||||
if (shf_emptybuf(shf, EB_GROW) == EOF)
|
||||
return (EOF);
|
||||
/* then write everything into the buffer */
|
||||
} else {
|
||||
/* flush deals with sticky errors */
|
||||
if (shf_emptybuf(shf, EB_GROW) == EOF)
|
||||
return (EOF);
|
||||
/* write chunks larger than window size directly */
|
||||
if (nbytes > shf->wbsize) {
|
||||
ncopy = nbytes;
|
||||
if (shf->wbsize)
|
||||
ncopy -= nbytes % shf->wbsize;
|
||||
nbytes -= ncopy;
|
||||
while (ncopy > 0) {
|
||||
n = write(shf->fd, buf, ncopy);
|
||||
if (n < 0) {
|
||||
if (errno == EINTR &&
|
||||
!(shf->flags & SHF_INTERRUPT))
|
||||
continue;
|
||||
shf->flags |= SHF_ERROR;
|
||||
shf->errno_ = errno;
|
||||
shf->wnleft = 0;
|
||||
/*
|
||||
* Note: fwrite(3) returns 0
|
||||
* for errors - this doesn't
|
||||
*/
|
||||
return (EOF);
|
||||
}
|
||||
buf += n;
|
||||
ncopy -= n;
|
||||
}
|
||||
buf += n;
|
||||
ncopy -= n;
|
||||
}
|
||||
/* ... and buffer the rest */
|
||||
}
|
||||
if (nbytes > 0) {
|
||||
/* write remaining bytes to buffer */
|
||||
memcpy(shf->wp, buf, nbytes);
|
||||
shf->wp += nbytes;
|
||||
shf->wnleft -= nbytes;
|
||||
|
Loading…
x
Reference in New Issue
Block a user