home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-08-21 | 54.3 KB | 1,327 lines |
-
-
- NCSA Telnet
- Developers Guide
-
- This is an ASCII-printable version of the real documentation.
- It was crudely transformed from the original Macintosh MSWord version
- which is also included on this disk. The Mac version is much easier
- to read and contains the same words.
-
-
-
- Version 2.2 release
- July 15, 1988
- National Center for Supercomputing Applications
- The code and documentation are in the public domain.
-
-
- Note to developers:
-
- Thanks for your interest and support of this source code. Please give us your
- comments on where the libraries and/or source need more documentation.
-
- We keep a running list of bugs and modify the source code ourselves, so
- please submit diffs for the changes you make to avoid duplicated effort.
-
- Those of you who care will note that there are ifdefs in "whatami.h" which
- control the difference between compiling on a PC or Macintosh with AppleTalk
- or Ethernet. Most of the code runs on both machines and we will keep it that
- way.
-
- The enclosed "enhancements" list is a list of projects that we ARE NOT
- currently working on, though we may pick up one or two. What we plan to do is
- maintain this list with names of people who are working on each project. If
- you do pick up one of the larger projects, let us know and we will funnel
- questions, help and ideas in your direction. The mailing list may help here
- also.
-
- For questions, send us email first, think about it for a while, read the
- developers documentation again, then give us a call.
-
- Tim Krauskopf
- timk@ncsa.uiuc.edu
- (217)244-0638
-
- Gaige Paulsen
- gaige@ncsa.uiuc.edu
- (217)244-1957
-
-
-
- Compiler Notes
-
- Source changes from 2.1 to 2.2
-
- To help the port to MPW C, internal ints in the protocol code are
- declared with a length, like int16 or int32.
- Some additional calls and events were added to support better
- functionality in the FTP server.
- The drivers for Ethernet were combined on the PC, function
- pointers are used to reference the board calls.
- The AppleTalk and EtherTalk low level routines are switchable in
- the Mac version.
- On the Mac, the stored IP number and configuration information
- were moved to an "NCSA Telnet Settings" file in the System Folder.
- RARP support was added, the special IP number "R","A","R","P" is
- used to indicate that the value has not been looked up yet.
-
- PC
-
- The PC version compiles in Lattice C version 3.0 or 3.1. The Macro Assembler
- code must be modified to work with Microsoft C 4.0 - I don't know what MSC 5.0
- does. Modifying each driver means taking each one and converting the public
- labels and also the return values for all LONGS and POINTERS. MSC uses a
- different calling convention than Lattice C. Also, static pointers in the
- rgX.c programs must be changed. If I get a real good DIFF for the MSC code, I
- will post it.
-
- The assembler code works for Lattice C in IBM Macro Assembler 2.0 (MS 3.0),
- but the Microsoft 4.0 assembler support requires MS Assember 4.0. There are
- different assembler files for supporting each compiler. They are not hard to
- translate, NCSAIO even supports both.
-
- If you have the Lattice C compiler and MASM installed in your PATH, just run
- the batch file: COMPILE.BAT.
-
- Mac
-
- Execute the Unix Aliases script in the Examples directory. The source code as
- posted will make and run under MPW/MPW C 2.02.
-
- We compiled the release 2.2 under Aztec C, but future releases will not use
- Aztec C. Because we are converting as of this release date, Aztec C
- compatible source is available ONLY upon request.
-
-
-
- Suggestions for source code enhancements
-
- User FTP
- The Macinstosh needs a user FTP. The source to user FTP for the
- PC and the source to the background FTP server could be used as an
- example for how to get the file transferred. The user interface
- should obviously be in the Macintosh style and allow file
- transfers to be specified by dragging file names or icons.
- Other UNIX utilities
- They won't be direct ports, but it should be relatively easy to
- create a user rcp, rlogin, finger, rwho, and other BSD utilities.
- PING and finger have been common requests.
- lpr
- lpr is not a difficult protocol, and an lpr application for the PC
- and/or the Mac would be very handy. The problem would be that all
- of the PCs and Macs would have to be trusted hosts. One
- suggestion there is to modify lpd to accept members of a
- particular netgroup in addition to/instead of trusted hosts.
- New drivers
- There are many more Ethernet and Token ring boards for the PC. To
- write a new driver, look at the files in the enet directory for
- examples. For a new Ethernet board, you should only have to
- replace this one file and hook it into pctools.c, no other mods
- will be required.
- New video drivers for PC
- More RG routines can be written for different PC video options.
- Driver for smart board
- The code is divided into the TCP/IP layer and the session layer.
- Certain routines in the TCP/IP layer, all beginning with "net"
- could be replaced with routines which reside inside a "smart"
- board. netopen, netclose, netlisten, netread, netwrite, netsetip,
- for starters, and all of the status routines have to be integrated
- with the board (netqlen, netest). You also have to make sure that
- the events for netevent get posted when anything on the board
- changes.
- New terminal emulator (ADM, DG, etc)
- There is additional documentation on the insertion of new
- emulators. These character oriented terminal emulators should be
- easy to incorporate.
- User mail for PC and Mac
- We need to find a POP server to standardize on. With that, a POP
- client with local disk storage would be easy to do.
- UDP
- The UDP support needs to be filled out by adding support for
- allocation of several ports, each of which buffer data waiting to
- be read by the applications. A buffering scheme for each port
- would keep the last few packets for each port which is being
- listened to. These buffers should be allocated when the UDP port
- is opened (like TCP).
- Tek 4105
- Filter all 4105 commands, find a subset of features to emulate so
- that we can take advantage of color.
- tn3270
- Some interest in different models of the 3270 series emulated,
- color, 44 lines, etc.
- TSR telnet for PC
- A Sidekick-like program which pops up on a certain key sequence
- Windows/DesqView version for PC
- Multiple session output goes to different windows on PC
- Network "ping" monitor
- Ping a bunch of hosts to see which ones are up
- SLIP
- Serial Line IP is now a part of 4.3BSD UNIX, so there is a lot of
- interest in providing all of the NCSA Telnet capabilities over
- phone lines.
- FTP server improvements
- A DIR command (LIST) could show file sizes and other information.
- The names of subdirectories should show up in the list.
-
-
-
- TCP Kernel Calls
-
- Tim Krauskopf July 11, 1988
-
- netsetip(ipnum)
- char ipnum[4]; IP address to use.
- Set my IP address. This routine must be called before
- calling netinit, in order for netinit to know what return
- address to use during initialization. Usually called by a
- session layer routine.
-
- netconfig(hw)
- char *hw; Hardware type - string of <10 chars.
- This call tells the kernel what type of hardware to use,
- "AppleTalk" or "Ether" on the Mac, for example. When
- multiple hardware types are supported, the lower layer must
- be informed of which type to use. Called by Snetinit()
- after the value is read from the configuration file.
-
- netparms(irq,address,ioaddr)
- int irq; Hardware parameter, irq is the interrupt request
- level
- int address; Shared memory segment address to use for starting
- Ethernet driver
- int ioaddr; Hardware I/O address parameter
- Set hardware dependent network configuration. The address
- and I/O address parameters only apply if the hardware needs
- them. These values are filled in by the Session layer in
- most cases.
-
- neteventinit()
- Initializes network event queue so that errors and
- connection information can be posted. VERY IMPORTANT.
- Called by Snetinit().
-
- netarptime(secs)
- int secs; Amount of time in seconds to try to find local hosts or
- local gateways.
- A particularly slow machine may take five seconds to respond
- to an ARP request. Most return an answer within 1/2 second.
- This timeout produces the "local host not responding" error.
-
- netsetmask(mask)
- char mask[4]; Subnet mask to use for future gateway calculations
- Set the subnetting mask. If this is not called before
- netinit(), netinit() will install the default addressing
- mask for the class A,B or C network according to the address
- in netsetip.
-
- netgetmask(mask)
- char mask[4]; location to put the copy of the subnet mask
- Copies the subnetting mask. Not very useful if called
- before the network initialization. Session layer routines
- are typically used to set the value before you try to call
- netgetmask().
-
- netgetip(ipnum)
- char ipnum[4]; Location to place IP address
- Get my IP address. Used when one session layer routine sets
- the IP address but another one needs to know the value. Any
- time after netsetip, netgetip can obtain a copy of the
- address.
-
- char *neterrstring(errno)
- int errno; error number of look up
- Get a pointer to the error string associated with "errno".
- Your custom error handler can use this to look up a "canned"
- error message. Copy the message, print it, whatever. Don't
- worry if the errno is -1, that is a special case that works
- OK. Neterrstring will always return a valid string.
-
- netinit()
- Sets up the hardware and initializes vars. Must be called
- before netopen. Use of Snetinit() is recommended instead of
- netinit(). It calls Sreadhosts(), netinit() and Ssetgates()
- for you.
-
- netsetgate(ipnum)
- char ipnum[4]; IP address of gateway
- Install this IP number as a gateway. Does an ARP request
- immediately, because we assume we will need its Ethernet
- address.
-
- dl = netdlayer(ipnum)
- char *dl; 48-bit Ethernet address or psuedo-address from ARP cache
- char ipnum[4]; IP number to look up with ARP.
- Queries the network with a broadcast ARP request every
- second and returns the Ethernet address for the requested IP
- address. Returns NULL on failure. Blocks for arptime
- seconds or until the response arrives. One of the very few
- blocking calls, only done this way because it is easier and
- ARP is so quick.
-
- netgetrarp()
- Pulls the local Ethernet address stored during the netinit()
- and sends a RARP packet every second. Waits for the
- response and returns 0 for success or negative for failure.
- If a valid response comes in, then netgetip() will return
- the new IP number. Unfortunately, to get everything to
- work, the combination netgetip(); netsetip() must be
- executed to set all of the internal variables.
-
- netsegsize(size)
- int size; new segment size to use for future connection attempts
- Set the maximum segment size (for incoming packets). This
- value will take affect on all future opening connections,
- whether from netopen() or netlisten(). Can be changed any
- time, but cannot affect current connections, only future
- ones. Netlisten takes this value when called, not when the
- connection eventually opens.
-
- netquench(limit)
- int limit; largest TCP window that can be advertised.
- Set the maximum window (for incoming packets) that future
- connections should allow. Will have no effect when set to
- a value over the program's maximum.
-
- netfromport(port)
- int port; TCP protocol number to use for next netopen request.
- When netopen starts a connection, the destination port
- number is requested by the application, i.e. 23 for the
- well-known telnet port. The return (local) port number is
- usually randomly generated to be unique from all local ports
- in use. If the application needs a specific local port
- number (as the default port for FTP data transfers
- requires), this call can force a particular number. The
- setting goes away after the next netopen call.
-
- pn = netopen(ipnum,service)
- char ipnum[4]; Address of machine to connect to, in binary
- int service; TCP port to attempt to connect to, often the WKA for a
- service
- int pn; port number for use in later calls to just about every
- routine available
- Open a connection to another machine (up to 30 times).
- Returns a file descriptor to use in later calls. Netopen is
- often used only in a session layer routine which does name
- to IP address translation before calling netopen. See
- Snetopen() for open which includes name translation.
-
- cnt = netread(pn,buf,len)
- int pn; port number from netopen()
- char *buf; pointer to data space to read into
- int len; maximum length of data to read
- int cnt; returns # of bytes read, -1 on closed connection, 0
- for waiting
- Similar to UNIX read, but using a file descriptor from
- netopen(). Does not block EVER.
-
- cnt = netwrite(pn,buf,len)
- int pn; port number from netopen()
- char *buf; pointer to data space to write from
- int len; length of data to try to write
- int cnt; returns # of bytes written, -1 on closed connection, 0
- for waiting
-
- Similar to UNIX write, but using a file descriptor from
- netopen(). Does not block EVER.
-
- netclose(pn)
- int pn; port number from netopen()
- Close a connection, like closing a file. You must make sure
- (with netpush()) that all data which went through netwrite()
- to this file descriptor has been sent before closing.
- Before closing, you will also want to read all of the
- available data from the connection if you don't want to lose
- it.
-
- netshut()
- Shut down communication, disable interrupts. It is not wise
- to call any network routines at all after calling netshut().
-
- netsleep(secs)
- int secs; number of seconds to wait before returning
- This is what keeps the network drivers alive. It makes sure
- that any required ACKs are sent. Often called with a
- parameter of zero, but can be made to wait some # of secs.
- Has a resolution of 1/18th of a second on PC, 1/60th on Mac.
-
- netest(pn)
- int pn; port number from netopen()
- Returns 0 if the connection is in established mode, <0 if
- one side or the other has closed the connection.
-
- cnt = netpush(pn)
- int pn; port number from netopen()
- int cnt; number of bytes still waiting to be delivered
- (outgoing)
- Sets push bit on transmit, returns size of output queue
- (unacknowledged data). Check to see that this value is zero
- before calling netclose(). Unless you don't care.
-
- netqlen(pn)
- int pn; portnumber from netopen()
- Returns the number of bytes waiting to be read (incoming)
- which have been acked, but have not been taken from the
- queue.
-
- netroom(pn)
- int pn; port number from netopen()
- Get information on buffer space from a port. netroom
- returns the number of bytes available for a netwrite()
- command to write into. If the TCP is caught up, this will
- be WINDOWSIZE, if we are loaded, this could be zero.
-
- netgetftp(a,pn)
- int a[8]; return values
- int pn; port number from netopen()
- Get information about an active connection. Returns the IP
- address of the other machine which is connected to you and
- the incoming and outgoing TCP port numbers in use. a[0] to
- a[3] is the IP number of the other host. Note that these
- are integers, not characters! a[4] and a[5] are the high
- and low bytes (yet stored in integers) of your local port
- number. a[6] and a[7] are the high and low bytes of the
- other side's port number for this connection.
-
- pn = netlisten(service)
- int service; TCP port number to listen to.
- int pn; Returns a port number equivalent to a netopen() port
- number
- Listen to a TCP port number. The TCP will establish the
- connection for you automatically. You will be notified
- with an event when the connection occurs. Try not to get
- the TCP port number confused with the netopen() port number.
- The TCP port number defines the network connection between
- machines while the netopen() port number is a local
- descriptor for a given connection.
-
- netusend(ipnum,port,retport,buf,len)
- char *ipnum[4]; IP number of other machine
- int port,retport; to and from ports for the other machine's UDP socket
- char *buf; data to be sent in the packet
- int len; number of bytes of data to send, must fit in 512 byte
- packet
- Send a UDP packet to another machine, to a certain port,
- with the data in buf, length n.
-
- netulisten(port)
- int port; port to be sensitive about
- Listen for a UDP packet on a certain incoming port. Often
- port is the same as retport on a netusend(). Any packets
- for this port will be kept for reading later. Another
- packet for this port before a neturead will overwrite the
- last one. This should be expanded later to give similar
- socket addressing as TCP uses.
-
- theevent = netgetevent(class,theclass,dat)
- int class; Classes to search for (OR combination)
- int *theclass; Actual class of the event returned (return value)
- int *dat; Data which tags the event
- int theevent; Which event has occurred
- Receive the next event in the queue. Classes are in
- whatami.h. Not usually called by the user because the user
- will want the session layer handling of Sgetevent().
- Returns 0 on no event available.
-
- netputevent(class,event,dat)
- int class; Class of the event to post
- int event; Which event within that class to post
- int dat; The data to carry in the event queue
- Place an event into the event queue to be picked up later.
- The user may want to define classes to be posted this way.
- See Sgetevent().
-
- netputuev(class,event,dat)
- int class; Class of the event to post
- int event; Which event within that class to post
- int dat; The data to carry in the event queue
- Place an event into the event queue. First checks to see if
- there already is an identical such event. If so, another
- copy will not be posted.
-
- netposterr(enum)
- int enum; Error number in errorclass.
- Post a user error message. The error message is one from
- the list in TOOLS.C. This message will wait in the queue
- until an ERRORCLASS event is requested.
-
- cnt = neturead(buf)
- char *buf; data area to drop the UDP packet (<512 bytes)
- int cnt; actual length of the packet which is ready
- Reads the data from a UDP packet which was received.
- Returns the number of bytes read into buf, or -1 if there is
- no packet available to read. Automatically clears the
- incoming UDP buffer for the next read.
-
- Session Layer routines
-
- hostform.h
- Include file which contains the structure of the machine
- information record and the configuration information record.
- Use these structures with the following calls to read or
- manipulate machine specific information. Includes struct
- machinfo and struct config.
- whatami.h
- Currently contains the definition of PC vs. Mac in terms of
- program and compiler settings to get the code to compile on
- both the Mac and PC. Also includes netevent.h.
- netevent.h
- Contains the list of event types, both low-level event types
- used internally, and the events which the application
- program will pay attention to. See documentation section
- on rules for event handling that explain what you can do
- with events.
-
-
- Sgetconfig(conp)
- struct config *conp; Pointer to a config structure which will receive a
- copy of current data
- Copies the config structure to user memory. The hosts file
- contains a lot of configuration information that the
- application may need to know. The structure of the data
- area is in hostform.h.
-
- mp = Shostlook(name)
- char *name; name of machine to get information about
- struct machinfo *mp; Pointer to machine information record
- Takes a machine name (standard ASCII string) and returns a
- pointer to the machine information record associated with
- that name. Searches the sname field first, then the hname
- field. Returns NULL if not found. The structure definition
- is in hostform.h. Take care when writing to fields in this
- structure (i.e. don't). If you mess up the data, strange
- things may happen. Shostlook does a simple lookup on the
- name field, so the "default" record can be looked up if
- necessary.
-
- mp = Sgethost(name)
- char *name; name or IP number of machine to get information about
- struct machinfo *mp; Pointer to machine information record
- Takes a machine name or IP number in ASCII format
- (192.17.20.10) or a special shorthand form (#10) and returns
- a pointer to the machine information record associated with
- that name. Uses Shostlook() to look up name if number is
- not used. Returns NULL if not found. The structure
- definition is in hostform.h. Sgethost guarantees that the
- record returned has a valid IP number which Snetopen() will
- accept. Sgethost should be the primary lookup call to
- determine whether the domain name server is required or not.
- If the IP number is given, a pointer to the "default"
- machine is returned with a temporary IP number installed.
- "default" cannot be returned as a real machine because
- Sgethost guarantees a real IP number in the machine record.
-
- mp = Slooknum(mnum)
- int mnum; Machine number to look for
- struct machinfo *mp; Pointer to machine information record
- Used primarily for domain lookups, this number is unique for
- all entries in the memory host list.
-
- mp = Slookip(ipnum)
- char *ipnum; IP number of the host to look for
- struct machinfo *mp; Pointer to machine information record
- Look up host information when you know the host's IP number.
- Used by background ftp server.
-
- mp = Smadd(name)
- char *name; ASCII name of the host to add to the memory host list
- struct machinfo *mp; Pointer to machine information record
- Adds a machine to the host list, generating a unique host
- number for it. Copies the configuration information from
- "default". Returns a pointer to the machine record created.
- Returns NULL if no memory could be allocated. Be careful
- updating the information in the machine record. If the name
- already exists somewhere as a session or host name, it just
- returns that record pointer.
-
- Shostfile(newname)
- char *newname; pointer to new configuration file name
- Takes a pointer to static storage of the host file name.
- The storage associated with the name must remain allocated.
- Default is "config.tel". Typically called with an argv[]
- parm.
-
- Snetinit()
- Calls Sreadhosts(), netinit(), neteventinit(), and
- Ssetgates() for you and initializes the timer queue.
- Returns non-zero on error. Sreadhosts() sets up the config
- structure, so Sgetconfig() can be called after Snetinit().
- RARP handling is done in Snetinit() - if RARP fails,
- Snetinit returns -2 -- this condition requires a netshut()
- to clear any interrupt drivers. A -1 return means that the
- netinit() never succeeded so the interrupt drivers were
- never installed.
-
- Sreadhosts()
- Reads the hosts file, using the filename provided by
- nethostfile(). Uses the new type of config file. Sets
- Smachlist to NULL before reading the file and creating the
- list. Processes and logs all information to the config
- structure or into the machinfo list. Calls some of the
- setup options for ftp, rcp, screen modes, etc. Called by
- Snetinit, user does not need to call this routine.
-
- Ssetgates()
- This routine is called by Snetinit() automatically. It sets
- the netmask with the field read from the hosts file, turns
- on ftp and rcp if they are specified in the hosts file, and
- traverses the machinfo list to set up any gateways which are
- marked.
-
- pn = Snetopen(mp,tport)
- struct machinfo *mp; Machine information record obtained from Sgethost()
- int tport; TCP port to attempt connection with
- int pn; Port number passed through from netopen()
- Tries to connect to the specified port on that machine and
- returns the port descriptor for netread and netwrite.
- Should be used instead of netopen(). Calls netopen() and
- uses any special configuration information found in the
- machinfo record. Sets a timer for the connection timeout
- which will be posted in an event. You cannot access this
- connection until you are notified with an event that shows
- the connection opened or failed.
-
- Sdomain(name)
- char *name; name of the machine to look up, s/b in DOMAIN format
- Tries to use the DOMAIN name server to look up the IP number
- of the named host. Sdomain() posts appropriate events to
- notify you of the results. If the name does not have any
- periods, the default suffix from the config structure is
- added to the lookup. All domain events return a machine
- number which can be looked up with Slooknum() to find out
- which machine is referred to. Remember, the local host
- file lookup is faster, so look up the machine name with
- Sgethost() first. Returns 0 on success, -1 if there is no
- name server to query.
-
- Snewns()
- Rotate name servers. If there is more than one nameserver
- in the machine list, the one with the next highest number
- will become the current nameserver. Wraps to nameserver 1
- when there are no more nameservers.
-
- Ssetns(ipn)
- char ipn[4]; IP number of nameserver to become primary nameserver.
- For situations when your primary nameserver is not indicated
- in the config file, but is obtained over the network
- somehow, this sets that host up as nameserver #1. The ns #1
- set by Snewns() will rotate to ns #2 as necessary.
-
- Stask()
- Should be called instead of netsleep() to support the timer
- queue and network updates. Sgetevent() calls Stask() for
- you. The FTP server can't function without repeated Stask()
- calls.
-
- Stimerset(class,event,dat,howlong)
- int class; Class of event which should be posted
- int event; Event number which should be posted
- int dat; Associated data which should be posted
- int howlong; Seconds to wait before posting this event
- Stimerset() adds events to the timer queue. Stask()
- contains the checks to post any events which have come due.
-
- Stimerunset(class,event,dat)
- int class; Class of event which should be dequeued
- int event; Event number which should be dequeued
- int dat; Associated data which should be dequeued
- Searches the timer queue for a matching entry and removes
- the entry from the queue without generating an event. The
- timer may have just gone off with the event in the event
- queue. This procedure will not prevent that event from
- occurring, only those which have unexpired timers are
- removed.
-
- theevent = Sgetevent(class,theclass,dat)
- int class; Classes to search for (OR combination)
- int *theclass; Actual class of the event returned (return value)
- int *dat; Data which tags the event
- int theevent; Which event has occurred
- Sgetevent() does the background processing of ftp, rcp and
- domain name lookup. Events are posted with netputevent()
- and are usually posted by lower layer routines. Calling
- Snetopen() will guarantee that you will get either a CONOPEN
- or CONFAIL event depending on how things went. The
- associated data for CONXXXX events is always the port number
- of the connection involved. The routine will return 0 if
- there are no events available. Class types are in whatami.h
- and the user may define new events and classes as described
- under "events".
- Currently, it is quite common to receive undesired extra
- events which are for ports which you don't have defined.
- Check the data tag for validity.
-
- FILE *Sopencap()
- Opens the capture file with the previously stored name.
- Returns a file pointer or NULL if there is an error. Use
- Snewcap() to change the name. Always opens for append.
- Snewcap(name)
- char *name; Name to use for a capture file
- Copies the name into private storage for use by Sopencap().
- Limit of 80 chars on name length (no warning).
-
- Stekmode(m)
- Sftpmode(m)
- Srcpmode(m)
- Scwritemode(m)
- int m; Value of boolean flag to set
- Sets modes and turns switches for the session layer. Tek is
- tektronix mode. FTP and rcp turn the listeners on and off.
- When writemode is 1 (true), direct writes to the screen
- should be enabled. Tek and writemode are simply services to
- the upper layers, they only store the boolean flag.
-
- Stmode()
- Sfmode()
- Srmode()
- Scmode()
- Returns the value of the boolean flag set above.
-
- Snewpsfile(s)
- Snewhpfile(s)
- Snewtekfile(s)
- char *s new file name to use
- For each of the graphic options, Postscript, tek and HPGL,
- the configuration structure maintains a filename as a
- service to higher layers. These routines change those
- filenames. Pointers to the filenames are obtained through
- the structure copy which is retrieved from Sgetconfig().
-
- Scheckpass(user,passwd)
- char *user; User name to check the password of
- char *passwd; The password to check the validity of
- Returns true if the passwd associated with the user field
- matches the value in the password file associated with
- telnet. If there is a password file and the username is not
- present, returns false. If no password file is specified in
- the hosts file, returns true.
-
- Sneedpass()
- Returns a boolean flag indicating whether we need to check
- FTP passwords. The determination is made depending upon
- whether there has been a filename specified with the
- passfile option in the config file.
-
- Scompass(password,encrypt)
- char *password; The password to compare
- char *encrypt; The encryption to check against
- Checks to see if the encrypted string has been encrypted
- from a particular password string. Returns true or false.
-
- Sftpname(s)
- char *s; Space to copy the name of the file being transferred
- The name of the current file being transferred by FTP is
- stored internally. Use Sftpname() to get a copy of that
- internal name.
-
- Sftphost(host)
- char *host; Space to copy the name of the host involved.
- The IP number of the FTP client for FTP transfers is stored
- internally. Use Sftphost() to get a copy of that internal
- number. Then you can look up the host's name with
- Slookip().
-
- Sftpuser(user)
- char *user; Space to copy the username.
- The name field from the FTP USER command is stored
- internally. Use Sftpuser() to get a copy of that name.
-
- Sftpstat(bytes)
- long *bytes; Pointer to long, number of bytes
- The value copied into this long int returns number of bytes
- transferred or left to transfer in the currently active ftp
- transfer. Used to update status displays.
-
-
-
- Events -- how to use them
-
- Non-blocking code
- NCSA Telnet is centered around an event structure similar to
- the Macintosh toolbox event manager. There are no blocking
- routines in the lower layers of NCSA Telnet. We don't
- intend to ever add any blocking routines and we continue to
- eliminate higher layer routines which block for user input.
- A re-write of the user input routines which uses events to
- map keystrokes is not out of the question. Simply put,
- anywhere that a programmer might want to put in code which
- blocks to wait for something to happen, you will find an
- event defined.
- netgetevent() and Sgetevent()
- The routines netgetevent() (at a low level) and
- Sgetevent()(at the session level) look for events which are
- stored in NCSA Telnet's event queue. Sgetevent() calls
- netgetevent(), so if you are using the session layer
- library, you will never call netgetevent(). Sgetevent()
- sifts through the events and captures events related to the
- background name serving and ftp file transfers. All other
- events are passed through to the application.
- Classes
- Events are divided into classes to help different portions
- of the application look for only certain kinds of events.
- When you call one of the getevent routines, the class which
- you pass to the routine is a mask of the OR combination of
- the classes that you want to retrieve from the event queue.
- When the routine returns with a greater than zero event
- number, that mask will have been transformed into the exact
- class to which the returned event belongs. The classes are
- defined below.
- Events
- For each class, several events are defined. They are
- documented individually, along with the use of the data
- value which is returned from the getevent call.
- User-defined events
- Applications programmers are welcome to use class 0x80 (128)
- for their own events. Events in each of the predefined
- classes in the range 128-255 are also available for use.
- Specifically, use events 128-255 of the USERCLASS because
- they will be more convenient to use. Use of any events or
- classes not in these ranges may conflict with future NCSA
- software. If you want certain events to be defined by NCSA,
- let us know. The official "defined events" list will be
- updated periodically.
- Timer events
- Stimerset() and Stimerunset() control a separate queue from
- the event queue. The important thing to know is that when a
- timer goes off, it places its specific event into the event
- queue. You may use user-defined event types to set timers
- for yourself in this queue. Some events like DOMFAIL and
- CONFAIL are caused by timers if something doesn't occur to
- unset the timers for those events.
- minitel.c
- Look at minitel.c for the simplest possible telnet. This
- one doesn't even have a telnet command parser and it only
- talks to BSD hosts. It does show you how to handle events
- for the simple cases.
-
- The following events are defined in netevent.h:
-
-
- #define USERCLASS 1
- #define ICMPCLASS 2
- #define ERRCLASS 4
- #define SCLASS 8
- #define CONCLASS 0x10
-
- #define ERR1 1 /* an error message is waiting, ERRCLASS */
-
- #define IREDIR 1 /* ICMP redirect, ICMPCLASS */
-
- #define CONOPEN 1 /* connection has opened, CONCLASS */
- #define CONDATA 2 /* there is data available on this connection */
- #define CONCLOSE 3 /* the other side has closed its side of the connection */
- #define CONFAIL 4 /* connection open attempt has failed */
-
- #define UDPDATA 1 /* UDP data has arrived on listening port, USERCLASS */
- #define DOMOK 2 /* domain name ready */
- #define DOMFAIL 3 /* domain name lookup failed */
- #define FTPCOPEN 20 /* FTP command connection has opened */
- #define FTPCLOSE 21 /* FTP command connection has closed */
- #define FTPBEGIN 22 /* FTP transfer beginning, dat =1 for get, 0 for put */
- #define FTPEND 23 /* FTP transfer ending */
- #define FTPLIST 24 /* FTP file listing taking place */
- #define FTPUSER 25 /* FTP user name has been entered */
- #define FTPPWOK 26 /* FTP password verified */
- #define FTPPWNO 27 /* FTP password failed */
- #define RCPBEGIN 30 /* RCP beginning */
- #define RCPEND 31 /* RCP ending */
-
- #define UDPTO 1 /* UDP request from DOMAIN timed out, SCLASS */
- #define FTPACT 2 /* FTP transfer is active, keep sending */
- #define TCPTO 3 /* TCP for DOMAIN timed out */
- #define RCPACT 4 /* rcp is active, needs CPU time */
- #define RETRYCON 5 /* retry connection packet, might be lost */
-
-
-
- Class USERCLASS
- Event UDPDATA
- To get this event you must have already called netulisten
- with a port number. A UDP packet with some data has arrived
- for you on that port. The data field for the event is the
- UDP port number which you were listening to. In the future,
- you will be able to listen to multiple ports and the data
- field will become important. Port 998 is arbitrarily used
- by our domain name server.
- Event DOMOK
- To get this event, you must have already placed a domain
- name request. You may get more than one DOMOK for one
- request. The data field contains the machine number of the
- name you looked up. You can look up the machine record with
- Slooknum() now. The IP number has been placed into the
- record. A Snetopen() with that machine record should
- succeed now.
- Event DOMFAIL
- To get this event, you must have already placed a domain
- name request. You may get more than one DOMFAIL for one
- request. The data field contains the machine number of the
- name you looked up. That machine name could not be
- resolved. You may also have an error event waiting for you
- which explains why the resolve failed.
- Event FTPCOPEN
- A command connection has been established to your background
- FTP server. NCSA Telnet uses this to post informative
- messages.
- Event FTPCLOSE
- The command connection for your server FTP has closed.
- Event FTPBEGIN
- A file transfer to or from your machine has begun. The data
- field=1 for get (transfer from) and 0 for put (transfer to)
- transfers.
- Event FTPEND
- A file transfer or a LIST command has ended.
- Event FTPLIST
- A LIST command has begun for your background FTP.
- Event FTPUSER
- A USER command has been entered for the background FTP.
- Event FTPPWOK
- An FTP PASS command has been entered and verified by
- comparing to the entries in the password file.
- Event FTPPWNO
- An FTP PASS command has been entered and rejected by failing
- to match anything in the password file.
- Event RCPBEGIN
- Someone has started an rcp transfer to or from your
- computer.
- Event RCPEND
- That rcp has ended.
- Class ICMPCLASS
- Event IREDIR
- The netsleep() routine automatically does a netgetevent()
- for ICMP redirect messages and performs the addressing
- change required by the ICMP redirect. When an ICMP redirect
- packet is received, this event is posted by the ICMP
- routine. Bugfix in 2.2 makes sure ALL redirects are
- registered.
- Class ERRCLASS
- Event ERR1
- There is currently only one error event which pertains to
- all of the possible errors. These events should be
- reclassified as ERRWARNING, ERRINFO, ERRFATAL, etc., so the
- rest of this class is reserved. The data field contains the
- error number which can be looked up with neterrstring().
- Class SCLASS (session class)
- The entire SCLASS is for special session layer events. You
- will not receive these events from Sgetevent() because they
- are always removed.
- Event UDPTO
- The current UDP domain request timed out.
- Event FTPACT
- When FTP is active, it uses as much CPU as it can get. To
- get more CPU it posts events back to itself.
- Event TCPTO
- not used, we don't need TCP lookups.
- Event RCPACT
- rcp posts this event back to itself when it needs CPU.
- Event RETRYCON
- Snetopen() posts this in a timer to send multiple SYN
- packets if the first one is lost.
- Class CONCLASS
- Event CONOPEN
- A connection has just opened. This may be a connection
- which you are listening to, or one which you are trying to
- open with Snetopen(). Remember Snetopen() does not block
- until the connection is open. The data field returns the
- port number (descriptor) of the connection.
- Event CONDATA
- Data has arrived for a certain port number. The data field
- contains that port number. Because this event always comes
- up when there is data in the incoming TCP buffer, you never
- have to poll netread() to find out if there is data to be
- read. If you get CONDATA events, there is data to be read,
- if you are not getting CONDATA events, then there won't be
- data to be read. Unless you drop an event, of course.
- CONDATA events which arrive after a CONCLOSE event or a
- netclose() call may get a -1 return from netread(),
- indicating that the connection has no more data or does not
- exist.
- Event CONCLOSE
- If the host you are talking to decides to drop the
- connection, or reset it, then you may get a CONCLOSE event.
- This can be interpreted as the last CONDATA event that you
- will get. There may be a large amount of data waiting for
- you to pick it up with netread() even after receiving a
- CONCLOSE event. The correct procedure is to take data from
- netread() until you receive a 0 or -1 return code and then
- call netclose() to finalize your side of the connection.
- Event CONFAIL
- The timer ran out on a connection which you tried to open.
- This does not mean that you are done. You must netclose()
- to allow the memory for that port to be re-used.
-
-
- Virtual Screen Kernel Calls
-
- Gaige B. Paulsen October 31, 1987
- updated July 14,
- 1988
-
- int VSinit(max)
- int max; Maximum number of Virtual screens to allow.
- Initializes the Virtual Screen Kernel for use with up to max
- screens.
- Returns 0 if successful.
-
- VSscrn *VSwhereis(i)
- int i; Virtual Screen to examine.
- Returns the current address of the virtual screen control
- record. This is used for debugging.
-
- int VSnewscreen( maxlines, screensave, maxwid, IDC)
- int maxwid; How wide can this window be. Only tested for 80 and 132.
- int maxlines; Maximum number of lines to save.
- int screensave; Is scrollback enabled at start?
- int IDC; Do we have support for insert and delete of characters.
-
- Creates a new screen if possible. VSnewscreen returns a
- number >=0 if it succeeds, which is to be used as the window
- parameter(w) in all subsequent calls to vs routines. If the
- return value is <0, there was an error, and no screen was
- created.
-
- VSdestroy(w)
- int w; Window number to destroy.
- Destroy the window corresponding to w. Returns an error if
- applicable.
-
- VSdetatch(w)
- int w; Window number to detach.
- Detach the window corresponding to w. Returns an error if
- applicable. Note that this function currently just calls
- VSdestroy(w). Previously and hopefully sometime in the
- future as well, it did/will allow for the destruction of a
- screen without freeing memory.
-
- VSredraw(w,x1,y1,x2,y2)
- int w; Window number to redraw.
- int x1, y1,x2,y2; Bounds of the rectangle to be drawn, in local window
- coordinates.
- Redraw the portion of window w which lies within (x1,y1) -
- (x2,y2). The coordinates are local to the window and should
- NOT be adjusted for scrollback, as most of scrollback is
- handled by the VS routines and not the RS.
-
- VSwrite(w,ptr,len)
- int w; Window number to write to.
- int len; How many characters to write.
- char *ptr; Where to get the characters.
- The big routine. This one is called to write a character
- stream to the virtual screen w. VSwrite calls VSem to parse
- the emulation.
-
- VSclear(w)
- int w; Window number to clear.
- Clear the virtual screen of window w.
-
- char VSkbsend(w,k,echo)
- int w; Window number to send the characters from.
- int echo; Boolean - whether to local echo the key.
- unsigned char k; VT-100 key code to send
- Sends the VT-102 representation of the key represented by k.
- This routine uses somewhat of a hack by calling RSsendstring
- which is supposed to know how to send characters to
- whichever port corresponds to window w. The echo flag only
- applies to special keys (like arrows) and will cause them to
- echo on the local screen as they are transmitted.
-
- VSclearall(w)
- int w; Window number to clear all of.
- This routine currently does nothing. It was originally
- intended clear the current screen and all of the scrollback
- as well as setting the top of the scrollback to the top of
- the available storage space, but this was deemed
- unnecessary.....at least for now.
-
- VSreset(w)
- int w; Window number to reset.
- Resets the virtual screen (w) with respect to VT-100 modes.
- Changes the wrap mode to off and clears the screen as well
- as setting all other modes to their ORIGINAL POWER-ON
- defaults as specified by the VT-100 programmers manual.
-
- char *VSgetline(w,y)
- int w; Window number to get line from.
- int y; Line from which to get the pointer
- This routine in now out of date and SHOULD NOT BE USED
- unless you really know what you are doing. It retrives a
- pointer to the data string associated with line (y) of the
- screen (w). This ONLY works with lines that are on the
- active vt100 screen (lines 0-23).
-
- VSsetrgn(w,x1,y1,x2,y2)
- int w; Window number to set the display region for.
- int x1,y1,x2,y2; The vs's bounding rectangle in GLOBAL VS coordinates .
- Set the current display region for window w to (x1,y1)-
- (x2,y2). This will perform
- scrollback/scrollforward/scrollleft/scrollright/etc. as
- necessary to make the current screen reflect the values of
- the passed display region. It restricts you from doing
- anything really stupid (I hope).
-
- VSgetrgn(w,x1,y1,x2,y2)
- int w; Window number to scroll forward in.
- int *x1,*y1,*x2,*y2; Where to retrieve the display region into.
-
- Get the current value of the display region (as set by
- setrgn and/or modified by the scroll routines as well as
- auto--scroll). Pass pointers to the integers you would like
- to have the values put into.
-
- VSscrolback(w,in)
- int w; Window number to scroll back in.
- int in; Number of lines to scroll back.
- Scroll back in lines in window w if possible. Note that
- this routine will prevent you from scrolling back beyond the
- top of the buffer, so it is safe to call it whenever you get
- a request to scroll back further, even if you don't know if
- there is data left to scroll back into.
-
- VSscrolforward(w,n)
- int w; Window number to scroll forward in.
- int n; Number of lines to scroll forward.
- Scrolls forward n lines in window w. See VSscrolback for
- details.
-
- VSscrolright(w,n)
- int w; Window number to scroll right in.
- int n; Number of columns to scroll right.
- Scrolls right n columns in window w. See VSscrolback for
- details.
-
- VSscrolleft(w,n)
- int w; Window number to scroll forward in.
- int n; Number of columns to scroll left.
- Scrolls left n columns in window w. See VSscrolback for
- details.
-
- VSscrolcontrol(w,scrolon,savescroll)
- int w; Window number to set scroll variables for.
- int scrolon; Do we scroll or don't we?
- int savescroll; Save cleared lines into scrollback.
- Changes the value of the scrolon variable in window w,
- therefore disabling and enabling scrollback, not really
- necessary. If savescroll is on, all clearscreen commands
- will load the text into the scrollback buffer.
-
- VSsnapshot(w)
- int w; Window number to take snapshot of.
- Currently does nothing. Will/should eventually make a copy
- of the current screen into the scrollback buffer. This is
- most easily done by sending 24 line feeds and then copying
- the values of lines (-24) - (-1) into 0-24. But, I hope to
- do this before 2.1 and the source release.
-
- int VSmaxwidth(w)
- int w; Window number to retrieve the maximum width of.
- Retrieves the current maximum width of window w. Used
- primarily to get the maximum possible size of a selection
- for copying. NOTE: a 132 column window in 80 column mode
- returns 80.
-
- long VSgettext(w, x1, y1, x2, y2, charp, max, EOLS)
- int w; Window number to get text from.
- int x1,y1,x2,y2; The starting and ending points of the text in global VS
- coordinates .
- char *charp; Pointer to the destination of the gotten text.
- char *EOLS; Pointer to the string to be used for end of line.
- long max; Maximum number of characters charp can hold.
- Copies a section of text from window w, which corresponds to
- an area starting from the x1th character of line y1 to the
- x2th character of line y2, inclusive of all of the
- characters on lines y1+1 to y2-1 into a buffer pointed at
- by charp to exceed no more than max and inserting the string
- pointed at by EOLS whenever there is a line transition.
- (...whew...) This is mainly used for copy and print of VS
- data. Extraneous blanks are ommitted at the end of lines by
- searching backward to the beginning of the line.
-
- Global VS coordinates vs. local coordinates
-
- Global
- Global coordinates are used to represent a range of
- information that can span the entire VS space as it
- currently exists. To accurately portray the area, we must
- have some standard method of referring to scrollback. For
- this, we have chosen to refer to the top of the currently
- active VT-102 screen as line 0, the bottom of the active
- screen as line 23, and the lines of scrollback as negative
- offsets from line 0. Hence, a line that has been scrolled
- off by a CR-LF would be seen as line -1. To perform actions
- such as scrolling back to the top of the virtual screen, you
- would ask for lines from (top of buffer) to (top of buffer
- +length of display window). Similarly, if you wished to
- scroll to make the right hand side of a 132 column window
- visible, you would ask for the columns from (maxwidth -20)
- to (maxwidth).
- Local
- Local coordinates are used to represent things that happen
- relative to the area being displayed by the Virtual Screen.
- An example would be a portion (or all) of the virtual screen
- being made visible. This action would cause whichever lines
- are in the visible area to be redrawn, therefore you will
- need to inform the VS routines to do this. Since the VS
- routines attempt to maintain as much of the information
- about scrollback by themselves so as not to burden you with
- extraneous information, you pass these coordinates as local
- to the currently active screen. Therefore, a full redraw
- would be line 0 character 0 through line 23 character 79,
- which would then be translated by VSredraw to whatever
- global coordinates are appropriate.
-
- Replacing the Terminal Emulation package in the VS
- routines.
-
- The VS routines can be used as a basis for just about any 24 line screen
- terminal emulator. This document shows how to use the internal routines in
- vsintern.c to construct a vsem.c file as a basis for a new terminal emulator.
-
- VSem(c,ctr) -
- char *c pointer to the buffer to use as input to the emulator
- int ctr how many characters to read from the input buffer
-
- This is the main emulation routine. It is the entry point from VSwrite and
- should be the only thing that needs to be replaced when changing the terminal
- emulation.
-
- escflg: current escape state
- 0 - normal character wait
- 1 - have escape, waiting for next character
- 2 - escape '[' sequence, waiting for parameters
- 3 - escape '#' sequence
- 4 - escape '(' sequence
- 5 - escape ')' sequence
- c: pointer to character currently being parsed
- VSIw: points to the window structure for the current window.
- VSIwn: is the current window number
-
- VSI routines from vsintern.c for use in emulation
-
- VSIreset() - Cause a terminal reset
- VSItabinit() - Initialize tabs to default stat (every 8
- characters)
- VSItabclear() - Clear the tab at the current position
-
- VSIdellines(n,s) - delete n lines at s (current line if s<0)
- VSIinslines(n,s) - insert n lines at s (current line if s<0)
-
- VSIeeol() - erase to end of line
- VSIebol() - erase to beginning of line
- VSIel(s) - erase the entire line s (current line if s<0)
- VSIeeos() - erase to end of screen
- VSIebos() - erase to beginning of screen
- VSIes() - erase the whole screen
-
- VSIrange() - check and resolve range errors for x and y
-
- VSIdraw( VSIwn, x, y, a, len, c)
- - draw len characters at (x,y) in attribute a
- with the chars at c
- VSIinsstring(len,start) - insert len characters at the current position
- with the chars at start
-
- VSIdelchars(x) - delete x characters at the current position
- VSIinschar(x) - insert x blank characters at the current position
- VSItab() - move to next tab stop
- VSIsave() - save current x, y, a
- VSIrestore() - restore previous x,y,a
-
- VSIindex() - index one line
- VSIrindex() - reverse index one line
-
- VTsendpos() - Send the VT-100 cursor report
- VTsendstat() - Send the VT-100 status report
- VTsendident() - Send the VT-100 identity report
- VSIsetoption(toggle) - Set the VT-100 option depending on toggle
-
-
-
- How to write a new PC driver
-
- There are six routines which must be provided in a new
- driver. All of these routines are currently provided in
- assembly language in one file. When you write a new
- driver, you will probably take a current driver and replace
- each of the six routines in the file. The current examples
- are in the ENET subdirectory and the three best examples
- are:
-
- NET501.ASM
- 3COM 3C501 driver. Uses interrupts, and will be a
- reasonable template for other interrupt-driven drivers. I
- highly discourage trying to improve this driver for the
- 3C501. I've tried.
- NETUB.ASM
- Ungermann-Bass (IBM) NIC board driver. Does not use
- interrupts. This driver may be a good template for simple
- shared-memory boards which divide the memory into pages.
- NET5210.ASM
- MICOM NI5210 driver. The NI5210 uses the Intel 82586 chip.
- You will need the Intel databook for this chip in order to
- understand the driver. This driver should be directly
- applicable to all boards which are built around the 82586.
- Works with 8K or 16K boards. Only uses 8K of a 16K board,
- so save your money.
-
- With dual-ported RAM and intelligent chipsets, interrupts are entirely
- unnecessary. The board will automatically buffer a certain number of packets
- which are picked up when NCSA Telnet has time to process incoming packets.
- TCP takes care of preventing overruns.
-
- The six routines are described below. They generally return -1 on error.
- getaddr() is usually called first and etopen must be called next for any of
- the other routines to make sense. Function pointers for the routines are
- declared and installed in PCTOOLS.C. A new driver should install new pointers
- right alongside the existing ones.
-
- etopen(eaddr,irq,addr,ioaddr)
- char eaddr[6]; Hardware ethernet address to use on board.
- int irq; Interrupt request level from configuration file.
- int addr; Shared memory base segment address from configuration file.
- int ioaddr; I/O address from configuration file.
- This routine must do all of the initializations for the
- Ethernet board. Any interrupt drivers must be placed,
- interrupts turned on, base register variables set up,
- packets initialized and the address set for the board. Do
- not return until you are receiving packets. Most drivers
- will ignore some of the fields provided. Map them to
- whatever values are appropriate for your hardware.
-
- getaddr(eaddr,addr,ioaddr)
- char eaddr[6]; Buffer to place address.
- int addr; Base segment address for shared memory
- int ioaddr; Base I/O address for board
- Some of these parameters are also ignored, depending upon
- the hardware. The hardware address from the board's EPROMs
- should be copied into the eaddr buffer. This address is
- generally given back to etopen, so getaddr cannot depend on
- etopen's initialization.
-
- etclose()
- Shut down Ethernet board. Primarily to turn off interrupts.
- This routine can be just a RET for non-interrupt boards.
-
- recv()
- Receive a packet. Used only for boards that do not use
- interrupts. The interrupt handler generally replaces the
- need for recv(). The interrupt handler or recv() must use
- my undocumented buffering scheme. Generally, keep the same
- code and replace the board handling side.
-
- xmit(packet,size)
- char *packet; Address of packet to transmit.
- int size; Size of packet to transmit, including all headers.
- Send out one packet. This is generally not interrupt
- driven. The packet size may be smaller than the minimum
- Ethernet packet size. If so, this routine must take care of
- the details. The frame to transmit always includes the
- entire Ethernet frame header, so non-802.3 drivers may need
- to strip the header to modify higher layer code.
-
- etupdate()
- Remove one packet from the buffer. This routine is
- generally unmodified from driver to driver. The incoming
- packet is not copied from the buffer until fully processed,
- so the driver must wait until etupdate() is called before
- freeing the space back to the buffer.
-
-