mat@emcard.UUCP (Mat Waites) (01/03/89)
I had pretty good response for the source code to this terminal program,
so I am posting it.
It is for the C64 and Power C compiler.
Note that two of the files are for Unix, not for the C64.
I hope to add Punter protocol to this as I have time.
#!/bin/sh
# shar: Shell Archiver (v1.22)
#
# Run the following text with /bin/sh to create:
# ReadMe
# asctocbm.c
# cbmtoasc.c
# cmast.c
# dial.c
# dos.c
# menus.c
# screen.c
# xmodem.c
#
sed 's/^X//' << 'SHAR_EOF' > ReadMe &&
XThis is the first UseNet distribution of the Cmaster terminal program.
X
XThese are the files in the distribution:
X
Xasctocbm.c
Xcbmtoasc.c
Xcmast.c
Xdial.c
Xdos.c
Xmenus.c
Xscreen.c
Xxmodem.c
X
X
Xasctocbm.c and cbmtoasc.c are unix utilities to convert to Commodore ascii
Xand vice versa.
X
XThe rest are Power C source code for the terminal.
X
Xcmast.c - main program
Xdial.c - hayes dialer
Xdos.c - dos support, including serial port routines
Xmenus.c - menu for setting parameters
Xscreen.c - screen access routines, color, cursor positioning, etc.
Xxmodem.c - xmodem protocol
X
XWhen linking, you will have to link libraries after linking 3 or so files,
Xand then continue with the linking process. The linker cannot hold all of the
Xreferences in one pass.
X
XHave fun and send me comments.
X
XW Mat Waites
Xgatech!emcard!mat
X8-5 ET: (404) 727-7197
SHAR_EOF
chmod 0664 ReadMe || echo "restore of ReadMe fails"
sed 's/^X//' << 'SHAR_EOF' > asctocbm.c &&
X/* asctocbm.c - convert real ascii to cbm ascii */
X
X#include <stdio.h>
X#include <strings.h>
X#include <ctype.h>
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X FILE *infile, *outfile;
X char *strchr();
X int i;
X char nambuf[30];
X char stripped[30];
X
X if(argc > 1)
X {
X for(i=1; i<argc; i++)
X {
X strcpy(stripped, argv[i]);
X if(strchr(stripped, '.'))
X {
X *strchr(stripped, '.') = '\0';
X }
X fprintf(stderr, "Translating %s\n", stripped);
X
X strcpy(nambuf, stripped);
X strcat(nambuf, ".c");
X if(infile = fopen(nambuf, "r"))
X {
X strcpy(nambuf, stripped);
X strcat(nambuf, ".cbm");
X if(outfile = fopen(nambuf, "w"))
X {
X convert(infile, outfile);
X fclose(outfile);
X }
X else
X {
X fprintf(stderr, "Couldn't open %s\n", nambuf);
X }
X fclose(infile);
X }
X else
X {
X fprintf(stderr, "Couldn't open %s\n", nambuf);
X }
X }
X }
X else
X {
X convert(stdin, stdout);
X }
X
X}
X
Xconvert(infile, outfile)
XFILE *infile, *outfile;
X{
X int c, a;
X
X while((c=getc(infile)) != EOF)
X {
X if(c == '\n')
X {
X a = '\r';
X }
X else if(c >= 'a' && c <= 'z')
X {
X a = c - 'a' + 'A';
X }
X else if(c >= 'A' && c <= 'Z')
X {
X a = c - 'A' + 193;
X }
X else if(c == '~')
X {
X a = 175;
X }
X else if(c == '{')
X {
X a = 219;
X }
X else if(c == '}')
X {
X a = 221;
X }
X else if(c == '|')
X {
X a = 223;
X }
X else if(isprint(c))
X {
X a = c;
X }
X else if(c == 0)
X {
X continue;
X }
X else
X {
X fprintf(outfile, "{{%d}}", c);
X continue;
X }
X putc(a, outfile);
X }
X}
X
SHAR_EOF
chmod 0660 asctocbm.c || echo "restore of asctocbm.c fails"
sed 's/^X//' << 'SHAR_EOF' > cbmtoasc.c &&
X/* cbmtoasc.c - convert cbm ascii to real ascii */
X
X#include <stdio.h>
X#include <strings.h>
X#include <ctype.h>
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X FILE *infile, *outfile;
X char *strchr();
X int i;
X char nambuf[30];
X char stripped[30];
X
X if(argc > 1)
X {
X for(i=1; i<argc; i++)
X {
X strcpy(stripped, argv[i]);
X if(strchr(stripped, '.'))
X {
X *strchr(stripped, '.') = '\0';
X }
X fprintf(stderr, "Translating %s\n", stripped);
X
X strcpy(nambuf, stripped);
X strcat(nambuf, ".cbm");
X if(infile = fopen(nambuf, "r"))
X {
X strcpy(nambuf, stripped);
X strcat(nambuf, ".c");
X if(outfile = fopen(nambuf, "w"))
X {
X convert(infile, outfile);
X fclose(outfile);
X }
X else
X {
X fprintf(stderr, "Couldn't open %s\n", nambuf);
X }
X fclose(infile);
X }
X else
X {
X fprintf(stderr, "Couldn't open %s\n", nambuf);
X }
X }
X }
X else
X {
X convert(stdin, stdout);
X }
X
X}
X
X
Xconvert(infile, outfile)
XFILE *infile, *outfile;
X{
X int c, a;
X
X while((c=getc(infile)) != EOF)
X {
X if(c == '\r')
X {
X a = '\n';
X }
X else if(c >= 'A' && c <= 'Z')
X {
X a = c - 'A' + 'a';
X }
X else if(c >= 193 && c <= 218)
X {
X a = c - 193 + 'A';
X }
X else if(c == 175)
X {
X a = '~';
X }
X else if(c == 219)
X {
X a = '{';
X }
X else if(c == 221)
X {
X a = '}';
X }
X else if(c == 223)
X {
X a = '|';
X }
X else if(isprint(c))
X {
X a = c;
X }
X else if(c == 0)
X {
X continue;
X }
X else
X {
X /* fprintf(outfile, "{{%d}}", c); */
X continue;
X }
X putc(a, outfile);
X }
X}
X
SHAR_EOF
chmod 0660 cbmtoasc.c || echo "restore of cbmtoasc.c fails"
sed 's/^X//' << 'SHAR_EOF' > cmast.c &&
X/* cmast.c - main for cmaster */
X/* W Mat Waites - Sept 1988 */
X
X#include <stdio.h>
X
X#define DEFBAUD 1200
X#define DEFDRIVE 8
X#define DEFMODE 1
X#define DEFLF 0
X#define DEFFLOW 0
X
X/* globals */
Xint echo;
Xint baud;
Xint bpchar;
Xint stopbits;
Xint parity;
Xint ddrive;
Xint done;
Xint asciimode;
Xint autolf;
Xint flowcont;
X
X/* main() - main program for cmast */
Xmain(argc, argv)
Xunsigned argc;
Xchar *argv[];
X{
X int kbchar, serchar;
X int outch;
X char *qtsw = 0x00d4;
X
X /* initialization */
X done = 0;
X echo = 0;
X baud = DEFBAUD;
X bpchar = 8;
X stopbits = 1;
X parity = 0; /* 0 - none */
X ddrive = DEFDRIVE;
X asciimode = DEFMODE;
X autolf = DEFLF;
X flowcont = DEFFLOW;
X
X /* check for baud rate parameter */
X if(argc > 1)
X {
X baud = atoi(argv[1]);
X switch(baud)
X {
X case 300:
X case 450:
X case 1200:
X break;
X default:
X baud = DEFBAUD;
X break;
X }
X }
X
X /* open files */
X openkb();
X openserial();
X setserial(baud, bpchar,
X stopbits, parity);
X
X /* set colors */
X setborder(15);
X setbg(0);
X setfg(1);
X
X initscr();
X titlescr();
X sleep(2);
X
X erase();
X move(0, 0);
X cursoron();
X updatecursor();
X
X /* main loop */
X while(!done)
X {
X
X /* check for <C=> key */
X if(chkstop())
X {
X cursoroff();
X menu();
X updatecursor();
X cursoron();
X }
X
X /* check keyboard */
X while(charsinq() > 0 && !done)
X {
X kbchar = getkb();
X
X if(kbchar >= 133 &&
X kbchar <= 140)
X {
X /* function keys */
X putfunct(kbchar);
X }
X else
X {
X /* non-function keys */
X if(echo) /* local echo */
X {
X if(isprint(kbchar) ||
X iscntrl(kbchar))
X {
X putchar(kbchar);
X updatecursor();
X }
X }
X outch = cbmtoasc(kbchar);
X if(outch)
X {
X putserial(outch);
X }
X }
X }
X
X /* check serial port */
X if(!done)
X {
X while((serchar=getserial()) >= 0)
X {
X if(asciimode)
X {
X /* mask to 7 bits */
X serchar &= 0x7f;
X switch(serchar)
X {
X case 7: /* BEL */
X break;
X case 8: /* BS */
X putchar(157);
X break;
X case 9: /* TAB */
X putchar(' ');
X putchar(' ');
X break;
X case 10: /* LF */
X putchar(17);
X break;
X case 12: /* FF */
X erase();
X break;
X case 13: /* CR */
X putchar(13);
X if(!autolf)
X {
X putchar(145); /* move up */
X }
X break;
X default:
X outch=asctocbm(serchar);
X if(outch)
X {
X putchar(outch);
X }
X else /* unexpected char */
X {
X /*printf("[%d]", serchar);*/
X /*putchar(serchar);*/
X }
X break;
X }
X }
X else
X {
X putchar(serchar);
X }
X *qtsw = 0;
X updatecursor();
X if(charsinq() > 0 || chkstop())
X {
X break;
X }
X }
X }
X }
X
X /* shut down */
X cursoroff();
X erase();
X closekb();
X closeserial();
X move(23, 0);
X}
X
X/* cmaster support routines */
X
X/* titlescr() - initial display */
Xtitlescr()
X{
X erase();
X center(5, "Cmaster Terminal");
X center(15, "Press <C=> for menu");
X}
X
X/* cbmtoasc() - convert cbm to ascii */
Xcbmtoasc(cbmchar)
Xint cbmchar;
X{
X if(!asciimode)
X {
X return(cbmchar);
X }
X
X /* lower case */
X if(cbmchar >= 65 && cbmchar <= 90)
X {
X return(cbmchar + 32);
X }
X
X /* upper case */
X if(cbmchar >= 193 && cbmchar <= 218)
X {
X return(cbmchar - 128);
X }
X
X if(cbmchar == 20) /* backspace */
X {
X return(8);
X }
X
X return(cbmchar);
X}
X
X/* asctocbm() - convert ascii to cbm */
Xasctocbm(ascchar)
Xint ascchar;
X{
X if(!asciimode)
X {
X return(ascchar);
X }
X
X /* upper case */
X if(ascchar >= 65 && ascchar <= 90)
X {
X return(ascchar + 128);
X }
X
X /* lower case */
X if(ascchar >= 97 && ascchar <= 122)
X {
X return(ascchar - 32);
X }
X
X if(ascchar >= 32 && ascchar <= 64)
X {
X return(ascchar);
X }
X
X if(ascchar >= 91 && ascchar <= 95)
X {
X return(ascchar);
X }
X
X return 0;
X}
X
X/* putserstr() - put string to port */
Xputserstr(str)
Xchar *str;
X{
X while(*str)
X {
X putserial(cbmtoasc((int)*str));
X str++;
X }
X}
X
Xstatic char *funcstr[8] =
X {
X "Function Key 1\n",
X "Function Key 3\n",
X "Function Key 5\n",
X "Function Key 7\n",
X "Function Key 2\n",
X "Function Key 4\n",
X "Function Key 6\n",
X "Function Key 8\n"
X };
X
X/* putfunct() - put function key string */
Xputfunct(key)
Xint key;
X{
X unsigned lockey;
X
X if(key < 133 || key > 140)
X {
X return;
X }
X
X lockey = key - 133;
X
X putserstr(funcstr[lockey]);
X
X}
X/* end of file */
SHAR_EOF
chmod 0664 cmast.c || echo "restore of cmast.c fails"
sed 's/^X//' << 'SHAR_EOF' > dial.c &&
X/* dial.c - dial routines for cmaster */
X/* W Mat Waites - Sept 1988 */
X
X#include <stdio.h>
X#include <strings.h>
X
X#define DIALTIME 20
X#define WAITTIME 5
X#define NUMTRIES 5
X
Xchar *prefix = "atdt";
Xchar *suffix = "\r";
Xchar *attnstr = "+++";
Xchar *hangupstr = "ath\r";
Xchar *initstr = "ats7=45e0q0v1x4\r";
X
Xchar *moddial();
X
Xstatic int tmo;
X
X/* dial() - main dialing menu */
Xdial()
X{
X int len, i, nt, wt, dt;
X char numbuf[21];
X char *msg;
X
X nt = NUMTRIES;
X wt = WAITTIME;
X dt = DIALTIME;
X
X center(1, "Cmaster Dialing Menu");
X
X putmodstr(initstr);
X sleep(1);
X while(getserial() >= 0)
X {
X }
X
X move(5, 5);
X printf("Number: ");
X len = getstring(numbuf, 20);
X if(len <= 0)
X {
X return(0);
X }
X
X move(8, 5);
X printf("Trying %2d times:\n", nt);
X
X for(i=1; i<=nt; i++)
X {
X move(10, 5);
X printf("Dialing %s try %2d\n",
X numbuf, i);
X while(getserial() >= 0)
X {
X }
X msg = moddial(numbuf, dt);
X
X if(atoi(msg) > 0)
X {
X move(12, 5);
X printf("Connected!\n");
X sleep(1);
X return(1);
X }
X else
X {
X move(14, 5);
X printf("Dial failed - %s\n", msg);
X if(strcmp(msg, "ABORT") == 0)
X {
X sleep(3);
X return(0);
X }
X if(i <= nt) /* tries left? */
X {
X sleep(wt);
X }
X }
X }
X return(0);
X}
X
X/* moddial() - main dialing menu */
Xstatic char *moddial(numstr, dtime)
Xchar *numstr;
Xint dtime;
X{
X int i, skip, timer, modch, rc;
X char s[50], number[40], rcbuf[60];
X char *n;
X
X s[0] = '\0';
X strcpy(s, prefix);
X
X /* clean up number */
X i = 0;
X skip = 0;
X n = numstr;
X while (*n)
X {
X if(*n == '\\' && !skip)
X {
X skip++;
X n++;
X continue;
X }
X if(!index("-() ", *n) || skip)
X number[i++] = *n;
X n++;
X skip = 0;
X }
X number[i] = '\0';
X
X strcat(s, number);
X strcat(s, suffix);
X
X putmodstr(s);
X
X rc=0;
X timer=0;
X rcbuf[0] = '\0';
X
X while(rc < 59 && timer < dtime)
X {
X modch = getmodch(1);
X if(!tmo)
X {
X /* ignore LF */
X if(modch == 0x0a)
X {
X continue;
X }
X
X /* ignore leading CR */
X if(modch == 0x0d)
X {
X if(rc == 0)
X {
X continue;
X }
X modch = '!';
X }
X
X rcbuf[rc] = modch;
X rcbuf[rc+1] = '\0';
X rc++;
X }
X else
X {
X timer++;
X }
X
X /* printf("answer is '%s'\n", rcbuf); */
X
X if(strcmp(rcbuf, "connect!") == 0)
X return("300");
X
X if(strcmp(rcbuf, "connect 1200!") == 0)
X return("1200");
X
X if(strcmp(rcbuf, "busy!") == 0)
X return("BUSY");
X
X if(strcmp(rcbuf, "voice!") == 0)
X return("VOICE");
X
X if(strcmp(rcbuf, "no carrier!") == 0)
X return("NO CARRIER");
X
X if(chkstop())
X {
X /* aborted */
X putmodstr("\r");
X sleep(1);
X while(getserial() >= 0)
X {
X }
X return("ABORT");
X }
X
X }
X
X /* didn't connect */
X putmodstr("\r");
X sleep(1);
X while(getserial() >= 0)
X {
X }
X return("ERROR");
X}
X
X/* modhangup() - hangup modem */
Xmodhangup()
X{
X char *match;
X
X sleep(2);
X putmodstr(attnstr);
X sleep(2);
X putmodstr(hangupstr);
X sleep(1);
X while(getserial() >= 0)
X {
X }
X}
X
X/* putmodstr() - put string to modem */
Xstatic putmodstr(str)
Xchar *str;
X{
X while(*str)
X {
X putserial(*str);
X str++;
X }
X}
X
X/* getmodch() - get char w/timeout */
Xstatic getmodch(timlen)
Xint timlen;
X{
X int serchar;
X
X tmo = 0;
X setclock((unsigned)0); /* start timer */
X
X for(;;)
X {
X
X serchar = getserial();
X if(serchar >= 0)
X {
X return(serchar);
X }
X
X if(getclock() >= timlen)
X {
X tmo = 1;
X return 0;
X }
X }
X}
X
X/* end of file */
SHAR_EOF
chmod 0664 dial.c || echo "restore of dial.c fails"
sed 's/^X//' << 'SHAR_EOF' > dos.c &&
X/* dos2.c - operating system stuff:
X disk support
X serial i/o
X kb i/o
X timers */
X/* W Mat Waites - Sept 1988 */
X
X#include <stdio.h>
X
X/* 5-9 may be used with "basic" open */
X#define KB 5
X#define RS 6
X
X/* kludge for reliable 1200 baud */
X#define KLUDGE 40
X
X/* flow control params */
X#define FLOWON 30
X#define FLOWOFF 128
X#define XON 17
X#define XOFF 19
X
X/* kernel routines */
X#define CHKIN 0xffc6
X#define GETIN 0xffe4
X#define TKSA 0xff96
X#define ACPTR 0xffa5
X#define TALK 0xffb4
X#define UNTLK 0xffab
X
X/* input and output serial buffers */
Xstatic char inbuf[256], otbuf[256];
X
X/* flow control turned on? */
Xchar flowact = 1;
X
X/* serial interface functions */
X
X/* openserial() - open serial port */
Xopenserial()
X{
X short *ribuf = 0x00f7;
X short *robuf = 0x00f9;
X
X /* open serial port */
X open(RS, 2, 0, "");
X
X /* move pointers to buffers */
X *ribuf = inbuf;
X *robuf = otbuf;
X}
X
X/* closeserial() - close serial port */
Xcloseserial()
X{
X close(RS);
X}
X
X/* 300, 450, 1200 implemented */
X
Xstatic short hibyte[3] = { 6, 4, 1};
Xstatic short lobyte[3] = {68, 12, 61};
X
X/* setserial() - set serial port */
Xsetserial(bd, bpc, sb, par)
Xint bd, bpc, sb, par;
X{
X short *m51ajb = 0x0295;
X short *baudof = 0x0299;
X char *m51ctr = 0x0293;
X char *m51cdr = 0x0294;
X char *bitnum = 0x0298;
X unsigned indx;
X
X switch(bd)
X {
X case 300:
X indx = 0;
X break;
X case 450:
X indx = 1;
X break;
X case 1200:
X indx = 2;
X break;
X default: /* default to 300 baud */
X indx = 0;
X break;
X }
X
X /* set baud rate */
X *m51ajb = 256 * hibyte[indx] +
X lobyte[indx];
X *baudof = (*m51ajb)*2 + 200;
X
X /* stopbits */
X if(sb < 1 || sb > 2)
X {
X sb = 1;
X }
X sb--;
X
X /* bits per char */
X if(bpc < 5 || bpc > 8)
X {
X bpc = 8;
X }
X *bitnum = (char)(bpc + 1);
X bpc = 8 - bpc;
X
X /* parity */
X if(par < 0 || par > 7)
X {
X par = 0;
X }
X
X /* put bpc, sb, and par in regs */
X *m51ctr = (char)((bpc << 5)
X | (sb << 7));
X *m51cdr = (char)(par << 5);
X}
X
X/* setflow() - set flowcontrol */
Xsetflow(mode)
Xint mode;
X{
X flowact = mode;
X}
X
X
X/* getserial() - char from serial port */
Xgetserial()
X{
X int ch;
X char diff;
X static char *rsstat = 0x0297;
X static char *ridbe = 0x029b;
X static char *ridbs = 0x029c;
X static char flowing = 1;
X
X ch = getonechar(RS);
X
X /* check for empty buffer */
X if((*rsstat & 0x08) == 0x08)
X {
X return -1;
X }
X else
X {
X if(flowact)
X {
X /* check for flow control */
X if(*ridbs > *ridbe)
X {
X diff = *ridbs - *ridbe;
X }
X else
X {
X diff = *ridbe - *ridbs;
X }
X
X if(flowing)
X {
X if(diff > FLOWOFF)
X {
X putserial(XOFF);
X flowing = 0;
X }
X }
X else
X {
X if(diff < FLOWON)
X {
X putserial(XON);
X flowing = 1;
X }
X }
X }
X return ch;
X }
X}
X
X/* putserial() - char to serial port */
Xputserial(ch)
Xchar ch;
X{
X int i;
X
X putc(ch, RS);
X
X /* delay loop for 1200 baud kludge */
X for(i=0; i<KLUDGE; i++)
X {
X }
X}
X
X
X/* keyboard interface functions */
X
X/* openkb() - open keyboard */
Xopenkb()
X{
X char *rptflg = 0x028a;
X
X open(KB, 0, 0, "");
X /* let the keyboard repeat */
X *rptflg = 0x80;
X}
X
X/* closekb() - close keyboard */
Xclosekb()
X{
X close(KB);
X}
X
X/* getkb() - get char from keyboard */
Xgetkb()
X{
X return getonechar(KB);
X}
X
X/* charsinq() - # available kb chars */
Xcharsinq()
X{
X char *ndx = 0x00c6;
X
X return (int)*ndx;
X}
X
X/* chkstop() - check for <C=> key */
Xchkstop()
X{
X char *shflag = 0x028d;
X
X return(*shflag == 0x02);
X}
X
X/* getonechar() - get char from chan */
Xstatic getonechar(channel)
Xint channel;
X{
X char ac, xc, yc;
X
X xc = (char)channel;
X sys(CHKIN, &ac, &xc, &yc);
X sys(GETIN, &ac, &xc, &yc);
X return(int)ac;
X}
X
X
X/* disk i/o functions */
X
X#define SADDR 0x6f
X
X/* diskerr() - read error channel */
Xchar *diskerr(disk)
Xint disk;
X{
X int cc;
X char ac, xc, yc;
X static char msgbuf[41];
X char *mp;
X char *second = 0x00b9;
X char *status = 0x0090;
X
X /* tell drive to talk */
X ac = (char)disk;
X sys(TALK, &ac, &xc, &yc);
X
X /* tell it what to talk about */
X ac = (char)SADDR;
X *second = SADDR;
X sys(TKSA, &ac, &xc, &yc);
X
X /* read in the response */
X mp = msgbuf;
X for(;;)
X {
X /* get byte from bus in acc */
X sys(ACPTR, &ac, &xc, &yc);
X
X if(ac == '\r')
X {
X break;
X }
X *mp = ac;
X mp++;
X }
X *mp = '\0';
X
X /* tell drive to shut up */
X sys(UNTLK, &ac, &xc, &yc);
X
X return(msgbuf);
X}
X
X
X/* timer functions */
X
Xunsigned getclock();
X
X/* sleep() - sleep for seconds */
Xsleep(usecs)
Xunsigned usecs;
X{
X setclock((unsigned)0);
X
X while(getclock() < usecs)
X {
X }
X}
X
Xstruct clock /* struct matches CIA */
X {
X char tenths;
X char seconds;
X char minutes;
X char hours;
X };
X
X/* setclock() - set timer clock */
Xsetclock(usecs)
Xunsigned usecs;
X{
X unsigned bsecs;
X struct clock *clock1 = 0xdc08;
X char *c1mode = 0xdc0f;
X
X *c1mode &= 0x7f; /* mode is clock */
X
X if(usecs > 59) usecs = 59;
X
X /* convert secs to bcd */
X bsecs = usecs%10 | ((usecs/10)<<4);
X
X clock1->hours = 0;
X clock1->minutes = 0;
X clock1->seconds = (char)bsecs;
X clock1->tenths = 0; /* free clock */
X}
X
X/* getclock() - get current clock secs */
Xunsigned getclock()
X{
X unsigned usecs;
X char junk;
X struct clock *clock1 = 0xdc08;
X
X junk = clock1->seconds;
X usecs = (junk & 0x0f) +
X 10 * (junk >> 4);
X
X junk = clock1->tenths; /* free clock */
X
X return usecs;
X}
X
X/* end of file */
SHAR_EOF
chmod 0664 dos.c || echo "restore of dos.c fails"
sed 's/^X//' << 'SHAR_EOF' > menus.c &&
X/* menus.c - menu routines */
X/* W Mat Waites - Sept 1988 */
X
X#include <stdio.h>
X
X/* globals */
Xextern int done;
Xextern int echo;
Xextern int baud;
Xextern int bpchar;
Xextern int stopbits;
Xextern int parity;
Xextern int ddrive;
Xextern int asciimode;
Xextern int autolf;
Xextern int flowcont;
X
Xchar *parval();
Xchar *dupval();
Xchar *modeval();
X
X/* menu() - main menu */
Xmenu()
X{
X int mdone = 0;
X int kbchar;
X int ycoord;
X char fname[21];
X
X /* draw menu */
X erase();
X while(!mdone)
X {
X center(1, "Cmaster Main Menu");
X
X ycoord = 4;
X move(ycoord++, 5);
X printf("(Q)uit");
X ycoord++;
X
X move(ycoord++, 5);
X printf("(A)utodial");
X move(ycoord++, 5);
X printf("(H)angup");
X move(ycoord++, 5);
X printf("(U)pload");
X move(ycoord++, 5);
X printf("(D)ownload");
X move(ycoord++, 5);
X printf("(N)umber of drive %1d",
X ddrive);
X ycoord++;
X
X move(ycoord++, 5);
X printf("(M)ode %10s",
X modeval(asciimode));
X move(ycoord++, 5);
X printf("(L)inefeeds %10s",
X lfval(autolf));
X move(ycoord++, 5);
X printf("(T)og Duplex %10s",
X dupval(echo));
X move(ycoord++, 5);
X printf("(F)low Control %10s",
X boolval(flowcont));
X ycoord++;
X
X move(ycoord++, 5);
X printf("(B)aud %4d",
X baud);
X move(ycoord++, 5);
X printf("(C)har length %1d",
X bpchar);
X move(ycoord++, 5);
X printf("(P)arity %10s",
X parval(parity));
X move(ycoord++, 5);
X printf("(S)top bits %1d",
X stopbits);
X ycoord++;
X
X move(ycoord, 5);
X printf("(R)eturn");
X
X /* wait for keypress */
X while(charsinq() == 0)
X {
X }
X kbchar = getkb();
X
X /* switch on key */
X switch(kbchar)
X {
X case 'q': /* quit */
X case 'Q':
X done = 1;
X mdone = 1;
X break;
X case 'a': /* autodial */
X case 'A':
X erase();
X if(dial())
X {
X mdone = 1;
X }
X erase();
X break;
X case 'h': /* hangup */
X case 'H':
X modhangup();
X break;
X case 'u': /* upload */
X case 'U':
X erase();
X center(1, "Cmaster Upload Menu");
X move(5, 5);
X printf("Filename:");
X if(getstring(fname, 16))
X {
X erase();
X setserial(baud, 8, 1, 0);
X setflow(0);
X sendfile(fname, ddrive);
X setserial(baud, bpchar,
X stopbits, parity);
X setflow(flowcont);
X printf("Press key:");
X while(charsinq() == 0)
X {
X }
X kbchar = getkb();
X mdone = 1;
X }
X erase();
X break;
X case 'd': /* download */
X case 'D':
X erase();
X center(1, "Cmaster Download Menu");
X move(5, 5);
X printf("Filename:");
X if(getstring(fname, 15))
X {
X erase();
X setserial(baud, 8, 1, 0);
X setflow(0);
X recvfile(fname, ddrive);
X setserial(baud, bpchar,
X stopbits, parity);
X setflow(flowcont);
X printf("Press key:");
X while(charsinq() == 0)
X {
X }
X kbchar = getkb();
X mdone = 1;
X }
X erase();
X break;
X case 'n': /* change active drive */
X case 'N':
X if(ddrive == 8)
X {
X ddrive = 9;
X }
X else
X {
X ddrive = 8;
X }
X break;
X case 'b': /* cycle baud */
X case 'B':
X switch(baud)
X {
X case 300:
X baud = 450;
X break;
X case 450:
X baud = 1200;
X break;
X case 1200:
X baud = 300;
X break;
X default:
X baud = 300;
X break;
X }
X setserial(baud, bpchar,
X stopbits, parity);
X break;
X case 'c': /* bits per char */
X case 'C':
X bpchar++;
X if(bpchar > 8)
X {
X bpchar = 7;
X }
X setserial(baud, bpchar,
X stopbits, parity);
X break;
X case 'p': /* parity */
X case 'P':
X if(parity == 0)
X {
X parity = 1;
X }
X else
X {
X parity += 2;
X if(parity > 7)
X {
X parity = 0;
X }
X }
X setserial(baud, bpchar,
X stopbits, parity);
X break;
X case 's': /* stopbits (1 or 2) */
X case 'S':
X stopbits++;
X if(stopbits > 2)
X {
X stopbits = 1;
X }
X setserial(baud, bpchar,
X stopbits, parity);
X break;
X case 'm': /* mode */
X case 'M':
X asciimode = !asciimode;
X break;
X case 'l': /* auto LF */
X case 'L':
X autolf = !autolf;
X break;
X case 'f': /* flow control */
X case 'F':
X flowcont = !flowcont;
X setflow(flowcont);
X break;
X case 't': /* toggle local echo */
X case 'T':
X echo = !echo;
X break;
X case 'r': /* return to terminal */
X case 'R':
X mdone = 1;
X break;
X default:
X break;
X }
X }
X erase();
X}
X
X/* parval() - return parity string */
Xstatic char *parval(par)
Xint par;
X{
X switch(par)
X {
X case 0:
X return("Disabled");
X case 1:
X return("Odd");
X case 3:
X return("Even");
X case 5:
X return("Mark");
X case 7:
X return("Space");
X default:
X return("Invalid");
X }
X}
X
X/* dupval() - return duplex string */
Xstatic char *dupval(ech)
Xint ech;
X{
X if(ech)
X {
X return("Half");
X }
X else
X {
X return("Full");
X }
X}
X
X/* modeval() - return display mode string */
Xstatic char *modeval(mode)
Xint mode;
X{
X if(mode)
X {
X return("ASCII");
X }
X else
X {
X return("Graphics");
X }
X}
X
X/* lfval() - return linefeed mode string */
Xstatic char *lfval(mode)
Xint mode;
X{
X if(mode)
X {
X return("Auto LF");
X }
X else
X {
X return("No Auto LF");
X }
X}
X
X/* boolval() - return On/Off string */
Xstatic char *boolval(mode)
Xint mode;
X{
X if(mode)
X {
X return("On");
X }
X else
X {
X return("Off");
X }
X}
X
X/* end of file */
SHAR_EOF
chmod 0664 menus.c || echo "restore of menus.c fails"
sed 's/^X//' << 'SHAR_EOF' > screen.c &&
X/* screen.c - screen routines */
X/* W Mat Waites - Sept 1988 */
X
X#include <stdio.h>
X
X#define PLOT 0xfff0
X
X/* initscr() - initialize cursor, etc */
Xinitscr()
X{
X int i;
X char *tmp;
X char *sprite0 = 0x07f8;
X char *spcol0 = 0xd027;
X
X /* cursor sprite is defined in
X basic input buffer */
X
X /* put sprite 0 at $0200 */
X *sprite0 = 8;
X
X /* set color to white */
X *spcol0 = 1;
X
X /* first, set sprite to all bgd */
X for(i=0; i<64; i++)
X {
X tmp = 0x0200 + i;
X *tmp = 0;
X }
X
X /* fill in fgd of sprite */
X for(i=7; i<8; i++)
X {
X tmp = 0x0200 + 3*i;
X *tmp = 0xff;
X }
X}
X
X/* cursoron() - turn on cursor */
Xcursoron()
X{
X char *enab = 0xd015;
X
X *enab = 0x01; /* turn on sprite 0 */
X}
X
X/* cursoroff() - turn off cursor */
Xcursoroff()
X{
X char *enab = 0xd015;
X
X *enab = 0x00; /* turn off sprite 0 */
X}
X
X/* updatecursor() - correct sprite loc */
Xupdatecursor()
X{
X char *cury, *curx;
X char *ypos, *xpos;
X char *highx;
X int sy, sx;
X
X cury = 0x00d6;
X curx = 0x00d3;
X xpos = 0xd000;
X ypos = 0xd001;
X highx = 0xd010;
X
X /* compute cursor screen location */
X sy = (int)*cury;
X sx = (int)*curx;
X if(sx > 39) /* check for wrap */
X {
X sx -= 40;
X }
X sy = sy << 3;
X sx = sx << 3;
X sy += 50;
X sx += 24;
X
X *ypos = (char)sy;
X *xpos = (char)sx;
X if(sx > 255)
X {
X *highx = 0x01;
X }
X else
X {
X *highx = 0x00;
X }
X}
X
X/* erase() - clear screen */
Xerase()
X{
X putchar((char)147);
X}
X
X/* standout() - reverse video */
Xstandout()
X{
X putchar((char)18);
X}
X
X/* standend() - standard video */
Xstandend()
X{
X putchar((char)146);
X}
X
X/* center() - center string on line */
Xcenter(y, str)
Xint y;
Xchar *str;
X{
X int x;
X
X x = 20 - strlen(str)/2;
X move(y, x);
X printf(str);
X}
X
X/* move() - cursor positioning */
Xmove(y, x)
Xint y, x;
X{
X char ac, xc, yc;
X
X /* check for bozo parameters */
X if(y > 24) y = 24;
X if(y < 0) y = 0;
X if(x > 79) x = 79;
X if(x < 0) x = 0;
X
X xc = (char)y;
X yc = (char)x;
X
X sys(PLOT, &ac, &xc, &yc);
X}
X
X/* setborder() - set border color */
Xsetborder(color)
Xint color;
X{
X char *border = 0xd020;
X
X *border = (char)color;
X}
X
X/* setbg() - set background color */
Xsetbg(color)
Xint color;
X{
X char *bg = 0xd021;
X
X *bg = (char)color;
X}
X
X/* setfg() - set foreground color */
Xsetfg(color)
Xint color;
X{
X static char colchars[16] =
X {
X 144, /* black */
X 5, /* white */
X 28, /* red */
X 159, /* cyan */
X 156, /* purple */
X 32, /* green */
X 31, /* blue */
X 158, /* yellow */
X 129, /* orange */
X 149, /* brown */
X 150, /* lt. red */
X 151, /* grey 1 */
X 152, /* grey 2 */
X 153, /* lt. green */
X 154, /* lt. blue */
X 155 /* grey 3 */
X };
X
X if(color < 0) color = 0;
X if(color > 15) color = 15;
X
X putchar(colchars[color]);
X}
X
X/* getstring() - get string with echo */
Xgetstring(s, len)
Xchar *s;
Xint len;
X{
X int done, kbchar, ll;
X char *ls;
X
X done = 0;
X ll = 0;
X ls = s;
X *ls = '\0';
X updatecursor();
X cursoron();
X
X while(!done)
X {
X /* check for <C=> key */
X if(chkstop())
X {
X cursoroff();
X return(0);
X }
X if(charsinq() > 0)
X {
X kbchar = getkb();
X /* only printable characters */
X /* if(isprint(kbchar)) */
X if((kbchar >= 32 && kbchar <= 95) ||
X (kbchar >= 193 && kbchar <= 218))
X {
X *ls = (char)kbchar;
X ls++;
X ll++;
X *ls = '\0';
X putchar((char)kbchar);
X updatecursor();
X if(ll >= len)
X {
X done = 1;
X }
X }
X else if(kbchar == 13)
X {
X done = 1;
X }
X else if(kbchar == 20)
X {
X /* backspace */
X if(ll > 0)
X {
X ll--;
X ls--;
X *ls = '\0';
X putchar((char)20);
X updatecursor();
X }
X }
X }
X }
X cursoroff();
X return(strlen(s));
X}
X
X/* end of file */
SHAR_EOF
chmod 0664 screen.c || echo "restore of screen.c fails"
sed 's/^X//' << 'SHAR_EOF' > xmodem.c &&
X/* xmodem.c - xmodem protocol */
X/* W Mat Waites - Sept 1988 */
X
X#include <stdio.h>
X
X/* number of retries, timeouts */
X#define RETRY 5
X#define TOUT 2
X#define BTOUT 10
X
X/* protocol characters */
X#define SOH 0x01
X#define EOT 0x04
X#define ACK 0x06
X#define NAK 0x15
X#define CAN 0x18
X
X#define RECSIZE 128
X
Xchar *diskerr();
X
Xint rec;
Xint tries;
Xint timeout;
X
X/* buffer for data in/out */
Xchar buffer[132];
X
X/* sendfile() - send file via xmodem */
Xsendfile(fname, disk)
Xchar *fname;
Xint disk;
X{
X int st;
X int ch;
X char errbuf[41];
X char locname[21];
X char *status = 0x0090;
X FILE dfile;
X
X rec = 1;
X
X strcpy(locname, fname);
X strcat(locname, ",r");
X
X /* attempt to open file for read */
X device(disk);
X dfile = fopen(locname);
X
X /* check for disk error */
X strcpy(errbuf, diskerr(disk));
X st = atoi(errbuf);
X if(st >= 20)
X {
X close(dfile);
X showerr(fname, errbuf);
X return(0);
X }
X
X printf("%s opened\n", fname);
X
X /* clear input buffer */
X while(getserial() >= 0)
X {
X }
X
X tries = RETRY;
X
X for(;;)
X {
X printf("Synching...\n");
X if(chkstop())
X {
X close(dfile);
X return(0);
X }
X ch = getchtmo(BTOUT);
X if(timeout)
X {
X printf("Timeout\n");
X tries--;
X if(tries > 0)
X {
X continue;
X }
X close(dfile);
X return(0);
X }
X if(ch == NAK)
X {
X break;
X }
X printf("Strange char [%02x]\n", ch);
X }
X
X printf("Synched\n");
X
X /* send the file */
X while(fillbuf(dfile, buffer))
X {
X if(chkstop())
X {
X close(dfile);
X return(0);
X }
X if(!txrec(buffer))
X {
X close(dfile);
X return(0);
X }
X }
X
X /* tell 'em we're done */
X putserial(EOT);
X for(;;)
X {
X ch = getchtmo(TOUT);
X if(timeout)
X {
X putserial(EOT);
X }
X else
X {
X if(ch == ACK)
X {
X printf("sent EOT\n\n");
X break;
X }
X }
X }
X
X close(dfile);
X printf("%s transferred\n\n", fname);
X return(1);
X}
X
X/* recvfile() - recv file via xmodem */
Xrecvfile(fname, disk)
Xchar *fname;
Xint disk;
X{
X int st;
X int ch;
X int i;
X char r1, r2, dt;
X int response;
X char rchk;
X char locname[21];
X char errbuf[41];
X unsigned chksum;
X FILE dfile;
X
X rec = 1;
X
X strcpy(locname, fname);
X strcat(locname, ",w");
X
X /* attempt to open file for write */
X device(disk);
X dfile = fopen(locname);
X
X /* check for disk error */
X strcpy(errbuf, diskerr(disk));
X st = atoi(errbuf);
X if(st >= 20)
X {
X close(dfile);
X showerr(fname, errbuf);
X return(0);
X }
X
X printf("%s opened\n", fname);
X
X /* clear input queue */
X while(getserial() >= 0)
X {
X }
X
X /* transfer file */
X response = NAK;
X for(;;)
X {
X /* get a record */
X printf("Record %3d ", rec);
X tries = RETRY;
X for(;;)
X {
X if(chkstop())
X {
X close(dfile);
X return(0);
X }
X /* shake hands */
X putserial(response);
X /* get 1st char */
X ch = getchtmo(TOUT);
X if(timeout)
X {
X tries--;
X if(tries > 0)
X {
X continue; /* try again */
X }
X printf("Can't sync w/sender\n");
X
X close(dfile);
X return(0);
X }
X if(ch == SOH) /* beg of data */
X {
X break;
X }
X else if(ch == EOT) /* done */
X {
X printf("got EOT\n\n");
X close(dfile);
X putserial(ACK);
X printf("%s transferred\n\n",
X fname);
X return(1);
X }
X else if(ch == CAN) /* cancelled */
X {
X close(dfile);
X printf("Transfer cancelled!\n");
X return(0);
X }
X else
X {
X printf("Strange char [%02x]\n", ch);
X gobble(); /* clear any weirdness */
X response = NAK; /* and try again */
X }
X }
X
X response = NAK;
X r1 = getchtmo(TOUT); /* record number */
X if(timeout)
X {
X printf("TMO on recnum\n");
X continue;
X }
X /* get 1's comp record number */
X r2 = getchtmo(TOUT);
X if(timeout)
X {
X printf("TMO on comp recnum\n");
X continue;
X }
X
X /* get data */
X chksum = 0;
X for(i=0; i<RECSIZE; i++)
X {
X dt = getchtmo(TOUT);
X if(timeout)
X {
X break;
X }
X buffer[i] = dt;
X chksum += dt;
X chksum &= 0xff;
X }
X /* check for data timeout */
X if(timeout)
X {
X printf("TMO on data\n");
X continue;
X }
X
X /* get checksum */
X rchk = getchtmo(TOUT);
X if(timeout)
X {
X printf("TMO on checksum\n");
X continue;
X }
X
X /* compare rec num and 1's comp */
X if((~r1 & 0xff) != (r2 & 0xff))
X {
X printf("Bad recnum's\n");
X continue;
X }
X
X /* compare checksum and local one */
X if(rchk != chksum)
X {
X printf("Bad checksum\n");
X response = NAK;
X continue;
X }
X
X if((r1 ==(rec-1) & 0xff)) /* dupe */
X {
X printf("Duplicate record\n");
X response = ACK;
X continue;
X }
X
X if(r1 != (rec & 0xff))
X {
X printf("Record numbering error\n");
X close(dfile);
X return(0);
X }
X
X rec++;
X
X /* write data to file */
X for(i=0; i<RECSIZE; i++)
X {
X putc(buffer[i], dfile);
X }
X
X printf("OK\n");
X response = ACK;
X }
X}
X
X/* showerr() - display disk error */
Xshowerr(fname, errmsg)
Xchar *fname;
Xchar *errmsg;
X{
X erase();
X move(11, 5);
X printf("Error accessing %s", fname);
X move(13, 5);
X printf("[%s]", errmsg);
X move(20, 5);
X}
X
X/* getchtmo() - get char w/timeout */
Xgetchtmo(timlen)
Xint timlen;
X{
X int serchar;
X
X timeout = 0;
X setclock((unsigned)0); /* start timer */
X
X for(;;)
X {
X
X serchar = getserial();
X if(serchar >= 0)
X {
X return(serchar);
X }
X
X if(getclock() >= timlen)
X {
X timeout = 1;
X return 0;
X }
X }
X}
X
X/* fillbuf() - get buffer of data */
Xfillbuf(filnum, buf)
Xint filnum;
Xchar buf[];
X{
X int i;
X int echk;
X char *status = 0x0090;
X
X for(i=0; i<RECSIZE; i++)
X {
X /* get a char from file */
X if((echk=fgetc(filnum)) == EOF)
X {
X break;
X }
X buf[i] = echk;
X }
X
X if(i == 0) return 0;
X
X /* set rest of buffer to CTRL-Z */
X for(; i<RECSIZE; i++)
X {
X buf[i] = (char)26;
X }
X return(1);
X}
X
X/* txrec() - send rec, get response */
Xtxrec(buf)
Xchar buf[];
X{
X int i;
X int ch;
X unsigned chksum;
X
X tries = RETRY;
X
X for(;;)
X {
X /* send record */
X
X printf("Record %3d ", rec);
X putserial(SOH);
X putserial(rec);
X putserial(~rec);
X chksum = 0;
X for(i=0; i<RECSIZE; i++)
X {
X putserial(buf[i]);
X chksum += buf[i];
X chksum &= 0xff;
X }
X putserial(chksum);
X
X /* get response */
X ch = getchtmo(BTOUT);
X if(timeout)
X {
X tries--;
X if(tries > 0)
X {
X printf("Retrying...\n");
X continue;
X }
X printf("Timeout\n");
X return(0);
X }
X
X /* analyze response */
X if(ch == CAN)
X {
X printf("Cancelled\n");
X return(0);
X }
X else if(ch == ACK)
X {
X printf("ACKed\n", rec);
X break;
X }
X else
X {
X if(ch == NAK)
X {
X printf("NAKed\n", rec);
X }
X else
X {
X printf("Strange response\n");
X }
X tries--;
X if(tries > 0)
X {
X continue;
X }
X printf("No more retries!\n");
X return(0);
X }
X }
X rec++;
X return(1);
X}
X
X/* gobble() - gobble up stray chars */
Xgobble()
X{
X unsigned gotone;
X
X printf("\ngobbling\n");
X
X sleep(2);
X
X for(;;)
X {
X gotone = 0;
X /* clear input queue */
X while(getserial() >= 0)
X {
X gotone = 1;
X }
X if(gotone)
X {
X sleep(1);
X }
X else
X {
X return;
X }
X }
X}
X
X/* end of file */
SHAR_EOF
chmod 0664 xmodem.c || echo "restore of xmodem.c fails"
exit 0
--
W Mat Waites
gatech!emcard!mat
8-5 ET: (404) 727-7197