I'm not sure I understand the goal of the signal handler.

sdiff is moving forward through the file, only.  If you are in a pager,
you want to increase the width for the later output not yet visible?
the normal way one does that in programs which don't backtrack and
re-output, is by restarting the program.

You don't want a mix of shorter, then longer.  If you are using a pager,
I suspect at least one of the next lines is already be buffered out.  So
I don't understand how this will create output which looks correct.

I think you should remove the signal handler.

Marc Espie <[email protected]> wrote:

> This patch allows sdiff to auto-detect tty width,
> by passing -w auto
> 
> More importantly, sdiff will adjust its variables on the fly for
> subsequent lines (I don't know if redrawing the current
> lines when the tty changes is advisable).
> 
> It's pretty straightforward, tested thru sysmerge.
> 
> Doesn't seem it's standardized anywhere, I'm not sure having a functionality 
> that's
> not in gnu-sdiff would be an issue ?
> 
> 
> Index: sdiff.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/sdiff/sdiff.c,v
> retrieving revision 1.37
> diff -u -p -r1.37 sdiff.c
> --- sdiff.c   28 Sep 2018 18:21:52 -0000      1.37
> +++ sdiff.c   11 Dec 2019 16:42:25 -0000
> @@ -17,12 +17,14 @@
>  #include <getopt.h>
>  #include <limits.h>
>  #include <paths.h>
> +#include <signal.h>
>  #include <stdint.h>
>  #include <stdio.h>
>  #include <stdlib.h>
>  #include <string.h>
>  #include <unistd.h>
>  #include <util.h>
> +#include <sys/ioctl.h>
>  
>  #include "common.h"
>  #include "extern.h"
> @@ -43,7 +45,9 @@ struct diffline {
>  };
>  
>  static void astrcat(char **, const char *);
> +static void compute_width(void);
>  static void enqueue(char *, char, char *);
> +static void find_width(void);
>  static char *mktmpcpy(const char *);
>  static void freediff(struct diffline *);
>  static void int_usage(void);
> @@ -55,12 +59,16 @@ static void printd(FILE *, size_t);
>  static void println(const char *, const char, const char *);
>  static void processq(void);
>  static void prompt(const char *, const char *);
> +static void recompute_width(void);
>  __dead static void usage(void);
> +static void window_changed(int);
>  static char *xfgets(FILE *);
>  
>  SIMPLEQ_HEAD(, diffline) diffhead = SIMPLEQ_HEAD_INITIALIZER(diffhead);
>  size_t        line_width;    /* width of a line (two columns and divider) */
>  size_t        width;         /* width of each column */
> +size_t        wflag = WIDTH;
> +volatile sig_atomic_t got_signal = 0;
>  size_t        file1ln, file2ln;      /* line number of file1 and file2 */
>  int   Iflag = 0;     /* ignore sets matching regexp */
>  int   lflag;         /* print only left column for identical lines */
> @@ -153,11 +161,47 @@ FAIL:
>       exit(2);
>  }
>  
> +static void
> +window_changed(int sig __attribute__((__unused__)))
> +{
> +     got_signal = 1;
> +}
> +
> +static void
> +find_width(void)
> +{
> +     struct winsize ws;
> +
> +     if (ioctl(0, TIOCGWINSZ, &ws) != 0) {
> +             wflag = WIDTH;
> +             signal(SIGWINCH, SIG_DFL);
> +     } else
> +             wflag = ws.ws_col;
> +}
> +
> +static void
> +recompute_width(void)
> +{
> +     find_width();
> +     compute_width();
> +}
> +
> +static void
> +compute_width(void)
> +{
> +     /* Subtract column divider and divide by two. */
> +     width = (wflag - 3) / 2;
> +     /* Make sure line_width can fit in size_t. */
> +     if (width > (SIZE_MAX - 3) / 2)
> +             errx(2, "width is too large: %zu", width);
> +     line_width = width * 2 + 3;
> +}
> +
>  int
>  main(int argc, char **argv)
>  {
>       FILE *diffpipe, *file1, *file2;
> -     size_t diffargc = 0, wflag = WIDTH;
> +     size_t diffargc = 0;
>       int ch, fd[2], status;
>       pid_t pid;
>       const char *outfile = NULL;
> @@ -236,6 +280,11 @@ main(int argc, char **argv)
>                       diffargv[diffargc++] = "-w";
>                       break;
>               case 'w':
> +                     if (strcmp(optarg, "auto") == 0) {
> +                             signal(SIGWINCH, window_changed);
> +                             find_width();
> +                             break;
> +                     }
>                       wflag = strtonum(optarg, WIDTH_MIN,
>                           INT_MAX, &errstr);
>                       if (errstr)
> @@ -273,7 +322,7 @@ main(int argc, char **argv)
>               if (unveil(_PATH_BSHELL, "x") == -1)
>                       err(2, "unveil");
>       }
> -     if (pledge("stdio rpath wpath cpath proc exec", NULL) == -1)
> +     if (pledge("stdio rpath wpath cpath proc exec tty", NULL) == -1)
>               err(2, "pledge");
>  
>       /*
> @@ -302,12 +351,7 @@ main(int argc, char **argv)
>       /* Add NULL to end of array to indicate end of array. */
>       diffargv[diffargc++] = NULL;
>  
> -     /* Subtract column divider and divide by two. */
> -     width = (wflag - 3) / 2;
> -     /* Make sure line_width can fit in size_t. */
> -     if (width > (SIZE_MAX - 3) / 2)
> -             errx(2, "width is too large: %zu", width);
> -     line_width = width * 2 + 3;
> +     compute_width();
>  
>       if (pipe(fd))
>               err(2, "pipe");
> @@ -522,6 +566,11 @@ static void
>  println(const char *s1, const char div, const char *s2)
>  {
>       size_t col;
> +
> +     if (got_signal) {
> +             got_signal = 0;
> +             recompute_width();
> +     }
>  
>       /* Print first column.  Skips if s1 == NULL. */
>       col = 0;
> 

Reply via email to