home *** CD-ROM | disk | FTP | other *** search
/ Network CD 2 / Network CD - Volume 2.iso / programs / internet / terminal / xpr2001.lha / xprotocol.doc < prev   
Encoding:
Text File  |  1993-10-03  |  90.5 KB  |  2,366 lines

  1. +----------------------------------------------------------------------+
  2. |                                                                      |
  3. |                  D I S C L A I M E R   N O T I C E                   |
  4. |                                                                      |
  5. |  This document and/or  portions of the material and  data furnished  |
  6. |  herewith,  was developed under sponsorship of the U.S. Government.  |
  7. |  Neither the U.S.  nor  the U.S.D.O.E.,  nor  the  Leland  Stanford  |
  8. |  Junior University, nor their employees,  nor their respective con-  |
  9. |  tractors, subcontractors, or their employees, makes  any warranty,  |
  10. |  express or implied, or assumes any liability or responsibility for  |
  11. |  accuracy,  completeness or  usefulness of any information, appara-  |
  12. |  tus, product or process disclosed, or represents that its use will  |
  13. |  not infringe privately-owned rights.  Mention of any product,  its  |
  14. |  manufacturer, or suppliers shall not, nor is it intended to, imply  |
  15. |  approval, disapproval, or fitness for any particular use. The U.S.  |
  16. |  and  the University at all times  retain the right to use and dis-  |
  17. |  seminate same for any purpose whatsoever.                           |
  18. |                                                                      |
  19. +----------------------------------------------------------------------+
  20.  
  21. Trademarks:
  22. Amiga is a trademark of Commodore Business Machines.
  23. A-Talk III is a trademark of Felsina Software.
  24. Manx is a trademark of Manx Software Systems.
  25. Lattice is a trademark of Lattice, Inc.
  26.  
  27.  
  28.  
  29.  
  30.         XPR: External File Transfer Protocols as Amiga Libraries.
  31.         =========================================================
  32.  
  33.                    Version 2.0   - 11 September 1989
  34.                    Version 2.001 - 17 August    1993 / Unauthorized adds by
  35.                                                        Pasi Ristioja.
  36.  
  37.                        (C) Copyright 1989 by
  38.  
  39.                          W.G.J. Langeveld
  40.  
  41.                  Stanford Linear Accelerator Center
  42.  
  43.  
  44.                               ABSTRACT
  45.                               ========
  46.  
  47.              This  document  describes a  standard method
  48.              of using  Amiga  shared  libraries  for  the
  49.              implementation  of  external  file  transfer
  50.              protocols  (XPR's), as  implemented  in  the
  51.              Amiga  terminal  emulators  A-Talk  III  and
  52.              VLT.  The  method  can  also be  used to im-
  53.              plement external terminal emulations (XEM's).
  54.  
  55. [>* .. *<] - XPR 2.001 feature / additions provide easier and faster
  56.              implemention of birectional protocol without need to use
  57.              XProtocolHostMon() or XProtocolUserMon(). They are real
  58.              pain to use and IMHO only usable to write external emulation.
  59.  
  60. 1. Introduction.
  61. ================
  62.  
  63.         One of the most frequently asked questions of the author of a
  64. communications program is "Why don't you implement this wonderful file transfer
  65. protocol in addition to the 25 you already have?". Clearly, implementing more
  66. FTP's leads to larger code size and to increased product development time and
  67. customer support requirements, unless there is a way to have the additional
  68. protocols available as separate entities. One obvious way is to put the
  69. additional FTP's in overlays, but that only mitigates the code size problem and
  70. does not allow protocols to be used with communications programs of different
  71. vendors. Better is to open the serial device as a shared port and to have a
  72. completely separate program access it at the same time. However, this method has
  73. the disadvantage that shared use of a single serial port can lead to
  74. unpredictable results unless there is a well-established priority system
  75. enforcing which program is allowed to write to the device at which time. The
  76. advantage is that the FTP can now be developed separately and even by someone
  77. other than the author of the communications program. There are variations
  78. involving inter-process communication to add access control to the latter
  79. system, but I will not go into further detail.
  80.         The system described here is based on Amiga shared libraries. The
  81. library implements a small number of primary functions, such as "Send File(s)"
  82. and "Receive File(s)". These functions are called with a single argument, a
  83. pointer to an XPR_IO structure. This structure contains a number of things, the
  84. more obvious one being a pointer to a null terminated string indicating which
  85. files are to be sent or received and addresses of "call-back" functions inside
  86. the code of the communications program to access the serial device, which is
  87. opened typically in exclusive access. The scheme described here opens the
  88. possibility for the Amiga community to write a multitude of file transfer
  89. protocols, all rather small in size because they don't contain any overhead,
  90. that work with any communications program following the rules outlined in this
  91. document.
  92.         Possible problems with shared libraries are that they should be
  93. reentrant and that they should, if possible, not open dos.library [1]. On the
  94. other hand, these problems can easily be turned into advantages: for one,
  95. reentrancy is not hard to accomplish and in addition when there are multiple
  96. serial ports in use all of them can use the FTP with a single copy of the code.
  97. Not having to open dos.library can be accomplished by having call-back functions
  98. that provide all the DOS access needed in the original communications program.
  99. Typically these DOS functions are already linked into the original code anyway,
  100. and call-backs have to be provided for serial port access in any case.
  101.         For the sake of reentrancy across calls to the external protocol library
  102. (XPR), a field for storing a pointer to a data area is added for use by the XPR
  103. internally.
  104.  
  105.         Section 2 explains the library structure itself. Section 3 covers the
  106. XPR_IO structure and defines all the call-back functions. Section 4 describes an
  107. example library for a simple ASCII transfer without bells or whistles and will
  108. show how to code the library part of the call-backs. Section 5 shows how to set
  109. up a partial interface on the communications program side, sufficient to work
  110. with the ASCII example. Note: Sections 2 through 5 only describe the
  111. functionality of the specification that was present in the first public release.
  112. Section 6, finally, describes a number of extensions that were added later.
  113.  
  114.         Note: the examples are all for Manx C and assembler but should be easily
  115. modifyable for Lattice or any other language. Not all source files are given in
  116. this document. This archive, however, contains the example library plus all
  117. files needed to link it and interface to it, for Manx. Specifically, the
  118. routines that interface to XPR from VLT are in the "comm-program" subdirectory,
  119. and the sources to the library are in the "library" subdirectory. Also note,
  120. that both communications program and XPR implementers can only count on the
  121. the arguments passed in the registers as indicated. While it may appear from
  122. some of the code that the arguments are also available on the stack, this can
  123. not be relied on.
  124.  
  125.         I would like to thank Marco Papa of Felsina Software for his help in
  126. working out some of the details of the XPR standard, and Rick Huebner for his
  127. comments and debugging in the later stages.
  128.  
  129.         Neither this document, nor the XPR standard, nor the other files in this
  130. archive are in the public domain, but they may be freely distributed and used
  131. for any purpose bearing in mind the stipulations given in the disclaimer above,
  132. and with the proviso that in case of further distribution all files of this
  133. archive must remain together and unchanged.
  134.  
  135.  
  136. Reference:
  137. [1] Jim Mackraz says that opening dos.library inside a library is not a good
  138.     idea.
  139.  
  140.  
  141. 2. XPR libraries.
  142. =================
  143.  
  144.         Each external FTP is implemented as a separate library which lives in
  145. the libs: directory. It is mandatory that the names of XPR libraries start with
  146. the three letters "xpr" so that they are easily identified. The template for the
  147. name is xpr<protocol-name>.library, where <protocol-name> is a descriptive name
  148. of the protocol that is implemented. Obvious examples would be xprkermit.library
  149. and xprxmodem.library, but xprmykermit.library would be fine for a
  150. user-customized kermit implementation. When thinking of a name, the  implementer
  151. of an XPR library should keep in mind that communication programs will likely
  152. use the <protocol-name> part in their XPR requester.
  153.         Each XPR library in turn has four mandatory public functions. The
  154. functions are:
  155.  
  156.         XProtocolCleanup()
  157.         XProtocolSetup()
  158.         XProtocolSend()    and
  159.         XProtocolReceive()
  160.  
  161. in addition to the usual open, close expunge and reserved vectors. The library
  162. skeleton is given in Appendix A.
  163.         Two more library functions, XProtocolHostMon() and XProtocolUserMon(),
  164. are optional, see chapter 6.
  165.         Typically, a session with a terminal emulator using external protocols
  166. would consist of
  167.  
  168.         1. Selecting an external protocol (Using e.g. a file requester
  169.            showing only those files in libs: starting with "xpr").
  170.         2. Retrieving the library base XProtocolBase of the selected protocol
  171.            using OpenLibrary().
  172.         3. (Allocating and) initializing an XPR_IO structure.
  173.         4. Optionally calling XProtocolSetup() with the initialized structure.
  174.         5. Optionally Calling XProtocolSend() and/or XprotocolReceive() once or
  175.            multiple times to transfer files.
  176.         6. Optionally calling XProtocolSetup() to change parameters or to send
  177.            special commands. Perhaps repeat 5.
  178.         7. Calling XprotocolCleanup() to deallocate any resources allocated by
  179.            XProtocolSetup(). (Deallocate the XPR_IO structure if needed).
  180.         8. Closing the library using CloseLibrary().
  181.         9. Repeat the process, or
  182.        10. Exit.
  183.  
  184.         All four XPR functions take a single argument, a pointer to an XPR_IO
  185. structure, properly initialized as described in section 5, and passed in
  186. register A0. After XProtocolSetup() has been called, the same XPR_IO structure
  187. should be used for calls to any of the other functions. Only the xpr_filename
  188. field is allowed to be changed between  calls. In particular, the xpr_data field
  189. is for internal use by the XPR library only! It should be initialized to NULL
  190. before calling XProtocolSetup() and should not be changed by the communications
  191. program. XProtocolSetup() should be called once right after opening the library
  192. and subsequently only at the request of the user. XProtocolCleanup() should
  193. always be called before the library is closed.
  194.         In the form of a sample program, the rules above look like this:
  195.  
  196. /** MyWonderFullCommProgram.c
  197. *
  198. *   Just an example. An actual implementation would likely look different.
  199. *
  200. **/
  201. #include <stdio.h>
  202. #include <functions.h>
  203. #include "xproto.h"
  204.  
  205. struct Library *XProtocolBase = NULL;
  206.  
  207. #define SEND 1
  208. #define RECEIVE 2
  209. #define INITIALIZE 3
  210.  
  211. main()
  212. {
  213.    struct XPR_IO io;
  214.    int user_said, Waiting_for_user_input();
  215.  
  216.    XProtocolBase = OpenLibrary("xprascii.library", 0L);
  217.    if (XProtocolBase == NULL) {
  218.       printf("protocol not found\n");
  219.       exit(10);
  220.    }
  221.  
  222. /*
  223. *   Initialize structure (see later).
  224. */
  225.    xpr_setup(io);
  226. /*
  227. *   Retrieve the initalization string
  228. */
  229.    Get_init_string_from_user_or_wherever(buffer);
  230.    io->xpr_filename = buffer;
  231.    XProtocolSetup(io);
  232.  
  233.    while (user_said = Waiting_for_user_input(filename)) {
  234.       if (user_said == SEND) {
  235.          io->xpr_filename = filename;
  236.          XProtocolSend(io);
  237.       }
  238.       else if (user_said == RECEIVE) {
  239.          io->xpr_filename = filename;
  240.          XProtocolReceive(io);
  241.       }
  242.       else if (user_said == INITIALIZE) {
  243.          io->xpr_filename = NULL;
  244.          XProtocolSetup(io);
  245.       }
  246.    }
  247.  
  248.    XProtocolCleanup(io);
  249.  
  250.    CloseLibrary(XProtocolBase);
  251.  
  252.    exit(0);
  253. }
  254.  
  255.         Clearly, only one FTP can be active at any particular instant in the
  256. life of the session of the communications program. However, this is not really a
  257. limitation in practice, and can be worked around at the cost of some amount of
  258. programming effort.
  259.         XProtocolSetup(), XProtocolSend(), XProtocolReceive() and
  260. XProtocolCleanup() return 0L on failure, non-zero on success. Note to XPR
  261. implementers: the vanilla success return code should be 1L. Other bits in the
  262. return code may have special meaning, see section 6.
  263.  
  264.  
  265.  
  266.  
  267. 3. The XPR_IO structure.
  268. ========================
  269.  
  270.         The XPR_IO structure definition is given in Appendix B. The reader
  271. should keep in mind that the callback functions are to be implemented by the
  272. author of the communications program, not by the author of the external
  273. protocol. However, most communications programs already have functions that
  274. perform the operations listed here, so the implementation should not be too
  275. difficult. Also, the communications program author is not required, strictly
  276. speaking, to implement any of the functions: functions that are not implemented
  277. should be indicated by initializing the corresponding XPR_IO field to NULL.
  278. Obviously, a minimum set of functions must be implemented in order to be useful.
  279. On the other hand, it is up to the implementer of the external protocol to
  280. determine if the given set of functions is sufficient to perform the protocol
  281. transfer. In case of missing functions (indicated by NULL fields in the XPR_IO
  282. structure) suitable default actions should be taken.
  283.  
  284.         We will now examine all the fields of XPR_IO in detail. 
  285.  
  286.  
  287. 3.1     char  *xpr_filename;
  288. ----------------------------
  289.  
  290.         The xpr_filename field is used primarily to pass null-terminated strings
  291. containing a file name (or file names specified by wild cards) to the functions
  292. XProtocolSend() or XProtocolReceive(). The XPR implementer may elect to support
  293. wild cards in the file name. Call-backs for finding the first and next filename
  294. matching the pattern are provided in the XPR_IO structure, but on the other hand
  295. XPR implementers should take care to check that these call-backs are implemented
  296. by the communications program by testing the corresponding XPR_IO fields for
  297. NULL. Never assume that all call-backs are implemented! If a particular
  298. call-back without which the XPR cannot function is not implemented, the XPR
  299. should fail gracefully.
  300.  
  301.         The xpr_filename field can also be used to pass an initialization string
  302. to XProtocolSetup(). Typically, if this field is left NULL in a call to
  303. XProtocolSetup(), it would be the duty of XProtocolSetup() to query the user for
  304. initialization information, using e.g. the xpr_gets function (see later). If an
  305. initialization string is present, XProtocolSetup() should NOT query the user,
  306. but this is left to the discretion of the implementer of the protocol, as is the
  307. precise form of the initialization string. It is the duty of the communications
  308. program to determine any default initialization strings for the protocol in
  309. question. Suggested is the use of environment variables named for the protocols
  310. they refer to, containing the initialization string. For the simple Ascii
  311. protocol shown later, the user might have a statement like
  312.  
  313.         set xprascii=50
  314.  
  315. in his startup sequence, or with AmigaDOS 1.3, a file called xprascii in his
  316. env: directory containing the letters "50" (50 referring here to the number of
  317. ticks delay between 80-character packets - obviously more extensive
  318. initialization might be needed).
  319.         Given the presence of such default information, XProtocolSetup() should
  320. always be called using the default initialization string right after opening the
  321. library. Conversely, a mechanism (menu option) should be present in the
  322. communications program to change the settings by calling XProtocolSetup() with a
  323. NULL value for this field. On the other hand, if no default initialization
  324. string is present, the legal situation can arise that XProtocolSetup() is never
  325. called.
  326.         It should be noted that XProtocolSetup() can be used to implement any
  327. commands not directly related to sending or receiving files. Examples that come
  328. to mind are Kermit Bye and Finish. One should keep in mind, that typically the
  329. communications program does not know what protocol it is running, much less what
  330. commands that protocol might support. When the user asks to "setup" the external
  331. protocol, XProtocolSetup() should be called with a NULL xpr_filename field,
  332. and the external protocol should request a command, as stated before. In the
  333. case of an external Kermit protocol, the user might type a Bye or Finish, and
  334. the external protocol could act accordingly. See section 6 for additional
  335. information.
  336.  
  337.         The xpr_filename field is ignored by the XProtocolCleanup() function.
  338.  
  339.  
  340. 3.2    long (*xpr_fopen)();
  341. ---------------------------
  342.  
  343.         The xpr_fopen() call-back function works in most respects identically to
  344. the stdio function fopen(). Calling sequence:
  345.  
  346.         long fp = (*xpr_fopen)(char *filename, char *accessmode)
  347.         D0                     A0              A1
  348.  
  349. The result is a FILE structure, but one should not count on it being a
  350. particular one, since it may be compiler dependent. The return value should only
  351. be used in calls to other stdio functions. The only accesmodes available are
  352. "r"  (read-only)
  353. "w"  (write-only, create new file if none exists, truncate existing file)
  354. "a"  (write-only, create new file if none exists, append to existing file)
  355. "r+" (same as "r", but may also write)
  356. "w+" (same as "w", but may also read)
  357. "a+" (same as "a", but may also read).
  358.         An error return is indicated when the function returns NULL.
  359.         Note that the arguments must be passed in registers A0 and A1
  360. respectively. See also section 4.
  361.  
  362. [>*
  363.  
  364. Use mode "r" to open upload file and nothing else, if you use other mode
  365. comm-prog cannot know when to add upload and when download path... Of course
  366. you MUST NOT open dnload files with mode "r".
  367.  
  368. *<]
  369.  
  370.  
  371. 3.3     long (*xpr_fclose)();
  372. -----------------------------
  373.  
  374.         The xpr_fclose() call-back function works in most respects identically
  375. to the stdio function fclose(). Calling sequence:
  376.  
  377.         (*xpr_fclose)(long filepointer)
  378.                       A0
  379.  
  380. Note that the argument must be passed in register A0.
  381.  
  382.  
  383. 3.4     long (*xpr_fread)();
  384. ----------------------------
  385.  
  386.         The xpr_fread() call-back function works in most respects identically to
  387. the stdio function fread(). Calling sequence:
  388.  
  389.         long count = (*xpr_fread)(char *buffer, long size, long count,
  390.         D0                        A0            D0         D1
  391.  
  392.                                   long fileptr)
  393.                                   A1
  394.  
  395. The function returns the actual number items read. The size argument is in bytes.
  396. The function returns 0 on error or end of file.
  397.  
  398.  
  399. 3.5     long (*xpr_fwrite)();
  400. -----------------------------
  401.  
  402.         The xpr_fwrite() call-back function works in most respects identically
  403. to the stdio function fwrite(). Calling sequence:
  404.  
  405.         long count = (*xpr_fwrite)(char *buffer, long size, long count,
  406.         D0                         A0            D0         D1
  407.  
  408.                                   long fileptr)
  409.                                   A1
  410.  
  411. The function returns the actual number items written. The size argument is in
  412. bytes. The function returns 0 on failure.
  413.  
  414.  
  415. 3.6     long (*xpr_sread)();
  416. ----------------------------
  417.  
  418.         The xpr_sread() call-back function has the following calling sequence:
  419.  
  420.         long count = (*xpr_sread)(char *buffer, long size, long timeout)
  421.         D0                        A0            D0         D1
  422.  
  423. The first argument is a pointer to a buffer to receive the characters from the
  424. serial port, with a size specified in the second argument. The third item is a
  425. timeout in microseconds. The function returns the actual number of characters
  426. put into the buffer, or -1L on error. When the timeout argument is non-zero, the
  427. function will return when one of three events occurs: (1) the timeout period
  428. has expired, or (2) the buffer has been filled with  exactly "size" characters,
  429. or (3) an error occurs.
  430.         Specifically, when the routine is called, a timer is started and set to
  431. the value contained in timeout. The routine now starts collecting data from the 
  432. serial port and stores them in buffer. If the timer times out before size
  433. characters are received, the routine returns immediately with count set to the
  434. actual number of characters received. In case no characters at all are received,
  435. it will return count = 0L. If the buffer is full before the timer has expired,
  436. the routine returns immediately with count = size. It is up to the XPR to set
  437. the  timeout long enough to ensure that at the current baud rate the buffer can
  438. actually be filled to the specified size within the timeout period. The routine
  439. can also return with count set to -1L. This might happen, for example, when the
  440. carrier is lost. The XPR should then fairly quickly get around to checking
  441. the abort status using the xpr_chkabort() function: BBS programs will want to
  442. regain control quickly after the carrier is dropped.
  443.         The timeout may be set to 0L if the objective is to just read any
  444. characters that may currently be available. In this case, the function will not
  445. start up a timer, but will instead check the serial device for currently
  446. available characters and return them in the usual fashion, and return as quickly
  447. as possible. Note: the value 0L for the timeout argument is a special case.
  448. Remember that AmigaDOS 1.3 may have problems with small non-zero values for
  449. timeouts.
  450.     Further notes on the implementation of xpr_sread() can be found in the
  451. discussion about XProtocolHostMon in section 6.3.1.
  452.  
  453.  
  454. 3.7     long (*xpr_swrite)();
  455. -----------------------------
  456.  
  457.         The xpr_swrite() call-back function has the following calling sequence:
  458.  
  459.         long status = (*xpr_swrite)(char *buffer, long size)
  460.         D0                          A0            D0
  461.  
  462. This function writes a buffer with the given size to the serial port. It returns
  463. 0L on success, non-zero on failure.
  464.  
  465. 3.8     long (*xpr_sflush)();
  466. ----------------------------
  467.  
  468.         The xpr_sflush call-back function has the following calling sequence:
  469.  
  470.         long status = (*xpr_sflush)()
  471.         D0
  472.  
  473. This function flushes all the data in the serial port input buffer.  It is
  474. typically used to recover after a protocol error. The function returns 0L on
  475. success, non-zero on failure.
  476.  
  477. 3.9     long (*xpr_update)();
  478. -----------------------------
  479.  
  480.         The xpr_update() call-back function has the following calling sequence:
  481.  
  482.         (*xpr_update)(struct XPR_UPDATE *updatestruct)
  483.                       A0
  484. where:
  485.  
  486. struct XPR_UPDATE {     long  xpru_updatemask;
  487.                         char *xpru_protocol;
  488.                         char *xpru_filename;
  489.                         long  xpru_filesize;
  490.                         char *xpru_msg;
  491.                         char *xpru_errormsg;
  492.                         long  xpru_blocks;
  493.                         long  xpru_blocksize;
  494.                         long  xpru_bytes;
  495.                         long  xpru_errors;
  496.                         long  xpru_timeouts;
  497.                         long  xpru_packettype;
  498.                         long  xpru_packetdelay;
  499.                         long  xpru_chardelay;
  500.                         char *xpru_blockcheck;
  501.                         char *xpru_expecttime;
  502.                         char *xpru_elapsedtime;
  503.                         long  xpru_datarate;
  504.                         long  xpru_reserved1;
  505.                         long  xpru_reserved2;
  506.                         long  xpru_reserved3;
  507.                         long  xpru_reserved4;
  508.                         long  xpru_reserved5;
  509.                    }
  510.  
  511. This function is intended to communicate a variety of values and strings from
  512. the external protocol to the communications program for display. Hence, the
  513. display format itself (requester, text-I/O) is left to the implementer of the
  514. communications program.
  515.         The mask xpru_updatemask indicates which of the other fields are valid,
  516. i.e. have had their value updated. It is possible to update a single or multiple
  517. values. Values that the external protocol does not use can be indicated by a
  518. NULL for pointers and -1L for longs.
  519.         The possible bit values for the xpru_updatemask are:
  520.  
  521. [>* OR one at time / call twice if your proto is doing bi-xfer  *<]
  522. [>*             #define XPRU_UPLOAD        0x80000000L    *<]
  523. [>*             #define XPRU_DNLOAD        0x40000000L    *<]
  524.  
  525.                 #define XPRU_PROTOCOL           0x00000001L
  526.                 #define XPRU_FILENAME           0x00000002L
  527.                 #define XPRU_FILESIZE           0x00000004L
  528.                 #define XPRU_MSG                0x00000008L
  529.                 #define XPRU_ERRORMSG           0x00000010L
  530.                 #define XPRU_BLOCKS             0x00000020L
  531.                 #define XPRU_BLOCKSIZE          0x00000040L
  532.                 #define XPRU_BYTES              0x00000080L
  533.                 #define XPRU_ERRORS             0x00000100L
  534.                 #define XPRU_TIMEOUTS           0x00000200L
  535.                 #define XPRU_PACKETTYPE         0x00000400L
  536.                 #define XPRU_PACKETDELAY        0x00000800L
  537.                 #define XPRU_CHARDELAY          0x00001000L
  538.                 #define XPRU_BLOCKCHECK         0x00002000L
  539.                 #define XPRU_EXPECTTIME         0x00004000L
  540.                 #define XPRU_ELAPSEDTIME        0x00008000L
  541.                 #define XPRU_DATARATE           0x00010000L
  542.  
  543.         The other fields of the XPR_UPDATE structure have the following
  544. meaning:
  545.  
  546. xpru_protocol    -- a string that indicates the name of the protocol used
  547. xpru_filename    -- the name of the file currently sent or received
  548. xpru_filesize    -- the size of the file
  549. xpru_msg         -- a "generic" message (50 characters or less)
  550. xpru_errormsg    -- an "error" message  (50 characters or less)
  551. xpru_blocks      -- number of transferred blocks
  552. xpru_blocksize   -- size of most recently transferred block (bytes)
  553. xpru_bytes       -- number of transferred bytes
  554. xpru_errors      -- number of errors
  555. xpru_timeouts    -- number of timeouts
  556. xpru_packettype  -- type of packet (e.g. Kermit 'D'-packet)
  557. xpru_packetdelay -- delay between packets in msec
  558. xpru_chardelay   -- delay between characters in msec
  559. xpru_blockcheck  -- block check type (e.g. "Checksum", "CRC-16", "CRC-32")
  560. xpru_expecttime  -- expected transfer time (e.g. "5 min 20 sec", "00:05:30")
  561. xpru_elapsedtime -- elapsed time from start of transfer (see xpru_expecttime)
  562. xpru_datarate    -- rate of data transfer expressed in characters per second.
  563. xpru_reserved1   -- for further expansion
  564.  ...         .   --  ...
  565. xpru_reserved5   -- for further expansion
  566.  
  567.         The communications program is free to ignore any field and to only update
  568. the ones it can handle.
  569.         If xpru_updatemask is equal to -1L, then ALL fields are either valid or 
  570. are unambiguously valued to indicate they are unused: NULL for pointers and -1L
  571. for longs.
  572.         When writing an external protocol, it is advisable to keep any strings
  573. as short as possible, and not longer than about 50 characters. Remember, if your
  574. strings are too long, they may overflow whatever display mechanism the
  575. communications program has chosen. It is also advisable to fill in as many
  576. fields as you can, since the communications program may not choose to display
  577. the ones you favor. When writing a communications program interface to XPR, on
  578. the other hand, remember that strings can be as much as 50 characters long. If
  579. you don't receive your favorite variables, it may be possible to compute them
  580. from those that are given. It is good practice for the external protocol to call
  581. xpr_update before starting the transfer with a message in the xpru_msg field
  582. indicating whether the protocol is sending or receiving a file.
  583.         The XPR_UPDATE structure must be provided by the external protocol, and
  584. must, of course be allocated either on the stack (as a local variable) or using
  585. AllocMem or malloc(). This is needed to ensure reentrancy. In general, it is a
  586. good idea to keep the entire library reentrant, since more than one
  587. communications program may be using the same code simultaneously. (If you use
  588. malloc(), make sure your implementation of malloc() is reentrant!).
  589.  
  590. 3.10     long (*xpr_chkabort)();
  591. -------------------------------
  592.  
  593.         The xpr_chkabort() call-back function has no arguments:
  594.  
  595.         long status = (*xpr_chkabort)()
  596.         D0
  597.  
  598. When it returns non-zero, it means that the user has requested an abort. It is
  599. possible to implement levels of abort by returning 1L, 2L, 3L, etc, depending on
  600. the user's actions. The highest level of abort is -1L, which should be
  601. interpreted to mean stop all actions and return. The chkabort function should be
  602. called reasonably frequently.
  603.  
  604.  
  605. 3.11    long (*xpr_chkmisc)();
  606. ------------------------------
  607.  
  608.         The xpr_chkmisc() call-back function has no arguments and returns
  609. nothing.
  610.  
  611.         (*xpr_chkmisc)()
  612.  
  613. It is intended to give the communications program that is currently executing
  614. the external protocol transfer a chance to service its various message ports and
  615. to respond to user actions. It should be called on a regular basis.
  616.  
  617.  
  618. 3.12    long (*xpr_gets)();
  619. ---------------------------
  620.  
  621.         The xpr_gets() call-back function works somewhat like the stdio function
  622. gets(). Calling sequence:
  623.  
  624.         long status = (*xpr_gets)(char *prompt, char *buffer)
  625.         D0                        A0            A1
  626.  
  627. The first argument is a pointer to a string containing a prompt, to be displayed
  628. by the communications program in any manner it sees fit. The second argument
  629. should be a pointer to a buffer to receive the user's response. It should have a
  630. size of at least 256 bytes. The function returns 0L on failure or user
  631. cancellation, non-zero on success. The buffer has to be supplied by the XPR.
  632.  
  633.  
  634. 3.13    long (*xpr_setserial)();
  635. --------------------------------
  636.  
  637.         The xpr_setserial() call-back function has the following calling
  638. sequence:
  639.  
  640.         long oldstatus = (*xpr_setserial)(long newstatus)
  641.         D0                                D0
  642.  
  643. This function returns the current serial device status in encoded form. If the
  644. newstatus argument is -1L, the serial device status will not be changed.
  645. Otherwise the serial device status will be changed to newstatus. If oldstatus
  646. is returned as -1L, the call failed and the serial status was not changed.
  647.         Note: if the serial device status is changed with this function, the 
  648. external protocol must change the status back to oldstatus before returning.
  649.  
  650.         serial status longword:
  651.         .......................
  652.  
  653.         byte 0:         as the SerFlags field in IOExtSer structure.
  654.                 bit 0:  - parity on if set
  655.                 bit 1:  - parity odd if set
  656.                 bit 2:  - 7-wire protocol enabled if set
  657.                 bit 3:  - queued break if set
  658.                 bit 4:  - rad-boogie if set
  659.                 bit 5:  - shared if set
  660.                 bit 6:  - EOF mode if set
  661.                 bit 7:  - Xon/Xoff disabled if set
  662.         byte 1:         summary of other settings
  663.                 bit 0:  - enable mark/space parity if set
  664.                 bit 1:  - parity mark if set, space otherwise
  665.                 bit 2:  - 2 stop bits if set, 1 otherwise
  666.                 bit 3:  - read wordlength is 7 if set, 8 otherwise
  667.                 bit 4:  - write wordlength is 7 if set, 8 otherwise
  668.                 bit 5:  - not used
  669.                 bit 6:  - not used
  670.                 bit 7:  - not used
  671.         byte 2:         specifies one of a limited set of baud rates, as in
  672.                         preferences.h.
  673.                         -    110 baud =  0
  674.                         -    300 baud =  1
  675.                         -   1200 baud =  2
  676.                         -   2400 baud =  3
  677.                         -   4800 baud =  4
  678.                         -   9600 baud =  5
  679.                         -  19200 baud =  6
  680.                         -   midi      =  7
  681.                         -  38400 baud =  8
  682.                         -  57600 baud =  9
  683.                         -  76800 baud = 10
  684.                         - 115200 baud = 11
  685.         byte 3:         not used
  686.  
  687.  
  688. 3.14    long (*xpr_ffirst)();
  689. -----------------------------
  690.  
  691.         The xpr_ffirst() call-back function has the calling sequence:
  692.  
  693.         long stateinfo = (*xpr_ffirst)(char *buffer, char *pattern)
  694.         D0                             A0            A1
  695.  
  696. The first argument is a buffer to receive the first filename that matches the
  697. pattern in the second argument. The function returns 0L if no file matching the
  698. pattern was found, non-zero otherwise. The buffer should have a size of at least
  699. 256 bytes and is provided by the XPR. See also 3.14.
  700.  
  701.  
  702. 3.15    long (*xpr_fnext)();
  703. ----------------------------
  704.  
  705.         The xpr_fnext() call-back function has the calling sequence:
  706.  
  707.         long stateinfo = (*xpr_fnext)(long oldstate, char *buffer, char *pattern)
  708.         D0                            D0             A0            A1
  709.  
  710. The first argument is a buffer to receive the next filename that matches the
  711. pattern in the second argument. The function returns 0L if no further file
  712. matching the pattern was found, non-zero otherwise. The buffer should have a
  713. size of at least 256 bytes and is provided by the XPR.
  714.         Note: the value returned by xpr_ffirst and xpr_fnext may be used by the
  715. implementing communications program to maintain state information, but the
  716. mechanism is up to the implementer. If reentrancy is not required, state
  717. information may be kept in global variables by the implementer, and the oldstate
  718. argument can be ignored. However, the external protocol implementation must pass
  719. the stateinfo variable returned by ffirst or fnext to the next invocation of
  720. fnext.
  721.  
  722.  
  723. 3.16    long (*xpr_finfo)();
  724. ----------------------------
  725.  
  726.         The xpr_finfo() call-back function has the calling sequence:
  727.  
  728.         long info = (*xpr_finfo)(char *filename, long typeofinfo)
  729.         D0                       A0              D0
  730.  
  731. This function returns information about a file given its name and the type of
  732. information requested. Notice that some information may not be accessible if
  733. the file is already write locked. Therefore, you should call this function
  734. (where appropriate) before opening the file.
  735.  
  736.         typeofinfo value:       resulting info:              on failure:
  737.         ..................................................................
  738.  
  739.         1L                      file size (bytes)            0L
  740.  
  741.         2L                      file type: 1L is binary,     0L
  742.                                            2L is text.
  743.  
  744.         (other values)          (to be determined)
  745.  
  746. [>*
  747.  
  748. OR either 0x80000000 (uploadname) or 0x40000000 (dnloadname) to typeinfo.
  749. This is needed that comm-prog can add right path for name. (read fopen also)
  750.  
  751. *<]
  752.  
  753. 3.17    long  *xpr_fseek();
  754. ---------------------------
  755.  
  756.         The xpr_fseek() call-back function works in most respects identically to
  757. the stdio function fseek(). Calling sequence:
  758.  
  759.         long status = (*xpr_fseek)(long fileptr, long offset, long origin)
  760.         D0                         A0            D0           D1
  761.  
  762. This function sets the current position of a file to "offset" from the 
  763. beginning (origin = 0), current position (origin = 1) or end (origin = 2) of
  764. the file.
  765. The function returns 0 on success.
  766.  
  767.  
  768. 3.18    long  *xpr_extension;
  769. -----------------------------
  770.  
  771.         This field indicates how many extension fields follow this structure.
  772. Before using any of those functions or fields (as defined in section 6), the
  773. XPR must check that the desired function is indeed present by ensuring that
  774. xpr_extension is larger than the position of the function beyond the xpr_data
  775. field.
  776.  
  777.  
  778. 3.19    long  *xpr_data;
  779. ------------------------
  780.  
  781.         This field is for internal use by the external protocol. Typically the
  782. field is initialized to point to a structure containing information extracted
  783. from the initialization string handed to or retrieved by the XProtocolSetup()
  784. function, see section 2. The structure should be deallocated and the field
  785. restored to NULL by the XProtocolCleanup() function. The communications program
  786. should never access this field, except when initializing the XPR_IO structure:
  787. the field should be initialized to NULL.
  788.  
  789.  
  790. 4. An example protocol.
  791. =======================
  792.  
  793.         The following is an annotated listing of an ascii upload protocol.
  794. Notice that the files supplied in this archive are likely more up to date and
  795. more extensive than the example given here.
  796.  
  797. /** xprascii.c
  798. *
  799. *   These are the protocol transfer routines for a simple ASCII upload.
  800. *
  801. **/
  802. #include <exec/exec.h>
  803. #include <functions.h>
  804. #include <stdio.h>
  805. /*
  806. *   xproto.h is the include file given in Appendix B.
  807. */
  808. #include "xproto.h"
  809. /*
  810. *   The following two strings must exist.
  811. */
  812. char  XPRname[]   = "xprascii.library";
  813. char  XPRid[]     = "xprascii 0.9 (May 89)\r\n";
  814. UWORD XPRrevision = 9;
  815.  
  816. long atol();
  817. /*
  818. *   The callxx...() routines are described later. They provide the 
  819. *   assembler interface from the XPR library to the call-back routines.
  820. */
  821. long calla(), callaa(), callad(), calladd(), calladda();
  822.  
  823. char *malloc();
  824.  
  825.  
  826. /**
  827. *
  828. *   Send a file
  829. *
  830. **/
  831. long XProtocolSend(IO)
  832. struct XPR_IO *IO;
  833. {
  834.    long fp, r, i;
  835.    long brkflag = 0, fl = 0L, sd = 0L;
  836.    long (*xupdate)(), (*xswrite)(), (*xfopen)(), (*xfclose)(), (*xfread)(),
  837.         (*xsread)(),  (*xchkabort)();
  838.    unsigned char *buff = NULL, *serbuff = NULL;
  839.    struct XPR_UPDATE xpru;
  840.  
  841. /*
  842. *   These are the call-backs we need. If any of them isn't provided, quit.
  843. *   Could do some error reporting if at least xupdate is there.
  844. */
  845.    if ((xupdate    = IO->xpr_update)   == NULL) return(0L);
  846.    if ((xswrite    = IO->xpr_swrite)   == NULL) return(0L);
  847.    if ((xfopen     = IO->xpr_fopen)    == NULL) return(0L);
  848.    if ((xfclose    = IO->xpr_fclose)   == NULL) return(0L);
  849.    if ((xfread     = IO->xpr_fread)    == NULL) return(0L);
  850.    if ((xsread     = IO->xpr_sread)    == NULL) return(0L);
  851.    if ((xchkabort  = IO->xpr_chkabort) == NULL) return(0L);
  852. /*
  853. *   Allocate a few buffers.
  854. */
  855.    buff    = (unsigned char *) malloc(80);
  856.    serbuff = (unsigned char *) malloc(80);
  857. /*
  858. *   If we ran out of memory, print a message.
  859. *   The argument needs to go in A0: calla does this for us. 
  860. */
  861.    if (buff == NULL || serbuff == NULL) {
  862.       xpru.xpru_updatemask = XPRU_ERRORMSG;
  863.       xpru.xpru_errormsg   = "Ran out of memory!";
  864.       calla(xupdate, &xpru);
  865.       return(0L);
  866.    }
  867. /*
  868. *   Read the send delay, if a XProtocolSetup() was done before.
  869. *   If send delay is too large, cut it off at 10 seconds.
  870. *   In this example, the xpr_data field contains a null terminated string
  871. *   containing the number of ticks to delay each 80 characters.
  872. */
  873.    if (IO->xpr_data) {
  874.       sd = atol(IO->xpr_data);
  875.       if (sd > 500L) sd = 500L;
  876.    }
  877. /*
  878. *   Open the file. One could do wild card detection here.
  879. *   xfopen requires two arguments, in a0 and a1 respectively.
  880. *   Again, this must be done in assembler, and callaa does it.
  881. */
  882.    fp = callaa(xfopen, IO->xpr_filename, "r");
  883.    if (fp == NULL) {
  884.       free(buff);
  885.       free(serbuff);
  886.       xpru.xpru_updatemask = XPRU_ERRORMSG | XPRU_FILENAME;
  887.       xpru.xpru_errormsg   = "Failed to open input file";
  888.       xpru.xpru_filename   = IO->xpr_filename;
  889.       calla(xupdate, &xpru);
  890.       return(0L);
  891.    }
  892. /*
  893. *   Start the transfer. See 3.8 for a discussion on how to implement
  894. *   xupdate. 
  895. */
  896.    xpru.xpru_updatemask = XPRU_MSG | XPRU_FILENAME;
  897.    xpru.xpru_msg        = "Starting ASCII Send";
  898.    xpru.xpru_filename   = IO->xpr_filename;
  899.    calla(xupdate, &xpru);
  900. /*
  901. *   Now read 80 byte chunks from the file using xfread.
  902. *   xfread requires four arguments, a0, d0, d1 and a1.
  903. */
  904.    xpru.xpru_blocks = 0L;
  905.    while (r = calladda(xfread, buff, 1L, 80L, fp)) {
  906. /*
  907. *   Convert line feeds to carriage returns before sending to host.
  908. *   fl counts the characters. Display how many characters are sent.
  909. */
  910.       for (i = 0L; i < r; i++) if (buff[i] == '\n') buff[i] = '\r';
  911.       fl += r;
  912.       xpru.xpru_updatemask = XPRU_BYTES | XPRU_BLOCKS | XPRU_BLOCKSIZE;
  913.       xpru.xpru_bytes      = fl;
  914.       xpru.xpru_blocks++;
  915.       xpru.xpru_blocksize  = r;
  916.       calla(xupdate, &xpru);
  917.       callad(xswrite, buff, r);
  918. /*
  919. *   Every 80 bytes, put out a message and delay if requested.
  920. */
  921.       xpru.xpru_updatemask  = XPRU_PACKETDELAY;
  922.       xpru.xpru_packetdelay = sd * 20L;  /* msec! */
  923.       calla(xupdate, &xpru);
  924. /*
  925. *   Can't use Delay() here, because Delay() is in dos.library!
  926. *   However writing an equivalent function using the timer.device is
  927. *   trivial.
  928. */
  929.       TimeOut(sd);
  930. /*
  931. *   Eat any characters that might arrive from the serial port.
  932. *   calladd stores arg1 in a0, arg2 in d0, arg3 in d1.
  933. *   We're not really waiting for any characters: use a timeout of 0L.
  934. */
  935.       while (calladd(xsread, serbuff, 80L, 0L) > 0L) ;
  936. /*
  937. *   Check for "abort" here. Perhaps should call chkmisc() as well.
  938. */
  939.       if (brkflag = xchkabort()) break;
  940.    }
  941. /*
  942. *   Close the file
  943. */
  944.    calla(xfclose, fp);
  945.    free(buff);
  946.    free(serbuff);
  947. /*
  948. *   If we got here through chkabort() say Aborted.
  949. */
  950.    xpru.xpru_updatemask       = XPRU_MSG;
  951.    if (brkflag) xpru.xpru_msg = "Aborted";
  952.    else         xpru.xpru_msg = "Done"; 
  953.    calla(xupdate, &xpru);
  954.    if (brkflag) return(0L);
  955.    else         return(1L);
  956. }
  957.  
  958.  
  959. /**
  960. *
  961. *   Receive a file.
  962. *
  963. **/
  964. long XProtocolReceive(IO)
  965. struct XPR_IO *IO;
  966. {
  967.    long fp, r, i;
  968.    long brkflag = 0, fl = 0L, sd = 0L;
  969.    long (*xupdate)(), (*xswrite)(), (*xfopen)(), (*xfclose)(), (*xfwrite)(),
  970.         (*xsread)(),  (*xchkabort)();
  971.    unsigned char *serbuff = NULL;
  972.    struct XPR_UPDATE xpru;
  973.  
  974. /*
  975. *   These are the call-backs we need. If any of them isn't provided, quit.
  976. *   Could do some error reporting if at least xupdate is there.
  977. */
  978.    if ((xupdate    = IO->xpr_update)   == NULL) return(0L);
  979.    if ((xswrite    = IO->xpr_swrite)   == NULL) return(0L);
  980.    if ((xfopen     = IO->xpr_fopen)    == NULL) return(0L);
  981.    if ((xfclose    = IO->xpr_fclose)   == NULL) return(0L);
  982.    if ((xfwrite    = IO->xpr_fwrite)   == NULL) return(0L);
  983.    if ((xsread     = IO->xpr_sread)    == NULL) return(0L);
  984.    if ((xchkabort  = IO->xpr_chkabort) == NULL) return(0L);
  985. /*
  986. *   Allocate a buffer.
  987. */
  988.    serbuff = (unsigned char *) malloc(80);
  989. /*
  990. *   If we ran out of memory, print a message.
  991. *   The argument needs to go in A0: calla does this for us. 
  992. */
  993.    if (serbuff == NULL) {
  994.       xpru.xpru_updatemask = XPRU_ERRORMSG;
  995.       xpru.xpru_errormsg   = "Ran out of memory!";
  996.       calla(xupdate, &xpru);
  997.       return(0L);
  998.    }
  999. /*
  1000. *   Open the file.
  1001. *   xfopen requires two arguments, in a0 and a1 respectively.
  1002. *   Again, this must be done in assembler, and callaa does it.
  1003. */
  1004.    fp = callaa(xfopen, IO->xpr_filename, "w");
  1005.    if (fp == NULL) {
  1006.       free(serbuff);
  1007.       xpru.xpru_updatemask = XPRU_ERRORMSG | XPRU_FILENAME;
  1008.       xpru.xpru_errormsg   = "Failed to open output file";
  1009.       xpru.xpru_filename   = IO->xpr_filename;
  1010.       calla(xupdate, &xpru);
  1011.       return(0L);
  1012.    }
  1013. /*
  1014. *   Start the transfer. See 3.8 for a discussion on how to implement
  1015. *   xupdate. 
  1016. */
  1017.    xpru.xpru_updatemask = XPRU_MSG | XPRU_FILENAME;
  1018.    xpru.xpru_msg        = "Starting ASCII Receive";
  1019.    xpru.xpru_filename   = IO->xpr_filename;
  1020.    calla(xupdate, &xpru);
  1021. /*
  1022. *   Now read 80 byte chunks from the serial port using xsread. Stop
  1023. *   when no characters arrive for 5 sec.
  1024. */
  1025.    xpru.xpru_blocks = 0L;
  1026.    while ((r = calladd(xsread, serbuff, 80L, 5000000L)) > 0L)  {
  1027. /*
  1028. *   Strip high-bit before storing in file.
  1029. *   fl counts the characters. Display how many characters are received.
  1030. */
  1031.       for (i = 0L; i < r; i++) serbuff[i] &= 0177;
  1032.       fl += r;
  1033.       xpru.xpru_updatemask = XPRU_BYTES | XPRU_BLOCKS | XPRU_BLOCKSIZE;
  1034.       xpru.xpru_bytes      = fl;
  1035.       xpru.xpru_blocks++;
  1036.       xpru.xpru_blocksize  = r;
  1037.       calla(xupdate, &xpru);
  1038. /* 
  1039. *   Write 80 byte chunks to the file using xwrite
  1040. */
  1041.       calladda(xfwrite, serbuff, 1L, r, fp);
  1042.  
  1043. /*
  1044. *   Check for "abort" here. Perhaps should call chkmisc() as well.
  1045. */
  1046.       if (brkflag = xchkabort()) break;
  1047.    }
  1048. /*
  1049. *   Close the file
  1050. */
  1051.    calla(xfclose, fp);
  1052.    free(serbuff);
  1053. /*
  1054. *   If we got here through chkabort() say Aborted.
  1055. */
  1056.    xpru.xpru_updatemask       = XPRU_MSG;
  1057.    if (brkflag) xpru.xpru_msg = "Aborted";
  1058.    else         xpru.xpru_msg = "Done"; 
  1059.    calla(xupdate, &xpru);
  1060.    if (brkflag) return(0L);
  1061.    else         return(1L);
  1062. }
  1063.  
  1064.  
  1065. /**
  1066. *
  1067. *   Setup
  1068. *
  1069. **/
  1070. long XProtocolSetup(IO)
  1071. struct XPR_IO *IO;
  1072. {
  1073.    long (*xupdate)(), (*xgets)();
  1074.    struct XPR_UPDATE xpru;
  1075.  
  1076.    if ((xupdate = IO->xpr_update) == NULL) return(0L);
  1077.    if ((xgets   = IO->xpr_gets)   == NULL) return(0L);
  1078. /*
  1079. *   Allocate a bit of memory for a data buffer
  1080. */
  1081.    if (IO->xpr_data == NULL) {
  1082.       if ((IO->xpr_data = (long *) malloc(256)) == NULL) {
  1083.          xpru.xpru_updatemask = XPRU_ERRORMSG;
  1084.          xpru.xpru_errormsg   = "ASCII - Out of memory!";
  1085.          calla(xupdate, &xpru);
  1086.          return(0L);
  1087.       }
  1088.    }
  1089. /*
  1090. *   If setup string isn't handed to us, ask questions
  1091. */
  1092.    if (IO->xpr_filename == NULL) {
  1093. /*
  1094. *   Get the value for the send delay
  1095. */
  1096.       callaa(xgets, "Enter ASCII send delay (ticks, 1 tick = 20 msec)",
  1097.                   IO->xpr_data);
  1098.    }
  1099.    else {
  1100.       strcpy(IO->xpr_data, IO->xpr_filename);
  1101.    }
  1102.    
  1103.    return(1L);
  1104. }
  1105.  
  1106. /**
  1107. *
  1108. *   Cleanup
  1109. *
  1110. **/
  1111. long XProtocolCleanup(IO)
  1112. struct XPR_IO *IO;
  1113. {
  1114.    if (IO->xpr_data) free(IO->xpr_data);
  1115.    IO->xpr_data = NULL;
  1116.  
  1117.    return(1L);
  1118. }
  1119.  
  1120. /**
  1121. *
  1122. *   The following functions setup the proper registers for the call-back 
  1123. *   functions.
  1124. *
  1125. **/
  1126. #asm
  1127.         public _callad
  1128. _callad:
  1129.         movea.l 8(sp),a0                ; Second argument goes in a0
  1130.         move.l  12(sp),d0               ; Third  argument goes in d0
  1131. /*
  1132. *   Now this is a trick to avoid using another register.
  1133. *   Charlie taught me this...
  1134. */
  1135.         move.l  4(sp),-(sp)             ; First  argument is function
  1136.         rts
  1137.  
  1138.         public  _calladda
  1139. _calladda:
  1140.         movea.l 8(sp),a0                ; Second argument goes in a0
  1141.         move.l  12(sp),d0               ; Third  argument goes in d0
  1142.         move.l  16(sp),d1               ; Fourth argument goes in d1
  1143.         movea.l 20(sp),a1               ; Fifth  argument goes in a1
  1144.         move.l  4(sp),-(sp)             ; First  argument is function
  1145.         rts
  1146.  
  1147.         public  _calla
  1148. _calla:
  1149.         movea.l 8(sp),a0                ; Second argument goes in a0
  1150.         move.l  4(sp),-(sp)             ; First  argument is function
  1151.         rts
  1152.  
  1153.         public  _callaa
  1154. _callaa:
  1155.         movea.l 8(sp),a0                ; Second argument goes in a0
  1156.         movea.l 12(sp),a1               ; Third  argument goes in a1
  1157.         move.l  4(sp),-(sp)             ; First  argument is function
  1158.         rts
  1159.  
  1160.         public  _calladd
  1161. _calladd:
  1162.         move.l  8(sp),a0                ; Second argument goes in a0
  1163.         move.l  12(sp),d0               ; Third  argument goes in d0
  1164.         move.l  16(sp),d1               ; Fourth argument goes in d1
  1165.         move.l  4(sp),-(sp)             ; First  argument is function
  1166.         rts
  1167.  
  1168. #endasm
  1169. /*
  1170. *   Could have added any other functions needed for other call-backs.
  1171. *   Could have written a fancier single one... Could've...
  1172. */
  1173.                               __                
  1174.                              /  \ o    /        
  1175.                        -----/----\----/-----
  1176.                            /    o \__/          
  1177.                                                 
  1178.         Clearly it isn't very hard to implement a simple protocol. More
  1179. elaborate protocols are straightforward extensions to the above example. Of
  1180. course, there are a few more standard files needed to make the above example
  1181. into a complete library (like Open, Close and Expunge functions and a ROM-Tag
  1182. structure) but those parts are the same for any library and aren't given here.
  1183.  
  1184.  
  1185.  
  1186. 5. The interface to the communications program.
  1187. ===============================================
  1188.  
  1189.         The following is an annotated listing of a few call-back functions as
  1190. they are implemented in VLT. Also, it is shown how to initialize the XPR_IO
  1191. structure. Notice that the files supplied in this archive are likely more up to
  1192. date and more extensive than the minimal example given here.
  1193.  
  1194. /** xprfuncs.c
  1195. *
  1196. *   Call-back functions for eXternal PRotocol support
  1197. *
  1198. **/
  1199. #include <functions.h>
  1200. #include <exec/exec.h>
  1201. #include <stdio.h>
  1202. /*
  1203. *   xproto.h is given in Appendix B
  1204. */
  1205. #include "xproto.h"
  1206. /*
  1207. *   xfer.h is a VLT private header file containing some information for
  1208. *   file transfer protocols
  1209. */
  1210. #include "xfer.h"
  1211.  
  1212. /*
  1213. *   These are the C versions of the interface
  1214. */
  1215. long        vlt_update(),  vlt_swrite(),  vlt_fread(),  vlt_fopen(),
  1216.             vlt_fclose(),  vlt_gets(),    vlt_sread(),  vlt_chkabort();
  1217. /*
  1218. *   These are the assembly level glue functions, see vltface.asm
  1219. */
  1220. extern long avlt_update(), avlt_swrite(), avlt_fread(), avlt_fopen(),
  1221.             avlt_fclose(), avlt_gets(),   avlt_sread(), avlt_chkabort();
  1222.  
  1223. /**
  1224. *
  1225. *   This function initializes an XPR_IO structure.
  1226. *
  1227. **/
  1228. xpr_setup(IO)
  1229. struct XPR_IO *IO;
  1230. {
  1231. /*
  1232. *   NULL out all the functions we don't do yet.
  1233. *   Fill the other ones with the addresses to the assembler glue version
  1234. *   of the interface routines. See vltface.asm
  1235. */
  1236.    IO->xpr_filename  = NULL;
  1237.    IO->xpr_fopen     = avlt_fopen;
  1238.    IO->xpr_fclose    = avlt_fclose;
  1239.    IO->xpr_fread     = avlt_fread;
  1240.    IO->xpr_fwrite    = NULL;
  1241.    IO->xpr_sread     = avlt_sread;
  1242.    IO->xpr_swrite    = avlt_swrite;
  1243.    IO->xpr_sflush    = NULL;
  1244.    IO->xpr_update    = avlt_update;
  1245.    IO->xpr_chkabort  = avlt_chkabort;
  1246.    IO->xpr_chkmisc   = NULL;
  1247.    IO->xpr_gets      = avlt_gets;
  1248.    IO->xpr_setserial = NULL;
  1249.    IO->xpr_ffirst    = NULL;
  1250.    IO->xpr_fnext     = NULL;
  1251.    IO->xpr_finfo     = NULL;
  1252.    IO->xpr_fseek     = NULL;
  1253. /*
  1254. *   Support the 1 defined extension
  1255. */
  1256.    IO->xpr_extension = 1L;
  1257. /*
  1258. *   But don't actually implement it yet.
  1259. */
  1260.    IO->xpr_options   = NULL
  1261. /*
  1262. *   Especially, NULL out the XPR private data field.
  1263. */
  1264.    IO->xpr_data      = NULL;
  1265.  
  1266.    return;
  1267. }
  1268.  
  1269. /**
  1270. *
  1271. *   Interface to VLT's MsgDisplay() function.
  1272. *
  1273. **/
  1274. /*
  1275. *   These are formats for VLT's requester
  1276. */
  1277. static char *xprnamfmt = "%s\n%s\n\n\n\n";
  1278. static char *filnamfmt = "\n\n%s\n\n\n";
  1279. static char *blksizfmt = "\n\n\n\nBlock:  %6ld  --  Block Size:  %6ld\n";
  1280. static char *errtimfmt = "\n\n\n\n\nErrors: %6ld  --  Timeouts:    %6ld";
  1281. static char *delayfmt  = "\n\n\n\n\nPacket delay %ld";
  1282. /*
  1283. *   Below are some VLT globals to orchestrate the display
  1284. */
  1285. long xpr_blocks = 0L, xpr_blocksize = 0L, xpr_errors = 0L, xpr_timeouts = 0L;
  1286. /*
  1287. *   The function
  1288. */
  1289. long vlt_update(x)
  1290. struct XPR_UPDATE *x;
  1291. {
  1292.    extern struct Window *mywindow;
  1293.    extern char *XPR_Name;
  1294. /*
  1295. *   First time, determine the window size (50 chars wide, 5 lines tall).
  1296. */
  1297.    SetMsgWindow(mywindow, 50, 6);
  1298. /*
  1299. *   Use VLT's PostMsg function to display all the information.
  1300. */
  1301.    if (x->xpru_updatemask & XPRU_PROTOCOL) {
  1302.       PostMsg(mywindow, xprnamfmt, XPR_Name, x->xpru_protocol);
  1303.    }
  1304.    if (x->xpru_updatemask & XPRU_MSG) {
  1305.       PostMsg(mywindow, xprnamfmt, XPR_Name, x->xpru_msg);
  1306.    }
  1307.    if (x->xpru_updatemask & XPRU_ERRORMSG) {
  1308.       PostMsg(mywindow, xprnamfmt, XPR_Name, x->xpru_errormsg);
  1309.    }
  1310.    if (x->xpru_updatemask & XPRU_FILENAME) {
  1311.       PostMsg(mywindow, filnamfmt, x->xpru_filename);
  1312.    }
  1313.    if (x->xpru_updatemask & XPRU_PACKETDELAY) {
  1314.       PostMsg(mywindow, delayfmt, x->xpru_packetdelay);
  1315.    }
  1316.    if (x->xpru_updatemask & (XPRU_BLOCKS | XPRU_BLOCKSIZE)) {
  1317.       if (x->xpru_updatemask & XPRU_BLOCKS)    xpr_blocks    = x->xpru_blocks;
  1318.       if (x->xpru_updatemask & XPRU_BLOCKSIZE) xpr_blocksize = x->xpru_blocksize;
  1319.       PostMsg(mywindow, blksizfmt, xpr_blocks, xpr_blocksize);
  1320.    }
  1321.    if (x->xpru_updatemask & (XPRU_ERRORS | XPRU_TIMEOUTS)) {
  1322.       if (x->xpru_updatemask & XPRU_ERRORS)   xpr_errors   = x->xpru_errors;
  1323.       if (x->xpru_updatemask & XPRU_TIMEOUTS) xpr_timeouts = x->xpru_timeouts;
  1324.       PostMsg(mywindow, errtimfmt, xpr_errors, xpr_timeouts);
  1325.    }
  1326.    return(0L);
  1327. }
  1328.  
  1329. /**
  1330. *
  1331. *   Prompt the user for input
  1332. *
  1333. **/
  1334. long vlt_gets(s, t)
  1335. char *s, *t;
  1336. {
  1337. /*
  1338. *   Use VLT's DoRequest() function
  1339. */
  1340.    return((long) DoRequest(mywindow, t, s, NULL, " Cancel "));
  1341. }
  1342.  
  1343. /**
  1344. *
  1345. *   Write a string to the serial port
  1346. *
  1347. **/
  1348. long vlt_swrite(s, n)
  1349. char *s;
  1350. long n;
  1351. {
  1352. /*
  1353. *   Use VLT's SendString() function
  1354. */
  1355.    SendString(s, (int) n);
  1356.    return(0L);
  1357. }
  1358.  
  1359. /**
  1360. *
  1361. *   Read characters from the serial port
  1362. *
  1363. **/
  1364. long vlt_sread(buff, length, micros)
  1365. unsigned char *buff;
  1366. long length, micros;
  1367. {
  1368.    extern int timeout;
  1369.    long secs = 0L;
  1370.  
  1371.    if (buff == NULL) return(-1L);
  1372. /*
  1373. *   Convert timeout to seconds and micros if necessary
  1374. */
  1375.    if (micros) {
  1376.       if (micros > 1000000L) {
  1377.          secs   = micros / 1000000L;
  1378.          micros = micros % 1000000L;
  1379.       }
  1380.    }
  1381. /*
  1382. *   What follows is pseudo code. VLT's implementation is at this point
  1383. *   different.
  1384. */
  1385.    StartTimer(secs, micros);
  1386. /*
  1387. *   VLT has a global called timeout. This comes in xfer.h.
  1388. *   If the read was successful, add character to buffer.
  1389. */
  1390.    for (i = 0; (timeout == GOODREAD) && (i < size); i++)
  1391.       buff[i] = (unsigned char) readchar();
  1392. /*
  1393. *   Either timed out or buffer is full.
  1394. */
  1395.    if (timeout != TIMEOUT) AbortTimer();
  1396. /*
  1397. *   If carrier dropped, return error condition
  1398. */
  1399.    if (timeout == CARRIER_DROPPED) return(-1L);
  1400. /*
  1401. *   Else return the number of characters read.
  1402. */
  1403.    return(i);
  1404. }
  1405.  
  1406. /**
  1407. *
  1408. *   Interfaces to stdio
  1409. *
  1410. **/
  1411. long vlt_fopen(s, t)
  1412. char *s, *t;
  1413. {
  1414.    return((long) fopen(s, t));
  1415. }
  1416.  
  1417. long vlt_fclose(fp)
  1418. FILE *fp;
  1419. {
  1420.    return((long) fclose(fp));
  1421. }
  1422.  
  1423. long vlt_fread(buff, size, count, fp)
  1424. char *buff;
  1425. long size, count;
  1426. FILE *fp;
  1427. {
  1428.    int res;
  1429.    res = fread(buff, (int) size, (int) count, fp);
  1430.    return((long) res);
  1431. }
  1432.  
  1433. /**
  1434. *
  1435. *   Check for Abort
  1436. *
  1437. **/
  1438. long vlt_chkabort()
  1439. {
  1440. /*
  1441. *   VLT aborts its protocols when the escape key is pressed.
  1442. *   CheckForKey loops over the UserPort messages looking for an escape.
  1443. */
  1444.    return((long) CheckForKey(69));
  1445. }
  1446.                               __                
  1447.                              /  \ o    /        
  1448.                        -----/----\----/-----
  1449.                            /    o \__/          
  1450.                                                 
  1451.         Clearly, this part of the implementation isn't hard either. The only
  1452. thing left is the assembly level glue on the communications program side. You
  1453. may wonder at this point why all this assembly level stuff is necessary. It is
  1454. necessary because many programs and libraries are written in small code/small
  1455. data. This means that both the communications program and the library address
  1456. their code/data off of some register, in the case of Manx usually A4. The
  1457. problem is that the communications program and the library are loaded in
  1458. different parts of memory, while startup code takes care of setting up the
  1459. proper value for A4. And the values of A4 are different for the the
  1460. communications program and the library! Now, if you just call a library
  1461. function, the assembly level glue does a few things, among which are: (1) saving
  1462. the caller's A4 somewhere safe and (2) retrieving the A4 it stored somewhere
  1463. when the library was loaded. Then the library function is executed, and the
  1464. function returns to the glue. The glue then restores A4 to the state it was in
  1465. before the library call.
  1466.         In the case of these call-back functions, we have to do the reverse.
  1467. After all, when a function like xpr_update is called, the current value of A4 is
  1468. the one that goes with the library's code. If the call-back function tries to
  1469. access any data back in the communications program, we're in big trouble.
  1470.         So what the assembly part of the call-backs has to do is (1) save the
  1471. library's A4 (on the stack) and (2) get the value of A4 appropriate for the
  1472. communications program. Then we can push the various registers onto the stack,
  1473. call the C version of the call-back and then restore the value of A4 to what the
  1474. library wants.
  1475.         For the above call-backs, the assembly level glue is listed below. 
  1476.  
  1477. ;;; vltface.asm
  1478. ;
  1479. ;   DESCRIPTION:
  1480. ;   ===========
  1481. ;
  1482. ;        This is an interface to VLT callback functions from
  1483. ;        external protocol libraries.
  1484. ;
  1485. ;   AUTHOR/DATE:  W.G.J. Langeveld, March 1989.
  1486. ;   ============
  1487. ;
  1488. ;;;
  1489.  
  1490.         public  _geta4
  1491.  
  1492. setup   macro
  1493.         movem.l d2/d3/d4-d7/a2-a6,-(sp)
  1494.         jsr     _geta4                        ; Get a4.
  1495.         endm
  1496.  
  1497. push    macro
  1498.         move.l  \1,-(sp)
  1499.         endm
  1500.  
  1501. fix     macro
  1502.         ifc     '\1',''
  1503.                 mexit
  1504.         endc
  1505.         ifle    \1-8
  1506.                 addq.l  #\1,sp
  1507.         endc
  1508.         ifgt    \1-8
  1509.                 lea     \1(sp),sp
  1510.         endc
  1511.         endm
  1512.  
  1513. restore macro
  1514.         fix     \1
  1515.         movem.l (sp)+,d2/d3/d4-d7/a2-a6        
  1516.         rts
  1517.         endm
  1518.  
  1519.         public  _avlt_fopen
  1520.         public  _vlt_fopen
  1521.         public  _avlt_fclose
  1522.         public  _vlt_fclose
  1523.         public  _avlt_fread
  1524.         public  _vlt_fread
  1525.         public  _avlt_sread
  1526.         public  _vlt_sread
  1527.         public  _avlt_swrite
  1528.         public  _vlt_swrite
  1529.         public  _avlt_update
  1530.         public  _vlt_update
  1531.         public  _avlt_chkabort
  1532.         public  _vlt_chkabort
  1533.         public  _avlt_gets
  1534.         public  _vlt_gets
  1535.  
  1536. _avlt_fopen:
  1537.         setup
  1538.         push    a1
  1539.         push    a0
  1540.         jsr     _vlt_fopen
  1541.         restore 8
  1542.  
  1543. _avlt_fclose:
  1544.         setup
  1545.         push    a0
  1546.         jsr     _vlt_fclose
  1547.         restore 4
  1548.  
  1549. _avlt_fread:
  1550.         setup
  1551.         push    a1
  1552.         push    d1
  1553.         push    d0
  1554.         push    a0
  1555.         jsr     _vlt_fread
  1556.         restore 16
  1557.  
  1558. _avlt_sread:
  1559.         setup
  1560.         push    d1
  1561.         push    d0
  1562.         push    a0
  1563.         jsr     _vlt_sread
  1564.         restore 12
  1565.  
  1566. _avlt_swrite:
  1567.         setup
  1568.         push    d0
  1569.         push    a0
  1570.         jsr     _vlt_swrite
  1571.         restore 8
  1572.  
  1573. _avlt_update:
  1574.         setup
  1575.         push    a0
  1576.         jsr     _vlt_update
  1577.         restore 4
  1578.  
  1579. _avlt_chkabort:
  1580.         setup
  1581.         jsr     _vlt_chkabort
  1582.         restore
  1583.  
  1584. _avlt_gets:
  1585.         setup
  1586.         push    a1
  1587.         push    a0
  1588.         jsr     _vlt_gets
  1589.         restore 8
  1590.  
  1591.                               __                
  1592.                              /  \ o    /        
  1593.                        -----/----\----/-----
  1594.                            /    o \__/          
  1595.                                                 
  1596.  
  1597.  
  1598.  
  1599.  
  1600.  
  1601.  
  1602. 6. XPR Extensions
  1603. =================
  1604.  
  1605.         While simple protocols can usually get by with the functionality  given
  1606. in sections 2 through 5 above, some more elaborate protocols may need additional
  1607. functionality. Also, one may want to present the user with a more polished
  1608. interface in certain situations. This is accomplished under the XPR
  1609. specification in a number of ways.
  1610.         It has become clear that in many cases the communications program needs
  1611. to know a few details about the XPR that it is currently running. Some of these
  1612. relate to simple yes/no decisions on the part of the communications program, and
  1613. can be represented as bits that are either set or not. A number of bits in the
  1614. return codes of the XProtocolSetup() function have been defined in this way, and
  1615. they are listed in section 6.1.
  1616.         The straightforward way to extend the XPR capabilities is through the
  1617. use of more call-back functions. The first such function, xpr_options(), was
  1618. already described in a previous release of this document. This document will
  1619. describe and standardize this and a few more such functions in section 6.2.
  1620.         Finally, there is a need in certain file transfer protocols to monitor
  1621. what host and/or user are doing even while not in the process of sending or
  1622. receiving files by protocol transfer. For that purpose, a few XPR library
  1623. functions have been added. The mechanics of this is described in section 6.3.
  1624.  
  1625.  
  1626. 6.1 Library function calling conventions and return codes.
  1627. ----------------------------------------------------------
  1628.  
  1629.         This section defines more precisely what the return codes of the four
  1630. standard XPR library functions mean. Also, in some cases calling conventions
  1631. are more clearly specified.
  1632.  
  1633. 6.1.1 XProtocolSetup()
  1634. ----------------------
  1635.  
  1636.         The library function XProtocolSetup() is called with as the single
  1637. argument a pointer to a previously initialized XPR_IO structure. The calling
  1638. sequence is:
  1639.  
  1640.         long setup_flags = XProtocolSetup(struct XPR_IO *IO);
  1641.         D0                                A0
  1642.  
  1643. where struct XPR_IO is defined as in section 3 and appendix B.
  1644.         When this function is called by the communications program with a NULL
  1645. value in the xpr_filename field, the function is expected to prompt the user for
  1646. setup information. When the xpr_filename field points to a null terminated
  1647. string, this string is expected to be interpreted as a direct command or
  1648. initialization sequence, and the function is in general NOT expected to prompt
  1649. the user for input. An exception to this latter rule occurs, when the command or
  1650. initialization string directly or indirectly instructs the XPR to prompt the
  1651. user for input. In particular, the empty string "", should always be interpreted
  1652. as a void command (a NOP), and should never cause XProtocolSetup() to prompt for
  1653. input.
  1654.         This is particularly useful when the communications program only wants
  1655. to retrieve the value of setup_flags, which is the return code of
  1656. XProtocolSetup(), without going through the protocol setup sequence.
  1657.         With this extension of the specification, it now becomes natural to 
  1658. always call XProtocolSetup() right after opening the XPR library, either with an
  1659. empty string or with an initialization string if one can be found. In all cases,
  1660. the XPR should return a proper value for the return code, as defined below. The
  1661. communications program still should have a menu option or other way to allow the
  1662. user to go through an XPR setup sequence, by calling XProtocolSetup() with a
  1663. NULL pointer in the xpr_filename field.
  1664.  
  1665.         The return code, setup_flags, is a bit mask. The currently defined bits,
  1666. when turned on, have the following meaning:
  1667.  
  1668.         Bit 0:   Successful completion.
  1669.         Bit 1:   Protocol requires no communications program supplied file
  1670.                  requester for receive: either the XPR supplies the file
  1671.                  requester or the protocol is capable of receiving file name
  1672.                  information through other means (e.g., from the host).
  1673.         Bit 2:   Protocol requires no communications program supplied file
  1674.                  requester for send: either the XPR supplies the file requester
  1675.                  or the protocol is capable of receiving file name information
  1676.                  through other means.
  1677.         Bit 3:   Communications program is requested to call XProtocolHostMon()
  1678.                  for all serial port input (see section 6.3).
  1679.         Bit 4:   Communications program is requested to call XProtocolUserMon()
  1680.                  for all user input (see section 6.3).
  1681.         Bit 5:   Communications program is requested to call XProtocolHostMon()
  1682.                  without waiting for serial input (see section 6.3).
  1683. [>*
  1684.         Bit15:   Communication program should not open transfer status
  1685.                  screen. (Protocol handles status/skip/abort etc...)
  1686.                  This will propably need working xpr_getptr option which
  1687.                  is 4th extension.
  1688.         Bit16:   Protocol follows XPR2.001 definations.
  1689.                  (Upload files are always open with mode "r")
  1690.         Bit17:   Protocol uses internal double buffer, xpr_swrite can
  1691.                  return immediately if previous xpr_swrite is done.
  1692.                  If previous xpr_swrite isn't done you must wait till
  1693.                  it's sent and return after that. Ie. comprog don't
  1694.                  wait current xpr_swrite. This is generally known as
  1695.                  double buffering;-)
  1696. <*]
  1697.  
  1698.         The value 0L is returned to indicate failure.
  1699.  
  1700.  
  1701. 6.1.2 XProtocolSend()
  1702. ---------------------
  1703.  
  1704. The calling sequence is:
  1705.  
  1706.         long status = XProtocolSend(struct XPR_IO *IO);
  1707.         D0                          A0
  1708.  
  1709. where struct XPR_IO is defined as in section 3 and appendix B.
  1710.         The value 0L is returned to indicate failure, 1L to indicate success.
  1711. Other non-zero return codes are also to be interpreted as successful, but the
  1712. meaning of the other bits is not currently specified.
  1713.  
  1714.  
  1715. 6.1.3 XProtocolReceive()
  1716. ------------------------
  1717.  
  1718. The calling sequence is:
  1719.  
  1720.         long status = XProtocolReceive(struct XPR_IO *IO);
  1721.         D0                             A0
  1722.  
  1723. where struct XPR_IO is defined as in section 3 and appendix B.
  1724.         The value 0L is returned to indicate failure, 1L to indicate success.
  1725. Other non-zero return codes are also to be interpreted as successful, but the
  1726. meaning of the other bits is not currently specified.
  1727.  
  1728.  
  1729. 6.1.4 XProtocolCleanup()
  1730. ------------------------
  1731.  
  1732. The calling sequence is:
  1733.  
  1734.         long status = XProtocolCleanup(struct XPR_IO *IO);
  1735.         D0                             A0
  1736.  
  1737. where struct XPR_IO is defined as in section 3 and appendix B.
  1738.         The value 0L is returned to indicate failure, 1L to indicate success.
  1739. Other non-zero return codes are also to be interpreted as successful, but the
  1740. meaning of the other bits is not currently specified.
  1741.  
  1742.  
  1743.  
  1744.  
  1745. 6.2 XPR_IO extension functions.
  1746. -------------------------------
  1747.  
  1748.         The following functions are now part of the XPR_IO extended structure
  1749. definition:
  1750.  
  1751.         xpr_options()     Prompts user for commands or options.
  1752.         xpr_unlink()      Deletes files by name.
  1753.         xpr_squery()      Returns actual size of current serial buffer contents.
  1754.         xpr_getptr()      Gets various pointers from user.
  1755.  
  1756.         The following sections will discuss each of these functions in detail.
  1757.  
  1758.  
  1759. 6.2.1    long  *xpr_options();
  1760. ------------------------------
  1761.  
  1762.         This function is in the first extension field of the XPR_IO structure.
  1763. Only use this function if the value of the xpr_extension field is 1L or larger.
  1764. The calling sequence is:
  1765.  
  1766.         long status = (*xpr_options)(long n, struct xpr_option *opt[])
  1767.         D0                           D0      A0
  1768.  
  1769. The function passes to the comm program a pointer to an array of n pointers to
  1770. xpr_option structures, where n is limited to 31. The xpr_option structures are
  1771. defined as follows:
  1772.  
  1773. struct xpr_option {
  1774.    char *xpro_description;      /* description of the option                  */
  1775.    long  xpro_type;             /* type of option                             */
  1776.    char *xpro_value;            /* pointer to a buffer with the current value */
  1777.    long  xpro_length;           /* buffer size                                */
  1778. }
  1779.  
  1780. Valid values for xpro_type are:
  1781.  
  1782. #define XPRO_BOOLEAN 1L         /* xpro_value is "yes", "no", "on" or "off"   */
  1783. #define XPRO_LONG    2L         /* xpro_value is string representing a number */
  1784. #define XPRO_STRING  3L         /* xpro_value is a string                     */
  1785. #define XPRO_HEADER  4L         /* xpro_value is ignored                      */
  1786. #define XPRO_COMMAND 5L         /* xpro_value is ignored                      */
  1787. #define XPRO_COMMPAR 6L         /* xpro_value contains command parameters     */
  1788.  
  1789.         The array is allocated and initialized by the XPR to default values. If
  1790. the comm program implements this function, it should display the description of
  1791. the option and its current value to the user and allow him/her to change them.
  1792. This could be accomplished either by dynamically building a requester or by
  1793. displaying each line one at a time and allow the user to enter new values or
  1794. accept the default. Options that have boolean values could be implemented by the
  1795. comm program as boolean gadgets, but the new value must be returned as "yes" or
  1796. "on" for logical 1 or "no" or "off" for logical 0 in the xpro_value buffer.
  1797. Note, that the XPR, if it uses this function must recognize both "yes" and "on"
  1798. for logical 1 and "no" and "off" for logical 0. Long values must if necessary be
  1799. converted to a string and copied to the xpro_value buffer.  For options that
  1800. have string values, the comm program must ensure that the new string selected by
  1801. the user fits in the value buffer as determined by the xpro_length field. The
  1802. buffer is supplied by the XPR, and must be large enough to be able to hold the
  1803. '\0' termination.
  1804.         The option of type XPRO_HEADER contains a pointer to an explanatory
  1805. message in its xpro_description field. It is to be interpreted as a header
  1806. string for the options that follow. It has no other function, any bits
  1807. corresponding to this option in the return value should be ignored, and the
  1808. xpr_value string is meaningless, but should be initialized to either NULL or a
  1809. valid pointer to a buffer. The message should have a length of 50 characters or
  1810. less.
  1811.         The options of type XPRO_COMMAND and XPRO_COMMPAR are used for such
  1812. functions as Kermit Bye or Finish. Simple commands (XPRO_COMMAND) could be
  1813. displayed as boolean gadgets in a requester, while commands needing parameters
  1814. could have an associated string gadget. The difference between commands like
  1815. this and other options is that when one of these commands is selected, the
  1816. requester should disappear and xpr_options() should return immediately, with
  1817. only the bit coresponding to the command set. Therefore, ideally, the XPR should
  1818. not mix XPRO_COMMAND/XPRO_COMMPAR options with other options (except of type
  1819. XPRO_HEADER). Rather, the XPR should first call xpr_options() with only 
  1820. XPRO_COMMAND/XPRO_COMMPAR/XPRO_HEADER options, one of which would be a "Change
  1821. Defaults" command (type XPRO_COMMAND). This command, when selected, would cause
  1822. the XPR to call xpr_options() with a list of other xpr_option structures for
  1823. non-commands and their headers. This way, the communications program would
  1824. automatically list the XPR commands first, and one of the commands would be a
  1825. "Change Defaults" command, which when selected by the user would bring up a
  1826. second requester with the various other options supported by the XPR. For simple
  1827. commands, the xpr_value string is meaningless and should either be set to NULL
  1828. or contain a valid pointer to a buffer anyway. For commands needing parameters,
  1829. the xpr_value string should contain the current default value of the parameter.
  1830. There is a compatibility issue: communications programs written with earlier
  1831. versions of the XPR spec may not know about XPRO_COMMAND etc. It is therefore
  1832. advisable to bring up the second requester anyway if no command is selected
  1833. from the first requester. In that case, it would be a good idea to include a
  1834. "CANCEL" command in the first requester, which does nothing but provide a means
  1835. to prevent the second requester from appearing.
  1836.  
  1837.         As an example, when selecting a ZMODEM based XPR the following array of
  1838. xpr_option structures could be passed to the comm program:
  1839.  
  1840. xpro_description                xpro_value    xpro_type
  1841. --------------------------------------------------------------
  1842. Convert NL to NL/CR             no            XPRO_BOOLEAN
  1843. Escape only CTRL chars          yes           XPRO_BOOLEAN
  1844. Escape ALL chars                no            XPRO_BOOLEAN
  1845. Send full pathname              yes           XPRO_BOOLEAN
  1846. Send 1K blocks                  no            XPRO_BOOLEAN
  1847. Subpacket length                512           XPRO_LONG
  1848. Disable 32-bit CRC              no            XPRO_BOOLEAN
  1849. Protect destination file        no            XPRO_BOOLEAN
  1850. Timeout value (sec)             10            XPRO_LONG
  1851. Delete after transmission       no            XPRO_BOOLEAN
  1852. Overwrite existing file         no            XPRO_BOOLEAN
  1853.  
  1854. Notice again, that the COMM program still knows little about the individual
  1855. option items (and in fact there is no way for it to find out, in keeping with
  1856. the philosophy of XPR). Also notice that a cheap way to implement this function
  1857. is to loop over the n supplied xpr_option's and to call the likely already
  1858. implemented xpr_gets function with the option description and the value buffer
  1859. (but remember that some options may not have valid value buffers!).
  1860.         It is important to follow a few rules when calling this function: the
  1861. description strings should be 25 characters or less (except for XPRO_HEADER's).
  1862. The value strings can be any length up to 255 characters, but be aware that in a
  1863. typical situation only about 10 to 15 of them will be displayed in a string
  1864. gadget.
  1865.         The return value, status, reflects which options have changed by having
  1866. the corresponding bit set. The first option in the xpr_option array corresponds
  1867. to  bit 0 (low-order), etc. If the options are all of the types boolean, long,
  1868. string or header, the comm program may decide to not detect whether the options
  1869. changed or not, and 0x07FFFFFFL may be returned, in effect specifying that all
  1870. options have changed. On the other hand, if the communications program returns
  1871. a value with multiple bits set even though some or all of the options are of
  1872. type command, the XPR should be careful to cause minimal damage, or display
  1873. an error message.
  1874.         If nothing changed or no command was selected, 0L is returned. If an
  1875. error occurred, the function returns -1L.
  1876.  
  1877.  
  1878. 6.2.2    long  *xpr_unlink();
  1879. -----------------------------
  1880.  
  1881.         This function is in the second extension field of the XPR_IO structure.
  1882. Only use this function if the value of the xpr_extension field is 2L or larger.
  1883. The calling sequence is:
  1884.  
  1885.         long status = (*xpr_unlink)(char *filename)
  1886.         D0                          A0
  1887.  
  1888. This function returns 0L on success, -1L on failure. It attempts to delete the
  1889. file who's name is contained in the character array pointed to bye the only
  1890. argument. The file cannot be locked at the time by any process.
  1891.  
  1892.  
  1893. 6.2.3    long  *xpr_squery();
  1894. ------------------------------
  1895.  
  1896.         This function is in the third extension field of the XPR_IO structure.
  1897. Only use this function if the value of the xpr_extension field is 3L or larger.
  1898. The calling sequence is:
  1899.  
  1900.         long size = (*xpr_squery)()
  1901.         D0
  1902.  
  1903.         This function returns the number of characters currently available
  1904. in the serial device. It returns -1L on error. When no characters are available
  1905. the function returns 0L.
  1906.  
  1907.  
  1908. 6.2.4    long  *xpr_getptr();
  1909. -----------------------------
  1910.  
  1911.         This function is in the fourth extension field of the XPR_IO structure.
  1912. Only use this function if the value of the xpr_extension field is 4L or larger.
  1913. The calling sequence is:
  1914.  
  1915.         long *ptr = (*xpr_getptr)(type)
  1916.         D0                        D0
  1917.  
  1918. This function returns selected pointers to structures or buffers defined in 
  1919. the communications program.
  1920.         Currently the only allowed pointer type is 
  1921.  
  1922.         type:                   resulting pointer:         
  1923.         ...................................................
  1924.  
  1925.         1L                      pointer to custom Screen
  1926.                                 or 0L for Workbench.
  1927.  
  1928.         (other values)          (to be determined)
  1929.  
  1930. This function can be used to open windows on the communications program's
  1931. custom screen, and together with the library functions XProtocolHostMon() and
  1932. XProtocolUserMon() such protocols as DoubleTalk should be feasible. Indeed,
  1933. entire external terminal emulations might be written in this way.
  1934.  
  1935. The function returns -1L on failure. Note that the failure can be due to 
  1936. various causes: the communications program may not want to return a particular
  1937. pointer, the version may not know about some allowed types, or the type may for
  1938. other reasons not be valid. Also: if 0L is returned, it is up to the XPR to 
  1939. determine whether this is a legal return value. With type 1, this is fine, but
  1940. in general a NULL pointer may of course not be valid. The XPR is responsible
  1941. for closing any windows or other resources on a call to XProtocolCleanup().
  1942.  
  1943.  
  1944. 6.3 New library functions.
  1945. --------------------------
  1946.  
  1947.         We now discuss the two library functions XProtocolHostMon and
  1948. XProtocolUserMon(). These two functions are provided by the XPR as additional
  1949. library entries and their presence is made known to the communications program
  1950. by setting certain bits in the return value of XProtocolSetup(). They are called
  1951. by the communcations program whenever data is received from (HostMon) or sent to
  1952. (UserMon) the serial port, except that care has to be taken that these functions
  1953. are not called directly or indirectly by the xpr_sread() and xpr_swrite()
  1954. functions.
  1955.  
  1956.  
  1957. 6.3.1 XProtocolHostMon()
  1958. ------------------------
  1959.  
  1960.         This function should be called by the communications program only when
  1961. bit 3 of the flags returned by XProtocolSetup() is set. Calling this function
  1962. when bit 3 is not set will probably cause a system failure. The function should
  1963. be called just after any input from the serial device is received, and just
  1964. before anything else is done with the received data. The calling sequence is
  1965.  
  1966.         long newactual = XProtocolHostMon(struct XPR_IO *IO, char *serbuff,
  1967.         D0                                A0                 A1
  1968.                                           long actual, long maxsize)
  1969.                                           D0           D1
  1970.  
  1971. Here, IO is a previously initialized XPR_IO structure, serbuff is a pointer to a
  1972. buffer containing the data from the serial device, actual is the number of bytes
  1973. received from the serial device, and maxsize is the actual allocated size of
  1974. serbuff. The XPR is entitled to make any modifications to the data in serbuff it
  1975. wants, as long as the amount of modified data does not overflow the buffer as
  1976. indicated by maxsize. When the XPR is done looking at or changing the data, it
  1977. returns the new actual number of bytes of data in serbuff in newactual. Note,
  1978. that some actions of the XPR may cause the buffer to become invalid: for
  1979. efficiency, the communications program will usually hand a pointer to its one
  1980. and only serial port read buffer in "serbuff" rather than making a copy every
  1981. time. Whenever the XPR, based on the information found in the buffer, decides to
  1982. call any of the callbacks that deal with the serial device (xpr_sread(),
  1983. xpr_sflush(), xpr_squery()), the communications program may reuse the buffer,
  1984. erasing the previous contents. Consequently, if the XPR needs to preserve the
  1985. contents of the buffer, it must first make a local copy. Whenever there is a
  1986. chance that the data in serbuff was invalidated, the XPR should return
  1987. newactual = 0L.
  1988.     Note to the communications program author: when this function is called
  1989. after serial input was received, the state of the communications program is
  1990. usually such that no serial read request is outstanding. Still, the XPR may
  1991. start a file transfer from inside XProtocolHostMon. This situation is different
  1992. from the case where the user requests an upload or download by selecting e.g. a
  1993. menu item: at such a time, the communications program typically does have an
  1994. outstanding serial read request. Moreover, upon return from the
  1995. XProtocolHostMon() call, a previous call by the XPR to xpr_sread() may have
  1996. caused a serial read request to be queued. It is therefore important that the
  1997. communications program ensure that read requests are queued when appropriate,
  1998. including from inside xpr_sread(), and that read requests are not queued more
  1999. than once.
  2000.     Some XPR's may require control even when there is no outstanding
  2001. serial input or user input. In order to prevent the communications program
  2002. from going into a Wait() state, there is another bit returned by
  2003. XProtocolSetup(). When bit 5 is set, the communications program should not
  2004. wait, but call XProtocolHostMon() instead. If XProtocolHostMon() returns a
  2005. non-zero newactual, the data in serbuff should be treated just as if new
  2006. serial input was received. The XPR should never set this bit unless there is
  2007. a good reason: bypassing the communications program's Wait is very multitasking
  2008. unfriendly.
  2009.  
  2010.         This function, together with XProtocolUserMon(), can be used to modify
  2011. the behavior of communications programs dramatically. Especially, the entire data
  2012. handling of the communications program could be bypassed by returning newactual
  2013. = 0L, and processing all data inside of XProtocolHostMon(), effectively allowing
  2014. external terminal emulations if the XPR were to open appropriate windows for
  2015. displaying the data. It is in fact possible to have both an external protocol
  2016. (XPR) and an external emulation (XEM) running at the same time: the best way
  2017. to do this is to have duplicate copies of the xpr.lib glue routines, one for
  2018. XPR's and one for XEM's. It is recommended that names of external emulation
  2019. libraries follow the prescription: xem<emulation>.library, e.g. xemvt100.library
  2020. or xemtek4014.library.
  2021.         Another use for these functions would be to decode and encode and
  2022. perhaps compress the data after, resp. before transmission, for example for use
  2023. with hosts supporting error correction/detection protocols such as MNP.
  2024.         A more mundane purpose of this function is to watch the data stream
  2025. for incoming escape or control sequences otherwise not supported by the 
  2026. communications program. Most notably, those sequences used to automatically
  2027. start file transfers as in ZMODEM or CompuServe B+, etc. When such a sequence
  2028. is detected, the XPR should directly call the appropriate XPR function to
  2029. handle the transfer from inside XProtocolHostMon(), and return newactual = 0L
  2030. to the communications program after the transfer has finished.
  2031.     Note to the XPR implementer: if the protocol the XPR implements is able
  2032. to autostart using XProtocolHostMon(), but als needs user input, it can use
  2033. xpr_gets() or xpr_options(). If those functions do not satisfy the need, the XPR
  2034. must use other means. One should be aware that for example the ARP file
  2035. requester can be called from inside an XPR library, in the same manner as it
  2036. can be called from any other program. The function xpr_getptr() can be used to
  2037. retrieve the pointer to the communications program's screen.
  2038.  
  2039.  
  2040. 6.3.2 XProtocolUserMon()
  2041. ------------------------
  2042.  
  2043.         This function should be called by the communications program only when
  2044. bit 4 of the flags returned by XProtocolSetup() is set. Calling this function
  2045. when bit 4 is not set will probably cause a system failure. The function should
  2046. be called just before any output is sent to the serial device. The calling
  2047. sequence is
  2048.  
  2049.         long newactual = XProtocolUserMon(struct XPR_IO *IO, char *serbuff,
  2050.         D0                                A0                 A1
  2051.                                           long actual, long maxsize)
  2052.                                           D0           D1
  2053.  
  2054. Here, IO is a previously initialized XPR_IO structure, serbuff is a pointer to a
  2055. buffer containing the data to be sent to the host, actual is the number of bytes
  2056. to be sent, and maxsize is the actual allocated size of serbuff. The XPR is
  2057. entitled to make any modifications to the data in serbuff it wants, as long as
  2058. the amount of modified data does not overflow the buffer as indicated by
  2059. maxsize. When the XPR is done looking at or changing the data, it returns the
  2060. new actual number of bytes of data in serbuff in newactual.
  2061.         This function, together with XProtocolHostMon(), can be used to modify
  2062. the behavior of communications programs dramatically. Especially, the entire data
  2063. handling of the communications program could be bypassed by returning newactual
  2064. = 0L, and processing all data inside of XProtocolUserMon(), effectively allowing
  2065. external terminal emulations, if the XPR were to open appropriate windows for
  2066. displaying the data. To get RAW KEY user input etc., the XPR would however have
  2067. to also open its own windows for IDCMP input. To that end, the function
  2068. xpr_getptr can be used to obtain the pointer to the screen of the communications
  2069. program where the window(s) should open.
  2070.         Another use for these functions would be to decode and encode and
  2071. perhaps compress the data after, resp. before transmission, for example for use
  2072. with hosts supporting error correction/detection protocols such as MNP.
  2073.  
  2074.                               __                
  2075.                              /  \ o    /        
  2076.                        -----/----\----/-----
  2077.                            /    o \__/          
  2078.                                                 
  2079.  
  2080. This concludes the documentation on external protocols using Amiga shared
  2081. libraries. If you have any questions, comments or suggestions, contact me on
  2082. BIX.
  2083.         Meanwhile, have fun!
  2084.  
  2085.  
  2086.  
  2087.  
  2088.  
  2089.  
  2090.  
  2091.  
  2092. Appendix A: XPR library skeleton.
  2093. =================================
  2094.  
  2095. ;;; libface.c
  2096. ;
  2097. ;   DESCRIPTION:
  2098. ;   ===========
  2099. ;
  2100. ;       This is the skeleton for an Amiga Exec library.
  2101. ;       This version is written for Aztec C. It is based on the example
  2102. ;       library by Jim Mackraz who got some stuff from Neil Katin.
  2103. ;       This library implements a protocol transfer library.
  2104. ;       All changes and additions by me.
  2105. ;
  2106. ;   AUTHOR/DATE:  W.G.J. Langeveld, February 1989.
  2107. ;   ============
  2108. ;
  2109. ;;;
  2110.  
  2111.         include 'exec/types.i'
  2112.  
  2113. setup   macro
  2114.         movem.l d2/d3/d4-d7/a2-a6,-(sp)
  2115.         jsr     _geta4                  ;set up a4 for small model
  2116.         endm
  2117.  
  2118. push    macro
  2119.         move.l  \1,-(sp)
  2120.         endm
  2121.  
  2122. fix     macro
  2123.         ifc     '\1',''
  2124.                 mexit
  2125.         endc
  2126.         ifle    \1-8
  2127.                 addq.l  #\1,sp
  2128.         endc
  2129.         ifgt    \1-8
  2130.                 lea     \1(sp),sp
  2131.         endc
  2132.         endm
  2133.  
  2134. restore macro
  2135.         fix     \1
  2136.         movem.l (sp)+,d2/d3/d4-d7/a2-a6 
  2137.         rts
  2138.         endm
  2139.  
  2140.         dseg
  2141.  
  2142.         public  _libfunctab
  2143. _libfunctab:
  2144.         dc.l    XPRopen
  2145.         dc.l    XPRclose
  2146.         dc.l    XPRexpunge
  2147.         dc.l    $0000
  2148.         dc.l    XPRXProtocolCleanup
  2149.         dc.l    XPRXProtocolSetup
  2150.         dc.l    XPRXProtocolSend
  2151.         dc.l    XPRXProtocolReceive
  2152.         dc.l    XPRXProtocolHostMon
  2153.         dc.l    XPRXProtocolUserMon
  2154.         dc.l    $ffffffff
  2155.  
  2156.         cseg
  2157.  
  2158.         ;--- library functions
  2159.         public  _XPROpen
  2160.         public  _XPRClose
  2161.         public  _XPRExpunge
  2162.         public  _XProtocolCleanup
  2163.         public  _XProtocolSetup
  2164.         public  _XProtocolSend
  2165.         public  _XProtocolReceive
  2166.         public  _XProtocolHostMon
  2167.         public  _XProtocolUserMon
  2168.  
  2169.         public  _geta4
  2170.  
  2171. XPRopen:
  2172.         setup
  2173.         push a6
  2174.         jsr     _XPROpen
  2175.         restore 4
  2176.  
  2177. XPRclose:
  2178.         setup
  2179.         push a6
  2180.         jsr     _XPRClose
  2181.         restore 4
  2182.  
  2183. XPRexpunge:
  2184.         setup
  2185.         push a6
  2186.         jsr     _XPRExpunge
  2187.         restore 4
  2188.  
  2189. XPRXProtocolCleanup:
  2190.         setup
  2191.         push a0
  2192.         jsr     _XProtocolCleanup
  2193.         restore 4
  2194.  
  2195. XPRXProtocolSetup:
  2196.         setup
  2197.         push a0
  2198.         jsr     _XProtocolSetup
  2199.         restore 4
  2200.  
  2201. XPRXProtocolSend:
  2202.         setup
  2203.         push a0
  2204.         jsr     _XProtocolSend
  2205.         restore 4
  2206.  
  2207. XPRXProtocolReceive:
  2208.         setup
  2209.         push a0
  2210.         jsr     _XProtocolReceive
  2211.         restore 4
  2212.  
  2213. XPRXProtocolHostMon:
  2214.         setup
  2215.         push d1
  2216.         push d0
  2217.         push a1
  2218.         push a0
  2219.         jsr     _XProtocolHostMon
  2220.         restore 16
  2221.  
  2222. XPRXProtocolUserMon:
  2223.         setup
  2224.         push d1
  2225.         push d0
  2226.         push a1
  2227.         push a0
  2228.         jsr     _XProtocolUserMon
  2229.         restore 16
  2230.  
  2231.  
  2232.         end
  2233.  
  2234.  
  2235.  
  2236.  
  2237.  
  2238. Appendix B: The xproto.h include file
  2239. =====================================
  2240.  
  2241. /** xproto.h
  2242. *
  2243. *   Include file for External Protocol Handling
  2244. *
  2245. **/
  2246. /*
  2247. *   The structure
  2248. */
  2249. struct XPR_IO {
  2250.                   char  *xpr_filename;      /* File name(s)             */
  2251.                   long (*xpr_fopen)();      /* Open file                */
  2252.                   long (*xpr_fclose)();     /* Close file               */
  2253.                   long (*xpr_fread)();      /* Get char from file       */
  2254.                   long (*xpr_fwrite)();     /* Put string to file       */
  2255.                   long (*xpr_sread)();      /* Get char from serial     */
  2256.                   long (*xpr_swrite)();     /* Put string to serial     */
  2257.                   long (*xpr_sflush)();     /* Flush serial input buffer*/
  2258.                   long (*xpr_update)();     /* Print stuff              */
  2259.                   long (*xpr_chkabort)();   /* Check for abort          */
  2260.                   long (*xpr_chkmisc)();    /* Check misc. stuff        */
  2261.                   long (*xpr_gets)();       /* Get string interactively */
  2262.                   long (*xpr_setserial)();  /* Set and Get serial info  */
  2263.                   long (*xpr_ffirst)();     /* Find first file name     */
  2264.                   long (*xpr_fnext)();      /* Find next file name      */
  2265.                   long (*xpr_finfo)();      /* Return file info         */
  2266.                   long (*xpr_fseek)();      /* Seek in a file           */
  2267.                   long   xpr_extension;     /* Number of extensions     */
  2268.                   long  *xpr_data;          /* Initialized by Setup.    */
  2269.                   long (*xpr_options)();    /* Multiple XPR options.    */
  2270.                   long (*xpr_unlink)();     /* Delete a file.           */
  2271.                   long (*xpr_squery)();     /* Query serial device      */
  2272.                   long (*xpr_getptr)();     /* Get various host ptrs    */
  2273.               };
  2274. /*
  2275. *   Number of defined extensions
  2276. */
  2277.  
  2278. #define XPR_EXTENSION 6L
  2279.  
  2280. /*
  2281. *   The functions
  2282. */
  2283. extern long XProtocolSend(),  XProtocolReceive(),
  2284.             XProtocolSetup(), XProtocolCleanup();
  2285. /*
  2286. *   Flags returned by XProtocolSetup()
  2287. */
  2288. #define XPRS_FAILURE    0x00000000L
  2289. #define XPRS_SUCCESS    0x00000001L
  2290. #define XPRS_NORECREQ   0x00000002L
  2291. #define XPRS_NOSNDREQ   0x00000004L
  2292. #define XPRS_HOSTMON    0x00000008L
  2293. #define XPRS_USERMON    0x00000010L
  2294. #define XPRS_HOSTNOWAIT 0x00000020L
  2295. #define XPRS_NOUPDATE   0x00008000L
  2296. #define XPRS_SMARTXFER  0x00010000L
  2297. #define XPRS_DOUBLE     0x00020000L
  2298.  
  2299. /*
  2300. *   The update structure
  2301. */
  2302. struct XPR_UPDATE {     long  xpru_updatemask;
  2303.                         char *xpru_protocol;
  2304.                         char *xpru_filename;
  2305.                         long  xpru_filesize;
  2306.                         char *xpru_msg;
  2307.                         char *xpru_errormsg;
  2308.                         long  xpru_blocks;
  2309.                         long  xpru_blocksize;
  2310.                         long  xpru_bytes;
  2311.                         long  xpru_errors;
  2312.                         long  xpru_timeouts;
  2313.                         long  xpru_packettype;
  2314.                         long  xpru_packetdelay;
  2315.                         long  xpru_chardelay;
  2316.                         char *xpru_blockcheck;
  2317.                         char *xpru_expecttime;
  2318.                         char *xpru_elapsedtime;
  2319.                         long  xpru_datarate;
  2320.                         long  xpru_reserved1;
  2321.                         long  xpru_reserved2;
  2322.                         long  xpru_reserved3;
  2323.                         long  xpru_reserved4;
  2324.                         long  xpru_reserved5;
  2325.                    };
  2326. /*
  2327. *   The possible bit values for the xpru_updatemask are:
  2328. */
  2329. #define XPRU_UPLOAD             0x80000000L
  2330. #define XPRU_DNLOAD             0x40000000L
  2331. #define XPRU_PROTOCOL           0x00000001L
  2332. #define XPRU_FILENAME           0x00000002L
  2333. #define XPRU_FILESIZE           0x00000004L
  2334. #define XPRU_MSG                0x00000008L
  2335. #define XPRU_ERRORMSG           0x00000010L
  2336. #define XPRU_BLOCKS             0x00000020L
  2337. #define XPRU_BLOCKSIZE          0x00000040L
  2338. #define XPRU_BYTES              0x00000080L
  2339. #define XPRU_ERRORS             0x00000100L
  2340. #define XPRU_TIMEOUTS           0x00000200L
  2341. #define XPRU_PACKETTYPE         0x00000400L
  2342. #define XPRU_PACKETDELAY        0x00000800L
  2343. #define XPRU_CHARDELAY          0x00001000L
  2344. #define XPRU_BLOCKCHECK         0x00002000L
  2345. #define XPRU_EXPECTTIME         0x00004000L
  2346. #define XPRU_ELAPSEDTIME        0x00008000L
  2347. #define XPRU_DATARATE           0x00010000L
  2348. /*
  2349. *   The xpro_option structure
  2350. */
  2351. struct xpr_option {
  2352.    char *xpro_description;      /* description of the option                  */
  2353.    long  xpro_type;             /* type of option                             */
  2354.    char *xpro_value;            /* pointer to a buffer with the current value */
  2355.    long  xpro_length;           /* buffer size                                */
  2356. };
  2357. /*
  2358. *   Valid values for xpro_type are:
  2359. */
  2360. #define XPRO_BOOLEAN 1L         /* xpro_value is "yes", "no", "on" or "off"   */
  2361. #define XPRO_LONG    2L         /* xpro_value is string representing a number */
  2362. #define XPRO_STRING  3L         /* xpro_value is a string                     */
  2363. #define XPRO_HEADER  4L         /* xpro_value is ignored                      */
  2364. #define XPRO_COMMAND 5L         /* xpro_value is ignored                      */
  2365. #define XPRO_COMMPAR 6L         /* xpro_value contains command parameters     */
  2366.