[BusyBox] Sed -i support.
Rob Landley
rob at landley.net
Tue Feb 17 10:04:20 UTC 2004
Well, there's bound to be something wrong with it since it debugged way
too easy, but here's the patch adding -i support to sed.
Notice that -i is a global option, applying to every file listed even if
there are more than one.
Bugs in gnu sed's -i option:
If you fill up the disk, the temp file isn't deleted.
Differences between gnu sed -i and busybox sed -i:
"sed -i -" creates an empty - file.
"busybox sed -i -" complains "-: no such file or directory"
I know I should use a better error message function on line 1161,
but I don't know what it is.
Rob
--- busybox/editors/sed.c 2004-02-04 04:57:46.000000000 -0600
+++ busybox.sed/editors/sed.c 2004-02-17 03:53:54.616241168 -0600
@@ -111,7 +111,10 @@
/* globals */
/* options */
-static int be_quiet = 0;
+static int be_quiet = 0, in_place=0;
+FILE *nonstdout;
+char *outname;
+
static const char bad_format_in_subst[] =
"bad format in substitution expression";
@@ -168,6 +171,13 @@
}
#endif
+/* If something bad happens during -i operation, delete temp file */
+
+static void cleanup_outname(void)
+{
+ if(outname) unlink(outname);
+}
+
/* strdup, replacing "\n" with '\n', and "\delimiter" with 'delimiter' */
static void parse_escapes(char *dest, const char *string, int len, char from, char to)
@@ -690,7 +700,7 @@
{
/* Output appended lines. */
while(append_head) {
- puts(append_head->string);
+ fprintf(nonstdout,"%s\n",append_head->string);
append_tail=append_head->next;
free(append_head->string);
free(append_head);
@@ -728,12 +738,17 @@
fputs(s,file);
if(!no_newline) fputc('\n',file);
+ if(ferror(file)) {
+ fprintf(stderr,"Write failed.\n");
+ exit(4); /* It's what gnu sed exits with... */
+ }
+
return no_newline;
}
-#define sed_puts(s,n) missing_newline=puts_maybe_newline(s,stdout,missing_newline,n)
+#define sed_puts(s,n) missing_newline=puts_maybe_newline(s,nonstdout,missing_newline,n)
-static void process_file(FILE * file)
+static void process_file(FILE *file)
{
char *pattern_space, *next_line, *hold_space=NULL;
static int linenum = 0, missing_newline=0;
@@ -819,7 +834,7 @@
/* Print line number */
case '=':
- printf("%d\n", linenum);
+ fprintf(nonstdout,"%d\n", linenum);
break;
/* Write the current pattern space up to the first newline */
@@ -1091,8 +1106,12 @@
#endif
/* do normal option parsing */
- while ((opt = getopt(argc, argv, "ne:f:")) > 0) {
+ while ((opt = getopt(argc, argv, "ine:f:")) > 0) {
switch (opt) {
+ case 'i':
+ in_place++;
+ atexit(cleanup_outname);
+ break;
case 'n':
be_quiet++;
break;
@@ -1131,23 +1150,51 @@
/* Flush any unfinished commands. */
add_cmd("");
+ /* By default, we write to stdout */
+ nonstdout=stdout;
+
/* 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) {
+ if(in_place) {
+ fprintf(stderr,"sed: Filename required for -i\n");
+ exit(1);
+ }
process_file(stdin);
} else {
int i;
FILE *file;
for (i = optind; i < argc; i++) {
- if(!strcmp(argv[i], "-")) {
+ if(!strcmp(argv[i], "-") && !in_place) {
process_file(stdin);
} else {
file = bb_wfopen(argv[i], "r");
if (file) {
+ if(in_place) {
+ struct stat statbuf;
+ outname=bb_xstrndup(argv[i],strlen(argv[i])+6);
+ strcat(outname,"XXXXXX");
+ /* Set permissions of output file */
+ fstat(fileno(file),&statbuf);
+ mkstemp(outname);
+ nonstdout=bb_wfopen(outname,"w");
+ /* Set permissions of output file */
+ fstat(fileno(file),&statbuf);
+ fchmod(fileno(file),statbuf.st_mode);
+ atexit(cleanup_outname);
+ }
process_file(file);
fclose(file);
+ if(in_place) {
+ fclose(nonstdout);
+ nonstdout=stdout;
+ unlink(argv[i]);
+ rename(outname,argv[i]);
+ free(outname);
+ outname=0;
+ }
} else {
status = EXIT_FAILURE;
}
More information about the busybox
mailing list