aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--editors/sed.c61
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 */
114static int be_quiet = 0; 114static int be_quiet = 0, in_place=0;
115FILE *nonstdout;
116char *outname;
117
115 118
116static const char bad_format_in_subst[] = 119static 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
176static 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
173static void parse_escapes(char *dest, const char *string, int len, char from, char to) 183static 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
736static void process_file(FILE * file) 751static 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 }