101 comments

[ 3.1 ms ] story [ 148 ms ] thread
"The less(1) we're all familiar with has been completely rewritten. After importing a fork from illumos' Garrett D'Amore, OpenBSD continued to make improvements to the code. A safer and more modern tool was the end result, even if it's just for viewing text. Hopefully there will be less bugs now."

Impressive work.

And less bugs. Beautiful pun there.
...until you realize that the proper word would be "fewer" because bugs are countable.
Hopefully fewer less bugs.
...or until you realise that the personal preferences of Robert Baker do not constitute what is "proper". It was a daft preference when expressed and it's no less a daft "rule" now.
(comment deleted)
I think you meant ”fewer daft”.
Wordplay humour is not built for pedants.
english grammar strikes again
Less was unsafe? How so?
Probably by emitting control sequences from the input files unfiltered to your terminal. Just guessing, but it's the one big thing that occurs to me when thinking of an unsafe pager.
It may be much, much worse. http://seclists.org/fulldisclosure/2014/Nov/74:

"Many Linux distributions ship with the 'less' command automagically interfaced to 'lesspipe'-type scripts, usually invoked via LESSOPEN.

This is certainly the case for CentOS and Ubuntu.

Unfortunately, many of these scripts appear to call a rather large number of third-party tools that likely have not been designed with malicious inputs in mind. On CentOS, lesspipe appears to include things such as groff + troff + grotty, man, and cpio. On Ubuntu, there's isoinfo (?!), ar from binutils, and so on. Ancient and obscure compression utilities and doc converters crop up, too."

I vaguely remember a ?different? issue where less would load a shared library to list its symbols.

The release notes mention good support for running on AWS. I would love to see more distributions embrace building AMIs, or at the least provide good documentation to get it running. Ubuntu probably has the best support by building AMIs for all the regions, it would be awesome to see some others do the same thing. I think this is probably an overlooked area that could provide more growth for the BSDs.
When 5.9 was still -current, https://github.com/ajacoutot/aws-openbsd was a viable if clunky way of producing one's own AMIs. As you can see from the script, there's quite a bit of work that happens before a -current snapshot could be turned into a valid AMI.

I think this will become really useful when attached EBS volumes are properly detected by an OpenBSD system running in EC2. Right now EBS attachments are silently ignored. (Someone please correct me!)

As far as I'm aware there isnt any blkfront support in the recent changes, which would be needed for EBS.

Support for blkfront is not needed to get up and running with Xen though, so it makes sense to defer it until later and get the bootstrap going and then the devs can focus on the remaining pieces.

I'm excited about this too- I almost always choose OpenBSD for small, single-role servers, because it runs so well on small hardware like Soekris single board machines, and the maintenance is so low with OpenBSD that I rarely have to touch a machine again after setting it up.
It just says they will support Xen, I doubt they will provide an official AMI.
My point is that if they DID provide an official AMI then they would possibly see even more adoption. I know for myself, I am going to go with the company that provides the best support on AWS, which at the moment is Ubuntu.
and I completely agree, my opinion is that they are sort of short-sighted when it comes to marketing. Debian has official aws images too.
you are correct. we suck at marketing. which is OK, because the focus of the project is to produce free and quality code. any time we spend in marketing is time we don't spend in the tree.

I can live with that tradeoff.;)

Yeah, but better marketing means more money so you don't face the prospect of an electric bill that you can't pay.
OpenBSD is a project, not a company. If a company decides to build an OpenBSD AMI and support it, it's the company choice alone. The project has no such goals. This is of course not limited to a company, an individual or a group can do so too.
Hopefully I didn't come across as bashing OpenBSD because that was not my intention. I was just providing a potential users perspective.
Not sure if it is all of them, but for example the FreeBSD10.2 release announcements lists AMIs for 9 different AWS regions, as well as images in various formats for Azure, Compute Engine and Vagrant.

And even before they were part of the official release build, there were AMIs available, built by cperciva, in multiple regions for many, many releases (7.4/8.2+/9.0+) - but you had to know where to look for the ids (or use google).

Great to see FreeBSD doing this! I knew cperciva had been building them but didn't realize FreeBSD had incorporated it into official images. That's great!
Good work to OpenBSD team. Especially on pledge. Widespread changes are risky and often fail. Just speaks even more about the quality of work they do.
Yeah, that caught my attention. I envy OpenBSD's ability to do "apply this to everything" projects like this one. Linux had seccomp for ages now, but there's still barely any application using it. I even wrote patches to add supports in some projects and they were just ignored. :(
You might want to check out firejail - https://firejail.wordpress.com/ - it supports seccomp as well.
It's a step in the right direction, but it misses one great feature of seccomp - you don't have to activate seccomp at startup.

What it means in practice is (for example) a daemon running under firejail must be able to open log for writing and open sockets. An application which uses seccomp natively can first do those things and then block all further open/socket syscalls.

Are you talking about pledge? Pledge works as you describe
> If running OpenBSD under Xen (such as on Amazon's cloud platform) sounds interesting to you, you'll be happy to know that 5.9 includes some pretty solid support for this.

Exciting! Does the default build include Xen PV drivers for networking and storage, or is a custom build needed? How about SMP support? OpenBSD would make an excellent firewall VM for Qubes, XenServer, etc.

Yesterday I discovered that OpenBSD runs well in EC2, but EBS attachments are silently ignored. :(
" OpenBSD would make an excellent firewall VM for Qubes, XenServer, etc."

That's a good idea.

I'm hoping for a portable version of OpenBSD's less(1) fork (now rewrite) ever since Theo mentioned it in his pledge(2) talk at Hackfest.
It is likely they released early because they want additional testing time for the SMP diffs they are about to merge. With 6.0 we may be seeing both fully SMP routing and PF support. As of now, routing and PF are fully giantlocked in the kernel, and can only run on one core. This should greatly speed up routing and filtering performance.
After saving an old laptop at work from landing on the garbage pile, I took it home and, on a whim, decided to install OpenBSD on it.

I expected problems of some kind or another and was mentally prepared to install Debian instead, but I was pleasantly surprised that all of the hardware worked out of the box. Since it is old an fragile, and the battery lasts about five minutes, I don't do much with it but keep it around for good luck.

Guess I'll be upgrading this weekend. As luck will have it, I am also binge-watching Doctor Who currently, which fits in nicely with the cover art. ;-)

I am using OpenBSD as my primary workstation on a 2015 Carbon X1, and it works like a charm.
The 5.9 release includes many pledge(2)'d programs in base, but some notable ports include decompressors like bzip2/unzip/p7zip/xz.. oh, and Chromium.
OpenBSD has been my go to firewall since my firewall was a Sparcstation IPC. There have been some major changes along the way, but most of the time rebuilding the system takes less than an hour and is a matter of porting a few config files to a fresh copy of the OS. Even the major changes are usually trivial since the documentation is kept up-to-date and there are plenty of examples in the docs and on the mailing lists.

The last time I saw anyone test packet passing speeds against OpenBSD it was around the time of the pf/ipf split and rewrite and OpenBSD was the slowest of the lot. Although modern hardware can saturate a cable modem, the multithreading of their network stack is still a positive, as is the work to support modern wifi cards (N); hopefully AC will be next.

Also definitely looking forward to pledge since it further reduces attack surfaces on an already hardened OS.

There's a lot more work to do for 802.11n in future releases (e.g. MIMO support). So putting 802.11ac on the roadmap doesn't make much sense at this stage.
Fair enough - just wishful thinking, and as my friends in OpenBSD-land say "If you want it so bad, submit a patch."
802.11n

Another big one for laptop users: initial support for N wireless has landed in both the iwm(4) and iwn(4) drivers.

Does that mean that 802.11n wasn't supported by OpenBSD until now? 802.11n was first available in (2010?) and is no longer the current version (802.11ac is).

802.11n is a lot more complicated than its predecessors, OpenBSD has it's own wireless stack and drivers. A lot of 11n hardware was supported in a/b/g modes only.
I've found the same on Linux with the Broadcom chips that at least Apple users in laptops. Maybe the proprietary driver supports it.
I imagine wireless is a "secondary" concern for the OpenBSD team given the focus on the server.
Not really. Most OpenBSD developers run OpenBSD on their laptops which of course includes wifi.

The real reasons are that 11a is still good enough for many use cases, and that OpenBSD's wireless developer department is seriously understaffed (apply by sending a patch).

No one uses a. It was not a 2.4Ghz radio and not compatible with the b/g/n/ac cards that came after it.
I don't think this is true - AFAIK most 5Ghz hardware supports 802.11a.
While only anecdata, I've got a 5Ghz router and 802.11a is not an option (but 802.11b is).
New base stations don't typically have options for 11a-only 5 GHz, but 5 GHz capable 11n clients can still connect to older 5 GHz 11a networks. I imagine there is similar backwards compatibility to the other direction even without an explicit configuration option.
Wow, so much doubt. I'd normally link Wikipedia, but this is HN so let's just quote the spec to clear this up once and for all.

Legend:

PHY: think of this as "wifi radio"

HT: "High Throughput" aka 802.11n

"Clause 20": HT PHY specification

"Clause 19": 802.11g PHY specification

"Clause 18": 802.11a PHY specification

"Clause 17": 802.11b PHY specification

STA: any 802.11 capable device

[[[

20.1.1 Introduction to the HT PHY

Clause 20 specifies the PHY entity for a high throughput (HT) orthogonal frequency division multiplexing (OFDM) system.

In addition to the requirements found in Clause 20, an HT STA shall be capable of transmitting and receiving frames that are compliant with the mandatory PHY specifications defined as follows:

— In Clause 18 when the HT STA is operating in a 20 MHz channel width in the 5 GHz band

— In Clause 17 and Clause 19 when the HT STA is operating in a 20 MHz channel width in the 2.4 GHz band

]]]

Translation: All of 11a/b/g are a proper subset of 11n.

11ac is 5GHz only. I assume it's backwards compatible to 11a but I haven't read the 11ac spec.

Reversing firmware without documentation takes time. Especially when a single developer does it on their spare time as a hobby.
Does OpenBSD actually write open WiFi firmware?
No. But they still have to write drivers that will interact with those firmwares.
Can anyone explain pledge?
Another great release from the OpenBSD team. Always looking forward to the great things Theo and team put out. Pleasantly surprised to see this release a month early.

OpenBSD has been my favorite OS since 2000. Such an easy-to-use OS for any number of things. I've used it for firewalls, Web servers, and a nice simple desktop with a custom FVWM config. Fast and simple.

Considering how much the OpenBSD team cares about secure programming and the time they invest rewriting unsafe kernel and userland code, why do they still use C when they could use a safe language like Rust?
C is a systems language from the ground up with decades of successful use and knowledge behind it. Rust is the new kid on the block with everything to prove. C is the best tool for the job. I think Theo de Raadt and his devs know exactly what they are doing. With only two holes in the default install in over a decade, why fix what isn't broken?

I'm one of these guys that still clings to old tech because it works. If C works, use it. Rust is too new, too unproven. C has proven its worth with billions of lines of code, something Rust will likely never achieve as a niche language.

"C is a systems language from the ground up"

It was actually an extension of BCPL, which wasn't designed: just what parts of a good language compiled on 1960's hardware. Proof below.

http://pastebin.com/UAQaWuWG

"with decades of successful use"

It actually had decades of failures with all sorts of bugs and hacks that safer, system languages dodged by design. Only the best coders got successful and secure use out of it. We praise OpenBSD quality for a reason: it's not easy.

"Rust is the new kid on the block with everything to prove. "

This is true. I have a rule against using anything new for security-critical coding if its in the TCB. Takes time to discover all the issues in things.

"With only two holes in the default install in over a decade"

Propaganda I've called out plenty. On the other systems, people finding bugs often weaponize them, declare a vulnerbaility, and add that to the count. OpenBSD treats bugs as just bugs then fixes them while assuming their mitigations stopped any attack attempts. It's easy to say you only had 2 vulnerabilities when you're not counting vulnerabilities. ;)

"C has proven its worth with billions of lines of code, something Rust will likely never achieve as a niche language."

It does have proven worth. After billions of lines, you can be sure you'll be fixing all sorts of things and doing breach notifications if you rely on it. Unless you pay extra money for top coders. Rust already beat it on app-level safety w/ effects of low-level interactions and compiler risk being next to assess or address. Ada and SPARK beat both for systematic safety with many empirical results from case studies and field use. Safe versions of C like Cyclone and Popcorn outdid C, too, in security but nobody invested more in them. TAL and CoqASM are even doing safety/security at assembler level.

And so we have a language proven worthless for quality or security the mainstay of quality or security focused UNIXen even with decades of alternatives empirically shown to be better. Sounds like a cultural thing to me. Drawback too.

Only advantages: lots of people know it and lots of existing code/tooling. Valid reasons to choose it for existing BSD code but allows it was inferior on other angles. And that rewrites to safer languages for it or new projects should be ongoing.

I am genuinely wondering, what is (or could you point me to) the alternative with the following properties:

- Compiled, type-safe and available for armv6.

- Simple semantics: Rust and Ada are complex (C++-ish) and it gets hard to limit the number of memory allocations/accesses as well as data copies going on.

- Tooling and discoverability: Man pages and Emacs with a few modes that are easy to setup beats anything I've tried so far.

I understand that C has shortcomings when it comes to safety/security and even lacks features that would make programming certain things easier, but what do you suggest I use when I want to write a UNIX daemon that needs to transfer a boatload of data from disk over the network and vice-versa?

I personally like it, I find it to be clear and concise, a little tedious but at the price of giving me fine grained control over the data in memory: I just have to be careful with that.

  > it gets hard to limit the number of memory allocations/accesses
  > as well as data copies going on.
I would be interested in hearing more about this, if you have the time.
That statement didn't fully sink in first time I saw it. I'm also curious as to what that was referring to. Especially since Ada/SPARK are mainly used in real-time, resource-constrained systems.
In this video[0] on Rust, in this example I was unable to directly tell whether the Vec structure is being copied to the take() function. If ownership is being handed over, why is a copy being made? And if a copy really isn't being made, then why aren't the function signature and the calling site reflecting that?

I hope I am making any sense... Please tell me if I should try to rephrase, or if I am in need of clarification on the subject.

(BTW, this is also something I really dislike about C++, two function calls that look exactly the same, foo(x) and bar(x), could either be pass by value or pass by reference: you have to go dig up the function signatures to figure that out).

[0] https://youtu.be/O5vzLKg7y-k?t=1110

Gotcha. I thought the video would have explained this, but since it didn't get through, let me try :)

  fn take(vec: Vec<i32>)

In Rust, the default way that things operate is to _move_. So when you call take(), we'd say that the vector moves into the function.

Moving is always a memcpy. There's no way to change this behavior, so you can always know that it's true. But with a Vec, there's a subtlety: the Vec itself is three words: a pointer to the heap, a length, and a capacity. So when I say that the Vec is memcpy'd, I mean literally those three things. It doesn't try to follow the pointer and copy the data that it points to.

Incidentally, that pointer is why we say that it moves: because two copies of the Vec structure itself would mean an aliased pointer to the heap, the compiler doesn't allow the use of the older binding after take() is called.

For simpler types, like integers:

    fn take(i: i32)
they implement a trait called Copy. This means that when you call take, the i32 is copied, in the same fashion that the Vec was copied. The only difference is that there's no problem with having these two copies, as an i32 is, well, just an i32. So the compiler won't prevent the use of the binding outside the function like it would with a non-Copy type.

References are like pointers, but with the extra static checking that Rust does.

    fn take(vec: &Vec<i32>)
References also implement Copy, and so when you pass a reference to a Vec to this function, the same thing happens as in the i32 case. The reference itself gets copied.

This is sort of a long-winded way of saying that Rust is "pass by value", not "pass by reference." Some people like to call this "pass reference by value", since while it's always pass by value, references are themselves values.

What if we _did_ want to make a full copy of the Vec, including its elements? For that, we have to use the .clone() method.

    let v = ... // some Vec<i32>
    let v1 = v.clone();
Now, v and v1 will be full, independent copies of the same thing. In other words, if you don't see .clone(), it will never be a deep copy.

    let v = ... // some Vec<i32>
    let v1 = v; // a move, always a shallow memcpy
    let v2 = v1.clone(); // a deep copy
You can always see, syntactically, when you're making a possibly expensive copy of something.

Does that help? I'm happy to elaborate further.

It was a great detailed explanation that also illustrates why I've held off on Round 2 of reviewing the docs. I mean, I read this...

"This is sort of a long-winded way of saying that Rust is "pass by value", not "pass by reference." Some people like to call this "pass reference by value", since while it's always pass by value, references are themselves values."

...and instantly have to focus hard to make sure I'm not slipping on the basic concepts. The wording of many Rust descriptions seems unnecessarily confusing to the point that I just googled value vs reference semantics to make sure my memory wasn't screwed up [more]. In a normal 3GL, pass by reference basically stores a pointer in a variable and passes that value somewhere. That value/reference can be used to modify original data outside its original function. Is that what Rust does? If so, it's just pass by reference "with (caveats/rules here)." End of story. Otherwise, I'll see if I can guess a wording that doesn't merge opposite concepts.

This concept isn't Rust specific, it's a general PLT thing. Rust is the same as C in this regard. Almost every language is pass by value these days. IIRC Fortran is pass by reference, an exception.
Then just say it's pass by reference instead of stuff I quoted. Counter anyone else doing the same in your usual, gentle style reminding how unnecessary confusion hurts adoption. Ill get back on helping find more of this stuff in the docs once im done moving.

Btw, I tried to get on your draft but link didnt work by time I got back to it. Was it merged into official docs or where so I read/review the right thing?

I still failed, it's pass by value :( just like C.

http://github.com/rust-lang/book is the repo, and has a link to the rendered version.

It's all good. You still take the feedback and try to improve things. That's what counts. :)

Thanks for the link. Ill look at it again in coming weeks.

Yes! That definitely reinforces my understanding. So Rust is more like C and less like C++ in that it is pass-by-value everywhere, with the exception that references are not pointers but _real_ references.

Does this make things like "const int * const x" (in C syntax) pointless in Rust?

Does that mean that in Rust I can only pass to a function an immutable reference to a mutable object, but not a mutable reference to an immutable object?

Also, out of curiosity, how would something like a recv() call into the middle of an array (buffer) look like in rust? Something like "recv(sock_fd, buf + 5 * sizeof(char), buf_len - 5 * sizeof(char), 0)"?

Great :)

  > Does this make things like "const int * const x"
  > (in C syntax) pointless in Rust?
Checking myself with cdecl, because I _always_ get this wrong:

  > declare x as const pointer to const int
This is

  let x: &i32;
(using i32 because it's the default int type, even though it's different than C's int.)

The variations are:

  let x: &i32; // an immutable binding to an immutable reference
  let mut x: &i32; // a mutable binding to an immutable reference
  let x: &mut i32; // an immutable binding to a mutable reference
  let mut x: &mut i32; // a mutable binding to a mutable reference
More mutablity == longer declaration, roughly.

  > Does that mean that in Rust I can only pass to a function an immutable reference
  > to a mutable object,but not a mutable reference to an immutable object?
You're right in both. No problem treating something mutable as immutable, but treat something immutable as mutable and you get a compiler error.

  > Also, out of curiosity,
Rust has a concept called "slices". These are "fat pointers", that have both a pointer and a length inside:

  let x = vec![1, 2, 3, 4, 5];
  let slice = &x[1..3];
Here, 'slice' will be a pair, (ptr, len), so the ptr will point to the interior of the vector, and the length will be 2. If we printed it, we'd see "2, 3".

So let's check out the signature of recv:

  ssize_t recv(int sockfd, void *buf, size_t len, int flags);
This pointer, length pair looks suspiciously like buf and len here. That's for good reason. A first step towards a more Rust-like wrapper over recv would look like this:

  fn recv(socket: libc::c_int, buf: &mut [u8], flags: libc::c_int) -> libc::ssize_t {
    let ptr = buf.as_mut_ptr() as *mut c_void;
    let len = buf.len() as libc::size_t;

    unsafe { recv(socket, ptr, len, flags) }
  }
which would end up being called like this:

  recv(sock_fd, slice, 0);
combining the names from your example and mine from the slice above, heh.

The next step would be to turn `flags` into an enum, and take that as an argument rather than a C int. Then you'd want to convert the return type to a Rust integer rather than a C one... eventually, you end up with the API we have in the standard library, which looks like this for a udp socket, for example:

  use std::net::UdpSocket;

  {
      let mut socket = try!(UdpSocket::bind("127.0.0.1:34254"));

      // read ten bytes from the socket
      let mut buf = [0; 10];
      let (amt, src) = try!(socket.recv_from(&mut buf));

  } // the socket is closed here
A few comments on this:

We only said &mut buf, but I showed you syntax with [] above. When you pass a reference to an array or vector, and the function is expecting a slice, it will automatically convert to a slice of the full length. To be more accurate to your original question:

      let (amt, src) = try!(socket.recv_from(&mut buf[1, 5]));
or whatever middle part of the buffer you want.

amt is the amount of bytes read, and the src is the address, in this particular API.

You'll notice this particular API doesn't expose flags: we try to Do The Right Thing in the standard library, so you don't worry about these. Here's the source of rec_from: https://github.com/rust-lang/rust/blob/master/src/libstd/sys... c::recvfrom is libc::recvfrom, rather than recv, technically. But as an examp...

IIRC moving is a possibly-optimized memcpy, LLVM might remove it entirely.
The problem is, outside Ada and Rust, there isn't much of anything that's maintained because people stayed rejecting anything but C. I will post this on Ada so you can see (a) a nice survey of problems that show up and (b) how it systematically counters them.

http://www.adacore.com/uploads/technical-papers/SafeSecureAd...

The best candidates for simpler ones were Wirth-like languages, esp Modula-3. I used to recommend Delphi as it was a Pascal alternative to Visual C++ whose apps rarely crashed. Free Pascal succeed w/ Lazaurus IDE succeeded it w/ tons of hardware support. Component Pascal w/ Blackbox is still active AFAIK. D is quite active.

Some Modula-2 benefits https://news.ycombinator.com/item?id=9640126

Modula-3 features https://en.wikipedia.org/wiki/Modula-3

Note: Fast to compile, fast to run, easy to read, easy to integrate, optional GC, optional OOP... why we need C and C++ again? Outside legacy systems...

Free Pascal http://www.freepascal.org/

Component Pascal https://en.wikipedia.org/wiki/Component_Pascal

D language (C/C++ successor) https://en.wikipedia.org/wiki/D_%28programming_language%29

Julia http://julialang.org/

Note: It's a language for scientific programming but it's worth considering given speed and C support.

On functional side, people are writing OS's in Haskell, Ocaml, and so on. OcaPic put Ocaml on 8-bitters. ATS Language was used for drivers and 8-bitters. RED/System is like LISP w/out parenthesis for system programming with ability to make DSL's. Any such language can have safety checks built in or output something for analysis. So, even functional languages are performing acceptably in places where C used to be required. Just need more people investing into any trouble spots.

Someone could also pick up the code of Popcorn, Cyclone, or another safer C to develop it. Cyclone is worth linking to as it was so clever:

https://en.wikipedia.org/wiki/Cyclone_%28programming_languag...

Just gotta maintain the front-end. Ivory language from Galois is still maintained & extracts to C. Tools like Softbound+CETS will autotransform your code to safety at a 10-40% performance hit. A typed assembler language like TALx86 or custom one from Hyde's HLA would give you lower level than C with more safety ironically. So, many options for OSS to build on with some like Pascals having mature tooling.

EDIT: Just remembered the Pike programming language used in Roxen web & app servers as a C alternative. They're FAST. So, do google it.

Wow, thank you for that reply!

I don't think that C stays alive because people just automatically rejected anything else. There is something to C that I appreciate extremely, and that is the clarity and simple semantics: there is not much hiding and unintentional obfuscation that one can cause when writing C code.

Maybe safety and simplicity are mutually exclusive if speed and fine-grained control over memory are the main goals.

For Modula, the tools and documentation are not being updated anymore, I could not find a programming environment for eg., emacs and on armv6.

Free Pascal and Lazarus are great, until I realized there were no resources to learn modern pascal from. The emacs mode is too basic and doesn't take any advantage of things offered by fpc. But I have to admit, I've never seen anything as good as Lazarus before.

D is more like a C++ successor that's aiming at Java than a successor to C. It is complex and does not seem to be making any effort in unifying its concepts: in the same spirit of C++.

Cyclone is definitely interesting, but unmaintained and not exactly simple, similarly to Rust but with a C-like syntax.

Julia crashes all the time with segmentation faults, sorry, the quality of Julia is super low. I would not use it for anything serious. It has great ideas though.

OCaml is super complex with its syntax and semantics.

I love Haskell, which makes great efforts to unify its concepts: the language is super simple (its implementation can be arbitrarily complicated). Haskell is where I go to write beautiful things. Fast (like, systems programming fast) Haskell code is ugly and unmaintainable and defeats the purpose of choosing Haskell in the first place.

I'll be taking a look at the rest! Thanks!

> crashes all the time with segmentation faults

We would very much appreciate any bug reports, even if you don't have the time to reduce (if you have filed under another username, thank you!).

> Julia crashes all the time with segmentation faults, sorry, the quality of Julia is super low. I would not use it for anything serious.

I've seen a lot of Julia used in real world scenarios at companies and this is a pretty surprising claim. Segfaults are very rare – much rarer than in code written in C or C++. You may either have a messed up build of Julia or you could be using packages that call C libraries and do so incorrectly – that would certainly cause segfaults.

Sorry for not being clear on this. I was not talking about Julia code crashing. What I meant was when playing around with it, the julia binary would segfault here and there.

echo "print(3)" > boot.jl

julia --compile=all -O --inline=yes --check-bounds=no --output-o foo.o

Stefan can tell me if my hunch is right but check-bounds=no might turn off protections against out-of-bounds, memory access. If so, then that command is straight up telling it to segfault.
That's true, but it shouldn't segfault unless you do an out-of-bounds memory access, which this code isn't doing.

However, there seems to be a misunderstanding about how --compile=all (an experimental feature on the development branch of Julia) works. You can't run an impure operation like print during compilation. In the future, we may have a `julia-compile` command that translates a given Julia program into a binary equivalent, which seems to be what @fredmorcos expects, but that's not how the --compile=all flag works.

If you use Julia in the normal manner like you would Python, it's very reliable and stable. If you use experimental features and use them wrong, you can get segfaults. See these posts for more information about and some examples of using the Julia's experimental static compilation features:

http://juliacomputing.com/blog/2016/02/09/static-julia.html

http://juliacomputing.com/blog/2016/03/10/j2c-announcement.h...

That makes a lot of sense. Yeah, you should consider renaming it to something more clear. Maybe even change it into several commands with better names. Your docs frame the issue as whether it allows dynamic/JIT stuff or not. So, static-only, allow-dynamic, or allow-jit come to mind.
> Maybe even change it into several commands with better names.

That's what I've been pushing for – I don't think it make sense to continue to have all these compilation-related flags baked into the interactive `julia` command.

"There is something to C that I appreciate extremely, and that is the clarity and simple semantics: there is not much hiding and unintentional obfuscation that one can cause when writing C code."

It is pretty straight-forward. However, Modula-2 and Pascal's are even more so as you can represent everything with a simple BNF grammar. There's more consistency, less corner cases, and so on. Every change they make is specifically designed to improve it while maintaining simplicity. The most complicated and modern one can be described fully in around 30 pages [1]. The uppercase and declarations throw people sometimes but keep in mind people used text editors w/out syntax highlighting.

http://www.oberon.ch/pdf/CP-Lang.pdf

re mutually exclusive. Nah, there's still tradeoffs you can make. Cyclone and Rust both do that with better design decisions to allow safe, manual management. At some point, you have to choose one or the other though. Your language design matters at this point where the compiler has to know it can remove a check. C's design is so rough and allows so much unpredictable behavior that this is an ongoing research problem for it. Whereas, it happened with Modula-3 libraries in one academic project and happened for Ada with SPARK.

Re Modula. Oh yeah, it's not updated anymore. I was just illustrating a language as lean and efficient as C that was safer & easier to compile. A better foundation. It was rejected by C users when it did have compilers. Plus, there's a Modula-2 to C compiler floating around the net.

Re Free Pascal and Lazaurus. Interesting feedback. I'll look into that to see if I or developers could remedy it. Except for Emacs: Lazarus is the IDE and better suited. Emacs support might stay dead. Re D. Yes, it's more like C++ but can be used where C is many times. I see you're looking for simple stuff, though. Re Cyclone. It's not simple but not hard either. Remember C is deceptively simple: using it safey is HARD. Cyclone is slightly more complex but way easier to use. Unmaintained, yes, but people (esp GCC or LLVM types) could pick it up any day... if they weren't glued to C. Good call on the Rust connection.

https://doc.rust-lang.org/reference.html#appendix-influences

re Julia. That's not good... re Ocaml. I think you're focusing too much on complexity of semantics vs complexity of effective use. It's worthwhile to increase learning curve a bit to boost productivity, safety, and maintenance. re Haskell. That reaction surprised me and you're the first to call it simple. Ive been holding off cuz it seemed ridiculously hard and different. What did you use to learn it? Btw, I agree fast Haskell is usually ugly but look up Tolmach's Habit programming language. It's on hold right now cuz he had a better project.

Thanks :) You've given me a lot to go through over the weekend.

Regarding Haskell, I used LYAH and the standard library documentation.

I agree that Haskell is not easy to learn and that the libraries require a lot of foundation before becoming understandable and/or usable (eg, Monoids -> Applicatives/Monads vs. "I just want to read the contents of this file into a string"). The language "proper" is built on extremely simple and straightforward concepts.

You might like Nim or Crystal?
I left Nim off on purpose because it wasn't simple or C-like at all. It's an interesting language that could be a C++ or C replacement, though.