23
23
* resulting sed_cmd_t structures are appended to a linked list
24
24
* (G.sed_cmd_head/G.sed_cmd_tail).
25
25
*
26
- * add_input_file() adds a FILE * to the list of input files. We need to
26
+ * add_input_file() adds a char * to the list of input files. We need to
27
27
* know all input sources ahead of time to find the last line for the $ match.
28
28
*
29
29
* process_files() does actual sedding, reading data lines from each input FILE*
@@ -135,20 +135,23 @@ static const char semicolon_whitespace[] ALIGN1 = "; \n\r\t\v";
135
135
struct globals {
136
136
/* options */
137
137
int be_quiet , regex_type ;
138
+
138
139
FILE * nonstdout ;
139
140
char * outname , * hold_space ;
141
+ smallint exitcode ;
140
142
141
- /* List of input files */
143
+ /* list of input files */
142
144
int input_file_count , current_input_file ;
143
- FILE * * input_file_list ;
145
+ const char * * input_file_list ;
146
+ FILE * current_fp ;
144
147
145
148
regmatch_t regmatch [10 ];
146
149
regex_t * previous_regex_ptr ;
147
150
148
151
/* linked list of sed commands */
149
152
sed_cmd_t * sed_cmd_head , * * sed_cmd_tail ;
150
153
151
- /* Linked list of append lines */
154
+ /* linked list of append lines */
152
155
llist_t * append_head ;
153
156
154
157
char * add_cmd_line ;
@@ -200,8 +203,8 @@ static void sed_free_and_close_stuff(void)
200
203
201
204
free (G .hold_space );
202
205
203
- while (G .current_input_file < G . input_file_count )
204
- fclose (G .input_file_list [ G . current_input_file ++ ] );
206
+ if (G .current_fp )
207
+ fclose (G .current_fp );
205
208
}
206
209
#else
207
210
void sed_free_and_close_stuff (void );
@@ -939,8 +942,20 @@ static char *get_next_line(char *gets_char, char *last_puts_char, char last_gets
939
942
/* will be returned if last line in the file
940
943
* doesn't end with either '\n' or '\0' */
941
944
gc = NO_EOL_CHAR ;
942
- while (G .current_input_file < G .input_file_count ) {
943
- FILE * fp = G .input_file_list [G .current_input_file ];
945
+ for (; G .input_file_list [G .current_input_file ]; G .current_input_file ++ ) {
946
+ FILE * fp = G .current_fp ;
947
+ if (!fp ) {
948
+ const char * path = G .input_file_list [G .current_input_file ];
949
+ fp = stdin ;
950
+ if (path != bb_msg_standard_input ) {
951
+ fp = fopen_or_warn (path , "r" );
952
+ if (!fp ) {
953
+ G .exitcode = EXIT_FAILURE ;
954
+ continue ;
955
+ }
956
+ }
957
+ G .current_fp = fp ;
958
+ }
944
959
/* Read line up to a newline or NUL byte, inclusive,
945
960
* return malloc'ed char[]. length of the chunk read
946
961
* is stored in len. NULL if EOF/error */
@@ -971,8 +986,8 @@ static char *get_next_line(char *gets_char, char *last_puts_char, char last_gets
971
986
* (note: *no* newline after "b bang"!) */
972
987
}
973
988
/* Close this file and advance to next one */
974
- fclose (fp );
975
- G .current_input_file ++ ;
989
+ fclose_if_not_stdin (fp );
990
+ G .current_fp = NULL ;
976
991
}
977
992
* gets_char = gc ;
978
993
return temp ;
@@ -1399,7 +1414,7 @@ static void add_cmd_block(char *cmdstr)
1399
1414
free (sv );
1400
1415
}
1401
1416
1402
- static void add_input_file (FILE * file )
1417
+ static void add_input_file (const char * file )
1403
1418
{
1404
1419
G .input_file_list = xrealloc_vector (G .input_file_list , 2 , G .input_file_count );
1405
1420
G .input_file_list [G .input_file_count ++ ] = file ;
@@ -1423,8 +1438,6 @@ int sed_main(int argc UNUSED_PARAM, char **argv)
1423
1438
"file\0" Required_argument "f" ;
1424
1439
#endif
1425
1440
1426
- int status = EXIT_SUCCESS ;
1427
-
1428
1441
INIT_G ();
1429
1442
1430
1443
/* destroy command strings on exit */
@@ -1491,27 +1504,21 @@ int sed_main(int argc UNUSED_PARAM, char **argv)
1491
1504
if (argv [0 ] == NULL ) {
1492
1505
if (opt & OPT_in_place )
1493
1506
bb_error_msg_and_die (bb_msg_requires_arg , "-i" );
1494
- add_input_file (stdin );
1507
+ add_input_file (bb_msg_standard_input );
1495
1508
} else {
1496
1509
int i ;
1497
1510
1498
1511
for (i = 0 ; argv [i ]; i ++ ) {
1499
1512
struct stat statbuf ;
1500
1513
int nonstdoutfd ;
1501
- FILE * file ;
1502
1514
sed_cmd_t * sed_cmd ;
1503
1515
1504
1516
if (LONE_DASH (argv [i ]) && !(opt & OPT_in_place )) {
1505
- add_input_file (stdin );
1517
+ add_input_file (bb_msg_standard_input );
1506
1518
process_files ();
1507
1519
continue ;
1508
1520
}
1509
- file = fopen_or_warn (argv [i ], "r" );
1510
- if (!file ) {
1511
- status = EXIT_FAILURE ;
1512
- continue ;
1513
- }
1514
- add_input_file (file );
1521
+ add_input_file (argv [i ]);
1515
1522
if (!(opt & OPT_in_place )) {
1516
1523
continue ;
1517
1524
}
@@ -1523,7 +1530,7 @@ int sed_main(int argc UNUSED_PARAM, char **argv)
1523
1530
G .nonstdout = xfdopen_for_write (nonstdoutfd );
1524
1531
1525
1532
/* Set permissions/owner of output file */
1526
- fstat ( fileno ( file ) , & statbuf );
1533
+ stat ( argv [ i ] , & statbuf );
1527
1534
/* chmod'ing AFTER chown would preserve suid/sgid bits,
1528
1535
* but GNU sed 4.2.1 does not preserve them either */
1529
1536
fchmod (nonstdoutfd , statbuf .st_mode );
@@ -1549,12 +1556,13 @@ int sed_main(int argc UNUSED_PARAM, char **argv)
1549
1556
}
1550
1557
}
1551
1558
/* Here, to handle "sed 'cmds' nonexistent_file" case we did:
1552
- * if (G.current_input_file >= G.input_file_count )
1553
- * return status ;
1559
+ * if (G.current_input_file[G.current_input_file] == NULL )
1560
+ * return G.exitcode ;
1554
1561
* but it's not needed since process_files() works correctly
1555
1562
* in this case too. */
1556
1563
}
1564
+
1557
1565
process_files ();
1558
1566
1559
- return status ;
1567
+ return G . exitcode ;
1560
1568
}
0 commit comments