See the reference page for links to the early Unix papers.
      
       while (1) {
	    printf ("$");
	    readcommand (command, args);   // parse user input
	    if ((pid = fork ()) == 0) {  // child?
	       exec (command, args, 0);
	    } else if (pid > 0) {   // parent?
	       wait (0);   // wait for child to terminate
	    } else {
	       perror ("Failed to fork\n");
            }
        }
The split of creating a process with a new program in fork and exec is mostly a historical accident. See the assigned paper for today.
        $ ls
     read (1, buf, bufsize)
     write (1, "hello\n", strlen("hello\n")+1)
     $ls > tmp1
just before exec insert:
    	   close (1);
	   fd = open ("tmp1", O_CREAT|O_WRONLY);   // fd will be 1!
The kernel will return the first free file descriptor, 1 in this case.
     $ls 2> tmp1 > tmp1
replace last code with:
	   close (1);
	   close (2);
	   fd1 = open ("tmp1", O_CREAT|O_WRONLY);   // fd will be 1!
	   fd2 = dup (fd1);
both file descriptors share offset
        $ sort file.txt | uniq | wc
or
$ sort file.txt > tmp1 $ uniq tmp1 > tmp2 $ wc tmp2 $ rm tmp1 tmp2or
        $ kill -9
	int fdarray[2];
	
	if (pipe(fdarray) < 0) panic ("error");
	if ((pid = fork()) < 0) panic ("error");
	else if (pid > 0) {
	  close(fdarray[0]);
	  write(fdarray[1], "hello world\n", 12);
        } else {
	  close(fdarray[1]);
	  n = read (fdarray[0], buf, MAXBUF);
	  write (1, buf, n);
        }
	    
	    int fdarray[2];
  	    if (pipe(fdarray) < 0) panic ("error");
	    if ((pid = fork ()) == 0) {  child (left end of pipe)
	       close (1);
	       tmp = dup (fdarray[1]);   // fdarray[1] is the write end, tmp will be 1
	       close (fdarray[0]);       // close read end
	       close (fdarray[1]);       // close fdarray[1]
	       exec (command1, args1, 0);
	    } else if (pid > 0) {        // parent (right end of pipe)
	       close (0);
	       tmp = dup (fdarray[0]);   // fdarray[0] is the read end, tmp will be 0
	       close (fdarray[0]);
	       close (fdarray[1]);       // close write end
	       exec (command2, args2, 0);
	    } else {
	       printf ("Unable to fork\n");
            }
        $ compute &