henesy
This can get a little tricky when ownership comes in to play since you don't want to end up in a situation where (not in the above program's situation, but in general) the caller might pass out a value that never gets freed and you can easily create memory leaks.
You wouldn't want to do, for example:
print("%s\n", smprint("%s", L"世界"));
Since smprint(2)'s return value was allocated and will need to be freed, but we have no way of doing that after the value is passed.You'd need to do:
char *buf = smprint("%s", L"世界");
print("%s\n", buf);
free(buf);I never changed the return value after I did this and didn’t see an issue at the time
For the record, this program was written casually on a live stream and is hardly a textbook definition of correctness :)
While the other comments are correct, the exact reason for this use of providing in/out is that the reversal is called on a subset of the incoming array.
line = Brdstr(in, '\n', 1);
will give us a null-terminated string, but we don't want to flip the null and truncate the string, so to lazily avoid that we do: rlen = runestrlen(rstr);
rev = calloc(rlen+1, sizeof (Rune));
reverse(rstr, rev, rlen);
so we get the number of runes in the input, add 1 for the \0, then reverse the pre-\0 characters.We could have the reverse() function allocate n+1 elements for the string and return an always null-delimited string, but then we need to pass it a string that doesn't have a \0, or make it assume that it will always get a \0 and treat that some way.
Passing in both items and the number to iterate felt less noisy for a quick solution :)
Go's History in Code
Platform-specific files are stored in /$architecture and binaries in /$architecture/bin. Shell scripts are stored in /rc/bin. For the home directory, traditionally, this style is reversed so your shell scripts would be in $home/bin/rc.
The namespace for any process can be enumerated, so in my default shell, I can see which directories are currently bound (and how) on /bin:
tenshi% ns | grep 'bind' | grep '/bin'
bind /amd64/bin /bin
bind -a /rc/bin /bin
bind -b /usr/seh/bin/rc /bin
bind -b /usr/seh/bin/amd64 /bin
bind -a /sys/go/bin /bin
bind -a /usr/seh/go/bin /bin
tenshi%
[1] http://man.cat-v.org/9front/1/bindhttps://github.com/0intro/plan9-contrib/blob/master/sys/src/...
Also mentioned in sysfatal(2)'s manual:
Userspace implementation of union directories with control of which half of the union made gets precedence for certain operations such as file creation, etc.
A small change, but being able to just do $foo instead of $(foo) is so nice.
Dis VM instances are super light… you wouldn't really be needing to worry much about running a large number of them.
Point aside in many cases you can sandbox applications in crafted namespaces using spawn and flags like NODEVS.
http://doc.cat-v.org/inferno/4th_edition/styx-on-a-brick/
The ev3dev project is partially inspired by everything is a file and I've used it in the past for educational purposes by making the business of controlling/using motors/sensors as trivial as read/write.
Linux lacks a lot of core abstraction properties that would make containers elegant to implement under something like the Plan9 model, at least.
Cool project inspired partially by Linux containers: https://doc.9gridchan.org/guides/spawngrid
Just ask aux/icanhasvmx :)
Manuals:
Lisp everything is a symbol, in Plan9 everything is a file and all namespaces are mutable. This concept is combined in the Interim OS experiment[1]. The idea of everything is a file is very literal and very serious compared to say, unix.
It's worth noting that 9p, while a filesystem protocol, is closer in concept to a REST api than something like say ext4.
In Plan9, the kernel could be thought of as a 9p connection router/multiplexer and all system resources and all servers must express themselves as 9p filesystems. The tooling 9p provides allows you to take trees of named objects (filesystems) and rearrange them however you please and place child processes under rules for modifying their own trees and how they can break scope, if at all.
Forking is more dynamic as provided by rfork[2] where you can give a child a specific subset of your process's namespace. So you could make a child who can only see specific files, executables, or resources and make it so that the child can't mount, unmount, etc.
[1] Interim OS: https://github.com/mntmn/interim
[2] http://man.cat-v.org/9front/2/fork
Some cool manuals:
- http://man.cat-v.org/9front/1/bind
- http://man.cat-v.org/9front/1/ns
Last 9front commit was… 3 days ago: http://code.9front.org/hg/plan9front/
Purgatorio 64-bit is a ways away, but is a goal.
It'll happen eventually, but the more eyes the better.
Some Inferno related stuff:
- Limbo by Example: https://github.com/henesy/limbobyexample
- The Inferno Shell: http://debu.gs/entries/inferno-part-1-shell
- Try Inferno in the browser: http://tryinferno.rekka.io/
- Cat-v Inferno resources: http://doc.cat-v.org/inferno
- Experiments in Inferno/Limbo: https://github.com/caerwynj/inferno-lab/
- Inferno Programming with Limbo: https://web.archive.org/web/20160304092801/http://www.gemuse... (also on cat-v)
- Developing Limbo modules in C: https://powerman.name/doc/Inferno/c_module_en
- Simple FS example in Limbo: https://github.com/henesy/simplefs-limbo
- Inferno client for Redis: https://github.com/pete/iredis
- Inferno for Nintendo DS: https://bitbucket.org/mjl/inferno-ds/src/default/
- Inferno as an Android app: https://github.com/bhgv/Inferno-OS_Android
- Inferno replacing Android (hellaphone): https://bitbucket.org/floren/inferno/wiki/Home
- Porting Inferno to Raspberry Pi: https://github.com/yshurik/inferno-rpi
Jointly, an important detail is that the complexity of said source is kept to a sane minimum and general style trends mean that most, if not all, of the source is formatted similarly and legibly. The system is so compact that you can keep most of the system source in your head at one time if you really need to.