On 07/17/15 13:51, Antoine Jacoutot wrote:
> 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?
> 

Oh, heh. Yes. I mean gsed.
Either way, it's one less package I have to remember. (and clearly I'm
not so good at remembering them in the first place!)

> 
>> 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
>>>
>>
> 

Reply via email to