Home
        Introduction to Operating Systems Abstractions Using Plan 9 from
         Contents
1.                                l        Aul    tempc        f    panelc n   l                Figure 11 5  Process structure for the enhanced airport application     etticker c     include  lt u h gt    include  lt libc h gt      include  lt bio h gt               include  lt thread h gt    enum   Npanels   2      Channel timerc     of char   Channel consc     of char   Channel tempc     of char   Channel bcastc     of char   Channel panelc Npanels      of char     typedef struct PArg PArg   struct PArg         Channel  c     to get new messages from  int fd     to the panel   s file         void  consreadthread  void         Biobuf bin     char  ln     threadsetname   Consread          279         Binit   amp bin  0  OREAD     while  ln   Brdstr  amp bin      n     1    sendp consc  ln     sendp consc  nil     Bterm  amp bin      threadexits  nil      void  bcastthread  void       char  msg     int ars    threadsetname   bcast       do    msg   recvp bcastc    for  i   0  i  lt  Npanels  i     if  msg    nil   sendp panelc i   strdup msg      else  sendp panelc i   nil    free  msg      while msg    nil      threadexits  nil      void  panelthread void  a      PArg  arg   a     char  msg     threadsetname   panel     while  msg   recvp arg  gt c       write arg  gt fd  msg  strlen msg           free  msg           threadexits  nil      void  timerthread void  a          Channel  c   a     void      280         ulong NOW    Tm  tm   char msg 10    for     f   now   time  nil  
2.           ep   xep  17   print   cnt d n    cp         threadexits  nil        266      The other runs this instead   void  decr  void  arg          int  cp   arg        threadsetname   decrthread      for       if   cp  gt  0    cp      cp    1   print   cnt d n    cp       threadexits  nil           This time  we pass an an argument for both threads a pointer to the shared counter     tent c          include  lt u h gt        include  lt libc h gt              include  lt thread h gt     int ent     void  incr  void  arg        int  cp   arg     threadsetname   incrthread      for         Sep    epi Ly   print   cnt d n    cp         threadexits  nil      void  decr  void  arg        int  cp   arg        threadsetname   decrthread      for       if o  tep   gt  20    cp    cp   1   p  int   cnt d n    cp         threadexits  nil        267      void  threadmain int  char             threadsetname   main     threadcreate incr   amp cnt  8 1024    threadcreate decr   amp cnt  8 1024    threadexits  nil          One of the threads will never run   It will starve  When we executed the program  the thread   incrementing the counter was the lucky one  It started running  and because it does not call any   synchronization function from the thread library  it will never leave the processor in favor of the   other thread   a  36s  ent 1  ent  2  cnt 3  cnt 4  ent  5   cnt 6     and so on ad nauseum     We can double check by using the debugger  First  let   s locate the process that
3.           int cnt     void  incrthread  void        int ae    int loc     for  i   0  i  lt  2  itt       loc   cnt        loct t   sleep  0    cnt   loc      print   cnt is d n   cnt      threadexits  nil      void   threadmain int  char          threadcreate incrthread  nil  8 1024    incrthread  nil           Executions for this program yield the same result we expect       8 CIncr2  ent is 2  cnt is 4    No race was exposed  Indeed  no thread was ever moved out of the processor by the call to      264      sleep  If the first thread was executing incrthread  the call to sleep moved the whole pro   cess out of the processor  as shown in figure 11 2  When later  the process was put back into the  running state  the first thread was still the one running  Remember  the underlying Plan 9 kernel  knows nothing about threads  The call to sleep puts the process to sleep  Of course  the thread  went to sleep as a result  like all other threads in the process  But in any case  you did not call any  function from the thread library  and there was no context switch between threads  For the thread  library  it seems that the first thread is still executing in very much the same way that if you never  called sleep           1st thread run  o     sleep ready    k  ur process  wee  2nd thread ready     ready          context switch because of sleep    ready q run   ready       Another process     Figure 11 2  A call to sleep from a thread moves the entire process out of the processor   
4.        Let   s improve the script  It does not accept arguments  and it would be better to print a diagnostic  and exit when arguments are given       211         bin re   if      S   0    echo usage   0  gt  1 2   exit usage         exec sed  s          This is what diff says now     diff  bin tt tab    La2  5    gt  if      S   0       gt  echo usage   0  gt  1 2    gt  exit usage    gt  3     r    In this case  no line has to change in  bin t  to obtain the contents of tab  However  we must  add lines 2 to 5 from tab after line 1 of  bin t   This is what 1a2  5 means  Reversing the  arguments of diff produces this       diff tab  bin tt    2 501    lt  if      S   Q      lt  echo usage   0  gt  1 2    lt  exit usage    lt       Lines 2 to 5 of tab must be deleted  they would be after line 1 of  bin t    if we want tab to  have the same contents of  bin t     Usually  it is more convenient to run diff supplying the option  n  which makes it print  the file names along with the line numbers  This is very useful to easily open any of the files  being compared by addressing the editor to the file and line number       diff  n  bin tt tab   bin t  1 a tab 2 5     gt  if      S   0       gt  echo usage   0  gt  1 2    gt  exit usage    gt  3     Although some people prefer the  c  context  flag  that makes it more clear what changed by  printing a few lines of context around the ones that changed       diff  n  bin tt tab   bin t  1 2   tab 1 6       bin re  ATE  ee SH OO  I    
5.        mount Swsys  n rio    new  pid    Spid     bind  b  n rio  dev     stats Ituses the new window   i Until hitting Delete in that window   This time  hitting Delete in either window will stop stats  The new window has been  instructed to post the note to the note process group of our shell  It will do so  Our old window  of  course  does the same     In almost all the cases  the window command  a script  is used to create new windows  It  creates a new window like we have done  Most of its arguments are given to rio to let it know  where to place the window and which pid to use to deliver notes  Window accepts as an argu   ment the command to run in the new window  which is  bin rc by default  For example       window  r 0 0 90 100 stats    creates a new window in the rectangle going from the point  0 0  to the point  90 100   It will run  stats  There is a C library  window 2   that provides a C interface for creating windows   among other things related to windows   The window system and the graphics library use may  use it  but it is not likely you will ever need to use it from your programs  Your programs are  expected to use their    console     whatever that might be     Going back to the files served by rio  the files winid and winname contain strings that  identify the window used  You can see them for the new window at  n rio  And because of  the  customary  bind of these files at  dev  you will always see them at  dev winid and   dev winname  In what follows  w
6.        option  36     pattern  73     pattern  74     Qid  328    A    a process  killing  51   abort  49   absolute paths  13   abstract data types  2  abstraction  2   acceleration  hardware  298 299  accept connection  146  accept  146    access  authorized  357  checking for  67  access  67  94  Access control  360  access  control list  18  control lists  360  sequential  59  time  346  time  file  69  access mode  AEXEC  67  94  AEXIST  67  AREAD  67  AWRITE  67  account  4  18  360  374  new  374  open  4  student  219  acid  48  50  267  355  command  lstk  48  command  stk  48  threads function  267  ACL  see access control list  acme commands  7  acme  7  164  pipe command  115  plumbing  128  acquiring window  303  adding  key  367  partitions  323  address  construction  141  EOF  195  file  129  local  142  network  135  137 138  pair  195  space  virtual  32  text  195  address     195   adm keys  374   adm users  221  aecho c  37  AEXEC access mode  67  94  AEXIST access mode  67  afd  361  366  after c  90  agent  authentication  362                            airport  application  241 274  panels  241  274    alarm  cancel  122  process  121  alarm  121    alarm c  122  allocation  image  307  allocimage  307  Alt  284   alternate window  314  alternative channel operation  284  alts  284   amount  170  364  amount_getkey  367  amount c  365  aname  169   and  logical  191  announce  144    port  144  announce  144  apid  97 118  append   only  64    redirect
7.       Le  net bep    0 11 14 17 2 22 stats  1 12 15 18 20 23 26  10 13 16 19 21 24 clone    Each network is represented in Plan 9 as a directory  that has at least one clone file  and several  other directories  called line directories  Opening the clone file reserves a new connection  and  creates a directory that represents the interface for the new line used to establish a connection   Line directories are named with a number  and kept within the directory for the network  For  example   net tcp 14 is the interface for our TCP connection number 14  It doesn   t need to  be a fully established connection  it may be in the process of getting established  But in any case   the directory represents what can be a particular  individual  TCP connection  The program that  opens clone may read this file to discover the number assigned to the line directory just created     As shown in figure 6 1  for each connection Plan 9 provides at least a ct 1 file and a data  file  For example       lc  net tcp 14  eet  data err listen local remote status    The file ctl can be used to perform control operations to the connection  For example  to hangup      137      o  clone 0  ctl data ctl data ctl data ctl data    Figure 6 1  The file interface for a network  protocol  in Plan 9    break  this connection  we can just      echo hangup  gt  net tcp 14    The data file is used to send and receive bytes through the connection  It can be used very much  like one end of a pipe  Writing to the da
8.       exits   usage       fd   open argv 1   ORDWR    if  fd  lt  0   sysfatal   open  s  Sr   argv 1                      if  authmount  fd  argv 2   MREPL MCREATE  argv 3    amp ai   lt  0   sysfatal  authmount   3r      if  ai    nil   print   no auth information obtained n                    else    print   client uid   s n   ai  gt cuid    print   server uid   s n   ai  gt suid    auth_freeAI  ai          exits nil      The first argument for the program is a file used as a connection to the server  The program opens  it and calls its own authmount function  This function returns the Aut hinfo obtained by call   ing auth_proxy using its last parameter  and our program prints some diagnostics about such    structure before calling auth_freeAT to release it           The important part of this program is the implementation for authmount  similar to that  of amount but for returning the Aut hinfo to the caller     int    authmount  int fd  char  mntpt  int flags  char  aname  AuthInfo   aip          ine afd  E     afd   fauth  fd  aname    if  afd  lt  0     aip   nil   fprint  2   fauth   r n     return mount  fd  afd  mntpt  flags  aname       aip   auth_proxy  afd  amount_getkey   proto p9any role client     if   aip    nil   return  1       366      r   mount  fd  afd  mntpt  flags  aname    close  afd    if  r  lt  0    auth_freeAI   aip     aip   nil        return r          The function is used by a client process to authenticate to a  file  server process  First  th
9.      CHAPTERS   echo ch  ms ch   ms   PROGRAMS    echo src   ms        S ps   ms  eval     doctype Sstem ms     lp  d stdout  gt   stem ps    We defined variables to contain the source files for chapters  named ch  ms   and for formatted  text for programs  These were used by rules not shown here  but you can still see how the shell  can be combined with mk to yield a very powerful tool  The meta rule that follows  describes  how to compile the source for chapters  or any other document formatted using troff  to obtain a  postscript file     The program doctype prints the shell commands needed to compile a troff document  and  the eval shell built in executes the string given as an argument as if it was typed  to evaluate  environment variables or other artifacts printed by doctype  Again  this is just an example  If it  seems confusing  experiment with the building blocks that you have just seem  Try to use them  separately  and try to combine them to do things  That is what Plan 9  and UNIX   is about     There are several other features  described in the mk 1  manual page  that we omit  What has  been said is enough to let you use this tool  For a full description   8  is a good paper to read     13 9  Debugging and testing    Having executed our program a couple of times is not enough to say that semfs is reliable  enough to be used  At the very least  it should be used for some time besides being tested  Also   some tools available in Plan 9 may help to detect common pro
10.      The resulting program is shown next   lock c   include  lt u h gt      finclude  lt libc h gt        int ent   Lock entilck   void    main int  char           int ale    if  rfork  RFPROC RFMEM RFNOWAIT   lt  0   sysfatal  fork   r     for  i   0  i  lt  2  itt     lock   amp cntlck    cntt     unlock   amp cntlck             print   cnt is d n   cnt    exits  nil           Just to make it more clear  we can replace cnt    with      235      loc   cnt   sleep 1    loctt    cnt   loc     and the program will in any case work as expected  Each process would loop and do its two incre   ments  without interference from the other process     When our two processes try to execute the critical region  one of them is going to execute  lock   amp cntlck  first  That one wins and gains the lock  The region is now locked  When the  second process calls lock   amp cnt1ck  it finds the lock set  and waits inside the function Lock  until the lock is released and can be set again  The net effect is that we achieve mutual exclusion  for our critical region     Note that the output from the program may still be the same than that of our first two ver   sions  but those versions were incorrect  They are poltergeists  awaiting for the worst time to hap   pen  When you do not expect them to misbehave  they would miss an increment  and the program  with the race will fail in a mysterious way that you would have to debug  That is not fun     By the way  did we lie  We said that locks are bool
11.      char ldir 40      char buf  1024    l     cfd   announce   tcp   9988   adir      if  cfd  lt  0   sysfatal      announce  Sr       print   announced tcp   9988 in  s n   adir      for        lfd   li  if  lfd    sten  adir  ldir     lt  0   sysfatal  listen   r       switch  fork        case  1     case 0     default     sysfatal  fork  Sr       close  cfd    dfd   accept  lfd  ldir    if  dfd  lt  0   sysfatal  can   t accept  Sr     close  lfd    print   accepted call at  s n   ldir    for       nr   read dfd  buf  sizeof buf    if  nr  lt   0   break   write dfd  buf  nr       print   terminated call at  s n   ldir      exits nil      close  lfd        150     6 5  System services    You know that certain machines provide several services  For example  the machine known as  lsub org in the Internet is a Plan 9 system  The machine name is indeed aquamar  but it is  registered in DNS as lsub org  This particular machine provides web  mail  and several other  services  including echo       telnet tcp lsub org echo  Hi   Hi   Delete    r    How can it be  Before reading this book  you might think that the operating system was arranging  for this services to run at that machine  But now you know that the operating system is doing  nothing  but for supplying the abstractions used to provide such services     When this particular machine starts  Plan 9 executes an rc script as part of the normal boot  process  This script runs the program aux listen  which listens for incom
12.      xX        echo  a b c  S x  abe    r    There are two slightly different values that can be used to represent a null variable  One is the  empty string  and the other one is the empty list  Here they are  in that order     z x       y      echo Sx      echo sy      xd  c  env x  0000000 00  0000001     xd  c  env y  0000000  0000000     echo S x S y  1 0    Both values yield a null string when used  yet they are different  An empty string is a list with  just the empty string  When expanded by getenv in a C program  or by using   in the shell  the  result is the empty string  However  its length is 1 because the list has one  empty  string  For an  empty list  the length is zero  In general  it is common to use the empty list as the nil value for  environment variables       183      8 3  Simple things  We are now prepared to start doing useful things  To make a start  we want to write a couple of  shell scripts to convert from decimal to hexadecimal and vice versa  We should start most scripts  with   rfork e    to avoid modifying the set of environment variables in the calling shell     The first thing needed is a program to perform arithmetic calculations  The shell knows  nothing about numbers  not to talk about arithmetic  The shell knows how to combine commands  together to do useful work  Therefore  we need a program to do arithmetic if we want to do arith   metic with the shell  We may type numbers  but for shell  they would be just strings  Lists of  strings ind
13.     bin dir lib tmp  jim dir    gt  TC   bin lib tmp    r    The command mv  that we saw before  can move files from one directory to another  Hence its  name  When the source and destination files are within the same directory  mv simply renames  the file  i e   changes the name for the file in the directory        touch a    a LC   a bin lib tmp     mkdir dir   oe TC   a bin dir lib tmp    mv a dir b   ao EC   bin dir lib tmp   hes ALE   b    r    Now we have a problem  1s can be used to list a lot of information about a file  For example  flag     m asks 1s to print the name of the user who last modified a file  along with the file name  Sup   pose we want to know who was the last user who created or removed a file at dir  We might do  this  but the output is not what we could perhaps expect      ls  m dir    nemo  dir b    r    The output refers to file b  and not to dir  which was the file we were interested in  The problem  is that 1s  when given a directory name  lists its contents  Option  d asks 1s not to list the con   tents  but the precise file we named      ls  md dir    nemo  dir    Like other commands  cp works with more than one file at a time  It accepts more than one   source  file name to copy to the destination file name  In this case it is clear that the destination  must be a directory  because it would make no sense to copy multiple files to a single one  This  copies the two files named to the current directory       cp  LICENSE  NOTICE    eae  LICENSE
14.     threadexits  nil           The application must redraw the window when the resize thread receives a resize event  To do so   resizethread will no longer call blank  Instead  it asks the slider thread to redraw the  slider on the new window  as if the value had changed   Because only values between 0 and 100  are meaningful to the slider  we can adopt the convention that when the slider receives any num   ber not in the range  0 100   it simply redraws for its current value  So  we replace    blank        in resizethread with    sendul sliderc   0      Any number not in 0  100    This is the code for the new thread  It will be blocked most of the time  waiting for a value to  arrive through sliderc  Upon receiving a value  the slider value kept in val is updated if the  value is in range  Otherwise  the value is discarded  In any case  the slider is drawn and its value  printed in the output  That is the utility of the program  to generate a value adjusted by the user  using the slider  As an optimization  we do not draw the slider if the value received through the  channel is the current value for the slider  The code for drawing the slider will be encapsulated in  drawslider  to keep the function readable       307      void  sliderthread  void           uint val  nval   val    0   for       nval   recvul sliderc    if  nval  gt   0  amp  amp  nval  lt   100     if  nval    val   continue   val   nval        drawslider val    print   Sd n   val           Note how differe
15.    Video Graphic Arrays   Such devices use system memory  and or memory attached directly to  the graphics card  to store images to be shown at the monitor  In turns out that monitors are also  very complex these days  You only have to consider that graphic cards and monitors speak  together using particular protocols through the video cable that goes from the card to the monitor    Games and other popular applications demanding graphics have lead to graphic cards that  know by themselves how to do many 2D and 3D graphics operations  Sometimes  this is called  hardware acceleration for video and graphics operations     Fortunately  all this is hidden behind the device driver for the video card used in your termi   nal  The vga 3  device is in charge for dealing with the VGA card in your PC  Its file interface is  available at  v    a Te Yyy   vgabios vgactl vgaovl vgaovictl    The most interesting file is vgact1  which is the interface for configuring the card for a proper  operation  Other files provide access to extra features  like overlaid images  and for the software  kept in ROM in the PC  called BIOS  for Basic Input Output System  but not basic  that is useful  to deal with the card     Initially  while the system is booting  the graphics card operates in an ancient text only set   ting  It uses some memory to display a matrix of characters in the screen  usually of 80 columns  and 24 rows  or 80x24  But the hardware can do much more  It knows how to display graphics 
16.    main          instead of calling fauth  following an authentication protocol  and calling mount  It is easier  to let amount take care of authentication by itself  In the next section we will show how could  this be     By now  the important point is to note how authentication is performed by exchanging mes   sages between the two processes involved  In this case  the file server and our client process  The  authentication file descriptor obtained above is just a channel where to speak an authentication  protocol  using some sort of shared secret to convince the other process  nothing else  It permits  keeping the authentication messages apart from 9P     If there was only a single server  providing a secret to it for each user would suffice to  authenticate all users in the Plan 9 network  However  there can be may ones  Furthermore   authentication is used not just to convince file servers  It is also used to convince other servers  providing different services  like command execution  Instead of having to open an account with  the user   s secret for each server  authentication is centralized in  so called  authentication  servers     An authentication server is a machine that runs an authentication server process  perhaps  surprisingly  The idea behind an authentication server is simple  Authentication is delegated to      362      this server  Instead of sharing a secret  and trusting each other because of the shared secret  both  the client process and the server pro
17.    menting such a tool  But  what if our program had to read one byte at a time  or one line at a  time  We can experiment using the program below  It is a simple cp  that copies one file into  another  but using the size for the buffer that we supply as a parameter     bep c   include  lt u h gt      include  lt libc h gt        static void  usage  void      fprint  2   usage   s   b bufsz  infile outfile n   argv0      exits   usage       296     void  main int argc  char  argv                     char  buf   long nr  bufsz   8 1024   int infd  outfd   ARGBEGIN   case  b      bufsz   atoi EARGF  usage       break   default   usage       ARGEND   if  argc    2   usage     buf   malloc bufsz    if  buf    nil     sysfatal  no more memory     infd   open argv 0   OREAD    if  infd  lt  0    sysfatal   Ss  Ss  Sr   argv0O  argv 0     outfd   create argv 1   OWRITE  0664    if  outfd  lt  0    sysfatal   Ss   s  Sr   argv0O  argv 1     for        nr   read infd  buf  bufsz     if  nr  lt   0    break   write outfd  buf  nr                close  infd    close  outfd    exits  nil           We are going to test our new program using a file created just for this test  To create the file  we  use dd  This is a tool that is useful to copy bytes in a controlled way from one place to another   its name stands for device to device   Using this command         dd  if  dev zero  of  tmp sfile  bs 1024  count 1024  1024 0 records in   1024 0 records out     ls  1  tmp sfile     rw r  r   M
18.    nil was added as well     Let   s proceed with other operations for our data type  To add tickets we can simply handle      341      Sem tickets as we please  To remove tickets we can do the same  The only operations that  remain to be provided are those handling the list of pending requests in the semaphore  They are  simply implementing a queue of requests using Sem  reqs  This function enqueues a new pend   ing request in the semaphore  adding it to the tail of the queue    void   queueregq Sem  s  Req  r          QReq  q    QReq   1    q   emalloc9  9p  sizeof  QReq       q  gt r   r     q  gt next   nil    for  1    amp s  gt reqs   1    nil  1    amp   1   gt next   i    l   q          The next one returns the first request in the queue  and removes it from the head     Req   dequeuereq Sem  s          QReq  q   Req  ry  if  s  gt reqs    nil     return  nil   q   s  gt reqs   s  gt reqs   q  gt next   Ee Saar   free q    return r             Because we might change this part of the implementation in the future  we add a function to  check if there is any queued request  so that nobody would need to touch Sem  reqs    int   queuedreqs Sem  s         return s  gt reqs    nil          13 7  Semaphores as files    We have all the tools needed to complete our file server  The following function serves  Tcreate requests  which create semaphores  To do so  it allocates a new Sem data structure by  calling newsem       342      static void  fscreate  Req  r          Fid  fi
19.    print   one n     fork     print   fork n     exits  nil           This is the output      8 onefork  one  fork  fork    The first print was first executed  After that  we can see twice the text for the second print   Indeed  it executed twice  When we asked the shell to run 8 onefork  it created a process to  run our program  This process provides the flow of control that  for us  starts at main and pro   ceeds until the call to exits  Our process obeys the behavior we expect  It executes the first  line  then the next  and so on until it dies  At some point  this process makes a call to fork  and  that creates another process that proceeds executing from fork one line after another until it  dies     This can be seen in figure 4 1  The figure depicts the state for both processes at different  points in time  Time increases going down in the figure  The arrows in the figure represent the  program counter  Initially  only the parent exists  it executes the instructions for the first print   Later  the parent calls fork  Later  during the system call  a clone  i e  the child  is created as a  copy of the original  This means that the memory of the child is a copy of the memory of the par   ent  This memory includes the code  all the data  and the stack  Because the child is a copy  it  will return from the fork call like the parent will  Its registers are also  almost  a copy     From now on  we do not know in which order they will execute  and we do not know for  how much 
20.    s exit status is all right  i e   the empty string   the body is executed  Otherwise  the  body is not executed  This is the classical if them  but using a command as the condition  which  makes sense for a shell   and one command  or a group of them  as a body       if  ls  d  tmp  echo  tmp is there    tmp   tmp is there     rA    if  ls  d  blah  echo blah is there  ls   blah    blah    file does not exist    In the first case  rc executed 1s  d  tmp  This command printed the first output line  and   because its exit status was the empty string  it was taken as true regarding the condition for the  if  Therefore  echo was executed and it printed the second line  In the second case  1s  d   blah failed  and 1s complained to its standard error  The body command for the if was not  executed     It can be a burden to see the output for commands that we use as conditions for ifs  and it  may be wise to send the command output to  dev nu11  including its standard error       if  ls  d  tmp  gt  dev null  gt  2 1   echo is there  is there    if  ls  d  blah  gt  dev null  gt  2 1   echo is there    i  Once we know how to decide  how can we compare strings  The   operator in rc compares one    string to other ones   and yields an exit status meaning true  or success  when the compare suc   ceeds  and one meaning false otherwise     aE E     echo Sstatus    AS oF    echo Sstatus  no match      if    1 1  echo this works  this works    So  the plan is as follows  If      the numb
21.    using a while loop and the read command  which reads a single line from the input  Each line  read is placed in  name  to be processed in the body of the while  And now we can try to add a  user using each method     To try to add an account  we defined the function add  It determines if the account exists  as we saw  If it does  it sets status to a non null value  which is taken as a failure by the one  calling the function  Otherwise  it sets a null status after printing the command to add the  account  and adding a fake entry to our users file  In the future  this user name will be consid   ered to exist  even though it may not be in the real  adm users     Finally  note how the script catches interrupt and hangup notes by defining two func   tions  to remove the temporary file for the user list  Note also how we print a message when the  program fails to determine a user name for the new user  And this is it      dist2usr list  adduser rmartinez rodolfo martinez  adduser jblack joe black    adduser libanez luis ibanez  adduser ricardom ricardo martinez    We admit that  depending on the number of students  it might be more trouble to write this pro   gram than to open the accounts by hand  However  in all semesters to follow  we can prepare the  student accounts amazingly fast  And there is another thing to take into account  Humans make  mistakes  programs do not so as often  Using our new tool we are not likely to make mistakes by  adding an account with a duplicate 
22.   All the text read is converted to lower case before matching the expression       grep  i figure chi ms   Each window shows a file or the output of commands  Figure  figure are understood by acme itself  For commands   shown in the figure would be     and other matching lines       A popular searching task is determining if a file containing a mail message is spam or not  Today       210      it would not work  because spammers employ heavy armoring  and even send their text encoded  in multiple images sent as HTML mail  However  it was popular to see if a mail message con   tained certain expressions  if it did  it was considered spam  Because there will be many expres   sions  we may keep them in a file  The option  f for grep takes as an argument a file contain   ing all the expressions to search for     7 cat patterns   ake money fast    Earn 10  millions    Take use  viagra for a  better best  life      if  grep  i  f patterns S mailfile   echo Smailfile is spam       9 3  Searching for changes    A different kind of search is looking for differences  There are several tools that can be used to  compare files  We saw cmp  that compares two files  It does not give much information  because  it is meant to compare files that are binary and not textual  and the program reports just which one  is the first byte that makes the files different  However  there is another tool  diff  that is more  useful than cmp when applied to text files  Many times  diff is used just to com
23.   Another command that comes with the manual is sig  It displays the signature  i e   the  prototype for a C function documented in section 2 of the manual  That is very useful to get a  quick reminder of which arguments receives a system function  and what does it return  For  example      sig chdir  int chdir char  dirname     When a new command or function appears in this book  it may be of help for you to take a look at  its manual page  For example  intro 1  is a kind introduction to Plan 9  The manual page rio 1   describes how to use the window system  The meaning of all the commands in rio menus can be  found there  In the same way  acme 1  describes how to use acme  and rc 1  describes the shell   fG     If some portions of the manual pages seem hard to understand  you might ignore them for  the time being  This may happen for some time while you learn more about the system  and about  operating systems in general  After completing this course  you should have no problem to  understand anything said in a manual page  Just ignore the obscure parts and try to learn from the  parts you understand  You can always get back to a manual page once you have the concepts  needed to understand what it says     1 6  Using files    Before proceeding to write programs and use the system  it is useful for you to know how to use  the shell to see which files you created  search for them  rename  and remove them  etc     When you open a window  rio starts a shell on it  You can type 
24.   As we said before  most commands that accept a file name as an argument  work with their stan   dard input when no file name is given  And wc is not an exception  For example     we  when I see it  I believe it  control d  1 7 28    counts the lines  words  and characters that we type until pressing a control d     The shell is able to redirect the standard input for a command  and not just its output  The  syntax is similar to a redirection for output  but using     lt     instead of     gt      To remember  imagine  the bytes entering through the wide part of the symbol  going out through the little hole in the  other end  We can now do this      cat  lt  rememberthis  Thu Jul 13 12 10 38 MDT 2006    and it would have the same effect that doing this      cat rememberthis  Thu Jul 13 12 10 38 MDT 2006    Both commands produce the same output  but they are very different  In the first case  the shell  makes the arrangements so that the standard input for cat comes from rememberthis and not  from the console  The cat program has no arguments  other than argv  0    and therefore starts  reading from its standard input  But cat does not even know the name of the file it is reading  In  the second case  the shell is not doing anything to the standard input for cat  The program itself  has to open the file  and read from it     For those rare cases when there is a command that requires a file name as its input  and you  still want to run the command to work on its standard input
25.   Besides  we need to record the  name for the file representing the semaphore and its index in the array  used to build its qid      When a down is made on a semaphore with no tickets  we must hold the operation until  there is one ticket available  In our case  when a Tread request is received for a semaphore that  has no tickets  we must hold the request until there is one ticket and we can reply  Therefore  the  semaphore needs to maintain a list of requests to be replied when tickets arrive  For now  this is  all we need  The resulting data structure is as follows  Ignore the field Re f by now        339         sem h  typedef struct Sem Sem   typedef struct QReq QReq   struct Sem         Ref    int id     index in array  qid path  char  name     of file   int tickets    QReq  reqs     veads  i e   downs  pending          struct QReq    QReq  next     in pending request list  Req  E     the request pending         extern Sem  sems  Nsems      Before proceeding  we are going to complete the implementation for the semaphore abstraction  by implementing its operations  We need to create semaphores  The function newsem does that     The Sem structure is initialized to contain no tickets  The id field keeps the index in the  array  and the name for the file representing the semaphore is kept as well        sem c    Sem  sems  Nsems      Sem     newsem char  name             int ie  for  i   0  i  lt  Nsems  i     if  sems i     nil   break   if  i    Nsems     return nil   se
26.   Both programs achieve the same effect  This one does  not use even a single lock  nor sleep wakeup  It does not have any race either  Each thread uses its  own data  like when you connect multiple processes using pipes  Race conditions are dealt with  by avoiding them in a natural way     The next program does a ping pong between two threads  Each one sends an integer value  to the other  which increments the number before sending it back to the former  see figure 11 3        271      The program uses channels with no buffering        ong c        lt u h gt    lt libc h gt    lt thread h gt     include       include                include       of int     of int    Channel  pingc     Channel  pongc        void  pingthread  void         int msg   for       recv pingc   amp msg    msgtt   print   Sd n   msg    send  pongc   amp msg          void  pongthread  void       int msg   for       recv pongc   amp msg    msgtt      print    t d n   msg      send pingc   amp msg         void   threadmain int  char          int kickoff   pinge   chancreate sizeof int   0    ponge   chancreate sizeof int   0    threadcreate pingthread  nil  8 1024    threadcreate pongthread  nil  8 1024      kickoff   0   send pingc   amp kickoff    threadexits  nil          Each channel is created to send messages with the size of an int  and with no buffering     0    0      chancreate  sizeof  int    chancreate  sizeof  int      pingc    ponge      The ping thread calls    recv pingc   amp msg        
27.   It is started  in  the file server machine  during the boot process  Once started  programs may use files by talking  to the file server using the network     But there is a problem  The file system  see fossil 4   has to be able to accept commands  from a human operator  to carry out administration tasks  For fossil  a simple way is to create  a pipe and attend one end of the pipe  reading commands and writing replies  pipes are bi   directional   Any process used by a human at the other end of the pipe may talk to the file sys   tem  to administer it  Here is an example of a conversation between a human and the file system     main  fsys   main  main  sync   main sync  wrote 0 blocks  main  who    console    sxrv boot nemo   sxrv fossil nemo   srv vfossil nemo   srv fboot nemo    When we wrote fsys  fossil replied with the list of file systems  When we typed sync  fossil  synchronized its changes with disk  any change to a file that was not yet copied to the disk  was  copied immediately   When we typed who  the file system wrote the list of users using the file  system     How can we reach the pipe used to talk to fossil  The directory  srv is special  It is a  file descriptor bulletin board  A process can post a file descriptor into this bulletin board by creat   ing a file on it  For example  in my system   srv fscons is a file that corresponds to the end  of the pipe used to talk to fossil     The idea is not complex  once you realize that files in Plan 9 are not real
28.   Looking at the process 1 in the figure shows that   while this process is running  the time is used to execute two different flows of control  one for  each thread     For Plan 9  there are no threads  The kernel puts process 1 to run and what process 1 does  with the processor is up to it  Therefore  when the process 1 is moved out of the processor in the  context switch  both threads cease running  In fact  it is the single flow of control for process 1  which ceased running     Why should you ever want to use threads  Unlike for processes  that are moved out of the  processor when the system pleases  a thread may not be moved out of the processor  preempted   unless you call functions of the thread library to synchronize with other threads  What does this  mean  There will be no context switch between threads unless you allow it  There will be no  races  You are free to touch any shared data structure as you please  and nobody would interrupt  in the middle of a critical operation  provoking a race     This is the same program used as an example in the beginning of the last chapter  It incre   ments a shared counter using two different flows of control  This time  we use two threads to  increment the counter  As any other program using the thread library  it includes thread  h  that  contains the definitions for thread data types and functions  Also  note that the program does not  have a main function  That function is provided by the thread library  It creates a single
29.   Only when the first thread calls threadexits  the second thread gets a chance to run   The thread library releases the resources for the exiting thread  and switches to the other thread in  the process  that was ready to run   This thread runs to completion  like its sibling  and after call   ing threadexits  the whole process is terminated by the thread library  by a call to exits    because there are no more threads in this process     How can a thread abandon voluntarily the processor  E g   to favor other threads  The func   tion yield in the thread library makes a context switch between threads  Any other thread ready  to run will be put to execute  Of course  if no more threads are ready to run yield will return  immediately to the calling thread  Therefore  this change to incrthread creates a bug in our  program    for  i   0  i  lt  2  i      loc   cnt   loctt   yield     ent   loc          The call to yield forces a context switch at the worst moment  But note that  unlike when using  processes  this time you had to ask for the context switch     11 2  Thread names    Like processes  threads have identifiers  The thread library assigns a unique integer to each  thread  known as its thread id  Do not confuse the thread id with the PID for the process where  the thread is running  The former is known by the thread library  and unknown to the underlying  Plan 9  The next program creates several threads  that print their own ids  The call to threadid  returns the ident
30.   Plan 9 provides files named  fd 0    f  d 1  etc  These are not real files  but other interface to use your file descriptors  For example   this is another way of running cat to copy its standard input      gt  cat  fd 0     and cat reads what you type   and this is achieves the same effect      cp  fda 0  fd 1      and cp copies what you type back to the console    In the last chapter  we did see that a command line executed in the background  i e   terminated  with     amp      is not allowed to read from the console  What happens is that the shell redirects the      103      command   s standard input to  dev nul1l  the file that seems to be always empty  You can  achieve a similar effect doing this       cat  lt  dev null    Therefore  the input redirection here is redundant       cat  lt  dev null  amp     r    How can the shell redirect the standard input output for a command  Think about it  The program  cat reads from file descriptor 0  when given no arguments  That is the convention for standard  input  For output  cat writes at file descriptor 1  If the shell manages to get the file descriptor 1  for cat open for writing into rememberthis  the bytes written by cat will go into  rememberthis  And of course cat would know nothing about where does its standard output  go  They are written into an open file descriptor that must lead to some file  Also  if the shell  manages to get the file descriptor 0 for cat open for reading from  dev null  cat would be  reading fro
31.   Re  PC  1  subl  4  di   process  2     movl bx  cx    Ree ee a   System    Memory             Figure 2 2  Concurrent execution of multiple programs in the same system     All this happens behind the scene  The operating system program knows that there is a sin   gle flow of control per processor  and jumps from one place to another to transfer control  For the  users of the system  all that matters is that each process executes independently of other ones  as  if it had a single processor for it     Because all the processes appear to execute simultaneously  we say they are concurrent  processes  In some cases  they will really execute in parallel when each one can get a real pro   cessor  In most cases  it would be a pseudo parallel execution  For the programmer  it does not  matter  They are just concurrent processes that seem to execute simultaneously     In this chapter we are going to explore the process we obtain when we execute a program   Before doing so  it is important to know what   s in a program and what   s in a process     Afh    2 2  Loaded programs    When a program in source form is compiled and linked  a binary file is generated  This file keeps  all the information needed to execute the program  i e   to create a process that runs it  Different  parts of the binary file that keep different type of information are called sections  A binary file  starts with a few words that describe the following sections  These initial words are called a  header  and us
32.   Ss   s   r  gt fid  gt aux        while r   dequeueregq s      respond q   file has been removed     closesem  s    r  gt fid  gt aux   nil   closesem s       release reference from sems    respond r  nil              Before actually removing anything  all the poor requests waiting for future tickets are responded   with an error message that reports that the semaphore was removed     One word about reference counting before continuing  A semaphore may point to requests   that point to fids  that may point to the semaphore  So  at first sight  we have a data structure with  cycles and we should not use reference counting to release it  However  upon a Tremove  all the  requests in the semaphore are released  From this point  the semaphore will not create any cycle  in the data structure  and reference counting may be safely used     The 9P message Tread is attended by fsread  This function implements reading from a  fid  i e   a file   But note that the root directory may be one of the files read by the client  e g   to  list its contents  This is very different from reading for a semaphore file  and the function must  take a different course of action if QTDIR is set in the qid for the file being read        static void  fsread Req  r        Fid  fid    Qid q    Sem  S    char ALEZ   Nn    fid   r     gt fid    q   fid  gt qid    if  q type amp QTDIR     dirread9p r  getdirent  nil    respond r  nil    return       344      s   fid  gt aux    if  s  gt tickets  gt  0    s 
33.   This function has one problem  The command file might not exist  or lack execution per   mission  but the program calling run would never know  This can be a temporary fix  until we  learn more in the next section    int  run char  cmd  char  argv                     if  access cmd  AEXEC   lt  0   return  1     switch  fork        case  1   return  1    case 0     child  exec cmd  argv    sysfatal  exec  Sr      default   return 0             Before creating the child  we try to be sure that the file for the command has access for executing  it  The access system call checks this when given the AEXEC flag                 After calling access  and before doing the exec  things could change  So  there is a  potential race condition here  It could be that access thinks that the command can be executed   and then something changes  and exec fails  What is really needed is a way to let the child pro   cess tell the parent about what happen  The parent is only interested in knowing if the child could  actually perform its work  or not     4 7  Waiting for children    Did you notice that the shell awaits until one command terminates before prompting for the next   How can it know that the process executing the command has completed its execution  Also  if  you create a process for doing something  how can you know if it could do its job     When a process dies  it always dies by a call to exits  remember that there is one after     95     returning from main   The string the proc
34.   When the card operates to show graphics  it can be adjusted to show a particular number of pix   els  We saw a little bit of this when describing the coordinates used by the mouse     Most graphic cards can show 640x480 pixels  1024x768 pixels  1280x1024 pixels  and      299      perhaps even more  For each pixel  the number of colors that the card can show is determined by  the number of bits used to encode a value for the pixel  Using 8 bits per pixel leads to at most 256  colors  Therefore  a particular screen size would not just be 1024x768  but rather 1024x768x8 or  perhaps 1024x768x24     Each one of these different configurations is usually called a graphics mode  So  the con   figuration for the VGA size 1280x1024x24 is also known as the 1280x1024x24 mode  Because  the size of the actual screen is fixed  the number of pixels determines the size of each pixel in the  screen  Thus  different modes are also referred to as different resolutions     Changing the mode in the VGA card can be very complex  An auxiliary program   aux vga is in charge of adjusting the vga configuration  You will use the file interface pro   vided by the vga device driver just to adjust a few parameters  and not for doing other complex  things  For that  you have aux vga  For example     aux vga  l text    puts the machine back into text mode  as it was during boot  In the same way     aux vga  1 1024x768x8    loads the mode for 1024x768x8  On the other hand  if our graphics card is not proper
35.   but a single click with the middle button  button 2   in the square can maximize a window if you need more space  The shaded boxes near the top left  corner of each column can be used in the same way  to rearrange the layout for entire columns     The middle button  button 2  is used in acme to execute commands  Those shown in the fig   ure are understood by acme itself  For example  a click with the button 2 on De1 in our tag line        8     would execute Del  an acme command   and delete the window  Any text shown by acme can be  used as a command  For commands acme does not implement  Plan 9 is asked to execute them     Some commands understood by acme are De1  to delete the window  Snarf  to copy the  selected text to the clipboard  Get  to reread the file shown  and discard your edits   and Put  to  store your edits back to the file  Another useful command is Exit  to exit from acme  For exam   ple  to create a new file with some text in it        1 Execute Get with a button 2 click on that word  You get a new window  that has no file  name      2 Give a name to the file  Just click  button 1  near the left of the tag line for the new window  and type the file name where it belongs  The file name typed on the left of the tag line is  used for acme to identify which file the window is for  For example  we could type   usr nemo newfile  you would replace nemo with your own user name      3 Point to the body of the window and type what you want   4 Execute Put in that w
36.   e g  some type of wire or the air for radio communication      A network device in Plan 9 may be an actual piece of hardware  but it can also be a piece of  software used to speak some protocol  For example  most likely  your PC includes an ethernet  card  It uses an RJ45 connector to plug your computer to an ethernet network  just some type of  cabling and conventions   The interface for the ethernet device in Plan 9 is just a file tree  most  likely found at  net  ether0      Ic  net ether0d  0 dl 2 addr clone ifstats stats    Machines attached to the wire have addresses  used by the network hardware to identify different  machines attached to the wire  Networks using wireless communication are similar  but use the  air as their    wire     We can use the file interface provided by Plan 9 for our ethernet device to find  out which one is its address       cat  net ether0 addr  000c292839fc     As you imagine  this file is just an interface for using your ethernet device  in this case  for asking  for its address     Once you have the hardware  e g   the ethernet card  for exchanging messages with other  machines attached to the same medium  wiring or air   your machine and exchange bytes with  them  The problem remains of how to send messages to any machine in the Internet  even if it is  not attached to the same wire your machine is attached at  One protocol very important to the  Internet  IP  Internet Protocol   is provided in Plan 9 by a device driver called IP  This 
37.   echo  file  C source code  case   gif  echo  file  GIF image  case    jpg  echo  file  JPEG image       case         echo  file  who knows         As you can see  in a single case you may use more than one expression  like you can with    As  a matter of fact  this script is doing poorly what is better done with a standard command that has  the same name  file  This command prints a string after inspecting each file whose name is  given as an argument  It reads each file to search for words or patterns and makes an educated  guess       file ch7 ms ch8 ps src hi c  ch7 ms  Ascii text  ch8 ps  postscript  src hi c  c program    There is another command that was built just to test for things  to be used as a condition for if  expressions in the shell  This program is test  For example  the option  e can be used to check  that a file does exist  and the option  ad checks that a file is a directory       test  e  LICENSE    echo Sstatus      test  e  blah     echo Sstatus   test 52313  false     if  test  d  tmp  echo yes   yes     if  test  d  LICENSE  echo yes    a    Rc includes two conditional operators that remind of the boolean operators in C  The first one is   amp  amp   it represents an AND operation and executes the command on its right only if the one on its  left completed with success  Only when both commands succeed  the operator does so  For  example  we can replace the switch with the following code in our naive file script        file    ch   amp  amp  echo  fi
38.   hardware devices for Input Output  I O   and other  artifacts  If you had to write software to drive all the ones you want to use  you would not have  time to write your own application software  The concept is therefore similar to a software  library  Indeed  operating systems begun as libraries used by people to write programs for a  machine     When you power up the computer  the operating system program is loaded into memory   This program is called the kernel  Once initialized  the system program is prepared to run user  programs and permits them use the hardware by calling into it  From this point on  you can think  about the system as a library  There are three main benefits that justify using an operating system     1 You don   t have to write the operating system software yourself  you can reuse it     2 You can forget about details related to how the hardware works  because this library pro   vides more abstract data types to package services provided by the hardware     3 You can forget about how to manage and share the hardware among different programs in  the same computer  because this library has been implemented for use with multiple pro   grams simultaneously     Most of the programs you wrote in the past used disks  displays  keyboards  and other devices   You did not have to write the software to drive these devices  which is nice  This argument is so  strong that nothing more should have to be said to convince you  It is true that most programmers  under
39.   hello    r    The call to open  caused the file afile to be truncated  If was empty  open for writing on it   and the offset for the next file operation was zero  Then  write wrote 6 bytes  at offset zero  At  last  we closed the file     What would the following program do to our new version of afile     seekhello c   include  lt u h gt      include  lt libc h gt     void  main int   char           int fd        fd   open  afile   OWRIT   seek fd  32  0    write fd   there n   6    close  fd      exits  nil      GI               All system calls are very obedient  They do just what they are asked to do  The call to seek  changes the file offset to 32  Therefore  write must write six bytes at offset 32  This is the out   put for 1s and xd on the new file after running this program       64       8 seekhello     is  l1 afile       r  r  r   M 19 nemo nemo 38 Jul 9 18 14 afile     xd  c afire   0000000 h e 1 1 o  n 00 00 00 00 00 00 00 00 00 00  0000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  0000020 t h e r e n   0000026    The size is 38 bytes  That is the offset before write  32  plus the six bytes we wrote  In the con   tents you see how all the bytes that we did not write were set to zero by Plan 9  And we know a  new thing  The size of a file corresponds to the highest file offset ever written on it     A variant of this program can be used to create files of a given size  To create a 1 Gigabyte  file you do not need to write that many bytes  A single write suf
40.   include  lt libc h gt        void   usage  void       fprint 2   usage   s   nv    d delims  args n   argv0    exits   usage          void   main int argc  char  argv                     int nflag   0    int vflag   0    char  delims           int iy   ARGBEGIN    case  v    vflag   1   break    case  n    nflag   1   break    case  d    delims   ARGF     if  delims    nil    strlen delims   lt  2    usage       break    default   usage          ARGEND         39     for  i   0  i  lt  argc  itt   if  vflag   print   Sc Ss sc    delims 0   argv i   delims 1     else  print   s    argv i     if   nflag     print    n     exits  nil           And this is an example of use for our new program          8 becho  v  d   repeat after me     repeat    atter     nie     8 becho  vd    repeat after me note the space before the      repeat   after   me       8 becho  y      8 becho  v  d  usage  8 becho   nv    d delims  args       A missing argument for an option usually means that the program calls a function to terminate   e g   usage   the macro EARGF is usually preferred to ARGF  We could replace the case for our  option  d to be as follows        case  d    delims   EARGF  usage       if  strlen  delims   lt  2   usage           break        And EARGF would execute the code given as an argument when the argument is not supplied  In  our case  we had to add an extra if  to check that the argument has at least the two characters we  need     Most of the Plan 9 programs that accept
41.   int cleanup  void   char  msg      if  strcmp  msg     interrupt      0   remove    tmp tempfile      return 0          But this is an horrible idea  Notes can happen at any time  behind your back  You are executing  your nice single flow of control  and there are functions as nasty as the pop ups in other window  systems  that run at unexpected times and may cause your program to fail     When are notes posted by Plan 9  The kernel is not a magic program  It can post a note  only when it executes  Besides  for simplicity  a note is handled from within the process that  receives it  A write into the note or the notepg file records that the target process es  has a  note posted  Sooner or later  the target process will be allowed to run  if only to process the pend   ing note   At that point  when returning from the kernel back to the user   s code  is when the note  is processed     If the process receiving the note was performing a system call that does not block  the sys   tem call is allowed to complete and the note is posted while returning from the call  On the other  hand  if the process was performing a slow system call  and was blocked trying to read  or write   or any other thing  the system call is interrupted  as we saw before     5 7  Reading  notes  and alarms    You know how to read from a file  To read n bytes from a file the program must call read until  all the n bytes are read  because read may return less bytes than requested  This is so common   that a l
42.   mnt cd    7 ctl wa wd    cp  tmp songs    mnt cd wa to copy songs as audio tracks    rm  mnt cd wa to fixate the disk contents      unmount  mnt cd    For a blank CD  cdfs presents two directories in its file tree  wa and wd  Files copied into wa  are burned as audio tracks  File copied into wd are burned as data tracks  Removing either direc   tory fixates the disk  closing the disk table of contents    If the disk is re writable  and had some data in it  we could even get rid of the previous con     tents by sweeping through the whole disk blanking it  It would be as new  a little bit more thin   ner  admittedly        echo blank  gt  mnt cd ct1  blanking in progress       When you know that it will not be the last time you will be doing something  writing a small shell  script will save time in the future  Copying a CD seems to be the case for a popular task     cdcopy     bin re    rfork ne       fn prompt   echo  n  1   read      prompt insert the source CD   cdfs  d  dev sdDO    exit failed   if    test  e  mnt cd a       echo not an audio CD  exit failed         echo copying CD contents     mkdir  tmp songs Spid   cp  mnt cd a   tmp songs  pid  unmount  mnt cd    prompt insert a blank CD  cdfs  d  dev sdDO    exit failed  if    test  e  mnt cd wa      echo not a blank CD  exit failed      227      echo burning      cp  tmp songs Spid    mnt cd wa  echo fixating      rm  mnt cd wa   rm  r  tmp songs Spid   echo eject  gt  mnt cd ctl   unmount  mnt cd       The script 
43.   nr   read fd 0   buf  sizeof buf      if  nr  lt   0        break   write 1  buf  nr       print   exiting n     exits  nil           The create call for  srv echo creates a file where the program can post a file descriptor   The way to do the post is by writing the file descriptor number into the file  and closing it  The  created file at  srv is just an artifact  What matters is that now there is another way to get to the  descriptor in fd 1   Because the program does not use that descriptor itself  it closes it  Note  that the pipe end is not closed at this point  The descriptor kept inside  srv echo is also lead   ing to that end of the pipe  which therefore remains open  From now on  the program reads from  the other end of the pipe to do the echo       8 srvecho  amp     z be  fsrv   boot echo plumb nemo 264 slashmnt   cs_net fscons slashdevs vol     echo hi there   gt  gt  srv echo   hi there      ps   grep 8 srvecho   nemo 2553 0 00 0 00 24K Pread 8 srvecho    If we remove the file  srv echo  and no process has the file descriptor open for that end of the  pipe  our program would receive an end of file indication at the other end of the pipe  and termi   nate       125        rm  srv echo  exiting    r    Files in   srv are just file descriptors  They only difference is that they are published in a bulletin  board for anyone to see  How is this done  In a simple way  each file for  srv contains a refer   ence to the Chan of the descriptor posted in it  Figure 5 4 sh
44.   ps   awk 7     7  BEGIN   max 0    rr mem   5 0    ae if  max  lt  mem   E max mem  ii     7  END   print max     11844  Adding 0 to  5 forced the  string  value in  5 to be understood as a integer value  Therefore   mem is now an integer with the numeric value from the 5th field  Where is the    K     When con   verting the string to an integer  AWK stopped when it found the    K     Therefore  this forced con   version has the nice side effect of getting rid of the final letter after the memory size  It seems  simple to compute the average process  memory  size  doesn   t it  AWK lets you do many things   easily       ps   awk 7         BEGIN   tot 0         tot    S5 0        END   print tot  tot NR            F    319956 2499 66    9 5  Processing data    Each semester  we must open student accounts to let them use the machines  This seems to be  just the job for AWK and a few shell commands  and that is the tool we use  We take the list for  students in the weird format that each semester the bureaucrats in the administration building  invent just to keep as entertained  This format may look like this list     list       List of students in the random format for this semester             you only know the format when you see it        2341 Rodolfo Martinez Operating Systems B ESCET  6542 Joe Black Operating Systems B ESCET  23467 Luis Ibafiez Operating Systems B ESCET                                  23341 Ricardo Martinez Operating Systems B ESCET  7653 Jos   Prieto C
45.   s      write s  gt fd 1    x   1           A wait must acquire one ticket   void  wait  Sem  s        char buf 1      read s  gt fd 0   buf  1         We do not show it  but to destroy a semaphore it suffices to close the pipe at both ends and  release the memory for the data structure  Given the implementation we made  the only limitation  is that a semaphore may hold no more tickets than bytes are provided by the buffering in the pipe   But that seems like a reasonable amount of tickets for most purposes     Another restriction to this implementation is that the semaphore must be created by a com   mon ancestor  e g   the parent  of processes sharing it  Unless such processes are sharing their file  descriptor set       259      Problems   1 Locate the synchronization construct in programming languages you use    2 Do shell programs have race conditions    3 Implement a concurrent program simulating a printer spooler  It must have several pro   cesses  Some of them generate jobs for printing  spool print jobs  and two other ones print  jobs  Needless to say that the program must not have race conditions    4 Implement a semaphore using shared variables protected with  spin  locks  Would you use  it  Why    5 Assume you have monitors  invent the syntax   Implement a sempahore using monitors       260        261      11     Threads and Channels    11 1  Threads    Processes are independent flows of control known to Plan 9  The kernel creates then  it ter   minates them  and
46.   sed    s   cc  c g     focca x    It seems to work  The backslash removes the special meaning for the dot  and makes it match just  one dot  But this may still happen       echo foo cc x   sed    s   cc  c g     foo c x    And we wanted to replace only the extension for file names ending in  cc  We can modify our  expression to match  cc only when immediately before the end of the line  which is the string  being matched here        echo foo cc x   sed    s   ccS  c g     foo cc x     echo foo x cc   sed    s   cc  c g     foo x c    Sometimes  it is useful to be able to refer to text that matched part of a regular expression  Sup   pose you want to replace the variable name text with word in a program  You might try with  s text word g  but it would change other identifiers  which is not what you want       203      oo Cake MEG  void  printtext  char  text      print      s    text         sed    s text word g    f c  void  printword char  word        print      s    word           The change is only to be done if word is not surrounded by characters that may be part of an  identifier in the program  For simplicity  we will assume that these characters are just   a z0 9_   We can do what follows       sed    s    a z0 9_   text    a z0 9_    lword 2 g    f c  void  printtext  char  word      print      s    word           The regular expression   a z0 9_ text   a z0 9_  means    any character that may not be  part of an identifier     then text  and then    any character t
47.   tm   localtime  now       seprint  msg  msgt 10   Sd  d   tm  gt hour  tm  gt min    sendp c  strdup msg     sleep 60   1000      tempthread void  a          void          Channel  c   a   char temp  10    char last  10    int fd  nr   last  0    0   fd   open   dev temp   OREAD     if  fd  lt  0   sysfatal   dev temp   r     for       nr   read fd  temp  sizeof temp    1      if  nr  lt   0   sysfatal  can   t read temp     temp nr    0   if  strcmp  last  temp     0    strcpy  last  temp    sendp  c  strdup temp        sleep 60   1000      decoratorthread  void           char  lcons   ltimer    ltemp   char  consmsg   timermsg   tempmsg   char  msg    Alt alts            timerc   amp timermsg  CHANRCV         consc   amp consmsg  CHANRCV       tempc   amp tempmsg  CHANRCV       nil  nil  CHANEND       lcons   strdup      ltimer   strdup      ltemp  for       msg   nil   switch  alt  alts       case 0     operation in alts 0  made  msg   smprint   s   s  s  n    free  ltimer    ltimer   timermsg   break   case 1     operation in alts 1  made  msg   smprint   s   s  s  n    free lcons    lcons   consmsg   break   case 2     operation in alts 2  made         sendp  bcastc       281                o    oS    msg smprint     s  s  n      free  ltemp       ltemp    tempmsg     break     msg               void  threadmain  int  char         int as  PArg  arg   timerc   chancreate sizeof char    0    consc   chancreate sizeof char    0    tempc   chancreate sizeof char    0    pr
48.   to awake the parent once it has initialized  However  this time  we cannot exchange a value as we  could using rendezvous     As a further example  we can implement our bounded buffer program using semaphores   The data type must have now one semaphore with just one ticket  to achieve mutual exclusion for  the buffer  And we need two extra semaphores  Processes that want to put an item in the buffer  require a hole where to put it  Using a semaphore with initially Nmsgs tickets  we can make the  producer acquire its holds nicely  One ticket per hole  When no more holes are available to put a  message  the producer will sleep upon a call to wait  sholes   In the same way  the consumer  requires messages  and there will be zero messages available  initially     typedef struct Buffer Buffer   struct Buffer         Sem  mutex     with 1 ticket  for mutual exclusion    char  msgs  Nmsgs      messages in buffer   int hd     head of the queue   int tl    tail  First empty slot    int nmsgs     number of messages in buffer    Sem  smsgs      0 tickets  acquire message in buffer   Sem  sholes       Nmsgs tickets  acquire a hole in the buffer           The implementation for put is similar to before  But there are some remarkable differences       257      void   put  Buffer  b  char  msg       wait  b  gt sholes    wait  b  gt mutex     b  gt msgs b  gt tl    strdup  msg    b  gt tl     b  gt tl   Nmsgs   b  gt nmsgst t   signal  b  gt mutex     signal  b  gt smsgs            Before
49.  0 hello    Touch created an empty file  therefore its size is zero     You will be creating files using acme  Nevertheless  you may want to copy an important file  so that you don   t loose it by accidents  We can use cp to copy files   7 cp hello goodbye  Ue  bin goodbye hello lib tmp    r    We can now get rid of he11lo and remove it  to clean things up        2      rm hello  2 Le  bin goodbye lib tmp    d    Many commands that accept a file name as an argument also accept multiple ones  In this case   they do what they know how to do to all the files given       TC   bin goodbye lib tmp     touch mary had a little lamb   be   a goodbye lamb little tmp  bin had lib mary     rm little mary had a lamb   2 Be   bin goodbye lib tmp    Was rm very smart  No  For rm  the names you gave in the command line were just names for  files to be removed  It did just that     A related command lets you rename a file  For example  we can rename goodbye to  hello again by using mv  move       mv goodbye GoodBye   a UEC   GoodBye bin lib tmp    r    Let   s remove the new file       rm goodbye  rm  goodbye      goodbye    file does not exist    What  we can see it  What happens is that file names are case sensitive  This means that  GoodBye  goodbye  and GOODBYE are entirely different names  Because rm could not find the  file to be removed  it printed a message to tell you  We should have said                  rm GoodBye  B aLe  bin lib tmp    In general  when a command can do its job  it
50.  0 nemo nemo 536870912 May 23 17 44  dev sdC0 swap                            For each file representing a partition  the file size reports the partition size  in bytes   as could be  expected  This disk has just 8 Gbytes of data  8589934592 bytes   That would be the data file   Some partitions have been made for this disk  to name different parts of it and use them separat   edly  For example  there is a 9fat partition going from sector 63  included  to sector 204863   not included   And then a fs partition  going from sector 204863 to sector 13626132  And sev   eral other ones     For us   dev sdC0 9fat is just a like a little disk  that is what a partition is for   only  that it lives inside  dev sdC0 data  Also   dev sdC0 fs is another little disk  also living  inside  dev sdC0 data  Indeed  both 9fat and fs leave inside a partition named plan9   as you may see by looking where these partitions start and end     The convention in Plan 9 is to make a partition  named plan9  in the disk  This partition is  known to other operating systems  because it is declared using a partition table  kept in the disk   following a particular convention that most systems follow  Within this partition  Plan 9 main   tains its own partitions  by declaring them in another table known to the storage device driver      323       kept in disk  of course   This is done so because many disks are only able to support 4  so called   primary partitions     How can we create a partition  By filling a
51.  14          Plan 9 tried to access  n ram a several times  to see if it existed  It could be mkdir  calling  access  or Plan 9 itself  It does not really matter  What matters is that the file server replied  with Rerror  stating that there was an error  file not found  Then  a last Twalk was  issued to obtain a new fid referring to the directory where the file is being created  In this case   the fid 474 was obtained to refer to the root directory in the file server  At last Tcreate asks to  create a file with the name indicated in the name field  i e   a  After the call  the fid in the mes   sage refers to the newly created file  and it is open  Because we are creating a directory  the bit  DMDIR would be set in the perm field  along with other file permissions  This is similar to what  we did when using create 2         There are several other messages  Removing a file issues a Tremove message  The  Tremove request is similar to Tclunk  However  it also removes the file identified by the fid   Tstat obtains the attributes fora file  Twstat updates them       rm  n ram y   lt  12  Twalk tag 14 fid 435 newfid 491 nwname 1 O y   12  gt  Rwalk tag 14 nwgid 1 0  0000000000000001 0     lt  12  Tremove tag 14 fid 491   12  gt  Rremove tag 14         ls  1  n ram z    lt  12  Twalk tag 14 fid 435 newfid 458 nwname 1 0 z   12  gt  Rwalk tag 14 nwqid 1 0  0000000000000002 O     lt  12  Tstat tag 14 fid 458     12  gt  Rstat tag 14 stat    z     nemo       nemo       nemo    q  00000
52.  19 nemo nemo 1048576 Jul 29 16 20  tmp sfile    we create a file with 1 Mbyte of bytes  all of them zero  The option  if lets you specify the input  file for dd  i e   where to read bytes from  In this case  we used  dev zero  which a  fake   file  that seems to be an unlimited sequence of zeroes  Reading it would just return as many zeroes as  bytes you tried to read  and it would never give an end of file indication  The option  of lets you  specify which file to use as the output  In this case  we created the file  tmp sfile  which we  are going to use for our experiment     This tool  dd  reads from the input file one block of bytes after another  and writes each  block read to the output file  A block is also known as a record  as the output from the program  shows  In our case  we used  bs  block size  to ask dd to read blocks of 1024 bytes  We asked  dd to copy just 1024 blocks  using its  count option  The result is that  tmp sfile has  1024 blocks of 1024 bytes each  therefore 1 Mbyte  copied from  dev zero     We are using a relic that comes from ancient times  Times when tapes and even more weird    mae i ee    artifacts were very common  Many of such devices required programs to read  or write  one  record at a time  Using dd was very convenient to duplicate one tape onto another and similar  things  Because it was not common to read or write partial records  the diagnostics printed by dd  show how many entire records were read  1024 here   and how many bytes wer
53.  2    etc  They are similar to  1   2  etc  This is an example session with the program       8 match      c     regerror  missing operand for   The   needs something on the left       8 match       123      x123   no match   EE   matched      1       gt  A   no match   X3   matched  7 3       9 2  Sorting and searching    One of the most useful task achieved with a few shell commands is inspecting the system to find  out things  In what follows we are going to learn how to do this  using several assorted examples     Running out of disk space  It is not likely  given the big disks we have today  But anyway   which ones are the biggest files you have created at your home directory     The command du  disk usage  reports disk usage  measured in disk blocks  A disk block is  usually 8 or 16 Kbytes  depending on your file system  Although du  a reports the size in  blocks for each file  it is a burden to scan by yourself through the whole list of files to search for  the biggest one  The command sort is used to sort lines of text  according to some criteria  We  can ask sort to sort the output of du numerically     n  in decreasing order   r   which biggest  numbers first  and then use sed to print just the first few lines  Those ones correspond to the big   gest files  which we are interested in       206        du  a bin   sort  nr   sed 15q                4211 bin   3085 bin arm   864 bin arm enc   834 bin 386   333 bin arm madplay  320 bin arm madmix  319 bin arm deco  316 b
54.  294    A4     v device driver  298  value  semaphore  255  variable  environment  49  51  73  93  153  157  180  expansion  73  global  32  229  length  180  null  182  shell  73  180  variable  cpu  151  path  170  variables  AWK  214  condition  251  Environment  153  environment  42  variables  mk  351    vector  argument  92  verbose output  198  version  file  328  number  241  VGA  298  vga device  298  vga  299  vgactl  298  Svgasize  299  318  viewer  document  129  MS Word  129  PostScript  129  virtual  address space  32  console  292  machine  2  memory  32  34  46  memory segment  153  virus  86    W    wait for  child process  114  children  94  wait  95  156  194  255  285  waiting  busy  46  125  238  Waitmsg  95  channel  285  waitpid  96  114 115  wakeup  248  walk  159 160  328  processing  348  wastebasket  67  wc  102  107  flag  w  108  wdir  130  wdith  tab  17  web  135  werrstr  41 95  whale  137  whatis  207  when rc script  192 193  who last modified  file  15  width  rectangle  308  window  42  57  165  313  acquiring  303  alternate  314  bottom  317  coordinates  302  creation  313  current  317  hide  317    a OT      image  52  label  301  316  name  303  new  6 314  overlap  317  pid  315  resize  303  318  system  3  6  25  117  172  289  313  text  52  316  top  317  window  315  command  172  library  315  wishful thinking  331  with holes  file  64  wlock  245  wname  329  word  count  102  107  search  108  working directory  see current 
55.  361  mounted file  161                      Mouse  297  mouse  button  6    button 1  296  309  button2  296  button 3  128  coordinate  295  device  295  event  295  event channel  297  event processing  304  initialization  297  input  295  library  296  position  296  Mousectl  297  mousethread  304  Move  6  move  file  15  files  198  MREPL mount flag  169  MS Word viewer  129  mtime  69  MT Safe  285  multiple reader  244  multiplexing  console  313  resource  2  multiprogramming  46  multiway  branch  190  communication  277  mutex  256  347  mutual exclusion  234 235  256       mv  15    N    name  file  12  58  69  73  153  159  patterns  file  73  process  45  program  92  resolution  159  service  159  service  137  139  144  space  153  159  169  space  new  171  space  standard  173  system  43  172  thread  264  translation  139  user  4  43  172  359  window  303  names    file  166  namespace  new  371  namespace file  203  ndata  130  ndb  139  ndb cs  139  ndb csquery  139   n dump  75  negation  190   net file system  135  NetConninfo  142  netecho c  147   net ipifc  136  netmkaddr  141  netstat  139  145  flag  n  140  network  address  135  137 138  computer  135  connection  135 136  140  159  connection information  142  database  139  device  135  echo server  147  format  68  70  port  136  port creation  144  protocol  139  services  135  150  status  139  network  ctl file  136  data file  136  New  6  new     16     account  374  fid  329  line  
56.  37 MDT 2006    today      date      echo Stoday   Fri Jul 21 16 36 50 MDT 2006    Another example  using a command that writes numbers in sequence  follows     seq 1 5    Os WHR    echo     seq i 5   2 37 45    H     As you can see  the second command was equivalent to this one     E echo 1 2 3   4 5    The shell executed seq 1 5  and then did read the text printed by this command through its  standard output  using a pipe   Once all the command output was read  Re replaced the whole         construct with the text just read  The resulting line was the one executed  instead of the  one that we originally typed  Because a newline character terminates a command  the shell  replaced each  n in the command output with a space  That is why executing seq directly yields  5 lines of output  but using it with        produces just one line of output     A related expression provided by the shell is  lt         Like before  Rc executes the command  within the brackets  when it finds this construct in a command line  The output of the command is  sent through a pipe  and the whole  lt       is replaced by a file name that represents the other end  of the pipe  pipes are also files   as we will see in a following chapter      There are several interesting uses for  lt         one of them is to be able to give a file name for  the input file for a command  but still use as input another command that writes to its standard  output       wc  lt  seq 1 5   LICENSE             5 5 10    d 13
57.  39  43  status   exit  39  43  48  95  188   network  139  Sstem  352  stk acidcommand  48  storage   device  321   device driver  176   disk  321   local  357  store   backing  305   secure  375  stream  295   editor  194  string  180   draw  312   error  40  67  95   match  188  190   optional  202   read  81   replace  194   split  192   substitute  197  string  312  stringsize  313  strip  31  structure  process  276  student account  219  sub expression match  202  subshell  157  substitute string  197     24     substitution  command  116  187  global  197  switch  context  46  231  261  264  thread  264  switch  190  symbol  48  table  31  text  292  undefined  23  symbols  program  22  synchronization  229  246  process  243  thread  272  synchronize  232  235  synchronous communication  117  syntax  command invocation  39  sysfatal  41   sys include  129  Ssysname  43  172  sysname  51  system  call  23  25  46  83  call error  40  67  92  distributed  135  dump  file  163  file  166  224    load  126  mount  file  160  name  43  172    operating  1   protocol  file  159   secure  357   snapshot  file  163   statistics  127   time  77   window  3  6  25  117  172  289  313   system    env file  51   fdfile  102  171   mnt plumb file  128   proc file  50  118  162  rio file  172    T    t   115  203   t   203   Tab  17   tab wdith  17   table  file descriptor  56  153  mount  160 161  symbol  31    tag  8   message  326   rendezvous  246  Tags  326  take c  20  tape 
58.  76   archive  198  tar  198  tarfs  224  TARG  353  Starget  352  targets  mk  349  tas instruction  235  Tattach  326  360  Tauth  361  368  Tclunk  328  tent c  267  TCP echo service  150  tcp7  150  Tcreate  341  telnet protocol  138  telnet  138   flag  r  138  temporary   file  213   files  45  terminal  3  24  313  358   file system  174  termination   process  39  84  158  243   program  254  275  termination  Biobuf  79  termrce  151 171  test  191   flag  d  191   flag  e  191   flag  older  192  test and set  235  testing  354   regression  355  texec c  286    text  address  195  delete  195    drawing  312  editing  193   end of  201   files  179   indent  203  matching  201  mode  298  program  22  representation  292  search  129  201     25      segment  34  51   sort  205   start of  201   symbol  292   window  52  316  the system   entering  3   leaving  6  thello c  63  things  building  349  thinking  wishful  331  Thompson  Ken  21  293  thread  261   argument  266   debugging  267   id  264   identifier  264   T O  274   library  261   name  264   stack  262   stack dump  268   switch  264   synchronization  272   timer  282  threadcreate  262  275  threaded server  148  hreadexits  262  hreadexitsall  262  hreadgetname  267  hreadid  264  hreadmain  262  hreadname  305  hreadnotify  287  hreadpostmountsrv  334  hreads function  acid  267  hreadsetname  267  hreadwaitchan  285  ticker c  243  tickets  362   semaphore  255  tid c  265  tiling  302  time  
59.  8 pnote  the program runs until we press Delete  And then       Delete  note  interrupt  done  interrupted     echo Sstatus       r    The program was executing the sleep system call  it was blocked waiting for time to pass  After  hitting Delete  a note was posted  The natural flow of control for the process was interrupted  and      120     it jumped to execute the note handler  It prints the text for the note  interrupt  and returns true   The note was recognized and Plan 9 is happy with that  The process is not killed  Instead  it con   tinues were it was  Well  mostly     The process did not wait for one hour  Because of the note  the system call was interrupted   It returns an error to report that  But it returns  The program is still running at the same point it  was when the note was posted  We printed the error string reported from sleep to see that it is  interrupted     In general  notes are not to be used in your programs  In other systems  they are used to  remove temporary files if a program is interrupted  In Plan 9  there is a better way for doing this   Any file that you open with the ORCLOSE flag  for example        fd   open   tmp tempfile   ORDWR ORCLOS        Gl    i    is automatically removed by the system when the file descriptor is closed  If your program dies  because of a note  the descriptor is closed as part of the natural dying process  At that point  the  file is removed  Using notes it could be done by installing a note handler like this one  
60.  9 sent a Tversion message to ramfs  which replied by send   ing an Rversion message back  This message is used to agree on a particular version of the  protocol to speak  The request carries the version proposed by Plan 9  The reply carries the ver   sion proposed by the server  The string 9P2000  sent by Plan 9  and acknowledged by ramfs   identifies the version in this case  For the rest of the conversation  both programs agreed to use  messages as defined in the 9P2000 version of the 9P protocol     Furthermore  this message is also used to agree on a maximum message size for the 9P con   versation that follows  In our case  they agreed on using 8 Kbytes as the maximum size for a mes   sage  the value of the msize fields in Tversion and Rversion   This is useful to let both  parties know how big their buffers should be for holding data being exchanged     The second request sent by Plan 9 was Tauth  This has to do with security  which is dis   cussed later  The purpose of the message is to convince the file server that the user mounting the  file tree is who he says he is  In this case  ramfs is credulous and does not need any proof to let  Plan 9 use it  so it replies with an diagnostic message that states that there is no need for authenti   cation  This is the Rerror message that you see  When a request cannot be processed or causes  some error  the file server does not send its corresponding reply message back  Instead  it sends  an Rerror message to the client that b
61.  Each process has certain resources that are abstractions provided by Plan 9 to let it perform  its job  We have seen many of such resources  Memory  environment variables  file descriptors   and note groups     When we discussed fork  we said that a child process is a copy of the parent process   Therefore  it seemed that all resources for the parent were copied to build a  child  clone  Because  fork is so hard to understand the first time you use it  we decided to lie     But the truth is that to create a Plan 9 process you do not have to copy all the resources from  the parent process  You may specify which resources are to be copied  which ones are to be  shared with the parent  and which ones are to be brand new  and empty  just for the child     The system call doing this is rfork  and fork is equivalent to a call to rfork asking for  a copy of the parent   s file descriptor table  a new flow of control  and a copy of the parent   s mem   ory  On the other hand  environment variables  and the note group are shared with the parent     This is the complete list of resources for a process  which can be controlled using rfork     e The flow of control There is not much we can do about it  but to ask for new one  Each one  is called a process        The file descriptor table  Also known as the file descriptor group  You can ask for a copy   or for sharing with the child when creating a process  or for a new table with all descriptors  closed        Environment variables  Al
62.  In few words  mk executes only what is strictly needed to obtain an up to date target  If nothing  has to be done  it does nothing  Of course mk only knows what the mkfile says  you should not  expect mk to know C or any other programming language  It does not know anything about your  source code     What if we want to compile semfs for an ARM  and not for a PC  We must use 5c and 51  instead of 8c and 81  Adjusting the mk file for each architecture we want to compile for is a  burden at least  It is better to use variables    An mkfile may declare variables  using the same syntax used in the shell  Environment  variables are created for each variable you define in the mkfile  Also  you many use environ   ment variables already defined  That is to say that mk uses environment variables in very much  the same way the shell uses it  The next mk file improves our previous one      mice   CC 8c  LD 81  O 8       SO semfs  semfs  O sem  O  SLD  o SO semfs semfs SO sem SO    semfs S O  semfs c sem h  SCC  FVw semfs c    sem SO  sem c sem h  SCC  FVw sem c    The mkfile defines a CC variable to name the C compiler  an LD variable to name the loader   and an O variable to name the character used to name object files for the architecture  The behav   ior of mk when using this mk file is exactly like before  However  we can now change the defi   nitions for CC  LD  and O as follows    CC 5c  LD 51  O 5    Running mk again will compile for an ARM       mk   5c  FVw semfs c   5c  FVw s
63.  It can  be used to pass the data structure for the directory being iterated through calls to getdirent   In our case  we have a single directory and do not use the auxiliary argument     Having implemented getdirent makes it quite easy to implement fsstat  to serve  Tstat requests  The function fsstat must fill r    gt d with the directory entry for the file  involved  Later  respond will fill up an appropriate Rstat message by packing a directory  entry using the network format for it  similar to directory entries traveling in Rread messages for  directories      static void   fsstat  Req  r       Fid  fid   Qid q     fid   r  gt fid   q   fid  gt qid   if  q type amp QTDIR   getdirent   1   amp r  gt d  nil         else  getdirent q path   amp r  gt d  nil    respond r  nil           When the file for Tst at is the directory  we call getdirent to fill r    gt d with the entry for the  file number    1  i e   for the directory itself  Once getdirent did its job  we only have to call  respond     We are now close to completing our file server  We must still implement the function  fswalkl  used by the library  along with fsclone  to implement walk  This function  receives a fid  a file name and a qid  It should walk to the file name from the one pointed to by  fid  For example  if fid refers to the root directory  and name is mut ex  the function should  leave the fid pointing to  mutex  If later  the function is called with the same fid but the name is      the function sho
64.  Let   s do it by hand  We need a victim     Sleep 3600  amp     And this one gives us one hour to play with it  The process is alive and in well shape       118        ps   grep sleep   nemo 1157 0 00 0 00 8K Sleep sleep    echo Sapid   11 537    We check out that it is our process  looking at Sapid  No tricks here  To post a note to a pro   cess  the note text is written to a file in  proc that provides the interface to post notes to it   Remember that this file is just an interface for the process  and not a real file  For this process  the  file would be  proc 1157 note  To do exactly the same that the window system is doing   we want to post the note to all processes sharing its window  Writing the note to   proc 1157 notepg does this       echo interrupt  gt  proc 1157 notepg  7  ps   grep 1157    It is gone     The file is called not epg because it refers to a process group  Processes belong to groups  only for administrative reasons  For example  Delete should affect all the processes active in a  window  Otherwise  you would not be able to interrupt a command line with more than one pro   cess  like a pipeline     Usually  there is a process group per window  and it is used to deal with all the programs on  the window at once  When a window is deleted using the mouse  you expect the programs run   ning on it to die  The window system posts a hangup note when the window is deleted  The note  is posted to all the processes in the window  i e   to the process group of t
65.  Looking back at figure 1 8 will let you see the elements involved  Processes using Plan 9  make system calls  including open  close  read  and write  Plan 9 implements such system  calls by speaking 9P with the file server involved  In the figure  steps 3 and 4 correspond to 9P  messages exchanged to implement write  The last element involved is the file server process   which attends the messages sent by Plan 9 to do the file operations requested by Plan 9     All the 9P dialog between Plan 9 and a file server is based on remote procedure calls  Plan 9  sends a request to the server and receives a reply from it  The file server is called a server because  it accepts requests  represented by messages   and it attends each request before sending a reply  back  also represented by a message   In the same way  the program making requests  Plan 9 in  this case  is called a client because of a similar reason  Each request and reply is just a particular  data structure  sent as an array of bytes through a network connection  a pipe  or any other com   munication means     Before discussing 9P any further  let   s take a look at an example  The command ramfs  as  many other file servers  prints the 9P dialog when called with the flag  D  Any 9P message  received by ramfs  carrying a request  is printed and then processed  Any 9P message sent back  as a reply from ramfs is printed as well  Of course  ramfs does not print in the console the  actual messages as exchanged through the n
66.  NOTICE bin dir lib tmp                1 8  Files and data    Like in most other systems  in Plan 9  files contain bytes  Plan 9 does not know  nor cares  about  what is in a file  It just provides the means to let you create  remove  read  and write files  If you  store a notice in a file  it is you who knows that it is a notice  For Plan 9  that is just bytes  We  can use cat  catenate  to display what is in a file      16       cat  NOTICE  Copyright    2002 Lucent Technologies Inc   All Rights Reserved    T    This program reads the files you name and prints their contents  Of course  if you name just one   it prints just its content  If you cat a very long file in a Plan 9 terminal  beware that you might  have to press the down arrow key in your keyboard to let the terminal scroll down     What is stored at  NOTICE  We can see a dump of the bytes kept within that file using the  program xd  hexadecimal dump   This program reads a file and writes its contents so that it is  easy for us to read  Option  b asks xd to print the contents as a series of bytes                xd  b  NOTICE   0000000 43 6f 70 79 72 69 67 68 74 20 c2 a9 20 32 30 30  0000010 32 20 4c 75 63 65 6e 74 20 54 65 63 68 6e 6f 6c  0000020 6f 67 69 65 73 20 49 6e 63 2e Oa 41 6c 6c 20 52  0000030 69 67 68 74 73 20 52 65 73 65 72 76 65 64 Oa  000003Ff    g       The first column in the program output shows the offset  the position  in the file where the bytes  printed on the right can be found  This offset is
67.  No one else has to care about which particular network  address  or  port number corresponds to a network address     All the information regarding the connections in use at your machine can be obtained by  looking at the files below  net  Nevertheless  the program netstat provides a convenient  way for obtaining statistics about what is happening with the network  For example  this is what  is happening now at my system       netstat      140                     tcp 0 nemo Listen audio 0 23   tep  I Established 5757 9fs whale lsub org  ECP 2 nemo Established 5765 ads whale lsub org  tep 3 nemo Established 5759 9fs whale lsub org  tcp 4 nemo Listen what 0     tcp 5 nemo Established 5761 ads whale lsub org  tcp 6 nemo Established 5766 ads whale lsub org  ECD   lt 7 nemo Established 5763 9fs whale lsub org  tcp 8 nemo Listen kbd 0 oes      many other lines of output for tcp      udp 0 network Closed 0 0   udp 1 network Closed 0 0          Each line of output shows information for a particular line directory  For example  the TCP con   nection number 1  i e   that in  net  tcp 1  is established  Therefore  it is probably being used  to exchange data  The local end for the connection is at port 5757  and the remote end for the con   nection is the port for service 9fs at the machine with name whale 1lsug org  This is a con   nection used by the local machine to access the 9P file server at whale  It is being used to  access our main file server from the terminal where I executed
68.  ORCLOSE open flag  120  order  instruction  233  OREAD open mode  58 59  origin  screen  302  OTRUNC open mode  62                         Fs    out  loging  4  6  output    base  183   discard  107   formatted  55  redirection  101  redirection  standard  105  standard  56 57  verbose  198    overlap  window  317  owner    file  69  machine  358    ownership  file  18  OWRITE open mode  58 59  61       P     p device driver  50  162  167  P format  298   page  manual  129   page  129  355   paging  demand  34   pair  address  195   panel process  241   panels  airport  241  274  parallel  30    execution  30    parent process  83  88  153  parsing  192   partition  321   partition    9fat  322  fs  322  plan9  322    partitioning    automatic  324  disk  324    partitions  322    adding  323  deleting  323    passwd  374  password  357  363   path  43   path  13  58  153  159    device  166  relative  35    path  51    Qid  328  variable  170    paths    absolute  13  relative  13    pattern  191    AWK  215    character range  74  pattern     73     74  BEGIN  217  END  217  patterns  file name  73  patterns file  210  pce c  254  performance  77  measurement  194  permission check  360  permissions  69  change  19  directory  19  file  18  in octal  20  octal  69  permitted operation  360  person  malicious  357  Pfmt  298  picture element  295  Spid  45 58  PID  265  pid  45  shell  45  window  315  pid c  45  Pike  Rob  7  293  ping  140  189  ping pong  270  pipe  107 
69.  Plumbmsg m           int fd   fd   plumbopen  send   OWRITE    if  fd  lt  0    sysfatal  open  Sr     m src   m dst   m wdir   nil   m type    text    m attr   nil   m data     NOTICE    m ndata   strlen m data    if  plumbsend fd   amp m   lt  0       sysfatal  send  Sr         133      Problems    1    What would this command do    cp  fd 1  fd 0  Why do you think that the code to initialize standard input  output  and error in the first pro   cess differs from this     open    dev cons  ORDWR     dup  0  1    dup  0  2      The code    fd   open   NOTICE    dup  fd  0    close  fd         OREAD             may fail and leave standard input closed  When does this happen  Why do you think this  code was used for a program that redirected standard input to  notice     Show that a process that reads from an empty pipe gets blocked and will never run  Which  state is reported by ps for such process     Modify the code for the srvecho program to perform the echo through the pipe  and not to  the console  Use the program con 1  to connect to the pipe through  srv echo and test  that it works       134       135      6     Network communication    6 1  Network connections    Plan 9 is a distributed system  But even if it was as its ancestor  UNIX  a centralized system that  was designed just for one machine  it is very important to be able to use the network to provide  services for other machines and to use services from others  All the operating systems that are in  use today 
70.  Rerror       Rattach  Ropen  Ropen  Rcreate       ay    Rauth    Tattach  Tattach  Tattach    Tauth   Tauth   Tauth        Tcreate     Tcreate     Tcreate  Topen    Twalk     Twalk        Twalk    Rwalk        Rwalk    Twrite  Twrite   Rread    Tread   Tread   Twrite     Rstat  Rstat    Twstat   Twstat     sion     sion         Recreate             X7        if                xo  Rread               ar      338      Most 9P requests refer to a particular fid  which is a number that represents a particular file  in use by the client  Thus  a Req contains a pointer to a Fid data structure that represents a fid   maintained by 1ib9p  The library keeps a table for fids in use  and a F id data structure for each  one  When the protocol dictates that a new fid is allocated  the library creates a Fid and updates  the table  The library also releases fids when they are no longer in use  A Fid looks like follows     typedef struct Fid Fid   struct Fid      ulong fid     char omode      1   not open     Qid qid   void  aux           It contains the fid number  the open mode for the fid  or    1 if it is not open   and the qid for the  file referenced by the fid     The purpose of fsattach is to let clients attach to our tree  by making the fid refer to our  root directory and replying with an Rattach message informing of its qid  The library helps in  mapping fids to qids  because it handles all the Fid structures and keeps their qids in each  Fid qid  But the file server must still m
71.  This is the pipe   261 1887 13006  LICENSE  266 1892 13016 total    a    But  perhaps  the most amazing use for this construct is to build non linear pipelines  That is  to  use the output of several commands as input for another one  For the latter  the output of the for   mer ones would be just a couple of file names  An interesting example is comparing the output of  two commands  The shell command cmp compares two files  and informs us whether they have  the same contents or not       cp  LICENSE  tmp 1     cmp  LICENSE  tmp 1   7 cmp  LICENSE  NOTICE   LICENSE  NOTICE differ  char 1                  117     Therefore  if you want to execute two commands and compare what they write to their standard  output  you can now use cmp as well       cmp  lt  seq 1 3   lt fecho 1   echo 2   echo 3     cmp  lt  seq 1 3   lt fecho 1 2 3      d 14  fda 13 differ  char 2    g    You will get used to        and  lt       after using them in the couple of chapters that discuss pro   gramming in Rc     5 6  Notes and process groups    Pipes are a synchronous communication mechanism  A process using a pipe must call read or  write to receive or send data through the pipe  and communication happens only when the pro   cess makes these calls  Sometimes  the world is not so nice and we need an asynchronous  communication mechanism  For example  if a process gets out of control and you want to stop it   you may want to post a note saying    interrupt    to the process  The process is not rea
72.  Variables can  be strings  integers  floating point numbers  and arrays  As a convenience  AWK defines a new      215      variable the first time you use it  i e   when you initialize it     The predefined variable  1 is a string with the text from the first field  Because the action  where  1 appears is executed for a record   1 would be the first field of the record being pro   cessed  In our program  each time print  1 is executed for a line   1 refers to the first field for  that line  In the same way   2 is the second field and so on  This is how we can list the names for  the processes in our system       ps   awk     print  7 7  genrandom   alarm   rxmitproc   factotum   fossil    It may be easier to use AWK to cut fields than using sed  because splitting a line into fields is a  natural thing for for former  White space between different fields might be repeated to tabulate  the data  but AWK managed nicely to identify field number 7    The predefined variable  0 represents the whole record  We can use it along with the vari   able NR  which holds an integer with the record number  to number the lines in a file     number     bin re  awk      printf  S4d s n   NR   0               We have used the AWK function printf  which works like the one in the C library  It provides  more control for the output format  Also  we pass the entire argument list to AWK  which would  process the files given as arguments or the standard input depending on how we call the script      
73.  a time  but it must use raw mode     4 Write a program that draws the pixels under the mouse while a button is pressed     5 Make the program draw text when a key is pressed  The text to draw is the character typed  and the position would be the last position given by the mouse    6 There is an alternate library  called event that provides event driven mouse and keyboard  processing  Implement the previous programs using this library  Compare     7 The  dev kbmap file provides keyboard maps  Look through the manual and try to      319      change the map  Locate one defining several keyboard keys as mouse buttons       320        321      13     Building a File Server    13 1  Disk storage    The file server we are going to build will not be using a disk to provide file storage  it will pro   vide a rather different service  But before building our new file server  it may be instructive to  look a little bit to what would be needed to actually store files on a disk     There are many file servers involved in disk storage  not just one  To store files on disk   you need a disk  Like all other devices  disks are files in Plan 9  This may be a surprise  as disks  are also used to store files  The device sd 3  provides storage devices  This is a list of files served  by the device driver    z te  5     sdco sdcl sdDO sdcetl    Each such file  but for sdct1  is a directory that represents a disk  or perhaps a CD or DVD  reader or writer  The file name for each device is similar t
74.  always executed by a new shell  Commands in the script are  read by the child shell  and not by the original one  Look at this    7 cat cdtmp     bin re   cd  tmp     pwd    usr nemo     chmod  x cdtmp  7 cdatmp     pwd    usr nemo    Is Plan 9 disobeying  Of course not  We executed cdtmp  But commands in the script are not  executed by the shell we are using  A new shell was started to read and execute the commands in  the file  That shell changed its working directory to  tmp  and then died  The parent process  the  shell we are using  remains unaffected  This may confirm what we said    7 cat cdtmp     bin re  cd  tmp   pwd     pwd   usr nemo   7 cdtmp   tmp     pwd   usr nemo    This mechanism works for any program  and not just for the shell  For example  hoc is a floating  point calculator language  It can be used to evaluate arbitrary floating point calculations  When  given a file name  hoc interprets the expressions in the file and prints any result  Now we can  make an interpreted program that lets you know the output of 2 2       99        cat 242     bin hoc   2  2     chmod  x 2 2  eee SA   4    Amazing    Because the shell can be used to write programs  it is a programming language  It includes  even a way to write comments  When the shell finds a   character  it ignores it and the rest of the  line  That is why the special format for the first line of interpreted programs in Plan 9 starts with    that character  When the shell interprets the script  it reads t
75.  and tmp  as the arguments for echo  instead of supplying the           It could be either  the shell or echo the one responsible for this behavior  There is no magic  and no other program    was involved on this command line   The shell gives special meaning to certain characters  we already saw two           and                One of them is          When the a command line contains a word that is          it is replaced with the    kas    names for all the files in the current directory  Indeed          works for all directories   Le pin  386 re    echo bin    bin 386 bin re    r    In this case  the shell replaced bin   with two names before running echo  bin 386 and  bin rc  This is called globbing  and it works as follows  When the shell reads a command  line  it looks for file name patterns  A pattern is an expression that describes file names  It can    be just a file name  but useful patterns can include special characters like     The shell replaces  the pattern with all file names matching the pattern     For example    matches with any sequence of characters not containing          Therefore  in  this directory    ane KO  bin book lib tmp  the pattern   matches with bin  book  lib  and tmp     echo    bin book lib tmp  The pattern b  matches with any file name that has an initial    bo    followed by          i e  followed  by anything  This means    echo b   bin book  The pattern  i  matches with anything  then an i  and then anything      echo  ZIF  bin lib  Ano
76.  be combined in any of the ways shown  Furthermore  the user  might want to echo just  word   and echo might be confused because it would think that     word  was a set of options  The standard procedure is to do it like this        8 echo word    The double dash indicates that there are no more options  Isn   t it a burden to process argc and  argv to handle all these combinations  That is why there are a set of macros to help  macros are  definitions given to the C preprocessor  that are replaced with some C code before actually com   piling   The following program is an example     eee    aecho c     include  lt u h gt      include  lt libc h gt     void  main int argc  char  argv               int nflag   0   int vflag   0   int Ty  ARGBEGIN   Case tyin   vilag   1    break   case  ne    nilag 21    break   default    fprint 2   usage   s   nv  args n   argv0      exits   usage            ARGEND   for  i   0  i  lt  argc  itt   if  vflag   print      s     argv i     else  print   Ss    argv i     if   nflag     print    n     exits  nil                    The macros ARGBEGIN and ARGEND loop through the argument list  removing and processing  options  After ARGEND  both argc and argv reflect the argument list without any option   Between both macros  we must write the body for a switch statement  supplied by  ARGBEGIN   with a case per option  And the macros take care of any feasible combination of  flags in the arguments  Here are some examples of how can we run our prog
77.  be read  the func   tion returns zero     Sometimes it is useful to change file attributes  For example  changing the length to zero  may truncate the file  A rename within the same directory can be achieved by changing the name  in the directory entry  Permissions can be changed by updating the mode in the directory entry   Some of the attributes cannot be updated  For example  it is illegal to change the modification  type  or any of the type  dev  and qid fields     The function dirwstat is the counterpart of dirstat  It works in a similar way  but  instead of reading the attributes  it updates them  New values for the update are taken from a Dir  structure given as a parameter  However  the function ignores any field set to a null value  to  allow you to change just one attribute  or a few ones  Beware that zero is not a null value for  some of the fields  because it would be a perfectly legal value for them  The function nulldir  is to be used to null all of the fields in a given Dir     Here is an example  The next program is similar to chgrp 1   change group  and can be  used to change the group for a file  The main function iterates through the file name s  and calls  a chgrp function to do the actual work for each file     ms pee    chgrp c     include  lt u h gt    include  lt libc h gt     void  chgrp char  gid  char  fname        Dir d     nulldir  amp d    d gid   gid   if  dirwstat  fname   amp d   lt  0   forint  2   chgrp  wstat   Sr n       void  main int ar
78.  because  if you remove a binary file for a program that is executing  the corresponding  process may get broken if it needs a part of the program that was not yet loaded into memory   And the same might happen if you overwrite a binary file while a process is using it to obtain its  code     Because memory is virtual  and is only allocated when first used  any unused part of the  BSS segment is free  It consumes no memory until you touch it  However  if you initialized it  with a loop  all the memory will be allocated  One particular case when this may be useful is  when you implement large hash tables that contain few elements  called sparse   You might  implement them using a huge array  not initialized  Because it is not initialized  no physical mem   ory will be allocated for the array  initially  If the program uses later a portion of the array for the  first time  the system will allocate memory and zero it  The array entries would be all nulls      35     Therefore  in this example  initializing by hand the array would have a big impact on memory  consumption     2 3  Process birth and death    Programs are not called  they are executed  Besides  programs do not return  their processes ter   minate when they want or when they misbehave  Being this said  we can supply arguments to  programs we run  to control what they do     When the shell asks the system to execute a program  after it has been loaded into memory   the system provides a flow of control for it  This me
79.  bind  a  tmp other  tmp adir    When a mount entry is a union  and has several mounted files  the name space tries each one in  order  until one works for the name being resolved  When reading the directory  all of the feasible  targets are read  Note that unions only make sense when the files are directories  By the way  to  mount or bind before the previous contents of a union  use the flag  b for either program     Unions can be confusing  and when you create files you want to be sure about where in the  union are you creating your files  To help  the flag  c can be supplied to either bind or mount  to allow you to create files in the file tree being mounted  If you do not supply this flag  you are  not allowed to create files in there  When trying to create a file in a union  the first file in the  union mounted with    c is the one used     7 9  Changing the name space    To adjust the name space in a C program  two system calls are available  They are similar to the  shell commands used above  which just call these functions according to their command line  arguments      sig bind mount  int bind char  name  char  old  int flag   int mount  int fd  int afd  char  old  int flag  char  aname     The system call used by the mount command we saw above is mount  It takes a file descriptor   fd  used to reach the file server to mount  It must be open for reading and writing  because a 9P  conversation will go through it  The descriptor is usually a pipe or a network connecti
80.  but uses the machine name   whale  and the service name  9fs  instead of the raw addresses understood by the network soft   ware  Often  ports are used by programs to provide services to other programs in the network  As  aresult  a port name is also known as a service name     From the shell  it is very easy to create connections  The srv program dials a network  address and  once it has established a connection to that address  posts a file descriptor for the  connection at  srv  This descriptor comes from opening the data file in the directory for the  connection  but you may even forget this  Therefore       srv tcp  whale 9fs    Poste s24     posts at  srv tcp whale  9fs a file descriptor that corresponds to an open network connec   tion from this machine to the port named 9fs at the machine known as whale  in the network  speaking the protocol t cp     To connect to the web server for LSUB  we may just    srv tcp ilsub org http  post i     Here  tcp is just a shorthand for  net tcp  which is the real  file  name for such network in  Plan 9  Now we can see that  srv tcp 1lsub org http is indeed a connection to the web      138      server at lsub org by writing an HTTP request to this file and reading the server   s reply             echo GET  index html  gt  gt  srv tcp lsub org http Get the main web page    cat  srv tcp isub org http    lt html gt     lt head gt     lt title gt  Laboratorio de Sistemas ls  lt  title gt     lt link rev  made  href  mailto ls plan9 esce
81.  buttons 0   mouse pos  887 191 buttons 1 button I down  mouse pos  887 191 buttons 3 button 2 down  mouse pos  887 191 buttons 1 button 2 up  mouse pos  887 191 buttons 0 button I up  mouse pos  887 191 buttons 0   mouse pos  887 191 buttons 1 button I down  mouse pos  887 191 buttons 3 button 2 down  mouse pos  887 191 buttons 7 button 3 down    L    As you could see  each button is codified as a single bit in the number  Button 1 is the bit 0   button 2 is the bit 1  button 3 is the bit 2  and so on  A click for button one will yield 1 while it is  down  and 0 when released  A click for button 3 will yield 4  i e   100 in binary  when it is down  and O when released  Our program exits when all the three buttons are down  that is  when the  number is 7  i e   111 in binary      Instead of reading  dev mouse by itself  the program uses the mouse 2  library  This  library provides a mouse interface for threaded programs  Programs using the mouse are likely to  do several things concurrently  attend the keyboard  do something for their user interface  etc     Therefore  it is natural to write a threaded program when the application requires a graphical user  interface     mouse c    include  lt u h gt           include  lt libc h gt     include  lt thread h gt           include  lt draw h gt                 include  lt mouse h gt       297      void  threadmain int   char           Mousect1l mctl   Mouse m     fmtinstall    P     Pfmt     mctl   initmouse   dev mouse   nil    
82.  can see the contents of the archive using the option t       tar  t  lt  tmp music tar  alanparsons   alanparsons irobot mp3  alanparsons whatgoesup mp3  pausini   pausini trateilmare mp3  supertramp   supertramp logical mp3    Option    v  adds verbosity to the output  like in many other commands       199        tar  tv  lt  tmp music tar    d rwxr xr x O Jul 21 00 02 2006 alanparsons        Yw Yr  r     13 Jul 21 00 01 2006 alanparsons irobot mp3      Yw Yr  r     13 Jul 21 00 02 2006 alanparsons whatgoesup mp3  d rwxr xr x O0 Jul 21 00 02 2006 pausini        Yw Yr  r     13 Jul 21 00 02 2006 pausini trateilmare mp3  d rwxr xr x O Jul 21 00 02 2006 supertramp        Yw Yr  r     13 Jul 21 00 02 2006 supertramp logical mp3    This lists the permissions and other file attributes  To extract the files in the archive  we can use  the option    x  Here we add an v as well just to see what happens       cd otherdir     tar xv  lt  tmp music tar  alanparsons  alanparsons irobot mp3  alanparsons whatgoesup mp3    pausini   pausini trateilmare mp3   supertramp   supertramp logical mp3   a  SC   alanparsons pausini supertramp    The size of the archive is a little bit more than the size of the files placed in it  That is to say that  tar does not compress anything  If you want to compress the contents of an archive  so it occu   pies less space in the disk  you may use gzip  This is a program that uses a compression algo   rithm to exploit regularities in the data to use more effic
83.  case the child wrote  first  That advances its own offset for the file  The other offset stays at 0  Therefore  both     91     processes overwrite the same part of the file     It could be that the parent executes its write before the child  in which case we would get  this  which would be also an overwrite       cat afile  child    There is one interesting thing to learn here  We have said that either write  parent   s and child   s   can execute before the other one  Couldn   t it be that part of a write is executed and then part of  the other  In principle it could  But in this case  it will never happen     Plan 9 guarantees that a single write to a particular file is fully executed and not mixed  with other writes to the same file  This means that if there are two write calls being made for  the same file  one must execute before the other  For different files  they could execute simultane   ously  i e   concurrently   but not for the same file in Plan 9     When one operation is guaranteed to execute completely without being interrupted  it is  called atomic  The Plan 9 write system call is atomic at least for writes on the same file and  when the number of bytes is not large enough to force the system to do several write operations to  implement your system call  In our system this happens for writes of at most 8Kbytes     4 4  Race conditions    What you just saw is very important  It is not to be forgotten  or you risk going into a debugging  Inferno  When multiple
84.  chan  1  Ox777777FF       A call to allocimage allocates a new image  associated to the Display given as an argu   ment       sig allocimage  Image  allocimage  Display  d  Rectangle r  ulong chan  int repl  int col     When the display is closed  and the connection to draw is closed as a result   the images are deal   located  Note that the images are kept inside the draw device  The function talks to the device  to  allocate the images  and initializes a couple of data structures to describe the images  you might  call them image descriptors      The second argument for allocimage is the rectangle occupied by the image  In this  case  we use a rectangle with points  0 0  and  1 1  as its min and max points  If you remember  the convention that the minimum point is included in the rectangle  but the maximum point is not   it just marks the limit   you will notice that both images have just one pixel  That is  the point      308      with coordinates  0 0   For declaring a literal  i e   a constant  fora Rectangle data type  we  used Rect  which returns a Rectangle given the four integer values for both coordinates of  both extreme points  Another function  useful to obtain a Rectangle from two Point values   is Rot       Sig Rect Rpt  Rectangle Rect  int x0  int yO  int xl  int yl   Rectangle Rpt  Point p  Point q     By the way  the function Pt does the same for a Point  Indeed  ZP is defined as Pt  0 0        sig Pt  Point Pt int x  int y     Images for colors need just o
85.  child    Let   s have some fun  This is a runaway program  It creates a child and then dies  The child con   tinues playing the same game  This is a nasty program because it is very hard  or impossible  to  kill  When you are prepared to kill it  the process has gone and there is noone to kill  But there is  another process taking its place       88      diehard c     include  lt u h gt      include  lt libc h gt     void  main int  char         while fork      0   A    catch me   exits  nil           This version is even more nasty  It creates processes exponentially  which might happen to you  some day when you make a mistake calling fork  Once the system cannot cope with more pro   cesses  there will be nothing you could do but rebooting the machine  Try it as the last thing do  you in one of your sessions so that you could see what happens     rabbits c   include  lt u h gt      include  lt libc h gt        void   main int  char             just like rabbits     while  fork        exits  nil      4 3  Shared or not     Fork creates a clone process  Because the child is a clone  it has its own set of file descriptors   When fork returns  the descriptors in the child are a copy of those in the parent  However  that is  the only thing copied     Of course  the files referenced by the descriptors are not copied  The Chan data structures  that maintain the offset for the open files are not copied either  Figure 4 2 shows both a parent  and a child just after calling fork  sho
86.  compiled program is free to use any  of them  What the system does is to assign the whole resource for a limited amount of time to a  program  and then to another one in turn  In this case  the resource is multiplexed on time   Because machines are so fast  you get the illusion that all the programs work nicely as if the  resource was always theirs     People make mistakes  and programs have bugs  A bug in a program may bring the whole  system down if the operating system does not take countermeasures  However  the system is not  God  and magic does not exist  or does it    Most systems use hardware facilities to protect exe   cuting programs  and files  from accidents     For example  one of the first things that the system does is to protect itself  The memory  used to keep the system program is marked as privileged and made untouchable by non   privileged software  The privilege level is determined by a bit in the processor and some informa   tion given to the hardware  The system runs with this bit set  but your programs do not  This  means that the system can read the memory used by your program  but not the other way around   Also  each program can read and write only its own memory  assigned to it by the system   This    mee    means that a misleading pointer in a buggy program would not affect other programs  Did you  notice that when your programs crash the other programs seem to remain unaffected  Can you say  why    To summarize  the operating system is just some 
87.  conditions  You must use threads  and channels as the building blocks for the program     2 One way to determine if a number is prime is to filter all natural numbers to remove num   bers that are not prime  Using different thread for filtering numbers that divide candidate  numbers  write a program to write prime numbers     3 There are different cars trying to cross a bridge  There are cars on both sides of the bridge   Simulate this scenario using threads and channels  Avoid accidents     4 The dining philosophers problem is a very famous one in concurrent programming  There  are philosophers who loop forever trying to think  and then to eat  All of them are sitted  around a round table  with a single chopstick between each two philosophers  To eat  a  philosopher needs both the chopstick on the left and the one on the right  Write a program to  simulate this scenario using threads for the different philosophers     5 Avoid starvation in the previous problem       288        289      12     User Input Output    12 1  Console input    In chapter 7 we saw that  c is the root of the file tree exported by the cons 3  driver  It is conven   tionally bound at  dev  and provides the familiar  dev cons file  Reading  c cons obtains  input from the console keyboard  Writing to  c cons writes characters in the console screen     When rio  the window system  is running  it reads  c cons to obtain the characters you  type  Writing them in the screen is a different story that we will 
88.  could exploit this in our program to synchronize more tightly both threads and use just  one channel  This is useful to better understand how channels can be used  but  perhaps arguably   it leads to a more obscure  yet compact  program     Suppose that initially ping sends a message to pong and pong receives it  The former  calls send and the later calls recv  If ping calls send first  it is going to block until pong  calls recv on the channel  which had no buffering   And vice versa     Now comes the point  When ping completes its send it is for sure that pong has com   pleted its recv  Or we could say that when pong completes its recv it is certain that ping  completed its send  Therefore  the same channel can be used again to send a number back  This  time  pong calls send and ping calls recv  Again  both calls will rendezvous  the first call  made will block and wait for the other  There is no doubt regarding which recv is going to  receive for which send  So  the code would work along these lines       273      ping        1  send c   amp msg      sends to  3     2  recv c   amp msg      receives from  4       pong        3  recv c   amp msg      receives from  l    4  send c   amp msg      sends to  2          But both threads look fairly similar  In fact  considering their loops  they look the same  Receive  something  increment it  send it back  Only that while one is receiving the other one is sending   Therefore  we could use the same code for both threads  like t
89.  data structures that do not form cycles  If there are cycles  there may be circular lists not  referenced from outside  that would never be deallocated by reference counting because there is at  least one reference for each node  from the previous node in the cycle      The thread library provides reference counters  protected by locks  They can be used safely  even when multiple processes are incrementing and decrementing the counters  which by the way   is not the case here  A Ref structure is a reference counter  containing a ref field with the  counter and a lock  The function incref increments the counter  using the lock to protect from  possible races   The function decref decrements the counter and returns the new value for it     As you could see  newsem sets sems  i      gt ref to 2  because it is returning one reference  and also storing another reference in the array of semaphores  Both references must go away  before releasing the semaphore  To release one reference  the function closesem can be called     void   closesem Sem  s        if  s    nil  amp  amp  decref s     0     assert  s  gt reqs    nil    assert  sems s  gt id  s    sems  s  gt id    nil   free  s  gt name    free  s                    It decrements the reference counter for s  but releases the data structure only when no other refer   ences exist  i e   only when decref reports that s    gt ref is zero after discounting one reference   To allow calls to closesem with nil pointers  a check for s
90.  display  301  dissociated child  158  distributed  computing  151  174  system  135  distributive concatenation  182  DMA  321  dma  321  DMA  setting up  321  DMDIR  66  330  DNS  139  doctype  354  document viewer  129  domain  authentication  363  domains  authentication  362  dot directory  14  dot dot directory  14  down  338  down  255  draw  connection  299  device  299  operation flush  302  string  312  draw  302  drawing  functions  312  graphics  301  slider  306  text  312  drive unit  322  driver  device  26  166  storage device  176  driver    device  166  c device  171  289  d device  171  e device  51  167  i device  300  m device  295  p device  50  162  167  S device  176  321  v device  298  dst  130  du  198  205  dump  file  75  file hexadecimal  16  file system  163  message  369  stack  237  thread stack  268  dup  104 105  123          in rc  107  duplicate file descriptor  104  duplicates  remove  207  Dx  308  Dy  308  DYellow  308    E     e device driver  51  167  EARGF  39  echo   character  292   console  292   server  123   server  network  147   service  TCP  150  echo  35  73   flag  n  36  echo c  35  44  edata  33  edit plumb port  128  editing  6   text  193  editor  stream  194  edits c  130  efficiency  125  194  elapsed time  77  element  picture  295  emalloc9p  340  empty   directory  67   list  182  encrypt  375  end of   file  17  111   line  201   pipe  225   text  201  end  33  END pattern  217  entering the system  3  entry   dir
91.  editors are shar   ing the files at  mnt  plumb  When you plumb a file name  the plumber sends the message to  all editors reading from the edit port  as we saw     But let   s change the name space in a window  for example  by executing      9fs whale    to mount at  n whale the file server named whale  Here comes the surprise  When we try to  plumb  n whale NOTICE  this is what we get                plumb  n whale NOTICE    echo Sstatus  plumb 1499  error          The plumber was unable to locate  n whale NOTICE  After we mounted whale on   n whale     But reconsider what happen  The shell running in the window is the one that mounted   n whale  the plumber is running using its own name space  far before our window was  brought to life  Therefore  the plumber does not have anything mounted at  n whale  It is our  shell the one that has something mounted on it           To change the name space for the plumber  a nice trick is used  The plumbing file  con   taining the rules to customize plumbing  usually has one specific rule for messages starting with      166      the string Local  This rule asks the plumber to execute the text after Local in a shell started  by the plumber  For example  we could do this       plumb    Local 9fs whale       plumb  n whale NOTICE    echo Sstatus    r    The first command plumbs Local 9fs whale  which makes the plumber execute 9fs  whale in a shell  Now  this shell is sharing the name space with the plumber  Thus  the com   mand plumbed ch
92.  even trying to put anything in the buffer  the producer tries to get a hole  To do so  it  acquires a ticket from the semaphore representing the holes available  If there are no tickets  the  producer sleeps  Otherwise  there is a hole guaranteed  Now  to put the message in the hole  acquired  a semaphore called mutex  with just one ticket for providing mutual exclusion  is  used  Upon acquiring the only slot for executing in the critical region  the producer adds the mes   sage to the buffer  Also  one we have done our work  there is a new message in the buffer  A new  ticket is added to the semaphore representing tickets to maintain it consistent with the reality     The code for a consumer is equivalent     char   get  Buffer  b        char  msg     wait  b  gt smsgs      wait  b  gt mutex      msg   b  gt msgs b  gt hd    b  gt hd     b  gt hd   Nmsgs   b  gt nmsgs      signal  b  gt mutex      signal  b  gt sholes    return msg          Semaphores are to be handled with care  For example  changing the first two lines above with    wait  b  gt mutex     wait  b  gt smsgs       is going to produce a deadlock  First  the consumer takes the mutex  ticket  for itself  If it hap   pens now that the buffer is empty  and smsgs has no tickets  the consumer will block forever   Nobody would be able to wake it up  because the producer will not be able to acquire the mut ex  for itself  It is very dangerous to go to sleep with a lock held  and it is also very dangerous to go  to sl
93.  files  most of the  times  The file  srv fscons is not a file  it looks like  but it is just a file interface for a file  descriptor that fossil has open  Because  srv fscons looks like a file  you can open it and  gain access to the file descriptor  And you do not require a common ancestor with fossil     For example  this  when executed in the file server  asks fossil to write any pending  change to the disk       echo sync  gt  gt  srv fscons    When the shell opens  srv fscons  it is not opening yet another file  It is obtaining a file  descriptor that is similar to the one posted into  srv fscons by fossil  The result is the  same of calling dup to duplicate the descriptor kept inside  srv fscons  however  you cannot  call dup  You do not have the file descriptor to duplicate  because it belongs to another process     This program is an example of how to use this bulletin board  It creates one pipe and reads  text from it  printing a copy to standard output  so we could see what is read  The other end of the  pipe is posted at  srv echo  for us to use       124      srvecho c     include  lt u h gt      include  lt libc h gt     void  main int  char             int fd 2    int srvfd   char buf  128    int nr     if  pipe fd   lt  0   sysfatal  pipe  Sr     srvfd   create   srv echo   OWRITE  0664    if  srvfd  lt  0   sysfatal   can   t create at  srv   r     if  fprint srvfd    d   fd 1    lt  0   sysfatal  can   t post file descriptor   r     close fd 1     for  77   
94.  files connected to each other  What you write into one of them  is what will be read from the  the other  That is why in the figure  the input for one process goes into one end of the pipe  and  the output for the other process may go to the other end of the pipe     To create a pipe in a C program  you can use the pipe system call  It returns two descrip   tors  one for each end of the pipe  Both descriptors are stored at the integer array passed as a  parameter to the function     int fd 2      pipe  fd         d 0  has the fd for one end       d 1  has the fd for the other     This program does some stupid thing  but it helps to understand  It writes some text to one end of  the pipe  and reads it back from the other end  To see the outcome  it prints what it did read to its  standard output       110         include  lt u h gt      include  lt libc h gt     void  main int  char             int fd 2    char buf  128    int nr     if  pipe fd   lt  0   sysfatal  can   t create a pipe  Sr     write fd 1    Hello  n   7    nr   read fd 0   buf  sizeof  buf     write 1  buf  nr    exits nil           This is the output    8 pipe  Hello     z    Because standard output is file descriptor 1  and standard input is file descriptor 0  the tradition is  to read from fd 0  and write into fd 1   as the program does  Pipes are bi directional in Plan  9  and doing it the other way around works as well  It is said that Plan 9 pipes are full duplex     Let   s try now something slightly 
95.  for the terminals in your network  Use   1ib ndb 1local to locate other terminals    3 Start the echo server implemented in this chapter  and try to hangup its connection using the  shell    4 Which processes are listening to the network in your terminal  What do they do   use the  manual    5 Which one is the IP address for google com  Is the machine alive  Try to determine that  in several different ways    6 Implement a time of day service  It must return the local time to any client  Use telnet to  test it    7 Implement a client program for the server from the previous problem    8 Print all the information you can determine for all clients connecting to your time of day  server    9 Change your server so it could be started using aux listenl  Test it    10 Change your profile to adjust the shell prompt according to the machine name  It must work    both for terminals and connections to CPU servers       153      7     Resources  Files  and Names    7 1  Resource fork    In chapter 4 we used fork to create new processes  We said that fork was a system call  We  lied  It is not a venial lie  like when saying that getenv is a system call  because it is a library  function   It is a terrible lie  because Plan 9 processes are not just clones  Now it is time to tell  the truth     A Plan 9 process is mostly what you imagine because of what we have said so far  It is a  flow of control known by the kernel  which creates the illusion of having a dedicated processor to  run it 
96.  given a complete address  Including the network name and the service name  Like  for  example       8 srv tcp whale 9fs    Instead  the program calls netmkaddr which is a standard Plan 9 function that may take an  address with just the machine name  or perhaps the network name and the machine name  This  function completes the address using default values for the network and the service  and returns a  full address ready to use  We make tcp the default value for the network  protocol  and 9fs as  the default value for the service name  Therefore  the program admits any of the following  with  the same effect that the previous invocation      142        8 srv tcp whale    8 srv whale    The actual work is done by dial  This function dials the given address and returns an open file  descriptor for the connection   s data file  A write to this descriptor sends bytes through the connec   tion  and a read can be used to receive bytes from it  The function is used in the same way for  both datagram protocols and connection oriented protocols  The connection will be open as long  as the file descriptor returned remains open     sig dial  int dial char  addr  char  local  char  dir  int  cfdp     The parameter local permits specifying the local address  for network protocols that allow  doing so   In most cases  given nil suffices  and the network will choose a suitable  unused   local port for the connection  When dir is not nil  it is used by the function as a buffer to copy  the 
97.  gt     void  main int   char              char msg      hello n    int L   1   strlen  msg      write 1  msg  1    exits nil           This is what it does  It does the same that print would do given the same string         write  hello    The function write writes bytes into a file  Isn   t it a surprise  To find out the declaration for this  function  we can use sig      sig write  long write int fd  void  buf  long nbytes     The bytes written to the file come from buf  which was msg in our example program  The num   ber of bytes to write is specified by the third parameter  nbytes  which was the length of the  string in msg  And the file were to write was specified by the first parameter  which was just 1  for us     Files have names  as we learned  We can use a full path  absolute or relative  to name a file   Files being used by a particular process have    names    as well  The names are called file    1 Remember that this program looks at the source of the manual pages  in section 2  to find a function with  the given name in any SYNOPSIS section of any manual page  Very convenient to get a quick reminder of  which arguments receives a system function  and what does it return      56     descriptors and are small integers  You know from your programming courses that to read write  a file you must open it  Once open  you may read and write it until the file is closed  To identify  an open file you use a small integer  its file descriptor  This integer is used by the o
98.  gt tickets     readstr r  nl    respond r  nil       else  queuereq s  r           We defer the discussion of reading from the root directory until later  Regarding from a sema   phore file means obtaining a ticket from the semaphore  The semaphore is pointed to by  fid  gt aux  So  it all depends on the value of s  gt tickets  When there is one ticket to sat   isfy the request  i e   to do a down in the semaphore   we decrement s    gt tickets  to give one  ticket to the process reading  When there are no tickets  the request r is queued in the semaphore  by a call to queuereq  Not responding until we have one ticket means blocking a down until it  obtains its ticket     But a read must return some bytes from the file  maybe none   What do we read when we  obtain a ticket  To permit using the command read to obtain tickets using the shell  we return a  newline character for each ticket read  For the read command  a new line terminates the line it  should read  For us  reading once from the semaphore means obtaining one ticket  Both concepts  match if we read an empty line     The data supposedly contained in the file  read by a Tread request is contained in the  string nl  Just an empty line  To satisfy a Tread  the program must look at  r  gt ifcall offset and r  gt ifcall count  which contains the offset in the file where to  start reading and the number of bytes to return at most  Then  the program must update  r  gt ofcall count and r    gt ofcall data to reply later wi
99.  if  mctl    nil   sysfatal  initmouse   r       while recv mctl  gt c   amp m   gt   0     print   mouse pos  P tbuttons  d n   m xy  m buttons    if  m buttons    7   break        closemouse  mctl    exits  nil           The program must include mouse  h  which contains the definitions for the library  along with  draw h  which defines some data types used by the library  The function initmouse initial   izes the mouse interface provided by the library  It creates a process to read the file given as an  argument and obtain mouse events     sig initmouse  Mousectl  initmouse char  file  Image  i     The return value is a pointer to aMousect 1 structure     typedef struct Mousectl Mousectl   struct Mousectl       Channel  c     chan  Mouse      Channel  resizec     chan int   2              that contains a channel  Mousect1 c  where mouse events are sent by the process reading the  mouse  Therefore  to obtain mouse events all we have to do is to call recv on this channel  Each  mouse event is codified as a Mouse structure  containing the buttons  the coordinates  and the  time stamp for the mouse  as read from the mouse file      typedef struct Mouse Mouse   struct Mouse         int buttons     bit array  LMR 124     Point XY   ulong msec         Thus  the call    recv mctl  gt c   amp m     is the one reading mouse events in the program  The program prints the coordinates  kept at  Mouse  xy  and the buttons  kept at Mouse  buttons  Using coordinates is so common that  draw 
100.  if  n  gt   0  amp  amp  n  lt  nsems  amp  amp  sems n     nil     d  gt qid    Qid  n  0  0    d  gt mode   0664   d  gt name   estrdup9p sems n   gt name     d  gt length   sems n   gt tickets             else  return  1   return 0          We pretend that the access time and last modification time for the file is just now  Regarding the  owner  and group and last modifier user  for the file we use the username of the owner of our pro   cess  That is reasonable     Now things differ depending on which entry is requested by the caller to getdirent  Ifn  is    1  we assume that d must be filled with a directory entry for the directory itself  In this case   we update the qid  permissions  file name  and length to be those of our root directory  Note that  conventionally directories have a length of zero  Note also how strings kept by the directory entry  must be allocated using est rdup9p  or maybe using emalloc9p     If n is a valid identifier  index  for a semaphore  we update the qid  permissions  file name       347      and length in d  Otherwise we return  1 to signal that there is no such file  Note how  d  gt qid path is the index for the semaphore  Also  we report as the file size the number of  tickets in the semaphore  In this way  1s can be used to see if a semaphore has any available tick   ets in it     The last parameter in getdirent corresponds to the last parameter we gave to  dirread9p  This function passes such argument verbatim to each call of getdirent 
101.  in hexadecimal  we write hexadecimal numbers  starting with Ox  as done in C   For example  the byte at position 0x10  which is the byte at posi   tion 16  decimal  has the value 0x32  This is the 17th byte  The first byte is at position zero   which makes arithmetic more simple when dealing with offsets     So  why does cat display text  It   s all numbers  The program cat reads bytes  and writes  them to its output  Its output is the terminal in this case  and the terminal assumes that everything  it shows is just text  The text is represented using a binary codification known as UTF 8  This for   mat encodes runes  i e  characters  kanjis  and other glyphs  as a sequence of bytes  For most of  the characters we use  UTF 8 uses exactly the same format used by ASCII  another standard that  codifies each character using a single byte   The program implementing the terminal  the win   dow  decodes UTF 8 to obtain the runes to display  and renders them on the screen     We can ask xd to do the same for the file contents  Adding option    c  the program prints  the character for each byte when feasible       xd  b  c  NOTICE  0000000 43 6f 70 79 72 69 67 68 74 20 c2 a9 20 32 30 30       0 Ca On Oe ye eee ag  he ee c2 a9 2 0 0  0000010 32 20 4c 75 63 65 6e 74 20 54 65 63 68 6e 6f 6c  10 2 L u c e n t T fee  Ge Sho a eos L  0000020 6f 67 69 65 73 20 49 6e 63 2e Oa 41 6c 6c 20 52  20 o g i e s Te me Co iya Aw dk R  0000030 69 67 68 74 73 20 52 65 73 65 72 76 65 64 Oa  30 iaag Ai E
102.  interfaces for using Plan 9  system calls and the shell  There is another  interface  the 9P file system protocol  Plan 9 provides all the abstractions needed to use the  machine  including processes  virtual address spaces  devices  etc  However  many abstractions  are provided by external file servers  and not by the system itself     The protocol spoken between Plan 9 and any external file server is called 9P  and is docu   mented in the section 5 of the manual  For example  intro 5  summarizes the protocol and pro   vides a good introduction to it     A word of caution  If you ever have to implement a file server  you should read the whole  section 5 of the manual before doing so  It describes all the messages in the protocol  what they  do  and how a file server should behave  Here we are interested just in describing how the proto   col works  and how it relates to the system calls made to Plan 9  The description here is far from  being complete  but you have the manual     As a user  you might probably ignore which particular protocol is spoken by your system   Windows speaks CIFS  Linux speaks NFS  and Plan 9 speaks 9P  In general  you do not have to  care  However  this is a good time to take a look into 9P for two different reasons  First  it might  give you more insight regarding how the system works and how to use it more effectively  Sec   ond  looking into 9P is an excellent excuse to learn how to develop a file server program  using  what we learned so far    
103.  introduced because our program moved out  of the processor  or because the system went busy  etc       Mouse coordinates correspond to the position of the pointer in the screen  The screen is a      296      matrix of pixels  A typical screen size is 1024x768  1024 pixels wide  on the x axis  and 768 pix   els of height  on the y axis   Other popular screen sizes are 1280x1024 or 1600x1200  The origin  is coordinate  0 0   at the upper left corner of the screen  Thus  for a 1024x768 screen  the bottom  right corner would be  1023 767   There are increasing values for x as you move to the right  and  increasing y values as you move down     The first mouse event reported by cat was for the coordinate  670 66   That is  the tip of  the arrow used as a cursor was pointing at the pixel number 670 on the x axis  counting from 0   and number 66 on the y axis  The mouse was then moved a little bit down right  and the next  coordinate reported by cat was  676 68      Following the two numbers reporting the pointer position  there is a number that lets you  know the state for mouse buttons  always zero in the example above   To experiment with this   we are going to write a small program that reads the mouse and prints one mouse event per line   which is easier to read  Before looking at the source for the program  this is an example run                                    amp  mouse   mouse pos  896 189 buttons 0 we move the mouse     mouse pos  895 190 buttons 0   mouse pos  894 190
104.  is running our pro   gram      ps   grep 8 tcnt   nemo 4546 0 00 0 00 120K Pwrite 8 tcnt  Now we can run acid on the process 4546       acid  1 thread 4546   proc 4546 text 386 plan 9 executable     sys lib acid port   sys lib acid thread   sys lib acid 386  acid     The option  1 thread loads functions into acid for debugging threaded programs  For exam   ple  the function threads lists the threads in the process     acid  threads       p   Proc  0x169b8 pid 4546 Running  t   Thread  0x19a68 Running  usr nemo tcent c 14 incr  incrthread   t   Thread  0xlbb28 Ready  file  0      acid     There are two threads  Reasonable  because the main thread called threadexits by this time   Both threads are listed  a line each  after one line describing the process where the threads run   This process has pid 4546  as we knew  and is running  The lucky running thread is executing at  line 14 of tcnt   c  in the function named incr  The debugger does even show a name for the  thread  incrthread  That is what the calls to threadsetname in our program were for   This function assigns a  string  name to the calling thread  for debugging  This string can be also  obtained using threadgetname  for example  to print diagnostics with the name of the thread  issuing them    The second thread is ready to run  but it did not even touch the processor  In fact  it did not  have time to initialize some of its data  and the debugger gets confused regarding which file  line  number  and thread name cor
105.  it decides when to move one process out of the processor and when to put a  process back on it  Because of the unpredictability of context switches between processes  they  must synchronize using locks  rendezvous  sleep wakeup  or any other means if they want to  share memory without race conditions     But there is an alternative  The thread 2  library provides an abstraction similar to a pro   cess  called a thread  A thread is just a flow of control within a process  In the same way that  Plan 9 multiplexes the flow of control of a single processor among multiple processes  the thread  library multiplexes the flow of control of a single process among multiple threads     Thread 1 run rdy  ready  oie ee Ne eee ready a   Process 1    ST kplan ee Se E  Thread 2 ready run   Aron        context switch  Process 2           J i nse   m ea oe        Figure 11 1  Threads are flows of control implemented using the single flow of control of a process     Figure 11 1 shows an example  If there are two processes  Plan 9 may put process 1 to run at  the processor for some time  During this time  process 2 would be ready to run  After the time  passes  there is a context switch and Plan 9 puts process 2 to run and leaves process 1 as ready to  run  In this figure  the process 1 has two threads in it  Each thread thinks that it is a single  inde   pendent  flow of control  like all processes think   However  both threads are sharing the time in  the processor that was given to process 1
106.  it has the real display  keyboard  and mouse   That is far from being the truth  The window system is the one providing a fake set of display   keyboard  and mouse to programs running in that window  You see that a window system is sim   ply a program that multiplexes the real user I O devices to permit multiple programs to have their  own virtual ones     It will not happen in a while  but in the near future we will be typing many commands in a  window  As commands write text in the window  it may fill up and reach the last  bottom  line in  the window  At this point  the window will not scroll down to show more text unless you type the  down arrow key     in the window  The up arrow key  1  can be used to scroll up the window     aoe    You can edit all the text in the window  However  commands may be typed only at the end  You  can always use the mouse to click near the end and type new commands if you changed  The  Delete key can be used to stop a command  should you want to do so     To edit files  and also to run commands and most other things  hence its name   we use  acme  a user interface for programmers developed by Rob Pike  When you run acme in your  new window it would look like shown in figure 1 4  Just type the command name  in the new  window  which has a shell accepting commands  and press return     _ Newcol Kill Putall Dump Exit    oO  New Cut Paste Snarf Sort Zerox Delc   New Cut Paste Snarf Sort Zerox Delcol  _  _  Zusr nemo   Del Snarf Get   Look  ping 
107.  it to the output stream  Files that keep text used as input  or coming as output  for  programs  are also maintained in UTF     The file  dev cons does not provide characters when read  It provides runes  In many  cases  a rune may fit in a single byte  In other cases  it will not  The console keyboard driver  knows how to compose multiple keys to type runes not in the keyboard  The whole set of rules is  described in keyboard 6   Many runes may be generated by using the compose key  usually Alt   and a couple of keys that remind the rune generated  For example  typing Alt      gt  will produce       Alt  lt      will produce      Alt s o leads to      and Alt s a leads to    Greek letters can be generated  by typing Alt   and their roman counterparts  Thus  Alt   m leads to u  The file   1lib keyboard lists many runes that can be composed using several other keys in this way     In general  any Unicode rune may be also generated by typing Alt X nnnn  where nnnn is the  code in Unicode for the rune  So  Alt X 00 fe leads to p  The file  lib unicode lists unicode  runes along with their codes     Programs that read and write data without assuming that it is text  may still operate one byte  at a time  if they want  Or many at a time  However  programs reading text and looking into it   should use the functions in rune 2   or they would misbehave for non english text  The functions  in the C library described in rune 2  provide conversion from UTF to runes and vice versa   Amo
108.  label for the current window  or  dev wsys 3 label for the window with identi   fier 3  contain strings to let us know which program is using which window       cat  dev label   re 839      cat  dev wsys 3 label  stats     A convenience script  wloc  lists all the windows along with their labels     7 wloc  window  r 125 32 576 315 re 839    dev wsys 1  window  r 69 6 381 174 stats    dev wsys 3    r    Basically  it lists  dev wsys to see which windows exist  and reads  dev label for each  one  to describe it  The following command would do something similar       for  w in  dev wsys         echo window     cat Sw label   window rc 839   window stats    Other useful files are  dev screen   dev window  and  dev text  They are provided  for each window  The first one is an image for the entire screen  It can be used to take an snapshot  for it  The second one is the same  but only for the window image  The last one contains all the  text shown in the window  although it is read only   For example  this can be used to see the first  three lines in the current window       317        sed 3q  dev text     echo Swsys   srv rio nemo  832     mount Swsys  n rio new    r    Note that we only typed the first one  The next command prints all the mount commands that  we executed in our window  assuming the prompt is the one used in this book       grep       mount     dev text    mount Swsys  n rio new    In the same way  this executes the first mount command that we executed in our wi
109.  line number before calling abort     The system call dup receives a file descriptor and duplicates it into another  This is what  we need  The code             fd   open   NOTICE   OREAD     dup fd  0    close  fd               opens  NOTICE for reading  then duplicates the descriptor just open into file descriptor 0  After  the call  file descriptor 0 leads to the same place fd was leading to  It refers to the same file and  shares the same offset  This is shown in figure 5 1  which assumes that fd was 3  As you can see   both descriptors refer now to the same Chan   At this point  the descriptor whose number is in fd  is no longer necessary  and can be closed  The program in cat is only going to read from 0  It  does not even know that we have other file descriptors open             Child  process    Child  process    File descriptor File descriptor                                                                                                                            table table  0 dev cons ORDWR 0 dev cons ORDWH  1     s  gt  1      2 offset  3245 2 offset  3245  3 3  n NOTICE OREAD n NOTICE OREAD  offset  0 offset  0  Before dup  3  0  After dup  3  0     Figure 5 1  File descriptors before and after duplicating descriptor 3 into descriptor 0     This is the correct implementation for the program shown before  Its output remains the  same  but the previous program could fail  Note that in this section we are not checking for errors   to keep the programs more clear to
110.  longer necessary  we can close the file  descriptor for the ct 1 file that it returns  and the port will be released     This program announces the port 8899  and sleeps forever to let us inspect what happen       145         ann c     include  lt u h gt      include  lt libc h gt     void  main int argc  char  argv         int cfd    char dir 40      cfd   announce   tcp   9988   dir    if  cfd  lt  0   sysfatal  announce   r     print   announced in  s n   dir    for       sleep  1000         We may now do this      S ann  amp       announced in  net tcp 52 We typed return here  to let you see    netstat   grep 9988  tcp 52 nemo Listen 9988 0    According to net stat  the TCP port number 9988 is listening for incoming calls  Note how the  path printed by our program corresponds to the TCP line number 52     Now let   s try to run the program again  without killing the previous process       8 out  announce  announce writing  net tcp  address in use    It fails  Of course  there is another process already using the TCP port number 9988  This new  process cannot announce that port number again  It will be able to do so only when nobody else is  using it      kill 8 ann rce     6 ann  amp      announced in  net tcp 52    Our program must now await for an incoming call  and accept it  before it could exchange data  with the process at the other end of the connection  To wait for the next call  you may use  listen  This name is perhaps misleading because  as you could see  afte
111.  machines to execute commands on them  Besides  you have  one or more file servers  that are machines whose solely purpose is providing files by running  programs similar to the one we developed in the previous chapter  Most  if not all  the objects in  the computer system are represented by files  Thus  the objects that must be protected by the sys   tem are files  Protecting access to files means deciding if a particular process  acting on behalf of  a user  may or may not do a particular operation on a file       358      14 2  The local machine    You know that there are many machines involved in your computing system  But let   s start by  considering just the one you are using  or  in general  a single machine     A user may execute commands in a terminal  and use any of its devices  by booting it and  supplying a user name  Terminals are not supposed to keep state  local storage  in Plan 9 and so  there is no state to protect  Also  terminals are not supposed to export their devices to the net   work  by listening to network calls made to access them  This means that nobody should be able  to access a terminal  but for the user who brought it into operation  Also  a terminal is a single   user machine  It is not meant to be shared by more than one user  Computers are cheap these  days     How is your terminal secured  The local machine is protected merely by identifying the  user who is using it  Identification is one of the things needed to secure a system  Plan 9 mus
112.  matches a line  with the text FEEL in it  Then  we must use the d command to delete this line  And later we will  have to insert in place the contents of the other file                      sed  FEEL d  lt salutation  Today I feel  So be warned          The address  FEEL  matches the string FEEL  and therefore selects that line  For each match   the command d removes its line  If there were more than one line matching the address  all of  such lines would have been deleted  In general  sed goes line by line  doing what you want                         cat salutation salutation   sed  FEEL d  Today I feel  So be warned  Today I feel  So be warned                We also wanted to insert the text in how in place  besides deleting the line with FEEL  There   fore  we want to execute two commands when the address  FEEL  matches in a line in the input   This can be done by using braces  but sed is picky regarding the format of its program  and we  prefer to use several lines for the sed program  Fortunately  the shell knows how to quote it all                   sed  e     FEEL    7  E how   77 A           lt salutation  Today I feel  Really in bad mood  So be warned    In general  it is a good idea to quote complex expressions that are meant not for shell  but for the  command being executed  Otherwise  we might use a character with special meaning for rc  and  there could be surprises       197      This type of editing can be used to prepare templates for certain files  for exam
113.  mention file  and then use  wc on that file         wc  w  tmp lineswithfile  7355  tmp lineswithfile    This is inconvenient  We have to type a lot  and require temporary files just to use the output of  one program as the input for another  There is a better way       cat ch  ms   wc  i  39880       y       executes both cat and wc  The standard output for cat is conveyed by the into the standard  input for wc  We get the output we wanted in a simple way  This is how we count just the lines  using the word file       cat ch  ms   grep file   wc  1l  7355    r    Here  the output of cat was conveyed to grep  whose output was conveyed to wc  A small  command line performed a quite complex task  By the way  because grep accepts as arguments  the names for its input files  a more compact command could be used       grep file ch ms   wc  1l  1255    f    The conveyer represented by the vertical bar is called a pipe  Its function is the same  Think of  input as bytes flowing into a command  for processing  and output as bytes flowing out the com   mand  If you have a pipe  you can plumb one output to one input  But you must use a pipe  Other   wise  bytes would pour on the floor    Before  we have used ps to lists processes  Usually  there are many lines printed by the  command  but we can be interested in a particular one  There is no need to scroll down the termi   nal and search through many lines just to find the information for a broken process       109        ps   grep Br
114.  multiple options use these macros to process their  argument list in search for options  This means that the invocation syntax is similar for most pro   grams  As you have seen  you may combine options in a single argument  use multiple argu   ments  supply arguments for options immediately after the option letter  or use another argument   terminate the option list by giving a    argument  and so on     As you have probably noticed after going this far  a process terminates by a call to exits   see exits 2  for the whole story  This system call terminates the calling process  The process may  leave a single string as its legacy  reporting what it has to say  Such string reports the process  exit status  that is  what happen to it  If the string is null  it means by convention that everything  went well for the dying process  i e   it could do its job  Otherwise  the convention is that string  should report the problem the process had to complete its job  For example     sic c   include  lt u h gt      include  lt libc h gt           void  main int  char         exits   sic             would report sic  to the system when exits terminates the process  Here is a run that shows  that by echoing  status we can learn how it went to this depressive program       40         64 8EEC    echo Sstatus  8 sic 2046  sic     r    Commands exit with an appropriate status depending on what happen to them  Thus  1s reports  success as its status when it could list the files given as argumen
115.  netstat  The states for a con   nection may depend on the particular protocol  and we do not discuss them here        In some cases  there may be problems to reach the name service for the Internet  our DNS  server   and it is very useful to call netstat with the  n flag  which makes the program print  just the addresses  without translating them into  more readable  names  For example     7  netstat  n    tcp 0 nemo Listen 11004 0 ie  tcp  1 Established 5757 564 193 147 71   tcp 2 nemo Established 5765 11010 193 147 71   tcp  3 nemo Established 5759 564 193 147 71   tcp 4 nemo Listen 11003 0 Fe  tep  5 nemo Established 5761 11010 193 147 71           many other lines of output    It is very instructive to compare the time it takes for this program to complete with  and without  using    n    To add yet another tool to your network survival kit  the ip ping program sends particu   lar messages that behave like probes to a machine  to an IP address  which is for a network inter   face found at a machine  indeed   and prints one line for each probe reporting what happen  It is  very useful because it lets you know if a particular machine seems to be alive  If it replies to a  probe  the machine is alive  no doubt  If the machine does not reply to any of the probes  it might  be either dead  or disconnected from the network  Or perhaps  it is your machine the one discon   nected  If only some probes get replied  you are likely to have bad connectivity  your network is  loosing 
116.  new memory  The appropriate action is sim   ply aborting the entire program  but you may implement your own versions for these functions if  something better is needed     Perhaps surprisingly  there is no function to free a semaphore  The point is that we can only  free a Sem when we know that no data structure in our program is using it  But when does that  happen  Requests mention fids  that may refer to Sem data structures  If a user wants to remove a  file representing a semaphore  we can only do so when no references remain to that semaphore   Calling free on a semaphore while there might be requests and or fids pointing to it would be a  disaster     The solution is to do reference counting  Each semaphore contains one integer  which is  called a reference counter  For each reference that points to a Sem we count one reference using  the counter  New references made to the semaphore increment the counter  When a reference is  gone  we decrement the reference counter  Only when the counter gets down to zero it is safe to  release the data structure  This technique is used in many different places by operating systems   to release file descriptors when no process is using them  to remove files when nobody is using  them  to destroy windows when no process is using them  etc     In general  releasing data structures or other resources when they are no longer needed is  called garbage collection  Reference counting is a form of garbage collection that may be used  for any
117.  newns to build a whole new namespace according to a file given as a param   eter  Because of the call to rfork  RFNOMNT  that follows  the process will not be allowed to  mount any other file tree  It may access just those files that are in the namespace described in the  file  That is a very nice sand box                           box c   include  lt u h gt   include  lt libc h gt   include  lt auth h gt     for newns  void    main int argc  char  argv          char  user     if  arge    2    fprint 2   usage   s ns prog n   argv0    sysfatal   usage          switch  rfork  RFPROC RFNAMEG            case  1   sysfatal  fork   r       default   waitpid     exits  nil    case 0   user   getuser     if  newns  user  argv 1    lt  0     sysfatal  newns  Sr     rfork  RFNOMNT     execl argv 1   argv 1   nil      sysfatal  exec   r       The call to getuser returns a string with the user name  We have already seen all other calls  used in this program  The program can be used like in      8 box sandbox  bin rc    Where sandbox is a file similar to  1ib namespace  but with mounts and binds appropriate  for a sandbox       174     7 12  Distributed computing revisited    In the last chapter  we learned about CPU servers and connected on one of them to execute com   mands  But there is one interesting thing about that kind of connection  Indeed  you have already  seen it  but perhaps it went unnoticed  This thing may become more visible if you connect to a  cpu server and execute ri
118.  not matter what fs is  It is just a file  Upon starting  k fs  noticed that there was none of its data structures stored in fs  It understood that there was an  inconsistent  corrupt  data structure stored in the disk  and asks us to reinitialize it  We will let it  do it     Would you like to ream it  y n   y  kfs  reaming the file system using 1024 byte blocks    Now kfs is initializing the data in fs  as it pleases to store a file tree in there  After finishing  with disk initialization  the partition contains the kfs data structures  It is said that the partition  has been formatted for k fs  or that it has a kfs format     At last  we can mount the  empty  file tree served by kf  s  When we create files in the new  mounted directory  kfs will use write on  dev sdC1 fs to keep them stored in that parti   tion  Indeed  it will be the storage device the one that will update the disk  upon calls to write  for one of its files       325        mount  c  srv kfs  n kfs    touch  n kfs anewfile    r    All other file systems  stored in disk  work along the same lines  All other systems include pro   grams that understand how to use the disk  like the storage device  and how to store files in it   like kfs   As you see  each program is just using an abstraction provided by yet another pro   gram  Even inside the disk hardware you may find programs that provide the abstraction of a con   tiguous array of disk sectors     13 2  The file system protocol    So far  we have seen two
119.  not the name of the program it runs  That is convenient to know  never   theless  Each process is given a unique number by the system when it is created  That number is  called the process id  or the pid  The pid identifies  and therefore names  a process     The pid of a process is a positive number  and the system tries hard not to reuse them  This  number can be used to name a process when asking the system to do things to it  Needless to say  that this name is also an invention of the operating system  The shell environment variable pid  contains the pid for the shell  Note that its value is a string  not an integer  Useful for creating  temporary files that we want to be unique for a given shell     To know the pid of the process that is executing our program  we can use get pid     pid c        include  lt u h gt      include  lt libc h gt     void  main int  char         int pid     pid   getpid     print   my pid is  d n   pid    exits  nil           Executing this program several times may look like this    8 pid  my pid is 345    8 pid  my pid is 372    r    The first process was the one with pid 345  but we may say as well that the first process was the  345  for short  The second process started was the 372  Each time we run the program we would  get a different one     The command ps  process status  lists the processes in the system  The second field of each  line  there is one per process  is the process id  This is an example    i PS   nemo 280 0 00 0 00 13 1
120.  number number  1    bin re  2 awk    printf   S4d  s0  NR   0              In general  it is usual to wrap AWK programs using shell scripts  The input for AWK may be pro   cessed by other shell commands  and the same might happen to its output     To operate on arbitrary records  you may specify a pattern for an action  A pattern is a rela   tional expression  a regular expression  or a combination of both kinds od expressions  This  example uses NR to print only records 3 to 5       awk    NR  gt   3  amp  amp  NR  lt  5  print S0      LICENSE  with the following notable exceptions     1  No right is granted to create derivative works of or    Here  NR  gt  3  amp  amp  NR  lt   5 isarelational expression  It does an and of two expressions  Only  records with NR between 3 and 5 match the pattern  As a result  print is executed just for lines  3 through 5  Because syntax is like in C  it is easy to get started  Just try  Printing the entire  record  i e    0  is so common  that print prints that by default  This is equivalent to the previ   ous command       awk    NR  gt  3  amp  amp  NR  lt   5  print      LICENSE    Even more  the default action is to print the entire record  This is also equivalent to our command       awk    NR  gt  3  amp  amp  NR  lt   5     LICENSE    By the way  in this particular case  using sed might have been more simple       sed  n 3 5p  LICENSE  with the following notable exceptions       216      1  No right is granted to create derivative wo
121.  only want to take care of  reading and writing to their files may create a file tree and place a pointer to it in the Srv struc   ture  After doing so  most of the calls that work on the file tree would be supplied by the library   In general  only reading and writing to the files must be implemented  besides creation and  removal of files   We do not discuss this here  but the program  sys src cmd ramfs c is  an excellent example of how to use this facility     13 8  A program to make things    For all the previous programs  compiling them by hand could suffice  For our file server program   it is likely that we will have to go through the compile test debug cycle multiple times  Instead  of compiling and linking it by hand  we are going to use a tool that knows how to build things     The program mk is similar to the UNIX program make  Its only purpose is to build things  once you tell it how to build them  The instructions for building our products must be detailed in  a file called mk file  read by mk to learn how to build things     We placed the source code  along with an initial version for our mk file  in a directory for  our file server program     2 w TC  mkfile sem c sem h semfs c    cat mkfile  8 semfs  semfs 8 sem 8   81  o 8 semfs semfs 8 sem 8       semfs 8  semfs c sem h  8c  FVw semfs c    sem 8  sem c sem h  8c  FVw sem c          Now  running mk in this directory has the following effect       mk   8c  FVw semfs c   8c  FVw sem c   81  o 8 semfs semfs 8 se
122.  output text a little bit before  copying it to your editor    We could change d2h to accept more than one argument and do its work for all the num   bers given as argument  Calling d2h with all the numbers from 0 to 255 would get us close to  obtaining an initializer for the array  But first things first  We need to iterate through all the com   mand line arguments in our script  Re includes a for construct that can be used for that  It takes a  variable name and a list  and executes the command in the body once for each word in the list  On  each pass  the variable takes the value of the corresponding word  This is an example  using x as  the variable and  a b c  as the list     for  x in abc     echo Sx    a Fyr    Note how the prompt changed after typing the for line  rc wanted more input  The command  for the body  To use more than one command  we may use the brackets as before  to group them   First attempt       for  num in 10 20 30  f      echo       obase 16      7  echo Snum   riod   obase 16   10   obase 16   20   obase 16   30  It is useful to try the commands before using them  to see what really happens  The for loop  gave three passes  as expected  Each time   num kept the value for the corresponding string in the  list  10  20  and 30  Remember  these are strings  The shell does not know they mean numbers      187      to you  Setting obase in each pass seems to be a waste  We will do it just once  before iterating  through the numbers  The numbers are taken f
123.  point file with the  mounted file  This is what a mount table entry does  However  you can also add a mounted file to  the mount point  To see how this works in a controlled way  let   s create a few files       168        mkdir adir other     touch adir a adir b adir c     touch other a other x other y  le adir   a b Cc     e    If we bind other into adir  we know what happens  From now on  dir refers to other       bind other adir  saba adir  a X y    After undoing the effect of the bind  to leave adir undisturbed  we do another bind  But this  time  we bind other into adir after what it previously had  by using the  a flag for bind   And this is what we get       bind  a other adir  7 de adir  a a b c x y    You can see how the file that used to be adir now leads to a union of both the old adir and  other  Its contents appear to be the union of the contents for both directories  Because there are  two files named a  one at the old adir and another at other  we see that file name twice  Fur   thermore  look what happens here       rm adir b      JC adir   a a e x y    rm adir y   a EC adir   a a c x     le other   a x    Removing adir b removed the b file from the original adir  And removing the file adir y  removed the file y  and of course the file is no longer at other either  Let   s continue the game       echo hola  gt other a    cat other a   hola     cat adir a    r    We modify the file a in other  and write something on it  Reading other a yields the  expected re
124.  port lock c 16  main   0x90  usr nemo 9intro cnt2 c 19   _main 0x31  sys src libc 386 main9 s 16   acid     The child process is always trying to lock the resource  inside lock      What happens is that the  parent is holding the lock almost at all times  The parent only releases the lock for a very brief  time  between the end of an iteration and the beginning of the next iteration  Only if during this  time there is a context switch  and the child is allowed to run  will the child be able to acquire the  lock  But it seems that in our case the system always decides to let the child run while the parent  is holding the lock     This is called starvation  A process may never be able to acquire a resource  and it will  starve to death  It can be understood that this may happen to our program  because only for a  very little fraction of time the lock is released by the parent  The most probable thing is that once  a process gets the lock  the other one will never be able to acquire it     Look at the stack trace shown above  Did you notice that lock calls sleep  You know  that the system gives some processor time to each process  in turns  If the implementation for  lock was the one we presented before in assembly language  we would be wasting a lot of pro   cessor time  Figure 10 3 depicts the execution for our two processes  assuming that lock is  implemented as we told before  In the figure  a solid line represents a process that is running  in  the processor  A dotted line
125.  prints nothing  If it completes and does not com   plaint by printing a diagnostic message  then we know that it could do its job     Some times  we may want to remove a file and ignore any errors  For example  we might  want to be sure that there is no file named goodbye  and would not want to see complaints from  rm when the file does not exist  and therefore cannot be removed   Flag    f for rm achieves this  effect       rm goodbye  rm  goodbye   goodbye       file does not exist    rm  f goodbye    Both command lines achieve the same effect  Only that the second one is silent     1 7  Directories    As it happens in Windows and most other systems  Plan 9 has folders  But it uses the more ven   erable name directory for that concept  A directory keeps several files together  so that you can  group them  Two files in two different directories are two different files  This seems natural  It    Ba ee    doesn   t matter if the files have the same name  If they are at different directories  they are differ   ent          JMS    386 usr tmp    Vales    nemo glenda mero    ors    bin lib tmp    Figure 1 5  Some files that user Nemo can find in the system     Directories may contain other directories  Therefore  files are arranged in a tree  Indeed  directo   ries are also files  A directory is a file that contains information about which files are bounded  together in it  but that   s a file anyway  This means that the file tree has only files  Of course   many of them would b
126.  processes work on the same data  extra care is to be taken  You saw how  the final value for afile depends on which process is faster  i e   gets more processor time  and  reaches a particular point in the code earlier than another process  Because the final result depends  on this race  its said that the program has a race condition     You are entering a dangerous world  It is called concurrent programming  The moment  you use more than one process to write an application  you have to think about race conditions  and try to avoid them as much as you can  The name concurrent is used because you do not  know if all your processes execute really in parallel  when there is more than one processor  or  relying on the operating system to multiplex a single processor among them  In fact  the problems  would be the same  Race conditions  Therefore  it is best to think that they execute concurrently   try to avoid races  and forget about what is really happening underneath     Programs with race conditions are unpredictable  They should be avoided  Doing so is a  subject for a book or a course by itself  Indeed  there are many books and courses on concurrent  programming that deal with this topic  In this text  we will deal with this problem by trying to  avoid it  and showing a few mechanisms that can protect us from races     4 5  Executing another program    We know how to create a new process  Now it would be interesting to learn how to run a new  program using a process we hav
127.  processing step  in the pipeline is just 5 22 seconds  Besides  we had to type less  Do you think it pays       195      The program sed is a stream editor  It can be used to edit data as it flows through a pipe   line  Sed reads text from the input  applies the commands you give to edit that text  and writes the  result to the output  In most cases  this command is used to perform simple tasks  like inserting   deleting  or replacing text  But it can be used for more  As with most other programs  you may  specify the input for sed by giving some file names as arguments  or you may let it work with  the standard input otherwise     In general  editing commands are given as arguments to the  e option  but if there is just  one command  you may omit the  e  For example  this prints the first 3 lines for a file       sed 3q  LICENSE   The Plan 9 software is provided under the terms of the  Lucent Public License  Version 1 02  reproduced below   with the following notable exceptions        a    All sed commands have either none  one  or two addresses and then the command itself  In the  last example there was one address  3  and one command  q  The editor reads text  usually line  by line  For each text read  sed applies all the editing commands given  and copies the result to  standard output  If addresses are given for a command  the editor applies the command to the text  selected by those addresses     A number is an address that corresponds to a line number  The command q  
128.  processing the input that comes from  the pipe  the shell prompt gets printed almost immediately  If this is a problem  the parent must  wait for the child after writing all the data to the pipe  Otherwise  the waitpid call would block  waiting for the child to die  and the child would block waiting for the end of file indication   because the parent has the pipe open for writing      Figure 5 3 shows the processes involved  all their descriptors  and the pipe  We use the  same conventions used for the last figure  which we will follow from now on         Parent  Process          pipe          Figure 5 3  A process using a pipe to send input to a command     All the interesting things happen in the function pipeto  It executes the Plan 9 shell  sup   pling the command line as the argument for option    c  this asks rc to execute the argument as a  command  and not to read commands from standard input     First  before creating the child process  the parent process makes a pipe  It is very important  to understand that the pipe must be created before we call fork  Both processes must share the  pipe  If the pipe is created after forking  in the child process  the parent process does not have the  descriptor to write to the pipe  If it is created by the parent  after calling fork  the child will not  have the descriptor to read from the pipe     Even if both processes create a pipe  after the child creation  there are two different pipes   Each process can use only its own pip
129.  provides a data type representing a font  called Font  It includes func   tions like    Font  openfont  Display  d  char  file     that reads a font description from the file given as an argument and returns a pointer to a Font  that may be used to employ that font       313      To use a loaded font  it suffices to give it as an argument to functions like string  We  used font  which is a global for the font used by default  To see which font you are using by  default  you may see which file name is in the  font environment variable       echo Sfont   lib font bit VeraMono VeraMono 12 font    That variable is used to locate the font you want to use  The window system supplies a reasonable  default otherwise     The following function  that may be called from sliderthread  draws the slider value   given as a parameter  in the window        void  writeval  int val      Point SZ  pos   char str 5       0   to  100    seprint  str  strt 5   Sd S    val    sz   stringsize font  str    if  sz x  gt  Dx screen  gt r  2    sz y  gt  Dy screen  gt r     return   pos   screen  gt r min     pos x    10   pos y     Dy screen  gt r   sz y    2   string screen  pos  display  gt black  ZP  font  str              It prints the integer value as a string  in str  adding a   sign after the number  The window  could be so small  or perhaps the font so big  that there could be not enough space to draw the  text  The function stringsize returns the size for a string in the given font  We use it 
130.  reading the port edit  i e   editors  Thus  the message is conveyed back to Acme in many cases   You may try it by hand  If you have an Acme running and you execute      129      sender web image image  process browser viewer viewer                      send edit WWW image                                        http   lsub org   message delivered by the plumber       Figure 5 8  The plumber provides ports  used to deliver messages to applications       plumb  NOTICE    r          on a shell  the file  NOTICE will show up in your editor  The plumber even knows that if there    s  no editor reading from the edit port  an editor should be started  You can try by executing again  the plumb command above  but this time  while no editor is running        How does the plumber know what to do  The file Shome 1ib plumbing is read by the  plumber when it starts  usually from your Shome 1ib profile while entering the system    This file has rules that instruct the plumber to which port should each message be sent according  to the message data  Furthermore  the file may instruct the plumber to start a particular applica   tion  e g   an editor  when no one is listening at a given port  After the plumber has been started   its rules can be updated by copying whatever rules are necessary to the  mnt  plumb rules  file     It is still too early for us to inspect this file  because it uses regular expressions  that are yet  to be discussed  However  it is useful to know that by default cer
131.  removes all the characters read from the keyboard  thus it cancels the current  input line       A newline terminates the cooking from the current line  which is made available to the  application reading from the console        The compose  usually Alt  key  followed by a few other keys  produces a character that is a  function of the other keys  This is used to type characters not usually found in the keyboard   like  amp  and XK        Any other character stands for itself  and is queued to be cooked along with the rest of the  line     The virtual version for  dev cons provided by the window system gives also a special mean   ing to a few other characters  most notably        Delete posts an interrupt note to the process group associated to the window   e Arrow keys f and   scroll backward and forward      Arrow keys     and     move the text insertion point to the right and to the left        The Escape key puts the window in a  so called  hold mode  All the text typed while in hold  mode is not supplied to any application reading from  dev cons  Therefore  you can  freely edit multiple lines of text  When Escape is preseed again  and the window leaves hold  mode  the text is given to any process reading from  dev cons     This is called the console   s cooked mode  When it is enabled  lines can be edited as dictated by  the rules stated above  This is also called a line discipline  But the console can be also put in a  so  called  raw mode  In raw mode  the console doe
132.  represents a process that is ready to run  but is not running in the pro   cessor  The figure shows how the system gives some time to each process for running  in turns     Parent Run  R dy  wie vane ___Run  og uN R dy  ETRE N  unlock  lock  Child    r dy  sr teeee E es se eees R dy  eereree a aonn R dy  erreren  alls Lock  which spins around trying to acquire it  Time         Figure 10 3  Two processes using a shared resource protected by a spin lock     Initially  the parent calls 1ock  and acquires the lock because it was initially released   Later  the parent process releases the lock by a call to unlock  but it quickly calls Lock again   and re acquires the lock  Now it is the time for the child process to run  This poor process calls  lock  but you know what happens  The routine cannot acquire the lock  which is held by the par   ent process  Therefore  it waits in its loop calling TAS to try to gain the lock  That is all this pro   cess would do while it is allowed to remain running  The very thick line in the figure represents  the process executing this while  spinning around desperately hoping for TAS to succeed and  obtain the lock  Because of this  this kind of lock is called a spin lock       239      One problem with this execution  as you already know  is that the child suffers starvation   and is very likely to never acquire its lock  This can be solved by trying to hold locks as few time  as feasible  unlike we are doing in our program  The other problem tha
133.  same system software used in a terminal  however  its kernel is com   piled with the variable cpuserver set to true  and it behaves slightly differently  The main dif   ference is that the boot program executes the script  rc bin cpurc instead of   cc bin termrc to initialize the system for operation  You may remember that one of the  things this script does is running aux listen to run several system services upon incoming  calls from clients     Other systems  most notably UNIX  start most existing system services during the boot pro   cess  in a similar way  That is why you can connect to a UNIX machine to execute commands on  it  e g   using telnet or ssh   but you cannot do the same to your Plan 9 terminal  If you want  to connect to your terminal to use a particular service  you must start that service first  i e   run  listen or its variant that listens just for one service  listen1      By the way  if you ever wandered what is the difference between the different flavors of  Windows for running on a PC  it is the same  They compiled the system with different parameters  for    optimizing     they same so  we are not to be held responsible  the system for different kinds  of usage  Also  they arranged for the system to start different services depending on the kind of  edition     The cpu command makes a connection to a CPU server  using by default that named by  Scpu  as set by your system administrator  The connection is used to run a program in the CPU  server  whi
134.  see        105      void  main int  char          int fd     switch  fork       case  1    sysfatal   fork failed     case 0              fd   open   NOTICE   OREAD     dup  fd  0    close  fd    execl    bin cat    cat   nil    sysfatal  exec  Sr      default   waitpid          exits  nil           There are some pitfalls that you are likely to experience by accident in the future  One of them is  redirecting standard input to a file descriptor open for writing  That is a violation of the conven   tion that file descriptor 0 is open for reading  For example  this code makes such mistake     fd   create  outfile   OWRITE  0664      WRONG   dup  fd  0    close  fd         Using this code in the previous program puts cat in trouble  A write call for a descriptor open  just for reading is never going to work      8 iredir   cat  error reading  lt stdin gt   inappropriate use of fd    d    Output redirections made by the shell use create to open the output file  because most of the  times the file would not exist  When the file exists  it is truncated by the call and nothing bad hap   pens        fd   create   outfile   OWRITE  0664    dup  fd  1    close  fd      A common mistake is redirecting both input and output to the same file in a command line  like  we show here       cat  lt processlist  gt processlist  When the shell redirects the output  create truncates the file  There is nothing there for cat to  read  and your data is gone  If you ever want to do a similar thing  
135.  sigint  213  sign on  single  375  signal  255  silent grep  221  simultaneous  channel operation  284  read  289    single   sign on  375   writer  244  single user  358  size   file  11    message  326   screen  295  318  skip record  220  slash  13  153    yee    sleep  248  sleep  59  97  119  126 127  192  231  264  sleep c  59  slider  drawing  306  graphic  303  slider c  311  smprint  285  snapshot  file system  163  Snarf  8  software interrupt  24  sort  reverse  217  text  205  sort  205  flag  n  205  flag  r  205  flag  u  208  sorting  205  source  program  48  space  disk  64  name  153  159  169  new name  171  virtual address  32  spam  210  speak for  372  specifier  attach  163  313  mount  163  169  spin lock  238  split  string  192    src  130   src  48    srv  123  137  175  313  Srv  332   srv  137  160      srv file system  123  srv c  141  srvecho c  123  srvfs  175   sxrv ram  326  stack   dump  237   dump  thread  268   process  237  262   segment  34  51   thread  262  stamp  time  295  stand alone   installation  324   machine  357  standard   error  56 57  106    error redirection  188   includes  21   input  56 57  102 103   name space  173   output  56 57   output redirection  105  start   of line  201   of text  201   script  machine  151  starvation  238  249  267  stat processing  347    stat  69 70  stat c  70  state    blocked  231   process  45 46  127  stateless  3  statement  AWK  214  statistics  system  127  stats  127 314  Sstatus 
136.  src libc 9syscall pwrite s 5       print  fmt 0x1136a  0x24  sys src libc fmt print c 13  decr  arg 0xd010  0x3b  usr nemo tcnt c 30    launcher386  arg 0xd010  f   0x105f  0x10  sys src libthread 386 c 10    Oxfefefefe  file  0       This is a very useful tool to debug programs using the thread library  It makes debugging as easy  as when using processes  The debugger reports that incrthread was executing yield  and  decrthread was executing its call to print  by the time the stack dump was made  Note how  the process was running  but only one of the threads is running  The other one is ready to run       269      because it did yield     11 3  Channels    Synchronizing several processes was very easy when we used pipes  While programming  we  could forget all about race conditions  Each process was making its job  using its own data  and  both processes could still work together to do something useful     Fortunately  there is an abstraction provided by the thread library that is very similar  It is  called a channel  A channel is an unidirectional communication artifact  One thread can send  data through one end of the channel  and another thread may receive data at the other end   Because channels are meant to send data of a particular type  a channel delivers messages of a  given size  decided when the channel is created  This is not a restriction  If data of different sizes  must be sent through a channel  you can always send a pointer to it     To create a channel  ca
137.  stores the string at the buffer you supply  Here is an example    char error 128    rerrstr error  sizeof error      After the call  error contains the error string     A function implemented to be placed in a library also needs to report errors  If you write  such function  you must think how to do that  One way is to use the same mechanism used by  Plan 9  This is good because it allows any programmer using your library to do exactly the same  to deal with errors  no matter if the error is being reported by your library function or by Plan 9     The system call werrstr writes a new value for the error string  It is used like print   Using it  we can implement a function that pops an element from a stack and reports errors  nicely      42     int  pop  Stack   s      if  isempty s      werrstr  pop on an empty stack     return  1            do the pop otherwise             Now  we could write code like the following     if  pop s   lt  0    print   pop failed   r n            and  upon an error in pop this would print something like     pop failed  pop on an empty stack    2 5  Environment    Another way to supply    arguments    to a process is to define environment variables  Each pro   cess is supplied with a set of name value strings  that are known as environment variables  They  are used to customize the behavior of certain programs  when it is more convenient to define a  environment variable than to give a command line argument every time we run a program  Usu   all
138.  structure  representing a 9P request  Its definition may be found at  sys include 9p h  and includes  the following fields     typedef struct Req Req   struct Req     ulong tag   Fcall ifcall        Fcall ofcall   Fid  fid   D  r ci   void  aux   Srv  Srv           The tag field is the tag for the request  It is must be the same in the T  message and in the R   message used to respond  The actual message that was received  as a request  from the client is  kept at ifcall  This structure contains the message unpacked as a C structure  reflecting the  actual message received as an array of bytes from the connection to the client  The purpose of the  function is to attend the request as found in Req  ifcall  and then fill up a response message   The response message is actually Req ofcall  This field contains a structure similar to that of  Req ifcall1  but this one is for the response message instead of being for the request message     The function respond  see in fst attach above  builds a response message by looking  into Req  ofcall and packing the message in an array of bytes  which is then sent back to the  client  It does so if the second argument is nil  Otherwise  the second argument is taken as an  error string  and respond responds with an Rerror message instead  In our fstattach  implementation  we never respond with errors and accept any request  After the request has been  responded respond releases the Req data structure  A request should never be used again aft
139.  sys src libc fmt dofmt c 37    We gave the name of the binary file as an argument  The option  n causes the source file name  and line to be printed  Otherwise src would ask your editor to display that file and line  Option   s permits you to give a memory address or a symbol name to locate its source  By the way  this  program is an endless source of wisdom  If you want to know how to implement  say  cat  you  can run src  bin cat     Because of the source file name printed  we know that the problem seems to be within the C  library  in dofmt  c  What is more likely  Is there a bug in the C library or did we make a mis   take when calling one of its functions  The mystery can be solved by looking at the stack of the  broken process  We can read the process stack because the process is still there  in the broken  state     7 PS     many other processes     nemo 788 0 00 0 00 24K Broken 8 hi    To print the stack  we call the debugger  acid       acid 788   proc 788 text 386 plan 9 executable     sys lib acid port   sys lib acid 386  acid     This debugger is indeed a powerful tool  described in  6   we will use just a couple of its func   tions  After obtaining the prompt from acid  we ask for a stack dump using the stk command     acid  stk      dofmt  fmt 0x0  f 0xdfffef08  0x138  sys src libc fmt dofmt c 37   vfprint  fd 0x1 args 0xdfffef60  fmt 0x0  0x59  sys src libc fmt vfprint c 30  print  fmt 0x0  0x24  sys src libc fmt print c 13   main  argv 0xdfffefb4  0x12  usr n
140.  sysfatal   initkeyboard    r     if initdraw nil  nil  argv 0    lt  0   sysfatal  initdraw   r     setcol   allocimage  display  Rect 0 0 1 1   screen  gt chan  1  DYellow    unsetcol   allocimage  display  Rect 0 0 1 1   screen  gt chan  1  Ox777777FF     sliderc   chancreate sizeof ulong   0    threadcreate resizethread  mctl  8 1024    threadcreate  mousethread  mctl  8 1024    threadcreate  keyboardthread  kctl  8 1024    threadcreate sliderthread  sliderc  8 1024    sendul sliderc  50    threadexits  nil              The function keyboardthread is executed on its own thread  It receives runes from kctl c  and processes them without paying much attention to the rest of the program    void   keyboardthread void  a        Keyboardctl kctl   a     Rune Pi  Cr   int nval   for         recv kctl  gt c   amp 4r    switch  r     case Kdel   case Kesc     case  q      terminate      break   default   if  utfrune  0123456789   r     nil     recv kctl  gt c   amp rr    if  utfrune  0123456789   rr     nil     nval    r     0     10    rr  0         sendul sliderc  nval           The constants Kdel and Kesc are defined in keyboard h with the codes for the Delete and  the Escape runes  We terminate the program when either key is pressed  or when a q is typed   Otherwise  if the rune received from kct1     gt c is a digit  we try to obtain another digit to build a  slider value and send it through sliderc     To terminate the program  we must now call closekeyboard  which releases t
141.  tape panels at an  airport  This program is going to read lines from standard input  When a new message must be  displayed at the airport panels  the user is supposed to type the message in the keyboard and press  return     Once a new message has been read  all the panels must be updated to display it instead of  the old one  Because updating a panel is a very slow operation  we do not want to use a loop to  update each one in turn  Instead  we create one process per panel  as shown in figure 10 5            message    Figure 10 5  Process structure for the ticker tape panels application for the airport     The parent process will be the one reading from the input  After reading a new message  it  will increment a version number for the message along with the message text itself  The panel  processes will be polling the version number  to see if their messages are out of date  If they are   they will just write the new message to their respective panels  and record the version for the mes   sage  This is our data structure       242      typedef struct Msg Msg   struct Msg         QLock lck     to protect the other fields from races  char  text     for the message  ulong vers     for the message         Msg msg   The code for the message reader is as follows  It works only when reading from the terminal   because it is using just read to read a line from the input     void  reader  void          char buf  512    int nr   for         nr   read 0  buf  sizeof  buf  1    if  n
142.  tat E E eae   Reader 1 a R EIE E OE OE indie ase AEs  Reader 2 cecesenenn e     ek E E ST  Reader 3 a EE A T NA    Figure 10 7  Multiple readers may share the lock at the same time using a read write lock     When there is not much competition to acquire the lock  or when there are not many read   ers  the difference may be unnoticed  However  locks heavily used with many processes that just  want to read the data  can make a difference between both types of locks     10 4  Rendezvous    A primitive provided to synchronize several processes is rendezvous  It has this name  because it allows two different processes to rendezvous  i e   to meet  at a particular point in their  execution  This is the interface       sig rendezvous  void  rendezvous  void  tag  void  value     When a process calls rendezvous with a given tag  the process blocks until another process  calls rendezvous with the same tag  Thus  the first process to arrive to the rendezvous  will block and wait for the second to arrive  At that point  the values both processes gave as  value are exchanged  That is  rendezvous for each process returns the value passed to the  call by the other process  See figure 10 8     The tag used for the rendezvous represents the meeting point where both processes want  to rendezvous  The ability to exchange values makes the primitive more powerful  and converts it  into a generic communication tool for use when synchronization is required  In general  any two  processes may ren
143.  text selected  p  selecting lines 3 to 5  And also  we must ask sed not to print  lines by default after processing them  by giving the  n flag       sed  n 3 5p  LICENSE  with the following notable exceptions     1  No right is granted to create derivative works of or    The special address   matches the end of the file  Therefore  this deletes from line 3 to the end of  the file       196        sed  3 Sd     LICENSE  The Plan 9 software is provided under the terms of the  Lucent Public License  Version 1 02  reproduced below        What follows deletes lines between the one matching  granted   i e   the first one that con   tains that word  and the end of the file  This is like using 1  3d  There are two addresses and a d  command  It is just that the two addresses are more complicated this time       sed     granted   Sd     LICENSE   The Plan 9 software is provided under the terms of the  Lucent Public License  Version 1 02  reproduced below   with the following notable exceptions        r    Another interesting command for sed is r  This one reads the contents of a file  and writes them  to the standard output before proceeding with the rest of the input  For example  given these files       cat salutation  Today I feel   FEEL   So be warned     cat how   Really in bad mood             r             we can use sed to adjust the text in salutation so that the line with FEEL is replaced with  the contents of the file how  What we have to do is to give sed an address that
144.  that the program is  terminating     A panel thread  one for each panel  can simply read new messages from the panel   s chan   nel and update a panel  It needs to know which channel to read messages from  and which panel  to write to  A structure is declared to pass such information as an argument     typedef struct PArg PArg    struct PArg    Channel  c     to get new messages from  int fd     to the panel   s file              Using it  this can be its implementation  Like before  a nil message is an indication to exit     void   panelthread  void  a       PArg  arg   a   char  msg     threadsetname   panel      while  msg   recvp arg  gt c       write arg  gt fd  msg  strlen msg      free  msg              threadexits  nil           All threads were simple to implement  and the structure for the program follows easily from the  problem being solved  We did not have to worry about races since each thread is only using its  own data     There is one problem  though  If a thread calls Brdstr  to read from the console  it is  going to block all the threads  It blocks the entire process  The same happens while updating the  slow panels using a write to their files  This problem is easy to solve  Instead of creating a  thread to run consreadthread  and one more thread to run each panelthread function  we  can create processes  The function proccreate creates a new process  using rfork  with a  single thread in it  Otherwise  it works like threadcreate       276        sig proc
145.  the child   s write updates the file and advances the offset by 6  The  next write does the same  The order of child and dad may differ in the output  depending on  which process executes first its write  Both will be there     Compare what happen before with the behavior for the next program  The program is very  similar  The parent tries to write dad to a file  and the child tries to write chid  According to  our experience  the file should have both strings in it after the execution     after c          include  lt u h gt                 include  lt libc h gt     void  main int  char          int fd     if  fork      0    fd   open  afile   OWRITE    write fd   child n   6           else            fd   open  afile   OWRITE    write fd   dad n   4         close  fd     exits  nil           But this is what happens     rm afile   touch afile   8 after   cat afile   dad   d     xd  c afile   0000000 ad a d n d n  0000006    Ne Ne Ne Ne    Why  Because each process had its own file descriptor for the file  that now is not sharing any   thing with the other process  In the previous program  the descriptors in both processes came from  the same open  They were sharing the offset  When the child wrote  it advanced the offset  The  parent found the offset advanced  and could write past the child   s output     But now  the parent opens the file  and gets its own offset  starting at 0   The child does the  same and gets its own offset as well  also 0   One of them writes  in this
146.  the data struc   ture at the same time  in those periods when nobody is modifying msg     Plan 9 has read write locks  A read write lock  or RWLock  is similar to a queuing lock   However  it makes a distinction between readers and writers of the resource being protected by  the lock  Multiple readers are admitted to hold the very same RWLock  at the same time  How   ever  only one writer can hold a RWLock  and in this case there can be no other reader or writer   This is also called a multiple reader single writer lock     Processes that want to acquire the lock for reading must use rlock and runlock       245        sig rlock runlock  void rlock RWLock  1   void runlock RWLock  1     Processes that want to acquire the lock for writing must use wlock  and wunlock       sig wlock wunlock  void wlock RWLock  1   void wunlock RWLock  1     The improved version for our program requires a change in the data structure  that must use a  RWLock now     struct Msg      RWLock lck     multiple readers for this data  just one writer   char  text     for the message  ulong vers     for the message         The new code for panelproc must acquire a lock for reading  but is otherwise the same     void  panelproc int fd         as before     rlock    msg 1lck    if msg text    nil  amp  amp  lastvers    msg vers     text strdup  msg text    lastvers   msg vers        runlock   amp msg lck      as before            And the process writing to the data structure now requires a write lock   vo
147.  the file server  Your terminal has nothing to save  You can switch  it off at any time     1 4  Editing and running commands    The window system is a program that can be used to create windows  Initially  each window runs  the Plan 9 shell  another program called rc  To create a window you must press the right mouse  button  button 3  and hold it  A menu appears and you can move the mouse  without releasing the  button  to select a particular command  You can select New  see figure 1 3  by releasing the  mouse on top of that command     Because rio is now expecting one argument  the pointer is not shown as an arrow after  executing New  it is shown as a cross  The argument rio requires is the rectangle where to show  the window  To provide it  you press button 3  then sweep a rectangle in the screen  e g   from the  upper left corner to the bottom right one   and then release button 3  Now you have your shell   The other rio commands are similar  They let you resize  move  delete  and hide any window   All of them require that you identify which window is to be involved  That is done by a single  button 3 click on the window  Some of them  e g   Resize  require that you provide an addi   tional rectangle  e g   the new one to be used after the resize   This is done as we did before        Figure 1 3  The rio menu for mouse button 3     The window system uses the real display  keyboard  and mouse  to provide multiple  virtual   ones  A command running at a window thinks that
148.  the file with name usr   3 Walk down again to the file named nemo  You have arrived     This name specifies a path to walk through the tree of files to reach a particular file of interest  as  shown in figure 7 1  What is a file  Something that you can open  read  write  etc  As long  as the file implements these operations  both you and Plan 9 are happy with it     ZS   J      nemo glenda mero    Figure 7 1  A file name is a path to walk in the tree of files     But how can          which is just a name  refer to a file  Where does it come from  And why  can a name like  dev cons refer to different files at different windows  The answers come  from the abstraction used to provide names for files  the name space  In this case  names are for  files  and we will not be saying this explicitly  It should be clear by the context     A name space is just a set of names that you can use  all the file paths that you might ever  use in your file tree   Somewhat confusingly  the abstraction that provides a name space is also  called a name space  To add more confusion  this is also called a name service     The name space takes a name  i e   a string  and translates this name into something that can  be used as a file in Plan 9  This translation is called resolving a name  It takes a name and yields  a Chan  the data structure used to represent a file within the Plan 9 kernel  Thus  you might say  that resolving a name takes a string and yields a file  The translation is done by walki
149.  the write function  the system call  in the kernel  must send a message  through the network to the machine that keeps the file  to the file server  This message con   tains a request to perform the write operation and all the information needed to perform it   e g   all the values and data you supplied as parameters for the write     4 The remote machine  the file server  performs the operation and replies sending a message     25      through the network back to your terminal  The message reports if the operation was com   pleted or not  and contains any output result for the operation performed  e g   the number of  bytes that could be written into the file     5 You kernel does some bookkeeping and returns to your system call  returning the result of  the operation  as reported by the other machine      6 The library function returns to your program when everything was printed     Steps 3 and 4 are called a remote procedure call  This is not as complex as it sounds  but it is  not a procedure call either  A remote procedure call is a call made by one program to another that  is at a different place in the network  Because your processor cannot call procedures kept at dif   ferent machines  what the system does is to send a message with a request to do something  and  to receive a reply back with any result of interest     1 13  The Shell  commands  binaries  and system calls    It is important to know how these elements come into play  As you know  the operating system  
150.  these commands  Why       Ca  7  FCO s hiss    pwd    After reading date 1   change the environment variable timezone to display the current  time in New Jersey  East coast of US     How can we know the arguments given to a process that has been already started    Give another answer for the previous problem     What could we do if we want to debug a broken process tomorrow  and want to power off  the machine now     What would happen if you use the debugger  acid  to inspect 8  out after executing the  next command line  Why       strip 8 out     54      55     3     Files    3 1  Input Output    It is important to know how to use files  In Plan 9  this is even more important  The abstractions  provided by Plan 9 can be used through a file interface  If you know how to use the file interface   you also know how to use the interface for most of the abstractions that Plan 9 provides    You already know a lot about files  In the past  we have been using print to write mes   sages  And  before this course  you used the library of your programming language to open  read   write  and close files  We are going to learn now how to do the same  but using the interface pro   vided by the operating system  This is what your programming language library uses to do its job  regarding input output    Consider print  it is a convenience routine to print formatted messages  It writes to a file   by calling write  Look at this program     write c   include  lt u h gt      include  lt libc h
151.  thread  within the process that starts executing the function threadmain  This is the function that you  are expected to provide as your entry point       262         tincr c     include  lt u h gt    include  lt libc h gt      include  lt thread h gt   int cnt   void    incrthread  void           int ane  for  i   0  i  lt  2  itt   cntt t      print   cnt is  d n   cnt      threadexits  nil      void  threadmain int  char             int T     threadcreate  incrthread  nil  8 1024    for  i   0  i  lt  2  i     CIES  p  tint   cnt is  d n   cnt    threadexits  nil           The program calls threadcreate to create a new thread  the second in this process   that starts  executing the function incrthread  After this call  there are two independent flows of control   One is executing threadmain  after the call to threadcreate  The other is starting to exe   cute incrthread  The second parameter given to threadcreate is passed by the library as  the only argument for the main procedure for the thread  Because incrthread does not require  any argument  we pass a nil pointer  The third argument to threadcreate is the thread   s  stack size  The stack for a thread is allocated as a byte array in the data segment  like other  dynamic variables  it lives in the heap  within the data segment      It is interesting to see that threads call threadexits to terminate  instead of calling  exits  Calling exits would terminate the entire process  the only flow of control provided by  Plan 
152.  time and then wrote that byte to the output file  Before  we did the same but  for a more reasonable buffer size     Let   s continue the experiment  What would happen if our program reads one line at a time   The source file does not have lines  but we can pretend that all lines have 80 characters of one  byte each       time 8 bcp  b 80  tmp sfile  tmp dfile  0 11u 0 74s 10 38r 8 bcp  b 80  tmp sfile  tmp dfile    Things improved  but nevertheless we still need 10 38 seconds just to copy 1 Mbyte  What hap   pens is that making a system call is not so cheap  at least it seems very expensive when compared  to making a procedure call  For a few calls  it does not matter at all  However  in this experiment  it does  Using a buffer of just one byte means making 2 097 152 system calls   1 048 576 to read  bytes and 1 048 576 to write them   Using an 8Kbyte buffer requires just 128 calls   e   1 048 576    8 196   You can compare for yourself  In the intermediate experiment  reading one line at a  time  it meant 26 214 system calls  Not as many as 2 097 152  but still a lot     How to overcome this difficulty when we really need to write an algorithm that reads writes  a few bytes at a time  The answer  as you probably know  is just to use buffering  It does not mat   ter if your algorithm reads one byte at a time  It does matter if you are making a system call for  each byte you read     The bio 2  library in Plan 9 provides buffered input output  This is an abstraction that   a
153.  to  chanprint is similar to calling smprint  to print the arguments in a string allocated in  dynamic memory   and then sending the resulting string through the channel  This function is  very convenient in many cases     At any time  the operator might send an end of file indication  typing control d  When the  decorator thread receives a nil message  sent by consthread upon EOP   it calls  threadexitsall  This function terminates all the processes and threads of the program  ter   minating it     11 6  Other calls    In general  it is safe to use whatever functions from the C library  or from any other one  in a pro   gram using the thread library  We have done so through this chapter  Function libraries try not to  use global variables  and when they do  they try to protect from races so that you could call them  from a concurrent program  In other systems  things are not so nice and you should look into the  manual pages for warnings regarding multi threaded programs  For example  many UNIX manual  pages have notes stating that functions are MT Safe  i e   safe for use in multithreaded programs   That is  in programs with multiple threads     Even in Plan 9  some other functions and system calls are not to be used when using the  thread library  In general  this happens whenever a function deals with the flow of control for the  process  A threaded program has multiple flows of control  and it would make no sense to operate  on the underlying flow of control of the proce
154.  to match the pattern   rio     As you know  by default  the action is to print the matching record  The operator   yields true  when both arguments match  Any argument can be a regular expression  enclosed between two  slashes  The pattern we used required all of field number 7 to be just rio  because we used   and    to require rio to be right after the start of the field  and before the end of the field  As we said     and   mean the start of the text being matched and its end  Whether the text is just a field  a  line  or the entire file  it depends on the program using the regexp     It is easy now to list process pids for rio that belong to user nemo       217        ps   awk    S7     rioS   amp  amp   1     nemoS   print  2      39  ZL  277  280    How do we kill broken processes  AWK may help       ps   awk    S6    Broken   printf  echo kill  gt  proc  s ctl0   2   7   echo kill  gt  proc 1010 ctl  echo kill  gt  proc 2602 ctl       The 6th field must be Broken  and to kill the process we can write kill to the process control  file  The 2nd field is the pid and can be used to generate the file path  Note that in this case the  expression matched against the 6th field is just  Broken   which matches with any string con   taining Broken  In this case  it suffices and we do not need to use   and             Which one is the biggest process  in terms of memory consumption  The 6th field from the  output of ps reports how much memory is using a process  We could use our 
155.  to print lines in our ns file that contain the  string whale      echo spid   843     grep whale  proc 843 ns   mount  c  s tcp whale 9fs  n whale  mount  c  s tcp whale 9fs  n other    Because lines at  proc Spid ns are not yet ready for use as shell commands  there is a com   mand called ns  name space  that massages them a little bit to make them prettier and ready for  use  Using ns is also more convenient because you do not need to type so much       ns   grep whale  mount  c      s tcp whale 9fs     n whale  mount  c   s tcp whale 9fs     n other    The effect of a mount  or a bind  can be undone with another system call  called unmount  or  using the shell command of the same name       unmount  n whale     Ic  n whale     grep whale  proc 843 ns   mount  c  s tcp whale 9fs  n other    r    After executing unmount  the name space no longer jumps to the root of the file server at  whale when reaching  n whale  because the entry in the mount table for  n whale has been  removed  What would happen now to  n other       163        le  n fother                      386 acme cron mnt tmp  LICENSE adm dist n usr  LICENSE afpl alpha lib power   LICENSE  gp  arm lp re   NOTICE cfg mail sys       Nothing  It remains as before  We removed the entry for  n whale  but we did not say anything  regarding the bind for  n other  This is simple to understand if you think that your name  space  i e   your mount table  is just a set of translations from one file to another file  Here    
156.  to the client with the result for the operation     To use Plan 9  you must switch on your terminal  Depending on the local installation  you  may have to select PXE as the boot device  PXE is a facility that lets the computer load the sys   tem from the network   But perhaps the terminal hardware has been configured to boot right from  the network and you can save this step  Once the Plan 9 operating system program  you know  the  kernel  has been loaded into memory  the screen looks similar to this     PBS  5 02   Plan 9   cpu0  1806MHz GenuineIntel P6  cpuid  AX 0x06D8 DX OxFE9SFBBF   ELCR  OE20    10  AMD79C970  10Mbps port 0x1080 irq 10  000c292839fc    11  AMD79C970  10Mbps port 0x1400 irq 9  000c29283906   U usb0  uhci  port 0x1060 irq 9   512M memory  206M kernel data  305M user  930M swap   root is from  local  tcp   tcp                  There are various messages that show some information about your terminal  including how  much memory you have  Then  Plan 9 asks you where do you want to take your files from  To do  so  it writes a prompt  i e   some text to let you know that a program is waiting for you to type  something  In this prompt  you can see tcp between square brackets  That is the default value  used if you hit return without further typing  Replying tcp to this prompt means to use the TCP  network protocol to reach the files kept in the machine that provides them to your terminal   called  the file server   Usually  you just have to hit return at this 
157.  to wake up one of the possibly many processes waiting for the  condition to hold     The idea is that rsleep is a temporary sleep waiting for a condition to hold  And it always  happens in the middle of an operation on the resource  after checking out if the condition holds   This function releases the lock before going to sleep  and re acquires it after waking up  There   fore  the process can nicely sleep inside its critical region  because the lock is not held while  sleeping  If the lock was kept held while sleeping  the process would never wake up  To wake up   it requires another process to call rwakeup  Now  a process can only call rwakeup while hold   ing the resource  i e   while holding the lock  And to acquire the lock  the sleeper had to release it  before sleeping     The behavior of rwakeup is also appropriate with respect to the lock of the resource  This  function wakes up one of the sleepers  but the caller continues with the resource locked and can  complete whatever remains of its critical region  When this process completes the operation and  releases the lock  the awaken one may re acquire it and continue     Re acquiring the lock after waking up might lead to starvation  when there is always some  process coming fast to use the resource and acquiring the lock even before the poor process that  did wake up can acquire it again  To avoid this  it is guaranteed that a process that is awaken will  acquire the lock sooner than any other newcomer  In few word
158.  variable   reads the corresponding file  and returns a C string for the value read     This simple idea  representing almost everything as a file  is very powerful  It will take  some ingenuity on your part to fully exploit it  For example  the file  dev text represents the  text shown in the window  when used within that window   To make a copy of your shell session   you already know what to do       cp  dev text Shome saved    The same can be done for the image shown in the display for your window  which is also repre   sented as a file   dev window  This is what we did to capture screen images for this book   The same thing works for any program  not just for cp  for example  1p prints a file  and this  command makes a hardcopy of the whole screen       Ip  dev screen    Problems  1 Why was not zero the first address used by the memory image of program global     2 Write a program that defines environment variables for arguments  For example  after call   ing the program with options      args  ab  d x y zZ    the following must happen       echo Sopta  yes     echo Soptb  yes     echo Soptc  yes     echo Sargs  xX y Zz    3 What would print  bin ls  blahblah  given that  blahblah does not exits    Would 1s  blahblah print the same  Why     4 What happens when we execute       22 CO     after executing this program  Why      include  lt u h gt     include  lt libc h gt    void   main int  char          putenv  home     tmp      exits  nil      10     53     What would do
159.  variables  214  AWK script  List  219  AWRITE access mode  67  axis  309       B    background  184   command  97  103  backing store  305  backslash  44  202  backspace  290  backward compatibility  2  base   input  183   output  183  be  183  194  bep c  76  become none  371  before c  89  BEGIN pattern  217  Bflush  79  bidirectional pipe  110   bin  43 171  BIN  353  binary  97   file  21 22  25  31 171  bind  161  163  169   flag  a  168   flag    b  168   flag  c  169  binding  161  Binit  80  bio  77  Biobuf  77   file descriptor  80   flushing  79   termination  79  biocat c  80  biocp c  79  bio h  79  BIOS  298  birth  process  35  black  302  black c  300  blank   CD  226   screen  299  blank  303  Blinelen  81  block  file  76  blocked  46       process  112   state  231  board  file descriptor  123  boldface  236   boot  360  boot  123  150   program  151  boot  151  359  booting  4  172  359  Bopen  79  bottom window  317  boundaries  write  110  137  bounded buffer  252  256  box c  173  branch  multiway  190  Brdline  80  274  Brdstr  81 274  Bread  79  broadcast  274  broke  109  Broken  109  217  broken  47   pipe  112   process  kill  109  broken  49  bss segment  34  51  Bterm  79  buffer  77   bounded  252  256   flushing  81   shared  252  buffered I O  75  77  274  buffering  channel  270  building things  349  builtin command  158  burn  CD  225  busy waiting  46  125  238  button  mouse  6  button 1  mouse  296  309  button2  mouse  296  button 3  mo
160.  web server  that is meant to  be always running  This program is meant to run in the background  because it does not need a  console to read commands  The user is expected to run our server as in     httpd  amp    to be able to type more commands in the shell  However  if the user now hits Delete to stop  another program  the web server is killed as well  This can be avoided by calling    rfork  RFNOTEG          in the program for httpd  This puts the process in a new note group  We are no longer affected  by notes to the group of the shell that runs in our window  To try this  run this program comment   ing out the call to rfork  and hit Delete       156      noterfork c     include  lt u h gt    include  lt libc h gt     void  main int  char           int ae       rfork  RFNOTEG      for i   0  i  lt  5  itt     sleep  1000    print   sd      IN        print    n      exits  nil           The program gets killed         noterfork  O 1 2 Delete    F    With the call in place  the program happily ignores us until it completes       8 noterfork  O 1 2 Delete 3 4 5    r    Imagine this program is our httpd server  If the user forgets to type the ampersand  it will block  the shell forever  it is waiting for the child to die   The only way to kill it is to open a new win   dow and kill manually the process by writing to its ct 1 file  as we saw before  To be more nice   our program could fork a child and let its original process die  The shell prompt would be right  back  Becau
161.  were simple to use   They also noticed that it was well known how to engineer the system to permit one machine use  files that were kept at another     Here comes the idea  For most abstractions provided by Plan 9  to let you use your hard   ware  a file interface is provided  This means that the system lies to you  and makes you believe     50     that many things  that of course are not  are files  The point is that they appear to be files  so that  you can use them as if that was really the case     The motivation for doing things this way is that you get simple interfaces to write programs  and use the system  and that you can use also these files from remote machines  You can debug  programs running at a different machine  you can use  almost  anything from any other computer  running Plan 9  All you have to do is to apply the same tools that you are using to use your real  files at your terminal  while keeping them at a remote machine  the file server      Consider the time  Each Plan 9 machine has an idea of what is the time  Internally  it keeps  a counter to notice the time passing by and relies on a hardware clock  However  for a Plan 9  user  the time seems to be a file       cat  dev time  1152301434 1152301434554319872    Reading  dev time yields a string that contains the time  measured in various forms  Seconds  since the epoch  since a particular agreed upon point in time in the past   nanoseconds since the  epoch  and clock ticks since the epoch     Is  dev 
162.  with the arguments  stored as an environment vari   able        181      To access the n th element of a list  you can use  var  n   However  to access the n th  argument in a shell script you are expected to use  n  An example for our popular abc list fol   lows     echo Sx 2     o       echo  x 1   a    Lists permit doing funny things  For example  there is a concatenation operator that is best shown  by example       X  a bo   ya a a  echo  x  y  al p2 c3    The   operator  used in this way  is useful to build expressions by building separate parts  e g   prefixes and suffixes   and then combining them  For example  we could write a script to adjust  permissions that might set a variable ops to decide if we should add or remove a permission  and  then a variable perms to list the involved permissions  Of course in this case it would be easier  to write the result by hand  But  if we want to generate each part separately  now we can       OpS             perms  r w x      echo  ops  perms afile   r  w  x afile    Note that concatenating two variables of length 1  i e   with a single word each  is a particular  case of what we have just seen  Because this is very common  the shell allows you to omit the     which is how you would do the same thing when using a UNIX shell  In the example below  con   catenating both variables is exactly the same than it would have been writing a1 instead       X a     yal     echo Sx Sy   al     echo SxSy   al  A powerful use for this operat
163.  write locks  244  Ready  127  261  ready  46  receive  plumb message  131  receiving  call  146  record  input  220  skip  220  Rect  308  Rectangle  301  rectangle  height  308  width  308  rectangle  screen  301  recv  269  297  recvp  274  recvul  274  redirection  append  106  file descriptor  101  input  103  input and output  107  T O  101  output  101    standard error  188   standard output  105  Ref  340  reference counting  340  Refnone  305  regcomp  205  regexp  204  region  critical  233  235  registers  84  registry  123  regression testing  355  regular expression  129  201   compiler  205  relative   path  35   paths  13  relying  364  remote   command execution  151   debugging  175   execution  174   file system  174   procedure call  25  remote file  137  remove   duplicates  207   file  11  343  remove  66  rename  file  15  197  Rendez  249  252  rendez c  248  rendezvous  272   group  153 154   tag  246  rendezvous  153  246  repl  308  replace string  194  replicated image  308  representation  text  292  Reprog  204  Req  336  request  9P  325  336  Rerror  326  rerrstr  41  Resize  6  resize   event  303  305   window  303  318  resize c  304  resizethread  305  resolution   name  159   screen  299  resource     2      fork  153  lock  234  manager  2  multiplexing  2  process  153  shared  89  91  sharing  98  153  157  respond  336  Return  4  return  carriage  138  return value  fork  84  reverse sort  217  FENVG rfork flag  158  FFDG rfork flag  
164.  you don   t help yourself in the first place  Machines love regular structures  so it is  better to try to do the same thing in the same way everywhere  If it can be done in a way that can  simplify your job  much better     Plan 9 is a nice example of this is practice  Because all the resources are accessed using the  same interface  a file interface   all the programs that know how to do particular things to files  can be applied for all the resources in the system  If many different interfaces were used instead   you would need many different tools for doing the same operation to the many different resources  you find in the computer     This explains the popularity of XML and other similar data representations  which are  attempts to provide a common interface for operating on many different resources  But the idea is  just the same       180      8 2  Lists    The shell includes lists as its primary data structure  as its only data structure  indeed  This data  type is there to make it easier for you to write shell programs  Because shell variables are just  environment variables  lists are stored as strings  the only value a environment variable may have   This is the famous abc list       X  a boc     echo Sx  abe    It is just syntax  It would be the same if we had typed any of the following     X  a  b c     echo  x   be     X    a   b    c    echo Sx   abe    Q  xe Ne     e    It does not matter how you nest the same values using multiple parenthesis  All of them w
165. 0 nemo nemo 0 May 23 17 44  srv tcp localhost 9988    The program srv dialed the address tcp  whale  9fs and  after establishing a connection     posted the file descriptor for the connection at  srv tcp whale  9fs  This file  descriptor   has a file server program that speaks 9P at the other end of the connection     However  to access files in the file server  we must be able to see those files in our file tree   i e   in our name space  Otherwise we would not be able to write paths leading to such files  We  can do it  The Plan 9 mount system call modifies the name space and instructs it to jump to a  new file when you reach a given file  The shell command mount does the same     386 arm usr tmp n         nemo glenda mero   whale Tep Moun Ey Ioi  386 arm usr Dagi    Figure 7 2  The file tree reached through tcp  whale  9fs is mounted at  n whale     This may seem confusing at first  but it is quite simple  For example  we may change our  name space so that when we walk through our file tree  and reach the directory  n whale  we  continue our walk  not at  n whale  but at the root directory of the file server reached through   srv tcp whale  9fs  For example      lc  n whale      mount  c  srv tcp whale 9fs  n whale    Ic  n whale                         386 acme cron mnt tmp  LICENSE adm dist n usr  LICENSE afpl alpha lib power   LICENSE  gp  arm lp re   NOTICE cfg mail sys    Before executing mount  the directory  n whale was empty  After executing it  the original  direc
166. 00000000002 0     lt  12  Tclunk tag 14 fid 458   12  gt  Rclunk tag 14    rw r  r   M 125 nemo nemo 0 Aug 20 01 28  n ram z         m 0644 at 1      331        chmod  w  n ram z                 lt  12  Twalk tag 14 fid 435 newfid 458 nwname 1 0 z    12  gt  Rwalk tag 14 nwgid 1 0   0000000000000002 0      lt  12  Tstat tag 14 fid 458    12  gt  Rstat tag 14 stat    z     nemo       nemo       nemo    q  0000000000000002 0   lt  12  Tclunk tag 14 fid 458    12  gt  Reclunk tag 14    lt  12  Twalk tag 14 fid 435 newfid 458 nwname 1 0 z    12  gt  Rwalk tag 14 nwgid 1 0   0000000000000002 0      lt  12  Twstat tag 14 fid 458 stat                fr    q  ffffffffFLLLLLLL 4294967295 dalA    12  gt  Rwstat tag 14    lt  12  Tclunk tag 14 fid 458    12  gt  Reclunk tag 14          At this point  we know enough of 9P and what a file server does to start building a new file  server     13 3  Semaphores for Plan 9    For most tasks  it would be probably better to use channels  from the thread library  instead of  using semaphores  Semaphores are a synchronization abstraction prone to errors  But assuming  that we need semaphores due to some reason  it may be useful to write a file server to provide  them  Before  we used pipes to implement semaphores  This is reasonable and works well within  a single machine  But what if you want to use semaphores to synchronize processes that run at  different machines  Also  using a byte of buffering in the pipe for each ticket in the semaphore  lo
167. 108  110  117  124  128  136  184  252  bidirectional  110  broken  112  closed  112  conditional  191  creation  114  device  225  end of  225  non linear  117  208  to child process  112  pipe command  acme  115  pipe  109  pipe c  110  pipeto  114  pipeto c  112  pixel  295  plan9 partition  322  plumb  message  128  message attribute  131  message attributes  129  message receive  131  port open  130           18     plumb port  edit  128  plumb  131   command  130   library  130  Plumbattr  131  plumber port  128  plumber   rules  128  send  128   plumber  128  165  plumbing  128  165  plumbing  acme  128  plumbing  129  165  Plumbmsg  131  plumbopen  130  plumbrecv  131  plumbsend  132  plumbsendtext  132  Point  297  point   mount  161  166  168   program entry  35   to type  8  pointer  null  51  pollb c  126  poll c  126  polling  125  127  248  pong c  271  port  128   announce  144   creation  network  144   network  136   number  136  138   plumber  128  position  mouse  296  post   file descriptor  123  160  326   note  117  postmountsrv  333  PostScript viewer  129  practice  programming  40  pragma  21  Pread  46  predefined variables  mk  352  preemptive scheduling  46  prep  323  Sprereq  352  principle  least privilege  371  print   current directory  14   lines  195  print  23  40   channel  285  privacy  18          m  m  m  m  m  m       private memory  363  privilege principle  least  371  privileged mode  2  24  probe  internet  189   proc file system  
168. 11 r M 94  0000000000000001 0 00  8192 18  dev cons    r    The first line reports the current working directory for the process  Each other line reports a file      59     descriptor open by the process  Its number is listed on the left  As you could see  our shell has  descriptors 0  1  and 2 open  among others   All these descriptors refer to the file  dev cons   whose name is listed on the right for each descriptor  Another interesting information is that the  descriptor 0 is open just for reading  OREAD   because there is an r listed right after the descrip   tor number  And as you can see  both standard output and error are open just for writing   OWRITE   because there is a w printed after the descriptor number  The  proc S pid  fd file  is a useful information to track bugs related to file descriptor problems  Which descriptors has  the typical process open  If you are skeptic  this program might help     sleep c                      include  lt u h gt                 include  lt libc h gt    void   main int  char           print   process pid is  d  have fun  n   getpid      sleep  3600 1000      one hour to play   exits  nil           It prints its PID  and hangs around for one hour  After running this program      8 sleep  process pid is 1413  have fun     and it hangs around for one hour     we can use another window to inspect the file descriptors for the process       cat  proc 1413 fd   usr nemo 9intro    Or M 94  0000000000000001 0 00  8192 87  dev cons  lw M 
169. 154  FMEM rfork flag  229  FNOMNT rfork flag  173  371  FNOTEG rfork flag  155  FNOWAIT rfork flag  158  rfork  153  164  229  237  276  command  158  183  flag  RFENVG  158  flag  RFFDG  154  flag  RFMEM  229  flag  RFNOMNT  173  371  flag  RFNOTEG  155  flag  RFNOWAIT  158  flag  RFPROC  154  rforkls c  154  RFPROC rfork flag  154  RFREND  276  HINCK sy 229  rio  5  42  52  289  313  commands  6  file system  172  313  menu  6  317  RJ45  135  clock  244  rm  11  14  66  74 75  flag  f  12  flag  r  67  rm c  67  Rob Pike  7  293  robust file read  120  robustreadn  121  role  366  ROM  298   root  171  root  device  166  directory  13  153  directory  file server  327  Ropen  328  round trip time  140  rpc file  364          DW Dw yD                Rpt  308  rsleep  248  RTT  140   tule  implicit  352  rules  mk  349  rules  plumber  128  runaway process  87  Rune  293   rune  16  292  conversion  294  rune c  294  runetochar  293  runlock  244  runls c  83  Running  127  running  46  program  29  Rversion  326  rwakeup  248  rwakeupall  248  Rwalk  328  Rwrite  328   rx  151             S     S device driver  176  321   s device driver  123  sandbox  173  sandboxing  172  371  scheduler  46  scheduling  45 46  230  261  preemptive  46  screen  295  300  blank  299  image  52  layout  318  origin  302  resolution  299  size  295  318  screen  301  316  rectangle  301  script  97  argument  180  arguments  99  189  diagnostics  211  machine start  151  shell  98 99  157  18
170. 189  protocol  135  interpreted program  97  interpreter  98  command  25  interrupt  117 232  hardware  26  process  118  program  292  software  24  interrupt note  117  120  155  213  223  314  intfork c  86  into  loging  4  invocation syntax  command  39  TO  55  buffered  75  77  274  redirection  101  thread  274  user  289  IP  135  ip ping  140  189  iredir c  103  is a file  everything  49    K    Ken Thompson  21  293  kernel  1  24  46  159  261  359  compilation  192  key  374  adding  367  escape  290  reading  367  key  363  keyboard  293  initialization  309  input  309  library  309  Keyboardctl  310  keyboardthread  311  keyfs  374  keys  362  arrow  290  kfs  324  kill  broken process  109  process  119  kill  51 217  killing a process  51    L    label  window  301  316  language   arithmetic  183   C  20     13     programming  179  laptop computer  357  layout   automatic  318   screen  318  lc  seels  Les 12  SLD  351  leak  memory  355  leak  355  least privilege principle  371  leaving the system  6  length   file  69   line  81   variable  180  letter  greek  293  lib9p  332   memory allocation  340  libc h  21  68   lib namespace  173  203  371   lib ndb auth  372  libraries  1  library  21  135   9P  332   C  68   function  23   keyboard  309   mouse  296   thread  261  library   auth  364   plumb  130   window  315  line   command  5  25  42  97  101  116  191  194   directory  136  145  300   discipline  290   end of  201   fields  215   length  
171. 272      to receive a message from the channel pingc  The message is stored by recv at the address  given as the second argument  That is  recv receives an integer and stores it at msg  Once the  integer has arrived  ping increments it and calls    send  pongc   amp msg      to send through pongc the message pointed to by  amp msg  That is  to send the integer msg   because the channel was created to send messages with the size of a integer      Initially  both threads would block at recv  because nobody is sending anything yet  To  kick off the ping pong  the main thread sends an initial zero to the pingc channel  See figure    11 3        gt  ponge  gt    lt    pingc      Figure 11 3  A ping pong with threads and channels                          The output from the program is a nice ping pong  Note that context switches between  threads happen when we call send and recv  Any synchronization function from the thread  library is likely to produce a context switch       8 out  1   2  3   4    A channel with no buffering is producing a rendezvous between the thread sending and the one  receiving  A recv from such a channel will block  until there is something to receive  Because  the channel has no buffering  there can be nothing to receive until another thread calls send for  the same channel  In the same way  a send to a channel with no buffering is going to block if  nobody is receiving on it  It will block until another thread calls recv and the message can be  sent     We
172. 3  script  rc  183  scroll mode  317  sdco  176  search  manual  183  text  129  201  word  108      22    searching  205  file  74  secret  374  shared  360  secstore  375  secure  server  368  store  375  system  357  security  357  9P  360  sed  194  201  command  compound  196  flag  e  195  flag  n  195  seek  60  62 63  322  seekhello c  63  segment  bss  34  51  data  34 51  memory  34  48  51  stack  34  51  text  34 51  virtual memory  153  Sem  338  semaphore  255  331  file system  331  tickets  255  value  255  semfs  331  send  269  plumber  128  sendp  274  sendul  274  seq  116  187  218  sequences  187  sequential  access  59  server  148  server  144  325  9P  325  authentication  374  concurrent  148  connection  139  CPU  174  372  echo  123  file  3  24  62  123 124  159  224  321  loop  334  mail  151  network echo  147  process  333  357  program  file  163  secure  368  sequential  148    threaded  148  uid  367  servers  authentication  361  CPU  151  service  137  name  137  139  144  name  159  TCP echo  150  service  151  services  machine  150  network  135  150  providing  144  set  character  201  setting up DMA  321  shared  buffer  252  counter  229  261  memory  229  333  offset  90  resource  89  91  secret  360  sharing  resource  98  153  157  shell  5  25  comment  99  comment character  21  function  206  note handler  213  pid  45  program  180  script  98 99  157  183  variable  73  180  sic c  39  sig  10 55  sigalrm  213  sighup  213 
173. 3 1148K Pread rio  nemo 281 0 02 0407  13 13 1148K Pread rio  nemo 303 0 00 0 00 13 13 1148K Await rio  nemo 305 0 00 02 00  13  3 248K Await re  nemo 306 0 00 0 00 13 13 1148K Await rio        more output omitted          46      The last field is the name of the program being run by the process  The third field going right to  left is the size of the  virtual  memory being used by the process  You may now know how much  memory a program consumes when loaded     The second field on the right is interesting  You see names like Pread and Await  Those  names reflect the process state  The process state indicates what the process is doing  For exam   ple  the first processes 280 and 281  running rio  are reading something  and everyone else in the  listing above is awaiting for something to happen  To understand this  it is important to get an  idea of how the operating system implements processes     There is only one processor  but there are multiple processes that seem to run simultane   ously  That is the process abstraction  Multiple programs that execute independently of each  other  None of them transfer control to others  However  the processor implements only a single  flow of control     What happens is that when one process enters the kernel because of a system call  or an  interrupt  the system may store the process state  its registers mostly  and then jump to the previ   ously saved state for another process  Doing this quickly  with the amazingly fast processors w
174. 50   access  346   CPU  127   elapsed  77   file access  69   file modification  69   modification  346   of day  282   process  95   round trip  140   stamp  295             CY 8  Chet os er er et Pe eer       system  77   user  77  time  50  77  282   command  194  timeout  121  timer  122   thread  282  tincr c  262  TLS  375  to   device  device  76   type  click  8   type  point  8  tools  179  top window  317  Topen  328  360  touch  11  toupperrune  294  tr  185   flag  d  185  translation   coordinate  302   name  139  transport protocol  136  trap  24  47  tree  file  13  153  159  Tremove  343  trinc c  263  troff  107  354  truncate  62  66  105  Tstat  330  Tversion  326  Twalk  328  Twrite  328  Twstat  330  type  130   CPU  172   message  326  type  Qid  328  types  abstract data  2  typesetting  107  typing acommand  10    U    UDP  136  u h  21  uid  359  change  373  client  367  server  367  uid  69  unbuffered channel  271  undefined symbol  23  Unicode  292      26      unicode code  293  union  168  172  mount  167  uniq  207  unique  identifier  327  lines  207  unit  drive  322  UNIX  3  17  21  110  135  151  179  285  349    unlock  234  unmount  162   up  338   up  255   updates  concurrent  232  usage    disk  198  205  memory  217  usage  39  Suser  43  172  user  357  data  342  id  69  id  modification  69  T O  289  name  4  43  172  359  new  360  374  time  77  user  51  users  357  using files  10  using rc  179  UTF 8  293  UTF8  16  UTFmax 
175. 50  118  162  proccreate  275  procedure call  remote  25  process  29  46  49  83  261   alarm  121   average  219   birth  35   blocked  112   child  84  87 88  98  153  157   communication  109  269   creation  83 84  153  275   death  35   environment  83   execution  230   frozen  115   group  42  117 118   group  environment  153   group  file descriptor  153   group  note  153   id  45   independent child  158   interrupt  118   kill  119   kill broken  109   list  101   memory  46  84   name  45   new  154   panel  241   parent  83  88  153   resource  153   runaway  87   server  333  357   stack  237  262   state  45 46  127   structure  276   synchronization  243   termination  39  84  158  243   time  95    process  ctl file  51  fd file  58    mem file  51  note file  118  120  notepg file  118  120  ns file  162  processes  concurrent  30  processing  data  179  data  219     19     mouse event  304  read  344  stat  347  walk  348  write  345  procexec  285  procexecl  285  producer consumer  252  257  profile  151  profile  5 129  program  arguments  35  AWK  220  boot  151  C  20  checking  354  counter  30  entry point  35  execution  26  83  91  285  file server  163  321  interpreted  97  interrupt  292  loaded  31  loader  32  loading  83  meaning of  230  name  92  running  29  shell  180  source  48  symbols  22  termination  254  275  text  22  programming  concurrent  91  229  language  179  practice  40  prompt  4  proof of identity  360  protection  
176. 61  name space  171  namespace  371  process  154  user  360  374  window  6  314  newline  290  new line character  16  newns  171 371  newuser  5  next AWK command  220  om  22  flag  n  32  no attach  173  none  371  become  371  non linear pipe  117  208  noswap  363  not  if  188  note  group  153  155  handler  118  120  handler  shell  213  post  117  process group  153  note  handler  rc  223  hangup  118  213  223  interrupt  117  120  155  213  223  314  note file  process  118  120  notepg file  process  118  120  noterfork c  156  notes  117  287   NOTICE  60  nread c  65  ns  162  file  process  162  null  list  182  pointer  51  variable  182  number  line  209  port  136  138  version  241  NVRAM  375  nvram  375  nwname  329             o    So  351  object file  22   objtype  353  octal  mode  20  permissions  69  of  control  flow  46  file  end  17  111  identity  proof  360  ofcall  336  offset  16  60  file  59  61  shared  90  OFILES  353  on  demand  loading  34  single sign  375  onefork c  84  only  append  64  open  account  4  exclusive  295  mode  58  plumb port  130  open  flag  ORCLOSE  120  mode  OREAD  58 59  mode  OTRUNC  62  mode  OWRITE  58 59  61  open  58  61  65  75  159  openfont  312  operating system  1  operation  alternative channel  284  permitted  360  simultaneous channel  284  operator  compare  188  concatenation  181  option  11  argument  38  command  9  option          36   e  hoc  183  optional string  202  or  logical  191 
177. 71  374  375          Getting started    1 1  What is an Operating System     The operating system is the software that lets you use the computer  What this means depends  on the user   s perspective  For example  for my mother  the operating system would include not  just Windows  but most programs in the computer as well  For a programmer  many applications  are not considered part of the system  However  he would consider compilers  libraries  and other  programming tools as part of it  For a systems programmer  the software considered part of the  system might be even more constrained  We will get back to this later     This book aims to teach you how to effectively use the system  in many cases  we say just     system    to refer to the operating system   This means using the functions it provides  and the  programs and languages that come with it to let the machine do the job  The difference between  ignoring how to ask the system to do things and knowing how to do it  is the difference between  requiring hours or days to accomplish many tasks and being able to do it in minutes  You have to  make your choice  If you want to read a textbook that describes the theory and abstract concepts  related to operating systems  you may refer to  1      So  what is an operating system  It is just a set of programs that lets you use the computer   The point is that hardware is complex and is far from the concepts you use as a programmer   There are many different types of processors
178. 8   connected to tcp alboran 9988 on  net tcp 54  Echo echo      Echo echo      Delete    r       And this is what our server said in its standard output       8 netecho   announced tcp   9988 in  net tcp 52  accepted call at  net tcp 54  terminated call at  net tcp 54  accepted call at  net tcp 55  terminated call at  net tcp 55    The program is very simple  To announce our port  wait for call  and accept it  it has to call just  announce  listen  and accept  At that point  you have an open file descriptor that may be  used as any other one  You just read and write as you please  When the other end of the connec   tion gets closed  a reader receives an EOF indication in the conventional way  This means that  connections are used like any other file  So  you already know how to use them     Out program has one problem left to be addressed  When we connected to it using telnet   there was only one client at a time  For this program  when one client is connected and using the  echo  nobody else is attended  Other processes might connect  but they will be kept on hold wait   ing for this process to call Listen and accept  This is what is called a sequential server   because it attends one client after another  You can double check this by connecting from two  different widows  Only the first one will be echoing  The echo for the second to arrive will not be  done until you terminate the first client     A sensible thing to do would be to fork a new process for each client that 
179. 81   new  61   number  209   read  80   start of  201  line feed character  17  lines   print  195   unique  207  linker  31  list   access control  18   concatenation  181   directory  72    empty  182   file  72   indexing  181   null  182   process  101  list AWK script  219  list2grades rc script  224  list2usr  221  listen  148  listen  145  148   command  150  listenl  151  listen c  145  lists  access control  360  lists  rc  180       load  machine  101  system  126    loaded program  31  loader  21  32  program  32  loading  on demand  34  program  83  Local  164  local  address  142  disk  324  storage  357  local file  137  localtime  282  Lock  234  lock  232  234  contention  246  queueing  239  resource  234  spin  238  lock  234  lock c  234  locks  read write  244  logical  and  191  or  191  login  4  login  373  loging  into  4  out  4 6  logout  4  6  lookman  9  183  loop  server  334  loop  rc  186  lp  52  lr  207     14     lrusers  208  ls  10  69  72  flag  d  15  flag  1  31  flag  m  15  flag  s  11  lsdot c  71  lstk acid command  48  luck  good  232    M     m device driver  295  machine  load  101  owner  358  services  150  stand alone  357  start script  151  virtual  2  machines  357  MAF TER mount flag  169  magic  2  mail  135  server  151  ail  112  125  192  ain  35  49  83  ain active  163  ake  349  making calls  141  malicious person  357  malloc  34  69  355  man  9  manager  resource  2  manual  8  page  129  search  183  mask  302  m
180. 9   When all the threads in the process have terminated their main functions  or called  threadexits  the thread library will call exits to terminate the entire process  The exit sta   tus for the whole process is that given as a parameter to the last thread to exit  which is a reason   able behavior  By the way  there is a more radical function for exiting that terminates all the  threads in the process  it is called threadexitsall1 and is used in the same way     And is this is what we get for using threads instead of processes  The program will always  produce this output  although the order of prints may vary       263         6 tiner  cnt is 2  cnt is 4    And there are no races  When a thread starts executing  it will continue executing until it calls  threadexits  We did not call any function of the thread library  and there is no magic  There  is no way the thread could suffer a context switch in a bad moment  The program is safe  although  it does not use even a single lock  Of course  if a thread loops for a long time without giving  other threads the chance of running  the poor other threads will wait a very long time until they  run  But this is seldom the case     What if we modify the program as we did with the one with processes  You may think that  using a sleep may lead to a context switch  and expose a possible race condition  Although this  is not the case  let   s try it     tincr2 c  include  lt u h gt   include  lt libc h gt      include  lt thread h gt 
181. 94  0000000000000001 0 00  8192 936  dev cons  2w M 94  0000000000000001 0 00  8192 936  dev cons  3r C O  0000000000000002 0 00  0 0  dev cons  4w c O  0000000000000002 0 00  0 0  dev cons  5 w c O  0000000000000002 0 00  0 0  dev cons  6 rw   O  0000000000000241 0 00  65536 38    data  7 rw   O  0000000000000242 0 00  65536 85044698    datal  8 rw   O  0000000000000281 0 00  65536 0    data  9 rw   O  0000000000000282 0 00  65536 0    datal    You process has descriptors 0  1  and 2 open  as they should be  However  it seems that there are  many other ones open as well  That is why you cannot assume that the first file you open in your  program is going to obtain the file descriptor number 3  It might already be open  You better be  aware     There is one legitimate question still pending  After we open a file  how does read know  from where in the file it should read  The function knows how many bytes we would like to read  at most  But its parameters tell nothing about the offset in the file where to start reading  And the  same question applies to write as well     The answer comes from open  Each time you open a file  the system keeps track of a file  offset for that open file  to know the offset in the file where to start working at the next read or  write  Initially  this file offset is zero  When you write  the offset is advanced the number of  bytes you write  When you read  the offset is also advanced the number of bytes you read   Therefore  a series of writes wou
182. 9p  provided by the library   is a helper routine that fills r  gt ofcall data and r  gt ofcall count to read correctly  from a directory     But how can dirread9p know which entries are kept in the directory  That is  how can it  know what bytes should be read  A function  called here getdirent  and called dirgen by  the 9p 2  manual page  is given as an argument to dirread9p     What happens is that dirread9p calls get dirent to obtain the first entry in the direc   tory  then the second  then the third  etc  until it has enough entries to fill the Rread message in  r  gt ofcall  The parameter n of getdirent shows which file is the one whose directory  entry should be copied into  d by the function  Each call to getdirent  to a dirgen func   tion  must fill a Dir structure for the n th file in the directory  and return zero  Or it must return   1 to signal that there is no n th file in the directory  Another usual convention is that an index  of  1 given to a dirgen refers to the directory itself  and not to any of its entries  Although we  do not depend on that  we follow it as well  This is the implementation for getdirent     static int  getdirent  int n  Dir  d  void                       d  gt atime  time nil     d  gt mtime  d  gt atime    d  gt uid   estrdup9p  getuser       d  gt gid   estrdup9p  d  gt uid      d  gt muid  estrdup9p  d  gt uid      LE  n     d  gt qid    Qid  0  0  QTDIR    d  gt mode   0775   d  gt name   estrdup9p        d  gt length   0      else
183. Chet 2 lent  2    a   b        Figure 10 2  Incrementing a shared counter using an atomic increment operation  No races       233      Why is this so  Consider our two processes trying to increment the global counter  as shown  in figure 10 2  Imagine also that cnt   was a single instruction  One of the two processes is  going to execute cnt    before the other  It could happen what figure 10 2  a  shows  or what is  shown in 10 2  b   There is no other case  As we are assuming that this is an atomic  non divisi   ble  instruction  the increment is performed correctly  There can be no context switch in the mid   dle  Now  when the other process executes its cnt     it finds cnt already incremented  and no  increment is missed  There is no race  The only two possibilities are those depicted in figure 10 2     Of course  we do not know the order in which increments are going to be made  Perhaps  the parent in our program does its two increments  and then the child  or perhaps the other way  around  or perhaps in some interleaved way  No matter the order  the program will yield the  expected result if the increments are atomic  as we just discussed     The code where we are using a shared resource  which posses problems when not executed  atomically  is called a critical region  It is just a piece of code accessing a shared resource  A  context switch while executing within the critical region may be a problem  More precisely  the  problem is not having a context switch  but swi
184. Cliffs  New Jersey  2004    2  R  Pike  D  Presotto  K  Thompson and H  Trickey  Plan 9 from Bell Labs  EUUG Newslet   ter 10  3  Autumn 1990   2 11    3  R  Pike  Acme  A User Interface for Programmers  Proceedings for the Winter USENIX  Conference  1994  223 234  San Francisco  CA     4  R  Pike  How to Use the Plan 9 C Compiler  Plan 9 Programmer   s Manual  AT amp T Bell  Laboratories  Murray Hill  NJ   1995    5  B  W  Kernighan and R  Pike  The practice of programming  Addison Wesley  1999    6  P  Winterbottom  Acid Manual  Plan 9 Programmer   s Manual  AT amp T Bell Laboratories   Murray Hill  NJ   1995    7  R  Pike  D  Presotto  K  Thompson  H  Trickey and P  Winterbottom  The Use of Name  Spaces in Plan 9  Operating Systems Review 25  2  April 1993        8  A  G  Hume and B  Flandrena  Maintaining files on Plan 9 with Mk  Plan 9 Programmer   s    Manual  AT amp T Bell Laboratories  Murray Hill  NJ   1995     Index      139    386  172   5c  97   51  97   9P  62  159  325  file  327  implementation  336  library  332  message handler  334  request  325  336  security  360  server  325   S    180   S   180      159  166    command  188   _main  49   5c  21 351   Si  2l   8c  21   81  21  flag  o  22   8 out  21  partition  322   9fs  137  139   rc script  161  163   messages  325   9P2000  326   9PANY  363   9PSK1  363   S address  195     command  190    amp  amp  command  191       command  191      device driver  166       device driver  225     file names  166  
185. F  end of file  character  Such thing is an invention of some programming lan   guages  For Plan 9  the file terminates right after the last byte that has been stored on it     Another interesting control character is the tabulator  generated pressing the Tab key in the  keyboard  It is used in text files to cause editors and terminals to advance the text following the  tabulator character to the next tab stop  On typewriters  sorry once more   the carriage could be  quickly advanced to particular columns  called tab stops  by hitting a Tab key  This control char   acter achieves the same effect  Of course  there is no carriage any more and Tab advances to  say   the next column that is a multiple of 8  column 8  16  etc    This value is called the tab width   The file scores contains several tabs       cat scores    Real Madrid 1   Barcelona 0     xd  c scores   0000000 R e a 1 M a d r i d  t 1 n B a  0000010 E     e 1     na  t O  n   000001a    Note how in the output for cat  the terminal tabulates the scores to form a column after the  names  The number 0 is shown right below the number 1  However  the output from xd reveals  that there are no spaces after Madrid and Barcelona  Following each name  there is a single   t character  which is the notation for Tab  In general   t is used to tabulate data and to indent  source code  The appearance of the output text depends on the tab width used by the editor or the  terminal  which was 8 characters in our case   The net effec
186. Introduction to Operating Systems Abstractions    he    d    Using Plan 9 from Bell Labs     Draft     9 28 2007     Francisco J Ballesteros    Copyright    2006 Francisco J Ballesteros  Plan 9 is Copyright    2002 Lucent Technologies Inc  All Rights Reserved     Preface    Using effectively the operating system is very important for anyone working with computers  It can    be the difference between performing most tasks by hand  and asking the computer to perform them     Traditionally  Operating Systems courses used UNIX to do this  However  today there is no such  thing as UNIX  Linux is a huge system  full of inconsistencies  with programs that do multiple tasks and do  not perform them well  Linux manual pages just cannot be read     These lecture notes use Plan 9 from Bell Labs to teach a first  practical   course on operating sys   tems  The system is easy to use for programmers  and is an excellent example of high quality system design  and software development  Studying its code reveals how simplicity can be more effective than contortions  made by other systems     The first Operating Systems course at Rey Juan Carlos University is focused on practice  Because in  theory  theory is like practice  but in practice it is not  What is important is for you to use the system  and  to learn to solve problems  Theory will come later to fill the gaps and try to give more insight about what a  system does and how can it be used     The whole text assumes that you have been al
187. K Wakeme genrandom  nemo 3 0 00 0 00 OK Wakeme alarm  nemo 9 0 00 0 00 OK Wakeme rxmitproc    Is  1     c          rw rw r   c 0 nemo nemo 24 May 23 17 44   c bintime         rw rw     c 0 nemo nemo 0 May 23 17 44   c cons       w  w     c 0 nemo nemo 0 May 23 17 44   c consctl       r  r  r   c 0 nemo nemo 72 May 23 17 44   c cputime         r  r  r   c 0 nemo nemo 0 May 23 17 44   c drivers       This can be double checked by changing the host owner  which is usually a bad idea       359           echo  n pepe  gt  dev hostowner we seta new host owner     p lig al FO       rw rw r   c 0 pepe pepe 24 May 23 17 44   c bintime           rw rw     c 0 pepe pepe 0 May 23 17 44   c cons          w  w     c 0 pepe pepe 0 May 23 17 44   c consctl       echo  n nemo  gt  dev hostowner _    and now restore the original one    The host owner can do things like adjusting permissions for files in  proc  which are owned by  him  There is nothing that prevents this user from adding permissions to post notes  for example   to kill processes       ls  1  proc Spid note     rw r      p 0 nemo nemo 0 May 23 17 44  proc 1235 note    chmod atw  proc Spid note     ls  1  proc Spid note     rw rw  w  p 0 nemo nemo 0 May 23 17 44  proc 1235 note    The truth is that users do not exist  For the system  processes are the ones that may perform  actions  There is no such thing as a human  For example  the human using the window system is  represented by the user name of the process es  implementing th
188. M 00 13 00 00 00 00 00 00 00 00 cO al 01  0000010 00 00 00 00 00 a4 01 00 00   Ibi  D   Ibi    0000020 D 00 00 00 00 00 00 00 00 07 00 a n o t h  0000030 e r 04 00 n e m o 04 00 n e m o 04 00  0000040 n e m o B 00 M 00 13 00 00 00 00 00 00 00  0000050 00 bf al 01 00 00 00 00 00 a4 01 00 00  r I bl  0000060 D r T pT D 00 00 00 00 00 00 00 00 07 00 o  0000070 ne f i 1 e04 00 n e  m oo 04 00 ni e  0000080 m o 04 00 n e m o   0000088    When programming in C  there are convenience functions that convert this portable  but not  amenable  data structure into a C structure  The C data type declared in 1ibc  h that describes a  directory entry is as follows       69      typedef  struct Dir       system modified data     ushort type     server type          uint dev     server subtype         file data      Qid qid     unique id from server     ulong mode     permissions      ulong atime     last read time      ulong mtime     last write time     vlong length     file length      char  name     last element of path     char  uid     owner name      char  gid     group name      char  muid     last modifier name         Dir     From the shell  we can use 1s to obtain most of this information  For example       ls  Im onefile   nemo  rw r  r M 19 nemo nemo 0 Jul 9 19 24 onefile          The file name is onefile  The field name within the directory entry is a string with the  name  Just with the name  An absolute path to refer to this file would include all the names  from that of the r
189. Read rfc821 and stop wasting my time   Delete    We gave the option  r to telnet  to ask it not to print carriage return characters  its protocol  uses the same convention for new lines used by DOS   When telnet connected to the address we  gave  it printed a diagnostic message to let us know  and entered a loop to send the text we type   and to print the text it receives from the other end  Our mail server wrote a salutation through the  connection  the line starting 220      and then we typed help  which put our mail server into a  bad mood  We interrupted this program by hitting Delete in the terminal  and the connection was  terminated when telnet died  A somewhat abrupt termination     It is interesting to open several windows  and connect from all of them to the same address   Try it  Do you see how each telnet is using its own connection  Or  to put it another way  all  the connections have the same address for the other end of the connection  yet they are different  connections    To name a connection  it does not suffice to name the address for one of its ends  You must    give both addresses  for the two ends  to identify a connection  It is the four identifiers local  address  local port  remote address  and remote port  what makes a connection unique       139      It is very important to understand this clearly  For example  in our telnet example  you  cannot know which connection are you talking about just by saying    The connection to  tcp 1lsub org smtp     T
190. S R e s e rv e d n  000003f    Here we see how the value 0x43 represents the character    C     If you look after the text  Copyright  you see 0xc2 0xa9  which is the UTF 8 representation for the          sign  This pro   gram does not know and all it can do is print the byte values     Another interesting thing is shown near the end of each line in the file  After the text in the  first line  we see a     n     That is a byte with value 0x0a  The same happens at the end of the sec   ond line  the last line in the file   The syntax     n    is used to represent control characters  i e    characters not to be printed as text  The character  n is just a Ox0a byte stored in the file  but xd  printed it as  n to let us recognize it  This systax is understood by many programs  like for exam   ple the C compiler  which admits it to embed control characters in strings  like in  hello n       Control characters have meaning for many programs  That is way they seem to do things    SATS     but of course they do not    For example      n    is the new line character  It can be generated  using the keyboard by pressing the Return key  When printed  it causes the current line to termi   nate and the following text will be printed starting at the left of the next line     If you compare the output of xd and the output of cat you will see how each one of the  two lines in  NOTICE terminates with an end of line character that is precisely  n  That is the  convention in Plan 9  and UNIX   Th
191. You know what fork and exec do  That must take time  Processes  are cheap  but not free  Wouldn   t it be better to use a single bc to do all the computation  and  then adjust the output  For example  this command  using our last version for d2h  produces the  same output  The final sed command inserts some text at the beginning and at the end of each  line  to get the desired output       seq 1 255   d2h   sed  e    s    0x       e    s S        0x0     roxi     0x2 my     and many others follow     To see the difference between this command line  and the direct for loop used above  we can use  time to measure the time it takes to each one to complete  We placed the command above using  a for into a  tmp for script  and the last command used  using sed  at a script in   tmp sed  This is what happen     time  tmp sed  gt  dev null    0 34u 1 63s 5 22r  tmp sed    time  tmp for  gt  dev null  3 64u 24 38s 74 30r  tmp for    The time command uses the wait system call to obtain the time for its child  the command we  want to measure the time for   It reports the time spent by the command while executing user  code  the time it spent while inside the kernel  executing system calls and the like  and the real   elapsed  time until it completed  Our loop  starting several processes for each number being pro   cessed  takes 74 3 seconds to generate the output we want  That is admittedly a lot shorter than  doing it by hand  However  the time needed to do the same using sed as a final
192. ack was the source image     The source image represents the color black  because it is an image with all its pixels in that  color  Although we could draw the entire screen by copying black pixels from  display  gt black  this image is not that large  Images that have their rep1 field set to true are  used as tiles  The implementation for draw tiles the image as many times as necessary to fill the  rectangle where it is to be drawn  So  display    gt black might have just one black pixel  Only  that before copying any pixel from it  draw replicated it to obtain an image of the appropriate  size     The second parameter is the rectangle where to confine the drawing of the source in the tar   get  This is called a clip rectangle  because no drawing occurs outside it  The program used  screen     gt r  and so it draws in the screen the whole rectangle used by screen  Drawing ina  target image will not draw outside that image  Thus  the drawing is confined to the intersection of  the target image   s rectangle and the rectangle given to draw  In this case  we draw in the inter   section of screen     gt r  the target   s rectangle  and screen     gt r  the parameter for draw   That  is  of course  just screen     gt r     The image for the screen uses real screen coordinates  In other cases  you may have images  that do not use screen coordinates  To draw one of these images you must translate the coordi   nates for the source so that they match the area in the target where you 
193. acter is an option      echo a b c   tr  a XA   tr  bad option  But this can be fixed reversing the order for characters in the argument       eCho  a b c J Or a  AX    AXbXc    Now we can get back to our h2d tool  and modify it to supply just upper case hexadecimal digits  to bc     h2d     bin re    echo    ibase 16     echo print  1   tr a f A F      be    The new h2d version works as we could expect  even when we use lower case hexadecimal dig   its       186        h2d abc  2748    Does it pay to write h2d and d2h  Isn   t it a lot more convenient for you to use your desktop cal   culator  For converting just one or two numbers  it might be  For converting a docen or more  it  is for sure it pays to write the script  The nice thing about having one program to do the work is  that we can now use the shell to automate things  and let the machine work for us     8 4  Real programs    Our programs h2d and d2h are useful  for a casual use  To use them as building blocks for doing  more complex things  more work is needed  Imagine you need to declare an array in C  and ini   tialize it  to use the array for translating small integers to their hexadecimal representation     char  d2h         0x00     Ox1ll       Ose          To obtain a printable string for a integer i in the range 0 255 you can use just d2h i   Would  you write that declaration by hand  No  The machine can do the work  What we need is a com   mand that writes the first 256 values in hexadecimal  and adjust the
194. ain  the user id  of the host owner  and its secret in non volatile RAM or nvram  Here  nvram is just an abstrac   tion  usually implemented using a partition called nvram in the hard disk  When a server  machine is installed  it is supplied with the information needed to authenticate  The program  auth wrkey prompts for such information and stores it in the nvram  From that point on  the  machine can boot unattended  This is very convenient  specially when considering that CPU  servers tend to reboot by themselves when they loose the connection to the file server     There is another place where keys are kept  The nvram for the server machines would suf   fice  because each user knows the relevant password and can perfectly type it to the factotum  used when needed  However  users tend to have so many keys these days that it would be a bur   den for the user to have to type all of them whenever they are needed     The program secstore provides  so called  single sign on to the system  A single sing on  facility is one that allows a user to give just one password  to sign on just once   After that  the  user may just access any of the services he is authorized to use without providing any other  secret     The secstore is a highly secure file server  it uses strong encryption algorithms  that  may store files for each user  The storage used by the secstore is encrypted using the host  owner key  Besides  to prevent the host owner from accessing the secure files for a user  th
195. aiting for the data to arrive   However  from time to  time  there will be some processes with a high demand of CPU time  like for example  a compiler  trying to compile a program  and the system load will increase because there   s now some process  that is often ready to run  or running     We can use the st ats tool to display the system load  This tool shows a graphic depicting  the system load and other statistics  For example  both figures 5 6 and 5 7 show a window run   ning stats  Figure 5 6 shows the system load for our first experiment regarding polling  It is  hard to see in a book  but the graph displayed by stats is always scrolling from right to left as  time goes by  Around the middle of the graph it can be seen how the load increased sharply  and  went to a situation where almost always there was something to do  The system started to be  heavily loaded  This was the result of executing the following       8 poll polise   and the machine got very busy until we hit Delete  Delete    r    nautilus    adom    Figure 5 6  A window running stats while the intensive polling program increased the load     The process 8 pol1 was always polling for a change on its file  Therefore  there was always  something to do  Despite being run on a very fast machine  8  po11 never ceased to poll  When  the system decided that 8 po11 got enough processor time  and switched to execute any other  process  our polling process ceased to poll for a tiny fraction of time  Later on  it w
196. al      rw r  r   M 19 nemo nemo 328 Jul 6 23 06 global 8    Clearly  there is no room in the 328 bytes of the object file for the global array  which needs  one megabyte of storage  The explanation is that only the size required to hold the  not initial   ized  array is kept in the file  The binary file does not include the array either  change the array  size  and recompile to check that the size of the binary file does not change      When the shell asks the system  making a system call  to execute 8  global  the system  loads the program into memory  The part of the system  kernel  doing this is called the loader   How can the system load a program  By reading the information kept in the binary        The header in the binary file reports the memory size required for the program text  and the  file keeps the memory image of that text  Therefore  the system can just copy all this into  memory  For a given system and architecture  there is a convention regarding which  addresses the program must use  Therefore  the system knows where to load the program        The header in the binary reports the memory size required for initialized variables  globals   and the file contains a memory image for them  Thus  the system can copy those bytes to  memory  Note that the system has no idea regarding where does one variable start or how  big it is  The system only knows how many bytes it has to copy to memory  and at which  address should they be copied        For uninitialized globa
197. all  In fact  the machine might be diskless     network       ommand execution  vhs    Command execution   Window system            Files     network  Lae Accounts         Figure 1 1  You terminal provides you with a window system  Your files are not there     There is one reason for doing this  Because your terminal does not keep state  i e   data in your  files   it can be replaced at will  If you move to a different terminal and start a session there  you  will see the very same environment you saw at the old terminal  Because terminals do not keep  state  they are called stateless  Another compelling reason is that the whole system is a lot easier  to administer  For example  none of the terminals at the university had to be installed or cus   tomized to be used with Plan 9  There is nothing to install because there is no state to keep within  the terminal  remember     Your files are kept at another machine  called the file server  The reason for this name is  that the machine serves  i e   provides  files to other machines in the network  In general  in a     4     network of computers  or programs  a server is a program that provides any kind of service  e g    file storage   Other programs order the server to perform operations on its files  for example  to  store new files or retrieve data  These programs placing orders on the server are called clients  In  general  a client sends a message to a server asking it to perform a certain task  and the server  replies back
198. aller of wait is  responsible for releasing this memory     Another detail is that the routine updates the process error string in the parent process when  the child fails  That is where the caller program expects to find out the diagnostic for a failed  sys   tem  call     In this case we know that there is at least one child  and wait cannot return nil  The con   vention in Plan 9 is that an empty string in the exit message means    everything ok     That is the     96     information returned by run  The field m in the Waitmsg contains a copy of the child   s exit  message     This code still has flaws  The program that calls run might have created another child  before calling our function  In this case  it is not sure that wait returns information about the  child it created  This is a better version of the same function    int  run char  cmd  char  argv            Waitmsg  m   int ret   int pid     pid   fork      switch  pid      case  1   return  1    case 0     child  exec cmd  argv    sysfatal  exec  Sr       default   while m   wait       if  m  gt pid    pid     if  m  gt msg 0     0   ret   0   else      werrstr m  gt msg     ret    1        free m     return ret     free  m           The routine  when executed by the parent process  makes sure that the message comes from the  right  death  child  Its manual page should now include a warning stating clearly that this routine  waits for any child until the one it creates is waited for  Callers must know this  Othe
199. am calls the function blank that draws the  entire window in black       304      resize c    include  lt u h gt    include  lt libc h gt    include  lt thread h gt    include  lt draw h gt    include  lt mouse h gt       code for blank  resizethread  and mousethread       void  threadmain int  char argv          Mousect1l mctl     Mouse m    mctl   initmouse   dev mouse   nil     if  mctl    nil   sysfatal  initmouse   r      if initdraw nil  nil  argv 0    lt  0     sysfatal  initdraw   r     threadcreate resizethread  mctl  8 1024    threadcreate  mousethread  mctl  8 1024    blank      threadexits  nil                 Try running the program 8  b1lack and using the arrow keys to scroll up down the window  It  scrolls  Rio thinks that nobody is using graphics in the window  That does not happen to  8  resize  which keeps the mouse file open     The implementation for blank is taken from our previous program  It draws the entire win   dow image in black and flushes the draw operations to the actual device    void   blank  void       draw screen  screen  gt r  display  gt black  nil  ZP    flushimage  display  1          Mouse processing for our program is simple  Any button click terminates the program  But users  expect the action to happen during the button release  and not during the previous press  There   fore  mousethread loops receiving mouse events  When a button is pressed  the function reads  more events until no button is pressed  At that point  closedisplay term
200. ame  The group that contains just you as the only member  This is the output of  1s when called to print long listing for a file  It list permissions and ownership for the file    a gt  Ca    ls  1 lib profile      rwxrwxr x M 19 nemo nemo 1024 May 30 16 31 lib profile    r    You see a user name listed twice  The first name is the owner for the file  It is nemo in this case   The second name is the user group for the file  which is also nemo in this case  This group con   tains a single user  nemo      19     The initial           printed by 1s indicates that the file is a not a directory  For directories  a    qa     would be printed instead  The following characters show the ACL for the file  i e   its permis   sions     There are three groups of rwx permissions  each one determining if the file can be read  r    written  w  and executed  x   The first rwx group refers to the owner of the file  For example  if r  is set on it  the owner of the file can read the file  As you see for lib profile  nemo  its  owner  can read  write  and execute this file     The second rwx group determines permissions applied to any other user who belongs to the  group for the file  In this case the group is also nemo  which contains just this user  The last rwx  group sets permissions applied to any other user  For example  esoriano can read and execute  this file  but he cannot write it  The permissions for him  not the owner  and not in the group  are  r x  which mean this     Because it do
201. ame is sent in the Tattach  request  As you know  the attach operation gives a handle  a fid  to the client attaching to the file  system  This permits the file server to identify the user responsible for operations requested on  that fid  When new fids are obtained by walking the file tree  the file server keeps track of which  user is responsible for which fids     Access control  that is  deciding if a particular operation is to be allowed or not  is per   formed by the file server when a user opens a file  walks a directory  and tries to modify its  entries  including creating and removing files   When a process calls open on a file  the system  sends a Topen request to the file server providing the file  At this point  the file server takes the  user name responsible for the request and decides whether to grant access or not  You know   from the first chapter  that this is done using per file access control lists  that determine which  operations can be performed on which file  Once a file has been open for a particular access  mode  reading  writing  or both   no further access control check is made  The file descriptor   or  the fid for that matter  behaves like a capability  a key  that allows the holder to perform file  operations consistent with the open mode     These are all the elements involved in securing access to files  but for an important one  It is  necessary to determine if the user  as identified for a file server  is who he or she claims to be   Users c
202. amp b  gt 1ck     To play with our implementation  we are going to create two processes the produce messages and  two more process that consume them and print the consumed ones to standard output  Also  to  exercise the code when the buffer gets full  we use a ridiculous low size       254          include  lt u h gt      include  lt libc h gt     enum  Nmsgs   4          definitions for Buffer  put  get  and init here       void  producer  Buffer  b  char id        char msg 20      int Ty    forn  i SOS  ay  lt  lt   D EE  seprint  msg  msg 20   Sc Sd   id  i    put  b  msg         put  b  nil      exits  nil      void  consumer  Buffer  b      chars msg   while  msg   get  b      print   s    msg    free  msg       exits  nil         Buffer buf     void  main int  char         init   amp buf    if  rfork  RFPROC RFMEM RFNOWAIT        producer   amp buf   a       if  rfork  RFPROC RFMEM RFNOWAIT        producer   amp buf   b       if  rfork  RFPROC RFMEM RFNOWAIT        consumer   amp buf          else             consumer   amp buf            The producers receive a letter as their name  to produce messages like a0  al  etc   and bO  b1   etc  To terminate the program cleanly  each producer puts a final nil message  When a consumer  receives a nil message from the buffer  it terminates  And this is the program output       255      i 6p  a0 bO al bl a2 b2 a3 b3 a4 b4      As you can see  messages are inserted in a very fair way  Changing a little bit put  and get   would le
203. an  i e   the file  it is working  with refers to the file  n ram  Plan 9 needs to be able to compare two Chans for equality  that  is  to determine if they refer to the same file     To help with this  other type of file identifiers  called qids  univocally identify files within a  file server  All 9P file servers promise that each file will be assigned an unique number  called its      328      qid  Furthermore  a gid used for a file will not be used for any other file even after the file is  removed  So  two files with the same qid within the same file server are the same file  Otherwise   files are different     Each Chan contains the qid for the file it refers to  In our 9P dialog  the Ratt ach message  sent a qid back to the client  and Plan 9 knows which qid corresponds to the   of our ramfs file  tree  If you look back to see the Dir data structure returned by dirstat  with attributes for a  file  you will see that one of the fields is a Qid     We said that a qid is a number  But a qid is indeed a tiny structure that contains three num   bers     typedef   struct Qid      uvlong path   ulong vers   uchar type      Qid     The path field is the actual value for the qid  the unique number for the file within its file server   Beware  this is not a string with a file name  but it identifies a file in the file server and that is the  reason for calling it path  The vers field is a number that represents the version for the file  It  is incremented by the file server when
204. an lie  This operation is called authentication  Authenticating a user means just obtain   ing some proof that the user is indeed the one identified by the user name  Most of the machinery  provided for security by Plan 9 is there just to authenticate users     And here comes the problem  In general  the way a program has to convince another of  something is to have a secret also known to the other  For example  when an account is open for a  user in a Plan 9 environment  the user must go near the console of a server machine and type a  password  a secret  The same secret is later typed by the same user at a terminal  Because the      361      terminal and the server machine share the same secret  the sever can determine that the user is  indeed who typed the password while opening the account  Well  indeed  the server does not  know if the password is also known by another user  but the server assumes this would not hap   pen     Authentication is complex because it must work without trusting the network  There are  many different protocols consisting on messages exchanged in a particular way to allow an end of  a connection to authenticate the other end  without permitting any evil process spying or inter   cepting network messages to obtain unauthorized access  Once more  we do not cover this subject  in this book  For use  the important point is that there are multiple authentication protocols  and  that there is an interface provided by the system for this purpose     Th
205. and sets the processor flag to reflect if the previous  value was not zero or was zero     In this loop  if a process is trying to set the lock and finds that it was set  TAS will set an  already set lock  store 1 in the lock that already was 1   and that operation would be harmless  In  this case  TAS would report that the lock was set  and the process would be held in the loop wait   ing for the lock to be released  On the other hand  if the process trying to set the lock executes  TAS while the lock was not set  this instruction will both set the lock and report that it was clear   When more than one process call Lock     one of them is going to run TAS first  That one wins     To play with locks a little bit  we are going to implement a tiny program  This program has  two processes  One of them will always try to increment a counter  The other  will be trying to  decrement it  However  we do not allow the counter to be negative  If the process decrementing      236      the counter finds that the value is zero  it will just try again later  Once per second  one of the pro   cesses prints the counter value  to let us see what is happening    In the program  we print in boldface statements that are part of a critical region  As you can  see  any part of the program where cnt is used is a critical region  Furthermore  note that even  print is in the critical region if it is printing cnt  because we do not want cnt to change in the  middle of a print     cnt c          includ
206. anges the name space for the plumber  Afterwards  if we plumb   n whale NOTICE the plumber will see that file and there will be no problem              Is the problem solved  Maybe  After an editor is running at a different window  receives the  plumb message for  n whale NOTICE  it will not be able to open this file  because its name  space is also different  In general  this is not a problem at all  provided that you understand how  you are using your name spaces              Another consequence of the per process name spaces and the plumbing tool is that you can  isolate an editor regarding plumbing  Just do this       plumber    acme    and the Acme will have its own set of plumbing files  Those files are supplied by the plumber that  you just started  which are different from the ones in use before executing these commands     7 7  Device files    If you understood the discussion in the last section  this is a legitimate question  How could my  name space get anything mounted in the first place  To do a mount  you must have a file where to  mount  That is  you need a mount point  Initially  your machine is not even connected to the file  server and you have just what is inside your machine  You must have something that you could  mount at   in the first place     Besides  you must be able to use your devices to reach the file server  This includes at least  the network  and maybe the disk if you have your files stored locally in a laptop  In Plan 9  the  interface for us
207. ans just that a full set of processor registers  is initialized for the new running program  including the program counter and stack pointer  along  with an initial  almost empty  stack  When we compile a C program  the loader puts main at the  address where the system will start executing the code  Therefore  our C programs start running at  main  The arguments supplied to this program  e g   in the shell command line  are copied by  the system to the stack for the new program     The arguments given to the main function of a program are an array of strings  the argu   ment vector  argv  and the number of strings kept in the array  We can write a program to print  its arguments     echo c   include  lt u h gt      finclude  lt libc h gt           void  main int argc  char  argv            int a  for  i   0  i  lt  argc  itt   print   Sd  s n    i  argv i l      exits  nil           If we execute it we can see which arguments are given to the program for a particular command  line       8c  FVw echo c  81  o 8 echo echo 8    8 echo one little program    8 echo   one   little   program     e    WNE OS    T    There are several things to note here  First  the first argument supplied to the program is the pro   gram name  More precisely  it is the command name as given to the shell  Second  this time we  gave a relative path as a command name  Remember    8 echo  is the file 8   echo within the  current working directory for our shell  which is a relative path  And that was the 
208. ap different qids to different files     In semfs  there is a flat  root  directory that may contain files representing semaphores   The qid for the directory must have QTDIR set in its type field  Having just one directory  we  may use Qid type to see if a qid refers to the root or to any other file in our tree  The path  field for the qid  i e   the actual qid number  may be just zero  as the version field  Therefore  this  is what fstattach does           r  gt fid  gt qid    Qid  0 0 QTDIR    r  gt ofcall qid   r  gt fid  gt qid     The fid represented by r  gt fid  the one mentioned by the Tattach  now refers to the root  directory of our tree  The response message carries the qid back to the client  That is all we had to  do     We still must invent a scheme for assigning qids to files representing semaphores  A simple  way is to keep all the semaphores in a single array  and use the array index as the Qid path for  each file  Given a qid  we would know if it is the directory or a file  Should it be a file   Qid path would be the unique index for each semaphore in the array     13 6  Semaphores    What is a semaphore  For our server  it is just an instance of a Sem data structure  We can place  in sem h its declaration and all the definitions needed to use the implementation for semaphores   that we may keep at sem c  The file semfs  c is kept just with the implementation for the dif   ferent file server requests     The structure Sem needs to keep the number of tickets
209. ar that it  should probably be delivered to a web browser  If a message looks like pnote c 15  then it is  likely that it should be delivered to an editor  to open that file and show the line after the colon     Like many other programs  the plumber is used through a file interface  The files that make  up the interface for the plumber are usually available at  mnt  plumb       Ic  mnt plumb    edit msntalk rules showmail  exec msword seemail song  image none send voice  man postscript sendmail www    Each one of these files  but for rules and send  is called a port  and can be used to dispatch  messages to applications reading from them  The send file is used to send a message to the  plumber  which will choose an appropriate port for it and then deliver the message to any process  reading from it     For example  figure 5 8 shows what would happen when a process writes to the send port  a message carrying the data http    1lsub org   Because the data looks like something for a  www port  the plumber delivers the message to any process reading from that port  If more than  one process is reading from the port  as shown in the figure for images   the message is delivered  to all of them     Even if you didn   t notice  you have been using the plumber a lot  Every time you click with  the mouse button 3 at something in Acme  the editor sends a message to the plumber with the text  where you did click  Most of the times  the plumber determines that the message is for processes 
210. are stored in the directory in a portable  machine independent  and not amen   able  format  Therefore  instead of using read  it is more convenient to use dirread  This  function calls read to read the data stored in the directory  But before returning to the caller  it  unpacks them into a  more convenient  array of Dir structures     As an example  the next program lists the current directory  using dirread to obtain the  entries in it     Running the program yields the following output  As you can see  the directory was being  used to keep a few C programs and compile them       8 isdot  8 1sdot  create 8  create c  lsdot 8  lsdot c    r    mor Mle       Isdot c     include  lt u h gt      include  lt libc h gt     void  main int   char                 Dir  dents    int ndents  fd  i   fd   open      OREAD    if  fd  lt  0     sysfatal  open  Sr     for       ndents   dirread fd   amp dents    if  ndents    0   break   for  i   0  i  lt  ndents  itt   print   Ss n   dents i  name     free  dents         exits nil           The array of directory entries is returned from dirread using a pointer parameter passed by ref   erence  We know  C passes all parameters by value  The function receives a pointer to the  pointer   Such array is allocated by dirread using malloc  like before  Therefore  the caller  must call free  once  to release this memory  The number of entries in the array is the return  value for the function  Like read would do  when there are no more entries to
211. ariables  Therefore  the size of the program when loaded into memory will be  even larger  To know how much memory a program will consume  use nm  do not list the binary  file     The memory of a loaded program  and thus that of a process  is arranged as shown in figure  2 3  But that is an invention of the operating system  That is the abstraction supplied by the sys   tem  implemented using the virtual memory hardware  to make your life easier  This abstraction  is called virtual memory  A process believes that it is the only program loaded in memory  You  can notice by looking at the addresses shown by nm  All processes running such program will  use the same addresses  which are absolute  virtual  memory addresses  And more than just one  of such processes might run simultaneously in the same computer     The virtual memory of a process in Plan 9 has several  so called  segments  This is also an  abstraction of the system and has few to do with the segmentation hardware found at some popu   lar processors  A memory segment is a portion of contiguous memory with some properties   Segments used by a Plan 9 process are        The text segment  It contains instructions that can be executed but not modified  The hard   ware is used by the system to enforce these permissions  The memory is initialized by the  system with the program text  code  kept within the binary file for the program        The data segment  It contains the initialized data for the program  Protection is se
212. around 198  More tools 201  9 1  Regular expressions 201  9 2  Sorting and searching 205  9 3  Searching for changes 210  9 4  AWK 214  9 5  Processing data 219  9 6  File systems 224  Concurrent programming 229  10 1  Synchronization 229  10 2  Locks 232  10 3  Queueing locks 239  10 4  Rendezvous 246  10 5  Sleep and wakeup 248  10 6  Shared buffers 252  10 7  Other tools 255  Threads and Channels 261    11 1  Threads 261    12     13     14     11 2   11 3   11 4   11 5   11 6     12 1   12 2   12 3   12 4   12 5   12 6   12 7   12 8   12 9     13 1   13 2   13 3   13 4   13 5   13 6   13 7   13 8   13 9     14 1   14 2   14 3   14 4   14 5   14 6   14 7   14 8     Thread names   Channels   I O in threaded programs  Many to one communication  Other calls    User Input Output    Console input  Characters and runes  Mouse input  Devices for graphics  Graphics   A graphic slider  Keyboard input  Drawing text   The window system    Building a File Server    Disk storage   The file system protocol  Semaphores for Plan 9  Speaking 9P   9P requests   Semaphores   Semaphores as files   A program to make things  Debugging and testing    Security    Secure systems   The local machine   Distributed security and authentication  Authentication agents   Secure servers   Identity changes   Accounts and keys   What now     289    321    357    264  269  274  277  285    289  292  295  298  300  303  309  312  313    321  325  331  332  336  338  341  349  354    357  358  359  362  368  3
213. art to implement semfs  To attend 9P messages  we must imple   ment several functions and place pointers to them in a Srv structure  All the functions correspond  with 9P requests  but for fswalk1 and fsclone  used by the library to implement walk  and  for freefid  which will be addressed later  Given this structure  it is simple to construct a file  server by using postmountsrv  or its version for programs using the thread library                    threadpostmountsrv    semfs c  include  lt u h gt   include  lt libc h gt   include  lt auth h gt     required by 1ib9p  include  lt thread h gt   include  lt fcall h gt     required by 1ib9p  include  lt 9p h gt     definitions for lib9p  include  sem h     our own definitions                                  static void fsattach Req  r           static void fscreate Req  r           static void fsread Req  r          static void fswrite Req  r          static char  fswalkl Fid  fid  char  name  Qid  qid          static char  sclone Fid  fid  Fid  newfid          static void fsstat Req  r          static void fsremove Req  r          static void freefid Fid  fid          static Srv sfs       attach   fsattach    create   fscreate    remove   fsremove    read   fsread    write   fswrite    walkl   fswalkl    clone   fsclone    stat   fsstat    destroyfid  freefid       void  usage  void      fprint 2   usage   s   D    s srv    m mnt  n   argv0    threadexitsall   usage        void  threadmain int argc  char   argv      char  mn
214. as expected         xrforkls  rforkls c  rforkls 8  8 rforkls    r    But let   s change the call to rfork with this other one  rfork  RFCFDG RFREND   RFPROC        and try again    8 rforkls  Nothing     The explanation is that RFCFDG provided a clean file descriptor table  or group  to the child  process  Because standard output was not open in the child  1s could not print its output       155      Furthermore  because its standard error was closed as well  it could not even complaint about it   Now we are going to do the same  to our own process   rforkhi c      include  lt u h gt    include  lt libc h gt     void   main int  char argv         print   hi n     rfork  RFCFDG     print   there n          exits  nil           This produces this output    8 rforkhi   gt  hi  The second message was not shown  The RFCFDG flag to rfork asks for a clean file descriptor    set  group   This works like in the previous program  but this time we did not specify RFPROC  and therefore  the request was applied to our own process     7 2  Protecting from notes  The note group is shared by default when doing a fork  because no flag is specified regarding  this resource  This means that when we run our program in a window  pressing Delete in the win   dow will kill our process  The window system posts an interrupt note to the note group of the  shell in the window  and our process is a child of the shell  sharing its note group    This may be an inconvenience  Suppose we are implementing a
215. at a different file  as happen to  n whale  If  there is no such entry  the walk continues through the file tree  as expected     As a convenience  the program srv can mount a 9P file server  besides dialing its address  and posting the connection file descriptor at  srv  The following command line dials  tcp whale  9fs  like before  but it also mounts that connection at  n whale  like we did   The file created at  srv is named by the second parameter       srv tcp whale 9fs whale  n whale  post        lc  srv whale   whale    d    By convention  there is a script called  bin 9fs  that accepts as an argument the file system to  mount  It is customized for each local Plan 9 installation  Therefore  looking into it is a good way  of finding out which file servers you have around  This command achieves the same effect of the  previous command line  when used at URJC       9fs whale  POSET    r    We have added new files to our file tree  by mounting a remote file tree from a 9P file server into  a directory that we already had  The mechanism used was a translation going from one file to  another  When we have two files in our file tree  the same mechanism can be applied to translate  from one to another  That is  we can ask our name space to jump to a file already in our tree  when we reach another that we also have in the tree  A mount for two files already in the tree is  called a binding     The system call  and the shell command  used to do a bind is bind  For example      b
216. at match the previous  regexp  Itis like    but there has to be at least one match  For example  x  does not match  the empty string  but it matches every other thing matched by x         Adding a   after a regular expression  matches either the empty string or one string match   ing the expression  For example  x  matches x and the empty string  This is used to make  parts optional        Different expressions may be surrounded by parenthesis  to alter grouping  For example    ab    matches ab  abab  etc        Two expressions separated by   match anything matched either by the first  or the second  regexp  For example  ab   xy matches ab  and xy        A backslash removes the special meaning for any character used for syntax  This is called a  escape character  For example    is not a well formed regular expression  but     is  and  matches the string    To use a backslash as a plain character  and not as a escape  use the  backslash to escape itself  like in        That was a long list  but it is easy to learn regular expressions just by using them  First  let   s fix  the ones we used in the last section  This is what happen to us       echo foo xcc   sed    s  cc  c g     foo  c    echo focca x   sed    s  cc  c g     f ca x    But we wanted to replace   cc  and not any character and a cc  Now we know that the first argu   ment to the sed command s  is a regular expression  We can try to fix our problem       echo foo xcc   sed    s   cc  c g     foo xcc    echo focca x 
217. atch  context  203  string  188  190  sub expression  202  match c  205  matching  73  text  201  maximum  218  MBEFORE mount flag  169  MCREATE mount flag  169  meaning  of  data  18  of program  230  measurement  performance  194  mem file  process  51  memory  image  32       353838                            leak  355   private  363   process  46  84   segment  34  48  51   segment  virtual  153   shared  229  333   usage  217   virtual  32  34  46  memory allocation  1ib9p  340  menu  rio  6  317  message   attribute  plumb  131   attributes  plumb  129   delimiters  110  137   delivering  128   dump  369   handler  9P  334   plumb  128   reader  242   receive  plumb  131   size  326   tag  326   type  326  messages  9P  325  metadata  67  meta protocol  366  meta rule  352  mk  349   install  353   predefined variables  352   rules  349   targets  349   variables  351  kdir  14  kfile  349  355  kone  353  mnt  plumb file system  128  mnt sem  332  mnt term  174  mnt wsys  314  mode   cooked  290   file  69   graphics  298   hold  290   octal  20   open  58   privileged  2  24   raw  290   scroll  317   text  298  mode  AEXEC access  94  modification   time  346    a   g g                 15     time  file  69  user id  69  Smonitor  299  monitor  251  298  mount  authentication  170  file server  327  file system  160  point  161  166  168  specifier  163  169  table  160 161  union  167  mount flag  MAFTER  169  MBEFORE  169  MCREATE  169  MREPL  169  mount  160  169 
218. ated the output buffer and its contents were written to the underlying file  If  we modify this program to add a call to          Bflush   amp bout          after the one to Bwrite  this is what happens         biocat  Another little cat  Another little cat  did follow   did follow   control d    d       The call to Bflush flushes the buffer  Of course  it is now a waste to use bout at all  If we are  flushing the buffer after each write  we could have used just write  and forget about bout     Problems    1 Use the debugger  acid  to see that a program reading from standard input in a window is  indeed waiting inside  read while the system is waiting for you to type a line in the win   dow     Hint  Use ps to find out which process is running your program   2 Implement the cat 1  utility without looking at the source code for the one in your system     3 Compare your program from the previous problem with the one in the system  Locate the  one in the system using a command  Discuss the differences between both programs     4 Implement a version of chmod 1  that accepts an octal number representing a new set of  permissions  and one or more files  The program is to be used like in         8 out 0775 filel filez file3    5 Implement your own program for doing a long listing like    dh SL    would do     6 Write a program that prints all the files contained in a directory  hierarchy  along with the  total number of bytes consumed by each file  If a file is a directory  its repo
219. authentication server know which users there are  and which secrets  can be used to authenticate them  Furthermore  we still need to know how the initial password for  a user is established  and how can a user change it     Secrets  that is  keys  are not are maintained by the authentication server process  Instead   another server keeps them  All the keys for users are handled by a file server  called key fs     The keys and other information about the user accounts are actually stored in the file   adm keys  stored in the file server  To avoid disclosure of the keys  the file is encrypted using  the secret of the host owner in the authentication server machine  The program keyfs decrypts  this file  and serves a file tree at  mnt  keys that is the interface for authentication information  used by other programs  including the authentication server authsrv     For example  the directory  mnt  keys nemo contains information about the account for  the user nemo  In particular   mnt keys nemo key is the key for such user  That is how the  authentication server can access the secret for nemo to know if a remote user is indeed nemo or  not  All the operations to create  remove  enable  and disable user accounts are done through this  file system  Creating another directory under  mnt keys would create another user entry in   adm keys  And so on     In any case  it is not usual to use the file interface directly for handing user accounts   Instead  commands listed in auth 8  provi
220. b messages sent to the edit port  and prints  the file name for each such message     edits c       include  lt u h gt     include  lt libc h gt                    include  lt plumb h gt     void  main int   char              int fd   Plumbmsg m    char  addr        fd   plumbopen  edit   OREAD      if  fd  lt  0   sysfatal   edit port   r      while m   plumbrecv  fd       addr   plumblookup m  gt attr   addr     if  addr    nil    addr    none     print   msg  wdir     s    data       m  gt wdir    write 1  m  gt data  m  gt ndata    print      addr      s    n   addr    plumbfree  m         fprint  2   plumbrecv  Sr      close  fd     exits  nil           The function plumbopen opens the plumb port given as its first parameter  using the open mode      131      indicated by the second one   It returns an open file descriptor where we can read or write plumb  messages  In this case  we open the edit port  The function opens  mnt plumb edit if we  do not supply a path for the file name  To receive a message  the program calls plumbrecv   which blocks reading from the port until the plumber supplies the data from the message  This  function may have to read several times  until an entire message has been read  It returns a  pointer to the message read  which has this data structure     typedef struct Plumbattr Plumbattr   typedef struct Plumbmsg Plumbmsg     struct Plumbmsg            char SC   char  dst   char  wdir   char  type   Plumbattr xattr     linked list of attribute
221. be  created  In general  there is a text file on the system that lists user accounts  In Plan 9  the file   adm users lists users known to the file server machine  This is an example       sed 4q  adm users  adm adm adm elf sys  aeverlet aeverlet aeverlet   agomez agomez agomez   albertop albertop         The second field is the user name  according to the manual page for our file server program   fossil 4   As a result  this is how we can know if a user name can be used for a new user       grep  s         t     Suser            adm users  amp  amp  echo Suser exists  nemo exists    grep  s               rjimenez            adm users  amp  amp  echo rjimenez exists    The flag  s asks grep to remain silent  and only report the appropriate exits status  which is  what we want  In our little experiment  searching for  user in the second field of   adm users succeeds  as it could be expected  On the contrary   there is no rjimenez known  to our file server  That could be a valid user name to add     There is still a little bit of a problem  User names that we add can no longer be used for new  user names  What we can do is to maintain our own users file  created initially by copying   adm users  and adding our own entry to this file each time we produce an output line to add a  new user name     We have all the pieces  Before discussing this any further  let   s show the resulting script       222      list2usr     bin re    rfork e  users  tmp list2usr S pid  cat  adm users  g
222. ble before prompting for more commands  And  finally  we can write this partition table to disk and quit      gt  gt  gt  w   gt  gt  gt        That before seeing the effect       lc  dev sdCcl  9fat ctl data fs plang raw    At this point we have two partitions named fs and 9fat that can be used for example to install a  stand alone Plan 9 on them  one that may run without using an external file server   Both pro   grams  fdisk and prep used the file given as an argument to access the disk  That file was the  disk  They informed the storage device about the new partitions by writing control commands to  the disk ct1 file  At last  we can use the files supplied at  S to use our new partitions     But how can we create files in our partition  We need a program that knows how to store  files on disk  using a particular data structure to keep them stored  access them  and update them   This is what a file server is  But this time  files served by this program would be actual files in a  disk     There are several programs that can be used for this task  The standard file server for Plan 9  is fossil  This program is used by the  central  file server machine to serve files to terminals   Another  more ancient program is kfs  We are going to use this one       disk kfs  f  dev sdCl1 fs  File system main inconsistent  Would you like to ream it  y n      This command started k fs  a file server program  using  dev sdC1 fs as the disk  partition   where to keep files  For kfs  it does
223. blems  Reading a book that  addresses this topic may also help  5      To test the program  we might think on some tests to try to force it to the limit and see if it  crashes  Which tests to perform heavily depend on the program being tested  In any case  the shell  can help us to test this program     The idea is to try to use our program and then check if it behaved correctly  To do this  we  can see if the files served behave as they should  At least  we could do this for some simple  things  For example  if the file system is correct  it must at least allow us to create semaphores  and to remove them  So  executing        semfs    for  i in     seq 1 100     echo 1  gt  mnt sem si      should always leave  mnt   sem with the same files  One hundred of semaphore files with names  1  2  etc   up to 100  This means that executing      for  i in     seq 1 100     echo 1  gt  mnt sem si      ls  mnt sem    should always produce the same output  if the program is correct  In the same way  if semaphores  behave correctly  the following will not block  and the size for the semaphore file after the loop  should be zero  Thus  the following is also a program that should always produce the same output  if the file system is correct       echo 4  gt  mnt sem mutex     for  i in     seq 1 4     read  lt  mnt sem mutex      if  test  s  mnt sem mutex    ae echo not zero sized   r    For all these checks we can think of how to perform them in a way that they always produce the  same ou
224. by the abstraction     Disks may contain multiple parts  named partitions  A partition is just a contiguous por   tion of the disk kept separate for administrative purposes  For example  most machines with Win   dows come preinstalled with two partitions in your hard disk  One of them corresponds to the C   unit  and contains system files  The other corresponds to the D  unit  and contains user files  Both  ones are just partitions in the hard disk     Reading the ct1 file for a disk reports all the list of partitions  with their names  start sec   tor  and end sector  This is the one for our hard disk       cat  dev sdC0 ctl   inquiry VMware Virtual IDE Hard Drive   config 427A capabilities 2F00 dma 00550004 dmactl 00550004 rwm 16 rwmctl 0  geometry 16777216 512 17475 15 63   part data 0 16777216   part plan9 63 16771860   part 9fat 63 204863   part fs 204863 13626132   part swap 13626132 14674708   part cache 14674708 16771860       Although we might have listed them  perhaps just to see the file sizes     Is  1  dev sdco      rw r      S 0 nemo nemo 104857600 May 23 17 44  dev sdC0 9fat       rw r      S 0 nemo nemo 1073741824 May 23 17 44  dev sdC0 cache    rw r      S 0 nemo nemo 0 May 23 17 44  dev sdC0 ctl    rw r      S 0 nemo nemo 8589934592 May 23 17 44  dev sdC0 data    rw r      S 0 nemo nemo 6871689728 May 23 17 44  dev sdc0 fs    rw r      S 0 nemo nemo 8587160064 May 23 17 44  dev sdC0 plan9   lrw        S 0 nemo nemo 0 May 23 17 44  dev sdC0 raw    rw r      S
225. c  The program  executed by procexec knows nothing about your program  Therefore  a substitute for wait is  appropriate for this case  The function threadwaitchan returns a channel that can be used to  receive Waitmsgs for processes what we used to execute other programs     The following program is a complete example regarding how to execute an external pro   gram and wait for it        texec c     include  lt u h gt       286       include  lt libc h gt      include  lt thread h gt     Channel waitc     Channel pidc     void    cmdproc void  arg          char     procexecl  pidc     sysfatal    void  threadmain int      char  int    Waitmsg    write l1   nr    if    rea     nr  lt     in nr 1   pide  c  waitc  t  proccrea  pid   re  print  s    if  pid         threadex         cmd   arg     cmd  cmd  nil      br         procexecl     charmli     1n 512    pid  nr      m     woma  My  d  0     1   threadexits  nil     a    drop  n    hancreate  sizeof  ulong      SNG    ln  sizeof  ln  1      hreadwaitchan        te cmdproc  ln  8 1024      cvul  pidc        gt   0      m        recvp  waitc      print   terminated pid  d sts  s n      free  m      its nil      tarted new proc pid  d n      1      pid      m  gt pid  m  gt msg       The initial thread reads a file name and executes it  The actual work is done by proccreate   which creates the process to execute the file  and by procexec1  which executes the new pro     gram in the calling process     The first parameter for 
226. c  e  env    bind  p  proc          bind  c  s  srv       several other binds         standard bin  bind  Scputype bin  bin  bind  a  rc bin  bin      User mounts   bind  c  usr Suser tmp  tmp   bind  bc  usr Suser bin Scputype  bin  bind  bc  usr Suser bin re  bin   cd  usr Suser    As you can see  a namespace file for use with newns contains lines similar to shell commands  used to adjust the namespace  that are like the ones in  proc   ns files  The file  s boot is  a connection to the file server used to boot the machine  This is what you find at  srv boot   after the line    bind  c  s  srv    in the namespace file has been processed  Ignoring some details  you can see how this file server  is mounted at  root  and then this directory is added to    Both directories come from your  root device      which is always available  The dance around  root and   adds the root of the  file server to those files already in  root     The next few lines bind device driver file trees at conventional places  For example   c is  the cons driver  which is bound at  dev and provides files like  dev null   dev time  and  other common files for the machine  Also   d provides the file interface for your file descriptors   and is bound at   fd as expected  The same is done for other drivers     Now look at the sections marked as standard bin  and user mounts  They answer our      172      question regarding  bin     The program init defined several environment variables  For example   user ho
227. call sleep between each two polls  The following two programs wait until the file given  as a parameter changes  and then print a message to let us know  The first one performs a continu   ous poll for the file  and the second one makes one poll each 5 seconds     poll c       include  lt u h gt     include  lt libc h gt                 void  main int argc  char  argv            Dur  d   ulong mtime  nmtime   if  argc    2      fprint 2   usage   s file n   argv 0     exits   usage          d   dirstat  argv 1      if  d    nil     sysfatal  dirstat  Sr       mtime   d  gt mtime   free d    do    d   dirstat  argv 1     if  d    nil   break   nmtime   d  gt mtime   free d      while  nmtime    mtime      print   Ss changed n   argv 1       exits  nil      pollb c    everything the same  but for the call to sleep  do    sleep 5   1000    d   dirstat  argv 1     if  d    nil   break   nmtime   d  gt mtime   free d      while  nmtime    mtime      It is interesting to see how loaded is the system while executing each program  The system load      127     is a parameter that represents how busy the system is  and it is usually an indicative of how much  work the system is doing  The load is measured by determining which percentage of the time the  system is running a process and which percentage of the time the system is not  In a typical sys   tem  most of the time there is just nothing to do  Most processes will be blocked waiting for  something to happen  e g   inside a read w
228. can  be perfectly done by a server process without changing its user id  After authenticating a client  a  server may just spawn a child process to execute a command for the remote user  But this works  as long as the process for the remote user does not try to use resources outside the CPU server  As  soon as it tries  for example  to mount a file server  it would need to authenticate and identify  itself using the client user id  and not the user id for the server that provides remote execution in  the CPU server  Of course  in practice  a process for a remote user is very likely to access  resources outside the CPU server and therefore requires some mean to change its user id     And there is an even more interesting thing to see now  When you connect to a CPU server  to execute a command on it  the name space from your terminal is exported to the server process  that runs the command in the CPU server  We saw this time ago  The name space is exported  using the connection to the CPU server  after authentication has been performed  As a result  the  process started for you in the CPU server does not require to change its ownership to use any of  the files re exported from your terminal for it  Is has all of them in its name space  Of course   mounting something while running in a CPU server is a different thing  and requires an identity  change as you now know     Because speaking for others  as a result of changing the user identity  is potentially very  dangerous  The au
229. can we achieve mutual exclusion for our critical region  The idea is that when a pro   cess is about to enter the critical region  if must wait until it is sure that nobody else is executing  code inside it  Only in that case it may proceed  To achieve this we need new abstractions     A lock is a boolean variable  or an integer used as a boolean  used to indicate if a critical  region is occupied or not  A process entering the critical region sets the lock to true  and resets the  lock to false only after leaving the region  To enter the region  a process must either find the lock  set to false or wait until it becomes false  otherwise there would be more than one process execut   ing within the critical region and we would have race conditions     The intuition is that the lock is a variable that is used to lock a resource  the region   A pro   cess wanting to use the shared resource only does so after locking it  After using the resource  the  process unlocks it  While the resource is locked  nobody else will be able to lock it and use it     Using locks  we could protect our critical region by declaring a Lock variable  cntlck   calling 1ock on it  to set the lock  before entering the critical region  and calling unlock on it   to release the lock  after leaving the region  By initializing the variable to zero  the lock is ini   tially released  remember that globals are initialized to zero by default        sig lock unlock  void lock  Lock  1   void unlock  Lock  1      
230. cation protocol used in Plan 9     Factotum keeps keys  A key is just a secret  along with some information about the secret  itself  e g   which protocol is the secret for  which user is the secret for  etc   Factotum is indeed a  file system  started soon after the the machine boots  which mounts itself at  mnt   factotum   Its interface is provided through the files found there       lc  mnt factotum  confirm ctl log needkey proto rpc       The file ct 1 is used to control the set of secrets kept by the factotum  Reading it  reports the list  of keys known  without reporting the actual secrets        363        cat  mnt factotum ctl   key proto p9sk1l dom dat escet urjc es user nemo  password    key proto p9sk1l dom outside plan9 bell labs com user nemo  password    key proto vne dom dat escet urjc es server aquamar  password    key proto pass dom urjc es server orson service ssh user nemo  password   key proto rsa service ssh size 1024 ek 10001 n DE6D279ECCOF5D08B4 9C9BI1F44B  9CA26114005BD2EB1B255A92F42D475B4 9D3EF 9C923B9ECI80D882033FA4886990DDF17108  B4237A2FD6E1CB2C040C1E319206B8A9FBA5 942 9AF5361F03352DAE67243B62CE2664663B  EOAEIF1933CDF935  dk   p   q   kp   kq   c2                                Hy                                     Each one of the lines above corresponds to a single key kept by this factotum process  and starts  with key  The last line is so large  that it required four output files in the terminal session repro   duced above     The first line s
231. cause the pipe is full      fill c     include  lt u h gt    include  lt libc h gt        void  main int  char             int fd 2    char buf  1024    int nw     if  pipe fd   lt  0   sysfatal  can   t create a pipe  Sr     for       nw   write fd 0   buf  sizeof  buf     print   wrote  d bytes n   nw       exits  nil           This is the output  The pipe in my system can hold up to 30 Kbytes     EEEN   wrote 1024 bytes   wrote 1024 bytes   wrote 1024 bytes       29 lines including these two ones     wrote 1024 bytes       and it blocks forever    And this is what ps says for the process       ps   grep 8 fill  nemo 2473 0 00 0 00 24K Pwrite 8 fill    It is trying to write  but will never do    In the shell examples shown above  it is clear that the process reading from the pipe gets an  end of file  i e   a read of 0 bytes  after all data has gone through the pipe  Otherwise  the com   mands on the right of a pipe would never terminate  This is the rule  When no process can write  to one end of the pipe  and there is nothing inside the pipe  reading from the other end yields 0  bytes  Note that when the pipe is empty  but a process can write to one end  reading from the  other end would block     This is easy to check using our single process program  If we do this    close fd 1     nr   read fd 0   buf  sizeof  buf       the value of nr becomes zero  and read does not block  However  removing the close line      112     makes the program block forever     Writing to a pi
232. cess trust a third process  the authentication server  This  means that both processes must share a secret with the third trusted one     No matter how many servers there are  the client only needs one secret  for using the  authentication server  Using it  the client asks the authentication server for tickets to gain access  to servers  Each ticket is a piece of data than is given to a client  and can be used to convince the  server that the client is indeed who it claims to be  This can be done because the authentication  server may use the secret it shares with the server to encrypt some data in the ticket given to the  client  When the client sends the ticket to the server  the server may know that the ticket was  issued by someone knowing its own secret  i e   by the authentication server     The authentication server in Plan 9 is implemented by the program authsrv  described in  auth 8   It runs on a machine called the authentication server  as you might guess  In many cases   this machine may be the same used as the main file server  if it runs such process as well     Things are a little bit more complex  because a user might want to use servers maintained by  different organizations  It would not be reasonable to ask all Plan 9 file servers in the world to  share a single authentication server  As a result  machines are grouped into  so called   authentication domains  An authentication domain is just a name  representing a group of  machines that share an authentica
233. cesses in  Plan 9  Each of the files listed above is a directory  and its name is the process pid  For example   to go to the directory representing the shell we are using we can do this       echo spid    938     cad  proc 938   se LC   args fd kregs note notepg proc regs status wait  ctl fpregs mem noteid ns profile segment text    These files provide the interface for the process with pid 938  which was the shell used  Many of  these  fake  virtual  files are provided to permit debuggers to operate on the process  and to permit  programs like ps gather information about the process  For example  look again at the first lines  printed by acid when we broke a process in the last section      gt  acid 788   proc 788 text 386 plan 9 executable    eee    Acid is reading  proc 788 text  which appears to be a file containing the binary for the pro   gram  The debugger also used  proc 788 regs  to read the values for the processor registers  in the process  and  proc 788 mem  to read the stack when we asked for a stack dump     Besides files intended for debuggers  other files are for you to use  as long as you remember  that they are not files  but part of the interface for a process   We are now in position of killing a  process  If we write the string kill into the file named ct1  we kill the process  For example   this command writes the string kill into the ct1 file of the shell where you execute it  The  result is that you are killing the shell you are using  You are not wri
234. ch is rc by default  The net effect is that you can connect to a shell at any CPU server   and run commands on it  This is an example       echo Ssysname  alboran   ep   cpu  echo Ssysname  aquamar   control d     echo Ssysname  alboran    Your profile  executed each time you enter the system  changes the prompt for the shell to  advice you that it is not running at your terminal  When an initial shell is started for you at a  machine  a CPU server  a terminal  etc    it executes your Shome 1ib profile file  Now  the  process that started the shell for you defined a environment variable to indicate which kind of ses   sion you are using  For terminals  the variable service has terminal as its value  However   on CPU servers this variable may have cpu or rx as its value  depending on how did you con   nect to the CPU server  Your profile may do different things  like adjusting the shell prompt    depending on Sterminal        A more rudimentary alternative is provided  for those cases when you want to execute just  one command at another machine  It is called rx  and accepts a machine name and a command to  run on it       rx aquamar    echo S sysname     aquamar    r      152      Note how we had to quote the whole command  which is to be executed verbatim by the remote    machine    Problems   1 Use  net to see which networks are available at your terminal  Determine the local  address for your terminal for each one of the networks    2 Repeat the second problem of chapter 1
235. cho 1  gt  mnt sem mutex    echo 3  gt  mnt sem other      ls  1  mnt sem      rw rw r   M 174 nemo nemo 1 Aug 23 00 16  mnt sem mutex    rw rw r   M 174 nemo nemo 3 Aug 23 00 16  mnt sem other      read  lt  mnt sem other      ls  1  mnt sem other      rw rw r   M 174 nemo nemo 2 Aug 23 00 16  mnt sem other      read  lt  mnt sem other    read  lt  mnt sem other      read  lt  mnt sem other  This blocks until a ticket is added  And then        r    The program we built uses a single process to attend all the 9P requests  Nevertheless  we  decided to show how to use the thread library together with 1ib9p  If we decide to change the  program to do something else  that requires multiple threads or processes  it is easy to do so   Once again  it is important to note that by processing all the requests in a single process  there is  no race condition  All the data structures for the semaphores are free of races  as long as they are  touched only from a single process     For example  if this program is ever changed to listen for 9P clients in the network  it might  create a new process to attend each connection  That process may just forward 9P requests      349      through channels to a per client thread that attends the client requests  Once again  there would be  no races because of the non preemption for threads     There are several other tools for building file servers in Plan 9  Most notably  there is a  implementation of file trees  understood by 1ib9p  File servers that
236. client  In the same way  Twrite messages  are processed by Srv write  and so on       334          Srv  attach  auth  read                          server call to   gt    loop srv read       client 9P 3 Tread   Plan 9   7P1P                                              Rread Fesa    function walk                       child  server process    Figure 13 3  A 9P server process created by a call to postmountsrv     The main server loop function  srv may be used directly when postmountsrv does not  do exactly what we want  It reads messages from Srv  infd  and sends replies to Srv  out fd   These descriptors usually refer to the pipe created by postmount srv  but that does not have to  be the case     Not all functions in Srv have to be implemented  In many cases  leaving a nil function  pointer for a 9P request in Srv provides a reasonable default  For example  If files cannot be  written  the pointer Srv  write may be set to nil  and the main loop will respond with an appro   priate Rerror reply upon write attempts  The details about which functions must be provided   which ones do not have to be  and what should such functions do  are described in the 9p 2  man   ual page  In any case  if a function is provided for a message  it is responsible for responding     As an additional help  because walk may be complicated to implement  two functions that  are building blocks for walk may be implemented instead of walk  This functions are walk1  and clone     At this point  we can st
237. col Kill Putall Dump Exit    _  usr nemo  Del Snarf Get   Look  oo  bin  guide mail  ohist src    doc  lib  offline  private  tmp   mkdir  tmp dir   bind  usr nemo  tmp dir     tmp dir  Del Snarf Get   Look                          Figure 7 5  Executing a bind on Acme does not seem to work  What is happening      by selecting the text and then doing a click on it with the mouse button 2   Later  we asked Acme  to open  tmp dir  using the mouse button 3  It was empty  What a surprise  Our home direc   tory was not empty  and after performing the bind  it seems that  tmp dir was not bound to  our home directory  Is Acme broken     Acme is behaving perfectly fine  When we used the mouse button 2 to execute the com   mand line  it created a child process to execute the command  The child process prepared to exe   cute the command and called rfork with flags RFNAMEG RFENVG RFFDG RFNOTEG   Acme is just trying to isolate the child process  The flag RFNAMEG caused the child process to  obtain its own copy of the name space used by Acme  As a result  any change performed to the  name space by the command you executed is unnoticed by Acme  The command starts  changes  its own name space  and dies                       To change this behavior  and ask Acme not to execute the child in its own name space  you  must use Acme   s built in command Local  If a command is prefixed by Local  Acme under   stands that it must execute the command sharing its namespace with the child process that w
238. commands to it  as you  already know  For example  to execute date from the shell we can simple type the command  name and press return       date  Sat Jul 8 01 13 54 MDT 2006    In what follows  we do not remember to press return after typing a command  Now we will use  the shell in a window to play a bit with files  You can list files using 1s    ATS   bin   lib   tmp    z    There is another command  1c  list in columns   that arranges the output in multiple columns  but  is otherwise the same    2  LC   bin lib tmp    r    If you want to type several commands in the same line  you can do so by separating them with a  semicolon  The only         we typed here is the one between date and 1c  The other ones are the  shell prompt     ae aie  He   Sat Jul 8 01 18 54 MDT 2006   bin lib tmp  Another convenience is that if a command is getting too long  we can type a backslash and then  continue in the next line  When the shell sees the backslash character  it ignores the start of a new     1ll     line and pretends that you typed an space instead of pressing return       date      ii date       lt  lt  date    Sat Jul 8 01 19 54 MDT 2006  Sat Jul 8 01 19 54 MDT 2006  Sat Jul 8 01 19 54 MDT 2006    F    The double semicolon that we get after typing the backslash and pressing return is printed by the  shell  to prompt for the continuation of the previous line  prompts might differ in your system    By the way  backslash     is called an escape character because it can be used to e
239. connects  The par   ent process may be kept listening  waiting for a new client  When one arrives  a child may be  spawned to serve it  This is called a concurrent server  because it attends multiple clients con   currently  The resulting code is shown below     There are some things to note  An important one is that  as you know  the child process has  a copy of all the file descriptors open in the parent  by the time of the fork  Also  the parent has  the descriptor open for the new call received after calling 1isten  even though it is going to be  used just by the child process  We close 1 fd in the parent  and cfd in the child     We might have left cfd open in the child  because it would be closed when the child termi   nates by calling exits  after having received an end of file indication for its connection  But in  any case  it should be clear that the descriptor is open in the child too     Another important detail is that the child now calls exits after attending its connection   because that was its only purpose in life  Because this process has  initially  all the open file  descriptors that the parent had  it may be a disaster if the child somehow terminates attending a  client and goes back to call Listen  Well  it would be disaster because it is not what you expect  when you write the program     cecho c     include  lt u h gt      include  lt libc h gt     void    main int argc            149      char  argv       int efras ltd   dtda   long nx    char adir 40
240. cons   OWRITE         n       r  d    Later  all the descendents had their descriptors 0  1  and 2 open and referring to  dev cons   This code would do the same     open    dev cons   OREAD     open    dev cons   OWRITE     dup  1  2            5 3  Other redirections    Output can be redirected to a file appending to its contents  In this case  the shell seeks to the end  of the file used for output before executing the command  To redirect output appending  use     gt  gt      instead of use     gt          echo hello  gt  tmp note     echo there  gt  gt  tmp note     echo and there  gt  gt  tmp note     cat  tmp note   hello   there   and there     echo again  gt  tmp note     cat  tmp note   again    The code executed by the shell to redirect the output appending is similar to this one     fd   open  outfile   OWRITE    if  fd  lt  0   fd   create  outfile   OWRITE  0664    seek  fd  0  2    dup  fd  1    close  fd              107      which creates the output file only when it does not exist  If the program used create  it would  truncate the file to a zero length  If it used just open  the output redirection would not work  when file does not exist  Also  the call to seek is utterly important  to actually append to the file     FIle descriptors other than O and 1 can be redirected from the shell  You must write the  descriptor number between square brackets after the operator  For example  this discards any error  message from the command by sending its standard error 
241. copies a lot of data at  tmp songs Spid  Hitting Delete  might leave those  files there by mistake  One fix would be to define a sigint function  However  provided that  machines have plenty of memory  there is another file system that might help  The program  ramfs supplies a read write file system that is kept in memory  It uses dynamic memory to keep  the data for the files created in its file tree  Ramfs mounts itself by default at  tmp  So  adding  a line    ramfs  c    before using  tmp in the script will ensure that no files are leaved by mistake in Shome tmp   which is what is mounted at  t mp by convention      Like most other file servers listed in section 4 of the manual  ramfs accepts flags  abc to  mount itself after  before  and allowing file creation  Two other popular options are    m dir  to  choose where to mount its file tree  and  s srvfile  to ask ramfs to post a file at  srv  for  mounting it later  Using these flags  we may able to compile programs in directories where we do  not have permission to write     ramfs  bc  m  sys src cmd  cd  sys src cmd   8c  FVw cat c   81  o 8 cat cat 8   LOO Cab    cat cat 8 cat c     rm 8 cat cat 8    CO Ne Ne Ne Ne Ne    After mounting ramfs with  bc at  sys src cmd  new files created in this directory will be  created in the file tree served by ramfs  and not in the real  sys src cmd  The compiler and  the loader will be able to create its output files  and we will neither require permission to write in  that directo
242. correct or not  the only tool you have is just careful thinking  about the program code  Playing with example scenarios  trying hard to show that the program  fails  There are some formal tools to verify if an implementation for a concurrent program has  certain properties or not  but you may make mistakes when using such tools  and therefore  you  are on your own to write correct concurrent programs     10 7  Other tools    A popular synchronization tool  not provided by Plan 9  is a semaphore  A semaphore is an  abstraction that corresponds to a box with tickets to use a resource  The inventor of this abstrac   tion made an analogy with train semaphores  but we do not like trains     The idea behind a semaphore is simple  To use a resource  you need a ticket  The operation  wait waits until there is a ticket in the semaphore  and picks up one  When you are no longer  using the resource  you may put a ticket back into the semaphore  The operation signal puts a  new ticket into the semaphore  Because of the analogy with train semaphores  wait is also  known as down  to low a barrier  and signal is also known as up  to move up a barrier   But  in general  you will find either up and down as operations  or signal and wait     Internally  a semaphore is codified using an integer to count the number of tickets in the box  represented by the semaphore  When processes call wait and find no tickets in the semaphore       256      wait guarantees that they are put into sleep  Further
243. could do nothing else but to return an error  What value returns exec1 when it fails  It does not  matter  If it returns  it must be an error     Now replace the call with the next one  What would happen       93      execl   bin 1ls     1     usr nemo   nil      This is what happens       8 execl  running ls   usr nemo bin   usr nemo lib   usr nemo tmp    Clearly 1s did run in our process  Its output is there and our second print is not  However  where  is the long listing we requested  Nowhere  For 1s  argv 0  was  1 and argv 1  was   usr nemo  We executed 1s  usr nemo  Even worse  we told 1s that its name was    1        Now that we master exec1  let   s try doing one more thing  If we replace the call with this  other one  what happens     exec     bin ls   tigi wip    Shome   nil         The answer is obvious only when you think which program takes care of understanding    Shome         It is the shell  and not 1s  The shell replaces Shome with its value   usr nemo in this case  It  seems natural now that this is he output for the program       8 execl  running ls  ls  Shome     Shome    file does not exist    What we executed was the equivalent of the shell command line    Is  1    Shome       which we know well now  Should we want to run the program for Shome  we must take care of  the environment variable by ourselves      include  lt u h gt    include  lt libc h gt     void  main int  char           char  home     print   running l1s n      home   getenv   home      
244. create  int proccreate void   fn   void    void  arg  uint stacksize     The processes created using this function share the data segment among them  Internally   proccreate calls rfork  RFPROC RFMEM RFNOWAIT   because the thread library keeps  its data structures in the data segment  which must be shared  In a few cases  you may want to  supply a few extra flags to rfork  when creating a process  The call procrfork is like  proccreate  but accepts a final flags argument that is or ed to the ones shown above                sig procrfork  int procrfork void   fn   void    void  arg  uint stacksize        But beware  the thread library uses rendezvous in its implementation  Supplying a RFREND  flag to procrfork will break the program  Using proccreate  we can make our program  without blocking all the threads while doing I O     tticker c     include  lt u h gt    finclude  lt libc h gt    include  lt bio h gt      include  lt thread h gt           enum   Npanels   2     Channel bcastc     of char   Channel panelc Npanels      of char             code for PArg  consreadthread  bcastthread  and panelthread       void  threadmain int  char          int i    PArg  arg     beastc   chancreate sizeof char    0    proccreate consreadthread  nil  16  1024    for  i   0  i  lt  Npanels  itt     panelc i    chancreate sizeof char    0    arg   malloc sizeof  arg     arg  gt c   panelc i    arg  gt fd   1     to test the program   proccreate panelthread  arg  8 1024               The cur
245. creates a child process  and each one of the processes increment a counter twice  The counter is  shared  because the call to rfork uses the RFMEM flag  which causes all the data to be shared  between parent and child  Note that only cnt  which is a global  is shared  The local variable i  lives on the stack which is private  as it should be           Executing the program yields this output         riner  cnt is 2  cnt is 4    r      230      We now declare an integer local variable  Loc  and replace the body of the loop with this code   equivalent to what we were doing     loc   cnt   loctt   cnt   loc     It turns out that this is how cnt   is done  by copying the memory value into a temporary vari   able  kept at a register   then incrementing the register  and finally updating the memory location  for the variable with the incremented value  The result for this version of the program remains the  same         riner  cnt is 2  cnt is 4    z    But let   s change a little bit more the program  Now we replace the body of the loop with these  statements     loc   cnt   sleep 1    loctt    cnt   loc     The call to sleep does not change the meaning of the program  i e   what it does  However  it  does change the result  The call to sleep exposed a race condition present in all the versions of  the program     y Brin  cnt is 2  cnt is 2    Both processes execute one instruction after another  but you do not know when will the operat   ing system  or any external event  move on
246. d   Qid q   Sem  Ss     fid    r  gt fid    q   fid  gt qid    if    q type amp QTDIR       respond r   not a directory     return        s   newsem r  gt ifcall name     fid  gt qid    Qid  s  gt id  0  0     fid  gt aux   s    fid  gt omode   r  gt ifcall mode    incref s     r  gt ofcall gqid   fid  gt qid    respond r  nil              In a Tcreate  the fid in the request  represented by r    gt fid  should point to a directory  The  server is expected to create a file with the name specified in the request  which is  r  gt ifcall name here  within that directory  Also  after the Tcreate  the fid must point to  the newly created file and must be open according to the mode specified in the request  This is  what the function does        If the qid is not for the directory  the OTDIR bit is not set in its qid   an Rerror message  is sent back to the client  instead of creating the file  This is achieved by calling respond witha  non null string as the error string  Otherwise  we create a Sem data structure by calling newsem   The qid in the fid and the response  r    gt ofcal11  is also updated to refer to the new file        To make things more simple for us  we place a pointer to the Sem implied by the qid in the  Fid aux field of each fid  All of Fid  Reg  and Srv data structures contain an aux field that  can be used by your programs to keep a pointer to any data of interest for your file server  In our  case    id  gt aux will always point to the Sem structure for the 
247. d 476 nwname 1 0 x   12  gt  Rwalk tag 14 nwqid 1 0  0000000000000000 1     lt  12  Topen tag 14 fid 476 mode 17   fid mode is 0x11    12  gt  Ropen tag 14 qid  0000000000000000 1   iounit 0   lt  12  Twrite tag 14 fid 476 offset 0 count 4    hola      12  gt  Rwrite tag 14 count 4    lt  12  Tclunk tag 14 fid 476    12  gt  Reclunk tag 14          First  Plan 9 took the name  n ram x and tried to open it for writing  It walked the file tree  using the name space  as we learned before  After reaching  n ram  it knows it has to continue      329      the walk at the root for our file server  So  Plan 9 must walk to the file  x of the file server  That  is what Twalk is for     The first 9P request  Twalk  is used to walk the file tree in ramfs  It starts walking from  the file with fid 435  That is the root of the tree  The walk message contains a single step  walking  to x  relative to wherever fid 435 points to  The field nwname contains how many steps  or  names  to walk  Just one in this case  The field wname in the message is an array with that num   ber of names  This array was printed in the right part of the line for the message  It had a single  component  wname  0   containing the name x  If the file exists  and there is no problem in  walking to it  both Plan 9 and the file server agree that the fid number in newfid  476 in this  case  refers to the resulting file after the walk  The reply message  Rwalk  mentions the qids for  the files visited during the walk  Aft
248. d is used to ask the user for a key when fac   totum does not have the key needed for the protocol chosen  For example  below we try to mount  the file server whale  in the window where we started a new factotum  which starts with no  keys       auth factotum     cat  mnt factotum ctl     This one has no keys      8 amount  srv tcp whale 9fs  n whale main archive       Adding key  dom dat escet urjc es proto p9skl  user  nemo   we pressed return    password  we typed the password here    client uid  nemo  server uid  nemo    Here  auth_proxy called the function anount_getkey  given as a parameter  to ask for a  key to mount whale  At this point  the message starting  Adding key    was printed  and we  were asked for a user name and password for the P9SK1 protocol within the  dat escet urjc es authentication domain  That information was given to factotum  to  install a new key  and authentication could proceed  After that  factotum has the new key for use  in any future authentication that requires it       cat  mnt factotum ctl  key proto p9sk1l dom dat escet urjc es user nemo  password     We will never be prompted for that key again as long as we use this factotum       368      14 5  Secure servers    Handling authentication in a server can be done in a similar way  In general  the server calls  auth_proxy to rely messages between the client and factotum  The only difference is that  the role is now server  instead of client     For 9P servers  the 9p 2  library provides h
249. d sed 3q from the pipeline  because this command does what we wanted to  do and we want to process the whole file tree  and not just the first three ones  It happens that  sort also knows how to remove duplicate lines  after sorting them  The flag  u asks sort to  print a unique copy of each output line  We can optimize a little bit our command to list file own   ers       Ir bin   sed    s    fa z0 9       1       sort  u    What if we want to list user names that own files at several file trees  Say   n fs1 and   n   s2  We may have several file servers but might want to list file owners for all of them  It  takes time for lr to scan an entire file tree  and it is desirable to process all trees in parallel  The  strategy may be to use several command lines like the one above  to produce a sorted user list for  each file tree  The combined user list can be obtained by merging both lists  removing duplicates   This is depicted in figure 9 1     lr  n fs1   sed H sort ssu    lr  n fs2    sed H sort                                           sort  mu  gt  sorted list                                                 Figure 9 1  Obtaining a file owner list using sort to merge two lists for fs1 and fs2    We define a function 1rusers to run each branch of the pipeline  This provides a compact  way of executing it  saves some typing  and improves readability  The output from the two pipe   lines is merged using the flag  m of sort  which merges two sorted files to produce a single li
250. d waiting for a read to complete   When  the event a blocked process is waiting for happens  the process state is changed to ready  Some   time in the future it will be selected for execution in the processor     In Plan 9  the state shown for blocked processes reflects the reason that caused the process     47        Broken Death    Birth Blocked        Figure 2 4  Process states and transitions between them     to block  That is why ps shows many different states  They are a help to let us know what is hap   pening to our processes     There is one last state  broken  which is entered when the process does something illegal   i e   it suffers an error   For example  dividing by zero or dereferencing a null pointer causes a  hardware exception  an error   Exceptions are dealt with by the hardware like interrupts are  and  the system is of course the handler for these exceptions  Upon this kind of error  the process  enters the broken state  A broken process will never run  But it will be kept hanging around for  debugging until it dies upon user request  or because there are too many broken processes      2 7  Debugging    When we make a mistake  and a running program enters the broken state  it is useful to see what  happen  There are several ways of finding out what happen  To see them  let   s write a program  that crashes  This program says hello to the name given as an argument  but it does not check that  the argument was given  nor does it use the appropriate format s
251. de a more convenient interface  For example  a new  user account is created using likeauth changeuser       auth changeuser nemo    This command is executed in the authentication server  It prompts for the secret for the new user   which should be only known to that user  and therefore is typed by him or her   along with some  administrative information  For example  the program asks when should the account expire  how  can the user be reached by email  etc     The account created is just a key along with a new user name  that will be kept encrypted in   adm keys  But this does not allow the new user to use any file servers  Each file server main   tains its own list of users  as you saw  Accounts in the authentication servers are just for authenti   cation purposes     Sometime later  a user might decide to change the secret used for authentication  This is  done with the passwd command  which talks directly to the authentication server to change the  secret for the user  This server updates the key using the  mnt  keys Suser key file for the  user     Because of what we said  you might think that it is necessary for an administrator to come  near each authentication server to type the password for the host owner  Otherwise  how could  keyfs decrypt  adm keys  And the same might apply to file servers and CPU servers  They  need the secret of the host owner to authenticate themselves       375      This is not the case  CPU servers and file servers keep the authentication dom
252. debug  363  protocol  136  authentication  361  file system  159  325  internet  135  network  139  telnet  138  transport  136  providing services  144  ps  45  50  101  108  pseudo parallel execution  30  Pt  308  Put  8  put  252  putenv  45    pwd  14  42  Pwrite  111  PXE  4    Q    qent c  241  QID  69  Qid     328   conventions  339   file  327  Qid   path  328  type  328   qids  327  QLock  239  244  glock  239  244  252  QTAPPEND  328  QTAUTH  368  QTDIR  328  342  OTEXCL  328  quantum  46  queue  341  queueing lock  239  qunlock  239  quoting  43  75  184          R    r  40  rabbits c  88  race condition  91  229  ram file system  227  ramfs  227  325  range  character  201  pattern  character  74  Rattach  326  Rauth  361  raw mode  290  raw c  291  rawoff  290  rawon  290  310  rey    conditionals  190  flag  c  114  in pipes  109  lists  180  loop  186  note handler  223  script  183  script  9fs  161  163  script  args  188  script  cdcopy  227  script  copy  157      20      script  d2h  184  script  file  190  script  h2d  185  script  list2grades  224  script  when  192 193  using  179   vrc bin service  150  rcecho rc script  99  rcinr c  233  Rclunk  328  read  console  290  directory  70  line  80  processing  344  robust file  120  simultaneous  289  string  81  read  56 58  75  77  79  120  command  97  readbuf  344  read c  56 58  reader  console  242  message  242  multiple  244  reading  key  367  readn  120  reads  directory  345  readstr  344  read
253. dezvous  It is not necessary for them to share memory  Of course  the values  supplied as tags and values cannot be used to point to shared variables when the processes      247      Process A    calls  rendezvous  tag   hi        Waiting       Process B    calls  rendezvous  tag   there      rendezvous       call returns   there     time    call returns   hi     time    Figure 10 8  Two processes doing a rendezvous     are not sharing memory  but that is the only limit  memory is not shared     The following program creates a child proces    ation  The values are still exchanged even if    s  which is supposed to run an HTTP server     To execute nicely in the background  all the job is done by the child  and not by the parent  This    way  the user does not need to add an additional     amp  when starting the program from the shell     However  before doing the actual work  the child must initialize its data structures and perhaps  read some configuration files  This is a problem  because initialization could fail  If it fails  we    want the parent process to exits with a non null  failed     status  to let the shell know that our program    One way to overcome this problem is to make the parent process wait until the child has  been initialized  At that point  it is safe for the parent to call exits  and let the child do the work  if everything went fine  This can be done using rendezvous like follows     rendez c   void  main int  char         int i   int childsts     sw
254. did not  create them in the old one  We must copy them again     IZE      213        grep     Only in  usr nemo bin     tmp diffs        sed    s Only in  usr nemo bin   t             cp  usr nemo bin  1  2  tmp bin  1      cp  usr nemo bin rc d2h  tmp bin re   cp  usr nemo bin rc h2d  tmp bin re    In this command   1 is the path for the file  relative to the directory being compared  and  2 is  the file name  We have not used Shome to keep the command as clear as feasible  To complete  our job  we must undo any change to any file by coping files that differ       grep     diff      tmp diffs   sed    s diff cp      cp  usr nemo bin rc t   tmp bin rc t     All this can be packaged into a script  that we might call restore     restore  _      bin re   rfork e   if      S   2    echo usage  0 olddir newdir  gt  1 2   exit usage       old  1   new  2    diffs  tmp restore Spid  diff  r Sold Snew  gt Sdiffs    grep     Only in     Snew  tmp diffs   sed  e    s Only in rm      e s           fromstr    Only in     Sold            I           tostr     cp     Sold      1  2   Snew      1    grep     Only in     Sold Sdiffs   sed  e    s     Sfromstr          Stostr           grep   diff      S diffs   sed  s diff cp       rm Sdiffs   exit           And this is how we can use it       restore   rm  tmp bin rc rcecho   cp  usr nemo bin rc d2h  tmp bin re   cp  usr nemo bin rc h2d  tmp bin re   cp  usr nemo bin rc t   tmp bin rc t      restore rce after having seen what this is going 
255. different  If we replace the single write in the program  with two ones  like    write fd 1    Hello  n   7    write fd 1    there n   6      this is what the program prints now     8 pipe  Hello     r    the same  Plan 9 pipes preserve write boundaries  known also as message delimiters   That is to  say that for each read from a pipe  you will get data from a single write made to the pipe  This is  very convenient when you use the pipe to speak a dialog between two programs  because different  messages in the speech do not get mixed  But beware  UNIX does not do the same  This is the  output from the same program in a UNIX system     S pipe  Hello   there         In Plan 9  we need a second read to obtain the data sent through the pipe by the second write     The pipe has some buffering  usually  a few Kbytes   and that is where the bytes written by  the program were kept until they were read from the pipe  Plan 9 takes care of those cases when  data is written to the pipe faster than it is read from the pipe  If the buffer in the pipe gets full  the      111     pipe is full of bytes   Plan 9 will make the writer process wait until some data is read and there is  room in the pipe for more bytes  The same happens when data is read faster than written  If the  pipe is empty  a read operation on it will wait until there is something to read     You can see this  This program fills a pipe  It keeps on writing into the pipe until Plan 9  puts the process in the blocked state  be
256. different part in a line is delimited by  white space  For AWK  each part would be a field  This is our first AWK program  It prints the  user names for owners of processes running in this system  Similar to what could be achieved by  using sed       ps   awk     print  1 7     nemo  nemo      ps   sed    s         nemo  nemo    The program for AWK was given as its only argument  quoted to escape it from the shell  AWK  executed the program to process its standard input  because no file to process was given as an  argument  In this case  the program prints the first field for any line  As you can see  AWK is very  handy to cut columns of files for further processing  There is a command in most UNIX  machines named cut  that does precisely this  but using AWK suffices  If we sort the set of user  names and remove duplicates  we can know who is using the machine       ps   awk     print SI   sort  u  nemo  none    In general  an AWK program consists of a series of statements  of the form    pattern   action        Each record is matched against the pattern  and the action is executed for all records with a  matching one  In our program  there was no pattern  In this case  AWK executes the action for all  the records  Actions are programmed using a syntax similar to C  using functions that are either  built into AWK or defined by the user  The most commonly used one is print  which prints its  arguments     In AWK we have some predefined variables and we can define our own ones 
257. ding from  anywhere to obtain the message you want to send  but you still can send the message at any  moment  The message will interrupt the normal execution of the process  so this mechanism is to  be used with care     Posting notes can be dangerous  when the process is not paying attention to the note posted  it is killed by the system     This is our first example  we are going to use the window system to interrupt a process   When cat is given no arguments  it reads from the console  It will be doing so unless you type a  control d to ask the window to signal a  fake  end of file  This time  we are not going to do so   Run this command and press Delete     7 cat   cat waits reading     Delete   Until you press delete   A and cat is gone       What happen to cat  Let   s ask the shell       echo Sstatus  cat 735  interrupt         According to the shell  cat died because of interrupt     When you type characters  the window system reads them from the real console  Depending  on which window has the focus  i e  on which one did you click last  it sends the characters to the  corresponding window  If the window system reads a Delete key  it understands that you want to  interrupt the process in the window that has the focus  and it posts a note with the text  interrupt for all the processes sharing the window  The shell is paying attention  and ignor   ing  the note  therefore it remains unaffected  However  cat is not paying attention to it  and gets  killed in action    
258. directory  working directory  153  write  boundaries  110  137  CD  198  console  290  processing  345  write  23 55  58  61  64  75  90  atomic  91  write c  55  writer  single  244  wrkey  375  WRLock  244  wstat  72  Swsys  314  wunlock  245    X    xd  16  61 62  XML  179    Y  yield  264    Z    zipfs  224  ZP  302  312      28      Post Script    This book was formatted using the following command         eval     doctype title ms   eval     doctype preface ms   mktoc toc   troff  ms  labels SCHAPTERS   bib   pic  tbl   eqn   slant   troff  ms  mpictures  idx mkindex index   troff  ms  eval     doctype epilog ms       lp  d stdout  gt  9intro ps       Many of the tools involved are shell scripts  Most of the tools come from UNIX and Plan 9  Other tools  were adapted  and a few were written just for this book     
259. dx   100   Dx screen  gt r    sendul sliderc  val    recv mctl  gt c   amp m      while m buttons    1           Executing the program  moving the slider  and pressing Delete to kill it  leads to this output       8 slider  gt   tmp values  Delete     cat  tmp values   50   32   30    Usually  the output for the program will be the input for an application requiring a user adjustable  value  For example  the following uses the slider to adjust the volume level for the sound card in  the terminal          8 out   while v      read   echo audio out Sv  gt  gt  dev volume  Changing the slider changes the volume level       12 7  Keyboard input    Using Delete to terminate the program is rather unpolite  The program might understand a few  keyboard commands  Typing q might terminate the slider  Typing two decimal digits might set  the slider to the corresponding value  The library keyboard 2  is similar to mouse 2   but provides  keyboard input instead of mouse input  Using it may fix another problem that we had with the  slider  The program kept the console in cooked mode  Typing characters in the slider window will  make the console device  provided by rio  echo them  That was ugly     To process the keyboard  one character at a time  hence putting the console in raw mode  the  main function may call initkeyboard       Sig ini    Keyboardctl  initkeyboard char  file     This function opens the console file given as an argument  and creates a process that reads charac   ters fro
260. e  342  new  329   fids  327   field delimiter  220   fields  line  215   file  7  49  9P  327  access time  69  address  129  archive  75  attributes  67  authentication  361  368  binary  21 22  25  31  171  block  76  comparation  210  compare  116  content  15  copy  11 75  creation  65  76  deletion  66  dependencies  349  descriptor  56  58  88  102  descriptor  authentication  170  descriptor board  123  descriptor  duplicate  104  descriptor group  154  descriptor post  123  160  326  descriptor process group  153  descriptor redirection  101  descriptor table  56  153  differences  210  disk  321  display  15  dump  75  executable  19  font  312    group  69  head  195  here  116  hexadecimal dump  16  identifier  327  include  196  interface  49  179  length  69  list  72  mode  69  modification time  69  mounted  161  move  15  name  12  58  69  73  153  159  name patterns  73  object  22  offset  59  61  owner  69  ownership  18  permissions  18  Qid  327  read  robust  120  remove  11  343  rename  15  197  searching  74  server  3  24  62  123 124  159  224  321  server debugging  336  server mount  327  server program  163  321  server root directory  327  size  11  system  166  224  system  CD  225  system dump  163  system export  175  system mount  160  system protocol  159  325  system  ram  227  system  remote  174  system  semaphore  331  system snapshot  163  system  terminal  174  temporary  213  tree  13  153  159  version  328  who last modified  15  
261. e  but they cannot talk  It does not matter if the numbers  returned from pipe for the two descriptors are the same  or not  for both processes  They are dif   ferent descriptors because each process made its own call to pipe  Therefore  pipes are created  always by a common ancestor of the processes communicating through the pipe     Another important detail is that all the descriptors are closed  by all processes  as soon as  they are no longer useful  The child is going to call exec1  and the new program will read from  its standard input  Thus  the child must close both pipe descriptors after redirecting its standard  input to the end for reading from the pipe  The parent process is going to write to the pipe  but it  is not going to read  It closes the end for reading from the pipe  Not doing so risks leaving open  the pipe for writing  and in this case the reader process would never get its end of file indication     Why does the child redirect its standard input to the pipe and not the parent  We wrote the  code for the parent  We know that it has fd  1  open for writing  and can just use that descriptor  for writing  On the other hand  the child does not know  After the child executes grep  how can  grep possibly know that it should use a file descriptor other than zero for reading     The following example is a counterpart to what we made  This function creates a child pro   cess that is used to execute a command  However  this time  we return the output produced by 
262. e  have today  makes it appear that all processes can run at the same time  Each process is given a  small amount of processor time  and later  the system decides to jump to another one  This  amount of processor time is called a quantum  and can be 100ms  which is a very long time  regarding the number of machine instructions that you can execute in that time     A transfer of control from one process to another  by saving the state for the old process and  reloading the state for the new one  is called a context switch  because the state for a process  its  registers  stack  etc   is called its context  But note that it is the kernel the one that transfers con   trol  You do not include    jumps    to other processes in your programs     The part of the kernel deciding which process runs each time is called the scheduler   because it schedules processes for execution  And the decisions made by the scheduler to multi   plex the processor among processes are collectively known as scheduling  In Plan 9 and most  other systems  the scheduler is able to move a process out of the processor even if it does not call  the operating system  and gives it a chance to move the process out   Interrupts are used to do  this  Such type of scheduling is called preemptive scheduling     With a single processor  just one process may be running at a time  and many others may  be ready to run  These are two process states  see figure 2 4  The running process becomes ready  when the system termi
263. e  lt u h gt     include  lt libc h gt                 int ent   Lock entlck   void    main int  char           long last  now     switch  rfork  RFPROC RFMEM RFNOWAIT         case  1        sysfatal  fork   r       case 0   last   time nil    for        lock   amp cntlck    assert cnt  gt   0    cnt     unlock   amp cntlck     now   time nil    if  now   last  gt   1     lock   amp cntlck    print  cnt    d n   cnt    unlock   amp cntlck     last   now         default     for       lock   amp cntlck    assert cnt  gt   0    if  cnt  gt  0   cnt     unlock   amp cntlck            Also  in the parent process  both the check for cnt  gt 0 and the cnt   must be part of the same      237      critical region  Otherwise  the other process might have changed cnt between the if and its  body     The idea is simple  If you want to be sure that no other process is even touching the shared  resource while you are doing something  you must provide mutual exclusion for your critical  region  As you see  one way is to use a Lock along the shared resource  to lock it  An example  execution follows     8 cnt  t  2043  t  1    Ww  D       D  oO  Oo       OO A  Os OO  Or  Q  OO   Q  s        n  n  n  n  n  n  n  n  n  n  n    PRPRPONF AOR                The value moves in bursts  up as the child manages to increment it  and down when the parent  manages to decrement it many times  The value printed was 1 when the child finds a zero  counter  increments it  and prints its value  The value prin
264. e  not actual system calls  i e   are not implemented within the kernel   but library functions  For  example  the manual page for read 2  gives multiple functions that can be used to read a file      24      However  only one  or maybe a few  are actual system calls  The others are implemented within  the C library in terms of the real system call s   Going from one version of the system to another   we may find that an old system call is now a library function  and vice versa  What matters is that  the function is part of the programmer   s interface for a system provided abstraction  Indeed  in  what follows  we may refer to functions within the C library as system calls  Be warned  But in  any case  the entire section 2 of the manual describes the functions available     As a remark  programmer   s interfaces are usually called APIs  for Application  Programmer   s Interface     1 12  Where are the files     If you remember  we said that your files are not kept in the machine you use to execute Plan 9  commands and programs  Plan 9 calls the machine you use  a terminal  and the machine where  the files a kept  a file server  The Plan 9 that runs at your terminal lets you use the files that you  have available at other places in the network  and there can be many of them  For simplicity  we  assume that all your files are stored at a single machine behaving as the file server     How does this work  What we said about how a program performs a system call to the ker   nel  
265. e all the time  As you now know  they call sleep  0   just to abandon  the processor and let others run if the lock was held  However  because they are very similar  and  loop around  many people refer to them as spin locks     10 3  Queueing locks    How can avoid starvation in our program  The code for both processes was very similar  and had  a nice symmetry  However  the execution was not fair  At least for the child process  There is a  different kind of lock  yet another abstraction  that may be of help     A queueing lock is a lock like the ones we know  It works in a similar way  But unlike a  spin lock  a queueing lock uses a queue to assign the lock to processes that want to acquire it   The data type for this lock is QLock  and the functions for acquiring and releasing the lock are  qlock and qunlock       sig glock quniock  void glock  QLock  1   void gqunlock QLock  1           again       240      When a process calls qlock  it acquires the lock if the lock is released  However  if the lock is  held and cannot be acquired yet  the process is put in a queue of processes waiting for the lock   When the lock is released  the first process waiting in queue for the lock is the one that acquires  it     There is a huge difference between Locks and QLocks because of the queue used to wait  for the lock  First  a process is not kept spinning around waiting for a lock  It will be waiting  but  blocked  sitting in the queue of waiting processes  Second  the lock is assign
266. e client  process must obtain a connection to the server and pass its descriptor in fd  Before authentica   tion takes place  the function calls fauth to obtain a file descriptor that can be used to send and  receive messages for authenticating with the server  and keeps it in afd  In general  clients may  use the initial connection to a server to authenticate  However  for a 9P file server  you know that  a separate  authentication  descriptor is required instead     In any case  the point is that calling aut h_proxy with a descriptor to reach the server pro   cess  afd in this case  suffices to authenticate our user to the server  Auth_proxy opens   mnt factotum ctl  and loops asking factotum what to do  by doing RPCs through this  ctl file  If factotum says so  auth_proxy reads a message from the peer  by reading afd  and  writes it to factotum  to the ct1 file   If factotum  instead  asks for a message to be sent to the  peer  auth_proxy takes the message from the ct 1 file and writes it to afd        Which protocol to speak  and which role to take in that protocol  client or server   is deter   mined by the last parameters given to auth_proxy  Such parameters are similar to the argu   ments for print  to permit may different invocations depending on the program needs  In our  case  we gave just the format string     proto p9any role client     But passing more arguments in the style of print can be done  for example  to specify the user  for the key  like here     char  
267. e created  This is done with the exec system call  This call  receives two parameters  a file name that corresponds to the executable file that we want to exe   cute  and its argument list  The argument list is an array of strings  with one string per argument     If we know the argument list in advance  when we write the program   another system call  called execl is more convenient  It does the same  but lets you write the arguments directly as  the function arguments  without having to declare and initialize an array  We are going to use this  call here     This is our first example program     92         execl c     include  lt u h gt      include  lt libc h gt     void  main int  char           print   running l1s n          execl   bin 1ls    ls     1     usr nemo   nil    print   exec failed   r n            When run  it produces the following output       8 execl  running ls    d rwxrwxr x M 19 nemo nemo 0 Jul 11 18 11  usr nemo bin  d rwxrwxr x M 19 nemo nemo 0O Jul 11 21 24  usr nemo lib  d rwxr xr x M 19 nemo nemo 0 Jul 11 21 13  usr nemo tmp    The output is produced by the program found in  bin 1s  Clearly  our program did not read a  directory nor print any file information  Furthermore  the output is the same printed by the next  command       ls  1  usr nemo    d rwxrwxr x M 19 nemo nemo 0 Jul 11 18 11  usr nemo bin  d rwxrwxr x M 19 nemo nemo O Jul 11 21 24  usr nemo lib  d rwxr xr x M 19 nemo nemo 0 Jul 11 21 13  usr nemo tmp    This is what the execl call d
268. e directories  and might contain other files     Figure 1 5 shows a part of the file tree in the system  relevant for user Nemo  You see now  that the files bin  1ib  and tmp files that we saw in some of the examples above are kept within  a directory called nemo  To identify a file  you name the files in the path from the root of the tree   called slash  to the file itself  separating each name with a slash     character  This is called a  path  For example  the path for the file 1ib shown in the figure would be  usr nemo 1lib   Note how  tmp and  usr nemo tmp are different files  depite using the name tmp in both  cases     The first directory at the top of the tree  the one which contains everything else  is called the  root directory  guess why    It is named with a single slash        Bee   386   usr   tmp       other files omitted       r    That is the only file whose name may have a slash on it  If we allowed using the slash within a  file name  the system would get confused  because it would not know if the slash is part of a  name  or is separating different file names in a path     Typing paths all the time  for each file we use  would be a burden  To make things easier for  you  each program executing in the system has a directory associated to it  It is said that the pro   gram is working in that directory  Such directory is called the current directory for the program   or the working directory for the program     When a program uses file names that are paths no
269. e discussing other details of this program  let   s see how the whole program looks like   ticker c     include  lt u h gt     include  lt libc h gt     enum   Npanels   2       all the code shown above for Msg  reader  and panelproc     void    main int  char             int i   for  i   0  i  lt  Npanels  i     if  rfork  RFPROC RFMEM RFNOWAIT     0        panelproc  1    reader         does not return            It creates one process per panel  and then executes the reader code using the parent process  To  test the program  we used the standard output as the file descriptor to write to each one of the pan   els     When a program is built using multiple processes  it is important to pay attention to how the  program is started and how is it going to terminate  In general  it is best if the program works no  matter the order in which processes are started  Otherwise  initialization for the program will be  more delicate  and may fail mysteriously if you make a mistake regarding the order in which pro   cesses are started  Furthermore  you do not know how fast they are going to run  If you require  certain order for the starting up of processes  you must use a synchronization tool to guarantee  that such order is met     For example  a panelproc should not write a message to its panel before there is at least  one message to print  All panelprocs should be waiting  silently  until reader has got the  chance of reading the first message and updating the data structure  The 
270. e files  stored are encrypted with the user key before sending them to the secstore     The most popular use for secstore is keeping a file with all the keys for a user  using the  format expected by factotum  When a user has an account in the secstore file server   factotum prompts the user for the secret used to access such store  Then  it retrieves a file  named factotum from the secure store for the user that is supposed to contain all the user keys   Because all the keys are now known to factotum  the user is no longer bothered to supply  secrets     14 8  What now     Before concluding  it seemed necessary to note that there are many other tools for security in Plan  9  like in most other systems  Not to talk about tools for cryptography  which are the building  blocks for security protocols and therefore  also available in the system     For example  it is important in a distributed system to encrypt the connections between pro   cesses running at different machines so that causal users tapping on the network do not see the  data exchanged in clear     While using Plan 9  the commands provided by the system try to make sure that the system  remains secure  For example  passwd may be run only on a terminal  to change the password   Running it on a CPU server would mean that the characters might be sent in clear from the termi   nal to the CPU server  These days  connections to CPU servers are usually encrypted  but time  ago this was an issue and passwd refused to run a
271. e files terminated in   cc to files terminated in    C   in case you thought it twice and decided to use C instead of C     We make some attempts  before writing the command that does it       echo foo cc   sed    s  cc  Cc g     foo c     f f00 cc     nf     fecho  f   sed    s  cc  c g        echo Snf   foo c      for  fin   ec   f      nf      echo Sf   sed    s  cc  c g      eb  Sn SOR SNT    ri     i all of them renamed   At this point  it should be easy for you to understand the command we used to generate the array  initializer for hexadecimal numbers  sed  e  s    0x    e  5         It had two editing commands  therefore we had to use  e for both ones  The first one replaced the    start of a line with    0x     thus  it inserted this string at the beginning of line  The second inserted     w     at the end of line       198      8 7  Moving files around    We want to copy all the files in a file tree to a single directory  Perhaps we have one directory per  music album  and some files with songs inside       du  a   1   alanparsons irobot  mp3   1   alanparsons whatgoesup mp3  2   alanparsons   1   pausini trateilmare mp3   1   pausini   1   supertramp logical mp3   1   supertramp   4    But we may want to burn a CD and we might need to keep the songs in a single directory  This  can be done by using cp to copy each file of interest into another one at the target directory  But  file names may not include    and we want to preserve the album name  We can use sed to s
272. e is only a single program for those processes  Namely  that kept stored in the file  bin  rce   Furthermore  if we change the working directory in a shell  the other two ones remain unaffected   Try it  Suppose that the program rc keeps in a variable the name for its working directory  Each  shell process has its own current working directory variable  However  the program had only one  such variable declared        Figure 2 1  Three  bin rc processes  But just one  bin rc     So  what is a process  Consider all the programs you made  Pick one of them  When you  execute your program and it starts execution  it can run independently of all other programs in  the computer  Did you have to take into account other programs like the window system  the sys   tem shell  a clock  a web navigator  or any other just to write your own  independent  program  and execute it  Of course not  A brain with the size of the moon would be needed to be able to  take all that into account  Because no such brains exist  operating systems provide the process  abstraction  To let you write and run one program and forget about other running programs     Each process gets the illusion of having its own processor  When you write programs  you  think that the machine executes one instruction after another  But you always think that all the  instructions belong to your program  The implementation of the process abstraction included in  your system provides this fantasy      30     When machines have seve
273. e mount system call receives two file descriptors  and not just one  even though a file  descriptor for a connection to a file server is all we need to speak 9P with it        sig mount  int mount  int fd  int afd  char  old  int flag  char  aname     The fd descriptor is the connection to the file server  The second one  afd  is called an  authentication file descriptor  used to authenticate to the file server  Before calling mount  a pro   cess calls fauth to authenticate its user to a file server at the other end of a connection       sig fauth  int fauth int fd  char  aname     For example  if the file descriptor 12 is connected to a file server     afd   fauth 12   main      obtains an authentication file descriptor for authenticating our user to access the file tree main in  the file server  This descriptor is obtained by our system using a Tauth 9P request  And now  comes the hard part  We must negotiate with the file server a particular authentication protocol to  use  Furthermore  we must exchange messages by reading and writing afd according to that pro   tocol  to give proof of our identity to the file server  This is complex and is never done by hand   Assuming we already made it  afd can be given to mount  to prove that we have been already  authenticated  For example  like in    mount  12  afd    n remote   MREPL   main          In most cases  the library function amount does this  So  it would have been the same to do just         amount  12    n remote   MREPL
274. e new line character terminates a line only because programs  in Plan 9  and UNIX  follow the convention that lines terminate with a  n character  The termi   nal shows a new line when it finds a  n  programs that read files a line at a time decide that they  get a line when a  n character is found  etc  It is just a convention              Windows  and its ancestor MSDOS  uses a different format to encode text lines  and termi   nates each line with two characters       r n     or carriage return  and new line   This comes from  the times when computers used a typewriter machine for console output  The former character    xv  makes the carriage in the typewriter return to its left position  We have to admit  there are no  typewriters anymore  But the character  r makes the following text appear on the left of the line   The  n character advances  the carriage  we are sorry  to the next line  That is why  n is also  known as the line feed character  A consequence is that if you display in Plan 9 a Windows text  file  you will see one little control character at the end of each line       cat windowstext  This is one line   and this is another     r    That is the  r  Going the other way around  and displaying in Windows a text typed in Plan 9   may produce this output    This is one line  and this is another    because Windows misses the carriage return character     Now that we can see the actual contents of a file  there is another interesting thing to note   There is no EO
275. e not sure about removing  a file  just don   t do it  Or move it to  tmp or to some other place where it does not gets in your  way    Now that we can create and remove files  it is interesting to see if a file does exist  This  could be done by opening the file just to see if we can  However  it is more appropriate to use a  system call intended just to check if we can access a file  It is called  perhaps surprisingly   access  For example  this code excerpt aborts the execution of its program when the file name  in fname does not exist        if  access fname  AEXIST   lt  0   sysfatal   s does not exist   fname      The second parameter is an integer constant that indicates what do you want access to check  the file for  For example  AWRITE checks that you could open the file for writing  AREAD does  the same for reading  and AEXEC does the same for executing it                             3 5  Directory entries    Files have data  There are many examples above using cat and xd to retrieve the data stored in a  file  Besides  files have metadata  i e   data about the data  File metadata is simply what the sys   tem needs to know about the file to be able to implement it  File metadata includes the file name   the file size  the time for the last modification to the file  the time for the last access to the file   and other attributes for the file  Thus  file metadata is also known as file attributes       68      Plan 9 stores attributes for a file in the directory that c
276. e process out of the processor or move it back to it   The result is that we do not know how the two sequences of instructions  one for each process    will be merged in time  Despite having just one processor that executes only a sequence of  instructions  any merge of instructions from the first and the second process is feasible  Such a  merge is usually called an interleaving     Perhaps one process executes all of its statements  and then second  This happen to the for  loop in all but the last version of the program  On the other hand  perhaps one process executes  some instructions  and then the other  and so on  Figure 10 1 shows the interleaving of statements  that resulted from our last modification to the program  along with the values for the two local  variables loc  and the global cnt  The initial call to rfork is not shown  The statements corre   sponding to the loop itself are not shown either     What you see is that something happens while one process is happily incrementing the vari   able  by copying the global counter to its local  incrementing the local  and copying back the local  to the shared counter  While one process is performing its increment  the other process gets in the  way  In the sequence of statements    loc   cnt   loctt   ent   loc     we assume that right after the the first line  loc has the value that is kept in the shared variable   We further assume that when we execute the last line  the global variable cnt has the value it had  whe
277. e read from a last  but partial record   0 in our case   And the same for writing  Today  it is very common to see  always  0 for both the data read in  and the data written out  By the way  for our little experi   ment we could have used just dd  instead of writing our own dumb version for it  but it seemed  more appropriate to let you read the code to review file I O once more     So  what would happen when we copy our file using our default buffer size of 8Kbytes       time 8 bcp  tmp sfile  tmp dfile  0 01lu 0 01s 0 40r 8 bcp  tmp sfile  tmp dfile    Using the command t ime  to measure the time it takes for a command to run  we see that using a  8Kbyte buffer it takes 0 4 seconds of real time  0 401  to copy a 1Mbyte file  As an aside   time reports also that 8   bcp spent 0 01 seconds executing its own code  0   01u  and 0 01 sec   onds executing inside the operating system  0 01s   e g   doing system calls  The remaining  0 38 seconds  until the total of 0 4 seconds  the system was doing something else  perhaps execut   ing other programs or waiting for the disk to read or write      What would happen reading one byte at a time   and writing it  of course        time 8 bcp  b 1  tmp sfile  tmp dfile  9 01lu 56 48s 755 31r 8 bcp  b 1  tmp sfile  tmp dfile    Our program is amazingly slow  It took 755 31 seconds to complete  That is 12 6 minutes  which  is an eon for a computer  But it is the same program  we did not change anything  Just this time   we read one byte at a
278. e seems to be no memory leaks  However  doing the  same for a program called omero  reported some memory leaks       356        leak  s omero rc    src 0x0000dd77      7  src 0x000206a8      3  src 0x000213bc      3  src 0x00027e68      3  src 0x00027fe7      2  src 0x00002666      1  src Ox0000c6ff        1    Each line can be used as a command for the debugger to find the line where the memory  leaked   was allocated  Using      src  s 0x0000dda77 omero    would point our editor to the offending source line that leaked 7 times some memory  as reported  by the first line in the output of Leak  Once we know where the memory was allocated  we may  be able to discover which call to free is missing  and fix the program     Problems  1 Convert the printer spooler program from a previous problem into a file server       357      14     Security    14 1  Secure systems    Security is a topic that would require a book on its own  Here we just show the abstractions and  services provided by Plan 9 to secure the computer system  But in any case you should keep in  mind that the only secure system is one that is powered down  and also kept under a lock    As  long as the system can perform tasks  there is a risk that some attacker convinces the system to do  something that it should not legitimately do     In general  there is a tradeoff between security and convenience  For example  a stand alone  Plan 9 machine like a laptop that is not connected to the network does not ask for a pas
279. e simple to let you use the programming language to customize whatever you  want in the process before it runs a new program     Before going any further  this is a complete example using both system calls  This program cre   ates a new process by calling fork  and executes  bin ls in the new process by calling  execl        runls c     include  lt u h gt      include  lt libc h gt     void  main int  char         switch  fork       case  1l   sysfatal   fork failed     case 0     execl   bin ls    ls   nil         break   default    print   ls started n        exits  nil           The process running this program proceeds executing main  and then calls fork  At this point   a new process is created as an exact clone of the one we had  Both processes continue execution  returning from fork  For the original process  the parent process   fork returns the pid for the  new process  Because this is a positive number  it enters the default case  For the new process      84      the child process   fork returns zero  So  the child process continues executing at case 0   The child calls exec1  which clears its memory and loads the program at  bin 1s for execu   tion     We will now learn about each call at a time  to try to understand them well     4 2  Process creation  The system call fork creates an exact clone of the calling process  What does this mean  For  this program    onefork c    include  lt u h gt                    include  lt libc h gt     void   main int  char       
280. e talk about Plan 9  this program is more appropriate than the one you are thinking on  If you  don   t know why  you did not use Internet to discover why this system has this name     291 3    take c     include  lt u h gt      include  lt libc h gt     void   main int  char          print   take me to your leader  n     exits  nil           This program is just text stored in a file  To execute it  we must compile it and then link the pro   gram with whatever libraries are necessary  in this case  the C library   There is one command for  each task       8c take c   compile it    81l take 8   link the resulting object    7    As you see  the shell ignores text following the   sign  That is the line comment character for rc   That is usual in most shells found in other systems  like UNIX  The C compiler for Intel architec   tures is 8c  80x86 compiler  and 81 is the linker  In Plan9  81 is called a loader  because it pre   pares the way for loading the resulting program into memory   Object files generated by 8c use  the extension   8  to make it clear that the object is for an Intel  it reminds of 8086   The binary  file produced by linking the object file s  and the libraries implied is named 8   out  when using  81  This binary has execute permission and can be executed     In Plan 9 there are many C compilers  One for each architecture where the system runs   And  as it could be expected  each compiler has been compiled for all the architectures where the  system runs  F
281. e the attribute name was pre   fixed with a   sign  factotum understands that it is an important secret  not to be shown while  reading ctl  In general  factotum does its best to avoid disclosing secrets  It keeps them for  itself  for use when speaking the authentication protocols involved  Look what happens below       ps   grep factotum   nemo 6 0 00 0 00 268K Pread factotum    acid 6    proc 6 text 386 plan 9 executable     lt stdin gt  1   error  setproc  open  proc 6 mem  permission denied   sys lib acid port    sys lib acid 386   no symbol information   acid     You cannot debug factotum  It protects its memory  to prevent any process from reading its mem   ory and obtaining the keys it maintains  This can be done to any process by by writing the string  private to the process ct1 file  That is what factotum did to itself to keeps its memory  unreadable from outside  In the same way  factotum wrote noswap to its process control file  to  ask Plan 9 not to swap its memory out to disk when running out of physical memory     It is now clear how add keys to factotum  But now  how can a process authenticate  A      364      process can authenticate to another peer process by relying messages between its factotum and the  other peer  As figure 14 1 shows  during authentication  a client process would simply behave as  an intermediary between its factotum and the server  When its factotum asks the process so send a  message to the other end  it does so  When it asks the proce
282. e this exercise there as well     4 Does your TV set remote control have its own operating system  Why does your mobile  phone include an operating system  Where is the shell in your phone     5 Explain this     2 ake   bin lib tmp   oS   ls       bin ls     file does not exist    6 How many users do exist in your Plan 9 system   7 What happens if you do this in your home directory  Explain why     s2 ee      touch a  j mvaa    8 What would happen when you run this  Try it and explain     mkdir dir    touch dir a dir b    em aie    mv dir  tmp    9 And what if you do this  Try it and explain       mkdir dir dir b    cd dir b   eM a AD     pwd     28      29      2     Programs and Processes    2 1  Processes    A running program is called a process  The name program is not used to refer to a running pro   gram because both concepts differ  The difference is the same that you may find between a cookie  recipe and a cookie  A program is just a bunch of data  and not something alive  On the other  hand  a process is a living program  It has a set of registers including a program counter and a  stack  This means that it has a flow of control that executes one instruction after another as you  know     The difference is quite clear if you consider that you may execute simultaneously the same  program more than once  For example  figure 2 1 shows a window system with three windows   Each one has its own shell  This means that we have three processes running  bin  rc  although  ther
283. e we plan to use rsleep and rwakeup   The operation put will have to sleep  when the buffer is full  and we need a Rendez called isfull to sleep because of that reason   The operation get will go to sleep when the buffer is empty  which makes necessary another  isempty Rendez  To store the messages we use an array to implement a queue  The array is  used in a circular way  with new messages added to the position pointed to by t1  Messages are  extracted from the head  pointed to by hd     typedef struct Buffer Buffer   struct Buffer    QLock Iek     char  msgs  Nmsgs      messages in buffer   int hd     head of the queue   int tl     tail  First empty slot    int nmsgs     number of messages in buffer   Rendez isfull     to sleep because of no room for put  Rendez isempty     to sleep when nothing to get          This is our first operation  put  It checks that the buffer is full  and goes to sleep if that is the  case  If the buffer was not full  or after waking up because it is no longer full  the message is  added to the queue     void      253      put  Buffer  b  char  msg               glock   amp b  gt 1ck      if  b  gt nmsgs    Nmsgs   rsleep   amp b  gt isfull    b  gt msgs b  gt tl    strdup  msg      b  gt tl     b  gt tl   Nmsgs   b  gt nmsgst t   if  b  gt nmsgs    1    rwakeup   amp b  gt isempty     gqunlock   amp b  gt 1lck      Note how this function calls rwakeup   amp b  gt isempty  when the buffer ceases to be empty  It  could be that some processes were 
284. e when more than one file is given  we could  use  dev null1 as a second file where to search for the line  It would not be there  but it would  make grep print the file name       grep      cat       sys src cmd cat c  dev null   sys src cmd cat c cat int f  char  s     Giving the option  n to grep makes it print the line number  Now we can really search for func   tions  like we do next       grep  n     cat       sys src cmd   c   sys src cmd cat c 5  cat int f  char  s     And because this seems useful  we can package it as a shell script  It accepts as arguments the  names for functions to be located  The command grep is used to search for such functions at all  the source files in the current directory        bin re  rfork e  for  f in      grep en HASEENO     ch     How can we use grep to search for    n  If we try  grep would get confused  thinking that we  are supplying an option  To avoid this  the  e option tells grep that what follows is a regexp to  search for     7  cat text   Hi there   How can we grep for  n   Who knows      grep  n text   grep  e   n text   how can we grep for  n     This program has other useful options  For example  if may want to locate lines in the file for a  chapter of this book where we mention figures  However  if the word figure is in the middle of  a sentence it would be all lower case  When it is starting a sentence  it would be capitalized  We  must search both for Figure and figure  The flag  i makes grep become case insensitive 
285. e will use file names at  dev  but it should be clear that  they are provided by rio       316        cat  dev winid   che newline supplied by us    cat  dev winname  window 3 3    newline supplied by us    The window id  kept at winid  is a number that identifies the window  The directory   dev wsys contains one directory per window  named after its identifier  In our case  rio is  running just two windows       Ic  dev wsys    J  3     Ic  dev wsys 3   cons cursor label screen text wdir winid wsys  consctl kbdin mouse snarf wetl window winname    Each window directory contains all the files we are accustomed to expect for using the console  and related devices  For each window  rio   makes its files also available in its root directory  so that a bind of the rio file system at  dev  will leave the appropriate files in  dev  and not just in  dev wsys 3 ora similar directory     The file winname contains the name for the image in the draw device that is used as the  screen for the window  The draw device may keep names for images  and the window system  relies on this to coordinate with programs using windows  Rio creates the image for each win   dow  and gives a name to it that is kept also in winname  The function get window  called by  initdraw  uses this name to locate the image used for the window  That is how your graphic  programs know which images are to be used as their screens     The file label contains a text string for labeling the window  That is  the file   dev
286. e window system  Therefore   each process is entitled to a user  for identification purposes  In a terminal  all the processes are  usually entitled to the host owner  But how can this happen     What happens is that the initial process  boot was initially running on the name of the user  none  which represents an unknown user  After a user name was given to boot  while booting  the terminal  it wrote such user name to  dev user and  from there on  the boot process was  running on the name of nemo  The file  dev user provides the interface for obtaining and  changing the user name for the current process  for the one reading or writing the file   The user  name can only be set once  initially  From there on  the user name can only be read but not  changed  For example  the following happens when using the user name for our shell       cat  dev user   nemo      echo  n pepe  gt  dev user   echo  write error  permission denied       Child processes inherit the user name from their parents  So  all the processes in your terminal are  very likely to be owned by you  because they all descend from the boot process  that changed its  ownership to your user name     It is important for you to notice that only the local machine trusts this  And that you might  perfectly change the kernel in your terminal to admit doing weird things like changing   dev user  Other machines do not trust this information at all  As a result  running a custom  made kernel just to break into the system wou
287. e would match a  b  or 3  but not x  A set of char   acters  but starting with    matches any character not in the set  For example    abc123   matches x  but not 1  which is in the string that follows the    A range may be used  like in   a z0 9   which matches any single character that is a letter or a digit     y        matches a and b  but not       A single    matches the start of the text  And a single    matches the end of the text   Depending on the program using the regexp  the text may be a line or a file  For example   when using grep  a matches the character a at any place  However   a matches a only  when it is the first character in a line  and  a  also requires it to be the last character in the  line        Two regular expressions concatenated match any text matching the first regexp followed by  any text matching the second  This is more hard to say than it is to understand  The expres   sion abc matches abc because a matches a  b matches b  and so on  The expression   a z x matches any two characters where the first one matches  a z   and the second  one is an x        Adding a   after a regular expression  matches zero or any number of strings that match the  expression  For example  x  matches the empty string  and also x  xx  xxx  etc  Beware   ab  matches a  ab  abb  etc  But it does not match abab  The   applies to the preceding      202      regexp  with is just b in this case        Adding a   after a regular expression  matches one or more strings th
288. e yields mouse events  However  this file may not be open more  than once at the same time       cat     m mouse     cat  can   t open  m mouse    m mouse    device or object already in use    Since rio has open  m mouse  to read mouse events  nobody else will be able to open it until  rio terminates and the file is closed  This is a safety measure to avoid multiple programs to use  this device at the same time  In any case  the multiplexed version of the mouse   dev mouse   provided by rio for each window is for us to read       cat  dev mouse    m 670 66 0 2257710 m 676  68 0 2257730 m 677 74  0 2257750 m 680 77 0 2257770    This file will never seem to terminate  No end of file indication for it  Indeed   dev mouse is a  stream of mouse events  Each read will block until the mouse produces an event  it is moved or a  button is pressed or released   At that point   dev mouse returns 49 bytes  There is an initial  letter m followed by four numbers  the x and y coordinates for the mouse  a number stating which  buttons are pressed  and a time stamp     The time stamp is handy when a program wants to detect double and triple clicks  In Plan 9   the mouse might be attached even to a different machine  The time for the clicks that matters is  that of the machine with the mouse  when the mouse events were received from the hardware by  the mouse driver  The time as seen by the program reading the mouse might differ a little bit   there may be delays between different mouse events
289. each date  For example   n dump 2002 0217 is the path for the dump   copy  made in February 17th  2002  The command below uses a pattern to list directories for  dumps made the 17th of any month not after June  in a year beyond 2000  but ending in 2  i e    just 2002 as of today        ls  n dump 2 2 0 1 6 17   n dump 2002 0117   n daump 2002 0217   n dump 2002 0317   n daump 2002 0417   n dump 2002 0517   n daump 2002 0617    In general  you concoct patterns to match on file names that may be of interest for you  The shell  knows nothing about the meaning of the file names  However  you can exploit patterns in file  names using file name patterns  Confusing     To ask the shell not to touch a single character in a word that might be otherwise considered  a pattern  the word must be quoted  For example     z ule   bin lib tmp  s Couch  CA     echo        bin lib tmp    Because the   for touch was quoted  the shell took it verbatim  It was not interpreted as a pat   tern  However  in the next command line it was used unquoted and taken as a pattern  Removing  the funny file we just created is left as an exercise  But be careful  Remember what    zo Sem A    would do     3 7  Buffered Input Output    The interface provided by open  close  read  and write suffices many times to do the task  at hand  Also  in many cases  it is just the more convenient interface for doing I O to files  For  example  cat must just write what it reads  It is just fine to use read and write for imple
290. ean variables  but we declared cnt 1ck  as a structure Lock  This is how Lock is defined in libc h    typedef  struct Lock     int val     Lock     The lock is also a shared variable  It would not make sense to give each process its own lock  The  lock is used to synchronize both processes  to make them agree upon when is it safe to do some   thing  Therefore  it must be shared  That means that if you write two C functions for implement   ing lock and unlock  they would have race conditions     The implementation for unlock is simple  it sets Lock  val to false  The implementation  for lock is more delicate  It is made in assembly language to use a single machine instruction  capable of consulting the lock and modifying it  all that within the same instruction  That is rea   sonable  If we do not both consult the lock  to see if it is set  and update it within an atomic  instruction  there would be race conditions  There are several kinds of test and set instructions   that test a variable for a value but also modify it  A famous one is precisely called TAS  or test  and set        Using TAS  here is a description of how to implement a lock function        loop   MOVL lock  AO put address of lock in register AO  TAS  A0  test and set word at memory address in AO  BNE loop if the word was set  continue the loop  RTS return otherwise    To emphasize it even more  the key point why this works at all is because TAS is atomic  It puts a  non zero value at the address for the lock 
291. ec    print   lsys  t s n   i  gt lsys    print   lserv  t s n   i  gt lserv    print   rsys  t s n   i  gt rsys    print   rserv  t s n   i  gt rserv    print   laddr  t s n   i  gt laddr     print   raddr  t s n   i  gt raddr     freenetconninfo i      close  fd      exits nil        144        8 out tcp whale 9fs    dir   net tcp 46  root   net   spec   10   lsys   212 128 4 124  lserv  6672   rsys  193 147 71 86    rserv  564  laddr  tcep 212 128 4 124 6672  raddr  tcp 193 147 71 86 564       The line directory for this connection was  net  tcp 46  which belongs to the network inter   face at  net  This connection was using  10  which is the first IP interface for the machine   The remaining output should be easy to understand  given the declaration of the structure above   and the example output shown        6 4  Providing services    We know how to connect to processes in the network that may be providing a particular service   However  it remains to be seen how to provide a service  In what follows  we are going to imple   ment an echo server  A client for this program would be another process connecting to this ser   vice to obtain an echo service  This program provides the service  i e   provides the echo  and is  therefore a server  The echo service  surprisingly enough  consists on doing echo of what a client  writes  When the echo program reads something  writes it back through the same connection  like  a proper echo     The first thing needed is to announce the 
292. echo usage   0  gt  1 2     exit usage    3   exec sed  s          r    Searching for differences is not restricted to comparing just two files  In many cases we want to  compare two file trees  to see how they differ  For example  after installing a new Plan 9 in a disk   and using it for some time  you might want to see if there are changes that you made by mistake       212      Comparing the file tree in the disk with that used as the source for the Plan 9 distribution would  let you know if that is the case     This tool  diff  can be used to compare two directories by giving their names  If works  like above  but compares all the files found in one directory with those in the other  Of course   now it can be that a given file might be just at one directory  but not at the other  We are going to  copy our whole Shome bin to a temporary place to play with changes  instead of using the  whole file system     i     cd  tar c bin        cd  tmp   tar x      Now  we can change t  in the temporary copy  by copying the tab script we recently made  We  will also add a few files to the new file tree and remove a few other ones     cp tab  tmp bin rc tt  cp rcecho  tmp bin rc  rm  tmp bin rc   da2h h2d     Ne Ne Ne T    So  what changed  The option  r asks diff to go even further and compare two entire file  trees  and not just two directories  It descends when it finds a directory and recurs to continue the  search for differences       diff  r  Shome  tmp   bin   Only in  usr ne
293. ection between parenthesis  as in acme 1   This page refers to a command   because the section is 1  and the name for the page  i e   the name of the command  is acme     From the shell  you can use the man command to access the system manual  If you don   t  know how to use it  here is how you can learn to do it       man man    Asks the manual to give its own manual page       man man  MAN  1  Plan 9     4th edition MAN  1     NAME       man  lookman  sig   print or find pages of this manual    SYNOPSIS  man    bnpPStw     section       title    lookman key    sig function                   DESCRIPTION  Man locates and prints pages of this manual named title in  the specified sections  Title is given in lower case  Each    As you can see  you can give to man the name of the program or library function you are inter   ested in  It displays a page with useful information  If you are doing this in the shell  you can use  the down arrow key           to page down the output  To read a manual page found at a particular  section  you can type the section number and the page name after the man command  like in      man 1 1s    If you look at the manual page shown above  you can see several sections  The synopsis section  of a manual page is a brief indication on how to use the program  or how to call the function if  the page is for a C library   This is useful once you know what the program does  to avoid re   reading the page again  In the synopsis for commands  words following 
294. ectory  68  328   point  program  35   env  157   file system  51  env c  44  environment   group  158   process  83   process group  153   variable  49  51  73  93  153  157  180  Environment variables  153  environment variables  42          EOF  17  address  195  epoch  50  erealloc9p  340  err c  4l  errfun  301  error  47  redirection  standard  188  standard  56 57  106  string  40  67  95  system call  40  67  92   Errors  see acme  Escape  290  escape  character  11  44  202  key  290  etext  33  ether0  135  ethernet  135  etticker c  282  event  125  128  channel  128  channel  mouse  297  mouse  295  processing  mouse  304  resize  303  305  everything is a file  49  evil  357  exception  47  118  exclusion  mutual  234 235  256  exclusive open  295  exec  83 91  93  header  97  execl  83  91 92  103  114  execl c  92  executable  97  file  19  executing commands  6  execution  conditional  188  independent  29  84  parallel  30  process  230  program  26  83  91  285  pseudo parallel  30  remote  174  remote command  151  Exit  8  exit status  39  43  48  95  188  exits  23  39  84  95  243  262  expansion  variable  73  export  file system  175  exportfs  175  expression             arithmetic  98  183   compiler  regular  205   inner  202   regular  129  201  extraction  archive  199    F    faces  125   factotum  362  375   fault  47   fauth  361   Fcall  336   fd file  process  58       d file system  102  171   fdisk  323   fhello c  60   Fid  338   fid  clon
295. ed  This happens to many other programs that search for things  For  example  we have used grep to print only lines containing a string  Well  the string given to  grep  like in      grep string filel file2    is not a string  It is a regular expression  A regular expression is a little language  It is very use   ful to master it  because many commands employ regular expressions to let you do complex  things in an easy way    The text in a regular expression represents many different strings  You have already seen  something similar  The    c in the shell  used for globbing  is very similar to a regular expres   sion  Although it has a slightly different meaning  But you know that in the shell      c matches  with many different strings  In this case  those that are file names in the current directory that hap   pen to terminate with the characters     c     That is what regular expressions  or regexps  are for   They are used to select or match text  expressing the kind of text to be selected in a simple way   They are a language on their own  A regular expression  as known by sed  grep  and many oth   ers  is best defined recursively  as follows        Any single character matches the string consisting of that character  For example  a matches  a  but not b     e A single dot           matches any single character  For example        ab        A set of characters  specified by writing a string within brackets  like  abc123   matches  any character in the string  This exampl
296. ed a few files necessary to automatically start the window system when you enter the system   This is why you got some error messages complaining about some missing files  The only file  created for you was a folder  we use the name directory  where you can save your files  That  directory is your home directory        Figure 1 2  Your terminal after entering rio  Isn   t it a clean window system     Proceeding is simple  If you execute       sys lib newuser    the newuser program will create a few files for you and start rio  the Plan 9 window system   To run this command  type  sys 1ib newuser and press return  All the commands are exe   cuted that way  you type them at the shell prompt and press return     Running newuser is only necessary the first time you enter the system  Once executed   this program creates for you a profile file that is executed when you enter the system  and  starts rio for you  The profile for the user nemo is kept in the file   usr nemo lib profile  Users are encouraged to edit their profiles to add any command  they want to execute upon entering the system  to customize the environment for their needs  To  let you check if things went right  figure 1 2 shows your screen once rio started     1 3  Leaving the system    To leave your terminal you have all you need  Press the terminal power button  don   t look at the  window system for it  and switch it off  Because the files are kept in the file server  any file you  changed is already kept safe in
297. ed to processes in a  very fair way  The first process that entered the queue to wait for the lock would be the first to  acquire it after the lock is released  Because of both reasons  it is always a good idea to use  QLocks instead of Locks  The spin locks are meant for tiny critical regions with just a few  instructions  For example  the data structure used to implement a QLock is protected by using a  Lock  Such spin lock is held just for a very short time  while updating the QLock during a call  to qlock or qunlock     Our  in famous program follows  but using queueing locks this time     qent c          include  lt u h gt                 include  lt libc h gt     IAE cnt  QLock entlck     void  main int  char           long last  now     switch  rfork  RFPROC RFMEM RFNOWAIT            case  1   sysfatal  fork  Sr     case 0   last   time nil    for          glock   amp cntlck    assert  cnt  gt   0    Cnty     print   Sd n   cnt         qunlock   amp cntlck        241      default   for       glock   amp cntlck    assert  cnt  gt   0    if  cnt  gt  0   cnt     print   Sd n   cnt    gunlock    cntlck           Note the huge difference in behavior  An execution for this program follows  As you can see  this  time  both processes take turns  This happens because of the queue  The lock is assigned in a very  fair way  and both processes get a chance to do their job     8 gent    OP     FO ese    To do something more useful  we are going to implement a tool to update ticker
298. eed  Let   s search for that program       lookman arithmetic expression  man 1 2c   2c 1     man 1 awk   awk 1   man 1 be   bc 1    man 1 hoc   hoc 1   man 1 test   test  1   man 8 prep   prep 8     There are several programs shown in this list that we might use to do arithmetic  In general  hoc  is a very powerful interactive floating point calculation language  It is very useful to compute  arbitrary expressions  either by supplying them through its standard input or by using its  e  option  which accepts as an argument an expression to evaluate       NOG ee TZE 2   4    echo 2   2   hoc   4  Hoc can do very complex arithmetic  It is a full language  using a syntax similar to that of C  It  reads expressions  evaluates them  and prints the results  The program includes predefined vari   ables for famous constants  with names E  PI  PHT  etc   and you can define your own  using the  assignment  For example          hoc   r 3 2   PDL Re RP   32 16990877276  control d    r    defines a value for the radius of a circle  and computes the value for its area     But to do the task we have at hand  it might be more appropriate another calculation pro   gram  called bc  This is program is also a language for doing arithmetic  The syntax is also simi   lar to C  and it even allows to define functions  like Hoc   Like before  this tool accepts expres   sions as the input  It evaluates them and prints the results  The nice thing about this program is  that it has a simple way of chang
299. een  setrect  setcol  nil  ZP    draw screen  unsetrect  unsetcol  nil  ZP      draw screen  markrect  display  gt black  nil  ZP    flushimage  display  1       If the value represented by the slider is val  in the range  0 100   and our window is Dx pixels  wide  then  the offset for the x coordinate in the window that corresponds to val is defined by  val     D Cs  vee T00    A zero value would be a zero offset  A 100 value would mean a Dx offset  The function Dx  returns the width of a rectangle  there is also a Dy function that returns its height   So     dx   Dx screen  gt r    val   100       309      computes the offset along the x axis that corresponds to the value for the slider  Once we know  dx  defining the rectangle for set rect is straightforward  We take initially the rectangle for the  window and change the max  x coordinate to cut the rectangle at the offset dx in the window   The markrect is initialized in the same way  but occupies just the next two pixels on the x axis   past setrect  The rectangle unset rect goes from that point to the end of the x axis     What remains to be done is to change mousethread to let the user adjust the slider using  the mouse  The idea is that holding down the button 1 and moving it will change the slider to the  point under the mouse    void  mousethread void  arg          Mousect1l mctl   arg   Mouse m   int dx  val   for       recv mctl  gt c   amp m    if m buttons    1     do    dx   m xy x   screen  gt r min x   val   
300. eep with a mutex taken  Only a few times it might be the right thing to do  and you must be  sure that there is no deadlock produced as a result     Note that a semaphore is by no means similar to rsleep and rwakeup  Compare    rwakeup  r    rsleep r      with    signal  s    wait s      The former wakes up any sleeper at r  and the goes to sleep  Unconditionally  The latter  adds a  ticket to a semaphore  If nobody consumes it between the two sentences  the call to wait will not      258      sleep  Remember that a semaphore is used to model slots available for using a particular  resource  On the other hand  sleep wakeup are more related to conditions that must hold for you  to proceed doing something     We said that Plan 9 does not supply semaphores  But there is an easy way to implement  them  You need something to put tickets into  Something that when wanting to get a ticket   blocks until there is one ticket available  And returns any ticket available immediately otherwise   It seems that pipes fit right into the job  This is our semaphore     typedef struct Sem Sem   struct Sem     int fd 2          To create a semaphore  we create a pipe and put as many bytes in it as tickets must be initially in  the semaphore     Sem   newsem  int n        Sem  Ss     s   malloc sizeof Sem     if  pipe s  gt fd   lt  0    free s    return nil      while n    gt  0   write  s  gt fd 1    x   1    return Ss          A signal must just put a ticket in the semaphore   void  signal  Sem
301. eletyp  0          The problem is that bc expects hexadecimal digits from A to F to be upper case letters  Before  sending the input to bc  we would better convert our numbers to upper case  just in case  There is  a program that may help  The program tr  translate  translates characters  It reads its input files   or standard input   performs its simple translations  and writes the result to the output  The pro   gram is very useful for doing simple character transformations on the input  like replacing certain  characters with other ones  or removing them  Some examples follow       echo x10 y20 z30   tr x y  y10 y20 z30     echo x10 y20 z30   tr xy z  Z210 220 2z30     echo x10 y20 z30   tr a z A Z  X10 Y20 2Z30     echo x10 y20 z30   tr  d a z  10 20 30    The first argument states which characters are to be translated  the second argument specifies to  which ones they must be translated  As you can see  you can ask tr to translate several different  characters into a single one  When many characters are the source or the target for the translation   and they are contiguous  a range may be specified by separating the initial and final character  with a dash  Under flag  d  tr removes the characters from the input read  before copying the  data to the output  So  how could we translate a dash to other character  Simple      echo a b c   tr   X   axbxXc    This may be a problem we need to translate some other character  because t r would get confused  thinking that the char
302. elper routines that handle authentication  A 9P  server that implements authentication for its clients must create  fake  authentication files in  response to Tauth requests  Such files exist only in the protocol  and not in the file tree served   They are just a channel to exchange authentication messages by using read and write in the  client     To secure our semfs file server  developed in a previous chapter   we first provide a key  template in the Srv structure that defines the implementation for the server  The function  auth9p provided by the library can be used as the implementation for the auth operation in  Srv  It allocates authentication files  flagging them by setting OTAUTH in their Qid  types     static Srv sfs           auth   auth9p    attach   fsattach    create   fscreate    remove   fsremove    read   fsread    write   fswrite    walkl   fswalkl    clone   fsclone   Stat   fsstat    destroyfid  freefid    keyspec    proto p9any role server     i    Because there are authentication files  the implementation of fsread and fswrite must  behave differently when the file read written is an authentication file  In this case  the data must  be relied to factotum and not to a file served  The new implementation for f sread would be as  follows     static void  fsread Req  r        Fid  fide   Qid q    Sem  Ss    char nl 2     0     fid   r  gt fid    q   fid  gt qid    if  q type amp QTAUTH   authread  r    return            everything else as before            I
303. em     One final note  Can you see how main is not the main function in your program  It seems  that _main in the C library called what we thought was the main function     The last note about debugging is not about what to do after a program crashes  but about  what to do before  There is a library function called abort  This is its code  void  abort  void      while     int   0          This function dereferences a nil pointer  You know what would happen to the miserable program  calling abort  It gets broken  While you program  it is very sensible to prepare for things that in  theory would not happen  In practice they will happen  One tool for doing this is abort  You  can include code that checks for things that should never happen  Those things that you know in  advance that would be very hard to debug  If your code detects that such things happen  it may  call abort  The process will enter the broken state for you to debug it before things get worse     2 8  Everything is a file     We have seen two abstractions that are part of the baggage that comes with processes in  Plan 9  Processes themselves and environment variables  The way to use these abstractions is to  perform system calls that operate on them     That is nice  But Plan 9 was built considering that it is natural to have the machine con   nected to the network  We saw how your files are not kept at your terminal  but at a remote  machine  The designers of the system noticed that files  another abstraction  
304. em c   51  o 5 semfs semfs 5 sem 5       g    As another example  we can prepare for adding more source files in the future  and declare a vari   able to list the object files used to build our program  The resulting mkfile is equivalent to our  previous one  like in all the examples that follow       352       miki   CC 8c  LD 81  O 8    OFILES semfs SO sem SO       SO semfs  SOFILES  SLD  o S O semfs SOFILES       other rules             There are several variables defined by mk  to help us to write rules  For example   target is the  target being built  for each rule  Also  Sporereq are the dependencies  prerequisites  for the rule   So  we could do this      miki   CC 8c  LD 81  O 8    OFILES semfs SO sem SO       SO semfs  SOFILES  SLD  o  target Sprereg          other rules       Using these variables  all the rules we are using for compiling a source file look very similar   Indeed  we can write just a single rule to compile any source file  It would look as follows    o        O    c sem h  SCC  FVw Sstem c    This rule is called a meta rule  It defines many rules  one for each thing that matches the   char   acter  In our case  it would be like defining a rule for semfs    O and another for sem   0  The  rule says that anything  the    terminated in  O can be built from the corresponding file  but ter   minated in  c  The command in the body of the rule uses the variable  stem  which is defined  by mk to contain the string matching the   in each case     All this let
305. emo 9intro hi c 8   _main 0x31  sys src libc 386 main9 s 16   acid     The function stk    dumps the stack  The program crashed while executing the function  dofmt  at file dofmt  c  This function was called by vfprint  which was called by print   which was called by main  As you can see  the parameter fmt of print is zero  That should  never happen  because print expects its first parameter to be a valid  non null  string  That was  the bug     We can gather much more information about this program  For example  to obtain the val   ues of the local variables in all functions found in the stack      49      acid  lstk    dofmt  fmt 0x0  f Oxdfffef08  0x138  sys src libc fmt dofmt c 37  nfmt 0x0  rt 0x0  rs 0x0  r 0x0  rune 0x15320000  t Oxdfffee08  s Oxdfffef08  n 0x0  vfprint  fd 0x1l  args Oxdfffef60  fmt 0x0  0x59  sys src libc fmt vfprint c 30     0x0  buf 0x0  n 0x0    print  fmt 0x0  0x24  sys src libc fmt print c 13  args Oxdfffef60   main  argv Oxdfffefb4  0x12  usr nemo 9intro hi c 8   _main 0x31  sys src libc 386 main9 s 16    When your program gets broken  using 1stk   in acid is invaluable  Usually  that is all you  need to fix your bug  You have all the information about what happen from main down to the  point where it crashed  and you just have to think a little bit why that could happen  If your pro   gram was checking out for errors  things can be even more easy  because in many case the error  diagnostic printed by the program may suffice to fix up the probl
306. ems to be empty when read     This can be double checked  The read command reads a single line of text from its input   and then writes it to its standard output       read  hello you type this     hello    and it writes this     r    Look what happens here       read  amp     The program did not print anything  Because it could not read anything from its input     Some programs may want to execute in the background  without making the shell wait for  them until terminated  For example  a program that opens a new window in the window system  should avoid blocking the shell until the new window is closed  You want a new window  but you  still want your shell     This effect can be achieved without using  amp  in the command line  The only thing needed is  to perform the actual work in a child process  and allow the parent process to die  Because the  shell waits for the parent process  its child   it will prompt for a new command immediately after  this process dies  The first program of this chapter is an example  even though it makes not sense  to do this just to run 1s      4 8  Interpreted programs    An executable is a file that has the execute permission set  If it is a binary file for the architecture  we are running on  it is understandable what happens  If it is a binary for another architecture  the  kernel will complaint  This was executed using an Intel based PC     os 96  LS se  ob  LS   rr SPS LOUE    5 0out  exec header invalid    The header for the binary file 
307. en  gt r describes the  rectangular  area used  in the screen by our window  Like coordinates  or Points   rectangles are a popular data type  when doing graphics  The draw library defines the appropriate data type       302      typedef struct Rectangle Rectangle   struct Rectangle      Point min    Point max           A rectangle is defined by two points  the upper left corner and the bottom right one   Choosing   0 0  as the origin simplifies arithmetic operations for points  In accordance with this  the conven   tion is that a rectangle includes its min point  upper left corner  but does not include its max  point  bottom right corner   The point with biggest coordinates inside a rectangle would be   max  x l max  y l     We are close to understand the line    draw screen  screen  gt r  display  gt black  nil  ZP      that calls the function draw      sig draw  void draw Image  dst  Rectangle r  Image  src  Image  mask     You might think that after understanding how to use this function  there will come many other  ones that will be hard to understand  That is not the case  The function draw is the only thing  you need for drawing  There are other routines as a convenience to draw particular things  but all  of them use just draw     Basically  draw takes a image as the source and draws it  over  on a destination image   That is  each pixel  i  j  in the source is copied to the pixel  i  j  in the destination  Here  screen  was the destination image  and display    gt bl
308. ep used by programs that poll introduces another problem  delays  If the event      128      nautilus    a2 0 m     Figure 5 7  The system load is not altered if the program sleeps between polls     does occurs and the polling program is sleeping  it will not take an appropriate action until the  sleep completes  And this is a delay  If the process waiting for the event produces  as a result   another event  the delay of any other process polling for the later event is added to the chain     The consequence of what we have discussed so far is that most operating systems provide  an abstraction to deliver events and to wait for them  The abstraction is usually called an event  channel  and is used to convey events from the ones that produce them to the ones that await for  them     An event is a particular data structure  that contains the information about the success it rep   resents  This means that events can be used as a communication means between the processes that  produce them and the ones that consume them     In Plan 9  there is a service called plumbing that provides a message delivery service  The  name of the program is plumber because it is meant to do the plumbing to convey data from  message producers to consumers  In effect  it provides a nice event delivery service  The plumber  is built upon the assumption that once you look at a particular piece of data it is clear what to do  with it  For example  if a message looks like http   lsub org     then it is cle
309. er  responding to it  As you can see in our function  there is no need to fill all fields in the response   The library takes care of many of them  including setting the tag and the type in the reply to cor   respond to those in the request  So  for fsattach  we only had to fill up the qid sent in the  reply    The data structure Fcall  defined in  sys include fcall h  is used in Plan 9 to         337      represent a 9P message  It is used both for Req ifcall and Req ofcall  The meaning of  its fields is exactly the meaning of the fields in the 9P message represented by the Fcall  as  described in the section 5 of the manual     typedef  struct           Feall     Feall    uchar   u32int  ushort  union      i    type   fid   tag   struct    hi  struct    i  struct    i  struct        struct        struct        struct        struct        struct        struct        struct    i    u32int  char    ushort    char    Qid  u32int       Qid       u32int  char  char    u32int  char  uchar       u32int  ushort  char         ushort  Qid       viong  u32int  char       ushort  uchar    msize    xversion     oldtag      ename     qid   iounit     aqid     afid    uname    aname     perm    name   mode     newfid   nwname    wname  MAXWELE             nwqid   wqid  MAXWELE                offset   count    data     nstat    stat                                                                                                               Rver  Rver    Tversion   Tversion     Tflush      
310. er of arguments for our script  is zero  we must do  something else  Otherwise  we must execute our previous commands in the script  Before imple   menting it  we are going to try just to do different things depending on the number of arguments   But we need an else  This is done by using the construct if not afteran if  If the command  representing the condition for an if fails  the following if not executes its body   args      bin re  if        0   echo no arguments  if not  echo got some arguments        And we can try it     1 We will see how   is comparing a string to expressions  not just to strings       189        args  no arguments     args 1 2   got some arguments  1 2    Now we can combine all the pieces     d2h      bin re  rfork e  if    S   0   args     cat   if not  args S       echo    obase 16     for  num in Sargs   echo  num      be    We try our new script below  When using its standard input to read the numbers  it uses the         construct to execute cat  which reads all the input  and to place the text read in the envi   ronment variable args  This means that it will not print a single line of output until we have  typed all the numbers and used control d to simulate an end of file       Aa2h3  20  30  control d  14  le    d2h3 3 4    e  awn tw          Our new command is ready for use  and it can be combined with other commands  like in seq  10 d2h  It would work as expected     An early exercise in this book asked to use ip ping to probe for all add
311. er this message  things stand as shown in figure 13 2     Ramfs                Figure 13 2  Fids after walking to the file x in the file server     After the walk  Plan 9 sent a Topen request to open the file  Actually  to prepare the fid for  doing further reads and writes on it  The message mentions which fid to open  476 in this case  or   x within the file server  It also mentions which mode to use  The mode corresponds to the flags  given to open 2   or to create 2   The reply informs about the qid for the file just open  Both  requests  Twalk and Topen are the result of the system call made from the shell to create the  file     Now its time for echo to write to the file  To implement the write system call  Plan 9  sent a Twrite 9P request  I mentions to which fid to write  which must be open   at which offset  to write  how many bytes  and the bytes to write  The reply  Rwrite  indicates how many bytes  were written     The last request  Tclunk  releases a fid  It was sent when the file was closed  after echo  exited and its standard output was closed     The dialog for reading a file would be similar  Of course  the open mode would differ  and  Tread will be used instead of Twrite  Look this for example       cat  n ram x    lt  12  Twalk tag 14 fid 435 newfid 486 nwname 1 0 x   12  gt  Rwalk tag 14 nwqid 1 0  0000000000000000 2     lt  12  Topen tag 14 fid 486 mode 0   fid mode is 0x0    12  gt  Ropen tag 14 qid  0000000000000000 2   iounit 0   lt  12  Tread tag 14 f
312. es 604 oh   echo  file  C source code  if    Sfile   gif   echo  file  GIF image  if     file   jpg   echo  file  JPEG image         And here is one usage example       file x c a h b gif z  x c  C source code  a h  C source code  b gif  GIF image    Note that before executing the   command  the shell expanded the variables  and  file was  replaced with the corresponding argument on each pass of the loop  Also  because the shell  knows that   takes expressions  it is not necessary to quote them  Rc does it for you        The script can be improved  It would be nice to state that file does not know what a file is  if its name does not match any of the expressions we have used  We could add this if as a final  conditional inside the loop of the script    if       file    ch    gif    jpg   echo  file  who knows    The builtin command   in rc is used as a negation  It executes the command given as an argu   ment  If the command exit status meant ok  then   fails  And vice versa     But that was a poor way of doing things  There is a switch construct in rc that permits  doing multiway branches  like the construct of the same name in C  The one of rc takes one  string as the argument  and executes the branch with a regular expression that matches the string   Each branch is labeled with the word case followed by the expressions for the branch  This is an  example that improves the previous script       191         bin re  rfork e  for  file in        switch   file     case   c   h
313. es not makes sense to grant the owner of a file less permissions than to others   the file owner has a particular permission if it is enabled for the owner  the group  or for the oth   ers  The same applies for members of the group  They have permission when either permissions  for the group or permissions for others grant access     In general  read permission means permission to access the file to consult its contents  Write  permission means permission to modify the file  This includes not just writing the file  but also  truncating it  Execute permission means the right to ask a Plan 9 kernel to execute the file  Any  file with execution permission is an executable file in Plan 9     For directories  the meaning of the permissions is different  For a directory  read permission  means permission to list the directory  Because the directory has to be read to list its contents   Write permission means permission to create and remove files in the directory  These operations  require writing the directory contents  Execute permission means the right to enter  i e   to cd  into it    When there is a project involving several users  it is convenient to create a directory for the  files of the project and to create a group of users for that project  All files created in that directory  will be entitled to the group of users that the directory is entitled to  For example  this directory  keeps documents for a project called Plan B       ds  ld docs  d rwxrwxr x M 19 nemo planb 0 J
314. es the statements in the order you  wrote them  It reads one record after another and executes  in order  all the statements with a  matching pattern  Lines with comments match the first and the third statement  But it does not  help to skip to the next input record once you printed it  The same happens to empty lines     Now that we know how to get rid of weird lines  we can proceed  To create accounts for all  students in the course in Operating Systems  group B  we must first select lines for that course  and group  This semester  fields are delimited by a vertical bar  the course field is the 3rd  and the  group field is the 4th  This may help       awk FETS 7         7   next     3     S    next     i   3    Operating Systems   amp  amp   4    B    print  2    ra X TSC   Rodolfo Mart  nez   Joe Black   Luis Ib    ez   Ricardo Mart  nez    r    We had to tell AWK how fields are delimited using  F    quoting it from the shell  This option  sets the characters used to delimit fields  i e   the field delimiter  Although it admits as an argu   ment a regular expression  saying just   suffices for us now  We also had to match the 3rd and  4th fields against desired values  and print the student name for matching records     Our plan is a follows  We are going to assume that a program adduser exists  If it does  not  we can always create it for our own purposes  Furthermore  we assume that we must give the  desired user name and the full student name as arguments to this progra
315. escriptor                                              table  0  1 Chan  2 offset  6      3 mode  OWRITE  file   n                h e 1l  1l o  n 323 afile                            Figure 3 3  The file offset for next operations is kept separate from the file descriptor     We can use seek to write at a particular offset in the file  For example  the following code  writes starting at offset 10 into our original version of afile     int tas    fd   open  afile   OWRITE    seek  fd  10  0     write fd   hello n   6    close  fd         The contents of afile have six bytes changed  as it could be expected       xd  c afile    0000000 C O    ps    ye sry a cg  CR st h e 1 1 o n  0000010 2 Lucent T e c h n o 1  0000020 o g ies TE omy Gs  Ve 2A Cd  L R  0000030 L    ge ih  tt S R e s erv e d n  000003f    How can we write new contents into afile  getting rid of anything that could be in the file  before we write  Simply by specifying to open that we want to truncate the file besides opening  it  To do so  we can do a bit or of the desired open mode and OTRUNC  a flag that requests file  truncation  This program does so  and writes a new string into our file       63      thello c     include  lt u h gt      include  lt libc h gt     void  main int   char           int fd        GI    fd   open  afile   OWRIT   write fd   hello n   6    close  fd    exits  nil        OTRUNC            After running this program  afile contains just the 6 bytes we wrote       8 thello  p Cat afire
316. ess gives to exits is its exit status  This was not new   The new point is that the parent may wait until a child dies and obtain its exit status  The function  used to do this is wait     sig wait  Waitmsg  wait  void     where Waitmsg is defined like follows     typedef  struct Waitmsg            int pid     of loved one     ulong time 3      of loved one  amp  descendants     char  msg      Waitmsg     A call to wait blocks until one child dies  At that point  it returns a wait message that contains  information about the child  including its pid  its status string  and the time it took for the child to  execute  If one child did already die  there is no need to wait and this call returns immediately  If  there is no children to wait for  the function returns nil   Now we can really fix the problem of our last program   int  run char  cmd  char  argv        Waitmsg  m   int Lets    switch  fork        case  1   return  1    case 0     child  exec cmd  argv    sysfatal  exec  Sr       default   m   wait     if  m  gt msg 0     0   ret   0   else      werrstr m  gt msg     ret    1        free  m     return ret          After calling fork  the parent goes through the default case and calls wait  If by this time the  child did complete its execution by calling exits  wait returns immediately Waitmsg with  information about the child  If the child is still running  wait blocks until the child terminates   The data structure returned by wait is allocated using malloc  and the c
317. esses in Plan 9  Environment vari   ables are not different  The interface for using environment variables in Plan 9 is a file interface   To know which environment variables we have  we can list a  virtual  directory that is invented  by Plan 9 to represent the interface for our environment variables  This directory is  env       Ic  env   Bee cpu init planb sysname  0 cputype location plumbsrv tabstop  MKFILE disk menuitem prompt terminal  afont ether0 monitor rename timezone  apid facedom mouseport role user  auth   fn sigexit    nobootprompt rootdir vgasize  bootdisk font objtype sdcOpart wetl  bootfile fs part sdClpart wsys  cflag home partition service  cfs i path status  cmd ifs pid sysaddr    r    Each one of these  fake   files represents an environment variable  For you and your programs   these files are as real as those stored in a disk  Because you can list them  read them  and write  them  However  do not search for them on a disk  They are not there     You can see a file named sysname  another named user  and yet another named path   This means that your shell has the environment variables sysname  user  and path  Lets double  check      525      echo Suser  nemo     cat  env user  nemo     The file  env user appears to contain the string nemo   with no new line at the end   That is  precisely the value printed by echo  which is the value of the user environment variable  The  implementation of getenv  which we used before to return the value of an environment
318. estimate the effort made by others and overestimate what they can do by themselves  But  surely you would not apply this to all the software necessary to let you use the hardware     Abstract data types are also a convenience to write software  For example  you wrote pro   grams using files  However  your hard disk knows nothing about files  Your hard disk knows  how to store blocks of bytes  Even more  it only knows about blocks of the same size  However   you prefer to use names for a piece of persistent data in your disk  that you imagine as contiguous  storage nicely packaged in a file  The operating system invents the file data type  and provides  you with operations to handle objects of this type  Event the file   s name is an invention of the  system     This is so important  that even the    hardware    does this  Consider the disk  The interface  used by the operating system to access the disk is usually a set of registers that permits transfer   ring blocks of bytes from the disk to main memory and vice versa  The system thinks that blocks  are contiguous storage identified by an index  and therefore  it thinks that the disk is an array of    Oh  ie    blocks  However  this is far from being the truth  Running in the circuitry of a hard disk there is a  plethora of software inventing this lie  These days  nobody  but for those working for the disk  manufacturer  knows really what happens inside your disk  Many of them use complex geome   tries to achieve better perf
319. ething  and that  requires the former to do another thing  which cannot be done because it is waiting  You know  when you have a deadlock because the processes involved freeze  Deadlocks must be avoided   We avoided one here simply by doing the things in a sensible order  and waiting for the child  after we have read all its output     What we have seen is very useful  Many programs do precisely this  or other similar things   The editor Acme admits commands to be applied to a portion of text selected by the user  For  example  using the button 2 in Acme to run the command  t  asks Acme to execute the program  t  with the selected text as the input for t   and to replace that text with the output from the  command  Of course  Acme uses pipes to send text to the input of t  and to read its output  The  command t  is a shell script used to indent text by inserting a tab character at the start of each  line     The shell is also a heavy user of pipes  as you might expect  Rc includes several interesting      116      constructs that are implemented along the lines of what we saw before     When Rc finds a command inside         it executes the command  and substitutes the  whole        text with the output printed by the command  We did something alike in the C pro   gram when reading the output for a command using a pipe  This time  Re will do it for us  and  relieve us from typing something that can be generated using a program  This is an example       date   Fri Jul 21 16 36
320. etwork  Instead  it prints the relevant data carried by  each message in a format that could be understood by a human       ramfs  D  s ram  postfd  srv ram  postfd successful    r      326      Using  s we asked ramfs to post at  srv ram the end of a pipe that we can mount to access  the files it provides  This is what happens when we mount its file tree       mount  c  srv ram  n ram    lt  12  Tversion tag 65535 msize 8216 version    9P2000      12  gt  Rversion tag 65535 msize 8216 version    9P2000      lt  12  Tauth tag 16 afid 435 uname nemo aname    12  gt  Rerror tag 16 ename auth no required    lt  12  Tattach tag 16 fid 435 afid  1 uname nemo aname   12  gt  Rattach tag 16 qid  0000000000000000 0 d     F    The mount command makes a mount system call  To perform the mount system call  Plan 9  sent three different requests to this ramfs file server  The file server printed the messages  and  attended the requests and sent the replies  before Plan 9 could complete the mount call     Ramfs prints a line for each 9P message exchanged  The first field of each line shows if it  is a message received from Plan 9  the arrow points to the left  or sent by the server  the arrow  points to the right   The former ones are requests  and the latter ones are replies  The file descrip   tor used to receive  or send  the message is the number printed in the middle of each arrow  In  this case  ramfs is attending an end of a pipe  open in file descriptor 12  The other end of the  pi
321. ever the file is updated  This is useful to let Plan 9 know if  a cached file is up to date or not  It is also useful to let applications know if a file has changed or  not  The field t ype contains bits that are set to indicate the type for a file  including these ones         define QTDIR 0x80    type bit for directories      define QTAPPEND 0x40    type bit for append only files      define QTEXCL 0x20    type bit for exclusive use files             For example  the QTDIR bit is set in Qid type for directories  unset for other files  The  QTAPPEND bit is set for append only files  The OTEXCL bit is set for files with the exclusive use  permission set  files that can be open by at most one process at the same time   Looking back to  the Rattach message sent by ramfs  its root directory has a gid whose path was  0000000000000000  i e   0  Its version was 0  and it had the QTDIR bit set  printed as a d      In the figure 13 1 we assumed that the file tree served by ramfs had three files in its root  directory  Before continuing  we are going to create three such empty files using this command                touch  n ram   x y Z     9P dialog omitted       r    What would now happen if we write the string hello to  n ram x  We can use echo to do  it  The shell will open  n ram x for writing  and echo will write its argument to the file  This  is the 9P conversation spoken between Plan 9 and ramfs as a result       echo  n hola  gt  n ram x    lt  12  Twalk tag 14 fid 435 newfi
322. execl   bin 1ls    ls     1   home  nil    print   exec failed   r n          4 6  Using both calls    Most of the times you will not call exec using the process that initially runs your program  Your  program would be gone  You combine both fork and exec to start a new process and run a pro   gram on it  as saw first in this chapter  We are going to implement a function called run  which  receives a command including its arguments and runs it at a separate process  This is useful  whenever you want to start an external program from your own one     The header for the function will be     int run char  file  char  argv        and its parameters have the same meaning that those of exec  The file to execute and the      94      argument vector  This is the code   int  run char  cmd  char  argv        switch  fork       case  1   return  1   case 0     child  exec cmd  argv    sysfatal  exec  Sr     default     parent  return 0           The function creates a child process  unless forks fails  in which case it reports the error by  returning  1  The parent process returns zero to indicate that it could fork  The child calls exec  to run the new program  Should it fail  there is nothing we could do but to terminate the execution  of this process reporting the error  Note that the child process should never return from the func   tion  When a program calls run  only one flow of control performs the call  and you expect only  one flow of control coming out and returning from it   
323. face to use the device  that is known as the console  which corresponds to your terminal  When you read this file  you  obtain the text you type in the keyboard  When you write this file  the text is printed in the screen     When used within the window system   dev  cons corresponds to a fake console invented  just for your window  The window system takes the real console for itself  and provides each win   dow with a virtual console  that can be accessed via the file  dev cons within each window   We can rewrite the previous program  but opening this file ourselves     read c   include  lt u h gt      include  lt libc h gt           void  main int   char              char buffer 1024    int fa  nr   fd   open   dev cons   ORDWR       read fd  buffer  sizeof buffer    write fd  buffer  nr    close  fd      exits  nil      nr      58      This program behaves exactly like the previous one  You are invited to try  To open a file  you  must call open specifying the file name  or its path  and what do you want to do with the open  file  The integer constant ORDWR means to open the file for both reading and writing  This func   tion returns a new file descriptor to let you call read or write for the newly open file  The  descriptor is a small integer that we store into fd  to use it later with read and write  Figure  3 2 shows the file descriptors for the process running this program after the call to open  It  assumes that the file descriptor for the new open file was 3        F
324. fer      write 1  buffer  nr    exits  nil           And here is how it works     257       8 read  from stdin  to stdout  Ifyou type this  from stdin  to stdout  the program writes this    When you run the program it calls read  which awaits until there is something to read  When  you type a line and press return  the window gives the characters you typed to the program  They  are stored by read at buffer  and the number of bytes that it could read is returned and stored  at nr  Later  the program uses write to write so many bytes into standard output  echoing what  we wrote     Many of the Plan 9 programs that accept file names as arguments work with their standard  input when given no arguments  Try running cat     7  Cat     It waits until you type something    It reads what you type and writes a copy to its standard output    eo Oat  from stdin  to stdout  Ifyou type this  from stdin  to stdout  cat writes this    and again  and again  control d    r    until reaching the end of the file  The end of file for a keyboard  There is no such thing  but you  can pretend there is  When you type a control d by pressing the d key while holding down  Control  the program reading from the terminal gets an end of file     Which file is standard input  And output  Most of the times  standard input  standard out   put  and standard error go to  dev cons  This file represents the console for your program   Like many other files in Plan 9  this is not a real  disk  file  It is the inter
325. fer for it      If you remove this line from the program  it will draw  but the window will remain white   because the operation will not take effect   Fortunately  you will not need to worry about this in  many cases  because the functions for drawing graphics and text call f lushimage on their own   Nevertheless  you may have to do it by yourself if you use draw     12 6  A graphic slider    We want to implement a small graphical application  to let the user adjust a value between 0   and 100   This is a graphical slider  that can be run in a window  The program will print to its  standard output the value corresponding to the position of the slider as set by the user using the  mouse or the keyboard     The real display does not have that problem  but windows can be resized  The window sys   tem supplies its own menus and mouse language to let the user resize  move  and even hide and  show windows  For our program  this means that the screen might change     Rio assumes that a program using graphics is also reading from the mouse  And note that  the mouse is the virtual mouse file rio provides for the window  Upon a resize  rio delivers a  weird mouse event to the program reading  dev mouse  This event does not start with the  character m  it starts with the character r  to alert of the resize  After the program is alerted  it  should update the image it is using as its screen  that is  as the window   The program can do  so because the file  dev winname contains the name 
326. ffect  This is where the shell gets rele   vance  The shell is the programming language you use to combine the programs you have in  a simple way  Knowing how to use it may relieve you from your last resort     3 The last resort is to write your own program for doing the task you are considering   Although the libraries may prove invaluable as helpers  this requires much more time  spe   cially for debugging and testing     To be able to use shell effectively  it helps to follow conventions that may be useful for automat   ing certain tasks by using simple shell programs  For example  writing each C function using the  style   void   func    args                permits using this command line to find where function foo is defined       grep  n         foo        c    By convention  we declared functions by writing their names at the beginning of a new line   immediately followed by the argument list  As a result  we can ask grep to search for lines that  have a certain name at the beginning of line  followed by an open parenthesis  And that helps to  quickly locate where a function is defined     The shell is very good for processing text files  and even more if the data has certain regu   larities that you may exploit  The shell provides a full programming language where commands  are to be used as elementary statements  and data is handled in most cases as plain text     In this chapter we will see how to use rc as a programming language  but no one is going  to help you if
327. fices with just one byte  Of  course  that write must be performed at an offset of 1 Gigabyte  minus 1 byte      Creating large files in this way is different from writing all the zeroes yourself  First  it  takes less time to create the file  because you make just a couple of system calls  Second  it can be  that your new file does not consume all its space in the disk until you really use it  Because Plan 9  knows the new size of the file  and it knows you never did write most of it  it can just record the  new size and allocate disk space only for the things you really wrote  Reading other parts of the  file yield just zeroes  There is no need to store all those zero bytes in the disk     This kind of file  i e   one created using seek and write   is called a file with holes  The  name comes from considering that the file has    holes    on it  where you did never write anything   Of course  the holes are not really stored in a disk  It is funny to be able to store files for a total  amount of bytes that exceeds the disk capacity  but now you know that this can happen     To append some data to a file  we can use seek to set the offset at the end of the file before  calling write  like in    fd   open  afile   OWRITE    seek fd  0  2      move to the end  write fd  bytes  nbytes         For some files  like log files used to append diagnostic messages  or mail folders  used to append  mail messages  writing should always happen at the end of the file  In this case  it is m
328. figure 12 2  The slider draws in  yellow a bar representing the value set by the slider  and fills the rest of the window with the  same background color used by rio  Using the mouse  it can be adjusted to the left  the one  above in the figure  and to the right  the one below in the figure   When the slider is at the left  it  represents a value of 0  or 0  of a value set by the slider   When it is at the right  it represents a  value of 100     Maintaining the slider is a separate part of the processing done by the program  which uses a  different thread for that purpose  We will call it sliderthread  The existing code also  requires changes  First  threadmain must create now a channel to send new values for the  slider to the slider thread  and must create the thread itself  Also  we must get rid of the call to  blank   in threadmain  This program does not blank its window  Since we decided that  sliderthread is in charge of the slider  threadmain will no longer draw anything  Instead   it may send a value to the slider  to adjust it to a reasonable initial value  and draw it           306         Figure 12 2  Two example windows for the slider application  One at 30   another at 84      slider c     Initially  all the code as before  but for the changes explained in the text     Channel sliderc     void   threadmain int  char argv           all code here as before     sliderc   chancreate sizeof ulong   0    threadcreate sliderthread  sliderc  8 1024    sendul sliderc  50
329. file referenced by the fid  We do  so for all fids referring to semaphore files     The f  sclone routine is called by the library when a new fid is created as a clone of an  existing one  as part of the implementation for the Twalk message  that creates new fids by clon   ing old ones   The implementation updates the aux field for the new fid and the reference  counter for the semaphore involved  which is now pointed to by a new fid   The function might  return a non null string to signal errors  but this implementation will never fail     static char   fsclone Fid  fid  Fid  newfid           Sem  Ss    s   fid  gt aux    if  s    nil   incref s     newfid  gt aux   s     return nil          The library uses reference counting to know when a Fid is no longer used  e g   because of a  Tclunk that removed the last reference to a fid   When a fid is released the library calls  Srv destroyfid  which we initialized to point to freefid  This function releases one      343      reference to the semaphore for the fid  If this was the last one pointing to the semaphore  it will be  released  Note that there will always be one reference from the array of semaphores  as long as the  file has not been removed     static void  freefid Fid  fid        Sem  S     s   fid  gt aux   fid  gt aux   nil   closesem s           Removing of files is done by fsremove  which releases the reference from the array as well as  the one from the fid     static void  fsremove  Req  r          Req  q   Sem
330. for  you  But this file has comments  on lines starting with    and may have empty lines  The sim   plest thing would be to search just for what we want  and count the lines       204        sed 7q  lib namespace     root   mount  aC  S boot  root Srootspec  bind  a S rootdir     bind  c S rootdir mnt  mnt      kernel devices   bind  c  dev     grep      bind mount      lib namespace  mount  aC  S boot  root Srootspec  bind  a S rootdir     bind  c Srootdir mnt  mnt         grep      bind mount      lib namespace   wc  1  41     grep      bind mount      proc  pid ns   wc  1  72    We had 41 binds mounts in the standard namespace  and the one used by our shell  as reported by  its ns file  has 72 binds mounts  It seems we added many ones in our profile     There are many other useful uses of regular expressions  as you will be able to see from here to  the end of this book  In many cases  your C programs can be made more flexible by accepting  regular expressions for certain parameters instead of mere strings  For example  an editor might  accept a regular expression that determines if the text is to be shown using aconstant width  font ora proportional width font  For file names matching  say       ch   it could use a con   stant width font    It turns out that it is trivial to use regular expressions in a C program  by using the regexp  library  The expression is compiled into a description more amenable to the machine  and the  resulting data structure  called a Reprog  ca
331. for the image to be used as a window   and this can be used to lookup the appropriate image for the window using its name     The function getwindow updates the screen variable  after locating the image to be  used as the new window  As a curiosity  the window system draws a border for the window in  the image for the screen  However  your program is unaware of this because get window  adjusts screen to refer to the portion of the image inside the border     But how do we know of resize events from the mouse  Simple  Look back to see the fields  for a Mousect1 structure  which we obtained before by calling initmouse  You will notice  that besides the channel Mouse c  used to report mouse events  it contains a channel  Mouse resizec  Resize events are sent through this channel  The receipt of an integer value  from this channel means that the window was resized and that the program must call  get window to reestablish its screen for the new window     The following program draws the entire window in black  like before  However  this pro   gram re acquires its window when it is resized  It creates a separate thread to attend the mouse   and another one to process resizes of the window  removing all that processing from the rest of  the program  In this case  it may be considered an overkill  In more complex programs  placing  separate processing in separate threads will simplify things  After starting the thread for attending  the mouse  and the one attending resizes  the progr
332. format  P  298  formatted  324  output  55  fossil console  123  fossil  123  163  221  324  free  69  freenetconninfo  143  frozen process  115  fs partition  322  fstat  70  full duplex  110  function  definition  207  library  23  shell  206  function  acid threads  267  functions  drawing  312  fwstat  72     J       G    garbage collection  340  generation  code  186  Get  8  get  253  getenv  44  52  153  180  getnetconninfo  142  getpid  45  getuser  173  getwindow  303  316  gid  69  global  substitution  197  variable  32  229  global c  32  globbing  73  190  201  God  106  good luck  232  376       graphic  devices  298  slider  303    graphics  300  drawing  301  initialization  300  mode  298  greek letter  293  grep  108  162  179  201  flag  e  209  flag  f  210  flag  i  209  flag  n  209  flag  s  221  silent  221  group  18  environment  158  environment process  153  file  69  file descriptor  154  file descriptor process  153  id  69  note  153  155  note process  153  process  42  117 118  rendezvous  153 154  gzip  199    H    h2d rc script  185  handler  note  118  120  handling authentication  368  hangup  connection  137  hangup note  118  213  223  hardware  26   acceleration  298 299    device  26  interrupt  26  head  file  195  header files  21  header  exec  97  height  rectangle  308  hello rc script  98  help  8  here file  116  hexadecimal  183  dump  file  16  HFILES  353  Hide  6  hide  window  317  hoc  98  option  e  183  hold mode  290  h
333. formation about  NOTICE  nothing that 1s could not  do  and produces this output when run          6 stat   file name  NOTIC  file mode  0444  file size  63 bytes    GI       r     70        stat c     include  lt u h gt      include  lt libc h gt     void  main int   char           Dir  d     d   dirstat    NOTICE      if  d    nil   sysfatal  dirstat  Sr          print   file name   s n   d  gt name      print   file mode  0 o n   d  gt mode      print   file size  Sd bytes n   d  gt length    free d     exits  nil           Note that the program called free only once  for the whole Dir  The strings pointed to by  fields in the structure are stored along with the structure itself in the same malloc allocated  memory  Calling f ree once suffices     An alternative to using this function is using dirfstat  which receives a file descriptor  instead of a file name  This function calls fst at  which is another system call similar to stat   but receiving a file descriptor instead of a file name   Which one to use depends on what do you  have at hand  a name  or a file descriptor     Because directories contain directory entries  reading from a directory is very similar to  what we have just done  The function read can be used to read directories as well as files  The  only difference is that the system will read only an integral number of directory entries  If one  more entry does not fit in the buffer you supply to read  it will have to wait until you read again     The entries 
334. fter running the window system  When  run in the console  a graphics program will use the entire screen as its window  when run within  the window system  it will use just the window  That is the only difference regarding graphics   which is why you can execute rio ina window  as we did time ago when connecting to a CPU  server     The following program draws the entire screen in black for 10 seconds  Like many other  programs  it uses the functions from the draw library  as described in graphics 2   and draw 2    instead of speaking to the draw device by itself     black c       include  lt u h gt   include  lt libc h gt                    include  lt draw h gt    void   main int  char argv         Rectangle rect     Image  black     fmtinstall    R     Rfmt     if initdraw nil  nil  argv 0    sysfatal  initdraw   r    Ct    sereen  gt r    lack   display  gt black    raw screen  rect  black  nil  Pt rect min x 20 rect min x 20      lushimage  display  1     leep 5   1000     closedisplay  display      print   rectangle was  R n   rect     exits  nil       lt  0   JG     z       nUmAAaAOOR               The program calls initdraw to establish a connection to the draw device  This function      301      initializes some global variables  including screen  and display  that are used later in the  program     sig initdraw  int initdraw void   errfun   Display   char    char  font  char  label     The first parameter points to a function called by the library upon errors  Passin
335. g       290      Writing some more things in the real console may cause a scroll  and the images in the  screen will scroll along with the text  Poor rio  it will never know that the screen is messed up   To prevent this from happening  the file  c kprint may be used  If a process has  c kprint  open for reading  the kernel will not print in the screen whatever is written at  c cons  Instead   all that text is used to satisfy reads for  c kprint  For example  executing cat on this file   prior to doing the echo above  produces this effect       cat  dev kprint  where will this go     All text sent to the console will now go to that window  For the record  it might help to print also   dev kmesg  which records all the messages printed in the console so far  before reading  kprint      cat  dev kmesg  dev kprint  Plan 9  E820  00000000 0009  800 memory  E820  0009f800 000a0000 reserved       where will this go     When we implemented programs to read from the console  it gave us a line at a time  We could  even edit the line before hitting return  However  this time  using cat to read  c  cons returned  characters  as we typed them  What is going on     Usually  the console device driver reads characters from the keyboard   s hardware  and  cooks what you type a little bit  before supplying such characters to any process reading   dev cons  This is the cooking recipe used by the console        A backspace  removes the previous character read from the keyboard        A control u
336. g a nil pointer  means that the draw library will use its own  which prints a diagnostic message and terminates the  program  Usually  that is all you will want to do  The second parameter states which font to use  for drawing text  Again  passing a nil value means that the library will use a reasonable default   The last parameter is simply a textual label for the window  which we define to be the program  name  The function writes the text in label to the file  dev label  to let rio know how the  window is named  in case it is hidden     The display variable points to a Display structure that represents the connection to the  draw device  It maintains all the information necessary to speak with the device  for drawing  In  particular  it keeps the file descriptor for the  dev draw n data file  that is  for the connec   tion to the device  Calling closedisplay  display  as the program does after 10 seconds   closes the connection and releases any graphic resources associated to it           Another useful global variable  also initialized by initdraw  is screen  This variable  points to a structure representing the screen  i e   the memory  where you may draw and use  graphics  When running in the console  screen corresponds to the entire screen  When running  inside a rio window  screen corresponds to the part of the screen used by the window  In  what follows  we will always speak about the window used by the program  But it should be clear  that such    window    may be t
337. g call in  net tcp 54  lfd 11     You can see how there are two lines used  The line number 52 is still listening  and the call  received is placed at line 54  where we might accept it  By the way  the line number 46 is the    other end of the connection     Now we can do something useful  If we accept the call by calling accept  this function  will provide an open file descriptor for the data file for the connection  and we can do our echo    business       147      netecho c     include  lt u h gt      include  lt libc h gt     void  main int argc  char  argv            int efras ltd   dtda   long nx    char adir 40     char ldir 40     char buf  1024      cfd   announce   tcp   9988   adir    if  cfd  lt  0   sysfatal  announce  Sr       print   announced tcp   9988 in  s n   adir      for       lfd   listen adir  ldir    if  lfd  lt  0   sysfatal  listen  Sr     dfd   accept  lfd  ldir    if  dfd  lt  0   sysfatal   can   t accept   close  lfd    print   accepted call at  s n    for         nr   read dfd  buf  sizeof buf      if  nr  lt   0   break   write dfd  buf  nr       print   terminated call at  s n    close  dfd           If we do as before  and use telnet to connect to our server and ask for a nice echo  we get the  echo back  After quitting telnet  we can connect again to our server and it attends the new call       148        telnet  r tcp Ssysname 9988   connected to tcp alboran 9988 on  net tcp 46  Hi there    Hi there    Delete     telnet  r tcp Ssysname 998
338. g file  servers into its namespace  is now unaccessible for this process     We could go even further by calling rfork  RFNOMNT  near the end of becomenone   This prevents the process from mounting any other resource into its namespace  It will be con   fined for life  with almost no privilege     In general  for a server  calling a function like becomenone would be done early in main   before attending requests from the network  In our case  we cannot do this in the main function   because the process that has to belong to none is the one implementing the file server  This pro   cess is started by threadpostmountsrv  and therefore we must arrange for such process  and  not the parent  to call becomenone  We placed the call in fstattach  because the server is  not likely to do any damage before a client can mount it     Becoming the user none was an identity change  In general  this is the only identity change      372      made by most programs  In CPU servers it is usual for processes that listen for network requests   like HTTP servers  to run as none     Sometimes  it may be necessary to become a different user  and not just none  Consider  again CPU servers  Running on them  there are other server processes that must execute com   mands on behalf of a user  For example  the processes listening for remote command execution  requests must execute commands on behalf of a remote user     There is one interesting thing to learn here  Executing new processes for a remote user 
339. g the window  like the real ones are the interface for  using the real console    Each time the rio file system is mounted  it creates a new window  The attach specifier     the optional file tree name given to mount  must be new  possibly followed by some flags for the  newly created window  Rio posts at a file in   srv a file descriptor that can be used to mount it      314      The name for this file is kept at the environment variable  wsys  Therefore  these commands  create a new window       echo Swsys   srv rio nemo 557    mount Swsys  n rio new    After doing this  the screen might look like the one shown in figure 12 3  where the empty win   dow is the one that has just been created  Which files are provided by rio  We are going to use  the window were we executed the previous commands to experiment at little bit          echo  wsys   srv rio nemo 832    mount  wsys  n rio new    3       Figure 12 3  Mounting rio creates a new window  In this one  no shell is running       lc  n rio    cons kbdin screen wetl winid  consctl label snarf wdir winname  cursor mouse text window wsys    We see cons  consctl  cursor  and mouse  among others  The are virtual versions for the  ones that were mounted at  dev prior to running rio  The convention in Plan 9 is to mount the  window system files at  mnt  wsys  and not at  n rio  We use  n rio just to make it clear  that these files come from the file tree that we have mounted  In your system  you may browse   mnt wsys and you will 
340. gc  char  argv          int ae    if  argc  lt  3    fprint 2   usage   s gid file    n   argv 0     exits   usage        for  i   2  i  lt  argc  itt   chgrp argv 1   argv il    exits nil       The interesting part is the implementation of the chgrp function  It is quite simple  Internally   dirwstat packs the structure into the portable format  and calls wst at  the actual system call    As a remark  there is also a dirfwstat variant  that receives a file descriptor instead of a file  name  It is the counterpart of dirfstat and uses the fwstat system call  Other attributes in  the directory entry can be updated as done above for the group id     The resulting program can be used like the real chgrp 1          8 chgrp planb chgrp c chgrp 8     ls  l chgrp c chgrp 8       rw r  r   M 19 nemo planb 1182 Jul 10 12 09 chgrp 8      rw r  r   M 19 nemo planb 377 Jul 10 12 08 chgrp c    r    3 6  Listing files in the shell   It may be a surprise to find out that there is now a section with this title  You know all about list   ing files  It is a matter of using 1s and other related tools  Well  there is something else  The shell  on its own knows how to list files  to help you type names  Look at this session     TA      cd Shome   ae ta    bin lib tmp    echo     bin lib tmp    First  we used 1c to list our home  Later  we used just the shell  It is clear that echo is simply  echoing its arguments  It knows nothing about listing files  Therefore  the shell had to supply  bin  lib 
341. gned integer value  They are very convenient  when the channel is used to send integers  There are other similar functions  called sendp and  recvp that send and receive pointers instead       sig sendul recvul sendp recvp  int sendul Channel  c  ulong v   ulong recvul  Channel  c   int sendp Channel  c  void  v   void  recvp Channel  c     They are exactly like send and recv for messages of the size of integers and messages of the  size of pointers  respectively     11 4  I O in threaded programs    Performing I O from a thread that shares the process with other threads is usually a bad idea  It is  not harmful to call print and other I O functions for debugging and similar purposes  But it  may be harmful to the program to read from the console or to read from or write to a network  connection     Consider the airport panels application from the last chapter  We are going to make an  implementation using threads  The application must convey a message typed at a console to the  multiple panels in the airport  This implies several different activities     1 Reading messages from the console   2 Broadcasting each new message to all the panels   3 Updating each panel    Using the thread library  we can program the application in a very modular way  Each activity  may be performed by a different thread  without even thinking on what the other threads would  do  To make all the threads work together  we can use channels     For example  a consread thread may be in charge of readi
342. gram we implemented before     8 echo    this is    weird  echo   this is   weird    NEOS    r    As you may see  argv  1  contains the string this is  including the white space  The shell  did not split the string into two different arguments for the command  Because you quoted it   Even the new line can be quoted       echo    how many     lines      how many   lines    The prompt changed because the shell had to read more input  to complete the quoted string  That  is its way of telling us  Quoting also removes the special meaning of other characters  like the  backslash       echo    ee waiting for the continuation of the line  7    Until we press return    echo prints the empty line    echo V       r    To obtain the value for a environment variable  from a C program  we can use the getenv sys   tem call  An of course  the program must check out for errors  Even get env can fail  Perhaps the  variable was not defined  In this case get env returns a null string     env c        include  lt u h gt      include  lt libc h gt     void  main int  char             char  home   home   getenv   home     if  home    nil     sysfatal  we are homeless     print   home is  s n   home    exits  nil           Running it yields     45       8 env  home is  usr nemo    A related call is putenv  which accepts a name and a value  and sets the corresponding environ   ment variable accordingly  Both the name and value are strings     2 6  Process names and states    The name of a process is
343. h defines a Point  along with some functions to operate on points       298      typedef struct Point Point   struct Point     int x  int y         So  the x coordinate for the mouse event stored at m would be m xy x  and the y coordinate  would be m  xy y     To print Points  the function Pfmt  declared by draw h  can be installed as a format  function for the print function family  The call    fmtinstall    P     Pfmt      instructs print to use Pftmt to print any argument that corresponds to a  P in its format  string  This is very convenient for printing coordinates  By the way  there are many other format  functions defined in the standard library  And you may define your own ones  It is all explained  in fmtinstall 2   which details the support for user defined print formats     Finally  the function closemouse closes the mouse file and releases any resource related  to the Mousect1 structure  most notably  its memory  the channel  and the process reading the  mouse      The rest of the mouse interface  not used by this program  will wait until we see something  about graphics     12 4  Devices for graphics    The whole idea behind graphic terminals is quite simple  A portion of memory is used to keep the  image s  to be shown at the terminal  The hardware device that updates the monitor image by  reading this memory is called a graphics card  But things are not so simple anymore     Ultimately  graphics are supported by extremely complex hardware devices like VGA cards
344. har           int fds    fd   open   srv tcp whale 9fs   ORDWR    iE Eda  lt 0   sysfatal  can   t open  srv tcp whale 9fs  Sr     if  amount  fd    n whale   MREPL MCREATE       lt  0   sysfatal  mount   Sr     if  amount  fd    n dump   MRE    sysfatal  mount  Sr                      PL   main archive    lt  0     exits nil               Because the dump cannot be modified  we do not use MCREATE for it  it would make no sense to  try to create files in the  read only  archive  Running this program is equivalent to executing         mount  c  srv tcp whale 9fs  n whale    mount  srv tcp whale 9fs  n dump main archive    As you could see  the program calls amount and not mount  The function amount is similar  to mount  but takes care of authentication  i e   convincing the file server that we are who we say  we are  This is necessary or the file server would not allow attaching to its file tree with the access  rights granted to our user name  After amount convinces the file server  it calls mount supply   ing an authentication file descriptor as the value for the mount parameter afd  The other  parameters for mount are just those we gave to amount     The other system call  bind  is used in the same way  Its flags are the same used for mount   However  unlike mount  it receives a file name instead of a file descriptor  As you could expect  after having using the shell command bind     7 10  Using names    We have seen that the shell has an environment variable  path  to dete
345. has a constant  weird  number in it  It is placed there by the loader  and checked by the kernel  which is doing its best to be sure that the binary corresponds to the  architecture executing it       98      But there is another type of executable files  Interpreted programs  For Plan 9  an interpreted  program is any file starting with a text line that has a format similar to       bin re    It must start with     followed by the command that interprets the file  In the example above  the  program interpreting the file is  bin rc  i e   the standard Plan 9 shell  You know what the shell  does  It reads lines  interprets them  and execute commands as a result  For the shell  it does not  matter if commands come from the console or from a file  Both things are files actually     This is an example of a program interpreted by the shell  also known as a shell script  We  can try it by storing the text in a file named he11o and executing it       cat hello     bin re   echo hello there     chmod  x hello  7 hello   hello there     r    When Plan 9 tries to execute a file  and it finds that the two initial characters are     it executes  the interpreter as the new binary program for the process  and not the file whose name was given  to exec  The argument list given to exec is altered a little bit by the kernel to include the script  file name as an argument  As a result  executing hello is actually equivalent to doing this      rc hello    To say it explicitly  a shell script is
346. hat may not be part of an identifier      Because the substitution affects all the regular expression  we need to substitute the matched  string with another one that has word instead of text  but keeping the characters matching    a z0 9_  before and after the string text  This can be done by surrounding in parentheses  both   a z0 9_   Later  in the destination string  we may use  1 to refer to the text matching  the first regexp within parenthesis  and   2 to refer to the second     Because printtext is not matched by   a z0 9_ text  a z0 9_   it was  untouched  However      text     was matched  In the destination string   1 was a white space   because that is what matched the first parenthesized part  And  2 was a right parenthesis  because  that is what matched the second one  As a result  we left those characters untouched  and used  them as context to determine when to do the substitution     Regular expressions permit to clean up source files in an easy way  In may cases  it makes  no sense to keep white space at the end of lines  This removes them       sed    s     S         We saw that a script t  can be used to indent text in Acme  Here it is       cat  bin tt     bin re  sed  s          r    This other script removes one level of indentation       cat  bin t      bin re  sed  s    Loft    r    How many mounts and binds are performed by the standard namespace  How many others of  your own did you add  The file  lib namespace is used to build an initial namespace 
347. he  Keyboardctl structure and puts the console back in cooked mode  So  both control structures      312      were kept as globals in this version for the program  The next function does all the final cleanup     void   terminate  void       closekeyboard kctl    closemouse  mctl    closedisplay  display    threadexitsall  nil         12 8  Drawing text    With all the examples above it should be clear how to use the abstractions for using the devices  related to graphical user interfaces  Looking through the manual pages to locate functions  and  other abstractions  not described here should not be hard after going this far     Nevertheless  it is instructive to see how program can write text  For example  the imple   mentation for the console in rio writes text  Both because the echo and because of writes to the   dev cons file  But can this be on a graphic terminal     There are many convenience functions in draw 2  to draw lines  polygons  arcs  etc  One of  them is st ring  which can be used to draw a string  Note  not to write a string     Sig string  Point string Image  dst  Point p  Image  src  Point sp  Font  f  char  s     Suppose that we want to modify the slider program to write the slider value using text  near the  left border of the slider window  This could be done by adding a line to sLiderthread  similar  to this one    string screen  pos  display  gt black  ZP  font   68          This draws the characters in the string 68 on the image screen  the destinatio
348. he entire screen if no window system is running     To which data type does screen point to  Where can you draw things on  It turns out that  the screen is an image  the data abstraction provided by draw 3   It represents a piece of memory  used as an image by the graphics card  It is just a rectangular picture  A program may draw by  changing bits in the image for its screen  Most of things a program uses for drawing are also  images  For example  colors are images  with pixels in the appropriate color   to write text in the  screen a program draws images for the appropriate characters  a window is essentially an image   that a program will use as its screen   the entire screen  also called the display  is an image as  well  The data type Image  is defined in draw h     typedef struct Image Image   struct Image         Display  display     display  connection to draw 3      int id     id of draw 3  Image      Rectangle r     rectangle for the image     Rectangle clipr     clipping rectangle      int depth     number of bits per pixel      ulong chan     how to encode colors      int repl     flag  replicated to tile clipr     Screen  screen     or nil if not a window                Together  display and id identify an image as the one named id in the draw device at the other  end of the connection represented by the display        An interesting piece of information in this structure is Image   r  It describes the rectangle  in the entire screen used by the image  Thus  scre
349. he first line as well  However  that  line is a comment and  therefore  ignored    Scripts have arguments  as any other executable program has  The shell interpreting the  script stores the argument list in the environment variable named          This is echo using echo     rcecho     bin re  echo          And this is what it does    rcecho hello world  hello world    As an additional convenience  within a shell script   0 is equivalent to argv  0  ina C program    1 to argv  1   and so on     Problems  1 Trace  by hand  the execution of this program  Double check by executing it in the machine      include  lt u h gt    include  lt libc h gt     void  main int  char         fork     fork     print   hi n           Compile and execute the first program shown in this chapter  Explain the output     3 Fix the program from the previous problem using wait 2      Implement your own version of the time 1  tool  This program runs a single command and  reports the time the command took to execute  elapsed time  time spent executing user code   and time spent executing kernel code      5 Implement a function  char  system char  cmd    That receives a command line as an argument and must execute it in a child process like the  Plan 9 shell would do  Think of a reasonable return value for the function   Hint  Which program did we say that knows how to do this type of work   6 Write a script that interprets another script  for example  by using rc  Can you specify that      100      a pr
350. he next program does     pong2 c  include  lt u h gt   include  lt libc h gt     include  lt thread h gt                    void  pingpongthread  void a       ulong msg     Channel c   a     for        msg   recvul  c      i e   rvrecv c   amp msg    msgt    print   Sd n   msg      sendul c  msg      i e   send c   amp msg           void   threadmain int  char          Channel  c    int kickoff     c   chancreate sizeof int   0    threadcreate  pingpongthread  c  8 1024    threadcreate  pingpongthread  c  8 1024    kickoff   0    sendul c  kickoff     threadexits  nil              Initially  both threads  now running pingpongthread  will block at recv  They are ready  for their match  When the main thread sends an initial zero through the only channel  the thread  that called recv first will be the one receiving the message  Which one does receive it  We do  not care  If both players run the same code  why should we care     At this point things work as discussed above  The thread that received the initial zero is now  after its recv  preparing to send 1 to the other  The other thread is still waiting inside recv   The send from the former will deliver the number to the later  And both calls will meet in time  because of the lack of buffering in the channel  Later  the very same channel will be free to send      274      another number back     The program uses sendul and recvul  instead of send and recv  These functions are  convenience routines that send and receive an unsi
351. he same  output  Another special name is            called dot dot  It refers the parent directory  That is  it  walks up one element in the file tree  For example   usr nemo    is  usr  and     usr nemo       is simply      To change the current directory in the shell  we can use the cd  change dir  command  If we  give no argument to cd  it changes to our home directory  To know our current working direc   tory  the command pwd  print working directory  can be used  Let   s move around and see where  we are     Ca   i pwd    usr nemo     cad     pwd         cd usr nemo lib   pwd   usr nemo lib   Pe Od  Bef o gt  7 OWE     usr    This command does nothing  Can you say why     ee CA    r    Now we know which one is the current working directory for commands we execute  But  which  one would be the working directory for a command executed using acme  It depends  When you  execute a command in acme  its working directory is set to be that shown in the window  or con   taining the file shown in the window   So  the command we executed time ago in the acme win   dow for  usr nemo had  usr nemo as its working directory  if we execute a command in the  window for a file  usr nemo newfile  its working directory would be also  usr nemo     Directories can be created with mkdir  make directory   and because they are files  they can be  also removed with rm  Although  because it may be dangerous  rm refuses to remove a directory  that is not empty      15     zuca     mkdir dir   a i a
352. he shell running in the  window  We can also try this       echo hangup  gt  proc Spid notepg  And the window is gone     This required having an abstraction  i e   a mechanism  to be able to group those processes and  post a note just for them  The process group is this abstraction     By the way  notes are the mechanism used by the system to signal exceptional conditions   like dividing by zero  Notes posted by the system start with suicide   and put the process into  the broken state  for debugging     Processes can use atnotify to register a notification handler that listens for notes  The  function receives a note handler as a parameter  and installs the handler if the second parameter is  true  or removes the handler otherwise       sig atnotify  int atnotify int   f   void   char    int in     The handler is a function that receives a pointer to the process registers as they were when it  noted the note  This is usually ignored  The second parameter is more interesting  it is a string  with the text from the note  When the note is recognized by the handler  it must return true  to  indicate that the note was attended  Otherwise  it must return false  This is required because there  can be many handlers installed for a process  e g   one for each type of note  When a note is  posted  each handler is called until one returns true  If no handler does so  the note is not  attended  and the process is killed     This program may provide some insight about notes  It register
353. he size of a char   and with enough buffering for  Nmsgs messages  Thus  the channel is our bounded buffer     bufc   chancreate sizeof char    Nmsgs      The program will never destroy the channel  ever  Should we want to destroy it  we might call    chanfree  bufc      But that can only be done when the channel is no longer needed  after the last consumer com   pletes its job  The consumer calls    recv bufc   amp msg      to receive a message from the channel  Once a message is received  the message is stored by  recv at the address given as the second argument  That is  recv receives a char  and stores it  at  amp msg  After having received the message  the consumer prints it and tries to receive another  one     The producer  on the other hand  concocts a message and calls    send bufc   amp msg      This call sends through the channel the message pointed to by  amp msg  with the size of a char    That is  send sends the  pointer  value in msg through the channel     If producers start first and put messages in the channel  they will block as soon as the  buffering in the channel fills up  similar to what would happen in a pipe   If the consumers start  first and try to get messages from the channel  they will block if the buffer in the channel has no  messages  This is the behavior of send and recv when the channel has some buffering     It may be illustrative for you to compare this program with pc c  the version without using  channels that we made in the last chapter
354. henti   cation fid 465  Such operations obtain messages and send them to the server   s factotum  respec   tively  After a series of messages authenticate the client using the POSK1 protocol  the client  sends a Tattach request providing the authentication file  fid 465  as a proof of identity  The  server accepts the proof  and the client manages to attach to the server  At this point  the authenti   cation file is no longer useful and is clunked by the client  because its afid was closed      This was the idea  Both the client and the server managed to speak P9SK1 to authenticate  without having a single clue about that authentication protocol  They just arranged for their fac   totums to speak the protocol  on their behalf       371      14 6  Identity changes    At this point  despite our efforts  we could ask the question  is the server secure  In this case   semfs does not listen to requests in the network  and authenticates clients  That seems secure  enough  However  there is an important common sense rule in security  called the least privilege  principle  This rule says that a program should have no more rights than needed to perform its  job  The semfs file server serves semaphores  But a bug in the program might make it access  files or do any other weird thing  Attackers might exploit this     What we can do is to put the server in a sandbox  and remove any privileges that the user  who starts it might have  This can be done by changing our user to none  which ca
355. here can be a dozen of such connections  all different  that happen to  reach that particular address  They would differ in the addresses for their other extremes     6 2  Names    Above  we have been using names for machines and services  ports   However  these names must  be translated into addresses that the network software could understand  For example  the  machine name whale must be translated to an IP address like 193 147 81 86  The network  protocol  IP in Internet  knows nothing about names  It knows about machine addresses  In the  same way  the transport protocol TCP knows nothing about the service with name http  But it  does know how to reach the port number 80  which is the one that corresponds to the HTTP ser   vice     Translating names into addresses  including machine and service names  is done in a differ   ent way for each kind of network  For example  the Internet has a name service known as DNS   domain name service  that knows how to translate from a name like whale 1lsub org into an  IP address and vice versa  Besides  for some machines and services there may be names that  exist only within a particular organization  Your local system administrator may have assigned  names to machines that work only from within your department or laboratory  In any case  all the  information about names  addresses  and how to reach the Internet DNS is kept in a  textual  data   base known as the network database  or just ndb  For example  this is the entry in our   l
356. hese files are likely to show up in your  dev     If you want to format a hard disk found at a remote machine  you may do so from your ter   minal  Imagine the disk is at your CPU server  you might do what follows       Import Scpu     S     n cpudisks    Ic  n cpudisks  sdco sdcl sdDO sdD1 sdetl    r    If you do not have a floppy reader unit at your terminals  which is the common case today for lap   tops   there is no need to worry  You can import  f  the root directory for the floppy disk driver   from another machine  And then use the script a   which mounts the DOS formatted floppy of  your terminal at  n a       import  bc barracuda     f     dev  oo a      cp afile  n a afile txt     unmount  n a    As you could see  import admits the same familiar options for mount and bind  to mount the  imported tree before  after  or replacing part of your namespace    This applies to the the serial port  the audio card  and any other resource that any other  machine might have  provided it is represented as a file  As a final example  firewalls are  machines that are connected to two different networks  one protected network for local use  and  the internet  In many cases  connecting directly to the internet from the local network is forbid   ded  to create a firewall for viruses and malicious programs  Nevertheless  if the firewall network  for connecting to the Internet is  net  alt  at the firewall machine  this grants your machine  direct connection to the internet as well  a
357. hich files provide the interface for the device of interest  and how to use them  The  same idea is applied for many other cases  Many tools in Plan 9  listed in section 4 of the man   ual  adopt the form of a file server     For example  various archive formats are understood by programs like fs tarfs  which  understands tape archives with tar 1  format   f  s zipfs  which understands ZIP files   etc   Consider the tar file with music that we created time ago       225        tar tf  tmp music tar  alanparsons   alanparsons irobot mp3  alanparsons whatgoesup mp3  pausini   pausini trateilmare mp3  supertramp   supertramp logical mp3    We can use tarfs to browse through the archive as if files were already extracted  The program  tarfs reads the archive and provides a  read only  file system that reflects the contents in the  archive  It mounts itself by default at  n tapefs  but we may ask the program to mount itself  at a different path using the    m option       fs tarfs  m  n tar  tmp music tar    ns   grep tar  mount  c       datal     n tar    The device    is the pipe 3  device  Pipes are created by mounting this device  this is what  pipe 2  does   The file          datal    is an end for a pipe  that was mounted by tar at  n tar   At the other end of the pipe  tarfs is speaking 9P  to supply the file tree for the archive that we  have mounted     The file tree at  n tar permits browsing the files in the archive  and doing anything with  them  other than writing or 
358. hich terminates the buffering  If you really want to flush your buffer   i e   to send all the bytes in it to the file  you may call Bf lush                   80       sig Bflush  int Bflush Biobufhdr  bp        To play with this  and see a couple of other tools provided by Bio  we are going to reimplement  our little cat program but using Bio this time     biocat c   include  lt u h gt    include  lt libc h gt      include  lt bio h gt     void   main int   char           Biobuf bin   Biobuf bout   char  line     int len     Binit  amp bin  0  OREAD    Binit   amp bout 1  OWRITE    while line   Brdline  amp bin       n          len   Blinelen  amp bin            Bwrite  amp bout  line  len       Bterm  amp bin    Bterm  amp bout     exits nil              This program uses two Biobufs  like the previous one  However  we now want one for reading  from standard input  and another to write to standard output  Because we already have file  descriptors 0 and 1 open  it is not necessary to call Bopen  The function Binit initializes a  Biobuf for an already open file descriptor                Sig Binit  int Binit  Biobuf  bp  int fd  int mode        You must declare your own Biobuf  Note that this time bin and bout are not pointers  they  are the actual Biobufs used  Once we have our bin and bout buffers  we might use any other  Bio function on them  like before  The call to Bterm terminates the buffering  and flushes any  pending data to the underlying file  However  because Bio d
359. hostowner  358  device  107   capability  372   console  171  289   draw  299   driver  26  166   driver  storage  176   hardware  26   mouse  295   network  135   path  166   pipe  225   root  166   storage  321   to device  76   vga  298  device driver  166  225  171  289  171  51  167  300  295  50  162  167  176  321  123  v  298  devices  graphic  298   dev kmesg  290   dev kprint  290   dev label  301  316   dev mouse  174  295  314   dev mousectl  295   dev null  97  171  188   dev screen  52   dev sysname  358   dev text  316   dev text  52   dev time  50  69  171   dev user  359    Hn TB rOAaADT               dev window  52   dev winid  315   dev winname  303  315   dev wsys  316   dev zero  76  diagnostic  106  command  12  diagnostics  script  211  dial  142  dialing  141  diehard  88  diff  210  context  211  flag  n  211  differences  file  210  Dir  69 70  328  directory  5  12  change current  14  copy  198  creation  66  330  current  13  29  58  dot  14  dot dot  14  empty  67  entry  68  328  home  5  14  42  172  line  136  145  300  list  72  permissions  19  print current  14  read  70  reads  345  root  13  153  working  153  dirfstat  70  dirfwstat  72  dirgen  346  dirread  70  dirread9p  346  dirstat  69  71  328  dirwstat  71  discard  output  107  discipline  line  290  disk  321 322  description  321    file  321  initialization  324  local  324  partitioning  324  space  64    storage  321  usage  198  205  Display  301  307   display  file  15   
360. hown above corresponds to the key used to authenticate to file servers using  the P9SK1 authentication protocol  Plan 9 Shared Key  Ist      key proto p9sk1 dom dat escet urjc es user nemo  password     As you can see  a key is a series of attribute and value pairs  In this key  the attribute proto has  as value p9sk1  The purpose of this attribute is to identify the protocol that uses this key  Other  attributes depend on the particular authentication protocol for the key  In P9SK1 keys  dom iden   tifies the authentication domain for a key  This is just the name that identifies a set of machines   for organizative purposes  that share an authentication server  The attribute user identifies our  user name within that domain  Note that we might have different POSK1 keys for different  authentication domains  and might have different user names for them  The attribute password  has as its value a secret  that is not shown by factotum     New keys can be added to factotum by writing them to the ct 1 file  using the same syntax   The next command adds a key for using P9SK1  as the user nemo  for the foo  com authentica   tion domain       echo    key proto p9sk1 dom foo com user nemo  password whoknows           gt  mnt factotum ctl     grep foo com  mnt factotum ctl   proto p9sk1 dom foo com user nemo  password     r    The value for the attribute password is the shared secret used to authenticate the user nemo  by  using the authentication server for the foo com domain  Becaus
361. hronizing processes that  share memory  When they do not share memory  pipes are excellent synchronization means  and  you have already used them     10 2  Locks    How do we solve the problem  The race condition happens because more than one process may  simultaneously use a shared resource  i e  the global counter  This is what breaks the assumption  that cnt does not change between lines  1  and  3  in     1  loc   cnt    2  loc      3  ent   loc     Furthermore  the reason why more than one process may use cnt simultaneously is because this  block of code is not atomic  It is not a single instruction  which means that in the middle of the  block there may be a context switch  and the other process may change cnt or consult it while  we are in the middle of a change     On the contrary  the executions for the first two versions of our program behaved as if this  block of code was atomic  It just happen that one process executed the problematic code  and then  the other  The code was executed without being interrupted by the other process in the middle of  the update for cnt  And the net effect is that the program worked  We now know that we were  just lucky  because there could have been a context switch in the middle  But the point is that  when the block of code behaves as an atomic instruction  there are no races  and the program  behaves nicely                                      Parent Child Parent Child  cnt  0  ent  0   entt   Chik  ents  1  ent  1   cntt   cntt   
362. hrows away the output  by sending it to  dev null     5 4  Pipes    There is a whole plethora of programs in Plan 9 that read some data  perform some operation on  it  and write some output  We already saw some  Many tasks can be achieved by combining these  programs  without having to write an entire new program in C or other language     For example  this book is typeset using troff 1   and the input text is kept at files named  chl ms  ch2 ms  and so on  each one with the text for one chapter  A rough estimate of the  book size would be to count the number of words for all the files containing troff input for chap   ters  We can use a program to count words  Option  w for wc does just that       108        wc  w ch  ms    12189 chli ms  9252 ch2 ms  8153 ch3 ms  6470 ch4 ms  3163 ch5 ms   61 ch6 ms  592 chXX ms  39880 total       This gives a good break down of the number of words in each file  and also of the total  as of  today  when we are writing this   However  to obtain just the total we can give a single file to wc      cat ch  ms  gt  tmp all ms    wc  w  tmp all ms  39880  tmp all ms    If we suspect that we use the word file too many times in the book  and what to check that out  we  can count the number of lines that contain that word as an estimate  The program grep writes to  its output only those lines that contain a given word  We can run      grep file  lt  tmp all ms  gt  tmp lineswithfile  to generate a file 1ineswithfile that contains only the lines that
363. ib ndb local file for whale     dom whale lsub org ip 193 147 81 86 sys whale    When we used whale in the examples above  that name was translated into 193 147 81 86  and that was the address used  Also  this is the entry in our  1ib ndb common file for the ser   vice known as 9fs when using the TCP protocol     tcp 9fs port 564    When we used the service name 9fs  this name was translated into the port number 564  that  was the port number used  As a result  the address tcp  whale  9fs was translated into  tcp 193 147 81 86 564 and this was used instead  Names are for humans  but  sadly  the  actual network software prefers to use addresses     All this is encapsulated into a program that does the translation by itself  relieving from the  burden to all other programs  This program is known as the connection server  or cs  We can  query the connection server to know which address will indeed be used when we write a particu   lar network address  The program csquery does this  It is collected at  bin ndb along with  other programs that operate with the network data base       ndb csquery    gt  tcp whale 9fs    net tcp clone 193 147 81 86 564   gt     The     gt     sign is the prompt from csquery  it suggests that we can type an address asking for its  translation  As you can see  the connection server replied by giving the path for the clone file  that can be used to create a new TCP connection  and the address as understood by TCP that cor   responds to the one we typed 
364. ibc  h  as a short integer     However  using a stream of 16 bit numbers to exchange text between different programs  would be a nightmare because it would break all the programs written to use just ASCII  which  uses a single byte for each character  Furthermore  many C programs use strings codified as a  sequence of bytes terminated by a final null byte  Sending a stream of 16 bit runes to such pro   grams will make them fail     To maintain compatibility with the huge amount of software that existed when Unicode was  invented  a encoding was designed to transform an array of runes into a byte stream that could be  backward compatible with ASCII  This encoding is called UTF 8   Universal character set Trans   formation Format  8 bits  or just UTF  for short   UTF 8 was invented by Ken Thompson  appar   ently in a dinner   s table  shared with Rob Pike   Runes like      amp   and X do not use a single byte  when codified in UTF  A rune may use up to three bytes in Plan 9   s UTF     A program reading text  reads a UTF byte stream  that is exactly the same used by ASCII  when the text contains characters present in 7 bit ASCII  most characters but for accentuated let   ters and other special symbols   After having read some text  if it is to be processed as such  the  program converts the UTF representation into unicode  Then it is processed  Afterwards  to out   put some text as a result  the program is expected to convert the text from unicode back into UTF   before sending
365. ibrary function readn exists that keeps on calling read until all the n bytes have been  read  However  This function may return less bytes than requested  because of a note  Of course  this would happen only if the process is attending the note  because it would be killed otherwise   and what readn does would not matter at all     To actually read n bytes even when receiving notes  we can use this alternate function       121      long  robustreadn int fd  char  buf  long n          long nr  tot   char err 128    for  tot   tot  lt  n  tot    nr       0   nr   read fd  buft tot  n tot    if  nr    0    break   if  nr  lt  OJA   rerrstr  err  sizeof  err      if  strcmp  err   interrupted      0    nr   0     retry  did not read anything       else  break           return tot          It requires the process to install a handler for the interrupted note  or the process will be  killed     Surprisingly enough  there are times when the problem is not that read is interrupted  but   on the contrary  the problem is that it is not interrupted  For example  a process may need to read  a message sent from anywhere else in the network  This is achieved by calling read on a file that  is used to connect the process with the one that is supposed to send it a message  Similar to a  pipe  but crossing the network  There is a problem in this case  If the other  remote  process  hangs  because of a bug or any other reason  it may never send its message  The poor process that  is reading wi
366. id   r  gt fid  gt qid   respond r  nil           After compiling the new program into 8 asemfs  we can try it  As you may remember   8 asemfs mounts itself at  mnt sem  the parent process spawns a child to speak 9P  and  mounts it   Using the flag  D  we asked for a dump of 9P messages to see what happens  First   we execute it while using a factotum that has no keys       370        8 asemfs  D    lt  11  Tversion tag 65535 msize 8216 version    9P2000      11  gt  Rversion tag 65535 msize 8216 version    9P2000      lt  11  Tauth tag 10 afid 485 uname nemo aname    11  gt  Rauth tag 10 qid  8000000000000001 0 A     lt  11  Tread tag 10 fid 485 offset 0 count 2048    11  gt  Rerror tag 10 ename authrpc botch    lt  11  Tattach tag 10 fid 487 afid 485 uname nemo aname   11  gt  Rerror tag 10 ename authrpc botch    lt  11  Tclunk tag 10 fid 485   11  gt  Relunk tag 10  8 asemfs  mount  mnt sem  authrpc botch             r       This time  the server replied to Tauth with an Rauth message  and not with an Rerror to  indicate that authentication was not required  Because of this  the amount call made by the client   the parent process  calls auth_proxy to authenticate the user to the server     You may see how the poor client tries to read the authentication fid  485   to obtain a mes   sage from the server as part of the authentication protocol  It fails  The server    s factotum informed  with an authrpc botch error that it could not authenticate  This is not a surprise  beca
367. id  It loaded the program from  bin 1s into our process  and  jumped to its main procedure supplying the arguments    1s         1     and     usr nemo     Remem   ber that argv  0  is the program name  by convention  The last parameter to the exec1 call    was nil to let it know when to stop taking parameters from the parameter list     There is an important thing that the output for our program does show  Indeed  that it does  not show  The print we wrote after calling execl is missing from the output  This makes  sense if you think twice  Because exec1 loads another program  e g   that in  bin 1s  into our  process  our code is gone  If execl works  the process no longer has our program  It has that of  ls instead  Also  our process no longer has our data  nor our stack  Initial data and stack for 1s is  there instead  What a personality change     Now consider the same program but replacing the call to exec1 with this one     execl  ls     1     usr nemo   nil      This is the output now when the program is run       8 execl  running ls  exec failed     ls    file does not exist       This time  both calls to print execute  Because exec  failed to do its work  it did not load any  program into our process  Our mind is still here  and the second printed message shows up  Why  did exec1 fail  We forgot to supply the file name as the first parameter  Therefore  exec1 tried  to access the file    1s to load a program from it  Because such file did not exist  the system call  
368. id  reader  void        as before     wlock   amp   msg 1ck    free  msg text    msg text   strdup  buf    msg verst t    wunlock   amp   msg 1ick      as before            If you want to feel the difference between the version using QLocks and the one using  RWLocks  try to increase the number of panels to 15  and make the panelprocs take a little  bit more time to read msg  for example  by using sleep to make them hold the lock for some  time  In the first time  messages will slowly come out to the panels  or your standard output in  this case   If each process holds the lock for a second  the 15th process acquiring the lock will  have to wait at least 15 seconds  In the second case  all of the pannels will be quickly updated   Furthermore  using the RWLock keeps the resource locked for less time  because the readers are  now allowed to overlap     This is shown in figures 10 6 and 10 7  Both figures assume that initially  the writer and all  the readers try to acquire the lock  the time advances to the right   When using a queueing lock   look at what happens to the readers  Compare with the next figure  which corresponds to using a  read write lock       246         Writer Se a E eb hatte Dest E E ean ORTE teh Dam OANE  Reader 1 ea ee Se EE E louse idan adtea toes ae  Reader 2 cececesececsecenenn     ekd   eRe E Costes  Redet a oaee eae E E TRE EE AES had    Figure 10 6  Multiple readers make turns to read when using a queuing lock     Writer ee E Aaah inant hte Asha Taam
369. id 486 offset 0 count 8192   12  gt  Rread tag 14 count 4    hola      hola lt  12  Tread tag 14 fid 486 offset 4 count 8192   12  gt  Rread tag 14 count 0           lt  12  Tclunk tag 14 fid 486    12  gt  Rclunk tag 14            330      The program cat opens  n ram x  It all works like before  The Twalk request manages to  get a new fid  486  referring to file  x within the file server  However  the following Topen  opens the file just for reading  mode is zero   Now  cat calls read  to read a chunk of bytes  from the file  It asked for reading 8192 bytes  The reply  Rread  sent only 4 bytes as a result  At  this point  the system call read terminated and cat printed what it could read  the file contents   The program had to call read again  and this time there was nothing else to read  the number of  bytes in Rread is zero   So  cat closed the file     A file can be created by sending a Tcreate request to a file server  This is the 9P dialog  for creating the directory  n ram a       mkdir  n ram a    lt  12  Twalk tag 14 fid 435 newfid 458 nwname 1 O a   12  gt  Rerror tag 14 ename file not found    lt  12  Twalk tag 14 fid 435 newfid 474 nwname 1 O a   12  gt  Rerror tag 14 ename file not found    lt  12  Twalk tag 14 fid 435 newfid 474 nwname 0   12  gt  Rwalk tag 14 nwqid 0        lt  12  Tcreate tag 14 fid 474 name a perm d rwxr xr x mod 2147483137       12  gt  Recreate tag 14 qid  0000000000000003 0 d  iounit 0   lt  12  Tclunk tag 14 fid 474   12  gt  Reclunk tag
370. id not open the file descriptor for the  buffer  it will not close it either           Unlike the previous program  this one reads one line at a time  because we plan to use it  with the console  The function Brdline reads bytes from the buffer until the end of line delim   iter specified by its second parameter          sig Brdline  void  Brdline Biobufhdr  bp  int delim     We used      n     which is the end of line character in Plan 9  The function returns a pointer to the  bytes read  or zero if no more data could be read  Each time the program reads a line  it writes the  line to its standard output through bout  The line returned by Brdline is not a C string         81        There is not a final null byte after the line  We could have used Brdstr  witch returns the line  read in dynamic memory  allocated with malloc   and terminates the line with a final null byte   But we did not  Thus  how many bytes must we write to standard output  The function  Blinelen returns the number of bytes in the last line read with Brdline             sig Blinelen  int Blinelen Biobufhdr  bp        And that explains the body of the while in our program  Let   s now play with our cat         biocat   one little   cat was walking   control d   one little   cat was walking     r       No line was written to standard output until we typed control d  The program did call Bwrite   but this function kept the bytes in the buffer  When Brdline returned an EOF indication  the  call to Bterm termin
371. ides the primary system interface to graphics     Draw maintains connections between processes using graphics  and the graphics device  itself  Of course  connections to the draw device are represented as files  similar to what happen      300      with network connections  Its file tree is available at  i  but is also bound at  dev       lc  dev draw    1 2 42 new    Ic  dev draw 1  colormap ctl data refresh    Here  directories 1  2  and 42 are the interface for three different connections maintained as of  this moment in my terminal  The directory for a connection  besides other files  has a ct 1 anda  data file  like it happen with network line directories  Opening the file  dev draw new  establishes a new connection  So  a process that wants to use graphics must open   dev draw new  and then write to the data file for its connection messages that encode the  graphic operations to be performed     The draw device provides the Image abstraction  along with operations to allocate  deallo   cate  and drawing on it  All the graphics operations are performed by this device  Programs using  graphics talk directly to the device  by establishing connections to it  and asking it to perform  operations on images  Instead of using the device interface directly  most programs use the  draw 3  library  as shown next     12 5  Graphics    Graphics are provided through the file interface for the draw device  This happens both when  using the console  before the window system runs  and a
372. ient representation techniques for the  same data       gzip music tar     lIs  L music          rw r  r   M 19 nemo nemo 10240 Jul 21 00 17 music tar      rw r  r   M 19 nemo nemo 304 Jul 21 00 22 music tgz       The file music tgz was created by gzip  In most cases  gzip adds the extension   gz for the  compressed file name  But tradition says that compressed tar files terminate in   tgz     Before extracting or inspecting the contents of a compressed archive  we must uncompress  it  Below we also use the option  f for tar  that permits specifying the archive file as an argu   ment       tar  tf music tgz    386 bin tar  partial block read from archive    gunzip music tgz     tar  tf music tar   alanparsons    alanparsons irobot mp3   AIC       So  how can we copy an entire file tree from one place to another  You now know how to use  tar  Here is how         ced  music   tar  c         cd  otherdir   tar x    The output for the first compound command goes to the input of the second one  The first one    changes its directory to the source  and then creates an archive sent to standard output  In the sec   ond one  we change to the destination directory  and extract the archive read from standard input     A new thing we have seen here is the expression          which is like        but executes the  command block in a child shell  We need to do this because each block must work at a different      200      directory     Problems    1    The file  lib ndb local lists machine
373. ifier of the thread that calls the function     The function threadcreate returns the identifier for the thread it created  and the pro   gram prints this value as well  to let you see how things match  In general  threadid is used  when a thread wants to know its own identifier  However  to know the ids for some threads      265      created  it suffices to record the return values when threadcreate is called  The program  prints the PID along with the thread ids  to let you clearly see the difference     tid c          include  lt u h gt   include  lt libc h gt     include  lt thread h gt                    void   threadfunc  void        print   thread id   d tpid  d n   threadid    getpid      threadexits  nil      void  threadmain int  char           int i  id     print   thread id   d tpid  d n   threadid    getpid      for  i   0  i  lt  2  it     id   threadcreate threadfunc  nil  8 1024    print    tcreated thread  d n   id              This is the output from the program           tid   thread id  1 pid 3904  created thread 2  created thread 3   thread id  2 pid 3904   thread id  3 pid 3904    What would happen if we implement cnt from the last chapter  but using threads  This program  used two flow of controls  One was kept incrementing a counter  The other one tried always to  decrement the counter  but not below zero  The next program creates two threads  One runs this  function     void  incr  void  arg        int  cp   arg     threadsetname   incrthread     for 
374. ile descriptor  table                     y                          dev cons                Figure 3 2  File descriptors for the program after opening  dev cons     When the file is no longer useful for the program  it can be closed  This is achieved by call   ing close  which releases the file descriptor  In our program  we could have open  dev cons  several times  one for reading and one for writing    infd   open   dev cons   OREAD    outfd   open   dev cons   OWRITE                      using the integer constants OREAD and OWRITE  that specify that the file is to be open only for  reading or writing  But it seemed better to open the file just once        The file interface provided for each process in Plan 9 has a file that provides the list of open  file descriptors for the process  For example  to know which file descriptors are open in the shell  we are using we can do this       cat  proc Spid fd     usr nemo   Or M 94  0000000000000001 0 00  8192 18  dev cons  Iw M 94  0000000000000001 0 00  8192 2  dev cons  2w M 94  0000000000000001 0 00  8192 2  dev cons  3  G O  0000000000000002 0 00  0 0  dev cons  4w c O  0000000000000002 0 00  0 0  dev cons  5 w ic O  0000000000000002 0 00  0 0  dev cons  6 rw   O  0000000000000241 0 00  65536 38    data   7 rw   O  0000000000000242 0 00  65536 81320369    datal  8 rw   O  0000000000000281 0 00  65536 0    data   9 rw   O  0000000000000282 0 00  65536 0    datal  10r M 10  00003b49000035b0 13745 00  8168 512  rc lib rcmain  
375. ill  run the command  In this case  the child process will just call rfork  RFFDG RFNOTEG   but  it will share the namespace and environment variables with its parent  i e   with Acme   Figure  7 6 shows another attempt to change the name space in Acme  The command executed this time  was       Local mkdir  tmp dir   bind  usr nemo  tmp dir    and Acme executed      165      mkdir  tmp dir   bind  usr nemo  tmp dir    within its own name space  Note that Local refers to the whole text executed as a command line   and not just to the first command  This time  opening  tmp dir after the bind shows the  expected directory contents     Newcol Kill Putall Dump Exit    fusr nemo  Del Snarf Get   Look  _  bin  guide mail  ohist src   lib  private  imp                               bin  guide mail  ohist src   doc  lib  offline  private  tmp           Figure 7 6  Commands executed with Local share their name space with Acme     A related surprise may come from using the plumber  when you change the name space  after starting it  The plumber has its own name space  that in effect for the shell that executed  your Shome 1lib profile  in case it was started from that file  When the window system  Starts  it takes that name space as well  However  the window system puts each window  process   in its own name space     If there are three different windows running Acme  and you plumb a file name  the file will  be open by all the Acmes running  This is simple to understand  because all the
376. ill be  the same  namely  just  a b c   What is the actual value of the environment variable for x   We can see it       xd  c  env x  0000000 a 00 b 00 c 00  0000006    Just the three strings  a  b  and c  Rc follows the C convention for terminating a string  and sep   arates all the values in the list with a null byte  This happens even for environment variables that  are a list of a single word      x 3     xd  c  env x   0000000 3 00   0000002    The implementation for the library function getenv replaces the null bytes with spaces  and that  is why a getenv for an rc list would return the words in the list separated by white space  This  is not harmful for C  as a0 would be because 0 is used to terminate a string in C  And it is what  you expect after using the variable in the shell     The variable holding the arguments for the shell interpreting a shell script is also a list  The  only difference is that the shell initializes the environment variable for    automatically  with the  list for the arguments supplied to it  most likely  by giving the arguments to a shell script     Given a variable  we can know its length  For any variable  the shell defines another one to  report its length  For example     x hola  echo S x    Fi ne Ne      X  a bo     echo S x  3    The first variable was a list with just one word in it  As a result  this is the way to print the num   ber of arguments given to a shell script   echo        because that is the length of     which is a list
377. ill be put again  in the processor and consume all the time given to it by the system  When all processes are  blocked waiting for something to happen  8 po11 is still very likely to be ready to run  As a  result  the system load is at its maximum  Later  we pressed delete and killed 8  po11  and the  system load came back to a more reasonable value     Note that a high load does not mean that the system is unresponsive  i e   that it cannot cope  with any more work to do  It just means that there is always something to do  Of course  given the  sufficient amount of things to do  the system will become unresponsive because no process will  be given enough processor time to complete soon enough  But that does not need to be the case if  the load is high     Compare what you saw with the load while executing our second version for the polling  program  which calls sleep to perform one poll each 5 seconds  The window running stats  while we executed this program is shown in figure 5 7  This program behaved nicely and did not  alter much the system load  Most of the time it was sleeping waiting for the time for its next poll   As an aside  it is interesting to say that Plan 9 typically exhibits a much lower system load than  both figures show  The system used to capture both images is a derivative of Plan 9  called Plan  B  which uses polling for many things  When there are many processes polling  the load naturally  increases even if the processes sleep between polls     The sle
378. imilar to our Rendez  are called condition variables  because those languages used this  name for such time       252      10 6  Shared buffers    The bounded buffer is a classical problem  useful to learn a little bit of concurrent program   ming  and also useful for the real life  The problem states that there is a shared buffer  bounded in  size   Some processes try to put things into the buffer  and other processes try to get things out of  the buffer  The formers are called producers  and the latter are called consumers  See figure 10 9    producer       producer                                                 producer    Figure 10 9  The bounded buffer problem     The problem is synchronizing both producers and consumers  When a producer wants to put  something in the buffer  and the buffer is full  the producer must wait until there is room in the  buffer  In the same way  when a consumer wants to take something from an empty buffer  it must  wait until there is something to take  This problem happens for many real life situations  when   ever some kind of process produces something that is to be consumed by other processes  The  buffer kept inside a pipe  together with the process es  writing to the pipe  and the ones reading  from it  make up just the same problem     To solve this problem  we must declare our data structure for the buffer and two operations  for it  put  and get  The buffer must be protected  and we are going to use a QLock for that  purpose  becaus
379. in 386 minimad  316 bin arm minimad  280 bin arm mp3   266 bin 386 minisyncec  258 bin re   212 bin arm calc  181 bin arm mpg123       146 bin 386 r2bib    r    This includes directories as well  but point us quickly to files like bin arm enc that seem to  occupy 864 disk blocks     But in any case  if the disk is filling up  it is a good idea to locate the users that created files   or added data to them   to alert them  The flag  m for 1s lists the user name that last modified  the file  We may collect user names for all the files in the disk  and then notify them  We are  going to play with commands until we complete our task  using sed to print just a few lines until  we know how to process all the information  The first step is to use the output of du as the initial  data  the list of files  If we remove everything up to the file names  we obtain a list of files to  work with       du  a bin   sed    s            sed 3q  bin 386 minimad   bin 386 minisync   bin 386 r2bib    Now we want to list the user who modified each file  We can change our data to produce the com   mands that do that  and send them to a shell       du  a bin   sed    s            sed    s   ls  m        sed 3q  ls  m bin 386 minimad   ls  m bin 386 minisyne   ls  m bin 386 r2bib    du  a bin   sed    s            sed    s   ls  m        sed 3q   re  nemo  bin 386 minimad  none  bin 386 minisync  nemo  bin 386 r2bib    ee    We still have to work a little bit more  And our command line is growing  Bei
380. inates the connection  to the display  closemouse closes the mouse device  and the program exits       305      void  mousethread void  arg      Mousect1l mctl   arg   Mouse m   for       recv mctl  gt c   amp m    if  m buttons     do    recv mctl  gt c   amp m      while m buttons    closedisplay  display    closemouse  mctl    threadexitsall  nil              Note how by placing mouse processing in its own thread  the programming language can be used  to program the behavior of the mouse almost like when describing it in natural language     The new and interesting part in this program is the code for the thread reading resize events     void  resizethread void  arg      Mousectl mctl   arg   for       recvul  mctl     gt resizec    if  getwindow display  Refnone   sysfatal  getwindow  Sr   blank        r     lt  0             After receiving a resize event  through met 1    gt resizec  the program calls get window on the  display  which updates screen  Afterwards  it blanks the image for the new window  The sec   ond parameter to get window has to do with window overlapping  It identifies the method used  to refresh the window contents after being hidden  When two windows overlap  someone must  maintain a copy of what is hidden behind the window at the top  This backup is called backing  store  Rio provides backing store for windows  and the constant Refnone asks for no further  backup  i e   no refresh method      We now want this program to draw a slider  like those of 
381. ind  c  n whale  n other  installs a new entry in the mount table that says  When you reach  n other  continue at   n whale  But note  the names used are interpreted using the name space  Therefore      n whale is not the old  empty  directory it used to be  It now refers to the root of the file  server at whale  And so  listing  n other yields the list for the root directory of our file server          162        le  n fother                      386 acme cron mnt tmp  LICENSE adm dist n usr  LICENSE afpl  alpha lib power   LICENSE  gp  arm lp re   NOTICE cfg mail sys       Because our mount table includes now the entries shown in figure 7 4                                         Chan for Chan for     n whale at tcp whale 9fs  Chan for Chan for     n other at tcp whale 9fs                      Figure 7 4  Entries in the mount table after the bind from  n other to  n whale     How can we know how does our name space looks like  Or  how can we know which  entries are installed in our mount table  The name space is a resource  like file descriptors  and  environment variables  Each process may have its own name space  as controlled by rfork    although the custom is that processes in the same window use to share their name spaces     The file ns in the directory in  proc for a process  lists the mount table used by that pro   cess  Each entry is listed using a text line similar to the command used to install the entry  To  obtain the entries we have installed  we can use grep 
382. indi   cate file permissions  There are three permissions repeated three times  once for the user  once for  the group  and once for others  This is codified as nine bits  Using a number in octal base  which  has three bits for each digit  it is very simple to write a number for a given permission set     For example  consider the ACL rwxr xr x  That is three bits for the user  three for the  group  and three for others  A bit is set to grant permission and clear to deny it  For the user  the  bits would be 111  for the group  they would be 101  and for the others they would also be 101     You know that 111  binary  is 7 decimal  It is the same in octal  You also know that 101   binary  is 5 decimal  It is the same in octal  Therefore  an integer value representing this ACL  would be 0755  octal   We use the same format used by C to write octal numbers  by writing an  initial 0 before the number  Figure 1 6 depicts the process  Thus  the command      chmod 755 afile    would leave afile with rwxr xr x permissions     ii             X        X        K        X    Uv        lt     n         lt       w  1  7  Figure 1 6  Specifying permissions as integers using octal numbers     1 10  Writing a C program in Plan 9    Consider the traditional    take me to your leader     program    that we show here  We typed it into  a file named take c  When we show a program that is stored in a particular file  the file name  is shown in a little box before the file contents     1 Because w
383. indow  The file  whose name is shown in the tag line  is saved     You may notice that the window for  usr nemo is not showing the new file  Acme only does  what you command  no more  no less  You may reload that window using Get and the new file  should appear     The right button  button 3  is used to look for things  A click with the button on a file name  would open that file in the editor  A click on a word would look for it  i e   search for it  in the  text shown in the window     Keyboard input in acme goes to the window where the pointer is pointing at  To type at a  tag line  you must place the pointer on it  To type at the body of a window  you must point to it   This is called    point to type     Note that in rio things are different  Input goes to the window where  you did click last  This is called    click to type        Although you can use acme to execute commands  we will be using a rio window for that in  this book  to make it clear when you are executing commands and to emphasize that doing so has  nothing to do with acme     But to try it at least once  type date anywhere in acme  e g   in a tag line  or in the window  showing your home directory  Then execute it  again  by a click with button 2 on it   You will see  how the output of date is shown in a new window  The new window will be called   usr nemotErrors  Acmes creates windows with names terminated in  Errors to display  output for commands executed at the directory whose name precedes the  Error
384. ing connections and  executes programs to attend them  The machine provides services because certain programs are  started to attend incoming connections targeted to ports     Following the modular design of the rest of the system  listen does not even decide  which ports are to be listened  This program looks at the  rc bin service directory  for files  with names like tcp7  tcp25  and so on  Each file corresponds to a service provided by the  machine  and has a name that corresponds to the protocol and port number where connections for  the service may arrive       Ic  rc bin service    1117007 tcp17007 tcp220 tcp9  il17009 tcp17009 t  p25 tcp993  1117010 tcp17010 tcp53 tcp995  tcp113 tcp17013 tcp565 telcodata  tcp143 tcp19 tcp7    For many services  there are conventions for which ports to use for them in the Internet  you  might call it a standard   For example  TCP port 7 corresponds to the echo service  And this is  how it is implemented in Plan 9       cat  rc bin service tcp7     bin re   bin cat    r    Indeed  each one of the files in the service directory is an executable program that implements  a service  All that listen has to do  is to listen for calls to the ports determined by the file  names  and execute the files to attend each incoming call  Listen arranges for the standard input  and output of the process attending a call to be redirected to the connection itself  For a service   reading from standard input is reading from the connection  and writing to s
385. ing devices is a file tree provided by each device driver  Remember  a device  driver is just the program that drives your device  and is usually linked inside the kernel   That is  to say that Plan 9 device drivers are tiny file servers that are linked to the system     You need to use the files provided by your drivers  which are their interface  if you want to  use the devices  You want to use them to reach your file server across the network  So  you have  to mount these file trees for devices  And we are where we started     The answer to this chicken and the egg problem is a new kind of name that we have silently  omitted until now  You have absolute paths that start walking at    you have relative paths that  start walking at your current directory  and you also have device paths  that start walking at the  root of the file tree of a device     A device path starts with a hash         sign and a character  a rune in unicode  that is unique  for each device  The file  dev drivers lists your device drivers  along with their paths       167        cat  dev drivers  root   cons   arch   env   pipe   proc   mnt   srv       others omitted    oso      O VA             For example  the path  e corresponds to the root directory of the file tree provided by the device  that keeps the environment variables  Listing  e  quoted  because the   is special for the shell   gets the same file list than listing  env  That is because  e is bound at  env by convention       Ic  env   pat c
386. ing one number per input line  we  may set a ridiculous low initial value for the maximum and update its value as we see a bigger  value  It is better to take the first value as the initial maximum  but let   s forget about it  We can  use two special patterns  BEGIN  and END  The former executes its action before processing any  field from the input  The latter executes its action after processing all the input  Those are nice  placeholders to put code that must be executed initially or at the end  For example  this AWK                     218      program computes the total sum and average for a list of numbers       seq 5000   awk 7         BEGIN   sum 0 0          sum     1     i  END   print sum  sum NR      7    12502500 2500 5    Remember that     is printed by the shell  and not part of the AWK program  We have used seq  to print some numbers to test our script  And  as you can see  the syntax for actions is similar to  that of C  But note that a statement is also delimited by a newline or a closed brace  and we do not  need to add semicolons to terminate them  What did this program do  Before even processing the  first line  the action of BEGIN was executed  This sets the variable sum to 0 0  Because the  value is a floating point number  the variable has that type  Then  field after field  the action with   out a pattern was executed  updating sum  At last  the action for END printed the outcome  By  dividing the number of records  i e   of lines or numbers  we comp
387. ing pending is calling respond to reply to the client  By the way  another  helper called readbuf is similar to readstr  but reads from an arbitrary array of bytes  and  not just from a string  Calling readstr is similar to calling    readbuf r  str  strlen str       in any case   That was the implementation for a down  The implementation for an up is contained in the      345      function that attends Twrite messages  Our convention was that a write with a number  printed  as a string  would add so many tickets to the semaphore     static void  fswrite  Req  r          Fid  fid    Qid q    Sem  S    char str 10     Req  qr    char ALEZI      Aas    fid   r  gt fid   q   fid  gt qid   if  q type amp QTDIR     respond r     permission denied       return        if  r  gt ifcall count  gt  sizeof str    1    respond r   string too large     return          memmove  str  r  gt ifcall data  r  gt ifcall count    str r  gt ifcall count    0    s   fid  gt aux    s  gt tickets    atoi str      while s  gt tickets  gt  0  amp  amp  queuedreqs s       qr   dequeuereq s    gr  gt ofcall count   1   s  gt tickets        readstr  qr  nl    respond  qr  nil         respond r  nil              Writing to directories is not permitted and he function checks that QTDIR is not set in the qid for  the file being written  When writing to a file  the function takes the bytes written from  r  gt ifcall data  and moves the bytes in there to a buffer  str  The number of bytes sent in  the write re
388. ing the numeric base used for input and output  Changing the  value for the variable obase changes the base used for output of numeric values  Changing the  value for the variable ibase does the same for the input  It seems to be just the tool  Here is a  session converting some decimal numbers to hexadecimal       184      zu De  obase 16  10   a   20   14   16   10    To print a decimal value in hexadecimal  we can write obase 16 and the value as input for bc   That would print the desired output  There are several ways of doing this  In any case  we must  send several statements as input for bc  One of them changes the output base  the other prints the  desired value  What we can do is to separate both bc statements with a          and use echo to  send them to the standard input of bc       echo    obase 16   512      be  200    We had to quote the whole command line for bc because there are at least two characters with  special meaning for rc  and we want the string to be echoed verbatim  This can be packaged in a  shell script as follows  concatenating  1 to the rest of the command for bc   d2h       bin re   echo    obase 16      S 1   be    Although we might have inserted a   before  1  rc is kind enough to insert one for free for us   You will get used to this pretty quickly  We can now use the resulting script  after giving it exe   cute permission       chmod  x d2h    d2h 32  20    We might like to write each input line for bc using a separate line in the script  
389. ion  106  application  airport  241  274  architecture  97   independent  68  archive  163  198   compressed  199   extraction  199   file  75   tape  198  AREAD access mode  67  ARGBEGIN  37  ARGEND  37  ARGF  38  args rc script  188  argument  11   command  9  11   option  38   script  180   thread  266   vector  92  arguments   program  35   script  99  189  argv  35  44  92  argv0  38  92  arithmetic   expression  98  183   language  183  arm  21             array initializer  186  arrow keys  290  ASCII  292  assert  104  asynchronous communication  117  119  atnotify  118  287  atomic  91   instruction  232  atomic write  91  attach  326  338   specifier  163  313  attribute  plumb message  131  attributes   file  67   plumb message  129  audio CD  225  auth library  364  h_chuid  373  h_freeAI  365  h_login  373  h_proxy  364  h9p  368  authdestroy  369  authentication  360  374   agent  362   domain  363   domains  362   file  361  368   file descriptor  170   handling  368   information  365   mount  170   protocol  361   server  374   servers  361  AuthInfo  373  Authinfo  365  authorization  358  authorized access  357  hread  368  authsrv  362  374  authwrite  369  automatic   layout  318   partitioning  324  aux listen  150  aux vga  299  average process  219  Await  46  await  96  AWK  214  AWK command  next  220  awk flag  F  220  AWK    au  au  au  au  au             EE Gr  Ch  Er et OF     au    EE    Ct             pattern  215  program  220  statement  214 
390. ion of afile  without placing on us the burden of creat   ing it  It does not check errors  because it is just an example       66      create c     include  lt u h gt      include  lt libc h gt     void  main int   char          int fd  n        char msg      a new file n      fd   create  afile   OWRITE  0664    write fd  msg  strlen msg      close  fd      exits  nil              To test it  we remove our previous version for afile  run this program  and ask 1s and cat to  print information about the file and its contents       rm afile     ls afile   ls  afile      afile    file does not exist     8 create     is  l afile       rw r  r   M 19 nemo nemo 11 Jul 9 18 39 afile    cat afile   a new file    In fact  there was no need to remove afile before running the program  If the file being created  exists  create truncates it  If it does not exist  the file is created  In either case  we obtain a new  file descriptor for the file        Directories can be created by doing a bit or of the integer constant DMDIR with the rest of  the permissions given to create  This sets a bit  called DMDIR  in the integer used to specify  permissions  and the system creates a directory instead of a file        fd   create  adir   OREAD  DMDIR 0775      You cannot write into directories  That would be dangerous  Instead  when you create and  remove files within the directory  Plan 9 updates the contents of the directory file for you  If you  modify the previous program to try to create a di
391. ion protocol  it does not matter if it is the one actually speaking  or just a rely for a fac   totum     The connection kept between a process and its factotum during an authentication session is  provided by the  mnt factotum rpc file  This file provides a distinct channel each time it is  open  It is named rpc because the process performs RPCs to the factotum by writing requests  through this file  and reading replies from factotum   to ask what it should do and rely messages     The auth 2  library provides authentication tools that work along with factotum  Among  other things  it includes a function called auth_proxy that takes care of authentication by rely   ing messages between the factotum reached through  mnt factotum ct1 and the other end  of a connection  It returns a data structure with some authentication information       sig auth_proxy  AuthInfo  auth_proxy  int fd  AuthGetkey  getkey  char  fmt     To show how to use this function  the following program mounts a file server and performs any  authentication necessary to gain access to the server   s file tree  The auth library provides  amount to do this  Instead of using it  the program implements its own version for this function     amount c      365       include  lt u h gt    include  lt libc h gt      include  lt auth h gt        Implementation for authmount here       void    main int argc  char argv                 AuthInfo ai   int fd   if  arge    4    fprint 2   usage   s file mnt aname n   argv 0 
392. ir   tual console for this window has both cooked and raw modes  In shell windows  that operate in  cooked mode  the window cooks the characters before giving lines to programs reading them   When acme is run in a window  it puts its  virtual  console device in raw mode  to do the editing  by itself     12 2  Characters and runes    But that was not all about the console  The console  line most other devices using text  and like  all Plan 9 programs using text  does not use characters  This may be a surprise  but think about     characters    like      amp   and X  For languages like english or spanish  all text is made up with char   acters  that might be letters  numbers  and other symbols  Spanish has also accented letters like     and     And this is just the start of the problem  Other languages use symbols to represent con   cepts  or what would be words or lexemes  for a spanish person  When computers were used for  english text  the standard ASCII for codifying characters as bytes was enough  Today  it is not   There are many symbols and one byte is not enough     Plan 9 uses Unicode  which is a standard for representing symbols used for text writing   Indeed  Plan 9 was the first system to use Unicode  The writing symbols used to write text are      293      not called characters  but runes  Each rune is represented in Plan 9 as a 16 bit  two bytes  num   ber  Most programs processing text are expected to use runes to do their job  The data type Rune  is defined in l
393. ironment variable  Thus  most things said for  environment variables apply for functions as well  e g   think about rfork e        cat  env     fn lr     fn lr  du  a  l sed    s        sed  s   1s  m       rc     g    The builtin function whatis is more appropriate to find out what a name is for rc  It prints the  value associated to the name in a form that can be used as a command  For example  here is of  whatis says about several names  known to us       whatis ir   fn lr  du  a  1 sed    s          sed  s   1ls  m        rc     whatis cd   builtin cd     whatis echo path    bin echo   path     bin     f    This is more convenient than looking through  bin   env  and the rc 1  manual page to see  what a name is  Let   s try our new function     j LE pin    nemo  bin 386 minimad   none  bin 386 minisync   nemo  bin 386 r2bib   nemo  bin 386 rc2bin    and many other lines of output       To obtain our list of users  we may remove everything but the user name       Ir bin   sed    s    a z0 9       1       sed 3q  nemo  none  nemo    r    And now  to get a list of users  we must drop duplicates  The program uniq knows how to do it   it reads lines and prints them  lines showing up more than once in the input are printed once  This  program needs an input with sorted lines  Therefore  we do what we just did  and sort the lines  and remove duplicate ones       208        Ir bin   sed    s     a z0 9       1       sort   unig  esoriano   nemo   none          Note that we remove
394. it must be done in two steps      cat  lt processlist  gt  tmp temp    cp  tmp temp processlist    rm  tmp temp      106      5 2  Conventions    Why does standard error exist  Now you can know  Consider what happens when we redirect the  output for a program and it has a problem       Ic  usr nemos  gt  tmp list  ls   usr nemos       usr nemos    file does not exist    cat  tmp list    Clearly  the diagnostic printed by 1c is not the output data we expect  If the program had write  this message to its standard output  the diagnostic message would be lost between the data  Two  bad things would happen  We would be unaware of the failure of the command  and the command  output would be mixed with weird diagnostic messages that might be a problem if another pro   gram has to process such output     In the beginning  God created the Heaven and the Earth          and God said  Let there be  Light  and there was Light  Yes  you are still reading the same operating systems book  This cite  seemed appropriate because of the question  How did my process get its standard input  output   and error  and  How can it be that the three of them go to  dev cons     The answer is simple  Child processes inherit a copy of the parent   s file descriptors  In the  beginning  Plan 9 created the first process that executes in the system  This process had no file  descriptor open  initially  At that point  this code was executed     open    dev cons   OREAD   open    dev cons   OWRITE  open    dev 
395. itch  rfork  RFPROC RFNOTI       EG RENOWAIT         case  1   sysfatal  rfork  Sr     case 0   if  httpinit    lt  0   rendezvous   amp main   void   1    else  rendezvous   amp main   void  0    httpservice       do the job     exits nil        248      default   childsts    int  rendezvous  amp main   void  0    if  childsts    0   exits  nil    else    forint  2   httpinit failed n     exits  httpinit failed            Note that each process calls rendezvous once  The parent calls it to rendezvous with the child   after it has initialized  The child calls it to rendezvous with the parent  and report its initialization  status  As the tag  we used the address for main  It does not really matter which tag we use  as  long as it is the same address  Using  amp main seemed like a good idea to make it explicit that we  are doing a rendezvous just for this function  As values  the child gave    1  as a pointer  sic  to  report failure  or O  as a pointer  to report success  As we said  rendezvous works although  these processes are not sharing memory   To test this program  we used an utterly complex implementation for HTTP  void  httpservice  void      sleep  50000         That is the best we could do given the so many standards that are in use today for the Web  Also   we tried the program with two implementations for httpinit  one returning O and another  returning    1  like this one   int  httpinit  void      sleep  2000    return 0          And this is an example executio
396. its nil           In the same way  the reader process is also simplified  It calls wmsg and forgets about concur   rency as well    void   reader  void          char buf  512    int nr   for       nr   read 0  buf  sizeof  buf  1    if  nr  lt   0   break   buf nr    0     wmsg  amp msg  buf       exiting   1   exits nil           The rest of the program stays the same  However  this initialization is now necessary  because the  Rendez needs a pointer to the lock     msg newmsg l    amp msg lck     If you try this program  you will notice a difference regarding its responsiveness  There are no  polls now  and no delays  As soon as a new message is updated  the panels are updated as well   Because of the interface we provided  the write for the panels is kept outside of the critical region   And because of dealing with concurrency inside the resource operations  callers may be kept  unaware of it  Been this said  note that the program still must care about how to start and termi   nate in a clean way     It is very usual to handle concurrency in this way  by implementing operations that lock the  resource before the do anything else  and release the lock before returning  A module imple   mented following this behavior is called a monitor  This name was used by some programming  languages that provided syntax for this construct  without requiring you to manually lock and  unlock the resource on each operation  The abstractions used to wait for conditions inside a mon   itor  s
397. k port  144   pipe  114   process  83 84  153  275   window  313  critical region  233  235  cron  372  cross compiler  21  csquery  139  ctl  51   file  300   file  connection  142   file  network  136    file  process  51  current   directory  13  29  58   directory  change  14   directory  print  14   window  317    D     d device driver  171  d2h rc script  184  data  15  meaning of  18  processing  219  processing  179  segment  34  51  types  abstract  2  user  342  data file  300  network  136     datal  225  database  network  139  datagram  136  date  8 10  101  dd  76  deadlock  115  257  death  process  35  debug protection  363  debugger  48  267  debugging  40  43  47 48  179  354  file server  336  remote  175  thread  267  declaration  C  186  decref  340  definition  function  207  Del  8  Delete  6  119  155  290  314  delete text  195  deleting partitions  323  deletion  file  66  delimiter  field  220  delimiters  message  110  137  delivering  message  128  demand paging  34  dependencies  file  349  DES  375  description  disk  321  descriptor  authentication file  170  board  file  123  duplicate file  104  file  56  58  88  102  group  file  154  image  307    post  file  123  160   process group  file  153   redirection  file  101   table  file  56  153  descriptor  Biobuf file  80  destroyfid  342  369   dev  174  289   dev cons  57  106  289  314   dev consctl  314   dev cursor  314   dev draw  174  300   dev drivers  166   dev hostdomain  362   dev 
398. ke other backup tools  is preserving the integrity of your data  of your files   This is also part of  the security provided by the computing system  In any case  it is usual to understand security in a  computer as the feature that prevents both    1 unauthorized use of the system  e g   running programs   and  2 unauthorized access to data in the system  e g   reading or modifying files      We will focus on security understood in this way  that is  as something to determine who can do  which operations to which objects in the system  But keep in mind that security is a much more  wide subject     We have already seen several abstractions that have to do with security  understood this  way  First  the persons who can perform actions on things in the computer system are represented  by users  A user is represented in the system by a user name  as you saw  Users rely on net   worked machines or systems to do things in the computing system  Machines execute programs   Indeed  the only way for a user to do something on a machine is to execute a program  or to use  one already running   Protecting the system to permit using it only to authorized users means just  protecting machines so that only authorized users may convince already running processes to do  things for them  Things like  for example  running new programs and reading and writing files     In Plan 9  some of the machines are terminals for the users  Other machines are CPU servers  that accept connections from other
399. known tools to  answer this question  The argument  4r for sort asks for a sort of lines but starting in the field  4 as the sort key  This is a lexical sort  but it suffices  The r means reverse sort  to get biggest  processes first  And we can use sed to print just the first line and only the memory usage     ips sorta FAE                nemo 3899 0 01 0 00 11844K Pread gs  nemo 18 0 00 0 00 9412K Sleep fossil    and more fossils   nemo 33 0 00 0 00 1536K Sleep bns  nemo 39 0 09 0333 1276K Rendez rio  nemo 278 0 00 0 00 1276K Rendez rio  nemo 279 0 02 0 14 1276K Pread rio    and many others      ps   sort  4r   sed iq   nemo 3899 0 01 0 00 11844K Pread gs    ps   sort  4r   sed  e    s      0 9 4 K    1      e Ig    11844K    We exploited that the memory usage field terminates in an upper case K  and is preceded by a  white space  This is not perfect  but it works  We can improve this by using AWK  This is more  simple and works better       ps   sort  4r   sed iq   awk  print  5      11844K    The sed can be removed if we ask AWK to exit after printing the 5th field for the first record   because that is the biggest one       ps   sort  4r   awk     print  5  exit      11844K    And we could get rid of sort as well  We can define a variable in the AWK program to keep  track of the maximum memory usage  and output that value after all the records have been pro   cessed  But we need to learn more about AWK to achieve this     To compute the maximum of a set of numbers  assum
400. l meaning  To use it just as a character  it must  be quoted  We already knew  but just as a reminder      echo     gt      gt  file     cat file    gt     Another example  If our machine seems to be heavily loaded  we may want to conserve the list of  running processes  to inspect it later  That is simple     ps  gt  processlist    Now that we have the list of processes stored in a file  we can take our time to inspect what is  happening to the machine  For example  we may use cat to print the list  It reads the file and  prints all the bytes read to the standard output       cat processlist    nemo 1 0 00 0 00 2308K Await bns   nemo 2 5 03 0 00 OK Wakeme genrandom  nemo 3 0 00 0 00 OK Wakeme alarm  nemo 4 0 00 0 00 OK Wakeme rxmitproc        Other lines omitted        We can count how many processes there were in the system by the time we stored the list  To do  so  we can count the lines in the file processlist  because we know there is one line in that      102      file per process  The program wc  word count  counts lines  words  and characters in a file  and  prints what it finds       we processlist  147 1029 8795 processlist    r    The file processlist has 147 lines  1929 words  and 8795 characters in it  This means that we  had 147 processes in the machine at that time  Because we are only interested in the number of  lines  we might have used the option  1 to wc  as said in wc 1   to ask just for the number of  lines       wc  1 processlist  147 processlist    r  
401. l variables  the binary header reports their total size  The system  allocates that amount of memory for the program  That is all it has to do  As a courtesy   Plan 9 guarantees that such memory is initialized with all bytes being zero  This means that  all your global variables are initialized to null values by default  That is a good thing   because most programs will misbehave if variables are not properly initialized  and null val   ues for variables seem to be a nice initial value by default     We saw how the program nm prints addresses for symbols  Those addresses are memory  addresses that are only meaningful when the program has been loaded  In fact  the Plan 9 manual  refers to the linker as the loader  The addresses are virtual memory addresses  because the sys   tem uses the virtual memory hardware to keep each process in its own virtual address space   Although virtual  the addresses are absolute  and not relative  offsets  to some particular origin   Using nm we can learn more about how the memory of a loaded program looks like  Option  n    eS eo    asks nm to sort the output by symbol address       nm  n 8 global          1020 T main   1033 T _main   1073 T atexit   10e2 T atexitdont   1124 T exits   1180 T _exits   1188 T getpid   11fb T memset   122a T lock   12e7 T canlock   130a T unlock   1315 T atol   1442 T atoi   1455 T sleep   145d T open   1465 T close   146d T read   14a0 T _tas   14ac T pread   14b4 T etext   2000 D argv0   2004 D _tos   2008 D _np
402. ld only break into the terminal running that kernel   and not into other machines     This does not happen on other systems  For example  UNIX was made when a computing  system was just a single machine  Networks came later and it was considered very unlikely that a  user could own a machine  attach it to the network  and run a fake kernel just to break into the  system  The result is that most UNIX machines tend to trust the users responsible for the kernels  at different machines within the same organization  Needless to say that this is a severe security  problem     14 3  Distributed security and authentication    We have seen that a terminal is secured just by not sharing it  It trusts whoever boots it  This  allows you to run processes in your terminal and use its devices  However  the terminal needs  files to do anything  For example  unless you have a binary file you cannot execute a new      360      program  There are some programs compiled into the kernel  kept at  boot  just to get in touch  with the file server machine  but that does not suffice to let the user do any useful work     Files are provided by file server programs  like the ones we have seen before  Each file  server is responsible for securing its own files  Therefore  there is no such thing as an account in  Plan 9  Strictly speaking  each file server has a list of user  and group  names known to it  and is  responsible for deciding if a user at the other end of a 9P connection is allowed to do some
403. ld store bytes sequentially  one write at a time  each one right  after the previous one  And the same happens while reading       60      The offset for a file descriptor can be changed using the seek system call  Its second  parameter can be 0  1  or 2 to let you change the offset to an absolute position  to a relative one  counting from the old value  and to a relative one counting from the size of the file  For example   this sets the offset in fd to be 10     seek fd  10  0      This advances the offset 5 bytes ahead   seek fd  5  1      And this moves the offset to the end of the file        seek fd  0  2      We did not use the return value from seek  but it is useful to know that it returns the new offset  for the file descriptor     3 2  Write games    This program is a variant of the first one in this chapter  but writes the salutation to a regular file   and not to the console    fhello c    include  lt u h gt                    include  lt libc h gt     void   main int   char           char msg      hello n    int fd     fd   open  afile   OWRIT                  write  fd  msg  strlen msg     close  fd    exits  nil                 We can create a file to play with by copying  NOTICE to afile  and then run this program to  see what happens          cp  NOTICE afile    8 fhello    This is what was at  NOTICE                cat  NOTICE  Copyright    2002 Lucent Technologies Inc   All Rights Reserved    r    and this is what is in afile      61       cat afile   hell
404. lds your  user name   sysname your machine name  and Shome your home directory  It also defined  another variable   cput ype  which holds the name for the architecture it was compiled for  That  is  for the architecture you are using now  Therefore     bind  Scputype bin  bin  bind  a  rc bin  bin    binds  386 bin into  bin  ona PC  All the binaries compiled for a 386 are now available at  their conventional place   bin  Besides  portable Rc scripts found at  rc bin  which can be  interpreted by rc at any architecture  are added to  bin  after the binaries just bound  You have  now acomplete  bin  all set for using  It that was not enough  the lines    bind  bc  usr Suser bin Scputype  bin  bind  bc  usr Suser bin re  bin    add your own binaries and Rc scripts  that are stored at bin 386  in this case  and bin rc in  your home directory     If you want to add  or remove  more binaries at  bin  you can just use bind  to customize     bin as you please  There is no need for a longer  path  because  bin may have just what  you want  And you always know where your binaries are  i e   just look at  bin     Another detail that you see is that the directory  tmp is indeed  usr Suser tmp  You  have your own directory for temporary files  although all programs create them at  tmp  by con   vention  Even if the file system is being shared by multiple users  each user has its own  tmp  to  avoid disturbing others  and being disturbed    We are going to continue showing how to use the 
405. le  C source code     file   gif  amp  amp  echo  file  GIF image     file   jpg  amp  amp  echo  file  JPEG image       Here  on each line  echo is executed only if the previous command  i e      succeeds     The other conditional is      It represents an OR operation  and executes the command on  the right only if the one on the left fails  It succeeds if any of the commands do  As an example   this checks for an unknown file type in our simple script        file    ch    gif   jpg    echo  file  who knows    The next command is equivalent to the previous one  but it would execute   three times and not  just once       192         file    ch        file   gif       file   jpg    echo  file  who knows    As you can see  the command is harder to read besides being more complex  But it works just fine  as an example     Many times you would want to execute a particular command when something happens  For  example  to send you an email when a print job completes  to alert you when a new message is  posted to a web discussion group  etc  We can develop a tiny tool for the task  Let   s call it when   Our new tool can loop forever and check the condition of interest from time to time  When the  condition happens  it can take an appropriate action     To loop forever  we can use the while construct  It executes the command used as the con   dition for the loop  If the command succeeds  the while continues looping  Let   s try it       while sleep 1    7  echo one more loop  one mo
406. le  including the size in  bytes       ils  l 8 take      rwxr xr x M 19 nemo nemo 36348 Jul 6 22 49 8 take    strip 8 take    ls  1 8 take      rwxr xr x M 19 nemo nemo 21713 Jul 6 22 49 8 take    The number after the user name and before the date is the file size in bytes  The binary file size  changed from 36348 bytes down to 21713 bytes  The difference in size is due to the symbol table   And without the symbol table  nm knows nothing  Just like the system       nm 8 take  Well  of course the system has a convention regarding which one is the address where to start  executing the program  But nevertheless  it does not care much about which code is in there     A program stored in a file is different from the same program stored in memory while it  runs  They are related  but they are not the same  Consider this program  It does nothing  but has  a global variable of one megabyte     239 5    global c     include  lt u h gt      include  lt libc h gt   char global 1l   1024   1024      void  main int  char          exits  nil           Assuming it is kept at global  c  we can compile it and use the linker option    o to specify that  the binary is to be generated in the new file 8 global  It is a good practice to name the binary  file for a program after the program name  specially when multiple programs may be compiled in  the same directory       8c  FVw global c    81  o 8 global global 8      ds  1 8 global global 8      rwxr xr x M 19 nemo nemo 3380 Jul 6 23 06 8 glob
407. lib  tmp           Figure 1 4  Acme  used to edit  browse system files  and run commands     As you can see  acme displays a set of windows using two columns initially  Acme is  indeed a window system  Each window in acme shows a file  a folder  or the output of com   mands  In the figure  there is a single window showing the directory  remember  this is the name  we use for folders   usr nemo  For Nemo  that is the home directory  As you can see  the hor   izontal text line above each window is called the tag line for the window  In the figure  the tag  line for the window showing  usr nemo contains the following text      usr nemo Del Snarf Get   Look    Each tag line contains on the left the name of the file or directory shown  Some other words fol   low  which represent commands  buttons    For example  our tag line shows the commands Del   Snarf  Get  and Look     Within acme  the mouse left mouse button  button 1  can be used to select a portion of text   or to change the insertion point  the tiny vertical bars  where text is to be inserted  All the text  shown can be edited  If we click before Look with the left button  do not move the mouse  and  type Could  the tag line would now contain         usr nemo Del Snarf Get   Could Look    The button 1 can be also used to drag a window and move it somewhere else  to adjust its posi   tion  This is done by dragging the tiny square shown near the left of the tag line for the window   Resizing a window is done in the same way
408. little  program  this would be the command used to generate its binary       81  o 8 amp  take take 8    For the first few programs  we will explicitly say how we compiled them  Later  we start assum   ing that you remember that the binary for a file named t ake  c was compiled and linked using      8c  FVw take c    81  o 8 amp  take take 8    and the resulting executable is at 8  take     There is an excellent paper for learning how to use the Plan 9 C compiler  4   It is a good  thing to read if you want to learn more details not described here about how to use the compiler     1 11  The Operating System and your programs    So far so good  But  what is the actual relation between the system and your programs  How can  you understand what happens  You will see that things are more simple than you did image  But  lets revisit what happens to your program after your write it  before introducing the operating  system in the play  We can use some commands to do this  By now  ignore what you cannot  understand       Is  1 take c take 8 8 take       rwxr xr x M 19 nemo nemo 36280 Jul 2 18 46 8 take      rw r  r   M 19 nemo nemo 388 Jul 2 18 46 take 8      rw r  r   M 19 nemo nemo 110 Jul 2 18 46 take c    The command 1s tells us that take c has 110 bytes in it  That is the text of our program  After  8c compiled it  the resulting object file take 8 has just 388 bytes in it  The contents are  machine instructions for our program plus initial values for our variables  e g   the st
409. ll be blocked awaiting  forever  for the message to arrive     To recover from this circumstance  it is usual to employ a timeout  A timeout is an alarm  timer used to be sure that there is a limit in the amount of time that we wait for some operation to  complete  In this case  it seems reasonable to use a timeout of 30 seconds  That is an incredibly  long time for a computer  even when considering the delays involved in crossing the network to  send or receive a message     Plan 9 provides an alarm timer for each process  The timer is started by calling alarm  giv   ing as a parameter the number of milliseconds that must pass before the timer expires       sig alarm  long alarm unsigned long millisecs        There is no guarantee that the timer will last for exactly that time  It might take a little bit more if  the system is busy doing any other thing  However  real soon after the specified number of mil   liseconds  an alarm note will be posted for the process that did call alarm  And you know  what happens  when the note is posted  any system call that kept the process awaiting  e g    read  will be interrupted  The following program reads a line from the terminal  and prints it to  the standard output  However  it will wait at most 30 seconds for a line to be typed       122      alarm c     include  lt u h gt      include  lt libc h gt     int  handler  void   char  msg      if   strcmp  msg   alarm        fprint  2   timed out n     return 1        return 0     void  
410. ll chancreate      sig chancreate  Channel  chancreate int elsize  int nel           and specify with the first argument the size for the data type being sent through it  The second  parameter specifies how many messages may be buffered inside the channel  i e   the buffer size  for the channel   To send and receive messages  the functions send and recv provide the pri   mary interface      sig send recv    int send Channel  c  void  v   int recv Channel  c  void  v     Before any further discussion  let   s see an example  In the previous chapter we implemented a  program for the bounded buffer problem  This is another solution to the same problem  using  threads and channels     tpe c          include  lt u h gt   include  lt libc h gt                 include  lt thread h gt    enum  Nmsgs   4     Channel  bufc    void   producer  void  arg        char  id   arg   char  msg     int iy     for  i   0  i  lt  5  i t     msg   smprint   Ss d   id  i    send bufc   amp msg         send bufc  nil      threadexits  nil        270      void  consumer  void       char  msg   do    recv bufc   amp msg    if  msg    nil       consume it  print   Ss    msg    free  msg         while msg    nil    threadexits  nil           void   threadmain int  char          bufc   chancreate sizeof char    Nmsgs    threadcreate  producer   a   8 1024    threadcreate  producer   b   8 1024    threadcreate  consumer  nil  8 1024    consumer  nil           The channel is created to send messages with t
411. ll will not be able to do its  work  For example  this will happen if we try to change our current working directory and supply  a path that does not exist     Almost any function that we call  and system calls are functions  may have problems to  complete its job  In Plan 9  when a system call encounters an error or is not able to do its work   the function returns a value that alerts us of the error condition  Depending on the function  the  return value indicating the error may be one or another  In general  absurd return values are used  to report errors     For example  we will see how the system call open returns a positive small integer  How   ever  upon failure  it returns  1  This is the convention for most system calls returning integer val   ues  System calls that return strings will return a null string when they fail  and so on  The manual  pages report what a system call does when it fails     You must always check out for error conditions  If you do not check that a system call  could do its work  you do not know if it worked  Be warned  not checking for errors is like driv   ing blind  and it will surely put you into a debugging Inferno  limbo didn   t seem bad enough    An excellent book  that anyone programming should read  which teaches practical issues regard   ing how to program is  5      Besides reporting the error with an absurd return value from the system call  Plan 9 keeps a  string describing the error  This error string is invaluable information f
412. lly forgotten while debugging a problem  If some program  input value should be a command line argument  use a command line argument  If somehow you  need an environment variable to avoid passing an argument all the times a program is called  per   haps the command arguments should be changed  Sensible default values for program arguments  can avoid the burden of having to supply always the same arguments  Command line arguments  make the program invocation explicit  more clear at first sight  and therefore  simpler to grasp and  debug  On the other hand  environment variables are used by programs without the user noticing     Because of the syntax in the shell for environment variables  we may have a problem if we  want to run echo  or any other program  supplying arguments containing either the dollar sign  or  the equal sign  Both characters we know are special  This can be done by asking the shell not to  do anything with a string we type  and to take it literally  Just type the string into single quotes  and the shell will not change anything between them       echo Suser   nemo     echo    Suser    is  user  Suser is nemo    r    Note also that the shell behaves always the same way regarding command line text  For example   the first word  which is the command name  is not special  and we can do this     44       cmd pwd    Scmd   usr nemo    r    and use variables wherever we want in command lines  Also  quoting works always the same  way  Let   s try with the echo pro
413. lthough not provided by the underlying Plan 9  is so common that you really must know how it  works  The idea is that your program creates a Bio buffer for reading or writing  called a  Biobuf  You program reads from the Biobuf  by calling a library function  and the library  will call read only to refill the buffer each time you exhaust its contents  This is our  in famous  program  but this time we use Bio              biocp c     include  lt u h gt    include  lt libc h gt    include  lt bio h gt   static void   usage  void           78     fprint  2   usage   s   b bufsz  infile outfile n   argv0    exits   usage        void  main int argc  char  argv        char  buf   long nr  bufsz   8 1024     Biobuf  bin   Biobuf  bout                    ARGBEGIN    Case    b s  bufsz   atoi EARGF  usage       break   default   usage       ARGEND   if  argc    2   usage     buf   malloc  bufsz    if  buf    nil   sysfatal  no more memory     bin   Bopen argv 0   OREAD    if  bin    nil   sysfatal   Ss   s  Sr   argv0  argv 0     bout   Bopen argv 1   OWRITE    if  bout    nil   sysfatal   Ss   s  Sr   argv0  argv 1     for       nr   Bread bin  buf  bufsz    if  nr  lt   0   break   Bwrite bout  buf  nr         Bterm  bin    Bterm  bout      exits  nil       79      The first change you notice is that to use Bio the header bio  h must be included  The data struc   ture representing the Bio buffer is a Biobuf  The program obtains two ones  one for reading the  input file and one for w
414. ly a set of lines with the source application   destination port  working directory  message type  message attributes  and number of bytes of  data  followed by the indicated number of bytes carrying the data  This is easy to see by using  cat to read from the edit port while executing the same plumb commands used above       132        cat  mnt plumb edit    plumb  edit     usr nemo 9intro    text  addr 2  7   NOTICI  plumb  edit       GI    New line supplied by us     usr nemo 9intro    text  addr   24     usr nemo 9intro edits c    plumb  edit     usr nemo 9intro    text    addr  main    24     usr nemo 9intro edits c    Delete         New line supplied by us    New line supplied by us    Sending a plumb message is very simple  given the helper routines in plumb 2   The routine       string     For example  this would send a message with the text  NOTICE       sig plumbsend plumbsendtext    int plumbsend int fd  Plumbmsg  m   int plumbsendtext  int fd        char  src     Ti  G             int fd   fd   plumbopen  send   OWRITE    if  fd  lt  0   sysfatal  open  Sr     if  plumbsendtext  fd  argvO  nil     sr       sysfatal  send     nal     char  dst     plumbsend sends a message as described by a Plumbmsg structure  The routine  plumbsendtext is aeven more simple version  for those cases when the message is just a text    char  wdir  char  data          NOTICI    E    E       lt  0     A similar effect can be achieved by initializing and sending a Plumbmsg as follows    
415. ly handled  by our device driver  we may disable hardware acceleration by using the interface at  v instead of  aux vga       echo hwaccel off  gt  dev vgact1    Also  writing blank to vgact1 will blank the screen  until we move the mouse  And      echo blanktime 30  gt  dev vgactl    will make the screen blank after 30 minutes of  mouse  inactivity     The size used by aux vga to set the mode for the graphics card is kept in the environment  variable vgasize  The type of monitor is kept in the environment variable monitor       echo Svgasize  1280x800x24     echo Smonitor  cinema    Both are the primary parameters used by aux vga to set the VGA mode  This happens during  the system startup  and you will probably not be concerned about this  but in any case   Svgasize is a useful bit of information to write scripts that depend on the screen resolution     In any case  reading vgact1 provides most of the configuration parameters for the graph   ics card that you might want to use       cat  dev vgactl   type vmware   size 1280x800x32 x8r8gq8b8   blank time 30 idle 0 state on   hwaccel on   hwbhlank off   panning off   addr p Oxfa000000 v Oxe0000000 size Oxa8c000    The interface provided by the kernel for using graphics is not that of vga  That is a particular con   trol interface for a particular kind of graphics card  Graphics are provided by the draw 3  device  driver  The draw device relies on the facilities provided by the graphics card attached to the sys   tem  and prov
416. m  dev null     Input output redirection must be done in the process that is going to execute the command   Otherwise  the shell would loose its own standard input or output  It must be done before doing  the exec for the new command  It would not make sense to do it after  because there would be  no I O redirection  and because when exec works  your program is gone     Consider this program  iredir c  include  lt u h gt     include  lt libc h gt                    void  main int  char         switch  fork       case  l   sysfatal   fork failed                case 0   close  0      WRONG   open    NOTICE   OREAD     execl    bin cat    cat   nil    sysfatal  exec  Sr     default     waitpid        exits  nil       and its output     8 iredir    Copyright    2002 Lucent Technologies Inc   All Rights Reserved    We supplied no argument to cat in the call to execl  Therefore  cat was reading from stan   dard input  However  because of the two previous calls  file descriptor 0 was open to read      104             NOTICE  The program cat reads from there  and writes a copy to its output        This is a real kludge  We do not know that open is going to return 0 as the newly open file  descriptor for  NOTICE  At the very least  the program should check that this is the case  and  abort its execution otherwise              fd   open   NOTICE   OREAD     assert  fd    0               At least  if fd is not zero  assert receives false  i e   0  as a parameter and prints the file and 
417. m  like in      221        adduser rmartinez Rodolfo Martinez    Because it is not clear how to do all this  we experiment using the shell before placing all the bits  and pieces into our l1ist2usr shell script     One way to invent a user name for each student is to pick the initial for the first name  and  add the last name  We can use sed for the job       name    Luis Ib    ez        echo  name   sed    s                   1 2     LIb    ez     name    Jos   Martinez        echo  name   sed    s                   1 2    JMartinez    But the user name looks funny  we should translate to lower case and  to avoid problems for this  user name when used in UNIX  translate accented characters to their ascii equivalents  Admit   tedly  this works only for spanish names  because other names might use different non ascii char   acters and we wouldn   t be helping our UNIX systems     ser een      echo LIb    ez   tr A Z a z    tr     a  idoun        faeioun      libanez    r    But the generated user name may be already taken by another user  If that is the case  we might  try to take the first name  and add the initial from the last name  If this user name is also already  taken  we might try a few other combinations  but we won   t do it here       name     Luis Ibanez       echo  name   sed    s                    1 2 7       ie tr A Z a z J tr    f a  ioun         faeioun      luisi    How do we now if a user name is taken  That depends on the system where the accounts are to 
418. m 8       r    The mkfile contains rules  that describe how to build one file provided you have other ones   For example  this was one rule     8 semfs  semfs 8 sem 8  8l  o 8 semfs semfs 8 sem 8       It says that we can build 8 semfs if we have both semfs 8 and sem 8  The way to build  8 semfs according to this rule is to execute the command       81  o 8 semfs semfs 8 sem 8    All the rules have this format  There is a target to build  followed by a   sign and a list of  dependencies  that is  things that our target depends on   The target and the list of dependencies  must be in the same line  If a line gets too long  the backslash character     can be used to con   tinue writing on the next line as if it was a single one  A rule says that provided that we have the  files listed in the dependencies list  the target can be built  It is also said that the target depends on      350      the files listed after the   sign  Following this line  sometimes called the header of the rule  a  rule contains one or more lines starting with a tabulator character  Such lines are executed as shell  commands to build the target  These lines are sometimes called the body for the rule     When we executed mk  it understood that we wanted to build the first target mentioned in  the mkfile  That was 8 semfs  So  mk checked out to see if it had semfs 8 and sem 8   the dependencies for 8 semfs   Neither file was there  What could mk do  Simple  The pro   gram searched the mk file to see if  fo
419. m it  The console is put in raw mode by assuming that if the file is named   a cons file  there will be another file named  a cons filect1 that accepts a rawon  command  So  giving  dev cons as an argument will mean that rawon is written to    tkeyboard      310      dev consctl  and the file is kept open      The function returns a pointer to a Keyboardct1 structure  similar to a Mousectl  It  contains a channel where the I O process sends runes  not characters   as they are received     typedef s         truct Keyboardctl Keyboardctl   struct Keyboardctl    Channel  c           Like we did for the mouse  to process the keyboard input  we will change threadmain to call  initkeyboard and to create a separate thread for processing keyboard input  This is the result   ing code for the program  omitting the various functions that we have seen  and a couple of other    ones that are shown later                                chan  Rune   20     slider c   include  lt u h gt   include  lt libc h gt   include  lt thread h gt   include  lt draw h gt   include  lt mouse h gt   include  lt keyboard h gt   Channel  sliderc   Image  setcol   Image  unsetcol   Keyboardct1  kctl   Mousect1  mctl         r       code for auxiliary functions  including thread entry points         311      void  threadmain int  char argv                           Mouse m   mctl   initmouse   dev mouse   nil    if  mctl    nil   sysfatal  initmouse   r     ketl   initkeyboard   dev cons      if  kctl    nil  
420. main int  char         char buf  1024      long nx     atnotify handler  1      print   type something       alarm 30   1000      30 secs   nr   read 0  buf  sizeof buf      alarm 0      if  nr  gt   0        write 1  buf  nr    exits  nil           Right before calling read  the program installs an alarm timer of 30 seconds  That much time  later  it will post the alarm note  If we type something and read completes before that time  the  program calls alarm  0  to cancel the timer  Otherwise  the timer expires and read is inter   rupted       8 alarm   type something  Hi there   Hi there     8 alarm   type something  timed out We did not type anything for 30secs    r    In general  timers are to be used with caution  They make programs unpredictable  For example   it could happen that right after we typed our line the timer expires  This could happen at any  time  not necessarily while we are waiting in read  but perhaps when we are in our way to can   cel the timer  At least  it is wise to give plenty of time for a timeout  to make things more pre   dictable  and it is even better not to use it unless it is absolutely necessary       123      5 8  The file descriptor bulletin board    Sometimes  processes need to talk through a pipe  but they do not have an appropriate ancestor  where to create the pipe  This happens when  after a process has been created  a newcomer wants  to talk to that process     The program that implements the file system  fossil  is a perfect example
421. med to come from a C  file with the same name  but different extension   The variable BIN names the directory where to  copy the resulting target to install it  and the variable TARG names the target to be built  Now we  can do much more than just compiling our program  there are several useful targets defined by  mkone                            mk   8c  FVw semfs c   8c  FVw sem c   8l  o 8 out semfs 8 sem 8     mk install   cp 8 out  usr nemo bin 386 8 semfs    mk clean          ES       rm  f    578qv   578qv  out y tab   y debug y output 8 semfs SCLEANFILI    As before  changing Sob jt ype changes the target we would be compiling for     It might seem confusing that install and clean were used as targets  They are not files   That point is that targets do not need to be files  A target may be a virtual thing  invented by you   just to ask mk to do something  For example  this might be the rule for install        install V  S O semfs  cp  O semfs SBIN    The rule is declared as a virtual target  using the  V  in the header for the rule  This means that  mk will consider install to be something that is not a file and is never up to date  Each time  we build the target install  mk would execute the body for the rule  That is how mkone could  define targets for doing other things        One final advice  This tool can be used to build anything  and not just binaries  For exam   ple  the following is an excerpt of the mk fi 1e used to build a PDF file for this book       354 
422. mo bin re  d2h   Only in  usr nemo bin re  h2d   Only in  tmp bin re  rcecho   diff  usr nemo bin rc t   tmp bin rce tt    La2 5    gt  if      S   0       gt  echo usage   0  gt  1 2    gt  exit usage    gt  3     r    The files d2h and h2d are only at Shome bin rc  we removed them from the copied tree  The  file rcecho is only at  tmp bin rc instead  We created it there  For diff  it would be the  same if it existed at Shome bin rc and we removed rcecho from there  Also  there is a file  that is different  t   as we could expect  Everything else remains the same     It is now trivial to answer questions like  which files have been added to our copy of the file  tree       diff  r  Shome  tmp   bin   grep     Only in  tmp bin     Only in  tmp bin rce  rcecho    f    This is useful for security purposes  From time to time we might check that a Plan 9 installation  does not have files altered by malicious programs or by user mistakes  If we process the output of  diff  comparing the original file tree with the one that exists now  we can generate the com   mands needed to restore the tree to its original state  Here we do this to our little file tree  Files  that are only in the new tree  must be deleted to get back to our original tree       diff  r  Shome  tmp   bin  gt  tmp diffs    grep     Only in  tmp      tmp diffs   sed  e    s Only in rm      e    s    rm  tmp bin rc rcecho    Files that are only in the old tree have probably been deleted in the new tree  assuming we 
423. modifying the file tree        lc  n tar    alanparsons pausini supertramp    lc  n tar alanparsons  irobot mp3 whatgoesup mp3      cp  n tar alanparsons irobot mp3  tmp    The program terminates itself when its file tree is finally unmounted       ps   grep tarfs   nemo 769 0 00 0 00 88K Pread tarfs    unmount  n tar     ps   grep tarfs    r    The shell along with the many commands that operate on files represent a useful toolbox to do  things  Even more so if you consider the various file servers that are included in the system     Imagine that you have an audio CD and want to store its songs  in MP3 format  at   n music album  The program cdfs provides a file tree to operate on CDROMs  After  inserting an audio CD in the CD reader  accessed through the file  dev sdD0  we can list its  contents at  mnt cd       cdfs  d  dev sdD0O     Ic  mnt cd   a000 a002 a004 a006 a008 a010  a001 a003 a005 a007 a009 ctl    Here  files a000 to a010 correspond to audio tracks in the CD  We can convert each file to MP3  using a tool like mp3enc       for  track in  mnt cd a          mp3enc Strack  n music album Strack mp3  i     all tracks being encoded in MP3         226      It happens that cdfs knows how to  re write CDs  This example  taken from the cdfs 4  manual  page  shows how to duplicate an audio CD     First  insert the source audio CD      cdfs  d  dev sdDO     mkdir  tmp songs     cp  mnt cd a   tmp songs    unmount  mnt cd   Now  insert a black CD      cdfs  d  dev sdDO     Ic
424. more  such processes will be awaken  upon  arrival of new tickets  in a fair way  An initial integer value may be given to a semaphore  to rep   resent the initial number of tickets in the box  This could be the interface for this abstraction     Sem  newsem int n      create a semaphore with n tickets  void wait  Sem  s      acquire a ticket  possibly waiting for it   void signal Sem  s      add a ticket to the semaphore     Mutual exclusion can be implemented using a semaphore with just one ticket  Because there is  only one ticket  only one process will be able to acquire it  This should be done before entering  the critical region  and the ticket must be put back into the semaphore after exiting from the criti   cal region  Such a semaphore is usually called a mutex  This is an example     Sem  mutex   newsem 1    wait  mutex      critical region here  signal  mutex      Also  because a wait on an empty semaphore puts a process to sleep  a semaphore with no tick   ets can be used to sleep processes  For example  this puts the process executing this code to sleep   until another process calls signal  w       Sem  w   newsem 0         wait  w      This tool can be used to synchronize two processes  to make one await until the other executes  certain code  Remember the HTTP server initialization example shown before  We could use an  empty semaphore  and make the parent call    wait  w   to await for the initialization of the child  Then  the child could call    signal  w   
425. ms i    emalloc9p sizeof  Sem        memset  sems i   0  sizeof Sem       sems i   gt ref   2   sems i   gt id   i   sems i   gt name   estrdup9p  name         return sems il           The function locates a free entry in sems  where to keep the new semaphore  When a semaphore  is no longed needed  and is released  we will deallocate it and set its entry to nil in the array  So   the function sweeps the array from the beginning  looking for the first available entry     All the semaphores will be kept in the array sems  indexed by their gids  This violates a lit   tle bit the convention that a qid number is never reused for a different file  A semaphore using an  array entry that was used before by an old semaphore  now removed  is going to have the same      340      qid used by the old one  This may cause problems if binds are done to semaphore files  and also if  any client caches semaphores  In our case  we prefer to ignore this problem  To fix it  the file  server can keep a global counter to assign qid numbers to semaphores  and increment the counter  each time a new semaphore is created  Nevertheless  the implementation shown here suffices for  our purposes     Instead of using malloc  we must use emalloc9p  The 9P library provides implementa   tions for emalloc9p  erealloc9p  and estrdup9p that mimic the ones with a similar  name in the C library  These implementations take an appropriate action when there is no more  memory  and guarantee that they will always return
426. n  wait for  94  chmod  19  64  69  flag  a  64  click  309  to type  8  client  144  325  connection  148  uid  367  clients  4  clip  302  clone  fid  342  clone file  136  close  connection  148  close  58  75  114  closed pipe  112  closedisplay  301  closekeyboard  311  closemouse  298  304  cmp  116  210  cnt c  236  code  generation  186  unicode  293  collection  garbage  340  color  307  combining commands  179  command  3  25  43  83  179  argument  9  11  background  97  103  builtin  158    compound  10  107  184  199  conditional  188  diagnostic  12  execution  remote  151  flag  9  interpreter  25  invocation syntax  39  line  5  25  42  97  101  116  191  194  option  9  substitution  116  187  typing a  10  command     190   amp  amp   191      191    188  acme pipe  115  cpu  151  file  190  for  186  if  188  listen  150  lstk acid  48  plumb  130  read  97  rfork  158  183  stk acid  48  time  194  window  172  commands  acme  7  combining  179  executing  6  commands  rio  6  comment  character  shell  21  ignore  220  Shell  99  communication  asynchronous  117  119  channel  269  multiway  277  process  109  269  synchronous  117  comparation  file  210  compare  file  116  operator  188  compilation  kernel  192  compiler  21  31  flags  21  regular expression  205  compose  290  compound command  10  107  184  199    compound sed command  196  compressed archive  199  computer   laptop  357   network  135  computing  distributed  151  174  concatenati
427. n always be  done for a process by writing none to  dev user  Also  we can rebuild the process name  space from scratch  for the new user name  using newns  provided by the auth library  This  function may be called to become none        void  becomenone  void      int Eds       fd   open   c user   OWRITE      if  fd  lt  0   sysfatal    c user  Sr     if  write fd   none   4   lt  0     sysfatal  can   t become none     close  fd    newns  none   nil           The second parameter to newns names a namespace file  which is  lib namespace by  default  After modifying our asemfs file server to call becomenone early in fstattach   we can see the effect       8 asemfs  s sem     ps   grep asemfs   nemo 1410 0 00 0 00 204K Pread 8 asemfs    mount  c  srv sem  mnt sem     ps   grep asemfs   none 1410 0 00 0 00 240K Pread 8 asemfs    The first command started 8  asemfs  asking it to post at  srv sem a file descriptor to mount  its file tree  As you can see  at this point the process is owned by the user who started the server   Le   nemo  The server may potentially access any resource this user could access  However   after mounting it  ps reports that the process is entitled to user none  It no longer can access  files using nemo as its identity  This limits the damage the server can do  due to any bug  Fur   thermore  reading  proc 1410 ns would report that this process now has a clean namespace   built from the scratch for the user none  Any resource obtained by nemo  by mountin
428. n be used for matching strings against the expres   sion  This program accepts a regular expression as a parameter  and then reads one line at a time   For each such line  it reports if the string read matches the regular expression or not     match c    include  lt u h gt     include  lt libc h gt                       include  lt regexp h gt     void  main int argc  char  argv         Reprog  prog    Resub sub 16      char buf  1024    int nr  ismatch  i   if  argc    2       fprint 2   usage   s regexp n   argv 0       exits   usage         205      prog   regcomp  argv 1     if  prog    nil   sysfatal  regexp      s     Sr   buf    for       nr   read 0  buf  sizeof  buf  1    if  nr  lt   0   break   buf nr    0   ismatch   regexec prog  buf  sub  nelem sub     if   ismatch     print   no match n     else    print   matched          write 1l  sub 0  sp  sub 0  ep   sub 0  sp    print   Iya        exits  nil           The call to regcomp compiles the regular expression into prog  Later  regexec executes the  compiled regular expression to determine if it matches the string just read in buf  The parameter  sub points to an array of structures that keeps information about the match  The whole string  matching starts at the character pointed to by sub 0   sp and terminates right before the one  pointed to by sub  0   ep  Other entries in the array report which substring matched the first  parenthesized expression in the regexp  sub  1   which one matched the second one  sub 
429. n entry in the partition name to declare it  includ   ing the information about where does it start and where does it end  The command fdisk can be  used to modify the partition table for the whole disk  The command prep can be used to modify  the one used by Plan 9  kept within the the Plan 9 partition in the disk      In any case  we can add a partition to our disk by writing a control command to the disk   s  ctl file  For example  this creates a partition named check on the sdC1 disk       echo part check 63 2001  gt  dev sdCl1 ctl    grep check  dev sdCl ctl  part check 63 2001    To remove it  we may write a delpart command to the disk   s control file       echo delpart check  gt  dev sdC1 ctl    In general  it is wiser to use the programs fdisk and prep to create partitions  because they  update the tables besides informing the storage device about the new partitions  We are going to  create some partition for a new disk  As you may see  we tell fdisk that the disk to use is   dev sdC1 data  That is just a file  For fdisk  that would be the disk       disk fdisk  dev sdCl data  cylinder   8225280 bytes   empty 0 522  522 cylinders  3 99 GB    gt  gt  gt     After running fdisk  it prints the list of partitions found  None so far  The  gt  gt  gt  is the prompt  from fdisk  where we can type commands to handle the disk  The command a  adds a new par   tition     gt  gt  gt  a pl    start cylinder  0  end  0  522  522    We added a partition called p1 occupying the enti
430. n for both versions of the program       8 rendez  httpinit failed      8 rendez After two seconds we got another prompt     ps   grep 8 rendez  nemo 7076 0 00 0 00 24K Sleep 8 rendez    10 5  Sleep and wakeup    Going back to our airport panels program  it is a resource waste to keep all those  panelprocs polling just to check if there is a new message  Another abstraction  provided by  the functions rsleep  rwakeup  and rwakeupall may be more appropriate  By the way  do  not confuse this with the function sleep 2  that puts the process to sleep for some time  It is  totally different     The idea is that a process that wants to use a resource  locks the resource  The resource is  protected by a lock  and all operations made to the resource must keep the lock held  That is not  new  In our program  processes updating or consulting msg must have msg locked during these  operations     Now suppose that  during an operation  like consulting the message   the process decides      249      that it cannot proceed  e g   because the message is not new  and we only want new messages    Instead of releasing the lock and trying again later  the process may call rsleep  This puts the  process to sleep unconditionally  The process goes to sleep because it requires some condition to  be true  and it finds out that the condition does not hold and calls rsleep     At a later time  another process may make the condition true  e g   the message is updated    This other process calls rwakeup 
431. n image   The  point pos is the pixel where drawing starts  Each character is a small rectangular image  The  image for the first character has its top left corner placed at pos  and other characters follow to  the right  The source image is not the image for the characters  The source image is the one for  the black color in this example  Character images are used as masks  so that black pixels are  drawn where each character shape determines that there has to be a pixel drawn  To say it in  another way  the source image is the one providing the pixels for the drawing  e g   the color    Characters decide just which pixels to draw  The point given as ZP is used to translate the image  used as a source  like when calling draw  Here  drawing characters in a solid color  ZP works  just fine     But where are the images for the characters  Even if they are used as masks  there has to be  images for them  Which images to use is determined by the Font parameter     A font is just a series of pictures  or other graphical descriptions  for runes or characters   There are many fonts  and each one includes a lot of images for characters  Images for font runes  are kept in files under  1ib font  Many files there include images just for a certain contigu   ous range of runes  e g   letters  numbers  symbols  etc   Other files  conventionally with names  ending in   font  describe which ones of the former files are used by a font for certain ranges of  unicode values     The draw library
432. n other leads to the file that had the name  n whale  This file was the root of our file  server  and not the empty directory  To undo the mount for this directory  we know what to do       unmount  n other   gt  Ic  n fother    r    In some cases  a single file server may provide more than one file tree  For example  the file sys   tem program used in Plan 9  fossil  makes a snapshot of the entire file tree each day  at 5am   and archives it for the posterity  It archives only the changes with respect to the last archive  but  provides the illusion that the whole tree was archived as it was that day     Above  we mounted the active file tree provided by the fossil file server running at  whale  But we can mount the archive instead  This can be done supplying an optional argument  for mount  that specifies the name of the file tree that you want to mount  When you do not  name a particular file tree served from the file server  its main file tree is mounted  For fossil  the  name of the main file tree is main active  This command mounts the archive  also known as  the dump  for our main file server  and not the active file tree  i e   that of today        mount  srv tcp whale 9fs  n dump main archive    Ic  n dump   2001 2002 2003 2004 2005 2006    ls  n dump 2004   0101   0102   0103   0104       and may more directories  One per day  until      1230   1231    r    This is very useful  You may copy files you had years ago  you may compare them to those you  have today  and y
433. n we executed the first line     That is no longer true  Because there is another process that might change cnt while we are  doing something else  The net effect in this case is that we loose increments  The counter should      23       Parent          loc    ent  0                Child                loc   cnt  sleep       loc              loc  0 ent  0                               loc              loc  0 ent  0                loc   cnt  sleep                loct   cnt   loc  loc   cnt  sleep       loc              Loecs 1 ent  1                               loc              LOC  Al  ents  T                loct    cnt   loc  loc   cnt  sleep                loct    cent   loc  loc   cnt  sleep       loc              rocs 2 cnt  2                               loc     1             Loect  2 ents 2                loct    cnt   loc  loc   cnt  sleep                print    loc     2          print    Figure 10 1  One interleaving of statements for the two processes  last version of the program      end up with a value of 4  But it has the value 2 at the end  The same would had happen if the    interleaving had been like follows   Process 1  Consult the variable  Process 2  Consult the variable  Process 1  Increment   Process 2  Increment   Process 1  Update the variable    NO BP WN    Process 2  Update the variable    This interleaving also looses increments  This is because of the race condition resulting from  using the shared cnt in two different processes without taking a
434. nal informa   tion about the data  Thus  each message has a set of attributes and their values  besides the data   Some attributes are always present in a message  although their values might be empty   Other      130     attributes are used by programs using a particular kind of message  and there can be any number  of them  You may also invent any attribute that you need if you use plumber messages for a par   ticular thing  These are the standard attributes for a message     src A string that names the source for the message  usually a program name   dst A string that names the destination port for the message  If it is not supplied  the  plumber tries to choose using the rules file     wdir The working directory used by a process that is sending a message carrying a file  name  This is necessary to let the receipt of the message determine to which file the mes   sage refers to  Note that a file name may be a relative path  and you need to know with  respect which  current working  directory it is relative to     type A string describing the type of data  Most of the times the type is just text  which is  later  perhaps  interpreted as a file name or as the name for a manual page   ndata Number of bytes in the data for the message     How can you use the plumber  From the shell  the plumb program lets you send messages  as  you saw  From a C program  there is a library called plumb 2  that provides an interface for using  the plumber  The following program listens for plum
435. name space to do a variety of things  Nev   ertheless  if you want to read a nice introduction to using name spaces for doing things  refer to     7      7 11  Sand boxing    Being able to customize the name space for a particular process is a very powerful tool  For  example  the window system does a    rfork  RFNAMEG        to make a duplicate of the namespace it runs in  for each window  actually  for each shell that is  started for a new window   The shell script      window    creates a new Rio window  with a new shell on it  This shell is provided with its own copy of the  namespace  customized to use the console  mouse  and screen just for that window  These are the  commands     rfork ne  mount  srv rio nemo 39  mnt wsys  bind  b  mnt wsys  dev    Mounting the file server for the window system creates a new window  and binding its file tree at    dev replaces the files that represent the console  All the programs are unaware of this     Many other things can be done  To freeze the time in your system  just provide a file inter   face that never changes       173        cp  dev time  dev bintime  tmp     bind  tmp time  dev time    bind  tmp bintime  dev bintime    One interesting use of namespaces is in creating sandboxes for processes to run  A sandbox is a  container of some kind that isolates a process to prevent it from doing any damage  like when you  do a sand box in the beach to contain the water  This program creates a sandbox to run some  code inside  It uses
436. nates its time in the processor  Then  the system picks up a ready process to  become the next running one  States are just constants defined by the system to cope with the pro   cess abstraction     Many times  a process would be reading from a terminal  or from a network connection  or  any other device  When this happens  the process has to wait for input to come  The process could  wait by using a loop  but that would be a waste of the processor  The idea is that when one pro   cess starts waiting for input  or output  to happen  the system can switch to another process and  let it run  Input output devices are so slow compared with the processor that the machine can exe   cute a lot of code for other processes while one is waiting  The time the processor needs to exe   cute some instructions  compared to the time needed by I O devices to perform their job  is like  the time you need to move around in your house and the time you need to go to the moon     This idea is central to the concept of multiprogramming  which is the name given to the  technique that allows multiple programs to be loaded at the same time on a computer     To let one process wait out of the processor  without considering it as a candidate to be put  into the running state  the process is flagged as blocked  This is yet another process state  All the  processes listed above where blocked  For example  Pread and Await mean that the process is  blocked  i e   the former shows that the process is blocke
437. nd replies with Rattach  both Plan 9 and the server agree that the fid proposed will  now be a reference to the root of the file tree mounted  So  from now on  the fid 435 can be used  in other 9P requests to mean   within the file server     Ramfs       Mount table entry    Chan for Chan for Ri ee   n ram server   s fid 435          fid  435                               Plan 9    Figure 13 1  After an attach Plan 9 has a fid number that refers to the file server   s   file     The figure depicts the scenario after completing the mount system call that issued the  attach request  There is a new entry in the name space where we mounted the file server  The new  entry in the mount table says that whenever we reach the file  n ram  while resolving a file  name  we should continue at the root for the file server instead  As we saw time ago  a Chan is  the data structure used in Plan 9 to refer to a file in a particular server  The Chan identifies the file  server that contains the file  and also includes a fid number  The fid is used when speaking 9P  with the file server containing the file  to identify the file     Fids let the 9P client refer to a file in a request made to the server  But another kind of file  identifier is needed  Consider the mount table entry shown in the figure  It says     when you get to  a file that is  n  ram  you must continue at             How can Plan 9 know that it has reached the  file  n ram  To know if that happens  Plan 9 must check if the Ch
438. ndow      grep       mount     dev text   sed 1q   re    Each window provides a control interface  through its wct 1 file  Many of the operations that can  be performed by the user  using the mouse and the menus provided by rio  can be performed  through this file as well     Windows may be hidden  to put them apart without occupying screen space while they are  not necessary by the moment  The Hide command from button 3 menu in rio hides a window   While hidden  the window label is shown in that menu  and selecting it shows the window again   The next command line hides the window for 3 seconds using its control file       echo hide  gt  dev wctl   sleep 3   echo unhide  gt  dev wctl  hidden for 3 seconds    and back again     r    We typed the three commands in the same line because after      echo hide  gt  dev wct1    the window would no longer be visible to accept input  This remains of the input focus  The  window where you did click last is the one receiving keyboard input and mouse input  The place  where the window system sends input events is also known as the focus because you seem to be  focusing on that window  Manually  focus can be changed by using the mouse to click on a differ   ent window  From a program  the wct 1 file can be used       echo current  gt  dev wsys 3 ctl    Sets the focus to window 3  Itis also said that window 3 becomes the current window  hence the  control command name  By the way  most of the control operations done to a wct 1 file make i
439. ne pixel  because we ask allocimage to set the rep1 flag for  both images  This is done passing true as a value for its rep1 parameter  Remember that when  this flag is set  draw tiles the image as many times as needed to fill the area being drawn     Two arguments for allocimage remain to be described  but we will not provide much  detail about them  The argument chan is an integer value that indicates how the color will be  codified for the pixels  There are several possible ways to codify colors  but we use that employed  by the screen image  So  we used screen  gt chan as an argument  The last parameter is the  value that states which one is the code for the color  Given both chan and the number for the  color  allocimage can specify to the draw device which color is going to use the pixels in the  new image     In our program  we used the constant DYe11ow for the color of the set part  and the number  0x777777FE for the unset part  This number codifies the a color by giving values for red  blue   and green  We borrowed the constant by looking at the source code for rio  to use exactly its  background color     At last  this is drawslider   void  drawslider int val             Rectangle setrect  unsetrect  markrect   int dx     dx   Dx screen  gt r    val   100                 setrect   unsetrect   markrect   screen  gt r   setrect max x   setrect min x   dx   markrect min x   setrect max x   markrect max x   setrect max x   2   unsetrect min x   markrect max x   draw scr
440. new service to the system  Think about it  To  allow other processes to connect to our process  it needs a port for itself  This is like allocating a     mailbox    in the    building    to be able to receive mail  The function announce receives a net   work address and announces it as an existing place where others may send messages  For exam   ple     announce   tcp alboran echo   dir      would allocate the TCP port for the service named echo and the machine named alboran   This makes sense only when executed in that machine  because the port being created is an  abstraction for getting in touch with a local process  To say it in another way  the address given to  announce must be a local address  It is a better idea to use    announce   tcp   echo   dir      instead  The special machine name         refers to any local address for our machine  This call  reserves the port echo for any interface used by our machine  not just for the one named  alboran   Besides  this call to announce now works when used at any machine  no matter its  name     This function returns an open file descriptor to the ct1 file of the line directory used to  announce the port  The second parameter is updated with the path for the directory  Note that  this line directory is an artifact which  although has the same interface  is not a connection  It is  used just to maintain the reservation for the port and to prepare for receiving incoming calls   When the port obtained by a call to announce is no
441. ng able to edit the  text at any place in a Rio window does help  but it can be convenient to define a shell function  that encapsulates what we have done so far  A shell function is like a function in any other lan   guage  The difference is that a shell function receives arguments as any other command  in the  command line  Besides  a shell function has command lines in its body  which is not a surprise   Defining a function for what we have done so far can save some typing in the near future  Fur   thermore  the command we have just built  to list all the files within a given directory  is useful  by itself       207      ey TER Ie UY  7  du  a  1   sed    s            sed    s   1ls  m        re  iif    r    This defined a function  named 1r  that executes exactly the command line we developed  In the  function lr  we removed the sed 3q because it is not reasonable for a function listing all files  recursively to stop after listing three of them  If we want to play  we can always add a final sed  in a pipeline  Arguments given to the function are accessed like they would be in a shell script   The difference is that the function is executed by the shell where we call it  and not by a child  shell  By the way  it is preferable to create useful commands by creating ia shell  functions can  not be edited as scripts  and are not automatically shared among all shells like files are  Functions  are handy to make modular scripts     Rc stores the function definition using an env
442. ng it in the same command line  before the command  like in the following exam   ple       temp  tmp foobar echo Stemp   tmp foobar    echo Stemp    r    At this point  we can understand what  status means  It is the value of the environment vari   able status  This variable is updated by the shell once it finds out how it went to the last com   mand it executed  This is done before prompting for the next command  As you know  the value  of this variable would be the string given to exits by the process running the command     Another interesting variable is path  This variable is a list of paths where the shell should  look for executable files to run the user commands  When you type a command name that does  not start with   or     the shell looks for an executable file relative to each one of the directories  listed in  path  in the same order  If a binary file is found  that is the one executed to run the  command  This is the value of the path variable in a typical Plan 9 shell       echo  path   bin    r    It contains the working directory  and  bin  in that order  If you type 1s  the shell tries with    1s  and if there is no such file  it tries with  bin 1s  If you type ip ping  the shell tries  with   ip ping  and then with  bin ip ping  Simple  isn   t it     Two other useful environment variables are user  which contains the user name  and  sysname  which contains the machine name  You may define as many as you want  But be  careful  Environment variables are usua
443. ng one line at a time from the  console  and send each new message read through a channel to a bcast thread     void   consreadthread  void        Biobuf bin   char  Las    threadsetname   consread      Binit   amp bin  0  OREAD     while  ln   Brdstr  amp bin      n     0    sendp bcastc  1n    sendp bcastc  nil     Bterm  amp bin     threadexits  nil                 The code can now be almost as simple as the definition for the thread   s task  We have used  Brdstr from bio 2  to read a line at a time from standard input  Unline Brdline  this function  returns a C string allocated with malloc that contains the line read  The final argument 0 asks  Brdstr not to remove the trailing  n in the string  which is just what we need  To make things  terminate cleanly  upon EOF from standard input  we send a nil message as an indication to exit           Another thread  bcast  will be only concerned about broadcasting messages to pannels   When it receives a new message  it sends one copy of the message to each panel  To do this  the      275      program may use an array of channels  panelc  with one channel per panel   void  bceastthread  void         char  msg   int ie    threadsetname   bcast        do    msg   recvp bcastc    for  i   0  i  lt  Npanels  i     if  msg    nil     sendp  panelc i   strdup msg     else  sendp panelc i   nil    free  msg      while msg    nil    threadexits  nil           The nil message meaning exiting is also broadcasted  to indicate to all panels
444. ng others  we have these ones       sig runetochar chartorune  int runetochar char  s  Rune  r   int chartorune  Rune  r  char  s     Now we can read    characters    properly from the console  for the first time  The next program con   verts what it reads to uppercase       294         rune c     include  lt u h gt    include  lt libc h gt   void   main int  char             char buf 512    char out  UTFmax     Rune ry   int ny  irl  ord   char  Ss     for  7     nr   read 0  buf  sizeof  buf     if  nr  lt   0   break   s   buf   while  nr  gt  0     irl   chartorune  amp r  s      s    irl     nr   irl   r   toupperrune r    orl   runetochar out   amp Yr      write 1  out  orl         exits  nil           It processes one rune at a time  The function chartorune extracts a rune from the byte string  pointed to by s  and places it at  amp r  The number of bytes occupied by the rune in UTF  that is  in  the string at s   is the return value from the function  The function runetochar does the oppo   site conversion  and returns also the number of bytes used  It is guaranteed that a rune will not  occupy more than UTFmax bytes  3 bytes in Plan 9   Other convenience routines  like  toupperrune  replace the traditional ones for characters  Our program works perfectly with  runes that do not fit in ASCII       8 out  I feel     today   I FEEL    TODAY        E          An equivalent program  but unaware of unicode  would fail  Using this loop to do the conversion  instead of the R
445. ng the AuthInfo to the user  fact ot um used the cap device to ask the  kernel to allow any process holding the data in Authinfo cap to change its id to the user who  authenticated  It did so by writing a hash of the capability to  dev caphash  Later  our server  process may write to  dev capuse the capability in Authinfo  cap  and change its identity     The function auth_chuid  from the auth library  takes care of using the capability in  AuthInfo for changing the user id  Also  as an extra precaution  it builds a new name space  according to the name space file supplied  or  1ib namespace if none is given  The following  code might be used by a server program to authenticate a client and then changing its user id to  continue execution on the user   s name                 int fd     file descriptor to the client process  AuthInfo ai        ai   auth_proxy fd  getkey  keyspec    if  ai    nil   sysfatal   authentication failed     auth_chuid ai  nil    auth_freeAI  ai         This should be done by the process attending the client  In some cases  the process attending the  client is the initial process for the server  if the server is started by listen  That is because this  program spawns one server process for each client  In other cases  this has to be done after creat   ing a child process in the server program just to serve a connection to a client     One program that uses auth_chuid is auth login  It can be used to simulate a user  login at a terminal  The program pr
446. ng through  the file tree as shown above     Because Plan 9 is a distributed system  your kernel does not have any data structure to  implement files  This may be a surprise  because in Plan 9 everything is a file  or at least looks  like a file  But Plan 9 does not provide the files itself  Files are provided by other programs that  may be running far away in the network  at different machines  These programs are called file  servers     File servers implement and maintain file trees  and you may talk to them across the network  to walk their trees and use their files  But you cannot even touch nor see the files  they are kept  inside a file server program  far away  What you can do is to talk to the file server program to ask  it to do whatever you may want to do to the files it keeps  The protocol used to talk  i e   the lan   guage spoken  is called 9P  The section 5 of the system manual documents this protocol  Any  program speaking 9P can be used as a file server for Plan 9     The conversation between Plan 9 and a file server is made through a network connection  If      160      you have not attended to a computer networks course  you can imagine it is a phone call  with  Plan 9 at one end  and the file server at the other  In the last chapter we saw how to establish net   work connections  i e   how to make calls  This makes a network connection to the program we  use as our file server       srv tcp whale 9fs   POSTgaz     ls  1  srv tcp whale 9fs       rw rw rw  s 
447. nges   When wmsg changes the message  it will wake up all the processes waiting for the new message     This is rmsg  It locks the message  and goes to sleep waiting for the condition  need a new  message  to hold  After waking up  we still have the lock  Of course  any other process could use  the resource while we were sleeping  but this is not a problem because all we wanted was to wait  for a new message  and now we have it  Thus  the function makes a copy of the new message   releases the lock  and returns the new message to the caller     char     rmsg  Msg  m               char  new     glock   amp m  gt 1ck     rsleep   amp m  gt newmsg     new   strdup m  gt text    qunlock   amp m  gt 1ck     return new     And this is wmsg  It locks the resource  and updates the message  Before returning  it wakes up  anyone waiting for a new message     void    wmsg Msg  m  char  newtext               glock   amp m  gt 1ck     free  m  gt text     m  gt text   strdup  newtext    rwakeupall   amp m  gt newmsg     gunlock   amp m  gt 1ck       Now things are simple for our program  the panel process may just call rmsg to obtain a new  message  There is no need to bother with concurrency issues here  The function rmsg is our  interface for the message  and it cares about it all       251      void   panelproc int fd       ulong lastvers    1   char  text     while   exiting     text   rmsg  amp msg     write fd  text  strlen text     free  text       fprint 2   panel exiting n     ex
448. not  know how much screen space will the string need  To avoid making our window too bizarre   writeval does not draw anything when the window is not as tall as the height for the string   that is  when sz y  gt  Dy screen  gt r   Also  the string is not shown either when it needs  more than the half of the width available in the window     12 9  The window system    A window is an abstraction provided by the window system  rio in this case  It mimics the  behavior of a graphic terminal  including its own mouse and keyboard input  and both text and  graphics output    In other systems  the abstraction used for windows differs from the one used for the entire  console  Programs must be aware of the window system  and use its programming interface to  create  destroy  and operate windows     Instead  the model used in Plan 9 is that each application uses the console  understood as the  terminal devices used to talk to the user  including the draw device and the mouse  In this way   applications may be kept unaware of where are they actually running  the console or a window    Running the window system in a window is also a natural consequence of this     Nevertheless  it may be useful to know how to use the window system from a program   Like other services  the window system is also a file server  You already know that its primary  task is to multiplex the files for the underlying console and mouse to provide virtual ones  one per  window  Such files are the interface for usin
449. ns       229      10     Concurrent programming    10 1  Synchronization    In the discussion of rfork that we had time ago  we did not pay attention to what would happen  when a new process is created sharing the parent   s memory  A call like    rfork  RFPROC   RFMEM        is in effect creating a new flow of control within our program  This is not new  but what may be  new is the nasty effects that this might have if we are not careful enough     We warned you that  in general  when more than one process is sharing some data  there  may be race conditions  You could see how two processes updating the same file could lead to  very different contents in the file after both processes complete  depending on when did they their  updates with respect to each other  Sharing memory is not different     What happens is that the idea that you have of sequential execution for your program in an  isolated world is no longer true  We saw that when more than one process was trying to update  the same file  the resulting file contents might differ from one run to another  It all depends on  when did each process change the data  And this is what we called a race condition  Consider  this program     rincr c          include  lt u h gt                 include  lt libc h gt     int cnt     void  main int  char           int iy    if  rfork  RFPROC RFMEM RFNOWAIT   lt  0   sysfatal  fork  Sr      for  i   0  i  lt  2  itt   cntt          print   cnt is  d n   cnt    exits  nil           It 
450. nt parts of the program can be kept simple  and without race conditions  This  thread is the only one in charge of the value for the slider  Each other thread is also in charge of  other type of processing  using its own data  Communication between threads happens through  channels  which at the same time synchronizes them and allows them to exchange data     To draw the slider  we must draw three elements  A yellow rectangle for the part set  a grey  rectangle for the unset part  and a black thick line to further mark them apart  After defining rect   angles set  unset  and mark  for each element  we can draw the slider as follows     draw screen  setrect  setcol  nil  ZP    draw screen  unsetrect  unsetcol  nil  ZP    draw screen  markrect  display  gt black  nil  ZP         Provided that setcol is an image for the color of the set part  and unsetcol is an image for  the color of the unset part  An image for the black color was available  but we also needed two  other colors     The function allocimage can be used to allocate a new image  We are going to use it to  build two new images for the yellow and the grey colors used for the set and the unset parts  We  declare both images as globals  along with sliderc     Channel sliderc   Image  setcol   Image  unsetcol     and add these two lines to threadmain  right after the call to initdraw     setcol   allocimage  display  Rect 0 0 1 1   screen  gt chan  1  DYellow    unsetcol   allocimage  display  Rect 0 0 1 1   screen  gt
451. nts the file server at the  directory given in mtpt  using flag as flags for mount  So  postmountsrv provides all the  main loop logic for a file server  and makes it available to other processes  It is optional to give  name  and mtpt  Passing nil as either value makes postmountsrv not to post or not to  mount the file server respectively     One thing to note is that the process created by postmountsrv will not share its name  space with the parent process  the one calling postmountsrv   It could not be otherwise  If it  was  a process would have to reply to 9P requests for the file tree it is using  This would lead to  deadlocks  For example  opening a file would make the process wait for Plan 9 to speak 9P with  the server  that would wait until the server attends 9P requests  and the server would be waiting  for the open to complete  The flag RFNAMEG  RFFDG  and RFMEM are given to rfork by  postmountsrv  This means that the child process shares memory with the parent process  but  does not share the name space nor the file descriptors with the parent           Things work as shown in figure 13 3  The child process created by postmount srv exe   cutes the main server loop  This loop  implemented by the srv function from 1ib9p  keeps on  reading 9P messages from the pipe  When it reads a Tread message  it calls the function  Srv xread to process the request  The function is expected to perform the read and then reply to  the client  by sending perhaps an Rread back to the 
452. number of file descrip   tors for the same cases  That would let you know if a change you make leaks any file descriptor   by leaving it open   The same could be done by looking into memory usage and alerting about  huge increases of memory     There are other tools to help you optimize your programs  including a profiler that reports  where the program spends time  and several tools for drawing graphics and charts to let you see if  changes improve or not the time spent by the program  or the memory  for different usages  All  of them are described in the manual  Describing them here would require many more space  and  there are good books that focus just on that topic     To conclude with this notes about how to check your program once it has been executed a  couple of times  we must mention the leak tool  This tool helps a lot to find memory leaks  a  very common type of error while programming  A memory leak is simply memory that you have  allocated  using malloc or a routine that calls malloc  but not released  This tool uses the  debugger  with some help from the library implementing dynamic memory  to detect any such  leak  For example       leak  s page  leak  s 1868 1916 1917 1918  tries to find memory leaks for the process running page  The program prints a command that    can be executed to scan the different processes for that program for memory leaks  Executing  such command looks like follows       leak  s page rc  i    There was no output  which meant that ther
453. ny precaution     Why did our last program exhibit the race condition but others did not  Because calling  sleep puts the process to sleep  in the blocked state  and the system is very likely to let the other      232      process run while we sleep  We are forcing a context switch at the place where we call sleep   Nevertheless  the previous versions for the program are broken as well  We do not know if the  system is going to decide to switch from one process to another in the middle of our loop  What  happen is that in our case  the system did not switch  It was not too probable to have a context  switch right in the middle  but it could happen     Instructions are said to execute atomically  because one instruction is not interrupted in the  middle to do something else  Interrupts happen at the end of instructions  but not in the middle   However  even cnt    is implemented using several instructions  along the lines of our late ver   sions for the program  This means that another process may get in the way  even in the middle of  something like cnt    The same applies to if conditions and to any other statement     What we need is some way to synchronize multiple processes  That is  to arrange for multi   ple process to agree regarding when is a good time to do particular operations  In the rest of this  chapter  and in the following one  we are going to explore some abstractions provided by Plan 9  that can be used to synchronize processes  We are going to focus on sync
454. o   ght    2002 Lucent Technologies Inc   All Rights Reserved    At first sight  it seems that something weird happen  The file has one extra line  However  part of  the original text has been lost  These two things seem contradictory but they are not  Using xd  may reveal what happen       xd r e afrite    0000000 h     2 Lt wAn g h t c2 a9 2 0 0  0000010 2 Lucent T e c h n 1  0000020 o g i e s T ty e 2 Ane cA L l R  0000030 ight is R e s erv e d n  000003f     xd  c  NOTICE   0000000 C  o p y e a egy E c2 a9 ZO  r0  0000010 2 Lucent T e Hie  o lt  0000020 o g i e s L Om ice   a Amy A ko R  0000030 Lg  she se  XS R e s erv e d n  000003f          Our program opened afile  which was a copy of  NOTICE  and then it wrote    hello n      After the call to open  the file offset for the new open file was set zero  This means that write  wrote 6 bytes into afile starting at offset 0  The first six bytes in the file  which contained     Copyri     have been overwritten by our program  But write did just what it was expected to  do  Write 6 bytes into the file starting at the file offset  0   Nothing more  nothing less  It does not  truncate the file  it shouldn   t    It does not insert  It just writes        If we change the program above  adding a second call to write  so that it executes this  code    write fd   hello n     write fd   there n       we can see what is inside afile after running the program       cat afile  hello  there  2002 Lucent Technologies Inc   All Rights Re
455. o  The result is shown in figure 7 8        gi       Figure 7 8  Rio run in a Rio window  The inner rio runs at a CPU server  not at your terminal       Cpu  cpu  rio    and you get a whole window system in your window     You just started the window system  but it is running at the CPU server  and not at your terminal   However  it is using your mouse  your keyboard  and your screen to do its job  Not exactly   indeed  it is using the virtual mouse  keyboard  and screen provided by the Rio in your terminal  for the window you used to connect to the CPU server  Is it magic     The answer may come if you take a look at the name space used by a shell obtained by con   necting to a CPU server  This shell has a namespace that has at  mnt  term the whole names   pace you had available in the window where you did run cpu  Furthermore  some of the files at   mnt term dev were bound to  dev  Therefore  many of the devices used by the shell  or  any other process  in the CPU server do not come from the CPU server itself  They come from  your terminal     The namespace at your terminal includes files like  dev cons   dev draw  and   dev mouse  This name space was initialized by a process that called newns using   1ib namespace  as we saw in another example before  and then perhaps you customized it  further by doing mounts or binds in your profile  The same happens for the shell started for you in  the CPU server  It gets a namespace initialized by a call to newns  and perhaps by your 
456. o sdC0  where the CO names the partic   ular hardware device  In this case  it is the first disk  0  in the first controller board  C   The tree  from  S is bound at  dev  so that  dev  saco is the conventional name for  S sdCoO     Each directory for a disk contains several files  At the terminal we are using now  sdDO is  a CD reader  These are the files used as its interface       Ic  dev sdDO  ctl data raw    Reading the control file reports some information about the device       cat  dev sdD0 ctl   inquiry NECVMWarVMware IDE CDR101 00   config 85C4 capabilities O0F00 dma 00550004 dmactl 00550004  part data 0 54656          The line starting with inquiry describes the disk  It seems to be a CD reader  CDR  plugged to  an IDE controller board  Here  NECVMWarVMware is the vendor name for the disk  which is  funny for this one        The line starting with config describes some capabilities for the device  It seems that the  device knows how to do DMA  to transfer bytes from the disk to the memory of the machine  without direct intervention from the processor  We know this because the number right after dma  is not zero  We can use the ct 1 file to ask the device driver not to use DMA for this device      echo dma off  gt  dev sdD0 ct1    grep dma  dev sdD0 ct1  config 85C4 capabilities OF00 dma 00550004 dmactl 00000000    And this time we see 00000000 and not 00550004 as the value for the attribute dmactl  It  does not really matter what this is  but it matters that it is 
457. o the machine owner  but for perhaps a few that decided  to switch to the user none   However  some of these processes might want to change the user id     This can be done by using the cap 3  device  This device provides capabilities to change  ownership  A capability is just a key that allows a process to do something  In this case  a capa   bility may be used to convince the kernel to change the user id for a process     As you know  the host owner is very powerful within the local machine  A process running  on the name of the host owner may permit any other process in the machine to change its user  identity by means of the files  dev caphash and  dev capuse provided by cap       373      The idea is as follows  When a user authenticates to a server  the factotum for the server  process  if running on the name of the host owner  may help the server to change its identify to  that of the user who authenticated  After a successful authentication  the function auth_proxy  returns an AuthInfo structure with authentication information for the user  This happens also  for a server process  when it uses auth_proxy  ie   factotum  to authenticate the client   Besides the cuid and suid fields  with the user ids for the client and the server  an AUthInfo  contains a cap field with some data that is a capability for changing the user id to that of the user  authenticated     What happens is that cap 3  trusts factotum  because it runs on the name of the host  owner  Besides returni
458. occreate timerthread  timerc  8 1024    proccreate consreadthread  consc  16 1024    proccreate tempthread  tempc  8 1024    for  i   0  i  lt  Npanels  i       panelc i    chancreate  sizeof  char     arg   malloc sizeof  arg       arg  gt c    arg  gt fd   1     panelc i l       strdup        lcons  timermsg  ltemp    consmsg  ltimer  ltemp    lcons  ltimer  tempmsg     0         to test the program       282      proccreate panelthread  arg  8 1024            bceastc   chancreate sizeof char    0    threadcreate  decoratorthread  nil  8 1024    bceastthread  nil          Sending time updates is simple  A timer thread can send a message each minute  with a string  representing the time to be shown in the panels  It receives as a parameter the channel where to  send events to     void  timerthread void  a          Channel  c   a     ulong now   Tm  tm   char msg 10    for       now   time nil      tm   localtime  now     seprint  msg  msgt 10   Sd  d   tm  gt hour  tm  gt min    sendp c  strdup msg      sleep 60   1000           The function Localtime was used to break down the clock obtained by the call to time into  seconds  minutes  hours  and so on  This thread does not generate a very precise clock  It sends  the time once per minute  but it could send it when there is only one second left for the next  minute  In any case  this part of the program can be refined and programmed independently of the  rest of the application     To read the temperature  we need a temperat
459. ogram interpreter is also an interpreted file  Explain   7 How could you overcome the limitation expossed in the previous problem       101      5     Communicating Processes    5 1  Input Output redirection    Most commands we have executed so far write their output to the console  because their standard  output file descriptor is usually leading to the console     In some cases  it may be useful to redirect the output for a command to store the data pro   duced in a file  For example  to record the date for an important moment  we can execute date  and store its output in a file  for posterity  The shell knows how to do this       date  gt  rememberthis    r    This command line means  Execute the command date as usual  but send its output to  rememberthis  The obedient Plan 9 shell makes the arrangements to get the output for the  command sent to file  and not to the console  As a result  date did now write anything in the  console  But it did write  Its output is here instead       cat rememberthis  Thu Jul 13 12 10 38 MDT 2006    This can be done to any command  as you may expect  When the shell finds a     gt     in a command  line  it takes the next word as the name of a file where to send the output for the command  This  is a poor   s man editor  We use cat to read what we write in the terminal  and write it into a file       cat  gt  tmp note  must leave at 8   control d     cat  tmp note   must leave at 8    The     gt     character is an operator  and has a specia
460. oken  nemo 1633 0 00 0 00 24K Broken 8 out    r    The output of ps is sent into the pipe  It flows through it and becomes the input for grep  which  writes just those lines that contain the string Broken        To get rid of this broken process  we can execute broke  This program prints a command  to kill the broken processes  but does not kill them itself  killing is too dangerous and broke  does not want to take responsibility for your actions        broke  echo kill gt  proc 1633 ctl   8 out    r    But to execute this command  we must use it as input for the shell  Now we can       broke  rce    ps   grep Broken    r    Figure 5 2 shows what happens when you execute broke   rc The file descriptor 1 for broke  gets sent to the input of the pipe  The output from the pipe is used as source for file descriptor 0  in rc Therefore  rc reads from its standard input what broke writes on its output  In the figure   processes are represented by circles  Arrows going out from circles are file descriptors open for  writing  The descriptor number is the value or variable printed in the arrow  Arrows pointing into  circles are file descriptors open for reading  Of course  the process represented by the circle is the  one who reads  Pipes and files do not read  they are not alive           brok   pipe             Figure 5 2  Using a pipe to connect the output of oroke to the input of rc     The pipe is an artifact provided by Plan 9 to let you interconnect processes  It looks like  two
461. oks like wasting resources     We are going to implement a program  semfs  that provides semaphores as if they were  files  It will export a single  flat  directory  Each file in the directory represents a semaphore  And  we have to think of an interface for using a semaphore by means of file operations  It could be as  follows        Creating a file in our file server creates a semaphore  with no tickets inside  That is  its ini   tial value is zero        To put tickets in a semaphore  a process may write into its file a string stating how many  tickets to add to the semaphore  We prefer to write the string 3 instead of the binary number  3 because strings are portable  all machines store them in the same way         To get a ticket from a semaphore  a process may read from its file  Each read would have to  await until there is a ticket to get  and it will return some uninteresting data once a ticket is  available     Before implementing anything  we want to be sure that the interface could be used  We can use  some wishful thinking and assume that it has been already implemented  And now we can try to  use it  just to see if we can  For example  we can start by providing a C interface for using the  semaphores  The function newsem can create a semaphore and give it an initial number of tick   ets     m    m 0644 at 1    0      332      int  newsem char  sem  int val       int Fas       fd   create sem  OWRITE  0664    if  fd  lt  0   return  1   print  fd   Sd   val    cl
462. oles  file with  64  Shome  93  172  home directory  5  14  42  172  hostdomain  362  hostowner  362  HTTP  137       I     1 device driver  300  id  group  69  modification user  69  process  45  thread  264  user  69  Identification  358  identifier  203  file  327  thread  264  unique  327  identity  360  change  372 373  if  command  188  not  188  ifcall  336  ignore comment  220  Image  301  image  300  allocation  307  chan  308  copy  302  descriptor  307  memory  32  replicated  308  screen  52  window  52      I2     implementation  9P  336  implicit rule  352  import  174  in octal  permissions  20  in   pipes  rc  109   rc  dup  107   include file  196  includes  standard  21  incref  340  indent  text  203  independent   architecture  68   child process  158   execution  29  84  indexing  list  181  information   authentication  365   network connection  142  inheritance  106  init  172  initdraw  300  initialization   disk  324   graphics  300   keyboard  309   mouse  297  initializer  array  186  initkeyboard  309  initmouse  297  inner expression  202  input   and output redirection  107   base  183   focus  317   keyboard  309   mouse  295   record  220   redirection  103   standard  56 57  102 103  inquiry  321  insensitive  case  209  install  format  298  install  mk  353  installation  stand alone  324  instruction   atomic  232   order  233  instruction  tas  235  integrity  357  Intel  21  interface  file  49  179  interleaving  230  internet    probe  
463. ome c sic c trunc c    Patterns may contain a          which matches a single character  For example  we know that the  linkers generate output files named 8   out  5 out  etc  This removes any temporary binary that  we might have in the directory       rm   out    Any file name containing a single character  and then  out  matches this pattern  The shell  replaces the pattern with appropriate file names  and then executes the command line  If no file  name matches the pattern  the pattern itself is untouched by the shell and used as the command  argument  After the previous command  if we try again    7 rm  P out  rm    out       out    file does not exist    Another expression that may be used in a pattern is a series of characters between square brackets   It matches any single character within the brackets  For example  instead of using   out we  might have used  58   out in the command line above  The only file names matching this  expression are 5  out and 8  out  which were the names we meant     Another example  This lists any C source file  any string followed by a single dot  and then  either a c or an h      7 ALC Aa keh     As a shorthand  consecutive letters or numbers within the brackets may be abbreviated by using a      between just the first and the last ones  An example is  0 9   which matches again any single    Qoa onan    275     digit    The directory  n  dump keeps a file tree that uses names reflecting dates  to keep a copy of  files in the system for 
464. ompts for a user name and a password  and then changes the  user identity to that of the new user  adjusting also the name space and the conventional environ   ment variables  We use it now to become the user e1 f       cat  mnt factotum ctl   key proto p9sk1 dom dat escet urjc es user nemo  password     auth login elf   Password      cat  mnt factotum ctl   key proto p9sk1l dom dat escet urjc es user elf  password     cat  dev user   elf      cat  dev hostowner   nemo    control d    r    Initially  the factotum used contains just the key for nemo  to authenticate with Plan 9 servers in  dat escet urjc es  After running auth login  we obtain a new shell  This one is run   ning with the user id elf  and not nemo  As you see  the program started a new factotum for the  new shell  which was given a key for using Plan 9 servers as the user elf     A program might do the same by calling the function auth_login  which does just this   It uses a code like the following one       374         authenticate      ai   auth_userpasswd  user  pass     if  ai    nil    ai  gt cap    nil   sysfatal   login incorrect             change uid     auth_chuid ai    lib namespace       First  it calls the library function auth_userpasswd to authenticate a user given its user name  and is secret  Then  auth_chuid is used to become the new user     14 7  Accounts and keys    We are near the end of the discussion about security tools provided by the operating system  but  we did not show how can the 
465. omputer Networks  A ESCET             We want to write a program  called 1ist2usr that takes this list as its input and helps to open  the student accounts  But before doing anything  we must get rid of empty lines and the com   ments nicely placed after   signs in the original file       220        awk 7             7   next     7     S    next     ae   print     oe TSE   2341 Rodolfo Martinez Operating Systems B ESCET  6542 Joe Black Operating Systems B ESCET  23467 Luis Ibafiez Operating Systems B ESCET  23341 Ricardo Martinez Operating Systems B ESCET  7653 Jos   Prieto Computer Networks  A ESCET                                              There are several new things in this program  First  we have multiple patterns for input lines  for  the first time  The first pattern matches lines with an initial    and the second matches empty  lines  Both patterns are just a regular expression  which is a shorthand for matching it against  0   This is equivalent to the first statement of our program     SO          next      Second  we have used next to skip an input record  When a line matches a commentary line   AWK executes next  This skips to the next input record  effectively throwing away the input  line  But look at this other program      awk 7      it   print            7   next     7     S    next j   ae ERSE     List of students in the random format for this semester     you only know the format when you see it     It does not ignore comments nor empty lines  AWK execut
466. on   distributive  182   list  181   operator  181  concurrent   processes  30   programming  91  229   server  148   updates  232  condition  190   race  91  229   variables  251  conditional   command  188   construct  190   execution  188   pipe  191  conditionals  rc  190  connection  136   accept  146   client  148   close  148   draw  299   hangup  137   information  network  142   network  135 136  140  159   server  139  connection ct1 file  142  conninfo c  143  console  57  117  313   device  171  289   echo  292   fossil  123   multiplexing  313   read  290   reader  242   virtual  292   write  290  construct  conditional  190  construction  address  141  content  file  15  contention  lock  246  context  46   match  203   switch  46  231  261  264  context diff  211  control   Access  360    character  16   flow  153 154  261   flow of  46   list  access  18   lists  access  360  control d  57  102  control u  290  conventions  Qid  339  conversion   case  185   rune  294  cooked mode  290  coordinate   mouse  295   translation  302  coordinates  window  302  copy   CD  227   directory  198   file  11 75   image  302  copy rc script  157  count  word  102  107  counter   program  30   shared  229  261  counting  reference  340    cp  11  15  75  cpu  174   command  151  CPU    server  174  372   servers  151   time  127   type  172  cpu variable  151  Scputype  172  create  65  105  107  124  329  create c  66  creation   directory  66  330   file  65  76   networ
467. on  and  must have a 9P speaker at the other end of the pipe  To be on the safe side  Plan 9 closes fd for  your process after the mount has been done  This prevents you from reading and writing that  descriptor  which would disrupt the 9P conversation between Plan 9 and the file server     After the call  the old file has the file server reached through fd mounted on it  The  parameter aname corresponds to the optional argument for the mount command that names a  particular file tree to be mounted  To mount the server   s main file free  supply an empty  not  null   string    The options given to the shell command mount are specified here using a bit or of flags   You may use one of the integer constants MREPL  MBEFORE  and MAFTER  Using MREPL asks  for replacing the old file  the mount point  with the new file tree  Using instead MBEFORE asks  mount to mount the new file tree before the previous contents for the old file  equivalent to    b  in the shell command   Using MAF TER instead asks for mounting the file tree after the old one   like giving a    a to the shell command   To allow creation of files in the mounted tree  do a bit   or of the integer constant MCREATE with any other flag                                                             170      This program mounts the main file tree of our file server at  n whale  and the archive at   n dump   whale c _    include  lt u h gt     include  lt libc h gt     include  lt auth h gt     for amount   void   main int  c
468. one in  cmd  How   ever  the shell understood that  cond is a single word  This is perfectly reasonable  as we quoted  the whole command  We can use echo to echo our variable within a          construct  that will  break the string into words       193      lcond     echo Scond     lcmd   f echo Scmd     echo S lcond     e    3    echo S lcmd   4   And we get back our commands  split into different words as in a regular command line  Now we  can try them       Slcond  amp  amp  Slcmd  R There was no file named  tmp file    And now       touch  tmp file    Slcond  amp  amp  Slcmd  file is there    We are now confident enough to write our new tool   when      bin re   rfork e   if     S   2      echo usage  0 cond cmd  gt  1 2        exit usage     cond     echo  1   emd      echo  2   while sleep 15      Scond   gt  dev null  gt  2 1   amp  amp     cmd    exit              We placed braces around  cond and  cmd as a safety measure  To make it clear how we want to    group commands in the body of the while  Also  after executing the action  the script exits  The  condition held and it has no need to continue checking for anything     8 6  Editing text    Before  we managed to generate a list of numbers for an array initializer that we did not want to  write by ourselves  But the output we obtained was not yet ready for a cut and paste into our edi   tor  We need to convert something like    1  2    into something like    woz   Ox2      that can be used for our purposes  There a
469. ontained in the binary file   When our program calls print  this function will write bytes to the output  e g   the window    But the procedure that knows how to write is not in our program  nor is in the C library  This pro   cedure is within the operating system kernel  A procedure provided by the system is known as a  system call  calling such procedure is known as making a system call     Your program Other program          procedure    main          PLING  sce  main                call                system call          System kernel       write                      Figure 1 7  System calls  user programs  and the system kernel     Figure 1 7 depicts two different programs  e g   the one you executed before and another  one  and the system kernel  Those programs are executing  not just files sitting on a disk  Your  program contains all the code it needs to execute  including portions of the C library  Your main  procedure calls print  with a local procedure call  The code for print was taken from the C  library and linked into your program by 81  To perform its job  print calls another procedure   write  that is contained within the operating system kernel  That is a system call  As you can  see in the figure  the other program might perform its own system calls as well     In general  you don   t mind if a particular function is a system call or is defined in the stan   dard system library  the C library   Many functions that are part of the interface of the system ar
470. ontains the file  Thus  the data struc   ture that contains file metadata is known as a directory entry  A directory contains just a  sequence of entries  each one providing the attributes for a file contained in it  Let   s see this in  action    a EC   n Cat    An empty directory is an empty file       touch onefile   a  lt 6 Neal Omer   0000000 B 00 M 00 13 00 00 00 00 00 00 00 00 bf al 01  0000010 00 00 00 00 00 a4 01 00 00  r T HI D r Ibi  0000020 D  00 00 00 00 00 00 00 00 07 00 o n e     i  0000030 1 e04 00 n e m o 04 00 n e m o 04 00  0000040 n e m o   0000044    After creating onefile in this empty directory  we see a whole bunch of bytes in the directory   Nothing that we could understand by looking at them  although you can see how there are several  strings  including nemo and onefile within the data kept in the directory     For each file in the directory  there is an entry in the directory to describe the file  The for   mat is independent of the architecture used  which means that the format is the same no matter the  machine that stored the file  Because the machine using the directory  e g   your terminal  may  differ from the machine keeping the file  e g   your file server   this is important  Each machine  could use a different format to encode integers  strings  and other data types     We can double check our belief by creating a second file in our directory  After doing so   the directory has twice the size       touch another    a XO ers  0000000 B 00 
471. oot directory down to the file  each component separated by a slash  But  the file name is just onefile        The times for the last access and for the last modification of the file  this one printed by 1s   are kept at atime and mt ime respectively  These dates are codified in seconds since the  epoch  as we saw for  dev time        The length for the file is zero  This is stored at field Length in the directory entry  The  file is owned by user nemo and belongs to the group nemo  These values are stored as  string  using the fields uid  user id  and gid  group id  respectively       The field mode records the file permissions  also known as the mode  that is why chmod  has that name  for    change mode      Permissions are encoded in a single integer  as we saw   For this file mode would be 0644        The file was last modified by user nemo  and this value is encoded as a string in the direc   tory entry  using field muid  modification user id         The fields type  dev  and qid identify the file  They deserve a separate explanation on  their own that we defer by now     To obtain the directory entry for a file  i e   its attributes  we can use dirstat  This function  uses the actual system call  st at  to read the data  and returns a Dir structure that is more con   venient to use in C programs  This structure is stored in dynamic memory allocated with malloc  by dirstat  and the caller is responsible for calling free on it           The following program gives some in
472. or example  for the Arm  the compiler is 5c and the linker 51  We have these  programs available for all the architectures  e g   PCs  and Arms   To compile for one architec   ture you only have to use the compiler that generates code for it  But you can compile from any  other architecture because the compiler itself is available for all of them     For the Arm  the files generated by the compiler and the linker would be take 5 and  5 out  This makes it easy to compile a single program for execution at different platforms in  the same directory  We still know which file is for which architecture  Now you may have the  pleasure of executing your first hand made Plan 9 program      8 out  take me to your leader     r    The Plan 9 C dialect is not ANSI  nor ISO  C  It is a variant implemented by Ken Thompson   One of the authors of UNIX  It has a few differences with respect to the C language you can use  in other system  You already noticed some  Most programs include just two files  u h  which  contains machine and system definitions  and 1ibc h  which contains most of the things you  will need  The header files include a hint for the linker that is included in the object file  For  example  this is the first line in the file Libc h      pragma lib  Iibera   The linker uses this to automatically link against the libraries with headers included by your pro   grams  There is no need to supply a long list of library names in the command line for 81      There are several flags 
473. or fixing the problem   You really want to print it out to let the user know what happen     There are several ways of doing so  The more convenient one is using the format    Sr    in  print  This instructs print to ask Plan 9 for the error string and print it along with other out   put  This program is an example      41        err c     include  lt u h gt    include  lt libc h gt     void  main int   char          if  chdir   magic    lt  0    print   chdir failed   r n     exits   failed               do other things         exits  nil           Let   s run it now      8 err  chdir failed     magic    file does not exist    The program tried to use chdir to change its current working directory to magic  Because it  did not exist  the system call failed and returned  1  A good program would always check for  this condition  and then report the error to the user  Note the use of Sr in print and compare to  the output produced by the program     If the program cannot proceed because of the failure  it is sensible to terminate the execution  indicating that the program failed  This is so common that there is a function that both prints a  message and exits  It is called sysfatal  and is used like follows     if  chdir  magic    lt  0   sysfatal  chdir failed    r          In a few cases you will need to obtain the error string for a system call that failed  For example  to  modify it and print a customary diagnostic message  The system call rerrstr reads the error  string  It
474. or is concatenating a list with another one that has a single element   It saves a lot of typing  Several examples follow  We use echo in all of them to let you see the  outcome       files  stack run cp     echo Sfiles  c  stack c run  c Cpe     echo Sfiles  h  stack h run h cp h     rm Sfiles     8     echo  8 5    out  8 out 5 out     rm  8 5   out    Another example  These two lines are equivalent       cp   source dir  dest dir   a very long path    cp  source dir a very long path  dest dir a very long path    And of course  we can use variables here       182        src  source dir    ast  dest dir    cp   src S dst   a very long path    Concatenation of lists that do not have the same number of elements and do not distribute   because none of them has a single element  is illegal in rc  Concatenation of an empty list is also  forbidden  as a particular case of this rule       ops               perms  W x      echo Sops   Sperms   rc  mismatched list lengths in concatenation  i  x        echo  a b c  Sx   re  null list in concatenation    In some cases it is useful to use the value of a variable as a single string  even if the variable con   tains a list with several strings  This can be done by using a         before the variable name  Note  that this may be used to concatenate a variable that might be an empty list  because we translate  the variable contents to a single word  which happens to be empty       X  a boc      echo Sx      al bl cl     echo S x  1   a b ci
475. ore appro   priate to use an append only permission bit supported by the Plan 9 file server       chmod ta  sys log diagnostics    ls  1  sys log diagnostics  a rw r  r   M 19 nemo nemo 0 Jul 10 01 11  sys log diagnostics    This guarantees that any write will happen at the end of existing data  no matter what the offset is   Doing a seek in all programs using this file might not suffice  If there are multiple machines  writing to this file  each machine would keep its own offset for the file  Therefore  there is some  risk of overwriting some data in the file  However  using the  a permission bit fixes this problem  once and for all     3 3  Read games    To read a file it does not suffice to call read once  This point may be missed when using this  function for the first few times  The problem is that read does no guarantee that all the bytes in  the file could be read in the first call  For example  early in this chapter we did read from the con   sole  Before typing a line  there is no way for read to obtain its characters  The result in that  when reading from the console our program did read one line at a time  If we change the program  to read from a file on a disk  it will probably read as much as it fits in the buffer we supply for  reading      65     Usually  we are supposed to call read until there is nothing more to read  That happens  when the number of bytes read is zero  For example  this program reads the whole file  NOTICE   and prints what it can read each 
476. ormance  Most disks have also memory used to cache entire tracks   What old textbooks say about disks is no longer true  However  the operating system still works  because it is using its familiar disk abstraction     Using abstract data types instead of the raw hardware has another benefit  portability  If the  hardware changes  but the data type you use remains the same  your program would still work   Did your programs using files still work when used on a different disk     Note that the hardware may change either because you replace it with more modern one  or  because you move your program to a different computer  Because both hardware and systems are  made with backward compatibility in mind  which means that they try hard to work for pro   grams written for previous versions of the hardware or the system  Thus  it might even be unnec   essary to recompile your program if the basic architecture remains the same  For instance  your  Windows binaries would probably work in any PC you might find with this system  When they  do not work  it is probably not because of the hardware  but due to other reasons  a missing  library in the system or a bug      This is the reason why operating systems are sometimes called  at least in textbooks  a  virtual machine  They provide a machine that does not exist  physically  hence it is virtual  The  virtual machine provides files  processes  network connections  windows  and other artifacts  unknown to the bare hardware     With powerf
477. ose  fd    return 0          Removing a semaphore is easy  we can use remove  To do ups and downs we can use the fol   lowing functions    int   up  char  sem        int fd        fd   open sem  OWRIT   if  fd  lt  0    return  1   writer   LY  Ly  close  fd    return 0     GI               int   down  char  sem       char buf  1    int Eas    fd   open  sem  OREAD     we  Ed  lt  0    return  1   read fd  buf  1    return 0             The interface seems to be convenient  because we can even use the shell to initialize and list our  semaphores  An invented session could be as follows  provided that semfs has been mounted at   mnt sem       echo 1  gt  mnt sem mutex create a semaphore for mutual exclusion    touch  mnt sem items create a semaphore with 0 tickets     ls  mnt sem list semaphores   mutex items    r    13 4  Speaking 9P    It is quite easy to build a file server that speaks 9P using the 9p 2  library  known also as 1ib9p   It provides most of the machinery needed to maintain the data structures necessary for a file  server  and many of the common functions found in most file servers     The main data structure provided by 1ib9p is Srv  The task of a 9P file server is to serve      333      9P requests  For each 9P message received  it must execute a function to perform the actions  requested by the message  and reply with an appropriate message to the client  This is what Srv  represents  the implementation of a file server  Srv is a structure that contains poin
478. oth indicates the failure and explains its cause  The expla   nation is just an string  sent in the ename field  The error was auth not required in this      327      case     The first two requests were just establishing a 9P conversation between both parties  The  third one  Tat tach  was the one used by Plan 9 to mount the file tree      lt  12  Tattach tag 16 fid 435 afid  1 uname nemo aname   12  gt  Rattach tag 16 qid  0000000000000000 0 d     The attach request lets Plan 9 obtain a reference to the root of the file tree from the server  The  field uname tells the file server which user is attaching to the tree  The field aname tells to  which file tree in the server we are attaching  It corresponds to the last  optional  argument for  mount  In this case  the empty string is the conventional name for the main file server   s tree     How can Plan 9 obtain a reference to a file in the server  References are pointers  which  point into memory  and cannot cross the network  Numbers  called fids  or file identifiers  are  used to do that  The point is that both Plan 9 and the file server may agree that a particular fid  number identifies a particular file in the server     As figure 13 1 and the attach messages above show  Plan 9 sent a fid number in Tattach   It was 435  Which number it was  it does not matter  It is just a number proposed as a fid  i e   a  file identifier  or a file reference  by Plan 9 to the file server  After the server accepts the attach  request  a
479. ou have to think about what the shell program was doing   You never did  You wrote your own program  executed by your own process  and you forgot  completely about other processes in the system  The same happens here  In Plan 9  when a process  has offspring  the child leaves the parent    s house immediately     Because the child is a copy  and all its memory is a copy of the parent   s  variables in the  child start with the values they had by the time of the fork  From there on  when you program   you must keep in mind that each variable you use may have one value for the parent and another  for the child  You just have to fork  hence the system call name  the flow of control at the fork   and think separately from there on for each process  To check out that you really understand this   try to say what this program would print     intfork c  include  lt u h gt     include  lt libc h gt                    void  main int  char           int       i   1  fork    itt     i    print   i  sd n   i    exits  nil           The variable i is initialized to 1 by the only process we have initially  After calling fork  each  process  parent and child  increments it   s own copy of the variable  The variable i of the parent  becomes 2  and that of the child becomes 2 as well  Finally  each process will print its variable   but we will always get this output       8 intfork  1 2  1 2  After calling fork  you may want to write an if that makes the child do something different  from the 
480. ou may even used them  The following commands change your name space to  use the C library you were using on May 4th  2006       bind  n dump 2006 0504 386 lib libc a  386 lib libc a    bind  n dump 2006 0504 sys include libc h  sys include libc h    Remember what bind does  When your compiler and linker try to use 1ibc a  and libc h   the name space jumps to those archived in the dump  If you suspect that a program is failing  because of a recent bug in the C library  you can check that out by compiling your program using  the library you had time ago  and running it again to see if it works this time     The script 9f s also knows how to mount the dump  So  we could have said      9fs dump    bind  n dump 2006 0504 386 lib libc a  386 lib libc a    bind  n dump 2006 0504 sys include libc h  sys include libc h    instead of mounting the dump using srv and mount       164      7 6  Local name space tricks    You must always take into account that name spaces  i e   mount tables  are per process in Plan 9   Most processes in the same window share the same name space  i e   their mount table   and a  mount  bind  or unmount done at a window will not in general be noticed at other ones  How   ever  any process may have its own name space  This catches many users that have not been using  Plan 9 for some time  when they try to change the namespace using Acme     Figure 7 5 shows a window running Acme  Using this acme  we executed    mkdir  tmp dir   bind  usr nemo  tmp dir    New
481. ows the elements involved in the ses   sion we have just seen     Echo    process    File     srv echo       File descriptor  table                   file  pipe ORDWR  offset  0       Ww NY   oO                                       file  pipe ORDWR    a pipe    offset  0                      Figure 5 4  A file descriptor posted at  srv echo used to talk to a process through a pipe     5 9  Delivering messages    Presenting every resource as a file may be an inconvenience when programs need to act after  some success happens  For example  the program faces  see figure 5 5  shows a small face  image for each email received by the user  displaying an image that describes the sender for each  mail  When a mail arrives  faces must show a new face to alert the user of the new incoming  mail  In this case  usually  the program must check out the files of interest to see if the thing of  interest happen  This is called polling  and the thing of interest is called an event     T     mero sareva rsc esoria paurea nemo  13 27 13 27 13 27 13 27 13 27 13 27       Mon Jul 31 13 28    f       Figure 5 5  The program faces shows small faces for persons that sent email to us     Polling has the problem of consuming resources each time a poll is made to check out if an      126      interesting event happen  Most of the times  nothing happens and the poll is a waste  Therefore  it  would be very inefficient to be all the time polling for an event and  as a result  programs that poll  usually 
482. pare two files to  search for differences  For example  we can compare the two files  bin t  and  tmp t   that  look similar  to see how they differ  The tool reports what changed in the first file to obtain the  contents in the second one       diff  bin t   bin t   262  73   lt  exec sed  s    yi     gt  exec sed    s         gt     The output shows the minimum set of differences between both files  here we see just one  Each  difference reported starts with a line like 2c2  3  which explains which lines differ  This tool  tries to show a minimal set of differences  and it will try to agglutinate runs of lines that change   In this way  it can simply say that several  contiguous  lines in the first file have changed and cor   respond to a different set of lines in the second file  In this case  line 2 in the first file  t   has  changed in favor of lines 2 and 3 in the second file  If we replace line 2 in t  with lines 2 and 3  from t   both files have be the same contents     After the initial summary  diff shows the relevant lines that differ in the first file  pre   ceded by an initial  lt  sign to show that they come from the file on the left in the argument list  i e    the first file  Finally  the lines that differ in this case for the second file are shown  The line 3 is  an extra empty line  but for diff that is a difference  If we remove the last empty line in t    this is what diff says    p diff fbin7e    s   2c2   lt  exec sed    s           gt  exec sed    s   
483. parent  If you could not do this  they would be viruses  not processes  Fortunately  it is  simple  We have seen how fork returns two times  Only the parent calls it  but it returns for the  parent  in the parent process  and for the child  in the child process   The return value differs   This program      87     child c     include  lt u h gt      include  lt libc h gt     void  main int  char         switch  fork         case  1l   sysfatal   fork failed n     case 0   print   I am the child n     break   default     print   I am the parent n          exits  nil           produces the following output      8 child  I am the child  I am the parent    To the parent  fork returns the pid of the child  which we know is greater than zero  To the  child  fork always returns zero  Therefore  we can write different code to be executed in the par   ent and the child after calling fork  Both processes have their own copy for all the code  but they  can follow different paths from there on     When fork fails  it returns    1  and we should always check for errors  Of course when it  fails there would be no child  But otherwise  both processes execute different code after fork  In  which order  We do not know  And we should not care  Did you care if your shell executed its  code before or after the code in your programs  You forgot about the shell when writing your  programs  Do the same here  The program above might produce this output instead        child  I am the parent  I am the
484. path for the line directory representing the connection  The buffer must be at least 40 bytes  long  We changed the previous program to do print the path for the line directory used for the  connection     fd   dial addr  nil  dir  nil    if  fd  lt  0    sysfatal  dial  Ss   r   addr    print   dial   s0  dir      And this is what it said       8 srv tcp whale 9fs  dial   net tcp 24    The last parameter for dial  cfdp points to an integer which  when passing a non nil value  can  be used to obtain an open file descriptor for the connection  In this case  the caller is responsible  for closing this descriptor when appropriate  This can be used to write to the control file requests  to tune properties for the connection  but is usually unnecessary     There is a lot of useful information that we may obtain about a connection by calling  getnetconninfo  This function returns nothing that could not be obtained by reading files  from files in the line directory of the connection  but it is a very nice wrap that makes things more  convenient  In general  this is most useful in servers  to obtain information to try to identify the  other end of the connection   i e   the client   However  because it is much easier to make a call  than it is to receive one  we prefer to show this functionality here instead     Parameters for net conninfo are the path for a line directory  and one of the descriptors  for either a control or a data file in the directory  When nil is given as a path  
485. pe was posted at  srv ram  which is the file we used in mount     The second field printed for each 9P message shows the message type  A message is just a  data structure  Different messages for different requests and replies mean different things  and  have different data fields  The type of a message is identified by a number  However  ramfs  printed a string with the name of the type  instead of the number  In our case  three different  requests were sent by Plan 9  Tversion  Tauth  and Tattach  The file server replied with  three different replies  Rversion  Rerror  and Rattach  All 9P requests have names that  start with T  for transaction  The replies for each request have the name of the request  but starting  with R instead  Thus  Tversion is a version request  and Rversion is a version reply     Following the message type  the names and contents of most important fields for each mes   sage are printed as well  For example  the tag field of the Tatt ach message had 65535 as its  value  As you can see  all the messages have a tag field  besides a type field  The protocol dic   tates that each reply must carry the same number in the tag that was used by its corresponding  request  This is useful to have multiple outstanding  not yet replied  requests through the same  connection  Tags let the client know which reply corresponds to each request  Because of this  a  tag used in a request cannot be used again until its reply has been received     Before anything else  Plan
486. pe when no one is going to read what we write is a nonsense  Plan 9 kills any  process doing such think  For example executing this program    brokenpipe c   include  lt u h gt    finclude  lt libc h gt        void  main int  char             int fd 2    char buf  128    int nr     if  pipe fd   lt  0   sysfatal  can   t create a pipe  Sr       close fd 0     write fd 1    Hello  n   7    print   could write n           exits  nil      yields      8 brokenpipe    echo Sstatus  8 out 2861  sys  write on closed pipe pc 0x00002b43    5 5  Using pipes   One useful thing would be to be able to send from a C program an arbitrary string as the standard  input for a command  This can be used for many things  For example  the mail program is used  to send electronic mail from the command line  The body of the message is read from standard  input  and the subject and destination address can be supplied in the command line  This is an  example using the shell       mail  s    do you want a coffee     mero lsub org    Hi    If you want a coffee  let   s meet down at 5pm   see u    control d       To do something similar from a C program  we must create a child process to execute mail on it   Besides  we need a pipe to redirect to it the standard input for mail and write what we want from  the other end of the pipe     This seems a general tool  We are likely to want to execute many different commands in  this way  Therefore  we try to write a function as general as possible for doing thi
487. perating sys   tem as an index in a table of open files for your process  to know which file to use for reading or  writing  See figure 3 1                                                  Standard  File descriptor input  table  0  1 Standard  output  j tp  3  n Standard  error             Figure 3 1  File descriptors point to files used for standard input  standard output  and standard error     All processes have three files open right from the start  by convention  even if they do not  open a single file  These open files have the file descriptors 0  1  and 2  As you could see  file  descriptor 1 is used for data output and is called standard output  File descriptor O is used for  data input and is called standard input  File descriptor 2 is used for diagnostic  messages  output  and is called standard error     To read an open file  you may call read  Here is the function declaration       sig read  long read int fd  void  buf  long nbytes     It reads bytes from file descriptor fd a maximum of nbytes bytes and places the bytes read at  the address pointed to by buf  The number of bytes read is the value returned  Read does not  guarantee that we would get as many bytes as we want  it reads what it can and lets us know   This program reads some bytes from standard input and later writes them to standard output     read c   include  lt u h gt      include  lt libc h gt           void  main int   char              char buffer 1024    int Ar   nr   read 0  buffer  sizeof buf
488. ple  for your  web page  and then automatically adjust this template to generate something else  You can see the  page at http   1lsub org who nemo  which is generated using a similar technique to state  whether Nemo is at his office or not     The most useful sed command is yet to be seen  It replaces some text with another  Many  people who do not know how to use sed  know at least how to use sed just for doing this  The  command is s  for substitute   and is followed by two strings  Both the command and the strings  are delimited using any character you please  usually a    For example  s bad good  replaces  the string bad with good       echo Really in bad mood   sed    s bad good      Really in good mood    The quoting was unnecessary  but it does not hurt and it is good to get used to quote arguments  that may get special characters inside  There are two things to see here  The command  s  applies  to all lines of input  because no address was given  Also  as it is  it replaces only the first appear   ance of bad in the line  Most times you will add a final g  which is a flag that makes s substitute  all occurrences  globally  and not just the first one     This lists all files terminating in  h  and replaces that termination with   c  to generate a list  of files that may contain the implementation for the things declared in the header files     POLSON   cook h   gui h     Ils   h   sed    s  h  c g     cook c   gui c    You can now do more things  like renaming all th
489. pro   gram 8  raw did not read anything as we typed them  Not yet  However  in raw mode  the con   sole does not echo back to the screen what we type  It assumes that the program reading in raw  mode does want to do it all by itself  and echo is suppressed     Another effect of raw mode is that the program reads one character at a time  as we type  them  In cooked mode  only when we type a newline the program will get its input     A final and interesting difference is that we cannot interrupt the program pressing Delete   In fact  if  dev cons was  c cons  it would know nothing about Delete  This key is an  invention of the cooked mode in consoles provided for windows by the window system  In raw  mode  rio decides not to do anything special with this key  and the application can read it as any  other key     Using the hold mode  provided by rio   s consoles in cooked mode  this is what happens       8 OUL   Escape   hi hold mode is active     there we can edit this until     Escape    hi        there        The behavior is like in cooked mode  one line at a time   but we could type and edit while in hold  mode     To answer our pending question  The program cat  that we used to experiment with read   ing  c cons  got characters and not lines because rio keeps the system console in raw mode   The file  c cons returns characters as we type them  These characters are processed by rio   which uses them to supply a virtual console for the window were you are typing  Again  the v
490. procexecl may be either nil or point to a channel of unsigned      287      integers  In the later case  the pid for the process used to execute the command is sent through the  channel  This is useful for more than to obtain the pid for the process running the external com   mand  It is guaranteed that the arguments supplied to procexec will not be used after sending  the pid  In our case  1n is in the stack of the initial thread  After receiving the pid  we could ter   minate threadmain  which deallocates 1n  However  before receiving the pid  the arguments  for procexec must still exist  and cannot be deallocated yet     The program calls threadwaitchan to obtain a channel for notifying the termination of  the external program  Receiving from this channel yields the Waitmsg that wait would return  for a program not using threads     This is an example run         texec   cmd   bin date   started new proc pid 1436   Sat Aug 5 19 51 05 MDT 2006  terminated pid 1436 sts        texec   cmd  date   procexecl      date    file does not exist    r    To conclude  handling of notes is similar in threaded programs than in other ones  Only that  threadnotify must be used instead of atnotify  But the interface is otherwise the same     Problems    1 Implement a concurrent program simulating a printer spooler  It must have several pro   cesses  Some of them generate jobs for printing  spool print jobs  and two other ones print  jobs  Needless to say that the program must not have race
491. profile   However  the program initializing a namespace for you in the CPU server mounted at   mnt term the name space exported from your terminal  and made a few binds to adjust  dev  to use your terminal   s devices instead     This includes the files we mentioned above that are the interface for your console  for draw   ing graphics  and for using the mouse  At least  they are within your terminal   s window  At a dif   ferent window  you know that rio provides different files that represent the interface for the con   sole  graphics  and mouse for that other window       175      Now the question remains  How can a namespace be exported  Change the question  How  can a namespace be imported  To import anything into your namespace  you must mount a 9P  file server  Therefore  if your namespace is explored using a file server  it can be imported  It  turns out that there is a program for doing just that  Well  there are two     The real work is done by exportfs  This program uses the venerable calls open   close  read  write  etc  to access your namespace  and exports it by speaking 9P through a  network connection  like any other file server  When a 9P client of export fs asks this program  to return the result of reading a file  it reads the file and replies  When a 9P client asks  exportfs to write into a file  by sending a 9P write request to it  the program uses the write  system call to write to the file  The effect is that for anyone mounting the file tree provided b
492. program does so by  checking that msg text is not nil in panelproc before even looking at the message  The  msg text will be a null value until the reader initializes it for the first time  As a result  if we  start the panel processes after starting the reader  the program will still work     Termination is also a delicate thing  Now that there are multiple processes  when the pro   gram terminates  all the processes should exit  How to achieve this in a clean way  it depends on  the problem being solved  In this case we decided to use a global flag exiting  No  panelproc will remain in its while when exiting is true  Therefore  all we have to do to  terminate the program is to set exiting to 1  as we do in the reader after reaching the end of  file  Later  as panel processes awake from their sleep and check exiting  they will call exits  and terminate themselves     This is an example execution for the program  Note how the panel processes terminate after  we have sent the end of file indication       244        8 ticker   Iberia arriving late for flight 666  Iberia arriving late for flight 666  Iberia arriving late for flight 666  Iberia arriving very late for flight 666  Iberia arriving very late for flight 666  Iberia arriving very late for flight 666  control d     panel exiting   panel exiting          If you look at the program  you will notice that after we have updated the message  the panel pro   cesses will acquire the msg 1ck in sequence as they write their panel
493. protocol is  called a network protocol because it gives an address to each machine in the Internet  its IP   address  and it knows how to reach any machine  given its address  The interface for the IP net   work in Plan 9 is similar to the one we saw for Ethernet       136        lc  net ipifc  0 1 clone stats    This is not yet enough for communicating with programs across the internet  Using IP  you may  talk to one machine  and IP cares about how to reach that machine through the many different  wires and machines you need to cross   But you need to be able to talk to one process  This is  achieved by using another protocol  built upon the network protocol  This kind of protocol gives  addresses for    mailboxes    within each machine  called ports  Therefore  an address for this proto   col is a combination of a machine address  used to reach that machine through the underlying net   work protocol  and a port number     In few words  the network protocol gives addresses for each machine and knows how to  exchange messages between machines  Today  you are going to use IP as your network protocol   The transport protocol gives port numbers for processes to use  and knows how to deliver mes   sages to a particular port at a particular machine  Think of the network address as the address for a  building  and the port number as the number for a mailbox in the building     Some transport protocols provide an abstraction similar to the postal service  They deliver  individual me
494. provide abstractions similar to the one whose interface is described here  to let you use  the network     This chapter may be hard to understand if you have not attended a computer networks  course  but we try to do our best to explain how to use the network in any case  All the programs  you have used to browse the Web  exchange electronic mail  etc  are implemented using inter   faces that are similar to the ones described below  they use to be more complex  though      In general  things work as for any other service provided by the operating system  First  the  system provides some abstraction for using the network  As we will be seeing  Plan 9 uses also  the file abstraction as its primary interface for using networks  Of course  files used to represent a  network have a special meaning  i e   behave in a particular way  but they are still used like files   Other operating systems use a whole bunch of extra system calls instead  to provide the interface  for their network abstraction  Nevertheless  the ideas  and the programmatic interface that we will  see  are very similar     Upon such system provided abstraction  library functions may provide a more convenient  interface for the application programmer  And of course  in the end  there many programs already  installed in the system that  using these libraries  provide some services for the user     A network in Plan 9 is a set of devices that provide the ability to talk with other machines  using some physical medium
495. provides the implementation of several functions  known as system calls  These functions provide  the interface for the abstract data types invented by the system  to make it easier to use the com   puter     In general  the only way to use the system is to write a program that makes system calls   However  there many programs already compiled in your system  ready to run  To provide you  some mean to run them  another program is provided  the shell  When you type a command name  at the shell prompt  the shell searches for a file with the same name located at a directory that  by  convention  keeps the executable files for the system  If the shell finds such file  it asks the sys   tem to execute it           read execute  and li  in s  U    system kernel             Figure 1 9  Executing commands     Figure 1 9 shows what happens when you type 1s at the shell prompt  First  the shell reads  your command line  It looks for a file named  bin 1s  and because there is such file  the shell  executes it  To read the command line  and to execute the corresponding file for the command  you typed  the shell uses system calls  Only the operating system knows what it means to    read     and to    execute    a file  Remember  the hardware knows nothing about that     The consequence of your command request is that the program contained in  bin 1s is  loaded into memory by the operating system and gets executed as a new program  Note that if  you create a new executable file  you have c
496. pu init planb sysname  0 cputype location plumbsrv tabstop    and many others      Ic ter   oe  cpu init planb sysname  0 cputype location plumbsrv tabstop    and many others     We have also seen that files at  proc represent the processes in the system  Those files are pro   vided by the proc device  To list the files for the process running the shell  we can      lc  proc Spid  args fd kregs note notepg proc regs status wait  Ctl fpregs mem noteid ns profile segment text    But we can also    Ic     p    Spid  args fd kregs note notepg proc regs status wait  ctl fpregs mem noteid ns profile segment text    When a device path is used  the file tree for the device is automatically mounted by the kernel   You might not even have where to mount it  The rest of the name is resolved from there  Thus   device file names are always available  even if you have no entries in your name space     Where does   come from  It comes from     that is a tiny file tree that provides mount  points to let you mount files from other places  The device is called the root device and includes  the few programs necessary to reach your file server       OE ZA  bin dev fd net proc Srv  boot env mnt net alt root    This directory is bound to    a few other mounts and binds made  and now you have your tree   The programs needed to do this are also in there       lc       boot     boot factotum fossil ipconfig    7 8  Unions    The mounts  and binds  we made so far have the effect of replacing the mount
497. quest is reported by r  gt ifcall count  The offset for the write  kept at  r  gt ifcall offset  is ignored                 We had to move the bytes to str to terminate the string written with a final null byte  so  we could use at oi to convert the string to a number  and add so many tickets to s     gt tickets   If might seem simpler to write an integer directly  but then we could not use echo to update  semaphores  and we would have to agree on the endianness for the integers written to the file  It is  more simple in this way     Once the semaphore has been updated  the implementation still has to complete any pending  down that may proceed due to the new tickets added  The last while does just that  While there  are tickets and pending requests  we reply to each one of such requests with an empty line  like  fsread did when tickets were available     That is all we had to do  But we still have pending reading from the file that is the root  directory  The code used by fsread to attend such requests was as follows       346      if  q type amp QTDIR     dirread9p r  getdirent  nil    respond r  nil    return          Reading from a directory must return an integral number of directory entries  formatted as an  array of bytes  neutral to all architectures  so that reading from a directory would return meaning   ful data no matter the architecture of the machine used by the file server and the one used as a  client  Attending such reads can be a burden  The function dirread
498. quits  What  happen in the example is that the editor read lines  and printed them to the output  until the  address 3 was matched  That was at line number 3  The command quit was applied  and the rest  of the file was not printed  Therefore  the previous command can be used to print the first few  lines for a file     If we want to do the opposite  we may just delete some lines  from the one with address 1   to the one with address 3  As you can see below  both addresses are separated with a comma  and  the command to apply follows  Therefore  sed searched for the text matching the address pair  1 3  i e   lines 1 to 3   printing each line as it was searching  Then it copied the text selected to  memory  and applied the d command  These lines were deleted  Afterwards  sed continued  copying line by line to its memory  doing nothing to each one  and copying the result to standard  output       sed 1 3d  LICENSE  1  No right is granted to create derivative works of or  to redistribute  other than with the Plan 9 Operating System     more useful stuff for your lawyer     Supplying just one command  with no address  applies the command to all lines       sed d  LICENSE    r                   Was the  LICENSE deleted  Of course not  This editor is a stream editor  It reads  applies com   mands to the text while in the editor    s memory  and outputs the resulting text     How can we print the lines 3 to 5 from our input file  One strategy is to use the sed com   mand to print the
499. r                switch  rfork  RFFDG RFREND RFPROC               case  1l   sysfatal   fork failed     case 0   execl   bin ls    ls   nil    break   default   waitpid          exits  nil           This program is like the one we saw  run1s  which did run 1s in a child process  This time it is  using the actual system call  rfork  This call receives a set of flags  packaged into its single  parameter using a bit or  All the flags for rfork have names that start with    RF     The most  important one here is RFPROC  It asks for a new process  i e   a new flow of control     When you do not specify RFPROC  the operations you request with other flags are done to  your own process  and not to the child  When you do specify it  the other flags refer to the child     The default behavior of rfork is to make a copy of the memory for the child  and to share  most other things with the parent  To do exactly a fork  we must ask for a copy of the file  descriptor table including the RFFDG  RFork File Descriptor Group   But for the memory  which  is duplicated by default  other resources are shared by default  When you give the flag for a  resource to rfork  you are asking for a copy  When you use a slightly different flag  that has a C  in it  for    clean      you are asking for a brand new  clean  resource  Because of what we said  you  can imagine that RFREND is asking for a another rendezvous group  but this does not really mat   ter by now        Running this program executes 1s  
500. r  lt   0   break   buf nr    0   glock    msg 1ck    free  msg text    msg text   strdup  buf    msg verstt   gqunlock    msg 1ck       exiting   1   exits  nil           The critical region  updating the message text and its version  is protected by the QLock kept at  msg ick  This lock is kept within msg because it is used to protect it  If the program grows and  there are more data structures  there will be no doubt regarding what data structure is protecting  msg lck        Each panel process will be running a panelproc function  and receive a file descriptor  that can be used to write a message to the file representing the panel   void  panelproc int fd        ulong lastvers    1   do    glock   amp   msg 1ck    if msg text    nil  amp  amp  lastvers    msg vers     write fd  msg text  strlen msg text     lastvers   msg vers        gunlock    msg 1lck    sleep 5   1000      while   exiting    forint  2   panel exiting n     exits nil           The local lastvers keeps the version for the message shown at the panel  Basically   panelproc loops and  once each 5 seconds  checks out if msg vers changed  If it did  the      243      new text for the message is written to the panel  The initial value for Lastvers is just a kludge  to be sure that the message is updated the very first time  in that case  there is no previous ver   sion   Note how the critical region includes both the checks in the condition of the if and the  statements used to access msg in the body     Befor
501. r announce  the TCP  line is already listening for calls  Listen needs to know the line where it must wait for the call  and  therefore it receives the directory for a previous announce     Now comes an important point  to leave the line listening while we are attending a call  calls  are attended at a different line than the one used to listen for them  This is like an automatic trans   fer of a call to another phone line  to leave the original line undisturbed and ready for a next call   So  after listen has received a call  it obtains a new line directory for the call and returns it  In  particular  it returns an open file descriptor for its ct 1 file and its path     We have modified our program to wait for a single call  This is the result       146         listen c     include  lt u h gt      include  lt libc h gt     void  main int argc  char  argv            int Gd   tras  char adir 40    char dir 40      cfd   announce   tcp   9988   adir    if  cfd  lt  0   sysfatal  announce  Sr     print   announced in  s  cfd  d  n   adir  cfd    lfd   listen adir  dir    print   attending call in  s  lfd  d  n   dir  lfd    for       sleep  1000      let us see       When we run it  it waits until a call is received       8 listen  announced in  net tcp 52  cfd 10     At this point  we can open a new window and run telnet to connect to this address      telnet tcp Ssysname 9988  connected to tcp alboran 9988 on  net tcp 46    which makes our program receive the call     attendin
502. r each dependency  any other rule described to to build it   That was the case  There is a rule for building sem  8  and one for building semfs 8     So  mk tried to build semfs  8  using its rule  The rule says that given semfs c and  sem h  semfs 8 can be built     semfs 8  semfs c sem h  8c  FVw semfs c    Both semfs c and sem h are there  and mk can proceed to build semfs 8  How  By execut   ing the command in the body of the rule  This command runs 8c and compiles semfs c     Note one thing  The body of the rule does not use the file sem h  We know that the object  file semfs 8 comes from code both in semfs c and sem h  But mk does not  You see the  same invariant all the times  Programs usually know nothing about things  They just do what they  are supposed to do  but there is no magic way of telling mk which files really depend on others   and why the commands in the body can be used to build the target     In the same way  mk uses the rule for the target sem  8  to build this file  This is the last  dependency needed for building 8  semfs     sem 8  sem c sem h  8c  FVw sem c    After executing the body  and compiling sem c  both dependencies exist  and mk can proceed to  build  finally  8 semfs  How  You already know  It runs the command in the body of the rule  for 8 semfs  This command uses 81 to build a binary program from the object files     Mk chains rules in this way  recursively  trying to build the target  A target may be given as  an argument  If none is gi
503. ral processors  multiple programs can be executed in parallel   Le   at the same time  Although this is becoming common  many machines have just one proces   sor  In some cases we can find machines with two or four ones  But in any case  you run many  more programs than processors are installed  Count the number of windows at your terminal   There is at least one program per window  You do not have that many processors     What happens is that the operating system makes arrangements to let each program execute  for just some time  Figure 2 2 depicts the memory for a system with three processes running   Each process gets its own set of registers  including the program counter  The figure is just an  snapshot made at a point in time  During some time  the process 1 running rio may be allowed  to proceed  and it would execute its code  Later  a hardware timer set by the system may expire   to let the operating system know that the time for this process is over  At this point  the system  may jump to continue the execution of process 2  running rc  After the time for this process  expires  the system would jump to continue execution for process 3  running rio  When time for  this process expires  the system may jump back to process 1  to continue where it was left at        addl bx  di cmpl si  di    Rio jls label           hadd  bx  si    Rio  i subl  4  di    process  1  movl bx  cx    process  3   i i PC        movl bx  cx          addl bx  si     addl bx  di      addl bx  si
504. ram now                            8 aecho repeat after me  repeat after me    8 aecho  v repeat after me        repeat   after   me      8 aecho  vn repeat after me    repeat   after   me    we gave a return here     8 aecho  d repeat after me   usage  8 aecho   nv  args     8 aecho     d repeat after me     d repeat after me    SARs       In all but the last case  argc is 3 after ARGEND  and argv holds just repeat  after  and me     Another convenience of using these macros is that they initialize the global variable argv0  to point to the original argv  0  in main  that is  to point to the name of the program  We used  this when printing the diagnostic about how the program must be used  which is the custom when  any program is called in a erroneously way     In some cases  an option for a program carries an argument  For example  we might want to  allow the user to specify an alternate pair of characters to use instead of   and   when echoing  with the  v option  This could be done by adding an option  d to the program that carries as its  argument a string with the characters to use  For example  like in       8 aecho  v  d   repeat after me    This can be done by using another macro  called ARGF  This macro is used within the case for  an option  and it returns a pointer to the option argument  the rest of the argument if there are  more characters after the option  or the following argument otherwise   The resulting program  follows     becho c   include  lt u h gt    
505. re disk  Following the convention used for IDE  disks on PCs  the table may name up to 4 primary partitions  The name p1 identifies this partition  as the primary partition number 1     Now  we can print the new table  write it to disk after being sure  and quit from this pro   gram      gt  gt  gt  p    ook 0 522  522 cylinders  3 99 GB  PLANO   gt  gt  gt  W   gt  gt  gt  q    And this is what we can see now       cat  dev sdCl ctl   inquiry VMware Virtual IDE Hard Drive   config 427A capabilities 2F00 dma 00550004 dmactl 00550004 rwm 16 rwmctl 0  geometry 8388608 512 8322 16 63   part data 0 8388608   part plan9 63 8385930     Ic  dev sdCl   Gel data plang raw       There is a new partition  a new file at  dev sdC1l  Its name is plan9 because fdisk declared  the partition to be one for use with Plan 9  writing a particular integer value in the partition entry  that identifies the type for the partition        324      Within this partition  known to any other system sharing the same machine   we can create  several Plan 9 partitions using prep       disk prep  a 9fat  a fs  dev sdC1 plan9  no plan9 partition table found  9fat 204800    fs 8181067    Ofat O 204800  204800 sectors  100 00 MB   ES 204800 8385867  8181067 sectors  3 90 GB    gt  gt  gt     Note how prep uses  dev sdC1 plan9 as its disk  It is just a file  We asked prep to auto   matically choose appropriate sizes and locations for partitions named 9fat and fs within   dev sdC1 plan9  It printed the proposed ta
506. re loop   one more loop   one more loop   Delete    r    The command sleep always succeeds  It is a lucky command  Now  how can we express the  condition we are watching for  And how do we express the action to execute when the condition  holds  It seems that supplying two commands for each purpose is both general and simple to  implement  The script when is going to accept two arguments  a command to execute that must  yield success when the condition hold  and a command to perform the action  For example       when changed http   indoecencias blogspot com       ni    mail  s       new indoecencias       nemo     amp     r    sends a mail to nemo when there are changes in http   indoecencias blogspot  com   provided that changed exits with null status when there are changes in the URL  Also       when    test  sys src 9 pc main 8  older 4h             cd  sys src 9 pc   mk clean     amp     r    watches out for an object file main  8 older than 4 hours  When this happens  we assume that  someone forgot to clean up the directory  sys src 9 pc after compiling a kernel  and we  execute the command to do some clean up and remove the object files generated by the compila   tion     Nice  but  how do we do it  It is best to experiment first  First try       cond    test  e  tmp file        cmd    echo file is there      r     Scond  amp  amp  Scmd   test  e  tmp file      bin test  e     file does not exist    The aim was to execute the command in  cond and  when it succeeds  the 
507. re many programs that operate on text and know how to  do complex things to it  In this section we are going to explore them     To achieve our purpose  we might convert each number into hexadecimal  and store the      194      resulting string in a variable  Later  it is just a matter of using echo to print what we want  like  follows      num 32     hexnum     echo    obase 16      echo  num     bc       echo  0x  hexnum      0x20      We used the        construct execute hexnum      with the appropriate string on the right hand  side of the equal sign  This string was printed by the command      echo    obase 16      echo  num     be    that we now know that prints 20  It is the same command we used in the d2h script     For you  the         character may be special  For the shell  it is just another character  There   fore  the shell concatenated the     0Ox    with the string from  hexnum and the string            That  was the argument given to echo  So  you probably know already how to write a few shell com   mand lines to generate the text for your array initializer       for  num in        seq 0 255   t    as number       echo    obase 16      echo Snum     bc   ae echo  0x Snumber      ri      xO      Ox      0x2 me      and many others follow     Is the problem solved  Maybe  This is a very inefficient way of doing things  For each number   we are executing a couple of processes to run echo and then another process to run bc  It takes  time for processes to start  
508. ready exposed to computer  and used at least a com   puter running Windows  This is so common that it makes no sense to drop this assumption  Furthermore   we assume that you already know how to write programs  This is indeed the case for the lecture this text is  written for  One last assumption is that you attended a basic computer architecture course  and you know at  least basic concepts  There is a quick review appendix in case you need to refresh your memory     Through the text  the boldface font is used when a new concept is introduced  This will help you to  make quick reviews and to double check that you know the concepts  All important concepts are listed in  the index  at the end of the book  The constant width teletype font is used to refer to machine data   including functions  programs  and symbol names  In many cases  text in constant width font reproduces a  session with the system  e g   typing some commands and showing their output   The text written by the  user  and not by the computer  is slightly slanted  but still in constant width  Note the difference with  respect to the font used for text written by a program  which is not slanted  Italics are used to emphasize  things and to refer to the system manual  like in intro 1   Regarding numeric values  we use the C notation  to represent hexadecimal and octal numeric bases     Unlike in most other textbooks for operating systems courses  bibliographic references are kept to the  bare minimum  We cite a pa
509. reated a new command  All you have to do to run it is  to give its  file  name to the shell     When you run a window system  things are similar  The only difference is that the window  system must read input from both the mouse and the keyboard and writes at a graphics terminal  instead of at a text display  Of course  when the window system creates  i e      invents     a new  window  it has to ask the system to run a shell on it     ee    1 14  The Operating System and the hardware    As you can imagine now  most of the time  the operating system is not even executing  Usually  it  is your code the one running in the processor  At least  until the point in time when your program  makes a system call  At that point  the operating system code takes control  because its code starts  executing  and performs your request     However  the hardware may also require attention from the operating system  As you know  from computer architecture courses  this is done by means of hardware interrupts  When data  arrives from the network  or you hit a keyboard key  the hardware device interrupts the processor   What happens later is that the interrupt handler runs after the hardware saves the processor state     The interrupt handlers are kept within the operating system kernel  The kernel contains the  code used to operate each particular device  That is called a device driver  Device drivers use  I O instructions to operate the devices  and the devices interrupt the processor to reques
510. rectory  you must remove the line calling  write  But you should still close the file descriptor     Removing a file is simple  The system call remove removes the named file  This program  is similar to rm      67         include  lt u h gt      include  lt libc h gt     void  main int   char              int Ty  for       1  i  lt  argc  i     if  remove argv i    lt  0     fprint 2   Ss   r n   argv 0     exits  nil           It can be used like the standard rm 1  tool  to get rid of multiple files  When remove fails it  alerts the user of the problem        6 rm rm 8 x c afile  8 xrm   x c    file does not exist    Like other calls  remove returns    1 when it fails  In this case we print the program name   argv  0   and the error string  That suffices to let the user know what happen and take any  appropriate action  Note how the program iterates through command line arguments starting at 1   Otherwise  it would remove itself     A directory that is not empty  and contains other files  cannot be removed using remove   To remove it  you must remove its contents first  Plan 9 could remove the whole file tree rooted  at the directory  but it would be utterly dangerous  Think about rm    The system command rm  accepts option  r to recursively descend the named file and remove it and all of its contents  It  must be used with extreme caution  When a file is removed  it is gone  There is nothing you can  do to bring it back to life  Plan 9 does not have a wastebasket  If you ar
511. red  So  the function authmount simply called mount  using    1 as afd  after printing a diagnostic for us to see  As a result  no AuthInfo is obtained  in this case        Second  we use 8   amount to mount our main file server  wich does require authentication   the key for authenticating to the server using P9SK1 was known to the factotum used        8 amount  srv tcp whale 9fs  n whale main archive  client uid  nemo  server uid  nemo    In this case  auth_proxy was called and could authenticate using factotum  The  AuthInfo structure returned contains nemo in its cuid field  client uid   That is the actual user  id we are using at our terminal  It also contains nemo in its suid field  server uid   That is the  user id as known to the server  In our case  both user names were the same  but they could differ  if I was given a different user name for the account at whale        In most cases  a client is only interested in knowing if it could authenticate or not  Like in  our example  and in amount   most clients would just call auth_freeAT  to release the  AuthInfo structure  after a successful authentication  For server programs  things may be dif   ferent  They might employ the information returned from factotum as we will see later           But what would happen when fact ot um does not know the key needed to authenticate to  the server  In the call to auth_proxy  the function amount_getkey was given as a parame   ter  This function is provided by the auth 2  library an
512. rent thread is used for bcast     beastthread  nil         The process structure is shown in figure 11 4  which represents each separate process with a  dashed box and each thread with a circle  This time  we ended with a single thread within each  process  But usually  a central process has multiple threads to do the actual work  and there some  other processes created just for doing I O without blocking all the threads     int rforkflag       277                                          fy ot ew ee za    i        panelc 0    i    i     I    I  he Bee arta Se af  fe er tae q    I    I     bceastc panelc i  5 i    i   i  i ts BS ed din d             panelc n                 Figure 11 4  Process structure for the airport panels program  using threads     There is another benefit that arises from using threads that communicate through channels   This time  we do not need to optimize our program to maintain the write for updating the panel  outside of the critical region  to permit all panels to be updated simultaneously  All panels are  updated simultaneously in a natural way  because each one uses its own process and does not lock  any shared data structure  There are locks in this program  but they are hidden deep under the  implementation of send and recv     11 5  Many to one communication    The program that we built is nice  But it would be nicer to display in the panels  along with  each message  the current time and the temperature outside of the airport building  For e
513. respond to the second thread       268      We are going to modify the program a little bit  by calling yield on each thread to let the  other run  For example  this is the new incrthread  The other one is changed in a similar  way    void  incr  void  arg          iner Cp   arg     threadsetname   incrthread     for       zep    ep   ly  print   cnt d n    cp    yield        threadexits  nil           This is what results from the change  Each thread yields to the other one  and both onces execute  making turns  There will always be one pass in the for and then a context switch  forced by  yield     s 6 tent  Ents 1   cnt 0  ent 1    Another debugger function defined when called with  1 thread knows how to print the stacks  for all threads in the process  Now that both threads had a chance to run  you can see how the  debugger clearly identifies one thread as incrthread  and the other one as decrthread       ps   grep 8 tcnt   nemo 4571 0 00 0 00 120K Pwrite Sotet    acid  1 thread 4571    proc 4571 text 386 plan 9 executable     sys lib acid port   sys lib acid thread   sys lib acid 386  acid  stacks     p   Proc  0x169b8 pid 4571 Running  t   Thread  0x19a68 Ready  usr nemo tcent c 15 incr  incrthread     yield   0x5  sys src libthread sched c 186  incr  arg 0xd010  0x39  usr nemo tcnt c 15    launcher386  arg 0xd010     0x1020  0x10  sys src libthread 386 c 10    Oxfefefefe  file  0       t   Thread  0x1bb28 Running  usr nemo tcnt c 30 decr  decrthread   pwrite   0x7  sys
514. resses for  machines in a local network  Addresses were of the form 212 128 3 X with X going from 1 to  254  You now know how to it fast       nums      segq 1 254     for  n in Snums  ip ping 212 128 3 48n    Before this example  you might have been saying  Why should I bother to write several shell  command lines to do what I can do with a single loop in a C program  Now you may reconsider  the question  The answer is that in rc it is very easy to combine commands  Doing it in C  that  is a different business     By the way  Use variables  They might save a lot of typing  not to talk about making com   mands more simple to read  For instance  the next commands may be better than what we just  did  If we have to use 212 128 3 again  which is likely if we are playing with that network   we might just say Snet       190        nums      segq 1 254     net 212 128 3     for  n in Snums  ip ping Snet  sn    8 5  Conditions    Let   s go back to commands used for expressing conditions in our shell programs  The shell opera   tor   uses expressions  They are the same expressions used for globbing  The operator receives at  least two arguments  maybe more  Only the first one is taken as a string  The remaining ones are  considered as expressions to be matched against the string  For example  this iterates over a set of  files and prints a string suggesting what the file might be  according to the file name                 file     bin re  rfork e  for s   EvEe in S    TPs  eS Sti V
515. ring printed   and some other information  If we take this object file  and give it to 81 to link it against the C  library and produce the binary file 8   take  we get a file with 36 280 bytes on it     Let   s try to gather more information about these files  The command nm  name list  displays  the names of symbols  i e   procedure names  variables  that are contained or required by our  object and executable files     ots      nm take 8  U exits  T main  U print    nm 8 take  more output     1131 T exits  1020 T main  118d T print  more output       r    It seems that take  8 contains a procedure called main  We call text to binary program code   and nm prints a T before names for symbols that are text and are contained in the object file   Besides  our object file requires at least two other procedures  exits  and print to build a  complete binary program  We know this because nm prints U  undefined  but required  before  names for required things     If we look at the output for the executable file  you will notice that the three procedures are  in there  Furthermore  they now have addresses  The code for exits is at address 1131  hex   adecimal   and so on  The code that is now linked to our object file comes from the C library  It  was included because we included the library   s header 1ibc h in our program and called some  functions found in that library  The linker  81  knew where to find that code     But there is more code that is used by our program and is not c
516. riting the output file  The function Bopen is similar to open  but returns  a pointer to a Biobuf instead of returning a file descriptor                sig Bopen  Biobuf  Bopen char  file  int mode        Of course  Bopen must call open to open a new file  But the descriptor returned by the underly   ing call to open is kept inside the Biobuf  because only routines from bio 2  should use that  descriptor  You are supposed to read and write from the Biobuf              To read from bin  our input buffer  the program calls Bread  This function is exactly like  read  but reads bytes from the buffer when it can  without calling read  Therefore  Bread  does not receive a file descriptor as its first parameter  it receives a pointer to the Biobuf used  for reading             sig Bread  long Bread Biobufhdr  bp  void  addr  long nbytes        The actual system call  read  is used by Bread only when there are no more bytes to be read  from the buffer  e g   because you already read it all                 To write bytes to a BIobuf  the program uses Bwrite  This is to write what Bread is  to read          sig Bwrite  long Bwrite Biobufhdr  bp  void  addr  long nbytes           The call to Bterm releases a Biobuf  including the memory for the data structure  This closes  the file descriptor used to reach the file  after writing any pending byte still sitting in the buffer       sig Bterm  int Bterm Biobufhdr  bp           As you can see  both Bterm and Bflush return an integer  That i
517. rivates   200c d onexlock   2010 D _privates   2014 d _exits   2024 B edata   2024 B onex   2126 B global  10212c B end    Figure 2 3 shows the layout of memory for this program when loaded  Looking at the output of  nm we can see several things  First  the program code uses addresses starting at 0x1020 up to    0x14b4     The last symbol in the code is etext  which is a symbol defined by the linker to let you  know where the end of text is  Data goes from address 0x2000 up to address 0x10212c  There is  a symbol called end  also defined by the linker  at the end fo the data  This symbol lets you know  where the end of data is  This symbol is not to be confused with edata  which reports the    address where initialized data terminates     Text segment Data segment    BSS segment       Program  text    Initialized  data    Uninitialized  data             0x0 etext    In decimal  the address for end is 1 057 068 bytes  That is more than 1 Mbyte  which is a    Figure 2 3  Memory image for the global program        edata       end    Stack segment          stack           34     lot of memory for a program that was kept in a binary file of 3 Kbytes  Can you see the differ   ence     And there is more  We did not take into account the program stack  As you know  your pro   gram needs a stack to execute  That is the place in memory used to keep track of the chain of  function calls being made  to know where to return  and to maintain the values for function argu   ments and local v
518. rks of or    r    Still  AWK may be preferred if more complex processing is needed  because it provides a full  programming language  For example  this prints only even lines and stops at line 6       awk       NR 2    0  amp  amp  NR  lt    Lucent Public License     to redistribute    67     LICENSE  Version 1 02     reproduced below      other than with the Plan 9 Operating System     It is common to search for processes with a given name  We used grep for this task  But in some  cases  unwanted lines may get through                     ps   grep rio  nemo 39 0 04 0 16 1160K Rendez rio  nemo 275 0 01 0 07 1160K Pread rio  nemo 2602 0 00 0 00 248K Await rioban  nemo 277 0 00 0 00 1160K Pread rio  nemo 2607 0 00 0 00 248K Await brio  nemo 280 0 00 0 00 1160K Pread rio  We could filter them out using a better grep pattern     ps   grep    rios     nemo 39 0 04 0 16 1160K Rendez rio  nemo 275 0 01 0 07 1160K Pread rio  nemo 277 0 00 0 00 1160K Pread rio  nemo 2607 0 00 0 00 248K Await brio  nemo 280 0 00 0 00 1160K Pread rio    ps    grep l  rios     nemo 39 0 04 0 16 1160K Rendez rio  nemo 275 0 01 0 07 1160K Pread rio  nemo 277 0 00 0 00 1160K Pread rio  nemo 280 0 00 0 00 1160K Pread rio  But AWK just knows how to split a line into fields     ps   awk    S7     rioSs      nemo 39 0 04 0 16 1160K Rendez rio  nemo 275 0 01 0 07 1160K Pread rio  nemo 277 0 00 0 00 1160K Pread rio  nemo 280 0 00 0 00 1160K Pread rio    This AWK program uses a pattern that requires field number 7
519. rmine where to search for  commands  There are several interesting things to note about this  First  there are only two direc   tories where to search       echo Spath   bin  This is really amazing if you compare this with the list of directories in the PATH in other sys     tems  which uses to be much larger  For example  this is the variable used in a UNIX system we  have around       171        echo  PATH   bin  usr bin  sbin  usr sbin  usr local bin  opt bin  usr local plan9 bin            In UNIX  the variable uses to have the same name in upper case  and directories are separated by  colons instead of space     Also  how do you get at  bin only those binaries for the architecture you are using     After your machine has completed its boot process  and mounted the file server  it runs a  program called init  This program initializes a new namespace for your terminal and runs   bin rc within such namespace  to execute commands in  rc bin termrc  that start sys   tem services necessary for using the system  The namespace is initialized by a call to the function  newns       sig newns  int newns char  user  char  nsfile      which reads a description for an entire namespace from a file  nsfile  and builds a new names   pace for a given user that matches such description  This is is an excerpt from the file   1ib namespace  which is the nsfile used by default       root  mount  aC  s boot  root Srootspec  bind  a  root        kernel devices  bind  c  dev  bind  d  fd  bind  
520. rom the arguments given to the script  which are  kept at      d2h2      bin re  rfork e     echo    obase 16     for  num in      echo Snum      be    Now we have a better program  It can be used as follows       d2h 10 20 40  a  14  28    We still have the problem of supplying the whole argument list  a total of 256 numbers  It hap   pens that another program  seq   sequences  knows how to write numbers in sequence  It can do  much more  It knows how to print numbers obtained by iterating between two numbers  using a  certain step     seq 5 from lto5    Os WHR    seq 1 2 10 from I to 10 step 2    ony oawrn    L    What we need is to be able to use the output of seq as an argument list for d2h  We can do so   Using the        construct that we saw while discussing how to use pipes  We can do now what  we wanted       d2h        seq 0 255    0   1     and many other numbers up to     fd   fe   ff    That was nice  However  most programs that accept arguments  work with their standard input  when no argument is given  If we do the same to d2h  we increase the opportunities to reuse it  for other tasks  The idea is simple  we must check if we have arguments  If there are some  we  proceed as before  Otherwise  we can read the arguments using cat  and then proceed as before   We need a way to decide what to do  and we need to be able to compare things  Rc provides both  things       188      The construction if takes a command as an argument  within parenthesis   If the  command
521. rted size must  include that of the files found inside  Compare with du 1        82       83      4     Parent and Child    4 1  Running a new program    In chapter 2 we inspected the process that is executing your code  This process was created by  Plan 9 in response to a request made by the shell  Until now  we have created new processes only  by asking the shell to run new commands  In this chapter we explore how to create new processes  and execute new programs by ourselves     You may think that the way to start a new process to run a program is by executing a single  system call  something like run   bin 1ls   for executing 1s   That is not the case  There  are two different system calls involved in the process  One creates a new process  the other exe   cutes a new program  There are several reasons for this        One reason is that you may want to start a new process just to have an extra flow of control  for doing something  In this case  there would be no new program to execute  Thus  it  makes sense to be able to create a new process  e g   a new flow of control  just for its own  sake        Another reason is that you may want to customize the environment for the new process   e g   adjust its file descriptors  change its working directory  or any other thing  before it  executes the new program  It is true that a run    system call might include parameters to  specify all things you may want to customize  Such call would have countless parameters  It  is far mor
522. rticular text when we think that it may be worth reading to continue learning  about something said in this book  So  do not quickly dismiss references  We encourage you to read them   to learn more  There are not so many ones  If you want to get a thorough set of references for something  discussed in the test  we suggest looking at a more classical operating systems textbook  like for example   1     It is important to note that this book is not a reference for using an operating system nor a reference  for Plan 9 from Bell Labs  The user   s manual that comes installed within the system is the proper reference  to use  These lecture notes just shows you how things work  by using them  Once you have gone through  the course  you are expected to search and use the user   s manual as a reference     One final note of caution  This text is to be read with a computer side by side  The only way to learn  to use a system is by actually using it  Reading this without doing so is meaningless     I am grateful go to other colleagues who suffered or helped in one way or another to write this book   First  authors of Plan 9 from Bell Labs made an awesome system  worth describing for an Operating Sys   tems Course  It cannot be overemphasized how much help the authors of Plan 9 provide to anyone asking    questions in the 9fans list  For what is worth  I have to say that I am deeply grateful to people like Rob  Pike  Dave Presotto  Jim McKie  Russ Cox  and many others  In particular  R
523. rwise  what  would happen to programs like this one     if  fork      0        do something in this child        else     run cmd  args      m   wait       wait for our child    free m           The wait in this code seems to be for the child created by the fork  However  the call to run  would probably wait for the 2 children  and wait is likely to return nil     When a program is not interested in the exit message  it can use waitpid instead of wait   This function returns just the pid of the death child  Both functions are implemented using the  real system call  await  But that does not really matter      97     Although the shell waits by default until the process running a command completes  before  prompting for another line  it can be convinced not to wait  Any command line with a final  ampersand is not waited for  Try this      sleep 3    10 prompt for 3 seconds   and this    sleep 3  amp  and we get a new prompt right away     r    This is used when we want to execute a command in the background  i e   one that does not read  from our terminal and does not make the shell wait for it  We can start a command and forget it is  still there  The shell puts into  apid the pid for the last process started in the background  to let  you know its pid for things like killing it     Any output from the command will still go to the console  and may disturb us  However   the shell arranges for the command to have its standard input coming from  dev nu1l1  a file  that always se
524. ry  nor leave unwanted object files there     The important point here is not how to copy a CD  or how to use ramfs  The important  thing is to note that there are many different programs that allow you to use devices and to do  things through a file interface     When undertaking a particular task  it will prove to be useful to know which file system  tools are available  Browsing through the system manual  just to see which things are available   will prove to be an invaluable help  to save time  in the future     Problems    1 Write a script that copies all the files at Shome www terminated in  htm to files termi   nated in   html     2 Write a script that edits the HTML in those files to refer always to  htm1 files and not to    htm files     3 Write a script that checks that URLs in your web pages are not broken  Use the hget com   mand to probe your links     4 Write a script to replace duplicate empty lines with a single empty line     5 Write a script to generate  empty  C function definitions from text containing the function  prototypes     6 Do the opposite  Generate C function prototypes from function definitions       228      Write a script to alert you by e mail when there are new messages in a web discussion  group  The mail must contain a portion of the relevant text and a link to jump to the relevant  web page     Hint  The program html fmt may be of help     Improve the scripts resulting from answers to problems for the last chapter using regular  expressio
525. s  In this case   to display output for commands executed at  usr nemo  If you do not know what    at    means  in the last sentences  don   t worry  Forget about it for a while              There is a good description of Acme in  3   although perhaps a little bit too detailed for us at  this moment  It may be helpful to read it ignoring what you cannot understand  and get back to it  later as we learn more things     1 5  Obtaining help    Most systems include their manual on line  for users to consult  Plan 9 is not an exception  The  Plan 9 manual is available in several forms  From the web  you can consult  http   plan9 bell labs com sys man for a web version of the manual  At Rey Juan  Carlos University  we suggest you use http    plan9 1lsub org sys man instead  which  is our local copy     And there is even more help available in the system  The directory  sys doc  also avail   able at http    plan9 bell labs com sys doc  contains a copy of most of the papers  relevant for the system  We will mention several of them in this book  And now you know where  to find them     The manual is divided in sections  Each manual page belongs to a particular section     9     depending on its topic  For us  it suffices to know that section 1 is for commands  section 8 is for  commands not commonly used by users  i e   they are intended to administer the system   and  section 2 is for C functions and libraries  To refer to a manual page  we use the name of the page  followed by the s
526. s  int ndata   char  data           struct Plumbattr       char xname   char  value   Plumbattr  next           The program looks in the attribute list for the message  pointed to by the attr field  for an  attribute named addr  which is the address following the file name in the plumbed message  To  do so  it calls plumblookup  giving the attr list and the name of the desired attribute  The  working directory for the message  the data  and the address attribute   s value are printed next  At  last  the message data structure is deallocated by a call to plumbfree     We can deliver messages to our program by doing clicks on Acme  with the mouse button 3   and also by running plumb from the shell like we do below       plumb  NOTICE 2     plumb edits c     plumb  sys doc 9 9 ps    plumb edits c  main    The corresponding output for our program  which we did run at a different window  follows  Note  how the message for 9 ps was not sent to the edit port  and therefore is not received by our  program  It was sent to a different program  page  to display the postscript file         edits   msg  wdir     usr nemo 9intro    data     NOTICE    addr   2      msg  wdir     usr nemo 9intro    data      usr nemo 9intro edits c    addr          msg  wdir     usr nemo 9intro    data     usr nemo 9intro edits c    addr      main          One last question  Which format is used to actually write and read messages from the file that is  the plumb port  Is it a esoteric format  No  It is simp
527. s  one after another  If the  data structure msg is consulted a lot  the whole program will be very slow due to delays caused  by the use of a QLock to protect the data  While a panel process is writing to the panel  no other  panel process will be able to even touch the message  We can improve things a little bit by writ   ing to the panel outside of the critical region  By doing so  other panel processes will be allowed  to gain the lock and consult the message as well    void   panelproc int fd         ulong lastvers    1   char  text   do    text   nil   glock   amp   msg 1ck    if msg text    nil  amp  amp  lastvers    msg vers     text   strdup msg text    lastvers   msg vers        gunlock    msg 1ck    if  text    nil     write fd  text  strlen text     free  text       sleep 5   1000      while   exiting    forint  2   panel exiting n     exits  nil           Here  we moved the write outside of the critical region  Because the panel itself  i e   its file  is  not being shared in our program  we do not need to protect from races while writing it  We cre   ated one process for each panel and that was nice     But we can do much better  Are there races when multiple processes are just reading a data  structure  While nobody is changing anything  there are no races  During a long time  all the  panel processes will be polling msg  reading its memory  and the input process will be just  blocked waiting for a line  It would be nice to let all the panel processes to access
528. s  you do not have to worry about  this     A variant of rwakeup  called rwakeupall1  wakes up all the processes sleeping waiting  for the condition to hold  Although many processes may be awaken  they will re acquire the lock  before returning from rsleep  Therefore  only one process is using the resource at a time and  we still have mutual exclusion for the critical region     The data structure Rendez represents the rendezvous point where processes sleeping and  processes waking up meet  You can think of it as a data structure representing the condition that  makes one process go to sleep     typedef  struct Rendez       QLock ca      Rendez     The field 1 must point to the QLock protecting the resource  used also to protect the Rendez    Using this abstraction  and its operations       sig rsleep rwakeup rwakeupall  void rsleep  Rendez  r   int rwakeup  Rendez  r   int rwakeupall  Rendez  r     we can reimplement our airport panels program  We start by redefining our data structure and  providing two operations for using it       250      typedef struct Msg Msg   struct Msg            void  char        QLock lck     to protect the other fields from races  Rendez newmsg     to sleep waiting for a new message   char  text     for the message    wmsg  Msg  m  char  newtext    rmsg  Msg  m      The operation wmsg writes a new the text for the message  The operation rmsg reads a new text  for the message  The idea is that a call to rmsg will always sleep until the message cha
529. s a handler that prints the  note received and pretends that it was not attended  returning zero        119         pnote c     include  lt u h gt      include  lt libc h gt     int  handler  void   char  msg      print   note   s n   msg      return 0     void  main int  char         atnotify handler  1    sleep  3600   1000      one hour to play  print   done   r  n     exits nil           If we run the program  and press Delete while it is running  this is what happens       8 pnote  the program runs until we press Delete  And then       Delete  note  interrupt    echo Sstatus  8 pnote 1543  interrupt    r    The program is killed  because it did not handle the note  When we pressed Delete  the program  was executing whatever code it had to execute  In this case  it was blocked waiting inside sleep  for time to pass by  The note caused the system call to be interrupted  and the process jumped to  execute its handler where it printed its message  Because no handler recognized the note  the pro   cess was killed     Notes are asynchronous  and this means that the handler for a note may run at any time   when it pleases Plan 9 to instruct your process to stop what it was doing and jump into the note  handler  This is similar to the model used for interrupts  which is quite different from the process  model  One single continuous flow of control  easy to understand     We are now going to modify the handler to return true  and not zero  This is what the new  program does      
530. s along with their IP addresses  Suppose all  addresses are of the form  121 128 1 X  Write a script to edit the file and change all the  addresses to be of the form 212 123 2 X     Write a script to generate a template for a  lib ndb local  for machines named  alphaN  where N must correspond to the last number in the machine address        Write a script to locate in  sys src the programs using the system call pipe  How  many programs are using it  Do dot do anything by hand     In many programs  errors are declared as strings  Write a script that takes an error message  list and generates both an array containing the message strings and an enumeration to refer  to entries in the array     Hint  Define a common format for messages to simplify your task     Write a script to copy just C source files below a given directory to Shome source    How many source files do you have  Again  do not do anything by hand     Write a better version for the file script developed in this chapter  Use some of the com   mands you know to inspect file contents to try to determine the type of file for each argu   ment of the script       201      9     More tools    9 1  Regular expressions  We have used sed to replace one string with another  But  what happens here       echo foo xcc   sed    s  cc  c g     foo  c    echo focca x   sed    s  cc  c g     f ca x    We need to learn more     In addresses of the form  text  and in commands like s text other   the string  text is not a string for s
531. s are done after the first semesters  they can be used forever     And what happens when the bureaucrats change the format for the input list  You just have  to tweak a little bit Listusers  and it all will work  If this happens often  it might pay to put  listusers into a separate script so that you do not need to edit all the scripts using it     9 6  File systems    There are many other tools available  Perhaps surprisingly  or not   they are just file servers  As  we saw  a file server is just a process serving files  In Plan 9  a file server serves a file tree to pro   vide some service  The tree is implemented by a particular data organization  perhaps just kept in  the memory of the file server process  This data organization used to serve files is known as a file  system  Before reading this book  you might think that a file system is just some way to organize  files in a disk  Now you know that it does not need to be the case  In many cases  the program  that understands  e g   serves  a particular file system is also called a file system  perhaps confus   ingly  But that is just to avoid saying    the file server program that understands the file system          All device drivers  listed in section 3 of the manual  provide their interface through the file  tree they serve  Many device drivers correspond to real  hardware  devices  Others provide a par   ticular service  implemented with just software  But in any case  as you saw before  it is a matter  of knowing w
532. s how they report errors  They  can fail because it can be that the file cannot really be written  e g   because the disk is full   but  you will only know when you try to write the file  which does not necessarily happen in Bwrite        How will our new program behave  now that it uses buffered input output  Let   s try it     time 8 bcp  tmp sfile  tmp dfile    ott     00u 0 03s 0 38r 8 bcp  tmp sfile  tmp dfile    time 8 out  b 1  tmp sfile  tmp dfile  0 00u 0 13s 0 31r 8 bcp  b 1  tmp sfile  tmp dfile    time 8 out  b 80  tmp sfile  tmp dfile  0 00u 0 02s 0 20r 8 bcp  b 80  tmp sfile  tmp dfile    Always the same   Well  not exactly the same because there is always some uncertainty in every  measurement  In this case  give or take 2 10th of a second  But in any case  reading one byte at a  time is far from taking 12 6 minutes  Bio took care of using a reasonable buffer size  and calling  read only when necessary  as we did by ourselves when using 8Kbyte buffers     One word of caution  After calling write  it is very likely that our bytes are already in the  file  because there is probably no buffering between your program and the actual file  However   after a call to Bwrite it is almost for sure that your bytes are not in the file  They will be sitting  in the Biobuf  waiting for more bytes to be written  until a moment when it seems reasonable  for a Bio routine to do the actual call to write  This can happen either when you fill the buffer   or when you call Bterm  w
533. s job  It accepts  a string containing a shell command line as a parameter  and executes it in a child process  It  returns a file descriptor to write to a pipe that leads to the standard input of this process       113      pipeto c   include  lt u h gt      include  lt libc h gt     int  pipeto char  cmd      int fd 2      pipe  fd    switch  fork       case  1   return  1   case 0   close fd 1     dup  fd 0   0    close  fd 0     execl    bin re    re     c   cmd  nil    sysfatal  execl     default   close  fd 0     return fd 1      void  main int  char         int fd  iy  char  msgs         warning  the world is over n     Spam  earn money real fast  n       warning  it was not true n        fd   pipeto  grep warning     if     fd   lt   0   sysfatal  pipeto   r     for  i   0  i  lt  nelem msgs   i     write  fd  msgs i   strlen msgs i      close  fd    exits  nil           To see a complete example  where this function is used  the main function uses pipeto to send  several messages to the input of a process running grep warning  Messages are sent by writ   ing the the file descriptor returned from pipeto  When nothing more has to be sent  the file  descriptor is closed  The child process will receive an end of file indication as soon as it     114     consumes what may still be going through the pipe  This is the output for the program       8 pipeto    warning  the world is over  warning  it was not true    Because the parent process finishes before the child is still
534. s not cook the characters at all  It gives them to  the process reading from the console  as they arrive from the keyboard     The file  dev consct1 can be used to activate and de activate the raw mode  A write of  the string rawon into such file puts the console in raw mode  until the file is closed or the string  rawoff is written  The next program echoes what it can read from the console  But it puts the      291      console in raw mode when called with  r   raw c   include  lt u h gt      include  lt libc h gt        void   usage  void         s   r  n      fprint  2   usage     exits   usage             argv0      OWRIT        GI    void  main int argc  char argv        char buf  512    int raw   0   int Cid S s 1   int nr   ARGBEGIN   case  r    fawtt   break   default   usage      ARGEND   if  argc    0   usage     if  raw     cfd   open   dev consctl    write cfd   rawon   5       for        nr   read 0  buf  sizeof  buf  1    if  nr  lt   0   break   buf nr    0   print     s  n   buf         if  raw    close  cfd    exits  nil           This is what happens when we run it using the console   s cooked mode and its raw mode       8 raw  hi    hi       Delete    r      292        the program reads   n      oJ  the program reads  Del    uJ If we type  Esc   the program reads  Esc     There are some things to note  First  in cooked mode we can see the characters we type as we type  them  We could type hi  and its characters were echoed to the screen by the console  The 
535. s the projectdir environment variable   lcopy       bin re  projectdir  sys src planb  echo cp    ch  S projectdir cmd    echo cp   ms Sprojectdir docs    Look what happens     7 COPY    lc  env projectdir  projectdir    After executing copy  the environment variable is not yet known to our shell  The reason is that  the shell caches environment variables  Starting a new shell shows that indeed  the variable  projectdir is in our environment  This is also seen by listing  env  The file representing the      158      variable is defined there       echo Sprojectdir    ae ao     echo Sprojectdir   sys sxrc planb    How can we avoid polluting the set of environment variables for the parent shell  By asking in  the script for our own copy of the parent process    environment  This  in a C program  would be  done calling rfork  RFENVG   In the shell  we can run the command       rfork e    that achieves the same effect  The command is a builtin  understood and executed by rc itself  it  is very sensible to start most scripts doing this        bin re  rfork ne    This creates a copy of the environment variables table  e  and the name space  n  for the process  executing the request  Because it is a copy  any change does not affect the parent  When the shell  interpreting the script dies  the copy is disposed     7 4  Independent children    All the programs we have done  that create a child process and do not wait for it  are wrong  They  did not fail  but they were not too nice wi
536. s you write very compact mk files  for compiling your programs  But there is    even more help  We can include files in the mkfile  by using a  lt  character  And we can use  variables to determine which files to include  Look at the following file     mkfile   lt   objtype mkfile  OFILES semfs  O sem  O       SO semfs  SOFILES  SLD  o  target Sprereq           O    c sem h  SCC  FVw Sstem c    It includes  386 mkfile when Sobjtype is 386  That is our case  The file  386 mkfile      353      defines  CC   LD  and other variables to compile for that architecture  Now  changing the value  of objtype changes all the tools used to compile  because we would be including definitions for  the new architecture  For example       objtype arm mk  5c  FVw sem c  51  o 5 semfs semfs 5 sem 5       r    This way  it is very easy to cross compile  And that was not all  There are several mk files that  can be included to define appropriate targets for compiling a single program and for compiling  multiple ones  one per source file   What follows is once more our mkfile     mkfile     lt   objtype mkfile       OFILES semfs  O sem  O  HFITLES sem h  TARG SO semfs  BIN Shome bin Sobjtype        lt  sys src cmd mkone          The file mkone defiles targets for building our program  It assumes that the variable OF TILES list  the object files that are part of the program  Also  it assumes that the variable HF ILES list the  headers  which are dependencies for all the objects   Each object is assu
537. scape from the  special meaning that other characters have  e g   to escape from the character that starts a new  line     We can create a file by using acme  as you know  To create an empty file  we can use  touch  and then 1c to see our outcome       touch hello  zbe  bin hello lib tmp    r    The 1c command was not necessary  of course  But that lets you see the outcome of executing  touch  In the following examples  we will be doing the same to show what happens after exe   cuting other commands     Here  we gave an argument to the touch command  hello  Like functions in C  com   mands accept arguments to give    parameters    to them  Command arguments are just strings   When you type a command line  the shell breaks it into words separated by white space  spaces  and tabs   The first word identifies the command  and the following ones are the arguments     We can ask 1s to give a lot of information about hello  But first  lets list just that file   As you see  1s lists the files you give as arguments  Only if you don   t supply a file name  all files  are listed       ds hello  hello    r    We can see the size of the file we created giving an option to 1s  An option is an argument that  is used to change the default behavior of the command  Some options specify certain flags to  adjust what the command does  Options that specify flags always start with a dash sign             The  option  s of 1s can be used to print the size along with the file name       1s  s hello 
538. se we still want to protect from notes  we must get a new note group as well     The program  shown next  produces the same output  and convinces the shell that it should  read another line immediately after we start       8 noterfork    0 1 2 Delete  ee OAS     Because the shell is reading a command line  when we type Delete  it understands that we want to  interrupt what we typed and prints another prompt  but our fake httpd program is still alive  The  RENOTEG flag applies to our child process  because we said RFPROC as well          157      httpd c     include  lt u h gt    include  lt libc h gt     void  main int  char           int BB    switch  rfork  RFPROC RFNOTEG            case 0   for i   0  i  lt  5  itt       Isn t this a nice http  sleep  1000      implementation   print    d    i       print    n     exits  nil    case  1l   sysfatal  rfork  Sr     default     break          exits  nil      7 3  Environment in shell scripts    Environment variables are shared by default  This means that if we change any environment vari   able  our parent and other sibling process sharing the environment variables will be able to see  our change    Shell scripts are executed by a child shell process  and this applies to them as well  when  you define a variable in a shell script  the change remains in the environment variable table after  the script has died  For example  this script copies some source and documentation files to sev   eral directories for a project  It define
539. see a file tree with same aspect     Binding  n rio  before other files  at  dev will make any new process in our window to  use not this window  but the new one that we have created  So  these commands      bind  b  n rio  dev    Stats    cause stats to use the new window instead of the one we had  like shown in figure 12 4  For  stats  using the screen  mouse  and keyboard is just a matter of opening files at  dev  It does  not really care about where do the files come from  Regarding  dev draw  that device multi   plexes by its own means among multiple processes  each one keeps a separate connection to the  device  as we saw   The other files are provided by rio     Hitting Delete in the new window will not kill stats  The window system does not know  where to post the interrupt note for that window  To interrupt the program  we must hit Delete in  the old window  where the command was running  This can be fixed  Unmounting the files for      315        bind  b  nf rio  dev    stats       Figure 12 4  Binding the files for the new window at  dev makes stats use it   the new rio window will destroy it  nobody would be using it      7 unmount  n rio  dev  unmount  n rio and the window goes away    And now we mount rio again  creating another window   This time  we use the option  pid  within the attach specifier to let rio know that notes for this window should go the process  group for the process with pid  pid  That is  to our shell  Afterwards  we start stats like  before
540. served      xd  c afile    0000000 h e 1 1 o n t h e r e n 2 0 0  0000010 2 w w    o    hn O E T Ae  Ge ha n 1  0000020 o g i e s Ion      n A 1 1 R  0000030 ae  oo he t S R es erv e d n  000003f    After the first call to write  the file offset was 6  Therefore  the second write happen starting at  offset 6 in the file  And it wrote six more bytes  Once more  it did just it job  write bytes  The file  length is the same  The number of lines changed because the number of newline characters in the  file changed  The console advances one line each time it encounters a newline  but it is just a sin   gle byte     Figure 3 3 shows the elements involved in writing this file  after the first call to write  and  before the second call  The file descriptor  which we assume was 3  points to a data structure con   taining information about the open file  This data structure keeps the file offset  to be used for the  following read or write operation  and record what the file was open for  e g   OWRITE  Plan  9 calls this data structure a Chan  Channel   and there is one per file in use in the system  Besides               62     the offset and the open mode  it contains all the information needed to let the kernel reach the file  server and perform operations on the file  Indeed  a Chan is just something used by Plan 9 to  speak to a server regarding a file  This may require doing remote procedure calls across the net   work  but that is up to your kernel  and you can forget     File d
541. sleeping trying to get something  because the buffer was  empty  This function  which changes that condition  is responsible for waking up one of such pro   cesses  It wakes up just one  because there is only one thing to get from the buffer  If there are  more processes sleeping  trying to get  they will be waken up as more messages are added by fur   ther calls to put in the future     The function get is the counterpart for put  When there is no message to get  it sleeps at  isempty  Once we know for sure that there is at least one message to consume  it is removed  from the head of the queue and returned to the caller     char     get  Buffer  b               char  msg     glock   amp b  gt 1ck    if  b  gt nmsgs    0    rsleep   amp b  gt isempty     msg   b  gt msgs b  gt hd      b  gt hd   b  gt hd   Nmsgs   b  gt nmsgs     if  b  gt nmsgs    Nmsgs   1     rwakeup   amp b  gt isfull    gqunlock   amp b  gt 1ck    return msg     Note how get is also responsible for awakening one process  that might be sleeping  when the  buffer is no longer full  Both functions are quite symmetric  One puts items in the buffer  and  requires empty slots   the other puts empty slots in the buffer  and requires items      The data structure is initialized by calling init     void    init  Buffer  b                  release all locks  set everything to null values   memset  b  0  sizeof  b         set the locks used by the Rendezes   b  gt isempty 1l    amp b  gt 1ck    b  gt isfull 1l    
542. so known as the environment group  Like before  You can ask  for a copy  or for sharing with the child when creating a process  or for a new set of environ   ment variables with no variable defined on it        The name space  Utterly important  and central to Plan 9  We have been ignoring this until  now  This is the resource that maps file names to files  We study it in this chapter        The working directory and the root directory  used to walk the file tree for relative and  absolute paths        The memory segments  You can ask for sharing the data with the child  when creating a  process  or to make a copy for the child  The text  or code  is always shared  It is read only   and it would be a waste to copy memory that is going to remain the same  The stack is never  shared  because each process has its own flow of control and needs its own stack        The note group  You can ask for sharing it with the child  when creating a process  or to  obtain your own group to be isolated from others        The rendezvous group  A resource used to make groups of processes that can use the  rendezvous system call to coordinate among them  This is yet to be seen     Besides the requests mentioned above  there are several other things that rfork can do  that we  will be seen in this chapter along with them     Before proceeding  we are going to do a fork  but ina slightly different way       154     rforkls c     include  lt u h gt      include  lt libc h gt     void  main int  cha
543. software that provides convenient abstrac   tions to write programs without dealing with the underlying hardware by ourselves  To do so  it  has to manage the different resources to assign them to different programs and to protect ones  from others  In any case  the operating system is just a set of programs  nothing else     1 2  Entering the system    In this course you will be using Plan 9 from Bell Labs  There is a nice paper that describes the  entire system in a few pages  2   All the programs shown in this book are written for this operat   ing system  Before proceeding  you need to know how to enter the system  edit files and run  commands  This will be necessary for the rest of this book  One word of caution  if you know  UNIX  Plan 9 is not UNIX  you should forget what you assume about UNIX while using this sys   tem     In a Plan 9 system  you use a terminal to perform your tasks  The terminal is a machine  that lets you execute commands by using the screen  mouse  and keyboard as input output  devices  See figure 1 1  A command is simply some text you type to ask for something  Most  likely  you will be using a PC as your terminal  The window system  the program that imple   ments and draws the windows you see in the screen  runs at your terminal  The commands you  execute  which are also programs  run at your terminal  Editing happens at your terminal  How   ever  none of the files you are using are stored at your terminal  Your terminal   s disk is not used  at 
544. ss to receive a message from the other  end  and give it to it  the process obeys  In the same way  a server process relies messages to and  from its own factotum to authenticate clients              network  connection    client server       network server  connection          Figure 14 1  A process relies messages to and from its factotum to authenticate     The protocol is only understood by the factotum  So  if both the client and the server have a  factotum  it is both factotums the ones speaking the authentication protocol  The only peculiarity  is that messages exchanged for authentication between both factotums pass through the client and  the server processes  which behave just as relies  As the figure shows  different servers might  have different factotums  The same happens for clients  And of course  more than one process  may use the same factotum  Which factotum is used is determined by which factotum is mounted  at  mnt factotum     For example  executing a new factotum mounts another factotum at  mnt factotum   isolating the processes that from now on try to authenticate in our name space       auth factotum    cat  mnt factotum ctl  A This one has no keys     There is another important thing to note  A process may use a factotum even if the other peer does  not  For example  the server shown below in the figure does not use a factotum and is implement   ing the authentication protocol on its own  As long as a process speaks properly the necessary  authenticat
545. ss used to implement the various threads     We have seem that threadexits must be used instead of exits  because of the obvious  reason  This case was clear  A less clear one may be proccreate  which we used instead of  calling rfork or fork  The thread library knows about the processes it creates  It tries hard to  supply the same interface for both threads and processes  so that all its operations work in the  same way for both entities  Indeed  proccreate creates a single thread in a new process  Thus   you might say that all operations from the library work just on threads  In any case  using rfork  to operate on the resources for your process is safe  For example  to make a copy of environment  variables  put the process in a new note group  etc     In a similar way  procexec  or procexecl  should be used instead of exec  or  execl   A call to exec would replace the program for the process  making void all the threads  that might running on it  But a call to procexec works nicely when using processes and  threads  Of course  it only makes sense to call procexec when there is a single thread in the  process making the call  Otherwise  what would happen to the other threads  Their code and data  would be gone     In most cases  there is no need to call wait to wait for other processes  The processes you  create can synchronize with the rest of your program using channels  if you need to convey a  completion status or something else  That is not the case when using procexe
546. ssages that may arrive out of order and may even get lost in the way  Each such  message is called a datagram  which is the abstraction provided by this kind of transport  In the  Internet  the datagram service is usually UDP  The IP device driver in Plan 9 provides an interface  for using UDP  similar to the ones we saw for other protocols and network devices       lc  net udp  0 aE clone stats    Other transports use the ability to send individual messages to build a more convenient abstrac   tion for maintaining dialogs  similar to a pipe  This abstraction is called a connection  It is simi   lar to a pipe  but differs from it in that it can go from one port at one machine to another port at a  different machine in the network  This type of communication is similar to a phone call  Each end  has an address  a phone number   they must establish a connection  dial a number  pickup the  phone   then they can speak to each other  and finally  they hangup  The analogy cannot be  pushed too far  for example  a connection may be established if both ends call each other  which  would not be feasible when making a phone call  But you get the idea  In the Internet  the most  popular protocol that provides connections is TCP  it provides them using IP as the underlying  transport protocol  hence the name TCP IP for this suite of protocols   The IP device driver in  Plan 9 provides the interface for using TCP  It has the now familiar file interface for using a net   work in Plan 9    
547. st   The flag  u  unique  must be added as well  because the same user could own files in both file  trees  and we want each name to be listed once       fn Irusers   Ir  1   sed    s    a z0 9       1       sort      sort  mu  lt  lrusers  n fs1   lt  lrusers  n fs2    esoriano   nemo   none   paurea    r    For sort  each  lt       construct is just a file name  as we saw   This is a simple way to let us use  two pipes as the input for a single process     To do something different  we can revisit the first example in the last chapter  finding func   tion definitions  This script does just that  if we follow the style convention for declaring func   tions that was shown at the beginning of this chapter  First  we try to use grep to print just the  source line where the function cat is defined in the file  sys src cmd cat c  Our first try  is this       209        grep cat  sys src cmd cat c  cat  int f  char  s   argv0    cat    cat 0    lt stdin gt      cat  f  argv i       Which is not too helpful  All the lines contain the string cat  but we want only the lines where  cat is at the beginning of line  followed by an open parenthesis  Second attempt       grep     cat       sys src cmd cat c  cat  int f  char  s     At least  this prints just the line of interest to us  However  it is useful to get the file name and line  number before the text in the line  That output can be used to point an editor to that particular file  and line number  Because grep prints the file nam
548. stage  This leads to another  prompt  asking you to introduce your user name     You may obtain a user name by asking the administrator of the Plan 9 system to provide  one for you  along with a password that you will have to specify   This is called opening an  account  In this example we will type nemo as the user name  What follows is the dialog with  the machine to enter the system     user none   nemo   time   version         Adding key  dom dat escet urjc es proto p9skl  user nemo   Return    password  type your password here and press return    This dialog shows all conventions used in this book  Text written by the computer  the system  a  program       is in constant width font  like in user none   Text you type is in a slightly  slanted variant of the same font  like in nemo  When the text you type is a special key not shown  in the screen  we use boldface  like in Return  Any comment we make is in italics  like in type  your password  Now we can go back to how do we enter the system     At the user prompt  you told your terminal who you are  Your terminal trusts you  There   fore  there is no need to give it a password  At this point you have an open account at your termi   nal  This is to say that you now have a program running on your name in the computer  By the  way  entering the system is also called loging into the system  Leaving the system is called usu   ally loging out    However  the file server needs some proof to get convinced that you are who you say 
549. sult  However  adir a is still an empty file  Because we bound other after  using  the  a flag for bind  the name a is found in the old adir  which is before the file with the same  name in other  Therefore  although we see twice a  we can only use the one that is first found       rm adir a  le adir  G x    de other  a x    Y    Removing adir a removes the file a from the original adir  But there is another file at  other named a  and we still see that name  Because we bound other into adir  after what it  previously had  the remove system call finds first the name adir a at the old adir  and that  is the one removed     What happens to our name space  How can it be what we saw above  The answer is that  you can bind  or mount  more than one file for the same mount point  The mount table entry      169      added by the bind we made in this section is shown in figure 7 7              Chan for Chan for Chan for  adir adir other                               Figure 7 7  A union mount  The mount entry after bind  a other adir     This entry has a mount point  adir  When that file is reached  the name space jumps and  continues walking at the mounted file  However  here we have two mounted files for this entry   When we bound other after what was initially at adir  Plan 9 added adir as a file mounted  here  and then other was linked after as another mounted file  This can be seen if you use ns to  look for entries referring to adir       ns   grep adir  bind  tmp adir  tmp adir 
550. sword to  let you use it  Thus  any person that gets the laptop may power it up and use it  However  you do  not have to type a password to use it  which is more convenient  If  on the contrary  your laptop  requires a password to be used  typing the password would be an inconvenience  Nevertheless   you might think that this makes the laptop more secure because it requires to know a password  just to use it     By the way  this is not true because as long as a malicious person has your laptop in his or  her hands  the laptop will be broken into and the only question is how much time and effort it will  require to do so  So  using a password to protect the laptop would be given a false feeling that the  system is secure  Furthermore  although it is common for laptops that might be used on its own   terminals in Plan 9 are not supposed to have local storage nor any other local resource to protect   A Plan 9 terminal is just a machine to connect to the rest of services in the network     What does security mean  It depends  For example  the dump in the file server protects  your files from accidental removals or other errors  At least  it protects them in the sense that you  may still access a copy of the entire file tree  as it was yesterday  even if you loose today   s files   Furthermore  because old files kept in disk will never be overwritten by the file server once they  are in the dump  it is very unlikely that a bug or a software problem will corrupt them  The dump   li
551. t   char  Srv   srv   nil   mnt     mnt sem    ARGBEGIN   case  D    chatty9ptt    break   case  s    srv   EARGF  usage      break   case  m      mnt   EARGF  usage      break   default   usage       ARGEND          if argc   0    usage     threadpostmountsrv  amp sfs   threadexits  nil            EATE             srv  mnt  MREPL MCR    The call to threadpostmountsrv starts a process  containing a single thread  to serve 9P      336      requests  and dispatches to functions linked at s fs  which attend the different requests  This pro   gram mounts itself  i e   the file tree served by the child process  at  mnt   sem  but accepts the  conventional option  m to specify a different mount point  In the same way  the option  s can be  used to specify a file in  srv where to post a pipe to mount the file server  To aid the debugging  process  the flag  D increments the global flag chatty 9p  defined by 1ib9p  When this global  is non zero  the library prints 9P messages as they are exchanged with the client  Like we saw for  ramfs     13 5  9P requests    The first function we are going to implement is fstattach  This particular function  attends Tattach messages  Its implementation introduces several important data structures pro   vided and used by 1ib9p     static void  fsattach Req  r      r  gt fid  gt qid    Qid  0 0 QTDIR    r  gt ofcall qid   r  gt fid  gt qid   respond r  nil           Like all other functions for 9P messages  fst attach receives a pointer to a Req  aC
552. t   users    fn sigint   rm Susers     fn sighup   rm  f Susers      fn listusers    awk      F     7            next    FASZ   next     3    Operating Systems   amp  amp   4    B    print  2    la s     fn unamel    echo      sed  s       I           1 2      fn uname2    echo      sed       s                   1 2      fn add    if  grep  s             S1        Susers   status exist  TE mote    echo  1  1  1   gt  gt Susers  echo adduser       status         listusers      tr A Z a z   tr     a  idtnh          aeioun        while  name   read      add     unamel Sname  Sname      add     uname2 Sname  Sname        echo         cannot determine user name for  name       rm  f Susers  exit      We have defined several functions  instead of merging it all in a single  huge  command line  The  listusers function is our starting point  It encapsulates nicely the AWK program to list just      223      the student names for our course and group  The script arguments are given to the function  which  passes them to AWK  The next couple of commands are our translations to use only lower case  ascii characters for user names     The functions unamel and uname2 encapsulate our two methods for generating a user  name  They receive the full student name and print the proposed user name  But we may need to  try both if the first one yields an existing user name  What we do is to read one line at a time the  output from    listusers      tr A Z a z   tr      a  id  6un          aeioun   
553. t  know who is trying to do something  before deciding if that action is allowed or not  In Plan 9   the user who switched on the machine is called the machine owner and allowed to do anything to  the machine  This applies not just for terminals  but for any other Plan 9 machine as well     The console device  cons 3   provides several files that identify both the machine and its  owner  The file  dev hostowner names the user who owns the machine  and   dev sysname names the machine itself       cat  dev hostowner  nemo      cat  dev sysname  nautilus     It may be a surprise  but the machine name is irrelevant for security purposes  Only the host  owner is relevant  This terminal trusts that the user who owns it is nemo  only because one user  typed nemo when asked for the user name during the booting of the machine  That is all that mat   ters for this machine  Initially  Plan 9 created a boot process  described in boot 8   Besides doing  other things  it asked for a user name and wrote  dev hostowner  But note that in our exam   ple it might happen that the user was not actually nemo  For the local machine  it does not mat   ter     Deciding who is able to do what is called authorization  Authorization for the host owner  is automatic  The kernel is programmed so that the machine owner is authorized to do many  things  For example  ownership of console and other devices is given to the host owner       ps   sed 4q       nemo 1 0 00 0 00 1276K Await bns   nemo 2 0 58 0 00 O
554. t a CPU server        The AuthInfo structure contains two fields  nsecret and secret with a shared secret  provided from the authentication server to both the client and the server  This shared secret could  be used to encrypt and secure the communication channel  before exchanging data between the  client and the server process  We did not show how to do this  but that is why you have manual  pages  which contain examples     The   t s 3  devices provides transparent encryption for network connections  It was not dis   cussed here  But it is important to exchange data with servers or clients requiring TLS to secure  their connections     Libraries functions  like those described in encrypt 2   provide facilities to encrypt and  decrypt data  These ones in particular use the DES encryption algorithm     You have gone a long way  It is likely that you have found many different and new concepts  while reading this book  What remains is to practice  and use them  Hopefully  now that you      376      understand what an operating system is  and how its abstractions  calls  and commands help you  use the machine  you will not be scared of reading the reference manual that is usually contained  along with each operating system  Good luck     Problems  1 Use Plan 9 to do things you know how to do with other systems   2 Optimize answers to the previous question      377      References   1  A  S  Tanembaum  Operating Systems Design and Implementation  Prentice Hall  Inc    Englewood 
555. t calls the helper function authread  provided by 1ib9p  to handle reads from authentication  files  i e   to obtain data from the underlying factotum to be sent to the client   In the same way   fswrite must include      369      if  q type amp QTAUTH     authwrite r    return          to take a different course of action for writes to authentication files  The library function  authwrite takes care of writes for such files        Fids for authentication files keep state to talk to the underlying factotum  The function  authdest roy must be called for fids that refer to authentication files  This means that we must  change the function freefid  which we used to release the semaphore structure for a fid  to  release resources for authentication fids              static void  freefid Fid  fid        Sem  Ss     if  fid  gt qid type amp QTAUTH   authdestroy  fid    else    s   fid  gt aux   fid  gt aux   nil   closesem  s           The purpose of the entire authentication process is to demonstrate in the Tattach request that  the user was who he she claimed to be  So  fst attach must be changed as well  The library  function authattach makes sure that the user is authenticated  When it returns    1  to signal a  failure  it has already responded with an error to the caller  and the server should not respond   Otherwise  the user has been authenticated     static void  fsattach Req  r      if  authattach r   lt  0   return   r  gt fid  gt gqid    Qid  0 0 QTDIR    r  gt ofcall q
556. t is that it is a bad idea to mix spaces  and tabs to indent code or tabulate data  Depending on the editor  a single tab may displace the           18     following text 8  4  2  or any other number of characters  it depends on where the editor considers  the tab stop to be      The point is that characters like  n   r  and  t are control characters  with special mean   ing  just because there are programs that use them to represent actions and not to represent literal  text  Table 1 1 shows some usual control characters and their meaning        Byte value Character Keyboard Description   04 control d end of transmission  EOT   08  b Backspace remove previous character  09  t Tab horizontal tabulation   Oa  n line feed   Od  r Return carriage return   1b Esc escape       Table 1 1  Some control characters understood by most systems and programs     The table shows the usual escape syntax  a backslash and a character  used by most pro   grams to represent control characters  including the C compiler   and how to generate the charac   ters using the keyboard  Not all the control characters are shown and not all the cells in the table  contain information  We included just what you should know to avoid discomfort while using the  system     To summarize  files contain just data that has no meaning per se  Only programs and users  give meaning to data  This is what you could see here     1 9  Permissions    Each file in Plan 9 can be secured to provide some privacy and restrict 
557. t starting with    these paths are walked in  the tree relative to its current directory  For example  the shell we have been using in the previ   ous examples had  usr nemo as its current directory  Therefore  all file names we used were  relative to  usr nemo  This means that when we used goodbye  we were actually referring to  the file  usr nemo goodbye  Such paths are called relative paths  By the way  paths start   ing with a slash  i e   from the root directory  are called absolute paths      14     Another important directory is  usr nemo  it is called the home directory for the user  Nemo  The reason for this name is that Nemo   s files are kept within that directory  and because  the shell started by the system when Nemo logs in  the one that usually runs the window system    is using that directory initially as its current directory  That is the reason why all the  shells run   ning at  windows we open in rio have  usr nemo as their initial current directory  What fol   lows is a simple way to know which users have accounts in the system       le  usr    esoriano glenda nemo mero paurea  There is an special file name for the current directory  a single dot         Therefore  we can do two  things to list the current directory in a shell   er hE   bin lib tmp   y he   bin lib tmp    r    Note the dot given as the file to list to the second command  When 1s or lc are not given a  directory name to list  they list the current directory  Therefore  both commands print t
558. t the atten   tion of their drivers  Thus  while your program is executing  a device might interrupt the proces   sor  The hardware saves some state  registers mostly  and the operating system starts executing to  attend the interrupt  Many times  when the interrupt has been serviced  the operating system will  return from the interruption and your code would be running again     You can think that the kernel is a library but not just for your programs  also for things  needed to operate the hardware  You make system calls to ask the system to do things  The hard   ware issues interrupts for that purpose  And most of the time  the system is idle sitting in mem   ory  until some one makes a call     Problems    1 Open a system shell  execute ip ping to determine if all of the machines at the network  213 128 4 0 are alive or not  To do this  you have to run these 254 commands       ip ping  n 1 213 128 4 1    ip ping  n 1 213 128 4 2    ip ping  n 1 213 128 4 254  The option  n with argument 1 tells ping to send just one probe and not 64  which would  be its default   2 Do the same using this shell command line       for  m in     seq 1 254     ip ping 213 128 4 Sm         This line is not black magic  You are quite capable of doing things like this  provided you  pass this course    3 Start the system shell in all the operating systems where you have accounts  If you know of  a machine running an unknown system where you do not have an account  ask for one and  try to complet
559. t the price of some danger        import  c firewall  net alt  net    Problems  1 Add the line    rfork  RFNAMEG          to the program whale  before doing the calls to amount  and see what happens when you    NN FW WN      177      execute it  Explain    Enumerate the file servers available at your local Plan 9 site    Print down the name space used by the plumber in your session   Reproduce your name space at a different machine    Make your system believe that it has an extra CD unit installed  Use it   Put any server you have implemented in a sand box  Try to break it       178        179      8     Using the Shell    8 1  Programs are tools    In Plan 9  programs are tools that can be combined to perform very complex tasks  In most other  systems  the same applies  although it tends to be a little more complex  The idea is inherited  from UNIX  each program is meant to perform a single task  and perform it well     But that does not prevent you to combine existing programs to do a wide variety of things   In general  when there is a new job to be done  these are your options  listed from the easiest one  to the hardest one     1 Find a program that does the job  It is utterly important to look at the manual before doing  anything  In many cases  there will be a program that does what we want to do  This also  applies when programming in C  there are many functions in the library that may greatly  simplify your programs    2 Combine some programs to achieve the desired e
560. t to allow  both read and write operations on it  but you cannot execute instructions on it  The memory  is initialized by the system using the initialized data kept within the binary file for the pro   gram        The uninitialized data segment  called bss segment is almost like the data segment  How   ever  this one is initialized by zeroing its memory  The name of the segment comes from an  arcane instruction used to implement it on a machine that no longer exists  How much  memory is given depends on the size recorded in the binary file  Moreover  this segment can  grow  by using a system call that allocates more memory for it  Function libraries like  malloc cause this segment to grow when they consume all the available memory in this  segment  This is the reason for the gap between this segment and the stack segment  shown  in figure 2 3   to leave room for the segment to grow        The stack segment is also used for reading and writing memory  Unlike other segments   this segment seems to grow automatically when more space is used  It is used to keep the  stack for the process     All this is important to know because it has a significant impact on your programs and processes   Usually  not all the code is loaded at once from the binary file into the text  memory  segment   Binaries are copied into memory one virtual memory page at a time as demanded by references to  memory addresses  This is called demand paging   or loading on demand   It is important to  know this
561. t urjc es  gt     lt  head gt     lt body BGCOLOR white gt     lt h1 gt  ls     Laboratorio de Sistemas  ubicuos  del GSyC  lt  h1 gt       and more output omitted here       r    If we try to do the same again  it will not work  because the web server hangs up the connection  after attending a request       echo GET    gt  gt  srv tcp lsub org http     cat  srv tcp lsub org http   cat  error reading  srv tcp lsub org http  Hangup    echo GET    gt  gt  srv tcp lsub org http   echo  write error  Hangup    And  as you can see  it takes some time for our machine to notice  The first write seemed to suc   ceed  Our machine was trying to send the string GET    to the web server  but it couldn   t really  send it  The connection was closed and declared as hung up  Any further attempt to use it will be  futile  What remains is to remove the file from   srv          rm  srv tcp lsub org http    There is a very popular command named telnet  that can be used to connect to servers in the  Internet and talk to them  It uses the  so called  telnet protocol  But in few words  it dials an  address  and thereafter it sends text from your console to the remote process at the other end of  the connection  and writes to your console the text received  For example  this command con   nects to the e mail server running at 1sub org  and we use our console to ask this server for  help      telnet  r tcp lsub org smtp   connected to tcp lsub org smtp on  net tcp 52   220 lsub org SMTP   help   250 
562. t us know if the buffer is ever found to be full or empty  This is the change for get     char   get  Buffer  b        as before     if  b  gt nmsgs    0     print    lt empty gt  n      rsleep   amp b  gt isempty           as before            The change for put is done in a similar way  but printing  lt full1 gt  instead  And this is what we  find out     e phe OY    lt empty gt   lt empty gt  a0 b0  lt full gt   lt full gt  newline supplied by us  al bl  lt full gt   lt full gt  a2 b2  lt full gt   lt full gt  a3 b3 a4 b4         It seems that initially both consumers try to get messages out of the buffer  and they find the  buffer empty  Later  producers insert a0 and b0  and consumers seem to be awaken and proceed   Because both consumers were sleeping and the synchronization mechanism seems to be fair  we  can assume that a0 is printed by the one consumer and bO by the other  It seems that by this time  both consumers keep on inserting items in the buffer until it gets full  Both go to sleep  And for  the rest of the time it looks like producers are faster and manage to fill the buffer  and consumers  have no further problems and will never find the buffer empty from now on     In any case  the only thing we can say is that the code for dealing with a full buffer  and an  empty buffer  has been exercised a little bit  We can also affirm that no process seems to remain  waiting forever  at least for this run       ps   grep 8 pc    r    However  to see if the program is 
563. t you may see is that the  child is wasting processor time  When the child calls Lock  and finds that the lock was held and  it cannot acquire it  it is pointless to keep on trying to acquire it  Unless the child leaves the pro   cessor  and the process holding the lock is able to run  nobody is going to release the lock  There   fore  it is much better to let other processes run instead of insisting  This may give the one hold   ing the lock a chance to release it  And that is better for us  because we want to acquire it     In the actual implementation of Lock in Plan 9  when lock finds that the lock is held and  cannot be set  it calls sleep  This moves the process out of the processor  while it is blocked  during the sleep  Hopefully  after sleeping a little bit  the lock will be already released  And  at  the very least  we will not be wasting processor time spinning around inside lock without any  hope of acquiring the lock before leaving the processor  Figure 10 4 depicts the same scenario for  our two processes  but showing what happens when lock calls sleep  Compare it with the  previous one              Parent Run  Rdy  Rug Rdy  Run  Ce  Y  nlock  lock  Rdy Run    Blk Rdy Blk Rdy       No luck  Calls sleep    alls Lock  which calls sleep this time    Time       Figure 10 4  Same scenario  but using a lock that calls sleep to save processor time     One last remark  Because of the call to sleep  Plan 9 locks are not real spin locks  They do  not spin around in a whil
564. ta file delivers bytes through the connection that are to be  received at the other end  Reading from the data file retrieves bytes sent from the process writing  at the other end  Just like a pipe  Only that  if a transport provides datagrams  each write to a  data file will send a different datagram  and it may arrive out of order or get lost     There are more differences  An important one is that many transport protocols  including  TCP  do not respect message boundaries  This means that data sent through a connection by sev   eral writes may be received at the other end by a single read  If your program has to receive mes   sages from a network connection  it must know how much to read for each message  A single call  to read may return either part of a message or perhaps more than one message     In the line directory for our TCP connection  the local file has the local address  includ   ing the port number  for the connection  This identifies the local end of the pipe  The remote  file serves the same purpose for the other end of the connection     A network address in Plan 9 is a string that specifies the network  e g   the protocol  to use   the machine address  and the port number  For example  tcp 193 147 81 86 564 is a net   work address that says  Using the TCP protocol  the machine address is 193 147 81 86  and the  port number is 564  Fortunately  in most cases  we may use names as well  For example  the  address tcp whale 9fs is equivalent to the previous one 
565. tain messages are processed in a  particular way        Files with particular formats  like MS Word files  are delivered usually to the program  page  which converts them to postscript and shows their contents on a window     e Most other files go to the editor  Optionally  there may be a   followed by an address after  the file name  to instruct the editor to go to a particular piece of text in the file  For example    NOTICE 2 would make an editor show line 2 of  NOTICE  There are other types of  addresses  besides line numbers  A very useful one is of the form  text  That is  some  text after a    like in  NOTICE  cent  This causes the editor to search for the text  for  cent in this case   The text that you type is actually a regular expression  and not just a  string  This is a more powerful mechanism to search for things  that will be seen in a later  chapter                                   Mail addresses get a new window running the mail program     e A file name ending in  h is looked for at  sys include  and then passed to the editor   For example  a plumb of 1ibc h would open  sys include libc h       A name for a manual page  like 1s  1  causes the editor to display the formatted manual  page  Very convenient when using acme  Type the manual page  and click with the button 3  on it     We went this far  but we still do not know what a plumber message is  A plumber message does  not only carry data  Along with the data  there is some metadata that supplies additio
566. tandard output is writ   ing to the connection     This is a nice example of how simple things can be  Listen is in charge of listening and  spawning processes for attending services  The directory keeps the set of files that corresponds to  services  We can use familiar programs like 1c to list them  Each service is provided by a sepa   rate  independent program  And everything fits together     By the way  there is an important lesson to be learned here  It is much more simple to use  cat to implement an echo server than it is to write our own program  If we do not search the  manual and try to see if what we are trying to do is already done  we get a lot of extra work as a  penitency for this sin       151      6 6  Distributed computing    The time has come to reveal another lie we told  There are three kind of machines in a Plan 9  network  not just two  You already know about terminals and file servers  There are also CPU  servers  A CPU server is meant to let the user execute commands on it  in particular  commands  that make intensive use of the processor  Today  with the powerful machines that we have avail   able  most terminals can cope with anything you might what to execute on them     But CPU servers have found their way in this new world and are still very useful for run   ning the file server program  which used to be a different kernel   executing periodic user tasks  automatically  and providing services like Web  mail  and the like     A CPU server runs the
567. tates  Debugging   Everything is a file     55  Input Output  Write games  Read games  Creating and removing files  Directory entries  Listing files in the shell  Buffered Input Output    Parent and Child 83    Running a new program  Process creation   Shared or not    Race conditions   Executing another program  Using both calls   Waiting for children  Interpreted programs    Communicating Processes 101    Input Output redirection  Conventions   Other redirections   Pipes   Using pipes   Notes and process groups    29  31  35  40  42  45  47  49    55  60  64  65  67  72  75    83  84  88  91  91  93  94  97    101  106  106  107  112  117    5 7  Reading  notes  and alarms 120  5 8  The file descriptor bulletin board 123  5 9  Delivering messages 125  Network communication 135  6 1  Network connections 135  6 2  Names 139  6 3  Making calls 141  6 4  Providing services 144  6 5  System services 150  6 6  Distributed computing 151  Resources  Files  and Names 153  7 1  Resource fork 153  7 2  Protecting from notes 155  7 3  Environment in shell scripts 157  7 4  Independent children 158  75  Name spaces 159  7 6  Local name space tricks 164  7 7  Device files 166  7 8  Unions 167  7 9  Changing the name space 169  7 10  Using names 170  7 11  Sand boxing 172  7 12  Distributed computing revisited 174  Using the Shell 179  8 1  Programs are tools 179  8 2  Lists 180  8 3  Simple things 183  8 4  Real programs 186  8 5  Conditions 190  8 6  Editing text 193  8 7  Moving files 
568. tching to any other process that might also use or  change the shared resource  For example  it does not matter if while we are incrementing our  counter  Acme runs for a while  Acme does not interfere because we are not sharing our counter  with it  This is the last program  with the critical region shown inside a box     rincr c          include  lt u h gt     include  lt libc h gt                 int ent     void  main int  char          int i     int LOG     if  rfork  RFPROC RFMEM RFNOWAIT   lt  0   sysfatal  fork   r     for  i   0  i  lt  2  itt             Lost Cnt   sleep  1    loct t    cnt   loc              print   cnt is  d n   cnt    exits  nil           Given our critical region  If we could guarantee that at most one process is executing inside it   there would be no race conditions  The reason is that the region would appear to be atomic  at  least with respect to the processes trying to execute it  There could be any number of context  switches while executing the region  but no other process would be allowed to enter it until the  one executing it does leave the region  Thus  only one process would be using the shared resource  at a given time and that is why there would be no races     Guaranteeing that no more than one process is executing code within the critical region is      234      called achieving mutual exclusion  because one process executing within the region excludes any  other one from executing inside  when there is mutual exclusion      How 
569. ted is zero when  after the parent incre   ments the counter  the child manages to decrement it before the parent prints its value     It is very important to maintain critical regions as small as possible  If a process keeps a  resource locked most of the time  other processes will experience many delays while trying to  acquire the resource  Or even worse  if we are not careful  it may be that a process is never able to  acquire a lock it needs  because it always finds the resource locked  Look at this variant of our  last program  that we call cnt 2     switch  rfork  RFPROC RFMEM RFNOWAIT       case 0        last   time nil    for       lock   amp cntlck    assert  cnt  gt   0    cntt t   print   Sd n   cnt    unlock   amp cntlck       default   for       lock   amp cntlck    assert  cnt  gt   0    if  cnt  gt  0   cnte 3  print   Sd n   cnt    unlock   amp cntlck      Now look at this       8 cnt2   grep  v g  and no number is ever shown     We asked grep to print only lines that do not contain a 0  It seems that all lines in the output  report a zero value for cnt  Is it that the child process is not executing  We can use the debugger  to print the stack for the child       238        ps   grep 8 cnt2  nemo 5153 0 00 0 01 28K Pwrite 8 cnt2  nemo 5155 0 00 0 00 28K Sleep 8 cnt2    z acid 5 155    proc 5155 text 386 plan 9 executable     sys lib acid port    sys lib acid 386   acid  stk     sleep   0x7  sys src libc 9syscall sleep s 5   lock  1k 0x702c  0x47  sys src libc
570. tell later  Reading and writing   c cons while running the window system is not a good idea  If more than one program is  reading this file  the characters typed will go to either program  In the following experiment  we  ask cat to read  c cons  storing what it could read into  tmp out  so you could see what  happens       cat     c cons     gt  tmp out    hlo We typed  hello    Delete To restore things to a normal behavior    cat  tmp out   el     Despite typing hello  rio could only read hlo  The other characters were read by cat  Rio  expects to keep the real  c cons for itself  because it multiplexes this file nicely  providing a  virtual version of it on each window   s  dev cons     A write to  c cons is also processed by the cons device  even when rio is running  As a  result  it prints in the screen behind rio   s back  This command      echo    where will this go      gt      c cons       will produce an ugly message printed in the screen  which might look like the one shown in figure  12 1  In a very few occasions  the kernel itself may write a message for you in the console  The  same would happen  Programs started prior to running rio  that might also issue some diagnos   tics  would produce the same effect  All of them are writing to the console output device     Fhe re will this go   al ll Putall Dump Exit         New Cut Paste Snarf Sort Ze  New Cut Paste Sn   i          Figure 12 1  A write to the actual console may write to the screen even when rio is runnin
571. ters to func   tions to implement each 9P message  This is an excerpt of its declaration     typedef struct Srv Srv   struct Srv                  void   attach   Req      void   auth   Req      void   open   Req       void   create   Req      void   read   Req      void   write   Req      void   remove   Req       void   stat   Req      void   wstat   Req      void   walk   Req       void   flush   Req      char    clone   Fid   Fid      char    walk1   Fid   char   Qid      int infd     T messages read from here  int outfd     R messages written here  void  aux     for you to use          A file server program initializes a Srv structure with pointers to appropriate implementations   Then  it calls a function from lib9p that takes care of almost everything else  For example   postmountsrv takes a server implementation  i e   a Srv structure   a name for a file to be  posted at   srv  and a path for a mount point  as well as flags for mount        sig postmountsrv  void postmountsrv  Srv  s  char  name  char  mtpt  int flag     This function creates a separate process to run the server  as implemented by Srv  It creates a  pipe and puts the server process in a loop  reading 9P requests from one end of the pipe and call   ing the corresponding function in Srv for each request  See figure 13 3  The other end of the pipe  is posted at  srv  using the name given as an argument  At this point  the file in  srv can be  mounted to reach the file server  Furthermore  postmountsrv mou
572. th Plan 9     When a child process dies  Plan 9 must maintain its exit message until the parent process  waits for it  However  if the parent process is never going to wait for the child  Plan 9 does not  know for how long to keep the message  Sooner or later the message will be disposed of  e g    after the parent dies     But if we are not going to wait  it is best to tell Plan 9 that the child is dissociated from the  parent  When the child dies  it will leave no message because no one is going to wait for it  This  is achieved by specifying the flag RFNOWAIT along with RFPROC when the new  dissociated   child is being created  For example  this is the correct version for our child program that used  fork to create a child process         include  lt u h gt    include  lt libc h gt     void  main int  char         switch  rfork  RFFDG RFREND RFPROC RFNOWAIT            case  1   sysfatal   fork failed0O    case 0   print  I am the child0    break   default        print  I am the parent0O         exits  nil                 The flags RFFDG RFREND RFPROC are equivalent to calling fork  but this time we say  RENOWAIT as well          159      7 5  Name spaces    In Plan 9  we use file names like  usr nemo  A name is just a string  It is a sequence of charac   ters  However  because it is a file name  we give some meaning to the string  For example  the  name  usr nemo means     1 Start at the file named    which is also known as the root directory   2 Walk down the file tree to
573. th an Rread containing the  number of bytes in the message and the bytes themselves  In our case  we could ignore the offset  and do it as follows                 r  gt ofcall count   r  gt ifcall count   if  r  gt ofcall count  gt  1   r  gt ofcall count   1     memmove  r  gt ofcall data    n   r  gt ofcall count    respond r  nil      We read one byte at most  the new line  And then we respond with the Rread message     If we did not ignore the offset in the request  further reads from the file  at offsets bigger  than zero  would always return zero bytes  and not a new line  But in any case  reading from a  semaphore file still would have the semantics of blocking until a ticket is obtained  and then  returning something  perhaps just nothing   Nevertheless  we have been assuming that processes  using our file system will open the file for a semaphore before each operation  and then close it  after doing it  The C interface that we designed for using our semaphore file system did it this  way    In the implementation for fsread  the function did not update the response message by  itself  Instead  it calls readstr  which is a helper function from 1ib9p that fills an Rread  reply assuming that file contents are those in the string given as a parameter  in this case  the con   tents of n1   The function updates r  gt ofcall count and r  gt ofcall data  taking care  of the offset  the string size  and the maximum number of bytes requested  After calling  readstr  the only th
574. that may be given to the compiler to make it more strict regarding  the source code  It is very sensible to use them always  The  amp c 1  manual page details them  and  we hope you just take them as a custom     2 De      8c  FVw take c    The binary file generated by 81 is 8  out  by default  But it may be more convenient to give a  better name to this file  This can be done with the  o option for the linker  If we use a file name  like take  the file should be kept at a directory where it is clear which architecture it has been  compiled for  For example  for PCs  binaries are kept at  386 bin or at   usr nemo bin  386 for the user nemo  This is what is done when the program is installed  for people to use  People enjoy typing just the program name     But otherwise  it is a custom to generate a binary file with a name that states clearly the  architecture it requires  Think that you may be compiling a program today while using a PC as a  terminal  Tomorrow morning you might be doing the same on an Alpha  You wouldn   t like to get  confused     The tradition to name the binary file is to use the name 8  out if the directory contains the  source code for just one program  or a name like 8  take if there are multiple programs that can  be compiled in the same directory  This is our case     In this text we will always compile for the same architecture  an Intel PC  unless said other   wise  and generate the binary in the directory where we are working  For example  for our 
575. the      115      command  For example  calling  nr   cmdoutput   we   c   buf  sizeof buf      will fill in buf a string taken from what wc   c prints to its standard output  This is not the best  interface for the task  because we do not know how much the command will print  but it is useful  nevertheless  The caller must take the precaution of supplying a buffer large enough  The number  of bytes read is the result from the function  This is its code     long  cmdoutput  char  cmd  char buf  long len       int fd    long tot     if  pipe fd   lt  0     return  1     failed to create a pipe  switch  fork       case  1    return  1   case 0     close fd 0     dup fd 1   1    close fd 1     execl    bin re     c   cmd  nil    sysfatal   exec     default   close fd 1     for tot   0  len   tot  gt  1  tot    nr     r   read fd 0   buft tot  len   tot    if  nr  lt   0         close  fd 0      waitpid      buf tot    0     terminate string  return tot          In this function  we wait for the child to complete before returning  but after having read all the  data from the pipe  It is a serious mistake to wait for the child before having read all its output  If  the output does not fit into the pipe  the child will block as soon as the pipe is full  It will be wait   ing forever  because the parent is not going to read until waitpid completes  and this call is not  going to complete until the child dies     This is called a deadlock  One process is waiting for another to do som
576. the command name are  arguments  The words between square brackets are optional  They are called options  Any option  starting with           represents individual characters that may be given as flags to change the pro   gram behavior  So  in our last example  1 and 1s are options for man  corresponding to section  and title in the synopsis of man 1      The description section explains all you need to know to use the program  or the C func   tions   It is suggested to read the manual page for commands the first time you use them  Even if  someone told you how to use the command  This will always help in the future  when you may  need to use the same program in a slightly different way  The same happens for C functions     The source section tells you where to find the source code for programs and libraries  It will  be of great value for you to read as much source as you can from this system  Programming is an  art  and the authors of this system dominate that art well  The best way for you to quickly  become an artist yourself is to study the works of the best ones  This is a good opportunity     From time to time you will imagine that there must be a system command to do something   or a library function  To search for it  you may use lookman  as the portion of man 1  repro   duced before shows  Using lookman is to the manual what using search engines  e g   Google   is to the Web  You don   t know how to use the manual if you don   t know how to search it well      10   
577. the function uses the  file descriptor to locate the directory  and read all the information to be returned to the caller  The  function allocates memory for a NetConnInfo structure  fills it with relevant data  and returns  a pointer to it             typedef struct NetConnInfo NetConniInfo    struct NetConnInfo      char  aArr gt     connection directory     char  root     network root     char  spec     binding spec     char  lsys     local system     char  lserv     local service     char  rsys     remote system     char  rServ     remote service     char  laddr     local address     char  raddr     remote address                  143      This structure must be released by a call to freenetconninfo once it is no longer necessary   As an example  this program dials the address given as a parameter  and prints all the information  returned by getnetconninfo  Its output for dialing tcp  whale  9fs follows     conninfo c    include  lt u h gt     include  lt libc h gt                 void  main int argc  char  argv         int fd  srvfd   addr     NetConnInfo i     char     if  argc    2    fprint 2   usage     exits   usage       addr   netmkaddr argv 1    fd   dial addr  nil  nil  nil      if  fd  lt  0    sysfatal  dial  Ss  Sr   addr    i   getnetconninfo nil  fd    if  i    nil     sysfatal   cannot get info         s netaddr n      TEC   NOfS     3    argv 0             print   dir  t s n   i  gt dir    print   root  t s n   i  gt root    print   spec  t s n   i  gt sp
578. the user   s  terminal     cpu  mount  c  srv proc  n procs  cpu  Ic  n procs    1 20 257 30 33 367 662  10 21 259 300 330 37 663  11 213 26 305 334 38 669  111 214 260 306 339 387 674  12 22 265 310 34 389 676    13 23 266 311 346 39 677    f    Remember  because almost every resource looks like a file  you can now export whatever      176      resource you may want     Indeed  we do not even need to use cpu to connect to the CPU server to mount the exported   pxroc  we can import the directory   srv from the CPU server  and mount it at our terminal       Import Scpu  srv  n cpusrv    mount  c  n cpusrv proc  n procs    The program import is the counterpart of export fs  It imports a part of a remote namespace  into our namespace  What it does is to connect to the remote system  and start an exportfs  there  to export file tree of interest  And then  it mounts the now exported file tree in our names   pace     For example  the file name  S is the root directory for the storage device driver  This driver  provides one directory per hard disk  which contains one file per partition in the disk  It doesn   t  really matter how a disk interface looks like  or how a disk is managed in Plan 9  What matters is  that this is the way to get access to the disks in your system  for example  to format them  My ter   minal has two hard disks and a DVD reader      de TEGI  sdco sdcl sdDO sdetl    They are named sdC0  sdC1  and sdDO Because  S is usually added to  dev using bind   some of t
579. thentication server takes precautions to allow only certain users to speak for  others within its authentication domain  The file  lib ndb auth lists which users may speak  for which others  Usually  CPU servers are started by fake users whose sole purpose is to boot  such servers  Such users are usually the only ones allowed to speak for other users  to prevent a  user to impersonate as another     A notable example of a tool that requires identity changes is auth cron  This command  executes commands periodically  as mandated by each user  on a CPU server chosen by each  user  Each user has a file  cron Suser cron that lists periodic commands  For example  this  is the cron file for nemo     cat  cron nemo cron  m h dm m dw host  0       whale chmod  t  mail box nemo spam  0       aquamar  usr web cursos mkcursos  gt  usr web cursos index html    oo    Each line describes a periodic job  It contains the times when to execute it  using fields to select  which minute  hour  day of month  month  and day of week  In this case  both jobs are executed  at midnight  The first job is to be executed at the CPU server whale  and the second one is to be  executed at the CPU server aquamar  Each job is described by the command found last in each  line     The point is that for commands like cron and cpu to work  it is necessary to change the  identity of the processes that run in the CPU server on behalf of a user  As you know  initially  all  processes in the CPU server are entitled t
580. ther example    echo  b   bin book lib  showing that the part of the name matched by   can be also an empty string  Patterns like this one  mean the file name has ab in it     Patterns may appear within path names  to match against different levels in the file tree  For  example  we might want to search for the file containing 1s  and this would be a brute force  approach      74       Is  ls  ls   ls    ls    file does not exist       Not there  Let   s try one level down      Is    1s   bin 1s    Found  But let   s assume it was not there either     e  se FAS FS LS    It might be at  usr bin 1s  Not ina Plan 9 system  but we did not know  Each   in the pat   tern      1s matches with any file name  Therefore  this patterns means any file named 1s     inside any directory  which is inside any directory that is found at       This mechanism is very powerful  For example  this directory contains a lot of source and    object files  We can use a pattern to remove just the object files      gt  TC   8 out echo c home c sic c trunc   creat 8 err 8 open  8 sleep c write   creat c err c open c stat 8 write   dirread 8 global c read  8 stat c wstat   dirread c hi 8 read c take c wstat   echo 8 Hise rm c trunc 8    7 Fm   8    The shell replaced the pattern   8 with any file name terminated with  8  Therefore  rm  received as arguments all the names for object files     Le   8 out err c open c sleep c write   creat c global c read c stat c wstat   dirread c Hae rm c take c   echo c h
581. thing  on a file or not     Each file server has some mechanism to open accounts and authorize users  How to do this  is highly dependent on the particular file server used  For example  each fossil has a file   adm users that lists users known to it  Any user that wants to mount a particular fossil  file server must be listed in the  adm users file kept within that fossil  My file server  knows me because its administrator included nemo in its users file       grep     nemo     adm users  nemo nemo nemo     In this case  the fossil administrator used the uname and users commands in the fossil console  to create my user in that file server     main  uname nemo nemo add the user nemo  main  users  w and update the  adm users file in disk    But to use other file servers I need other accounts  One per file server  For each file server pro   gram its manual page must provide some help regarding how to let it know which user names  exist     Note that a user name in a file server is only meaningful to that file server  Different file  servers may have different lists of users  Within a single organization  it is customary to have a  central  main  file server and to use its  adm users file to initialize the set of users for other  secondary file servers also installed  This is how users are authorized to use file servers     Besides  a file server must also identify the user who is using it  This is done using 9P   When a process mounts a file server in its name space  the user n
582. thread sent an update  alt will immedi   ately return  reporting that a receive from timerc was made  In this case  alt returns zero   which is the index in the alts array for the operation performed  That is how we know which  operation was made  its index in the array is the return value from alt           Each Alt entry in the array is initialized with the channel where the operation is to be per   formed  a constant that can be CHANRCV or CHANSEND to indicate that we want to receive or  send in that channel  and a pointer to the message for the operation  The constant CHANEND is  used as the operation to mark the end of the array  as seen above  To say it in another way  the  call to alt above is similar to doing any of the following          recv timerc   amp timermsg     recv consc   amp consmsg     recv tempc   amp tempmsg       But alt works without requiring a precise order on those operations  That is a good thing   because we do not know in which order we are going to receive updates  We do not know which  particular channel operation is going to be picked up by alt if more than one can be performed     tempmsg         285      But we know that alt is fair  Adding a loop around alt guarantees that all the channel opera   tions that may be performed will be performed without starvation for any channel     Now that alt is not a mystery  we should mention some things done by the decorator  thread  This thread uses chanprint to send messages to the bcastchannel  A call
583. time  The program is unrealistic  because usually you should  employ a much larger read buffer  Memory is cheap these days     read c                   include  lt u h gt                 include  lt libc h gt     void  main int   char              char buffer 10    int nic   int fd     fd   open   NOTICE   OREAD     if  fd  lt  0     sysfatal  open   r                for       nr   read fd  buffer  sizeof buffer    if  nr  lt   0   break   if  write 1  buffer  nr     nr     o    sysfatal  write  br        exits  nil           Although we did not check out error conditions in most of the programs in this chapter  This pro   gram does so  When open fails   it returns  1  The program issues a diagnostic and terminates if  that is the case  Also  after calling read  it does not just check for nr    0  which means that  there is nothing more to read  Instead  it checks for nr  lt   0  because read returns    1 when it  fails  The call to write might fail as well  It returns the number of bytes that could be written   and it is considered an error when this number differs from the one you specified     3 4  Creating and removing files    The create system call creates one file  It is very similar to open  After creating the file  it  returns an open file descriptor for the new file  using the specified mode  It accepts the same  parameters used for open  plus an extra one used to specify permissions for the new file encoded  as a single integer     This program creates its own vers
584. time a real file  Does it exist in your disk with rest of the files  Of course not   How can you keep in a disk a file that contains the current time  Do you expect a file to change  by some black magic so that each different nanosecond it contains the precise value that matches  the current time  What happens is that when you read the file the system notices you are reading   dev time  and it knows what to do  To give you the string representing the current system  time     If this seems confusing  think that files are an abstraction  The system can decide what read   ing a file means  and what writing a file means  For real files sitting on a disk  the meaning is to  read and write data from and to the disk storage  However  for  dev time  reading means  obtaining the string that represents the system time  Other operating systems provide a time  system call that returns the time  Plan 9 provides a  fake   file  The C function t ime  described in  time 2   reads this file and returns the integer value that was read     Consider now processes  How does ps know which processes are in the system  Simple  In  Plan 9  the  proc directory does not exist on disk either  It is a virtual  read  fake  directory that  represents the processes running in the system  Listing the directory yields one file per process       Ic  proc  ili 1320 2 246 268 30 32 348  10   35 20 247 269 300 320 367    But these files are not real files on a disk  They are the interface for handling running pro
585. time one process will be executing each time it is given the processor  The figure  assumes that the child will execute now print   fork n   and then the parent will have  enough time to complete its execution  and the child will at last execute its remaining  instructions  But we do not know  The system may assign the processor in turns to these and  other processes in any other way  Perhaps the parent has time to complete right after calling  fork and before the child starts executing  or perhaps it will happen just the opposite     The child executes independently from the parent  For it  it does not matter what the parent  does  For the parent  it does not matter what the child does  That is the process abstraction  You    Parent    print   one n     fork      print   fork n        exits  nil      print   one n     fork      print   fork n        exits  nil         print   one n       fork        print   fork n               exits  nil      Flow of control    print   one n     fork      I EOCENO TY        exits  nil      print        i print   one n      i fork               fork n               exits  nil      print         85     PC   print   one n     eae fork       print   fork n             exits  nil      PC       Child   s flow    Figure 4 1  The call to fork creates a clone of the original process  Both proceed from there       86     get a new  separate  stand alone  flow of control together with everything it needs to do its job     To write your programs  did y
586. ting the string ki11 ona disk  file  Nobody would record what you wrote to that file  The more probable result of writing this is  that the window where the shell was running will vanish  because no other processes are using it        echo kill  gt  proc Spid ctl        Where is my window         We saw the memory layout for a process  It had several segments to keep the process memory   One of the  virtual  files that is part of the process interface can be used to see which segments a  process is using  and where do they start and terminate       cat  proc Spid segment    Stack defff000 dffff000 1  Text R 00001000 00016000 4  Data 00016000 00019000 1  Bss 00019000 0003  000 i    The stack starts at Oxdefff000  which is a big number  It goes up to Oxdffff000  The process is not  probably using all of this stack space  You can see how the stack segment does not grow  The  physical memory actually used for the process stack will be provided by the operating system on  demand  as it is referenced  Having virtual memory  there is no need for growing segments  The  text segment is read only  it has an R printed   And four processes are using it  There must be  four shells running at my system  all of them executing code from  bin rc     Note how the first few addresses  from 0 to OxOfff  are not valid  You cannot use the first  4K of your  virtual  address space  That is how the system catches null pointer dereferences     We have seen most of the file interface provided for proc
587. tion server  i e   that are grouped together for authentication pur   poses  Each Plan 9 machine belongs to an authentication domain  set by the machine boot process   usually through the same protocol used to determine the machine   s IP address  i e   DHCP      The file  dev hostdomain  provided by the cons 3  device  keeps the authentication  domain for the machine       cat  dev hostdomain  dat escet urjc es     r     Regarding authentication  a user is identified not just by the user name  e g   that in   dev hostowner   but also by the associated authentication domain  A single user might have  different accounts  for using different servers  within different authentication domains  In many  cases  the same user name is used for all of them  However  a user might have different user  names for each different authentication domain     14 4  Authentication agents    In any case  we still have to answer some questions  How does a client  or a sever  run the  authentication protocol  How do they speak with the authentication server  Where do they keep  the secrets  Strictly speaking  in Plan 9  neither process does any of these tasks  All the authenti   cation protocols are implemented by a program called factotum  This program is what is  known as an authentication agent  i e   a helper process to take care of authentication  A facto   tum keeps the secrets for other processes  and is the only program that knows how to perform the  client or the server side of any authenti
588. to  dev null       Ic   c  gt  2   dev null  open c seek c    r    This file in is another invention of the system  like most other files in  dev  When you write  into it  it seems that the write was done  However  the system did not write anything anywhere   That is why this file is used to throw away data sent to a file     The shell can do more things regarding I O redirection  The     lt  gt     operator redirects both  standard input and output to the file whose name follows  However  it opens the file just once for  both reading and writing  For example  this leaves file empty       echo hola gt file    cat  lt file  gt file    But this does not       echo hola  gt file    cat  lt  gt  file  hola    r    More useful is being able to redirect one file descriptor to another one  Errors are to be written to  standard error  but echo writes to standard output  To report an error from a shell script  this can  be done      echo something bad happen  gt  1 2     which is equivalent to a dup  1  2  in a C program   Redirections are applied left to right  and these two commands do different things       ls  blah  gt  dev null  gt  2 1     ls  blah  gt  2 1   gt  dev null  ls   blah    blah    file does not exist    r    The first one redirects its output to  dev null  which throws away all the output  and then  sends its standard error to the same place  Throwing it away as well  The second one send its  standard error to where standard output is going  the console   and then t
589. to do     We have a nice script  but pressing Delete while the script runs may leave an unwanted temporary  file       restore Shome bin  tmp bin    Delete     Ic  tmp   A1030 nemoacme omail 2558 body  ch6 ms restore 1425    r    To fix this problem  we need to install a note handler like we did before in C  The shell gives spe   cial treatment to functions with names sighup  sigint  and sigalrm  A function sighup  is called by rc when it receives a hangup note  The same happens for sigint with respect to  the interrupt note and sigalrm for the alarm note  Adding this to our script makes it     214      remove the temporary file when the window is deleted or Delete is pressed   fn sigint   rm  diffs    fn sighup   rm Sdiffs      This must be done after defining  dif fs  To check that it works     9 4  AWK    There is another tool is use extremely useful  which remains to be seen  Itis a programming lan   guage called AWK  Awk is meant to process text files consisting of records with multiple fields   Most data in system and user databases  and much data generated by commands looks like this   Consider the output of ps       ps   sed 5q    nemo 1 0 00 0 00 1392K Await bns   nemo 2 13 09 0 00 OK Wakeme genrandom  nemo 3 0 00 0 00 OK Wakeme alarm  nemo 5 0 00 0 00 OK Wakeme rxmitproc  nemo 6 0 00 0 00 268K Pread factotum    We have multiple lines  which would be records for AWK  All the lines we see contain different  parts carrying different data  tabulated  In this case  each 
590. to improve read   ability  The compound bc statement that we have used may become hard to read if we need to  add more things to it  It would be nice to be able to use a different echo for each different com   mand sent to bc  and we can do so  However  because the output for both echoes must be sent to  the standard input of bc  we must group them  This is done in rc by placing both commands  inside brackets  We must still quote the first command for bc  because the equal sign is special  for rc  The resulting script can be used like the one above  but this one is easier to read        bin re     echo    obase 16     echo  1       be    Here  the shell executes the two echoes but handles the two of them as it they were just one  command  regarding the redirection of standard output  This grouping construct permits using  several commands wherever you may type a single command  For example         sleep 3600   echo time to leave     amp   r    executes both sleep and echo in the background  Each command will be executed one after  another  as expected  The result is that in one hour we will see a message in the console remind   ing that we should be leaving     How do we implemented a script  called h2d  to do the opposite conversion  That is  to  convert from hexadecimal to decimal  We might do a similar thing       185         bin re     echo     ibase 16     echo  1       be    But this has problems       h2d abc   syntax error on line 1  teletyp  syntax error on line 1  t
591. to write into a file  is still true  But there was something missing in the description we made  in the last section  To do the write you requested  your Plan 9 kernel is likely to need to talk to  another machine  Most probably  your terminal does not have the file  and must get in touch with  the file server to ask him to write the file     Figure 1 8 shows the steps involved for doing the same print shown in the last section   This time  it shows how the file server comes into play  and it shows only your program  Other  programs running at your terminal would follow a similar path     Your program       main      1  call print         a    i T 6  return   l             5  return   2  system call  Your terminal   s kernel File server             write      3  message  write  write            4  message  done                         Figure 1 8  Your system kernel makes a remote procedure call to write a file in the file server     1 Your program makes a procedure call  to the function print in the C library     2 The function makes a system call to the kernel in your machine  This is similar to a proce   dure call  but calls a procedure that is implemented by your kernel and shared among all the  programs in your terminal  Because the kernel protects itself to prevent your program from  calling arbitrary procedures in the kernel  a software interrupt is the mechanism used to per   form this call  This is called a trap  and is mostly irrelevant for you now     3 The code for
592. too many packets   Here comes an example       ip ping lsub org   sending 32 64 byte messages 1000 ms apart  0  rtt 152 us  avg rtt 152 ys   ttl   255  i ret Lol ts  cava ret LoL ws  teL SH 255  2  rtt 149 ps  avg ttt 150 ps  ttl 255    In the output  rtt is for round trip time  the time for getting in touch and receiving the reply     86  86  86    86     141      6 3  Making calls    For using the network from a C program  there is a simple library that provides a more convenient  interface that the one provided by the file system from the network device  For example  this is  our simplified version for srv  It dials a given network address to establish a connection and  posts a file descriptor for the open connection at   srv     Srv c   include  lt u h gt      include  lt libc h gt        void  main int argc  char  argv            int fd  srvfd   char  addr    char fname 128    if  argc    2      fprint 2     usage   s netaddr n   argv 0       exits   usage       addr   netmkaddr argv 1    tcp    9fs     fd   dial addr  nil  nil  nil    if  fd  lt  0   sysfatal  dial  Ss   r   addr    seprint  fname  fname sizeof  fname     srv  s   argv 1     srvfd   create fname  OWRITE  0664    if  srvfd  lt  0   sysfatal  can   t post  s  sr   fname    if  fprint srvfd    d   fd   lt  0     sysfatal  can   t post file descriptor   r             close  srvfd    close  fd    exits nil           Using argv 1  verbatim as the network address to dial  would make the program work only  when
593. tory is still empty  but our name space is instructed to jump to the root directory of file  server at  srv tcp  whale  9fs  whenever we reach  n whale  Therefore  1c is not really  listing  n whale  but the root for our file server  The nice thing is that 1c is happy  because the  name space keeps it unaware of where the files might be  Figure 7 2 shows how 1c walked the      161      file tree  and makes it clear why it listed the root directory in the file server  The dashed boxes  and the arrow represent the mount we made     The data structure that implements the name space is called the mount table  It is a table  that maintains entries saying  Go from this file to this other file  This is what we just saw  After  calling mount in our example  our mount table contains a new entry represented in the figure 7 3   The source for the translation is called the mount point  the destination for the translation is  called the mounted file           Chan for Chan for     n whale at tcp whale 9fs                         Figure 7 3  New entry in mount table after mounting tcp whale 9fs at  n whale     Do not get confused by the Chans  For your Plan 9 kernel  a Chan is just a file  It is the data  structure used to speak 9P with a file server regarding a particular file  Therefore  the figure might  as well say    File for  n whale           Each time the name space walks one step in the file tree to resolve a name  the mount table  is checked out to see if walking should continue 
594. tput  as long as the program is correct   The first time we run a check  we check the out   put by hand and determine if it seems correct  If that is the case  we may record the output for  later  For example  suppose the first check above is contained in the script chk100  rc  and the      355      last check is contained in the script chkdowns rc  We could proceed as follows         semfs     chk100 rc  gt chk100 rc out      Inspect chk1 out to see if it looks ok  and proceed       chkdowns rc  gt chkdowns rc out      do the same for this new check       Now  if we make a change to the program and want to check a little bit if we broke something  we  can use the shell to run our tests again  and compare their output with previous runs  This is  called regression testing  That is  testing one program by looking at the output of previous ver   sions for the same program       for  chk in chk  rc      ae emp  lt   chk  Schk out    echo check  chk failed  iT     vv    This loop could perhaps be included in a rule for the target check in our mk file  so that typing    mk check    suffices     What we said does not teach how to test a program  nor tries to  We tried to show how to  combine the shell and other tools to help you in testing your programs  That is part of develop   ment and Plan 9 helps a lot in that respect     There are many other other things that you could check about your program  For example   listing  proc Spid  fd for the program should perhaps show the same 
595. tring for print     hi c   include  lt u h gt      include  lt libc h gt        void  main int  char argv           Wrong      pringe   hi 1y   print  argv 1     exits  nil       When we compile this program and execute it  this happens     8 hi  8 hi 788  suicide  sys  trap  fault read addr 0x0 pc 0x000016ff    The last line is a message printed by the shell  It was waiting for 8  hi to terminate its execution   When it terminated  the shell saw that something bad happen to the program and printed the diag   nostic so we could know  If we print the value of the st atus variable  we see this      echo Sstatus  8 hi 788  sys  trap  fault read addr 0x0 pc 0x000016ff      48      Therefore  the legacy  or exit status  of 8 hi is the string printed by the shell  This status does  not proceed from a call to exits in 8 hi  we know that  What happen is that we tried to read  the memory address 0x0  That address is not within any valid memory segment for the process   and reading it leads to an error  or exception  or fault   That is why the status string contains  fault read addr 0x0  The status string starts with the program name and the process pid   so we could know which process had a problem  There is more information  the program counter  when the process tried to read 0x0  was 0x000016ff  We do some post mortem analysis now     The program src knows how to obtain the source file name and line number that corre   sponds to that program counter       src  n  s 0x000016ff 8 hi  
596. ts  and it reports failure other   wise  In the same way  rm reports success when it could remove the file s  indicated  and failure  otherwise  And the same applies for other commands     We lied before when we said that a program starts running at main  it does not  It starts  running at a function that calls main and then  when main returns   this function calls exits to  terminate the execution  That is the reason why a process ceases existing when the main function  of the program returns  The process makes a system call to terminate itself  There is no magic  here  and a process may not cease existing merely because a function returns  A flow of control  does not vanish  the processor always keeps on executing instructions  However  because pro   cesses are an invention of the operating system  we can use a system call that kills the calling pro   cess  The system deallocates its resources and the process is history  A process is a data type after  all     In few words  if your program does not call exits  the function that calls main will do so  when main returns  But you better call exits in your program  Otherwise  you cannot be sure  about what value is being used as your exit status     2 4  System call errors    In this chapter and the following ones we are going to make a lot of system calls from programs  written in C  In many cases  there will be no problem and a system call we make will be per   formed  But in other cases we will make a mistake and a system ca
597. ts  window current  Only the top and bottom commands do not affect the focus     Windows may overlap  The window system maintains a stack of windows  Those down in  the stack are in the back  and may be obscured by windows more close to the top of the stack   which are up front   You may reclaim a window to the top of the stack to make it fully visible   With the mouse  a click on the window suffices  From a program  you can move it to the top eas   ily      echo top  gt  dev wsys 3 ct1    And also to the back  something that you cannot do directly using the mouse     echo bottom  gt  dev wsys 3 ctl  By now  you know that windows may scroll down automatically or not  depending on their scroll    status  as selected by the Scroll and Noscroll options from their button 2 menu  This is how to do  it through the control file  this time  for window 3       318        echo scroll  gt  dev wsys 3 wct1 puts the window number 3 in scroll mode    echo noscroll  gt  dev wsys 3 wctl    r    There are several other control commands described in the rio 4  manual page  including some  that might seem to be available only when using the mouse to perform them manually  The next  command resizes a window to be just 100 pixels wide       echo resize  dx 100     gt  dev wctl resizes our window to 100 pixels wide    It is not important to remember all the commands accepted  but it is to know that they can be used  to automate things that would have to be done manually otherwise  Tired of manuall
598. turns informing of which one of the channel operations was done  Before dis   cussing it  it is easier to see the decorator thread as an example       284      void  decoratorthread  void           char  lcons   ltimer    ltemp   char  consmsg   timermsg   tempmsg   char  msg    Alt alts            timerc   amp timermsg  CHANRCV       consc   amp consmsg  CHANRCV       tempc   amp tempmsg  CHANRCV       nil  nil  CHANEND                     lcons   strdup      ltimer   strdup      ltemp   strdup         for       msg   nil   switch  alt  alts       case 0     operation in alts 0  made    chanprint  bcastc    s   s  s  n   lcons  timermsg  ltemp       free  ltimer      ltimer   timermsg   break    case 1     operation in alts 1  made  if  msg    nil        threadexitsall   terminated by user       chanprint  bcastc    s   s  s  n   consmsg  ltimer  ltemp      free lcons     lcons   consmsg    break   case 2     operation in alts 2  made       chanprint  bcastc    s   S  s  n   lcons  ltimer     free  ltemp     ltemp   tempmsg   break                The call to alts receives an array of four Alt structures  The first three ones are the channel  operations we are interested in  The fourth entry terminates the alts array  so that alt could  know where the array ends  When the thread calls alt  it blocks  And it remains blocked until  any of the three channel operations represented by Alt entries in the array may be performed     For example  if right before calling alt the timer 
599. ually show the architecture where the binary can run  the size and offset in the file  for various sections     One section  i e   portion  of the file contains the program text  machine instructions   For  initialized global variables of the program  another section contains their initial values  Note that  the system knows nothing about the meaning of these values  For uninitialized variables  only the  total memory size required to hold them is kept in the file  Because they have no initial value  it  makes no sense to keep that in the file  Usually  some information to help debuggers is kept in the  file as well  including the strings with procedure and symbol names and their addresses     In the last chapter we saw how nm can be used to display symbol information in both  object and binary files  But it is important to notice that only your program code knows the  meaning of the bytes in the program data  i e   the program knows what a variable is   For the  system  your program data has no meaning  The system knows nothing about your program  It   s  you the one who knows  The program nm can display information about the binary file because it  looks at the symbol table stored in the binary for debugging purposes     We can see this if we remove the symbol table from our binary for the take  c program   The command st rip removes the symbol table  To find the binary file size  we can use option   1 for Js  which  as you know  lists a long line of information for each fi
600. ub   stitute the   with another character  and then copy the files       for  f in     mp3      i  nf      echo Sf   sed s   _ g       echo cp Sf  destdir Snf   id   cp alanparsons irobot mp3  destdir alanparsons_irobot mp3   cp alanparsons whatgoesup mp3  destdir alanparsons_whatgoesup mp3  cp pausini trateilmare mp3  destdir pausini_trateilmare mp3   cp supertramp logical mp3  destdir supertramp_logical mp3    r    Here  we used a comma as the delimiter for the sed command  because we wanted to use the  slash in the expression to be replaced     To copy the whole file tree to a different place  we cannot use cp  Even doing the same  thing that we did above  we would have to create the directories to place the songs inside  That is  a burden  A different strategy is to create an archive for the source tree  and then extract the  archive at the destination  The command tar   tape archive  was initially created to make tape  archives  We no longer use tapes for achieving things  But tar remains a very useful command   A tape archive  also known as a tar file  is a single file that contains many other ones  including  directories  bundled inside     What tar does is to write to the beginning of the archive a table describing the file names  and permissions  and where in the archive their contents start and terminate  This header is fol   lowed by the contents of the files themselves  The option  c creates one archive with the named  files       tar  c    gt  tmp music tar    We
601. ul 9 21 28 docs  If we create a file in that directory  permissions get reasonable       cd docs     touch memo     is  1 memo       rw rw r   M 19 nemo planb 0 Jul 9 21 30 memo    The group for the new file is planb  because the group for the directory was that one  The file  has write permission for users in the group because that was the case for the directory     To modify permissions  the chmod  change mode  command can be used  Its first argument  grants or revocates permissions  The following arguments are files where to perform this permis   sion change  For example  to grant execution permission for file program  you may execute      chmod  x program    To remove write permission for an important file that is not to be overwritten  you may    chmod  w file  The   sign grants permission  The     sign removes it  The characters following this sign indicate    which permissions to grant or remove  For example   rx grants both read and execution permis   sions     If you want to change the permissions just for the owner  or just for the group  or just for      20      anyone else  you may specify this before the   or     sign  For example       chmod gtr docs    grants read permission to users in the group  Permissions for the owner and for the rest of the  world remain unaffected  In the same way ut r would grant read permission for the owner  and  o r would do the same for others     In some cases  for example  in C programs  you are going to have to use an integer to 
602. ul computers like the ones we have today  most machines are capable of exe   cuting multiple programs simultaneously  The system makes it easy to keep these programs run   ning  unaware of the underlying complexity resulting from sharing the machine among them     Did you notice that it was natural for you to write and execute a program as if the computer  was all for itself  However  I would say that at least an editor  a web browser  and perhaps a  music player were executing at the same time  The system decides which parts of the machine   and at which times  are to be used by each program  That is  the system multiplexes the maching  among different applications  The abstractions it provides try to isolate one executing program  from another  so that you can write programs without having to consider all the things that hap   pen inside your computer while they run     Deciding which resources are used by which running programs  and administering them is  called  not surprisingly  resource management  Therefore the operating system is also a resource  manager  It assigns resources to programs  and multiplexes resources among programs     Some resources must be multiplexed on space  i e  different parts of the resource are given  to different programs  For example  memory  Different programs use different parts of your  computer   s memory  However  other resources cannot be used by several programs at the same  time  Think on the processor  It has a set of registers  but a
603. uld leave the fid pointing to    Walking to    from   leaves the fid  unchanged  The convention is that     is just    Like it happen with fsclone  the function  must return a nil string when it could do its job  or a string describing the error when it failed   Besides  both   id  gt qid and  qid must be updated with the qid for the new file after the walk   Furthermore  because we keep a pointer to a Sem in the fid  gt aux field  the function must  update such field to point to the right place after the walk     static char   fswalk1l Fid  fid  char  name  Qid  qid        Qid q   int ai  Sem  Ss     q   fid  gt qid   s   fid  gt aux       348      if    q type amp QTDIR      if   strcmp  name           fid  gt qid    Qid  0 0 QTDIR     qid   fid  gt qid   closesem  s    fid  gt aux   nil   return nil           else      for  i   0  i  lt  nsems  i     if  sems i   amp  amp   strcmp  name  sems i   gt name      fid  gt qid    Qid  i  0  0    incref sems i     closesem fid  gt aux     fid  gt aux   sems il    qid   fid  gt qid   return nil                return  no such file           Walking to the root directory releases any reference to the Sem that might be pointed to by  fid  gt aux  Walking to a file adds a new reference to the semaphore for the file  But otherwise   the function should be simple to understand     And this completes the implementation for our semaphore file server  After compiling it   we can now use it like follows       8 semfs  s sem  m  mnt sem    e
604. une routines    for  i   0  i  lt  nr  i     buf i    toupper  buf i     produces this result for this input     Espa  a includes Espu  a   ESPANA INCLUDES ESPUNA                 The letter A was not properly capitalized into N  It could have been worse  We could have      295      processed part of a rune  because runes may span several bytes  For example  translating to upper   case by    buf i    buf i       A         a       will lead to a surprise  besides being wrong anyway      12 3  Mouse input  Another popular input device is the mouse  The mouse interface is provided by the mouse driver  through a few files in  m      lo     m      cursor mouse mousectl  This name is usually bound along with other devices at  dev  The file mousect1 is used to  write strings to configure and adjust mouse settings  For example       echo accelerated  gt  dev mousect1       turns on mouse acceleration  a quick move in one direction will move the mouse fast in that  direction  many more pixels than implied by the actual movement   On the other hand       echo linear  gt  dev mousect1    disables mouse acceleration  There are several other messages  Depending on the hardware for the  mouse  some control requests may be ignored  if they do not make sense for a particular mouse      When the window system is running  rio is the one that reads and writes these files  Like it  happens with  dev cons  rio provides its own  multiplexed  version for these files  on each  window  Reading  m mous
605. ure meter device  We assume that the file   dev temp gives the current temperature as a string each time when read  To implement the  thread temp  we measure the temperature once per minute  However  the thread only sends a  temperature update when the temperature changes  and the first time it is measured   Once more   the channel where to send the updates is given as a parameter       283      void  tempthread void  a              Channel  c   a   char temp  10    char last  10    int fd  nr   last 0    0   fd   open   dev temp   OREAD     if  fd  lt  0   sysfatal   dev temp   r     for       nr   read fd  temp  sizeof temp    1      if  nr  lt   0   sysfatal  can   t read temp     temp nr    0   if  strcemp last  temp     0    strcpy  last  temp    sendp  c  strdup temp         sleep 60   1000           What remains to be done is to implement the decorator thread  This thread must receive alter   natively from one of three channels  timerc  tempc  or consc  When it receives a new mes   sage from either channel  it must concoct a new message including up to date information from  the three inputs  and deliver the new message through bcastc to update all the panels  Because  we do not know in which order we are going to receive inputs  we cannot use recvp  The func   tion alt implements many to one communication  It takes a set of channel operations  sends or  receives  and blocks until one of the operations may proceed  At that point  the operation is exe   cuted and alt re
606. use  128  Bwrite  79    C    C declaration  186   c device driver  171 289  C  language  20  library  68  program  20  calculator  98  call  error  system  40  67  92  receiving  146    remote procedure  25  system  23  25  46  83  calls  making  141  cancel  alarm  122  capabilities  372  capability device  372  carriage return  138  carriage return character  17  case  conversion  185  insensitive  209  case  190  cat  15 57  75  80  scc  351   c cons  289  cd  14  CD  audio  225  blank  226  burn  225  copy  227  file system  225  write  198  cdcopy rc script  227  cdfs  225  cdtmp rc script  98  cecho c  149  Chan  61  88  125  159  161  327  chan  image  308  chancreate  270  CHANEND  284  chanfree  270  change  current directory  14  identity  372 373  permissions  19  uid  373  changeuser  374  channel  62  269  305  buffering  270  communication  269  event  128  mouse event  297  operation  alternative  284  operation  simultaneous  284  unbuffered  271  channel  print  285  Waitmsg  285  chanprint  285  CHANRCV  284  CHANSEND  284  character  carriage return  17             control  16  echo  292  escape  11  44  202  line feed  17  new line  16  range  201  range pattern  74  set  201  chartorune  293  chatty9p  336  chdir  41  check  permission  360  checking  for access  67  program  354  chgrp  71  chgrp c  72  child  dissociated  158  process  84  87 88  98  153  157  process  independent  158  process  pipe to  112  process  wait for  114  child c  87  childre
607. use the  factotum for the server had no keys  The optimistic  but still poor  client tried to attach to the  server  anyway  The server refused this time  because the client was not authenticated  Things are  different when the server   s factotum is equipped with a key for P9SK1       8 asemfs  D    lt  11  Tversion tag 65535 msize 8216 version    9P2000       11  gt  Rversion tag 65535 msize 8216 version    9P2000       lt  11  Tauth tag 10 afid 465 uname nemo aname    11  gt  Rauth tag 10 qid  8000000000000001 0 A     lt  11  Tread tag 10 fid 465 offset 0 count 2048    11  gt  Rread tag 10 count 24  7039736b 31406461            lt  11  Twrite tag 10 fid 465 offset 24 count 24  7039736b 31206461   11  gt  Rwrite tag 10 count 24    lt  11  Twrite tag 10 fid 465 offset 48 count 8    750laf21 166c2391      11  gt  Rwrite tag 10 count 8    lt  11  Tread tag 10 fid 465 offset 56 count 141    11  gt  Rread tag 10 count 141    016e656d 6f000000            lt  11  Twrite tag 10 fid 465 offset 197 count 85      63182df 120add32   11  gt  Rwrite tag 10 count 85    lt  11  Tread tag 10 fid 465 offset 282 count 13    11  gt  Rread tag 10 count 13    2be8ff3e d96f0F29           ad ct              lt  11  Tattach tag 10 fid 234 afid 465 uname nemo aname  authenticate nemo   ok    11  gt  Rattach tag 10 qid  0000000000000000 0 d     lt  11  Tclunk tag 10 fid 465    11  gt  Relunk tag 10          In this output  you see how the client sends read and write requests  successfully  to the aut
608. user   auth_proxy afd  getkey   proto p9any role client user  s   user      Such string is given to factotum  which matches it against the keys it keeps  It is used as a tem   plate to select the key  and protocol  to use  In this case  any key matching the p9any protocol  can be used  using the role of a client  The p9any protocol is not exactly a protocol  but a way to  say that we do not care about which particular Plan 9 authentication protocol is used  When this  meta protocol is used  both the client and the server negotiate the actual authentication protocol  used  like for example  POSK1     Once auth_proxy completes  if may have succeeded authenticating the user or not  If it  does  it returns an Authinfo structure  which is a data structure that contains authentication  information returned from factotum     typedef struct AuthInfo AuthInfo   struct AuthInfo       char  cuid     caller id      char  suid     server id      char  cap     capability  only valid on server  int nsecret     length of secret      uchar  secret     secret             For example  this is what results from using 8   amount to mount several file servers  First  we  start anew ramfs  which does not require any authentication  and mount it     side             367        ramfs  s ram     8 amount  srv ram  n ram         fauth  authentication not required  no auth information obtained    The call to fauth  which sends a Tauth request to the server  fails with the error  authentication not requi
609. user name     After each semester  we must issue grades to students  Depending on the course  there are  several separate parts  e g   problems in a exam  that contribute to the total grade  We can reuse a  lot from our script to prepare a text file where we can write down grades     list2grades     bin re    rfork e  nquestions 3  fn listusers    awk   F     7            next    FESI   next     3    Operating Systems   amp  amp   4    B    print  2      S       224         listusers      awk      BEGIN   printf     30s t    Name      for  i   0  i  lt     Snquestions     itt     printf   Q  d t   i 1    printf   Total n         printf   S 30s t    0     for  i   0  i  lt     Snquestions     i     printf     t   i141    printi   ha             exit    7     Note how we interpolated Snquestions in the AWK program  but closing the quote for the  program right before it  and reopening it again  This program produces this output       list2grades list   Name Q 1 Q 2 Q 3 Total  Rodolfo Martinez     a     Joe Black x          Luis Ib    ez       n  Ricardo Mart  nez              We must just fill the blanks  with the grades  And of course  it does not pay to compute the final   total  grade by hand  The resulting file may be processed using AWK for doing anything you  want  You might send the grades by email to students  by keeping their user names within the list   You might convert this into HTML and publish it via your web server  or any other thing you see  fit  Once the script
610. uss Cox seems to be a pro   gram listening for questions at 9fans  at least his response time suggests that  I have learned a lot from  you all  or I tried   Other colleagues from Rey Juan Carlos University helped me as well  Pedro de las  Heras was eager to get new drafts for this manuscript  Sergio Ar  valo was an unlimited supply of useful  comments and fixes for improving this book  specially for using it as a textbook  Jos   Centeno was scared  to hell after reading our initial description of computer networks  and helped to reach a much better descrip   tion     Francisco J  Ballesteros   Laboratorio de Sistemas    Rey Juan Carlos University of Madrid  Madrid  Spain   2006    1  1 2   1 3   1 4   1 5   1 6   1 7   1 8   1 9     1 10   1 11   1 12   1 13   1 14     2 2   2 3   2 4   2 5   2 6   2 7   2 8     3 1   3 2   3 3   3 4   3 5   3 6   3 7     4 1   4 2   4 3   4 4   4 5   4 6   4 7   4 8     5 1   5 2   5 3   5 4   5 5   5 6     Table of Contents    Getting started 1    What is an Operating System    Entering the system   Leaving the system   Editing and running commands  Obtaining help   Using files   Directories   Files and data   Permissions   Writing a C program in Plan 9   The Operating System and your programs  Where are the files    The Shell  commands  binaries  and system calls  The Operating System and the hardware    Programs and Processes 29    Processes   Loaded programs  Process birth and death  System call errors  Environment   Process names and s
611. ute the average                    As an aside  it can be funny to note that there are many AWK programs with only an action  for BEGIN  That is a trick played to exploit this language to evaluate complex expressions from  the shell  Another contender for hoc                   awk    BEGIN  print sqrt 2    log 4 3       2 06279     awk    BEGIN  PI 3 1415926  print PI   3 7   2 7  43 0084    This program is closer to what we want to do to determine which process is the biggest one  It  computes the maximum of a list of numbers       seq 5000   awk 7        BEGIN   max 0      ra l if  max  lt   1   a max S   iif    7  END   print max    5000 Correct     This time  the action for all the records in the input updates max  to keep track of the biggest  value  Because max was first used in a context requiring an integer  assigned 0   it is integer   Let   s try now our real task       ps   awk 7        BEGIN   max 0      ii l if  max  lt   5   a max S5  iif    7  END   print max    7    9412K Wrong  because it should have said       ps   sort  4r   awk     print  5  exit      11844K  What happens is that 11844K is not bigger than 9412K  Not as a string     awk    BEGIN   if   11844K   gt   9412K   print  bigger          Watch out for this kind of mistake  It is common  as a side effect of AWK efforts to simplify  things for you  by trying to infer and declare variable types as you use them  We must force      219      AWK to take the 5th field as a number  and not as a string     
612. value of  argv 0  for our program  Programs know their name by looking at argv  0   which is very  useful to print diagnostic messages while letting the user know which program was the one that  had a problem     There is a standard command in Plan 9 that is almost the same  echo  This command     36     prints its arguments separated by white space and a new line  The new line can be suppressed  with the option  n       echo hi there   hi there   r     echo  n hi there  hi there     Note the shell prompt right after the output of echo  Despite being simple  echo is invaluable to  know which arguments a program would get  and to generate text strings by using echo to print  them     Our program is not a perfect echo  At least  the standard echo has the flag    n  to ask for a  precise echo of its arguments  without the addition of the final new line  We could add several  options to our program  Option  n may suppress the print of the additional new line  and option   v may print brackets around each argument  to let us know precisely where does an argument  start and where does it end  Without any option  the program might behave just like the standard  tool and print one argument after another  The problem is that the user may call the program in  any of the following ways  among others     8 echo repeat after me    echo  n repeat after me   echo  v repeat after me  cho  n  v repeat after me  cho  nv repeat after me          co C CO          It is customary that options may
613. ven  mk tries to build the first target mentioned     Suppose we now run mk again  This is what happens     mk  mk     8 semfs    is up to date    r    No rule was executed  The program mk assumes that a target built from some other files  if newer  than the other files  is already up to date and does not need to be built  Because we did not mod   ify any file  the file 8 semfs is newer than semfs 8 and sem 8  This means that 8 semfs  is up to date with respect to its dependencies  Before checking this out  mk checks if the depen   dencies themselves are up to date  The file semfs 8 is newer than its dependencies  which  means that it is up to date as well  The same happens to sem  8  In few words  the target given  to mk is up to date and there is nothing to make     Suppose now that we edit sem  c  which we can simulate by touching the file  updating its  modification time   Things change       touch sem c     mk   8c  FVw sem c   81  o 8 semfs semfs 8 sem 8       r    The file sem  8  needed because 8  semfs depends on it  is not up to date  One of the files it  depends on  sem  c  is newer than sem  8  This means that the target sem  8 is old  with respect      351      to sem  c  and must be rebuilt to be up to date  Thus  mk runs the body of its rule and compiles  the file again     The other dependency for the main target  semfs  8  is still up to date  However  because  sem  8 is now newer than 8 semfs  this file is out of date  and the body for its rule is executed  
614. want to draw  The last  parameter for draw is a point that indicates which translation to do  Passing the point  0 0    which is defined as ZP in draw h  performs no translation  each pixel  i  j  in the source is  copied to the pixel  i  j  in the destination  Passing other point will ask draw to translate the  source image  coordinates  so that the given point is aligned with the top left corner of the rectan   gle where to draw     The mask parameter allows an image to be used as a mask  This is useful to draw things  like cursors and the like  In most cases you may use nil  and not use a mask  We do not discuss  this parameter here  the draw 2  manual page has all the details     One thing that remains to be discussed about our program is the call to flushimage   Writing to the draw device for each single operation performed by the draw library would be very    Point p       303      costly  To improve efficiency  the library includes buffering for writes to the draw device   s files   This is similar to what we saw regarding buffered input output  Only that in this case  draw is  always doing buffered output  As a result  if you draw  it many happen that your operations are  still sitting in the buffer  and the actual device may not have received them  A call to    flushimage  display  1     flushes the buffer for the display  The last parameter is usually set to true  to indicate to the driver  that it must update the actual screen  in case it also maintains another buf
615. what people can do with  the file  The security mechanism to control access to files is called an access control list  This is  like the list given to security guards to let them know who are allowed to get into a party and  what are they allowed to do inside  In this case  the system is the security guard  and it keeps an  access control list  or ACL  for each file  To be more precise  the program that keeps the files   i e   the file server  keeps an ACL for each file     The ACL for a file describes if the file can be read  can be written  and can be executed   Who can be allowed by the ACL to do such things  The file server keeps a list of user names   You had to give your user name to log into the system and access your files in the file server   Depending on your user name  you may be allowed or not to read  write  and execute a particular  file  It depends on what the file   s ACL says     Because it would be too inconvenient to list these permissions for all the users in the ACL  for each file  a more compact representation is used  Each file belongs to a user  the one who cre   ated it  And each user is entitled to a group of users  The ACL lists read  write  and execute per   missions for the owner of the file  for any other user in the group of users  and for the rest of the  world  That is just nine permissions instead of a potentially very long list     In the file server  each user account can be used as a group  This means that your user name  is also a group n
616. wing file descriptors for both  This figure may correspond  to the following program     Parent    process       File descriptor  table         89      Child    process       File descriptor                __                             uU Ne OO                           z  gt              table   dev cons     0  offset  3245   1  2  3  afile     offset  6                   Figure 4 2  The child has a copy of the file descriptors that the parent had     before c     include  lt u h gt      include  lt libc h gt        void  main int  char         int fd   fd   create  afile   OWRITE  0644    write fd   hello n   6    if  fork       write fd   child n   6    else  write fd   dad n   4      close  fd    exits  nil           Initially  the parent had standard input  output  and error open  All of them went to file   dev cons  Then  the parent opens  i e   creates  af ile  and file descriptor 3 is allocated  It  points to a  Chan  data structure that maintains the offset  initially 0   and the reference to the    actual file  After writing 6 bytes  the offset becomes 6     At this point  fork creates the child as a clone  It has a copy of the parent   s file descriptors   but everything else is shared  Of course  if either process opens new files  their offsets would not  be shared  For each open you get an all new file offset  What would be the contents for afile    after running this program       90        8 before     cat afile   hello   child   dad  Each process calls write 
617. with holes  64  file   clone  136   ctl  300   data  300  descriptor  Biobuf  80   local  137  names     166     10     namespace  203  network data  136  patterns  210  process ctl  51  process fd  58  process mem  51  process note  118  120  process notepg  118  120  process ns  162  remote  137  rpc  364  system   env  51  system   fd  102  171  system   mnt plumb  128  system   net  135  system   proc  50  118  162  system  rio  172 313  system   srv  123  file  command  190  rc script  190  files  header  21  move  198  temporary  45  text  179  using  10  fill c  111  firewall  176  flag  command  9  flag   a  bind  168   a  chmod  64   b  bind  168   c  bind  169   c  rc  114   d  1s  15   d  test  191   d  tr  185   e  grep  209   e  sed  195   e test  191   F  awk  220   f  grep  210   f  rm  12   i  grep  209   1  1s  31   m  1s  15   n  diff  211     n  echo  36     n  grep  209   n  netstat  140   n  nm  32   n  sed  195           n  sort  205   o  81  22   older  test  192   r  rm  67   r  sort  205   r  telnet  138   s  grep  221   s  ls  11   u  sort  208   w  wc  108  flags  11  compiler  21  flow  control  153 154  261  of control  29  46  flush  draw operation  302  flushimage  302  flushing  buffer  81  flushing  Biobuf  79  fmtinstall  298  fn  206  focus  117  input  317  Sfont  313  Font  312  font  301  312  file  312  for command  186  fork  resource  153  fork  83 84  86  88  93  114  153  158  return value  84  format  install  298  network  68  70  
618. xample   if the operator types the message    AA flight 847 delayed    we would like pannels to show the message    AA flight 847 delayed  17 45 32  C     We could modify the code for the panel thread to do it  But it would not be very appropriate  A  pannel thread is expected to write messages to a panel  and to write them verbatim  The same  happens to other threads in this program  They do a very precise job and are modular building  blocks for building a program  Instead  it seems better to put another thread between consread  and bcast  to decorate messages with the time and the temperature  We call this new thread  decorator     There is still the problem of updating the panels when either the time changes  the minute   indeed  or the temperature changes  It would not be reasonable to display just the time and tem   perature for the moment when the operator typed the message shown     As a result  the new decorator thread must have three different inputs  It receives mes   sages  but it must also receive time and temperature updates  The leave us with the problem of  how do we generate the two additional input streams  To follow our modular design  two new  threads will be in charge of providing them  The resulting process design is that shown in figure  11 5  And the code of the whole program may look like this       278         panelc 0                    I  I                               j   timerc    ie a a      l          bcastc   panelc i                 consc   
619. y  all processes running in the same window share the environment variables     For example  the variable home has the path for your home directory as its value  The com   mand cd uses this variable to know where your home is  Otherwise  how could it know what to  do when given no arguments  Both names and values of environment variables are strings   Remember this     We can define environment variables in a shell command line by using an equal sign   Later  we can use the shell to refer to the value of any environment variable  After reading each  command line  the shell replaces each word starting with a dollar sign with the value of the envi   ronment variable whose name follows the dollar  For example  the first command in the following  session defines the variable dir       dir  a very long path    GO  SALE     pwd    a very long path    r    The second command line used  dir  and therefore  the shell replaced the string  dir with the  string that is the value of the dir environment variable   a very long path  Note that cd  knows nothing about  dir  We can see this using echo  because we know it prints the argu   ments received verbatim       echo  dir   a very long path    r    The next two commands do the same  However  one receives one argument and the other does  not  The output of pwd would be the same after any of them      43        cd Shome  eed     In some cases it is convenient to define an environment variable just for a command  This can be  done by defini
620. y  exportfs  that file tree is exactly the same than the one in effect in the namespace where  export fs runs     The second program that can be used to export a namespace  srvfs  is just a convenience  wrapper  that calls export fs in a way that is more simple to use from the shell  It receives the  name for a file to be created at  s rv  that when mounted  grants access to the file tree rooted at  the directory given as the second argument     To see that srvfs  i e   export fs  is indeed exporting a namespace  we can rearrange a  little bit our namespace  export a part of it  and see how after mounting it we gain access to the  rearranged file tree that we see  and not the real one from the file server       mkdir  tmp exported  tmp exported doc  tmp exported src    bind Shome doc  tmp exported doc    bind Shome src  tmp exported src      srvfs x  tmp exported      mount  c  srv x  n imported    lc  n imported    doc Sre     Ic  n imported src   9 gs misc  UGrad lang os  bbug limbo prj  chem mem sh    A nice example of use for this program can be found in the srvfs 4  manual page       cpu  cpu  srvfs procs  mnt term proc  cpu     This posts at  srv procs  in the CPU server  a file descriptor that can be used to mount the  file tree seen at  mnt term proc in the namespace where srvfs is executed  That is  the   pxroc file tree at the terminal used to run the cpu command  Therefore  mounting   sxrv procs in the CPU server permits obtaining access to the  proc interface for 
621. y adjusting a  window  after running acme  to use most available screen space  Just write a shell script for the  task     The first thing to be done by the script is to determine how much space is available at our  terminal  This was recorded in  vgasize  Later  we can define variables for the width and  height  in pixels  that we might use       echo Svgasize   1280x800x24     wid      echo Svgasize   sed    s x            echo Swid    1280     ht     fecho Svgasize   sed    s   x    x   1         echo Sht   800    Because most of the times we want some space to use rio  e g   to recall its menus   we may  save 90 pixels from the height  To keep an horizontal row with 90 pixels of height just for other  rio windows and menus       At    f echo ht   90   hoc     echo Sht  710    And now  we can resize the window  placing it in the rectangle computed for our screen        cho resiz r 0 0 Swid  ht  gt  dev wetl    The arguments for the move and resize commands  understood by the wct1 file  are similar  to those of the window command     If in the future you find yourself multiple times carefully adjusting windows to a particular  layout that is easy to compute  you know what to do     Problems  1 Record mouse events and try to reproduce them later     2 Use the window system to provide virtual desktops  You do not need to implement anything  to answer this problem     3 Write a program that implements console cooked mode by itself  It must write to standard  output one line at
622. you  are  That is why you will get immediately two more prompts  one to tell you user name at the file  server  and one to ask for your secret password for that account  Usually  the user name for your  account in the file server is also that used in the terminal  so you may just hit return and type your  password when prompted      5     If you come from UNIX  beware not to type your password immediately after you typed  your user name for the first time  That would be the file server user name  and not the password   All your password would be in the clear in the screen for anyone to read     You are in  If this is the first time you enter a Plan 9 system you have now the prompt of a  system shell  after several error messages   A shell is a program that lets you execute commands  in the computer  In Windows  the window system itself is the system shell  There is another shell  in Windows  if you execute Run command in the start menu you get a line of text where you  can type commands  That is a command line     At this point in your Plan 9 session  you can also type commands to the shell that is running  for you  The shell is a program  rc in this case  that writes a prompt  reads a command  text  line   executes it  waits for the command to complete  and then repeats the whole thing     The shell prompt may be term   or perhaps just a semicolon  which is the prompt we use  in this book   Because you never entered the system  and because your files are yours  nobody  creat
623. zero  meaning that there would be no  further DMA for this disk  This can slow down the system  and it is better to enable it again       echo dma on  gt  dev sdD0 ct1    grep dma  dev sdD0 ct1  config 85C4 capabilities OF0O0O dma 00550004 dmactl 00550004    Lines starting with part  read from the ct1 file  deserve further explanation     The abstraction provided by the hardware for a disk is usually an array of sectors  Each sec   tor is typically an array of 512 bytes  The disk knows how to read from disk into memory a given  sector  and how to write it       322      The last line read from the ct1 file describes a part of the disk  that goes from sector num   ber 0 to sector number 54656  Such part has the name data  and represents the actual data on  the disk  Did you notice that there is a file  dev sdD0O data  That is the abstraction for using  this disk in Plan 9  This file is the data in the disk  Reading the first 512 bytes from this file  would be reading the first sector from the disk   s data  To read or write a particular sector  any  program can use seek to set the file position at the appropriate offset  and then call read or  write  The device driver would understand that the program wants to read or write from the  disk  and would do just that     In case you wonder  the file raw is used to execute commands understood by the device  that have a very low level of abstraction  as a back door to provide raw access to the device  with   out the cooking provided 
    
Download Pdf Manuals
 
 
    
Related Search
    
Related Contents
Sistema de Mini- Componente de Alta Fidelidad  Manager les Y : les cinq commandements  Mellerware TRENTO 1200W User's Manual  L`innovation pédagogique L`innovation pédagogique  SmartMetals 112.2350 project mount  Citysphere    COGNEX - In-Sight Track & Trace User Manual  Blanco 157-182 User's Manual  HQ W9-RS-12BN    Copyright © All rights reserved. 
   Failed to retrieve file