Hey Heather, it's me again.
I know. This post isn’t about the Chrome extension. I’m going to write about that too so there should be another post soon. For now, let me tell you about this workshop I attended.
Yesterday, I learned a bit about building my own shell. The idea of the workshop
is to get you to understand how Unix processes work. There was mention about
clarifying some of the things that are misunderstood about POSIX shells but I
don’t know what that means yet. It’s pretty cool that we’ll end up with a
working shell. I got $$
to print out and take in an input and it sparked joy.
This is good. A feeling. Here’s the link to Julian’s Build your own shell
repo if you’re ever interested in making your own.
The reason to go through this is best summarized by the creator’s words:
The shell is at the heart of Unix. It’s the glue that makes all the little Unix tools work together so well. Understanding it sheds light on many of Unix’s important ideas, and writing our own is the best path to that understanding.
Sounds great, right?! After the workshop I took a bit of a step back and went over a bunch of Wikipedia articles again because of course I did. I’m trying to get into the habit of closing my tabs in general. It is difficult. But reading the Unix-related wikis makes programming seem so simple and logical. Of course things should be modular! Of course they should do one thing well! Isn’t this how everyone thinks? Of course you think of other developers who will work with your code in the future. But maybe we sometimes forget and then complacency sets in. I’ll try to veer away from that. I can and should always try to do better. Okay so let’s close these tabs now.
So the workshop
In the workshop I started out writing stage 1 in C but that was a
mistake. This is because in the second step, we need to split the line that was
input. Although C doesn’t have .split(). It does have *strtok
, which would
break a string into a series of tokens using a delimiter and would return a
pointer to the first token found. And this is when I remembered that I actually
don’t know C because I haven’t used pointers. Beyond knowing that it’s a
variable that stores the address in memory of another variable, I don’t know
what I’d do with it. I’ve read that it’s used to dynamically allocate memory,
but since I haven’t done it yet it’s still very abstract. Even if I did
understand pointers though, there were other considerations that I wasn’t aware
of and now can’t quite remember. It has something to do with the way C would
handle the string I think. But I stopped around there. Considering that Julian
said “let’s say you don’t know Python at all, you should still do it in Python”.
I think it’s best to listen. It’ll be less of a pain and I’ll still learn. And
of course he offered support in the future if I want to go back and try to do it
in C. But the point now was to get something started. Here is what I wrote in C:
char *line = NULL;
size_t len = 0;
ssize_t nread;
for(;;) {
printf("$$ ");
fflush(stdout);
nread = getline(&line, &len, stdin);
printf("%s", line);
if ( nread < 0) exit(0);
}
It’s pretty straightforward: show the prompt, get rid of anything that was input
previously, read the line, print it, exit if nread
returns less than 0. Do
this forever. I’m not sure I understand what nread
is doing. Let’s look at
that for a second.
Initially we set nread
to be of type ssize_t
. This type is used to
represent the size of an allocated block of memory. That variable then takes the
output of getline
. Looking at the man page for getline
it says that it
“reads an entire line from stream and stores the address of the buffer
containing the text into the line pointer”. So basically we’re just filling what
was “empty”, which here was line
and len
, with the standard input and it’s
returning the number of characters read. If it fails it’ll return -1 and this is
why we needed to set the type of nread to ssize_t
because it needs to be
signed typed, which means it can represent -1.
It’s amazing to me how much information is packed into just a few lines of code. Wow! Well that’s about how much I could do in C before I was encouraged to try building a shell in Python. All I’ve got in Python is:
while True:
print("$$")
line = sys.stdin.readline()
args = line.split()
print(args)
As you can see there is work to be done. For the first stage of the workshop, it’s just to get something basic working. Here is what the simplest shell should look like:
loop
print "$ "; flush(stdout)
line = getline(stdin).split()
if eof(stdin): exit(0)
pid = fork()
if pid == 0:
execvp(line)
waitpid(pid)
I think it’s pretty neat. You’ll probably see more posts regarding this project. And now, to work on a Chrome extension!