home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************
- * *
- * Minimal Term for DNET (uc) Stone, SST *
- * Further modifications by Unknown, SST *
- * Based on FTerm by Matt Dillon *
- * *
- * ShellTerm [DNET_PORT] [NETWORK] *
- * *
- * Set ya TABS to 4! *
- * Email me!! c9107253@mystra.newcastle.edu.au *
- * For any reason!! (eg DNet, AmiNet, Demos, amigas...) *
- * Please send any changes U make! *
- * Fully public domain *
- * Mega-thanx to Azza of the SST for hours of DNET source *
- * modification.... yes it compiles under SAS 6! *
- **********************************************************/
-
- #include "defs.h"
-
- /* DEFAULT STRINGS */
- char *WHITE = " \t\n\r",
- *EOLN = "\n\r";
-
- /* STANDARD FILE HANDLES */
- long out, err, in;
-
- struct AFileHandle *ain, *aout, *alogfile;
- char overridepkt, prevmoderaw, rawlocalecho, moderaw, notdone;
- long lineend;
- char Buf[512], prg[40], logfilename[100];
- void *chan;
- long startmem;
-
- extern struct IntuitionBase *IntuitionBase;
- extern struct GfxBase *GfxBase;
-
- #define SIGNALS (SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D | SIGBREAKF_CTRL_E | SIGBREAKF_CTRL_F)
-
- /* standard in & out async file handles */
- #define INBUFSIZE 500
- #define WAIT_TIMEOUT 700000 /* uSeconds */
-
-
- /* Do this on the next packet return */
- #define IN_NULL 0
- #define IN_WAIT 1
- #define IN_CHARS 2
- #define IN_RAWSET 3
- #define IN_RAWCLR 4
-
-
- /**********************************************************/
- void DoPacket(struct AFileHandle *afh, void *qbuf,
- long size, char pkttype)
- /**********************************************************
- Send a packet according to type. qbuf & size may not
- be required (in fact only used for ARead)
- **********************************************************/
- {
- switch(pkttype) {
- case IN_WAIT:
- ASendPacket(afh, ACTION_WAIT_CHAR, WAIT_TIMEOUT, 0, 0, 0); break;
- case IN_CHARS:
- ARead(afh, qbuf, size); break;
- case IN_RAWSET:
- ASendPacket(afh, ACTION_SCREEN_MODE, 1, 0, 0, 0); break;
- case IN_RAWCLR:
- ASendPacket(afh, ACTION_SCREEN_MODE, 0, 0, 0, 0); break;
- }
- }
-
- /**********************************************************/
- short CmpString(char *cmd, char *table[], long n, long dist)
- /**********************************************************
- Test a string against a table of string pointers,
- using every 'dist' pointer for a total of 'n' compares
- return -1 on fail
- otherwise the index (ith compare ie 0, 1, 2 ... )
- **********************************************************/
- {
- short i, j;
- for(i = 0, j = 0; i < n; i++)
- if(table[j] && (strncmp(cmd, table[j], strlen(table[j])) == 0)) return(i);
- else j += dist;
- return(-1);
- }
-
- /**********************************************************/
- char *FindChar(char *string, char *instring)
- /**********************************************************
- Find first character of 'string' contained in 'instring'
- **********************************************************/
- {
- short i, j;
- if(!(string && instring)) return(NULL);
- for(i = 0; string[i]; i++)
- for(j = 0; instring[j]; j++)
- if(string[i] == instring[j]) return(&string[i]);
- return(NULL);
- }
-
- /**********************************************************/
- char *SkipChar(char *string, char *instring)
- /**********************************************************
- Find first character of 'string' not contained in 'instring'
- **********************************************************/
- {
- short i, j;
- if(!(string && instring)) return(NULL);
- for(i = 0; string[i]; i++) {
- for(j = 0; instring[j] && (instring[j] != string[i]); j++);
- if(instring[j] == '\0') return(&string[i]);
- }
- return(NULL);
- }
-
- /* pass: rest of argline, command table, command count*4 */
- typedef void *(* cmdfunc)(char *, char **, long);
- /**********************************************************
- Commands available
- **********************************************************/
-
- /* NOTE!!! ARGUMENTS **MUST** FIT PROTOTYPE of cmdfunc!!!! */
-
- void cmds_help(char *dummy, char *table[], long noofcmds)
- { short j;
- fpf(err,"Known commands:\n");
- for(j = 0; j < noofcmds; j += 4)
- if(table[j+1] && table[j])
- fpf(err, "%s\tor %s (%s)\n",table[j+1], table[j], table[j+2]);
- else if(table[j+1])
- fpf(err, "%s\t(%s)\n", table[j+1], table[j+2]);
- else if(table[j])
- fpf(err, "%s\t(%s)\n", table[j], table[j+2]);
- }
- void cmds_raw(void)
- { overridepkt = IN_RAWSET; }
- void cmds_buf(void)
- { overridepkt = IN_RAWCLR; }
- void cmds_lf(void)
- { lineend = 0x0a000000; }
- void cmds_cr(void)
- { lineend = 0x0d000000; }
- void cmds_lfcr(void)
- { lineend = 0x0a0d0000; }
- void cmds_send(char *rest)
- { long n; if(rest && (n = strlen(rest))) DWrite(chan, rest, n); }
- void cmds_flush(void)
- { DIoctl(chan, CIO_FLUSH, 0, 0); fpf(err,"\nFlushed\n"); }
- void cmds_closelog(void)
- {
- if(!alogfile) return;
- fpf(err,"'%s' ", logfilename);
- ASafeClose(&alogfile);
- fpf(err,"closed ok.\n");
- }
- void cmds_log(char *rest)
- {
- cmds_closelog();
- if(!rest) return;
- spf(logfilename, sizeof(logfilename), rest, aout);
- fpf(err,"'%s' ", logfilename);
- if( !(alogfile = AEasyOpen(aout, rest, MODE_NEWFILE)) )
- fpf(err,"failed.\n"); else fpf(err,"opened ok.\n");
- }
- void cmds_execute(char *rest)
- {
- if(!rest) return;
- fpf(err,"%s Executing '%s'\n", prg, rest);
- Execute(rest, NULL, err);
- fpf(err,"%s Terminating '%s'\n", prg, rest);
- }
- void cmds_localecho(void)
- { rawlocalecho = 1; }
- void cmds_localechooff(void)
- { rawlocalecho = 0; }
- void cmds_ctrlf(void)
- { char c = 6; DWrite(chan, &c, 1); }
- void cmds_quit(void)
- { notdone = 0; }
-
- /** ADD ANY NEW COMMANDS HERE */
- static char *cmds[] = {
- "HELP","?","This message", (char *)cmds_help,
- "RAW","R","Raw (normal terminal) mode", (char *)cmds_raw,
- "BUF","B","Line buffered (shell) mode", (char *)cmds_buf,
- "LFCR",NULL,"Linefeed & Carriage Return",(char *)cmds_lfcr,
- NULL,"LF","Linefeed", (char *)cmds_lf,
- NULL,"CR","Carriage return", (char *)cmds_cr,
- "SEND",NULL,"Send text", (char *)cmds_send,
- "FLUSH","^F","Flush input", (char *)cmds_flush,
- "EXECUTE","X","AmigaDOS command", (char *)cmds_execute,
- "LOCALECHO","LE","Raw mode local echo on",(char *)cmds_localecho,
- "LOCALECHOOFF","LEO","Raw mode local echo off",(char *)cmds_localechooff,
- "LOG","L","Log to file", (char *)cmds_log,
- "CLOSELOG","CL","Close log file", (char *)cmds_closelog,
- NULL,"F","Send CTRL-F", (char *)cmds_ctrlf,
- "QUIT", NULL, "Quit terminal", (char *)cmds_quit
- };
- #define NOOFCMDS ((sizeof(cmds)/4)/4)
-
- /**********************************************************/
- void *ParseCommand(char *cmd)
- /**********************************************************
- Send this routine a command string and it will try and
- do something with it!
- **********************************************************/
- {
- char cmdbuf[400], *command, *rest;
- short n;
-
- /** KICK BACK INTO RAW IF WE WERE BEFORE (THO THIS MAY CHANGE) */
- overridepkt = prevmoderaw? IN_RAWSET : IN_NULL;
-
- /** GET THE COMMAND */
- strncpy(cmdbuf, cmd, sizeof(cmdbuf)-1); cmdbuf[sizeof(cmdbuf)-1] = 0;
- command = SkipChar(cmdbuf, WHITE);
- if(!command) return(NULL);
- rest = FindChar(command, WHITE);
- if(rest) {
- char *temp = SkipChar(rest, WHITE);
- rest[0] = '\0'; rest = temp;
- if(rest) {
- temp = FindChar(rest, EOLN);
- if(temp) temp[0] = '\0';
- }
- }
- strupper(command);
-
- /** DETERMINE THE COMMAND & DO THE CALL! */
- if((n = CmpString(command, cmds, NOOFCMDS, 4)) == -1 )
- if((n = CmpString(command, &cmds[1], NOOFCMDS, 4)) == -1 )
- { fpf(err, "%s unrecognised\n", command); return(NULL); }
- fpf(err, "%s corresponds to %ld\n", command, n);
- return(((cmdfunc)cmds[(n<<2)+3])(rest, cmds, NOOFCMDS<<2));
- }
-
- /* call this function for each character */
- typedef short (* mapfunc)(void *, char);
-
- struct CMap {
- unsigned char *Map; /* first 256 bytes is a table of offsets (/2) into next 510 bytes */
- short MapSize; /* Total in bytes */
- short MapUsed; /* Just of the seq part */
- };
-
- /**********************************************************/
- void CMapInit(struct CMap *cmap, short maxsize)
- /**********************************************************/
- {
- short i;
- for(i = 0; i < cmap->MapSize; i++) (cmap->Map)[i] = 0xff;
- cmap->MapSize = maxsize; cmap->MapUsed = 0;
- }
-
-
- /**********************************************************/
- void CMapRemoveSeq(struct CMap *cmap, char c)
- /**********************************************************/
- { short i, k, l, o;
- if((k = (cmap->Map)[c]) == 0xff) return;
- (cmap->Map) = -1;
- for(i = 0; i < 256; i++) if((cmap->Map)[i] == k) return;
- l = ((cmap->Map)[o]+2) >> 1;
- for(i = 0; i < 256; i++)
- if((cmap->Map)[i] > k) cmap->Map[i] -= l;
- l += l; o = 256 + k + k;
- cmap->MapUsed -= l;
- dbmov(&(cmap->Map)[o+l], &(cmap->Map)[o], cmap->MapSize - (o+l));
- }
-
- /**********************************************************/
- short CMapAddSeq(struct CMap *cmap, char c, char *seq)
- /**********************************************************/
- {
- short i, j, l, o, k;
- if((cmap->Map)[c] != 0xff) CMapRemoveEntry(c, cmap);
- l = strlen(seq); o = (l+2) & 0xfffe;
- k = (cmap->MapUsed+1) & 0xfffe;
- if(o + k + 256 > cmap->MapSize) return(0);
- cmap->MapUsed += m;
- (cmap->Map)[c] = k >> 1;
- (cmap->Map)[k+256] = l;
- dbmov(&((cmap->Map)[k+256+1]), seq, l);
- }
-
- /**********************************************************/
- long MapText(struct CMap *cmap, mapfunc fn, void *fn_data,
- char buffer[], short n)
- /**********************************************************
- Entries with a '-1' in the character map are unchanged
- otherwise the value is used as an offset << 1
- into the seqbase map for a complete sequence
- which has the sequence length as the first byte
- **********************************************************/
- {
- short i, k, l;
- long w;
- for(i = 0; i < n; i++)
- if((k = cmap->Map[buffer[i]]) == 0xff)
- { if(!fn(fn_data, buffer[i])) return(w); else w++; }
- else for(k += 256 + k, l = cmap->Map[k++]; k < l; k++)
- { if(!fn(fn_data, cmap->Map[k])) return(w); else w++; }
- return(w);
- }
-
-
- struct InterData {
- char *buffer; short buffersize, position;
- void *channel;
- };
- short DNet_DoWrite(InterData *data, char c)
- { data->buffer[data->position++] = c;
- if(data->position > data->buffersize)
- DWrite(data->channel, data->position, data->buffer);
- }
-
- void WriteText(void *dchan, struct CMap *cmap, char *buffer, short n)
- {
- char buf[256];
- struct InterData data;
- data.buffer = buf;
- data.buffersize = sizeof(buf);
- data.position = 0;
- data.channel = dchan;
- if(rawlocalecho && moderaw)
- { AWrite(aout, buffer, n); if(alogfile) AWrite(alogfile, buffer, n); }
- MapText(DNet_DoWrite, &data, buffer, n, cmap);
- if(data.position) DWrite(data.channel, data.position, data.buffer);
- }
-
- /**********************************************************/
- int main(int argc, char **argv)
- /**********************************************************
- Do the minimal term stuff!
- Wait on our message ports for incoming
- **********************************************************/
- {
- long amask, dmask, mask;
- char gettingoptions = 0,
- *hostname = NULL,
- inbuf[INBUFSIZE],
- currpkt, scriptmode;
-
-
- UWORD port = PORT_IALPHATERM;
- struct Process *us;
- startmem = AvailMem(MEMF_PUBLIC);
-
- /** STUFF WE NEED */
- out = Output(); in = Input(); err = Open("*", MODE_OLDFILE);
- us = (struct Process *)FindTask(NULL); SetSignal(0,SIGNALS);
- spf(prg, sizeof(prg), "%s [%s %ld]", argv[0], us->pr_Task.tc_Node.ln_Name, us->pr_TaskNum);
- IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 0);
- GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0);
-
-
- /** PRINT USAGE */
- fpf(out,"ShellTerm for DNET (uc) Stone, SST\n"
- "email: c9107253@mystra.newcastle.edu.au or c9107253@cs.newcastle.edu.au\n"
- "\nCTRL-\\ or CTRL-F then CTRL-C to quit, CTRL-F for options\n\n");
- if( argc<2 )
- fpf(err,"(Use: %s [>file] [<file] [DNET_PORTNUMBER] [NETWORK])\n", argv[0]);
-
-
- /** PARSE COMMAND LINE */
- if(argc > 1) port = (UWORD) atoi(argv[1]);
- if(argc > 2) hostname = argv[2];
-
-
- /** GET ASYNC INPUT & OUTPUT HANDLES ON DIFFERENT PORTS */
- if(! (ain = AEasyMakeFD2AFD(NULL, in)))
- { fpf(err, "No input!?\n"); goto e3; }
- if(! (aout = AEasyMakeFD2AFD(NULL, out)))
- { fpf(err, "No output!?\n"); goto e3; }
- if(!IsInteractive(((long)(ain->FileHandle))>>2))
- { fpf(err, "Warning: input is not of console type\n"); }
- DoPacket(ain, 0, 0, currpkt = IN_WAIT);
- overridepkt = IN_NULL;
- cmds_lf();
- cmds_localechooff();
- moderaw = 0;
-
-
- /** DO THAT FUNKY DNET STUFF */
- fpf(out,"Opening port %ld on network %s ",port,hostname?hostname:"0");
- if( ! (chan = DOpen(hostname, port, 20, 15)) )
- { fpf(err,"Sorry, Unable to connect\n"); goto e3; }
- DQueue(chan, 32);
- DIoctl(chan, CIO_SETROWS, 25, 0); DIoctl(chan, CIO_SETCOLS, 80, 0);
- fpf(out,"connected\n");
-
-
- /** KEEP ON LOOPING */
- dmask = 1 << ((PORT *)chan)->mp_SigBit;
- amask = 1 << ASIGBIT(ain);
- for (notdone = 1; notdone;) {
-
- mask = Wait(amask | dmask | SIGNALS);
-
- /** CHECK ASYNC INPUT FROM USER */
- if (mask & amask) {
- long n; struct AFileHandle *currafh;
-
- /** BE *VERY* CAREFUL ON WHERE WE MAY "ACCIDENTALLY" GETMSG */
- while(currafh = AGetReply(ain->APort)) {
- n = AResult(currafh);
- if(currafh == ain) {
- /** CHECK REPLY OF PACKET */
- switch(currpkt) {
- case IN_WAIT:
- currpkt = n? IN_CHARS: IN_WAIT;
- break;
- case IN_CHARS:
- currpkt = IN_WAIT;
- if(!n) notdone = 0;
- else if(n > 0) {
- if(!gettingoptions)
- WriteText(chan, inbuf, n, (char *)&lineend);
- else { ParseCommand(inbuf); gettingoptions = 0; }
- }
- break;
- case IN_RAWSET:
- currpkt = IN_WAIT;
- if(!n) fpf(err, "Couldn't set terminal mode RAW\n");
- else moderaw = 1;
- break;
- case IN_RAWCLR:
- currpkt = IN_WAIT;
- moderaw = 0;
- break;
- }
- /** SEND OUT NEXT PACKET (NOW CURRENT PACKET) */
- if(overridepkt) currpkt = overridepkt; overridepkt = 0;
- DoPacket(currafh, inbuf, sizeof(inbuf)-4, currpkt);
-
- } /* else OTHER INPUT FILES (others?? nah!) */
- }
- }
-
-
- /** CHECK DNET */
- if (mask & dmask) {
- long n;
- if ((n = DNRead(chan, Buf, sizeof(Buf))) > 0) {
- /* WE GOT SOME TEXT! PRINT TO STD OUTPUT! */
- AWrite(aout, Buf, n);
- if(alogfile) AWrite(alogfile, Buf, n);
- } else if (n == -2) {
- short val, cmd; char aux;
- cmd = DGetIoctl(chan, &val, &aux);
- switch(cmd) {
- case CIO_MODE:
- overridepkt = val ? IN_RAWCLR: IN_RAWSET; break;
- case CIO_SETROWS:
- break;
- case CIO_SETCOLS:
- break;
- }
-
- } else if (n < 0) cmds_quit();
- }
-
-
- /** CHECK SIGNALS (AND SEND THEM PERHAPS) */
- if(mask & SIGBREAKF_CTRL_C) {
- if(gettingoptions) cmds_quit();
- else { char c = 3; DWrite(chan, &c, 1); }
- }
-
- if(mask & SIGBREAKF_CTRL_D)
- { char c = 4; DWrite(chan, &c, 1); }
-
- if(mask & SIGBREAKF_CTRL_E)
- { char c = 5; DWrite(chan, &c, 1); }
-
- if(mask & SIGBREAKF_CTRL_F) {
- if(gettingoptions) {
- cmds_flush();
- gettingoptions = 0;
- } else {
- fpf(err,"\n%s ? <return> for help\n", prg);
- if(prevmoderaw = moderaw) overridepkt = IN_RAWCLR;
- gettingoptions = 1;
- }
- }
- }
-
-
- /** END ALL THE PAIN */
- e3:
- if(ain && moderaw) {
- fpf(err,"\nChanging mode back to normal");
- AResultWait(ain);
- DoPacket(ain, 0, 0, IN_RAWCLR); }
-
- fpf(err,"\n%s Closing channel. ", prg);
- if(chan) DClose(chan);
- /** CLOSE ALL FILES ON THE 2 PORTS */
- fpf(err,"output. ");
- ADeletePort(aout->APort);
- fpf(err,"input. ");
- ADeletePort(ain->APort);
- fpf(err,"done!\n");
- if(err) Close(err);
- CloseLibrary((LIB *)IntuitionBase);
- CloseLibrary((LIB *)GfxBase);
- return(0);
- }
-
- /* to add:
-
- arexx support
- text message support
-
- */
-