コード例 #1
0
ファイル: zlib_util.c プロジェクト: graaff/gtk-gnutella
/**
 * Attempt to grow the output buffer.
 *
 * @param zs		the zlib stream object
 * @param maxout	maximum length of dynamically-allocated buffer (0 = none)
 *
 * @return TRUE if we can resume processing after the output buffer was
 * expanded, FALSE if the buffer cannot be expanded (not dynamically allocated
 * or reached the maximum size).
 */
static bool
zlib_stream_grow_output(zlib_stream_t *zs, size_t maxout)
{
    if (zs->allocated) {
        z_streamp z = zs->z;

        /*
         * Limit growth if asked to do so.
         *
         * This is used when inflating, usually, to avoid being given a small
         * amount of data that will expand into megabytes...
         */

        if (maxout != 0 && zs->outlen >= maxout) {
            g_warning("%s(): reached maximum buffer size (%zu bytes): "
                      "input=%zu, output=%zu",
                      G_STRFUNC, maxout, zs->inlen, zs->outlen);
            return FALSE;	/* Cannot continue */
        }

        zs->outlen += OUT_GROW;
        zs->out = hrealloc(zs->out, zs->outlen);
        z->next_out = ptr_add_offset(zs->out, zs->outlen - OUT_GROW);
        z->avail_out = OUT_GROW;
        return TRUE;	/* Can process remaining input */
    }

    g_warning("%s(): under-estimated output buffer size: "
              "input=%zu, output=%zu", G_STRFUNC, zs->inlen, zs->outlen);

    return FALSE;		/* Cannot continue */
}
コード例 #2
0
ファイル: bh_download.c プロジェクト: Haxe/gtk-gnutella
/**
 * Read data from the message buffer we just received.
 *
 * @return TRUE whilst we think there is more data to read in the buffer.
 */
static gboolean
browse_data_read(struct browse_ctx *bc, pmsg_t *mb)
{
	/*
	 * Read header if it has not been fully fetched yet.
	 */

	if (!bc->has_header) {
		char *w = cast_to_gpointer(&bc->header);

		g_assert(sizeof bc->header >= bc->pos);
		bc->pos += pmsg_read(mb, &w[bc->pos], sizeof bc->header - bc->pos);
		if (bc->pos < sizeof bc->header)
			return FALSE;

		bc->has_header = TRUE;		/* We have read the full header */

		bc->size = gnutella_header_get_size(&bc->header);

		/*
		 * Protect against too large data.
		 */

		if (bc->size > BH_DL_MAX_SIZE) {
			download_stop(bc->owner, GTA_DL_ERROR, "Gnutella payload too big");
			return FALSE;
		}

		/*
		 * Resize payload buffer if needed
		 */

		if (bc->size > bc->data_size) {
			bc->data_size = MAX(BH_DL_DEFAULT_SIZE, bc->size);
			bc->data = hrealloc(bc->data, bc->data_size);
		}

		bc->pos = 0;

		/* FALL THROUGH */
	}

	/*
	 * Read message data, if any.
	 */

	if (bc->size) {
		g_assert(bc->size >= bc->pos);
		bc->pos += pmsg_read(mb, &bc->data[bc->pos], bc->size - bc->pos);
	}

	if (bc->pos >= bc->size) {
		bc->has_header = FALSE;		/* For next message */
		bc->pos = 0;
		return TRUE; /* Must process message and continue */
	} else {
		return FALSE;
	}
}
コード例 #3
0
ファイル: matching.c プロジェクト: Haxe/gtk-gnutella
/**
 * Makes a bin take as little memory as needed.
 */
static void
bin_compact(struct st_bin *bin)
{
	g_assert(bin->vals != NULL);	/* Or it would not have been allocated */

	bin->vals = hrealloc(bin->vals, bin->nvals * sizeof bin->vals[0]);
	bin->nslots = bin->nvals;
}
コード例 #4
0
ファイル: matching.c プロジェクト: Haxe/gtk-gnutella
/**
 * Inserts an item into a bin.
 */
static void
bin_insert_item(struct st_bin *bin, struct st_entry *entry)
{
	if (bin->nvals == bin->nslots) {
		bin->nslots *= 2;
		bin->vals = hrealloc(bin->vals, bin->nslots * sizeof bin->vals[0]);
	}
	bin->vals[bin->nvals++] = entry;
}
コード例 #5
0
ファイル: status.c プロジェクト: HamWAN/aprsc
int status_read_liveupgrade(void)
{
	char path[PATHLEN+1];
	char path_renamed[PATHLEN+1];
	FILE *fp;
	char *s = NULL;
	int sl = 0;
	char buf[32768];
	int i;
	
	snprintf(path, PATHLEN, "%s/liveupgrade.json", rundir);
	snprintf(path_renamed, PATHLEN, "%s/liveupgrade.json.old", rundir);
	
	fp = fopen(path, "r");
	if (!fp) {
		hlog(LOG_ERR, "liveupgrade dump file read failed: Could not open %s for reading: %s", path, strerror(errno));
		return -1;
	}
	
	hlog(LOG_INFO, "Live upgrade: Loading client status from %s ...", path);
	
	if (rename(path, path_renamed) < 0) {
		hlog(LOG_ERR, "Failed to rename liveupgrade dump file %s to %s: %s",
			path, path_renamed, strerror(errno));
		unlink(path);
	}
	
	while ((i = fread(buf, 1, sizeof(buf), fp)) > 0) {
		//hlog(LOG_DEBUG, "read %d bytes", i);
		s = hrealloc(s, sl + i+1);
		memcpy(s + sl, buf, i);
		sl += i;
		s[sl] = 0; // keep null-terminated
		//hlog(LOG_DEBUG, "now: %s", s);
	}
	
	if (fclose(fp)) {
		hlog(LOG_ERR, "liveupgrade dump file read failed: close(%s): %s", path, strerror(errno));
		hfree(s);
		return -1;
	}
	
	/* decode JSON */
	cJSON *dec = cJSON_Parse(s);
	if (!dec) {
		hlog(LOG_ERR, "liveupgrade dump parsing failed");
		hfree(s);
		return -1;
	}
	
	liveupgrade_status = dec;
	hfree(s);
	
	return 0;
}
コード例 #6
0
ファイル: lex.c プロジェクト: cdaffara/symbiandump-mw1
void
add(int c)
{
    *bptr++ = c;
    if (bsiz == ++len) {
#if 0
	int newbsiz;

	newbsiz = bsiz * 8;
	while (newbsiz < inbufct)
	    newbsiz *= 2;
	bptr = len + (tokstr = (char *)hrealloc(tokstr, bsiz, newbsiz));
	bsiz = newbsiz;
#endif

	int newbsiz = bsiz * 2;

	if (newbsiz > inbufct && inbufct > bsiz)
	    newbsiz = inbufct;

	bptr = len + (tokstr = (char *)hrealloc(tokstr, bsiz, newbsiz));
	bsiz = newbsiz;
    }
}
コード例 #7
0
ファイル: soap.c プロジェクト: Haxe/gtk-gnutella
/**
 * HTTP async callback, invoked when new HTTP data is read.
 * The EOF condition is indicated by data being NULL.
 */
static void
soap_data_ind(http_async_t *ha, char *data, int len)
{
	soap_rpc_t *sr = http_async_get_opaque(ha);
	size_t new_length;

	soap_rpc_check(sr);

	/*
	 * When data is NULL, we reached EOF and we're done.  Time to process
	 * the data we got back.
	 *
	 * The HTTP asynchronous handle is nullified since it is about to be
	 * closed by the HTTP layer upon return.
	 */

	if (NULL == data) {
		sr->ha = NULL;
		soap_process_reply(sr);
		return;
	}

	/*
	 * Ensure we don't get too much and resize the memory buffer where
	 * we store the reply if needed.
	 */

	new_length = size_saturate_add(sr->reply_len, len);

	if (new_length > sr->content_len) {
		http_async_error(ha, HTTP_ASYNC_DATA2BIG);
		return;
	}

	if (new_length > sr->reply_size) {
		size_t new_size = size_saturate_mult(sr->reply_size, 2);

		sr->reply_data = hrealloc(sr->reply_data, new_size);
		sr->reply_size = new_size;
	}

	/*
	 * Append new data.
	 */

	memcpy(&sr->reply_data[sr->reply_len], data, len);
	sr->reply_len = new_length;
}
コード例 #8
0
ファイル: lex.c プロジェクト: AMDmi3/zsh
void
zshlex_raw_add(int c)
{
    if (!lex_add_raw)
	return;

    *lexbuf_raw.ptr++ = c;
    if (lexbuf_raw.siz == ++lexbuf_raw.len) {
	int newbsiz = lexbuf_raw.siz * 2;

	tokstr_raw = (char *)hrealloc(tokstr_raw, lexbuf_raw.siz, newbsiz);
	lexbuf_raw.ptr = tokstr_raw + lexbuf_raw.len;
	memset(lexbuf_raw.ptr, 0, newbsiz - lexbuf_raw.siz);
	lexbuf_raw.siz = newbsiz;
    }
}
コード例 #9
0
ファイル: lex.c プロジェクト: cedarli/zsh
void
add(int c)
{
    *bptr++ = c;
    if (bsiz == ++len) {
	int newbsiz = bsiz * 2;

	if (newbsiz > inbufct && inbufct > bsiz)
	    newbsiz = inbufct;

	bptr = len + (tokstr = (char *)hrealloc(tokstr, bsiz, newbsiz));
	/* len == bsiz, so bptr is at the start of newly allocated memory */
	memset(bptr, 0, newbsiz - bsiz);
	bsiz = newbsiz;
    }
}
コード例 #10
0
ファイル: lex.c プロジェクト: AMDmi3/zsh
void
add(int c)
{
    *lexbuf.ptr++ = c;
    if (lexbuf.siz == ++lexbuf.len) {
	int newbsiz = lexbuf.siz * 2;

	if (newbsiz > inbufct && inbufct > lexbuf.siz)
	    newbsiz = inbufct;

	tokstr = (char *)hrealloc(tokstr, lexbuf.siz, newbsiz);
	lexbuf.ptr = tokstr + lexbuf.len;
	/* len == bsiz, so bptr is at the start of newly allocated memory */
	memset(lexbuf.ptr, 0, newbsiz - lexbuf.siz);
	lexbuf.siz = newbsiz;
    }
}
コード例 #11
0
ファイル: hlog.c プロジェクト: hessu/aprsc
char *str_append(char *s, const char *fmt, ...)
{
    va_list args;
    char buf[LOG_LEN];
    int len;
    char *ret;

    va_start(args, fmt);
    vsnprintf(buf, LOG_LEN, fmt, args);
    va_end(args);
    buf[LOG_LEN-1] = 0;

    len = strlen(s);
    ret = hrealloc(s, len + strlen(buf) + 1);
    strcpy(ret + len, buf);

    return ret;
}
コード例 #12
0
ファイル: thex_download.c プロジェクト: MrJoe/gtk-gnutella
/**
 * Read data from the message buffer we just received.
 *
 * @return TRUE if there was an error.
 */
static bool
thex_download_data_read(struct thex_download *ctx, pmsg_t *mb)
{
	size_t size;
	
	g_assert(ctx);
	g_assert((NULL != ctx->data) ^ (0 == ctx->data_size));
	g_assert(ctx->pos <= ctx->data_size);

	while ((size = pmsg_size(mb)) > 0) {
		if (ctx->pos + size > ctx->max_size)
			return TRUE;

		if (size > ctx->data_size - ctx->pos) {
			ctx->data_size += MAX(size, ctx->data_size);
			ctx->data = hrealloc(ctx->data, ctx->data_size);
		}
		ctx->pos += pmsg_read(mb, &ctx->data[ctx->pos], size);
	}
	return FALSE;
}
コード例 #13
0
ファイル: zle_hist.c プロジェクト: prabirshrestha/winzsh
void
doisearch(int dir)
{
    char *s, *ibuf = halloc(80), *sbuf = ibuf + FIRST_SEARCH_CHAR;
    int sbptr = 0, top_spot = 0, pos, sibuf = 80;
    int nomatch = 0, skip_line = 0, skip_pos = 0;
    int odir = dir, sens = zmult == 1 ? 3 : 1;
    int hl = histline;
    int cmd;
    int *obindtab = bindtab;
    static char *previous_search = NULL;
    static int previous_search_len = 0;

    clearlist = 1;

    strcpy(ibuf, ISEARCH_PROMPT);
    memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3);
    remember_edits();
    s = zle_get_event(hl);
    bindtab = mainbindtab;
    pos = metalen(s, cs);
    for (;;) {
	/* Remember the current values in case search fails (doesn't push). */
	set_isrch_spot(top_spot, hl, pos, cs, sbptr, dir, nomatch);
	if (sbptr == 1 && sbuf[0] == '^') {
	    cs = 0;
    	    nomatch = 0;
	    statusline = ibuf + NORM_PROMPT_POS;
	} else if (sbptr > 0) {
	    char *last_line = s;

	    for (;;) {
		char *t;

		if (skip_pos) {
		    if (dir < 0) {
			if (pos == 0)
			    skip_line = 1;
			else
			    pos -= 1 + (pos != 1 && s[pos-2] == Meta);
		    } else if (sbuf[0] != '^') {
			if (pos >= strlen(s+1))
			    skip_line = 1;
			else
			    pos += 1 + (s[pos] == Meta);
		    } else
			skip_line = 1;
		    skip_pos = 0;
		}
		if (!skip_line && ((sbuf[0] == '^') ?
		    (t = metadiffer(s, sbuf + 1, sbptr - 1) < sens ? s : NULL) :
		    (t = hstrnstr(s, pos, sbuf, sbptr, dir, sens)))) {
		    zle_goto_hist(hl);
		    pos = t - s;
		    cs = ztrsub(t, s) + (dir == 1? sbptr - (sbuf[0]=='^') : 0);
	    	    nomatch = 0;
		    statusline = ibuf + NORM_PROMPT_POS;
		    break;
		}
		hl += dir;
		if (!(s = zle_get_event(hl))) {
		    if (sbptr == (int)isrch_spots[top_spot-1].len
		     && (isrch_spots[top_spot-1].flags & ISS_FAILING))
			top_spot--;
		    get_isrch_spot(top_spot, &hl, &pos, &cs, &sbptr,
				   &dir, &nomatch);
		    if (!nomatch) {
			feep();
			nomatch = 1;
		    }
		    s = last_line;
		    skip_line = 0;
		    statusline = ibuf;
		    break;
		}
		pos = dir == 1? 0 : strlen(s);
		skip_line = !strcmp(last_line, s);
	    }
	} else {
	    top_spot = 0;
    	    nomatch = 0;
	    statusline = ibuf + NORM_PROMPT_POS;
	}
	sbuf[sbptr] = '_';
	statusll = sbuf - statusline + sbptr + 1;
    ref:
	refresh();
	if ((cmd = getkeycmd()) < 0 || cmd == z_sendbreak) {
	    int i;
	    get_isrch_spot(0, &hl, &pos, &i, &sbptr, &dir, &nomatch);
	    s = zle_get_event(hl);
	    zle_goto_hist(hl);
	    cs = i;
	    break;
	}
	switch (cmd) {
	case z_clearscreen:
	    clearscreen();
	    goto ref;
	case z_redisplay:
	    redisplay();
	    goto ref;
	case z_vicmdmode:
	    bindtab = (bindtab == mainbindtab) ? altbindtab : mainbindtab;
	    goto ref;
	case z_vibackwarddeletechar:
	case z_backwarddeletechar:
	    if (top_spot)
		get_isrch_spot(--top_spot, &hl, &pos, &cs, &sbptr,
			       &dir, &nomatch);
	    else
		feep();
	    if (nomatch) {
		statusline = ibuf;
		skip_pos = 1;
	    }
	    s = zle_get_event(hl);
	    if (nomatch || !sbptr || (sbptr == 1 && sbuf[0] == '^')) {
		int i = cs;
		zle_goto_hist(hl);
		cs = i;
	    }
	    memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3);
	    continue;
	case z_acceptandhold:
	    acceptandhold();
	    goto brk;
	case z_acceptandinfernexthistory:
	    acceptandinfernexthistory();
	    goto brk;
	case z_acceptlineanddownhistory:
	    acceptlineanddownhistory();
	    goto brk;
	case z_acceptline:
	    acceptline();
	    goto brk;
	case z_historyincrementalsearchbackward:
	    set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch);
	    if (dir != -1)
		dir = -1;
	    else
		skip_pos = 1;
	    goto rpt;
	case z_historyincrementalsearchforward:
	    set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch);
	    if (dir != 1)
		dir = 1;
	    else
		skip_pos = 1;
	    goto rpt;
	case z_virevrepeatsearch:
	    set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch);
	    dir = -odir;
	    skip_pos = 1;
	    goto rpt;
	case z_virepeatsearch:
	    set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch);
	    dir = odir;
	    skip_pos = 1;
	rpt:
	    if (!sbptr && previous_search_len) {
		if (previous_search_len > sibuf - FIRST_SEARCH_CHAR - 2) {
		    ibuf = hrealloc(ibuf, sibuf, sibuf + previous_search_len);
		    sbuf = ibuf + FIRST_SEARCH_CHAR;
		    sibuf += previous_search_len;
		}
		memcpy(sbuf, previous_search, sbptr = previous_search_len);
	    }
	    memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3);
	    continue;
	case z_sendstring:
	    sendstring();
	    goto ref;
	case z_viquotedinsert:
	    sbuf[sbptr] = '^';
	    refresh();
	case z_quotedinsert:
	    if ((c = getkey(0)) == EOF) {
		feep();
		continue;
	    }
	    goto ins;
	default:
	    if(cmd == z_selfinsertunmeta) {
		c &= 0x7f;
		if(c == '\r')
		    c = '\n';
	    } else if (cmd == z_magicspace)
		c = ' ';
	    else if (cmd != z_selfinsert) {
		ungetkeycmd();
		if (cmd == z_sendbreak)
		    sbptr = 0;
		goto brk;
	    }
	ins:
	    if (sbptr == PATH_MAX) {
		feep();
		break;
	    }
	    set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch);
	    if (sbptr == sibuf - FIRST_SEARCH_CHAR - 2) {
		ibuf = hrealloc(ibuf, sibuf, sibuf * 2);
		sbuf = ibuf + FIRST_SEARCH_CHAR;
		sibuf *= 2;
	    }
	    sbuf[sbptr++] = c;
	}
    }
  brk:
    if (sbptr) {
	zfree(previous_search, previous_search_len);
	previous_search = zalloc(sbptr);
	memcpy(previous_search, sbuf, previous_search_len = sbptr);
    }
    statusline = NULL;
    bindtab = obindtab;
}
コード例 #14
0
/**
 * Resize the scratch buffer to be able to hold ``len'' bytes.
 */
static void
big_scratch_grow(DBMBIG *dbg, size_t len)
{
	dbg->scratch = hrealloc(dbg->scratch, len);
	dbg->scratch_len = len;
}
コード例 #15
0
ファイル: files.c プロジェクト: AMDmi3/zsh
static int
recursivecmd_dorec(struct recursivecmd const *reccmd,
    char *arg, char *rp, struct stat const *sp, struct dirsav *ds, int first)
{
    char *fn;
    DIR *d;
    int err, err1;
    struct dirsav dsav;
    char *files = NULL;
    int fileslen = 0;

    err1 = reccmd->dirpre_func(arg, rp, sp, reccmd->magic);
    if(err1 & 2)
	return 2;

    err = -lchdir(rp, ds, !first);
    if (err) {
	if(!reccmd->opt_noerr)
	    zwarnnam(reccmd->nam, "%s: %e", arg, errno);
	return err;
    }
    err = err1;

    init_dirsav(&dsav);
    d = opendir(".");
    if(!d) {
	if(!reccmd->opt_noerr)
	    zwarnnam(reccmd->nam, "%s: %e", arg, errno);
	err = 1;
    } else {
	int arglen = strlen(arg) + 1;

	while (!errflag && (fn = zreaddir(d, 1))) {
	    int l = strlen(fn) + 1;
	    files = hrealloc(files, fileslen, fileslen + l);
	    strcpy(files + fileslen, fn);
	    fileslen += l;
	}
	closedir(d);
	for (fn = files; !errflag && !(err & 2) && fn < files + fileslen;) {
	    int l = strlen(fn) + 1;
	    VARARR(char, narg, arglen + l);

	    strcpy(narg,arg);
	    narg[arglen-1] = '/';
	    strcpy(narg + arglen, fn);
	    unmetafy(fn, NULL);
	    err |= recursivecmd_doone(reccmd, narg, fn, &dsav, 0);
	    fn += l;
	}
	hrealloc(files, fileslen, 0);
    }
    zsfree(dsav.dirname);
    if (err & 2)
	return 2;
    if (restoredir(ds)) {
	if(!reccmd->opt_noerr)
	    zwarnnam(reccmd->nam, "failed to return to previous directory: %e",
		     errno);
	return 2;
    }
    return err | reccmd->dirpost_func(arg, rp, sp, reccmd->magic);
}
コード例 #16
0
ファイル: zpty.c プロジェクト: zsh-users/zsh
static int
ptyread(char *nam, Ptycmd cmd, char **args, int noblock, int mustmatch)
{
    int blen, used, seen = 0, ret = 0, matchok = 0;
    char *buf;
    Patprog prog = NULL;

    if (*args && args[1]) {
	char *p;

	if (args[2]) {
	    zwarnnam(nam, "too many arguments");
	    return 1;
	}
	p = dupstring(args[1]);
	tokenize(p);
	remnulargs(p);
	/* Signals handlers might stomp PAT_STATIC */
	if (!(prog = patcompile(p, PAT_ZDUP, NULL))) {
	    zwarnnam(nam, "bad pattern: %s", args[1]);
	    return 1;
	}
    } else
	fflush(stdout);

    if (cmd->old) {
	used = cmd->olen;
	buf = (char *) zhalloc((blen = 256 + used) + 1);
	memcpy(buf, cmd->old, cmd->olen);
	zfree(cmd->old, cmd->olen);
	cmd->old = NULL;
	cmd->olen = 0;
    } else {
	used = 0;
	buf = (char *) zhalloc((blen = 256) + 1);
    }
    if (cmd->read != -1) {
	buf[used] = (char) cmd->read;
	buf[used + 1] = '\0';
	seen = used = 1;
	cmd->read = -1;
    }
    do {
	if (noblock && cmd->read == -1) {
	    int pollret;
	    /*
	     * Check there is data available.  Borrowed from
	     * poll_read() in utils.c and simplified.
	     */
#ifdef HAVE_SELECT
	    fd_set foofd;
	    struct timeval expire_tv;
	    expire_tv.tv_sec = 0;
	    expire_tv.tv_usec = 0;
	    FD_ZERO(&foofd);
	    FD_SET(cmd->fd, &foofd);
	    pollret = select(cmd->fd+1,
			 (SELECT_ARG_2_T) &foofd, NULL, NULL, &expire_tv);
#else
#ifdef FIONREAD
	    if (ioctl(cmd->fd, FIONREAD, (char *) &val) == 0)
		pollret = (val > 0);
#endif
#endif

	    if (pollret < 0) {
		/*
		 * See read_poll() for this.
		 * Last despairing effort to poll: attempt to
		 * set nonblocking I/O and actually read the
		 * character.  cmd->read stores the character read.
		 */
		long mode;

		if (setblock_fd(0, cmd->fd, &mode))
		    pollret = read(cmd->fd, &cmd->read, 1);
		if (mode != -1)
		    fcntl(cmd->fd, F_SETFL, mode);
	    }
	    if (pollret == 0)
		break;
	}
	if (!ret) {
	    checkptycmd(cmd);
	    if (cmd->fin)
		break;
	}
	if (cmd->read != -1 || (ret = read(cmd->fd, buf + used, 1)) == 1) {
	    int readchar;
	    if (cmd->read != -1) {
		ret = 1;
		readchar = cmd->read;
		cmd->read = -1;
	    } else
		readchar = STOUC(buf[used]);
	    if (imeta(readchar)) {
		buf[used++] = Meta;
		buf[used++] = (char) (readchar ^ 32);
	    } else
		buf[used++] = (char) readchar;
	    seen = 1;
	    if (used >= blen-1) {
		if (!*args) {
		    buf[used] = '\0';
		    unmetafy(buf, &used);
		    write_loop(1, buf, used);
		    used = 0;
		} else {
		    buf = hrealloc(buf, blen, blen << 1);
		    blen <<= 1;
		}
	    }
	}
	buf[used] = '\0';

	if (!prog) {
	    if (ret <= 0 || (*args && buf[used - 1] == '\n' &&
			     (used < 2 || buf[used-2] != Meta)))
		break;
	} else {
	    if (ret < 0
#ifdef EWOULDBLOCK
		&& errno != EWOULDBLOCK
#else
#ifdef EAGAIN
		&& errno != EAGAIN
#endif
#endif
		)
		break;
	}
    } while (!(errflag || breaks || retflag || contflag) &&
	     used < READ_MAX &&
	     !(prog && ret && (matchok = pattry(prog, buf))));

    if (prog && ret < 0 &&
#ifdef EWOULDBLOCK
	errno == EWOULDBLOCK
#else
#ifdef EAGAIN
	errno == EAGAIN
#endif
#endif
	) {
	cmd->old = (char *) zalloc(cmd->olen = used);
	memcpy(cmd->old, buf, cmd->olen);

	return 1;
    }
    if (*args)
	setsparam(*args, ztrdup(buf));
    else if (used) {
	unmetafy(buf, &used);
	write_loop(1, buf, used);
    }

    {
	int ret = cmd->fin + 1;
	if (seen && (!prog || matchok || !mustmatch))
	    ret = 0;
	if (prog)
	    freepatprog(prog);
	return ret;
    }
}