1/* 2 * Copyright (c) 2005, 2008 Sun Microsystems, Inc. All Rights Reserved. 3 * Use is subject to license terms. 4 * 5 * Copyright (c) 1984 AT&T 6 * All Rights Reserved 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * http://www.apache.org/licenses/LICENSE-2.0. 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 16 * or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21#include "apr.h" 22#include "apr_lib.h" 23#include "libsed.h" 24#include "sed.h" 25#include "apr_strings.h" 26#include "regexp.h" 27 28static const char *const trans[040] = { 29 "\\01", 30 "\\02", 31 "\\03", 32 "\\04", 33 "\\05", 34 "\\06", 35 "\\07", 36 "\\10", 37 "\\11", 38 "\n", 39 "\\13", 40 "\\14", 41 "\\15", 42 "\\16", 43 "\\17", 44 "\\20", 45 "\\21", 46 "\\22", 47 "\\23", 48 "\\24", 49 "\\25", 50 "\\26", 51 "\\27", 52 "\\30", 53 "\\31", 54 "\\32", 55 "\\33", 56 "\\34", 57 "\\35", 58 "\\36", 59 "\\37" 60}; 61static const char rub[] = {"\\177"}; 62 63extern int sed_step(char *p1, char *p2, int circf, step_vars_storage *vars); 64static int substitute(sed_eval_t *eval, sed_reptr_t *ipc, 65 step_vars_storage *step_vars); 66static apr_status_t execute(sed_eval_t *eval); 67static int match(sed_eval_t *eval, char *expbuf, int gf, 68 step_vars_storage *step_vars); 69static apr_status_t dosub(sed_eval_t *eval, char *rhsbuf, int n, 70 step_vars_storage *step_vars); 71static char *place(sed_eval_t *eval, char *asp, char *al1, char *al2); 72static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc, 73 step_vars_storage *step_vars); 74static apr_status_t wline(sed_eval_t *eval, char *buf, int sz); 75static apr_status_t arout(sed_eval_t *eval); 76 77static void eval_errf(sed_eval_t *eval, const char *fmt, ...) 78{ 79 if (eval->errfn && eval->pool) { 80 va_list args; 81 const char* error; 82 va_start(args, fmt); 83 error = apr_pvsprintf(eval->pool, fmt, args); 84 eval->errfn(eval->data, error); 85 va_end(args); 86 } 87} 88 89#define INIT_BUF_SIZE 1024 90 91/* 92 * grow_buffer 93 */ 94static void grow_buffer(apr_pool_t *pool, char **buffer, 95 char **spend, unsigned int *cursize, 96 unsigned int newsize) 97{ 98 char* newbuffer = NULL; 99 int spendsize = 0; 100 if (*cursize >= newsize) 101 return; 102 /* Avoid number of times realloc is called. It could cause huge memory 103 * requirement if line size is huge e.g 2 MB */ 104 if (newsize < *cursize * 2) { 105 newsize = *cursize * 2; 106 } 107 108 /* Align it to 4 KB boundary */ 109 newsize = (newsize + ((1 << 12) - 1)) & ~((1 << 12) -1); 110 newbuffer = apr_pcalloc(pool, newsize); 111 if (*spend && *buffer && (*cursize > 0)) { 112 spendsize = *spend - *buffer; 113 } 114 if ((*cursize > 0) && *buffer) { 115 memcpy(newbuffer, *buffer, *cursize); 116 } 117 *buffer = newbuffer; 118 *cursize = newsize; 119 if (spend != buffer) { 120 *spend = *buffer + spendsize; 121 } 122} 123 124/* 125 * grow_line_buffer 126 */ 127static void grow_line_buffer(sed_eval_t *eval, int newsize) 128{ 129 grow_buffer(eval->pool, &eval->linebuf, &eval->lspend, 130 &eval->lsize, newsize); 131} 132 133/* 134 * grow_hold_buffer 135 */ 136static void grow_hold_buffer(sed_eval_t *eval, int newsize) 137{ 138 grow_buffer(eval->pool, &eval->holdbuf, &eval->hspend, 139 &eval->hsize, newsize); 140} 141 142/* 143 * grow_gen_buffer 144 */ 145static void grow_gen_buffer(sed_eval_t *eval, int newsize, 146 char **gspend) 147{ 148 if (gspend == NULL) { 149 gspend = &eval->genbuf; 150 } 151 grow_buffer(eval->pool, &eval->genbuf, gspend, 152 &eval->gsize, newsize); 153 eval->lcomend = &eval->genbuf[71]; 154} 155 156/* 157 * appendmem_to_linebuf 158 */ 159static void appendmem_to_linebuf(sed_eval_t *eval, const char* sz, int len) 160{ 161 unsigned int reqsize = (eval->lspend - eval->linebuf) + len; 162 if (eval->lsize < reqsize) { 163 grow_line_buffer(eval, reqsize); 164 } 165 memcpy(eval->lspend, sz, len); 166 eval->lspend += len; 167} 168 169/* 170 * append_to_linebuf 171 */ 172static void append_to_linebuf(sed_eval_t *eval, const char* sz) 173{ 174 int len = strlen(sz); 175 /* Copy string including null character */ 176 appendmem_to_linebuf(eval, sz, len + 1); 177 --eval->lspend; /* lspend will now point to NULL character */ 178} 179 180/* 181 * copy_to_linebuf 182 */ 183static void copy_to_linebuf(sed_eval_t *eval, const char* sz) 184{ 185 eval->lspend = eval->linebuf; 186 append_to_linebuf(eval, sz); 187} 188 189/* 190 * append_to_holdbuf 191 */ 192static void append_to_holdbuf(sed_eval_t *eval, const char* sz) 193{ 194 int len = strlen(sz); 195 unsigned int reqsize = (eval->hspend - eval->holdbuf) + len + 1; 196 if (eval->hsize <= reqsize) { 197 grow_hold_buffer(eval, reqsize); 198 } 199 strcpy(eval->hspend, sz); 200 /* hspend will now point to NULL character */ 201 eval->hspend += len; 202} 203 204/* 205 * copy_to_holdbuf 206 */ 207static void copy_to_holdbuf(sed_eval_t *eval, const char* sz) 208{ 209 eval->hspend = eval->holdbuf; 210 append_to_holdbuf(eval, sz); 211} 212 213/* 214 * append_to_genbuf 215 */ 216static void append_to_genbuf(sed_eval_t *eval, const char* sz, char **gspend) 217{ 218 int len = strlen(sz); 219 unsigned int reqsize = (*gspend - eval->genbuf) + len + 1; 220 if (eval->gsize < reqsize) { 221 grow_gen_buffer(eval, reqsize, gspend); 222 } 223 strcpy(*gspend, sz); 224 /* *gspend will now point to NULL character */ 225 *gspend += len; 226} 227 228/* 229 * copy_to_genbuf 230 */ 231static void copy_to_genbuf(sed_eval_t *eval, const char* sz) 232{ 233 int len = strlen(sz); 234 unsigned int reqsize = len + 1; 235 if (eval->gsize < reqsize) { 236 grow_gen_buffer(eval, reqsize, NULL); 237 } 238} 239 240/* 241 * sed_init_eval 242 */ 243apr_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) 244{ 245 memset(eval, 0, sizeof(*eval)); 246 eval->pool = p; 247 eval->writefn = writefn; 248 return sed_reset_eval(eval, commands, errfn, data); 249} 250 251/* 252 * sed_reset_eval 253 */ 254apr_status_t sed_reset_eval(sed_eval_t *eval, sed_commands_t *commands, sed_err_fn_t *errfn, void *data) 255{ 256 int i; 257 258 eval->errfn = errfn; 259 eval->data = data; 260 261 eval->commands = commands; 262 263 eval->lnum = 0; 264 eval->fout = NULL; 265 266 if (eval->linebuf == NULL) { 267 eval->lsize = INIT_BUF_SIZE; 268 eval->linebuf = apr_pcalloc(eval->pool, eval->lsize); 269 } 270 if (eval->holdbuf == NULL) { 271 eval->hsize = INIT_BUF_SIZE; 272 eval->holdbuf = apr_pcalloc(eval->pool, eval->hsize); 273 } 274 if (eval->genbuf == NULL) { 275 eval->gsize = INIT_BUF_SIZE; 276 eval->genbuf = apr_pcalloc(eval->pool, eval->gsize); 277 } 278 eval->lspend = eval->linebuf; 279 eval->hspend = eval->holdbuf; 280 eval->lcomend = &eval->genbuf[71]; 281 282 for (i = 0; i < sizeof(eval->abuf) / sizeof(eval->abuf[0]); i++) 283 eval->abuf[i] = NULL; 284 eval->aptr = eval->abuf; 285 eval->pending = NULL; 286 eval->inar = apr_pcalloc(eval->pool, commands->nrep * sizeof(unsigned char)); 287 eval->nrep = commands->nrep; 288 289 eval->dolflag = 0; 290 eval->sflag = 0; 291 eval->jflag = 0; 292 eval->delflag = 0; 293 eval->lreadyflag = 0; 294 eval->quitflag = 0; 295 eval->finalflag = 1; /* assume we're evaluating only one file/stream */ 296 eval->numpass = 0; 297 eval->nullmatch = 0; 298 eval->col = 0; 299 300 for (i = 0; i < commands->nfiles; i++) { 301 const char* filename = commands->fname[i]; 302 if (apr_file_open(&eval->fcode[i], filename, 303 APR_WRITE | APR_CREATE, APR_OS_DEFAULT, 304 eval->pool) != APR_SUCCESS) { 305 eval_errf(eval, SEDERR_COMES, filename); 306 return APR_EGENERAL; 307 } 308 } 309 310 return APR_SUCCESS; 311} 312 313/* 314 * sed_destroy_eval 315 */ 316void sed_destroy_eval(sed_eval_t *eval) 317{ 318 int i; 319 /* eval->linebuf, eval->holdbuf, eval->genbuf and eval->inar are allocated 320 * on pool. It will be freed when pool will be freed */ 321 for (i = 0; i < eval->commands->nfiles; i++) { 322 if (eval->fcode[i] != NULL) { 323 apr_file_close(eval->fcode[i]); 324 eval->fcode[i] = NULL; 325 } 326 } 327} 328 329/* 330 * sed_eval_file 331 */ 332apr_status_t sed_eval_file(sed_eval_t *eval, apr_file_t *fin, void *fout) 333{ 334 for (;;) { 335 char buf[1024]; 336 apr_size_t read_bytes = 0; 337 338 read_bytes = sizeof(buf); 339 if (apr_file_read(fin, buf, &read_bytes) != APR_SUCCESS) 340 break; 341 342 if (sed_eval_buffer(eval, buf, read_bytes, fout) != APR_SUCCESS) 343 return APR_EGENERAL; 344 345 if (eval->quitflag) 346 return APR_SUCCESS; 347 } 348 349 return sed_finalize_eval(eval, fout); 350} 351 352/* 353 * sed_eval_buffer 354 */ 355apr_status_t sed_eval_buffer(sed_eval_t *eval, const char *buf, int bufsz, void *fout) 356{ 357 apr_status_t rv; 358 359 if (eval->quitflag) 360 return APR_SUCCESS; 361 362 if (!sed_canbe_finalized(eval->commands)) { 363 /* Commands were not finalized properly. */ 364 const char* error = sed_get_finalize_error(eval->commands, eval->pool); 365 if (error) { 366 eval_errf(eval, error); 367 return APR_EGENERAL; 368 } 369 } 370 371 eval->fout = fout; 372 373 /* Process leftovers */ 374 if (bufsz && eval->lreadyflag) { 375 eval->lreadyflag = 0; 376 eval->lspend--; 377 *eval->lspend = '\0'; 378 rv = execute(eval); 379 if (rv != APR_SUCCESS) 380 return rv; 381 } 382 383 while (bufsz) { 384 char *n; 385 int llen; 386 387 n = memchr(buf, '\n', bufsz); 388 if (n == NULL) 389 break; 390 391 llen = n - buf; 392 if (llen == bufsz - 1) { 393 /* This might be the last line; delay its processing */ 394 eval->lreadyflag = 1; 395 break; 396 } 397 398 appendmem_to_linebuf(eval, buf, llen + 1); 399 --eval->lspend; 400 /* replace new line character with NULL */ 401 *eval->lspend = '\0'; 402 buf += (llen + 1); 403 bufsz -= (llen + 1); 404 rv = execute(eval); 405 if (rv != APR_SUCCESS) 406 return rv; 407 if (eval->quitflag) 408 break; 409 } 410 411 /* Save the leftovers for later */ 412 if (bufsz) { 413 appendmem_to_linebuf(eval, buf, bufsz); 414 } 415 416 return APR_SUCCESS; 417} 418 419/* 420 * sed_finalize_eval 421 */ 422apr_status_t sed_finalize_eval(sed_eval_t *eval, void *fout) 423{ 424 if (eval->quitflag) 425 return APR_SUCCESS; 426 427 if (eval->finalflag) 428 eval->dolflag = 1; 429 430 eval->fout = fout; 431 432 /* Process leftovers */ 433 if (eval->lspend > eval->linebuf) { 434 apr_status_t rv; 435 436 if (eval->lreadyflag) { 437 eval->lreadyflag = 0; 438 eval->lspend--; 439 } else { 440 /* Code can probably reach here when last character in output 441 * buffer is not a newline. 442 */ 443 /* Assure space for NULL */ 444 append_to_linebuf(eval, ""); 445 } 446 447 *eval->lspend = '\0'; 448 rv = execute(eval); 449 if (rv != APR_SUCCESS) 450 return rv; 451 } 452 453 eval->quitflag = 1; 454 455 return APR_SUCCESS; 456} 457 458/* 459 * execute 460 */ 461static apr_status_t execute(sed_eval_t *eval) 462{ 463 sed_reptr_t *ipc = eval->commands->ptrspace; 464 step_vars_storage step_vars; 465 apr_status_t rv = APR_SUCCESS; 466 467 eval->lnum++; 468 469 eval->sflag = 0; 470 471 if (eval->pending) { 472 ipc = eval->pending; 473 eval->pending = NULL; 474 } 475 476 memset(&step_vars, 0, sizeof(step_vars)); 477 478 while (ipc->command) { 479 char *p1; 480 char *p2; 481 int c; 482 483 p1 = ipc->ad1; 484 p2 = ipc->ad2; 485 486 if (p1) { 487 488 if (eval->inar[ipc->nrep]) { 489 if (*p2 == CEND) { 490 p1 = 0; 491 } else if (*p2 == CLNUM) { 492 c = (unsigned char)p2[1]; 493 if (eval->lnum > eval->commands->tlno[c]) { 494 eval->inar[ipc->nrep] = 0; 495 if (ipc->negfl) 496 goto yes; 497 ipc = ipc->next; 498 continue; 499 } 500 if (eval->lnum == eval->commands->tlno[c]) { 501 eval->inar[ipc->nrep] = 0; 502 } 503 } else if (match(eval, p2, 0, &step_vars)) { 504 eval->inar[ipc->nrep] = 0; 505 } 506 } else if (*p1 == CEND) { 507 if (!eval->dolflag) { 508 if (ipc->negfl) 509 goto yes; 510 ipc = ipc->next; 511 continue; 512 } 513 } else if (*p1 == CLNUM) { 514 c = (unsigned char)p1[1]; 515 if (eval->lnum != eval->commands->tlno[c]) { 516 if (ipc->negfl) 517 goto yes; 518 ipc = ipc->next; 519 continue; 520 } 521 if (p2) 522 eval->inar[ipc->nrep] = 1; 523 } else if (match(eval, p1, 0, &step_vars)) { 524 if (p2) 525 eval->inar[ipc->nrep] = 1; 526 } else { 527 if (ipc->negfl) 528 goto yes; 529 ipc = ipc->next; 530 continue; 531 } 532 } 533 534 if (ipc->negfl) { 535 ipc = ipc->next; 536 continue; 537 } 538 539yes: 540 rv = command(eval, ipc, &step_vars); 541 if (rv != APR_SUCCESS) 542 return rv; 543 544 if (eval->quitflag) 545 return APR_SUCCESS; 546 547 if (eval->pending) 548 return APR_SUCCESS; 549 550 if (eval->delflag) 551 break; 552 553 if (eval->jflag) { 554 eval->jflag = 0; 555 if ((ipc = ipc->lb1) == 0) { 556 ipc = eval->commands->ptrspace; 557 break; 558 } 559 } else 560 ipc = ipc->next; 561 } 562 563 if (!eval->commands->nflag && !eval->delflag) { 564 rv = wline(eval, eval->linebuf, eval->lspend - eval->linebuf); 565 if (rv != APR_SUCCESS) 566 return rv; 567 } 568 569 if (eval->aptr > eval->abuf) 570 rv = arout(eval); 571 572 eval->delflag = 0; 573 574 eval->lspend = eval->linebuf; 575 576 return rv; 577} 578 579/* 580 * match 581 */ 582static int match(sed_eval_t *eval, char *expbuf, int gf, 583 step_vars_storage *step_vars) 584{ 585 char *p1; 586 int circf; 587 588 if(gf) { 589 if(*expbuf) return(0); 590 step_vars->locs = p1 = step_vars->loc2; 591 } else { 592 p1 = eval->linebuf; 593 step_vars->locs = 0; 594 } 595 596 circf = *expbuf++; 597 return(sed_step(p1, expbuf, circf, step_vars)); 598} 599 600/* 601 * substitute 602 */ 603static int substitute(sed_eval_t *eval, sed_reptr_t *ipc, 604 step_vars_storage *step_vars) 605{ 606 if(match(eval, ipc->re1, 0, step_vars) == 0) return(0); 607 608 eval->numpass = 0; 609 eval->sflag = 0; /* Flags if any substitution was made */ 610 if (dosub(eval, ipc->rhs, ipc->gfl, step_vars) != APR_SUCCESS) 611 return -1; 612 613 if(ipc->gfl) { 614 while(*step_vars->loc2) { 615 if(match(eval, ipc->re1, 1, step_vars) == 0) break; 616 if (dosub(eval, ipc->rhs, ipc->gfl, step_vars) != APR_SUCCESS) 617 return -1; 618 } 619 } 620 return(eval->sflag); 621} 622 623/* 624 * dosub 625 */ 626static apr_status_t dosub(sed_eval_t *eval, char *rhsbuf, int n, 627 step_vars_storage *step_vars) 628{ 629 char *lp, *sp, *rp; 630 int c; 631 apr_status_t rv = APR_SUCCESS; 632 633 if(n > 0 && n < 999) { 634 eval->numpass++; 635 if(n != eval->numpass) return APR_SUCCESS; 636 } 637 eval->sflag = 1; 638 lp = eval->linebuf; 639 sp = eval->genbuf; 640 rp = rhsbuf; 641 sp = place(eval, sp, lp, step_vars->loc1); 642 while ((c = *rp++) != 0) { 643 if (c == '&') { 644 sp = place(eval, sp, step_vars->loc1, step_vars->loc2); 645 if (sp == NULL) 646 return APR_EGENERAL; 647 } 648 else if (c == '\\') { 649 c = *rp++; 650 if (c >= '1' && c < NBRA+'1') { 651 sp = place(eval, sp, step_vars->braslist[c-'1'], 652 step_vars->braelist[c-'1']); 653 if (sp == NULL) 654 return APR_EGENERAL; 655 } 656 else 657 *sp++ = c; 658 } else 659 *sp++ = c; 660 if (sp >= eval->genbuf + eval->gsize) { 661 /* expand genbuf and set the sp appropriately */ 662 grow_gen_buffer(eval, eval->gsize + 1024, &sp); 663 } 664 } 665 lp = step_vars->loc2; 666 step_vars->loc2 = sp - eval->genbuf + eval->linebuf; 667 append_to_genbuf(eval, lp, &sp); 668 copy_to_linebuf(eval, eval->genbuf); 669 return rv; 670} 671 672/* 673 * place 674 */ 675static char *place(sed_eval_t *eval, char *asp, char *al1, char *al2) 676{ 677 char *sp = asp; 678 int n = al2 - al1; 679 unsigned int reqsize = (sp - eval->genbuf) + n + 1; 680 681 if (eval->gsize < reqsize) { 682 grow_gen_buffer(eval, reqsize, &sp); 683 } 684 memcpy(sp, al1, n); 685 return sp + n; 686} 687 688/* 689 * command 690 */ 691static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc, 692 step_vars_storage *step_vars) 693{ 694 int i; 695 char *p1, *p2; 696 const char *p3; 697 int length; 698 char sz[32]; /* 32 bytes enough to store 64 bit integer in decimal */ 699 apr_status_t rv = APR_SUCCESS; 700 701 702 switch(ipc->command) { 703 704 case ACOM: 705 if(eval->aptr >= &eval->abuf[SED_ABUFSIZE]) { 706 eval_errf(eval, SEDERR_TMAMES, eval->lnum); 707 } else { 708 *eval->aptr++ = ipc; 709 *eval->aptr = NULL; 710 } 711 break; 712 713 case CCOM: 714 eval->delflag = 1; 715 if(!eval->inar[ipc->nrep] || eval->dolflag) { 716 for (p1 = ipc->re1; *p1; p1++) 717 ; 718 rv = wline(eval, ipc->re1, p1 - ipc->re1); 719 } 720 break; 721 case DCOM: 722 eval->delflag++; 723 break; 724 case CDCOM: 725 p1 = eval->linebuf; 726 727 while(*p1 != '\n') { 728 if(*p1++ == 0) { 729 eval->delflag++; 730 return APR_SUCCESS; 731 } 732 } 733 734 p1++; 735 copy_to_linebuf(eval, p1); 736 eval->jflag++; 737 break; 738 739 case EQCOM: 740 length = apr_snprintf(sz, sizeof(sz), "%d", (int) eval->lnum); 741 rv = wline(eval, sz, length); 742 break; 743 744 case GCOM: 745 copy_to_linebuf(eval, eval->holdbuf); 746 break; 747 748 case CGCOM: 749 append_to_linebuf(eval, "\n"); 750 append_to_linebuf(eval, eval->holdbuf); 751 break; 752 753 case HCOM: 754 copy_to_holdbuf(eval, eval->linebuf); 755 break; 756 757 case CHCOM: 758 append_to_holdbuf(eval, "\n"); 759 append_to_holdbuf(eval, eval->linebuf); 760 break; 761 762 case ICOM: 763 for (p1 = ipc->re1; *p1; p1++); 764 rv = wline(eval, ipc->re1, p1 - ipc->re1); 765 break; 766 767 case BCOM: 768 eval->jflag = 1; 769 break; 770 771 772 case LCOM: 773 p1 = eval->linebuf; 774 p2 = eval->genbuf; 775 eval->genbuf[72] = 0; 776 while(*p1) 777 if((unsigned char)*p1 >= 040) { 778 if(*p1 == 0177) { 779 p3 = rub; 780 while ((*p2++ = *p3++) != 0) 781 if(p2 >= eval->lcomend) { 782 *p2 = '\\'; 783 rv = wline(eval, eval->genbuf, 784 strlen(eval->genbuf)); 785 if (rv != APR_SUCCESS) 786 return rv; 787 p2 = eval->genbuf; 788 } 789 p2--; 790 p1++; 791 continue; 792 } 793 if(!isprint(*p1 & 0377)) { 794 *p2++ = '\\'; 795 if(p2 >= eval->lcomend) { 796 *p2 = '\\'; 797 rv = wline(eval, eval->genbuf, 798 strlen(eval->genbuf)); 799 if (rv != APR_SUCCESS) 800 return rv; 801 p2 = eval->genbuf; 802 } 803 *p2++ = (*p1 >> 6) + '0'; 804 if(p2 >= eval->lcomend) { 805 *p2 = '\\'; 806 rv = wline(eval, eval->genbuf, 807 strlen(eval->genbuf)); 808 if (rv != APR_SUCCESS) 809 return rv; 810 p2 = eval->genbuf; 811 } 812 *p2++ = ((*p1 >> 3) & 07) + '0'; 813 if(p2 >= eval->lcomend) { 814 *p2 = '\\'; 815 rv = wline(eval, eval->genbuf, 816 strlen(eval->genbuf)); 817 if (rv != APR_SUCCESS) 818 return rv; 819 p2 = eval->genbuf; 820 } 821 *p2++ = (*p1++ & 07) + '0'; 822 if(p2 >= eval->lcomend) { 823 *p2 = '\\'; 824 rv = wline(eval, eval->genbuf, 825 strlen(eval->genbuf)); 826 if (rv != APR_SUCCESS) 827 return rv; 828 p2 = eval->genbuf; 829 } 830 } else { 831 *p2++ = *p1++; 832 if(p2 >= eval->lcomend) { 833 *p2 = '\\'; 834 rv = wline(eval, eval->genbuf, 835 strlen(eval->genbuf)); 836 if (rv != APR_SUCCESS) 837 return rv; 838 p2 = eval->genbuf; 839 } 840 } 841 } else { 842 p3 = trans[(unsigned char)*p1-1]; 843 while ((*p2++ = *p3++) != 0) 844 if(p2 >= eval->lcomend) { 845 *p2 = '\\'; 846 rv = wline(eval, eval->genbuf, 847 strlen(eval->genbuf)); 848 if (rv != APR_SUCCESS) 849 return rv; 850 p2 = eval->genbuf; 851 } 852 p2--; 853 p1++; 854 } 855 *p2 = 0; 856 rv = wline(eval, eval->genbuf, strlen(eval->genbuf)); 857 break; 858 859 case NCOM: 860 if(!eval->commands->nflag) { 861 rv = wline(eval, eval->linebuf, eval->lspend - eval->linebuf); 862 if (rv != APR_SUCCESS) 863 return rv; 864 } 865 866 if(eval->aptr > eval->abuf) { 867 rv = arout(eval); 868 if (rv != APR_SUCCESS) 869 return rv; 870 } 871 eval->lspend = eval->linebuf; 872 eval->pending = ipc->next; 873 874 break; 875 case CNCOM: 876 if(eval->aptr > eval->abuf) { 877 rv = arout(eval); 878 if (rv != APR_SUCCESS) 879 return rv; 880 } 881 append_to_linebuf(eval, "\n"); 882 eval->pending = ipc->next; 883 break; 884 885 case PCOM: 886 rv = wline(eval, eval->linebuf, eval->lspend - eval->linebuf); 887 break; 888 case CPCOM: 889 for (p1 = eval->linebuf; *p1 != '\n' && *p1 != '\0'; p1++); 890 rv = wline(eval, eval->linebuf, p1 - eval->linebuf); 891 break; 892 893 case QCOM: 894 if (!eval->commands->nflag) { 895 rv = wline(eval, eval->linebuf, eval->lspend - eval->linebuf); 896 if (rv != APR_SUCCESS) 897 break; 898 } 899 900 if(eval->aptr > eval->abuf) { 901 rv = arout(eval); 902 if (rv != APR_SUCCESS) 903 return rv; 904 } 905 906 eval->quitflag = 1; 907 break; 908 case RCOM: 909 if(eval->aptr >= &eval->abuf[SED_ABUFSIZE]) { 910 eval_errf(eval, SEDERR_TMRMES, eval->lnum); 911 } else { 912 *eval->aptr++ = ipc; 913 *eval->aptr = NULL; 914 } 915 break; 916 917 case SCOM: 918 i = substitute(eval, ipc, step_vars); 919 if (i == -1) { 920 return APR_EGENERAL; 921 } 922 if(ipc->pfl && eval->commands->nflag && i) { 923 if(ipc->pfl == 1) { 924 rv = wline(eval, eval->linebuf, eval->lspend - 925 eval->linebuf); 926 if (rv != APR_SUCCESS) 927 return rv; 928 } else { 929 for (p1 = eval->linebuf; *p1 != '\n' && *p1 != '\0'; p1++); 930 rv = wline(eval, eval->linebuf, p1 - eval->linebuf); 931 if (rv != APR_SUCCESS) 932 return rv; 933 } 934 } 935 if (i && (ipc->findex >= 0) && eval->fcode[ipc->findex]) 936 apr_file_printf(eval->fcode[ipc->findex], "%s\n", 937 eval->linebuf); 938 break; 939 940 case TCOM: 941 if(eval->sflag == 0) break; 942 eval->sflag = 0; 943 eval->jflag = 1; 944 break; 945 946 case WCOM: 947 if (ipc->findex >= 0) 948 apr_file_printf(eval->fcode[ipc->findex], "%s\n", 949 eval->linebuf); 950 break; 951 case XCOM: 952 copy_to_genbuf(eval, eval->linebuf); 953 copy_to_linebuf(eval, eval->holdbuf); 954 copy_to_holdbuf(eval, eval->genbuf); 955 break; 956 957 case YCOM: 958 p1 = eval->linebuf; 959 p2 = ipc->re1; 960 while((*p1 = p2[(unsigned char)*p1]) != 0) p1++; 961 break; 962 } 963 return rv; 964} 965 966/* 967 * arout 968 */ 969static apr_status_t arout(sed_eval_t *eval) 970{ 971 apr_status_t rv = APR_SUCCESS; 972 eval->aptr = eval->abuf - 1; 973 while (*++eval->aptr) { 974 if ((*eval->aptr)->command == ACOM) { 975 char *p1; 976 977 for (p1 = (*eval->aptr)->re1; *p1; p1++); 978 rv = wline(eval, (*eval->aptr)->re1, p1 - (*eval->aptr)->re1); 979 if (rv != APR_SUCCESS) 980 return rv; 981 } else { 982 apr_file_t *fi = NULL; 983 char buf[512]; 984 apr_size_t n = sizeof(buf); 985 986 if (apr_file_open(&fi, (*eval->aptr)->re1, APR_READ, 0, eval->pool) 987 != APR_SUCCESS) 988 continue; 989 while ((apr_file_read(fi, buf, &n)) == APR_SUCCESS) { 990 if (n == 0) 991 break; 992 rv = eval->writefn(eval->fout, buf, n); 993 if (rv != APR_SUCCESS) { 994 apr_file_close(fi); 995 return rv; 996 } 997 n = sizeof(buf); 998 } 999 apr_file_close(fi); 1000 } 1001 } 1002 eval->aptr = eval->abuf; 1003 *eval->aptr = NULL; 1004 return rv; 1005} 1006 1007/* 1008 * wline 1009 */ 1010static apr_status_t wline(sed_eval_t *eval, char *buf, int sz) 1011{ 1012 apr_status_t rv = APR_SUCCESS; 1013 rv = eval->writefn(eval->fout, buf, sz); 1014 if (rv != APR_SUCCESS) 1015 return rv; 1016 rv = eval->writefn(eval->fout, "\n", 1); 1017 return rv; 1018} 1019 1020