/* * Input to be processed is collected in a Client specific buffer. It * is filled by reading information from a stream, a terminal, or by * scheduling strings constructed internally. The latter involves * removing any escape character needed to manipulate the string within * the kernel. The buffer space is automatically expanded to * accommodate new information and the read pointers are adjusted. * * The input is read from a (blocked) stream and stored in the client * record input buffer. The storage area grows automatically upon need. * The origin of the input stream depends on the connectivity mode. * * Each operation received from a front-end consists of at least one * line. To simplify misaligned communication with front-ends, we use * different prompts structures. * * The default action is to read information from an ascii-stream one * line at a time. This is the preferred mode for reading from terminal. * * The next statement block is to be read. Send a prompt to warn the * front-end to issue the request. */ int MCreadClient(Client c) { bstream *in = c->fdin; #ifdef MAL_CLIENT_DEBUG printf("# streamClient %d %d\n", c->idx, isa_block_stream(in->s)); #endif while (in->pos < in->len && (isspace((int) (in->buf[in->pos])) || in->buf[in->pos] == ';' || !in->buf[in->pos])) in->pos++; if (in->pos >= in->len || in->mode) { ssize_t rd, sum = 0; if (in->eof || !isa_block_stream(c->fdout)) { if (!isa_block_stream(c->fdout) && c->promptlength > 0) mnstr_write(c->fdout, c->prompt, c->promptlength, 1); mnstr_flush(c->fdout); in->eof = 0; } while ((rd = bstream_next(in)) > 0 && !in->eof) { sum += rd; if (!in->mode) /* read one line at a time in line mode */ break; } if (in->mode) { /* find last new line */ char *p = in->buf + in->len - 1; while (p > in->buf && *p != '\n') { *(p + 1) = *p; p--; } if (p > in->buf) *(p + 1) = 0; if (p != in->buf + in->len - 1) in->len++; } if (sum == 0 && in->eof && isa_block_stream(in->s)) { /* we hadn't seen the EOF before, so just try again (this time with prompt) */ #ifdef MAL_CLIENT_DEBUG printf("# retry stream reading %d %d\n", c->idx, in->eof); #endif return MCreadClient(c); } #ifdef MAL_CLIENT_DEBUG printf("# simple stream received %d sum " SZFMT "\n", c->idx, sum); #endif } if (in->pos >= in->len) { /* end of stream reached */ #ifdef MAL_CLIENT_DEBUG printf("# end of stream received %d %d\n", c->idx, c->bak == 0); #endif if (c->bak) { MCpopClientInput(c); if (c->fdin == NULL) return 0; return MCreadClient(c); } return 0; } if (*CURRENT(c) == '?') { showHelp(c->nspace, CURRENT(c) + 1, c->fdout); in->pos = in->len; return MCreadClient(c); } #ifdef MAL_CLIENT_DEBUG printf("# finished stream read %d %d\n", (int) in->pos, (int) in->len); printf("#%s\n", in->buf); #endif return 1; }
/* * Input to be processed is collected in a Client specific buffer. It * is filled by reading information from a stream, a terminal, or by * scheduling strings constructed internally. The latter involves * removing any escape character needed to manipulate the string within * the kernel. The buffer space is automatically expanded to * accommodate new information and the read pointers are adjusted. * * The input is read from a (blocked) stream and stored in the client * record input buffer. The storage area grows automatically upon need. * The origin of the input stream depends on the connectivity mode. * * Each operation received from a front-end consists of at least one * line. To simplify misaligned communication with front-ends, we use * different prompts structures. * * The default action is to read information from an ascii-stream one * line at a time. This is the preferred mode for reading from terminal. * * The next statement block is to be read. Send a prompt to warn the * front-end to issue the request. */ int MCreadClient(Client c) { bstream *in = c->fdin; #ifdef MAL_CLIENT_DEBUG fprintf(stderr,"# streamClient %d %d\n", c->idx, isa_block_stream(in->s)); #endif while (in->pos < in->len && (isspace((unsigned char) (in->buf[in->pos])) || in->buf[in->pos] == ';' || !in->buf[in->pos])) in->pos++; if (in->pos >= in->len || in->mode) { ssize_t rd, sum = 0; if (in->eof || !isa_block_stream(c->fdout)) { if (!isa_block_stream(c->fdout) && c->promptlength > 0) mnstr_write(c->fdout, c->prompt, c->promptlength, 1); mnstr_flush(c->fdout); in->eof = false; } while ((rd = bstream_next(in)) > 0 && !in->eof) { sum += rd; if (!in->mode) /* read one line at a time in line mode */ break; } if (in->mode) { /* find last new line */ char *p = in->buf + in->len - 1; while (p > in->buf && *p != '\n') { *(p + 1) = *p; p--; } if (p > in->buf) *(p + 1) = 0; if (p != in->buf + in->len - 1) in->len++; } #ifdef MAL_CLIENT_DEBUG fprintf(stderr, "# simple stream received %d sum %zu\n", c->idx, sum); #endif } if (in->pos >= in->len) { /* end of stream reached */ #ifdef MAL_CLIENT_DEBUG fprintf(stderr,"# end of stream received %d %d\n", c->idx, c->bak == 0); #endif if (c->bak) { MCpopClientInput(c); if (c->fdin == NULL) return 0; return MCreadClient(c); } return 0; } #ifdef MAL_CLIENT_DEBUG fprintf(stderr,"# finished stream read %d %d\n", (int) in->pos, (int) in->len); printf("#%s\n", in->buf); #endif return 1; }