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