Re: OpenBSD `ftp` port for MSVC (Windows)

2021-09-05 Thread Ingo Schwarze
Hi Samuel,

first, note that this is off-topic on tech@.  If you see a need to
continue the thread, please move it to misc@.

Samuel Marks wrote on Sun, Sep 05, 2021 at 02:10:14PM -0400:

> WiP, basically just started this:
> https://github.com/offscale/libacquire/tree/423b751/libacquire/openbsd_ftp

I feel unsure what you are trying to achieve.  The README.md in that
directory is so terse that i don't really understand what the point is.

> What:
> - My project allows for switching between the HTTPS interface provided
> by your OS, and libcurl's HTTPS interface.

I don't really understand what that is supposed to mean either.

> Why OpenBSD `ftp` port:
> - I don't have a "pure" socket solution, and OpenBSD does not have a C
> interface version of their `ftp` (like, `fetch` from FreeBSD does, for
> example)
> - SLOC is short
> - It's from OpenBSD which gives certain trust for protocol conformity,
> safety, security, lower rates of change, and all-in-all quality

None of that applies to our current implementation of the ftp(1) client.
Yes, like everything in OpenBSD, it did receive some auditing, some
maintenance, and some feature additions helping security in the past.

But all the same, our -current ftp(1) client consists of ancient,
terribly ill-designed, technically totally outdated and obsolete
code.  So much so that developers felt it was time to throw it all
away and write a completely new ftp(1) program from scratch.  One
developer started an effort to do so, and that new program can
already do most of what ftp(1) should, but before it was completely
ready for commit, the effort unfortunately somehow petered out, so
we still have the old shit in the tree.

> - Once the MSVC port is done, the port to other OSs should be
> relatively trivial

Porting OpenBSD software to other systems is often a good idea.
Worthy examples include OpenSSH, OpenBGPD, OpenNTPD, OpenSMTPD,
OpenIKED, LibreSSL, and there are likely many more.

But OpenBSD ftp(1) is most definitely not a worthy target for
porting.

Just look at this utter mess:

 $ cd /usr/src/usr.bin/ftp/
 $ grep jmp *.c
cmds.c: (void)setjmp(jabort);
cmds.c: (void)setjmp(jabort);
cmds.c: (void)setjmp(jabort);
cmds.c:jmp_buf abortprox;
cmds.c: longjmp(abortprox, 1);
cmds.c: if (setjmp(abortprox)) {
fetch.c:static jmp_buf  httpabort;
fetch.c:if (setjmp(httpabort)) {
fetch.c:if (setjmp(httpabort)) {
fetch.c:longjmp(httpabort, 1);
fetch.c:if (setjmp(toplevel)) {
ftp.c:jmp_buf   ptabort;
ftp.c:  longjmp(ptabort, 1);
ftp.c:jmp_buf   sendabort;
ftp.c:  longjmp(sendabort, 1);
ftp.c:  if (setjmp(sendabort)) {
ftp.c:  if (setjmp(sendabort))
ftp.c:jmp_buf   recvabort;
ftp.c:  longjmp(recvabort, 1);
ftp.c:  if (setjmp(recvabort)) {
ftp.c:  if (setjmp(recvabort))
ftp.c:  longjmp(ptabort, 1);
ftp.c:  if (setjmp(ptabort))
ftp.c:jmp_buf forceabort;
ftp.c:  longjmp(forceabort, 1);
ftp.c:  if (cout == NULL || setjmp(forceabort)) {
main.c:jmp_buf  toplevel;
main.c: if (setjmp(toplevel))
main.c: top = setjmp(toplevel) == 0;
main.c: longjmp(toplevel, 1);
small.c:jmp_buf jabort;
small.c:longjmp(jabort, 1);
small.c:longjmp(jabort, 1);
small.c:(void)setjmp(jabort);

Or look at this in small.c:

/* XXX - Signal race. */
/* ARGSUSED */
void
mabort(int signo)
{
int save_errno = errno;

alarmtimer(0);
(void) write(fileno(ttyout), "\n\r", 2);
#ifndef SMALL
if (mflag && fromatty) {
/* XXX signal race, crazy unbelievable stdio misuse */
if (confirm(mname, NULL)) {
errno = save_errno;
longjmp(jabort, 1);
}
}
#endif /* !SMALL */
mflag = 0;
errno = save_errno;
longjmp(jabort, 1);
}

Then look at util.c what confirm() is.  The word "unbelievable" is an
accurate description of the situation.

Or look at intr() in main.c.  On top of calling longjmp(3), that
signal handler also calls alarmtimer() in util.c, which happily
does multiple non-atomic stores into a struct, then calls the
function setitimer(2) which is not async-signal-safe either.

Or the updateprogressmeter() signal handler in util.c.  That one
calls progressmeter() in the same file, which is just as bad as
confirm().

We have a policy to mark broken code with /* XXX */ in the tree when
it is found and whoever discovers the breakage has no time to fix
it right away.  But ftp(1) is so bad that i feel like i don't even
have the time to mark stuff as broken.  No matter where i look,
almost all of it is broken.

I'm usually a great fan of fixing broken code by step-by-step
refactoring, even if it is broken in quite serious ways.  But that
is totally out of the question for OpenBSD ftp(1).  That code is
so thoroughly ill-designed throughout that starting over from scratch
is the only viable option.

> So, want me to finish working on this?

It sounds like a waste of time to me.

> - And 

OpenBSD `ftp` port for MSVC (Windows)

2021-09-05 Thread Samuel Marks
WiP, basically just started this:
https://github.com/offscale/libacquire/tree/423b751/libacquire/openbsd_ftp

What:
- My project allows for switching between the HTTPS interface provided
by your OS, and libcurl's HTTPS interface.

Why OpenBSD `ftp` port:
- I don't have a "pure" socket solution, and OpenBSD does not have a C
interface version of their `ftp` (like, `fetch` from FreeBSD does, for
example)
- SLOC is short
- It's from OpenBSD which gives certain trust for protocol conformity,
safety, security, lower rates of change, and all-in-all quality
- Once the MSVC port is done, the port to other OSs should be relatively trivial

So, want me to finish working on this? - And if so, once it's ready,
want me to offer it back to you?

Samuel Marks
https://github.com/SamuelMarks