On Fri, Jul 17, 2015 at 12:57:12PM -0400, Brian Callahan wrote:
> 
> 
> On 07/17/15 12:10, Jasper Lievisse Adriaanse wrote:
> > Hi,
> > 
> > Here's a diff to add the '-i' flag to sed to do inplace edits. It's mostly
> > from FreeBSD with some adjustments to prevent a race with unlink() and 
> > fopen()
> > during the tempfile creation.
> > 
> > It's been tested in a full ports bulk (thanks aja), and went through a build
> > of base and xenocara.
> > Regress tests will also be added for this.
> > 
> > This diff is already OK millert@. Any more OKs?
> > 
> 
> Cool. This saves me having to install coreutils just to work on some
> school projects.

You mean gsed right?


> ok bcallah@, fwiw.
> 
> > Index: defs.h
> > ===================================================================
> > RCS file: /cvs/src/usr.bin/sed/defs.h,v
> > retrieving revision 1.5
> > diff -u -p -r1.5 defs.h
> > --- defs.h  19 Jan 2015 15:30:52 -0000      1.5
> > +++ defs.h  16 Jul 2015 18:45:58 -0000
> > @@ -128,6 +128,7 @@ typedef struct {
> >     char *space;            /* Current space pointer. */
> >     size_t len;             /* Current length. */
> >     int deleted;            /* If deleted. */
> > +   int append_newline;     /* If originally terminated by \n. */
> >     char *back;             /* Backing memory. */
> >     size_t blen;            /* Backing memory length. */
> >  } SPACE;
> > Index: extern.h
> > ===================================================================
> > RCS file: /cvs/src/usr.bin/sed/extern.h,v
> > retrieving revision 1.9
> > diff -u -p -r1.9 extern.h
> > --- extern.h        13 Apr 2015 05:11:23 -0000      1.9
> > +++ extern.h        16 Jul 2015 00:23:57 -0000
> > @@ -40,17 +40,19 @@ extern regmatch_t *match;
> >  extern size_t maxnsub;
> >  extern u_long linenum;
> >  extern size_t appendnum;
> > -extern int lastline;
> >  extern int Eflag, aflag, eflag, nflag;
> > -extern char *fname;
> > +extern const char *fname, *outfname;
> > +extern FILE *infile, *outfile;
> >  
> >  void        cfclose(struct s_command *, struct s_command *);
> >  void        compile(void);
> > -void        cspace(SPACE *, char *, size_t, enum e_spflag);
> > +void        cspace(SPACE *, const char *, size_t, enum e_spflag);
> >  char       *cu_fgets(char **, size_t *);
> >  void        err(int, const char *, ...);
> >  int         mf_fgets(SPACE *, enum e_spflag);
> > +int         lastline(void);
> >  void        process(void);
> > +void        resetranges(void);
> >  char       *strregerror(int, regex_t *);
> >  void       *xmalloc(size_t);
> >  void       *xreallocarray(void *, size_t, size_t);
> > Index: main.c
> > ===================================================================
> > RCS file: /cvs/src/usr.bin/sed/main.c,v
> > retrieving revision 1.18
> > diff -u -p -r1.18 main.c
> > --- main.c  26 Nov 2014 18:34:51 -0000      1.18
> > +++ main.c  16 Jul 2015 19:21:16 -0000
> > @@ -34,6 +34,7 @@
> >   */
> >  
> >  #include <sys/types.h>
> > +#include <sys/stat.h>
> >  
> >  #include <ctype.h>
> >  #include <errno.h>
> > @@ -45,6 +46,7 @@
> >  #include <stdlib.h>
> >  #include <string.h>
> >  #include <unistd.h>
> > +#include <libgen.h>
> >  
> >  #include "defs.h"
> >  #include "extern.h"
> > @@ -78,15 +80,23 @@ struct s_flist {
> >   */
> >  static struct s_flist *files, **fl_nextp = &files;
> >  
> > +FILE *infile;                      /* Current input file */
> > +FILE *outfile;                     /* Current output file */
> > +
> >  int Eflag, aflag, eflag, nflag;
> > +static int rval;   /* Exit status */
> >  
> >  /*
> >   * Current file and line number; line numbers restart across compilation
> > - * units, but span across input files.
> > + * units, but span across input files.  The latter is optional if editing
> > + * in place.
> >   */
> > -char *fname;                       /* File name. */
> > +const char *fname;         /* File name. */
> > +const char *outfname;              /* Output file name */
> > +static char oldfname[PATH_MAX];    /* Old file name (for in-place editing) 
> > */
> > +static char tmpfname[PATH_MAX];    /* Temporary file name (for in-place 
> > editing) */
> > +char *inplace;                     /* Inplace edit file extension */
> >  u_long linenum;
> > -int lastline;                      /* TRUE on the last line of the last 
> > file */
> >  
> >  static void add_compunit(enum e_cut, char *);
> >  static void add_file(char *);
> > @@ -97,7 +107,8 @@ main(int argc, char *argv[])
> >     int c, fflag;
> >  
> >     fflag = 0;
> > -   while ((c = getopt(argc, argv, "Eae:f:nru")) != -1)
> > +   inplace = NULL;
> > +   while ((c = getopt(argc, argv, "Eae:f:i::nru")) != -1)
> >             switch (c) {
> >             case 'E':
> >             case 'r':
> > @@ -114,6 +125,9 @@ main(int argc, char *argv[])
> >                     fflag = 1;
> >                     add_compunit(CU_FILE, optarg);
> >                     break;
> > +           case 'i':
> > +                   inplace = optarg ? optarg : "";
> > +                   break;
> >             case 'n':
> >                     nflag = 1;
> >                     break;
> > @@ -123,8 +137,8 @@ main(int argc, char *argv[])
> >             default:
> >             case '?':
> >                     (void)fprintf(stderr,
> > -                       "usage: sed [-aEnru] command [file ...]\n"
> > -                       "       sed [-aEnru] [-e command] [-f command_file] 
> > [file ...]\n");
> > +                       "usage: sed [-aEnru] [-i [extension]] command [file 
> > ...]\n"
> > +                       "       sed [-aEnru] [-i [extension]] [-e command] 
> > [-f command_file] [file ...]\n");
> >                     exit(1);
> >             }
> >     argc -= optind;
> > @@ -148,7 +162,7 @@ main(int argc, char *argv[])
> >     cfclose(prog, NULL);
> >     if (fclose(stdout))
> >             err(FATAL, "stdout: %s", strerror(errno));
> > -   exit (0);
> > +   exit (rval);
> >  }
> >  
> >  /*
> > @@ -258,69 +272,128 @@ again:
> >  int
> >  mf_fgets(SPACE *sp, enum e_spflag spflag)
> >  {
> > -   static FILE *f;         /* Current open file */
> > +   struct stat sb;
> >     size_t len;
> >     char *p;
> > -   int c;
> > +   int c, fd;
> > +   static int firstfile;
> >  
> > -   if (f == NULL)
> > -           /* Advance to first non-empty file */
> > -           for (;;) {
> > -                   if (files == NULL) {
> > -                           lastline = 1;
> > -                           return (0);
> > -                   }
> > -                   if (files->fname == NULL) {
> > -                           f = stdin;
> > -                           fname = "stdin";
> > -                   } else {
> > -                           fname = files->fname;
> > -                           if ((f = fopen(fname, "r")) == NULL)
> > -                                   err(FATAL, "%s: %s",
> > -                                       fname, strerror(errno));
> > +   if (infile == NULL) {
> > +           /* stdin? */
> > +           if (files->fname == NULL) {
> > +                   if (inplace != NULL)
> > +                           err(FATAL, "-i may not be used with stdin");
> > +                   infile = stdin;
> > +                   fname = "stdin";
> > +                   outfile = stdout;
> > +                   outfname = "stdout";
> > +           }
> > +
> > +           firstfile = 1;
> > +   }
> > +
> > +   for (;;) {
> > +           if (infile != NULL && (c = getc(infile)) != EOF) {
> > +                   (void)ungetc(c, infile);
> > +                   break;
> > +           }
> > +           /* If we are here then either eof or no files are open yet */
> > +           if (infile == stdin) {
> > +                   sp->len = 0;
> > +                   return (0);
> > +           }
> > +           if (infile != NULL) {
> > +                   fclose(infile);
> > +                   if (*oldfname != '\0') {
> > +                           if (rename(fname, oldfname) != 0) {
> > +                                   err(WARNING, "rename()");
> > +                                   unlink(tmpfname);
> > +                                   exit(1);
> > +                           }
> > +                           *oldfname = '\0';
> >                     }
> > -                   if ((c = getc(f)) != EOF) {
> > -                           (void)ungetc(c, f);
> > -                           break;
> > +                   if (*tmpfname != '\0') {
> > +                           if (outfile != NULL && outfile != stdout)
> > +                                   fclose(outfile);
> > +                           outfile = NULL;
> > +                           rename(tmpfname, fname);
> > +                           *tmpfname = '\0';
> >                     }
> > -                   (void)fclose(f);
> > +                   outfname = NULL;
> > +           }
> > +           if (firstfile == 0)
> >                     files = files->next;
> > +           else
> > +                   firstfile = 0;
> > +           if (files == NULL) {
> > +                   sp->len = 0;
> > +                   return (0);
> > +           }
> > +           fname = files->fname;
> > +           if (inplace != NULL) {
> > +                   if (lstat(fname, &sb) != 0)
> > +                           err(1, "%s", fname);
> > +                   if (!S_ISREG(sb.st_mode))
> > +                           err(FATAL, "%s: %s %s", fname,
> > +                               "in-place editing only",
> > +                               "works for regular files");
> > +                   if (*inplace != '\0') {
> > +                           strlcpy(oldfname, fname,
> > +                               sizeof(oldfname));
> > +                           len = strlcat(oldfname, inplace,
> > +                               sizeof(oldfname));
> > +                           if (len > sizeof(oldfname))
> > +                                   err(FATAL, "%s: name too long", fname);
> > +                   }
> > +                   len = snprintf(tmpfname, sizeof(tmpfname), 
> > "%s/.%s.XXXXXXXXXX",
> > +                       dirname(fname), basename(fname));
> > +                   if (len >= sizeof(tmpfname))
> > +                           err(FATAL, "%s: name too long", fname);
> > +                   if ((fd = mkstemp(tmpfname)) == -1)
> > +                           err(FATAL, "%s", fname);
> > +                   if ((outfile = fdopen(fd, "w")) == NULL) {
> > +                           unlink(tmpfname);
> > +                           err(FATAL, "%s", fname);
> > +                   }
> > +                   fchown(fileno(outfile), sb.st_uid, sb.st_gid);
> > +                   fchmod(fileno(outfile), sb.st_mode & ALLPERMS);
> > +                   outfname = tmpfname;
> > +                   linenum = 0;
> > +                   resetranges();
> > +           } else {
> > +                   outfile = stdout;
> > +                   outfname = "stdout";
> > +           }
> > +           if ((infile = fopen(fname, "r")) == NULL) {
> > +                   err(WARNING, "%s", fname);
> > +                   rval = 1;
> > +                   continue;
> >             }
> > -
> > -   if (lastline) {
> > -           sp->len = 0;
> > -           return (0);
> >     }
> >  
> >     /*
> > +    * We are here only when infile is open and we still have something
> > +    * to read from it.
> > +    *
> >      * Use fgetln so that we can handle essentially infinite input data.
> >      * Can't use the pointer into the stdio buffer as the process space
> >      * because the ungetc() can cause it to move.
> >      */
> > -   p = fgetln(f, &len);
> > -   if (ferror(f))
> > +   p = fgetln(infile, &len);
> > +   if (ferror(infile))
> >             err(FATAL, "%s: %s", fname, strerror(errno ? errno : EIO));
> > +   if (len != 0 && p[len - 1] == '\n') {
> > +           sp->append_newline = 1;
> > +           len--;
> > +   } else if (!lastline()) {
> > +           sp->append_newline = 1;
> > +   } else {
> > +           sp->append_newline = 0;
> > +   }
> >     cspace(sp, p, len, spflag);
> >  
> >     linenum++;
> > -   /* Advance to next non-empty file */
> > -   while ((c = getc(f)) == EOF) {
> > -           (void)fclose(f);
> > -           files = files->next;
> > -           if (files == NULL) {
> > -                   lastline = 1;
> > -                   return (1);
> > -           }
> > -           if (files->fname == NULL) {
> > -                   f = stdin;
> > -                   fname = "stdin";
> > -           } else {
> > -                   fname = files->fname;
> > -                   if ((f = fopen(fname, "r")) == NULL)
> > -                           err(FATAL, "%s: %s", fname, strerror(errno));
> > -           }
> > -   }
> > -   (void)ungetc(c, f);
> > +
> >     return (1);
> >  }
> >  
> > @@ -353,4 +426,52 @@ add_file(char *s)
> >     *fl_nextp = fp;
> >     fp->fname = s;
> >     fl_nextp = &fp->next;
> > +}
> > +
> > +
> > +static int
> > +next_files_have_lines()
> > +{
> > +       struct s_flist *file;
> > +       FILE *file_fd;
> > +       int ch;
> > +
> > +       file = files;
> > +       while ((file = file->next) != NULL) {
> > +          if ((file_fd = fopen(file->fname, "r")) == NULL)
> > +                  continue;
> > +
> > +          if ((ch = getc(file_fd)) != EOF) {
> > +                  /*
> > +                   * This next file has content, therefore current
> > +                   * file doesn't contains the last line.
> > +                   */
> > +                  ungetc(ch, file_fd);
> > +                  fclose(file_fd);
> > +                  return (1);
> > +          }
> > +
> > +          fclose(file_fd);
> > +       }
> > +
> > +       return (0);
> > +}
> > +
> > +int
> > +lastline(void)
> > +{
> > +   int ch;
> > +
> > +   if (feof(infile)) {
> > +           return !(
> > +               (inplace == NULL) &&
> > +               next_files_have_lines());
> > +   }
> > +   if ((ch = getc(infile)) == EOF) {
> > +           return !(
> > +               (inplace == NULL) &&
> > +               next_files_have_lines());
> > +   }
> > +   ungetc(ch, infile);
> > +   return (0);
> >  }
> > Index: process.c
> > ===================================================================
> > RCS file: /cvs/src/usr.bin/sed/process.c,v
> > retrieving revision 1.23
> > diff -u -p -r1.23 process.c
> > --- process.c       18 Apr 2015 18:28:37 -0000      1.23
> > +++ process.c       16 Jul 2015 18:50:40 -0000
> > @@ -55,6 +55,7 @@ static SPACE HS, PS, SS;
> >  #define    pd              PS.deleted
> >  #define    ps              PS.space
> >  #define    psl             PS.len
> > +#define    psanl           PS.append_newline
> >  #define    hs              HS.space
> >  #define    hsl             HS.len
> >  
> > @@ -76,7 +77,10 @@ static regex_t *defpreg;
> >  size_t maxnsub;
> >  regmatch_t *match;
> >  
> > -#define OUT(s) do { fwrite(s, sizeof(u_char), psl, stdout); } while (0)
> > +#define OUT() do {\
> > +   fwrite(ps, 1, psl, outfile);\
> > +   if (psanl) fputc('\n', outfile);\
> > +} while (0)
> >  
> >  void
> >  process(void)
> > @@ -85,6 +89,7 @@ process(void)
> >     SPACE tspace;
> >     size_t len, oldpsl;
> >     char *p;
> > +   int oldpsanl;
> >  
> >     for (linenum = 0; mf_fgets(&PS, REPLACE);) {
> >             pd = 0;
> > @@ -118,8 +123,8 @@ redirect:
> >                     case 'c':
> >                             pd = 1;
> >                             psl = 0;
> > -                           if (cp->a2 == NULL || lastaddr)
> > -                                   (void)printf("%s", cp->t);
> > +                           if (cp->a2 == NULL || lastaddr || lastline())
> > +                                   (void)fprintf(outfile, "%s", cp->t);
> >                             break;
> >                     case 'd':
> >                             pd = 1;
> > @@ -128,7 +133,7 @@ redirect:
> >                             if (pd)
> >                                     goto new;
> >                             if (psl == 0 ||
> > -                               (p = memchr(ps, '\n', psl - 1)) == NULL) {
> > +                               (p = memchr(ps, '\n', psl)) == NULL) {
> >                                     pd = 1;
> >                                     goto new;
> >                             } else {
> > @@ -140,25 +145,25 @@ redirect:
> >                             cspace(&PS, hs, hsl, REPLACE);
> >                             break;
> >                     case 'G':
> > -                           if (hs == NULL)
> > -                                   cspace(&HS, "\n", 1, REPLACE);
> > +                           cspace(&PS, "\n", 1, 0);
> >                             cspace(&PS, hs, hsl, 0);
> >                             break;
> >                     case 'h':
> >                             cspace(&HS, ps, psl, REPLACE);
> >                             break;
> >                     case 'H':
> > +                           cspace(&HS, "\n", 1, 0);
> >                             cspace(&HS, ps, psl, 0);
> >                             break;
> >                     case 'i':
> > -                           (void)printf("%s", cp->t);
> > +                           (void)fprintf(outfile, "%s", cp->t);
> >                             break;
> >                     case 'l':
> >                             lputs(ps);
> >                             break;
> >                     case 'n':
> >                             if (!nflag && !pd)
> > -                                   OUT(ps);
> > +                                   OUT();
> >                             flush_appends();
> >                             if (!mf_fgets(&PS, REPLACE))
> >                                     exit(0);
> > @@ -166,33 +171,32 @@ redirect:
> >                             break;
> >                     case 'N':
> >                             flush_appends();
> > -                           if (!mf_fgets(&PS, 0)) {
> > -                                   if (!nflag && !pd)
> > -                                           OUT(ps);
> > +                           cspace(&PS, "\n", 1, 0);
> > +                           if (!mf_fgets(&PS, 0))
> >                                     exit(0);
> > -                           }
> >                             break;
> >                     case 'p':
> >                             if (pd)
> >                                     break;
> > -                           OUT(ps);
> > +                           OUT();
> >                             break;
> >                     case 'P':
> >                             if (pd)
> >                                     break;
> > -                           if (psl != 0 &&
> > -                               (p = memchr(ps, '\n', psl - 1)) != NULL) {
> > +                           if ((p = memchr(ps, '\n', psl)) != NULL) {
> >                                     oldpsl = psl;
> > -                                   psl = (p + 1) - ps;
> > -                                   OUT(ps);
> > +                                   oldpsanl = psanl;
> > +                                   psl = p - ps;
> > +                                   psanl = 1;
> > +                                   OUT();
> >                                     psl = oldpsl;
> >                             } else {
> > -                                   OUT(ps);
> > +                                   OUT();
> >                             }
> >                             break;
> >                     case 'q':
> >                             if (!nflag && !pd)
> > -                                   OUT(ps);
> > +                                   OUT();
> >                             flush_appends();
> >                             exit(0);
> >                     case 'r':
> > @@ -225,34 +229,36 @@ redirect:
> >                                 DEFFILEMODE)) == -1)
> >                                     err(FATAL, "%s: %s",
> >                                         cp->t, strerror(errno));
> > -                           if (write(cp->u.fd, ps, psl) != psl)
> > +                           if (write(cp->u.fd, ps, psl) != psl ||
> > +                               write(cp->u.fd, "\n", 1) != 1)
> >                                     err(FATAL, "%s: %s",
> >                                         cp->t, strerror(errno));
> >                             break;
> >                     case 'x':
> >                             if (hs == NULL)
> > -                                   cspace(&HS, "\n", 1, REPLACE);
> > +                                   cspace(&HS, "", 0, REPLACE);
> >                             tspace = PS;
> >                             PS = HS;
> > +                           psanl = tspace.append_newline;
> >                             HS = tspace;
> >                             break;
> >                     case 'y':
> >                             if (pd || psl == 0)
> >                                     break;
> > -                           for (p = ps, len = psl; --len; ++p)
> > +                           for (p = ps, len = psl; len--; ++p)
> >                                     *p = cp->u.y[(unsigned char)*p];
> >                             break;
> >                     case ':':
> >                     case '}':
> >                             break;
> >                     case '=':
> > -                           (void)printf("%lu\n", linenum);
> > +                           (void)fprintf(outfile, "%lu\n", linenum);
> >                     }
> >                     cp = cp->next;
> >             } /* for all cp */
> >  
> >  new:               if (!nflag && !pd)
> > -                   OUT(ps);
> > +                   OUT();
> >             flush_appends();
> >     } /* for all lines */
> >  }
> > @@ -263,7 +269,7 @@ new:            if (!nflag && !pd)
> >   */
> >  #define    MATCH(a)                                                \
> >     (a)->type == AT_RE ? regexec_e((a)->u.r, ps, 0, 1, psl) :       \
> > -       (a)->type == AT_LINE ? linenum == (a)->u.l : lastline
> > +       (a)->type == AT_LINE ? linenum == (a)->u.l : lastline()
> >  
> >  /*
> >   * Return TRUE if the command applies to the current line.  Sets the 
> > inrange
> > @@ -305,6 +311,19 @@ applies(struct s_command *cp)
> >  }
> >  
> >  /*
> > + * Reset all inrange markers.
> > + */
> > +void
> > +resetranges(void)
> > +{
> > +   struct s_command *cp;
> > +
> > +   for (cp = prog; cp; cp = cp->code == '{' ? cp->u.c : cp->next)
> > +           if (cp->a2)
> > +                   cp->inrange = 0;
> > +}
> > +
> > +/*
> >   * substitute --
> >   * Do substitutions in the pattern space.  Currently, we build a
> >   * copy of the new pattern space in the substitute space structure
> > @@ -392,19 +411,21 @@ substitute(struct s_command *cp)
> >      */
> >     tspace = PS;
> >     PS = SS;
> > +   psanl = tspace.append_newline;
> >     SS = tspace;
> >     SS.space = SS.back;
> >  
> >     /* Handle the 'p' flag. */
> >     if (cp->u.s->p)
> > -           OUT(ps);
> > +           OUT();
> >  
> >     /* Handle the 'w' flag. */
> >     if (cp->u.s->wfile && !pd) {
> >             if (cp->u.s->wfd == -1 && (cp->u.s->wfd = open(cp->u.s->wfile,
> >                 O_WRONLY|O_APPEND|O_CREAT|O_TRUNC, DEFFILEMODE)) == -1)
> >                     err(FATAL, "%s: %s", cp->u.s->wfile, strerror(errno));
> > -           if (write(cp->u.s->wfd, ps, psl) != psl)
> > +           if (write(cp->u.s->wfd, ps, psl) != psl ||
> > +               write(cp->u.s->wfd, "\n", 1) != 1)
> >                     err(FATAL, "%s: %s", cp->u.s->wfile, strerror(errno));
> >     }
> >     return (1);
> > @@ -425,7 +446,7 @@ flush_appends(void)
> >             switch (appends[i].type) {
> >             case AP_STRING:
> >                     fwrite(appends[i].s, sizeof(char), appends[i].len, 
> > -                       stdout);
> > +                       outfile);
> >                     break;
> >             case AP_FILE:
> >                     /*
> > @@ -439,12 +460,12 @@ flush_appends(void)
> >                     if ((f = fopen(appends[i].s, "r")) == NULL)
> >                             break;
> >                     while ((count = fread(buf, sizeof(char), sizeof(buf), 
> > f)))
> > -                           (void)fwrite(buf, sizeof(char), count, stdout);
> > +                           (void)fwrite(buf, sizeof(char), count, outfile);
> >                     (void)fclose(f);
> >                     break;
> >             }
> > -   if (ferror(stdout))
> > -           err(FATAL, "stdout: %s", strerror(errno ? errno : EIO));
> > +   if (ferror(outfile))
> > +           err(FATAL, "%s: %s", outfname, strerror(errno ? errno : EIO));
> >     appendx = sdone = 0;
> >  }
> >  
> > @@ -452,10 +473,14 @@ static void
> >  lputs(char *s)
> >  {
> >     int count;
> > -   char *escapes, *p;
> > +   const char *escapes;
> > +   char *p;
> >     struct winsize win;
> >     static int termwidth = -1;
> >  
> > +   if (outfile != stdout)
> > +           termwidth = 60;
> > +
> >     if (termwidth == -1) {
> >             termwidth = 0;
> >             if ((p = getenv("COLUMNS")))
> > @@ -470,29 +495,33 @@ lputs(char *s)
> >  
> >     for (count = 0; *s; ++s) { 
> >             if (count >= termwidth) {
> > -                   (void)printf("\\\n");
> > +                   (void)fprintf(outfile, "\\\n");
> >                     count = 0;
> >             }
> >             if (isascii((unsigned char)*s) && isprint((unsigned char)*s)
> >                 && *s != '\\') {
> > -                   (void)putchar(*s);
> > +                   (void)fputc(*s, outfile);
> >                     count++;
> > -           } else if (*s != '\n') {
> > +           } else if (*s == '\n') {
> > +                   (void)fputc('$', outfile);
> > +                   (void)fputc('\n', outfile);
> > +                   count = 0;
> > +           } else {
> >                     escapes = "\\\a\b\f\r\t\v";
> > -                   (void)putchar('\\');
> > +                   (void)fputc('\\', outfile);
> >                     if ((p = strchr(escapes, *s))) {
> > -                           (void)putchar("\\abfrtv"[p - escapes]);
> > +                           (void)fputc("\\abfrtv"[p - escapes], outfile);
> >                             count += 2;
> >                     } else {
> > -                           (void)printf("%03o", *(u_char *)s);
> > +                           (void)fprintf(outfile, "%03o", *(u_char *)s);
> >                             count += 4;
> >                     }
> >             }
> >     }
> > -   (void)putchar('$');
> > -   (void)putchar('\n');
> > -   if (ferror(stdout))
> > -           err(FATAL, "stdout: %s", strerror(errno ? errno : EIO));
> > +   (void)fputc('$', outfile);
> > +   (void)fputc('\n', outfile);
> > +   if (ferror(outfile))
> > +           err(FATAL, "%s: %s", outfname, strerror(errno ? errno : EIO));
> >  }
> >  
> >  static inline int
> > @@ -507,9 +536,7 @@ regexec_e(regex_t *preg, const char *str
> >     } else
> >             defpreg = preg;
> >  
> > -   /* Set anchors, discounting trailing newline (if any). */
> > -   if (slen > 0 && string[slen - 1] == '\n')
> > -           slen--;
> > +   /* Set anchors */
> >     match[0].rm_so = 0;
> >     match[0].rm_eo = slen;
> >     
> > @@ -575,7 +602,7 @@ regsub(SPACE *sp, char *string, char *sr
> >   * space as necessary.
> >   */
> >  void
> > -cspace(SPACE *sp, char *p, size_t len, enum e_spflag spflag)
> > +cspace(SPACE *sp, const char *p, size_t len, enum e_spflag spflag)
> >  {
> >     size_t tlen;
> >  
> > Index: sed.1
> > ===================================================================
> > RCS file: /cvs/src/usr.bin/sed/sed.1,v
> > retrieving revision 1.44
> > diff -u -p -r1.44 sed.1
> > --- sed.1   22 Oct 2014 23:23:22 -0000      1.44
> > +++ sed.1   16 Jul 2015 19:15:14 -0000
> > @@ -47,6 +47,7 @@
> >  .Op Fl aEnru
> >  .Op Fl e Ar command
> >  .Op Fl f Ar command_file
> > +.Op Fl i Op Ar extension
> >  .Op Ar
> >  .Sh DESCRIPTION
> >  The
> > @@ -94,6 +95,16 @@ Append the editing commands found in the
> >  .Ar command_file
> >  to the list of commands.
> >  The editing commands should each be listed on a separate line.
> > +.It Fl i Ar extension
> > +Edit files in-place, saving backups with the specified
> > +.Ar extension .
> > +If a zero-length
> > +.Ar extension
> > +is given, no backup will be saved.
> > +It is not recommended to give a zero-length
> > +.Ar extension
> > +when in-place editing files, as you risk corruption or partial content
> > +in situations where disk space is exhausted, etc.
> >  .It Fl r
> >  An alias for
> >  .Fl E ,
> > @@ -510,6 +521,12 @@ command,
> >  squeezing excess empty lines from standard input:
> >  .Bd -literal -offset indent
> >  $ sed -n '
> > +.Pp
> > +The
> > +.Fl i
> > +option is a non-standard
> > +.Fx
> > +extension and may not be available on other operating systems.
> >  # Write non-empty lines.
> >  /./ {
> >      p
> > @@ -543,7 +560,7 @@ utility is compliant with the
> >  specification.
> >  .Pp
> >  The flags
> > -.Op Fl aEru
> > +.Op Fl aEiru
> >  are extensions to that specification.
> >  .Pp
> >  The use of newlines to separate multiple commands on the command line
> > 
> 

-- 
Antoine

Reply via email to