Re: [hackers] [st][PATCH] Add support for DSR response "OK" escape sequence

2023-02-06 Thread Santtu Lakkala

On 6.2.2023 1.39, Adam Price wrote:

tsetattr(csiescseq.arg, csiescseq.narg);
break;
-   case 'n': /* DSR – Device Status Report (cursor position) */
-   if (csiescseq.arg[0] == 6) {
+   case 'n': /* DSR – Device Status Report */
+   switch (csiescseq.arg[0]) {
+   case 5: /* Status Report "OK" `0n` */
+   ttywrite("\033[0n", sizeof("\033[0n"), 0);


This will write a NUL byte to the tty, which doesn't seem intentional.


+   break;
+   case 6: /* Report Cursor Position (CPR) `;R` */
len = snprintf(buf, sizeof(buf), "\033[%i;%iR",
term.c.y+1, term.c.x+1);


--
Santtu



Re: [hackers] [sbase][PATCH 1/2] libutil: Implement a simple yes/no prompt

2022-11-25 Thread Santtu Lakkala
On 20.11.2022 16.58, Tom Schwindl wrote:> I don't quite get why there is 
a variable argument list instead of just using

a single argument which contains the prompt. I can't see the need for formatting
in a y/n prompt. I also wouldn't use `nomsg' since it just polutes stderr.


The specification for the -i flag says that the prompt must include the 
path, so if the function is to print the prompt, formatting does make sense.


--
Santtu



Re: [hackers] [sbase][PATCH 2/2] cp, mv, rm: Add `-i` for confirmation prompts

2022-11-25 Thread Santtu Lakkala




On 19.11.2022 23.46, Alan Potteiger wrote:

diff --git a/mv.c b/mv.c
index 8441f9c..51efde5 100644
--- a/mv.c
+++ b/mv.c
@@ -49,6 +57,9 @@ main(int argc, char *argv[])
 ARGBEGIN {
 case 'f':
 break;
+case 'i':
+mv_iflag = 1;
+break;
 default:
 usage();
 } ARGEND
diff --git a/rm.c b/rm.c
index 8bebfcb..70da082 100644
--- a/rm.c
+++ b/rm.c
@@ -19,6 +19,9 @@ main(int argc, char *argv[])
 case 'f':
 r.flags |= SILENT;
 break;
+case 'i':
+rm_iflag = 1;
+break;
 case 'R':
 case 'r':
 r.maxdepth = 0;


The POSIX specification says that for mv[0] and rm[1], -f and -i cancel 
each other out, with the last taking effect.


[0]: https://pubs.opengroup.org/onlinepubs/009604599/utilities/mv.html
[1]: https://pubs.opengroup.org/onlinepubs/009604599/utilities/rm.html

--
Santtu



Re: [hackers] [st][PATCH] Fix buffer overflow when handling composed input

2022-10-24 Thread Santtu Lakkala
On 24.10.2022 13.01, NRK wrote:> But which approach to take is the 
maintainer's call, not mine.

I've attched both fixed-size and dynamic-allocation patch (but
simplified without goto).


The dynmaic[sic] version incorrectly passes sizeof(buf), where buf is 
char *, as the size of buffer in the "happy case" leading to unnecessary 
hits to the dynamic path.


--
Santtu



Re: [hackers] [dmenu][PATCH] insert: use long instead of ssize_t

2022-09-05 Thread Santtu Lakkala

On 2.9.2022 23.38, NRK wrote:

`ssize_t` is bit of an exotic type. by POSIX, it's only guaranteed to be
able to hold {-1, SSIZE_MAX} [0], meaning that negative values less than
-1 isn't guaranteed to representable in `ssize_t` (though it works out
in practice).

by default `ctrl+u` will call `insert()` with `-cursor` which can be
lesser than `-1`. so just use `long` instead which doesn't have such
issues.


Could also use ptrdiff_t[0], although very likely long and ptrdiff_t are 
the same type.


> @@ -540,7 +540,7 @@ paste(void)
>   	if (XGetWindowProperty(dpy, win, utf8, 0, (sizeof text / 4) + 1, 
False,

>   utf8, &da, &di, &dl, &dl, (unsigned char **)&p)
>== Success && p) {
> -  insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strlen(p));
> +  insert(p, (q = strchr(p, '\n')) ? q - p : (long)strlen(p));

The true-branch of this ternary would already have type ptrdiff_t, as it 
is a substraction of pointers.


>XFree(p);
>}
>drawmenu();

[0]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stddef.h.html

--
Santtu



Re: [hackers] [dmenu] tab-complete: figure out the size before copying || NRK

2022-09-02 Thread Santtu Lakkala

On 2.9.2022 14.01, g...@suckless.org wrote:

commit 528d39b011afb7ef6fd794ba6b74155d4e69bc68

dmenu.c b/dmenu.c

index 969f6d8..6b285df 100644
--- a/dmenu.c
+++ b/dmenu.c
@@ -517,9 +517,9 @@ insert:
case XK_Tab:
if (!sel)
return;
-   strncpy(text, sel->text, sizeof text - 1);
+   cursor = strnlen(sel->text, sizeof text - 1);
+   memcpy(text, sel->text, cursor);
text[sizeof text - 1] = '\0'

This should now be
text[cursor] = '\0';

(Try, for example:
printf "short\nlongerstring\n" | dmenu

and type in: lon^Ks
and end up with shortgerstring)


-   cursor = strlen(text);
match();
break;
}


--
Santtu



[hackers] [PATCH] strings: Correctly handle non-UTF-8 data

2022-09-01 Thread Santtu Lakkala
Make fgetrune() put the breaking byte back, if it was not the only one
read, as this may be the start of the next, valid, rune.

Also consider erroneous runes to break a valid sequence, otherwise there
will be false-positive matches.
---
 libutf/fgetrune.c | 3 +++
 strings.c | 4 +---
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/libutf/fgetrune.c b/libutf/fgetrune.c
index 8cd78c6..97536fa 100644
--- a/libutf/fgetrune.c
+++ b/libutf/fgetrune.c
@@ -20,6 +20,9 @@ fgetrune(Rune *r, FILE *fp)
if (ferror(fp))
return -1;
 
+   if (*r == Runeerror && i > 1)
+   ungetc(buf[--i], fp);
+
return i;
 }
 
diff --git a/strings.c b/strings.c
index 8f5a154..13b54ea 100644
--- a/strings.c
+++ b/strings.c
@@ -20,9 +20,7 @@ strings(FILE *fp, const char *fname, size_t min)
 
for (off = 0, i = 0; (bread = efgetrune(&r, fp, fname)); ) {
off += bread;
-   if (r == Runeerror)
-   continue;
-   if (!isprintrune(r)) {
+   if (r == Runeerror || !isprintrune(r)) {
if (i == min)
putchar('\n');
i = 0;
-- 
2.25.1




[hackers] [sbase][PATCH] printf: Fixes and tweaks

2022-08-31 Thread Santtu Lakkala
Allow the use of multiple flags per conversion, as most flags are not
mutually exclusive.

Remove all dynamic memory usage, relying on stack buffer and variables
instead for generated format strings and character arguments.

Fix reading past format string end (with check before strchr) and use
of strtoll.

Only allow %% verbatim and simplify setting cooldown and process all
literal data in one iteration of the loop.

Fix incorrect default "width" value, and allow negative widths via *.

Consume away any length specifiers (l and h).
---
 printf.c | 121 +--
 1 file changed, 54 insertions(+), 67 deletions(-)

diff --git a/printf.c b/printf.c
index 039dac7..aa0a2df 100644
--- a/printf.c
+++ b/printf.c
@@ -9,6 +9,8 @@
 #include "utf.h"
 #include "util.h"
 
+static const char FLAGS[] = "#0- +";
+
 static void
 usage(void)
 {
@@ -18,12 +20,13 @@ usage(void)
 int
 main(int argc, char *argv[])
 {
-   Rune *rarg;
+   Rune rarg;
+   char fmtbuf[sizeof(FLAGS) + sizeof("%*.*ll")];
size_t i, j, argi, lastargi, formatlen, blen;
long long num;
double dou;
int cooldown = 0, width, precision, ret = 0;
-   char *format, *tmp, *arg, *fmt, flag;
+   char *format, *tmp, *arg;
 
argv0 = argv[0];
if (argc < 2)
@@ -38,40 +41,46 @@ main(int argc, char *argv[])
if (formatlen == 0)
return 0;
lastargi = 0;
-   for (i = 0, argi = 2; !cooldown || i < formatlen; i++, i = cooldown ? i 
: (i % formatlen)) {
+   for (i = 0, argi = 2;
+!cooldown || i < formatlen;
+cooldown = argi >= argc, i = (i + 1) % (formatlen + cooldown)) {
+   char flags[sizeof(FLAGS)] = { 0 };
if (i == 0) {
if (lastargi == argi)
break;
lastargi = argi;
}
if (format[i] != '%') {
-   putchar(format[i]);
+   size_t n = strcspn(format + i + 1, "%");
+   fwrite(format + i, sizeof(*format), n + 1, stdout);
+   i += n;
continue;
}
 
-   /* flag */
-   for (flag = '\0', i++; strchr("#-+ 0", format[i]); i++) {
-   flag = format[i];
+   if (format[++i] == '%') {
+   putchar('%');
+   continue;
}
 
+   /* flag */
+   for (; i < formatlen && strchr(FLAGS, format[i]); i++)
+   flags[strcspn(flags, (const char[]){ format[i], '\0' 
})] = format[i];
+
/* field width */
-   width = -1;
+   width = 0;
if (format[i] == '*') {
if (argi < argc)
-   width = estrtonum(argv[argi++], 0, INT_MAX);
-   else
-   cooldown = 1;
+   width = estrtonum(argv[argi++], INT_MIN, 
INT_MAX);
i++;
} else {
-   j = i;
-   for (; strchr("+-0123456789", format[i]); i++);
-   if (j != i) {
-   tmp = estrndup(format + j, i - j);
-   width = estrtonum(tmp, 0, INT_MAX);
-   free(tmp);
-   } else {
-   width = 0;
+   num = strtoll(format + i, &tmp, 10);
+   if (num > INT_MAX) {
+   if (tmp - format - i > INT_MAX)
+   tmp = format + i + INT_MAX;
+   eprintf("field width %.*s not in range\n", 
(int)(tmp - format - i), format + i);
}
+   width = num;
+   i = tmp - format;
}
 
/* field precision */
@@ -80,33 +89,25 @@ main(int argc, char *argv[])
if (format[++i] == '*') {
if (argi < argc)
precision = estrtonum(argv[argi++], 0, 
INT_MAX);
-   else
-   cooldown = 1;
i++;
} else {
-   j = i;
-   for (; strchr("+-0123456789", format[i]); i++);
-   if (j != i) {
-   tmp = estrndup(format + j, i - j);
-   precision = estrtonum(tmp, 0, INT_MAX);
-   free(tmp);
-   } else {
-   precision = 0;
+   num = strtoll(format 

Re: [hackers] [dwm][PATCH] Update monitor positions also on removal

2022-04-10 Thread Santtu Lakkala

On 9.4.2022 13.51, Hiltjo Posthuma wrote:

I've heard similar reports with monitor plugging and unplugging not working 
nicely.

Can someone test this patch and report back these conditions or if it improves 
things?


FWIW I've been using this change ever since I submitted it, and plug and 
unplug extra monitors multiple times a day, and have not needed dwm 
restarts ever since (don't even use the restart patch anymore =).


--
Santtu




[hackers] [dwm][PATCH] Update monitor positions also on removal

2022-02-21 Thread Santtu Lakkala
When monitors are removed, the coordinates of existing monitors may
change, if the removed monitors had smaller coordinates than the
remaining ones.

Remove special case handling so that the same update-if-necessary loop
is run also in the case when monitors are removed.
---
 dwm.c | 68 +--
 1 file changed, 34 insertions(+), 34 deletions(-)

diff --git a/dwm.c b/dwm.c
index a96f33c..85419e3 100644
--- a/dwm.c
+++ b/dwm.c
@@ -1874,42 +1874,42 @@ updategeom(void)
memcpy(&unique[j++], &info[i], 
sizeof(XineramaScreenInfo));
XFree(info);
nn = j;
-   if (n <= nn) { /* new monitors available */
-   for (i = 0; i < (nn - n); i++) {
-   for (m = mons; m && m->next; m = m->next);
-   if (m)
-   m->next = createmon();
-   else
-   mons = createmon();
+
+   /* new monitors if nn > n */
+   for (i = n; i < nn; i++) {
+   for (m = mons; m && m->next; m = m->next);
+   if (m)
+   m->next = createmon();
+   else
+   mons = createmon();
+   }
+   for (i = 0, m = mons; i < nn && m; m = m->next, i++)
+   if (i >= n
+   || unique[i].x_org != m->mx || unique[i].y_org != m->my
+   || unique[i].width != m->mw || unique[i].height != 
m->mh)
+   {
+   dirty = 1;
+   m->num = i;
+   m->mx = m->wx = unique[i].x_org;
+   m->my = m->wy = unique[i].y_org;
+   m->mw = m->ww = unique[i].width;
+   m->mh = m->wh = unique[i].height;
+   updatebarpos(m);
}
-   for (i = 0, m = mons; i < nn && m; m = m->next, i++)
-   if (i >= n
-   || unique[i].x_org != m->mx || unique[i].y_org 
!= m->my
-   || unique[i].width != m->mw || unique[i].height 
!= m->mh)
-   {
-   dirty = 1;
-   m->num = i;
-   m->mx = m->wx = unique[i].x_org;
-   m->my = m->wy = unique[i].y_org;
-   m->mw = m->ww = unique[i].width;
-   m->mh = m->wh = unique[i].height;
-   updatebarpos(m);
-   }
-   } else { /* less monitors available nn < n */
-   for (i = nn; i < n; i++) {
-   for (m = mons; m && m->next; m = m->next);
-   while ((c = m->clients)) {
-   dirty = 1;
-   m->clients = c->next;
-   detachstack(c);
-   c->mon = mons;
-   attach(c);
-   attachstack(c);
-   }
-   if (m == selmon)
-   selmon = mons;
-   cleanupmon(m);
+   /* removed monitors if n > nn */
+   for (i = nn; i < n; i++) {
+   for (m = mons; m && m->next; m = m->next);
+   while ((c = m->clients)) {
+   dirty = 1;
+   m->clients = c->next;
+   detachstack(c);
+   c->mon = mons;
+   attach(c);
+   attachstack(c);
}
+   if (m == selmon)
+   selmon = mons;
+   cleanupmon(m);
}
free(unique);
} else
-- 
2.32.0




[hackers] [st][PATCH] Delay redrawals on palette changes

2022-02-17 Thread Santtu Lakkala
Build on auto-sync and only mark window dirty on palette changes and let
the event handler do the actual draw.
---
 st.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/st.c b/st.c
index 51049ba..c71fa06 100644
--- a/st.c
+++ b/st.c
@@ -1927,7 +1927,7 @@ strhandle(void)
else if (xsetcolorname(defaultfg, p))
fprintf(stderr, "erresc: invalid foreground 
color: %s\n", p);
else
-   redraw();
+   tfulldirt();
return;
case 11:
if (narg < 2)
@@ -1940,7 +1940,7 @@ strhandle(void)
else if (xsetcolorname(defaultbg, p))
fprintf(stderr, "erresc: invalid background 
color: %s\n", p);
else
-   redraw();
+   tfulldirt();
return;
case 12:
if (narg < 2)
@@ -1953,7 +1953,7 @@ strhandle(void)
else if (xsetcolorname(defaultcs, p))
fprintf(stderr, "erresc: invalid cursor color: 
%s\n", p);
else
-   redraw();
+   tfulldirt();
return;
case 4: /* color set */
if (narg < 3)
@@ -1975,7 +1975,7 @@ strhandle(void)
 * TODO if defaultbg color is changed, borders
 * are dirty
 */
-   redraw();
+   tfulldirt();
}
return;
}
-- 
2.32.0