>>>>>>>> This file contains the sources for LCTERM, a communications >>>>>>>> program for the DEC Rainbow 100/100+ written by Larry Campbell >>>>>>>> of DEC in Computer Innovations C86. It incorporates both >>>>>>>> KERMIT and MODEM2 file transfer protocols. >>>>>>>> >>>>>>>> Lines beginning with ">>>>>>>>" delimit the various source files >>>>>>>> and show their names. The files follow: >>>>>>>> >>>>>>>> BUF.C /* * BUF.C * * Copyright (C) 1984 by Larry Campbell, 73 Concord St., Maynard Mass. * * This software may be freely copied and disseminated for * noncommercial purposes, if and only if this entire copyright * statement and notice is included intact. This software, and * the information contained herein, may not be used for commercial * purposes without my prior written permission. * * Implements simple ring buffers */ #include /* just for definition of NULL */ #include "buf.h" /* * create_buf (size) * * Create ring buffer of SIZE characters. Return NULL if failure, * address of buffer descriptor if successful. */ struct ring_buf *create_buf (size) int size; { struct ring_buf *new_buf; if (size < 2) return (NULL); if ((new_buf = malloc (sizeof (struct ring_buf))) == NULL) return (NULL); if ((new_buf->cdata = malloc (size)) == NULL) { free (new_buf); return (NULL); }; new_buf->putter = 0; new_buf->taker = 0; new_buf->size = size; return (new_buf); } /* * destroy_buf (buf) * * Release buffer and descriptor */ destroy_buf (buf) struct ring_buf *buf; { free (buf->cdata); free (buf); } /* * put_buf (buf, char) * * Put character into buffer. Return true (1) if successful, * false (0) if buffer full. */ int put_buf (buf, c) struct ring_buf *buf; char c; { int next; if ((next = ((buf->putter + 1) % buf->size)) == buf->taker) return (0); buf->cdata[buf->putter] = c; buf->putter = next; return (1); } /* * get_buf (buf) * * Get character from buffer, return 0 if buffer empty (user should * verify nonemptiness by calling buf_emptyp first) */ char get_buf (buf) struct ring_buf *buf; { char c; if (buf->taker == buf->putter) return (0); c = buf->cdata[buf->taker]; buf->taker = (buf->taker + 1) % buf->size; return (c); } /* * un_get_buf (buf, c) * * "unget" a character from a buffer, return true (1) if successful, * false (0) if failure because buffer full or character being * "ungotten" wasn't the same character "gotten" */ int un_get_buf (buf, c) struct ring_buf *buf; char c; { int dest; if ((dest = buf->taker - 1) < 0) dest = buf->size - 1; if (buf->putter == dest) return (0); /* buffer full */ if (buf->cdata[dest] != c) return (0); /* caller trying to cheat */ buf->taker = dest; return (1); } /* * buf_emptyp (buf) * * Test for emptiness of a buffer */ int buf_emptyp (buf) struct ring_buf *buf; { return (buf->putter == buf->taker); } /* * buf_fullp (buf) * * Test for fullness of buffer */ buf_fullp (buf) struct ring_buf *buf; { return (((buf->putter + 1) % buf->size) == buf->taker); } >>>>>>>> BUF.H /* * BUF.H * * Copyright (C) 1984 by Larry Campbell, 73 Concord St., Maynard Mass. * * This software may be freely copied and disseminated for * noncommercial purposes, if and only if this entire copyright * statement and notice is included intact. This software, and * the information contained herein, may not be used for commercial * purposes without my prior written permission. * * Ring buffer definitions * */ struct ring_buf { int size; char *cdata; int putter; int taker; }; >>>>>>>> BYTES.H /* * \usr\rainbow\bytes.h * * C definitions of RAM locations and constants used by * DEC Rainbow 100 firmware. Generated more or less mechanically * from BYTES.LST, which is generated from BYTES.A86, part * of the firmware source. All symbols are of the form * ROM_xxxxxx, where xxxxxx is the symbol name used in the * firmware source. Dollar signs are replaced with underscores, * since C doesn't like dollar signs in identifiers. * * source: BYTES.A86 version X00-09, December 19, 1983. * This file generated March 18, 1984. */ #define ROM_A_VTAD 0x0007 #define ROM_AABYTE 0x1EC0 #define ROM_ACK 0x0006 #define ROM_ACRPT1 0x1004 #define ROM_ACRPTR 0x1003 #define ROM_AILLIN 0x1000 #define ROM_ALLUPS 0x00B3 #define ROM_ALTROM 0x0003 #define ROM_ALTSPC 0x0004 #define ROM_ALTSTD 0x0003 #define ROM_ANSI 0x0001 #define ROM_ANYCHR 0x0008 #define ROM_APOSTR 0x0027 #define ROM_APTOFF 0x0000 #define ROM_APTON 0xFFFF #define ROM_AROMGR 0x0004 #define ROM_ARPCNT 0x0F69 #define ROM_ARPENA 0x0040 #define ROM_ARPFLG 0x0040 #define ROM_ARPKEY 0x0F6A #define ROM_ASBCUR 0x0080 #define ROM_ASBLHI 0x0ED5 #define ROM_ASBLNK 0x0EC5 #define ROM_ASBYTE 0x0EC1 #define ROM_ASCCAN 0x0018 #define ROM_ASCCR 0x000D #define ROM_ASCESC 0x001B #define ROM_ASCII 0x0000 #define ROM_ASCLF 0x000A #define ROM_ASCSP 0x0020 #define ROM_ASCSUB 0x001A #define ROM_ASCTLD 0x007E #define ROM_ATRIBS 0x0F40 #define ROM_ATROFS 0x1000 #define ROM_AUTFRE 0x1EE3 #define ROM_AUTOIN 0x00C1 #define ROM_AUTOPF 0x0ED6 #define ROM_AUTREP 0x0001 #define ROM_AUTUOF 0x00D9 #define ROM_AVTADD 0x1ECF #define ROM_BACKSP 0x0008 #define ROM_BEL 0x0007 #define ROM_BIT0 0x0001 #define ROM_BIT1 0x0002 #define ROM_BIT10 0x0400 #define ROM_BIT11 0x0800 #define ROM_BIT12 0x1000 #define ROM_BIT13 0x2000 #define ROM_BIT14 0x4000 #define ROM_BIT15 0x8000 #define ROM_BIT2 0x0004 #define ROM_BIT3 0x0008 #define ROM_BIT4 0x0010 #define ROM_BIT5 0x0020 #define ROM_BIT6 0x0040 #define ROM_BIT7 0x0080 #define ROM_BIT8 0x0100 #define ROM_BIT9 0x0200 #define ROM_BLANK 0x0002 #define ROM_BLINK 0x0004 #define ROM_BLKCNT 0x003F #define ROM_BLOB 0x0002 #define ROM_BOTTOM 0x0F59 #define ROM_BREAK 0x00E7 #define ROM_BRKCNT 0x0F91 #define ROM_BRKDET 0x0040 #define ROM_BRKIPR 0x0020 #define ROM_BRX1 0x0001 #define ROM_BRX16 0x0002 #define ROM_BRX64 0x0003 #define ROM_BUFCNT 0x0FB3 #define ROM_BUFEMP 0x0FB5 #define ROM_BUFSPA 0x0F6C #define ROM_C_URLE 0x000A #define ROM_C_URSO 0x000D #define ROM_C132VC 0x0010 #define ROM_C9600 0x000E #define ROM_CAN 0x0018 #define ROM_CAPSLK 0x0008 #define ROM_CARR 0x000D #define ROM_CBLINK 0x0ED7 #define ROM_CCCHAD 0x0ED8 #define ROM_CHARCN 0x0F93 #define ROM_CHARPL 0x0050 #define ROM_CHAR_P 0x0040 #define ROM_CHBLNK 0x0ECB #define ROM_CHR132 0x0084 #define ROM_CHRDIR 0x0002 #define ROM_CHRSET 0x0F38 #define ROM_CLICON 0x0001 #define ROM_CLRLSB 0x0000 #define ROM_CLRMSB 0x0004 #define ROM_CLRSIZ 0x005B #define ROM_CLRVFI 0x0009 #define ROM_CLUSTE 0x0001 #define ROM_CNTABL 0x0EC5 #define ROM_CNTRL 0x0004 #define ROM_CNTRLM 0x001F #define ROM_COL132 0x0001 #define ROM_COL80 0x0000 #define ROM_COM1ST 0x0FEB #define ROM_COMMA 0x00D2 #define ROM_COMPLE 0x0082 #define ROM_COMPOS 0x0084 #define ROM_COMPOS 0x0020 #define ROM_COMP_I 0x0008 #define ROM_COMREQ 0x0FE5 #define ROM_COMSTM 0x0FE6 #define ROM_COMTM3 0x0FE9 #define ROM_CONCHR 0x0020 #define ROM_CRLFON 0x0001 #define ROM_CSRATR 0x0EDA #define ROM_CSRCNT 0x0F2B #define ROM_CSRCOL 0x0F41 #define ROM_CSRFLG 0x0F2C #define ROM_CSRLIN 0x0F42 #define ROM_CSRPOS 0x0F41 #define ROM_CSRTYP 0x0F2D #define ROM_CTBLK 0x1EC8 #define ROM_CURLEN 0x1ED2 #define ROM_CURLIN 0x0F43 #define ROM_CURSET 0x0002 #define ROM_CURSOR 0x1ED5 #define ROM_D_YNMS 0x000B #define ROM_DARROW 0x00AB #define ROM_DB5 0x0000 #define ROM_DB6 0x0004 #define ROM_DB7 0x0008 #define ROM_DB8 0x000C #define ROM_DBELCT 0x0EC9 #define ROM_DC1 0x0011 #define ROM_DC2 0x0012 #define ROM_DC3 0x0013 #define ROM_DC4 0x0014 #define ROM_DEBASB 0x0000 #define ROM_DEBMOD 0x0000 #define ROM_DEBSTK 0x0000 #define ROM_DEBUG 0x0000 #define ROM_DEBVFR 0x0000 #define ROM_DEL 0x007F #define ROM_DELCHR 0x007F #define ROM_DHBATR 0x0000 #define ROM_DHTATR 0x0004 #define ROM_DIAGTS 0x0010 #define ROM_DISBEL 0x00A1 #define ROM_DISCLI 0x0099 #define ROM_DISCNT 0x00B9 #define ROM_DISFRE 0x1EDD #define ROM_DISPOS 0x1EDB #define ROM_DLE 0x0010 #define ROM_DLY133 0x0008 #define ROM_DO 0x0083 #define ROM_DOUBCO 0x0023 #define ROM_DOUBW 0x0008 #define ROM_DP7S 0x0004 #define ROM_DPCHAR 0x0000 #define ROM_DPMOD 0x0001 #define ROM_DRKBCK 0x000B #define ROM_DSKHMF 0x0012 #define ROM_DSKRDF 0x0013 #define ROM_DSKWRF 0x0014 #define ROM_DSR 0x0080 #define ROM_DTR 0x0002 #define ROM_DTREVR 0x0010 #define ROM_DTRNOW 0x0008 #define ROM_DWATR 0x0002 #define ROM_DYNMSG 0x1ED3 #define ROM_EH 0x0080 #define ROM_EM 0x0019 #define ROM_ENABEL 0x0023 #define ROM_ENACLI 0x001B #define ROM_ENACNT 0x00BB #define ROM_ENQ 0x0005 #define ROM_ENTER 0x00D8 #define ROM_EOT 0x0004 #define ROM_ER 0x0010 #define ROM_ERASE 0x00A1 #define ROM_ERRCOD 0x0040 #define ROM_ERROR 0x00B5 #define ROM_ERRSTA 0x0038 #define ROM_ESCAPE 0x001B #define ROM_ESCBFR 0x0002 #define ROM_ESCINP 0x0EDB #define ROM_ESCPTR 0x0EDC #define ROM_ESCSTR 0x0FB7 #define ROM_ESD 0x0040 #define ROM_ETB 0x0017 #define ROM_ETX 0x0003 #define ROM_EXITTS 0x0080 #define ROM_F10 0x0091 #define ROM_F14 0x0093 #define ROM_F17 0x0095 #define ROM_F18 0x0097 #define ROM_F19 0x0099 #define ROM_F20 0x009B #define ROM_F4 0x0087 #define ROM_F6 0x0089 #define ROM_F7 0x008B #define ROM_F8 0x008D #define ROM_F9 0x008F #define ROM_FALSE 0xFF00 #define ROM_FCNFLG 0x0001 #define ROM_FDXA 0x0000 #define ROM_FE 0x0020 #define ROM_FF 0x000C #define ROM_FILLIN 0x0000 #define ROM_FILLN1 0x0001 #define ROM_FIRST 0x0F94 #define ROM_FLASH 0x0001 #define ROM_FLGPRT 0x0F66 #define ROM_FLSHEN 0x0002 #define ROM_FNCLMT 0x0024 #define ROM_FOUR 0x0004 #define ROM_FS 0x001C #define ROM_G0 0x0F39 #define ROM_G1 0x0F3A #define ROM_GCSR 0x0002 #define ROM_GCSRC 0x1EE5 #define ROM_GRAF52 0x00FF #define ROM_GRAFIX 0x0002 #define ROM_GS 0x001D #define ROM_HELP 0x0082 #define ROM_HOLD 0x0080 #define ROM_HOLDLE 0x0088 #define ROM_HT 0x0009 #define ROM_HYPHEN 0x00CF #define ROM_HZ50 0x0033 #define ROM_HZ501 0x0009 #define ROM_HZ502 0x000C #define ROM_HZ503 0x000F #define ROM_HZ60 0x0022 #define ROM_INERR 0x00B6 #define ROM_INHIBX 0x0089 #define ROM_INSERT 0x009D #define ROM_INTZ80 0x0000 #define ROM_IR 0x0040 #define ROM_JMPTST 0x00CB #define ROM_K_AMER 0x0000 #define ROM_K_BRIT 0x0000 #define ROM_K_CANA 0x0001 #define ROM_K_DANI 0x0000 #define ROM_K_DUTC 0x0000 #define ROM_K_FINN 0x0000 #define ROM_K_FLEM 0x0000 #define ROM_K_FREN 0x0001 #define ROM_K_GERM 0x0002 #define ROM_K_ITAL 0x0000 #define ROM_K_NORW 0x0000 #define ROM_K_SPAN 0x0000 #define ROM_K_SWED 0x0000 #define ROM_K_SWIS 0x0001 #define ROM_K_SWIS 0x0002 #define ROM_K1 0x0001 #define ROM_K10 0x0008 #define ROM_K100H 0x0100 #define ROM_K10D 0x000A #define ROM_K10H 0x0010 #define ROM_K11 0x0009 #define ROM_K11D 0x000B #define ROM_K12 0x000A #define ROM_K12D 0x000C #define ROM_K13 0x000B #define ROM_K13D 0x000D #define ROM_K14 0x000C #define ROM_K14D 0x000E #define ROM_K15 0x000D #define ROM_K15D 0x000F #define ROM_K16 0x000E #define ROM_K16D 0x0010 #define ROM_K17 0x000F #define ROM_K18D 0x0012 #define ROM_K19D 0x0013 #define ROM_K2 0x0002 #define ROM_K20D 0x0014 #define ROM_K20H 0x0020 #define ROM_K23D 0x0017 #define ROM_K24D 0x0018 #define ROM_K254D 0x00FE #define ROM_K3 0x0003 #define ROM_K30H 0x0030 #define ROM_K37Q 0x001F #define ROM_K4 0x0004 #define ROM_K5 0x0005 #define ROM_K6 0x0006 #define ROM_K60 0x0030 #define ROM_K7 0x0007 #define ROM_K7000 0x7000 #define ROM_K80H 0x0080 #define ROM_K8D 0x0008 #define ROM_K8H 0x0008 #define ROM_K9D 0x0009 #define ROM_K9H 0x0009 #define ROM_KAH 0x000A #define ROM_KBDFAI 0x003E #define ROM_KBDFLG 0x0F90 #define ROM_KBDID 0x1FFB #define ROM_KBDLCK 0x00B7 #define ROM_KBH 0x000B #define ROM_KBRKCT 0x0ECF #define ROM_KCH 0x000C #define ROM_KDH 0x000D #define ROM_KEH 0x000E #define ROM_KEY0 0x00B1 #define ROM_KEY1 0x00B4 #define ROM_KEY2 0x00B7 #define ROM_KEY3 0x00BA #define ROM_KEY4 0x00BD #define ROM_KEY5 0x00C0 #define ROM_KEY6 0x00C3 #define ROM_KEY7 0x00C6 #define ROM_KEY8 0x00C9 #define ROM_KEY9 0x00CC #define ROM_KEYCNT 0x0F67 #define ROM_KEYEND 0x0F66 #define ROM_KEYFLG 0x1FF9 #define ROM_KEYMOD 0x0001 #define ROM_KEYREQ 0x0FE8 #define ROM_KEYS 0x0F5A #define ROM_KEYSFU 0x0009 #define ROM_KEYSIZ 0x000C #define ROM_KFFH 0x00FF #define ROM_KFH 0x000F #define ROM_KLEDOF 0x0011 #define ROM_KLEDON 0x0013 #define ROM_KPDMSK 0x003F #define ROM_KPRTCT 0x0EC7 #define ROM_KYBDCS 0x0011 #define ROM_KYBDDR 0x0010 #define ROM_KYDOWN 0x003D #define ROM_L_DANI 0x0040 #define ROM_L_DUTC 0x0008 #define ROM_L_ENGL 0x0001 #define ROM_L_FINN 0x0200 #define ROM_L_FREN 0x0002 #define ROM_L_GERM 0x0004 #define ROM_L_ITAL 0x0080 #define ROM_L_NORW 0x0010 #define ROM_L_SPAN 0x0100 #define ROM_L_SWED 0x0020 #define ROM_LANG_C 0x0003 #define ROM_LANG_I 0x0007 #define ROM_LANG_M 0x001F #define ROM_LANLEN 0x0F37 #define ROM_LARROW 0x00AF #define ROM_LASTPT 0x0006 #define ROM_LATINC 0x0F2E #define ROM_LATOFD 0x0F24 #define ROM_LATOFS 0x0EF4 #define ROM_LATOFU 0x0EF2 #define ROM_LBSTER 0x001E #define ROM_LCKKYB 0x0080 #define ROM_LCKYBD 0x0080 #define ROM_LINATR 0x0EBF #define ROM_LINC 0x0F26 #define ROM_LINEAD 0x0F27 #define ROM_LINEF 0x000A #define ROM_LINES 0x0019 #define ROM_LINKIN 0x0010 #define ROM_LITBCK 0x000A #define ROM_LNKPND 0x0008 #define ROM_LNLC1 0x1ED7 #define ROM_LNLC2 0x1ED9 #define ROM_LOKESC 0x0009 #define ROM_LONIBB 0x000F #define ROM_M_AJFL 0x0000 #define ROM_M_INBA 0x0005 #define ROM_M_INFL 0x0001 #define ROM_M_INMA 0x0004 #define ROM_MAINTP 0x000A #define ROM_MAJFLD 0x1EC8 #define ROM_MARK 0x00A3 #define ROM_MAXCPF 0x0014 #define ROM_MBENB 0x0004 #define ROM_METRO 0x00AD #define ROM_MINBAS 0x1ECD #define ROM_MINFLD 0x1EC9 #define ROM_MINMAX 0x1ECC #define ROM_MNONE 0x0000 #define ROM_MOD173 0x005E #define ROM_MOD200 0x004E #define ROM_MODFGS 0x0F8F #define ROM_MOVE 0x009F #define ROM_MSGFLG 0x0FCF #define ROM_MSGSNT 0x0080 #define ROM_MSGSTR 0x0FD0 #define ROM_MSTAT 0x0F44 #define ROM_MTPRTC 0x1EE6 #define ROM_M_BRK 0x005A #define ROM_M_COMP 0x00B1 #define ROM_M_DEL 0x00BC #define ROM_M_ENTE 0x0095 #define ROM_M_ESC 0x0071 #define ROM_M_F4 0x0059 #define ROM_M_HOLD 0x0056 #define ROM_M_LOCK 0x00B0 #define ROM_M_RET 0x00BD #define ROM_M_SETU 0x0058 #define ROM_M_TAB 0x00BE #define ROM_M_UP 0x00AA #define ROM_N_OTCU 0x000E #define ROM_N_VMAD 0x0002 #define ROM_N_VMMA 0x0009 #define ROM_NAK 0x0015 #define ROM_NBRPAR 0x0EDE #define ROM_NBRUSE 0x0EDF #define ROM_NEXT 0x00A7 #define ROM_NOATR 0x000E #define ROM_NOCODE 0x00FF #define ROM_NORM52 0x0000 #define ROM_NOTCUR 0x1ED6 #define ROM_NOTKBD 0x0FED #define ROM_NSTP1 0x0040 #define ROM_NSTP15 0x0080 #define ROM_NSTP2 0x00C0 #define ROM_NULL 0x0000 #define ROM_NVMADD 0x1ECA #define ROM_NVMMAX 0x1ED1 #define ROM_NVMMSK 0x000F #define ROM_NXTKEY 0x0FCD #define ROM_OCSCOL 0x0F29 #define ROM_OCSLIN 0x0F2A #define ROM_OCSPOS 0x0F29 #define ROM_OE 0x0010 #define ROM_OLDGX 0x0F36 #define ROM_ONE 0x0001 #define ROM_ONEPAR 0x0080 #define ROM_ONLINE 0x0000 #define ROM_ORGMOD 0x0001 #define ROM_OUTBUF 0x0F95 #define ROM_OUTERR 0x00B5 #define ROM_OUTND 0x001E #define ROM_P300 0x0002 #define ROM_P5016 0x0006 #define ROM_PARFGS 0x0F2F #define ROM_PARM0 0x0EE0 #define ROM_PARM1 0x0EE1 #define ROM_PCMFLG 0x0F54 #define ROM_PCMOFF 0x0000 #define ROM_PCMON 0xFFFF #define ROM_PCMSTM 0x0F55 #define ROM_PE 0x0008 #define ROM_PEN 0x0010 #define ROM_PERIOD 0x00D5 #define ROM_PEVEN 0x0020 #define ROM_PF1 0x00DB #define ROM_PF2 0x00DE #define ROM_PF3 0x00E1 #define ROM_PF4 0x00E4 #define ROM_PODD 0x0000 #define ROM_PORT0 0x0000 #define ROM_PREV 0x00A5 #define ROM_PRIOR 0x0004 #define ROM_PRNKEY 0x0085 #define ROM_PROTCT 0x0ED1 #define ROM_PROUTE 0x0009 #define ROM_PWRCNT 0x0F92 #define ROM_PWRGOO 0x0008 #define ROM_PWRIPR 0x0002 #define ROM_PWRREQ 0x00FD #define ROM_RARROW 0x00AD #define ROM_RAWBFI 0x0F6F #define ROM_RAWBFO 0x0F6D #define ROM_RAWEND 0x0F8F #define ROM_RAWKEY 0x0F71 #define ROM_RAWSIZ 0x000E #define ROM_REINDE 0x00D3 #define ROM_REINKY 0x00B3 #define ROM_REMAPV 0x0004 #define ROM_REQKYI 0x00AB #define ROM_RESERV 0x00FF #define ROM_RESETP 0x0D41 #define ROM_RESUMX 0x008B #define ROM_REVBIT 0x0001 #define ROM_REVVID 0x000D #define ROM_RIGHT 0x0F57 #define ROM_RMODEM 0x0FEE #define ROM_RS 0x001E #define ROM_RTS 0x0020 #define ROM_RXEN 0x0004 #define ROM_RXRDY 0x0002 #define ROM_SAMRT1 0x003C #define ROM_SAVATR 0x1EC4 #define ROM_SAVCP 0x0F4F #define ROM_SAVCR 0x0F38 #define ROM_SAVCRL 0x000E #define ROM_SAVEND 0x0F46 #define ROM_SAVLNK 0x1EC6 #define ROM_SAWCSI 0x000C #define ROM_SBASE 0x1FF7 #define ROM_SBCONH 0x000B #define ROM_SBCONS 0x25E0 #define ROM_SBOT 0x1EFA #define ROM_SBRK 0x0008 #define ROM_SBRKCT 0x0ED3 #define ROM_SCAN_T 0x0010 #define ROM_SCRATR 0x0007 #define ROM_SCRBEG 0x0012 #define ROM_SCRCTR 0x0F30 #define ROM_SCRDWN 0x0001 #define ROM_SCRFLG 0x000C #define ROM_SCRFRE 0x0D41 #define ROM_SCRINP 0x0004 #define ROM_SCRN50 0x0009 #define ROM_SCRPT1 0x0004 #define ROM_SCRPTR 0x0003 #define ROM_SCS 0x0080 #define ROM_SETDIS 0x007F #define ROM_SETIPR 0x0004 #define ROM_SETKEY 0x0002 #define ROM_SETUF 0x0001 #define ROM_SETUP 0x0081 #define ROM_SHFAD1 0x1EEA #define ROM_SHFAD2 0x1EEE #define ROM_SHFDT1 0x1EEC #define ROM_SHFDT2 0x1EF0 #define ROM_SHFIN 0x0000 #define ROM_SHFLA2 0x1EF2 #define ROM_SHFOUT 0x00FF #define ROM_SHFPND 0x0002 #define ROM_SHFTIN 0x000F #define ROM_SHFTLE 0x0084 #define ROM_SHIFT 0x0002 #define ROM_SHLINE 0x0017 #define ROM_SHSW 0x0006 #define ROM_SIGER 0x1FFA #define ROM_SILOK 0x0001 #define ROM_SILOS 0x1EE7 #define ROM_SISO 0x0F3C #define ROM_SLORAT 0x001E #define ROM_SMODE 0x0000 #define ROM_SMSCNT 0x0ECD #define ROM_SMSRAT 0x1EE8 #define ROM_SMTHSC 0x1EF5 #define ROM_SNDBEL 0x00A7 #define ROM_SNDCLI 0x009F #define ROM_SNDPWR 0x0004 #define ROM_SO 0x000E #define ROM_SOH 0x0001 #define ROM_SPCGRC 0x0002 #define ROM_SPSAV 0x1FF7 #define ROM_SRTCUR 0x0002 #define ROM_SSFLG 0x0F3B #define ROM_STATER 0x0040 #define ROM_STKFLG 0x1EF6 #define ROM_STKLEN 0x00FD #define ROM_STKSWP 0x0001 #define ROM_STPCUR 0x0001 #define ROM_STRINX 0x0FCC #define ROM_STRZ80 0x0020 #define ROM_STX 0x0002 #define ROM_SUACPD 0x1EF9 #define ROM_SUB 0x001A #define ROM_SVAREA 0x0F46 #define ROM_SWVFRE 0x1EE1 #define ROM_SWVPOS 0x1EDF #define ROM_SYN 0x0016 #define ROM_SYNDET 0x0040 #define ROM_SYPAR1 0x1FFC #define ROM_SYSPAR 0x1FFE #define ROM_TERM 0x00FF #define ROM_TERMOD 0x1EF8 #define ROM_THREE 0x0003 #define ROM_TILDE 0x00BF #define ROM_TOGHLD 0x0008 #define ROM_TOP 0x0F58 #define ROM_TRMMOD 0x0001 #define ROM_TRUE 0x00FF #define ROM_TSTMOD 0x00B8 #define ROM_TWO 0x0002 #define ROM_TXEMPT 0x0004 #define ROM_TXEN 0x0001 #define ROM_TXLOCK 0x0002 #define ROM_TXRDY 0x0001 #define ROM_UARROW 0x00A9 #define ROM_UCOFF 0x003E #define ROM_UK 0x0001 #define ROM_UKLANG 0x0001 #define ROM_UNUSED 0x00FF #define ROM_US 0x001F #define ROM_USEIT 0x0F3E #define ROM_VDCTRL 0x000C #define ROM_VFRATE 0x0023 #define ROM_VFRIPF 0x0002 #define ROM_VIDCTL 0x010C #define ROM_VIDTIM 0x0004 #define ROM_VOL1 0x0007 #define ROM_VOL2 0x0006 #define ROM_VOL3 0x0005 #define ROM_VOL4 0x0004 #define ROM_VOL5 0x0003 #define ROM_VOL6 0x0002 #define ROM_VOL7 0x0001 #define ROM_VOL8 0x0000 #define ROM_VT 0x000B #define ROM_VT52GM 0x0F45 #define ROM_WAITLE 0x0081 #define ROM_WID80 0x0000 #define ROM_WRPPND 0x0002 #define ROM_XLINBR 0x0F33 #define ROM_XMTRCV 0x0FEC #define ROM_XTRA 0x0F31 #define ROM_XTRATR 0x1EF4 #define ROM_X_OFF 0x0F6B #define ROM_Z80ORI 0x0F35 #define ROM_Z80RUN 0x0001 #define ROM_Z80STP 0x0000 #define ROM_Z80TAS 0x0F34 #define ROM_ZERO 0x0000 >>>>>>>> DOSERROR.C /* * DOSERROR.C * * Copyright (C) 1984 by Larry Campbell, 73 Concord St., Maynard Mass. * * This software may be freely copied and disseminated for * noncommercial purposes, if and only if this entire copyright * statement and notice is included intact. This software, and * the information contained herein, may not be used for commercial * purposes without my prior written permission. * * char *dos_error (error_num) * * Return address of string describing an MS-DOS error code * (useful only for Xenix-style calls, CP/M-style calls have * different error codes) */ static char ebuf[40]; char *dos_error (error_num) int error_num; { switch (error_num) { case 1: return ("invalid function"); case 2: return ("file not found"); case 3: return ("path not found"); case 4: return ("too many open files"); case 5: return ("access denied"); case 6: return ("invalid handle"); case 7: return ("arena trashed"); case 8: return ("not enough memory"); case 9: return ("invalid block"); case 10: return ("bad environment"); case 11: return ("bad format for EXE file"); case 12: return ("invalid access"); case 13: return ("invalid data"); case 15: return ("invalid drive"); case 16: return ("can't remove current directory"); case 17: return ("can't rename across devices"); case 18: return ("no more files"); default: sprintf (ebuf, "unknown error code %d", error_num); return (ebuf); }; } >>>>>>>> DOSFUN.ASM ; \usr\dos\dosfun.asm ; ; Various routines to call generic MS-DOS functions for C programs. ; ; Copyright (C) 1984 by Larry Campbell, 73 Concord St., Maynard, Mass. USA ; ; This software may be freely copied and disseminated for ; noncommercial purposes, if and only if this entire copyright ; statement and notice is included intact. This software, and ; the information contained herein, may not be used for commercial ; purposes without my prior written permission. ; get_date equ 2AH get_time equ 2CH break equ 33H dos macro call_number mov ah,call_number int 21H endm include \ubin\c86\v210\model.h include \ubin\c86\v210\prologue.h public get_break, set_break public tod_hours, tod_minutes, tod_seconds public toy_year, toy_month, toy_date, toy_dow set_break: push bp mov bp,sp mov al,1 ;"set" function mov dl,4[bp] ;get state to set dos break pop bp ret get_break: mov al,0 ;"get" function dos break mov al,dl mov ah,0 ret tod_hours: dos get_time mov al,ch mov ah,0 ret tod_minutes: dos get_time mov al,cl mov ah,0 ret tod_seconds: dos get_time mov al,dh mov ah,0 ret toy_year: dos get_date mov ax,cx ret toy_month: dos get_date mov al,dh mov ah,0 ret toy_date: dos get_date mov al,dl mov ah,0 ret toy_dow: dos get_date mov ah,0 ret include \ubin\c86\v210\epilogue.h end >>>>>>>> ENVFETCH.C #define CPEEK(off,seg) ((unsigned char) peek (off, seg)) /* * env_fetch (name, envseg, dest) * * Search environment at segment address for variable named and * if found store value of variable at dest. Return true (nonzero) * if found. */ env_fetch (name, envseg, dest) char *name, *dest; unsigned int envseg; { unsigned int envoff; char c, *dp, leftpart[132]; envoff = 0; /* starting environment offset */ dp = leftpart; while (1) { c = CPEEK (envoff++, envseg); switch (c) { case '=': *dp = 0; /* make ASCIZ */ if (strcmp (leftpart, "COMSPEC") == 0) { dp = dest; while (*dp++ = CPEEK (envoff++, envseg)); return (1); }; while (CPEEK (envoff++, envseg)); /* skip to end */ dp = leftpart; /* reset destination pointer */ break; case 0: if (CPEEK (envoff + 1, envseg) == 0) return (0); dp = leftpart; break; default: *dp++ = c; }; }; } >>>>>>>> HARDWARE.ASM ; \usr\rainbow\hardware.asm ; ; Copyright (C) 1984 by Larry Campbell, 73 Concord St., Maynard, Mass. USA ; ; This software may be freely copied and disseminated for ; noncommercial purposes, if and only if this entire copyright ; statement and notice is included intact. This software, and ; the information contained herein, may not be used for commercial ; purposes without my prior written permission. ; ; This file provides various routines to interface with the ; the hardware on a DEC Rainbow 100. The routines which ; manipulate AUX (comm port) require MS-DOS version 2.05 ; or later, which has the new BIOS which supports all this. ; This code has not been tested on a 100+, but probably will work. aux_input equ 3 aux_output equ 4 io_control equ 44H dos macro call_number mov ah,call_number int 21H endm include \ubin\c86\v210\model.h include \ubin\c86\v210\prologue.h public _put_line, _putattr, getkey, getaux, putaux public disable_cursor, enable_cursor, auxctl public aux_hungry, putcon, auxres ; _put_line (row, col, length, string) _put_line: push bp mov bp,sp mov ax,2 ;chars only, no attributes mov bl,4[bp] ;row mov bh,6[bp] ;col mov cx,8[bp] ;byte count mov si,10[bp] ;char offset mov di,14H ;function code mov bp,ds ;for ROM code int 18H ;write to screen pop bp ret ; _putattr (row, col, length, attribute) _putattr: push bp mov bp,sp mov di,8 int 18H ;disable cursor mov ax,1 ;attributes only mov bl,BYTE PTR 4[bp] ;row mov bh,BYTE PTR 6[bp] ;col mov cx,8[bp] ;byte count mov dx,10[bp] ;attributes offset mov di,14H ;function code mov bp,ds ;for ROM code int 18H ;write to screen mov di,0AH ;reenable cursor int 18H pop bp ret disable_cursor: mov di,8 int 18H ret enable_cursor: mov di,0AH int 18H ret ;Read keyboard - return -1 if no char available, -2 if level 2 sequence ; in progress, otherwise return (16-bit extended ASCII) character getkey: mov di,6 int 18H ;get char and status cmp cl,0FFH ;char available? je getkey_0 ;yes, return it mov ax,0FFFFH ;no, return -1 cmp cl,0 ;if no char available je getkey_0 ; .. mov ax,0FFFEH ;otherwise return -2 getkey_0: ret ;Put character out to console (must bypass DOS to avoid ctrl-C monkeying ; and have any speed left) putcon: push bp mov bp,sp mov di,0 mov al,4[bp] int 18H pop bp ret ;Reset AUX (comm port) to NVM settings auxres: push bp mov al,2 ;IOCTL fancy stuff mov auxfun,1 ;function code (reset to NVM settings) mov bx,3 ;AUX device mov dx,OFFSET auxfun ;addr of IOCTL packet dos io_control ;do it pop bp ret ; auxctl (buffer) ; char *buffer ; ; General IOCTL interface to BIOS (requires DOS v2.05 or later) ; auxctl: push bp mov bp,sp ;stack frame mov al,2 ;function code mov bx,3 ;builtin AUX handle mov dx,4[bp] ;get caller's buffer address dos io_control ;call the BIOS pop bp ret ;Read AUX (comm port), return -1 if no char available, else char getaux: push bp mov al,2 ;IOCTL function mov bx,3 ;AUX handle mov dx,OFFSET auxfun ;IOCTL packet address in DS:DX mov auxfun,7 ;Get char or FF if none there dos io_control ; .. cmp auxret,0FFH ;char available? jne noaux ;no mov al,auxchr ;yes, return char mov ah,0 ;zero high-order byte pop bp ret noaux: mov ax,0FFFFH pop bp ret putaux: push bp mov bp,sp mov al,2 ;IOCTL function mov bx,3 ;AUX handle mov dx,OFFSET auxfun ;IOCTL packet address in DS:DX mov auxfun,10 ;Put char (nonblocking) function mov cl,4[bp] ;Char to send mov auxchr,cl dos io_control ; .. mov al,auxret ;Return success/failure code to caller mov ah,0 pop bp ret aux_hungry: push bp mov al,2 ;IOCTL function mov bx,3 ;AUX handle mov dx,OFFSET auxfun ;IOCTL packet address in DS:DX mov auxfun,9 ;Read transmitter status dos io_control ; .. mov al,auxret ;Return status to caller mov ah,0 pop bp ret nothungry: mov ax,0 pop bp ret include \ubin\c86\v210\epilogue.h @datab segment ;AUX IOCTL packet (requires MS-DOS v2.05) auxfun db (?) auxret db (?) auxchr db (?) auxsts db (?) auxbuf db (?) @datab ends end >>>>>>>> KERMIT.C #include #include "kermit.h" /* * KERMIT.C * * KERMIT protocol routines * * Adapted from: * * UNIX Kermit, Columbia University, 1981, 1982, 1983 * Bill Catchings, Bob Cattani, Chris Maio, Frank da Cruz, Alan Crosswell * * * EXTERNAL INTERFACE: * * INITIALIZE PROTOCOL MODULE (must be called before using protocol) * kerini(); * * SENDING FILES * filnam = "filespec"; sendsw(); * * RECEIVING FILES * filnam = "filespec"; recsw(); * * SERVER COMMANDS * sendcmdsw('char',"cmd") * * The following external routines must be supplied: * * char read_modem () gets char from modem (blocking) * write_modem (char *s, int count) writes string to modem * flushinput () empty modem input buffer * printmsg (char *s) writes message to screen * notify_hook () called when packets leave or arrive to * give a hook for displaying stats on * screen */ #define COUNTED_STRING(s) strlen(s),s /* Global Variables */ int size, /* Size of present data */ rpsiz, /* Maximum receive packet size */ spsiz, /* Maximum send packet size */ pad, /* How much padding to send */ timint, /* Timeout for foreign host on sends */ n, /* Packet number */ numtry, /* Times this packet retried */ oldtry, /* Times previous packet retried */ maxtry, /* Maximum number of times to retry */ packets_sent, /* Packets sent */ packets_received, /* packets received */ bad_packets, /* packets received with checksum errors */ naked_packets, /* packets naked by other end */ remote, /* -1 means we're a remote kermit */ image, /* -1 means 8-bit mode */ binary, /* Nonzero => binary files ("wb" or "rb" fopen) */ quote_8bit, /* Nonzero => 8th-bit quoting */ debug, /* indicates level of debugging output (0=none) */ filnamcnv, /* -1 means do file name case conversions */ filecount; /* Number of files left to send */ long bytes_xferred; char state, /* Present state of the automaton */ padchar, /* Padding character to send */ eol, /* End-Of-Line character to send */ quote_8bit_char, /* character to use for 8th-bit quoting */ quote, /* Quote character in incoming data */ **filelist, /* List of files to be sent */ *filnam, /* Current file name */ recpkt[MAXPACKSIZ], /* Receive packet buffer */ packet[MAXPACKSIZ]; /* Packet buffer */ FILE *fp; /* File pointer for current disk file */ jmp_buf abort_env, /* Transaction abort SETJMP buffer */ env; /* Timeout SETJMP buffer */ /* * k e r i n i * * Init protocol routines * */ kerini() { eol = CR; /* EOL for outgoing packets */ quote = MYQUOTE; /* Standard control-quote char "#" */ quote_8bit_char = MY8BITQUOTE; /* Standard 8th-bit quote char */ pad = 0; /* No padding */ binary = TRUE; /* Default is binary files */ quote_8bit = FALSE; /* Default is no 8th-bit quoting */ padchar = NULL; /* Use null if any padding wanted */ fp = NULL; /* File pointer */ timint = DEFTIM; /* Initial timeout value */ maxtry = MAXTRY; /* Initial retry counter value */ #if UCB4X /* Default to 7-bit masking, CRLF */ image = FALSE; /* translation and filename case */ filnamcnv = TRUE; /* conversion for UNIX systems */ #else image = TRUE; /* Default to no processing for */ filnamcnv = FALSE; /* non-UNIX systems */ #endif filecount = 1; /* One file at a time */ } /* * s e n d s w * * Sendsw is the state table switcher for sending files. It loops until * either it finishes, or an error is encountered. The routines called * by sendsw are responsible for changing the state. * */ sendsw() { char sinit(), sfile(), sdata(), seof(), sbreak(); if (setjmp(abort_env)) return(FALSE); if (debug) printf ("Entering sendsw\n"); state = 'S'; /* Send initiate is the start state */ n = 0; /* Initialize message number */ packets_sent = packets_received = 0;/* Initialize statistics */ bad_packets = naked_packets = 0; bytes_xferred = 0L; numtry = 0; /* Say no tries yet */ while(TRUE) /* Do this as long as necessary */ { if (debug) printf("sendsw state: %c\n",state); switch(state) { case 'S': state = sinit(); break; /* Send-Init */ case 'F': state = sfile(); break; /* Send-File */ case 'D': state = sdata(); break; /* Send-Data */ case 'Z': state = seof(); break; /* Send-End-of-File */ case 'B': state = sbreak(); break; /* Send-Break */ case 'C': return (TRUE); /* Complete */ case 'A': if (fp != NULL) fclose(fp); fp = NULL; return (FALSE); /* "Abort" */ default: if (fp != NULL) fclose(fp); fp = NULL; return (FALSE); /* Unknown, fail */ } } } /* * s i n i t * * Send Initiate: send this host's parameters and get other side's back. */ char sinit() { int num, len; /* Packet number, length */ if (numtry++ > maxtry) return('A'); /* If too many tries, give up */ spar(packet); /* Fill up init info packet */ spack('S',n,7,packet); /* Send my init info */ switch(rpack(&len,&num,recpkt)) /* What was the reply? */ { case 'N': naked_packets++; /* count NAKs */ notify_hook (); /* maybe diddle screen */ return(state); /* NAK, try it again */ case 'Y': /* ACK */ if (n != num) /* If wrong ACK, stay in S state */ return(state); /* and try again */ rpar(recpkt); /* Get other side's init info */ if (eol == 0) eol = '\n'; /* Check and set defaults */ if (quote == 0) quote = MYQUOTE; numtry = 0; /* Reset try counter */ n = (n+1)%64; /* Bump packet count */ return('F'); /* OK, switch state to F */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case FALSE: return(state); /* Receive failure, try again */ default: return('A'); /* Anything else, just "abort" */ } } /* * s f i l e * * Send File Header. */ char sfile() { int num, len; /* Packet number, length */ char filnam1[50], /* Converted file name */ *newfilnam, /* Pointer to file name to send */ *cp; /* char pointer */ if (numtry++ > maxtry) return('A'); /* If too many tries, give up */ if (fp == NULL) /* If not already open, */ { if (debug) printf(" Opening %s for sending.\n",filnam); if (binary) fp = fopen(filnam,"rb"); /* open the file to be sent */ else fp = fopen(filnam,"r"); if (fp == NULL) /* If bad file pointer, give up */ { error("Cannot open file %s",filnam); return('A'); } } strcpy(filnam1, filnam); /* Copy file name */ newfilnam = cp = filnam1; while (*cp != '\0') /* Strip off all leading directory */ { /* and device names */ char c; if ((c = *cp++) == '\\' || c == ':') newfilnam = cp; }; if (filnamcnv) /* Convert lower case to upper */ for (cp = newfilnam; *cp != '\0'; cp++) if (*cp >= 'a' && *cp <= 'z') *cp ^= 040; len = cp - newfilnam; /* Compute length of new filename */ printmsg("Sending %s as %s",filnam,newfilnam); spack('F',n,len,newfilnam); /* Send an F packet */ switch(rpack(&len,&num,recpkt)) /* What was the reply? */ { case 'N': /* NAK, just stay in this state, */ num = (--num<0 ? 63:num); /* unless it's NAK for next packet */ if (n != num) /* which is just like an ACK for */ { naked_packets++; notify_hook (); return(state); /* this packet so fall thru to... */ }; case 'Y': /* ACK */ if (n != num) return(state); /* If wrong ACK, stay in F state */ numtry = 0; /* Reset try counter */ n = (n+1)%64; /* Bump packet count */ size = bufill(packet); /* Get first data from file */ return('D'); /* Switch state to D */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case FALSE: return(state); /* Receive failure, stay in F state */ default: return('A'); /* Something else, just "abort" */ } } /* * s d a t a * * Send File Data */ char sdata() { int num, len; /* Packet number, length */ if (numtry++ > maxtry) return('A'); /* If too many tries, give up */ spack('D',n,size,packet); /* Send a D packet */ switch(rpack(&len,&num,recpkt)) /* What was the reply? */ { case 'N': /* NAK, just stay in this state, */ num = (--num<0 ? 63:num); /* unless it's NAK for next packet */ if (n != num) /* which is just like an ACK for */ { naked_packets++; notify_hook (); return(state); /* this packet so fall thru to... */ }; case 'Y': /* ACK */ if (n != num) return(state); /* If wrong ACK, fail */ numtry = 0; /* Reset try counter */ n = (n+1)%64; /* Bump packet count */ if ((size = bufill(packet)) == EOF) /* Get data from file */ return('Z'); /* If EOF set state to that */ return('D'); /* Got data, stay in state D */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case FALSE: return(state); /* Receive failure, stay in D */ default: return('A'); /* Anything else, "abort" */ } } /* * s e o f * * Send End-Of-File. */ char seof() { int num, len; /* Packet number, length */ if (numtry++ > maxtry) return('A'); /* If too many tries, "abort" */ spack('Z',n,0,packet); /* Send a 'Z' packet */ switch(rpack(&len,&num,recpkt)) /* What was the reply? */ { case 'N': /* NAK, just stay in this state, */ num = (--num<0 ? 63:num); /* unless it's NAK for next packet, */ if (n != num) /* which is just like an ACK for */ { naked_packets++; notify_hook (); return(state); /* this packet so fall thru to... */ }; case 'Y': /* ACK */ if (n != num) return(state); /* If wrong ACK, hold out */ numtry = 0; /* Reset try counter */ n = (n+1)%64; /* and bump packet count */ if (debug) printf(" Closing input file %s, ",filnam); fclose(fp); /* Close the input file */ fp = NULL; /* Set flag indicating no file open */ if (debug) printf("looking for next file...\n"); /* if (gnxtfl() == FALSE) */ /* No more files go? */ return('B'); /* if not, break, EOT, all done */ if (debug) printf(" New file is %s\n",filnam); return('F'); /* More files, switch state to F */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case FALSE: return(state); /* Receive failure, stay in Z */ default: return('A'); /* Something else, "abort" */ } } /* * s b r e a k * * Send Break (EOT) */ char sbreak() { int num, len; /* Packet number, length */ if (numtry++ > maxtry) return('A'); /* If too many tries "abort" */ spack('B',n,0,packet); /* Send a B packet */ switch (rpack(&len,&num,recpkt)) /* What was the reply? */ { case 'N': /* NAK, just stay in this state, */ num = (--num<0 ? 63:num); /* unless NAK for previous packet, */ if (n != num) /* which is just like an ACK for */ { naked_packets++; notify_hook (); return(state); /* this packet so fall thru to... */ }; case 'Y': /* ACK */ if (n != num) return(state); /* If wrong ACK, fail */ numtry = 0; /* Reset try counter */ n = (n+1)%64; /* and bump packet count */ return('C'); /* Switch state to Complete */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case FALSE: return(state); /* Receive failure, stay in B */ default: return ('A'); /* Other, "abort" */ } } /* * r e c s w * * This is the state table switcher for receiving files. */ recsw() { char rinit(), rfile(), rdata(); /* Use these procedures */ if (setjmp(abort_env)) return(FALSE); state = 'R'; /* Receive-Init is the start state */ n = 0; /* Initialize message number */ numtry = 0; /* Say no tries yet */ packets_sent = packets_received = 0;/* Initialize statistics */ bad_packets = naked_packets = 0; bytes_xferred = 0L; while(TRUE) { if (debug) printf(" recsw state: %c\n",state); switch(state) /* Do until done */ { case 'R': state = rinit(); break; /* Receive-Init */ case 'F': state = rfile(); break; /* Receive-File */ case 'D': state = rdata(); break; /* Receive-Data */ case 'C': return(TRUE); /* Complete state */ case 'A': if (fp != NULL) fclose(fp); fp = NULL; return(FALSE); /* "Abort" state */ } } } /* * r i n i t * * Receive Initialization */ char rinit() { int len, num; /* Packet length, number */ if (numtry++ > maxtry) return('A'); /* If too many tries, "abort" */ spack('R',n,strlen(filnam),filnam); /* Send "receive init" */ switch(rpack(&len,&num,recpkt)) /* Get a packet */ { case 'S': /* Send-Init */ rpar(recpkt,len); /* Get the other side's init data */ spar(packet); /* Fill up packet with my init info */ spack('Y',n,7,packet); /* ACK with my parameters */ oldtry = numtry; /* Save old try count */ numtry = 0; /* Start a new counter */ n = (n+1)%64; /* Bump packet number, mod 64 */ return('F'); /* Enter File-Receive state */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case 'N': /* NAK */ naked_packets++; notify_hook(); return(state); /* stay in this state */ case FALSE: /* Didn't get packet */ spack('N',n,0,0); /* Return a NAK */ return(state); /* Keep trying */ default: return('A'); /* Some other packet type, "abort" */ } } /* * r f i l e * * Receive File Header */ char rfile() { int num, len; /* Packet number, length */ char filnam1[50]; /* Holds the converted file name */ if (numtry++ > maxtry) return('A'); /* "abort" if too many tries */ switch(rpack(&len,&num,packet)) /* Get a packet */ { case 'S': /* Send-Init, maybe our ACK lost */ if (oldtry++ > maxtry) return('A'); /* If too many tries "abort" */ if (num == ((n==0) ? 63:n-1)) /* Previous packet, mod 64? */ { /* Yes, ACK it again with */ spar(packet); /* our Send-Init parameters */ spack('Y',num,7,packet); numtry = 0; /* Reset try counter */ return(state); /* Stay in this state */ } else return('A'); /* Not previous packet, "abort" */ case 'Z': /* End-Of-File */ if (oldtry++ > maxtry) return('A'); if (num == ((n==0) ? 63:n-1)) /* Previous packet, mod 64? */ { /* Yes, ACK it again. */ spack('Y',num,0,0); numtry = 0; return(state); /* Stay in this state */ } else return('A'); /* Not previous packet, "abort" */ case 'F': /* File Header (just what we want) */ if (num != n) return('A'); /* The packet number must be right */ strcpy(filnam1, packet); /* Copy the file name */ if (filnamcnv) /* Convert upper case to lower */ for (filnam=filnam1; *filnam != '\0'; filnam++) if (*filnam >= 'A' && *filnam <= 'Z') *filnam |= 040; if (fp != NULL) fclose (fp); if ((fp = fopen(filnam1,"r")) != NULL) { error("File %s already exists",filnam1); spack('E',n,COUNTED_STRING("File already exists")); fclose(fp); fp = NULL; return('A'); }; if (binary) fp = fopen(filnam1,"wb"); /* Try to open a new file */ else fp = fopen(filnam1,"w"); if (fp == NULL) { error("Cannot create %s",filnam1); return('A'); } else { #if MSDOS /* convert to uppercase, 8.3 length name */ int i; char c, *sp; char name[NAMELEN + 1], ext[EXTLEN + 1]; sp = filnam1; i = 0; while ((c = *sp++) && c != '.' && i < NAMELEN) name[i++] = toupper (c); name[i] = 0; if (c && (c != '.')) while ((c = *sp++) && c != '.') ; i = 0; if (c) while ((c = *sp++) && i < EXTLEN) ext[i++] = toupper (c); ext[i] = 0; printmsg("Receiving %s as %s.%s",packet,name,ext); #else printmsg("Receiving %s as %s",packet,filnam1); #endif }; spack('Y',n,0,0); /* Acknowledge the file header */ oldtry = numtry; /* Reset try counters */ numtry = 0; /* ... */ n = (n+1)%64; /* Bump packet number, mod 64 */ return('D'); /* Switch to Data state */ case 'B': /* Break transmission (EOT) */ if (num != n) return ('A'); /* Need right packet number here */ spack('Y',n,0,0); /* Say OK */ return('C'); /* Go to complete state */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case FALSE: /* Didn't get packet */ spack('N',n,0,0); /* Return a NAK */ return(state); /* Keep trying */ default: return ('A'); /* Some other packet, "abort" */ } } /* * r d a t a * * Receive Data */ char rdata() { int num, len; /* Packet number, length */ if (numtry++ > maxtry) return('A'); /* "abort" if too many tries */ switch(rpack(&len,&num,packet)) /* Get packet */ { case 'D': /* Got Data packet */ if (num != n) /* Right packet? */ { /* No */ if (oldtry++ > maxtry) return('A'); /* If too many tries, abort */ if (num == ((n==0) ? 63:n-1)) /* Else check packet number */ { /* Previous packet again? */ spack('Y',num,6,packet); /* Yes, re-ACK it */ numtry = 0; /* Reset try counter */ return(state); /* Don't write out data! */ }; bad_packets++; notify_hook(); return('A'); /* sorry, wrong number */ } /* Got data with right packet number */ if (! bufemp(packet,len)) { spack('E',n,COUNTED_STRING("Write failed (disk full?)")); error("Write failed (disk full?)"); return('A'); }; spack('Y',n,0,0); /* Acknowledge the packet */ oldtry = numtry; /* Reset the try counters */ numtry = 0; /* ... */ n = (n+1)%64; /* Bump packet number, mod 64 */ return('D'); /* Remain in data state */ case 'F': /* Got a File Header */ if (oldtry++ > maxtry) return('A'); /* If too many tries, "abort" */ if (num == ((n==0) ? 63:n-1)) /* Else check packet number */ { /* It was the previous one */ spack('Y',num,0,0); /* ACK it again */ numtry = 0; /* Reset try counter */ return(state); /* Stay in Data state */ } else return('A'); /* Not previous packet, "abort" */ case 'Z': /* End-Of-File */ if (num != n) return('A'); /* Must have right packet number */ spack('Y',n,0,0); /* OK, ACK it. */ fclose(fp); /* Close the file */ fp = NULL; n = (n+1)%64; /* Bump packet number */ return('F'); /* Go back to Receive File state */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case FALSE: /* Didn't get packet */ spack('N',n,0,0); /* Return a NAK */ return(state); /* Keep trying */ default: return('A'); /* Some other packet, "abort" */ } } /* * s e n d c m d s w * * This is the state table switcher for sending server commands files. */ sendcmdsw(cmdchr,cmdstr) char cmdchr, *cmdstr; { char resp_init(), resp_data (); if (setjmp(abort_env)) return(FALSE); state = 'R'; /* Response-Init is the start state */ n = 0; /* Initialize message number */ numtry = 0; /* Say no tries yet */ packets_sent = packets_received = 0;/* Initialize statistics */ bad_packets = naked_packets = 0; bytes_xferred = 0L; while(TRUE) { if (debug) printf(" sendcmdsw state: %c\n",state); switch(state) /* Do until done */ { case 'R': state = resp_init(cmdchr, cmdstr); /* Response-Init */ break; case 'D': state = resp_data(); break; /* Response-Data */ case 'C': return(TRUE); /* Complete state */ case 'A': return(FALSE); /* "Abort" state */ } } } /* * r e s p _ i n i t * * Server command response init */ char resp_init(cmdchr,cmdstr) char cmdchr, *cmdstr; { int len, num; /* Packet length, number */ if (numtry++ > maxtry) return('A'); /* If too many tries, "abort" */ spack(cmdchr,n,strlen(cmdstr),cmdstr); /* Send server command */ switch(rpack(&len,&num,recpkt)) /* Get a packet */ { case 'Y': /* ACK (short reply) */ if (n != num) return(state); /* If wrong ACK, fail */ numtry = 0; /* Reset try counter */ n = (n+1)%64; /* Bump packet count */ putmsgc(recpkt,len); /* Type the response */ return('C'); /* Transaction complete */ case 'N': /* NAK */ naked_packets++; notify_hook(); return(state); /* stay in this state */ case 'Z': /* End-Of-File */ if (oldtry++ > maxtry) return('A'); if (num == ((n==0) ? 63:n-1)) /* Previous packet, mod 64? */ { /* Yes, ACK it again. */ spack('Y',num,0,0); numtry = 0; return(state); /* Stay in this state */ } else return('A'); /* Not previous packet, "abort" */ case 'F': /* File Header (Long reply) */ if (num != n) return('A'); /* The packet number must be right */ putmsgc(recpkt,len); /* Type "filename", if any */ spack('Y',n,0,0); /* Acknowledge the file header */ oldtry = numtry; /* Reset try counters */ numtry = 0; /* ... */ n = (n+1)%64; /* Bump packet number, mod 64 */ return('D'); /* Switch to Data state */ case 'B': /* Break transmission (EOT) */ if (num != n) return ('A'); /* Need right packet number here */ spack('Y',n,0,0); /* Say OK */ return('C'); /* Go to complete state */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case FALSE: /* Didn't get packet */ spack('N',n,0,0); /* Return a NAK */ return(state); /* Keep trying */ default: return ('A'); /* Some other packet, "abort" */ } } /* * r e s p _ d a t a * * Receive server command response data (long response) */ char resp_data() { int num, len; /* Packet number, length */ if (numtry++ > maxtry) return('A'); /* "abort" if too many tries */ switch(rpack(&len,&num,packet)) /* Get packet */ { case 'D': /* Got Data packet */ if (num != n) /* Right packet? */ { /* No */ if (oldtry++ > maxtry) return('A'); /* If too many tries, abort */ if (num == ((n==0) ? 63:n-1)) /* Else check packet number */ { /* Previous packet again? */ spack('Y',num,6,packet); /* Yes, re-ACK it */ numtry = 0; /* Reset try counter */ return(state); /* Don't write out data! */ }; bad_packets++; notify_hook(); return('A'); /* sorry, wrong number */ } putmsgc(packet,len); /* show the user */ spack('Y',n,0,0); /* Acknowledge the packet */ oldtry = numtry; /* Reset the try counters */ numtry = 0; /* ... */ n = (n+1)%64; /* Bump packet number, mod 64 */ return('D'); /* Remain in data state */ case 'F': /* Got a File Header */ if (oldtry++ > maxtry) return('A'); /* If too many tries, "abort" */ if (num == ((n==0) ? 63:n-1)) /* Else check packet number */ { /* It was the previous one */ spack('Y',num,0,0); /* ACK it again */ numtry = 0; /* Reset try counter */ return(state); /* Stay in Data state */ } else return('A'); /* Not previous packet, "abort" */ case 'Z': /* End-Of-File */ if (num != n) return('A'); /* Must have right packet number */ spack('Y',n,0,0); /* OK, ACK it. */ n = (n+1)%64; /* Bump packet number */ return('F'); /* Go back to Receive File state */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case FALSE: /* Didn't get packet */ spack('N',n,0,0); /* Return a NAK */ return(state); /* Keep trying */ default: return('A'); /* Some other packet, "abort" */ } } /* * s p a c k * * Send a Packet */ spack(type,num,len,data) char type, *data; int num, len; { int i; /* Character loop counter */ char chksum, buffer[100]; /* Checksum, packet buffer */ register char *bufp; /* Buffer pointer */ flushinput (); /* Flush pending input */ if (debug) /* Display outgoing packet */ { if (data != NULL) data[len] = '\0'; /* Null-terminate data to print it */ printf(" spack type: %c\n",type); printf(" num: %d\n",num); printf(" len: %d\n",len); if (data != NULL) printf(" data: \"%s\"\n",data); } bufp = buffer; /* Set up buffer pointer */ for (i=1; i<=pad; i++) write_modem(&padchar,1); /* Issue any padding */ *bufp++ = SOH; /* Packet marker, ASCII 1 (SOH) */ *bufp++ = tochar(len+3); /* Send the character count */ chksum = tochar(len+3); /* Initialize the checksum */ *bufp++ = tochar(num); /* Packet number */ chksum += tochar(num); /* Update checksum */ *bufp++ = type; /* Packet type */ chksum += type; /* Update checksum */ for (i=0; i> 6)+chksum)&077; /* Compute final checksum */ *bufp++ = tochar(chksum); /* Put it in the packet */ *bufp++ = eol; /* Extra-packet line terminator */ write_modem(buffer,bufp-buffer); /* Send the packet */ if (type != 'Y' && type != 'N') packets_sent++; /* Count all but ACKs and NAKs */ notify_hook (); /* Give a chance to update display */ } /* * r p a c k * * Read a Packet */ rpack(len,num,data) int *len, *num; /* Packet length, number */ char *data; /* Packet data */ { int i, done; /* Data character number, loop exit */ char t, /* Current input character */ type, /* Packet type */ cchksum, /* Our (computed) checksum */ rchksum; /* Checksum received from other host */ #if UCB4X /* TOPS-20 can't handle timeouts... */ if (setjmp(env)) return FALSE; /* Timed out, fail */ signal(SIGALRM,clkint); /* Setup the timeout */ if ((timint > MAXTIM) || (timint < MINTIM)) timint = MYTIME; alarm(timint); #endif /* UCB4X */ #if RAINBOW if (setjmp(env)) return FALSE; /* Timed out, fail */ if ((timint > MAXTIM) || (timint < MINTIM)) timint = MYTIME; alarm(timint); /* Setup timeout */ #endif while (t != SOH) /* Wait for packet header */ t = read_modem () & 0177; /* Handle parity */ done = FALSE; /* Got SOH, init loop */ while (!done) /* Loop to get a packet */ { t = read_modem (); /* Get a character */ if ((!image) || quote_8bit) t &= 0177; /* Handle parity */ if (t == SOH) continue; /* Resynchronize if SOH */ cchksum = t; /* Start the checksum */ *len = unchar(t)-3; /* Character count */ t = read_modem (); /* Get a character */ if ((!image) || quote_8bit) t &= 0177; /* Handle parity */ if (t == SOH) continue; /* Resynchronize if SOH */ cchksum = cchksum + t; /* Update checksum */ *num = unchar(t); /* Packet number */ t = read_modem (); /* Get a character */ if ((!image) || quote_8bit) t &= 0177; /* Handle parity */ if (t == SOH) continue; /* Resynchronize if SOH */ cchksum = cchksum + t; /* Update checksum */ type = t; /* Packet type */ for (i=0; i<*len; i++) /* The data itself, if any */ { /* Loop for character count */ t = read_modem (); /* Get character */ if ((!image) || quote_8bit) t &= 0177; /* Handle parity */ if (t == SOH) continue; /* Resynch if SOH */ cchksum = cchksum + t; /* Update checksum */ data[i] = t; /* Put it in the data buffer */ } data[*len] = 0; /* Mark the end of the data */ t = read_modem (); /* Get last character (checksum) */ rchksum = unchar(t); /* Convert to numeric */ t = read_modem (); /* get EOL character and toss it */ if ((!image) || quote_8bit) t &= 0177; /* Handle parity */ if (t == SOH) continue; /* Resynchronize if SOH */ done = TRUE; /* Got checksum, done */ } #if (UCB4X | RAINBOW) alarm(0); /* Disable the timer interrupt */ #endif if (debug) /* Display incoming packet */ { if (data != NULL) data[*len] = '\0'; /* Null-terminate data to print it */ printf(" rpack type: %c\n",type); printf(" num: %d\n",*num); printf(" len: %d\n",*len); if (data != NULL) printf(" data: \"%s\"\n",data); } /* Fold in bits 7,8 to compute */ cchksum = (((cchksum&0300) >> 6)+cchksum)&077; /* final checksum */ flushinput (); /* Flush any padding, etc. */ if (type != 'Y' && type != 'N') packets_received++; /* count all but ACKs and NAKs */ notify_hook (); /* maybe update screen */ if (cchksum != rchksum) { bad_packets++; notify_hook (); return(FALSE); }; return(type); /* All OK, return packet type */ } /* * b u f i l l * * Get a bufferful of data from the file that's being sent. * Only control-quoting is done; 8-bit & repeat count prefixes are * not handled. */ bufill(buffer) char buffer[]; /* Buffer */ { int i, /* Loop index */ t, /* Char read from file */ count; /* byte count */ char t7; /* 7-bit version of above */ i = 0; /* Init data buffer pointer */ count = 0; while((t = getc(fp)) != EOF) /* Get the next character */ { count++; t7 = t & 0177; /* Get low order 7 bits */ if (quote_8bit && t == quote_8bit_char) buffer[i++] = quote; if (quote_8bit && (t & 0200)) { buffer[i++] = quote_8bit_char; t = t7; }; if (t7 < SP || t7==DEL || t7==quote) /* Does this char require */ { /* special handling? */ if (t=='\n' && !image) { /* Do LF->CRLF mapping if !image */ buffer[i++] = quote; buffer[i++] = ctl('\r'); } buffer[i++] = quote; /* Quote the character */ if (t7 != quote) { t = ctl(t); /* and uncontrolify */ t7 = ctl(t7); } } if (image) buffer[i++] = t; /* Deposit the character itself */ else buffer[i++] = t7; if (i >= spsiz-8) /* Check length */ { bytes_xferred += (long) count; return(i); }; } bytes_xferred += (long) count; if (i==0) return(EOF); /* Wind up here only on EOF */ return(i); /* Handle partial buffer */ } /* * b u f e m p * * Put data from an incoming packet into a file. */ bufemp(buffer,len) char buffer[]; /* Buffer */ int len; /* Length */ { int i, count; /* Counters */ unsigned char t; /* Character holder */ int q8bit; count = 0; for (i=0; i MAXPACKSIZ) { printmsg ("Truncating remote's MAXPACKSIZ from %d\n", spsiz); spsiz = MAXPACKSIZ; }; if ((i = unchar(data[1])) > timint) { printmsg("Timeout increased to %d seconds at remote's request", i); timint = i; }; pad = unchar(data[2]); /* Number of pads to send */ padchar = ctl(data[3]); /* Padding character to send */ eol = unchar(data[4]); /* EOL character I must send */ quote = data[5]; /* Incoming data quote character */ if (len >= 7) /* If other side mentioned 8th-bit */ switch (data[6]) { case 'N': if (quote_8bit) printmsg("Remote refused 8th-bit quoting"); quote_8bit = FALSE; break; case 'Y': break; default: if ((data[6] < 33 || data[6] > 126) || (data[6] > 62 && data[6] < 96)) { printmsg("Remote requested invalid 8th-bit quote char"); quote_8bit = FALSE; break; }; quote_8bit = TRUE; quote_8bit_char = data[6]; }; } /* * p u t m s g c * * Print counted message */ putmsgc(msg,len) char *msg; int len; { char buf[132]; if (len >= 132) { callers_printmsg("putmsgc - message too long"); return; }; strncpy(buf,msg,len); buf[len] = 0; callers_printmsg(buf); } /* * p r i n t m s g * * Print message on standard output if not remote. */ /*VARARGS1*/ printmsg(fmt, a1, a2, a3, a4, a5) char *fmt; { char msg[132]; if (!remote) { sprintf(msg,fmt,a1,a2,a3,a4,a5); callers_printmsg(msg); } } /* * e r r o r * * Print error message. * * If local, print error message with printmsg. * If remote, send an error packet with the message. */ /*VARARGS1*/ error(fmt, a1, a2, a3, a4, a5) char *fmt; { char msg[80]; int len; if (remote) { sprintf(msg,fmt,a1,a2,a3,a4,a5); /* Make it a string */ len = strlen(msg); spack('E',n,len,msg); /* Send the error packet */ } else printmsg(fmt, a1, a2, a3, a4, a5); return; } /* * p r e r r p k t * * Print contents of error packet received from remote host. */ prerrpkt(msg) char *msg; { char emsg[132]; sprintf(emsg,"Aborted by remote: %s",msg); callers_printmsg(emsg); return; } >>>>>>>> KERMIT.H /* Symbol Definitions */ #define IBM_UTS 0 #define UCB4X 0 #define RAINBOW 1 #define MSDOS 1 #if MSDOS #define NAMELEN 8 /* MS-DOS filenames are 8.3 */ #define EXTLEN 3 #endif #define MAXPACKSIZ 94 /* Maximum packet size */ #define SOH 1 /* Start of header */ #define CR 13 /* ASCII Carriage Return */ #define SP 32 /* ASCII space */ #define DEL 127 /* Delete (rubout) */ #define MAXTRY 5 /* Times to retry a packet */ #define MYQUOTE '#' /* Quote character I will use */ #define MY8BITQUOTE '&' /* 8th-bit quote character */ #define MYPAD 0 /* Number of padding characters I will need */ #define MYPCHAR 0 /* Padding character I need (NULL) */ #if IBM_UTS #define MYEOL '\r' /* End-Of-Line character for UTS systems */ #else #define MYEOL '\n' /* End-Of-Line character I need */ #endif #define MYTIME 10 /* Seconds after which I should be timed out */ #define MAXTIM 60 /* Maximum timeout interval */ #define MINTIM 2 /* Minumum timeout interval */ #define DEFTIM 10 /* Default timeout (before send init) */ #define TRUE -1 /* Boolean constants */ #define FALSE 0 /* Macro Definitions */ /* * tochar: converts a control character to a printable one by adding a space. * * unchar: undoes tochar. * * ctl: converts between control characters and printable characters by * toggling the control bit (ie. ^A becomes A and A becomes ^A). */ #define tochar(ch) ((ch) + ' ') #define unchar(ch) ((ch) - ' ') #define ctl(ch) ((ch) ^ 64 ) >>>>>>>> LCTERM.C /* * \usr\kermit\lcterm.c * * Copyright (C) 1984 by Larry Campbell, 73 Concord St., Maynard Mass. * * This program may be freely copied and disseminated for * noncommercial purposes, if and only if this entire copyright * statement and notice is included intact. This program, and * the information contained herein, may not be used for commercial * purposes without my prior written permission. * * File transfer and terminal emulator facility. * Supports KERMIT and XMODEM protocols for file transfer * Currently runs only on DEC Rainbow 100 running MS-DOS * version 2.05 or later. CAVEAT: this program has not been * tested well on a 100+. In particular, some of the video * routines access firmware storage which may differ on a 100+. * You have been warned. */ /* Revision history * * 2.14 Convert to CI-C86 version 2.10. * 2.13 Improve message windowing in KERMIT/XMODEM screens; fix * "doubled screen" bug; change KERMIT RECEIVE to GET. * 2.12 Update help screen. * 2.11 Restore user's break state during push. * 2.10 Make MAIN SCREEN synonym for ADDTNL OPTIONS; make * RETURN synonym for DO in menus; ignore shift bit in menus * 2.09 Clean up scripts; change #wnn to #w'nn'; add script * commands to set KERMIT parameters * 2.08 Add support for eighth-bit quoting in KERMIT xfers. * 2.07 Add keypad and cursor key support (this code will also * eventually handle user-defined macro keys) * 2.06 Move more Rainbow-specific stuff to separate modules * 2.05 Add XMODEM commands to scripts * 2.04 Timestamp printmsg output * 2.03 Reorganize connect code for clarity and speed * 2.02 Make log files append, not overwrite * 2.01 Add scripts * 1.13 Close log file when EXITing * 1.12 Changes to work with split up vid.c * 1.11 Set scroll region to whole screen when pushing * 1.10 Better HELP key response in terminal mode * 1.09 Add autopush on INTERRUPT key * 1.08 Fix bug in finding COMSPEC env var when it's not first * 1.07 Fix screen bug induced by PUSH, scroll, POP, TERM * 1.06 Fix bug in memory release at startup which broke 128K systems * 1.05 Slight speedup of terminal output */ #define LCTERM_VERSION "LC-Term version 2.14" #include #include "video.h" #include "rainbow.h" #include "bytes.h" #include "buf.h" #define CONFIRM_BOX_LOC 4, 45 /* * Rainbow-specific hack -- keypad mode is determined by peeking at * firmware bit, rather than by parsing the escape sequences ourselves */ #define keypad_mode (peek (ROM_KEYFLG, SCREEN_BUF_SEG) & 0x1) #define ABORT(s) { puts (s); leave (); } #define DOS_ERROR(n) { fputs (dos_error (n), stderr); leave (); } #define DOS(n) { srv.ax = n << 8;\ status = sysint21 (&srv, &rrv);\ if (status & 1) DOS_ERROR (rrv.ax); }; /* script escape character */ #define SCRIPT_ESC '#' /* These are really FORWARD declarations */ extern int capture_file (), close_capture (), close_script (), connect (), debug_mode (), hangup (), kermit_finish (), kermit_logout (), kermit_get (), kermit_remote_dir (), kermit_send (), kmenu (), kpadding (), kparams_menu (), kretry (), ktimeout (), leave (), lower_dtr (), message (), modem_menu (), modem_send (), modem_receive (), mpush (), normal_mode (), open_script (), params_menu (), raise_dtr (), raw_menu (), send_file (), toggle_binary (), toggle_8bit_quote (); /* Here are the "real" external declarations */ extern int auxres (), buf_emptyp (), buf_fullp (), create_buf (), destroy_buf (), exit (), kerini (), put_buf (), readfile (), sendfile (), recsw (), sendsw (), un_get_buf (); extern struct saved_video *pop_up_boxed_text (); extern char get_buf (); extern char *filnam; extern int debug, pad, timint, maxtry, binary, quote_8bit, packets_sent, packets_received, bad_packets, naked_packets; extern long bytes_xferred; extern int mdm_packets_sent, mdm_packets_received, mdm_bad_packets, mdm_naked_packets; extern long mdm_bytes_xferred; static int timer, status, cursor_is_off, saved_screen, saved_row, saved_col, printmsg_row, hours, minutes, seconds, prev_packets_sent, prev_packets_received, prev_bad_packets, prev_naked_packets, esc_seq_state; static long prev_bytes_xferred; #define PROMPT_BUF_SIZE 80 static unsigned char screen_char_buffer[SCREEN_BUF_SIZE], screen_attr_buffer[SCREEN_BUF_SIZE], screen_cursor_buffer[ROM_KEYS - ROM_SAVCR], screen_lat_buffer[ROM_Z80TAS - ROM_LATOFU], prompt[PROMPT_BUF_SIZE], *prompt_ptr, *key_string, comspec[132]; static struct saved_video *kermit_box_save; static jmp_buf escape_jmp; static struct regval {int ax, bx, cx, dx, si, di, ds, es;}; static struct segval {int scs, sss, sds, ses;}; static struct regval srv, rrv; static struct segval seg; static long prev_mdm_bytes_xferred; static int prev_mdm_packets_sent, prev_mdm_packets_received, prev_mdm_bad_packets, prev_mdm_naked_packets; static struct menu_item m_main_menu[] = { {"Enter terminal emulation", &connect}, {"KERMIT file transfer menu", &kmenu}, {"XMODEM file transfer menu", &modem_menu}, {"Raw text file transfer menu", &raw_menu}, {"Hang up the phone", &hangup}, {"Set parameters", ¶ms_menu}, {"Push to new shell", &mpush}, {"Information", &message}, {"Exit LC-Term", &leave}, {"", 0} }; static struct menu_item m_kermit_menu[] = { {"Send file to remote", &kermit_send}, {"Get file from remote", &kermit_get}, {"Remote directory", &kermit_remote_dir}, {"Stop remote server", &kermit_finish}, {"Log out remote server", &kermit_logout}, {"Set parameters", &kparams_menu}, {"Done", DONE}, {"", 0} }; static struct menu_item m_raw_xfer_menu[] = { {"Log terminal output to a file", &capture_file}, {"Close log file", &close_capture}, {"Send file to remote system", &send_file}, {"Process script", &open_script}, {"Close script", &close_script}, {"Done", DONE}, {"", 0} }; static struct menu_item m_params_menu[] = { {"Raise DTR", &raise_dtr}, {"Lower DTR", &lower_dtr}, {"Debug mode", &debug_mode}, {"Normal mode", &normal_mode}, {"Reset comm port", &auxres}, {"Done", DONE}, {"", 0} }; static struct menu_item m_kparams_menu[] = { {"Toggle 8th-bit quoting", &toggle_8bit_quote}, {"Set retry limit", &kretry}, {"Set padding value", &kpadding}, {"Toggle Binary/Text mode", &toggle_binary}, {"Set timeout value", &ktimeout}, {"Done", DONE}, {"", 0} }; static struct menu_item m_modem_menu[] = { {"Send file", &modem_send}, {"Receive file", &modem_receive}, {"Done", DONE}, {"", 0} }; static FILE *script, *capture, *stuff; static int last_second, delay_counter, old_break_state; static struct ring_buf *key_to_comm_buf; #define BUFSIZ 132 #define KEY_TAB_LENGTH 22 struct { int key; unsigned char *string; unsigned char *keypad_mode_string; } key_tab[KEY_TAB_LENGTH] = { {KEY_KEYPAD_PF1, "\033OP", 0}, {KEY_KEYPAD_PF2, "\033OQ", 0}, {KEY_KEYPAD_PF3, "\033OR", 0}, {KEY_KEYPAD_PF4, "\033OS", 0}, {KEY_KEYPAD_0, "0", "\033Op"}, {KEY_KEYPAD_1, "1", "\033Oq"}, {KEY_KEYPAD_2, "2", "\033Or"}, {KEY_KEYPAD_3, "3", "\033Os"}, {KEY_KEYPAD_4, "4", "\033Ot"}, {KEY_KEYPAD_5, "5", "\033Ou"}, {KEY_KEYPAD_6, "6", "\033Ov"}, {KEY_KEYPAD_7, "7", "\033Ow"}, {KEY_KEYPAD_8, "8", "\033Ox"}, {KEY_KEYPAD_9, "9", "\033Oy"}, {KEY_KEYPAD_DASH, "-", "\033Om"}, {KEY_KEYPAD_COMMA, ",", "\033Ol"}, {KEY_KEYPAD_PERIOD, ".", "\033On"}, {KEY_KEYPAD_ENTER, "\015", "\033OM"}, {KEY_UP_ARROW, "\033[A", 0}, {KEY_DOWN_ARROW, "\033[B", 0}, {KEY_RIGHT_ARROW, "\033[C", 0}, {KEY_LEFT_ARROW, "\033[D", 0} }; /* * Main program * */ main (argc, argv) int argc; char **argv; { int v, majorv, minorv, k; script = stuff = capture = timer = cursor_is_off = saved_screen = debug = 0; prompt_ptr = delay_counter = esc_seq_state = key_string = 0; clear_screen (); /* Init video states */ /* * Check DOS version (modem handler requires 2.05 or later) * */ v = bdos (0x30); majorv = v & 0xFF; minorv = v >> 8; if ((majorv < 2) || ((majorv == 2) && (minorv < 5))) { cursor (1, 1); puts ("LC-Term requires MS-DOS version 2.05 or later... sorry."); exit (); }; kerini (); /* Init KERMIT.C protocol module */ mdmini (); /* Init MODEM.C protocol module */ raise_dtr (); init_aux (); /* init comm port */ key_to_comm_buf = create_buf (BUFSIZ); segment_init (); /* init segment memory, COMSPEC string */ old_break_state = get_break (); set_break (0); /* turn off DOS break "feature" */ if (argc <= 1) { top_menu (); return; }; if (argv[1][0] == '-') switch (argv[1][1]) { char *p, c; case 't': /* straight to terminal mode */ connect (); break; case 'd': /* dial a number, then terminal mode */ p = argv[1] + 2; put_buf (key_to_comm_buf, 'B' - 0x40); /* DF03 autodial chr */ while (c = *p++) put_buf (key_to_comm_buf, c); connect (); break; case 's': /* open script file and enter */ p = argv[1] + 2; /* terminal emulation */ if ((script = fopen (p, "r")) != NULL) connect (); else script = 0; break; default: puts ("Usage: LCTERM [-t] [-d]"); exit (); }; top_menu (); } /* * segment_init * * Read segment registers for later use * * Scan our environment for the COMSPEC= string and save it away * so we can find the shell (COMMAND.COM) when the user selects * the PUSH function * */ segment_init () { unsigned int envseg; segread (&seg); /* read segment registers */ envseg = peek (0x2C, seg.scs - 0x10); /* get environment segment */ if (! env_fetch ("COMSPEC", envseg, comspec)) ABORT ("can't find COMSPEC environment string"); } message () { struct saved_video *screen; screen = save_screen_rectangle (1, 1, SCREEN_ROWS, SCREEN_COLUMNS); clear_screen (); rectangle (1, 1, SCREEN_ROWS - 1, SCREEN_COLUMNS - 1, ATTR_NORMAL); putline (2, 30, LCTERM_VERSION); putattr_i (2, 28, strlen (LCTERM_VERSION) + 4, ATTR_BOLD_REVERSE); putline (4, 14, "A>lcterm [-t] [-sfilespec]"); putattr_i (4, 16, 6, ATTR_UNDERLINE); putattr_i (4, 24, 2, ATTR_UNDERLINE); putattr_i (4, 29, 10, ATTR_UNDERLINE); putline (5, 12, "Options:"); putline (6, 14, "-t goes directly to terminal emulation"); putline (7, 14, "-sfilespec open `filespec' and process as a script"); #define X(row,s) putline (row, 8, s) X (9, "The menus should be self-explanatory. LC-Term transfers files"); X (10, "using either KERMIT or XMODEM protocols, and provides terminal"); X (11, "emulation with optional logging of the session to a file."); X (13, "Copyright (C) 1984 by Larry Campbell. This program may be copied"); X (14, "and disseminated freely for noncommercial purposes, if and only if"); X (15, "this copyright notice is included in all copies. This program,"); X (16, "and the information contained herein, may not be used for com-"); X (17, "mercial purposes without my prior written permission."); #undef X putline (19,15, "Larry Campbell"); putline (20,15, "73 Concord St."); putline (21,15, "Maynard, MA 01754"); #define M "Strike any key to proceed" boxed_text (21, 51, M); putattr_i (22, 52, strlen (M), ATTR_BLINK); #undef M cursor_off (); WAIT_FOR_ANY_KEY; cursor_on (); restore_screen_rectangle (screen); } /* * push * * Invoke a new shell */ static struct /* execute program parameter block */ { int environment; int cmdoff; int cmdseg; int fcb5off; int fcb5seg; int fcb6off; int fcb6seg; } params; static char cmdstring[132]; push () { if (cmdstring[0] == 0) /* if PUSH and not command, clear screen 1st */ { clear_screen (); cursor (1, 1); pokew (ROM_TOP, SCREEN_BUF_SEG, 0x1801); /* set normal scroll region */ puts ("Give EXIT command to return to LCTERM..."); }; params.environment = peek (0x2c, seg.scs - 0x10); /* inherit our environment */ params.cmdseg = seg.sss; params.cmdoff = cmdstring; params.fcb5seg = params.fcb6seg = 0; params.fcb5off = params.fcb6off = 0; set_break (old_break_state); /* restore break state */ status = loadexec (comspec, seg.sds, ¶ms, seg.sds, 0, 0); /* status = exec (seg.sds, comspec, ¶ms); */ set_break (0); /* disable break again */ if (status) { printf ("Loadexec failed: %s\n", dos_error (status)); await_attention (); }; } mpush () { struct saved_video *screen; screen = save_screen_rectangle (1, 1, SCREEN_ROWS, SCREEN_COLUMNS); cmdstring[0] = 0; cmdstring[1] = 0x0D; push (); restore_screen_rectangle (screen); } top_menu () { int (*handler) (), (*parse_menu ()) (), code; parse_menu (m_main_menu, 3, 27, LCTERM_VERSION, MENU_CLEAR_SCREEN + MENU_ACTIVE_MODE); } kmenu () { parse_menu (m_kermit_menu, 6, 8, "LC-Term KERMIT", MENU_POST_CLEAR + MENU_ACTIVE_MODE); } raw_menu () { parse_menu (m_raw_xfer_menu, 8, 15, "LC-Term Raw Text Transfer", MENU_POST_CLEAR + MENU_ACTIVE_MODE + MENU_ONCE_ONLY); } params_menu () { parse_menu (m_params_menu, 10, 20, "LC-Term Parameters", MENU_ACTIVE_MODE); } kparams_menu () { int (*parse_menu ()) (); kermit_box_save = save_screen_rectangle (16, 1, 9, 28); display_kermit_params (); parse_menu (m_kparams_menu, 13, 30, "LC-Term KERMIT Parameters", MENU_POST_CLEAR + MENU_ACTIVE_MODE); erase_kermit_params_display (); } modem_menu () { int (*parse_menu ()) (); parse_menu (m_modem_menu, 7, 45, "LC-Term XMODEM", MENU_POST_CLEAR + MENU_ACTIVE_MODE); } raise_dtr () { outportb (2, 0); } lower_dtr () { outportb (2, 4); } hangup () { lower_dtr (); pause (4000); raise_dtr (); } /* * PAUSE * * Pause for n milliseconds to allow user to absorb something * */ pause (n) int n; { long k; for (k = LOOPS_PER_MILLISECOND * (long) n; k > 0; k--); } leave () { reset_aux (); if (capture != 0) fclose (capture); if (stuff != 0) fclose (stuff); if (script != 0) fclose (script); set_break (old_break_state); cursor (24, 1); clear_rest_of_line (); cursor_on (); exit (); } debug_mode () { debug = 1; } normal_mode () { debug = 0; } toggle_binary () { binary = ! binary; display_kermit_params (); } toggle_8bit_quote () { quote_8bit = ! quote_8bit; display_kermit_params (); } ktimeout () { kval ("Timeout", &timint); } kpadding () { kval ("Padding", &pad); } kretry () { kval ("Retry limit", &maxtry); } kval (name, addr) char *name; int *addr; { char c, buf[132]; int i; extern char blanks[]; struct saved_video *help_box; cursor_off (); sprintf (buf, "%s: Use arrow keys, DO when done", name); help_box = pop_up_boxed_text (22, 29, buf); putattr_i (23, 30, strlen (buf), ATTR_BLINK); while (1) { while ((c = kbdin ()) < 0); switch (c) { case KEY_UP_ARROW: if (++(*addr) > 99) { FEEP; *addr = 99; }; display_kermit_params (); break; case KEY_DOWN_ARROW: if (--(*addr) < 0) {FEEP; *addr = 0; }; display_kermit_params (); break; case KEY_DO: for (i = 22; i <= 24; i++) put_line (i, 29, 51, blanks); cursor_on (); restore_screen_rectangle (help_box); return; default: FEEP; }; }; } display_kermit_params () { char buf[6]; rectangle (16, 1, 8, 27, ATTR_NORMAL); horizontal_cut (18, 1, 28, ATTR_NORMAL); putline (17, 7, "KERMIT Parameters"); putattr_i (17, 7, strlen ("KERMIT Parameters"), ATTR_BOLD); putline (19, 2, "Eighth-bit quoting: "); putline (20, 2, "Retry limit: "); putline (21, 2, "No. of padding chars: "); putline (22, 2, "File mode: "); putline (23, 2, "Timeout (seconds): "); if (quote_8bit) putline (19, 2+23, "YES"); else putline (19, 2+23, " NO"); sprintf (buf, "%2d", maxtry); putline (20, 2+24, buf); sprintf (buf, "%2d", pad); putline (21, 2+24, buf); if (binary) putline (22, 2+20, "BINARY"); else putline (22, 2+20, " TEXT"); sprintf (buf, "%2d", timint); putline (23, 2+24, buf); } erase_kermit_params_display () { int i; putattr_i (17, 7, strlen ("KERMIT Parameters"), ATTR_NORMAL); restore_screen_rectangle (kermit_box_save); } save_screen () { unsigned int j, k, cursorpos; struct { int cs; int ss; int ds; int es; } regs; segread (®s); cursorpos = peek (ROM_CSRPOS, SCREEN_BUF_SEG); saved_row = cursorpos >> 8; saved_col = cursorpos & 0xFF; disable_cursor (); movblock (SCREEN_BUF_OFFSET, /* save characters */ SCREEN_BUF_SEG, screen_char_buffer, regs.ds, SCREEN_BUF_SIZE); movblock (SCREEN_ATTR_OFFSET, /* save attributes */ SCREEN_BUF_SEG, screen_attr_buffer, regs.ds, SCREEN_BUF_SIZE); movblock (ROM_SAVCR, /* save cursor state */ SCREEN_BUF_SEG, screen_cursor_buffer, regs.ds, ROM_KEYS - ROM_SAVCR); movblock (ROM_LATOFU, SCREEN_BUF_SEG, screen_lat_buffer, regs.ds, ROM_Z80TAS - ROM_LATOFU); enable_cursor (); saved_screen = 1; } restore_screen () { struct { int cs; int ss; int ds; int es; } regs; segread (®s); disable_cursor (); movblock (screen_char_buffer, regs.ds, SCREEN_BUF_OFFSET, SCREEN_BUF_SEG, SCREEN_BUF_SIZE); movblock (screen_attr_buffer, regs.ds, SCREEN_ATTR_OFFSET, SCREEN_BUF_SEG, SCREEN_BUF_SIZE); movblock (screen_cursor_buffer, regs.ds, ROM_SAVCR, SCREEN_BUF_SEG, ROM_KEYS - ROM_SAVCR); movblock (screen_lat_buffer, regs.ds, ROM_LATOFU, SCREEN_BUF_SEG, ROM_Z80TAS - ROM_LATOFU); enable_cursor (); cursor (saved_row, saved_col); saved_screen = 0; } /* * connect * * Terminal emulation. MAIN SCREEN key gets you the top menu. * INTERRUPT key pushes to new shell. EXIT key just exits. */ connect () { int t, com_char; struct saved_video *save; char c; save = save_screen_rectangle (1, 1, SCREEN_ROWS, SCREEN_COLUMNS); if (! saved_screen) { clear_screen (); putline (1, 1, "Connected to communications port, press MAIN SCREEN for menu..."); cursor (2, 1); } else restore_screen (); if (setjmp (escape_jmp)) /* MAIN SCREEN key longjmps thru here */ { save_screen (); restore_screen_rectangle (save); return; }; while (1) { if (delay_counter > 0) /* check for timer running */ if ((t = tod_seconds ()) != last_second) { last_second = t; delay_counter--; }; keyinput (); if ((! buf_emptyp (key_to_comm_buf)) && aux_hungry ()) { /* buffer nonempty and AUX hungry */ switch (c = get_buf (key_to_comm_buf)) { case '\n': c = 015; default: if (putaux (c)) break; else un_get_buf (key_to_comm_buf, c); }; }; keyinput (); com_char = getaux (); if (com_char > 0) process_aux_input (com_char); }; } /* * process_aux_input * * Handle incoming character. This is where inquiries and state * changes caused by incoming escape sequences get handled. */ process_aux_input (com_char) int com_char; { com_char = com_char & 0x7F; /* strip 8th bit */ if (prompt_ptr != 0) /* waiting for prompt? */ if (*prompt_ptr == com_char) /* yes, is this it? */ { if (*(++prompt_ptr) == 0) /* match done? */ prompt_ptr = 0; } else prompt_ptr = prompt; /* match failed, reset ptr to start */ switch (esc_seq_state) /* This grunge handles the terminal */ { /* type inquiry (ESC [ c) -- the */ case 0: /* only inquiry we support */ if (com_char == 033) esc_seq_state = 1; else put_to_screen (com_char); break; case 1: switch (com_char) { case '[': esc_seq_state = 2; break; case 'Z': return_terminal_id (); esc_seq_state = 0; break; default: esc_seq_state = 0; put_to_screen (033); put_to_screen (com_char); }; break; case 2: switch (com_char) { case 'c': return_terminal_id (); esc_seq_state = 0; break; case '0': esc_seq_state = 3; break; default: esc_seq_state = 0; put_to_screen (033); put_to_screen ('['); put_to_screen (com_char); }; break; case 3: if (com_char == 'c') return_terminal_id (); else { put_to_screen (033); put_to_screen ('['); put_to_screen ('0'); put_to_screen (com_char); }; esc_seq_state = 0; break; default: put_to_screen (com_char); }; } /* * put_to_screen (chr) * * Write a character to the screen, and log file if one is open */ put_to_screen (c) int c; { putcon ((char) c); if (capture != 0 && c != 015 && c != ('Z' - 0100)) fputc (c, capture); } /* * return_terminal_id * * Return escape sequence identifying me as a VT102 */ return_terminal_id () { put_buf (key_to_comm_buf, 033); put_buf (key_to_comm_buf, '['); put_buf (key_to_comm_buf, '?'); put_buf (key_to_comm_buf, '6'); put_buf (key_to_comm_buf, 'c'); } /* * keyinput * * Get keyboard input if any and stuff into buffer. * * Calls leave() if EXIT key hit. * Pushes to new shell if INTERRUPT hit. * Does longjmp thru escape_jmp if ADDTNL OPTIONS hit. */ keyinput () { int key_char, k; if (key_string) /* if fn key string pending, */ { if ((key_char = *key_string++) == 0)/* get next char */ { key_string = 0; /* if string exhausted, zero pointer */ key_char = getkey (); /* and try keyboard */ }; } else key_char = getkey (); /* if no fn key string, try keyboard */ if (key_char == -2) /* if level 2 sequence in progress, */ key_char = bdos (7, 0) & 0x77; /* get char from DOS */ if (key_char > 0) /* if char available */ { if (key_char & 0x100) /* see if function key */ switch (key_char &= 0xFF) /* ignore shifty bits */ { case KEY_EXIT: leave (); case KEY_MAIN_SCREEN: case KEY_ADDTNL_OPTIONS: longjmp (escape_jmp, 1); case KEY_INTERRUPT: save_screen (); push (); restore_screen (); return; case KEY_HELP: do_help (); break; default: for (k = 0; k < KEY_TAB_LENGTH; k++) if (key_char == key_tab[k].key) { if (keypad_mode && key_tab[k].keypad_mode_string) key_string = key_tab[k].keypad_mode_string; else key_string = key_tab[k].string; return; }; FEEP; /* no mapping for this key */ } else { /* non-function key */ if (! put_buf (key_to_comm_buf, key_char)) { FEEP; boxed_text (2, 50, "Keyboard buffer full"); }; return; }; }; /* * If buffer hungry, check for stuff or script file */ if (buf_fullp (key_to_comm_buf)) return; if (script != 0) return (do_script ()); if (stuff != 0) { if ((key_char = fgetc (stuff)) == EOF) { fclose (stuff); stuff = 0; } else put_buf (key_to_comm_buf, key_char); return; }; } do_script () { char c, key_char, buf[40], *dp; if (delay_counter > 0) /* quit if timer running */ return; if (prompt_ptr) /* quit if waiting for a prompt */ return; if ((key_char = fgetc (script)) == EOF) { fclose (script); script = 0; delay_counter = 0; } else { if (key_char == SCRIPT_ESC) /* script escape char? */ switch (key_char = fgetc (script)) { case EOF: fclose (script); script = 0; delay_counter = 0; break; case SCRIPT_ESC: put_buf (key_to_comm_buf, key_char); break; case 'c': if ((key_char = fgetc (script)) == EOF) break; cmdstring[0] = 2; /* length of command */ cmdstring[1] = '/'; cmdstring[2] = 'C'; dp = cmdstring + 3; /* shell command string */ while ((c = fgetc (script)) != key_char) { *dp++ = c; if (++cmdstring[0] > 131) break; }; *dp++ = 0x0D; /* magic cookie for DOS */ *dp = 0; /* another one */ push (); /* go get 'em */ break; case 'e': leave (); case 'h': hangup (); break; case 'k': /* KERMIT commands */ kermit_script (); break; case 'm': /* XMODEM commands */ modem_script (); break; case 'p': get_quoted_string (prompt, PROMPT_BUF_SIZE, script); prompt_ptr = prompt; break; case 'l': /* log file functions */ switch (fgetc (script)) { case 'o': /* open a log file */ get_quoted_string (buf, 40, script); if (capture) fclose (capture); capture = fopen (buf, "a"); break; case 'c': /* close log file */ if (capture) fclose (capture); capture = 0; break; }; break; case 'w': get_quoted_string (buf, 40, script); delay_counter = atoi (buf) + 1; if (delay_counter < 0) delay_counter = 0; last_second = tod_seconds (); /* init timer */ break; } else /* else just stuff it */ put_buf (key_to_comm_buf, key_char); }; } /* * kermit_script * * Called by script handler to process 'k' commands: * * kc'nn' set retry count to nn * kr'file' receive file * ks'file' send file * kt'nn' set timeout to nn seconds * kx stop remote server * k8+ turn on 8th-bit quoting * k8- turn it off */ kermit_script () { struct saved_video *save; char c, d, *dp, *msg, buf[40]; switch (fgetc (script)) { case 'c': get_quoted_string (buf, 40, script); maxtry = atoi (buf); break; case 'g': case 'r': get_quoted_string (buf, 40, script); filnam = buf; save = save_screen_rectangle (1, 1, SCREEN_ROWS, SCREEN_COLUMNS); kermit_screen (); if (recsw ()) boxed_text (CONFIRM_BOX_LOC, "File received OK"); else { boxed_text (CONFIRM_BOX_LOC, "Receive failed, script aborted"); fclose (script); script = 0; await_attention (); }; restore_screen_rectangle (save); cursor_on (); break; case 's': get_quoted_string (buf, 40, script); filnam = buf; save = save_screen_rectangle (1, 1, SCREEN_ROWS, SCREEN_COLUMNS); kermit_screen (); if (sendsw ()) boxed_text (CONFIRM_BOX_LOC, "File sent OK"); else { boxed_text (CONFIRM_BOX_LOC, "Send failed, script aborted"); fclose (script); script = 0; await_attention (); }; restore_screen_rectangle (save); cursor_on (); break; case 't': get_quoted_string (buf, 40, script); timint = atoi (buf); break; case 'x': save = save_screen_rectangle (1, 1, SCREEN_ROWS, SCREEN_COLUMNS); kermit_screen (); if (sendcmdsw ('G', "F")) boxed_text (CONFIRM_BOX_LOC, "Server stopped OK"); else { boxed_text (CONFIRM_BOX_LOC, "Stop failed, script aborted"); fclose (script); script = 0; await_attention (); }; restore_screen_rectangle (save); cursor_on (); break; case '8': switch (fgetc (script)) { case '+': quote_8bit = 1; break; case '-': quote_8bit = 0; break; }; break; }; } /* * get_quoted_string (buf, bufn, fd) * * Get a quoted string from a file, storing into buffer */ get_quoted_string (dp, bufn, fd) char *dp; int bufn; FILE *fd; { char c, d; d = fgetc (fd); /* get delimiter character */ while ((c = fgetc (fd)) != d && bufn-- >= 0) *dp++ = c; /* copy filespec */ *dp = 0; } /* * modem_script * * Called by script handler to process 'm' commands: * * ms'file' send file * mr'file' receive file */ modem_script () { struct saved_video *save; char c, d, *dp, *msg, buf[40]; switch (fgetc (script)) { case 'r': d = fgetc (script); /* get delimiter character */ dp = buf; while ((c = fgetc (script)) != d) *dp++ = c; /* copy filespec */ *dp = 0; save = save_screen_rectangle (1, 1, SCREEN_ROWS, SCREEN_COLUMNS); modem_screen (); save_aux_params (); disable_auto_xon_xof (); if (readfile (buf)) boxed_text (CONFIRM_BOX_LOC, "File received OK"); else { boxed_text (CONFIRM_BOX_LOC, "Receive failed, script aborted"); fclose (script); script = 0; await_attention (); }; restore_aux_params (); restore_screen_rectangle (save); cursor_on (); break; case 's': d = fgetc (script); /* get delimiter character */ dp = buf; while ((c = fgetc (script)) != d) *dp++ = c; /* copy filespec */ *dp = 0; save = save_screen_rectangle (1, 1, SCREEN_ROWS, SCREEN_COLUMNS); modem_screen (); save_aux_params (); disable_auto_xon_xof (); if (sendfile (buf)) boxed_text (CONFIRM_BOX_LOC, "File sent OK"); else { boxed_text (CONFIRM_BOX_LOC, "Send failed, script aborted"); fclose (script); script = 0; await_attention (); }; restore_aux_params (); restore_screen_rectangle (save); cursor_on (); break; }; } capture_file () { int k; struct saved_video *save; char buf[40]; if (capture) fclose (capture); pop_up_get_string (20, 1, "Name of file to receive:", buf, 40); if ((capture = fopen (buf, "a")) == NULL) { capture = 0; save = pop_up_boxed_text (21, 2, "Can't open that file"); await_attention (); restore_screen_rectangle (save); }; } close_capture () { if (capture != 0) fclose (capture); capture = 0; } /* * await_attention * * Feep, pop up box asking user to strike key, and return */ await_attention () { struct saved_video *box; #define MSG "Strike any key to proceed" disable_cursor (); FEEP; box = pop_up_boxed_text (3 + CONFIRM_BOX_LOC, MSG); putattr_i (1 + 3 + CONFIRM_BOX_LOC + 1, strlen (MSG), ATTR_BOLD_BLINK); WAIT_FOR_ANY_KEY; enable_cursor (); restore_screen_rectangle (box); } kermit_get () { int k; struct saved_video *save; char *msg, buf[40]; pop_up_get_string (20, 1, "Name of file to receive:", buf, 40); filnam = buf; save = save_screen_rectangle (1, 1, SCREEN_ROWS, SCREEN_COLUMNS); kermit_screen (); if (recsw ()) msg = "File received OK"; else msg = "Receive failed"; boxed_text (CONFIRM_BOX_LOC, msg); await_attention (); restore_screen_rectangle (save); cursor_on (); } kermit_remote_dir () { int k; struct saved_video *save; char *msg, buf[40]; pop_up_get_string (20, 1, "(Optional) wildcard filespec:", buf, 40); save = save_screen_rectangle (1, 1, SCREEN_ROWS, SCREEN_COLUMNS); kermit_screen (); buf[0] = 'D'; /* directory command */ if (sendcmdsw ('G', buf)) msg = "Directory list OK"; else msg = "Directory list failed"; boxed_text (CONFIRM_BOX_LOC, msg); await_attention (); restore_screen_rectangle (save); cursor_on (); } send_file () { int k; char *msg, buf[40]; struct saved_video *save; pop_up_get_string (20, 1, "Name of file to send:", buf, 40); if ((stuff = fopen (buf, "r")) == NULL) { stuff = 0; save = pop_up_boxed_text (21, 2, "Can't open that file"); await_attention (); restore_screen_rectangle (save); }; } open_script () { int k; char *msg, buf[40]; struct saved_video *save; pop_up_get_string (20, 1, "Name of script file:", buf, 40); if ((script = fopen (buf, "r")) == NULL) { script = 0; save = pop_up_boxed_text (21, 2, "Can't open that file"); await_attention (); restore_screen_rectangle (save); }; } close_script () { if (script) { fclose (script); delay_counter = 0; script = 0; }; } kermit_send () { int k; struct saved_video *save; char *msg, buf[40]; pop_up_get_string (20, 1, "Name of file to send:", buf, 40); filnam = buf; save = save_screen_rectangle (1, 1, SCREEN_ROWS, SCREEN_COLUMNS); kermit_screen (); if (sendsw ()) msg = "File sent OK"; else msg = "Send failed"; boxed_text (CONFIRM_BOX_LOC, msg); await_attention (); restore_screen_rectangle (save); cursor_on (); } modem_send () { int k; struct saved_video *save; char *msg, buf[40]; pop_up_get_string (20, 1, "Name of file to send:", buf, 40); save = save_screen_rectangle (1, 1, SCREEN_ROWS, SCREEN_COLUMNS); modem_screen (); save_aux_params (); disable_auto_xon_xof (); if (sendfile (buf)) msg = "File sent OK"; else msg = "Send failed"; restore_aux_params (); boxed_text (CONFIRM_BOX_LOC, msg); await_attention (); restore_screen_rectangle (save); cursor_on (); } modem_receive () { int k; struct saved_video *save; char *msg, buf[40]; pop_up_get_string (20, 1, "Name of file to receive:", buf, 40); save = save_screen_rectangle (1, 1, SCREEN_ROWS, SCREEN_COLUMNS); modem_screen (); save_aux_params (); disable_auto_xon_xof (); if (readfile (buf)) msg = "File received OK"; else msg = "Receive failed"; restore_aux_params (); boxed_text (CONFIRM_BOX_LOC, msg); await_attention (); restore_screen_rectangle (save); cursor_on (); } modem_screen () { if (debug) return; printmsg_row = 13; cursor_off (); clear_screen (); prev_mdm_bytes_xferred = 0L; prev_mdm_packets_sent = 0, prev_mdm_packets_received = 0, prev_mdm_bad_packets = 0, prev_mdm_naked_packets = 0; rectangle (1, 1, SCREEN_ROWS - 1, SCREEN_COLUMNS, ATTR_NORMAL); horizontal_cut (12, 1, SCREEN_COLUMNS, ATTR_NORMAL); #define TITLE "LC-Term XMODEM" putline (2, 33, TITLE); putattr_i (2, 32, strlen (TITLE) + 2, ATTR_REVERSE); rectangle (4, 4, 7, 23, ATTR_NORMAL); putline (5, 12, "Counters"); putattr_i (5, 12, strlen("Counters"), ATTR_BOLD); horizontal_cut (6, 4, 24, ATTR_NORMAL); putline (7, 5, "Packets sent: 0"); putline (8, 5, "Packets received: 0"); putline (9, 5, "Error packets: 0"); putline (10,5, "NAKed packets: 0"); cursor (24, 1); } mdm_notify_hook () { char buf[16]; if (debug) return; if (prev_mdm_bytes_xferred != mdm_bytes_xferred) { sprintf (buf, "%8ld", mdm_bytes_xferred); putline (6, 19, buf); prev_mdm_bytes_xferred = mdm_bytes_xferred; }; if (prev_mdm_packets_sent != mdm_packets_sent) { sprintf (buf, "%5d", mdm_packets_sent); putline (7, 22, buf); prev_mdm_packets_sent = mdm_packets_sent; }; if (prev_mdm_packets_received != mdm_packets_received) { sprintf (buf, "%5d", mdm_packets_received); putline (8, 22, buf); prev_mdm_packets_received = mdm_packets_received; }; if (prev_mdm_bad_packets != mdm_bad_packets) { sprintf (buf, "%5d", mdm_bad_packets); putline (9, 22, buf); prev_mdm_bad_packets = mdm_bad_packets; }; if (prev_mdm_naked_packets != mdm_naked_packets) { sprintf (buf, "%5d", mdm_naked_packets); putline (10, 22, buf); prev_mdm_naked_packets = mdm_naked_packets; }; } do_help () { save_screen (); boxed_text (4, 5, "Press MAIN SCREEN for menu, EXIT to leave LC-Term, INTERRUPT for shell"); await_attention (); restore_screen (); } kermit_finish () { struct saved_video *save; char *msg; save = save_screen_rectangle (1, 1, SCREEN_ROWS, SCREEN_COLUMNS); kermit_screen (); if (sendcmdsw ('G', "F")) msg = "Server stopped OK"; else msg = "Stop failed"; boxed_text (CONFIRM_BOX_LOC, msg); await_attention (); restore_screen_rectangle (save); cursor_on (); } kermit_logout () { struct saved_video *save; char *msg; save = save_screen_rectangle (1, 1, SCREEN_ROWS, SCREEN_COLUMNS); kermit_screen (); if (sendcmdsw ('G', "L")) msg = "Server logged out OK"; else msg = "Logout failed"; boxed_text (CONFIRM_BOX_LOC, msg); await_attention (); restore_screen_rectangle (save); cursor_on (); } kermit_screen () { char fspec[80]; if (debug) return; printmsg_row = 13; cursor_off (); clear_screen (); prev_bytes_xferred = 0L; prev_packets_sent = 0, prev_packets_received = 0, prev_bad_packets = 0, prev_naked_packets = 0; rectangle (1, 1, SCREEN_ROWS - 1, SCREEN_COLUMNS - 1, ATTR_NORMAL); horizontal_cut (12, 1, SCREEN_COLUMNS, ATTR_NORMAL); #define TITLE "LC-Term KERMIT" putline (2, 33, TITLE); putattr_i (2, 32, strlen (TITLE) + 2, ATTR_REVERSE); rectangle (3, 4, 8, 23, ATTR_NORMAL); putline (4, 12, "Counters"); putattr_i (4, 12, strlen("Counters"), ATTR_BOLD); horizontal_cut (5, 4, 24, ATTR_NORMAL); putline (6, 5, "Bytes xferred: 0"); putline (7, 5, "Packets sent: 0"); putline (8, 5, "Packets received: 0"); putline (9, 5, "Error packets: 0"); putline (10,5, "NAKed packets: 0"); cursor (24, 1); } notify_hook () { char buf[16]; if (debug) return; if (prev_bytes_xferred != bytes_xferred) { sprintf (buf, "%8ld", bytes_xferred); putline (6, 19, buf); prev_bytes_xferred = bytes_xferred; }; if (prev_packets_sent != packets_sent) { sprintf (buf, "%5d", packets_sent); putline (7, 22, buf); prev_packets_sent = packets_sent; }; if (prev_packets_received != packets_received) { sprintf (buf, "%5d", packets_received); putline (8, 22, buf); prev_packets_received = packets_received; }; if (prev_bad_packets != bad_packets) { sprintf (buf, "%5d", bad_packets); putline (9, 22, buf); prev_bad_packets = bad_packets; }; if (prev_naked_packets != naked_packets) { sprintf (buf, "%5d", naked_packets); putline (10, 22, buf); prev_naked_packets = naked_packets; }; } check_time () { static int old_seconds = 0; seconds = tod_seconds (); if (seconds == old_seconds) /* has clock ticked? */ return; /* no, just return */ old_seconds = seconds; hours = tod_hours (); minutes = tod_minutes (); draw_clock (hours, minutes, seconds); if (timer > 0) { extern jmp_buf env; if (--timer <= 0) { printmsg ("Timed out"); longjmp (env, 1); }; }; } alarm (sec) int sec; { timer = sec; } draw_clock (h, m, s) int h, m, s; { char buf[9]; if (debug) return; sprintf (buf, "%02d:%02d:%02d", h, m, s); boxed_text (4, 30, buf); } /* * Routines called by KERMIT.C (protocol module) * */ kabort () { extern jmp_buf abort_env; printmsg ("Aborted at user request"); longjmp (abort_env, 1); } static struct menu_item kabort_menu[] = { {"Abort this transaction", &kabort}, {"Resume this transaction", DONE}, {"", 0} }; monitor_kbd () { int c; c = kbdin (); if (c >= 0) if (c & 0x100) switch (c & 0xFF) { case KEY_EXIT: leave (); case KEY_ADDTNL_OPTIONS: parse_menu (kabort_menu, 8, 30, "LC-Term Transfer in Progress", MENU_POST_CLEAR + MENU_ACTIVE_MODE); break; case KEY_HELP: printmsg ("EXIT key to exit, ADDTNL_OPTIONS for more options"); break; default: FEEP; } else FEEP; check_time (); } unsigned char read_modem () { int c; while ((c = getaux()) == -1) monitor_kbd (); return ((unsigned char) c); } flushinput () { if (debug) fputs ("Input flushed... ", stdout); while ((getaux ()) != -1) monitor_kbd (); if (debug) puts ("OK"); } write_modem (cdata, count) unsigned char *cdata; int count; { char c; if (debug) { int i, j; if (count > 9) j = 9; else j = count; printf ("WRITE_MODEM: count is (%d), msg is (%x", count, cdata[0]); for (i = 1; i < j; i++) printf (", %x", cdata[i]); if (count > 9) fputs ("...", stdout); puts (")"); }; while (count-- > 0) { c = *cdata++; while (! aux_hungry ()) monitor_kbd (); if (! putaux (c)) { count++; cdata--; }; }; } callers_printmsg (s) char *s; { char buf[81]; if (*s == 0) return; sprintf (buf, "%02d:%02d:%02d %.68s", hours, minutes, seconds, s); if (debug) { fputs (buf, stdout); return; }; put_line (printmsg_row, 2, 78, blanks); putline (printmsg_row, 2, buf); if (++printmsg_row > (SCREEN_ROWS - 2)) printmsg_row = 12; } cursor_on () { if (cursor_is_off) enable_cursor (); cursor_is_off = 0; } cursor_off () { if (! cursor_is_off) disable_cursor (); cursor_is_off = 1; } >>>>>>>> MENU.C /* * \usr\c\menu.c * * Copyright (C) 1984 by Larry Campbell, 73 Concord St., Maynard Mass. * * This software may be freely copied and disseminated for * noncommercial purposes, if and only if this entire copyright * statement and notice is included intact. This software, and * the information contained herein, may not be used for commercial * purposes without my prior written permission. * * This module provides a general-purpose "windowing" menu handler */ #include #include "video.h" #include "rainbow.h" /* This array contains 132 blanks (ASCII 040) */ char blanks[132] = " \ "; extern struct saved_video *pop_up_boxed_text (); /* * Simple-minded menu handler. * * menu_addr Array of menu_type entries * row, col Position of upper left corner * title String used as caption * flags Various bits * */ int (*parse_menu ()) (menu_addr, row, col, title, flags) struct menu_item menu_addr[]; int row, col, flags; char *title; { #define PROMPT "Select, then press DO:" int prompt_length = strlen (PROMPT), i, length, width, safety_width, (*handler_routine) (), selection, old_selection, selection_row, selection_col, help_present, do_flag, c; char buf[132]; struct menu_item *item; struct saved_screen_rectangle *saved_region, *help_box; width = 0; help_present = 0; for (length = 0; (menu_addr[length].handler) != 0; length++) if ((i = strlen (menu_addr[length].name)) > width) width = i; if ((i = strlen (title)) > width) width = i; if (length > 9) abort ("Menu >9 items not supported"); safety_width = width + 6; /* includes sides and numbers */ if ((prompt_length + 2) > safety_width) safety_width = prompt_length + 2; saved_region = save_screen_rectangle (row, col, length + 5, safety_width); paint_menu (menu_addr, row, col, title, flags, length, width); /* Now handle menu selection. If MENU_ACTIVE_MODE, do this repeatedly, * calling semantic routines until user chooses DONE entry. */ while (1) { putline (length + row + 4, col + 1, PROMPT); putattr_i (length + row + 4, col + 1, prompt_length, ATTR_BOLD); selection_row = row + length + 4; selection_col = col + prompt_length + 2; selection = 0; old_selection = 0; while (1) { do_flag = 0; cursor (selection_row, selection_col); /* blink in useful place */ buf[0] = ' '; if (selection) buf[1] = selection + '0'; else buf[1] = ' '; buf[2] = 0; putline (selection_row, selection_col - 1, buf); while ((c = kbdin ()) < 0); /* poll keyboard until real char */ if (help_present) /* zap previous help box if necessary */ { restore_screen_rectangle (help_box); help_present = 0; }; c = map_keypad_numbers (c); /* map keypad numbers to normal ones */ if ((! (c & 0x100)) && ((c & 0xFF) == 015)) c = KEY_DO | 0x100; /* make RETURN synonym for DO */ if (c & 0x100) /* function key? */ { switch (c & 0xFF) { case KEY_DOWN_ARROW: selection++; if (selection > length) selection = 1; break; case KEY_UP_ARROW: selection--; if (selection < 1) selection = length; break; case KEY_KEYPAD_ENTER: case KEY_DO: if (selection != 0) /* if something chosen */ { do_flag = 1; break; }; /* go for it */ FEEP; /* else feep and fall thru */ case KEY_HELP: /* to help */ help_box = pop_up_boxed_text (22, 2, "Use arrow keys to move up and down, or type the number of the item you want"); help_present = 1; break; default: #ifdef DEBUG sprintf (buf, "Invalid character 0x%3x", c); boxed_text (10, 10, buf); #endif FEEP; }; } else { /* Got a real character, see if number */ int i; i = (c & 0xFF) - '0'; if ((i < 1) || (i > length)) FEEP; else selection = i; }; if (old_selection != selection) { putattr_i (row + 2 + old_selection, col + 1, width + 4, ATTR_NORMAL); putattr_i (row + 2 + selection, col + 1, width + 4, ATTR_REVERSE); }; old_selection = selection; if (do_flag) break; }; item = &menu_addr[selection - 1]; /* Erase prompt line */ put_line (length + row + 4, col + 1, prompt_length + 2, blanks); putattr_i (length + row + 4, col + 1, prompt_length + 2, ATTR_NORMAL); /* If not active mode, just return selection to caller */ if (! (flags & MENU_ACTIVE_MODE)) { if (flags & MENU_POST_CLEAR) menu_clear_region (row, col, length, width); restore_screen_rectangle (saved_region); return (item->handler); }; /* If active mode, call routine or return if user chose DONE */ if (item->handler == DONE) { restore_screen_rectangle (saved_region); return (DONE); }; handler_routine = item->handler; (*handler_routine) (); putattr_i (row + 2 + selection, col + 1, width + 4, ATTR_NORMAL); /* If MENU_ONCE_ONLY, restore screen and return to caller */ if (flags & MENU_ONCE_ONLY) { restore_screen_rectangle (saved_region); return (DONE); }; }; } paint_menu (menu_addr, row, col, title, flags, length, width) struct menu_item menu_addr[]; int row, col, flags, length, width; char *title; { char buf[132]; int i; /* Clear screen, or menu region */ disable_cursor (); if (flags & MENU_CLEAR_SCREEN) clear_screen (); else /* clear rectangle to be occupied */ menu_clear_region (row, col, length, width); /* Now either quickly or slowly (animated) draw menu outlines */ if (flags & MENU_ANIMATE) for (i = 1; i <= length + 3; i++) /* animatedly draw rectangle */ { put_line (row + i - 1, col + 1, width + 4, blanks); rectangle (row, col, i, width + 5, ATTR_NORMAL); } else rectangle (row, col, length + 3, width + 5, ATTR_NORMAL); horizontal_cut (row + 2, col, width + 6, ATTR_NORMAL); /* title line */ /* Put title, reverse video, centered in title box at top of menu */ putattr_i (row + 1, col + 1, width + 4, ATTR_REVERSE); putline (row + 1, col + ((width+4)/2) - (strlen (title) / 2) + 1, title); /* Write the menu items and their numbers */ for (i = 0; (menu_addr[i].handler) != 0; i++) { sprintf (buf, " %d: %s", i + 1, menu_addr[i].name); putline (i + row + 3, col + 1, buf); }; enable_cursor (); } menu_clear_region (row, col, length, width) { int i; disable_cursor (); for (i = row; i <= row + length + 4; i++) /* clear menu */ { put_line (i, col, width + 5, blanks); putattr_i (i, col, width + 5, ATTR_NORMAL); }; enable_cursor (); } map_keypad_numbers (c) int c; { if (c & 0x100) /* if function key */ switch (c & 0xFF) { case KEY_KEYPAD_0: c = '0'; break; case KEY_KEYPAD_1: c = '1'; break; case KEY_KEYPAD_2: c = '2'; break; case KEY_KEYPAD_3: c = '3'; break; case KEY_KEYPAD_4: c = '4'; break; case KEY_KEYPAD_5: c = '5'; break; case KEY_KEYPAD_6: c = '6'; break; case KEY_KEYPAD_7: c = '7'; break; case KEY_KEYPAD_8: c = '8'; break; case KEY_KEYPAD_9: c = '9'; break; case KEY_KEYPAD_ENTER: c = KEY_DO | 0x100; break; }; return (c); } >>>>>>>> MODEM.C #include #define FALSE 0 #define TRUE 1 #define DOTS 50 /* SECTOR COUNTING DOTS PER LINE */ #define SECSIZ 0x80 #define BUFSIZ 0x1000 /* Text buffer */ #define ERRORMAX 20 /* MAX ERRORS BEFORE ABORT */ #define RETRYMAX 15 /* MAXIMUM RETRYS BEFORE ABORT */ #define SOH 1 /* START OF SECTOR CHAR */ #define EOT 4 /* end of transmission char */ #define ACK 6 /* acknowledge sector transmission */ #define NAK 21 /* error in transmission detected */ static char bufr[ BUFSIZ ], filename[ 14 ]; static int fd; int mtimeout; int mdm_packets_sent, mdm_packets_received, mdm_bad_packets, mdm_naked_packets; long mdm_bytes_xferred; extern jmp_buf abort_env, env; extern int debug; extern unsigned char read_modem (); mdmini() { mtimeout = 60; mdm_bytes_xferred = 0L; mdm_packets_sent = 0; mdm_packets_received = 0; mdm_bad_packets = 0; mdm_naked_packets = 0; } sendchar(data) unsigned int data; { unsigned char buf[1]; buf[0] = (unsigned char) data; write_modem (buf, 1); } readfile(file) char *file; { int firstchar, sectnum, sectcurr, sectcomp, errors, errorflag; unsigned int checksum, j, bufptr; mdmini (); if ((fd = creat(file,BWRITE)) < 0) { error("cannot open %s (%x)",file,fd); return(FALSE); } else printmsg("receiving %s",file); sectnum = errors = bufptr = 0; flushinput(); sendchar(NAK); if (setjmp(env)) return(FALSE); /* timeout */ if (setjmp(abort_env)) return(FALSE); while (firstchar != EOT && errors != ERRORMAX) { errorflag = FALSE; alarm (mtimeout); /* set timeout trap */ do /* get sync char */ { firstchar = read_modem(); if (debug) printf("Got char '%x'\n", firstchar); } while (firstchar != SOH && firstchar != EOT); if (firstchar == SOH) { sectcurr = read_modem(); sectcomp = read_modem(); if (debug) printf("Sector %x, ~%x\n", sectcurr, sectcomp); if ((sectcurr + sectcomp) == 255) { if (sectcurr == (sectnum + 1 & 0xff)) { checksum = 0; for (j = bufptr;j < (bufptr + SECSIZ);j++) { bufr[j] = read_modem(); checksum = (checksum + bufr[j]) & 0xff; } if (checksum == read_modem()) { mdm_packets_received++; mdm_notify_hook (); errors = 0; sectnum++; bufptr += SECSIZ; mdm_bytes_xferred += SECSIZ; if (bufptr == BUFSIZ) { bufptr = 0; if (write(fd,bufr,BUFSIZ) == EOF) { error("error writing file"); close(fd); alarm(0); return(FALSE); }; }; flushinput (); sendchar(ACK); } else { mdm_bad_packets++; mdm_notify_hook (); errorflag = TRUE; if (debug) { printmsg("checksum error, expected "); printmsg("<%02x>",checksum); }; } } else { if (sectcurr == (sectnum & 0xff)) { printmsg("received duplicate sector %d",sectnum); flushinput(); sendchar(ACK); } else { if (debug) error("synch error"); mdm_bad_packets++; mdm_notify_hook (); errorflag = TRUE; } } } else { if (debug) error("sector number error"); mdm_bad_packets++; mdm_notify_hook (); errorflag = TRUE; } } if (errorflag == TRUE) { errors++; printmsg("error %d",errors); flushinput(); sendchar(NAK); } }; /* end while */ if ((firstchar == EOT) && (errors < ERRORMAX)) { sendchar(ACK); write(fd,bufr,bufptr); close(fd); alarm(0); return(TRUE); } alarm(0); return(FALSE); } sendfile(file) char *file; { int sectnum, sectors, attempts; unsigned int checksum, j, bufptr; char c; mdmini (); if ((fd = open(file,BREAD)) < 0) { error("cannot open %s",file); return(FALSE); } else printmsg("sending %s",file); attempts = 0; sectnum = 1; j = 0; if (setjmp(env)) return(FALSE); if (setjmp(abort_env)) return(FALSE); alarm(mtimeout); while (((c = read_modem ()) != NAK) && (j++ < (ERRORMAX*2))) if (debug) printf ("Ate char '%x'\n", c); if (j >= (ERRORMAX*2)) { error("Receiver not sending NAKs"); alarm(0); return(FALSE); }; if (debug) printf ("Got ACK: '%x'\n", c); flushinput (); alarm(mtimeout); while ((sectors = read(fd,bufr,BUFSIZ)) && (attempts != RETRYMAX)) { if (sectors == EOF) { error("error reading file"); close(fd); alarm(0); return(FALSE); }; bufptr = 0; do { attempts = 0; do { alarm(mtimeout); if (debug) if (((sectnum - 1) % DOTS) == 0) printf("\012\015<%4d>.",sectnum); else printf("."); sendchar(SOH); sendchar(sectnum); sendchar(~sectnum); checksum = 0; write_modem(&bufr[bufptr],SECSIZ); for (j = bufptr; j < (bufptr+SECSIZ); j++) checksum += bufr[j]; sendchar(checksum); flushinput(); mdm_packets_sent++; mdm_notify_hook (); attempts++; c = read_modem(); if (c != ACK) mdm_naked_packets++; if (debug) printf ("Response char is '%x'\n", c); } while ((c != ACK) && (attempts != RETRYMAX)); bufptr += SECSIZ; mdm_bytes_xferred += SECSIZ; sectnum++; } while ((bufptr < sectors) && (attempts != RETRYMAX)); }; close(fd); if (attempts == RETRYMAX) { error("no acknowledgment of sector, aborting"); alarm(0); return(FALSE); } else { attempts = 0; do { sendchar(EOT); attempts++; } while ((read_modem() != ACK) && (attempts != RETRYMAX)); if (attempts == RETRYMAX) error("no acknowledgment of end of file"); }; alarm(0); return(TRUE); } >>>>>>>> RAINBOW.H /* * \usr\rainbow\rainbow.h * * Copyright (C) 1984 by Larry Campbell, 73 Concord St., Maynard Mass. * * This software may be freely copied and disseminated for * noncommercial purposes, if and only if this entire copyright * statement and notice is included intact. This software, and * the information contained herein, may not be used for commercial * purposes without my prior written permission. * * Hardware-specific definitions for the DEC Rainbow 100 (model A) */ #define LOOPS_PER_MILLISECOND 9 #define SCREEN_ROWS 24 #define SCREEN_COLUMNS 80 #define SCREEN_BUF_SIZE (ROM_SCRFRE + 1) #define SCREEN_BUF_SEG 0xEE00 #define SCREEN_BUF_OFFSET 0x0 #define SCREEN_ATTR_OFFSET 0x1000 /* * Attribute bits in attribute RAM */ #define ATTR_NORMAL 016 #define ATTR_REVERSE 017 #define ATTR_BOLD 014 #define ATTR_BLINK 012 #define ATTR_UNDERLINE 006 /* Combinations */ #define ATTR_BOLD_REVERSE 015 #define ATTR_BOLD_BLINK 010 #define ATTR_REVERSE_BLINK 013 #define FEEP putcon ('\007') /* ding */ /* LK201 function key codes as returned by ROM function 6 */ #define KEY_HELP 0 #define KEY_DO 1 #define KEY_COMPOSE_CHARACTER 2 #define KEY_PRINT_SCREEN 3 #define KEY_F4 5 #define KEY_INTERRUPT 7 #define KEY_RESUME 9 #define KEY_CANCEL 0xB #define KEY_MAIN_SCREEN 0xD #define KEY_EXIT 0xF #define KEY_ADDTNL_OPTIONS 0x11 #define KEY_F17 0x13 #define KEY_F18 0x15 #define KEY_F19 0x17 #define KEY_F20 0x19 #define KEY_FIND 0x1B #define KEY_INSERT_HERE 0x1D #define KEY_REMOVE 0x1F #define KEY_SELECT 0x21 #define KEY_PREV_SCREEN 0x23 #define KEY_NEXT_SCREEN 0x25 #define KEY_UP_ARROW 0x27 #define KEY_DOWN_ARROW 0x29 #define KEY_RIGHT_ARROW 0x2B #define KEY_LEFT_ARROW 0x2D #define KEY_KEYPAD_PF1 0x59 #define KEY_KEYPAD_PF2 0x5C #define KEY_KEYPAD_PF3 0x5F #define KEY_KEYPAD_PF4 0x62 #define KEY_KEYPAD_0 0x2F #define KEY_KEYPAD_1 0x32 #define KEY_KEYPAD_2 0x35 #define KEY_KEYPAD_3 0x38 #define KEY_KEYPAD_4 0x3B #define KEY_KEYPAD_5 0x3E #define KEY_KEYPAD_6 0x41 #define KEY_KEYPAD_7 0x44 #define KEY_KEYPAD_8 0x47 #define KEY_KEYPAD_9 0x4A #define KEY_KEYPAD_DASH 0x4D #define KEY_KEYPAD_COMMA 0x50 #define KEY_KEYPAD_PERIOD 0x53 #define KEY_KEYPAD_ENTER 0x56 #define HORIZ_BAR_CHAR 0x12 /* horizontal bar */ #define VERT_BAR_CHAR 0x19 /* vertical bar */ #define ULC_CHAR 0x0D /* upper left corner */ #define URC_CHAR 0x0C /* upper right corner */ #define LLC_CHAR 0x0E /* lower left corner */ #define LRC_CHAR 0x0B /* lower right corner */ #define CROSS_CHAR 0x0F /* crossing lines */ #define LEFT_T_CHAR 0x15 /* left T */ #define RIGHT_T_CHAR 0x16 /* right T */ #define TOP_T_CHAR 0x18 /* top T */ #define BOTTOM_T_CHAR 0x17 /* bottom T */ /* * Offsets into AUX ctl buffer (this stuff should really be in * RAINBOW.H) * */ #define AUX_FUNCTION 0 #define AUX_FUNC_RETC 1 #define AUX_CHARACTER 2 #define AUX_CHAR_STAT 3 #define AUX_BUFFER 4 #define AUX_CCB 4 #define CCB_DEVNUM 0 /* device number */ #define CCB_MODE 1 /* mode */ #define CCB_STOPB 2 /* stop bits */ #define CCB_DATAB 3 /* data bits */ #define CCB_XMITP 4 /* transmit parity */ #define CCB_RCVBD 5 /* receive baud */ #define CCB_XMTBD 6 /* transmit baud */ #define CCB_XONCH 7 /* XON character */ #define CCB_XOFCH 8 /* XOF character */ #define CCB_RCVXX 9 /* receive XON/XOF */ #define CCB_XMTXX 10 /* transmit XON/XOF */ #define CCB_ALTBUF 11 /* alternate buffer size */ #define CCB_BUFOFF 13 /* buffer offset */ #define CCB_BUFSEG 15 /* buffer segment */ >>>>>>>> VID2.C /* * \usr\c\vid2.c * * Copyright (C) 1984 by Larry Campbell, 73 Concord St., Maynard Mass. * * This software may be freely copied and disseminated for * noncommercial purposes, if and only if this entire copyright * statement and notice is included intact. This software, and * the information contained herein, may not be used for commercial * purposes without my prior written permission. * * * Low-level video hacking routines. Originally written for the DEC * Rainbow and slowly trying to become more hardware-independent. * */ #include #include "video.h" #include "rainbow.h" int cursor_row, cursor_column; /* * putline (row, column, string) * * Rapidly put text to screen * */ putline (row, col, string) int row, col; char *string; { int count; count = strlen (string); #ifdef DEBUG if (row < 1) row = 1; if (row > SCREEN_ROWS) row = SCREEN_ROWS; if (col < 1) col = 1; if ((col + count) > SCREEN_COLUMNS + 1) count = (SCREEN_COLUMNS + 1) - col; #endif if (count > 0) put_line (row, col, count, string); } /* * putcons (string) * * Writes escape sequence to console via ROM call (bypassing * DOS to avoid keyboard input meddling) */ putcons (string) char *string; { char c; while ((c = *string++) != 0) putcon (c); } clear_rest_of_line () { putcons ("\033[K"); } cursor (row, column) int row, column; { char buf[32]; cursor_row = row; cursor_column = column; sprintf (buf, "\033[%d;%dH", row, column); putcons (buf); } double_height_top (row) int row; { cursor (row, 1); putcons ("\033#3"); } double_height_bottom (row) int row; { cursor (row, 1); putcons ("\033#4"); } double_width (row) int row; { cursor (row, 1); putcons ("\033#6"); } /* * put_line_attr (row, length, attribute) * * Set attribute for an entire line */ put_line_attr (row, n, attr) int row, n, attr; { int i; char line_buf[132]; for (i = 0; i < n; i++) line_buf[i] = (char) attr; putattr (row, 1, n, line_buf); } /* * putattr_i (row, column, length, attribute) * * Set attribute for string of characters */ putattr_i (row, col, n, attr) int row, col, n, attr; { char abuffer[132]; int i; for (i = 0; i < n; i++) abuffer[i] = attr; putattr (row, col, n, abuffer); } /* * Draw a rectangle * Parameters: * ulr, ulc - upper left row, upper left column * h, w - height, width * attr - attribute bits */ rectangle (ulr, ulc, h, w, attr) int ulr, ulc, h, w, attr; { int lrr, lrc, row, column; char cbuffer[133], abuffer[133]; disable_cursor (); lrr = ulr + h; lrc = ulc + w; cbuffer[0] = ULC_CHAR; /* upper left corner */ abuffer[0] = attr; for (column = ulc + 1; column < lrc; column++) { cbuffer[column - ulc] = HORIZ_BAR_CHAR; /* horizontal line */ abuffer[column - ulc] = attr; /* attribute bits */ }; cbuffer[lrc - ulc] = URC_CHAR; /* upper right corner */ abuffer[lrc - ulc] = attr; cbuffer[(lrc - ulc) + 1] = 0; putline (ulr, ulc, cbuffer); putattr (ulr, ulc, (lrc - ulc) + 1, abuffer); for (row = ulr + 1; row < lrr; row++) { cbuffer[0] = 0x19; /* vertical bar */ cbuffer[1] = 0; putline (row, ulc, cbuffer); putattr (row, ulc, 1, abuffer); putline (row, lrc, cbuffer); putattr (row, lrc, 1, abuffer); }; cbuffer[0] = LLC_CHAR; /* lower left corner */ abuffer[0] = attr; for (column = ulc + 1; column < lrc; column++) { cbuffer[column - ulc] = HORIZ_BAR_CHAR; /* horizontal line */ abuffer[column - ulc] = attr; /* attribute bits */ }; cbuffer[lrc - ulc] = LRC_CHAR; /* lower right corner */ abuffer[lrc - ulc] = attr; cbuffer[(lrc - ulc) + 1] = 0; putline (lrr, ulc, cbuffer); putattr (lrr, ulc, (lrc - ulc) + 1, abuffer); enable_cursor (); } /* * Section an existing rectangle, either horizontally or vertically * */ horizontal_cut (row, column, length, attr) int row, column, length; { int n; char cbuffer[133], abuffer[133]; cbuffer[0] = LEFT_T_CHAR; /* left T */ abuffer[0] = attr; for (n = 1; n < (length - 1); n++) { cbuffer[n] = HORIZ_BAR_CHAR; /* horizontal line */ abuffer[n] = attr; }; cbuffer[n] = RIGHT_T_CHAR; /* right T */ abuffer[n] = attr; cbuffer[n + 1] = 0; putline (row, column, cbuffer); putattr (row, column, length, abuffer); } vertical_cut (row, column, length, attr) int row, column, length, attr; { int this_row; char cbuffer[2], abuffer[1]; cbuffer[0] = TOP_T_CHAR; cbuffer[1] = 0; putline (row, column, cbuffer); abuffer[0] = attr; putattr (row, column, 1, abuffer); cbuffer[0] = VERT_BAR_CHAR; for (this_row = row + 1; this_row < (row + length - 1); this_row++) { putline (this_row, column, cbuffer); putattr (this_row, column, 1, abuffer); }; cbuffer[0] = BOTTOM_T_CHAR; putline (row + length - 1, column, cbuffer); /* Bottom T */ putattr (row + length - 1, column, 1, abuffer); } kbdin () { int c; c = getkey (); if (c == -2) /* if interference from DOS */ c = bdos (7, 0) & 0x77; /* and get char from DOS */ return (c); } boxed_text (row, col, text) int row, col; char *text; { int length; #define MAX_ROW SCREEN_ROWS - 2 length = strlen (text); if (row > MAX_ROW) row = MAX_ROW; if (row < 1) row = 1; if (col < 1) col = 1; if ((col + length) > SCREEN_COLUMNS) length = SCREEN_COLUMNS - col; rectangle (row, col, 2, length + 1, ATTR_NORMAL); putline (row + 1, col + 1, text); } >>>>>>>> VIDEO.H /* * \USR\C\VIDEO.H * * Copyright (C) 1984 by Larry Campbell, 73 Concord St., Maynard Mass. * * This software may be freely copied and disseminated for * noncommercial purposes, if and only if this entire copyright * statement and notice is included intact. This software, and * the information contained herein, may not be used for commercial * purposes without my prior written permission. * * Video hacking definitions * */ #define MENU_CLEAR_SCREEN 2 /* clear screen before drawing menu */ #define MENU_ANIMATE 4 /* draw menu like window shade */ #define MENU_POST_CLEAR 8 /* clear menu from screen when done */ #define MENU_ACTIVE_MODE 16 /* menu actively calls semantic routines, quits when "done" entry selected */ #define MENU_ONCE_ONLY 32 /* call just one routine then quit */ #define DONE -1 struct menu_item { char *name; int (*handler) (); }; #define WAIT_FOR_ANY_KEY while (kbdin () < 0) struct saved_video { struct saved_video *next; #ifdef DEBUG int magic; #endif int length; int row; int col; char *text; char *attributes; }; >>>>>>>> WINDOW.C /* * \usr\c\window.c * * Copyright (C) 1984 by Larry Campbell, 73 Concord St., Maynard Mass. * * This software may be freely copied and disseminated for * noncommercial purposes, if and only if this entire copyright * statement and notice is included intact. This software, and * the information contained herein, may not be used for commercial * purposes without my prior written permission. * * High-level screen management routines - provide rudimentary * window-oriented functionality for character-mapped video displays. * Based on low-level video functions supplied by vid2.c. */ #include #include "video.h" #include "rainbow.h" char screen_chars[SCREEN_ROWS * SCREEN_COLUMNS]; char screen_attributes[SCREEN_ROWS * SCREEN_COLUMNS]; /* * Copy counted string to screen, copying to our own area */ put_line (row, col, count, string) int row, col, count; char *string; { int k, index; char *sp, *dp; dp = &screen_chars[(row - 1) * SCREEN_COLUMNS + (col - 1)]; sp = string; movmem (sp, dp, count); _put_line (row, col, count, string); /* call hardware-dependent routine */ } /* * Put attributes to screen */ putattr (row, col, count, string) int row, col, count; char *string; { int k, index; char *sp, *dp; dp = &screen_attributes[(row - 1) * SCREEN_COLUMNS + (col - 1)]; sp = string; movmem (sp, dp, count); _putattr (row, col, count, string); /* call hardware-dependent routine */ } /* * getline (row, col, dest, n) * * Return state of character cells on screen */ getline (row, col, dest, n) int row, col, n; char *dest; { char *sp; sp = &screen_chars[((row - 1) * SCREEN_COLUMNS) + (col - 1)]; movmem (sp, dest, n); } /* * getattr (row, col, dest, n) * * Like getline but gets attributes */ getattr (row, col, dest, n) int row, col, n; char *dest; { char *sp; sp = &screen_attributes[((row - 1) * SCREEN_COLUMNS) + (col - 1)]; movmem (sp, dest, n); } clear_screen () { int j, k; putcons ("\033[2J"); setmem (screen_chars, SCREEN_ROWS * SCREEN_COLUMNS, 0); setmem (screen_attributes, SCREEN_ROWS * SCREEN_COLUMNS, ATTR_NORMAL); } /* * save_screen_rectangle * * Returns pointer to chain of 'struct saved_video' nodes. */ struct saved_video *save_screen_rectangle (row, col, h, w) int row, col, h, w; { int r; struct saved_video dummy, *prev, *ptr; disable_cursor (); #ifdef DEBUG if (row < 1 || (row + h - 1) > SCREEN_ROWS || col < 1 || (col + w - 1) > SCREEN_COLUMNS) { printf ("\n?BAD ARGS TO SAVE_SCREEN_RECTANGLE\n"); exit (); }; #endif ptr = &dummy; for (r = row; r < row + h; r++) { prev = ptr; ptr = malloc (sizeof (struct saved_video)); if (ptr == NULL) { printf ("\n?MALLOC\n"); exit (); }; prev->next = ptr; ptr->next = 0; #ifdef DEBUG ptr->magic = 12321; #endif ptr->row = r; ptr->col = col; ptr->length = w; ptr->text = malloc (w); ptr->attributes = malloc (w); getline (r, col, ptr->text, w); getattr (r, col, ptr->attributes, w); }; enable_cursor (); return (dummy.next); } /* restore_screen_rectangle * * Restores characters and attributes saved by 'save_screen_rectangle', * and returns storage to heap. */ restore_screen_rectangle (ptr) struct saved_video *ptr; { struct saved_video *next; disable_cursor (); while (ptr != 0) { #ifdef DEBUG if (ptr->magic != 12321) { printf ("\n? BAD NODE IN RESTORE_SCREEN_RECTANGLE\n"); exit (); }; #endif put_line (ptr->row, ptr->col, ptr->length, ptr->text); putattr (ptr->row, ptr->col, ptr->length, ptr->attributes); next = ptr->next; free (ptr->text); free (ptr->attributes); free (ptr); ptr = next; }; enable_cursor (); } struct saved_video *pop_up_boxed_text (row, col, text) int row, col; char *text; { int length; struct saved_video *box; #define MAX_ROW SCREEN_ROWS - 2 length = strlen (text); if (row > MAX_ROW) row = MAX_ROW; if (row < 1) row = 1; if (col < 1) col = 1; if ((col + length + 1) > SCREEN_COLUMNS) length = SCREEN_COLUMNS - col - 1; box = save_screen_rectangle (row, col, 3, length + 2); rectangle (row, col, 2, length + 1, ATTR_NORMAL); putline (row + 1, col + 1, text); return (box); } /* * pop_up_get_string * * Pop up a rectangle with a prompt, get a string, strip off * the newline, and disappear the box, restoring what it covered */ pop_up_get_string (row, col, prompt, buf, len) int row, col, len; char *prompt, *buf; { struct saved_video *save; int prompt_length, k, width; prompt_length = strlen (prompt); width = prompt_length + len; save = save_screen_rectangle (row, col, 3, width + 1); rectangle (row, col, 2, width, ATTR_NORMAL); putline (row + 1, col + 1, prompt); cursor (row + 1, col + prompt_length + 2); fgets (buf, len, stdin); for (k = 0; k < len; k++) { if (buf[k] == 0) break; if (buf[k] == '\n') { buf[k] = 0; break; }; }; restore_screen_rectangle (save); }