diff options
-rw-r--r-- | editors/sed.c | 61 |
1 files changed, 54 insertions, 7 deletions
diff --git a/editors/sed.c b/editors/sed.c index 5832e99a9..a7c99a16b 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -111,7 +111,10 @@ typedef struct sed_cmd_s { | |||
111 | 111 | ||
112 | /* globals */ | 112 | /* globals */ |
113 | /* options */ | 113 | /* options */ |
114 | static int be_quiet = 0; | 114 | static int be_quiet = 0, in_place=0; |
115 | FILE *nonstdout; | ||
116 | char *outname; | ||
117 | |||
115 | 118 | ||
116 | static const char bad_format_in_subst[] = | 119 | static const char bad_format_in_subst[] = |
117 | "bad format in substitution expression"; | 120 | "bad format in substitution expression"; |
@@ -168,6 +171,13 @@ static void free_and_close_stuff(void) | |||
168 | } | 171 | } |
169 | #endif | 172 | #endif |
170 | 173 | ||
174 | /* If something bad happens during -i operation, delete temp file */ | ||
175 | |||
176 | static void cleanup_outname(void) | ||
177 | { | ||
178 | if(outname) unlink(outname); | ||
179 | } | ||
180 | |||
171 | /* strdup, replacing "\n" with '\n', and "\delimiter" with 'delimiter' */ | 181 | /* strdup, replacing "\n" with '\n', and "\delimiter" with 'delimiter' */ |
172 | 182 | ||
173 | static void parse_escapes(char *dest, const char *string, int len, char from, char to) | 183 | static void parse_escapes(char *dest, const char *string, int len, char from, char to) |
@@ -690,7 +700,7 @@ static void flush_append(void) | |||
690 | { | 700 | { |
691 | /* Output appended lines. */ | 701 | /* Output appended lines. */ |
692 | while(append_head) { | 702 | while(append_head) { |
693 | puts(append_head->string); | 703 | fprintf(nonstdout,"%s\n",append_head->string); |
694 | append_tail=append_head->next; | 704 | append_tail=append_head->next; |
695 | free(append_head->string); | 705 | free(append_head->string); |
696 | free(append_head); | 706 | free(append_head); |
@@ -728,12 +738,17 @@ static int puts_maybe_newline(char *s, FILE *file, int missing_newline, int no_n | |||
728 | fputs(s,file); | 738 | fputs(s,file); |
729 | if(!no_newline) fputc('\n',file); | 739 | if(!no_newline) fputc('\n',file); |
730 | 740 | ||
741 | if(ferror(file)) { | ||
742 | fprintf(stderr,"Write failed.\n"); | ||
743 | exit(4); /* It's what gnu sed exits with... */ | ||
744 | } | ||
745 | |||
731 | return no_newline; | 746 | return no_newline; |
732 | } | 747 | } |
733 | 748 | ||
734 | #define sed_puts(s,n) missing_newline=puts_maybe_newline(s,stdout,missing_newline,n) | 749 | #define sed_puts(s,n) missing_newline=puts_maybe_newline(s,nonstdout,missing_newline,n) |
735 | 750 | ||
736 | static void process_file(FILE * file) | 751 | static void process_file(FILE *file) |
737 | { | 752 | { |
738 | char *pattern_space, *next_line, *hold_space=NULL; | 753 | char *pattern_space, *next_line, *hold_space=NULL; |
739 | static int linenum = 0, missing_newline=0; | 754 | static int linenum = 0, missing_newline=0; |
@@ -819,7 +834,7 @@ restart: | |||
819 | 834 | ||
820 | /* Print line number */ | 835 | /* Print line number */ |
821 | case '=': | 836 | case '=': |
822 | printf("%d\n", linenum); | 837 | fprintf(nonstdout,"%d\n", linenum); |
823 | break; | 838 | break; |
824 | 839 | ||
825 | /* Write the current pattern space up to the first newline */ | 840 | /* Write the current pattern space up to the first newline */ |
@@ -1091,8 +1106,12 @@ extern int sed_main(int argc, char **argv) | |||
1091 | #endif | 1106 | #endif |
1092 | 1107 | ||
1093 | /* do normal option parsing */ | 1108 | /* do normal option parsing */ |
1094 | while ((opt = getopt(argc, argv, "ne:f:")) > 0) { | 1109 | while ((opt = getopt(argc, argv, "ine:f:")) > 0) { |
1095 | switch (opt) { | 1110 | switch (opt) { |
1111 | case 'i': | ||
1112 | in_place++; | ||
1113 | atexit(cleanup_outname); | ||
1114 | break; | ||
1096 | case 'n': | 1115 | case 'n': |
1097 | be_quiet++; | 1116 | be_quiet++; |
1098 | break; | 1117 | break; |
@@ -1131,23 +1150,51 @@ extern int sed_main(int argc, char **argv) | |||
1131 | /* Flush any unfinished commands. */ | 1150 | /* Flush any unfinished commands. */ |
1132 | add_cmd(""); | 1151 | add_cmd(""); |
1133 | 1152 | ||
1153 | /* By default, we write to stdout */ | ||
1154 | nonstdout=stdout; | ||
1155 | |||
1134 | /* argv[(optind)..(argc-1)] should be names of file to process. If no | 1156 | /* argv[(optind)..(argc-1)] should be names of file to process. If no |
1135 | * files were specified or '-' was specified, take input from stdin. | 1157 | * files were specified or '-' was specified, take input from stdin. |
1136 | * Otherwise, we process all the files specified. */ | 1158 | * Otherwise, we process all the files specified. */ |
1137 | if (argv[optind] == NULL) { | 1159 | if (argv[optind] == NULL) { |
1160 | if(in_place) { | ||
1161 | fprintf(stderr,"sed: Filename required for -i\n"); | ||
1162 | exit(1); | ||
1163 | } | ||
1138 | process_file(stdin); | 1164 | process_file(stdin); |
1139 | } else { | 1165 | } else { |
1140 | int i; | 1166 | int i; |
1141 | FILE *file; | 1167 | FILE *file; |
1142 | 1168 | ||
1143 | for (i = optind; i < argc; i++) { | 1169 | for (i = optind; i < argc; i++) { |
1144 | if(!strcmp(argv[i], "-")) { | 1170 | if(!strcmp(argv[i], "-") && !in_place) { |
1145 | process_file(stdin); | 1171 | process_file(stdin); |
1146 | } else { | 1172 | } else { |
1147 | file = bb_wfopen(argv[i], "r"); | 1173 | file = bb_wfopen(argv[i], "r"); |
1148 | if (file) { | 1174 | if (file) { |
1175 | if(in_place) { | ||
1176 | struct stat statbuf; | ||
1177 | outname=bb_xstrndup(argv[i],strlen(argv[i])+6); | ||
1178 | strcat(outname,"XXXXXX"); | ||
1179 | /* Set permissions of output file */ | ||
1180 | fstat(fileno(file),&statbuf); | ||
1181 | mkstemp(outname); | ||
1182 | nonstdout=bb_wfopen(outname,"w"); | ||
1183 | /* Set permissions of output file */ | ||
1184 | fstat(fileno(file),&statbuf); | ||
1185 | fchmod(fileno(file),statbuf.st_mode); | ||
1186 | atexit(cleanup_outname); | ||
1187 | } | ||
1149 | process_file(file); | 1188 | process_file(file); |
1150 | fclose(file); | 1189 | fclose(file); |
1190 | if(in_place) { | ||
1191 | fclose(nonstdout); | ||
1192 | nonstdout=stdout; | ||
1193 | unlink(argv[i]); | ||
1194 | rename(outname,argv[i]); | ||
1195 | free(outname); | ||
1196 | outname=0; | ||
1197 | } | ||
1151 | } else { | 1198 | } else { |
1152 | status = EXIT_FAILURE; | 1199 | status = EXIT_FAILURE; |
1153 | } | 1200 | } |