/* * Stripped down tip clone -- Howard Chu, 10-10-90 * * This is a very simple terminal program intended for use with MiNT * (and MGR...). I tried to model it on the BSD 4.3 version of tip, * but got impatient and thus omitted a number of features. Still, * this is useful enough and easy enough to use... You may copy and * distribute this program freely as long as you keep all files intact * (meaning this source file and the accompanying doc and executable * file). You are also welcome to modify the program to suit your own * needs, but leave this notice intact. I would also appreciate it * if you send me any improvements you may make. * hyc@math.lsa.umich.edu */ #include #include #define Finstat(a) gemdos(0x105,a) #define Foutstat(a) gemdos(0x106,a) #define Fgetchar(a,b) gemdos(0x107,a,b) #define Fputchar(a,b,c) gemdos(0x108,a,b,c) /* The previous 4 defines don't actually get used. So it goes... they're up there because I thought about using them, and I haven't incorporated them into my MWC library yet. */ #define Pgetpid() gemdos(0x10b) #define Pkill(a,b) gemdos(0x111,a,b) char iobuf[8192]; struct iorec *rec, oldirec, oldorec; char shell[128], esc='~'; int par=0; /* none, odd, even - 0, 1, 2 */ int baud=1; /* see baud table 1=9600 */ int echo=0; int flow=0; /* none, xon/xoff, rts/cts */ int ucr, rsr, tsr, scr; char *bauds[]={"19200","9600","4800","3600","2400","2000","1800","1200", "600","300","200","150","134","110","75","50"}; /* Set up a large I/O buffer for the RS232 port, and set initial speed, flow control, and parity. */ void rs232init(){ register long m68901reg; rec=Iorec(0); oldirec=*rec; rec->io_buff=iobuf; rec->io_bufsiz = 4096; rec->io_head = 0; rec->io_tail = 0; rec->io_low = 100; rec->io_high = 4000; rec++; oldorec=*rec; rec->io_buff=&iobuf[4096]; rec->io_bufsiz = 4096; rec->io_head=0; rec->io_tail=0; rec->io_low=100; rec->io_high=4000; m68901reg=Rsconf(baud,0,-1,-1,-1,-1); scr=m68901reg&0xff; m68901reg>>=8; tsr=m68901reg&0xff; m68901reg>>=8; rsr=m68901reg&0xff; m68901reg>>=8; ucr=m68901reg&0xf8; Rsconf(-1,-1,ucr,-1,-1,-1); /* turn off parity */ } int getbaud(rate) char *rate; { register int i; for (i=0;i<16;i++) if (!strcmp(rate,bauds[i])) break; if (i==16) { Cconws(rate); Cconws(": unknown baudrate value\r\n"); i=(-1); } return(i); } main(argc,argv) int argc; char *argv[]; { register int c; register int cr=0; register int cmd=0; char *buf, *getenv(); void docommand(); switch(argc){ case 1: break; case 2: c=getbaud(argv[1]); if (c>=0) baud=c; break; default: Cconws("Use: tip [speed]\r\n"); break; } rs232init(); buf=getenv("SHELL"); if (buf) strcpy(shell,buf); for(;;) { if (Bconstat(1)) { c = Bconin(1); Bconout(2,c); } if (Cconis()) { c = Crawcin(); if (cmd) { cmd=0; docommand(c); cr=1; continue; } else if (cr && c == esc) { cmd = 1; cr = 0; continue; } else if (c == '\r') cr = 1; else cr = 0; if (Bcostat(1)) Bconout(1,c); if (echo) Bconout(2,c); } } } void docommand(c) int c; { int args=0; void dosetvar(), dobreak(); char *strchr(); if (strchr("!#.?s",c)||(c==4)||(c==26)) Cconout(esc); switch (c) { case '!': if (shell[0]) { Cconws("\r\n[sh]\r\n"); Pexec(0,shell,&args,0L); } else { Cconws("No shell.\r\n"); } break; #if 0 /* Not implemented. Too much hassle. */ case '|': Cconws("Local command? "); Cconws("List command for remote system? "); case '$': /* Pipe local command to remote */ case 'C': Cconws("Local command? "); #endif case '.': case 4: Cconws("\r\n[EOT]\r\n"); *rec=oldorec; /* reset to old I/O rec stuff, then exit */ rec--; *rec=oldirec; exit(0); case 26: /* Send a STOP to this process */ {register int i = Pgetpid(); Pkill(i,17); } break; case 's': dosetvar(); break; case '#': dobreak(); break; case '?': Cconws("\r\n ~! shell\r\n"); Cconws(" ~. exit from tip\r\n"); Cconws(" ~^D exit from tip\r\n"); Cconws(" ~^Z suspend tip\r\n"); Cconws(" ~s set variable\r\n"); Cconws(" ~# send break\r\n"); Cconws(" ~? get this summary\r\n"); break; default: Bconout(1,c); break; } } void dobreak() { #define Fselect(a,b,c,d) gemdos(0x11d,a,b,c,d) tsr |= 0x08; Rsconf(-1,-1,-1,-1,tsr,-1); Fselect(300,0L,0L,0L); /* sleep 300 milliseconds */ tsr &=0xf7; Rsconf(-1,-1,-1,-1,tsr,-1); } char *vars[]={"all","baudrate","flowcontrol","localecho","parity","escape","shell"}; char *flows[]={"none","xon/xoff","rts/cts"}; char *pars[]={"none","odd","even"}; void dosetvar() { register int i, j; char *strpbrk(); unsigned char buf[130]; register char *ptr; Cconws("[set] "); buf[0]=128; Cconrs(buf); Cconout('\n'); i=buf[1]; if (i==0) return; buf[i+2]='\0'; ptr=strpbrk(&buf[2]," = "); if (ptr) i=ptr-&buf[2]; else i=buf[1]; for (j=0;j<7;j++) if(!strncmp(&buf[2],vars[j],i)) break; if (j==7) { Cconws(&buf[2]); Cconws(": unknown variable\r\n"); return; } if (j&&!ptr) { Cconws("\r\nno value supplied\r\n"); return; } ptr++; switch(j) { case 0: Cconws("baudrate="); Cconws(bauds[baud]); Cconws("\r\nflowcontrol="); Cconws(flows[flow]); Cconws("\r\nlocalecho="); ptr=echo ? "on":"off"; Cconws(ptr); Cconws("\r\nparity="); Cconws(pars[par]); Cconws("\r\nescape="); Cconout(esc); Cconws("\r\nshell="); Cconws(shell); Cconws("\r\n"); break; case 1: i=getbaud(ptr); if (i>=0) { baud=i; Rsconf(i,-1,-1,-1,-1,-1); } break; case 2: j=buf[1]-i-1; for (i=0;i<4;i++) if (!strncmp(ptr,flows[i],j)) break; if (i==4) { Cconws(ptr); Cconws(": unknown flowcontrol value\r\n"); return; } flow=i; Rsconf(-1,i,-1,-1,-1,-1); break; case 3: echo=strcmp(ptr,"on") ? 0 : 1; break; case 4: j=buf[1]-i-1; for (i=0;i<3;i++) if (!strncmp(ptr,pars[i],j)) break; if (i==3) { Cconws(ptr); Cconws(": unknown parity value\r\n"); return; } par=i; ucr &=0x98; if (i) { ucr |= i|0x24; /* set 7 bits, parity on */ } Rsconf(-1,-1,ucr,-1,-1,-1); break; case 5: esc=*ptr; break; case 6: strcpy(shell,ptr); break; } }