home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1993 May / SIMTEL_0593.ISO / msdos / ncsatlnt / dev_note.txt < prev    next >
Text File  |  1991-07-01  |  56KB  |  1,327 lines

  1.  
  2.  
  3. NCSA Telnet
  4. Developers Guide
  5.  
  6. This is an ASCII-printable version of the real documentation.  
  7. It was crudely transformed from the original Macintosh MSWord version
  8. which is also included on this disk.  The Mac version is much easier 
  9. to read and contains the same words.
  10.  
  11.  
  12.  
  13. Version 2.2 release
  14. July 15, 1988
  15. National Center for Supercomputing Applications
  16. The code and documentation are in the public domain.
  17.  
  18.  
  19. Note to developers:
  20.  
  21. Thanks for your interest and support of this source code.  Please give us your 
  22. comments on where the libraries and/or source need more documentation.
  23.  
  24. We keep a running list of bugs and modify the source code ourselves,  so 
  25. please submit diffs for the changes you make to avoid duplicated effort.  
  26.  
  27. Those of you who care will note that there are ifdefs in "whatami.h" which 
  28. control the difference between compiling on a PC or Macintosh with AppleTalk 
  29. or Ethernet.  Most of the code runs on both machines and we will keep it that 
  30. way.
  31.  
  32. The enclosed "enhancements" list is a list of projects that we ARE NOT 
  33. currently working on, though we may pick up one or two.  What we plan to do is 
  34. maintain this list with names of people who are working on each project.  If 
  35. you do pick up one of the larger projects, let us know and we will funnel 
  36. questions, help and ideas in your direction.  The mailing list may help here 
  37. also.  
  38.  
  39. For questions, send us email first, think about it for a while, read the 
  40. developers documentation again, then give us a call.
  41.  
  42. Chris Wilson
  43. cwilson@ncsa.uiuc.edu
  44. (217)244-0702
  45.  
  46. Quincey Koziol
  47. koziol@ncsa.uiuc.edu
  48. (217)244-0705
  49.  
  50.  
  51.  
  52. Compiler Notes
  53.  
  54. Source changes from 2.1 to 2.2
  55.  
  56. To help the port to MPW C, internal ints in the protocol code are 
  57. declared with a length, like int16 or int32.  
  58. Some additional calls and events were added to support better 
  59. functionality in the FTP server.  
  60. The drivers for Ethernet were combined on the PC, function 
  61. pointers are used to reference the board calls.  
  62. The AppleTalk and EtherTalk low level routines are switchable in 
  63. the Mac version.  
  64. On the Mac, the stored IP number and configuration information 
  65. were moved to an "NCSA Telnet Settings" file in the System Folder.  
  66. RARP support was added, the special IP number "R","A","R","P" is 
  67. used to indicate that the value has not been looked up yet.  
  68.  
  69. PC
  70.  
  71. The PC version compiles in Lattice C version 3.0 or 3.1.  The Macro Assembler 
  72. code must be modified to work with Microsoft C 4.0 - I don't know what MSC 5.0 
  73. does.  Modifying each driver means taking each one and converting the public 
  74. labels and also the return values for all LONGS and POINTERS.  MSC uses a 
  75. different calling convention than Lattice C.  Also, static pointers in the 
  76. rgX.c programs must be changed.  If I get a real good DIFF for the MSC code, I 
  77. will post it.  
  78.  
  79. The assembler code works for Lattice C in IBM Macro Assembler 2.0 (MS 3.0), 
  80. but the Microsoft 4.0 assembler support requires MS Assember 4.0.  There are 
  81. different assembler files for supporting each compiler.  They are not hard to 
  82. translate, NCSAIO even supports both.  
  83.  
  84. If you have the Lattice C compiler and MASM installed in your PATH, just run 
  85. the batch file: COMPILE.BAT.
  86.  
  87. Mac
  88.  
  89. Execute the Unix Aliases script in the Examples directory.  The source code as 
  90. posted will make and run under MPW/MPW C 2.02.
  91.  
  92. We compiled the release 2.2 under Aztec C, but future releases will not use 
  93. Aztec C.  Because we are converting as of this release date, Aztec C 
  94. compatible source is available ONLY upon request.
  95.  
  96.  
  97.  
  98. Suggestions for source code enhancements
  99.  
  100. User FTP
  101. The Macinstosh needs a user FTP.  The source to user FTP for the 
  102. PC and the source to the background FTP server could be used as an 
  103. example for how to get the file transferred.  The user interface 
  104. should obviously be in the Macintosh style and allow file 
  105. transfers to be specified by dragging file names or icons.
  106. Other UNIX utilities
  107. They won't be direct ports, but it should be relatively easy to 
  108. create a user rcp, rlogin, finger, rwho, and other BSD utilities.  
  109. PING and finger have been common requests.
  110. lpr
  111. lpr is not a difficult protocol, and an lpr application for the PC 
  112. and/or the Mac would be very handy.  The problem would be that all 
  113. of the PCs and Macs would have to be trusted hosts.  One 
  114. suggestion there is to modify lpd to accept members of a 
  115. particular netgroup in addition to/instead of trusted hosts.
  116. New drivers
  117. There are many more Ethernet and Token ring boards for the PC.  To 
  118. write a new driver, look at the files in the enet directory for 
  119. examples.  For a new Ethernet board, you should only have to 
  120. replace this one file and hook it into pctools.c, no other mods 
  121. will be required.
  122. New video drivers for PC
  123. More RG routines can be written for different PC video options.
  124. Driver for smart board
  125. The code is divided into the TCP/IP layer and the session layer.  
  126. Certain routines in the TCP/IP layer, all beginning with "net" 
  127. could be replaced with routines which reside inside a "smart" 
  128. board.  netopen, netclose, netlisten, netread, netwrite, netsetip, 
  129. for starters, and all of the status routines have to be integrated 
  130. with the board (netqlen, netest).  You also have to make sure that 
  131. the events for netevent get posted when anything on the board 
  132. changes.
  133. New terminal emulator (ADM, DG, etc)
  134. There is additional documentation on the insertion of new 
  135. emulators.  These character oriented terminal emulators should be 
  136. easy to incorporate.
  137. User mail for PC and Mac
  138. We need to find a POP server to standardize on.  With that, a POP 
  139. client with local disk storage would be easy to do.
  140. UDP
  141. The UDP support needs to be filled out by adding support for 
  142. allocation of several ports, each of which buffer data waiting to 
  143. be read by the applications.  A buffering scheme for each port 
  144. would keep the last few packets for each port which is being 
  145. listened to.  These buffers should be allocated when the UDP port 
  146. is opened (like TCP).
  147. Tek 4105 
  148. Filter all 4105 commands, find a subset of features to emulate so 
  149. that we can take advantage of color.
  150. tn3270
  151. Some interest in different models of the 3270 series emulated, 
  152. color, 44 lines, etc.
  153. TSR telnet for PC
  154. A Sidekick-like program which pops up on a certain key sequence
  155. Windows/DesqView version for PC
  156. Multiple session output goes to different windows on PC
  157. Network "ping" monitor
  158. Ping a bunch of hosts to see which ones are up
  159. SLIP
  160. Serial Line IP is now a part of 4.3BSD UNIX, so there is a lot of 
  161. interest in providing all of the NCSA Telnet capabilities over 
  162. phone lines.
  163. FTP server improvements
  164. A DIR command (LIST) could show file sizes and other information.  
  165. The names of subdirectories should show up in the list.
  166.  
  167.  
  168.  
  169. TCP Kernel Calls
  170.  
  171. Tim Krauskopf                        July 11, 1988
  172.  
  173. netsetip(ipnum)
  174. char ipnum[4];        IP address to use.
  175. Set my IP address.  This routine must be called before 
  176. calling netinit, in order for netinit to know what return 
  177. address to use during initialization.  Usually called by a 
  178. session layer routine.
  179.  
  180. netconfig(hw)
  181. char *hw;        Hardware type - string of <10 chars.
  182. This call tells the kernel what type of hardware to use, 
  183. "AppleTalk" or "Ether" on the Mac, for example.  When 
  184. multiple hardware types are supported, the lower layer must 
  185. be informed of which type to use.  Called by Snetinit() 
  186. after the value is read from the configuration file.
  187.  
  188. netparms(irq,address,ioaddr)
  189. int irq;            Hardware parameter,  irq is the interrupt request 
  190. level
  191. int address;        Shared memory segment address to use for starting 
  192. Ethernet driver
  193. int ioaddr;        Hardware I/O address parameter
  194. Set hardware dependent network configuration.  The address 
  195. and I/O address parameters only apply if the hardware needs 
  196. them.  These values are filled in by the Session layer in 
  197. most cases.
  198.  
  199. neteventinit()
  200. Initializes network event queue so that errors and 
  201. connection information can be posted.  VERY IMPORTANT.  
  202. Called by Snetinit().
  203.  
  204. netarptime(secs)
  205. int secs;        Amount of time in seconds to try to find local hosts or 
  206. local gateways.
  207. A particularly slow machine may take five seconds to respond 
  208. to an ARP request.  Most return an answer within 1/2 second.   
  209. This timeout produces the "local host not responding" error.
  210.  
  211. netsetmask(mask)
  212. char mask[4];        Subnet mask to use for future gateway calculations
  213. Set the subnetting mask.  If this is not called before 
  214. netinit(),  netinit() will install the default addressing 
  215. mask for the class A,B or C network according to the address 
  216. in netsetip.
  217.  
  218. netgetmask(mask)
  219. char mask[4];        location to put the copy of the subnet mask
  220. Copies the subnetting mask.  Not very useful if called 
  221. before the network initialization.  Session layer routines 
  222. are typically used to set the value before you try to call 
  223. netgetmask().
  224.  
  225. netgetip(ipnum)
  226. char ipnum[4];        Location to place IP address
  227. Get my IP address.  Used when one session layer routine sets 
  228. the IP address but another one needs to know the value.  Any 
  229. time after netsetip, netgetip can obtain a copy of the 
  230. address.
  231.  
  232. char *neterrstring(errno)
  233. int errno;        error number of look up
  234. Get a pointer to the error string associated with "errno".  
  235. Your custom error handler can use this to look up a "canned" 
  236. error message.  Copy the message, print it, whatever.  Don't 
  237. worry if the errno is -1, that is a special case that works 
  238. OK.  Neterrstring will always return a valid string.
  239.  
  240. netinit()
  241. Sets up the hardware and initializes vars.  Must be called 
  242. before netopen.  Use of Snetinit() is recommended instead of 
  243. netinit().  It calls Sreadhosts(), netinit() and Ssetgates() 
  244. for you.
  245.  
  246. netsetgate(ipnum)
  247. char ipnum[4];        IP address of gateway
  248. Install this IP number as a gateway.  Does an ARP request 
  249. immediately, because we assume we will need its Ethernet 
  250. address.
  251.  
  252. dl = netdlayer(ipnum)
  253. char *dl;        48-bit Ethernet address or psuedo-address from ARP cache
  254. char  ipnum[4];        IP number to look up with ARP.
  255. Queries the network with a broadcast ARP request every 
  256. second and returns the Ethernet address for the requested IP 
  257. address.  Returns NULL on failure.  Blocks for arptime 
  258. seconds or until the response arrives.  One of the very few 
  259. blocking calls, only done this way because it is easier and 
  260. ARP is so quick.
  261.  
  262. netgetrarp()
  263. Pulls the local Ethernet address stored during the netinit() 
  264. and sends a RARP packet every second.  Waits for the 
  265. response and returns 0 for success or negative for failure.  
  266. If a valid response comes in, then netgetip() will return 
  267. the new IP number.  Unfortunately, to get everything to 
  268. work, the combination netgetip(); netsetip() must be 
  269. executed to set all of the internal variables.
  270.  
  271. netsegsize(size)
  272. int size;        new segment size to use for future connection attempts
  273. Set the maximum segment size (for incoming packets).  This 
  274. value will take affect on all future opening connections, 
  275. whether from netopen() or netlisten().  Can be changed any 
  276. time, but cannot affect current connections, only future 
  277. ones.  Netlisten takes this value when called, not when the 
  278. connection eventually opens.
  279.  
  280. netquench(limit)
  281. int limit;        largest TCP window that can be advertised.  
  282. Set the maximum window (for incoming packets) that future 
  283. connections should allow.   Will have no effect when set to 
  284. a value over the program's maximum.
  285.  
  286. netfromport(port)
  287. int port;        TCP protocol number to use for next netopen request.
  288. When netopen starts a connection, the destination port 
  289. number is requested by the application, i.e. 23 for the 
  290. well-known telnet port.  The return (local) port number is 
  291. usually randomly generated to be unique from all local ports 
  292. in use.  If the application needs a specific local port 
  293. number (as the default port for FTP data transfers 
  294. requires), this call can force a particular number.  The 
  295. setting goes away after the next netopen call.
  296.  
  297. pn = netopen(ipnum,service)
  298. char ipnum[4];        Address of machine to connect to, in binary
  299. int service;        TCP port to attempt to connect to, often the WKA for a 
  300. service
  301. int pn;            port number for use in later calls to just about every 
  302. routine available
  303. Open a connection to another machine (up to 30 times).  
  304. Returns a file descriptor to use in later calls.  Netopen is 
  305. often used only in a session layer routine which does name 
  306. to IP address translation before calling netopen.  See 
  307. Snetopen() for open which includes name translation.
  308.  
  309. cnt = netread(pn,buf,len)
  310. int pn;            port number from netopen()
  311. char *buf;        pointer to data space to read into
  312. int len;            maximum length of data to read
  313. int cnt;            returns # of bytes read, -1 on closed connection, 0 
  314. for waiting
  315. Similar to UNIX read, but using a file descriptor from 
  316. netopen().  Does not block EVER.
  317.  
  318. cnt = netwrite(pn,buf,len)
  319. int pn;            port number from netopen()
  320. char *buf;        pointer to data space to write from
  321. int len;            length of data to try to write
  322. int cnt;            returns # of bytes written, -1 on closed connection, 0 
  323. for waiting
  324.  
  325. Similar to UNIX write, but using a file descriptor from 
  326. netopen().  Does not block EVER.
  327.  
  328. netclose(pn)    
  329. int pn;            port number from netopen()
  330. Close a connection, like closing a file.  You must make sure 
  331. (with netpush()) that all data which went through netwrite() 
  332. to this file descriptor has been sent before closing.  
  333. Before closing, you will also want to read all of the 
  334. available data from the connection if you don't want to lose 
  335. it.
  336.  
  337. netshut()
  338. Shut down communication, disable interrupts.  It is not wise 
  339. to call any network routines at all after calling netshut().
  340.  
  341. netsleep(secs)
  342. int secs;        number of seconds to wait before returning
  343. This is what keeps the network drivers alive.  It makes sure 
  344. that any required ACKs are sent.  Often called with a 
  345. parameter of zero, but can be made to wait some # of secs.  
  346. Has a resolution of 1/18th of a second on PC, 1/60th on Mac.
  347.  
  348. netest(pn)
  349. int pn;            port number from netopen()
  350. Returns 0 if the connection is in established mode, <0 if 
  351. one side or the other has closed the connection.
  352.  
  353. cnt = netpush(pn)
  354. int pn;            port number from netopen()
  355. int cnt;            number of bytes still waiting to be delivered 
  356. (outgoing)
  357. Sets push bit on transmit, returns size of output queue 
  358. (unacknowledged data).  Check to see that this value is zero 
  359. before calling netclose().  Unless you don't care.
  360.  
  361. netqlen(pn)
  362. int pn;            portnumber from netopen()
  363. Returns the number of bytes waiting to be read (incoming) 
  364. which have been acked, but have not been taken from the 
  365. queue.
  366.  
  367. netroom(pn)
  368. int pn;            port number from netopen()
  369. Get information on buffer space from a port.  netroom 
  370. returns the number of bytes available for a netwrite() 
  371. command to write into.  If the TCP is caught up, this will 
  372. be WINDOWSIZE, if we are loaded, this could be zero.
  373.  
  374. netgetftp(a,pn)
  375. int a[8];        return values
  376. int pn;            port number from netopen()
  377. Get information about an active connection.  Returns the IP 
  378. address of the other machine which is connected to you and 
  379. the incoming and outgoing  TCP port numbers in use.  a[0] to 
  380. a[3] is the IP number of the other host.  Note that these 
  381. are integers, not characters!  a[4]  and a[5] are the high 
  382. and low bytes (yet stored in integers) of your local port 
  383. number.  a[6] and a[7] are the high and low bytes of the 
  384. other side's port number for this connection. 
  385.  
  386. pn = netlisten(service)
  387. int service;        TCP port number to listen to.
  388. int pn;            Returns a port number equivalent to a netopen() port 
  389. number
  390. Listen to a TCP port number.  The TCP will establish the 
  391. connection for you automatically.   You will be notified 
  392. with an event when the connection occurs.  Try not to get 
  393. the TCP port number confused with the netopen() port number.  
  394. The TCP port number defines the network connection between 
  395. machines while the netopen() port number is a local 
  396. descriptor for a given connection.
  397.  
  398. netusend(ipnum,port,retport,buf,len)
  399. char *ipnum[4];    IP number of other machine
  400. int port,retport;        to and from ports for the other machine's UDP socket
  401. char *buf;        data to be sent in the packet
  402. int len;            number of bytes of data to send, must fit in 512 byte 
  403. packet
  404. Send a UDP packet to another machine, to a certain port, 
  405. with the data in buf, length n.
  406.  
  407. netulisten(port)
  408. int port;        port to be sensitive about
  409. Listen for a UDP packet on a certain incoming port.  Often 
  410. port is the same as retport on a netusend().  Any packets 
  411. for this port will be kept for reading later.  Another 
  412. packet for this port before a neturead will overwrite the 
  413. last one.  This should be expanded later to give similar 
  414. socket addressing as TCP uses.
  415.  
  416. theevent = netgetevent(class,theclass,dat)
  417. int class;        Classes to search for (OR combination)
  418. int *theclass;        Actual class of the event returned (return value)
  419. int *dat;        Data which tags the event
  420. int theevent;        Which event has occurred
  421. Receive the next event in the queue.  Classes are in 
  422. whatami.h.  Not usually called by the user because the user 
  423. will want the session layer handling of Sgetevent().  
  424. Returns 0 on no event available.
  425.  
  426. netputevent(class,event,dat)
  427. int class;        Class of the event to post
  428. int event;        Which event within that class to post
  429. int dat;            The data to carry in the event queue
  430. Place an event into the event queue to be picked up later.  
  431. The user may want to define classes to be posted this way.   
  432. See Sgetevent().
  433.  
  434. netputuev(class,event,dat)
  435. int class;        Class of the event to post
  436. int event;        Which event within that class to post
  437. int dat;            The data to carry in the event queue
  438. Place an event into the event queue.  First checks to see if 
  439. there already is an identical such event.  If so, another 
  440. copy will not be posted.
  441.  
  442. netposterr(enum)
  443. int enum;        Error number in errorclass.
  444. Post a user error message.  The error message is one from 
  445. the list in TOOLS.C.  This message will wait in the queue 
  446. until an ERRORCLASS event is requested.
  447.  
  448. cnt = neturead(buf)
  449. char *buf;        data area to drop the UDP packet (<512 bytes)
  450. int cnt;            actual length of the packet which is ready
  451. Reads the data from a UDP packet which was received.  
  452. Returns the number of bytes read into buf, or -1 if there is 
  453. no packet available to read.  Automatically clears the 
  454. incoming UDP buffer for the next read.
  455.  
  456. Session Layer routines
  457.  
  458. hostform.h
  459. Include file which contains the structure of the machine 
  460. information record and the configuration information record.  
  461. Use these structures with the following calls to read or 
  462. manipulate machine specific information.  Includes struct 
  463. machinfo and struct config.
  464. whatami.h
  465. Currently contains the definition of PC vs. Mac in terms of 
  466. program and compiler settings to get the code to compile on 
  467. both the Mac and PC.  Also includes netevent.h.
  468. netevent.h
  469. Contains the list of event types, both low-level event types 
  470. used internally, and the events which the application 
  471. program will pay attention to.   See documentation section 
  472. on rules for event handling that explain what you can do 
  473. with events.
  474.  
  475.  
  476. Sgetconfig(conp)
  477. struct config *conp;    Pointer to a config structure which will receive a 
  478. copy of current data
  479. Copies the config structure to user memory.  The hosts file 
  480. contains a lot of configuration information that the 
  481. application may need to know.  The structure of the data 
  482. area is in hostform.h.  
  483.  
  484. mp = Shostlook(name)
  485. char *name;        name of machine to get information about
  486. struct machinfo *mp;    Pointer to machine information record
  487. Takes a machine name (standard ASCII string) and returns a 
  488. pointer to the machine information record associated with 
  489. that name.  Searches the sname field first, then the hname 
  490. field.  Returns NULL if not found.  The structure definition 
  491. is in hostform.h.  Take care when writing to fields in this 
  492. structure (i.e. don't).  If you mess up the data, strange 
  493. things may happen.  Shostlook does  a simple lookup on the 
  494. name field, so the "default" record can be looked up if 
  495. necessary.
  496.  
  497. mp = Sgethost(name)
  498. char *name;        name or IP number of machine to get information about
  499. struct machinfo *mp;    Pointer to machine information record
  500. Takes a machine name or IP number in ASCII format 
  501. (192.17.20.10) or a special shorthand form (#10) and returns 
  502. a pointer to the machine information record associated with 
  503. that name.   Uses Shostlook() to look up name if number is 
  504. not used.  Returns NULL if not found.  The structure 
  505. definition is in hostform.h.  Sgethost guarantees that the 
  506. record returned has a valid IP number which Snetopen() will 
  507. accept.  Sgethost should be the primary lookup call to 
  508. determine whether the domain name server is required or not.  
  509. If the IP number is given, a pointer to the "default" 
  510. machine is returned with a temporary IP number installed.  
  511. "default" cannot be returned as a real machine because 
  512. Sgethost guarantees a real IP number in the machine record.
  513.  
  514. mp = Slooknum(mnum)
  515. int mnum;        Machine number to look for
  516. struct machinfo *mp;    Pointer to machine information record
  517. Used primarily for domain lookups, this number is unique for 
  518. all entries in the memory host list.
  519.  
  520. mp = Slookip(ipnum)
  521. char *ipnum;        IP number of the host to look for
  522. struct machinfo *mp;    Pointer to machine information record
  523. Look up host information when you know the host's IP number.  
  524. Used by background ftp server.
  525.  
  526. mp = Smadd(name)
  527. char *name;        ASCII name of the host to add to the memory host list
  528. struct machinfo *mp;    Pointer to machine information record
  529. Adds a machine to the host list, generating a unique host 
  530. number for it.  Copies the configuration information from 
  531. "default".  Returns a pointer to the machine record created.  
  532. Returns NULL if no memory could be allocated.  Be careful 
  533. updating the information in the machine record.  If the name 
  534. already exists somewhere as a session or host name, it just 
  535. returns that record pointer.
  536.  
  537. Shostfile(newname)
  538. char *newname;    pointer to new configuration file name
  539. Takes a pointer to static storage of the host file name.   
  540. The storage associated with the name must remain allocated.  
  541. Default is "config.tel".  Typically called with an argv[] 
  542. parm.
  543.  
  544. Snetinit()
  545. Calls Sreadhosts(), netinit(), neteventinit(), and 
  546. Ssetgates() for you and initializes the timer queue.    
  547. Returns non-zero on error.  Sreadhosts() sets up the config 
  548. structure, so Sgetconfig() can be called after Snetinit().  
  549. RARP handling is done in Snetinit() - if RARP fails, 
  550. Snetinit returns -2 -- this condition requires a netshut() 
  551. to clear any interrupt drivers.  A -1 return means that the 
  552. netinit() never succeeded so the interrupt drivers were 
  553. never installed.
  554.  
  555. Sreadhosts()
  556. Reads the hosts file, using the filename provided by 
  557. nethostfile().  Uses the new type of config file.  Sets 
  558. Smachlist to NULL before reading the file and creating the 
  559. list.  Processes and logs all information to the config 
  560. structure or into the machinfo list.  Calls some of the 
  561. setup options for ftp, rcp, screen modes, etc.  Called by 
  562. Snetinit, user does not need to call this routine. 
  563.  
  564. Ssetgates()
  565. This routine is called by Snetinit() automatically.  It sets 
  566. the netmask with the field read from the hosts file, turns 
  567. on ftp and rcp if they are specified in the hosts file, and 
  568. traverses the machinfo list to set up any gateways which are 
  569. marked.
  570.  
  571. pn = Snetopen(mp,tport)
  572. struct machinfo *mp;    Machine information record obtained from Sgethost()
  573. int tport;        TCP port to attempt connection with
  574. int pn;            Port number passed through from netopen()
  575. Tries to connect to the specified port on that machine and 
  576. returns the port descriptor for netread and netwrite.  
  577. Should be used instead of netopen().  Calls netopen() and 
  578. uses any special configuration information found in the 
  579. machinfo record.  Sets a timer for the connection timeout 
  580. which will be posted in an event.  You cannot access this 
  581. connection until you are notified with an event that shows 
  582. the connection opened or failed.
  583.  
  584. Sdomain(name)
  585. char *name;        name of the machine to look up, s/b in DOMAIN format
  586. Tries to use the DOMAIN name server to look up the IP number 
  587. of the named host.   Sdomain() posts appropriate events to 
  588. notify you of the results.  If the name does not have any 
  589. periods, the default suffix from the config structure is 
  590. added to the lookup.  All domain events return a machine 
  591. number which can be looked up with Slooknum() to find out 
  592. which machine is referred to.   Remember, the local host 
  593. file lookup is faster, so look up the machine name with 
  594. Sgethost() first.  Returns 0 on success, -1 if there is no 
  595. name server to query.
  596.  
  597. Snewns()
  598. Rotate name servers.  If there is more than one nameserver 
  599. in the machine list, the one with the next highest number 
  600. will become the current nameserver.  Wraps to nameserver 1 
  601. when there are no more nameservers.
  602.  
  603. Ssetns(ipn)
  604. char ipn[4];        IP number of nameserver to become primary nameserver.
  605. For situations when your primary nameserver is not indicated 
  606. in the config file, but is obtained over the network 
  607. somehow, this sets that host up as nameserver #1.  The ns #1 
  608. set by Snewns() will rotate to ns #2 as necessary.
  609.  
  610. Stask()
  611. Should be called instead of netsleep() to support the timer 
  612. queue and network updates.   Sgetevent() calls Stask() for 
  613. you.  The FTP server can't function without repeated Stask() 
  614. calls.
  615.  
  616. Stimerset(class,event,dat,howlong)
  617. int class;        Class of event which should be posted
  618. int event;        Event number which should be posted
  619. int dat;            Associated data which should be posted
  620. int howlong;        Seconds to wait before posting this event
  621. Stimerset() adds events to the timer queue.  Stask() 
  622. contains the checks to post any events which have come due. 
  623.  
  624. Stimerunset(class,event,dat)
  625. int class;        Class of event which should be dequeued
  626. int event;        Event number which should be dequeued
  627. int dat;            Associated data which should be dequeued
  628. Searches the timer queue for a matching entry and removes 
  629. the entry from the queue without generating an event.  The 
  630. timer may have just gone off with the event in the event 
  631. queue.  This procedure will not prevent that event from 
  632. occurring, only those which have unexpired timers are 
  633. removed.
  634.  
  635. theevent = Sgetevent(class,theclass,dat)
  636. int class;        Classes to search for (OR combination)
  637. int *theclass;        Actual class of the event returned (return value)
  638. int *dat;        Data which tags the event
  639. int theevent;        Which event has occurred
  640. Sgetevent() does the background processing of ftp, rcp and 
  641. domain name lookup.  Events are posted with netputevent() 
  642. and are usually posted by lower layer routines.  Calling 
  643. Snetopen() will guarantee that you will get either a CONOPEN 
  644. or CONFAIL event depending on how things went.  The 
  645. associated data for CONXXXX events is always the port number 
  646. of the connection involved.  The routine will return 0 if 
  647. there are no events available.  Class types are in whatami.h 
  648. and the user may define new events and classes as described 
  649. under "events".  
  650. Currently, it is quite common to receive undesired extra 
  651. events which are for ports which you don't have defined.  
  652. Check the data tag for validity.
  653.  
  654. FILE *Sopencap()
  655. Opens the capture file with the previously stored name.  
  656. Returns a file pointer or NULL if there is an error.  Use 
  657. Snewcap() to change the name.  Always opens for append.
  658. Snewcap(name)
  659. char *name;        Name to use for a capture file
  660. Copies the name into private storage for use by Sopencap().  
  661. Limit of 80 chars on name length (no warning).
  662.  
  663. Stekmode(m)
  664. Sftpmode(m)
  665. Srcpmode(m)
  666. Scwritemode(m)    
  667. int m;            Value of boolean flag to set
  668. Sets modes and turns switches for the session layer.  Tek is 
  669. tektronix mode.  FTP and rcp turn the listeners on and off.  
  670. When writemode is 1 (true), direct writes to the screen 
  671. should be enabled.  Tek and writemode are simply services to 
  672. the upper layers, they only store the boolean flag.
  673.  
  674. Stmode()
  675. Sfmode()
  676. Srmode()
  677. Scmode()    
  678. Returns the value of the boolean flag set above.  
  679.  
  680. Snewpsfile(s)
  681. Snewhpfile(s)
  682. Snewtekfile(s)
  683. char *s            new file name to use
  684. For each of the graphic options, Postscript, tek and HPGL, 
  685. the configuration structure maintains a filename as a 
  686. service to higher layers.  These routines change those 
  687. filenames.  Pointers to the filenames are obtained through 
  688. the structure copy which is retrieved from Sgetconfig().
  689.  
  690. Scheckpass(user,passwd)
  691. char *user;        User name to check the password of
  692. char *passwd;        The password to check the validity of
  693. Returns true if the passwd associated with the user field 
  694. matches the value in the password file associated with 
  695. telnet.  If there is a password file and the username is not 
  696. present, returns false.  If no password file is specified in 
  697. the hosts file, returns true.
  698.  
  699. Sneedpass()
  700. Returns a boolean flag indicating whether we need to check 
  701. FTP passwords.  The determination is made depending upon 
  702. whether there has been a filename specified with the 
  703. passfile option in the config file.
  704.  
  705. Scompass(password,encrypt)
  706. char *password;    The password to compare
  707. char *encrypt;        The encryption to check against
  708. Checks to see if the encrypted string has been encrypted 
  709. from a particular password string.   Returns true or false.
  710.  
  711. Sftpname(s)
  712. char *s;        Space to copy the name of the file being transferred
  713. The name of the current file being transferred by FTP is 
  714. stored internally.  Use Sftpname() to get a copy of that 
  715. internal name.
  716.  
  717. Sftphost(host)
  718. char *host;        Space to copy the name of the host involved.
  719. The IP number of the FTP client for FTP transfers is stored 
  720. internally.  Use Sftphost() to get a copy of that internal 
  721. number.  Then you can look up the host's name with 
  722. Slookip().
  723.  
  724. Sftpuser(user)
  725. char *user;        Space to copy the username.
  726. The name field from the FTP USER command is stored 
  727. internally.  Use Sftpuser() to get a copy of that name.
  728.  
  729. Sftpstat(bytes)
  730. long *bytes;        Pointer to long, number of bytes
  731. The value copied into this long int returns number of bytes 
  732. transferred or left to transfer in the currently active ftp 
  733. transfer.  Used to update status displays.
  734.  
  735.  
  736.  
  737. Events -- how to use them
  738.  
  739. Non-blocking code
  740. NCSA Telnet is centered around an event structure similar to 
  741. the Macintosh toolbox event manager.  There are no blocking 
  742. routines in the lower layers of NCSA Telnet.  We don't 
  743. intend to ever add any blocking routines and we continue to 
  744. eliminate higher layer routines which block for user input.  
  745. A re-write of the user input routines which uses events to 
  746. map keystrokes is not out of the question.  Simply put, 
  747. anywhere that a programmer might want to put in code which 
  748. blocks to wait for something to happen, you will find an 
  749. event defined.  
  750. netgetevent() and Sgetevent()
  751. The routines netgetevent() (at a low level) and 
  752. Sgetevent()(at the session level) look for events which are 
  753. stored in NCSA Telnet's event queue.  Sgetevent() calls 
  754. netgetevent(), so if you are using the session layer 
  755. library, you will never call netgetevent().  Sgetevent() 
  756. sifts through the events and captures events related to the 
  757. background name serving and ftp file transfers.  All other 
  758. events are passed through to the application.
  759. Classes
  760. Events are divided into classes to help different portions 
  761. of the application look for only certain kinds of events.   
  762. When you call one of the getevent routines, the class which 
  763. you pass to the routine is a mask of the OR combination of 
  764. the classes that you want to retrieve from the event queue.  
  765. When the routine returns with a greater than zero event 
  766. number, that mask will have been transformed into the exact 
  767. class to which the returned event belongs.  The classes are 
  768. defined below.
  769. Events
  770. For each class, several events are defined.  They are 
  771. documented individually, along with the use of the data 
  772. value which is returned from the getevent call.
  773. User-defined events
  774. Applications programmers are welcome to use class 0x80 (128) 
  775. for their own events.  Events in each of the predefined 
  776. classes in the range 128-255 are also available for use.  
  777. Specifically, use events 128-255 of the USERCLASS because 
  778. they will be more convenient to use.  Use of any events or 
  779. classes not in these ranges may conflict with future NCSA 
  780. software.  If you want certain events to be defined by NCSA, 
  781. let us know.  The official "defined events" list will be 
  782. updated periodically.
  783. Timer events
  784. Stimerset() and Stimerunset() control a separate queue from 
  785. the event queue.  The important thing to know is that when a 
  786. timer goes off, it places its specific event into the event 
  787. queue.  You may use user-defined event types to set timers 
  788. for yourself in this queue.  Some events like DOMFAIL and 
  789. CONFAIL are caused by timers if something doesn't occur to 
  790. unset the timers for those events.
  791. minitel.c
  792. Look at minitel.c for the simplest possible telnet.  This 
  793. one doesn't even have a telnet command parser and it only 
  794. talks to BSD hosts.  It does show you how to handle events 
  795. for the simple cases.
  796.  
  797. The following events are defined in netevent.h:
  798.  
  799.  
  800. #define USERCLASS    1
  801. #define ICMPCLASS    2
  802. #define ERRCLASS        4
  803. #define SCLASS    8
  804. #define CONCLASS    0x10
  805.  
  806. #define ERR1        1    /* an error message is waiting, ERRCLASS */
  807.  
  808. #define IREDIR    1    /* ICMP redirect, ICMPCLASS */
  809.  
  810. #define CONOPEN     1    /* connection has opened, CONCLASS */
  811. #define CONDATA     2      /* there is data available on this connection */
  812. #define CONCLOSE     3    /* the other side has closed its side of the connection */
  813. #define CONFAIL     4    /* connection open attempt has failed */
  814.  
  815. #define UDPDATA     1    /* UDP data has arrived on listening port, USERCLASS */
  816. #define DOMOK        2    /* domain name ready */
  817. #define DOMFAIL     3    /* domain name lookup failed */
  818. #define FTPCOPEN     20     /* FTP command connection has opened */
  819. #define FTPCLOSE     21     /* FTP command connection has closed */
  820. #define FTPBEGIN    22     /* FTP transfer beginning, dat =1 for get, 0 for put */
  821. #define FTPEND       23     /* FTP transfer ending */
  822. #define FTPLIST     24     /* FTP file listing taking place */
  823. #define FTPUSER      25     /* FTP user name has been entered */
  824. #define FTPPWOK     26     /* FTP password verified */
  825. #define FTPPWNO     27     /* FTP password failed */
  826. #define RCPBEGIN     30    /* RCP beginning */
  827. #define RCPEND     31    /* RCP ending */
  828.  
  829. #define UDPTO     1    /* UDP request from DOMAIN timed out, SCLASS */
  830. #define FTPACT    2    /* FTP transfer is active, keep sending */
  831. #define TCPTO      3    /* TCP for DOMAIN timed out */
  832. #define RCPACT     4    /* rcp is active, needs CPU time */
  833. #define RETRYCON     5    /* retry connection packet, might be lost */
  834.  
  835.  
  836.  
  837. Class USERCLASS
  838. Event UDPDATA
  839. To get this event you must have already called netulisten 
  840. with a port number.  A UDP packet with some data has arrived 
  841. for you on that port.  The data field for the event is the 
  842. UDP port number which you were listening to.  In the future, 
  843. you will be able to listen to multiple ports and the data 
  844. field will become important.  Port 998 is arbitrarily used 
  845. by our domain name server.
  846. Event DOMOK
  847. To get this event, you must have already placed a domain 
  848. name request.  You may get more than one DOMOK for one 
  849. request.  The data field contains the machine number of the 
  850. name you looked up.  You can look up the machine record with 
  851. Slooknum() now.  The IP number has been placed into the 
  852. record.  A Snetopen() with that machine record should 
  853. succeed now.
  854. Event DOMFAIL
  855. To get this event, you must have already placed a domain 
  856. name request.  You may get more than one DOMFAIL for one 
  857. request.  The data field contains the machine number of the 
  858. name you looked up.  That machine name could not be 
  859. resolved.   You may also have an error event waiting for you 
  860. which explains why the resolve failed.
  861. Event FTPCOPEN
  862. A command connection has been established to your background 
  863. FTP server.  NCSA Telnet uses this to post informative 
  864. messages.
  865. Event FTPCLOSE
  866. The command connection for your server FTP has closed.
  867. Event FTPBEGIN
  868. A file transfer to or from your machine has begun.  The data 
  869. field=1 for get (transfer from) and 0 for put (transfer to) 
  870. transfers.
  871. Event FTPEND
  872. A file transfer or a LIST command has ended.
  873. Event FTPLIST
  874. A LIST command has begun for your background FTP.
  875. Event FTPUSER    
  876. A USER command has been entered for the background FTP.
  877. Event FTPPWOK
  878. An FTP PASS command has been entered and verified by 
  879. comparing to the entries in the password file.
  880. Event FTPPWNO
  881. An FTP PASS command has been entered and rejected by failing 
  882. to match anything in the password file.
  883. Event RCPBEGIN
  884. Someone has started an rcp transfer to or from your 
  885. computer.
  886. Event RCPEND
  887. That rcp has ended.
  888. Class ICMPCLASS
  889. Event IREDIR
  890. The netsleep() routine automatically does a netgetevent() 
  891. for ICMP redirect messages and performs the addressing 
  892. change required by the ICMP redirect.  When an ICMP redirect 
  893. packet is received, this event is posted by the ICMP 
  894. routine.  Bugfix in 2.2 makes sure ALL redirects are 
  895. registered.
  896. Class ERRCLASS
  897. Event ERR1
  898. There is currently only one error event which pertains to 
  899. all of the possible errors.  These events should be 
  900. reclassified as ERRWARNING, ERRINFO, ERRFATAL, etc., so the 
  901. rest of this class is reserved.  The data field contains the 
  902. error number which can be looked up with neterrstring().
  903. Class SCLASS (session class)
  904. The entire SCLASS is for special session layer events.  You 
  905. will not receive these events from Sgetevent() because they 
  906. are always removed.
  907. Event UDPTO
  908. The current UDP domain request timed out.
  909. Event FTPACT
  910. When FTP is active, it uses as much CPU as it can get.  To 
  911. get more CPU it posts events back to itself.
  912. Event TCPTO
  913. not used, we don't need TCP lookups.
  914. Event RCPACT
  915. rcp posts this event back to itself when it needs CPU.
  916. Event RETRYCON
  917. Snetopen() posts this in a timer to send multiple SYN 
  918. packets if the first one is lost.
  919. Class CONCLASS
  920. Event CONOPEN
  921. A connection has just opened.  This may be a connection 
  922. which you are listening to, or one which you are trying to 
  923. open with Snetopen().  Remember Snetopen() does not block 
  924. until the connection is open.  The data field returns the 
  925. port number (descriptor) of the connection.
  926. Event CONDATA
  927. Data has arrived for a certain port number.  The data field 
  928. contains that port number.  Because this event always comes 
  929. up when there is data in the incoming TCP buffer, you never 
  930. have to poll netread() to find out if there is data to be 
  931. read.  If you get CONDATA events, there is data to be read, 
  932. if you are not getting CONDATA events, then there won't be 
  933. data to be read.  Unless you drop an event, of course.  
  934. CONDATA events which arrive after a CONCLOSE event or a 
  935. netclose() call may get a -1 return from netread(), 
  936. indicating that the connection has no more data or does not 
  937. exist.
  938. Event CONCLOSE
  939. If the host you are talking to decides to drop the 
  940. connection, or reset it, then you may get a CONCLOSE event.  
  941. This can be interpreted as the last CONDATA event that you 
  942. will get.  There may be a large amount of data waiting for 
  943. you to pick it up with netread() even after receiving a 
  944. CONCLOSE event.  The correct procedure is to take data from 
  945. netread() until you receive a 0 or -1 return code and then 
  946. call netclose() to finalize your side of the connection.
  947. Event CONFAIL
  948. The timer ran out on a connection which you tried to open.  
  949. This does not mean that you are done.  You must netclose() 
  950. to allow the memory for that port to be re-used.
  951.  
  952.  
  953. Virtual Screen Kernel Calls
  954.  
  955. Gaige B. Paulsen                            October 31, 1987
  956.                                     updated July 14, 
  957. 1988
  958.  
  959. int VSinit(max)
  960. int max;        Maximum number of Virtual screens to allow.
  961. Initializes the Virtual Screen Kernel for use with up to max 
  962. screens. 
  963. Returns 0 if successful.
  964.  
  965. VSscrn *VSwhereis(i)
  966. int i;            Virtual Screen to examine.
  967. Returns the current address of the virtual screen control 
  968. record.  This is used for debugging.
  969.  
  970. int VSnewscreen( maxlines, screensave, maxwid, IDC)
  971. int maxwid;        How wide can this window be.  Only tested for 80 and 132.
  972. int maxlines;        Maximum number of lines to save.
  973. int screensave;    Is scrollback enabled at start?
  974. int IDC;        Do we have support for insert and delete of characters.
  975.  
  976. Creates a new screen if possible.   VSnewscreen returns a 
  977. number >=0 if it succeeds, which is to be used as the window 
  978. parameter(w) in all subsequent calls to vs routines.  If the 
  979. return value is <0, there was an error, and no screen was 
  980. created.
  981.  
  982. VSdestroy(w)
  983. int w;            Window number to destroy.
  984. Destroy the window corresponding to w.  Returns an error if 
  985. applicable.
  986.  
  987. VSdetatch(w)
  988. int w;            Window number to detach.
  989. Detach the window corresponding to w.  Returns an error if 
  990. applicable.  Note that this function currently just calls 
  991. VSdestroy(w).  Previously and hopefully sometime in the 
  992. future as well, it did/will allow for the destruction of a 
  993. screen without freeing memory.
  994.  
  995. VSredraw(w,x1,y1,x2,y2)
  996. int w;            Window number to redraw.
  997. int x1, y1,x2,y2;    Bounds of the rectangle to be drawn, in local window 
  998. coordinates.
  999. Redraw the portion of window w which lies within (x1,y1) - 
  1000. (x2,y2).  The coordinates are local to the window and should 
  1001. NOT be adjusted for scrollback, as most of scrollback is 
  1002. handled by the VS routines and not the RS.
  1003.  
  1004. VSwrite(w,ptr,len)
  1005. int w;            Window number to write to.
  1006. int  len;        How many characters to write.
  1007. char *ptr;        Where to get the characters.
  1008. The big routine.  This one is called to write a character 
  1009. stream to the virtual screen w.  VSwrite calls VSem to parse 
  1010. the emulation.
  1011.  
  1012. VSclear(w)
  1013. int w;            Window number to clear.
  1014. Clear the virtual screen of window w.
  1015.  
  1016. char VSkbsend(w,k,echo)
  1017. int w;            Window number to send the characters from.
  1018. int echo;        Boolean - whether to local echo the key.
  1019. unsigned char k;    VT-100 key code to send
  1020. Sends the VT-102 representation of the key represented by k.  
  1021. This routine uses somewhat of a hack by calling RSsendstring  
  1022. which is supposed to know how to send characters to 
  1023. whichever port corresponds to window w.  The echo flag only 
  1024. applies to special keys (like arrows) and will cause them to 
  1025. echo on the local screen as they are transmitted.
  1026.  
  1027. VSclearall(w)
  1028. int w;            Window number to clear all of.
  1029. This routine currently does nothing.  It was originally 
  1030. intended clear the current screen and all of the scrollback 
  1031. as well as setting the top of the scrollback to the top of 
  1032. the available storage space, but this was deemed 
  1033. unnecessary.....at least for now.
  1034.  
  1035. VSreset(w)
  1036. int w;            Window number to reset.
  1037. Resets the virtual screen (w) with respect to VT-100 modes.  
  1038. Changes the wrap mode to off and clears the screen as well 
  1039. as setting all other modes to their ORIGINAL POWER-ON 
  1040. defaults as specified by the VT-100 programmers manual.
  1041.  
  1042. char *VSgetline(w,y)
  1043. int w;            Window number to get line from.
  1044. int  y;            Line from which to get the pointer
  1045. This routine in now out of date and SHOULD NOT BE USED 
  1046. unless you really know what you are doing.  It retrives a 
  1047. pointer to the data string associated with line (y) of the 
  1048. screen (w).  This ONLY works with lines that are on the 
  1049. active vt100 screen (lines 0-23).
  1050.  
  1051. VSsetrgn(w,x1,y1,x2,y2)
  1052. int w;            Window number to set the display region for.
  1053. int x1,y1,x2,y2;    The vs's bounding rectangle in GLOBAL VS coordinates .
  1054. Set the current display region for window w to (x1,y1)-
  1055. (x2,y2).  This will perform 
  1056. scrollback/scrollforward/scrollleft/scrollright/etc. as 
  1057. necessary to make the current screen reflect the values of 
  1058. the passed display region.  It restricts you from doing 
  1059. anything really stupid (I hope).
  1060.  
  1061. VSgetrgn(w,x1,y1,x2,y2)
  1062. int w;            Window number to scroll forward in.
  1063. int *x1,*y1,*x2,*y2;    Where to retrieve the display region into.
  1064.  
  1065. Get the current value of the display region (as set by 
  1066. setrgn and/or modified by the scroll routines as well as 
  1067. auto--scroll).  Pass pointers to the integers you would like 
  1068. to have the values put into.
  1069.  
  1070. VSscrolback(w,in)
  1071. int w;            Window number to scroll back in.
  1072. int in;            Number of lines to scroll back.
  1073. Scroll back in lines in window w if possible.  Note that 
  1074. this routine will prevent you from scrolling back beyond the 
  1075. top of the buffer, so it is safe to call it whenever you get 
  1076. a request to scroll back further, even if you don't know if 
  1077. there is data left to scroll back into.
  1078.  
  1079. VSscrolforward(w,n)
  1080. int w;            Window number to scroll forward in.
  1081. int n;            Number of lines to scroll forward.
  1082. Scrolls forward n lines in window w.  See VSscrolback for 
  1083. details.
  1084.  
  1085. VSscrolright(w,n)
  1086. int w;            Window number to scroll right in.
  1087. int n;            Number of columns to scroll right.
  1088. Scrolls right n columns in window w.  See VSscrolback for 
  1089. details.
  1090.  
  1091. VSscrolleft(w,n)
  1092. int w;            Window number to scroll forward in.
  1093. int n;            Number of columns to scroll left.
  1094. Scrolls left n columns in window w.  See VSscrolback for 
  1095. details.
  1096.  
  1097. VSscrolcontrol(w,scrolon,savescroll)
  1098. int w;            Window number to set scroll variables for.
  1099. int scrolon;        Do we scroll or don't we?
  1100. int savescroll;        Save cleared lines into scrollback.
  1101. Changes the value of the scrolon variable in window w, 
  1102. therefore disabling and enabling scrollback, not really 
  1103. necessary.  If savescroll is on, all clearscreen commands 
  1104. will load the text into the scrollback buffer.
  1105.  
  1106. VSsnapshot(w)
  1107. int w;            Window number to take snapshot of.
  1108. Currently does nothing.  Will/should eventually make a copy 
  1109. of the current screen into the scrollback buffer.  This is 
  1110. most easily done by sending 24 line feeds and then copying 
  1111. the values of lines (-24) - (-1) into 0-24.  But, I hope to 
  1112. do this before  2.1 and the source release.
  1113.  
  1114. int VSmaxwidth(w)
  1115. int w;            Window number to retrieve the maximum width of.
  1116. Retrieves the current maximum width of window w.  Used 
  1117. primarily to get the maximum possible size of a selection 
  1118. for copying. NOTE: a 132 column window in 80 column mode 
  1119. returns 80.
  1120.  
  1121. long VSgettext(w, x1, y1, x2, y2, charp, max, EOLS)
  1122. int w;            Window number to get text from.
  1123. int x1,y1,x2,y2;    The starting and ending points of the text in global VS 
  1124. coordinates .
  1125. char *charp;        Pointer to the destination of the gotten text.
  1126. char  *EOLS;        Pointer to the string to be used for end of line.
  1127. long max;        Maximum number of characters charp can hold.
  1128. Copies a section of text from window w, which corresponds to 
  1129. an area starting from the x1th character of line y1 to the 
  1130. x2th character of line y2, inclusive of all of the 
  1131. characters on lines y1+1 to y2-1  into a buffer pointed at 
  1132. by charp to exceed no more than max and inserting the string 
  1133. pointed at by EOLS whenever there is a line transition.  
  1134. (...whew...) This is mainly used for copy and print of VS 
  1135. data.  Extraneous blanks are ommitted at the end of lines by 
  1136. searching backward to the beginning of the line.
  1137.             
  1138. Global  VS coordinates vs. local coordinates
  1139.  
  1140. Global
  1141. Global coordinates are used to represent a range of 
  1142. information that can span the entire VS space as it 
  1143. currently exists.   To accurately portray the area, we must 
  1144. have some standard method of referring to scrollback.  For 
  1145. this, we have chosen to refer to the top of the currently 
  1146. active VT-102 screen as line 0, the bottom of the active 
  1147. screen as line 23, and the lines of scrollback as negative 
  1148. offsets from line 0.  Hence, a line that has been scrolled 
  1149. off by a CR-LF would be seen as line -1.  To perform actions 
  1150. such as scrolling back to the top of the virtual screen, you 
  1151. would ask for lines from (top of buffer) to (top of buffer 
  1152. +length of display window).  Similarly, if you wished to 
  1153. scroll to make the right hand side of a 132 column window 
  1154. visible, you would ask for the columns from (maxwidth -20) 
  1155. to (maxwidth).
  1156. Local 
  1157. Local coordinates are used to represent things that happen 
  1158. relative to the area being displayed by the Virtual Screen.  
  1159. An example would be a portion (or all) of the virtual screen 
  1160. being made visible.  This action would cause whichever lines 
  1161. are in the visible area to be redrawn, therefore you will 
  1162. need to inform the VS routines to do this.  Since the VS 
  1163. routines attempt to maintain as much of the information 
  1164. about scrollback by themselves so as not to burden you with 
  1165. extraneous information, you pass these coordinates as local 
  1166. to the currently active screen.  Therefore, a full redraw 
  1167. would be line 0 character 0 through line 23 character 79, 
  1168. which would then be translated by VSredraw to whatever 
  1169. global coordinates are appropriate.
  1170.  
  1171. Replacing the Terminal Emulation package in the VS 
  1172. routines.
  1173.  
  1174. The VS routines can be used as a basis for just about any 24 line screen 
  1175. terminal emulator.  This document shows how to use the internal routines in 
  1176. vsintern.c to construct a  vsem.c file as a basis for a new terminal emulator.  
  1177.  
  1178. VSem(c,ctr) -
  1179. char *c     pointer to the buffer to use as input to the emulator
  1180. int ctr        how many characters to read from the input buffer
  1181.  
  1182. This is the main emulation routine.  It is the entry point from VSwrite and 
  1183. should be the only thing that needs to be replaced when changing the terminal 
  1184. emulation.
  1185.  
  1186.     escflg: current escape state
  1187.         0 - normal character wait
  1188.         1 - have escape, waiting for next character
  1189.         2 - escape '[' sequence, waiting for parameters
  1190.         3 - escape '#' sequence
  1191.         4 - escape '(' sequence
  1192.         5 - escape ')' sequence
  1193.     c:     pointer to character currently being parsed
  1194.     VSIw: points to the window structure for the current window.
  1195.     VSIwn: is the current window number
  1196.  
  1197. VSI routines from vsintern.c for use in emulation
  1198.  
  1199. VSIreset()            - Cause a terminal reset
  1200. VSItabinit()        - Initialize tabs to default stat (every 8             
  1201.         characters)
  1202. VSItabclear()        - Clear the tab at the current position
  1203.  
  1204. VSIdellines(n,s)        - delete n lines at s (current line if s<0)
  1205. VSIinslines(n,s)        - insert n lines at s (current line if s<0)
  1206.  
  1207. VSIeeol()            - erase to end of line
  1208. VSIebol()            - erase to beginning of line
  1209. VSIel(s)            - erase the entire line s (current line if s<0)
  1210. VSIeeos()            - erase to end of screen
  1211. VSIebos()            - erase to beginning of screen
  1212. VSIes()            - erase the whole screen
  1213.  
  1214. VSIrange()            - check and resolve range errors for x and y
  1215.  
  1216. VSIdraw( VSIwn, x, y, a, len, c)
  1217.                 - draw len characters at (x,y) in attribute a
  1218.                     with the chars at c
  1219. VSIinsstring(len,start)    - insert len characters at the current position         
  1220.             with the chars at start
  1221.  
  1222. VSIdelchars(x)        - delete x characters at the current position
  1223. VSIinschar(x)        - insert x blank characters at the current position
  1224. VSItab()            - move to next tab stop
  1225. VSIsave()            - save current x, y, a
  1226. VSIrestore()            - restore previous x,y,a
  1227.  
  1228. VSIindex()            - index one line
  1229. VSIrindex()            - reverse index one line
  1230.  
  1231. VTsendpos()            - Send the VT-100 cursor report
  1232. VTsendstat()            - Send the VT-100 status report
  1233. VTsendident()        - Send the VT-100 identity report
  1234. VSIsetoption(toggle)    - Set the VT-100 option depending on toggle
  1235.  
  1236.  
  1237.  
  1238. How to write a new PC driver
  1239.  
  1240. There are six routines which must be provided in a new 
  1241. driver.  All of these routines are currently provided in 
  1242. assembly language in one file.   When you write a new 
  1243. driver, you will probably take a current driver and replace 
  1244. each of the six routines in the file.  The current examples 
  1245. are in the ENET subdirectory and the three best examples 
  1246. are:
  1247.  
  1248. NET501.ASM
  1249. 3COM 3C501 driver.  Uses interrupts,  and will be a 
  1250. reasonable template for other interrupt-driven drivers.  I 
  1251. highly discourage trying to improve this driver for the 
  1252. 3C501.  I've tried.
  1253. NETUB.ASM
  1254. Ungermann-Bass (IBM) NIC board driver.  Does not use 
  1255. interrupts.  This driver may be a good template for simple 
  1256. shared-memory boards which divide the memory into pages.
  1257. NET5210.ASM
  1258. MICOM NI5210 driver.  The NI5210 uses the Intel 82586 chip.  
  1259. You will need the Intel databook for this chip in order to 
  1260. understand the driver.  This driver should be directly 
  1261. applicable to all boards which are built around the 82586.  
  1262. Works with 8K or 16K boards.  Only uses 8K of a 16K board, 
  1263. so save your money.
  1264.  
  1265. With dual-ported RAM and intelligent chipsets, interrupts are entirely 
  1266. unnecessary.  The board will automatically buffer a certain number of packets 
  1267. which are picked up when NCSA Telnet has time to process incoming packets.  
  1268. TCP takes care of preventing overruns.
  1269.  
  1270. The six routines are described below.  They generally return -1 on error.  
  1271. getaddr() is usually called first and etopen must be called next for any of 
  1272. the other routines to make sense.  Function pointers for the routines are 
  1273. declared and installed in PCTOOLS.C.  A new driver should install new pointers 
  1274. right alongside the existing ones.
  1275.  
  1276. etopen(eaddr,irq,addr,ioaddr)
  1277. char  eaddr[6];        Hardware ethernet address to use on board.
  1278. int irq;            Interrupt request level from configuration file.
  1279. int addr;        Shared memory base segment address from configuration file.
  1280. int ioaddr;        I/O address from configuration file.
  1281. This routine must do all of the initializations for the 
  1282. Ethernet board.  Any interrupt drivers must be placed, 
  1283. interrupts turned on, base register variables set up, 
  1284. packets initialized and the address set for the board.  Do 
  1285. not return until you are receiving packets.  Most drivers 
  1286. will ignore some of the fields provided.  Map them to 
  1287. whatever values are appropriate for your hardware.
  1288.  
  1289. getaddr(eaddr,addr,ioaddr)
  1290. char eaddr[6];        Buffer to place address.
  1291. int addr;        Base segment address for shared memory
  1292. int ioaddr;        Base I/O address for board
  1293. Some of these parameters are also ignored, depending upon 
  1294. the hardware.  The hardware address from the board's EPROMs 
  1295. should be copied into the eaddr buffer.  This address is 
  1296. generally given back to etopen, so getaddr cannot depend on 
  1297. etopen's initialization.
  1298.  
  1299. etclose()
  1300. Shut down Ethernet board.  Primarily to turn off interrupts.  
  1301. This routine can be just a RET for non-interrupt boards.
  1302.  
  1303. recv()
  1304. Receive a packet.  Used only for boards that do not use 
  1305. interrupts.  The interrupt handler generally replaces the 
  1306. need for recv().  The interrupt handler or recv() must use 
  1307. my undocumented buffering scheme.  Generally, keep the same 
  1308. code and replace the board handling side.
  1309.  
  1310. xmit(packet,size)
  1311. char *packet;        Address of packet to transmit.
  1312. int size;        Size of packet to transmit, including all headers.
  1313. Send out one packet.  This is generally not interrupt 
  1314. driven.  The packet size may be smaller than the minimum 
  1315. Ethernet packet size.  If so, this routine must take care of 
  1316. the details.  The frame to transmit always includes the 
  1317. entire Ethernet frame header, so non-802.3 drivers may need 
  1318. to strip the header to modify higher layer code.
  1319.  
  1320. etupdate()
  1321. Remove one packet from the buffer.  This routine is 
  1322. generally unmodified from driver to driver.  The incoming 
  1323. packet is not copied from the buffer until fully processed, 
  1324. so the driver must wait until etupdate() is called before 
  1325. freeing the space back to the buffer.
  1326.  
  1327.