Salz InterNetNews...
complicated because other parts of the server can
add and remove themselves from the select (2) read
and write mask, as needed.

Once the NNTP channel has been created for a
site, the server is ready to accept articles from that
site. The reader function for NNTP channels reads
as much data as is available from the descriptor. If
it is in ``get a command'' state, it looks for a simple
\r\n terminator; if it is in ``reading an article'' state,
it looks for a ``\r\n.\r\n'' terminator. If not found, it
just returns; the data will become available at some
point. If the terminator is found, it processes the
data in the buffer. For filing an article, this means
cleaning up the NNTP text escapes, and calling the
article abstraction to process the article.

Processing the article is the largest single rou-
tine in the server. The AssignName shown above
increments the high -water mark for the newsgroup.
If the article has already been written to disk, a link
is made under the new name. (Symbolic links, if
available, can be used if the spool area spans parti-
tions.) If the article has not been written, a
struct iovec array is set up as shown below, where
vertical bars separate each iovec element:

 First headers... 
 Path: |LOCAL_PATH_PREFIX|rest of path... 
 Second headers... 
 |XREF_HEADER| 
 |Article body. 
 
This is a very fast way of writing the article to disk;
it avoids extra memory copies, and is only possible
because the entire article is kept in memory until the
last moment.

Future work

RFC 977 follows the SMTP protocol for send-
ing text: line are terminated with \r\n, a period is
placed before all lines starting with a period, and
data is terminated with a line consisting of a single
period [Postel82]. Innd must scan the text of all
articles it receives and convert them to standard
UNIX format. On the transmission side, innxmit must
read the articles a line at a time in order to add the
extra data. If all newsreading is done via NNTP,
then articles could be stored directly in NNTP for-
mat, and innxmit could read and write the article in
two system calls. The innd gains would not be as
dramatic, but tests show it would still be somewhat
measurable.

There is no NNTP ``TURN'' command, so that
a single connection cannot be used for bidirectional
article transfer. Turn -around is very successful on
UUCP over conventional phone lines, but seems of
limited use on higher -performance network links.
The SMTP protocol has had a ``TURN'' command
since its inception, but it has received no practical
use. Several people find the idea of adding outgoing
transfer to innd attractive, since it is already struc-
tured for multi -host I/O and the idea of caching


 int 
 RemoteReader(cp ) 
     CHANNEL *cp; 
 { 
     int newfd; 
     struct sockadr_in remote; 
     int remsize; 
     
     newfd = accept(cp ->fd, &remote, &remsize); 
     if (InAccessFile(r emsocket)) 
         CHANcreate(new fd, TYPEnntp, STATEgetcmd, NCreader, NCwritedone); 
     else { 
        ForkAndExec("n nrpd", newfd); 
        close(newfd); 
     } 
 } 

 int 
 RemoteSetup() 
 { 
     int fd; 
     
     fd = GetSocketBoundToNNTPPort(); 
     CHANcreate(fd, TYPEremote, STATElisten, RemoteReader, NULL); 
 } 
 
Figure 3 : Listening on an NNTP port
Summer '92 USENIX -- June 8 -June 12, 1992 -- San Antonio, TX