summaryrefslogtreecommitdiffstats
path: root/debian/patches/wall-use-fputs_careful.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/wall-use-fputs_careful.patch')
-rw-r--r--debian/patches/wall-use-fputs_careful.patch215
1 files changed, 215 insertions, 0 deletions
diff --git a/debian/patches/wall-use-fputs_careful.patch b/debian/patches/wall-use-fputs_careful.patch
new file mode 100644
index 0000000..f14f327
--- /dev/null
+++ b/debian/patches/wall-use-fputs_careful.patch
@@ -0,0 +1,215 @@
+From: наб <nabijaczleweli@nabijaczleweli.xyz>
+Date: Wed, 15 Mar 2023 16:16:48 +0100
+Subject: wall: use fputs_careful()
+
+LINE_MAX only applies to teletypes in canonical mode: when stdin is a
+file, it could still very much tear; start off at 512 for the sprintf(),
+then use getline() like in write.
+
+The line wrapping has one suboptimal edge-case:
+ $ wall < all
+
+ Broadcast message from nabijaczleweli@tarta (pts/4) (Tue Mar 14 22:31:25
+ 2023):
+
+ ^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\^]^^^_
+ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ
+ KLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~^?\200\201\202\203\204\205\206
+ \207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232
+ \233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256
+ \257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302
+ \303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326
+ \327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352
+ \353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376
+ \377
+but that's a pathological input, and the result is still infinitely
+better than it was before, so fixing that is more trouble than it's
+worth.
+
+Origin: https://github.com/util-linux/util-linux/commit/aa13246a1bf1be9e4f6eb331f4d4d2dbc875e22f
+Bug-Debian: https://bugs.debian.org/826596
+---
+ include/carefulputc.h | 42 +++++++++++++++++++++++++++++++++---------
+ login-utils/last.c | 2 +-
+ term-utils/wall.c | 38 ++++++--------------------------------
+ term-utils/write.c | 2 +-
+ 4 files changed, 41 insertions(+), 43 deletions(-)
+
+diff --git a/include/carefulputc.h b/include/carefulputc.h
+index 38a61cc..8813783 100644
+--- a/include/carefulputc.h
++++ b/include/carefulputc.h
+@@ -6,6 +6,7 @@
+ #include <ctype.h>
+ #ifdef HAVE_WIDECHAR
+ #include <wctype.h>
++#include <wchar.h>
+ #endif
+ #include <stdbool.h>
+
+@@ -13,18 +14,35 @@
+ * A puts() for use in write and wall (that sometimes are sgid tty).
+ * It avoids control and invalid characters.
+ * The locale of the recipient is nominally unknown,
+- * but it's a solid bet that the encoding is compatible with the author's.
++ * but it's a solid bet that it's compatible with the author's.
++ * Use soft_width=0 to disable wrapping.
+ */
+-static inline int fputs_careful(const char * s, FILE *fp, const char ctrl, bool cr_lf)
++static inline int fputs_careful(const char * s, FILE *fp, const char ctrl, bool cr_lf, int soft_width)
+ {
+- int ret = 0;
++ int ret = 0, col = 0;
+
+ for (size_t slen = strlen(s); *s; ++s, --slen) {
+- if (*s == '\n')
++ if (*s == '\t')
++ col += (7 - (col % 8)) - 1;
++ else if (*s == '\r')
++ col = -1;
++ else if (*s == '\a')
++ --col;
++
++ if ((soft_width && col >= soft_width) || *s == '\n') {
++ if (soft_width) {
++ fprintf(fp, "%*s", soft_width - col, "");
++ col = 0;
++ }
+ ret = fputs(cr_lf ? "\r\n" : "\n", fp);
+- else if (isprint(*s) || *s == '\a' || *s == '\t' || *s == '\r')
++ if (*s == '\n' || ret < 0)
++ goto wrote;
++ }
++
++ if (isprint(*s) || *s == '\a' || *s == '\t' || *s == '\r') {
+ ret = putc(*s, fp);
+- else if (!isascii(*s)) {
++ ++col;
++ } else if (!isascii(*s)) {
+ #ifdef HAVE_WIDECHAR
+ wchar_t w;
+ size_t clen = mbtowc(&w, s, slen);
+@@ -33,21 +51,27 @@ static inline int fputs_careful(const char * s, FILE *fp, const char ctrl, bool
+ case (size_t)-1: // EILSEQ
+ mbtowc(NULL, NULL, 0);
+ nonprint:
+- ret = fprintf(fp, "\\%3hho", *s);
++ col += ret = fprintf(fp, "\\%3hho", *s);
+ break;
+ default:
+ if(!iswprint(w))
+ goto nonprint;
+ ret = fwrite(s, 1, clen, fp);
++ if (soft_width)
++ col += wcwidth(w);
+ s += clen - 1;
+ slen -= clen - 1;
+ break;
+ }
+ #else
+- ret = fprintf(fp, "\\%3hho", *s);
++ col += ret = fprintf(fp, "\\%3hho", *s);
+ #endif
+- } else
++ } else {
+ ret = fputs((char[]){ ctrl, *s ^ 0x40, '\0' }, fp);
++ col += 2;
++ }
++
++ wrote:
+ if (ret < 0)
+ return EOF;
+ }
+diff --git a/login-utils/last.c b/login-utils/last.c
+index e6a8c41..2acfb4a 100644
+--- a/login-utils/last.c
++++ b/login-utils/last.c
+@@ -542,7 +542,7 @@ static int list(const struct last_control *ctl, struct utmpx *p, time_t logout_t
+ /*
+ * Print out "final" string safely.
+ */
+- fputs_careful(final, stdout, '*', false);
++ fputs_careful(final, stdout, '*', false, 0);
+
+ if (len < 0 || (size_t)len >= sizeof(final))
+ putchar('\n');
+diff --git a/term-utils/wall.c b/term-utils/wall.c
+index ae8c22c..f375eca 100644
+--- a/term-utils/wall.c
++++ b/term-utils/wall.c
+@@ -269,29 +269,13 @@ int main(int argc, char **argv)
+ exit(EXIT_SUCCESS);
+ }
+
+-static void buf_putc_careful(FILE *fs, int c)
+-{
+- if (isprint(c) || c == '\a' || c == '\t' || c == '\r' || c == '\n')
+- fputc(c, fs);
+- else if (!isascii(c))
+- fprintf(fs, "\\%3o", (unsigned char)c);
+- else
+- fputs((char[]){ '^', c ^ 0x40, '\0' }, fs);
+-}
+-
+ static char *makemsg(char *fname, char **mvec, int mvecsz,
+ size_t *mbufsize, int print_banner)
+ {
+- register int ch, cnt;
+- char *p, *lbuf, *retbuf;
++ char *lbuf, *retbuf;
+ FILE * fs = open_memstream(&retbuf, mbufsize);
+- long line_max;
+-
+- line_max = sysconf(_SC_LINE_MAX);
+- if (line_max <= 0)
+- line_max = 512;
+-
+- lbuf = xmalloc(line_max);
++ size_t lbuflen = 512;
++ lbuf = xmalloc(lbuflen);
+
+ if (print_banner == TRUE) {
+ char *hostname = xgethostname();
+@@ -327,7 +311,7 @@ static char *makemsg(char *fname, char **mvec, int mvecsz,
+ will not overflow as long as %d takes at most 100 chars */
+ fprintf(fs, "\r%*s\r\n", TERM_WIDTH, " ");
+
+- snprintf(lbuf, line_max,
++ snprintf(lbuf, lbuflen,
+ _("Broadcast message from %s@%s (%s) (%s):"),
+ whom, hostname, where, date);
+ fprintf(fs, "%-*.*s\007\007\r\n", TERM_WIDTH, TERM_WIDTH, lbuf);
+@@ -372,18 +356,8 @@ static char *makemsg(char *fname, char **mvec, int mvecsz,
+ /*
+ * Read message from stdin.
+ */
+- while (fgets(lbuf, line_max, stdin)) {
+- for (cnt = 0, p = lbuf; (ch = *p) != '\0'; ++p, ++cnt) {
+- if (cnt == TERM_WIDTH || ch == '\n') {
+- fprintf(fs, "%*s\r\n", TERM_WIDTH - cnt, "");
+- cnt = 0;
+- }
+- if (ch == '\t')
+- cnt += (7 - (cnt % 8));
+- if (ch != '\n')
+- buf_putc_careful(fs, ch);
+- }
+- }
++ while (getline(&lbuf, &lbuflen, stdin) >= 0)
++ fputs_careful(lbuf, fs, '^', true, TERM_WIDTH);
+ }
+ fprintf(fs, "%*s\r\n", TERM_WIDTH, " ");
+
+diff --git a/term-utils/write.c b/term-utils/write.c
+index 231c77f..eda52d1 100644
+--- a/term-utils/write.c
++++ b/term-utils/write.c
+@@ -276,7 +276,7 @@ static void do_write(const struct write_control *ctl)
+ if (signal_received)
+ break;
+
+- if (fputs_careful(line, stdout, '^', true) == EOF)
++ if (fputs_careful(line, stdout, '^', true, 0) == EOF)
+ err(EXIT_FAILURE, _("carefulputc failed"));
+ }
+ free(line);