home *** CD-ROM | disk | FTP | other *** search
/ Network CD 2 / Network CD - Volume 2.iso / programs / internet / dnet / dshterm1_0.lha / client / shellterm_old.c < prev   
Encoding:
C/C++ Source or Header  |  1992-02-04  |  15.6 KB  |  517 lines

  1. /**********************************************************
  2.  *                                                        *
  3.  * Minimal Term for DNET (uc) Stone, SST                  *
  4.  * Further modifications by Unknown, SST                  *
  5.  * Based on FTerm by Matt Dillon                          *
  6.  *                                                        *
  7.  * ShellTerm [DNET_PORT] [NETWORK]                        *
  8.  *                                                        *
  9.  * Set ya TABS to 4!                                      *
  10.  * Email me!! c9107253@mystra.newcastle.edu.au            *
  11.  * For any reason!! (eg DNet, AmiNet, Demos, amigas...)   *
  12.  * Please send any changes U make!                        *
  13.  * Fully public domain                                    *
  14.  * Mega-thanx to Azza of the SST for hours of DNET source *
  15.  * modification.... yes it compiles under SAS 6!          *
  16.  **********************************************************/
  17.  
  18. #include "defs.h"
  19.  
  20. /* DEFAULT STRINGS */
  21. char    *WHITE        = " \t\n\r",
  22.         *EOLN        = "\n\r";
  23.  
  24. /* STANDARD FILE HANDLES */
  25. long    out, err, in;
  26.  
  27. struct    AFileHandle    *ain, *aout, *alogfile;
  28. char    overridepkt, prevmoderaw, rawlocalecho, moderaw, notdone;
  29. long    lineend;
  30. char    Buf[512], prg[40], logfilename[100];
  31. void    *chan;
  32. long    startmem;
  33.  
  34. extern struct IntuitionBase    *IntuitionBase;
  35. extern struct GfxBase        *GfxBase;
  36.  
  37. #define SIGNALS (SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D | SIGBREAKF_CTRL_E | SIGBREAKF_CTRL_F)
  38.  
  39. /* standard in & out async file handles */
  40. #define INBUFSIZE        500
  41. #define WAIT_TIMEOUT    700000 /* uSeconds */
  42.  
  43.  
  44. /* Do this on the next packet return */
  45. #define IN_NULL            0
  46. #define IN_WAIT            1
  47. #define IN_CHARS        2
  48. #define IN_RAWSET        3
  49. #define IN_RAWCLR        4
  50.  
  51.  
  52. /**********************************************************/
  53. void  DoPacket(struct AFileHandle *afh, void *qbuf,
  54.                                     long size, char pkttype)
  55. /**********************************************************
  56.      Send a packet according to type. qbuf & size may not
  57.          be required (in fact only used for ARead)
  58.  **********************************************************/
  59. {
  60.     switch(pkttype) {
  61.         case IN_WAIT:
  62.             ASendPacket(afh, ACTION_WAIT_CHAR, WAIT_TIMEOUT, 0, 0, 0); break;
  63.         case IN_CHARS:
  64.             ARead(afh, qbuf, size); break;
  65.         case IN_RAWSET:
  66.             ASendPacket(afh, ACTION_SCREEN_MODE, 1, 0, 0, 0); break;
  67.         case IN_RAWCLR:
  68.             ASendPacket(afh, ACTION_SCREEN_MODE, 0, 0, 0, 0); break;
  69.     }
  70. }
  71.  
  72. /**********************************************************/
  73. short CmpString(char *cmd, char *table[], long n, long dist)
  74. /**********************************************************
  75.      Test a string against a table of string pointers,
  76.   using every 'dist' pointer for a total of 'n' compares
  77.                    return -1 on fail
  78.          otherwise the index (ith compare ie 0, 1, 2 ... )
  79.  **********************************************************/
  80. {
  81. short i, j;
  82.     for(i = 0, j = 0; i < n; i++)
  83.         if(table[j] && (strncmp(cmd, table[j], strlen(table[j])) == 0)) return(i);
  84.         else j += dist;
  85.     return(-1);
  86. }
  87.  
  88. /**********************************************************/
  89. char            *FindChar(char *string, char *instring)
  90. /**********************************************************
  91.   Find first character of 'string' contained in 'instring'
  92.  **********************************************************/
  93. {
  94. short i, j;
  95.     if(!(string && instring)) return(NULL);
  96.     for(i = 0; string[i]; i++)
  97.         for(j = 0; instring[j]; j++)
  98.             if(string[i] == instring[j]) return(&string[i]);
  99.     return(NULL);
  100. }
  101.  
  102. /**********************************************************/
  103. char            *SkipChar(char *string, char *instring)
  104. /**********************************************************
  105. Find first character of 'string' not contained in 'instring'
  106.  **********************************************************/
  107. {
  108. short i, j;
  109.     if(!(string && instring)) return(NULL);
  110.     for(i = 0; string[i]; i++) {
  111.         for(j = 0; instring[j] && (instring[j] != string[i]); j++);
  112.         if(instring[j] == '\0') return(&string[i]);
  113.     }
  114.     return(NULL);
  115. }
  116.  
  117. /* pass: rest of argline, command table, command count*4 */
  118. typedef void *(* cmdfunc)(char *, char **, long);
  119. /**********************************************************
  120.                   Commands available
  121.  **********************************************************/
  122.  
  123. /* NOTE!!! ARGUMENTS **MUST** FIT PROTOTYPE of cmdfunc!!!! */
  124.  
  125. void cmds_help(char *dummy, char *table[], long noofcmds)
  126. { short j;
  127.     fpf(err,"Known commands:\n");
  128.     for(j = 0; j < noofcmds; j += 4)
  129.         if(table[j+1] && table[j])
  130.             fpf(err, "%s\tor %s (%s)\n",table[j+1], table[j], table[j+2]);
  131.         else if(table[j+1])
  132.             fpf(err, "%s\t(%s)\n", table[j+1], table[j+2]);
  133.         else if(table[j])
  134.             fpf(err, "%s\t(%s)\n", table[j], table[j+2]);
  135. }
  136. void cmds_raw(void)
  137. { overridepkt = IN_RAWSET; }
  138. void cmds_buf(void)
  139. { overridepkt = IN_RAWCLR; }
  140. void cmds_lf(void)
  141. { lineend = 0x0a000000; }
  142. void cmds_cr(void)
  143. { lineend = 0x0d000000; }
  144. void cmds_lfcr(void)
  145. { lineend = 0x0a0d0000; }
  146. void cmds_send(char *rest)
  147. { long n; if(rest && (n = strlen(rest))) DWrite(chan, rest, n); }
  148. void cmds_flush(void)
  149. { DIoctl(chan, CIO_FLUSH, 0, 0); fpf(err,"\nFlushed\n"); }
  150. void cmds_closelog(void)
  151. {
  152.     if(!alogfile) return;
  153.     fpf(err,"'%s' ", logfilename);
  154.     ASafeClose(&alogfile);
  155.     fpf(err,"closed ok.\n");
  156. }
  157. void cmds_log(char *rest)
  158. {
  159.     cmds_closelog();
  160.     if(!rest) return;
  161.     spf(logfilename, sizeof(logfilename), rest, aout);
  162.     fpf(err,"'%s' ", logfilename);
  163.     if( !(alogfile = AEasyOpen(aout, rest, MODE_NEWFILE)) )
  164.         fpf(err,"failed.\n"); else fpf(err,"opened ok.\n");
  165. }
  166. void cmds_execute(char *rest)
  167. {
  168.     if(!rest) return;
  169.     fpf(err,"%s Executing '%s'\n", prg, rest);
  170.     Execute(rest, NULL, err);
  171.     fpf(err,"%s Terminating '%s'\n", prg, rest);
  172. }
  173. void cmds_localecho(void)
  174. { rawlocalecho = 1; }
  175. void cmds_localechooff(void)
  176. { rawlocalecho = 0; }
  177. void cmds_ctrlf(void)
  178. { char c = 6; DWrite(chan, &c, 1); }
  179. void cmds_quit(void)
  180. { notdone = 0; }
  181.  
  182. /** ADD ANY NEW COMMANDS HERE */
  183. static char *cmds[] = {
  184.     "HELP","?","This message",                (char *)cmds_help,
  185.     "RAW","R","Raw (normal terminal) mode",    (char *)cmds_raw,
  186.     "BUF","B","Line buffered (shell) mode",    (char *)cmds_buf,
  187.     "LFCR",NULL,"Linefeed & Carriage Return",(char *)cmds_lfcr,
  188.     NULL,"LF","Linefeed",                    (char *)cmds_lf,
  189.     NULL,"CR","Carriage return",            (char *)cmds_cr,
  190.     "SEND",NULL,"Send text",                (char *)cmds_send,
  191.     "FLUSH","^F","Flush input",                (char *)cmds_flush,
  192.     "EXECUTE","X","AmigaDOS command",        (char *)cmds_execute,
  193.     "LOCALECHO","LE","Raw mode local echo on",(char *)cmds_localecho,
  194.     "LOCALECHOOFF","LEO","Raw mode local echo off",(char *)cmds_localechooff,
  195.     "LOG","L","Log to file",                (char *)cmds_log,
  196.     "CLOSELOG","CL","Close log file",        (char *)cmds_closelog,
  197.     NULL,"F","Send CTRL-F",                    (char *)cmds_ctrlf,
  198.     "QUIT", NULL, "Quit terminal",            (char *)cmds_quit
  199. };
  200. #define NOOFCMDS    ((sizeof(cmds)/4)/4)
  201.  
  202. /**********************************************************/
  203. void                *ParseCommand(char *cmd)
  204. /**********************************************************
  205.   Send this routine a command string and it will try and
  206.                do something with it!
  207.  **********************************************************/
  208. {
  209. char cmdbuf[400], *command, *rest;
  210. short n;
  211.  
  212. /** KICK BACK INTO RAW IF WE WERE BEFORE (THO THIS MAY CHANGE) */
  213.     overridepkt = prevmoderaw? IN_RAWSET : IN_NULL;
  214.  
  215. /** GET THE COMMAND */
  216.     strncpy(cmdbuf, cmd, sizeof(cmdbuf)-1); cmdbuf[sizeof(cmdbuf)-1] = 0;
  217.     command = SkipChar(cmdbuf, WHITE);
  218.     if(!command) return(NULL);
  219.     rest = FindChar(command, WHITE);
  220.     if(rest) {
  221.         char *temp = SkipChar(rest, WHITE);
  222.         rest[0] = '\0'; rest = temp;
  223.         if(rest) {
  224.             temp = FindChar(rest, EOLN);
  225.             if(temp) temp[0] = '\0';
  226.         }
  227.     }
  228.     strupper(command);
  229.  
  230. /** DETERMINE THE COMMAND & DO THE CALL! */
  231.     if((n = CmpString(command, cmds, NOOFCMDS, 4)) == -1 )
  232.         if((n = CmpString(command, &cmds[1], NOOFCMDS, 4)) == -1 )
  233.             { fpf(err, "%s unrecognised\n", command); return(NULL); }
  234.     fpf(err, "%s corresponds to %ld\n", command, n);
  235.     return(((cmdfunc)cmds[(n<<2)+3])(rest, cmds, NOOFCMDS<<2));
  236. }
  237.  
  238. /* call this function for each character */
  239. typedef short (* mapfunc)(void *, char);
  240.  
  241. struct CMap {
  242.     unsigned char *Map;        /* first 256 bytes is a table of offsets (/2) into next 510 bytes */
  243.     short    MapSize;        /* Total in bytes */
  244.     short    MapUsed;        /* Just of the seq part */
  245. };
  246.  
  247. /**********************************************************/
  248. void            CMapInit(struct CMap *cmap, short maxsize)
  249. /**********************************************************/
  250. {
  251. short i;
  252.     for(i = 0; i < cmap->MapSize; i++) (cmap->Map)[i] = 0xff;
  253.     cmap->MapSize = maxsize; cmap->MapUsed = 0;
  254. }
  255.  
  256.  
  257. /**********************************************************/
  258. void    CMapRemoveSeq(struct CMap *cmap, char c)
  259. /**********************************************************/
  260. {    short i, k, l, o;
  261.     if((k = (cmap->Map)[c]) == 0xff) return;
  262.     (cmap->Map) = -1;
  263.     for(i = 0; i < 256; i++) if((cmap->Map)[i] == k) return;
  264.     l = ((cmap->Map)[o]+2) >> 1;
  265.     for(i = 0; i < 256; i++)
  266.         if((cmap->Map)[i] > k) cmap->Map[i] -= l;
  267.     l += l; o = 256 + k + k;
  268.     cmap->MapUsed -= l;
  269.     dbmov(&(cmap->Map)[o+l], &(cmap->Map)[o], cmap->MapSize - (o+l));
  270. }
  271.  
  272. /**********************************************************/
  273. short    CMapAddSeq(struct CMap *cmap, char c, char *seq)
  274. /**********************************************************/
  275. {
  276. short i, j, l, o, k;
  277.     if((cmap->Map)[c] != 0xff) CMapRemoveEntry(c, cmap);
  278.     l = strlen(seq); o = (l+2) & 0xfffe;
  279.     k = (cmap->MapUsed+1) & 0xfffe;
  280.     if(o + k + 256 > cmap->MapSize) return(0);
  281.     cmap->MapUsed += m;
  282.     (cmap->Map)[c] = k >> 1;
  283.     (cmap->Map)[k+256] = l;
  284.     dbmov(&((cmap->Map)[k+256+1]), seq, l);
  285. }
  286.  
  287. /**********************************************************/
  288. long MapText(struct CMap *cmap, mapfunc fn, void *fn_data,
  289.                             char buffer[], short n)
  290. /**********************************************************
  291.    Entries with a '-1' in the character map are unchanged
  292.        otherwise the value is used as an offset << 1
  293.         into the seqbase map for a complete sequence
  294.       which has the sequence length as the first byte
  295.  **********************************************************/
  296. {
  297. short i, k, l;
  298. long w;
  299.     for(i = 0; i < n; i++)
  300.         if((k = cmap->Map[buffer[i]]) == 0xff)
  301.             { if(!fn(fn_data, buffer[i])) return(w); else w++; }
  302.         else for(k += 256 + k, l = cmap->Map[k++]; k < l; k++)
  303.             { if(!fn(fn_data, cmap->Map[k])) return(w); else w++; }
  304.     return(w);
  305. }
  306.  
  307.  
  308. struct InterData {
  309.     char    *buffer; short buffersize, position;
  310.     void    *channel;
  311. };
  312. short DNet_DoWrite(InterData *data, char c)
  313. {    data->buffer[data->position++] = c;
  314.     if(data->position > data->buffersize)
  315.         DWrite(data->channel, data->position, data->buffer);
  316. }
  317.  
  318. void WriteText(void *dchan, struct CMap *cmap, char *buffer, short n)
  319. {
  320. char buf[256];
  321. struct InterData data;
  322.     data.buffer = buf;
  323.     data.buffersize = sizeof(buf);
  324.     data.position = 0;
  325.     data.channel = dchan;
  326.     if(rawlocalecho && moderaw)
  327.         { AWrite(aout, buffer, n); if(alogfile) AWrite(alogfile, buffer, n); }
  328.     MapText(DNet_DoWrite, &data, buffer, n, cmap);
  329.     if(data.position) DWrite(data.channel, data.position, data.buffer);
  330. }
  331.  
  332. /**********************************************************/
  333.              int main(int argc, char **argv)
  334. /**********************************************************
  335.                 Do the minimal term stuff!
  336.         Wait on our message ports for incoming
  337.  **********************************************************/
  338. {
  339. long    amask, dmask, mask;
  340. char    gettingoptions = 0,
  341.         *hostname = NULL,
  342.         inbuf[INBUFSIZE],
  343.         currpkt, scriptmode;
  344.  
  345.  
  346. UWORD    port    =    PORT_IALPHATERM;
  347. struct    Process *us;
  348.     startmem = AvailMem(MEMF_PUBLIC);
  349.  
  350. /** STUFF WE NEED */
  351.     out = Output(); in = Input(); err = Open("*", MODE_OLDFILE);
  352.     us = (struct Process *)FindTask(NULL); SetSignal(0,SIGNALS);
  353.     spf(prg, sizeof(prg), "%s [%s %ld]", argv[0], us->pr_Task.tc_Node.ln_Name, us->pr_TaskNum);
  354.     IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 0);
  355.     GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0);
  356.  
  357.  
  358. /** PRINT USAGE */
  359.     fpf(out,"ShellTerm for DNET (uc) Stone, SST\n"
  360.         "email: c9107253@mystra.newcastle.edu.au or c9107253@cs.newcastle.edu.au\n"
  361.         "\nCTRL-\\ or CTRL-F then CTRL-C to quit, CTRL-F for options\n\n");
  362.     if( argc<2 )
  363.         fpf(err,"(Use: %s [>file] [<file] [DNET_PORTNUMBER] [NETWORK])\n", argv[0]);
  364.  
  365.  
  366. /** PARSE COMMAND LINE */
  367.     if(argc > 1) port = (UWORD) atoi(argv[1]);
  368.     if(argc > 2) hostname = argv[2];
  369.  
  370.  
  371. /** GET ASYNC INPUT & OUTPUT HANDLES ON DIFFERENT PORTS */
  372.     if(! (ain = AEasyMakeFD2AFD(NULL, in)))
  373.         { fpf(err, "No input!?\n"); goto e3; }
  374.     if(! (aout = AEasyMakeFD2AFD(NULL, out)))
  375.         { fpf(err, "No output!?\n"); goto e3; }
  376.     if(!IsInteractive(((long)(ain->FileHandle))>>2))
  377.         { fpf(err, "Warning: input is not of console type\n"); }
  378.     DoPacket(ain, 0, 0, currpkt = IN_WAIT);
  379.     overridepkt = IN_NULL;
  380.     cmds_lf();
  381.     cmds_localechooff();
  382.     moderaw = 0;
  383.  
  384.  
  385. /** DO THAT FUNKY DNET STUFF */
  386.     fpf(out,"Opening port %ld on network %s ",port,hostname?hostname:"0");
  387.     if( ! (chan = DOpen(hostname, port, 20, 15)) )
  388.         { fpf(err,"Sorry, Unable to connect\n"); goto e3; }
  389.     DQueue(chan, 32);
  390.     DIoctl(chan, CIO_SETROWS, 25, 0); DIoctl(chan, CIO_SETCOLS, 80, 0);
  391.     fpf(out,"connected\n");
  392.  
  393.  
  394. /** KEEP ON LOOPING */
  395.     dmask   = 1 << ((PORT *)chan)->mp_SigBit;
  396.     amask    = 1 << ASIGBIT(ain);
  397.     for (notdone = 1; notdone;) {
  398.  
  399.         mask = Wait(amask | dmask | SIGNALS);
  400.  
  401.     /** CHECK ASYNC INPUT FROM USER */
  402.         if (mask & amask) {
  403.             long n; struct AFileHandle *currafh;
  404.  
  405.         /** BE *VERY* CAREFUL ON WHERE WE MAY "ACCIDENTALLY" GETMSG */
  406.             while(currafh = AGetReply(ain->APort)) {
  407.                 n = AResult(currafh);
  408.                 if(currafh == ain) {
  409.                 /** CHECK REPLY OF PACKET */
  410.                     switch(currpkt) {
  411.                         case IN_WAIT:
  412.                             currpkt = n? IN_CHARS: IN_WAIT;
  413.                             break;
  414.                         case IN_CHARS:
  415.                             currpkt = IN_WAIT;
  416.                             if(!n) notdone = 0;
  417.                             else if(n > 0) {
  418.                                 if(!gettingoptions)
  419.                                     WriteText(chan, inbuf, n, (char *)&lineend);
  420.                                 else { ParseCommand(inbuf); gettingoptions = 0; }
  421.                             }
  422.                             break;
  423.                         case IN_RAWSET:
  424.                             currpkt = IN_WAIT;
  425.                             if(!n) fpf(err, "Couldn't set terminal mode RAW\n");
  426.                             else moderaw = 1;
  427.                             break;
  428.                         case IN_RAWCLR:
  429.                             currpkt = IN_WAIT;
  430.                             moderaw = 0;
  431.                             break;
  432.                     }
  433.                 /** SEND OUT NEXT PACKET (NOW CURRENT PACKET) */
  434.                     if(overridepkt) currpkt = overridepkt;  overridepkt = 0;
  435.                     DoPacket(currafh, inbuf, sizeof(inbuf)-4, currpkt);
  436.  
  437.                 } /* else OTHER INPUT FILES (others?? nah!) */
  438.             }
  439.         }
  440.  
  441.  
  442.     /** CHECK DNET */
  443.         if (mask & dmask) {
  444.             long n;
  445.             if ((n = DNRead(chan, Buf, sizeof(Buf))) > 0) {
  446.                 /* WE GOT SOME TEXT! PRINT TO STD OUTPUT! */
  447.                 AWrite(aout, Buf, n);
  448.                 if(alogfile) AWrite(alogfile, Buf, n);
  449.             } else if (n == -2) {
  450.                 short val, cmd; char aux;
  451.                 cmd = DGetIoctl(chan, &val, &aux);
  452.                 switch(cmd) {
  453.                     case CIO_MODE:
  454.                         overridepkt = val ? IN_RAWCLR: IN_RAWSET; break;
  455.                     case CIO_SETROWS:
  456.                         break;
  457.                     case CIO_SETCOLS:
  458.                         break;
  459.                 }
  460.  
  461.             } else if (n < 0) cmds_quit();
  462.         }
  463.  
  464.  
  465.     /** CHECK SIGNALS (AND SEND THEM PERHAPS) */
  466.         if(mask & SIGBREAKF_CTRL_C) {
  467.             if(gettingoptions) cmds_quit();
  468.             else { char c = 3; DWrite(chan, &c, 1); }
  469.         }
  470.  
  471.         if(mask & SIGBREAKF_CTRL_D)
  472.             { char c = 4; DWrite(chan, &c, 1); }
  473.  
  474.         if(mask & SIGBREAKF_CTRL_E)
  475.             { char c = 5; DWrite(chan, &c, 1); }
  476.  
  477.         if(mask & SIGBREAKF_CTRL_F) {
  478.             if(gettingoptions) {
  479.                 cmds_flush();
  480.                 gettingoptions = 0;
  481.             } else {
  482.                 fpf(err,"\n%s   ? <return> for help\n", prg);
  483.                 if(prevmoderaw = moderaw) overridepkt = IN_RAWCLR;
  484.                 gettingoptions = 1;
  485.             }
  486.         }
  487.     }
  488.  
  489.  
  490. /** END ALL THE PAIN */
  491. e3:
  492.     if(ain && moderaw) {
  493.         fpf(err,"\nChanging mode back to normal");
  494.         AResultWait(ain);
  495.         DoPacket(ain, 0, 0, IN_RAWCLR); }
  496.  
  497.     fpf(err,"\n%s Closing channel. ", prg);
  498.     if(chan) DClose(chan);
  499. /** CLOSE ALL FILES ON THE 2 PORTS */
  500.     fpf(err,"output. ");
  501.     ADeletePort(aout->APort);
  502.     fpf(err,"input. ");
  503.     ADeletePort(ain->APort);
  504.     fpf(err,"done!\n");
  505.     if(err) Close(err);
  506.     CloseLibrary((LIB *)IntuitionBase);
  507.     CloseLibrary((LIB *)GfxBase);
  508.     return(0);
  509. }
  510.  
  511. /* to add:
  512.  
  513. arexx support
  514. text message support
  515.  
  516. */
  517.