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