This tutorial is a brief introduction to programming in the C language implemented in the Plan 9 from Bell Labs operating system. It is aimed at participants in SDF's Plan 9 Bootcamp who already have some experience programming in C on a Unix-like system. For more details, see the documents in the References section.
1: #include <u.h>
2: #include <libc.h>
3:
4: void
5: main()
6: {
7: print("hello, world\n");
8: exits(0);
9: }
(hello-p9.c source file without line numbers)
The C language implemented by the Plan 9 compilers is based on standard ANSI C with some modifications. The modification most obvious to a programmer can be explained with the Plan 9 version of the famous "hello, world" program above.
main()
function. In Plan
9 C, exit status is indicated by the argument passed to the exits(2)
function, and function main()
is type void
.printf()
.Plan 9 provides a separate C compiler and linker for each supported hardware architecture. The SDF Plan 9 Bootcamp virtual servers use Intel 386 architecture, so the C compiler 8c(1) and the linker 8l(1) should be used.
To compile a C program in file hello-p9.c, use an rc session to change to the program source file's directory and enter the following command:
cpu% 8c hello-p9.c
This will generate the object file hello-p9.8.
To link the file, enter the command:
cpu% 8l hello-p9.8
This will generate the default executable file 8.out. To specify the
executable file name (for example hello-p9), use instead the command:
cpu% 8l -ohello-p9 hello-p9.8
To run the executable, enter the executable file name at the rc prompt:
cpu% hello-p9
(rc's search path for executable files includes the user's current
directory by default.)
The process of building (compiling, linking, and installing) C programs in Plan 9 can be automated with the mk(1) program, the successor of Unix make.
mk requires dependency rules for building your program to be defined in a file in your program source directory. The default name for the dependency file is mkfile.
mk's dependency rule format is similar to Unix make's. The following rules will build an executable file program from a source file program.c and header file program.h:
program: program.8
8l -oprogram program.8
program.8: program.c program.h
8c program.c
However, mkfile creating can be simplified by using Plan 9's standard architecture-dependent definition file /386/mkfile and the generic mkfile /sys/src/cmd/mkone as follows:
</$objtype/mkfile
TARG=program
OFILES=program.$O
HFILES=program.h
BIN=/$objtype/bin
</sys/src/cmd/mkone
The above mkfile defines the same dependency rules as the preceding explicit rule definitions, but includes several standard mk targets for convenience, and is portable across hardware platforms. (The generic mkfile mkone is designed for building a single executable file from one or more source files. Plan 9 provides other generic mkfiles for other build patterns (Flandrena). )
Using the above mkfile, the command mk
will compile
the source file program.c if either it or header
file program.h have been updated since the previous build,
and link the object file to produce the executable 8.out in
the program source directory.
The command mk install
will compile and link if necessary
and copy the executable to the file /386/bin/program.
Command line arguments are passed to C programs in the same
way as standard C with the argc
and argv
parameters of the main()
function:
void
main(int argc, char *argv[])
{ …
Normally console input is buffered until the user presses the Enter key and all buffered character data is passed to the program as input. However, if you want a program to read each character as the user presses it without waiting for the Enter key, you can set the console device to raw mode.
To set the console to raw mode, write the command rawon
to the
file /dev/consctl. Write the command rawoff
to the same
file to return the console to buffered mode.
int consctl, inkey;
consctl = open("/dev/consctl", OWRITE);
if(consctl == -1) exits("can't open /dev/consctl: %r\n");
…
if(write(consctl, "rawon", 5) != 5) exits("\ncan't turn off echo\n");
inkey = getchar(); /* next character pressed put in inkey */
…
if(write(consctl, "rawoff", 6) != 6) exits("\ncan't turn on echo\n");
A program running in rio can resize its own window by writing to the file /dev/wctl the command:
resize -dx width -dy height
For example:
int wctl;
wctl = open("/dev/wctl", OWRITE);
if(wctl == -1) exits("can't open /dev/wctl: %r\n");
if(write(wctl, "resize -dx 1000 -dy 500", 23) != 23) /* Resize window to 1000x500 */
exits("\ncan't resize window\n");
For other window control commands, see the rio(4) man page.
Plan 9 C coding conventions are documented on the style(6) man page. It is recommended to follow them especially if you want to integrate your code into the Plan 9 system. A few highlights:
if, for, while,
etc.if, for, while
bodies).//
to comment-out lines of code only. Use
/* … */
for comments.The SDF Bootcamp Plan 9 virtual servers include the source code for many Plan 9 programs and libraries under the directory /sys/src. Feel free to reference and copy them when developing your own programs.