Re: [dev] Special target ".POSIX" in Makefiles

2021-12-31 Thread Michael Forney
On 2021-12-30, NRK  wrote:
> Hmm, I was under the impression that `?=` was accepted into POSIX. But I
> cannot find any mention of it in the posix manpage (man 1p make) so I
> guess I was wrong.

It is accepted for the upcoming POSIX issue 8:
https://austingroupbugs.net/view.php?id=330



Re: [dev] tlsrp: a simple TLS reverse proxy

2020-07-05 Thread Michael Forney
On 2020-07-05, Nihal Jere  wrote:
> I wrote a very simple TLS reverse proxy which can be used as a companion
> to quark. Essentially, it just turns quark's HTTP into HTTPS. It depends
> only on libtls (from LibreSSL) and libbsd (for strlcpy).

Seems like a neat project. Have you considered using memccpy instead
of strlcpy? I don't think it's worth adding a dependency on libbsd
over such a simple function, and memccpy is POSIX (XSI) and accepted
for C2x.

I think it even simplifies things a bit:

diff --git a/tlsrp.c b/tlsrp.c
index 2766f32..c8d5d39 100644
--- a/tlsrp.c
+++ b/tlsrp.c
@@ -1,6 +1,5 @@
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -70,13 +69,11 @@ dounixconnect(const char *sockname)
 int sfd;
 struct sockaddr_un saddr = {0};

-if (strlen(sockname) > SUN_PATH_LENGTH-1)
+if (!memccpy(saddr.sun_path, sockname, '\0', SUN_PATH_LENGTH))
 die("unix socket path too long");

 saddr.sun_family = AF_UNIX;

-strlcpy((char *) &saddr.sun_path, sockname, SUN_PATH_LENGTH);
-
 if ((sfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
 die("failed to create unix socket:");

Some other things I noticed:
- You should probably use sizeof(saddr.sun_path) instead of a
hard-coded assumed minimum size.
- The tlsrp Makefile rule is missing a dependency on tlsrp.c and util.c.
- It might be useful to have separate options for the hostname to
listen on and the hostname to connect to.
- I think the way to include the libtls header is #include .
Some systems (including OpenBSD) don't install it in
/usr/include/libressl, and the .pc file should add the appropriate
include directory.



Re: [dev] [sdhcp] The problem with renewals

2020-04-07 Thread Michael Forney
On 2020-03-16, Laslo Hunhold  wrote:
> Would you be open to work on a small patchset for it reflecting your
> proposals? But before you do that, we might also just want to wait for
> feedback by Michael Forney, who seems to be the current active
> maintainer.

I'm not the maintainer, I just sent a few patches a while back. Now
that I think of it, there is still a pending patch:
https://lists.suckless.org/hackers/1908/16959.html

It's been a long time since I've looked at the details of DHCP. Over
the past few years I have run into a few situations where sdhcp didn't
work, but have not found the time to investigate them. So I can
confirm that sdhcp still has some issues, just not sure if they are
the same issues as Sean is reporting here.



Re: [dev] [sbase] [ed] A couple of notes

2020-04-05 Thread Michael Forney
On 2020-03-22, Hiltjo Posthuma  wrote:
> Maybe it's an idea to just place issues in a TODO file in the repository?

That's a good idea, thanks.

I added a section with the issues reported by Cág, some existing items
from ed.c, and a few others I have noticed.



Re: [dev] [sbase] [ed] A couple of notes

2020-03-21 Thread Michael Forney
On 2020-03-21, Hiltjo Posthuma  wrote:
> What kind of tracker?

Did you see my other reply?
https://lists.suckless.org/dev/2003/33827.html

>I think discussions of suckless projects should stay
> on the mailinglist and/or IRC, not an external bugtracker or something.

Would suckless.org consider hosting a todo.sr.ht instance?

> Have you tried sending the issues to the maintainer or gently bumping it?

I am the maintainer, so that wouldn't help much.



Re: [dev] [sbase] [ed] A couple of notes

2020-03-21 Thread Michael Forney
On 2020-03-17, Hiltjo Posthuma  wrote:
> Where is the patch?

I know it's contrary to the opinion of a lot of people here, but
personally, I have no issue with bug reports without a patch.
Sometimes people just don't have the time to investigate the issue and
come up with a fix. It could even be that the fix involves more
complex restructuring of the rest of the code.

If the choice is between no patch, or no bug report at all, I would
definitely prefer no patch. I'd like to at least be aware of places
where sbase is non-conforming or buggy. I myself created
https://todo.sr.ht/~mcf/sbase a while ago so I could keep track of
issues that I found and have not gotten around to fixing.

Of course supplying a patch should be highly encouraged, and if there
is no patch the issue might not get fixed quickly, or at all,
depending on its severity.



Re: [dev] [sbase] [ed] A couple of notes

2020-03-21 Thread Michael Forney
On 2020-03-17, Cág  wrote:
> There are a couple things I've come across the
> sbase's version of ed:
> 1. w doesn't print the byte count.  Suppose a sample
> ed session (using P to distinguish my input from ed's
> output):
> % ed
> P
> *a
> milk
> bread
> eggs
> meat
> veggies
> bananas
> apples
> .
> *w list
> *q
> %
> 2. I guess using ed for huge files is not really a good
> idea, however the sbase ed cannot open a 750MiB 3.5m lines
> CSV file, while the GNU version can.  Probably has to do
> with the limits set.
>
> As always, I'm very pleased working with sbase and want to
> thank everybody responsible for making it.

Hi Cág,

Thanks for the bug reports. As Hiltjo said, it would be very helpful
if you could supply a patch for these issues. I think at least the
first one should be pretty easy to fix.

If not, feel free to use the tracker I mentioned in my other reply to
make sure these issues are not forgotten.



Re: [dev] [sbase] sed 'd' command after 'r' or 'a' (POSIX interpretation question)

2020-01-17 Thread Michael Forney
On 2020-01-17, Quentin Rameau  wrote:
>> Perhaps we should bring this up on the austin group list and get them
>> to clarify the text.
>
> Done, let's wait and see.

Thanks, Quentin!

For anyone following, the clarification request is at
https://www.austingroupbugs.net/view.php?id=1319



[dev] [sbase] sed 'd' command after 'r' or 'a' (POSIX interpretation question)

2020-01-17 Thread Michael Forney
Hello,

I recently ran into a package (dialog), which uses the following sed
script to generate its dlg_config.h header:

/@DEFS@/r conftest.frag
/@DEFS@/d

The intention is to replace @DEFS@ in the header template with the
contents of a file. However, sbase sed skips writing the contents of
the file since the pattern space gets deleted later on.

All the other implementations I looked at *do* insert the contents of the file.

Here's what POSIX says on the matter:

> The a and r commands schedule text for later output. The text specified
> for the a command, and the contents of the file specified for the r
> command, shall be written to standard output just before the next
> attempt to fetch a line of input when executing the N or n commands, or
> when reaching the end of the script. If written when reaching the end
> of the script, and the −n option was not specified, the text shall be
> written after copying the pattern space to standard output. The
> contents of the file specified for the r command shall be as of the
> time the output is written, not the time the r command is applied. The
> text shall be output in the order in which the a and r commands were
> applied to the input.

and

> [2addr]d  Delete the pattern space and start the next cycle.

Only the cases where n or N are used or the end of the script is
reached are described. So I guess the question is whether or not
"start the next cycle" means "jump to the end of the script". It's not
really clear to me from the POSIX description.

Does anyone have any insight on this issue? I'm thinking we should
probably change sbase sed to match the other implementations.



Re: [dev] [sbase] chmod -R and symbolic links

2019-12-28 Thread Michael Forney
On 2019-12-23, Laslo Hunhold  wrote:
> On Sat, 21 Dec 2019 19:05:45 -0800
> Michael Forney  wrote:
>
> Dear Michael,
>
>> I can think of two possibilities here:
>>
>> 1. Remove the -H, -L, and -P options from chmod, always set r.follow =
>> 'H', and call chmod(3) conditional on !S_ISLINK(st->st_mode).
>> 2. Keep the -H, -L, and -P options, but use fchmodat(3) instead of
>> chmod(3) with AT_SYMLINK_NOFOLLOW depending on r->follow and r->depth.
>> If fchmodat fails with EOPNOTSUPP, ignore that and continue.
>>
>> Does anyone have a strong preference for 2? I'm leaning towards 1
>> since it doesn't seem like those options are used commonly.
>
> I have a strong preference for 2 tbh, but it's your discretion as the
> maintainer. Only because the other tools "suck" doesn't mean we should
> lower our standards. Especially with the H, L and P options we found
> many bugs in GNU coreutils, and keeping them in is essential if we
> want to claim that we are more or less POSIX compliant.

I'm only proposing removing -H, -L, and -P from chmod, not the other
tools. The only POSIX option is -R, and the only use I can think of
for chmod -L is if you wanted to modify the permissions of files
outside the directory tree, which are pointed to by symlinks inside
the tree.



Re: [dev] [sbase] wc output formatting

2019-12-21 Thread Michael Forney
On 2019-11-03, Silvan Jegen  wrote:
> I assume it's the leading whitespace that was the problem since here[0]
> the output format is given as
>
> "%d %d %d %s\n", , , , 
>
>
> Considering this and that [0] doesn't mention anything about alignment,
> just having "%zu %zu %zu %s\n" as before seems like the right choice.

Okay, that sounds good to me, and nobody else expressed an opinion, so
I made this change.

Thanks for your input!



[dev] [sbase] chmod -R and symbolic links

2019-12-21 Thread Michael Forney
Hi,

I'm looking into improving chmod(1) behavior with symbolic links.

First, some background:
- The mode of symbolic links is not used anywhere, and on linux,
fchmodat(AT_FDCWD, path, mode, AT_SYMLINK_NOFOLLOW) on a symlink
returns EOPNOTSUPP.
- POSIX only specifies the -R option, and doesn't say anything about
symbolic links.
- coreutils and busybox chmod(1) only have a -R option. For directory
traversal, they follow symlinks specified on the command-line (an
error is printed if it is dangling), but don't follow symlinks
encountered further down.
- Most BSD chmod(1) have -H, -L, and -P options (defaulting to -P),
and the filesystem *does* record the mode of a symlink, but this mode
has no affect on the kernel's access checks.
- sbase chmod(1) has -H, -L, and -P options (defaulting to -P), which
control how recurse() traverses the directory tree. The option do
*not* affect the calls to chmod(3) itself, which always follows
symlinks.

So currently, if sbase chmod -R encounters a dangling symlink, it always fails.

I can think of two possibilities here:

1. Remove the -H, -L, and -P options from chmod, always set r.follow =
'H', and call chmod(3) conditional on !S_ISLINK(st->st_mode).
2. Keep the -H, -L, and -P options, but use fchmodat(3) instead of
chmod(3) with AT_SYMLINK_NOFOLLOW depending on r->follow and r->depth.
If fchmodat fails with EOPNOTSUPP, ignore that and continue.

Does anyone have a strong preference for 2? I'm leaning towards 1
since it doesn't seem like those options are used commonly.

-Michael



[dev] [sbase] wc output formatting

2019-11-02 Thread Michael Forney
Hi,

I was looking through wc.c in sbase and noticed a couple curious
things about the output formatting. POSIX says the tool should write

"%d %d %d %s\n", , , , 

When the tool was first written, it used fixed field widths,
presumably to maintain alignment when multiple files were specified.

" %5zu %5zu %5zu %s", , , , 

This seems to match what several other implementations do.

In 39802832[0], this was changed to

"%*.zu%*.zu%*.zu %s", 0, , 7, , 7, , 

with the intention of making the output POSIX compliant. '%*.zu' has a
field width specifier of '*' (meaning it is passed as an argument),
and a precision of '.' (equivalent to '.0', which means the value 0
produces no characters). I'm not sure exactly what the problem was, or
how this was meant to fix it, but there are a few issues with this:

1. Now that the first field has no minimum width, the width depends on
the number of newlines in the file, so the remaining fields are not
aligned, even though that have fixed minimum widths. If we don't care
about alignment, we may as well just use "%zu %zu %zu %s\n".
2. With a precision of 0, any counts with value 0 get skipped. I'm
guessing this was just a mistake, and there wasn't meant to be a
precision specifier at all ('%*zu').
3. Since the field may consume the full width, we might end up with no
separating whitespace between the fields.

Issue 2 was fixed in bbd2b4d2[1], by changing the precision specifier to 1

"%*.1zu%*.1zu%*.1zu %s", 0, , 7, , 7, , 

But, 1 is the default precision for 'u' conversions, so I think a
better change would be

"%*zu%*zu%*zu %s", 0, , 7, , 7, , 

Issue 3 was fixed in 79e8e330[2], by reducing the field width to 6,
and adding a leading space

 "%*.1zu %*.1zu %*.1zu %s", 0, , 6, , 6, , 


This leaves issue 1, which makes me wonder about the point of the
field widths if they aren't for alignment of the output. If we don't
care about alignment, I think we should just use "%zu %zu %zu %s\n".
If we do care about the alignment, we should use fixed widths similar
to the original code, like "%6zu %6zu %6zu %s\n". But now we've come
full circle, which makes me wonder what POSIX compliance issue commit
39802832 was meant to fix. Is the leading whitespace for the first
field a problem? If so, I don't think trying for alignment makes sense
since we'd have to left-justify the first column, which breaks the
digit alignment.

Anyone have any thoughts on this?

[0] 
https://git.suckless.org/sbase/commit/39802832af40f1a24aa362ca73e369a0cd26ecf2.html
[1] 
https://git.suckless.org/sbase/commit/bbd2b4d2439e13d44ec7d1f55bbc84f23d256401.html
[2] 
https://git.suckless.org/sbase/commit/79e8e330cbfbce4cbabae7c2a31846a89afdc095.html



[dev] Re: [sbase] sys/sysmacros.h and major/minor

2019-06-25 Thread Michael Forney
On 2019-06-25, Michael Forney  wrote:
> 1. Invert the ifdef by conditionally *omitting* the sysmacros.h
> include on systems that don't have it rather than including it only on
> glibc. I know this includes at least OpenBSD. Does anyone know of any
> others?

I think this includes most BSD operating systems, so this option
probably isn't a good idea.



[dev] [sbase] sys/sysmacros.h and major/minor

2019-06-25 Thread Michael Forney
Since glibc 2.28, sys/types.h no longer includes sys/sysmacros.h which
defines the major and minor macros. Some BSDs don't have
sys/sysmacros.h, so sbase has been conditionally including
sys/sysmacros.h on glibc since 99c78763[0].

However, in the upcoming musl release, it too will remove the
sys/sysmacros.h include from sys/types.h[1]. To continue building with
musl, glibc, and on other operating systems, we have a few options:

1. Invert the ifdef by conditionally *omitting* the sysmacros.h
include on systems that don't have it rather than including it only on
glibc. I know this includes at least OpenBSD. Does anyone know of any
others?

2. Add a make variable to control whether sysmacros.h is included.
Users on systems without sysmacros.h will have to modify this variable
in config.mk or the make command-line.

3. Add a configure test to check the availability of sysmacros.h. This
would be the first such configure test in sbase, and I'm sure some of
you would disapprove. Personally, I wouldn't be happy with this option
either, but it does seem to be the only reliable way to automatically
determine whether sysmacros.h needs to be included.

Unfortunately there no longer seems to be any way to write a program
using major/minor that doesn't involve conditional inclusion and/or
configure tests. Right now I'm leaning towards option 2 by adding -D
HAVE_SYSMACROS_H to CFLAGS in config.mk, and guarding the sysmacros.h
include by ifdefs.

If anybody has a nice solution to this problem, please let me know.

[0] 
https://git.suckless.org/sbase/commit/99c787631013bacf71c27dcac16d5a55b82be1c2.html
[1] 
http://git.musl-libc.org/cgit/musl/commit/?id=a31a30a0076c284133c0f4dfa32b8b37883ac930



[dev] [ubase] Fixing passwd crash

2019-06-25 Thread Michael Forney
I noticed that when passwd in ubase is changing a password, it will
try to dereference a NULL pointer when /etc/shadow exists, but the
user's password is not stored in /etc/shadow (i.e. marked with "x" in
/etc/passwd). It will try to save the spw entry if /etc/shadow exists,
even if the shadow entry wasn't used (in which case spw is NULL).

I can think of a couple solutions, but I'm not sure what the right behavior is.

1. Always store the password in /etc/shadow (or tcb shadow) if it
exists, so if a password in /etc/passwd is updated, it is moved to
shadow and the passwd entry is replaced with "x".

2. Always store the password in the location the previous one was stored in.

I'm thinking (1) might be the best option. Does anyone know what other
implementations do?



Re: [dev] dwm alpha patch: const isn't a const??

2019-05-26 Thread Michael Forney
On 2019-05-26, Paul Swanson  wrote:
> Hello,
>
> I've a fresh clone of dwm and the dwm alpha patch (20180613-b69c870) and
> it's generating
> the following error:
>
> dwm.c
> In file included from dwm.c:280:0:
> config.h:24:27: error: initializer element is not constant
>   [SchemeNorm] = { OPAQUE, baralpha, borderalpha },
>^~~~
> config.h:24:27: note: (near initialization for ‘alphas[0][1]’)
> config.h:24:37: error: initializer element is not constant
>
> What I can't understand, is the fact that 'baralpha', and all the other
> variables
> accused of not being constants are in fact declared as "static const
> unsigned int":
>
> static const unsigned int baralpha = 0xd0;
> static const unsigned int borderalpha = OPAQUE;
>
> If I substitute the initialising variables for a numeric literal (ie. 1) it
> compiles.
> But if I leave the constants from the patch or make my own, it fails.
>
> How can a const, not be a const?
>
> Any help would be greatly appreciated.

I'm not familiar with the alpha patch, but in standard C, initializer
elements need to be constant expressions, which is different from an
identifier for a const-qualified object. See
http://port70.net/~nsz/c/c99/n1256.html#6.6p7 for what is allowed in
initializers for static objects.

Perhaps the author of the patch was using a compiler that allows these
initializers (it looks like gcc-8 does, but gcc-7 does not).

If you want a portable way to use an identifier in an initializer for
a global, you have to use a preprocessor define like `#define baralpha
0xd0`, or enum constant like `enum { baralpha = 0xd0 };`.



Re: [dev] Yet another C compiler

2019-05-20 Thread Michael Forney
On 2019-05-20, sylvain.bertr...@gmail.com  wrote:
> Sadly, gcc-4.7 does not have an aarch64 backend and it's a pain to
> configure
> without breaking anything.

I wonder what the state of ARM/aarch64-4.7-branch is:
https://gcc.gnu.org/viewcvs/gcc/branches/ARM/aarch64-4.7-branch/

It doesn't look like this branch is exported in the git mirror, but
maybe if I can figure out git-svn, I can merge it into my branch.

> Last time I tried to bootstrap, gcc 8 was not compiling with gcc 4.7 on
> x86_64,
> did you test it with gcc 9?

Yes, I tested building gcc-9.1 with gcc-4.7.4 built by my compiler. I
have not tried gcc-8.

> What you say is good news, I may be able to add again a "gnu C" bootstrap to
> my
> custom distro (may burn some sh scripts to kill the GNU autotools in gcc
> 4.7
> then).

At least gcc tracks the autotools-generated files in the repository,
so you don't actually need them installed to build.

> You can replace inline asm:
>   - machine code from an independant assembler, for big asm chunks.
>   - with many extension keywords ("intrinsics"). A good idea is to make
> addition of a keyword with their "machine code conversion" kind of
> pluggable: I know it would have many limitations (llvm is literally
> brain diarhea on this) but it can circumvent many inline asm snippets
> this way. linux would be the primary target for this.
>   - to a certain extend, you could patch the target source code if
> its authors are fine with it, (asm->plain and simple C, or
>   C11->simpler C).

The issue is for lower level code that can't be written in C, for
example making system calls. I don't think inline asm will be too
difficult to implement in QBE. For the most part I think it can be
treated similarly to a function call, but with a special calling
convention.

> I really need to check Quentin's QBE again.

Yes, it has improved a lot in the past few months.

> What you do is great work, keep going while real life let you.

Thanks!



[dev] Yet another C compiler

2019-05-19 Thread Michael Forney
Hi all,

I know there are a number of small C compilers out there in various
states of completion, but recently I've been working on another to add
to the mix:

https://git.sr.ht/~mcf/cc

It is a C11 compiler based on QBE. The name is not yet chosen. I hope
to differentiate it from the others by focusing on compiling lots of
real world software in various environments.

In particular, most suckless software builds and works with an
occasional tweak or two (dwm, dmenu, st, sbase, ...). I've also been
able to build some other toolchain components including binutils and
gcc-4.7 (which can then be used to bootstrap to gcc-9). It is not yet
able to build musl libc due to lack of inline asm, volatile, and long
double support, but I hope to add those features if QBE gains support
for them.

My ultimate goal is to use it as the system compiler for oasis
(https://github.com/michaelforney/oasis).

Currently, the following targets are supported:

- x86_64-linux-musl
- x86_64-linux-gnu
- x86_64-freebsd
- aarch64-linux-musl
- aarch64-linux-gnu

If you're interested in helping, probably the best way is to try to
build your favorite software and report any issues to the bug tracker
at https://todo.sr.ht/~mcf/cc-issues (checking for existing issues
first, of course).



Re: [dev] key-value config reader

2019-05-12 Thread Michael Forney
On 2019-05-12, Markus Wichmann  wrote:
> On Sat, May 11, 2019 at 08:52:32PM +0100, Piotr Oleskiewicz wrote:
>> I would prefer to
>> write
>>
>>  X(int, i, 1)
>>
>> rather than
>>
>>  X(int, i, atoi, "%d", 1)
>>
>> Many thanks,
>> Piotr
>>
>
> That is going to be tough, as in C in a macro, there is no way to really
> determine what type name you were given. The only thing standard C has
> to offer to help is "sizeof", but that doesn't help you, obviously.
> (sizeof(float) == sizeof(int)).

What about _Generic in C11? This allows you to choose an expression
based on the type of another expression.

So I think something like the following should work:

diff --git a/kv.h b/kv.h
index 4a0be52..57facce 100644
--- a/kv.h
+++ b/kv.h
@@ -23,7 +23,7 @@ atoc(char *str) {
return strlen(str) > 0 ? str[0] : '\0';
 }

-#define X(type, name, parse, format, init) \
+#define X(type, name, init) \
type name;
 typedef struct {
KV
@@ -33,7 +33,7 @@ typedef struct {
 kv
 kv_init() {
kv c;
-#define X(type, name, parse, format, init) \
+#define X(type, name, init) \
c.name = init;
KV
 #undef X
@@ -42,8 +42,13 @@ kv_init() {

 void
 kv_print(FILE *f, kv c) {
-#define X(type, name, parse, format, init) \
-   fprintf(f, "%s = "format"\n", #name, c.name);
+#define X(type, name, init) \
+   fprintf(f, _Generic((type){0}, \
+   char *: "%s = %s\n", \
+   double: "%s = %f\n", \
+   int: "%s = %d\n", \
+   bool: "%s = %d\n" \
+   ), #name, c.name);
KV
 #undef X
 }
@@ -51,9 +56,14 @@ kv_print(FILE *f, kv c) {
 void
 kv_read(FILE *f, kv *c) {
char k[MAXLEN], v[MAXLEN];
-#define X(type, name, parse, format, init) \
+#define X(type, name, init) \
if(strncmp(k, #name, MAX(strlen(k), strlen(#name))) == 0) \
-   c->name = parse(v);
+   c->name = _Generic((type){0}, \
+   char *: strdup, \
+   double: atof, \
+   int: atoi, \
+   bool: atob \
+   )(v);
while(fscanf(f, "%s = %s\n", k, v) == 2) {
KV
}



Re: [dev] miniyacc

2019-05-08 Thread Michael Forney
On 2019-05-08, Daniel Cegiełka  wrote:
>   • lack of {% and %}  which is quite common (license):
> https://github.com/openbsd/src/blob/master/usr.bin/awk/awkgram.y
>   • I don't even know what else:
> https://github.com/9fans/plan9port/blob/master/src/cmd/hoc/hoc.y#L32

I think these are both the same problem, lack of comment support in
the tokenizer. The '{%' and '%}' are present, just after the license
comment. It should be a pretty easy fix, and I'm sure mpu would
appreciate a patch.



Re: [dev] miniyacc

2019-05-08 Thread Michael Forney
On 2019-05-07, Daniel Cegiełka  wrote:
> Hi,
>
> I'm going to use Quentin's miniyacc with (for example) bc.y from Plan 9:
> https://github.com/9fans/plan9port/blob/master/src/cmd/bc.y
>
> Of course, I had to modify the code (a bit), but unfortunately I still
> get an error when using miniyacc - works correctly with yacc from
> OpenBSD and Plan 9.
>
> I'm getting a message from this place ("production rule too long"):
> https://c9x.me/git/miniyacc.git/tree/yacc.c#n1110
>
> I tried to increase the value of IdntSz and MaxRhs, but it didn't help
> in any way.

It looks like this error is caused when miniyacc encounters a
character that it doesn't recognize as a token. nexttk() returns a
zero-length TIdnt token, causing an infinite loop, filling up r->rhs.

Try the attached patch, which makes it fail on invalid tokens.

In the example bc.y you linked, I think the '={' is causing problems,
and is from an obsolete yacc syntax:

Some implementations recognize "={" as equivalent to '{' because it
appears in historical documentation. This construction was recognized
and documented as obsolete as long ago as 1978, in the referenced
Yacc: Yet Another Compiler-Compiler. This volume of POSIX.1-2017 chose
to leave it as obsolete and omit it.

I also ran into this problem on some other grammar files containing
comments. One other issue I noticed is miniyacc doesn't seem to handle
escape sequences in literals (i.e. '\n').

After working around those issues, I get a different error

$n has no type (on line 171)

I think this is due to the usage of $2 referring to a token (EQOP in
this case) rather than a non-terminal. I haven't investigated this
further.
From 2c333b66bcbf4278bd5d080a6722aad704160905 Mon Sep 17 00:00:00 2001
From: Michael Forney 
Date: Wed, 8 May 2019 01:14:57 -0700
Subject: [PATCH] Fail on invalid token

Reading a zero-length TIdnt token causes infinite loops or other failures.
---
 yacc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/yacc.c b/yacc.c
index 01f054e..8ea5137 100644
--- a/yacc.c
+++ b/yacc.c
@@ -837,6 +837,8 @@ nexttk()
 			die("identifier too long");
 		c = fgetc(fin);
 	}
+	if (p == idnt)
+		die("unknown token");
 	*p = 0;
 	if (strcmp(idnt, "%")==0)
 	if (c=='{')
-- 
2.20.1



Re: [dev][sdhcp] more updates

2019-02-02 Thread Michael Forney
On 2019-02-02, Sean MacLennan  wrote:
> First a question: how portable do we want things? The current sdhcp
> works only on Linux.

I think that depends on how feasible it is to make it portable without
relying on a bunch of ifdefs to support different platforms.

In terms of timerfd, I think it should be okay to use POSIX timers and
a self-pipe (like that patch I sent you a while back), but it is kind
of ugly to have to recreate the timers after the fork. Personally, I
don't see much value in having sdhcp fork; I always run it with a
service supervisor.

CLOCK_BOOTTIME is pretty important for being able to resume from
suspend, but I'm not sure how portable this is. It looks like OpenBSD
has it, but not FreeBSD. Maybe this could be an option in a config.h?

>   * calctimeout() was dividing the timeout by 2. Not sure why so I
> removed it. Also, the check for less than 60 seconds would only
> work if you went back in time to Jan 1, 1970 for the first minute
> after midnight.

Check the comment for the calctimeout() function. It sets the
itimerspec passed by the caller to half-way until the expiration of
the specified timer. The struct itimerspec here specifies a time
*duration*, not a time instant, so I don't think 1970 has anything to
do with it.

The function uses timerfd_gettime to determine the duration of time
left until timer `n` expires, then sets `ts` to half of that duration,
down to a minimum of 60 seconds. This is what RFC 2131 says to do:

   In both RENEWING and REBINDING states, if the client receives no
   response to its DHCPREQUEST message, the client SHOULD wait one-half
   of the remaining time until T2 (in RENEWING state) and one-half of
   the remaining lease time (in REBINDING state), down to a minimum of
   60 seconds, before retransmitting the DHCPREQUEST message.



Re: [dev] using vis (libtermkey) and netbsd-curses (was: oasis: small linux system inspired by stali)

2018-11-24 Thread Michael Forney
Hi Daniel,

On 2018-11-24, Daniel Cegiełka  wrote:
> Hi,
>
> https://lists.suckless.org/dev/1811/33025.html
>
> I prepared a more detailed description of how to compile vis +
> netbsd-curses.
>
> 1) copy from ncurses/ncurses/names.c strnames & strfnames:
>
> DCL(strnames) = {
> "cbt",
> "bel",
> (...)
> "box1",
> (NCURSES_CONST char *)0,
> };
>
> DCL(strfnames) = {
> "back_tab",
> "bell",
> (...)
> "box_chars_1",
> (NCURSES_CONST char *)0,
> };
>
>
> 2) replace ncurses macros (DCL etc.) with C declarations:
>
> const char *strnames[] = {
> "cbt",
> "bel",
> (...)
> "box1",
> NULL,
> };
>
> const char *strfnames[] = {
> "back_tab",
> "bell",
> (...)
> "box_chars_1",
> NULL,
> };

When I looked into this, I went with a slightly different approach.
Instead of copying from ncurses, I generated the arrays from term.h
and an awk script.

awk '
/TICODE_[a-z]+,/ {
names[++numnames] = substr($1, 8, length($1) - 8)
}

/^#define t_[a-z_]+(t)/ {
fnames[++numfnames] = substr($2, 3, length($2) - 5)
}

END {
print "const char *const strnames[] = {"
for (i = 1; i <= numnames; ++i)
print("\t\"" names[i] "\",")
print "\t(void *)0"
print "};"

print "const char *const strfnames[] = {"
for (i = 1; i <= numfnames; ++i)
print("\t\"" fnames[i] "\",")
print "\t(void *)0"
print "};"
}
' libterminfo/term.h > libterminfo/names.c

>
> 3) edit driver-ti.c (libtermkey) and include names.c:
>
> #ifdef HAVE_UNIBILIUM
> # include 
> #else
> # include 
> # include 
>
> /* strnames and strfnames */
> #include "names.c"
>
> /* curses.h has just poluted our namespace. We want this back */
> # undef buttons
> #endif

You don't need to include the whole names.c in term.h, just declare the arrays:

diff --git a/libterminfo/term.h b/libterminfo/term.h
index 884cfe9..8345a7f 100644
--- a/libterminfo/term.h
+++ b/libterminfo/term.h
@@ -1944,6 +1944,8 @@ extern "C" {
 #endif

 extern TERMINAL *cur_term;
+extern const char *const strfnames[];
+extern const char *const strnames[];

 /* setup functions */
 intsetupterm(const char *, int, int *);


> vis works fine, however, there is a problem when I use ':!' or ':e *'.
> I think that the terminal settings are not restored. Does anyone have
> an idea here how it can be solved?

I can confirm the issue here. No idea about how to solve it though.

Compared to ncurses, I also notice a bit of flickering when scrolling
fast (status bar occasionally blinks). I remember this problem being
more severe back when I looked into this, so I had decided to stick
with ncurses for oasis for the time being.



Re: [dev] [sdhcp] Part 1/3 Bugs

2018-11-14 Thread Michael Forney
On 2018-11-12, Sean MacLennan  wrote:
> I am surprised you are getting away with binding the socket to the
> broadcast address.

I found in ip(7):

INADDR_BROADCAST (255.255.255.255) means any host and has the same
effect on bind as INADDR_ANY for historical reasons.

So that explains why it worked.

BTW, is there going to be a part 3/3?



Re: [dev] GPL free Linux

2018-11-14 Thread Michael Forney
On 2018-11-13, Markus Wichmann  wrote:
> On Mon, Nov 12, 2018 at 01:14:38PM -0800, Michael Forney wrote:
>> Usually how it works is either the display server itself needs to be
>> setuid to open those input devices, or some other program (commonly
>> systemd-logind) needs to open it on its behalf. I believe Xorg with
>> systemd disabled will need to be setuid because of this.
>>
>
> I lack the words to describe how broken I think it is, to make an
> application setuid because you couldn't be arsed to set file permissions
> properly. Or at least, the words to do so in a civilised manner.

Well, you usually don't want just any process to be able to open your
keyboard device and read events from it; just the display server and
only when the VT it is running on is active. This is especially true
on a multi-user system. So, you want opening input devices to be
privileged or federated in some way.

There is also a problem with DRM, since while you can become master
(required for modesetting) implicitly if no other process is master,
you need CAP_SYS_ADMIN to be able to issue the ioctls to drop/regain
master. This makes it impossible to do VT switching properly as
non-root (see https://github.com/mpv-player/mpv/issues/6184 for
example).



Re: [dev] GPL free Linux

2018-11-12 Thread Michael Forney
On 2018-11-12, Alessandro Pistocchi  wrote:
> What is swc?

My wayland compositor library: https://github.com/michaelforney/swc

> Where can I find oasis? Would you be interested in helping a bit if I needed
> help starting from oasis and removing gpl/lgpl stuff? I am ok with gpl apps
> but not with libs...

https://github.com/michaelforney/oasis

I won't be removing GPL/LGPL packages just because of the license, but
you don't have to install them if you don't want them. You can also
just comment out what you don't want in pkg/gen.lua to make sure they
don't get pulled in by something. The core set of packages (required
for bootstrap and basic system operation) doesn't use any GPL/LGPL
libraries, but does include some GPL applications (bc, e2fsprogs, git,
iproute2, kbd, util-linux) and plan9port (Lucent Public License 1.02).

Going through the package list, the libraries will likely have
problems with are:
- libelf from elfutils (LGPLv3), required to build linux
- efivar (LGPLv2.1), required by efibootmgr (GPLv2)
- libfuse (LGPLv2.1), required by sshfs (GPLv2)
- libnl (LGPLv2.1), required by wpa_supplicant (BSD-3, but libnl is
linked statically, so also LGPLv2.1)
- jbig2dec (AGPLv3), required by mupdf (AGPLv3)
- ffmpeg (LGPLv2.1 or GPLv2, depending on what's enabled), required by
mpv (also GPLv2 or LGPLv2.1 depending on what's enabled).
- alsa-lib (LGPLv2.1), required by alsa-utils (GPLv2) and mpv

(licenses were determined by looking briefly at https://repology.org/)



Re: [dev] GPL free Linux

2018-11-12 Thread Michael Forney
On 2018-11-12, Markus Wichmann  wrote:
> On Mon, Nov 12, 2018 at 11:17:49AM +, Alessandro Pistocchi wrote:
>> I would use some help to make it work with X ( does it work with
>> Wayland? ). There are not many docs I found about it...
>
> Ah, that old chestnut. As far as I know, the X input driver "evdev"
> depends on the paths of the event devices being in /dev/input, and on
> you having read access to them. I don't know if smdev puts them there by
> default, nor how it sets the permissions on those files. Also, there's a
> dependency on libudev in there somewhere. I don't know if that can pick
> up files from smdev.

I don't know about smdev, but if your /dev is a devtmpfs, the kernel
will create those devices automatically with permissions 600
root:root. I run a system without any hotplug daemon, just
CONFIG_DEVTMPFS and CONFIG_DEVTMPFS_MOUNT, and a script that runs at
startup to set /dev/dri/* to 660 root:video and /dev/snd/* to 660
root:audio.

> The files should be named according to the links in /sys/class/input.
> You should also be able to see the error messages in X11's log file.
> That should tell you what's wrong. And if all else fails: strace.
>
> I have no experience with Wayland but I suppose it requires a similar
> setup. Not having read permission on a device file is a showstopper no
> matter the codebase.

Usually how it works is either the display server itself needs to be
setuid to open those input devices, or some other program (commonly
systemd-logind) needs to open it on its behalf. I believe Xorg with
systemd disabled will need to be setuid because of this.

Wayland compositors work the same way. They either run setuid so they
can open devices themselves, communicate with systemd-logind to get
device FDs, or with some parent setuid "launcher" program which opens
the devices for them. For swc, I went with the third approach.

Regarding hotplugging and libudev, most wayland compositors use
libinput to handle input devices, which uses libudev to detect when
devices are added or removed. I believe libudev *does* work without
udevd running (not completely sure). However, you can also just listen
to netlink uevents to do the same thing. I maintain a branch of
libinput that does exactly this:
https://github.com/michaelforney/libinput/blob/master/src/netlink-seat.c

Xorg seems to work similarly, and you might be able to avoid libudev
and retain hotplug support by writing a "netlink" config backend here:
https://cgit.freedesktop.org/xorg/xserver/tree/config

>> I want to have a windowing system, compilers and libraries mainly.
>> Also I need make and I would like to have flex and bison.  Maybe a web
>> browser and a graphical IDE for source code editing but I am not even
>> sure about that.
>
> I was going to ask "Why not just use sta.li?" but that project
> apparently doesn't exist anymore.
>
> And that is pretty much exactly what I want from a distribution as well,
> and I just use Debian (you know you can just remove systemd from Debian,
> right?)

My own oasis project has all of those components and was inspired by
sta.li, though avoiding GPL has not been a primary goal. It has some
main components that are GPL including gcc, e2fsprogs, git, iproute2,
kbd, fuse, and netsurf.



Re: [dev] Some questions about sdhcp

2018-10-11 Thread Michael Forney
On 2018-10-11, Markus Wichmann  wrote:
> Hi all,
>
> I recently read the source code of sdhcp, and it does seem to be a nice
> tool, but I couldn't help but notice a few things. Now, maybe I'm dense,
> and none of the things I'm about to bring up matter for some reason, and
> if so, that would be really cool. But some of these really do seem like
> major issues, so here goes:

Hey Markus,

I have a branch of sdhcp[0] I'm using for oasis that fixes some of
these issues. I didn't send them to the ML though since they were
linux-specific (timerfd, CLOCK_BOOTTIME, ...), and I wasn't sure if
sdhcp was meant to work on other systems as well.

It's been a while since I looked at it, but sdhcp has mostly been
working fine for me since then. Though, there have been a couple of
occasions where I wasn't able to connect for whatever reason, so I
keep a build of ISC dhclient as a backup. It'd be nice to get any
remaining issues resolved.

[0] https://github.com/michaelforney/sdhcp

> 1. Timeout based on alarm()
> ---
>
> That is, in principle, not a bad way to do it, but unsuitable for a
> laptop application, which might see extended time spent in a sleep
> state. This is mostly an issue during the Bound state, as I have no idea
> if the alarms get adjusted for the time slept, and what happens if the
> alarm times out during sleep.
>
> That said, I also have no idea what happens to monotonic clocks, so what
> the heck.

> 2. Signal handlers established with signal()
> 
>
> Unfortunately, the BSD-v-SysV war has destroyed that interface beyond
> usability. On Linux, it depends on the libc, and for glibc also on the
> compiler flags, whether you get oneshot behavior or persistent behavior.
> So now we have to use sigaction() to establish signal handlers, or
> always re-establish the handlers from within, just in case.
>
> musl gives the BSD behavior always, BTW.
>
> 3. Broken timing model
> --
>
> The code reads the value from the Lease Time option into a variable
> called "t1", and proceeds to use that variable as T1 (i.e. the time
> after which the lease should be renewed). That is not what the lease
> time is!
>
> The RFC states that after the lease time has elapsed, the client must no
> longer use the address granted to it, and failing to do so was the
> reason why many Apple devices where banned from some Ivy League campus
> network or other, some years back; which was a great source of humour
> for me and others. Yet here we are, doing the same thing wrong.
>
> The RFC states that T1 is specified in option 58, and T2 in option 59.
> Failing these, T1 is 1/2 lease time, and T2 is 7/8 lease time. Apropos
> failing:
>
> 4. Christian search routines
> 
>
> The Bible states "Seek and you will find" but it might not be a
> great idea to implement this in a computer program. Unfortunately,
> optget() has absolutely no way of communicating failure to find a given
> option, and its callers don't seem to care much, either way. "Be lenient
> in what you accept" is all well and good, but not when the most
> important pieces of data are missing.
>
> 5. Absolutely no timeout in Renewing and Rebinding states
> -
>
> I couldn't find info on what happens after an alarm fires, but the only
> behaviors that make any sense are (a) alarm() is oneshot, and (b)
> alarm() is cyclical. Once sdhcp has made it into Bound state, an alarm()
> for the lease time is registered. When that fires, no further alarm is
> registered as sdhcp sends out a single request for renewal. If that
> packet, or the acknowledgment of it, drops for any reason, we're stuck
> in Renewing with either no timeout, if (a) is true, or one lease time
> (typically something like 1 day) as timeout, if (b) is true.
>
> The RFC states that the client should set the packet timeout in these
> states to half the remaining time (until T2 or lease time), down to one
> minute.
>
> 6. No XID reroll or comparison
> --
>
> The XID is rolled once, at the start of the process, and never rolled
> again. Shouldn't a different XID be used for each separate transaction?
> That might be down to taste, but this one is not: XID is never compared
> to the XID of a received packet. And neither is the CID. Thus, sdhcp
> ends up stealing people's leases! I mean, the whole protocol is
> broadcast, we're bound to see a packet that wasn't meant for us.
>
> 7. Use of the realtime clock for time measurement
> -
>
> For some reason I don't quite get, DHCP clients are required to send the
> time they spent working in the packet header. Well, not required; we
> could just null the field. But since we do send something, we might as
> well do it right. Currently, the time is measured by way of the time()
> function, which returns the current realtime clock value. 

Re: [dev] [bc]

2018-03-13 Thread Michael Forney
On 2018-03-13, Laslo Hunhold  wrote:
> On Tue, 13 Mar 2018 13:44:08 -0600
> Gavin Howard  wrote:
>> About GNU extensions: this was originally implemented for toybox
>> (http://landley.net/toybox/), and the maintainer specifically asked
>> that my bc be able to run
>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/time/timeconst.bc
>> which has basically every GNU extension. Thus, my bc will probably not
>> fit the suckless philosophy because the GNU extensions need to stay.
>> Thanks, though.
>
> Toybox is a one-man operation and it shows in the code. I'd rather
> recommend busybox to anyone, and I hate busybox!
> You as a developer need to decide how you want to write your code. It's
> a mistery to me why you presented it here when you are not planning to
> even remove some of the insane GNU-extensions.

I know next to nothing about bc and what GNU extensions are used by
timeconst.bc, but being able to build a linux kernel sounds like a
good goal to me. However, if timeconst.bc can be changed to use only
portable features of bc (in a way that is acceptable to upstream), I
think that would be better than implementing the GNU extensions.

Currently sbase (and GNU make/bc) is almost sufficient for building
linux, except for
- Usage `-n` flag in ln(1), which I think we should add.
- Usage of `\t` in sed bracket expressions. I sent a patch and it was
accepted, so this should be fixed in a future linux version (maybe
4.17?).
- Usage of `stat -c "%s"` to determine file size. I sent a patch to
use `ls -dn`, but still need to respond to some comments.



Re: [dev] securiy guidance

2018-03-08 Thread Michael Forney
On 2018-03-07, pet...@riseup.net  wrote:
> Looking at the chacha API one needs to use a nonce, in the monocypher
> implementation it is 24 bits wide, which would give the option of almost
> 17M runs with a single key. IIUC adding a salt would further randomize
> the output and possibly prevent some other forms of attacks but won't
> replace the nonce as the salt cannot be secret either.

It is actually 24 *bytes*, so 192 bits. My understanding is that the
difference between ChaCha20 and XChaCha20 is the extended nonce size
(ChaCha20 uses a 64-bit nonce). This is big enough to select at random
and be confident there won't be a collision.

See the nonce description in
https://monocypher.org/manual/crypto_chacha20_init.html#DESCRIPTION



Re: [dev] securiy guidance

2018-03-08 Thread Michael Forney
On 2018-03-07, pet...@riseup.net  wrote:
> On 2018-03-07 00:23, Michael Forney wrote:
>> Another related project I've been following is https://monocypher.org/
>>
>> It has a quite permissive license and encourages inlining the source
>> like you want.
>
> Hi Michael,
>
> thanks, this looks really nice and small. I'm doing my homework reading
> crypto 101 and getting to know what do I actually need for proper
> encryption. It would seem that I'll be fine with a symmetric-key algo
> and I'll have to encrypt the secret key using a master password. I see
> xchacha20 in monocypher but I have to yet read up if it is safe to use
> with a single key, i.e. encrypting n passwords with the same secret key.

I'm no expert either (so follow this at your own risk), but I also did
some investigation, and I think either of the following schemes would
work:

(1)
Setup:
- Generate a random salt and store somewhere safe.

Encryption:
- Read the salt from its location and the master password from the
console. Use those to generate a key with crypto_argon2i.
- Read password from the console (or generate randomly) and encrypt it
with the key and a randomly generated nonce using crypto_lock.
- Write the mac, nonce, and encrypted password to a file.

Decryption:
- Read the salt from its location and the master password from the
console. Use those to generate a key with crypto_argon2i.
- Read the mac, nonce, and encrypted password from the file.
- Decrypt the password using the mac, nonce, and key using crypto_unlock.

It's not clear to me if it's okay to use the plain crypto_argon2i with
just a fixed secret salt. A related scheme might be to use
crypto_argon2i_general with a salt generated for each encryption and a
single saved key. Then, the salts could be stored as plain text the
output file (and probably authenticated with crypto_lock_aead).
Perhaps one benefit is if someone somehow figured out the encryption
key for one password, they still wouldn't be able to decrypt the
others.

(2)
Setup:
- Generate a random salt.
- Read a master password from the console and generate a master key
from it and the salt using crypto_argon2i.
- Use crypto_key_exchange_public_key to compute the master public key
from the secret key.
- Save the salt and the master public key somewhere safe.

Encryption:
- Read the master public key from its location.
- Randomly generate a single-use key, and compute a shared key from it
and the master public key using crypto_key_exchange.
- Compute the single-use public key using crypto_key_exchange_public_key.
- Read password from the console (or generate randomly) and encrypt it
with this shared key, a randomly generated nonce, and the single-use
public key as additional data using crypto_lock_aead.
- Write the mac, nonce, single-use public key, and encrypted password to a file.

Decryption:
- Read the salt from its location.
- Read a master password from the console and compute the master key
from it and the salt using crypto_argon2i.
- Read the mac, nonce, single-use public key, and encrypted password
from the file.
- Compute the shared key from the single-use public key and the master key.
- Decrypt the password using the mac, nonce, single-use public key,
and shared key using crypto_unlock_aead.

For (2) I'm not sure if the nonce is necessary or not, since passwords
are encrypted with randomly generated single-use keys (so maybe a
fixed value is sufficient; it is still only used once per key).

The main differences are that (1) requires the master password for
every encryption, but not setup, and (2) requires the master password
only for setup. I think (2) is more similar to how gpg works.

Perhaps somebody who knows more about these crypto primitives could
point out any flaws with these schemes.



Re: [dev] securiy guidance

2018-03-06 Thread Michael Forney
On 2018-03-06, pet...@riseup.net  wrote:
> On 2018-03-06 10:01, Truls Becken wrote:
>> Some libraries to look at are; libressl, libtomcrypt, nacl.cr.yp.to,
>> libsodium, nettle, libgcrypt and libmcrypt.
>
> Hello Truls,
>
> thank you for this list. I was hoping there would be a publicly
> available algo that could be inlined in the source since I really only
> need 1 algorithm, not a whole suite.
>
> If sticking to libraries, is there any one you recommend most?
> Preferably non-GPL.

Another related project I've been following is https://monocypher.org/

It has a quite permissive license and encourages inlining the source
like you want.



Re: [dev] Some suckless hackathon 2017 preparation

2017-09-01 Thread Michael Forney
On 2017-09-01, Silvan Jegen  wrote:
> On Fri, Sep 01, 2017 at 08:40:34AM -0400, Carlos Torres wrote:
>> > On Aug 30, 2017, at 2:07 PM, Silvan Jegen  wrote:
>> >
>> > * Wayland dwm prototype?
>> > * Suckless Wayland client library prototype?
>>
>> I think Michael Forney has already addressed these issues.
>
> Yes, I am aware of those.
>
> I assume we will have another look at those to see if suckless is
> interested in the apporach taken within them or not. The wl-st Michael
> wrote has diverged quite a bit from upstream so one goal could be to
> merge them back? Not sure.

Just to give an update on this:

It's not that my st branch has diverged from upstream (in fact, I've
tried hard to make the differences as small as possible). It was quite
difficult to keep up with changes to master because st was just a
single >4k line file with X11 calls mixed in throughout. Every change
was a tricky merge conflict. I attempted to separate the X11-specific
stuff into x.c, but have not had a chance to rebase my changes after
this split.

If anyone plans to work on this, I suggest rendering with pixman and
freetype rather than wld, which has quite limited font support (I have
plans to replace it with something else in the future).

I hope the wayland-related work at the hackathon won't just be
duplicates of my efforts.



Re: [dev] [ANN] samurai: ninja-compatible build tool

2017-07-26 Thread Michael Forney
On 7/26/17, Anselm R Garbe  wrote:
> On 26 July 2017 at 09:05, Silvan Jegen  wrote:
>> That's what I suspected. Not sure it's desirable to ever work on a
>> codebase big enough to require a build system which uses ninja under
>> the hood. If I find myself in such a position I will turn to samurai
>> first.
>
> Out of curiosity, what is the point of a build system like ninja, if
> the codebase requires to be complex?

ninja doesn't require the codebase to be complex, but does tolerate
it. Anyway, I'm a little suprised about the distaste for ninja since
it's features are pretty much the same as POSIX make (variable
assignments and rule definitions). The main differences being

- In make, variable assignments are evaluated only when used. In
ninja, they are evaluated at the assignment.
- In make, inference rules are used to run the same command template
for many different targets. In ninja, rules specify the
command-template and build lines invoke the rule.
- In make, a new scope (to change CFLAGS/LDFLAGS for instance) can
effectively be introduced with a recursive call to make. In ninja, you
can include another ninja file with a new scope using `subninja`.
- make is standardized and ninja is not.

In oasis I'm using ninja like you're use stali.mk in stali. The
advantage is that dependencies are tracked throughout all packages
(not only within a package and between packages), so I can edit a file
in some library (libcurl for instance), and git, mupdf, and netsurf
all get rebuilt automatically. The disadvantage of course is it's not
a standard UNIX tool.

> Isn't the issue to be tackled the
> codebase complexity then?

Yes ideally projects like llvm and chromium would instead focus on
codebase complexity. But the argument that ninja is bad because bad
projects use it does not make sense to me.



Re: [dev] [ANN] samurai: ninja-compatible build tool

2017-07-25 Thread Michael Forney
On 7/25/17, Silvan Jegen  wrote:
> Hi
>
> On Wed, Jul 26, 2017 at 7:32 AM, Michael Forney 
> wrote:
>> Over the past couple weeks, I implemented a ninja-compatible build
>> tool in C. It is much simpler and smaller than ninja and seems to
>> perform at least as well.
>>
>> https://github.com/michaelforney/samurai
>>
>> It has all the features I care about, apart from gcc -MD header
>> dependency parsing which is planned. I replaced ninja with samurai in
>> oasis to remove the C++ dependency.
>
> https://ninja-build.org/manual.html#ref_headers
>
> I assume it's this functionality that is still missing, correct?

Correct.

>> Even if you don't care for ninja, it does seem to be gaining
>> popularity, and I've noticed several projects start switching from
>> autotools to meson (which outputs ninja), so I thought it would be
>> good to have a small C implementation. It was also a fun project.
>
> I have seen that some of the Wayland projects I care about are working
> on switching to meson but I did not know that it uses ninja under the
> hood.
>
> Since you seem to have plenty of experience with ninja, do you think
> it has any advantages over using a Makefile containing 20-50 lines of
> code?

No, not at all. Definitely use a Makefile for that case.



[dev] [ANN] samurai: ninja-compatible build tool

2017-07-25 Thread Michael Forney
Hi all,

Over the past couple weeks, I implemented a ninja-compatible build
tool in C. It is much simpler and smaller than ninja and seems to
perform at least as well.

https://github.com/michaelforney/samurai

It has all the features I care about, apart from gcc -MD header
dependency parsing which is planned. I replaced ninja with samurai in
oasis to remove the C++ dependency.

Even if you don't care for ninja, it does seem to be gaining
popularity, and I've noticed several projects start switching from
autotools to meson (which outputs ninja), so I thought it would be
good to have a small C implementation. It was also a fun project.



[dev] git://git.suckless.org not accepting connections

2017-07-03 Thread Michael Forney
Hi,

I noticed that git.suckless.org is no longer accepting connections
with the git protocol. HTTP still works though.

Just pointing that out in case it wasn't a deliberate change.

-Michael



Re: [dev] [sbase] Changing BUFSIZ

2017-06-14 Thread Michael Forney
On 6/13/17, Mattias Andrée  wrote:
> On Linux, the performance of cat(1) can be doubled
> when cat(1):ing from one pipe to another, by compiling
> with -DBUFSIZ=(1<<16) (the default pipe capacity).
> This is close to optimial for a read(3)/write(3)
> implementation.

Agreed. On my sbase branch, I bumped it up to 8192 (from 1024 on musl)
and noticed significant performance improvements.

Speaking of a read(3)/write(3) implementation, I should ping my IO
improvement patch series thread...



Re: [dev] oasis: small linux system inspired by stali

2017-03-29 Thread Michael Forney
On Tue, Mar 28, 2017 at 3:34 AM, Kamil Cholewiński  wrote:
>> I think it might have been possible to use some other build tool to
>> achieve something similar, but I don't think it would have worked out
>> as well.
>
> http://gittup.org/tup/ ?

I think tup could have worked too, but I still prefer ninja for a few reasons:

- tup uses fancy trickery to calculate dependencies of commands using
a fuse filesystem. This requires setuid or user namespaces to work
correctly, or else runs in a "degraded" mode (though, not quite sure
how this works).
- tup has more dependencies (sqlite, libfuse, lua), and as a result,
larger binary size (1.4M vs 908K for static stripped binary built with
-O2).
- tup has a more complicated language because it is intended to be
written directly instead of generated by something else. I'd have to
do some experimentation to see if it could replace the rc scripts, or
if I'd have to use the lua API.



Re: [dev] oasis: small linux system inspired by stali

2017-03-28 Thread Michael Forney
On Mon, Mar 27, 2017 at 2:44 PM, Marc André Tanner  wrote:
> Hi Michael,
>
> Overall I like your package selection, but I also have a few questions:
>
>  * Did you consider using netbsd-curses[1] instead of ncurses?
>
>This probably won't work as is, because libtermkey as required by
>vis depends on the ncurses terminfo library. It might be worth
>investigating how much work it would be to either port libtermkey
>or provide the necessary terminfo symbols in netbsd-curses.

I have not. I actually was originally very hesitant to include any
curses library at all, since it seems to me like the wrong layer to
implement a graphical UI (instead going the route of acme + 9term).

If you find a way to use netbsd-curses (or maybe no curses at all; I
saw you added a vt100 UI to vis), I'd be interested.

>  * What is the justification for using ninja (I'm not really familiar
>with it). It seems like the only (non-toolchain) package requiring
>C++. Furthermore, you mentioned that you might write a compatible
>C replacement at some point, hence it must obviously be better than
>other existing alternatives.

I am actually quite happy with how the rc/ninja based build system
worked out. In my experience, ninja is quite good as a low level build
tool. The language itself is extremely simple, and the tool handles
projects with several thousand build actions with ease (since it was
designed for chromium).  This makes it really easy to hack on some
package a bit, and build incrementally. Since dependencies (including
C header dependencies) are tracked across the entire system, relinking
due to a static library change is easy and automatic, and everything
is always up to date.

I think it might have been possible to use some other build tool to
achieve something similar, but I don't think it would have worked out
as well.

>  * Did you try how much of the system can be built using a C only
>toolchain like cparser+libfirm?

I did try cparser/libfirm at one point in the project's infancy and I
was surprised at the amount of stuff that built no problem. I have
since added more packages though, so can't give you a recent answer. I
also spent a week or so a while ago fixing some bugs in scc to try to
get it to build sbase. I think it would be really cool to be able to
build the core system (or more!) with a lighter toolchain.

>  * Why did you settle for perp instead of s6[2]? Again I'm not really
>familiar with either of them (besides reading their respective
>websites etc.). Just curious, it would be interesting to get your
>reasoning behind the package selection process.

I tried both a couple of years ago, and liked perp more. It seemed
simpler and smaller in scope than s6. s6 has its own scripting
language and quite a lot of extra tools. Although, I have to admit,
one contributing factor is that the s6 tool names are just a pain to
type.

Though s6 is definitely more actively maintained and more popular, so
I may take another look at some point. I would not object if someone
wanted to package it as an alternative.

>  * Will you consider using BearSSL in the future, once it gets a bit
>more mature?

Of course, although there are a number of packages that depend on the
OpenSSL/LibreSSL API (curl, wpa_supplicant, msmtp, netsurf, openssh,
python, transmission), so it might involve a lot of porting effort.

> Thanks for your work!

Thanks for taking a look!



[dev] oasis: small linux system inspired by stali

2017-02-12 Thread Michael Forney
For a while now, I've been working on putting together a linux system
based on suckless core tools, as well as various other projects. There
are still a number of things left to do, but I'm now at a point where
it is quite usable for me, and maybe for others as well.

https://github.com/michaelforney/oasis/wiki
https://github.com/michaelforney/oasis/releases

# stali similarities
- Uses musl libc and suckless core tools.
- Everything is statically linked.
- Everything is built from a single repository.
- Root filesystem is managed with git.
- Package build systems are ignored in favor of uniform custom build scripts.

# stali differences
- Package sources are not checked into the source repository, but
fetched on demand depending on which packages you have selected in
config.rc[0].
- Though stali has given up on being a general purpose desktop system,
I have not, so oasis includes my wayland display server (velox),
wayland ports of dmenu and st, and a wayland implementation of the
framebuffer backend for the netsurf browser.
- Only x86_64 is supported at the moment.
- Self-bootstrappable. Nearly all packages are buildable with only the
core packages[1] and a toolchain targeting musl (some need special
handling to first build some tool and add to PATH). A new toolchain
can be built with the above and GNU make (using musl-cross-make). A
new kernel can be built with the above and python (after applying a
couple patches[2]).
- Instead of makefiles, oasis uses rc scripts to generate ninja build
files (maybe in the future I will work on a ninja-compatible build
tool in C to avoid the C++ dependency).
- Binaries are not distributed, users are expected to build their own
(though, you can do so on a separate system and pull from it).

# Trying it out
## Real hardware
I wrote up some installation instructions[3] on the github wiki. I've
tested the build and install with the xubuntu 16.10 live
environment[4]. If you try this and run into any problems, please let
me know so that I can fix/clarify things.

## qemu
I built a qemu image[5] containing all the core, extra, and desktop
packages as well as a toolchain. It is probably the best way to play
around with oasis. The installed kernel is pretty minimal, and only
has support for virtio drivers. The root password is `oasis`.

  qemu-system-x86_64 \
-enable-kvm -cpu host -m 2048 \
-device virtio-balloon \
-device virtio-keyboard \
-device virtio-tablet \
-device virtio-net,netdev=net \
-device virtio-scsi \
-device virtio-serial \
-device virtio-vga \
-chardev stdio,id=cons \
-mon chardev=cons \
-drive if=none,id=hd,file=oasis-20170211.qcow2 \
-device scsi-hd,drive=hd \
-netdev user,id=net

To enable ssh login, `ssh-keygen -A && perpctl A sshd` (you will
probably want to set up a bridge and change `user` to `bridge` in the
netdev option to access from the host system).

To start velox, `swc-launch velox`.

To run without graphics mode, add `mux=on,signal=off` to the chardev
option, and add `-device virtconsole,chardev=cons -display none`.

To reboot/shutdown cleanly, `kill -s INT 1`/`kill -s USR1 1` respectively.

## chroot
I also uploaded a tar archive[6] created with `git archive` on the
root repository. It might be useful for poking around with chroot.
Note that the tar does not contain any empty directories and some
files are missing special permissions. After extracting, run
`./libexec/oasis/applyperms -d . && ./libexec/oasis/applyperms -d etc`
to fix this. Also, be aware that there is no common parent directory,
so make sure to extract somewhere you can easily clean up (such as a
new directory).

I've added various bits of documentation to the github wiki[7] if you
want to read more (or clone
https://github.com/michaelforney/oasis.wiki).

[0] https://github.com/michaelforney/oasis/blob/master/config.def.rc
[1] https://github.com/michaelforney/oasis/blob/master/sets.rc#L1
[2] https://github.com/torvalds/linux/compare/master...michaelforney:oasis
[3] https://github.com/michaelforney/oasis/wiki/Install
[4] 
http://cdimages.ubuntu.com/xubuntu/releases/16.10/release/xubuntu-16.10-desktop-amd64.iso
[5] 
https://github.com/michaelforney/oasis/releases/download/20170211/oasis-20170211.qcow2
[6] 
https://github.com/michaelforney/oasis/releases/download/20170211/oasis-20170211.tar.xz
[7] https://github.com/michaelforney/oasis/wiki



Re: [dev] a

2017-02-02 Thread Michael Forney
On 2/2/17, willy  wrote:
> At this point, I'm not sure where to look at, or even if the bug
> really lies in tar and not in bzip2.
> I checked the size (both octal and converted) and the value is good. So
> I'm not sure why the headers are not well read.
> In the case of the archive above, the error occurs on the last entry,
> but depending on the archives, it can occur on the second entry or in
> the middle, there's no rule.
>
> I hope my example are clear to define what the issue is. Would anyone
> have an idea?

It's a tar bug. See http://lists.suckless.org/dev/1612/30865.html.



Re: [dev] [sbase] [tar] some errors

2016-12-24 Thread Michael Forney
On 12/24/16, Cág  wrote:
> Markus Wichmann wrote:
>
>> Well, that looks like it might be problematic, doesn't it? Especially
>> when you find out, that the size of h->name there is 100 bytes. path
>> contains, of course, the entire file path relative to the starting
>> directory. In short, you will get this error message whenever trying to
>> package files with a total relative path length of more than 100
>> characters.
>
> Indeed, I've just tried to compress an extracted Linux kernel
> (that doesn't have .git folder), it went without errors. Thanks for
> pointing out.
>
> But when I tried to extract it, it still said "malformed tar archive".
> Here's the part with it: http://git.suckless.org/sbase/tree/tar.c#n404

Fixing up tar bugs in sbase has been on my TODO list for a while. It's
the one tool I'm not using from sbase.

One thing that might be related is that in various places, it uses
eread(..., BLKSIZE), expecting that exactly BLKSIZE bytes are written
(skipblk, xt, unarchive). But, if you are extracting from a pipe
hooked up to a decompression program, it may be less than that. When
this happens, it calls chktar on a random piece of data from the
archive, which fails the checksum check.

I think we should add a readall function to libutil, similar to the
writeall function I sent in a patch set a few weeks ago.

I think I have a pending patch to make the "malformed tar archive"
errors more specific, but it's on a different computer and I am
visiting family for the holidays. If you want to try and debug the
error, I'd start with trying to figure out why it thinks it is
malformed. I suspect it is due to a bad checksum.



[dev] [sbase] Allow \t escape in sed?

2016-12-06 Thread Michael Forney
I recently came across an issue running `make headers_install` for
installing kernel headers. The headers_install.sh script runs

sed -r \
  -e 's/([ \t(])(__user|__force|__iomem)[ \t]/\1/g' \
  -e 's/__attribute_const__([ \t]|$)/\1/g' \
  -e 's@^#include @@' \
  -e 's/(^|[^a-zA-Z0-9])__packed([^a-zA-Z0-9_]|$)/\1__attribute__((packed))\2/g'
\
  -e 's/(^|[ \t(])(inline|asm|volatile)([ \t(]|$)/\1__\2__\3/g' \
  -e 's@#(ifndef|define|endif[ \t]*/[*])[ \t]*_UAPI@#\1 @' \
  "$SRCDIR/$i" > "$OUTDIR/$FILE.sed" || exit 1

which doesn't work correctly with sbase sed because it doesn't support
escaped tabs. There is a comment at the top of sed.c wondering about
allowing this. POSIX says "For each other  encountered, the
following character shall lose its special meaning (if any)", so for
strict compliance, '\t' should be treated as just 't', as in the
current version of sed.

How should we resolve this? Replace '\t' with a literal tab character
in the headers_install.sh script, or add '\t' to the list of
characters handled by escapes() in sed.c? Other sed implementations I
looked at do not support escaped tabs, but I'm not sure how willing
the kernel people would be to removing the tab escapes.

What do others think? I'm leaning towards just trying to fix this by
patching the headers_install.sh locally and hoping it gets accepted.



Re: [dev] [stali] Root CA certificates

2016-10-23 Thread Michael Forney
On 10/23/16, Bruno Vetter  wrote:
>> I suggest just grabbing cert.pem from libressl.
>
> Thanks for the quick reply. Do you know if there is a designated default
> path for certs in stali?

It looks like the stali curl_config.h sets CURL_CA_BUNDLE to
/etc/ssl/certs/ca-certificates.crt[0]. I suspect that this is the
detected location for the cert bundle on the system used to run curl's
configure script.

> From what I see, stali's curl is not built with any certs default path or
> default bundle file.

See above.

> I don't know if it falls back to some libressl settings
> in that case (I have no openssl.cnf yet). Same question for other
> applications using certs like git.

I believe git uses libcurl, so probably just uses the path specified
in curl. It looks like the default path in libressl is to use
OPENSSLDIR "/cert.pem", and stali is using the default value of
OPENSSLDIR, /etc/ssl.

So, other applications that use libressl directly and have no default
are probably looking for it in /etc/ssl/cert.pem.

> I just want to understand how it's meant to work.

I don't know how it's meant to work on stali, but on my system, I
install cert.pem to /share/libressl/cert.pem, and create a symlink
/etc/ssl/cert.pem -> ../share/libressl/cert.pem, and set
CURL_CA_BUNDLE to /etc/ssl/cert.pem.



Re: [dev] [stali] Root CA certificates

2016-10-23 Thread Michael Forney
On Sun, Oct 23, 2016 at 8:47 AM, Bruno Vetter
 wrote:
> what is the recommended way to obtain a decent bundle of CA certificates for 
> stali? Like the ones I find in /etc/ssl/certs in my current distro.

I suggest just grabbing cert.pem from libressl.



Re: [dev] [stali] How to view manpages?

2016-10-17 Thread Michael Forney
On Mon, Oct 17, 2016 at 6:53 PM, Evan Gates  wrote:
> The plan for now is to use 9 base troff and a pager which has not yet
> been picked. Currently 9 base troff has been added to the src repo,
> but the mdoc macros still need to be included (the ones from heirloom
> troff worked). As such you should be able to manually view pages using
> the man macros but not the mdoc macros (e.g. sbase man pages won't
> work). I don't think there is a plan yet on how to handle the
> search/troff/pager setup, whether a man script like plan 9's or
> something else entirely. A minor point, the man macros included with 9
> base troff seem to add page breaks. I started to learn troff to remove
> them but I got side tracked by other projects.
>
> If you come up with a good solution start a discussion.

Why not mdocml[0]? It supports man and mdoc macros, and also has can
find and display man pages when invoked as 'man'.

[0] http://mdocml.bsd.lv/



Re: AW: [dev] [stali] Need musl based toolchain on stali installation

2016-10-11 Thread Michael Forney
On Oct 7, 2016 7:24 AM, "Bruno Vetter"  wrote:
> yes, it's tedious and I understand that it's not crucial to have the 
> toolchain statically linked. Trying to do so also brings up a lot of 
> questions that I cannot answer easily. For example a statically linked linker 
> apparently does not support an lto plugin. I have no idea if that would be 
> acceptable for a toolchain.
>
> I might just go on with the existing toolchain as you describe. Thanks much 
> for your help.

What "header file not found" issue did you hit with musl-cross-make?
I've used it successfully to build a native statically-linked
toolchain, although I ran into and worked around a couple of issues.

If you like, I have uploaded a pre-built toolchain[0] for my own project.

Yes, I believe LTO doesn't work with a statically-linked gcc/binutils.

[0] https://github.com/michaelforney/oasis-toolchain



Re: [dev] sbase installed first impressions

2016-10-03 Thread Michael Forney
On Mon, Oct 3, 2016 at 5:02 PM, stephen Turner
 wrote:
> Thanks for the links i will check it out! Also i wasn't aware of the
> -F function, playing with it now and that is a big help with working
> around the whole color bit. Clearly the / is for directories. How are
> the rest used? Surprisingly even google doesn't know. From what i
> could see they didn't label links and such so not very helpful in that
> respect but at least i wont try to vi a directory or cd to a file.

It is documented in POSIX:
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html#tag_20_73_04



Re: [dev] Wayland vs X11

2016-08-02 Thread Michael Forney
On Tue, Aug 2, 2016 at 1:08 PM, Silvan Jegen  wrote:
> On Tue, Aug 02, 2016 at 08:41:57PM +0200, FRIGN wrote:
> > On Tue, 2 Aug 2016 20:33:39 +0200
> > Silvan Jegen  wrote:
> >
> > Hey Silvan,
> >
> > > One can argue that having a simple protocol *is* the suckless part of
> > > Wayland (dont forget Xprint[0] :P). The Wayland protocol also does not
> > > allow for communication between clients directly[1] but only through
> > > the Wayland compositor.
> >
> > yeah, but omitting the rest is not suckless, it just turns everything
> > into a big mess. You might say anything about X.org, but at least you
> > can more or less rely on a set of features available to you, even if
> > they are "default" XFree86 extensions.

You are comparing a specific implementation of X11 (Xorg) with a
protocol (wayland).

If you chose to implement your own suckless X11 server, you'd still
have all the problems you are describing (rendering, buffer
management, input handling, joysticks, etc), and probably a lot more
because of legacy X11 baggage.

> > > I see two main issues that stem from switching to Wayland.
> > > 1. With Wayland there will be no non-compositing desktop.
> >
> > I don't see this aspect too critically. See how Wayland performs vs.
> > X in limited environments[0].
>
> I always assumed that having a compositing window manager has negative
> performance impact but at least according to
>
> https://blog.martin-graesslin.com/blog/2013/05/compositing-and-lightweight-desktops/

Xorg is a compositor too... At the end of the day, *something* has to
combine all your windows into a single frame to display them on your
monitor.

I didn't read the article, but presumably the slowness is due to
Xcomposite redirecting to some compositing windowing manager. If the
display server does the compositing (as in normal Xorg, or a typical
wayland server), there is no such problem.

> > > 2. Since rendering is done client-side and there is no Xlib, it may be
> > >harder to get pixel on your screen if you don't want to use one of
> > > the big GUI libraries like Qt or GTK2/3/++/whatev.
> >
> > Yeah, very good point. Also, clients cannot rely on compositor
> > features, because each compositor can do things differently. There
> > really is no simple way to write software and making it deliberately
> > hard almost makes you believe its a GTK/Qt conspiracy of some sort.
>
> > > As a non-expert in this space I am not sure the Wayland future is
> > > looking that bleak though.
> > > Velox[2] does not look bloated to me and wayland-enabled st[3] is only
> > > barely larger than the current X11 version's git tip (though the
> > > wayland version depends on wld[4]).
> >
> > How can you compare the two? You need a third-party library (wld) to
> > get shit done. Just wait down the line how much of a fucking mess we
> > are going to have!

With X11 and Xlib, you need an X server that implements every drawing
routine you might want to call.

But maybe you are arguing for server-side rendering over the display
server connection. I think it's simpler to just have the client do the
rendering, which it can do however it pleases.

-- 
Michael Forney 



[dev] [sbase] [PATCH 1/3] grep: Reverse some if-else logic

2016-05-13 Thread Michael Forney
This way, people don't have to do double negatives in their head.
---
 grep.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/grep.c b/grep.c
index 64ffbe2..ae23967 100644
--- a/grep.c
+++ b/grep.c
@@ -114,23 +114,23 @@ grep(FILE *fp, const char *str)
if (len && buf[len - 1] == '\n')
buf[len - 1] = '\0';
SLIST_FOREACH(pnode, &phead, entry) {
-   if (!Fflag) {
-   if (regexec(&pnode->preg, buf, 0, NULL, 0) ^ 
vflag)
-   continue;
-   } else {
-   if (!xflag) {
-   if ((iflag ? strcasestr : strstr)(buf, 
pnode->pattern))
+   if (Fflag) {
+   if (xflag) {
+   if (!(iflag ? strcasecmp : strcmp)(buf, 
pnode->pattern))
match = Match;
else
match = NoMatch;
} else {
-   if (!(iflag ? strcasecmp : strcmp)(buf, 
pnode->pattern))
+   if ((iflag ? strcasestr : strstr)(buf, 
pnode->pattern))
match = Match;
else
match = NoMatch;
}
if (match ^ vflag)
continue;
+   } else {
+   if (regexec(&pnode->preg, buf, 0, NULL, 0) ^ 
vflag)
+   continue;
}
switch (mode) {
case 'c':
-- 
2.6.2




[dev] [sbase] [PATCH 3/3] grep: Fix -v output and exit status

2016-05-13 Thread Michael Forney
Previously, it printed lines that didn't match some pattern. Instead,
it should print lines that don't match *any* pattern.

Test case:

out=$(echo foo | ./grep -v -e foo -e bar)
if [ "$?" = 1 ] && [ -z "$out" ] ; then
echo pass
else
echo fail
fi
---
 grep.c | 28 +++-
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/grep.c b/grep.c
index fb911ff..c322a32 100644
--- a/grep.c
+++ b/grep.c
@@ -113,25 +113,28 @@ grep(FILE *fp, const char *str)
/* Remove the trailing newline if one is present. */
if (len && buf[len - 1] == '\n')
buf[len - 1] = '\0';
+   match = 0;
SLIST_FOREACH(pnode, &phead, entry) {
if (Fflag) {
if (xflag) {
-   if (!(iflag ? strcasecmp : strcmp)(buf, 
pnode->pattern))
-   match = Match;
-   else
-   match = NoMatch;
+   if (!(iflag ? strcasecmp : strcmp)(buf, 
pnode->pattern)) {
+   match = 1;
+   break;
+   }
} else {
-   if ((iflag ? strcasestr : strstr)(buf, 
pnode->pattern))
-   match = Match;
-   else
-   match = NoMatch;
+   if ((iflag ? strcasestr : strstr)(buf, 
pnode->pattern)) {
+   match = 1;
+   break;
+   }
}
-   if (match ^ vflag)
-   continue;
} else {
-   if (regexec(&pnode->preg, buf, 0, NULL, 0) ^ 
vflag)
-   continue;
+   if (regexec(&pnode->preg, buf, 0, NULL, 0) == 
0) {
+   match = 1;
+   break;
+   }
}
+   }
+   if (match != vflag) {
switch (mode) {
case 'c':
c++;
@@ -150,7 +153,6 @@ grep(FILE *fp, const char *str)
break;
}
result = Match;
-   break;
}
}
if (mode == 'c')
-- 
2.6.2




[dev] [sbase] [PATCH 2/3] grep: Fix exit status with -F when last line doesn't match

2016-05-13 Thread Michael Forney
Test case:

if printf '%s\n' foo bar | ./grep -F foo >/dev/null ; then
echo pass
else
echo fail
fi
---
 grep.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/grep.c b/grep.c
index ae23967..fb911ff 100644
--- a/grep.c
+++ b/grep.c
@@ -107,7 +107,7 @@ grep(FILE *fp, const char *str)
ssize_t len = 0;
long c = 0, n;
struct pattern *pnode;
-   int match = NoMatch;
+   int match, result = NoMatch;
 
for (n = 1; (len = getline(&buf, &size, fp)) > 0; n++) {
/* Remove the trailing newline if one is present. */
@@ -149,7 +149,7 @@ grep(FILE *fp, const char *str)
puts(buf);
break;
}
-   match = Match;
+   result = Match;
break;
}
}
@@ -158,9 +158,9 @@ grep(FILE *fp, const char *str)
 end:
if (ferror(fp)) {
weprintf("%s: read error:", str);
-   match = Error;
+   result = Error;
}
-   return match;
+   return result;
 }
 
 static void
-- 
2.6.2




[dev] Re: [sbase] [PATCH] sort: Fix -u option

2016-03-12 Thread Michael Forney
On Sat, Mar 12, 2016 at 11:46:31AM -0800, Michael Forney wrote:
> In eb9bda878736344d1bef06d42e57e96de542a663, a bug was introduced in the
> handling of -1 return values from getline. Since the type of the len
> field in struct line is unsigned, the break condition was never true.
> This caused sort -u to never succeed.

This should be "sort -c" (here and in subject).

Please amend before committing.

> ---
>  sort.c | 11 ---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/sort.c b/sort.c
> index 5cfe801..90ee911 100644
> --- a/sort.c
> +++ b/sort.c
> @@ -210,10 +210,15 @@ check(FILE *fp, const char *fname)
>  {
>   static struct line prev, cur, tmp;
>   static size_t prevsize, cursize, tmpsize;
> + ssize_t len;
>  
> - if (!prev.data && (prev.len = getline(&prev.data, &prevsize, fp)) < 0)
> - eprintf("getline:");
> - while ((cur.len = getline(&cur.data, &cursize, fp)) > 0) {
> + if (!prev.data) {
> + if ((len = getline(&prev.data, &prevsize, fp)) < 0)
> + eprintf("getline:");
> + prev.len = len;
> + }
> + while ((len = getline(&cur.data, &cursize, fp)) > 0) {
> + cur.len = len;
>   if (uflag > slinecmp(&cur, &prev)) {
>   if (!Cflag) {
>   weprintf("disorder %s: ", fname);
> -- 
> 1.8.5.1
> 



[dev] [sbase] [PATCH] sort: Fix -u option

2016-03-12 Thread Michael Forney
In eb9bda878736344d1bef06d42e57e96de542a663, a bug was introduced in the
handling of -1 return values from getline. Since the type of the len
field in struct line is unsigned, the break condition was never true.
This caused sort -u to never succeed.
---
 sort.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/sort.c b/sort.c
index 5cfe801..90ee911 100644
--- a/sort.c
+++ b/sort.c
@@ -210,10 +210,15 @@ check(FILE *fp, const char *fname)
 {
static struct line prev, cur, tmp;
static size_t prevsize, cursize, tmpsize;
+   ssize_t len;
 
-   if (!prev.data && (prev.len = getline(&prev.data, &prevsize, fp)) < 0)
-   eprintf("getline:");
-   while ((cur.len = getline(&cur.data, &cursize, fp)) > 0) {
+   if (!prev.data) {
+   if ((len = getline(&prev.data, &prevsize, fp)) < 0)
+   eprintf("getline:");
+   prev.len = len;
+   }
+   while ((len = getline(&cur.data, &cursize, fp)) > 0) {
+   cur.len = len;
if (uflag > slinecmp(&cur, &prev)) {
if (!Cflag) {
weprintf("disorder %s: ", fname);
-- 
1.8.5.1




Re: [dev] Re: Stali RC

2015-10-04 Thread Michael Forney
On Fri, Oct 02, 2015 at 05:25:55PM +0200, Jens Staal wrote:
> On Friday 02 October 2015 16.59.57 Christian Neukirchen wrote:
> > (Statically linking X11 apps results in massively bloated binaries,
> > I can't recommend it.)
> 
> Anyone tried a static wayland dwm-like client like velox and its wayland-
> ported variants of st and dmenu?

FWIW, I've used a statically-linked velox, st, and dmenu on a
custom-built musl/sbase/ubase system, and it works fine.

Perhaps the biggest issue is lack of touchpad support and input
hotplugging (libinput requires udev), and a browser that works well with
wayland and musl.



[dev] [sbase] [PATCH 3/3] touch: Use both atime and mtime of reference file

2015-05-15 Thread Michael Forney
---
 touch.c | 22 +-
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/touch.c b/touch.c
index 2789716..fb04142 100644
--- a/touch.c
+++ b/touch.c
@@ -14,14 +14,13 @@
 static int aflag;
 static int cflag;
 static int mflag;
-static struct timespec t;
+static struct timespec times[2];
 
 static void
 touch(const char *file)
 {
int fd;
struct stat st;
-   struct timespec times[2];
int r;
 
if ((r = stat(file, &st)) < 0) {
@@ -30,8 +29,10 @@ touch(const char *file)
if (cflag)
return;
} else if (!r) {
-   times[0] = aflag ? t : st.st_atim;
-   times[1] = mflag ? t : st.st_mtim;
+   if (!aflag)
+   times[0] = st.st_atim;
+   if (!mflag)
+   times[1] = st.st_mtim;
if (utimensat(AT_FDCWD, file, times, 0) < 0)
eprintf("utimensat %s:", file);
return;
@@ -117,8 +118,8 @@ int
 main(int argc, char *argv[])
 {
struct stat st;
-   char *ref;
-   clock_gettime(CLOCK_REALTIME, &t);
+   char *ref = NULL;
+   clock_gettime(CLOCK_REALTIME, ×[0]);
 
ARGBEGIN {
case 'a':
@@ -129,7 +130,7 @@ main(int argc, char *argv[])
break;
case 'd':
case 't':
-   t.tv_sec = parsetime(EARGF(usage()), t.tv_sec);
+   times[0].tv_sec = parsetime(EARGF(usage()), times[0].tv_sec);
break;
case 'm':
mflag = 1;
@@ -138,10 +139,11 @@ main(int argc, char *argv[])
ref = EARGF(usage());
if (stat(ref, &st) < 0)
eprintf("stat '%s':", ref);
-   t = st.st_mtim;
+   times[0] = st.st_atim;
+   times[1] = st.st_mtim;
break;
case 'T':
-   t.tv_sec = estrtonum(EARGF(usage()), 0, LLONG_MAX);
+   times[0].tv_sec = estrtonum(EARGF(usage()), 0, LLONG_MAX);
break;
default:
usage();
@@ -151,6 +153,8 @@ main(int argc, char *argv[])
usage();
if (!aflag && !mflag)
aflag = mflag = 1;
+   if (!ref)
+   times[1] = times[0];
 
for (; *argv; argc--, argv++)
touch(*argv);
-- 
2.1.3.1.g339ec9c




[dev] [sbase] [PATCH 2/3] touch: Handle nanosecond timestamps

2015-05-15 Thread Michael Forney
---
 touch.c | 24 +++-
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/touch.c b/touch.c
index 563f919..2789716 100644
--- a/touch.c
+++ b/touch.c
@@ -14,14 +14,14 @@
 static int aflag;
 static int cflag;
 static int mflag;
-static time_t t;
+static struct timespec t;
 
 static void
 touch(const char *file)
 {
int fd;
struct stat st;
-   struct utimbuf ut;
+   struct timespec times[2];
int r;
 
if ((r = stat(file, &st)) < 0) {
@@ -30,10 +30,10 @@ touch(const char *file)
if (cflag)
return;
} else if (!r) {
-   ut.actime = aflag ? t : st.st_atime;
-   ut.modtime = mflag ? t : st.st_mtime;
-   if (utime(file, &ut) < 0)
-   eprintf("utime %s:", file);
+   times[0] = aflag ? t : st.st_atim;
+   times[1] = mflag ? t : st.st_mtim;
+   if (utimensat(AT_FDCWD, file, times, 0) < 0)
+   eprintf("utimensat %s:", file);
return;
}
 
@@ -118,7 +118,7 @@ main(int argc, char *argv[])
 {
struct stat st;
char *ref;
-   t = time(NULL);
+   clock_gettime(CLOCK_REALTIME, &t);
 
ARGBEGIN {
case 'a':
@@ -128,7 +128,8 @@ main(int argc, char *argv[])
cflag = 1;
break;
case 'd':
-   t = parsetime(EARGF(usage()), t);
+   case 't':
+   t.tv_sec = parsetime(EARGF(usage()), t.tv_sec);
break;
case 'm':
mflag = 1;
@@ -137,13 +138,10 @@ main(int argc, char *argv[])
ref = EARGF(usage());
if (stat(ref, &st) < 0)
eprintf("stat '%s':", ref);
-   t = st.st_mtime;
+   t = st.st_mtim;
break;
case 'T':
-   t = estrtonum(EARGF(usage()), 0, LLONG_MAX);
-   break;
-   case 't':
-   t = parsetime(EARGF(usage()), t);
+   t.tv_sec = estrtonum(EARGF(usage()), 0, LLONG_MAX);
break;
default:
usage();
-- 
2.1.3.1.g339ec9c




[dev] [sbase] [PATCH 1/3] mv, cp: Preserve nanosecond timestamps

2015-05-15 Thread Michael Forney
Otherwise, we run into problems in a typical autoconf-based build
system:

  - config.status is created at some point between two seconds.
  - config.status is run, generating Makefile by first writing to a file
in /tmp, and then mv-ing it to Makefile.
  - If this mv happens before the beginning of the next second, Makefile
will be created with the same tv_sec as config.status, but with
tv_nsec = 0.
  - When make runs, it sees that Makefile is older than config.status,
and re-runs config.status to generate Makefile.
---
 libutil/cp.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libutil/cp.c b/libutil/cp.c
index 32e0dc6..0f098d3 100644
--- a/libutil/cp.c
+++ b/libutil/cp.c
@@ -30,7 +30,7 @@ cp(const char *s1, const char *s2, int depth)
FILE *f1, *f2;
struct dirent *d;
struct stat st;
-   struct utimbuf ut;
+   struct timespec times[2];
ssize_t r;
int (*statf)(const char *, struct stat *);
char target[PATH_MAX], ns1[PATH_MAX], ns2[PATH_MAX], *statf_name;
@@ -154,9 +154,9 @@ cp(const char *s1, const char *s2, int depth)
if (cp_aflag || cp_pflag) {
/* timestamp and owner*/
if (!S_ISLNK(st.st_mode)) {
-   ut.actime = st.st_atime;
-   ut.modtime = st.st_mtime;
-   utime(s2, &ut);
+   times[0] = st.st_atim;
+   times[1] = st.st_mtim;
+   utimensat(AT_FDCWD, s2, times, 0);
 
if (chown(s2, st.st_uid, st.st_gid) < 0) {
weprintf("chown %s:", s2);
-- 
2.1.3.1.g339ec9c




[dev] Miscellaneous sbase issues

2015-04-26 Thread Michael Forney
Hi suckless,

I came across some issues in sbase whose solution wasn't immediately
apparent:

printf
--
Ignores flag characters '#', '0', '-', ' ', and '+', but is labeled as
POSIX compliant and complete, so this is presumably unintentional.

"git am" breaks without this functionality.

tar
---
Since fb1595a69c091a6f6a9303b1fab19360b876d114, tar calls remove(3) on
directories before extracting them. I'm not sure that it is reasonable
for tar to do this because users may want to re-extract archives, or
extract archives on top a directory structure that already exists.
Additionally, it is fairly common to find tar archives containing the
"." directory (possibly with a trailing '/'), which were constructed
using "tar -cf foo.tar .".

cat, tee

These utilities read from stdin using fread(3) into a buffer of size
BUFSIZ. However, fread will read until it fills up the entire buffer (or
hits EOF) before returning, causing noticeable delay when the input
comes from other programs or scripts.

To demonstrate this problem, compare the output of these commands:

  for i in $(seq 500) ; do printf 0123456789abcdef ; sleep 0.005 ; done
  for i in $(seq 500) ; do printf 0123456789abcdef ; sleep 0.005 ; done | cat
  for i in $(seq 500) ; do printf 0123456789abcdef ; sleep 0.005 ; done | tee

I considered fixing this by making the concat function take an fd
instead and make a single call to read(2), but this causes problems for
sponge, which uses a FILE * obtained from tmpfile(3) as both output and
input for concat. We could also use mkstemp(3) to return a file
descriptor, and use a FILE * from fdopen for writing, and the file
descriptor for reading, but this seems unclean to me.

Another option would be to use fgetc and fputc for the concat
implementation, and let libc take care of the buffering. I'm not sure if
this has any performance implications.


Thanks everyone for their work on sbase! It really has come a long way
in the last 6 months.


pgpDBGzDW2cHX.pgp
Description: PGP signature


[dev] [sdhcp] [PATCH 1/2] Only fork once

2015-04-26 Thread Michael Forney
---
 sdhcp.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/sdhcp.c b/sdhcp.c
index aa3cef2..9ff9baf 100644
--- a/sdhcp.c
+++ b/sdhcp.c
@@ -339,6 +339,8 @@ acceptlease(void)
 static void
 run(void)
 {
+   int forked = 0;
+
 #if 0
 InitReboot:
/* send DHCPrequest to old server */
@@ -390,8 +392,11 @@ Requesting:
}
 Bound:
fputs("Congrats! You should be on the 'net.\n", stdout);
-   if(fork())
-   exit(EXIT_SUCCESS);
+   if(!forked) {
+   if(fork())
+   exit(EXIT_SUCCESS);
+   forked = 1;
+   }
switch (dhcprecv()) {
case DHCPoffer:
case DHCPack:
-- 
2.1.3.1.g339ec9c




[dev] [sdhcp] [PATCH 2/2] Add flag to run in foreground

2015-04-26 Thread Michael Forney
---
 sdhcp.1 | 3 +++
 sdhcp.c | 8 ++--
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/sdhcp.1 b/sdhcp.1
index ef22689..d037624 100644
--- a/sdhcp.1
+++ b/sdhcp.1
@@ -28,6 +28,9 @@ don't change interface information such as an IP address.
 .TP
 .B "\-e program"
 run program. Variables will be set, see VARIABLES.
+.TP
+.B \-f
+run in foreground.
 .SH VARIABLES
 .LP
 The following variables are set:
diff --git a/sdhcp.c b/sdhcp.c
index 9ff9baf..01f0d23 100644
--- a/sdhcp.c
+++ b/sdhcp.c
@@ -97,6 +97,7 @@ static unsigned long t1;
 
 static int dflag = 1; /* change DNS in /etc/resolv.conf ? */
 static int iflag = 1; /* set IP ? */
+static int fflag = 0; /* run in foreground */
 
 #define IP(a,b,c,d) (unsigned char[4]){a,b,c,d}
 
@@ -392,7 +393,7 @@ Requesting:
}
 Bound:
fputs("Congrats! You should be on the 'net.\n", stdout);
-   if(!forked) {
+   if(!fflag && !forked) {
if(fork())
exit(EXIT_SUCCESS);
forked = 1;
@@ -439,7 +440,7 @@ static void cleanexit(int unused) {
 
 static void
 usage(void) {
-   eprintf("usage: sdhcp [-i] [-d] [-e program] [ifname] [clientid]\n");
+   eprintf("usage: sdhcp [-i] [-d] [-f] [-e program] [ifname] 
[clientid]\n");
 }
 
 int
@@ -460,6 +461,9 @@ main(int argc, char *argv[])
case 'd': /* don't update DNS in/etc/resolv.conf */
dflag = 0;
break;
+   case 'f': /* run in foreground */
+   fflag = 1;
+   break;
default:
usage();
break;
-- 
2.1.3.1.g339ec9c




[dev] [sbase] [PATCH] tr: Fix -c option when translating

2015-04-26 Thread Michael Forney
---
 tr.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tr.c b/tr.c
index 38ea6a3..ad5c690 100644
--- a/tr.c
+++ b/tr.c
@@ -221,6 +221,8 @@ read:
else
goto write;
}
+   if (cflag)
+   goto write;
for (m = 0; m < i; m++)
off1 += rangelen(set1[m]);
off1 += r - set1[m].start;
-- 
2.1.3.1.g339ec9c




Re: [dev] [sbase] [PATCH v2] rm: Fix exit status with -f for nonexistent paths

2015-03-01 Thread Michael Forney
On Sun, Mar 01, 2015 at 11:51:35PM +0100, FRIGN wrote:
> On Sun, 1 Mar 2015 14:44:12 -0800
> Michael Forney  wrote:
> > That looks good to me.
> 
> Thanks! Applied:
> http://git.2f30.org/sbase/commit/?id=48696d8c955db9d0621812aca7ef5caac727da31

I just realized that this could potentially mask an error from a
previous rm(). For example, if you run

  rm -f foo bar

where foo exists and can't be removed, but bar does not exist, this will
exit with status 0.

So I think we need to do

  if (!(rm_fflag && errno == ENOENT))
rm_status = 1;

instead of

  rm_status = !(rm_fflag && errno == ENOENT);



pgpCoZvTvauOb.pgp
Description: PGP signature


Re: [dev] [sbase] [PATCH v2] rm: Fix exit status with -f for nonexistent paths

2015-03-01 Thread Michael Forney
On Sun, Mar 01, 2015 at 11:23:28PM +0100, FRIGN wrote:
> I'd do it like this instead, makes it clearer that we're
> dealing with one special case:
> 
>   if (remove(path) < 0) {
>   if (!rm_fflag)
>   weprintf("remove %s:", path);
>   rm_status = !(rm_fflag && errno == ENOENT);
>   }
> 
> What do you think?

That looks good to me.



[dev] [sbase] [PATCH v2] rm: Fix exit status with -f for nonexistent paths

2015-03-01 Thread Michael Forney
Under the description for the -f option, POSIX says, "Do not modify the
exit status in the case of nonexistent operands".
---

Whoops, just realized that simply using the errno from the remove call is way
simpler.

 libutil/rm.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/libutil/rm.c b/libutil/rm.c
index 53ae3f2..54987e5 100644
--- a/libutil/rm.c
+++ b/libutil/rm.c
@@ -1,4 +1,5 @@
 /* See LICENSE file for copyright and license details. */
+#include 
 #include 
 
 #include "../fs.h"
@@ -14,8 +15,9 @@ rm(const char *path, int unused)
if (rm_rflag)
recurse(path, rm, 'P');
if (remove(path) < 0) {
+   if (!rm_fflag || errno != ENOENT)
+   rm_status = 1;
if (!rm_fflag)
weprintf("remove %s:", path);
-   rm_status = 1;
}
 }
-- 
2.1.3.1.g339ec9c




[dev] [sbase] [PATCH] rm: Fix exit status with -f for nonexistent paths

2015-03-01 Thread Michael Forney
Under the description for the -f option, POSIX says, "Do not modify the
exit status in the case of nonexistent operands".
---
 libutil/rm.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/libutil/rm.c b/libutil/rm.c
index 53ae3f2..30a1b41 100644
--- a/libutil/rm.c
+++ b/libutil/rm.c
@@ -1,5 +1,7 @@
 /* See LICENSE file for copyright and license details. */
+#include 
 #include 
+#include 
 
 #include "../fs.h"
 #include "../util.h"
@@ -11,11 +13,14 @@ int rm_status = 0;
 void
 rm(const char *path, int unused)
 {
+   struct stat st;
+
if (rm_rflag)
recurse(path, rm, 'P');
if (remove(path) < 0) {
if (!rm_fflag)
weprintf("remove %s:", path);
-   rm_status = 1;
+   if (!rm_fflag || stat(path, &st) < 0 && errno != ENOENT)
+   rm_status = 1;
}
 }
-- 
2.1.3.1.g339ec9c




Re: [dev] [sbase] [PATCH v3] ls: Handle symlinks to directories properly

2014-12-08 Thread Michael Forney
On Mon, Dec 08, 2014 at 04:21:30PM -0800, Eric Pruitt wrote:
> Unless I'm missing something, I still don't see anything in that patch
> pertaining to the interpretation of slashes.

I'm not sure what you're expecting...

When you lstat "foo/", where foo is a symlink to a directory, you look
up information about the directory, not the symlink. "ls" does not do
anything differently. You can also see that POSIX does not specify
anything related to interpretation of slashes in the specification of
the "ls" (because it do not need any sort of special interpretation).

See, this example (pruned for the system calls that matter)

$ strace ls -l foo
lstat("foo", {st_mode=S_IFLNK|0777, st_size=3, ...}) = 0
stat("foo", {st_mode=S_IFDIR|0700, st_size=4096, ...}) = 0
lrwxrwxrwx1 michael  michael   3 Dec 09 20:22 foo -> bar
$ strace ls -l foo/
lstat("foo/", {st_mode=S_IFDIR|0700, st_size=4096, ...}) = 0
-rw---1 michael  michael   0 Dec 09 20:23 hello
-rw---1 michael  michael   0 Dec 09 20:23 world
$




[dev] [sbase] [PATCH] cp: Rename -d option to -P

2014-12-07 Thread Michael Forney
The -d option is a GNU extension and is equivalent to its "-P
--preserve=links" options.

Since we don't implement the --preserve=links functionality anyway (it
means preserve hard links between files), just call it -P, which is
specified by POSIX.

Additionally, there is no need to check for cp_Pflag again before
copying the symlink itself because the only way the mode in the stat
will indicate a symlink is if we used lstat (which we only do if -P is
specified).
---
 cp.1 | 6 +++---
 cp.c | 6 +++---
 fs.h | 2 +-
 libutil/cp.c | 8 
 4 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/cp.1 b/cp.1
index f0f5b65..95f39c3 100644
--- a/cp.1
+++ b/cp.1
@@ -8,7 +8,7 @@ cp \- copy files and directories
 .RI [ name ]
 .P
 .B cp
-.RB [ \-adpRrv ]
+.RB [ \-aPpRrv ]
 .RI [ file ...]
 .RI [ directory ]
 .SH DESCRIPTION
@@ -21,8 +21,8 @@ they will be copied into the given directory.
 preserve mode, timestamp, links and permissions.
 Implies \-d, \-p, \-r.
 .TP
-.B \-d
-don't dereference links. preserve links.
+.B \-P
+don't dereference symbolic links.
 .TP
 .B \-p
 preserve mode, timestamp and permissions.
diff --git a/cp.c b/cp.c
index f1c3d9b..f3b91f1 100644
--- a/cp.c
+++ b/cp.c
@@ -19,10 +19,10 @@ main(int argc, char *argv[])
ARGBEGIN {
case 'a':
/* implies -dpr */
-   cp_aflag = cp_dflag = cp_pflag = cp_rflag = 1;
+   cp_aflag = cp_Pflag = cp_pflag = cp_rflag = 1;
break;
-   case 'd':
-   cp_dflag = 1;
+   case 'P':
+   cp_Pflag = 1;
break;
case 'p':
cp_pflag = 1;
diff --git a/fs.h b/fs.h
index 18b7f4d..4d65766 100644
--- a/fs.h
+++ b/fs.h
@@ -1,7 +1,7 @@
 /* See LICENSE file for copyright and license details. */
 extern int cp_aflag;
-extern int cp_dflag;
 extern int cp_fflag;
+extern int cp_Pflag;
 extern int cp_pflag;
 extern int cp_rflag;
 extern int cp_vflag;
diff --git a/libutil/cp.c b/libutil/cp.c
index f274475..d252e52 100644
--- a/libutil/cp.c
+++ b/libutil/cp.c
@@ -16,8 +16,8 @@
 #include "../util.h"
 
 int cp_aflag = 0;
-int cp_dflag = 0;
 int cp_fflag = 0;
+int cp_Pflag = 0;
 int cp_pflag = 0;
 int cp_rflag = 0;
 int cp_vflag = 0;
@@ -39,14 +39,14 @@ cp(const char *s1, const char *s2)
if (cp_vflag)
printf("'%s' -> '%s'\n", s1, s2);
 
-   r = cp_dflag ? lstat(s1, &st) : stat(s1, &st);
+   r = cp_Pflag ? lstat(s1, &st) : stat(s1, &st);
if (r < 0) {
-   weprintf("%s %s:", cp_dflag ? "lstat" : "stat", s1);
+   weprintf("%s %s:", cp_Pflag ? "lstat" : "stat", s1);
cp_status = 1;
return 0;
}
 
-   if (cp_dflag && S_ISLNK(st.st_mode)) {
+   if (S_ISLNK(st.st_mode)) {
if (readlink(s1, buf, sizeof(buf) - 1) >= 0) {
if (cp_fflag)
unlink(s2);
-- 
2.1.3.1.g339ec9c




[dev] [sbase] [PATCH] ls: Always leave room for the NULL byte in the link target

2014-12-07 Thread Michael Forney
Otherwise, if the length of the link target is the same as BUFSIZ, we
will try to write past the end of buf.
---
 ls.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ls.c b/ls.c
index b48391b..a2fb5cb 100644
--- a/ls.c
+++ b/ls.c
@@ -291,7 +291,7 @@ output(Entry *ent)
printf("%10lu ", (unsigned long)ent->size);
printf("%s %s%s", buf, ent->name, indicator(ent->mode));
if (S_ISLNK(ent->mode)) {
-   if ((len = readlink(ent->name, buf, sizeof buf)) < 0)
+   if ((len = readlink(ent->name, buf, sizeof buf - 1)) < 0)
eprintf("readlink %s:", ent->name);
buf[len] = '\0';
mkent(&entlnk, buf, Fflag);
-- 
2.1.3.1.g339ec9c




[dev] [sbase] [PATCH v3] ls: Handle symlinks to directories properly

2014-12-07 Thread Michael Forney
Also, implement the -H and -L options.
---
Again, not sure how to handle the long line.

 ls.1 |  9 -
 ls.c | 32 
 2 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/ls.1 b/ls.1
index ec61bee..792b07b 100644
--- a/ls.1
+++ b/ls.1
@@ -3,7 +3,7 @@
 ls \- list directory contents
 .SH SYNOPSIS
 .B ls
-.RB [ \-adFiltU ]
+.RB [ \-adFHhiLlrtU ]
 .RI [ file ...]
 .SH DESCRIPTION
 .B ls
@@ -20,12 +20,19 @@ lists directories themselves, not their contents.
 .B \-F
 append a file type indicator to files.
 .TP
+.B \-H
+list information about the targets of symbolic links specified on the command
+line instead of the links themselves.
+.TP
 .B \-h
 show filesizes in human\-readable format.
 .TP
 .B \-i
 print the index number of each file.
 .TP
+.B \-L
+list information about the targets of symbolic links instead of the links
+themselves.
 .B \-l
 lists detailed information about each file, including their type, permissions,
 links, owner, group, size, and modification time.
diff --git a/ls.c b/ls.c
index b48391b..24af998 100644
--- a/ls.c
+++ b/ls.c
@@ -14,7 +14,7 @@
 
 typedef struct {
char *name;
-   mode_t mode;
+   mode_t mode, tmode;
nlink_t nlink;
uid_t uid;
gid_t gid;
@@ -26,14 +26,16 @@ typedef struct {
 static int entcmp(const void *, const void *);
 static void ls(Entry *);
 static void lsdir(const char *);
-static void mkent(Entry *, char *, int);
+static void mkent(Entry *, char *, int, int);
 static void output(Entry *);
 
 static int aflag = 0;
 static int dflag = 0;
 static int Fflag = 0;
+static int Hflag = 0;
 static int hflag = 0;
 static int iflag = 0;
+static int Lflag = 0;
 static int lflag = 0;
 static int rflag = 0;
 static int tflag = 0;
@@ -66,12 +68,18 @@ main(int argc, char *argv[])
case 'F':
Fflag = 1;
break;
+   case 'H':
+   Hflag = 1;
+   break;
case 'h':
hflag = 1;
break;
case 'i':
iflag = 1;
break;
+   case 'L':
+   Lflag = 1;
+   break;
case 'l':
lflag = 1;
break;
@@ -95,7 +103,7 @@ main(int argc, char *argv[])
ents = emalloc(argc * sizeof(*ents));
 
for (i = 0; i < argc; i++)
-   mkent(&ents[i], argv[i], 1);
+   mkent(&ents[i], argv[i], 1, Hflag || Lflag);
qsort(ents, argc, sizeof *ents, entcmp);
for (i = 0; i < argc; i++)
ls(&ents[rflag ? argc-i-1 : i]);
@@ -117,7 +125,7 @@ entcmp(const void *va, const void *vb)
 static void
 ls(Entry *ent)
 {
-   if (S_ISDIR(ent->mode) && !dflag) {
+   if ((S_ISDIR(ent->mode) || (S_ISLNK(ent->mode) && S_ISDIR(ent->tmode) 
&& !Fflag && !lflag)) && !dflag) {
lsdir(ent->name);
} else {
output(ent);
@@ -151,13 +159,13 @@ lsdir(const char *path)
if (d->d_name[0] == '.' && !aflag)
continue;
if (Uflag){
-   mkent(&ent, d->d_name, Fflag || lflag || iflag);
+   mkent(&ent, d->d_name, Fflag || lflag || iflag, Lflag);
output(&ent);
} else {
ents = erealloc(ents, ++n * sizeof *ents);
p = emalloc((sz = strlen(d->d_name)+1));
memcpy(p, d->d_name, sz);
-   mkent(&ents[n-1], p, tflag || Fflag || lflag || iflag);
+   mkent(&ents[n-1], p, tflag || Fflag || lflag || iflag, 
Lflag);
}
}
closedir(dp);
@@ -175,15 +183,15 @@ lsdir(const char *path)
 }
 
 static void
-mkent(Entry *ent, char *path, int dostat)
+mkent(Entry *ent, char *path, int dostat, int follow)
 {
struct stat st;
 
ent->name   = path;
if (!dostat)
return;
-   if (lstat(path, &st) < 0)
-   eprintf("lstat %s:", path);
+   if ((follow ? stat : lstat)(path, &st) < 0)
+   eprintf("%s %s:", follow ? "stat" : "lstat", path);
ent->mode   = st.st_mode;
ent->nlink  = st.st_nlink;
ent->uid= st.st_uid;
@@ -191,6 +199,8 @@ mkent(Entry *ent, char *path, int dostat)
ent->size   = st.st_size;
ent->mtime  = st.st_mtime;
ent->ino= st.st_ino;
+   if (S_ISLNK(ent->mode))
+   ent->tmode = stat(path, &st) == 0 ? st.st_mode : 0;
 }
 
 static char *
@@ -225,7 +235,6 @@ output(Entry *ent)
struct passwd *pw;
char pwname[_SC_LOGIN_NAME_MAX];
char grname[_SC_LOGIN_NAME_MAX];
-   Entry entlnk;
 
if (iflag)
printf("%lu ", (unsigned long)ent->ino);
@@ -294,8 +303,7 @@ output(Entry *ent)
if ((len = readlink(ent->name, buf, sizeof buf)) < 0)
eprintf("readlink %s:", ent->name);
buf[len] = '\0'

Re: [dev] [sbase] [PATCH v2] ls: List directory contents if file is a symlink to a directory

2014-12-07 Thread Michael Forney
On Sun, Dec 07, 2014 at 03:43:36PM -0800, Eric Pruitt wrote:
> I don't know if this is the correct behavior. Whether or not a symlink
> to a directory has its contents shown with GNU ls depends on whether or
> not there's a slash present and the flags used:
> 
> playground$ mkdir AFolder
> playground$ touch AFolder/Horse
> playground$ ln -s AFolder SymbolicLinkToAFolder
> playground$ ls SymbolicLinkToAFolder
> Horse
> playground$ ls -l SymbolicLinkToAFolder
> lrwxrwxrwx 1 ericpruitt ericpruitt 7 Dec  7 15:35 SymbolicLinkToAFolder
> -> AFolder
> playground$ ls -l SymbolicLinkToAFolder/
> total 0
> -rw--- 1 ericpruitt ericpruitt 0 Dec  7 15:34 Horse
> 
> Personally, that "-l" made a difference surprised me, but prior to
> actually running the command, I would expect "ls ... $SYMLINK" to show
> the information for the symlink while "ls ... $SYMLINK/" to show the
> contents of the directory. If I recall correctly, historically in things
> like Sys V, whether or not a trailing slash was added to a directory
> used as a command line argument changed the behaviour of various tools.
> Check out http://unix.stackexchange.com/a/50522 which has a few links to
> the POSIX docs.

Actually, POSIX specifies this behavior (contents of symlink without -l,
symlink itself with -l):

  "If one or more of the -d, -F, or -l options are specified, and
   neither the -H nor the -L option is specified, for each operand that
   names a file of type symbolic link to a directory, ls shall write the
   name of the file as well as any requested, associated information. If
   none of the -d, -F, or -l options are specified, or the -H or -L
   options are specified, for each operand that names a file of type
   symbolic link to a directory, ls shall write the names of files
   contained within the directory as well as any requested, associated
   information."

I will update the patch to interact correctly with the -l and -F flags,
and maybe look at adding the -H and -L flags.




[dev] [sbase] [PATCH v2] ls: List directory contents if file is a symlink to a directory

2014-12-07 Thread Michael Forney
---
Not sure if you want to break up the long line. Up to you.

Another possibility is

if (S_ISLINK(ent->mode))
stat(path, &st);
ent->isdir  = S_ISDIR(st.st_mode);

which looks nicer, but I'm not sure if stat(2) is required to not modify the st
argument if it fails.

 ls.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/ls.c b/ls.c
index b48391b..a6e4309 100644
--- a/ls.c
+++ b/ls.c
@@ -21,6 +21,7 @@ typedef struct {
off_t size;
time_t mtime;
ino_t ino;
+   int isdir;
 } Entry;
 
 static int entcmp(const void *, const void *);
@@ -117,7 +118,7 @@ entcmp(const void *va, const void *vb)
 static void
 ls(Entry *ent)
 {
-   if (S_ISDIR(ent->mode) && !dflag) {
+   if (ent->isdir && !dflag) {
lsdir(ent->name);
} else {
output(ent);
@@ -191,6 +192,7 @@ mkent(Entry *ent, char *path, int dostat)
ent->size   = st.st_size;
ent->mtime  = st.st_mtime;
ent->ino= st.st_ino;
+   ent->isdir  = S_ISDIR(ent->mode) || S_ISLNK(ent->mode) && stat(path, 
&st) == 0 && S_ISDIR(st.st_mode);
 }
 
 static char *
-- 
2.1.3.1.g339ec9c




[dev] Re: [sbase] [PATCH] ls: List directory contents if file is a symlink to a directory

2014-12-07 Thread Michael Forney
On Sun, Dec 07, 2014 at 10:40:42PM +, Michael Forney wrote:
> ---
>  ls.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/ls.c b/ls.c
> index b48391b..90193cc 100644
> --- a/ls.c
> +++ b/ls.c
> @@ -21,6 +21,7 @@ typedef struct {
>   off_t size;
>   time_t mtime;
>   ino_t ino;
> + int isdir;
>  } Entry;
>  
>  static int entcmp(const void *, const void *);
> @@ -117,7 +118,7 @@ entcmp(const void *va, const void *vb)
>  static void
>  ls(Entry *ent)
>  {
> - if (S_ISDIR(ent->mode) && !dflag) {
> + if (ent->isdir && !dflag) {
>   lsdir(ent->name);
>   } else {
>   output(ent);
> @@ -191,6 +192,7 @@ mkent(Entry *ent, char *path, int dostat)
>   ent->size   = st.st_size;
>   ent->mtime  = st.st_mtime;
>   ent->ino= st.st_ino;
> + ent->isdir  = S_ISLNK(ent->mode) && stat(path, &st) == 0 && 
> S_ISDIR(st.st_mode);

Whoops, this should also have S_ISDIR(ent->mode) || ...

Will send a new patch shortly.



[dev] [sbase] [PATCH] ls: List directory contents if file is a symlink to a directory

2014-12-07 Thread Michael Forney
---
 ls.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/ls.c b/ls.c
index b48391b..90193cc 100644
--- a/ls.c
+++ b/ls.c
@@ -21,6 +21,7 @@ typedef struct {
off_t size;
time_t mtime;
ino_t ino;
+   int isdir;
 } Entry;
 
 static int entcmp(const void *, const void *);
@@ -117,7 +118,7 @@ entcmp(const void *va, const void *vb)
 static void
 ls(Entry *ent)
 {
-   if (S_ISDIR(ent->mode) && !dflag) {
+   if (ent->isdir && !dflag) {
lsdir(ent->name);
} else {
output(ent);
@@ -191,6 +192,7 @@ mkent(Entry *ent, char *path, int dostat)
ent->size   = st.st_size;
ent->mtime  = st.st_mtime;
ent->ino= st.st_ino;
+   ent->isdir  = S_ISLNK(ent->mode) && stat(path, &st) == 0 && 
S_ISDIR(st.st_mode);
 }
 
 static char *
-- 
2.1.3.1.g339ec9c




[dev] [sbase] [PATCH] ln: Add support for target directories

2014-11-23 Thread Michael Forney
Also, now that we are using {sym,}linkat, implement the trivial -L and
-P options.
---
 ln.1 | 11 +--
 ln.c | 53 ++---
 2 files changed, 47 insertions(+), 17 deletions(-)

diff --git a/ln.1 b/ln.1
index 4205ea7..3b1ac98 100644
--- a/ln.1
+++ b/ln.1
@@ -3,12 +3,12 @@
 ln \- make links between files
 .SH SYNOPSIS
 .B ln
-.RB [ \-fs ]
+.RB [ \-LPfs ]
 .I file
 .RI [ name ]
 .P
 .B ln
-.RB [ \-fs ]
+.RB [ \-LPfs ]
 .RI [ file ...]
 .RI [ directory ]
 .SH DESCRIPTION
@@ -18,6 +18,13 @@ it is linked into the current directory.  If multiple files 
are listed they will
 be linked into the given directory.
 .SH OPTIONS
 .TP
+.B \-L
+create links to the files referenced by symbolic link source files (default
+behavior).
+.TP
+.B \-P
+create links to symbolic link source files themselves.
+.TP
 .B \-f
 remove existing destinations.
 .TP
diff --git a/ln.c b/ln.c
index d8809ce..0a5bf18 100644
--- a/ln.c
+++ b/ln.c
@@ -1,9 +1,11 @@
 /* See LICENSE file for copyright and license details. */
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "util.h"
@@ -11,16 +13,20 @@
 static void
 usage(void)
 {
-   eprintf("usage: %s [-fs] target [linkname]\n", argv0);
+   eprintf("usage: %1$s [-LPfs] target [linkname]\n"
+   "   %1$s [-LPfs] target... directory\n", argv0);
 }
 
 int
 main(int argc, char *argv[])
 {
-   int (*flink)(const char *, const char *);
char *fname, *to;
int sflag = 0;
int fflag = 0;
+   int hasto = 0;
+   int dirfd = AT_FDCWD;
+   int flags = AT_SYMLINK_FOLLOW;
+   struct stat st;
 
ARGBEGIN {
case 'f':
@@ -29,27 +35,44 @@ main(int argc, char *argv[])
case 's':
sflag = 1;
break;
+   case 'L':
+   flags |= AT_SYMLINK_FOLLOW;
+   break;
+   case 'P':
+   flags &= ~AT_SYMLINK_FOLLOW;
+   break;
default:
usage();
} ARGEND;
 
-   if (argc == 0 || argc > 2)
+   if (argc == 0)
usage();
 
-   if (sflag) {
-   flink = symlink;
-   fname = "symlink";
-   } else {
-   flink = link;
-   fname = "link";
-   }
+   fname = sflag ? "symlink" : "link";
 
-   to = argc < 2 ? basename(argv[0]) : argv[1];
+   if (argc >= 2) {
+   if (stat(argv[argc - 1], &st) == 0 && S_ISDIR(st.st_mode)) {
+   if ((dirfd = open(argv[argc - 1], O_RDONLY)) < 0)
+   eprintf("open:");
+   } else if (argc == 2) {
+   to = argv[1];
+   hasto = 1;
+   } else {
+   eprintf("destination is not a directory\n");
+   }
+   argc--;
+   }
 
-   if (fflag)
-   remove(to);
-   if (flink(argv[0], to) < 0)
-   eprintf("%s %s <- %s:", fname, argv[0], to);
+   for (; argc > 0; argc--, argv++) {
+   if (!hasto)
+   to = basename(argv[0]);
+   if (fflag)
+   remove(to);
+   if ((!sflag ? linkat(AT_FDCWD, argv[0], dirfd, to, flags)
+   : symlinkat(argv[0], dirfd, to)) < 0) {
+   eprintf("%s %s <- %s:", fname, argv[0], to);
+   }
+   }
 
return 0;
 }
-- 
2.1.3.1.g339ec9c




[dev] [sbase] [PATCH] sort: Implement -c and -C flags

2014-11-23 Thread Michael Forney
---
 sort.1 | 11 +++
 sort.c | 57 +++--
 2 files changed, 58 insertions(+), 10 deletions(-)

diff --git a/sort.1 b/sort.1
index 12fb95d..71c8154 100644
--- a/sort.1
+++ b/sort.1
@@ -15,9 +15,20 @@ writes the sorted concatenation of the given files to 
stdout.  If no file is
 given, sort reads from stdin.
 .SH OPTIONS
 .TP
+.B \-C
+check that the concatenation of the given files is sorted rather than sorting
+them.  In this mode, no output is printed to stdout, and the exit status
+indicates the result of the check.
+.TP
 .B \-b
 skip leading whitespace of columns when sorting.
 .TP
+.B \-c
+the same as
+.B \-C
+except that when disorder is detected, a message is printed to stderr
+indicating the location of the disorder.
+.TP
 .BI \-k \ key
 specifies a key definition of the form
 .BR S [. s ][ f ][, E [. e ][ f ]]
diff --git a/sort.c b/sort.c
index 2a89870..c4cd81f 100644
--- a/sort.c
+++ b/sort.c
@@ -32,6 +32,7 @@ static struct kdlist *head = NULL;
 static struct kdlist *tail = NULL;
 
 static void addkeydef(char *, int);
+static void check(FILE *);
 static void freelist(void);
 static int linecmp(const char **, const char **);
 static char *skipblank(char *);
@@ -40,13 +41,13 @@ static int parse_keydef(struct keydef *, char *, int);
 static char *nextcol(char *);
 static char *columns(char *, const struct keydef *);
 
-static int uflag = 0;
+static int Cflag = 0, cflag = 0, uflag = 0;
 static char *fieldsep = NULL;
 
 static void
 usage(void)
 {
-   enprintf(2, "usage: %s [-bnru] [-t delim] [-k def]... [file...]\n", 
argv0);
+   enprintf(2, "usage: %s [-Cbcnru] [-t delim] [-k def]... [file...]\n", 
argv0);
 }
 
 int
@@ -58,9 +59,15 @@ main(int argc, char *argv[])
int global_flags = 0;
 
ARGBEGIN {
+   case 'C':
+   Cflag = 1;
+   break;
case 'b':
global_flags |= MOD_STARTB | MOD_ENDB;
break;
+   case 'c':
+   cflag = 1;
+   break;
case 'k':
addkeydef(EARGF(usage()), global_flags);
break;
@@ -87,22 +94,33 @@ main(int argc, char *argv[])
addkeydef("1", global_flags & MOD_R);
 
if (argc == 0) {
-   getlines(stdin, &linebuf);
+   if (Cflag || cflag) {
+   check(stdin);
+   } else {
+   getlines(stdin, &linebuf);
+   }
} else for (; argc > 0; argc--, argv++) {
if (!(fp = fopen(argv[0], "r"))) {
enprintf(2, "fopen %s:", argv[0]);
continue;
}
-   getlines(fp, &linebuf);
+   if (Cflag || cflag) {
+   check(fp);
+   } else {
+   getlines(fp, &linebuf);
+   }
fclose(fp);
}
-   qsort(linebuf.lines, linebuf.nlines, sizeof *linebuf.lines,
-   (int (*)(const void *, const void *))linecmp);
 
-   for (i = 0; i < linebuf.nlines; i++) {
-   if (!uflag || i == 0 || linecmp((const char 
**)&linebuf.lines[i],
-   (const char **)&linebuf.lines[i-1])) {
-   fputs(linebuf.lines[i], stdout);
+   if (!Cflag && !cflag) {
+   qsort(linebuf.lines, linebuf.nlines, sizeof *linebuf.lines,
+   (int (*)(const void *, const void *))linecmp);
+
+   for (i = 0; i < linebuf.nlines; i++) {
+   if (!uflag || i == 0 || linecmp((const char 
**)&linebuf.lines[i],
+   (const char 
**)&linebuf.lines[i-1])) {
+   fputs(linebuf.lines[i], stdout);
+   }
}
}
 
@@ -129,6 +147,25 @@ addkeydef(char *def, int flags)
 }
 
 static void
+check(FILE *fp)
+{
+   static struct { char *buf; size_t size; } prev, cur, tmp;
+
+   if (!prev.buf)
+   getline(&prev.buf, &prev.size, fp);
+   while (getline(&cur.buf, &cur.size, fp) != -1) {
+   if (uflag > linecmp((const char **) &cur.buf, (const char **) 
&prev.buf)) {
+   if (!Cflag)
+   weprintf("disorder: %s", cur.buf);
+   exit(1);
+   }
+   tmp = cur;
+   cur = prev;
+   prev = tmp;
+   }
+}
+
+static void
 freelist(void)
 {
struct kdlist *node;
-- 
2.1.3.1.g339ec9c




[dev] [sbase] [PATCH 2/2] chown: Support numeric uids/gids

2014-11-02 Thread Michael Forney
---
 chown.c | 25 -
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/chown.c b/chown.c
index 3fd5f87..5d57801 100644
--- a/chown.c
+++ b/chown.c
@@ -11,8 +11,8 @@
 static void chownpwgr(const char *);
 
 static bool rflag = false;
-static struct passwd *pw = NULL;
-static struct group *gr = NULL;
+static uid_t uid = -1;
+static gid_t gid = -1;
 static int ret = 0;
 
 static void
@@ -24,7 +24,9 @@ usage(void)
 int
 main(int argc, char *argv[])
 {
-   char *owner, *group;
+   char *owner, *group, *end;
+   struct passwd *pw;
+   struct group *gr;
 
ARGBEGIN {
case 'R':
@@ -47,20 +49,26 @@ main(int argc, char *argv[])
if(owner && *owner) {
errno = 0;
pw = getpwnam(owner);
-   if (!pw) {
+   if(pw) {
+   uid = pw->pw_uid;
+   } else {
if(errno != 0)
eprintf("getpwnam %s:", owner);
-   else
+   uid = strtoul(owner, &end, 10);
+   if(*end != '\0')
eprintf("getpwnam %s: no such user\n", owner);
}
}
if(group && *group) {
errno = 0;
gr = getgrnam(group);
-   if (!gr) {
+   if(gr) {
+   gid = gr->gr_gid;
+   } else {
if(errno != 0)
eprintf("getgrnam %s:", group);
-   else
+   gid = strtoul(group, &end, 10);
+   if(*end != '\0')
eprintf("getgrnam %s: no such group\n", group);
}
}
@@ -73,8 +81,7 @@ main(int argc, char *argv[])
 void
 chownpwgr(const char *path)
 {
-   if(chown(path, pw ? pw->pw_uid : (uid_t)-1,
-  gr ? gr->gr_gid : (gid_t)-1) == -1) {
+   if(chown(path, uid, gid) == -1) {
weprintf("chown %s:", path);
ret = 1;
}
-- 
2.1.3.1.g339ec9c




[dev] [sbase] [PATCH 1/2] Fix symbolic mode parsing in parsemode

2014-11-02 Thread Michael Forney
I found quite a lot of bugs, so I ended up pretty much rewriting as I
followed the spec¹.

Now, it works as follows:

- Determine a mask (who) of bits that can be modified for the subsequent
  operations. If none are specified, select all file mode bits.
- In a loop, determine which operation (+, -, =) to apply.
- If the next character is a permcopy (u, g, o), set the new permissions
  (perm) corresponding to the bits set in the user, group or other parts
  of the existing mode.
- Otherwise, set the new permissions by looping through the next r, w,
  x, s, t characters.
- Now, the set of bits we want to add or remove is (who & perm). Set or
  remove these bits according the the operation (first clearing the
  appropriate bits if the operation is =).
- Continue from the top if the next character is a comma, otherwise,
  process the next operation.

I tested this on some made up inputs, and I believe it is working
correctly now:

  parsemode("g+w", 0644, 0),before: 0606, now: 0664, fixed
  parsemode("u+rx", 0222, 0),   before: 0077, now: 0722, fixed
  parsemode("+x", 0644, 023),   before: 0754, now: 0754, still works
  parsemode("+w", 0444, 022),   before: 0644, now: 0644, still works
  parsemode("+w", 0444, 0), before: 0666, now: 0666, still works
  parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed
  parsemode("u+s", 0755, 0),before: 0055, now: 4755, fixed
  parsemode("g+s", 0755, 0),before: 0705, now: 2755, fixed
  parsemode("g=u", 0700, 0),before: , now: 0770, fixed
  parsemode("go=u-w", 0700, 0), before: , now: 0755, fixed
  parsemode("o+u-g", 0641, 0),  before: , now: 0643, fixed
  parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed
  parsemode(",", 0654, 0), before: error, now: error, still works

¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
---
 util/mode.c | 129 
 1 file changed, 95 insertions(+), 34 deletions(-)

diff --git a/util/mode.c b/util/mode.c
index 4506023..c022e8d 100644
--- a/util/mode.c
+++ b/util/mode.c
@@ -16,9 +16,9 @@ mode_t
 parsemode(const char *str, mode_t mode, mode_t mask)
 {
char *end;
-   const char *p;
-   int octal, op = '+';
-   mode_t gmask = 0, m = 0;
+   const char *p = str;
+   int octal, op;
+   mode_t who, perm, clear;
 
octal = strtol(str, &end, 8);
if(*end == '\0') {
@@ -41,61 +41,122 @@ parsemode(const char *str, mode_t mode, mode_t mask)
if(octal & 1) mode |= S_IXOTH;
return mode;
}
-   for(p = str; *p; p++) {
+next:
+   /* first, determine which bits we will be modifying */
+   for(who = 0; *p; p++) {
switch(*p) {
/* masks */
case 'u':
-   gmask |= S_IRWXU;
-   break;
+   who |= S_IRWXU|S_ISUID;
+   continue;
case 'g':
-   gmask |= S_IRWXG;
-   break;
+   who |= S_IRWXG|S_ISGID;
+   continue;
case 'o':
-   gmask |= S_IRWXO;
-   break;
+   who |= S_IRWXO;
+   continue;
case 'a':
-   gmask |= S_IRWXU|S_IRWXG|S_IRWXO;
-   break;
+   who |= S_IRWXU|S_ISUID|S_IRWXG|S_ISGID|S_IRWXO;
+   continue;
+   }
+   break;
+   }
+   if(who) {
+   clear = who;
+   } else {
+   clear = S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO;
+   who = ~mask;
+   }
+   while(*p) {
+   switch(*p) {
/* opers */
case '=':
case '+':
case '-':
op = (int)*p;
break;
-   /* modes */
-   case 'r':
-   m |= S_IRUSR|S_IRGRP|S_IROTH;
-   break;
-   case 'w':
-   m |= S_IWUSR|S_IWGRP|S_IWOTH;
-   break;
-   case 'x':
-   m |= S_IXUSR|S_IXGRP|S_IXOTH;
+   default:
+   eprintf("%s: invalid mode\n", str);
+   return -1;
+   }
+
+   perm = 0;
+   switch(*++p) {
+   /* copy */
+   case 'u':
+   if(mode & S_IRUSR)
+   perm |= S_IRUSR|S_IRGRP|S_IROTH;
+   if(mode & S_IWUSR)
+   perm |= S_IWUSR|S_IWGRP|S_IWOTH;
+   if(mode & S_IXUSR)
+   perm |= S_IXUSR|S_IXGRP|S_IXOTH;
+   if(mode & S_ISUID)
+  

[dev] [sbase] [PATCH 2/2] grep: Fix -c flag

2014-11-01 Thread Michael Forney
---
 grep.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/grep.c b/grep.c
index 1376513..489f6e7 100644
--- a/grep.c
+++ b/grep.c
@@ -42,11 +42,11 @@ main(int argc, char *argv[])
case 'E':
flags |= REG_EXTENDED;
break;
-   case 'c':
case 'e':
addpattern(EARGF(usage()));
eflag = true;
break;
+   case 'c':
case 'l':
case 'n':
case 'q':
-- 
2.1.3.1.g339ec9c




[dev] [sbase] [PATCH 1/2] grep: Remove newlines before matching a line

2014-11-01 Thread Michael Forney
Otherwise, a pattern with a '$' anchor will never match and POSIX says that

  "By default, an input line shall be selected if any pattern ... matches any
   part of the line excluding the terminating "
---
 grep.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/grep.c b/grep.c
index 715f864..1376513 100644
--- a/grep.c
+++ b/grep.c
@@ -129,6 +129,9 @@ grep(FILE *fp, const char *str)
int match = NoMatch;
 
for(n = 1; (len = agetline(&buf, &size, fp)) != -1; n++) {
+   /* Remove the trailing newline if one is present. */
+   if (len && buf[len - 1] == '\n')
+   buf[len - 1] = '\0';
for(pnode = phead; pnode; pnode = pnode->next) {
if(regexec(&pnode->preg, buf, 0, NULL, 0) ^ vflag)
continue;
@@ -146,9 +149,7 @@ grep(FILE *fp, const char *str)
printf("%s:", str);
if(mode == 'n')
printf("%ld:", n);
-   printf("%s", buf);
-   if(len && buf[len - 1] != '\n')
-   putchar('\n');
+   puts(buf);
break;
}
match = Match;
-- 
2.1.3.1.g339ec9c




Re: [dev] [sbase] [PATCH 1/4] tar: Don't crash when get{pw,gr}uid fails

2014-11-01 Thread Michael Forney
On Sat, Nov 01, 2014 at 08:57:12PM +, Dimitris Papastamos wrote:
> On Sat, Nov 01, 2014 at 08:36:37PM +0000, Michael Forney wrote:
> > -   snprintf(h->uname, sizeof h->uname, "%s", pw->pw_name);
> > -   snprintf(h->gname, sizeof h->gname, "%s", gr->gr_name);
> > +   snprintf(h->uname, sizeof h->uname, "%s", pw ? pw->pw_name : "");
> > +   snprintf(h->gname, sizeof h->gname, "%s", gr ? gr->gr_name : "");
> 
> The patches look good, thanks!
> 
> Just a small clarification on this one, do other tar implementations
> do the same here?

It looks like GNU tar does¹, but BSD tar uses the string
representation of the UID/GID.

¹ http://git.savannah.gnu.org/cgit/tar.git/tree/src/names.c#n66

-- 
Michael Forney 


pgpemX9fk9wLs.pgp
Description: PGP signature


[dev] [sbase] [PATCH 1/4] tar: Don't crash when get{pw,gr}uid fails

2014-11-01 Thread Michael Forney
---
 tar.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tar.c b/tar.c
index 4f4abff..c18d89e 100644
--- a/tar.c
+++ b/tar.c
@@ -177,8 +177,8 @@ archive(const char* path)
putoctal(h->mtime, (unsigned)st.st_mtime, sizeof h->mtime);
memcpy(h->magic,   "ustar",   sizeof h->magic);
memcpy(h->version, "00",  sizeof h->version);
-   snprintf(h->uname, sizeof h->uname, "%s", pw->pw_name);
-   snprintf(h->gname, sizeof h->gname, "%s", gr->gr_name);
+   snprintf(h->uname, sizeof h->uname, "%s", pw ? pw->pw_name : "");
+   snprintf(h->gname, sizeof h->gname, "%s", gr ? gr->gr_name : "");
 
mode = st.st_mode;
if(S_ISREG(mode)) {
-- 
2.1.3.1.g339ec9c




[dev] [sbase] [PATCH 4/4] tar: Handle archives with the prefix field

2014-11-01 Thread Michael Forney
Also, handle names and prefixes that fill the entire field (and have no
NUL byte) by using a precision specifier.
---
 tar.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/tar.c b/tar.c
index 47d2334..7588a41 100644
--- a/tar.c
+++ b/tar.c
@@ -29,6 +29,7 @@ struct Header {
char gname[32];
char major[8];
char minor[8];
+   char prefix[155];
 };
 
 enum {
@@ -317,11 +318,14 @@ c(const char * path)
 static void
 xt(int (*fn)(char*, int, char[Blksiz]))
 {
-   char b[Blksiz], fname[101];
+   char b[Blksiz], fname[257], *s;
Header *h = (void*)b;
 
while(fread(b, Blksiz, 1, tarfile) && h->name[0] != '\0') {
-   snprintf(fname, sizeof fname, "%s", h->name);
+   s = fname;
+   if (h->prefix[0] != '\0')
+   s += sprintf(s, "%.*s/", (int)sizeof h->prefix, 
h->prefix);
+   sprintf(s, "%.*s", (int)sizeof h->name, h->name);
fn(fname, strtol(h->size, 0, 8), b);
}
 }
-- 
2.1.3.1.g339ec9c




[dev] [sbase] [PATCH 3/4] tar: Implement -m flag

2014-11-01 Thread Michael Forney
This changes the default behavior to adjust mtimes to what is present in
the file header.
---
 tar.c | 25 ++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/tar.c b/tar.c
index 7bd709d..47d2334 100644
--- a/tar.c
+++ b/tar.c
@@ -2,9 +2,11 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -49,13 +51,15 @@ static FILE *tarfile;
 static ino_t tarinode;
 static dev_t tardev;
 
+static bool mflag = false;
+
 static void
 usage(void)
 {
-   eprintf("usage: tar [-f tarfile] [-C dir] [-]x|t\n"
+   eprintf("usage: tar [-f tarfile] [-C dir] [-]x[m]|t\n"
"   tar [-f tarfile] [-C dir] [-]c dir\n"
"   tar [-C dir] cf tarfile dir\n"
-   "   tar [-C dir] x|tf tarfile\n");
+   "   tar [-C dir] x[m]|tf tarfile\n");
 }
 
 int
@@ -79,6 +83,9 @@ main(int argc, char *argv[])
case 'f':
file = EARGF(usage());
break;
+   case 'm':
+   mflag = true;
+   break;
default:
usage();
} ARGEND;
@@ -108,6 +115,9 @@ main(int argc, char *argv[])
argc--, argv++;
dir = argv[0];
break;
+   case 'm':
+   mflag = true;
+   break;
default:
usage();
}
@@ -224,9 +234,12 @@ unarchive(char *fname, int l, char b[Blksiz])
 {
char lname[101];
FILE *f = NULL;
-   unsigned long  mode, major, minor, type;
+   unsigned long  mode, major, minor, type, mtime;
+   struct timeval times[2] = {0};
Header *h = (void*)b;
 
+   if(!mflag)
+   mtime = strtoul(h->mtime, 0, 8);
unlink(fname);
switch(h->type) {
case REG:
@@ -276,6 +289,12 @@ unarchive(char *fname, int l, char b[Blksiz])
}
if(f)
fclose(f);
+
+   if(!mflag) {
+   times[0].tv_sec = times[1].tv_sec = mtime;
+   if(utimes(fname, times))
+   perror(fname);
+   }
return 0;
 }
 
-- 
2.1.3.1.g339ec9c




[dev] [sbase] [PATCH 2/4] tar: Support typeflag '\0' when extracting

2014-11-01 Thread Michael Forney
POSIX recommends that "For backwards-compatibility, a typeflag value of
binary zero ( '\0' ) should be recognized as meaning a regular file when
extracting files from the archive".
---
 tar.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tar.c b/tar.c
index c18d89e..7bd709d 100644
--- a/tar.c
+++ b/tar.c
@@ -34,7 +34,7 @@ enum {
 };
 
 enum Type {
-   REG = '0', HARDLINK = '1', SYMLINK = '2', CHARDEV = '3',
+   REG = '0', AREG = '\0', HARDLINK = '1', SYMLINK = '2', CHARDEV = '3',
BLOCKDEV = '4', DIRECTORY = '5', FIFO = '6'
 };
 
@@ -230,6 +230,7 @@ unarchive(char *fname, int l, char b[Blksiz])
unlink(fname);
switch(h->type) {
case REG:
+   case AREG:
mode = strtoul(h->mode, 0, 8);
if(!(f = fopen(fname, "w")) || chmod(fname, mode))
perror(fname);
-- 
2.1.3.1.g339ec9c




Re: [dev] [st] will global-less changes be wanted upstream?

2014-08-17 Thread Michael Forney
On Sat, Aug 16, 2014 at 06:32:01PM -0500, Steven Degutis wrote:
> > What is the point?
> > One obvious cons is that it will bloat the code, make it less readable.
> 
> First of all, I would not agree that it would bloat the code or make
> it less readable. In fact I think it will increase readability, as
> object structure and hierarchy will be more readily apparent. Plus, it
> would make for a more clean and obvious separation of
> responsibilities, such as terminal logic and logic for drawing to the
> screen, &c.
> 
> As a consequence, it might become easier for contributions to my fork
> of the terminal logic (i.e. if my users submit bug fixes or new
> features, &c.) to be merged upstream to st, where they would also be
> relevant.

I am interested in a separation of terminal and windowing system logic
for my wayland port[0] of st.

That said, I don't really see how moving globals into a Term structure
would help with this. I think you could accomplish this by moving any
X-related code to an x.c, and then you could drop in a wayland.c or
whatever.c, and have config.mk choose which one gets built into st.

I think it would also be beneficial because it is difficult (at least
for me) to keep track of a single ~4k line c file.

[0]: https://github.com/michaelforney/st.git



[dev] [st] [PATCH] Fix disabling of bold and fastblink

2014-07-26 Thread Michael Forney
According to ECMA-48¹ 8.3.117, an attribute value of 21 is "doubly
underlined", while 22 is "normal colour or normal intensity (neither
bold nor faint)".

Additionally, 25 is "steady (not blinking)", which likely means neither
slow blink nor fast blink.

¹: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf
---
 st.c | 10 ++
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/st.c b/st.c
index 546db41..0c917fd 100644
--- a/st.c
+++ b/st.c
@@ -1718,11 +1718,8 @@ tsetattr(int *attr, int l) {
case 9:
term.c.attr.mode |= ATTR_STRUCK;
break;
-   case 21:
-   term.c.attr.mode &= ~ATTR_BOLD;
-   break;
case 22:
-   term.c.attr.mode &= ~ATTR_FAINT;
+   term.c.attr.mode &= ~(ATTR_BOLD | ATTR_FAINT);
break;
case 23:
term.c.attr.mode &= ~ATTR_ITALIC;
@@ -1731,10 +1728,7 @@ tsetattr(int *attr, int l) {
term.c.attr.mode &= ~ATTR_UNDERLINE;
break;
case 25:
-   term.c.attr.mode &= ~ATTR_BLINK;
-   break;
-   case 26:
-   term.c.attr.mode &= ~ATTR_FASTBLINK;
+   term.c.attr.mode &= ~(ATTR_BLINK | ATTR_FASTBLINK);
break;
case 27:
term.c.attr.mode &= ~ATTR_REVERSE;
-- 
1.8.5.1




Re: [dev] swc: A small Wayland compositor

2014-01-29 Thread Michael Forney
On Sun, 26 Jan 2014 02:09:31 +0100, Markus Teich  
wrote:
> Heyho,
> 
> why do you not put the VT switching and input dev fd handling code into swc. 
> In
> this case the developer implementing a wm would have to do priviledge 
> dropping.
> This leads to one suid executable per wm without the need of a launcher. Am I
> missing something here?

Hi Markus,

The VT/TTY related code could go into swc, but having the window manager
drop privileges by itself won't work because it needs those again to
reopen input devices and regain DRM master when it's VT is activated
again. Also, it is quite handy to have your VT restored upon a crash
(instead of leaving it in graphics mode with the keyboard turned off).

On Sun, 26 Jan 2014 19:06:21 +0100, FRIGN  wrote:
> Why not specify this part in a config.h? Given the resulting wm is very
> small, this suckless-concept applied would be very convenient.

If I do end up adding such a list of allowed display servers, this does
seem like a good way to do it.

In any case, I think that this issue is fairly minor (at first glance,
it looks like systemd's logind acts the same way as swc-launch with
respect to opening and revoking devices) and for now I will probably
leave it as-is. As swc matures, we could revisit this if it does present
any problems.

-- 
Michael Forney 



Re: [dev] swc: A small Wayland compositor

2014-01-25 Thread Michael Forney
On Fri, 24 Jan 2014 09:23:20 +0100, Silvan Jegen  wrote:
> > This is very exciting.  I hope to play with this in the next few days.
> 
> I agree! I hope I'll find the time to look into the code base some

I've added a minimal example window manager in example/. It can be built
with "make example", and run with "launch/swc-launch example/wm". Note
that swc-launch needs either setuid root or to be run as root in order
to open input devices and to obtain DRM modesetting privileges.

Possible security concern: swc-launch passes opened input device file
descriptors to the user-specified display server process (which is run
with reduced privileges). However, it also switches to a new unused VT,
and revokes them when this VT is switched away from. One potential issue
with this is that it doesn't prevent a malicious program from pretending
to be swc-launch and starting a trusted display server to appear normal,
but underneath intercept any key presses. Though, I'm also not sure that
the situation is any better on X ("xev -id window-id" can dump input
events sent to window-id).

Weston solves this problem by hardcoding the display server path in
weston-launch. For swc, this would imply a separate launcher program for
each window manager, which doesn't seem like a good solution to me. On a
single-user development machine, it is quite convenient to be able to
run, for example, "swc-launch -- valgrind example/wm" to debug crashes.
However, I do see the potential risk. Another solution could be having a
configuration file in /etc containing a list of allowed display servers.

Thoughts?

-- 
Michael Forney 



[dev] swc: A small Wayland compositor

2014-01-23 Thread Michael Forney
Hi suckless,

As discussed in the previous thread (swc library to implement dwm under
Wayland), I've been working on a Wayland compositor library, and after
several redesigns, I'm pretty happy with where it is now.

You can find the source here: https://github.com/michaelforney/swc

There is still some more work to be done, in particular moving/resizing
windows with the mouse, and more careful handling of special window
states (for example transient and fullscreen). However, for basic usage
it should work fine.

Here is the current output of sloccount:

SLOCDirectory   SLOC-by-Language (Sorted)
5801libswc  ansic=5801
533 launch  ansic=533
409 cursor  ansic=409

launch/ contains code for swc-launch, a privileged launcher that handles
VTs, managing DRM master, and opening/revoking input devices. cursor/
contains a program taken from wayland to extract cursors from the X
server cursor font.

As far as dependencies go, currently you need wayland, libdrm, libevdev,
libxkbcommon, pixman, and wld[0]. wld contains the buffer management and
rendering code used by swc and Wayland versions of st and dmenu.

Optionally, you can use libudev for input hotplugging. This is the only
way I know to accomplish this, and I am open to suggestions for
alternatives (I'd still like to remain compatible with systems running
udevd though).

I'd also like suggestions for how to deal with configuration for things
like what settings to use for XKB (keyboard layout, etc). This is a
per-user setting, so I don't think setting it in a config.h would be
appropriate.

I have not begun any process of porting/rewriting dwm to use swc. I
figured I'd see where people want to go from here. One potential
obstacle that might show up is the status bar. Since with swc the window
manager is in the same process as the compositor, currently the status
bar would have to go in to a separate process. I accomplished this in
the video below by adding a protocol extension which can notify clients
when certain things happen in the window manager (like workspace or
focus change). I'm not sure if this is the best approach though.

I made a demo video showing some of swc's features (as well as Wayland
st and dmenu) here: http://www.youtube.com/watch?v=5thcLnLHkjs&hd=1

The window manager used in the video is one that I started quite a while
ago, which I hacked up to use swc instead. It suits my needs for
developing swc, but I'd like to see what others can come up with! The
public API is available in swc.h[1].

Comments, questions, and criticism are welcome! You can find me on
freenode or OFTC under the nick tridactyla.

[0]: https://github.com/michaelforney/wld
[1]: https://github.com/michaelforney/swc/blob/master/libswc/swc.h

-- 
Michael Forney 



Re: swc library to implement dwm under Wayland (was Re: [dev] gtk3 support for surf?)

2014-01-14 Thread Michael Forney
On Tue, 14 Jan 2014 20:41:40 +0100, Hadrian Węgrzynowski  
wrote:
> EGL as API is quite lean. There could be small implementation not
> depending on Mesa 3D.
> 
> Is there another problem with EGL?

EGL is fine, but it implies an implementation of OpenGL, which would be
quite complicated to implement.

> I am just curious:
> 1. Can Wayland clients use just simple blitting without special kernel
> infrastructures?

Yes, there is an interface wl_shm in the core protocol which allows
clients to create a shared memory buffer, render to it by whatever means
it wants, and then pass the file descriptor to the server.

> 2. Can Wayland Compositor work without special kernel infrastructures?

The protocol allows it, but at some stage your screen buffer needs to
get scanned out to your monitor, which requires some sort of kernel
interface.

> 3. Are Wayland clients using evdev or is it just for server?

Just the server. Clients receive input events via the wl_keyboard and
wl_pointer interfaces.

> 4. Does anybody know how good is pixman library (AFAIK software renderer
> used by Weston)?

I've found that while it isn't documented that well, it is very useful
and well optimized (from what I can tell). Text rendering was a bit
tough to get working because you have to do glyph arrangement and
rendering yourself (probably using FreeType).

-- 
Michael Forney 



Re: swc library to implement dwm under Wayland (was Re: [dev] gtk3 support for surf?)

2014-01-14 Thread Michael Forney
ager can
specify a border width and color for each window, just like in X. My st
and dmenu ports do nothing in terms of borders/window decorations (same
as they currently work in X).

Now, as far as other applications go, Gtk+ currently draws these massive
decorations around everything when running under Wayland. Given that the
Qt/KDE guys want to use server-side decorations, I'm sure that there
will be some setting you can disable to get rid of the borders (maybe
there already is, I haven't looked into it).

I'm in agreement that Weston is not the way to go. I think it would be
quite difficult to add server-side borders to the existing Weston
code-base, and would almost certainly not be accepted upstream.

> -4) Sucklessness
> What should we do then?
> My advice would be to take a look at tinyx[2] and tinyxlib[3], which is
> relatively small and fitting the purpose well (dwm runs on it).
> 
> Let's see what the future will bring us, but it now is all about making
> a decision.

I don't think it is so important to make a decision as much as to be
aware of all the possibilities.

Also, while I'm happy that swc is getting attention, it is perhaps
happening just a little too early; don't expect to be able to try it out
right now, I have a lot of changes pending in my working tree which I
hope to get committed over the next few days. Additionally, there are a
couple of final things I need to finish up (mainly VT switching).

-- 
Michael Forney 



Re: [dev] gtk3 support for surf?

2014-01-10 Thread Michael Forney
Hi,

On Fri, 10 Jan 2014 17:05:17 +0100, FRIGN  wrote:
> On Fri, 10 Jan 2014 18:49:13 +0100
> Markus Teich  wrote:
> 
> > If I can, I would like to help. Where is the code hosted?  I also found 
> > swc[0]
> > written by the same guy who wrote the st port to wayland. However I feel it 
> > is
> > not really as simple as it claims to be.
> 
> The code is hosted here[1].
> Thanks for linking me to swc! I'll check it out and combine it with my
> ideas. There really is a lot of code in that library!

I'm glad others are interested in this! In response to your comments
about it being a lot of code: writing a display server turns out to be a
lot of work, which I'm sure you will discover for yourself :) Although
perhaps it appears larger than it is; I tend to prefer working with many
small files instead of several large ones. While there are a lot of
source files, my current working tree sits at < 6k SLOC. Additionally, I
am quite open to suggestions about how certain portions could be
simplified or done differently.

I am definitely interested in combining efforts/ideas if possible. I've
been working on this off and on for about a year now, and I have learned
a lot in that time. Feel free to use swc as a reference for your project
if you want (I do believe it to be quite a bit simpler than weston).

Perhaps the biggest obstacle I've come across is how to do rendering in
a simple and efficient way, yet retain hardware support. I opted to
create a very primitive drawing library (which is also used by my st and
dmenu ports), which I am currently in the middle of a major refactor. It
currently only supports software and intel hardware rendering. There is
of course OpenGL, and while it will most likely be available on the
majority of systems, it is fairly heavyweight for the job.

> I'll definitely give you guys an update on my status, but I'm sure
> there should be a way to write a simple tiling-wm in less than 5k SLOC.

I'm of the opinion that the compositor and window manager should be
separate projects, which is why I implemented swc as a library. Look at
the number of tiling X11 window managers out there. It doesn't make
sense to have each of them implement their own compositing code.

Please let me know if you have any questions! I would be happy to help!

-- 
Michael Forney 



Re: [dev] [st] [PATCH] Fix some bugs in mouse tracking logic

2013-09-13 Thread Michael Forney
On Thu, 01 Aug 2013 10:10:23 +0200, "Roberto E. Vargas Caballero" 
 wrote:
> >   This suggests that we should still add 32 to the button value when in
> >   MODE_MOUSEX10.
> 
> It is no clear for me if we have to add it or not, did you test it with
> other emulators?

Hi,

I apologize for the delay in getting back to you (I've been distracted
by other projects).

I'm fairly certain that we are supposed to always add 32 unless in SGR
mode. I've just now confirmed with the xterm (version 296) source code:

button.c:4254
> static unsigned
> EmitButtonCode(TScreen * screen,
>  Char * line,
>  unsigned count,
>  XButtonEvent * event,
>  int button)
> {
> int value;
> 
> if (screen->send_mouse_pos == X10_MOUSE) {
>   value = CharOf(' ' + button);
> } else {
>   value = BtnCode(event, button);
> }
> 
> switch (screen->extend_coords) {
> default:
>   line[count++] = CharOf(value);
>   break;
> case SET_SGR_EXT_MODE_MOUSE:
>   value -= 32;/* encoding starts at zero */
>   /* FALLTHRU */
> case SET_URXVT_EXT_MODE_MOUSE:
>   count += (unsigned) sprintf((char *) line + count, "%d", value);
>   break;
> case SET_EXT_MODE_MOUSE:
>   if (value < 128) {
>   line[count++] = CharOf(value);
>   } else {
>   line[count++] = CharOf(0xC0 + (value >> 6));
>   line[count++] = CharOf(0x80 + (value & 0x3F));
>   }
>   break;
> }
> return count;
> }

As you can see, value begins as ' ' (== 32) + the button value (BtnCode
also adds 32), and then 32 is subtracted only when in SGR mode.

-- 
Michael Forney 



Re: [dev] Wayland st!!??

2013-07-29 Thread Michael Forney
On Mon, 29 Jul 2013 12:47:49 +0200, Silvan Jegen  wrote:
> So the reason you would not want dwm to be a shell plugin for Weston is
> that Weston is too focused on fancy modern features, correct?

Eh, maybe I am being a bit too hard on Weston. It just seems to be
growing quite steadily which scares me and I wasn't thrilled with it
overall.

> Implementing a proxy wl_shell for this hypothetical blitting compositor
> and having dwm as a separate process communicating with it would be
> another possible approach.

Yeah, that's what I tried to describe.

-- 
Michael Forney 



Re: [dev] Wayland st!!??

2013-07-29 Thread Michael Forney
On Mon, 29 Jul 2013 09:59:06 +0200, Silvan Jegen  wrote:
> I am very interested in st (as well as other suckless projects)
> on weston/wayland as well.
> 
> The wayland protocol seems to be very concise and it certainly does not
> come with all of the legacy baggage of X. That said, I noticed that the
> wayland port of the st code is around 70 lines longer than the X
> version[1]. I have not investigated way that is though.

It's mostly because of the many event handlers. In Wayland, you don't
have to register listeners for objects, but if you do, you have to
implement all of it's events. Mostly this is okay, but in a few places,
there were some events that I didn't use, like the drag and drop
facilities in wl_data_device. Also, Wayland uses separate events for
button/key press/release as well as axis (which required a new axis
binding shortcut list in config.h and handling in st.c).

These little changes add up (function prototypes as well as
definitions), which account for the difference in code size. However,
nearly all of this is cosmetic and doesn't really affect the code's
complexity.

> As far as I know dwm would have to be ported as a wayland-compositor
> (which does not do any composing). Does anyone know of a
> dwm-port/suckless-compositor for the wayland protocol that is still
> being actively developed?

Making dwm act as a Wayland shell (what Wayland calls a window manager),
wouldn't be too difficult. Many of the X11 related bits correspond
fairly closely to wl_shell bits, and the ones that don't probably aren't
even necessary under Wayland.

However, the compositor part is tricky. The easiest method would be to
make dwm a shell plugin for Weston. I don't like this approach because
Weston seems to be focusing on a more "modern" desktop features like
animation, transparency, window decorations, etc. I also dislike the
idea of dwm being loaded as a plugin.

I don't think that implementing a compositor from scratch (which would
do nothing more than blit the windows onto your screen, and maybe draw
some borders) is out of the question. I'm estimating that it could be
done in ~4000 lines (maybe more, maybe less). The question in this
scenario is where does the window manager fit in? I don't like the idea
of the window manager being in the same project as the compositor, as
they do two different jobs and other window managers should be able to
make use of it as well.

However, there has to be some implementation of wl_shell on the
compositor side. One solution would be to make a protocol extension
(which are really easy to do) and use it to communicate with a separate
window manager process. This would be similar to how an X window manager
works, but it would require implementing a wl_shell that kind of acts as
a proxy. Another option would be to make the compositor into a library
that a window manager can link with. The wl_shell implementation would
be more direct but then we would have to deal with giving the window
manager/compositor special privileges (Weston does this by using a suid
launcher which does stuff like open input devices and manage drm master
through a socket pair). Another problem is that we would have a single
program which does quite a lot of stuff.

I'd love to hear other people's opinions on this topic.

-- 
Michael Forney 



Re: [dev] Wayland st!!??

2013-07-27 Thread Michael Forney
On Sat, 27 Jul 2013 14:17:42 -0400, Carlos Torres  wrote:
> I didn't know about this
> 
> http://www.phoronix.com/scan.php?page=news_item&px=MTQyMTQ
> 
> I'm both excited or looking to troll

I'm the author of the port. I'm not sure how the suckless community
feels about Wayland, but it seems like the core protocol is fairly
lightweight, depends only on libffi, and is refreshing to work with
compared to X. Weston's goals are perhaps more orthogonal to suckless,
but I think there is potential for a suckless compositor.

I don't really expect there to be a suckless Wayland environment for a
while, and maybe something better will come around before there is, but
I think my rendering library could be useful in either case (the Wayland
part is just buffer creation/management and is separate from the
rendering part).

-- 
Michael Forney 



[dev] [st] [PATCH] Fix blink mode check

2013-07-25 Thread Michael Forney
ATTR_BLINK is an attribute for a Glyph and will not be set in term.mode.
---
Again, I haven't actually run into any problems caused by this, but this seems
like a typo to me.

 st.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/st.c b/st.c
index 8992998..734c345 100644
--- a/st.c
+++ b/st.c
@@ -3544,8 +3544,8 @@ run(void) {
ttyread();
if(blinktimeout) {
blinkset = tattrset(ATTR_BLINK);
-   if(!blinkset && term.mode & ATTR_BLINK)
-   term.mode &= ~(MODE_BLINK);
+   if(!blinkset)
+   MODBIT(term.mode, 0, MODE_BLINK);
}
}
 
-- 
1.8.3




  1   2   >