diff options
| author | Rob Landley <rob@landley.net> | 2004-02-18 09:54:15 +0000 |
|---|---|---|
| committer | Rob Landley <rob@landley.net> | 2004-02-18 09:54:15 +0000 |
| commit | 53302f80dae71c81377076992cf21128e6dff482 (patch) | |
| tree | c2a59ab147418738ff5a99f677bc0e8e4d1b25b5 | |
| parent | be8a6ae6ebc636d4f58d24a3d3b0c19f164952dd (diff) | |
| download | busybox-w32-53302f80dae71c81377076992cf21128e6dff482.tar.gz busybox-w32-53302f80dae71c81377076992cf21128e6dff482.tar.bz2 busybox-w32-53302f80dae71c81377076992cf21128e6dff482.zip | |
Add -i option to sed, to edit files in-place.
| -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 | } |
