home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / atarihc / atari.act next >
Text File  |  2020-01-01  |  41KB  |  2,491 lines

  1. ;<<<KERMIT.PNS>>> -- a sample phones file
  2. SU-Score(300)#4153221570
  3. SU-Score(1200)#4154970061
  4. ;<<<D:KCOM1030.ACT>>>
  5. ;All the communications stuff:
  6. ;
  7. ;Opening, closing and dialing for
  8. ;the ATARI 1030 modem
  9. ;
  10. ; KERMIT protocol
  11. ; for Atari Home Computers
  12. ; version 1.1
  13. ; (C) 1983 John Howard Palevich
  14. ; to be distributed free of charge
  15. ;
  16. ;Started NOVEMBER 5, 1983
  17.  
  18. ;Print a string which will identify,
  19. ;to the user, what hardware this
  20. ;COM file supports
  21.  
  22. PROC MODEMINIT()
  23.   PRINTE("for the Atari 1030 modem")
  24.   RETURN
  25.  
  26. ;Return number of character in the
  27. ;input buffer
  28.  
  29. CARD FUNC NCIB()
  30.   BYTE INCNT = $400
  31.   RETURN(INCNT)
  32.  
  33. ;Put a character out the modem
  34.  
  35. PROC PUTR(BYTE DATA)
  36.   PUTD(2, DATA)
  37.   RETURN
  38.  
  39. ;Put out a byte as a modem command
  40.  
  41. PROC PUTCMD(BYTE CMD)
  42.   BYTE CMCMD = $0007
  43.   CMCMD = $FF
  44.   PUTD(2, 27)
  45.   PUTD(2, CMD)
  46.   CMCMD = 0
  47.   RETURN
  48.  
  49. ;Temporarily Suspend Communications
  50. ;so that file I/O can take place
  51.  
  52. PROC StopR()
  53.   PUTCMD('Z)
  54.   RETURN
  55.  
  56. ;Close down the modem channel
  57.  
  58. PROC CloseR()
  59.   PUTCMD('Y)
  60.   CLOSE(2)
  61.   RETURN
  62.  
  63. ;Initialize communications
  64.  
  65. BYTE FUNC OpenR()
  66.   STRING fname = "##:"
  67.   BYTE T
  68.   Close(2)
  69.   fname(1) = 'T
  70.   fname(2) = '1
  71.   t = 12
  72.   Open(2, fname, t, 0)
  73.   T = MSTATUS(2)
  74.   IF T >= 128
  75.   THEN
  76.     PRINTF("Can't open %S, error %B%E",
  77.       fname, T)
  78.     CLOSE(2)
  79.     RETURN(T)
  80.   FI
  81.  
  82.   RETURN(0)
  83.  
  84. PROC StartR()
  85.   PUTCMD('Y) ;Resume operation
  86.   PUTCMD('A)
  87.     PUTR($20)
  88.     PUTR('?) ;No Translation
  89.   PUTCMD('C)
  90.     PUTR(PARITY)
  91.   RETURN
  92.  
  93. ;SubEQ(S, I, SS)
  94. ;
  95. ; Check if SS is = S(I..I+Len(SS)-1)
  96.  
  97. BYTE FUNC SUBEQ(STRING S BYTE I STRING SS)
  98.   INT J
  99.   IF S(0)-I+1 < SS(0) THEN RETURN(0) FI
  100.  
  101.   FOR J = 1 TO SS(0) DO
  102.     IF S(I+J-1) <> SS(J) THEN
  103.       RETURN(0)
  104.     FI
  105.   OD
  106.  
  107.   RETURN(1)
  108.  
  109.  
  110. ;Dial the number in string P
  111. ;return 0 if failure, 1 if OK
  112.  
  113. BYTE FUNC AutoDial(STRING P)
  114.   BYTE I, NN, C, DVSTAT1 = $2EB
  115.  
  116.   NN = P(0)     ;LENGTH OF STRING
  117.  
  118.   ;This modem ignores baud rate
  119.  
  120.   FOR C = 1 TO NN
  121.   DO
  122.     IF P(C) = '# THEN
  123.       DO
  124.         C ==+ 1
  125.       UNTIL
  126.         C > NN OR P(C) > 32
  127.       OD
  128.       EXIT
  129.     FI
  130.   OD
  131.   IF C > NN  THEN
  132.     PRINTE("No phone number in this entry!")
  133.     RETURN(0)
  134.   FI
  135.  
  136.   PRINTE("Dialing...press any key to abort")
  137.   ERRORNUM = 0
  138.   STARTR()
  139.  
  140.   IF dial = 0 THEN
  141.     PUTCMD('N)
  142.   ELSE
  143.     PUTCMD('O)
  144.   FI
  145.  
  146.   PUTCMD('K)
  147.   FOR I = C TO NN
  148.   DO
  149.     PutR(P(I))
  150.   OD
  151.   PutR($9B)
  152.  
  153.   ;Wait for carrier
  154.   WHILE CH = $FF DO
  155.     MDEVSTAT(2)
  156.     IF (DVSTAT1 & $80) <> 0 THEN
  157.       RETURN(1)
  158.     FI
  159.   OD
  160.   PRINTE("User abort")
  161.   PUTCMD('M) ;Go on-hook
  162.   STOPR()
  163.   RETURN(0)
  164.  
  165. ;Hang up the phone line
  166.  
  167. PROC HANGUP()
  168.   STARTR()
  169.   PUTCMD('M) ;Go on-hook
  170.   STOPR()
  171.   RETURN
  172.   
  173. ; --- END OF D:KCOM1030.ACT ---
  174.  
  175. ;<<<D:KCOM850.ACT>>>
  176. ;All the communications stuff:
  177. ;
  178. ; Opening, closing and
  179. ; DIALING
  180. ; (for the DC-Hayes Smartmodem)
  181. ; KERMIT protocol
  182. ; for Atari Home Computers
  183. ; version 1.1
  184. ; (C) 1983 John Howard Palevich
  185. ; to be distributed free of charge
  186. ;
  187. ;Started NOVEMBER 5, 1983
  188.  
  189. PROC MODEMINIT()
  190.   PRINTE("for the Atari 850 and the")
  191.   PRINTE("DC-Hayes Smartmodem")
  192.   RETURN
  193.  
  194. CARD FUNC NCIB()
  195.   CARD NC = 747,
  196.        INCNT = $400
  197.   BYTE I
  198.   MDEVSTAT(2)
  199.   I = MSTATUS(2)
  200.   IF I >= 128 THEN
  201.     PRINTF("R: device error: %D%E",
  202.       I)
  203.     RETURN(0)
  204.   FI
  205.   RETURN(NC)  
  206.  
  207. PROC PUTR(BYTE DATA)
  208.   PUTD(2, DATA)
  209.   RETURN
  210.  
  211. ;Temporarily Suspend Communications I/O
  212.  
  213. PROC StopR()
  214.   Close(2)
  215.   RETURN
  216.  
  217. PROC CloseR()
  218.   CLOSE(2)
  219.   RETURN
  220.  
  221. BYTE FUNC OpenR()
  222.   STRING fname = "##:"
  223.   BYTE T
  224.   Close(2)
  225.   fname(1) = 'R
  226.   fname(2) = dnum + '0
  227.   t = 13
  228.   Open(2, fname, t, 0)
  229.   T = MSTATUS(2)
  230.   IF T >= 128
  231.   THEN
  232.     PRINTF("Can't open %S, error %B%E",
  233.       fname, T)
  234.     CLOSE(2)
  235.     RETURN(T)
  236.   FI
  237.  
  238.   CIOV(2, 34, 0, 0, 192+48, 0)
  239.   CIOV(2, 38, 0, 0, 32+PARITY*5, 0)
  240.   CIOV(2, 36, 0, 0, 8+baud, 0)
  241.   CIOV(2, 40, 0, 0, 0, 0)
  242.   RETURN(0)
  243.  
  244. PROC StartR()
  245.     OpenR()
  246.     RETURN
  247.  
  248. ;SubEQ(S, I, SS)
  249. ;
  250. ; Check if SS is = S(I..I+Len(SS)-1)
  251.  
  252. BYTE FUNC SUBEQ(STRING S BYTE I STRING SS)
  253.   INT J
  254.   IF S(0)-I+1 < SS(0) THEN RETURN(0) FI
  255.  
  256.   FOR J = 1 TO SS(0) DO
  257.     IF S(I+J-1) <> SS(J) THEN
  258.       RETURN(0)
  259.     FI
  260.   OD
  261.  
  262.   RETURN(1)
  263.  
  264. ;GetMack() - wait for reply from SM
  265. PROC GetMack()
  266.   BYTE A, S
  267.   IF ERRORNUM >= 128 THEN RETURN
  268.   FI
  269.   S = 0
  270.   DO
  271.     IF CH <> $FF THEN
  272.       ERRORNUM = $FF
  273.       RETURN
  274.     FI
  275.     IF NCIB() > 0 THEN
  276.       A = GETD(2)
  277.       IF DEBUG = 1 THEN
  278.         PUT(27)
  279.         PUT(A)
  280.       FI
  281.       IF S = 0 THEN
  282.         IF A >= 32 THEN
  283.           S = 1
  284.         FI
  285.       ELSE
  286.         IF A = 10 THEN ;End of reply
  287.           RETURN
  288.         FI
  289.       FI
  290.     FI
  291.   OD
  292.   
  293. ;PutMatch(c) - put a character out
  294. ; to R:, wait for a matching character
  295. ; or user's abort
  296.  
  297. PROC PutMatch(BYTE c)
  298.   BYTE A
  299.   PUTD(2, C)
  300.   IF ERRORNUM >= 128 THEN RETURN
  301.   FI
  302.   DO
  303.     IF CH <> $FF THEN
  304.       ERRORNUM = $FF
  305.       RETURN
  306.     FI
  307.     IF NCIB() > 0 THEN
  308.       A = GETD(2)
  309.       IF DEBUG = 1 THEN
  310.         PUT(27)
  311.         PUT(A)
  312.       FI
  313.       IF A = C THEN
  314.         RETURN
  315.       FI
  316.     FI
  317.   OD
  318.  
  319. ;Dial the number in string P....
  320.  
  321. BYTE FUNC AUTODIAL(STRING P)
  322.   BYTE I, C, NN
  323.   
  324.   NN = P(0)     ;LENGTH OF STRING
  325.  
  326.   ;See if Baud Rate Specified
  327.   FOR C = 1 TO NN
  328.   DO
  329.     IF P(C) = '( THEN
  330.       IF SUBEQ(P,C,"(300)") = 1 THEN
  331.         BAUD = 0
  332.       ELSEIF SUBEQ(P,C,"(1200)") = 1
  333.       THEN
  334.         BAUD = 2
  335.       FI
  336.       EXIT
  337.     FI
  338.   OD
  339.  
  340.   FOR C = 1 TO NN
  341.   DO
  342.     IF P(C) = '# THEN
  343.       DO
  344.         C ==+ 1
  345.       UNTIL
  346.         C > NN OR P(C) > 32
  347.       OD
  348.       EXIT
  349.     FI
  350.   OD
  351.   IF C > NN  THEN
  352.     PRINTE("No phone number in this entry!")
  353.     RETURN(0)
  354.   FI
  355.  
  356.   PRINTE("Dialing...press any key to abort")
  357.   ERRORNUM = 0
  358.   STARTR()
  359.   PutMatch(13) ;Establish baud Rate
  360.   PutMatch('A)
  361.   PutMatch('T)
  362.   PutMatch(13)
  363.   GetMack() ;Swallow Reply
  364.   PutMatch('A)
  365.   PutMatch('T)
  366.   PutMatch(' )
  367.   PutMatch('D)
  368.   IF dial = 0 THEN
  369.     PutMatch('P)
  370.   ELSE
  371.     PutMatch('T)
  372.   FI
  373.   FOR I = C TO P(0)
  374.   DO
  375.     PutMatch(P(I))
  376.   OD
  377.   PutMatch(13)
  378.   DO
  379.     IF ERRORNUM >= 128
  380.       OR CH <> $FF THEN
  381.       PRINTE("User Aborted")
  382.       PUTD(2, 13) ;to get out of wait-for-carrier mode
  383.       I = RTCLOCK+10
  384.       WHILE RTCLOCK <> I DO OD ;Drain
  385.       STOPR()
  386.       RETURN(0)
  387.     FI
  388.     IF NCIB() > 0 THEN
  389.       C = GetD(2)
  390.       IF DEBUG = 1 THEN
  391.         PUT(27)
  392.         PUT(C)
  393.       FI
  394.       IF C = 'C OR C = '1 THEN ;Connected
  395.         STOPR()
  396.         RETURN(1)
  397.       ELSEIF C >= 32 THEN
  398.         PrintF("Unexpected result '%C'%E", C)
  399.         STOPR()
  400.         RETURN(0)
  401.       FI
  402.     FI
  403.   OD
  404.  
  405. ;CAUSE THE SMARTMODEM TO HANG UP
  406.  
  407. PROC HANGUP()
  408.   BYTE B
  409.   STARTR()
  410.   ;As per page 9-2 of the Smart-
  411.   ;modem manual.  Basicly, the
  412.   ;escape sequence has to be pre-
  413.   ;ceded by at least one character,
  414.   ;and we can't count on the user
  415.   ;having typed one, so we type one
  416.   ;ourselves.
  417.  
  418.   PUTR('+)
  419.   WAIT(100)
  420.   PUTR('+)
  421.   PUTR('+)
  422.   PUTR('+)
  423.   WAIT(200)
  424.   ;Flush buffer
  425.   WHILE NCIB() > 0 DO
  426.     B = GETD(2)
  427.     IF DEBUG = 1 THEN
  428.       PUT(27)
  429.       PUT(B)
  430.     FI
  431.   OD
  432.   ERRORNUM = 0
  433.   PutMatch(13) ;Establish baud Rate
  434.   PutMatch('A)
  435.   PutMatch('T)
  436.   PutMatch(13)
  437.   GetMack() ;Swallow Reply
  438.   PUTMATCH('A)
  439.   PUTMATCH('T)
  440.   PUTMATCH(32)
  441.   PUTMATCH('H)
  442.   PUTMATCH('0)
  443.   PUTMATCH(13)
  444.   GETMACK()
  445.   STOPR()
  446.   RETURN
  447.  
  448. ; --- END OF D:KCOM850.ACT ---
  449.  
  450. ;<<<D:KERMIT.ACT>>>
  451. ;<COMPILE THIS FILE>
  452. ; KERMIT protocol
  453. ; for Atari Home Computers
  454. ; version 1.2
  455. ; (C) 1984 John Howard Palevich
  456. ; to be distributed free of charge
  457. ;
  458. ;Started September 24, 1983
  459.  
  460. ;Start code above T: and/or R:
  461. ;by compiling while those devices
  462. ;are in RAM.  There ought to be a
  463. ;better way!
  464.  
  465. MODULE
  466.  
  467. DEFINE MAXPACK = "94"
  468.  
  469. BYTE ARRAY
  470.   RECPKT(MAXPACK),
  471.   PACKET(MAXPACK),
  472.   FILNAM,
  473.   SBUF(2050)
  474.  
  475. DEFINE
  476.   EOF = "-1",
  477.   SOH = "1",
  478.   CR = "13",
  479.  
  480.   MAXTRY = "5",
  481.   MYQUOTE = "'#",
  482.   TRUE = "1",
  483.   FALSE = "0"
  484.  
  485. BYTE
  486.   LMARGN = $52,;OS LEFT MARGIN
  487.   CH = 764,    ;OS CH VARIABLE
  488.   RTCLOCK = 20,;OS CLOCK IN JIFFYS
  489.   CRSINH = $2F0, ;OS CURSOR INHIBIT FLAG
  490.   BACKS,       ;CHAR TO SEND FOR BACK S
  491.   baud,        ;baud rate variable
  492.   dial,        ;nz for tone dialing
  493.   DISKN,       ;DEFAULT DISK
  494.   DNUM,        ;port num
  495.   localecho,   ;local echo flag
  496.   PARITY,      ;communication parity
  497.   ERRORNUM,    ;ERROR NUMBER
  498.   debug,       ;debugging flag
  499.  
  500.   STATE,
  501.   PADCHAR,
  502.   EOL,
  503.   QUOTE
  504.  
  505. INT
  506.   SIZE,
  507.   N,
  508.   RPSIZ,
  509.   SPSIZ,
  510.   PAD,
  511.   TIMINT,
  512.   NUMTRY,
  513.   OLDTRY,
  514.   FD,
  515.   REMFD,
  516.   IMAGE,
  517.   HOST
  518.  
  519. INCLUDE "D:KIO.ACT"
  520.  
  521. ; This is where KCOM#.ACT is
  522. ;included.  Include the KCOM file
  523. ;which matches the comunications
  524. ;device and/or modem you wish to use.
  525. ;
  526. ; For an 850 and a Hayes SmartModem,
  527. ;include KCOM850.ACT
  528. ;
  529. ; For the ATARI 1050,
  530. ;include KCOM1050.ACT
  531. ;
  532. ; For any other set of devices, write
  533. ;your own KCOM functions, and include
  534. ;that file here.
  535.  
  536. INCLUDE "D:KCOM850.ACT"
  537.  
  538. INCLUDE "D:KFUNC.ACT"
  539. INCLUDE "D:KPRO.ACT"
  540. INCLUDE "D:KTTY.ACT"
  541. INCLUDE "D:KMENU.ACT"
  542.  
  543. ; --- END OF D:KERMIT.ACT ---
  544.  
  545. ;<<<D:KFUNC.ACT>>>
  546. ; Utility functions for Kermit
  547. ; (C) 1983 John Howard Palevich
  548. ; to be distributed free of charge
  549. ;
  550. ;Started September 24, 1983
  551.  
  552. MODULE
  553.  
  554. CARD ARRAY bauds = [300 600 1200
  555.                     1800 2400 4800
  556.                     9600]
  557.  
  558. PROC SHOWBUF(STRING BUF, INT LEN)
  559.   INT I
  560.   FOR I = 0 TO LEN-1 DO
  561.     PUT(27)
  562.     PUT(BUF(I))
  563.   OD
  564.   RETURN
  565.  
  566. PROC MERROR(BYTE A,X,Y)
  567.   IF debug = 1 THEN
  568.     PRINTF("ERROR %B%E", y)
  569.     IF Y = 128 THEN
  570.       CLOSE(2)
  571.       CLOSE(3)
  572.       CLOSE(1)
  573.       BREAK()
  574.     FI
  575.   FI
  576.   ERRORNUM = Y
  577.   RETURN
  578.  
  579. CARD FUNC DecodeBaud(BYTE b)
  580.   STRING buf(6)
  581.   STRC(bauds(b), buf)
  582.   RETURN(buf)
  583.  
  584. CARD FUNC DecodeFlag(BYTE f)
  585.   IF f = 0 THEN
  586.     RETURN("off")
  587.   ELSE
  588.     RETURN("on")
  589.   FI
  590.  
  591. BYTE FUNC IsAlpha(BYTE c)
  592.   IF (c >= 'a AND c <= 'z) OR
  593.      (c >= 'A AND c <= 'Z)
  594.   THEN
  595.     RETURN(1)
  596.   ELSE
  597.     RETURN(0)
  598.   FI
  599.  
  600. BYTE FUNC ToUpper(BYTE c)
  601.   IF c >= 'a AND c <= 'z THEN
  602.     RETURN(c - 32)
  603.   ELSE
  604.     RETURN(c)
  605.   FI
  606.  
  607. ;SPack()
  608. ;
  609. ; Send a Packet
  610.  
  611. PROC SPack(BYTE TY
  612.            INT NUM, LEN
  613.            STRING DATA)
  614.   INT I, BUFP
  615.   BYTE CHKSUM
  616.   STRING BUFFER(100)
  617.  
  618.   IF DEBUG = 1 THEN
  619.     PRINTF("SPack('%C,%D,%D,",
  620.       TY, NUM, LEN)
  621.     PUT('")
  622.     SHOWBUF(DATA, LEN)
  623.     PRINTF("%C)%E", '")
  624.   ELSE
  625.     PUT('.)
  626.   FI
  627.  
  628.   FOR I = 1 TO PAD
  629.   DO
  630.     PUTD(2, PADCHAR)
  631.   OD
  632.  
  633.   BUFFER(0) = SOH
  634.   BUFFER(1) = 32 + LEN+3
  635.   BUFFER(2) = 32 + NUM
  636.   BUFFER(3) = TY
  637.  
  638.   CHKSUM = BUFFER(1)+BUFFER(2)
  639.     +BUFFER(3)
  640.  
  641.   FOR I = 0 TO LEN-1
  642.   DO
  643.     BUFFER(I+4) = DATA(I)
  644.     CHKSUM ==+ DATA(I)
  645.   OD
  646.  
  647.   CHKSUM = (CHKSUM + ((CHKSUM & 192)
  648.     RSH 6)) & 63
  649.   BUFFER(LEN+4) = 32 + CHKSUM
  650.   BUFFER(LEN+5) = EOL
  651.   CIOV(2, 11, BUFFER, LEN+6, -1, -1)
  652.   RETURN
  653.  
  654. ;GetRT
  655. ; Get a byte from R: with timeout
  656. ; and user-abort
  657.  
  658. BYTE FUNC GetRT(BYTE POINTER B)
  659.   CHAR FSC = 19, TIMER
  660.  
  661.   TIMER = FSC+3
  662.   WHILE NCIB() = 0 DO
  663.     IF FSC = TIMER THEN
  664.       IF DEBUG = 1 THEN ;say timeout
  665.         PRINTE("(Timeout)")
  666.       FI
  667.       RETURN(0)
  668.     ELSEIF CH <> $FF THEN ;User abort
  669.       RETURN(0)
  670.     FI
  671.   OD
  672.   B^ = GETD(2)
  673.   RETURN(1)
  674.  
  675. ; RPack()
  676. ;
  677. ; Read a Packet
  678.  
  679. INT FUNC RPack(INT POINTER LEN, NUM
  680.            STRING DATA)
  681.   INT I, DONE
  682.   CHAR CHKSUM, T, UT, TY
  683.  
  684.   IF DEBUG = 1 THEN
  685.     PRINT("RPack")
  686.   FI
  687.  
  688.   DO
  689.     IF GETRT(@T) = 0 THEN
  690.       RETURN(0)
  691.     FI
  692.     IF DEBUG = 1 AND T <> SOH THEN
  693.       PUT(27)
  694.       PUT(T)
  695.     FI
  696.   UNTIL
  697.     T = SOH
  698.   OD
  699.   DONE = FALSE
  700.   WHILE DONE = FALSE
  701.   DO
  702.     IF GETRT(@T) = 0 THEN
  703.       RETURN(0)
  704.     FI
  705.     IF IMAGE = FALSE
  706.     THEN
  707.       T ==& 127
  708.     FI
  709.     IF T <> SOH THEN   ;GOT LEN
  710.       CHKSUM = T
  711.       LEN^ = T-3-32
  712.  
  713.       IF GETRT(@T) = 0 THEN
  714.         RETURN(0)
  715.       FI
  716.       IF IMAGE = FALSE
  717.       THEN
  718.         T ==& 127
  719.       FI
  720.       IF T <> SOH THEN ;GOT NUM
  721.         CHKSUM ==+ T
  722.         NUM^ = T - 32
  723.  
  724.         IF GETRT(@T) = 0 THEN
  725.           RETURN(0)
  726.         FI
  727.         IF IMAGE = FALSE THEN T ==& 127 FI
  728.         IF T <> SOH THEN
  729.           CHKSUM ==+ T
  730.           TY = T
  731.  
  732.           FOR I = 0 TO LEN^-1 DO
  733.             IF GETRT(@T) = 0 THEN
  734.               RETURN(0)
  735.             FI
  736.             IF IMAGE = FALSE THEN T ==& 127 FI
  737.             IF T = SOH THEN EXIT FI
  738.             CHKSUM ==+ T
  739.             DATA(I) = T
  740.           OD
  741.  
  742.           IF T <> SOH THEN
  743.             IF GETRT(@T) = 0 THEN
  744.               RETURN(0)
  745.             FI
  746.             IF IMAGE <> TRUE THEN T ==& 127 FI
  747.             IF T <> SOH THEN
  748.               DONE = TRUE
  749.             FI
  750.           FI
  751.         FI
  752.       FI
  753.     FI
  754.   OD
  755.   CHKSUM = (CHKSUM + 
  756.     ((CHKSUM & 192) RSH 6)) & 63
  757.   UT = T - 32
  758.   IF CHKSUM <> UT THEN
  759.     IF DEBUG = 1 THEN
  760.       PRINTF("(Bad checksum: %D <> %D)%E",
  761.         CHKSUM, UT)
  762.     FI
  763.     RETURN(FALSE)
  764.   FI
  765.   IF DEBUG = 1 THEN ;give type
  766.     PRINTF("('%C%C,%D,%D,%C",
  767.       27, TY, NUM^, LEN^, '")
  768.     SHOWBUF(DATA, LEN^)
  769.     PRINTF("%C)%E", '")
  770.   FI
  771.   IF TY = 'E THEN
  772.     PRINT("Error: ")
  773.     SHOWBUF(DATA, LEN^)
  774.     PUTE()
  775.   FI
  776.   RETURN(TY)
  777.  
  778. ;BuFill
  779. ;
  780. ;Get a bufferful of data from the
  781. ;file that's being sent.  Only
  782. ;control-quoting is done;  8-bit &
  783. ;repeat count prefixes arn't handled
  784.  
  785. INT FUNC BuFill(STRING BUFFER)
  786.   INT I
  787.   BYTE T,T7
  788.   STOPR()
  789.   I = 0
  790.   DO
  791.     T = GETD(3)
  792.     IF MStatus(3) >= 128 THEN
  793.       IF DEBUG = 1 THEN
  794.         PRINTE("End-of-file")
  795.       FI
  796.       EXIT
  797.     FI
  798.     IF IMAGE = TRUE THEN
  799.       T7 = T & 127
  800.       IF T7 < 32 OR T7 = 127 OR
  801.         T7 = QUOTE
  802.       THEN
  803.         BUFFER(I) = QUOTE
  804.         I ==+ 1
  805.         IF T7 <> QUOTE THEN
  806.           T ==! 64
  807.         FI
  808.       FI
  809.     ELSE
  810.       IF T <> 155 THEN T ==& 127 FI
  811.       IF T < 32 OR T = 127
  812.         OR T = QUOTE OR T = 155
  813.       THEN
  814.         IF T = 155 THEN
  815.           BUFFER(I) = QUOTE
  816.           BUFFER(I+1) = 13 ! 64
  817.           I ==+ 2
  818.           T = 10
  819.         FI
  820.         BUFFER(I) = QUOTE
  821.         I ==+ 1
  822.         IF T <> QUOTE THEN T==! 64 FI
  823.       FI
  824.     FI
  825.     BUFFER(I) = T
  826.     I ==+ 1
  827.     IF I >= SPSIZ-8 THEN
  828.       STARTR()
  829.       RETURN(I)
  830.     FI
  831.   OD
  832.   STARTR()
  833.   IF I = 0
  834.   THEN
  835.     RETURN(EOF)
  836.   ELSE
  837.     RETURN(I)
  838.   FI
  839.  
  840. ;BufEmp
  841. ;
  842. ;Get data from an incomming packet
  843. ;into a file.
  844.  
  845. PROC BufEmp(STRING BUFFER
  846.                 INT LEN)
  847.  
  848.   INT I
  849.   BYTE T
  850.  
  851.   STOPR()
  852.   FOR I = 0 TO LEN-1
  853.   DO
  854.     T = BUFFER(I)
  855.     IF T = MYQUOTE
  856.     THEN
  857.       I ==+ 1
  858.       T = BUFFER(I)
  859.       IF (T & 127) <> MYQUOTE
  860.       THEN
  861.         T ==! 64
  862.       FI
  863.     FI
  864.     IF IMAGE = TRUE THEN
  865.       PUTD(3, T)
  866.     ELSEIF T = CR THEN
  867.       PUTD(3, 155)
  868.     ELSEIF T <> 10 THEN
  869.       PUTD(3, T)
  870.     FI
  871.   OD
  872.   STARTR()
  873.   RETURN
  874.  
  875. ;SPar()
  876. ;
  877. ;Fill the data array with my
  878. ;send-init parameters
  879.  
  880. PROC SPar(STRING DATA)
  881.   DATA(0) = 32 + MAXPACK
  882.   DATA(1) = 32 + 5
  883.   DATA(2) = 32 + 0
  884.   DATA(3) = 64 ! 0
  885.   DATA(4) = 32 + 13
  886.   DATA(5) = MYQUOTE
  887.   RETURN
  888.  
  889. ;RPar()
  890. ;
  891. ;Get the other host's send-init
  892. ;parameters
  893.  
  894. PROC RPAR(STRING DATA)
  895.   SPSIZ = DATA(0) - 32
  896.   TIMINT = DATA(1) - 32
  897.   PAD = DATA(2) - 32
  898.   PADCHAR = DATA(3) ! 64
  899.   EOL = DATA(4) - 32
  900.   QUOTE = DATA(5)
  901.   RETURN
  902.  
  903. ; --- END OF D:KFUNC.ACT ---
  904.  
  905. ;<<<D:KIO.ACT>>>
  906. ; I/O routines for kermit
  907. ; (C) 1983 John Howard Palevich
  908.  
  909. DEFINE STRING = "BYTE ARRAY"
  910.  
  911. STRING iocb
  912. CARD filenumber
  913.  
  914. STRING dname(20), fname(20)
  915.  
  916. ;WAIT T 60THS OF A SECOND
  917.  
  918. PROC WAIT(INT T)
  919.   BYTE I
  920.   WHILE T > 255
  921.   DO
  922.     I = RTCLOCK-1
  923.     WHILE I <> RTCLOCK DO OD
  924.     T ==- 255
  925.   OD
  926.   I = RTCLOCK + T
  927.   WHILE I <> RTCLOCK DO OD
  928.   RETURN
  929.  
  930. PROC STRCPY(STRING A, B)
  931.   CARD I
  932.   FOR I = 1 TO B(0) DO
  933.   A(I) = B(I)
  934.   OD
  935.   A(0) = B(0)
  936.   RETURN
  937.  
  938. BYTE FUNC MStatus(BYTE ch)
  939.   iocb = $340 + ch LSH 4
  940.   RETURN (iocb(3))
  941.  
  942. PROC CIO=$E456(BYTE a, x)
  943.  
  944. PROC CIOV(BYTE ch, cmd
  945.           CARD adr, len
  946.           INT ax1, ax2)
  947.  
  948.   iocb = $340 + ch LSH 4
  949.   iocb(2) = cmd
  950.   iocb(4) = adr 
  951.   iocb(5) = adr RSH 8
  952.   iocb(8) = len
  953.   iocb(9) = len RSH 8
  954.   IF ax1 >= 0 THEN
  955.     iocb(10) = ax1
  956.   FI
  957.   IF ax2 >= 0 THEN
  958.     iocb(11) = ax2
  959.   FI
  960.  
  961.   CIO(0, CH * 16)
  962.   RETURN
  963.  
  964. ;Do a Get Status Command
  965. BYTE FUNC MDevStat(BYTE ch
  966.                    STRING adr)
  967.   CIOV( ch, $0D,
  968.         adr + 1, adr(0), -1, -1)
  969.   RETURN(iocb(3))
  970.  
  971. ; -- file locking, unlocking, etc.
  972. ; -- directory hacking functions
  973.  
  974. ;Returns 0 if EOF, else the file name
  975. CARD FUNC GetNext(CHAR ch)
  976.   INT I, J
  977.   STRING DSPEC(20)
  978.   Close(ch)
  979.   Open(ch, dname, 6, 0)
  980.   IF mstatus(ch) >= 128
  981.   THEN
  982.     RETURN(0)
  983.   FI
  984.  
  985.   FOR i = 0 TO filenumber
  986.   DO
  987.     INPUTMD(ch, DSPEC, 20)
  988.     IF mstatus(ch) >= 128 THEN
  989.       Close(ch)
  990.       RETURN(0)
  991.     FI
  992.   OD
  993.   IF DSPEC(0) <> 17 THEN RETURN(0) FI
  994.   filenumber ==+ 1
  995.   Close(ch)
  996.   ;Convert dspec into file name
  997.   I = 1
  998.   DO
  999.     FNAME(I) = DNAME(I)
  1000.     I ==+ 1
  1001.   UNTIL
  1002.     DNAME(I-1) = ':
  1003.   OD
  1004.  
  1005.   J = 3
  1006.   DO
  1007.     FNAME(I) = DSPEC(J)
  1008.     I ==+ 1
  1009.     J ==+ 1
  1010.   UNTIL
  1011.     J > 10 OR DSPEC(J) = 32
  1012.   OD
  1013.   FNAME(I) = '.
  1014.   I ==+ 1
  1015.   J = 11
  1016.   WHILE
  1017.     J <= 13 AND DSPEC(J) <> 32
  1018.   DO
  1019.     FNAME(I) = DSPEC(J)
  1020.     I ==+ 1
  1021.     J ==+ 1
  1022.   OD
  1023.  
  1024.   FNAME(0) = I-1
  1025.   RETURN(fname)
  1026.  
  1027. ;Get the first name
  1028.  
  1029. CARD FUNC GetFirst(BYTE ch
  1030.                    STRING name)
  1031.  
  1032.   STRCPY(dname, NAME)
  1033.   filenumber = 0
  1034.   RETURN(GetNext(ch))
  1035.  
  1036. ;FIND CHAR C IN STRING A
  1037.  
  1038. BYTE FUNC FindC(STRING a
  1039.            BYTE c)
  1040.   CARD i,l
  1041.   l = a(0)
  1042.   FOR i = 1 TO l DO
  1043.     IF a(i) = c THEN
  1044.       EXIT
  1045.     FI
  1046.   OD
  1047.   RETURN(i)
  1048.  
  1049. ;Normalize a file name string to Dn:<0..8>.<0..3>
  1050. ;where n is the value of diskn
  1051. ;name should be at least 3+8+1+3+2=17 bytes long
  1052. ;returns 0 if not a valid name
  1053.  
  1054. BYTE FUNC Normalize(STRING name)
  1055.   CARD i, len
  1056.   BYTE C
  1057.  
  1058.  
  1059.   len = name(0)
  1060.   IF len = 0 THEN
  1061.     RETURN(0)
  1062.   FI
  1063.  
  1064. ;first, check if <letter>(<number>):
  1065.  
  1066.   i = FindC(name,':)
  1067.   IF i > len THEN
  1068.     FOR i = 1 TO len DO
  1069.       name(len-i+4) = name(len-i+1)
  1070.     OD
  1071.     name(1) = 'D
  1072.     name(2) = '0 + DISKN
  1073.     name(3) = ':
  1074.     len ==+ 3
  1075.   FI
  1076.  
  1077. ;fixup length
  1078.   name(0) = len
  1079.  
  1080. ;and convert to upper case
  1081.  
  1082.   FOR i = 1 TO len DO
  1083.     c = name(i)
  1084.     IF c >= 'a AND c <= 'z THEN
  1085.       name(i) = c - 32
  1086.     FI
  1087.   OD
  1088.  
  1089.   RETURN(1)
  1090.  
  1091. BYTE FUNC INSET(BYTE C STRING S)
  1092.   CARD I
  1093.   FOR I = 1 TO S(0)
  1094.   DO
  1095.     IF C = S(I) THEN
  1096.       RETURN(I)
  1097.     FI
  1098.   OD
  1099.   RETURN(0)
  1100.  
  1101. ; --- END OF D:KIO.ACT
  1102.  
  1103. ;<<<D:KMENU.ACT>>>
  1104. ; Menu functions of Kermit program
  1105.  
  1106. MODULE
  1107.   DEFINE NUMWID = "38"
  1108.  
  1109.   STRING PNFILE = "D:KERMIT.PNS"
  1110.   STRING PARAMFILE = "D:KERMIT.OPT"
  1111.  
  1112. ;Restore Phone Number Buffer
  1113.  
  1114. PROC RESTNUMS()
  1115.   BYTE I, J
  1116.  
  1117.   Close(3)
  1118.   ERRORNUM = 0
  1119.   OPEN(3, PNFILE, 4, 0)
  1120.   IF ERRORNUM < 128 THEN
  1121.     FOR I = 0 TO 19 DO
  1122.       ERRORNUM = 0
  1123.       InputMD(3,SBUF+I*NUMWID, 37)
  1124.       IF ERRORNUM >= 128 THEN
  1125.         EXIT
  1126.       FI
  1127.     OD
  1128.   ELSE
  1129.     I = 0 ;Couldn't find file
  1130.   FI
  1131.   CLOSE(3)
  1132.  
  1133.   FOR J = I TO 19
  1134.   DO
  1135.     SBUF(NUMWID*J) = 0
  1136.   OD
  1137.   RETURN
  1138.  
  1139. ;Display the editor screen
  1140.  
  1141. PROC DispES()
  1142.   BYTE I
  1143.  
  1144.   ;Display Screen
  1145.   CRSINH = 1
  1146.   PUT(125)
  1147.  
  1148.   PRINTE("Computer Name (baud rate) # 555-1212")
  1149.   FOR I = 0 TO 19
  1150.   DO
  1151.     Put(32)
  1152.     PRINTE(SBUF+NUMWID*I)
  1153.   OD
  1154.  
  1155.   PrintE("Use arrows, then RETURN to dial,")
  1156.   PrintE("or ESC to quit. ^S Saves")
  1157.   PRINT("SPACE modifies, ^R Restores")
  1158.   Position(LMARGN, 0)
  1159.   Put($1F)
  1160.   CRSINH = 0
  1161.   Put($1E)
  1162.   RETURN
  1163.  
  1164. ;Auto-Dial a number, return 1 if
  1165. ;successful, 0 if failure
  1166. ;
  1167. ; Also has provisions for editing
  1168. ; phone numbers.
  1169.  
  1170. BYTE FUNC EditDial()
  1171.   BYTE I, NN, C, CY
  1172.   BYTE POINTER P
  1173.  
  1174.   RESTNUMS()
  1175.   DISPES()
  1176.   CY = 0
  1177.  
  1178.   ;Edit/Select Loop
  1179.   
  1180.   DO
  1181.     CRSINH = 1
  1182.     POSITION(LMARGN, CY+1)
  1183.     PUT(27)
  1184.     PUT($1F)
  1185.     C = GetD(1)
  1186.     IF C = 32 THEN
  1187.     ;User wants to change this line
  1188.       POSITION(LMARGN,CY+1)
  1189.       CRSINH = 0
  1190.       PUT('?)
  1191.       InputMD(0,SBUF+CY*NUMWID, 37)
  1192.       DISPES()
  1193.  
  1194.     ELSEIF C = 27 THEN
  1195.       Position(LMARGN, 23)
  1196.       CRSINH = 0
  1197.       PUT($9C)
  1198.       PrintE("Not Dialing")
  1199.       RETURN(0)
  1200.  
  1201.     ELSEIF (C = $1C OR C = '-)
  1202.       AND CY > 0 THEN
  1203.       PUT($7E) ;Erase the arrow
  1204.       CY ==- 1
  1205.  
  1206.     ELSEIF (C = $1D OR C = '=)
  1207.       AND CY < 19 THEN
  1208.       PUT($7E) ;Erase the arrow
  1209.       CY ==+ 1
  1210.  
  1211.     ELSEIF C = 'S-'@ THEN ;^S
  1212.       OPEN(3, PNFILE, 8, 0)
  1213.       FOR I = 0 TO 19 DO
  1214.         P = SBUF+I*NUMWID
  1215.         IF P(0) > 0 THEN
  1216.           PRINTDE(3, P)
  1217.         FI
  1218.       OD
  1219.       CLOSE(3)
  1220.       RESTNUMS()
  1221.       DISPES() ;Just to inform user
  1222.       CY = 0
  1223.  
  1224.     ELSEIF C = 'R-'@ THEN ;^R
  1225.       RESTNUMS()
  1226.       DISPES()
  1227.       CY = 0
  1228.  
  1229.     ELSEIF C = $9B THEN ;RETURN
  1230.       EXIT
  1231.     FI
  1232.   OD
  1233.  
  1234.   ;Dial the chosen number
  1235.  
  1236.   CRSINH = 0
  1237.   PUT(125)
  1238.   P = SBUF+CY*NUMWID
  1239.   PrintE(P)
  1240.   C = AutoDial(P)
  1241.   RETURN(C)
  1242.  
  1243. ;Execute a DOS-type command
  1244.  
  1245. PROC DODOS(BYTE CMD
  1246.            STRING FSPEC)
  1247.   STRING FMSCOM = [0 $21 $23 $24 $FE]
  1248.   STRING FILNAM(21)
  1249.   BYTE I, CNF
  1250.  
  1251.   IF FSPEC(0) = 0 AND CMD <> 'A THEN
  1252.     RETURN
  1253.   FI
  1254.  
  1255.   IF CMD = 'A THEN     ;DIRECTORY
  1256.     IF FSPEC(0) = 0 THEN
  1257.       STRCPY(FSPEC, "D#:*.*")
  1258.       FSPEC(2) = '0 + DISKN
  1259.     FI
  1260.  
  1261.     NORMALIZE(FSPEC)
  1262.     CLOSE(6)
  1263.     ERRORNUM = 0
  1264.     OPEN(6, FSPEC, 6, 0)
  1265.     DO
  1266.       INPUTMD(6, FILNAM, 20)
  1267.       IF ERRORNUM >= 128 THEN EXIT FI
  1268.       PRINTE(FILNAM)
  1269.       IF FILNAM(1) >= '0 AND
  1270.          FILNAM(1) <= '9
  1271.       THEN EXIT FI
  1272.     OD
  1273.     CLOSE(6)
  1274.  
  1275.   ELSE         ;ALL OTHER COMMANDS
  1276.     NORMALIZE(FSPEC)
  1277.     I = INSET(CMD, "DFGI")
  1278.     IF I = 0 THEN RETURN FI
  1279.     IF CMD = 'I
  1280.     THEN
  1281.       PRINTF("Type 'Y' to format %S%E",
  1282.         FSPEC)
  1283.       CNF = GetD(1)
  1284.       IF TOUPPER(CNF) <> 'Y
  1285.       THEN
  1286.         PRINTF("Aborted%E")
  1287.         RETURN
  1288.       ELSE
  1289.         PRINT("Formatting. . .")
  1290.       FI
  1291.     FI
  1292.     ERRORNUM = 0
  1293.     XIO(6, 0, FMSCOM(I), 0, 0, FSPEC)
  1294.     IF ERRORNUM >= 128
  1295.     THEN
  1296.       PRINTF("Disk I/O error %B%E",
  1297.         ERRORNUM)
  1298.     FI
  1299.   FI
  1300.   RETURN
  1301.     
  1302. PROC MICRODOS()
  1303.   BYTE cmd
  1304.   STRING fspec(21)
  1305.   PUT(125)
  1306.   DO
  1307.     PRINTE("Micro-DOS:")
  1308.     PRINTE(" A - Disk Directory")
  1309.     PRINTE(" D - Delete File")
  1310.     PRINTE(" F - Lock File")
  1311.     PRINTE(" G - Unlock File")
  1312.     PRINTE(" I - Format Diskette")
  1313.     PRINTE(" Q - Quit (back to main menu)")
  1314.     PRINTF("%ECommand -> ")
  1315.     DO
  1316.       cmd = GetD(1)
  1317.       cmd = ToUpper(cmd)
  1318.     UNTIL
  1319.       INSET(CMD, "ADFGIQ") > 0
  1320.     OD
  1321.  
  1322.     PUT(CMD)
  1323.     IF cmd = 'Q
  1324.     THEN
  1325.       PUTE()
  1326.       RETURN
  1327.     FI
  1328.     PRINTF("%EFile spec -> ")
  1329.     InputMD(0, fspec, 20)
  1330.     DoDos(cmd, fspec)
  1331.   OD
  1332.  
  1333. ; SAVE PARAMETERS
  1334.  
  1335. PROC SaveParams()
  1336.   ERRORNUM = 0
  1337.   OPEN(3, PARAMFILE, 8, 0)
  1338.   IF ERRORNUM < 128
  1339.   THEN         ;Can write
  1340.     PUTD(3, BACKS)
  1341.     PUTD(3, BAUD)
  1342.     PUTD(3, DISKN)
  1343.     PUTD(3, DEBUG)
  1344.     PUTD(3, IMAGE)
  1345.     PUTD(3, LOCALECHO)
  1346.     PUTD(3, LMARGN)
  1347.     PUTD(3, PARITY)
  1348.     PUTD(3, DNUM)
  1349.     PUTD(3, dial)
  1350.   FI
  1351.   CLOSE(3)
  1352.   RETURN
  1353.  
  1354.  
  1355. ;RESTORE PARAMETERS
  1356.  
  1357. PROC RestoreParams()
  1358.   CARD TEMP
  1359.   CLOSE(3)
  1360.   ERRORNUM = 0
  1361.   OPEN(3, PARAMFILE, 4, 0)
  1362.   IF ERRORNUM >= 128
  1363.   THEN         ;Defaults
  1364.     PRINTF("Couldn't open %S; error %D%E",
  1365.       PARAMFILE, ERRORNUM)
  1366.     BACKS = 127          ;RUB OUT
  1367.     baud = 0             ;300 baud
  1368.     DISKN = 1            ;D1:
  1369.     debug = 0            ;debug off
  1370.     IMAGE = 0            ;TEXT
  1371.     localecho = 0        ;full
  1372.     LMARGN = 2           ;2 CHARS
  1373.     PARITY = 0           ;NO PARITY
  1374.     DNUM = 1             ;PORT 1
  1375.     dial = 0             ;Pulse
  1376.   ELSE
  1377.     BACKS = GETD(3)
  1378.     BAUD = GETD(3)
  1379.     DISKN = GETD(3)
  1380.     DEBUG = GETD(3)
  1381.     IMAGE = GETD(3)
  1382.     LOCALECHO = GETD(3)
  1383.     LMARGN = GETD(3)
  1384.     PARITY = GETD(3)
  1385.     DNUM = GETD(3)
  1386.     DIAL = GETD(3)
  1387.   FI
  1388.   CLOSE(3)
  1389.   RETURN
  1390.  
  1391. ;SET PARAMETERS
  1392.  
  1393. PROC Params()
  1394.   BYTE cmd
  1395.   STRING ts
  1396.  
  1397.   DO
  1398.     Put(125)
  1399.     PRINTE("Parameters are:")
  1400.  
  1401.     IF BACKS = 8 THEN
  1402.       TS = "control-H"
  1403.     ELSE TS = "rub out"
  1404.     FI
  1405.     PRINTF(" A - Back S sends (%S)%E",
  1406.       ts)
  1407.   
  1408.     ts = DecodeBaud(baud)
  1409.     PRINTF(" B - Baud rate (%S)%E",
  1410.       TS)
  1411.  
  1412.     IF IMAGE = 0 THEN
  1413.       ts = "text"
  1414.     ElSE
  1415.       ts = "binary"
  1416.     FI
  1417.  
  1418.     PRINTF(" D - Default disk drive (D%D:)%E",
  1419.       diskn)
  1420.  
  1421.     PRINTF(" F - File type (%S)%E",
  1422.       ts)
  1423.  
  1424.     PRINTF(" I - I/O Port (%D)%E",
  1425.       DNUM)
  1426.  
  1427.     IF dial = 0 THEN
  1428.       ts = "pulse"
  1429.     ELSE
  1430.       ts = "tone"
  1431.     FI
  1432.     PRINTF(" T - Dialing method (%S)%E",
  1433.       ts)
  1434.  
  1435.     ts = DecodeFlag(localecho)
  1436.     PRINTF(" L - Local-Echo (%S)%E",
  1437.       ts)
  1438.  
  1439.     PRINTF(" M - Margin (%D)%E", LMARGN)
  1440.  
  1441.  
  1442.     IF PARITY = 0 THEN
  1443.       TS = "none"
  1444.     ELSEIF PARITY = 1 THEN
  1445.       TS = "odd"
  1446.     ELSEIF PARITY = 2 THEN
  1447.       TS = "even"
  1448.     ELSEIF PARITY = 3 THEN
  1449.       TS = "on"
  1450.     FI
  1451.     PRINTF(" P - Parity (%S)%E", ts)
  1452.  
  1453.     PRINTE("^S - Save parameters")
  1454.     PRINTE("^R - Restore paramters")
  1455.      
  1456.     ts = DecodeFlag(debug)
  1457.     PRINTF(" * - Debug Mode (%S)%E",
  1458.       ts)
  1459.  
  1460.     PRINTF(" Q - Quit (back to Commands)%E")
  1461.  
  1462.     PRINTF("Parameter to change -> ")
  1463.     cmd = GetD(1)
  1464.     cmd = ToUpper(cmd)
  1465.     IF IsAlpha(cmd) <> 0 THEN
  1466.       Put(cmd)
  1467.     FI
  1468.  
  1469.     IF CMD = 'A THEN     ;BACK S
  1470.       IF BACKS = 8 THEN
  1471.         BACKS = 127
  1472.       ELSE
  1473.         BACKS = 8
  1474.       FI
  1475.  
  1476.     ELSEIF cmd = 'B THEN ;Baud-rate
  1477.       baud ==+ 1
  1478.       IF baud > 6 THEN baud = 0 FI
  1479.  
  1480.     ELSEIF cmd = 'D THEN ;Disk number
  1481.       diskn ==+ 1
  1482.       IF diskn > 4 THEN diskn = 1 FI
  1483.  
  1484.     ELSEIF cmd = '* THEN ;Debug
  1485.       debug = 1-debug
  1486.  
  1487.     ELSEIF cmd = 'Q THEN ;Quit
  1488.       PRINTF("uit%E")
  1489.       RETURN
  1490.  
  1491.     ELSEIF cmd = 'F THEN ;File type
  1492.       IMAGE = 1-IMAGE
  1493.  
  1494.     ELSEIF cmd = 'L THEN ;local-echo
  1495.       localecho ==+ 1
  1496.       IF localecho > 1 THEN
  1497.         LOCALECHO = 0
  1498.       FI
  1499.  
  1500.     ELSEIF cmd = 'T THEN ;dialing
  1501.       DIAL ==+ 1
  1502.       IF DIAL > 1 THEN
  1503.         DIAL = 0
  1504.       FI
  1505.  
  1506.     ELSEIF CMD = 'M THEN ;Margin
  1507.       LMARGN ==+ 1
  1508.       IF LMARGN > 2 THEN
  1509.         LMARGN = 0
  1510.       FI
  1511.  
  1512.     ELSEIF CMD = 'P THEN ;PARITY
  1513.       PARITY ==+ 1
  1514.       IF PARITY > 3 THEN
  1515.         PARITY = 0
  1516.       FI
  1517.  
  1518.     ELSEIF cmd = 'I THEN ;Port #
  1519.       dnum ==+ 1
  1520.       IF dnum > 4 THEN dnum = 1 FI
  1521.  
  1522.     ELSEIF cmd = 'S-'@ THEN ;Save Parameters
  1523.       PRINTE("Saving")
  1524.       SAVEPARAMS()
  1525.  
  1526.     ELSEIF cmd = 'R-'@ THEN ;Restore parameters
  1527.       PRINTE("Restoring")
  1528.       RESTOREPARAMS()
  1529.  
  1530.     ELSE
  1531.       PUT(253)
  1532.     FI
  1533.   OD
  1534.  
  1535. PROC Main()
  1536.   BYTE cmd, FLAG, I, BANK = $D500
  1537.  
  1538.   BANK = 0
  1539.  
  1540.   ;SETUP MY ERROR ROUTINE
  1541.   ERROR = MERROR
  1542.  
  1543.   EOL = CR
  1544.   QUOTE = MYQUOTE
  1545.   PAD = 0
  1546.   PADCHAR = 0
  1547.   HOST = FALSE
  1548.  
  1549.   FOR I = 1 TO 7 DO
  1550.     CLOSE(I)
  1551.   OD
  1552.  
  1553.   PRINTE("Kermit for the Atari Home Computer")
  1554.   PRINTE("v1.2 (c) 1984 John Howard Palevich")
  1555.   MODEMINIT()
  1556.   PRINTE("- Feel free to copy this program -")
  1557.  
  1558.   RestoreParams()
  1559.   Open(1, "K:", 4, 0)
  1560.   IF OPENR() <> 0 THEN
  1561.     PRINTE("PRESS ANY KEY TO EXIT")
  1562.     CH = $FF
  1563.     WHILE CH = $FF DO OD
  1564.     CH = $FF
  1565.   ELSE
  1566.     STOPR()
  1567.  
  1568.     DO
  1569.       PRINTF("%E%ECommands are:%E")
  1570.       PRINTE(" A - Auto-dial (then connect)")
  1571.       PRINTE(" C - Connect (to remote computer)")
  1572.       PRINTE(" D - Micro-DOS")
  1573.       PRINTE(" F - Finish (remote server mode)")
  1574.       PRINTE(" H - Hang up (the phone)")
  1575.       PRINTE(" P - Parameters (inspect and change)")
  1576.       PRINTE(" R - Receive (a file)")
  1577.       PRINTE(" S - Send (a file)")
  1578.       PRINTF(" Q - Quit (back to DOS)%E%E")
  1579.       PRINTF("Command -> ")
  1580.       DO
  1581.         cmd = GetD(1)
  1582.         cmd = ToUpper(cmd)
  1583.       UNTIL INSET(CMD, "ACDFHPRSQ") <> 0
  1584.       OD
  1585.       Put(cmd)
  1586.  
  1587.       IF CMD = 'A THEN
  1588.         ;Auto-dial
  1589.         PRINTE("uto-dial")
  1590.         IF EditDial() = 1 THEN
  1591.           TTYMODE()
  1592.         FI
  1593.       
  1594.       ELSEIF cmd = 'C THEN ;connect
  1595.         PRINTE("onnect")
  1596.         TTYMODE()
  1597.  
  1598.       ELSEIF cmd = 'F THEN ;Finish
  1599.         PRINTE("inish")
  1600.         Finish()
  1601.  
  1602.       ELSEIF cmd = 'H THEN
  1603.         ;Hang up the phone
  1604.         PRINTE("ang up")
  1605.         HangUp()
  1606.  
  1607.       ELSEIF cmd = 'D THEN ;MICRO-DOS
  1608.         PRINTE("os")
  1609.         MICRODOS()
  1610.  
  1611.       ELSEIF cmd = 'Q THEN ;Quit
  1612.         PRINTE("uit")
  1613.         EXIT
  1614.  
  1615.       ELSEIF cmd = 'P THEN ;Parameters
  1616.         PRINTE("arameters")
  1617.         Params()
  1618.  
  1619.       ELSEIF cmd = 'S THEN ;Send
  1620.         PRINTE("end")
  1621.         SENDSW()
  1622.  
  1623.       ELSEIF cmd = 'R THEN ;Recieve
  1624.         PRINTE("ecieve")
  1625.         RECSW()
  1626.       FI
  1627.     OD
  1628.  
  1629.     CLOSER()
  1630.   FI
  1631.   CLOSE(1)
  1632.   RETURN
  1633.  
  1634. ;--- END OF D:KMENU.ACT ---
  1635.  
  1636. ;<<<D:KPRO.ACT>>>
  1637. ; KERMIT protocol section
  1638.  
  1639. ; RInit()
  1640. ;
  1641. ; Receive Initialization
  1642.  
  1643. BYTE FUNC RINIT(STRING FSPEC)
  1644.   INT LEN, NUM, T
  1645.   IF DEBUG = 1 THEN
  1646.     PRINTE("RInit")
  1647.   FI
  1648.  
  1649.   NUMTRY ==+ 1
  1650.   IF NUMTRY > MAXTRY THEN
  1651.     RETURN('A)
  1652.   FI
  1653.  
  1654.   IF FSPEC(0) > 0 THEN
  1655.     FOR T = 1 TO FSPEC(0)
  1656.     DO
  1657.       PACKET(T-1) = FSPEC(T)
  1658.     OD
  1659.     SPACK('R, 0, T-1, PACKET)
  1660.   FI
  1661.  
  1662.   T = RPACK(@LEN, @NUM, PACKET)
  1663.   IF T = 'S THEN
  1664.     RPAR(PACKET)
  1665.     SPAR(PACKET)
  1666.     SPACK('Y, N, 6, PACKET)
  1667.     OLDTRY = NUMTRY
  1668.     NUMTRY = 0
  1669.     N = (N + 1) MOD 64
  1670.     RETURN('F)
  1671.  
  1672.   ELSEIF T = FALSE THEN RETURN(STATE)
  1673.   ELSE RETURN('A)
  1674.   FI
  1675.  
  1676. ; RFile()
  1677. ;
  1678. ; Receive File Header
  1679.  
  1680. BYTE FUNC RFile()
  1681.   INT LEN, NUM, T
  1682.   BYTE W
  1683.   IF DEBUG = 1 THEN
  1684.     PRINTF("RFile%E")
  1685.   FI
  1686.  
  1687.   NUMTRY ==+ 1
  1688.   IF NUMTRY > MAXTRY THEN
  1689.     RETURN('A)
  1690.   FI
  1691.  
  1692.   T = RPACK(@LEN, @NUM, PACKET+1)
  1693.   PACKET(0) = LEN
  1694.   IF T = 'S THEN
  1695.     OLDTRY ==+ 1
  1696.     IF OLDTRY > MAXTRY THEN RETURN('A) FI
  1697.     IF (N = 0 AND NUM = 63)
  1698.       OR (N <> 0 AND NUM = N-1)
  1699.     THEN
  1700.       SPACK('Y, NUM, 0, 0)
  1701.       NUMTRY = 0
  1702.       RETURN(STATE)
  1703.     ELSE
  1704.       RETURN('A)
  1705.     FI
  1706.  
  1707.   ELSEIF T = 'F THEN
  1708.     IF NUM <> N THEN RETURN('A) FI
  1709.     STOPR()
  1710.     NORMALIZE(PACKET)
  1711.     ERRORNUM = 0
  1712.     OPEN(3, PACKET, 8, 0)
  1713.     STARTR()
  1714.     IF ERRORNUM >= 128
  1715.     THEN
  1716.       PRINTF("Couldn't create %S; error %D%E",
  1717.         PACKET, ERRORNUM)
  1718.       RETURN('A)
  1719.     FI
  1720.     PRINTF("Receiving %S%E",
  1721.       PACKET)
  1722.     SPACK('Y, N, 0, 0)
  1723.     OLDTRY = NUMTRY
  1724.     NUMTRY = 0
  1725.     N = (N+1) MOD 64
  1726.     RETURN('D)
  1727.  
  1728.   ELSEIF T = 'B THEN
  1729.     IF NUM <> N THEN RETURN('A) FI
  1730.     SPACK('Y, N, 0, 0)
  1731.     ;WAIT 1 SECOND FOR ACK TO DRAIN
  1732.     W = RTCLOCK+60
  1733.     WHILE W <> RTCLOCK DO OD
  1734.     RETURN('C)
  1735.  
  1736.   ELSEIF T = FALSE THEN RETURN(STATE)
  1737.   ELSE RETURN('A)
  1738.   FI
  1739.  
  1740. ; RData()
  1741. ;
  1742. ; Receive Data
  1743.  
  1744. BYTE FUNC RData()
  1745.   INT NUM, LEN, T
  1746.   IF DEBUG = 1 THEN
  1747.     PRINTF("RData%E")
  1748.   FI
  1749.  
  1750.   NUMTRY ==+ 1
  1751.   IF NUMTRY > MAXTRY THEN
  1752.     RETURN('A)
  1753.   FI
  1754.  
  1755.   T = RPACK(@LEN, @NUM, PACKET)
  1756.   IF T = 'D THEN
  1757.     IF NUM <> N
  1758.     THEN
  1759.       OLDTRY ==+ 1
  1760.       IF OLDTRY > MAXTRY THEN RETURN('A) FI
  1761.       IF (N = 0 AND NUM = 63)
  1762.         OR (N <> 0 AND NUM = N-1)
  1763.       THEN
  1764.         SPACK('Y, NUM, 0, 0)
  1765.         NUMTRY = 0
  1766.         RETURN(STATE)
  1767.       ELSE
  1768.         RETURN('A)
  1769.       FI
  1770.     FI
  1771.  
  1772.     BUFEMP(PACKET, LEN)
  1773.     SPACK('Y, N, 0, 0)
  1774.     OLDTRY = NUMTRY
  1775.     NUMTRY = 0
  1776.     N = (N+1) MOD 64
  1777.     RETURN('D)
  1778.  
  1779.   ELSEIF T = 'F THEN
  1780.     OLDTRY ==+ 1
  1781.     IF OLDTRY > MAXTRY THEN
  1782.       RETURN('A)
  1783.     FI
  1784.     IF (N = 0 AND NUM = 63)
  1785.       OR (N <> 0 AND NUM = N-1)
  1786.     THEN
  1787.       SPACK('Y, NUM, 0, 0)
  1788.       NUMTRY = 0
  1789.       RETURN(STATE)
  1790.     ELSE
  1791.       RETURN('A)
  1792.     FI
  1793.  
  1794.   ELSEIF T = 'Z THEN
  1795.     IF NUM <> N THEN RETURN('A) FI
  1796.     IF DEBUG = 1 THEN
  1797.       PRINTE("End-of-File")
  1798.     FI
  1799.     STOPR()
  1800.     CLOSE(3)
  1801.     STARTR()
  1802.     SPACK('Y, N, 0, 0)
  1803.     N = (N+1) MOD 64
  1804.     RETURN('F)
  1805.  
  1806.   ELSEIF T = FALSE THEN RETURN(STATE)
  1807.   ELSE RETURN('A)
  1808.   FI    
  1809.  
  1810. ; RecSw()
  1811. ;
  1812. ; This is the state table switcher
  1813. ; for receiving files
  1814.  
  1815. PROC RECSW()
  1816.   STRING FSPEC(20)
  1817.   INT NUM, LEN, T
  1818.  
  1819.   STARTR()
  1820.   PUT(125)
  1821.   PRINTE("Type the file to receive, or just")
  1822.   PRINTE("RETURN if the other computer is not")
  1823.   PRINTE("in Server mode.")
  1824.   PUTE()
  1825.   PRINT("File Spec -> ")
  1826.   INPUTMD(0, FSPEC, 19)
  1827.  
  1828.   PRINTE("Receiving File(s)")
  1829.   PRINTE("type any key to abort")
  1830.  
  1831.   STATE = 'R
  1832.   N = 0
  1833.   NUMTRY = 0
  1834.   DO
  1835.     IF CH <> 255 THEN
  1836.       PRINTE("User Aborting")
  1837.       CH = 255
  1838.       EXIT
  1839.     FI
  1840.     IF STATE = 'D THEN STATE = RDATA()
  1841.     ELSEIF STATE = 'F THEN STATE = RFILE()
  1842.     ELSEIF STATE = 'R THEN STATE = RINIT(FSPEC)
  1843.     ELSEIF STATE = 'A THEN
  1844.       PRINTE("Aborting")
  1845.       EXIT
  1846.     ELSE
  1847.       EXIT
  1848.     FI
  1849.   OD
  1850.   STOPR()
  1851.   Close(3)
  1852.   RETURN
  1853.  
  1854. ; SInit
  1855. ;
  1856. ; Send Initiate:
  1857. ;  Send my parameters, get other
  1858. ;  side's back
  1859.  
  1860. BYTE FUNC SINIT()
  1861.   INT NUM, LEN
  1862.   BYTE T
  1863.  
  1864.   IF DEBUG <> 0 THEN
  1865.     PRINTF("SInit%E")
  1866.   FI
  1867.  
  1868.   NUMTRY ==+ 1
  1869.   IF NUMTRY > MAXTRY THEN
  1870.     RETURN('A)
  1871.   FI
  1872.   SPAR(PACKET)
  1873.   IF DEBUG <> 0 THEN
  1874.     PRINTF("n = %D%E", N)
  1875.   FI
  1876.   ;Clear out any junk in the input
  1877.   ;buffer
  1878.   WHILE NCIB() > 0 DO GETD(2) OD
  1879.  
  1880.   SPACK('S, N, 6, PACKET)
  1881.   T = RPACK(@LEN, @NUM, RECPKT)
  1882.   IF     T = 'N THEN RETURN(STATE)
  1883.   ELSEIF T = 'Y THEN
  1884.     IF N <> NUM THEN
  1885.       RETURN(STATE)
  1886.     FI
  1887.     RPAR(RECPKT)
  1888.     IF EOL = 0 THEN
  1889.       EOL = 13
  1890.     FI
  1891.     IF QUOTE = 0 THEN
  1892.       QUOTE = '#
  1893.     FI
  1894.     NUMTRY = 0
  1895.     N = (N + 1) MOD 64
  1896.     IF FILNAM = 0 THEN
  1897.       RETURN('A)
  1898.     FI
  1899.     ;Open a file
  1900.     STOPR()
  1901.     ERRORNUM = 0
  1902.     Close(3)
  1903.     OPEN(3, FILNAM, 4, 0)
  1904.     STARTR()
  1905.     IF ERRORNUM >= 128 THEN
  1906.       PRINTF("Error %D; couldn't read %S",
  1907.         ERRORNUM, FILNAM)
  1908.       RETURN('A)
  1909.     FI
  1910.     PRINTF("Sending %S%E", FILNAM)
  1911.     RETURN('F)
  1912.  
  1913.   ELSEIF T = FALSE THEN RETURN(STATE)
  1914.   ELSE RETURN('A)
  1915.   FI
  1916.   
  1917. ; SFile
  1918. ;
  1919. ; Send File Header
  1920.  
  1921. BYTE FUNC SFILE()
  1922.   INT NUM, LEN, T, I
  1923.   STRING STFNAME(20)
  1924.   IF DEBUG = 1 THEN
  1925.     PRINTE("SFile")
  1926.   FI
  1927.  
  1928.   NUMTRY ==+ 1
  1929.   IF NUMTRY > MAXTRY THEN RETURN('A) FI
  1930.  
  1931.   I = 1        ;STANDARD FILE NAMES DON'T HAVE D1:
  1932.   WHILE FILNAM(I) <> ': DO I ==+ 1 OD
  1933.   LEN = FILNAM(0)-I
  1934.   FOR T = 0 TO LEN-1 DO
  1935.     STFNAME(T) = FILNAM(I+T+1)
  1936.   OD
  1937.  
  1938.   SPACK('F, N, LEN, STFNAME)
  1939.   T = RPACK(@LEN, @NUM, RECPKT)
  1940.   IF T = 'N OR T = 'Y THEN
  1941.     IF T = 'N
  1942.     THEN
  1943.       NUM ==- 1
  1944.       IF NUM < 0 THEN NUM = 63 FI
  1945.     FI
  1946.  
  1947.     IF N <> NUM
  1948.     THEN
  1949.       RETURN(STATE)
  1950.     FI
  1951.     NUMTRY = 0
  1952.     N = (N + 1) MOD 64
  1953.     SIZE = BUFILL(PACKET)
  1954.     IF SIZE = EOF THEN
  1955.       RETURN('Z)
  1956.     ELSE
  1957.       RETURN('D)
  1958.     FI
  1959.   ELSEIF T = FALSE THEN RETURN(STATE)
  1960.   ELSE RETURN('A)
  1961.   FI
  1962.  
  1963. ; SData
  1964. ;
  1965. ; Send File Data
  1966.  
  1967. BYTE FUNC SData()
  1968.   INT NUM, LEN, T
  1969.  
  1970.   NUMTRY ==+ 1
  1971.   IF NUMTRY > MAXTRY THEN
  1972.     RETURN('A)
  1973.   FI
  1974.   SPACK('D, N, SIZE, PACKET)
  1975.   T = RPACK(@LEN, @NUM, RECPKT)
  1976.   IF T = 'N OR T = 'Y THEN
  1977.     IF T = 'N
  1978.     THEN
  1979.       NUM ==- 1
  1980.       IF NUM < 0 THEN NUM = 63 FI
  1981.     FI
  1982.  
  1983.     IF N <> NUM
  1984.     THEN
  1985.       RETURN(STATE)
  1986.     FI
  1987.     NUMTRY = 0
  1988.     N = (N + 1) MOD 64
  1989.     SIZE = BUFILL(PACKET)
  1990.     IF SIZE = EOF THEN
  1991.       RETURN('Z)
  1992.     FI
  1993.     RETURN('D)
  1994.   ELSEIF T = FALSE THEN
  1995.     RETURN(STATE)
  1996.   ELSE RETURN('A)
  1997.   FI
  1998.  
  1999. ; SEOF()
  2000. ;
  2001. ; Send End-Of-File
  2002.  
  2003. BYTE FUNC SEOF()
  2004.   INT NUM, LEN, T
  2005.  
  2006.   IF DEBUG = 1 THEN
  2007.     PRINTF("SEOF%E")
  2008.   FI
  2009.  
  2010.   NUMTRY ==+ 1
  2011.   IF NUMTRY > MAXTRY THEN
  2012.     RETURN('A)
  2013.   FI
  2014.   SPACK('Z, N, 0, PACKET)
  2015.  
  2016.   IF DEBUG = 1 THEN
  2017.     PRINT("SEOF1 ")
  2018.   FI
  2019.  
  2020.   T = RPACK(@LEN, @NUM, RECPKT)
  2021.   IF T = 'N OR T = 'Y THEN
  2022.     IF T = 'N
  2023.     THEN
  2024.       NUM ==- 1
  2025.       IF NUM < 0 THEN NUM = 63 FI
  2026.       IF N <> NUM THEN RETURN(STATE) FI
  2027.     FI
  2028.  
  2029.     IF DEBUG = 1 THEN
  2030.       PRINTF("SEOF2 ")
  2031.     FI
  2032.     IF N <> NUM
  2033.     THEN
  2034.       RETURN(STATE)
  2035.     FI
  2036.     NUMTRY = 0
  2037.     N = (N + 1) MOD 64
  2038.     IF DEBUG = 1 THEN
  2039.       PRINTF("Closing %S%E", FILNAM)
  2040.     FI
  2041.     STOPR()
  2042.     IF DEBUG = 1 THEN
  2043.       PRINTF("getting next file%E")
  2044.     FI
  2045.     DO
  2046.       FILNAM = GETNEXT(6)
  2047.       IF FILNAM = 0 THEN EXIT FI
  2048.       CLOSE(3)
  2049.       ERRORNUM = 0
  2050.       OPEN(3,FILNAM, 4, 0)
  2051.       IF ERRORNUM < 128 THEN
  2052.         EXIT
  2053.       ELSE
  2054.         PRINTF("Can't read %S; Error %D%E",
  2055.           FILNAM, ERRORNUM)
  2056.       FI
  2057.     OD
  2058.       
  2059.     STARTR()
  2060.     IF FILNAM = 0 THEN
  2061.       RETURN('B)
  2062.     FI
  2063.     PRINTE(FILNAM)
  2064.     RETURN('F)
  2065.   ELSEIF T = FALSE THEN RETURN(STATE)
  2066.   ELSE RETURN('A)
  2067.   FI
  2068.  
  2069. ; SBreak()
  2070. ;
  2071. ; Send Break (End-of-Text)
  2072.  
  2073. BYTE FUNC SBreak()
  2074.   INT NUM, LEN, T
  2075.  
  2076.   IF DEBUG = 1 THEN
  2077.     PRINTF("SBreak%E")
  2078.   FI
  2079.  
  2080.   NUMTRY ==+ 1
  2081.   IF NUMTRY > MAXTRY THEN
  2082.     RETURN('A)
  2083.   FI
  2084.   SPACK('B, N, 0, PACKET)
  2085.  
  2086.   T = RPACK(@LEN, @NUM, RECPKT)
  2087.   IF T = 'N OR T = 'Y THEN
  2088.     IF T = 'N
  2089.     THEN
  2090.       NUM ==- 1
  2091.       IF NUM < 0 THEN NUM = 63 FI
  2092.       IF N <> NUM THEN
  2093.         RETURN(STATE)
  2094.       FI
  2095.     FI
  2096.  
  2097.     IF N <> NUM
  2098.     THEN
  2099.       RETURN(STATE)
  2100.     FI
  2101.  
  2102.     NUMTRY = 0
  2103.     N = (N + 1) MOD 64
  2104.     RETURN('C)
  2105.  
  2106.   ELSEIF T = FALSE THEN RETURN(STATE)
  2107.   ELSE RETURN('A)
  2108.   FI
  2109.  
  2110. ;MAIN SEND FILE ROUTINE
  2111.  
  2112. PROC SENDSW()
  2113.   STRING FSpec(20)
  2114.   DO
  2115.     Print("File spec -> ")
  2116.     INPUTMD(0, FSPEC, 19)
  2117.     IF FSPEC(0) = 0 THEN RETURN FI
  2118.     Normalize(FSPEC)
  2119.     FILNAM = GETFIRST(6, FSPEC)
  2120.     IF FILNAM = 0 THEN
  2121.       PRINTE("Invalid file name")
  2122.     FI
  2123.   UNTIL
  2124.     FILNAM <> 0
  2125.   OD
  2126.   Put(125)
  2127.   PRINTF("Sending %S%E", FSpec)
  2128.   PRINTE("Type any key to abort.")
  2129.   STARTR()
  2130.  
  2131.   STATE = 'S
  2132.   N = 0
  2133.   NUMTRY = 0
  2134.   DO
  2135.     IF CH <> 255 THEN
  2136.       PRINTE("User Abort")
  2137.       CH = 255
  2138.       EXIT
  2139.     FI
  2140.     IF     STATE = 'D THEN STATE = SDATA()
  2141.     ELSEIF STATE = 'F THEN STATE = SFILE()
  2142.     ELSEIF STATE = 'Z THEN STATE = SEOF()
  2143.     ELSEIF STATE = 'S THEN STATE = SINIT()
  2144.     ELSEIF STATE = 'B THEN STATE = SBREAK()
  2145.     ELSEIF STATE = 'A THEN
  2146.       PRINTE("Aborting")
  2147.       EXIT
  2148.     ELSE EXIT
  2149.     FI
  2150.   OD
  2151.   STOPR()
  2152.   CLOSE(3)
  2153.   RETURN
  2154.  
  2155. ;Tell Server to quit
  2156.  
  2157. PROC Finish()
  2158.   INT NUM, LEN, T
  2159.  
  2160.   IF DEBUG = 1 THEN
  2161.     PRINTE("Finish")
  2162.   FI
  2163.   STARTR()
  2164.   FOR NUMTRY = 0 TO 3
  2165.   DO
  2166.     PACKET(0) = 'F
  2167.     SPACK('G, 0, 1, PACKET)
  2168.  
  2169.     T = RPACK(@LEN, @NUM, RECPKT)
  2170.     IF T = 'N OR T = 'Y THEN
  2171.       IF T = 'N
  2172.       THEN
  2173.         NUM ==- 1
  2174.         IF NUM < 0 THEN NUM = 63 FI
  2175.         IF 0 <> NUM THEN
  2176.           EXIT
  2177.         FI
  2178.       FI
  2179.  
  2180.       IF 0 = NUM
  2181.       THEN
  2182.         STOPR()
  2183.         RETURN
  2184.       FI
  2185.     FI
  2186.   OD
  2187.  
  2188.   STOPR()
  2189.   PRINTE("Server didn't respond")
  2190.   RETURN
  2191.  
  2192. ;--------------------------
  2193. ;Kermit Protocol code ends here
  2194. ;--------------------------
  2195.  
  2196. ; --- END OF D:KPRO.ACT ---
  2197.  
  2198. ;<<<D:KTTY.ACT>>>
  2199. ; Terminal emulation for the masses
  2200. ; Emulates a VT-52, Option quits,
  2201. ; Start scrolls.
  2202.  
  2203. MODULE
  2204.   CARD ARRAY LBASE(24)
  2205.   BYTE ARRAY LCUR(24)
  2206.  
  2207.   BYTE CX, CY, LMAR, DLTOGGLE,TSTATE,
  2208.        consol = $D01F
  2209.   CARD SDLST = $230,
  2210.        SAVEDL, HELPLINE
  2211.  
  2212. ;Create a display list and display it
  2213. ;
  2214. ; Uses: LBASE, LCUR, LMAR, SAVEDL,
  2215. ; Modifies: DLTOGGLE, SCREEN MEMORY
  2216.  
  2217. PROC HACKDISPLAY()
  2218.   BYTE ARRAY DBASE
  2219.   BYTE I
  2220.   CARD J, TBASE
  2221.   DBASE = DLTOGGLE*85+SAVEDL+72
  2222.   DLTOGGLE = 1 - DLTOGGLE
  2223.   TBASE = DBASE
  2224.   FOR I = 0 TO 2 DO
  2225.     DBASE(I) = $70
  2226.   OD
  2227.   FOR I = 0 TO 23 DO
  2228.     DBASE ==+ 3
  2229.     DBASE(0) = $42
  2230.     J = LCUR(I)
  2231.     J = LBASE(J) + LMAR - LMARGN
  2232.     DBASE(1) = J
  2233.     DBASE(2) = J RSH 8
  2234.   OD
  2235.   DBASE(3) = $00
  2236.   DBASE(4) = $42
  2237.   DBASE(5) = HELPLINE
  2238.   DBASE(6) = HELPLINE RSH 8
  2239.   DBASE(7) = $41
  2240.   DBASE(8) = TBASE
  2241.   DBASE(9) = TBASE RSH 8
  2242.   SDLST = TBASE
  2243.   RETURN
  2244.  
  2245. PROC CFLIP()
  2246.   BYTE POINTER M
  2247.   BYTE I
  2248.   I = LCUR(CY)
  2249.   M = LBASE(I) + CX
  2250.   M^ ==! $80
  2251.   RETURN
  2252.  
  2253. PROC LCLEAR(BYTE LINE)
  2254.   BYTE I
  2255.   BYTE ARRAY T
  2256.   I = LCUR(LINE)
  2257.   T = LBASE(I)-2
  2258.   FOR I = 0 TO 81 DO
  2259.     T(I) = 0
  2260.   OD
  2261.   RETURN
  2262.  
  2263. PROC TINIT()
  2264.   CARD I, J
  2265.   ;First, find 24 valid lines in
  2266.   ;Sbuf.  Valid lines don't cross 4K
  2267.   J = SBUF
  2268.   FOR I = 0 TO 23
  2269.   DO
  2270.     IF (J RSH 12) <>
  2271.         ((J + 81) RSH 12)
  2272.     THEN
  2273.       J = (J & $F000) + $1000
  2274.     FI
  2275.     LBASE(I) = J+2
  2276.     J ==+ 82
  2277.     LCUR(I) = I ;set up current line order
  2278.     LCLEAR(I)
  2279.   OD
  2280.   ;Now set up a display list
  2281.   SAVEDL = SDLST
  2282.   HELPLINE = SDLST+32
  2283.   PUT(125)
  2284.   PRINTE("OPTION quits, (SHIFT)+START scrolls")
  2285.   DLTOGGLE = 0
  2286.   TSTATE = 'N
  2287.   CX = 0
  2288.   CY = 0
  2289.   LMAR = 0
  2290.   CFLIP()
  2291.   HACKDISPLAY()
  2292.   RETURN
  2293.  
  2294. BYTE FUNC TPUTN(BYTE C)
  2295.   BYTE I, TEMP
  2296.   BYTE POINTER M
  2297.   BYTE ARRAY TOSCR = [$40 $00 $20 $60]
  2298.   CFLIP()
  2299.   IF C < 32 THEN
  2300.     IF C = 27 THEN
  2301.       RETURN('E)
  2302.     ELSEIF C = 10 THEN
  2303.       IF CY < 23 THEN
  2304.         CY ==+ 1
  2305.       ELSE
  2306.         LCLEAR(0)
  2307.         TEMP = LCUR(0)
  2308.         FOR I = 0 TO 22
  2309.         DO
  2310.           LCUR(I) = LCUR(I+1)
  2311.         OD
  2312.         LCUR(23) = TEMP
  2313.         HACKDISPLAY()
  2314.       FI
  2315.  
  2316.      ELSEIF C = 13 THEN
  2317.        CX = 0
  2318.  
  2319.      ELSEIF C = 7 THEN ;BELL
  2320.        SETCOLOR(4, 0, 14)
  2321.        I = RTCLOCK + 2
  2322.        WHILE I <> RTCLOCK DO OD
  2323.        SETCOLOR(4, 0, 0)
  2324.  
  2325.      ELSEIF C = 8 THEN ;BACKSPACE
  2326.        IF CX > 0 THEN
  2327.          CX ==- 1
  2328.        FI
  2329.  
  2330.      ELSEIF C = 9 THEN ;TAB
  2331.        IF CX < 72 THEN
  2332.          CX = (CX + 8) & $F8
  2333.        FI
  2334.  
  2335.      ELSEIF C = 12 THEN
  2336.        FOR I = 0 TO 23 DO
  2337.          LCLEAR(I)
  2338.        OD
  2339.        CX = 0
  2340.        CY = 0
  2341.  
  2342.      FI
  2343.   ELSE         ;printing char
  2344.     I = LCUR(CY)
  2345.     M = LBASE(I) + CX
  2346.     M^ = TOSCR((C & $60) RSH 5)
  2347.       % (C & $9F)
  2348.     IF CX < 79 THEN CX ==+ 1
  2349.     FI
  2350.   FI
  2351.   CFLIP()
  2352.   RETURN('N)
  2353.  
  2354. BYTE FUNC TPUTE(BYTE C)
  2355.   BYTE TEMP, I
  2356.   BYTE ARRAY M
  2357.   IF C = 'A THEN
  2358.     IF CY > 0 THEN
  2359.       CY ==- 1
  2360.     FI
  2361.  
  2362.   ELSEIF C = 'B THEN
  2363.     IF CY < 23 THEN
  2364.       CY ==+ 1
  2365.     FI
  2366.  
  2367.   ELSEIF C = 'C THEN
  2368.     IF CX < 79 THEN
  2369.       CX ==+ 1
  2370.     FI
  2371.  
  2372.   ELSEIF C = 'D THEN
  2373.     IF CX > 0 THEN
  2374.       CX ==- 1
  2375.     FI
  2376.  
  2377.   ELSEIF C = 'H THEN
  2378.     CX = 0
  2379.     CY = 0
  2380.  
  2381.   ELSEIF C = 'I THEN
  2382.     IF CY > 0 THEN
  2383.       CY ==- 1
  2384.     ELSE
  2385.       LCLEAR(23)
  2386.       TEMP = LCUR(23)
  2387.       FOR I = 0 TO 22 DO
  2388.         LCUR(23-I) = LCUR(22-I)
  2389.       OD
  2390.       LCUR(0) = TEMP
  2391.       HACKDISPLAY()
  2392.     FI
  2393.  
  2394.   ELSEIF C = 'J OR C = 'K THEN
  2395.     I = LCUR(CY)
  2396.     M = LBASE(I)
  2397.     FOR I = CX TO 79 DO
  2398.       M(I) = 0
  2399.     OD
  2400.     IF C = 'J THEN
  2401.       FOR I = CY+1 TO 23 DO
  2402.         LCLEAR(I)
  2403.       OD
  2404.     FI
  2405.   ELSEIF C = 'Y THEN
  2406.     RETURN('R)
  2407.   ELSEIF C = 'Z THEN
  2408.     PUTD(2, 27)
  2409.     PUTD(2, '/)
  2410.     PUTD(2, 'Z)
  2411.   FI
  2412.   CFLIP()
  2413.   RETURN('N)
  2414.  
  2415. PROC TPUTSW(BYTE C)
  2416.   IF TSTATE = 'N THEN
  2417.     TSTATE = TPUTN(C)
  2418.   ELSEIF TSTATE = 'E THEN
  2419.     TSTATE = TPUTE(C)
  2420.   ELSEIF TSTATE = 'R THEN
  2421.     IF C < 32 THEN C = 32 FI
  2422.     CY = C - 32
  2423.     IF CY > 23 THEN CY = 23 FI
  2424.     TSTATE = 'C
  2425.   ELSEIF TSTATE = 'C THEN
  2426.     IF C < 32 THEN C = 32 FI
  2427.     CX = C - 32
  2428.     IF CX > 79 THEN CX = 79 FI
  2429.     CFLIP()
  2430.     TSTATE = 'N
  2431.   ELSE
  2432.     TSTATE = 'N    
  2433.   FI
  2434.   RETURN
  2435.  
  2436. PROC TQUIT()
  2437.   SDLST = SAVEDL
  2438.   PUT(125)
  2439.   RETURN
  2440.  
  2441. PROC TTYMode()
  2442.   BYTE c, SKSTAT = $D20F, OLDSCROLL
  2443.  
  2444.   StartR()
  2445.  
  2446.   TINIT()
  2447.   OLDSCROLL = RTCLOCK - 1
  2448.   DO
  2449.     IF ch <> $FF THEN
  2450.       c = GetD(1)
  2451.       IF c = 155 THEN c = 13
  2452.       ELSEIF c = 127 THEN c = 9
  2453.       ELSEIF c = $7E THEN c = backs
  2454.       FI
  2455.       PutD(2, c)
  2456.       IF localecho = 1 THEN
  2457.         TPUTSW(c)
  2458.       FI
  2459.     FI
  2460.  
  2461.     IF ncib() > 0 THEN
  2462.       c = GetD(2) & $7F ;strip parity
  2463.       TPUTSW(c)
  2464.     FI
  2465.  
  2466.     consol = 8
  2467.     IF (consol & 4) = 0 THEN
  2468.       EXIT
  2469.  
  2470.     ELSEIF (CONSOL & 1) = 0
  2471.       AND RTCLOCK <> OLDSCROLL THEN
  2472.       ;START - SHIFT LEFT & RIGHT
  2473.       IF (SKSTAT & 8) = 0 THEN
  2474.         IF LMAR > 0 THEN
  2475.           LMAR ==- 1
  2476.         FI
  2477.       ELSE
  2478.         IF LMAR < 40+LMARGN THEN
  2479.           LMAR ==+ 1
  2480.         FI
  2481.       FI
  2482.       HACKDISPLAY()
  2483.       OLDSCROLL = RTCLOCK
  2484.     FI
  2485.   OD
  2486.   TQUIT()
  2487.   StopR()
  2488.   RETURN
  2489.  
  2490. ;End of D:KTTY.ACT
  2491.