It would be nice to support arbitrarily long lines, but a first step would be to skip them gracefuly.
The code modifies the loop condition: no tests against ferror(3)/feof(3) are performed any more (I don't see their point). We could print a warning on ferror(), though, but that would be another diff. ok? Index: history.c =================================================================== RCS file: /d/cvs/src/bin/ksh/history.c,v retrieving revision 1.72 diff -u -p -p -u -r1.72 history.c --- history.c 18 Oct 2017 15:41:25 -0000 1.72 +++ history.c 18 Oct 2017 20:18:24 -0000 @@ -739,24 +739,45 @@ history_close(void) static void history_load(Source *s) { - char *p, encoded[LINE + 1], line[LINE + 1]; + char *nl, *p, encoded[LINE + 1], line[LINE + 1]; rewind(histfh); + line_co = 1; /* just read it all; will auto resize history upon next command */ - for (line_co = 1; ; line_co++) { - p = fgets(encoded, sizeof(encoded), histfh); - if (p == NULL || feof(histfh) || ferror(histfh)) - break; - if ((p = strchr(encoded, '\n')) == NULL) { - bi_errorf("history file is corrupt"); - return; + for (p = fgets(encoded, sizeof(encoded), histfh); p != NULL; + p = fgets(encoded, sizeof(encoded), histfh)) { + if ((nl = strchr(encoded, '\n')) == NULL) { + static int corrupt, toolong; + + /* no trailing newline? */ + if (strlen(p) != sizeof(encoded) - 1) { + if (!corrupt) { + corrupt = 1; + bi_errorf("history file is corrupt"); + } + return; + } + + if (!toolong) { + toolong = 1; + bi_errorf( + "ignoring history line(s) longer than %d" + " bytes", LINE); + } + + do { + p = fgets(encoded, sizeof(encoded), histfh); + } while (p != NULL && strchr(p, '\n') == NULL); + + continue; } - *p = '\0'; + *nl = '\0'; s->line = line_co; s->cmd_offset = line_co; strunvis(line, encoded); histsave(line_co, line, 0); + line_co++; } history_write(); -- jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF DDCC 0DFA 74AE 1524 E7EE