C     SIMPLE KERMIT BOOT PROGRAM
C
C     WRITTEN BY: JIM LEWINSON;  BREUER & COMPANY  (JIML@SCORE.ARPA)
C
C     VERSION 1.0(25)  9-JUL-84
C
      INTEGER SEQNUM,RETRY,STATE,TYPE,NEWLEN,NEWSEQ
      INTEGER DATA(256),OUTDAT(256)
      INTEGER TOCHAR,UNCHAR,CTL
      INTEGER STATEI,STATEF,STATED,STATEB,STATEA
      INTEGER DLET,YLET,NLET,SLET,BLET,FLET,ZLET,ELET,TLET
      INTEGER MYQUO,FILOPN,FILLIN(512),FILPTR
      LOGICAL*1 FILNAM(40)
C
      FILOPN = 0
      SEQNUM = 0
      RETRY = 0
      STATEI = 1
      STATEF = 2
      STATED = 3
      STATEB = 4
      STATEA = 5
C
      DLET = 68
      YLET = 89
      NLET = 78
      SLET = 83
      BLET = 66
      FLET = 70
      ZLET = 90
      ELET = 69
      TLET = 84
      MYQUO = 35
C
      STATE = STATEI
C
1000  CONTINUE
CDBG        WRITE (2,1001) STATE
CDBG  1001  FORMAT (' STATE NOW IS ',I4)
      IF (STATE.EQ.STATEI) GO TO 2000
      IF (STATE.EQ.STATEF) GO TO 3000
      IF (STATE.EQ.STATED) GO TO 4000
      IF (STATE.EQ.STATEA) GO TO 5000
      GO TO 8000
C
C     SEND AN ACK
1100  CALL SNDPAK(0,SEQNUM,'Y',OUTDAT)
      GO TO 1000
C
C     SEND AN ACK AND INC SEQ NUMBER
1200  CALL SNDPAK(0,SEQNUM,'Y',OUTDAT)
      SEQNUM = MOD(SEQNUM+1,64)
      RETRY = 0
      GO TO 1000
C
C     SEND A NAK
1300  CALL SNDPAK(0,SEQNUM,'N',OUTDAT)
      GO TO 1000
C
C     REPLY TO AN SEND-INIT PACKET
1400  SEQNUM = 0
      RETRY = 0
      OUTDAT(1) = TOCHAR(60)
      OUTDAT(2) = TOCHAR(10)
      OUTDAT(3) = TOCHAR(0)
      OUTDAT(4) = ' '
      OUTDAT(5) = TOCHAR(13)
      OUTDAT(6) = MYQUO
      OUTDAT(7) = 'N'
      OUTDAT(8) = '1'
      OUTDAT(9) = ' '
      OUTDAT(10) = ' '
      CALL SNDPAK(10,SEQNUM,'Y',OUTDAT)
      STATE = STATEF
      SEQNUM = MOD(SEQNUM+1,64)
      RETRY = 0
      GO TO 1000
C
C     STATE S - AWAIT SEND-INIT
2000  SEQNUM = 0
      RETRY = 0
      CALL GETPAK(NEWLEN,NEWSEQ,TYPE,DATA)
      IF (NEWLEN.LT.0) GO TO 2800
      IF (TYPE.NE.SLET) GO TO 2800
      GO TO 1400
C
2800  RETRY = RETRY + 1
      GO TO 1300
C
C     STATE F - AWAIT FILE HEADER
3000  CALL GETPAK(NEWLEN,NEWSEQ,TYPE,DATA)
      IF (NEWLEN.LT.0) GO TO 3800
      IF (TYPE.EQ.FLET) GO TO 3100
      IF (TYPE.EQ.SLET) GO TO 3200
      IF (TYPE.EQ.ZLET) GO TO 3300
      IF (TYPE.EQ.BLET) GO TO 3400
      GO TO 3500
C
3100  DO 3110 I=1,40
3110  FILNAM(I) = 0
      DO 3120 I = 1,NEWLEN
3120  FILNAM(I) = DATA(I)
      IF (FILOPN.EQ.0) GO TO 3130
      CLOSE (UNIT=1)
3130  OPEN (UNIT=1,NAME=FILNAM,CARRIAGECONTROL='LIST')
      FILOPN = -1
      FILPTR = 1
      STATE = STATED
      GO TO 1200
C
3200  SEQNUM = 0
      RETRY = 0
      GO TO 1400
C
3300  NEWSEQ = MOD(NEWSEQ+1,64)
      IF (NEWSEW.NE.SEQNUM) GO TO 3500
      RETRY = RETRY + 1
      GO TO 1100
C
3400  STATE = STATEI
      GO TO 1100
C
3500  STATE = STATEA
      GO TO 1300
C
3800  GO TO 1300
C
C     STATE D - RECEIVE DATA
4000  CONTINUE
CDBG        WRITE (2,4001) SEQNUM
CDBG  4001  FORMAT (' LOOKING FOR PACKET ',I4)
      CALL GETPAK(NEWLEN,NEWSEQ,TYPE,DATA)
      IF (NEWLEN.LT.0) GO TO 4800
      IF (TYPE.EQ.DLET) GO TO 4100
      IF (TYPE.EQ.ZLET) GO TO 4200
      IF (TYPE.EQ.FLET) GO TO 4300
      GO TO 4400
C
4100  IF (NEWSEQ.EQ.SEQNUM) GO TO 4110
      RETRY = RETRY + 1
      GO TO 1100
4110  I = 1
CDBG        WRITE (2,4111) (DATA(J),J=1,NEWLEN)
CDBG  4111  FORMAT(' DATA RCVD=',132A1)
4120  IF (I.GT.NEWLEN) GO TO 4170
      IF (DATA(I).NE.MYQUO) GO TO 4160
4130  I = I + 1
      IF (DATA(I).EQ.MYQUO) GO TO 4160
      DATA(I) = CTL(DATA(I))
      IF ((DATA(I).NE.10).AND.(DATA(I).NE.13)) GO TO 4160
      IF (DATA(I).EQ.10) GO TO 4150
      IF (FILPTR.EQ.1) GO TO 4140
      WRITE (1,4131) (FILLIN(J),J=1,FILPTR-1)
4131  FORMAT(132A1)
      GO TO 4150
4140  WRITE (1,4131)
4150  I = I + 1
      FILPTR = 1
      GO TO 4120
4160  FILLIN(FILPTR) = DATA(I)
      FILPTR = FILPTR + 1
      I = I + 1
      GO TO 4120
C
4170  GO TO 1200
C
4200  CLOSE(UNIT=1)
      FILOPN = 0
      STATE = STATEF
      GO TO 1200
C
4300  RETRY = RETRY + 1
      GO TO 1100
C
4400  STATE = STATEA
      GO TO 1300
C
4800  GO TO 1300
C
C     STATE A - ABORT
5000  STATE = STATEI
      IF (FILOPN.EQ.0) GO TO 5010
      CLOSE (UNIT=1)
5010  FILOPN = 0
      RETRY = 0
      SEQNUM = 0
      GO TO 1300
C
8000  CONTINUE
      STOP
      END
C
      SUBROUTINE GETPAK(NEWLEN,NEWSEQ,TYPE,DATA)
C
      INTEGER NEWLEN,NEWSEQ,TYPE,DATA(256)
      INTEGER TOCHAR,UNCHAR,CTL
      INTEGER LINE(132),SOH,SEQ,LEN,DST,DEND,SUM,TYP,CHK
C
      NEWLEN = -1
      NEWSEQ = 0
      TYPE = ' '
C
100   READ (5,101) (LINE(I),I=1,132)
101   FORMAT(132A1)
C
      NONBLK = 0
      DO 110 I = 1,132
      J = MOD(LINE(I),128)
      IF (J.EQ.32) GO TO 110
      NONBLK = 1
110   LINE(I) = J
C
      IF (NONBLK.EQ.0) GO TO 100
C
      DO 200 I=1,132
200   IF (LINE(I).EQ.1) GO TO 210
      I = 0
C
210   SOH = I
      IF (SOH+4.GT.132) GO TO 800
      LEN = UNCHAR(LINE(SOH+1))
      SEQ = UNCHAR(LINE(SOH+2))
      TYP = LINE(SOH+3)
      IF ((SOH+1+LEN).GT.132) GO TO 800
      IF ((LEN.LT.3).OR.(LEN.GT.94)) GO TO 800
C
      CHK = LINE(SOH+1+LEN)
      SUM = 0
      DST = SOH + 4
      DEND = SOH + 4 + (LEN-3) - 1
C
      DO 310 I = SOH+1,DEND
310   SUM = MOD(SUM + LINE(I),256)
      SUM = TOCHAR(MOD( SUM + SUM/64,64))
CDBG        WRITE (2,311) LEN,SEQ,TYP,CHK,SUM
CDBG  311   FORMAT (' LEN,SEQ,TYP,GIVEN SUM,REAL SUM= ',5I6)
      IF (SUM.NE.CHK) GO TO 800
C
      DO 410 I = DST,DEND
410   DATA(I-DST+1) = LINE(I)
      NEWLEN = LEN - 3
      NEWSEQ = SEQ
      TYPE = TYP
      GO TO 900
C
800   NEWLEN = -1
      GO TO 900
C
900   RETURN
      END
C
      SUBROUTINE SNDPAK(DLEN,SEQ,TYP,OUTDAT)
C
      INTEGER DLEN,SEQ,TYP,OUTDAT(256)
      INTEGER TOCHAR,UNCHAR,CTL
      INTEGER SOH,SQ,SUM,LN,CHK
C
      SOH = 1
      LN = TOCHAR(DLEN+3)
      SQ = TOCHAR(SEQ)
C
      SUM = LN + SQ + TYP
      IF (DLEN.LE.0) GO TO 120
      DO 110 I = 1,DLEN
110   SUM = MOD(SUM + OUTDAT(I),256)
120   SUM = MOD(SUM + SUM/64,64)
      CHK = TOCHAR(SUM)
C
      IF (DLEN.EQ.0) GO TO 300
      WRITE (6,201) SOH,LN,SQ,TYP,(OUTDAT(I),I=1,DLEN),CHK
201   FORMAT (' ',132A1)
      GO TO 900
300   WRITE (6,201) SOH,LN,SQ,TYP,CHK
C
900   RETURN
      END
C
C
      FUNCTION TOCHAR(I)
      INTEGER TOCHAR,I
C
      TOCHAR = MOD(I,128) + 32
      RETURN
      END
C
      FUNCTION UNCHAR(I)
      INTEGER UNCHAR,I
C
      UNCHAR = MOD(I,128) - 32
      RETURN
      END
C
      FUNCTION CTL(I)
      INTEGER CTL,I,J
C
      J = I / 64
      J = MOD(J,2)
      IF (J.EQ.0) GO TO 10
      CTL = MOD(I,128) - 64
      GO TO 20
C
10    CTL = MOD(I,128) + 64
20    RETURN
      END
