/* * Copyright (c) 2005, 2008 Sun Microsystems, Inc. All Rights Reserved. * Use is subject to license terms. * * Copyright (c) 1984 AT&T * All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "apr.h" #include "apr_lib.h" #include "libsed.h" #include "sed.h" #include "apr_strings.h" #include "regexp.h" static const char *const trans[040] = { "\\01", "\\02", "\\03", "\\04", "\\05", "\\06", "\\07", "\\10", "\\11", "\n", "\\13", "\\14", "\\15", "\\16", "\\17", "\\20", "\\21", "\\22", "\\23", "\\24", "\\25", "\\26", "\\27", "\\30", "\\31", "\\32", "\\33", "\\34", "\\35", "\\36", "\\37" }; static const char rub[] = {"\\177"}; extern int sed_step(char *p1, char *p2, int circf, step_vars_storage *vars); static int substitute(sed_eval_t *eval, sed_reptr_t *ipc, step_vars_storage *step_vars); static apr_status_t execute(sed_eval_t *eval); static int match(sed_eval_t *eval, char *expbuf, int gf, step_vars_storage *step_vars); static apr_status_t dosub(sed_eval_t *eval, char *rhsbuf, int n, step_vars_storage *step_vars); static char *place(sed_eval_t *eval, char *asp, char *al1, char *al2); static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc, step_vars_storage *step_vars); static apr_status_t wline(sed_eval_t *eval, char *buf, apr_size_t sz); static apr_status_t arout(sed_eval_t *eval); static void eval_errf(sed_eval_t *eval, const char *fmt, ...) { if (eval->errfn && eval->pool) { va_list args; const char* error; va_start(args, fmt); error = apr_pvsprintf(eval->pool, fmt, args); eval->errfn(eval->data, error); va_end(args); } } #define INIT_BUF_SIZE 1024 #define MAX_BUF_SIZE 1024*8192 /* * grow_buffer */ static apr_status_t grow_buffer(apr_pool_t *pool, char **buffer, char **spend, apr_size_t *cursize, apr_size_t newsize) { char* newbuffer = NULL; apr_size_t spendsize = 0; if (*cursize >= newsize) { return APR_SUCCESS; } /* Avoid number of times realloc is called. It could cause huge memory * requirement if line size is huge e.g 2 MB */ if (newsize < *cursize * 2) { newsize = *cursize * 2; } /* Align it to 4 KB boundary */ newsize = (newsize + ((1 << 12) - 1)) & ~((1 << 12) - 1); if (newsize > MAX_BUF_SIZE) { return APR_ENOMEM; } newbuffer = apr_pcalloc(pool, newsize); if (*spend && *buffer && (*cursize > 0)) { spendsize = *spend - *buffer; } if ((*cursize > 0) && *buffer) { memcpy(newbuffer, *buffer, *cursize); } *buffer = newbuffer; *cursize = newsize; if (spend != buffer) { *spend = *buffer + spendsize; } return APR_SUCCESS; } /* * grow_line_buffer */ static apr_status_t grow_line_buffer(sed_eval_t *eval, apr_size_t newsize) { return grow_buffer(eval->pool, &eval->linebuf, &eval->lspend, &eval->lsize, newsize); } /* * grow_hold_buffer */ static apr_status_t grow_hold_buffer(sed_eval_t *eval, apr_size_t newsize) { return grow_buffer(eval->pool, &eval->holdbuf, &eval->hspend, &eval->hsize, newsize); } /* * grow_gen_buffer */ static apr_status_t grow_gen_buffer(sed_eval_t *eval, apr_size_t newsize, char **gspend) { apr_status_t rc = 0; if (gspend == NULL) { gspend = &eval->genbuf; } rc = grow_buffer(eval->pool, &eval->genbuf, gspend, &eval->gsize, newsize); if (rc == APR_SUCCESS) { eval->lcomend = &eval->genbuf[71]; } return rc; } /* * appendmem_to_linebuf */ static apr_status_t appendmem_to_linebuf(sed_eval_t *eval, const char* sz, apr_size_t len) { apr_status_t rc = 0; apr_size_t reqsize = (eval->lspend - eval->linebuf) + len; if (eval->lsize < reqsize) { rc = grow_line_buffer(eval, reqsize); if (rc != APR_SUCCESS) { return rc; } } memcpy(eval->lspend, sz, len); eval->lspend += len; return APR_SUCCESS; } /* * append_to_linebuf */ static apr_status_t append_to_linebuf(sed_eval_t *eval, const char* sz, step_vars_storage *step_vars) { apr_size_t len = strlen(sz); char *old_linebuf = eval->linebuf; apr_status_t rc = 0; /* Copy string including null character */ rc = appendmem_to_linebuf(eval, sz, len + 1); if (rc != APR_SUCCESS) { return rc; } --eval->lspend; /* lspend will now point to NULL character */ /* Sync step_vars after a possible linebuf expansion */ if (step_vars && old_linebuf != eval->linebuf) { if (step_vars->loc1) { step_vars->loc1 = step_vars->loc1 - old_linebuf + eval->linebuf; } if (step_vars->loc2) { step_vars->loc2 = step_vars->loc2 - old_linebuf + eval->linebuf; } if (step_vars->locs) { step_vars->locs = step_vars->locs - old_linebuf + eval->linebuf; } } return APR_SUCCESS; } /* * copy_to_linebuf */ static apr_status_t copy_to_linebuf(sed_eval_t *eval, const char* sz, step_vars_storage *step_vars) { eval->lspend = eval->linebuf; return append_to_linebuf(eval, sz, step_vars); } /* * append_to_holdbuf */ static apr_status_t append_to_holdbuf(sed_eval_t *eval, const char* sz) { apr_size_t len = strlen(sz); apr_size_t reqsize = (eval->hspend - eval->holdbuf) + len + 1; apr_status_t rc = 0; if (eval->hsize <= reqsize) { rc = grow_hold_buffer(eval, reqsize); if (rc != APR_SUCCESS) { return rc; } } memcpy(eval->hspend, sz, len + 1); /* hspend will now point to NULL character */ eval->hspend += len; return APR_SUCCESS; } /* * copy_to_holdbuf */ static apr_status_t copy_to_holdbuf(sed_eval_t *eval, const char* sz) { eval->hspend = eval->holdbuf; return append_to_holdbuf(eval, sz); } /* * append_to_genbuf */ static apr_status_t append_to_genbuf(sed_eval_t *eval, const char* sz, char **gspend) { apr_size_t len = strlen(sz); apr_size_t reqsize = (*gspend - eval->genbuf) + len + 1; apr_status_t rc = 0; if (eval->gsize < reqsize) { rc = grow_gen_buffer(eval, reqsize, gspend); if (rc != APR_SUCCESS) { return rc; } } memcpy(*gspend, sz, len + 1); /* *gspend will now point to NULL character */ *gspend += len; return APR_SUCCESS; } /* * copy_to_genbuf */ static apr_status_t copy_to_genbuf(sed_eval_t *eval, const char* sz) { apr_size_t len = strlen(sz); apr_size_t reqsize = len + 1; apr_status_t rc = APR_SUCCESS;; if (eval->gsize < reqsize) { rc = grow_gen_buffer(eval, reqsize, NULL); if (rc != APR_SUCCESS) { return rc; } } memcpy(eval->genbuf, sz, len + 1); return rc; } /* * sed_init_eval */ apr_status_t sed_init_eval(sed_eval_t *eval, sed_commands_t *commands, sed_err_fn_t *errfn, void *data, sed_write_fn_t *writefn, apr_pool_t* p) { memset(eval, 0, sizeof(*eval)); eval->pool = p; eval->writefn = writefn; return sed_reset_eval(eval, commands, errfn, data); } /* * sed_reset_eval */ apr_status_t sed_reset_eval(sed_eval_t *eval, sed_commands_t *commands, sed_err_fn_t *errfn, void *data) { int i; eval->errfn = errfn; eval->data = data; eval->commands = commands; eval->lnum = 0; eval->fout = NULL; if (eval->linebuf == NULL) { eval->lsize = INIT_BUF_SIZE; eval->linebuf = apr_pcalloc(eval->pool, eval->lsize); } if (eval->holdbuf == NULL) { eval->hsize = INIT_BUF_SIZE; eval->holdbuf = apr_pcalloc(eval->pool, eval->hsize); } if (eval->genbuf == NULL) { eval->gsize = INIT_BUF_SIZE; eval->genbuf = apr_pcalloc(eval->pool, eval->gsize); } eval->lspend = eval->linebuf; eval->hspend = eval->holdbuf; eval->lcomend = &eval->genbuf[71]; for (i = 0; i < sizeof(eval->abuf) / sizeof(eval->abuf[0]); i++) eval->abuf[i] = NULL; eval->aptr = eval->abuf; eval->pending = NULL; eval->inar = apr_pcalloc(eval->pool, commands->nrep * sizeof(unsigned char)); eval->nrep = commands->nrep; eval->dolflag = 0; eval->sflag = 0; eval->jflag = 0; eval->delflag = 0; eval->lreadyflag = 0; eval->quitflag = 0; eval->finalflag = 1; /* assume we're evaluating only one file/stream */ eval->numpass = 0; eval->nullmatch = 0; eval->col = 0; for (i = 0; i < commands->nfiles; i++) { const char* filename = commands->fname[i]; if (apr_file_open(&eval->fcode[i], filename, APR_WRITE | APR_CREATE, APR_OS_DEFAULT, eval->pool) != APR_SUCCESS) { eval_errf(eval, SEDERR_COMES, filename); return APR_EGENERAL; } } return APR_SUCCESS; } /* * sed_destroy_eval */ void sed_destroy_eval(sed_eval_t *eval) { int i; /* eval->linebuf, eval->holdbuf, eval->genbuf and eval->inar are allocated * on pool. It will be freed when pool will be freed */ for (i = 0; i < eval->commands->nfiles; i++) { if (eval->fcode[i] != NULL) { apr_file_close(eval->fcode[i]); eval->fcode[i] = NULL; } } } /* * sed_eval_file */ apr_status_t sed_eval_file(sed_eval_t *eval, apr_file_t *fin, void *fout) { for (;;) { char buf[1024]; apr_size_t read_bytes = 0; read_bytes = sizeof(buf); if (apr_file_read(fin, buf, &read_bytes) != APR_SUCCESS) break; if (sed_eval_buffer(eval, buf, read_bytes, fout) != APR_SUCCESS) return APR_EGENERAL; if (eval->quitflag) return APR_SUCCESS; } return sed_finalize_eval(eval, fout); } /* * sed_eval_buffer */ apr_status_t sed_eval_buffer(sed_eval_t *eval, const char *buf, apr_size_t bufsz, void *fout) { apr_status_t rv; if (eval->quitflag) return APR_SUCCESS; if (!sed_canbe_finalized(eval->commands)) { /* Commands were not finalized properly. */ const char* error = sed_get_finalize_error(eval->commands, eval->pool); if (error) { eval_errf(eval, error); return APR_EGENERAL; } } eval->fout = fout; /* Process leftovers */ if (bufsz && eval->lreadyflag) { eval->lreadyflag = 0; eval->lspend--; *eval->lspend = '\0'; rv = execute(eval); if (rv != APR_SUCCESS) return rv; } while (bufsz) { apr_status_t rc = 0; char *n; apr_size_t llen; n = memchr(buf, '\n', bufsz); if (n == NULL) break; llen = n - buf; if (llen == bufsz - 1) { /* This might be the last line; delay its processing */ eval->lreadyflag = 1; break; } rc = appendmem_to_linebuf(eval, buf, llen + 1); if (rc != APR_SUCCESS) { return rc; } --eval->lspend; /* replace new line character with NULL */ *eval->lspend = '\0'; buf += (llen + 1); bufsz -= (llen + 1); rv = execute(eval); if (rv != APR_SUCCESS) return rv; if (eval->quitflag) break; } /* Save the leftovers for later */ if (bufsz) { apr_status_t rc = appendmem_to_linebuf(eval, buf, bufsz); if (rc != APR_SUCCESS) { return rc; } } return APR_SUCCESS; } /* * sed_finalize_eval */ apr_status_t sed_finalize_eval(sed_eval_t *eval, void *fout) { if (eval->quitflag) return APR_SUCCESS; if (eval->finalflag) eval->dolflag = 1; eval->fout = fout; /* Process leftovers */ if (eval->lspend > eval->linebuf) { apr_status_t rv; apr_status_t rc = 0; if (eval->lreadyflag) { eval->lreadyflag = 0; eval->lspend--; } else { /* Code can probably reach here when last character in output * buffer is not a newline. */ /* Assure space for NULL */ rc = append_to_linebuf(eval, "", NULL); if (rc != APR_SUCCESS) { return rc; } } *eval->lspend = '\0'; rv = execute(eval); if (rv != APR_SUCCESS) return rv; } eval->quitflag = 1; return APR_SUCCESS; } /* * execute */ static apr_status_t execute(sed_eval_t *eval) { sed_reptr_t *ipc = eval->commands->ptrspace; step_vars_storage step_vars; apr_status_t rv = APR_SUCCESS; eval->lnum++; eval->sflag = 0; if (eval->pending) { ipc = eval->pending; eval->pending = NULL; } memset(&step_vars, 0, sizeof(step_vars)); while (ipc->command) { char *p1; char *p2; int c; p1 = ipc->ad1; p2 = ipc->ad2; if (p1) { if (eval->inar[ipc->nrep]) { if (*p2 == CEND) { p1 = 0; } else if (*p2 == CLNUM) { c = (unsigned char)p2[1]; if (eval->lnum > eval->commands->tlno[c]) { eval->inar[ipc->nrep] = 0; if (ipc->negfl) goto yes; ipc = ipc->next; continue; } if (eval->lnum == eval->commands->tlno[c]) { eval->inar[ipc->nrep] = 0; } } else if (match(eval, p2, 0, &step_vars)) { eval->inar[ipc->nrep] = 0; } } else if (*p1 == CEND) { if (!eval->dolflag) { if (ipc->negfl) goto yes; ipc = ipc->next; continue; } } else if (*p1 == CLNUM) { c = (unsigned char)p1[1]; if (eval->lnum != eval->commands->tlno[c]) { if (ipc->negfl) goto yes; ipc = ipc->next; continue; } if (p2) eval->inar[ipc->nrep] = 1; } else if (match(eval, p1, 0, &step_vars)) { if (p2) eval->inar[ipc->nrep] = 1; } else { if (ipc->negfl) goto yes; ipc = ipc->next; continue; } } if (ipc->negfl) { ipc = ipc->next; continue; } yes: rv = command(eval, ipc, &step_vars); if (rv != APR_SUCCESS) return rv; if (eval->quitflag) return APR_SUCCESS; if (eval->pending) return APR_SUCCESS; if (eval->delflag) break; if (eval->jflag) { eval->jflag = 0; if ((ipc = ipc->lb1) == 0) { ipc = eval->commands->ptrspace; break; } } else ipc = ipc->next; } if (!eval->commands->nflag && !eval->delflag) { rv = wline(eval, eval->linebuf, eval->lspend - eval->linebuf); if (rv != APR_SUCCESS) return rv; } if (eval->aptr > eval->abuf) rv = arout(eval); eval->delflag = 0; eval->lspend = eval->linebuf; return rv; } /* * match */ static int match(sed_eval_t *eval, char *expbuf, int gf, step_vars_storage *step_vars) { char *p1; int circf; if (gf) { if (*expbuf) return(0); step_vars->locs = p1 = step_vars->loc2; } else { p1 = eval->linebuf; step_vars->locs = 0; } circf = *expbuf++; return(sed_step(p1, expbuf, circf, step_vars)); } /* * substitute */ static int substitute(sed_eval_t *eval, sed_reptr_t *ipc, step_vars_storage *step_vars) { if (match(eval, ipc->re1, 0, step_vars) == 0) return(0); eval->numpass = 0; eval->sflag = 0; /* Flags if any substitution was made */ if (dosub(eval, ipc->rhs, ipc->gfl, step_vars) != APR_SUCCESS) return -1; if (ipc->gfl) { while (*step_vars->loc2) { if (match(eval, ipc->re1, 1, step_vars) == 0) break; if (dosub(eval, ipc->rhs, ipc->gfl, step_vars) != APR_SUCCESS) return -1; } } return(eval->sflag); } /* * dosub */ static apr_status_t dosub(sed_eval_t *eval, char *rhsbuf, int n, step_vars_storage *step_vars) { char *lp, *sp, *rp; int c; apr_status_t rv = APR_SUCCESS; if (n > 0 && n < 999) { eval->numpass++; if (n != eval->numpass) return APR_SUCCESS; } eval->sflag = 1; lp = eval->linebuf; sp = eval->genbuf; rp = rhsbuf; sp = place(eval, sp, lp, step_vars->loc1); if (sp == NULL) { return APR_EGENERAL; } while ((c = *rp++) != 0) { if (c == '&') { sp = place(eval, sp, step_vars->loc1, step_vars->loc2); if (sp == NULL) { return APR_EGENERAL; } } else if (c == '\\') { c = *rp++; if (c >= '1' && c < NBRA+'1') { sp = place(eval, sp, step_vars->braslist[c-'1'], step_vars->braelist[c-'1']); if (sp == NULL) return APR_EGENERAL; } else *sp++ = c; } else *sp++ = c; if (sp >= eval->genbuf + eval->gsize) { /* expand genbuf and set the sp appropriately */ rv = grow_gen_buffer(eval, eval->gsize + 1024, &sp); if (rv != APR_SUCCESS) { return rv; } } } lp = step_vars->loc2; step_vars->loc2 = sp - eval->genbuf + eval->linebuf; rv = append_to_genbuf(eval, lp, &sp); if (rv != APR_SUCCESS) { return rv; } rv = copy_to_linebuf(eval, eval->genbuf, step_vars); return rv; } /* * place */ static char *place(sed_eval_t *eval, char *asp, char *al1, char *al2) { char *sp = asp; apr_size_t n = al2 - al1; apr_size_t reqsize = (sp - eval->genbuf) + n + 1; if (eval->gsize < reqsize) { apr_status_t rc = grow_gen_buffer(eval, reqsize, &sp); if (rc != APR_SUCCESS) { return NULL; } } memcpy(sp, al1, n); return sp + n; } /* * command */ static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc, step_vars_storage *step_vars) { int i; char *p1, *p2; const char *p3; int length; char sz[32]; /* 32 bytes enough to store 64 bit integer in decimal */ apr_status_t rv = APR_SUCCESS; switch(ipc->command) { case ACOM: if (eval->aptr >= &eval->abuf[SED_ABUFSIZE]) { eval_errf(eval, SEDERR_TMAMES, eval->lnum); } else { *eval->aptr++ = ipc; *eval->aptr = NULL; } break; case CCOM: eval->delflag = 1; if (!eval->inar[ipc->nrep] || eval->dolflag) { for (p1 = ipc->re1; *p1; p1++) ; rv = wline(eval, ipc->re1, p1 - ipc->re1); } break; case DCOM: eval->delflag++; break; case CDCOM: p1 = eval->linebuf; while (*p1 != '\n') { if (*p1++ == 0) { eval->delflag++; return APR_SUCCESS; } } p1++; rv = copy_to_linebuf(eval, p1, step_vars); if (rv != APR_SUCCESS) return rv; eval->jflag++; break; case EQCOM: length = apr_snprintf(sz, sizeof(sz), "%d", (int) eval->lnum); rv = wline(eval, sz, length); break; case GCOM: rv = copy_to_linebuf(eval, eval->holdbuf, step_vars); if (rv != APR_SUCCESS) return rv; break; case CGCOM: rv = append_to_linebuf(eval, "\n", step_vars); if (rv != APR_SUCCESS) return rv; rv = append_to_linebuf(eval, eval->holdbuf, step_vars); if (rv != APR_SUCCESS) return rv; break; case HCOM: rv = copy_to_holdbuf(eval, eval->linebuf); if (rv != APR_SUCCESS) return rv; break; case CHCOM: rv = append_to_holdbuf(eval, "\n"); if (rv != APR_SUCCESS) return rv; rv = append_to_holdbuf(eval, eval->linebuf); if (rv != APR_SUCCESS) return rv; break; case ICOM: for (p1 = ipc->re1; *p1; p1++); rv = wline(eval, ipc->re1, p1 - ipc->re1); break; case BCOM: eval->jflag = 1; break; case LCOM: p1 = eval->linebuf; p2 = eval->genbuf; eval->genbuf[72] = 0; while (*p1) { if ((unsigned char)*p1 >= 040) { if (*p1 == 0177) { p3 = rub; while ((*p2++ = *p3++) != 0) if (p2 >= eval->lcomend) { *p2 = '\\'; rv = wline(eval, eval->genbuf, strlen(eval->genbuf)); if (rv != APR_SUCCESS) return rv; p2 = eval->genbuf; } p2--; p1++; continue; } if (!isprint(*p1 & 0377)) { *p2++ = '\\'; if (p2 >= eval->lcomend) { *p2 = '\\'; rv = wline(eval, eval->genbuf, strlen(eval->genbuf)); if (rv != APR_SUCCESS) return rv; p2 = eval->genbuf; } *p2++ = (*p1 >> 6) + '0'; if (p2 >= eval->lcomend) { *p2 = '\\'; rv = wline(eval, eval->genbuf, strlen(eval->genbuf)); if (rv != APR_SUCCESS) return rv; p2 = eval->genbuf; } *p2++ = ((*p1 >> 3) & 07) + '0'; if (p2 >= eval->lcomend) { *p2 = '\\'; rv = wline(eval, eval->genbuf, strlen(eval->genbuf)); if (rv != APR_SUCCESS) return rv; p2 = eval->genbuf; } *p2++ = (*p1++ & 07) + '0'; if (p2 >= eval->lcomend) { *p2 = '\\'; rv = wline(eval, eval->genbuf, strlen(eval->genbuf)); if (rv != APR_SUCCESS) return rv; p2 = eval->genbuf; } } else { *p2++ = *p1++; if (p2 >= eval->lcomend) { *p2 = '\\'; rv = wline(eval, eval->genbuf, strlen(eval->genbuf)); if (rv != APR_SUCCESS) return rv; p2 = eval->genbuf; } } } else { p3 = trans[(unsigned char)*p1-1]; while ((*p2++ = *p3++) != 0) if (p2 >= eval->lcomend) { *p2 = '\\'; rv = wline(eval, eval->genbuf, strlen(eval->genbuf)); if (rv != APR_SUCCESS) return rv; p2 = eval->genbuf; } p2--; p1++; } } *p2 = 0; rv = wline(eval, eval->genbuf, strlen(eval->genbuf)); break; case NCOM: if (!eval->commands->nflag) { rv = wline(eval, eval->linebuf, eval->lspend - eval->linebuf); if (rv != APR_SUCCESS) return rv; } if (eval->aptr > eval->abuf) { rv = arout(eval); if (rv != APR_SUCCESS) return rv; } eval->lspend = eval->linebuf; eval->pending = ipc->next; break; case CNCOM: if (eval->aptr > eval->abuf) { rv = arout(eval); if (rv != APR_SUCCESS) return rv; } rv = append_to_linebuf(eval, "\n", step_vars); if (rv != APR_SUCCESS) return rv; eval->pending = ipc->next; break; case PCOM: rv = wline(eval, eval->linebuf, eval->lspend - eval->linebuf); break; case CPCOM: for (p1 = eval->linebuf; *p1 != '\n' && *p1 != '\0'; p1++); rv = wline(eval, eval->linebuf, p1 - eval->linebuf); break; case QCOM: if (!eval->commands->nflag) { rv = wline(eval, eval->linebuf, eval->lspend - eval->linebuf); if (rv != APR_SUCCESS) break; } if (eval->aptr > eval->abuf) { rv = arout(eval); if (rv != APR_SUCCESS) return rv; } eval->quitflag = 1; break; case RCOM: if (eval->aptr >= &eval->abuf[SED_ABUFSIZE]) { eval_errf(eval, SEDERR_TMRMES, eval->lnum); } else { *eval->aptr++ = ipc; *eval->aptr = NULL; } break; case SCOM: i = substitute(eval, ipc, step_vars); if (i == -1) { return APR_EGENERAL; } if (ipc->pfl && eval->commands->nflag && i) { if (ipc->pfl == 1) { rv = wline(eval, eval->linebuf, eval->lspend - eval->linebuf); if (rv != APR_SUCCESS) return rv; } else { for (p1 = eval->linebuf; *p1 != '\n' && *p1 != '\0'; p1++); rv = wline(eval, eval->linebuf, p1 - eval->linebuf); if (rv != APR_SUCCESS) return rv; } } if (i && (ipc->findex >= 0) && eval->fcode[ipc->findex]) apr_file_printf(eval->fcode[ipc->findex], "%s\n", eval->linebuf); break; case TCOM: if (eval->sflag == 0) break; eval->sflag = 0; eval->jflag = 1; break; case WCOM: if (ipc->findex >= 0) apr_file_printf(eval->fcode[ipc->findex], "%s\n", eval->linebuf); break; case XCOM: rv = copy_to_genbuf(eval, eval->linebuf); if (rv != APR_SUCCESS) return rv; rv = copy_to_linebuf(eval, eval->holdbuf, step_vars); if (rv != APR_SUCCESS) return rv; rv = copy_to_holdbuf(eval, eval->genbuf); if (rv != APR_SUCCESS) return rv; break; case YCOM: p1 = eval->linebuf; p2 = ipc->re1; while ((*p1 = p2[(unsigned char)*p1]) != 0) p1++; break; } return rv; } /* * arout */ static apr_status_t arout(sed_eval_t *eval) { apr_status_t rv = APR_SUCCESS; eval->aptr = eval->abuf - 1; while (*++eval->aptr) { if ((*eval->aptr)->command == ACOM) { char *p1; for (p1 = (*eval->aptr)->re1; *p1; p1++); rv = wline(eval, (*eval->aptr)->re1, p1 - (*eval->aptr)->re1); if (rv != APR_SUCCESS) return rv; } else { apr_file_t *fi = NULL; char buf[512]; apr_size_t n = sizeof(buf); if (apr_file_open(&fi, (*eval->aptr)->re1, APR_READ, 0, eval->pool) != APR_SUCCESS) continue; while ((apr_file_read(fi, buf, &n)) == APR_SUCCESS) { if (n == 0) break; rv = eval->writefn(eval->fout, buf, n); if (rv != APR_SUCCESS) { apr_file_close(fi); return rv; } n = sizeof(buf); } apr_file_close(fi); } } eval->aptr = eval->abuf; *eval->aptr = NULL; return rv; } /* * wline */ static apr_status_t wline(sed_eval_t *eval, char *buf, apr_size_t sz) { apr_status_t rv = APR_SUCCESS; rv = eval->writefn(eval->fout, buf, sz); if (rv != APR_SUCCESS) return rv; rv = eval->writefn(eval->fout, "\n", 1); return rv; }