int sed_main(int argc, char **argv) { enum { OPT_in_place = 1 << 0, }; unsigned opt; llist_t *opt_e, *opt_f; int status = EXIT_SUCCESS; INIT_G(); /* destroy command strings on exit */ if (ENABLE_FEATURE_CLEAN_UP) atexit(sed_free_and_close_stuff); /* Lie to autoconf when it starts asking stupid questions. */ if (argc == 2 && !strcmp(argv[1], "--version")) { puts("This is not GNU sed version 4.0"); return 0; } /* do normal option parsing */ opt_e = opt_f = NULL; opt_complementary = "e::f::" /* can occur multiple times */ "nn"; /* count -n */ opt = getopt32(argv, "irne:f:", &opt_e, &opt_f, &G.be_quiet); /* counter for -n */ argc -= optind; argv += optind; if (opt & OPT_in_place) { // -i atexit(cleanup_outname); } if (opt & 0x2) G.regex_type |= REG_EXTENDED; // -r //if (opt & 0x4) G.be_quiet++; // -n while (opt_e) { // -e add_cmd_block(opt_e->data); opt_e = opt_e->link; /* we leak opt_e here... */ } while (opt_f) { // -f char *line; FILE *cmdfile; cmdfile = xfopen(opt_f->data, "r"); while ((line = xmalloc_getline(cmdfile)) != NULL) { add_cmd(line); free(line); } fclose(cmdfile); opt_f = opt_f->link; /* we leak opt_f here... */ } /* if we didn't get a pattern from -e or -f, use argv[0] */ if (!(opt & 0x18)) { if (!argc) bb_show_usage(); add_cmd_block(*argv++); argc--; } /* Flush any unfinished commands. */ add_cmd(""); /* By default, we write to stdout */ G.nonstdout = stdout; /* argv[0..(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[0] == NULL) { if (opt & OPT_in_place) bb_error_msg_and_die(bb_msg_requires_arg, "-i"); add_input_file(stdin); process_files(); } else { int i; FILE *file; for (i = 0; i < argc; i++) { struct stat statbuf; int nonstdoutfd; if (LONE_DASH(argv[i]) && !(opt & OPT_in_place)) { add_input_file(stdin); process_files(); continue; } file = fopen_or_warn(argv[i], "r"); if (!file) { status = EXIT_FAILURE; continue; } if (!(opt & OPT_in_place)) { add_input_file(file); continue; } G.outname = xasprintf("%sXXXXXX", argv[i]); nonstdoutfd = mkstemp(G.outname); if (-1 == nonstdoutfd) bb_perror_msg_and_die("cannot create temp file %s", G.outname); G.nonstdout = fdopen(nonstdoutfd, "w"); /* Set permissions of output file */ fstat(fileno(file), &statbuf); fchmod(nonstdoutfd, statbuf.st_mode); add_input_file(file); process_files(); fclose(G.nonstdout); G.nonstdout = stdout; /* unlink(argv[i]); */ // FIXME: error check / message? rename(G.outname, argv[i]); free(G.outname); G.outname = NULL; } if (G.input_file_count > G.current_input_file) process_files(); } return status; }
extern int sed_main(int argc, char **argv) { int opt, status = EXIT_SUCCESS; #ifdef CONFIG_FEATURE_CLEAN_UP /* destroy command strings on exit */ if (atexit(free_and_close_stuff) == -1) bb_perror_msg_and_die("atexit"); #endif #define LIE_TO_AUTOCONF #ifdef LIE_TO_AUTOCONF if(argc==2 && !strcmp(argv[1],"--version")) { printf("This is not GNU sed version 4.0\n"); exit(0); } #endif /* do normal option parsing */ while ((opt = getopt(argc, argv, "ne:f:")) > 0) { switch (opt) { case 'n': be_quiet++; break; case 'e': add_cmd_block(optarg); break; case 'f': { FILE *cmdfile; char *line; cmdfile = bb_xfopen(optarg, "r"); while ((line = bb_get_chomped_line_from_file(cmdfile)) != NULL) { add_cmd(line); free(line); } bb_xprint_and_close_file(cmdfile); break; } default: bb_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 (sed_cmd_head.next == NULL) { if (argv[optind] == NULL) bb_show_usage(); else add_cmd_block(argv[optind++]); } /* Flush any unfinished commands. */ add_cmd(""); /* 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) { process_file(stdin); } else { int i; FILE *file; for (i = optind; i < argc; i++) { if(!strcmp(argv[i], "-")) { process_file(stdin); } else { file = bb_wfopen(argv[i], "r"); if (file) { process_file(file); fclose(file); } else { status = EXIT_FAILURE; } } } } return status; }
int sed_main(int argc UNUSED_PARAM, char **argv) { unsigned opt; llist_t *opt_e, *opt_f; char *opt_i; #if ENABLE_LONG_OPTS static const char sed_longopts[] ALIGN1 = /* name has_arg short */ "in-place\0" Optional_argument "i" "regexp-extended\0" No_argument "r" "quiet\0" No_argument "n" "silent\0" No_argument "n" "expression\0" Required_argument "e" "file\0" Required_argument "f"; #endif int status = EXIT_SUCCESS; INIT_G(); /* destroy command strings on exit */ if (ENABLE_FEATURE_CLEAN_UP) atexit(sed_free_and_close_stuff); /* Lie to autoconf when it starts asking stupid questions. */ if (argv[1] && strcmp(argv[1], "--version") == 0) { puts("This is not GNU sed version 4.0"); return 0; } /* do normal option parsing */ opt_e = opt_f = NULL; opt_i = NULL; opt_complementary = "e::f::" /* can occur multiple times */ "nn"; /* count -n */ IF_LONG_OPTS(applet_long_options = sed_longopts); /* -i must be first, to match OPT_in_place definition */ /* -E is a synonym of -r: * GNU sed 4.2.1 mentions it in neither --help * nor manpage, but does recognize it. */ opt = getopt32(argv, "i::rEne:f:", &opt_i, &opt_e, &opt_f, &G.be_quiet); /* counter for -n */ //argc -= optind; argv += optind; if (opt & OPT_in_place) { // -i atexit(cleanup_outname); } if (opt & (2|4)) G.regex_type |= REG_EXTENDED; // -r or -E //if (opt & 8) // G.be_quiet++; // -n (implemented with a counter instead) while (opt_e) { // -e add_cmd_block(llist_pop(&opt_e)); } while (opt_f) { // -f char *line; FILE *cmdfile; cmdfile = xfopen_for_read(llist_pop(&opt_f)); while ((line = xmalloc_fgetline(cmdfile)) != NULL) { add_cmd(line); free(line); } fclose(cmdfile); } /* if we didn't get a pattern from -e or -f, use argv[0] */ if (!(opt & 0x30)) { if (!*argv) bb_show_usage(); add_cmd_block(*argv++); } /* Flush any unfinished commands. */ add_cmd(""); /* By default, we write to stdout */ G.nonstdout = stdout; /* argv[0..(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[0] == NULL) { if (opt & OPT_in_place) bb_error_msg_and_die(bb_msg_requires_arg, "-i"); add_input_file(stdin); } else { int i; for (i = 0; argv[i]; i++) { struct stat statbuf; int nonstdoutfd; FILE *file; sed_cmd_t *sed_cmd; if (LONE_DASH(argv[i]) && !(opt & OPT_in_place)) { add_input_file(stdin); process_files(); continue; } file = fopen_or_warn(argv[i], "r"); if (!file) { status = EXIT_FAILURE; continue; } add_input_file(file); if (!(opt & OPT_in_place)) { continue; } /* -i: process each FILE separately: */ G.outname = xasprintf("%sXXXXXX", argv[i]); nonstdoutfd = xmkstemp(G.outname); G.nonstdout = xfdopen_for_write(nonstdoutfd); /* Set permissions/owner of output file */ fstat(fileno(file), &statbuf); /* chmod'ing AFTER chown would preserve suid/sgid bits, * but GNU sed 4.2.1 does not preserve them either */ fchmod(nonstdoutfd, statbuf.st_mode); fchown(nonstdoutfd, statbuf.st_uid, statbuf.st_gid); process_files(); fclose(G.nonstdout); G.nonstdout = stdout; if (opt_i) { char *backupname = xasprintf("%s%s", argv[i], opt_i); xrename(argv[i], backupname); free(backupname); } /* else unlink(argv[i]); - rename below does this */ xrename(G.outname, argv[i]); //TODO: rollback backup on error? free(G.outname); G.outname = NULL; /* Re-enable disabled range matches */ for (sed_cmd = G.sed_cmd_head; sed_cmd; sed_cmd = sed_cmd->next) { sed_cmd->beg_line = sed_cmd->beg_line_orig; } } /* Here, to handle "sed 'cmds' nonexistent_file" case we did: * if (G.current_input_file >= G.input_file_count) * return status; * but it's not needed since process_files() works correctly * in this case too. */ } process_files(); return status; }