home *** CD-ROM | disk | FTP | other *** search
- /*
- * HAMIGA.C - 19th Aug 1988 - System dependent functions.
- * replacement for mbibm.c
- * Copyright 1990,1991 Pete Hardie VE5VA
- *
- */
-
- #include "mb.h"
- #include <intuition/intuition.h>
- #include <intuition/intuitionbase.h>
- #include <graphics/text.h>
- #include <ctype.h>
- #include <time.h>
- #include <string.h>
- #include <stdlib.h>
- #include "port.h"
-
- extern struct Window *mywindow;
- struct IntuiMessage *NewMessage;
- short interflag = 0;
- short debug;
- char tmpstr[100];
- extern struct IOStdReq *Con_Read,*Con_Write;
- extern struct MsgPort *my_port;
- extern unsigned char rs_in[2];
- extern unsigned char rs_out[2];
- extern char optflags[];
-
- char l_date[7], l_time[5];
- char pt_flag = 0;
- short done_flag = 1;
-
- short tapr_flag = 0;
- struct regd *CURBUF = 0L;
- unsigned char *B_FROM = 0,*B_TO = 0;
-
- char z_date[7], z_time[5];
- /*
- * Set the current I/O device.
- */
-
- ioport(pp)
- PORTS *pp;
- {
- port = pp;
- }
-
- /*
- * Return non-zero if a character waits at current input.
- */
- instat()
- {
- register int st;
-
- if (port->dev is p_console) {
- /* check for char at console */
- if(CheckIO((struct IORequest *)Con_Read))return(1);
- else return(0);
- }
- if(port->dev is p_tnc) {
- /* check for char at serial port */
- if(CheckIO((struct IORequest *)my_port)) {
- if(optflags[4])interflag = 1;
- return(1);
- }
- else return(0);
- }
- return(0);
- }
- /* output char to serial port */
- outi(ch)
- char ch;
- {
- schar(ch);
- }
-
- /*
- * Put the character out the current port,
- * echo to console if the current port is not the console.
- * Note special handling of end-of-line character.
- */
-
- outchar(ch)
- char ch;
- {
- if (ch is '\r') return;
- if (ch is '\n') ch = '\r';
- /*
- * Put it out to the console, if it is going there.
- */
-
- if ((port->dev is p_console) or port->ec) {
- if (ch is '\r') ttputc('\n');/* output '\n' */;
- ttputc(ch);
- }
-
- /*
- * If the port is the console, nothing more to do.
- */
-
- if (port->dev is p_console) return;
-
- /*
- * Stuff this byte out the port.
- */
-
- outi(ch);
- if (ch is '\r')
- if (port->flags & p_lf) outi('\n');
- }
- #define PROCLEN 100
- /* This can't use tmpstr because some of the routines call this with
- tmpstr as the argument
- */
- unsigned char procstr[PROCLEN];
- unsigned char procstr1[PROCLEN];
-
- outstr(cp)
- unsigned char *cp;
- {
- register unsigned char *p,*q;
- register int beepcount,i;
- /* count the number of beeps in the line so that we can give an audible
- as well as visual beep
- */
- beepcount = 0;
- if((port->dev is p_console) || port->ec) {
- for(q = cp,p = &procstr[0];*q && p < &procstr[PROCLEN-1];q++) {
- if(*q is '\r')continue;
- *p++ = *q;
- if(*q == '\007')beepcount++;
- }
- *p = 0;
- Con_Write->io_Data = (APTR) &procstr[0];
- Con_Write->io_Length = p-&procstr[0];
- Con_Write->io_Command = CMD_WRITE;
- DoIO((struct IORequest *)Con_Write);
- while(beepcount--) {
- beep();
- Delay(15L);
- }
- }
- if(port->dev is p_console)return;
- for(q = cp,p = &procstr1[0];*q && (p < &procstr1[PROCLEN-1]);q++) {
- if(*q is '\r')continue;
- if(*q == '\n')*p++ = '\r';
- else *p++ = *q;
- }
- *p = 0;
- senddata(&procstr1[0]);
- }
-
- hex(c)
- char c;
- {
- char k;
- k = c;
- if((k >= '0') && (k <= '9'))return(k - '0');
- k = toupper(k);
- if((k >= 'A') && (k <= 'F'))return(k - 'A' + 10);
- return(0);
- }
- flipdebug()
- {
- debug ^= 1;
- if(debug) {
- ttputs("debug now ON\n");
- }
- else {
- ttputs("debug now OFF\n");
- }
- }
- extern unsigned char ichar;
- extern long keybit,windbit,portbit,timerbit;
- long getbits;
- struct timeRequest {
- struct IORequest tr_node;
- struct timeval tr_time;
- };
- extern struct timeRequest timermsg;
-
- /* replace the original do_idle because it busy-waited ...
- this version sleeps until there is something to do
- */
- PORTS *devtnc;
- extern short cursecs;
- do_idle()
- {
- register unsigned char ch,*cp;
- register PORTS *p;
- register struct regd *rp;
- int curmin,curmon;
- ULONG class,waitbits;
- USHORT code;
-
- devtnc = NULL;
- cursor_off();
- devtnc = 0;
- for(p=porthd; p != NULL; p = p->next) {
- p->ec = p->ecmon;
- if((devtnc == 0) && (p->id != 'Z'))devtnc = p;
- }
- if(devtnc == 0) {
- ttputs("Can't find port\n");
- setbusy();
- done(1);
- }
- ioport(devtnc);
- allon();
- cp = (unsigned char *) devtnc->line;
- /* figure out time to next forward and set timer */
- curtim();
- curmin = 60 - cursecs;
- settimer(curmin);
- /* There might already be an unread char at the serial or console port */
- waitbits = windbit | portbit | timerbit | keybit;
- clrbusy();
- ttputs("\nIDLE\n");
- if(cpyline(0))goto logit;
- while(1) {
- if(CURBUF = (struct regd *)GetMsg(my_port)) goto port_loop;
- getbits = Wait(waitbits);
- if(windbit & getbits) {
- while(NewMessage = (struct IntuiMessage *)
- GetMsg(mywindow->UserPort)) {
- class = NewMessage->Class;
- code = NewMessage->Code;
- ReplyMsg((struct Message *)NewMessage);
- if(class == CLOSEWINDOW) {
- /* say a fond farewell, don't ask fer sure? */
- if(done_flag) {
- if(timerbit & getbits) {
- WaitIO((struct IORequest *)&timermsg);
- }
- else {
- cantimer();
- }
- SetWindowTitles(mywindow,"",(char *) -1L);
- /* Need this to cancel out the clrbusy in done() */
- setbusy();
- done(1);
- }
- }
- }
- }
- if(keybit & getbits) {
- WaitIO((struct IORequest *)Con_Read);
- ch = ichar;
- Con_Read->io_Data = (APTR)&ichar;
- Con_Read->io_Command = CMD_READ;
- Con_Read->io_Length = 1;
- SendIO((struct IORequest *)Con_Read);
- if(ch == wchar) {
- ioport(cport);
- cursor_on();
- /* could have a timerbit set here.
- */
- if(timerbit & getbits) {
- WaitIO((struct IORequest *)&timermsg);
- }
- else {
- cantimer();
- }
- return;
- }
- if(ch == '\033') {
- ttputs("do_idle\n");
- }
- }
- if(portbit & getbits) {
- port_loop:
- while(CURBUF = (struct regd *)GetMsg(my_port)) {
- while(cpyline(0)) {
- logit:
- ttputs(port->line);
- p->flags setbit p_give;
- if(iscon(port->line)) {
- if(timerbit & getbits) {
- WaitIO((struct IORequest *)&timermsg);
- }
- else {
- cantimer();
- }
- ioport(devtnc);
- return;
- }
- }
- }
- }
- /* This code is deliberately placed last. If a timer bit occurs
- at the same time as a character arrives from the serial port
- then this code will hang the serial port up because afwd()
- tries to use the port again without clearing the existing char.
- So workaround it. Putting the timer code here guarantees that
- even if the ser char did occur it will be handled first and the
- ser char code handles the problem of returning from this routine
- with a timer bit set.
- */
- if(timerbit & getbits) {
- WaitIO((struct IORequest *)&timermsg);
- /* call the forwarding routine */
- curtim();
- curmin = 10 * (l_time[2] - '0') + (l_time[3] - '0');
- afwd(curmin);
- curmon = 10 * (l_date[2] - '0') + (l_date[3] - '0');
-
- if (s_param & s_log_on) if (curmon isnt log_mon) chglog();
-
- settimer(60);
- }
- }
- }
- /* replace getdat from mbutil to reduce busy waits */
- /* IMPLEMENTATION BUG. In the original getdat it busy-idles and
- if the port is transparent and DCD goes off while the port is
- not idle, then it forces the mode to discon and then returns(true).
- This code can only do this properly IF it can wait for DCD to go
- off. I haven't even tried to implement this yet and not sure if it
- can be done properly. I assume that there's a way to Wait() for a
- DCD event but haven't checked it out
- */
- char *cp;
- getdat()
- {
-
- register char ch;
- register PORTS *p;
- register struct regd *rp;
- int eflag;
- int curmin;
- ULONG class,waitbits;
- USHORT code;
-
- p = port;
- cp = p->line;
- /* Is a timeout timer required? */
- curmin = 0;
- if(p->flags & p_dotmr) {
- if((p->mode & idle) && (p->dev == p_tnc))
- curmin = 2;
- else
- curmin = p->ctime;
- }
- if(curmin)settimer(curmin); /* set timeout timer if required */
- p->flags setbit p_dotmr;
-
- if(p == cport) {
- waitbits = windbit | timerbit | keybit;
- }
- else {
- waitbits = windbit | portbit | timerbit | keybit;
- if(cpyline(0))goto cpyin;
- }
- while(1) {
- /* See if there's already a message waiting for us */
- if(waitbits & portbit) {
- if(CURBUF = (struct regd *)GetMsg(my_port)) {
- goto port_check;
- }
- }
- getbits = Wait(waitbits);
- if(windbit & getbits) {
- while(NewMessage =
- (struct IntuiMessage *) GetMsg(mywindow->UserPort)) {
- class = NewMessage->Class;
- code = NewMessage->Code;
- ReplyMsg((struct Message *)NewMessage);
- if(class == CLOSEWINDOW) {
- /* say a fond farewell, don't ask fer sure? */
- if(done_flag) {
- if(timerbit & getbits) {
- WaitIO((struct IORequest *)&timermsg);
- }
- else {
- cantimer();
- }
- SetWindowTitles(mywindow,"",(char *) -1L);
- done(1);
- }
- }
- }
- }
- if(keybit & getbits) {
- WaitIO((struct IORequest *)Con_Read);
- ch = ichar;
- Con_Read->io_Data = (APTR)&ichar;
- Con_Read->io_Command = CMD_READ;
- Con_Read->io_Length = 1;
- SendIO((struct IORequest *)Con_Read);
- if(ch == '\033') {
- if(p == cport)ttputs("getdatCON\n");
- else ttputs("getdatTNC\n");
- }
- eflag = 0;
- if(p != cport) {
- if(ch == achar) {
- p->mode = forced;
- eflag = 1;
- }
- if(ch == tchar) {
- p->flags setbit p_opreq;
- eflag = 1;
- }
- }
- else {
- if(charf(ch)) {
- eflag = 1;
- }
- }
- /* If any of the previous three if statements want to
- exit then check that the timer is off and then get out
- */
- if(eflag) {
- if(timerbit & getbits) {
- WaitIO((struct IORequest *)&timermsg);
- }
- else {
- if(curmin)cantimer();
- }
- return(true);
- }
- }
- if(portbit & getbits) {
- while((CURBUF = (struct regd *)GetMsg(my_port)) != 0L) {
- if(optflags[4])interflag = 1;
- port_check:
- while(cpyline(0)) {
- cpyin:
- ttputs(p->line);
- if(timerbit & getbits) {
- WaitIO((struct IORequest *)&timermsg);
- }
- else {
- if(curmin)cantimer();
- }
- if(!(p->flags & p_trans)) {
- if(isdis(p->line)) {
- if(!(p->mode & idle))p->mode = discon;
- return (true);
- }
- if(isretry(p->line)) {
- return (false);
- }
- if(isreq(p->line)) {
- p->flags setbit p_req;
- pcall(p->rcall,p->line+20);
- p->flags clrbit p_dotmr;
- return (false);
- }
- }
- return (true);
- }
- }
- }
- if(timerbit & getbits) {
- WaitIO((struct IORequest *)&timermsg);
- *cp = 0;
- if(!(p->mode & idle))p->mode = timeout;
- return (true);
- }
- }
- }
- charf(s)
- unsigned char s;
- {
- register unsigned char ch;
- PORTS *p;
- p = port;
- ch = s;
- /* Ignore characters with high order bit set...they tie up the TNC */
- if(ch > 0177)return(0);
- *cp = ch;
- if((cp == p->line + linelen - 2) || (ch == '\r')) {
- if(ch == '\r')*cp = '\n';
- *++cp = 0;
- if(p->dev == p_tnc)ttputs(p->line);
- if(p->flags & p_echo)ttputc('\n');
- return(1);
- }
- switch(*cp) {
- default:
- if (p->flags & p_echo) ttputc(*cp);
- cp++;
- break;
- case '\b':
- if(cp > p->line) {
- cp--;
- if(p->flags & p_echo) ttputs("\b \b");
- }
- break;
-
- case '\n':
- if(cp is p->line) {
- *cp = '\0';
- return(1);
- }
- break;
- case '\0' : /* Ignore most ctl char */
- case ctl_c: /* Ignore most ctl char */
- case ctl_v: /* Ignore most ctl char */
- case '\033':
- break;
- }
- return(0);
- }
-
- /* I am not sure yet what waitcmd has to do anymore because the Host
- mode doesn't return "cmd:" to this process.
- */
- waitcmd()
- {
- }
-
- /* Remove the busy-wait from term() */
- term(s)
- PORTS *s;
- {
- register char ch,*cp;
- register struct regd *rp;
- register PORTS *m;
- ULONG class,waitbits;
- USHORT code;
- byte ec;
-
- cp = &tmpstr[0];
- m = cport;
- m->flags clrbit p_give;
- ec = s->ec;
- s->ec = true;
- ioport(m);
- waitbits = windbit | portbit | keybit;
- while(cpyline(1))ttputs(port->line);
- while(1) {
- getbits = Wait(waitbits);
- if(windbit & getbits) {
- while(NewMessage =
- (struct IntuiMessage *) GetMsg(mywindow->UserPort)) {
- class = NewMessage->Class;
- code = NewMessage->Code;
- ReplyMsg((struct Message *)NewMessage);
- if(class == CLOSEWINDOW) {
- /* say a fond farewell, don't ask fer sure? */
- if(done_flag) {
- SetWindowTitles(mywindow,"",(char *) -1L);
- done(1);
- }
- }
- }
- }
- if(keybit & getbits) {
- WaitIO((struct IORequest *)Con_Read);
- ch = ichar;
- Con_Read->io_Data = (APTR)&ichar;
- Con_Read->io_Command = CMD_READ;
- Con_Read->io_Length = 1;
- SendIO((struct IORequest *)Con_Read);
- if(ch == rchar) {
- m->flags setbit p_give;
- s->ec = ec;
- return;
- }
- if(ch == 010) {
- if(cp > &tmpstr[0]) {
- cp--;
- ttputs("\b \b");
- }
- }
- else {
- *cp = ch;
- if(ch == '\r') {
- ttputc('\n');
- if(tmpstr[0] != '!') {
- *cp++ = '\r';
- *cp = 0;
- senddata(&tmpstr[0]);
- }
- else {
- *cp = 0;
- sendcommand(&tmpstr[1]);
- }
- cp = &tmpstr[0];
- }
- else {
- cp++;
- ttputc(ch);
- }
- }
- }
- if(portbit & getbits) {
- while(CURBUF = (struct regd *)GetMsg(my_port)) {
- while(cpyline(1)) {
- ttputs(port->line);
- }
- }
- }
- }
- }
-
-
-
- /* Replace the pause routine so that it can be used with TNC as well
- as the console. If routine times out after 2 minutes then it will
- return 'Q'.
- The test for optflags[2] allows the SYSOP to specify whether the system
- will pause after 20 lines of output to the user.
- */
- pause()
- {
-
- register struct regd *rp;
- register char ch;
- ULONG class,waitbits;
- USHORT code;
-
- /* If remote user has interrupted, then return a 'Q' anyway */
- if((port != cport) && interflag)return('Q');
- if(!optflags[2] && ((port->mode != local) || (pt_flag)))return(' ');
-
- prtx(pausemsg);
- if(port->mode != local)outchar('\n');
- settimer(120); /* set timeout timer */
- waitbits = windbit | portbit | timerbit | keybit;
- if(cpyline(0))goto cpyout;
- while(1) {
- getbits = Wait(waitbits);
- if(windbit & getbits) {
- while(NewMessage =
- (struct IntuiMessage *) GetMsg(mywindow->UserPort)) {
- class = NewMessage->Class;
- code = NewMessage->Code;
- ReplyMsg((struct Message *)NewMessage);
- if(class == CLOSEWINDOW) {
- /* say a fond farewell, don't ask fer sure? */
- if(done_flag) {
- if(timerbit & getbits) {
- WaitIO((struct IORequest *)&timermsg);
- }
- else {
- cantimer();
- }
- SetWindowTitles(mywindow,"",(char *) -1L);
- done(1);
- }
- }
- }
- }
- if(keybit & getbits) {
- WaitIO((struct IORequest *)Con_Read);
- ch = toupper(ichar);
- Con_Read->io_Data = (APTR)&ichar;
- Con_Read->io_Command = CMD_READ;
- Con_Read->io_Length = 1;
- SendIO((struct IORequest *)Con_Read);
- if(timerbit & getbits) {
- WaitIO((struct IORequest *)&timermsg);
- }
- else {
- cantimer();
- }
- outchar('\n');
- return(ch);
- }
- if(portbit & getbits) {
- while(CURBUF = (struct regd *)GetMsg(my_port)) {
- if(cpyline(0)) {
- cpyout:
- ttputs(port->line);
- /* portbit has been handled but timerbit could be set */
- if(timerbit & getbits) {
- WaitIO((struct IORequest *)&timermsg);
- }
- else {
- cantimer();
- }
- return(port->line[0]);
- }
- }
- }
- /* check for timeout */
- if(timerbit & getbits) {
- WaitIO((struct IORequest *)&timermsg);
- return('Q');
- }
- }
- }
- /* if (instat()) if (getdat()) if (isdis(port->line)) */
- /* Replace a piece of the chkdis code in mbfwd.
- If there's received data, then if it is a disconnected message
- (ought to be sure of disconnect status - it could be data!)
- or if it is an abort command, then let them know .
- */
- disport()
- {
- register struct regd *rp;
- *port->line = 0;
- if(cpyline(0))goto gotone;
- while(CURBUF = (struct regd *)GetMsg(my_port)) {
- while(cpyline(0)) {
- gotone:
- if(isdis(port->line) || ((toupper(*port->line) == 'A') &&
- (rp->mp.msgsize == 2))) {
- ttputs(port->line);
- return(true);
- }
- return(false);
- }
- }
- return(false);
- }
-
-
- /* Copy data from the serial port to port->line.
- If flag is set then return an incomplete line, otherwise wait for
- a CR before sending a line.
- */
- cpyline(flag)
- {
- register struct regd *rp;
- register unsigned char *cp,*kp;
- register short i;
-
- if((rp = CURBUF) == 0)return(0);
- if((kp = B_FROM) == 0)
- kp = &rp->mp.msg[0];
- if((cp = B_TO) == 0)
- cp = (unsigned char *) port->line;
- i = rp->mp.msgsize;
-
- if(i == 0) {
- *cp = 0;
- ReplyMsg((struct Message *)CURBUF);
- CURBUF = 0;
- B_FROM = 0;
- return(0);
- }
- do {
- if(tapr_flag)
- *cp = *kp++ & 0177;
- else
- *cp = *kp++;
- if(*cp == '\r') {
- if((rp->mp.msgsize = (i-1)) == 0 ){
- out:
- ReplyMsg((struct Message *)CURBUF);
- CURBUF = 0;
- B_TO = B_FROM = 0;
- *cp++ = '\n';
- *cp = 0;
- return(1);
- }
- B_FROM = kp;
- B_TO = 0;
- *cp++ = '\n';
- *cp = 0;
- return(1);
- }
- cp++;
- } while(--i);
- if(rp->mp.cmd != 'D')goto out;
- *cp = 0;
- ReplyMsg((struct Message *)CURBUF);
- CURBUF = 0;
- B_FROM = 0;
- /* If flag is set then return a partial data packet.
- Otherwise say we're not done yet and let them give us more
- */
- if(flag) {
- B_TO = 0;
- return(1);
- }
- B_TO = cp;
- return(0);
- }
- fromhex(s)
- char *s;
- {
- register int i,j;
- register char *p;
- p = s;
- i = 0;
-
- if((i = hex(*p++)) < 0)return(-1);
- j = hex(*p);
- if(j < 0)return(-1);
- i <<= 4;
- i |= j;
- return(i);
- }
-