-
Notifications
You must be signed in to change notification settings - Fork 6
/
hydra.e
2768 lines (2418 loc) · 107 KB
/
hydra.e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
OPT LARGE,MODULE
MODULE 'dos/dos','*miscfuncs','devices/timer'
CONST EOF=-1
CONST CHATSTART = '\!\! * Chat mode start\b\n'
CONST CHATEND = '\!\!\b\n * Chat mode end\r\n'
CONST CHATTIME = '\!\!\b\n * Chat mode end - timeout\b\n'
/* HYDRA Specification Revision/Timestamp ---------Revision------Date------- */
CONST H_REVSTAMP=$2b1aab00 /* 001 01 Dec 1992 */
CONST H_REVISION=1
CONST HC_OS='AMIGA'
CONST PRGNAME='HydraCom'
CONST LOGID='HCom'
CONST VERSION='1.00'
/* HYDRA Basic Values ------------------------------------------------------ */
CONST FNAMELEN=31
CONST CHAT_TIMEOUT=60
CONST CHATLEN=256
CONST HEXDIGIT='0123456789abcdef'
CONST ABORTSTR='\x18\x18\x18\x18\x18\x18\x18\x18\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08'
CONST AUTOSTR='hydra\b'
CONST PKTPREFIX='\0' ->fix this
CONST HDXMSG='Fallback to one-way xfer'
CONST H_MINBLKLEN=64 /* Min. length of a HYDRA data block */
CONST H_MAXBLKLEN=2048 /* Max. length of a HYDRA data block */
CONST H_OVERHEAD=8 /* Max. no. control bytes in a pkt */
CONST H_MAXPKTLEN=6183 ->((H_MAXBLKLEN + H_OVERHEAD + 5) * 3) /* Encoded pkt */
CONST H_BUFLEN=6199 ->(H_MAXPKTLEN + 16) /* Buffer sizes: max.enc.pkt + slack */
CONST XON=17 /* Ctrl-Q (^Q) xmit-on character */
CONST XOFF=19 /* Ctrl-S (^S) xmit-off character */
CONST H_DLE=24 /* Ctrl-X (^X) HYDRA DataLinkEscape */
CONST H_PKTPREFIX=31 /* Max length of pkt prefix string */
CONST H_FLAGLEN=3 /* Length of a flag field */
CONST H_RETRIES=10 /* No. retries in case of an error */
CONST H_MINTIMER=10 /* Minimum timeout period */
CONST H_MAXTIMER=60 /* Maximum timeout period */
CONST H_START=5 /* Timeout for re-sending startstuff */
CONST H_IDLE=20 /* Idle? tx IDLE pkt every 20 secs */
CONST H_BRAINDEAD=120 /* Braindead in 2 mins (120 secs) */
CONST H_CRC16POLY=$8408
CONST H_CRC32POLY=$edb88320
/* HYDRA Transmitter States ------------------------------------------------ */
CONST HTX_DONE=0 /* All over and done */
CONST HTX_START=1 /* Send start autostr + START pkt */
CONST HTX_SWAIT=2 /* Wait for any pkt or timeout */
CONST HTX_INIT=3 /* Send INIT pkt */
CONST HTX_INITACK=4 /* Wait for INITACK pkt */
CONST HTX_RINIT=5 /* Wait for HRX_INIT -> HRX_FINFO */
CONST HTX_FINFO=6 /* Send FINFO pkt */
CONST HTX_FINFOACK=7 /* Wait for FINFOACK pkt */
CONST HTX_XDATA=8 /* Send next packet with file data */
CONST HTX_DATAACK=9 /* Wait for DATAACK packet */
CONST HTX_XWAIT=10 /* Wait for HRX_END */
CONST HTX_EOF=11 /* Send EOF pkt */
CONST HTX_EOFACK=12 /* End of file, wait for EOFACK pkt */
CONST HTX_REND=13 /* Wait for HRX_END && HTD_DONE */
CONST HTX_END=14 /* Send END pkt (finish session) */
CONST HTX_ENDACK=15 /* Wait for END pkt from other side */
/* HYDRA Device Packet Transmitter States ---------------------------------- */
CONST HTD_DONE=0 /* No device data pkt to send */
CONST HTD_DATA=1 /* Send DEVDATA pkt */
CONST HTD_DACK=2 /* Wait for DEVDACK pkt */
/* HYDRA Receiver States --------------------------------------------------- */
CONST HRX_DONE=0 /* All over and done */
CONST HRX_INIT=1 /* Wait for INIT pkt */
CONST HRX_FINFO=2 /* Wait for FINFO pkt of next file */
CONST HRX_DATA=3 /* Wait for next DATA pkt */
/* HYDRA Packet Types ------------------------------------------------------ */
CONST HPKT_START="A" /* Startup sequence */
CONST HPKT_INIT="B" /* Session initialisation */
CONST HPKT_INITACK="C" /* Response to INIT pkt */
CONST HPKT_FINFO="D" /* File info (name, size, time) */
CONST HPKT_FINFOACK="E" /* Response to FINFO pkt */
CONST HPKT_DATA="F" /* File data packet */
CONST HPKT_DATAACK="G" /* File data position ACK packet */
CONST HPKT_RPOS="H" /* Transmitter reposition packet */
CONST HPKT_EOF="I" /* End of file packet */
CONST HPKT_EOFACK="J" /* Response to EOF packet */
CONST HPKT_END="K" /* End of session */
CONST HPKT_IDLE="L" /* Idle - just saying I'm alive */
CONST HPKT_DEVDATA="M" /* Data to specified device */
CONST HPKT_DEVDACK="N" /* Response to DEVDATA pkt */
CONST HPKT_HIGHEST="N" /* Highest known pkttype in this imp */
/* HYDRA Internal Pseudo Packet Types -------------------------------------- */
CONST H_NOPKT=0 /* No packet (yet) */
CONST H_CANCEL=-1 /* Received cancel sequence 5*Ctrl-X */
CONST H_CARRIER=-2 /* Lost carrier */
CONST H_SYSABORT=-3 /* Aborted by operator on this side */
CONST H_TXTIME=-4 /* Transmitter timeout */
CONST H_DEVTXTIME=-5 /* Device transmitter timeout */
CONST H_BRAINTIME=-6 /* Braindead timeout (quite fatal) */
/* HYDRA Packet Format: START[<data>]<type><crc>END ------------------------ */
CONST HCHR_PKTEND="a" /* End of packet (any format) */
CONST HCHR_BINPKT="b" /* Start of binary packet */
CONST HCHR_HEXPKT="c" /* Start of hex encoded packet */
CONST HCHR_ASCPKT="d" /* Start of shifted 7bit encoded pkt */
CONST HCHR_UUEPKT="e" /* Start of uuencoded packet */
/* HYDRA Local Storage of INIT Options (Bitmapped) ------------------------- */
CONST HOPT_XONXOFF=1 /* Escape XON/XOFF */
CONST HOPT_TELENET=2 /* Escape CR-'@'-CR (Telenet escape) */
CONST HOPT_CTLCHRS=4 /* Escape ASCII 0-31 and 127 */
CONST HOPT_HIGHCTL=8 /* Escape above 3 with 8th bit too */
CONST HOPT_HIGHBIT=16 /* Escape ASCII 128-255 + strip high */
CONST HOPT_CANBRK=32 /* Can transmit a break signal */
CONST HOPT_CANASC=64 /* Can transmit/handle ASC packets */
CONST HOPT_CANUUE=128 /* Can transmit/handle UUE packets */
CONST HOPT_CRC32=256 /* Packets with CRC-32 allowed */
CONST HOPT_DEVICE=512 /* DEVICE packets allowed */
CONST HOPT_FPT=1024 /* Can handle filenames with paths */
/* What we can do */
CONST HCAN_OPTIONS=HOPT_XONXOFF OR HOPT_TELENET OR HOPT_CTLCHRS OR HOPT_HIGHCTL OR HOPT_HIGHBIT OR HOPT_CANASC OR HOPT_CANUUE OR HOPT_CRC32 OR HOPT_DEVICE
/* Vital options if we ask for any; abort if other side doesn't support them */
CONST HNEC_OPTIONS=HOPT_XONXOFF OR HOPT_TELENET OR HOPT_CTLCHRS OR HOPT_HIGHCTL OR HOPT_HIGHBIT OR HOPT_CANBRK
/* Non-vital options; nice if other side supports them, but doesn't matter */
CONST HUNN_OPTIONS=HOPT_CANASC OR HOPT_CANUUE OR HOPT_CRC32 OR HOPT_DEVICE
/* Default options */
CONST HDEF_OPTIONS=0
/* rxoptions during init (needs to handle ANY link yet unknown at that point */
CONST HRXI_OPTIONS=HOPT_XONXOFF OR HOPT_TELENET OR HOPT_CTLCHRS OR HOPT_HIGHCTL OR HOPT_HIGHBIT
/* ditto, but this time txoptions */
CONST HTXI_OPTIONS=0
/* HYDRA Return codes ------------------------------------------------------ */
CONST XFER_ABORT=-1 /* Failed on this file & abort xfer */
CONST XFER_SKIP=0 /* Skip this file but continue xfer */
CONST XFER_OK=1 /* File was sent, continue transfer */
#define h_uuenc(c) (((c) AND $3f) + "!")
#define h_uudec(c) (((c) - "!") AND $3f)
->#define h_long1(buf) (*((long *) (buf)))
->#define h_long2(buf) (*((long *) ((buf) + ((int) sizeof (long)))))
->#define h_long3(buf) (*((long *) ((buf) + (2 * ((int) sizeof (long))))))
->static char abortstr[] = { 24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0 };
->static char *hdxmsg = "Fallback to one-way xfer";
->static char *pktprefix = "";
->static char *autostr = "hydra\r";
OBJECT h_dev
dev:PTR TO CHAR
func:LONG
ENDOBJECT
OBJECT h_flags
str:PTR TO CHAR
val:LONG
ENDOBJECT
EXPORT OBJECT hydra_t
recv_dir:PTR TO CHAR
txbuf:PTR TO CHAR /* packet buffers */
rxbuf:PTR TO CHAR /* packet buffers */
crc16tab:PTR TO INT /* CRC-16 table */
crc32tab:PTR TO LONG /* CRC-32 table */
txbufin:LONG /* read data from disk here */
rxbufmax:LONG
originator:CHAR /* are we the orig side? */
hdxlink:CHAR /* hdx link & not orig side */
options:LONG /* INIT options hydra_init() */
timeout:LONG /* general timeout in secs */
chatfill:LONG
chattimer:LONG
lasttimer:LONG
batchesdone:LONG /* No. HYDRA batches done */
txoptions:LONG /* HYDRA options (INIT seq) */
rxoptions:LONG /* HYDRA options (INIT seq) */
txpktprefix[H_PKTPREFIX + 1]:ARRAY OF CHAR /* pkt prefix str they want */
txwindow:LONG /* window size (0=streaming) */
rxwindow:LONG /* window size (0=streaming) */
txlastc:CHAR /* last byte put in txbuf */
rxdle:CHAR /* count of received H_DLEs */
rxpktformat:CHAR /* format of pkt receiving */
braindead:LONG /* braindead timer */
rxbufptr:PTR TO CHAR /* current position in rxbuf */
txfname[FNAMELEN]:ARRAY OF CHAR /* fname of current files */
rxfname[FNAMELEN]:ARRAY OF CHAR /* fname of current files */
rxpathname:PTR TO CHAR /* pointer to rx pathname */
txftime:LONG /* file timestamp (UNIX) */
rxftime:LONG /* file timestamp (UNIX) */
txfsize:LONG /* file length */
rxfsize:LONG /* file length */
txfd:LONG /* file handles */
rxfd:LONG /* file handles */
rxpktlen:INT /* length of last packet */
rxblklen:INT /* len of last good data blk */
txblklen:INT /* length of last block sent */
txstate:CHAR /* xmit/recv states */
rxstate:CHAR /* xmit/recv states */
txpos:LONG /* current position in files */
rxpos:LONG /* current position in files */
txmaxblklen:INT /* max block length allowed */
txgoodbytes:INT /* no. sent at this blk size */
txgoodneeded:INT /* to send before larger blk */
txlastack:LONG /* last dataack received */
txstart1:LONG /* time we started this file */
txstart2:LONG /* time we started this file */
rxstart1:LONG /* time we started this file */
rxstart2:LONG /* time we started this file */
txoffset:LONG /* offset in file we begun */
rxoffset:LONG /* offset in file we begun */
txtimer:LONG /* retry timers */
rxtimer:LONG /* retry timers */
txretries:INT /* retry counters */
rxretries:INT /* retry counters */
rxlastsync:LONG /* filepos last sync retry */
txsyncid:LONG /* id of last resync */
rxsyncid:LONG /* id of last resync */
rxnewfile:CHAR
txnewfile:CHAR
warned:CHAR
nobell:CHAR
h_dev:PTR TO LONG
h_flags:PTR TO LONG
chatbuf1[256+5]:ARRAY OF CHAR
curbuf:PTR TO CHAR
xfer_real[FNAMELEN]:ARRAY OF CHAR
xfer_temp[FNAMELEN]:ARRAY OF CHAR
single_file[FNAMELEN]:ARRAY OF CHAR
xfer_pathname[FNAMELEN]:ARRAY OF CHAR
xfer_log[FNAMELEN]:ARRAY OF CHAR
download[FNAMELEN]:ARRAY OF CHAR
xfer_fsize:LONG
xfer_ftime:LONG
cur_speed:LONG
mailer:CHAR
single_done:CHAR
noresume:CHAR
xfer_logged:CHAR
nostamp:CHAR
loglevel:CHAR
opuslog:PTR TO CHAR
result:PTR TO CHAR
outbuff[4096]: ARRAY OF CHAR
datalen:LONG
txstatus[40]:ARRAY OF CHAR
rxstatus[40]:ARRAY OF CHAR
txresumepos:LONG
rxresumepos:LONG
txerrorpos:LONG
hydra_txwindow:LONG
hydra_rxwindow:LONG
bytes_recv_ptr:LONG
bytes_sent_ptr:LONG
ultime_taken_ptr:PTR TO LONG
dltime_taken_ptr:PTR TO LONG
err:INT
hyd_open:LONG
hyd_close:LONG
hyd_seek:LONG
hyd_read:LONG
hyd_write:LONG
hyd_firstfile:LONG
hyd_nextfile:LONG
hyd_uploadcompleted:LONG
hyd_uploadfailed:LONG
hyd_downloadcompleted:LONG
hyd_dupecheck:LONG
hyd_logmessage:LONG
hyd_recvbyte:LONG
hyd_flush:LONG
hyd_isconnected:LONG
hyd_iscancelled:LONG
hyd_sysidle:LONG
hyd_chatwrite:LONG
hyd_getkey:LONG
hyd_status:LONG
devtxstate:INT /* dev xmit state */
devtxtimer:LONG /* dev xmit retry timer */
devtxretries:INT /* dev xmit retry counter */
devtxid:LONG /* id of last devdata pkt */
devrxid:LONG /* id of last devdata pkt */
devtxdev[H_FLAGLEN + 1]:ARRAY OF CHAR /* xmit device ident flag */
devtxbuf:PTR TO CHAR /* ptr to usersupplied dbuf */
devtxlen:INT /* len of data in xmit buf */
ENDOBJECT
->crc16tab[( crc ^ (c)) & 0xff] ^ ((crc >> 8) & 0x00ff)
PROC h_updcrc16(hyd:PTR TO hydra_t,crc,c) IS Eor(hyd.crc16tab[(Eor(crc,c)) AND 255],((Shr(crc,8)) AND 255)) AND $FFFF
PROC h_updcrc32(hyd:PTR TO hydra_t,crc,c) IS Eor(hyd.crc32tab[(Eor(crc,c)) AND 255],((Shr(crc,8)) AND $00ffffff))
PROC h_crc32test(crc)
IF(crc=$debb20e3) THEN RETURN 1
ENDPROC 0
PROC h_crc16test(crc)
IF(crc=$f0b8) THEN RETURN 1
ENDPROC 0
EXPORT PROC time() IS getSystemTime()
PROC h_timer_running(t) IS t<>0
PROC h_timer_expired(t) IS time() > t
PROC h_revdate(date,c:PTR TO CHAR) IS formatCDateTime(date,c)
PROC intell(x) IS (((x AND $FF) << 24) OR ((x AND $FF00) << 8) OR ((x AND $FF0000) >> 8) OR (((x AND $FF000000) >> 24)AND $FF))
PROC isdigit(ch) IS (ch>='0') AND (ch<='9')
PROC loc_puts(hyd:PTR TO hydra_t,s:PTR TO CHAR)
DEF p
p:=hyd.hyd_chatwrite
IF p THEN p(s)
ENDPROC
PROC com_putbyte(hyd:PTR TO hydra_t,v)
hyd.outbuff[hyd.datalen]:=v
hyd.datalen:=hyd.datalen+1
IF hyd.datalen=4096 THEN com_flush(hyd)
ENDPROC
PROC com_flush(hyd:PTR TO hydra_t)
DEF p
p:=hyd.hyd_flush
IF p
p(hyd.outbuff,hyd.datalen)
hyd.datalen:=0
ENDIF
/* com_flush(VOID):
*
* Make sure all pending data gets written.
*/
ENDPROC
PROC com_purge()
/* com_purge(VOID):
*
* Clear the read/write buffers.
*/
->WriteF('com_purge\n')
ENDPROC
PROC com_dump(hyd)
com_flush(hyd)
ENDPROC
PROC com_getbyte(hyd:PTR TO hydra_t)
DEF p
/* com_getbyte(VOID):
*
* Read a single byte from the serial line. If not available,
* return EOF.
*/
p:=hyd.hyd_recvbyte
IF p
RETURN p(0)
ENDIF
ENDPROC -1
PROC com_outfull()
/* com_outfull(VOID):
*
* Return number of bytes still to be transferred.
*/
ENDPROC 0
PROC com_putblock(hyd:PTR TO hydra_t,b,l)
DEF i
/* com_putblock(byte *s,word len):
*
* Send a data block asynchronously.
*/
FOR i:=0 TO l-1 DO com_putbyte(hyd,b[]++)
com_flush(hyd)
ENDPROC
PROC dologmessage(hyd:PTR TO hydra_t,code,msg)
DEF p
p:=hyd.hyd_logmessage
IF p
p(code,msg)
ENDIF
ENDPROC
PROC get_key(hyd:PTR TO hydra_t)
DEF p
p:=hyd.hyd_getkey
IF p THEN RETURN p()
ENDPROC -1
PROC keyabort(hyd:PTR TO hydra_t)
DEF p:PTR TO CHAR
DEF esc=FALSE
DEF s[255]:STRING
DEF c
IF (hyd.chattimer > 0)
IF (time() > hyd.chattimer)
hyd.chattimer:=0
hyd.lasttimer:=0
hydra_devsend(hyd,'CON',CHATTIME,StrLen(CHATTIME))
loc_puts(hyd,CHATTIME+2)
ELSEIF (((time() + 10) > hyd.chattimer) AND (hyd.warned=FALSE))
loc_puts(hyd,'\!\b\n * Warning: chat mode timeout in 10 seconds\b\n')
hyd.warned:=TRUE
ENDIF
ELSEIF (hyd.chattimer <> hyd.lasttimer)
IF (hyd.chattimer=0)
IF (hyd.nobell)
p:=' * Remote has chat facility with bell disabled\n';
ELSE
p:= ' * Remote has chat facility with bell enabled\n';
ENDIF
hydra_devsend(hyd,'CON',p,StrLen(p))
loc_puts(hyd,' * Hydra session in progress, chat facility now available\b\n')
ELSEIF (hyd.chattimer = -1)
loc_puts(hyd,' * Hydra session in init state, can''t chat yet\b\n')
ELSEIF (hyd.chattimer = -2)
loc_puts(hyd,' * Remote has no chat facility available\b\n')
ELSEIF (hyd.chattimer = -3)
IF (hyd.lasttimer > 0) THEN loc_puts(hyd,'\b\n')
loc_puts(hyd,' * Hydra session in exit state, can''t chat anymore\b\n')
ENDIF
hyd.lasttimer:=hyd.chattimer
ENDIF
c:=get_key(hyd)
IF c=27
esc:=TRUE
ELSEIF (c="\b") OR (c=8) OR (c=7) OR ((c >= " ") AND (c < 127))
IF (hyd.chattimer>0)
hyd.chattimer:=time() + CHAT_TIMEOUT
hyd.warned:=FALSE
IF (hyd.chatfill >= CHATLEN)
loc_puts(hyd,'\!')
ELSE
IF (c="\b")
hyd.curbuf[hyd.chatfill]:="\n"
hyd.chatfill:=hyd.chatfill+1
loc_puts(hyd,'\b\n')
ELSEIF(c=8)
IF ((hyd.chatfill > 0) AND (hyd.curbuf[hyd.chatfill - 1] <> "\n"))
hyd.chatfill:=hyd.chatfill-1
ELSE
hyd.curbuf[hyd.chatfill]:=8
hyd.chatfill:=hyd.chatfill+1
hyd.curbuf[hyd.chatfill]:=" "
hyd.chatfill:=hyd.chatfill+1
hyd.curbuf[hyd.chatfill]:=8
hyd.chatfill:=hyd.chatfill+1
ENDIF
loc_puts(hyd,'\h08 \h08')
ELSE
hyd.curbuf[hyd.chatfill]:=c
hyd.chatfill:=hyd.chatfill+1
IF (c <> 7)
StringF(s,'\c',c)
loc_puts(hyd,s)
ENDIF
ENDIF
ENDIF
ENDIF
ELSEIF (c=3)
IF (hyd.chattimer=0)
hydra_devsend(hyd,'CON',CHATSTART,StrLen(CHATSTART))
loc_puts(hyd,CHATSTART+2)
hyd.chattimer:=time() + CHAT_TIMEOUT
hyd.lasttimer:=hyd.chattimer
ELSEIF (hyd.chattimer > 0)
hyd.chattimer:=0
hyd.lasttimer:=0
hydra_devsend(hyd,'CON',CHATEND,StrLen(CHATEND))
loc_puts(hyd,CHATEND+2)
ELSE
loc_puts(hyd,'\!')
ENDIF
ELSE
ENDIF
IF (hyd.chatfill > 0)
IF hydra_devsend(hyd,'CON',hyd.curbuf,hyd.chatfill)
hyd.curbuf:=hyd.chatbuf1
hyd.chatfill:=0
ENDIF
ENDIF
ENDPROC esc
PROC carrier(hyd:PTR TO hydra_t)
DEF p
p:=hyd.hyd_isconnected
IF p
RETURN p()
ENDIF
ENDPROC TRUE
PROC setstamp(name:PTR TO CHAR,time)
DEF ds:datestamp
dateTimeToDateStamp(time,ds)
SetFileDate(name,ds)
ENDPROC
PROC stat(fn:PTR TO CHAR)
DEF fsize=-1,fdate=-1
DEF fBlock: fileinfoblock
DEF fLock
IF((fLock:=Lock(fn,ACCESS_READ)))=NIL
RETURN -1,-1
ENDIF
IF((fBlock:=AllocDosObject(DOS_FIB,NIL)))=NIL
UnLock(fLock)
RETURN -1,-1
ENDIF
IF(Examine(fLock,fBlock))
fsize:=fBlock.size
fdate:=dateStampToDateTime(fBlock.datestamp)
ENDIF
UnLock(fLock)
FreeDosObject(DOS_FIB,fBlock)
ENDPROC fsize,fdate
PROC dosys_idle(hyd:PTR TO hydra_t)
DEF p
p:=hyd.hyd_sysidle
IF p THEN p()
ENDPROC
PROC freespace(s)
ENDPROC 10000000
PROC getFileDate(fn:PTR TO CHAR)
DEF fdate=-1
DEF fBlock: fileinfoblock
DEF fLock
IF((fLock:=Lock(fn,ACCESS_READ)))=NIL
RETURN -1,-1
ENDIF
IF((fBlock:=AllocDosObject(DOS_FIB,NIL)))=NIL
UnLock(fLock)
RETURN -1,-1
ENDIF
IF(Examine(fLock,fBlock))
fdate:=dateStampToDateTime(fBlock.datestamp)
ENDIF
UnLock(fLock)
FreeDosObject(DOS_FIB,fBlock)
ENDPROC fdate
PROC resultlog(hyd:PTR TO hydra_t,xmit, fname:PTR TO CHAR, bytes, xfertime)
DEF fp
DEF s[255]:STRING
IF (hyd.opuslog)
IF ((fp:=Open(hyd.opuslog,MODE_READWRITE))>0)
Seek(fp,0,OFFSET_END)
IF (fname)
PutF(fp, '\s \s\s \d', IF xmit THEN 'Sent' ELSE 'Got',
IF xmit THEN '' ELSE hyd.download, fname, bytes)
IF (hyd.mailer) THEN PutF(fp,' \d',xfertime)
PutF(fp,'\n')
ENDIF
Close(fp)
ELSE
StringF(s,'-Couldn''t append opus log-file \s',hyd.opuslog)
dologmessage(hyd,3,s)
ENDIF
ENDIF
IF (hyd.result)
IF ((fp:=Open(hyd.result,MODE_READWRITE))>0)
Seek(fp,0,OFFSET_END)
IF (fname)
PutF(fp,'\c \d[6] \u[5] bps \d[4] cps 0 errors 0 1024 \s -1\n',
IF xmit THEN "H" ELSE "R",
bytes, hyd.cur_speed,
IF xfertime THEN (bytes / xfertime) ELSE 9999,
fname)
ENDIF
Close(fp)
ELSE
StringF(s,'-Couldn''t append result-file \s',hyd.result)
dologmessage(hyd,3,s)
ENDIF
ENDIF
ENDPROC
PROC xfer_bad(hyd:PTR TO hydra_t)
DEF fsize,fp,n
IF (hyd.single_file[0]) THEN hyd.single_done:=TRUE
IF (hyd.xfer_logged) THEN RETURN TRUE /* Already a logged bad-xfer */
n:=StrLen(hyd.xfer_real) - 1
IF ((n > 3) AND ((StrCmp(hyd.xfer_real+n-3,'.PKT')=FALSE) OR ((StrCmp(hyd.xfer_real+n-3,'.REQ')=FALSE))))
xfer_del(hyd)
RETURN FALSE /* don't recover .PKT / .REQ */
ENDIF
fsize:=FileLength(hyd.xfer_pathname)
IF (hyd.noresume OR (fsize < 1024)) /* not allowed/worth saving */
xfer_del(hyd)
RETURN FALSE
ENDIF
IF ((fp:=Open(hyd.xfer_log,MODE_READWRITE))>=0)
Seek(fp,0,OFFSET_END)
PutF(fp, '\s \s \d \d\n',hyd.xfer_real, hyd.xfer_temp, hyd.xfer_fsize, hyd.xfer_ftime)
Close(fp)
RETURN TRUE /* bad-xfer logged now */
ENDIF
xfer_del(hyd)
/* Couldn't log bad-xfer */
ENDPROC FALSE
PROC xfer_del(hyd:PTR TO hydra_t)
DEF new_log[FNAMELEN]:ARRAY OF CHAR
DEF linebuf[256]:STRING
DEF bad_real[FNAMELEN]:ARRAY OF CHAR
DEF bad_temp[FNAMELEN]:ARRAY OF CHAR
DEF bad_fsize,bad_ftime;
DEF fp,new_fp
DEF left
DEF p,lb
IF (FileLength(hyd.xfer_pathname)>=0) THEN DeleteFile(hyd.xfer_pathname)
IF ((fp:=Open(hyd.xfer_log,MODE_OLDFILE))>=0)
AstrCopy(new_log,hyd.download)
AddPart(new_log,'BAD-XFER.$$$',256)
IF ((new_fp:=Open(new_log, MODE_NEWFILE))>=0)
left:=FALSE
WHILE (ReadStr(fp,linebuf)<>-1) OR (StrLen(linebuf)>0)
StrCopy(bad_real,'')
StrCopy(bad_temp,'')
bad_fsize:=0
bad_ftime:=0
IF (p:=InStr(linebuf,' '))>=0
StrCopy(bad_real,linebuf,p)
lb:=p+1
IF (p:=InStr(linebuf+lb,' '))>=0
StrCopy(bad_temp,linebuf+lb,p)
lb:=lb+p+1
bad_fsize:=Val(linebuf+lb)
IF (p:=InStr(linebuf+lb,' '))>=0
bad_ftime:=Val(linebuf+lb+p)
ENDIF
ENDIF
ENDIF
/*sscanf(linebuf,"%s %s %ld %lo",
bad_real, bad_temp, &bad_fsize, &bad_fime);*/
->this
IF (StrCmp(hyd.xfer_real,bad_real) OR StrCmp(hyd.xfer_temp,bad_temp) OR (hyd.xfer_fsize <> bad_fsize) OR (hyd.xfer_ftime <> bad_ftime))
PutF(new_fp,'\s',linebuf)
left:=TRUE
ENDIF
ENDWHILE
Close(fp)
Close(new_fp)
DeleteFile(hyd.xfer_log)
IF (left)
Rename(new_log,hyd.xfer_log)
ELSE
DeleteFile(new_log)
ENDIF
ELSE
Close(fp)
ENDIF
ENDIF
ENDPROC
PROC xfer_init(hyd:PTR TO hydra_t,fname:PTR TO CHAR,fsize,ftime)
DEF linebuf[256]:STRING
DEF bad_real[FNAMELEN]:ARRAY OF CHAR
DEF bad_temp[FNAMELEN]:ARRAY OF CHAR
DEF bad_fsize, bad_ftime, p:PTR TO CHAR, fp
DEF lb
IF (hyd.single_done) THEN RETURN NIL
AstrCopy(hyd.xfer_real,fname)
hyd.xfer_fsize:=fsize
hyd.xfer_ftime:=ftime
AstrCopy(hyd.xfer_pathname,hyd.download)
AddPart(hyd.xfer_pathname,hyd.xfer_real,256)
IF (FileLength(hyd.xfer_pathname)>=0)
/* already have file */
IF ((hyd.xfer_fsize = FileLength(hyd.xfer_pathname)) AND (hyd.xfer_ftime = getFileDate(hyd.xfer_pathname))) THEN RETURN NIL
ENDIF
AstrCopy(hyd.xfer_log,hyd.download)
AddPart(hyd.xfer_log,'BAD-XFER.LOG',256)
IF ((fp:=Open(hyd.xfer_log,MODE_OLDFILE))>0)
WHILE (ReadStr(fp,linebuf)<>-1) OR (StrLen(linebuf)>0)
StrCopy(bad_real,'')
StrCopy(bad_temp,'')
bad_fsize:=0
bad_ftime:=0
IF (p:=InStr(linebuf,' '))>=0
StrCopy(bad_real,linebuf,p)
lb:=p+1
IF (p:=InStr(linebuf+lb,' '))>=0
StrCopy(bad_temp,linebuf+lb,p)
lb:=lb+p+1
bad_fsize:=Val(linebuf+lb)
IF (p:=InStr(linebuf+lb,' '))>=0
bad_ftime:=Val(linebuf+lb+p)
ENDIF
ENDIF
ENDIF
/*sscanf(linebuf,"%s %s %ld %lo",
bad_real, bad_temp, &bad_fsize, &bad_ftime);
*/
->this
IF ((StrCmp(hyd.xfer_real,bad_real)=FALSE) AND (hyd.xfer_fsize = bad_fsize) AND (hyd.xfer_ftime = bad_ftime))
AstrCopy(hyd.xfer_pathname,hyd.download)
AddPart(hyd.xfer_pathname,bad_temp,255);
IF (FileLength(hyd.xfer_pathname)>=0)
Close(fp)
AstrCopy(hyd.xfer_temp,bad_temp)
hyd.xfer_logged:=TRUE
RETURN hyd.xfer_pathname
ENDIF
ENDIF
ENDWHILE
Close(fp)
ENDIF
AstrCopy(hyd.xfer_pathname,hyd.download)
p:=hyd.xfer_pathname + StrLen(hyd.xfer_pathname)
AddPart(hyd.xfer_pathname,'BAD-XFER.000',FNAMELEN)
unique_name(hyd.xfer_pathname);
AstrCopy(hyd.xfer_temp,p)
hyd.xfer_logged:=FALSE
ENDPROC hyd.xfer_pathname
PROC xfer_okay(hyd:PTR TO hydra_t)
DEF new_pathname[FNAMELEN]:ARRAY OF CHAR
DEF p:PTR TO CHAR
AstrCopy(new_pathname,hyd.download)
p:= new_pathname + StrLen(new_pathname); /* start of fname */
IF (hyd.single_file[0])
AddPart(new_pathname,hyd.single_file,FNAMELEN) /* add override fname */
hyd.single_done:=TRUE
ELSE
AddPart(new_pathname,hyd.xfer_real,FNAMELEN) /* add real fname */
unique_name(new_pathname) /* make it unique */
ENDIF
Rename(hyd.xfer_pathname,new_pathname) /* rename temp to real */
IF ((hyd.nostamp=0) AND hyd.xfer_ftime)
setstamp(new_pathname,hyd.xfer_ftime); /* set timestamp */
ENDIF
IF (hyd.xfer_logged) THEN xfer_del(hyd) /* delete from bad-xfer log */
IF StrCmp(p,hyd.xfer_real)=FALSE THEN RETURN hyd.xfer_real /* dup rename? */
ENDPROC 0
PROC unique_name(pathname:PTR TO CHAR)
DEF p:PTR TO CHAR, n
DEF suffix[4]:STRING
StrCopy(suffix,'.000')
IF (FileLength(pathname)>=0)
p:=pathname
WHILE (p[] AND (p[]<>'.')) DO p++
FOR n:=0 TO 3
IF (p[]=0)
p[]:=suffix[n]
p++
p[]:=0
ELSE
p++
ENDIF
ENDFOR
WHILE(FileLength(pathname)>=0)
p:=pathname + (StrLen(pathname)) - 1
IF (isdigit(p[])=0)
p[]:=0
ELSE
FOR n:=3 TO 0 STEP -1
IF (isdigit(p[])=0) THEN p[]:=0
p++
EXIT p[]<='9'
p[]:=0
p--
ENDFOR
ENDIF
ENDWHILE
ENDIF
ENDPROC
->hydracommui speed 115200 port 0 line 2400 device serial.device nocarrier receive dl: size 0/235/652/170 nologwin term
PROC hydra_devfree(hyd:PTR TO hydra_t)
IF (hyd.devtxstate OR ((hyd.txoptions AND HOPT_DEVICE)=0) OR (hyd.txstate >= HTX_END))
RETURN FALSE /* busy or not allowed */
ELSE
RETURN TRUE /* allowed to send a new pkt */
ENDIF
ENDPROC/*hydra_devfree()*/
/*---------------------------------------------------------------------------*/
PROC hydra_devsend(hyd:PTR TO hydra_t,dev:PTR TO CHAR, data:PTR TO CHAR,len)
IF ((dev=0) OR (data=0) OR (len=0) OR (hydra_devfree(hyd)=FALSE)) THEN RETURN FALSE
AstrCopy(hyd.devtxdev,dev,H_FLAGLEN+1)
hyd.devtxbuf:=data
hyd.devtxlen:=IF (len > H_MAXBLKLEN) THEN H_MAXBLKLEN ELSE len
hyd.devtxid:=hyd.devtxid+1
hyd.devtxtimer:=0
hyd.devtxretries:=0
hyd.devtxstate:=HTD_DATA
/* special for chat, only prolong life if our side keeps typing! */
IF ((hyd.chattimer > 0) AND (OstrCmp(hyd.devtxdev,'CON')=FALSE) AND (hyd.txstate = HTX_REND))
hyd.braindead:=time()+H_BRAINDEAD
ENDIF
ENDPROC TRUE/*hydra_devsend()*/
/*---------------------------------------------------------------------------*/
PROC hydra_devfunc(hyd:PTR TO hydra_t,dev:PTR TO CHAR,func)
DEF i
DEF dv:PTR TO h_dev
i:=0;
dv:=hyd.h_dev[i]
WHILE (dv.dev)
IF (OstrCmp(dev,dv.dev,H_FLAGLEN))
dv.func:=func
RETURN TRUE
ENDIF
i++
dv:=hyd.h_dev[i]
ENDWHILE
ENDPROC FALSE/*hydra_devfunc()*/
/*---------------------------------------------------------------------------*/
PROC hydra_devrecv(hyd:PTR TO hydra_t)
DEF i,p,len,f
DEF dv:PTR TO h_dev
p:=hyd.rxbuf
len:=hyd.rxpktlen
p+=SIZEOF LONG /* skip the id long */
len-=SIZEOF LONG
i:=0
dv:=hyd.h_dev[i]
WHILE (dv.dev) /* walk through devs */
IF (OstrCmp(p,dv.dev,H_FLAGLEN))
IF (dv.func)
len-=StrLen(p)+1 /* sub devstr len */
p+=StrLen(p)+1 /* skip devtag */
p[len]:=0; /* NUL terminate */
f:=dv.func
f(hyd,p,len) /* call output func */
ENDIF
EXIT TRUE
ENDIF
i++
dv:=hyd.h_dev[i]
ENDWHILE
ENDPROC/*hydra_devrecv()*/
/*---------------------------------------------------------------------------*/
PROC put_flags(buf:PTR TO CHAR,flags:PTR TO LONG,val)
DEF i,p:PTR TO CHAR
DEF fl:PTR TO h_flags
p:=buf;
i:=0
fl:=flags[i]
WHILE (fl.val)
IF (val AND fl.val)
IF (p > buf) THEN p[]++:=","
AstrCopy(p,fl.str)
p+=H_FLAGLEN
ENDIF
i++
fl:=flags[i]
ENDWHILE
p[]:=0
ENDPROC/*put_flags()*/
/*---------------------------------------------------------------------------*/
PROC get_flags(buf:PTR TO CHAR, flags:PTR TO LONG)
DEF val,p:PTR TO CHAR,i
DEF fl:PTR TO h_flags
DEF s[255]:STRING
val:=0
REPEAT
IF (p:=InStr(buf,','))>=0
StrCopy(s,buf,p)
buf:=buf+p+1
ELSE
StrCopy(s,buf)
buf:=0
ENDIF
i:=0
fl:=flags[i]
WHILE (fl.val)
IF (StrCmp(s,fl.str))
val:=val OR fl.val
EXIT TRUE
ENDIF
i++
fl:=flags[i]
ENDWHILE
UNTIL buf=0
ENDPROC val /*get_flags()*/
/*---------------------------------------------------------------------------*/
PROC crc16block(hyd:PTR TO hydra_t,buf:PTR TO CHAR,len)
DEF crc=$ffff,i
FOR i:=0 TO len-1
crc:=h_updcrc16(hyd,crc,buf[]++)
ENDFOR
ENDPROC crc/*crc16block()*/
/*---------------------------------------------------------------------------*/
PROC crc32block(hyd:PTR TO hydra_t,buf:PTR TO CHAR,len)
DEF crc=$ffffffff,i
FOR i:=0 TO len-1
crc:=h_updcrc32(hyd,crc,buf[]++)
ENDFOR
ENDPROC crc/*crc32block()*/
/*---------------------------------------------------------------------------*/
PROC put_binbyte(hyd:PTR TO hydra_t,p:PTR TO CHAR,c)
DEF n
n:=c
IF (hyd.txoptions AND HOPT_HIGHCTL) THEN n:=n AND $7f