+ case 'i':
+ fputs(sed_cmd->editline, stdout);
+ break;
+
+ case 'c':
+ fputs(sed_cmd->editline, stdout);
+ altered++;
+ break;
+ }
+
+ return altered;
+}
+
+static void process_file(FILE *file)
+{
+ char *line = NULL;
+ static int linenum = 0; /* GNU sed does not restart counting lines at EOF */
+ unsigned int still_in_range = 0;
+ int line_altered;
+ int i;
+
+ /* go through every line in the file */
+ while ((line = get_line_from_file(file)) != NULL) {
+
+ linenum++;
+ line_altered = 0;
+
+ /* for every line, go through all the commands */
+ for (i = 0; i < ncmds; i++) {
+
+ /* are we acting on a range of matched lines? */
+ if (sed_cmds[i].beg_match && sed_cmds[i].end_match) {
+ if (still_in_range || regexec(sed_cmds[i].beg_match, line, 0, NULL, 0) == 0) {
+ line_altered += do_sed_command(&sed_cmds[i], line);
+ if (still_in_range && regexec(sed_cmds[i].end_match, line, 0, NULL, 0) == 0)
+ still_in_range = 0;
+ else
+ still_in_range = 1;
+ }
+ }
+
+ /* are we trying to match a single line? */
+ else if (sed_cmds[i].beg_match) {
+ if (regexec(sed_cmds[i].beg_match, line, 0, NULL, 0) == 0)
+ line_altered += do_sed_command(&sed_cmds[i], line);
+ }
+
+ /* are we acting on a range of line numbers? */
+ else if (sed_cmds[i].beg_line > 0 && sed_cmds[i].end_line != 0) {
+ if (linenum >= sed_cmds[i].beg_line &&
+ (sed_cmds[i].end_line == -1 || linenum <= sed_cmds[i].end_line))
+ line_altered += do_sed_command(&sed_cmds[i], line);
+ }
+
+ /* are we acting on a specified line number */
+ else if (sed_cmds[i].beg_line > 0) {
+ if (linenum == sed_cmds[i].beg_line)
+ line_altered += do_sed_command(&sed_cmds[i], line);
+ }
+
+ /* not acting on matches or line numbers. act on every line */
+ else
+ line_altered += do_sed_command(&sed_cmds[i], line);
+
+ }
+
+ /* we will print the line unless we were told to be quiet or if the
+ * line was altered (via a 'd'elete or 's'ubstitution), in which case
+ * the altered line was already printed */
+ if (!be_quiet && !line_altered)
+ fputs(line, stdout);
+
+ free(line);
+ }
+}
+
+extern int sed_main(int argc, char **argv)
+{
+ int opt;
+
+#ifdef BB_FEATURE_CLEAN_UP
+ /* destroy command strings on exit */
+ if (atexit(destroy_cmd_strs) == -1)
+ perror_msg_and_die("atexit");
+#endif
+
+ /* do normal option parsing */
+ while ((opt = getopt(argc, argv, "ne:f:")) > 0) {
+ switch (opt) {
+ case 'n':
+ be_quiet++;
+ break;
+ case 'e':
+ add_cmd_str(optarg);
+ break;
+ case 'f':
+ load_cmd_file(optarg);
+ break;
+ default:
+ show_usage();
+ }
+ }
+
+ /* if we didn't get a pattern from a -e and no command file was specified,
+ * argv[optind] should be the pattern. no pattern, no worky */
+ if (ncmds == 0) {
+ if (argv[optind] == NULL)
+ show_usage();
+ else {
+ add_cmd_str(argv[optind]);
+ optind++;
+ }
+ }
+
+
+ /* argv[(optind)..(argc-1)] should be names of file to process. If no
+ * files were specified or '-' was specified, take input from stdin.
+ * Otherwise, we process all the files specified. */
+ if (argv[optind] == NULL || (strcmp(argv[optind], "-") == 0)) {
+ process_file(stdin);
+ }
+ else {
+ int i;
+ FILE *file;
+ for (i = optind; i < argc; i++) {
+ file = fopen(argv[i], "r");
+ if (file == NULL) {
+ perror_msg("%s", argv[i]);
+ } else {
+ process_file(file);
+ fclose(file);
+ }
+ }
+ }
+
+ return 0;
+}