home *** CD-ROM | disk | FTP | other *** search
- /************************************************
- * *
- * NutShell, an accessory for mouse-haters. *
- * *
- * written by *
- * Geert Jan van Oldenborgh, *
- * Ank van der Moerstraat 24, *
- * NL-2331 HS Leiden, *
- * tel 071-317512. *
- * t19@nikhefh.hep.nl *
- * *
- * and free for anyone. *
- * *
- ************************************************/
- /* #[ header: */
- #include <stdio.h>
- #include <stdlib.h>
- #include <aes.h>
- #include <tos.h>
- #include <string.h>
- #include <ext.h>
-
- /* REDRAW: no separate screen, save only menu bar,
- no REDRAW: save whole screen. */
- #define REDRAW
-
- #define MOUSE_ON graf_mouse( M_ON, (void *)0 )
- #define MOUSE_OFF graf_mouse( M_OFF, (void *)0 )
-
- #define BYTE unsigned char
-
- #define VT52_LEFT 'D'
- #define VT52_RIGHT 'C'
- #define VT52_CLRLINE 'K'
- #define VT52_CUR_ON 'e'
- #define VT52_CUR_OFF 'f'
- #define VT52_HOME 'H'
- #define VT52_CLEAR "E<-H"[0]
- #define CRETURN '\x0D'
-
- #define PROMPT "$ "
-
- /* prototypes */
-
- int getscreen(void);
- void redrawscreen(void);
- void eventloop(void);
- void putstring(char *string);
- void getstring(BYTE *string, int length);
- void putletter(char letter);
- void putescape(char letter);
- void clearcursor(void);
- void newline(void);
- void backspace(int n);
- void putenvparent(char *entry, char *env);
- void setshell(void);
- int mysystem(char *string);
- void zero_shell_p(void);
-
- /* #] header: */
- /* #[ globals: */
-
- /* AES garbage */
- int appl_id;
- int menu_id;
- int buffer[16];
-
- extern int _app;
-
- /* Basepage */
- extern BASPAG *_BasPag;
-
- /* screen info */
- #ifndef REDRAW
- long screensize = 5 + 32256L;
- #else
- int screensize;
- #endif
- int res,screenh,screenw;
- void *oldLogbase, *oldPhysbase, *newBase;
- char *screen_mem, *extra_mem,
- motd[] = "NutShell version 0.1, "\
- __DATE__\
- ", use 'lo' to exit",
- shell[] = "d:\\shell.prg\0<- your shell",
- home[] = "HOME=e:\\\0<- your home",
- error[] = "cannot execute or find shell",
- magic[] = "GJvO",
- st[] = "unset tosonly";
- long extra_size = 0L;
- int extra_allocated = 0,
- screen_allocated = 0,
- busy = 0,
- no_shell;
- BYTE string[79],
- oudstring[78] = "lo";
-
- /* #] globals: */
- /* #[ main: */
-
- int
- main(void)
- /********************************************************
- * *
- * NutShell: passes commends to any running shell *
- * which accepts system() calls over _shell_p *
- * *
- ********************************************************/
- {
- /* go through the all the formalities */
-
- if ( !_app )
- {
- appl_id = appl_init();
- if ( appl_id == -1 ) return(0);
- menu_id = menu_register( appl_id, " NutShell");
- if ( menu_id == -1 ) return(-1);
-
- #ifdef REDRAW
- /* find ot the resolution, set some globals accordingly (will not
- work on a 19" screen) */
- res = Getrez();
- switch ( res )
- {
- case 2:
- screenh = 400;
- screenw = 640;
- screensize = 19*80 + 5;
- break;
- case 1:
- screenh = 400;
- screenw = 320;
- screensize = 19*40 + 5;
- break;
- case 0:
- screenh = 200;
- screenw = 320;
- screensize = 10*40 + 5;
- break;
- }
- #endif
-
- /* if an accessory, hit _shell_p to 0 (there cannot be a shell) */
- Supexec(zero_shell_p);
- }
-
- /* and GO */
- eventloop();
-
- return(0);
- }
-
- /* #] main: */
- /* #[ eventloop: */
- void
- eventloop(void)
- {
- /* #[ loop: */
- /* the main (unending) loop: if an accesory, wait for an AC_OPEN or
- AC_CLOSE */
-
- while ( 1 ) {
-
- if ( !_app ) evnt_mesag(buffer);
- if ( busy ) continue;
-
- /* #] loop: */
- /* #[ open: */
- if ( _app || buffer[0] == AC_OPEN && buffer[4] == menu_id )
- {
- /* set a flag to indicate that we are being called
- recursively */
- busy = 1;
-
- /* The first thing to do is to free the memory we stole
- during startop of the .prg program (or desktop) */
- if ( extra_allocated )
- {
- extra_allocated = 0;
- if ( ! strcmp(extra_mem,magic) )
- {
- #ifdef DEBUG
- puts("freed extra_mem ");
- #endif
- Mfree( extra_mem );
- }
- else
- #ifdef DEBUG
- puts("lost extra_mem ");
- #endif
- ;
- }
- /* check whether we still own the screen */
- if ( screen_allocated )
- {
- if ( strcmp(screen_mem,magic) )
- {
- #ifdef DEBUG
- puts("lost screen ");
- #endif
- screen_allocated = 0;
- }
- else
- {
- #ifdef DEBUG
- puts("screen still OK ");
- #endif
- }
- }
- if ( getscreen() ) continue;
-
- if ( system("free") )
- {
- no_shell = 1;
- if ( mysystem("free") )
- {
- putstring(error);
- newline();
- }
- }
- else
- no_shell = 0;
- /* make doubly sure we only execute TOS progs (not much use)*/
- if ( !_app ) system(st+2);
-
- while ( 1 )
- {
- putstring(PROMPT);
- clearcursor();
- getstring(string,78);
- if ( ! strcmp(string,"lo") ) break;
- else if ( ! strncmp(string,"malloc",6) )
- {
- if ( (int)strlen(string) <= 7 )
- putstring("Usage: malloc extra_size[kB]");
- else
- {
- extra_size = 1024L * atol( string + 6 );
- if ( extra_size )
- putstring("trying");
- else
- putstring("given");
- }
- newline();
- }
- else
- {
- if ( no_shell )
- mysystem(string);
- else
- system(string);
- }
- }
-
- /* clean up */
- if ( _app )
- {
- MOUSE_ON;
- putescape(VT52_CUR_OFF);
- break;
- }
-
- system(st);
- redrawscreen();
-
- if ( extra_size )
- {
- if ( ( extra_mem = Malloc( extra_size ) ) > NULL )
- {
- #ifdef DEBUG
- puts("allocated extra_mem ");
- #endif
- strcpy(extra_mem,magic);
- extra_allocated = 1;
- }
- }
- else
- {
- /* give up everything */
- #ifdef DEBUG
- puts("freed screen ");
- #endif
- Mfree( screen_mem );
- screen_allocated = 0;
- }
-
- busy = 0;
- }
- /* #] open: */
- /* #[ close: */
- if ( buffer[0] == AC_CLOSE )
- {
- /* Just for safety if we happen to receive an AC_CLOSE within one
- application. Note that we rely heavily on the zeroing of
- memory when an application starts */
-
- if ( screen_allocated && ! strcmp(screen_mem,magic) )
- {
- #ifdef DEBUG
- puts("freed screen ");
- #endif
- Mfree(screen_mem);
- }
- if ( extra_allocated && ! strcmp(extra_mem,magic) )
- {
- #ifdef DEBUG
- puts("freed extra_mem ");
- #endif
- Mfree(extra_mem);
- }
- extra_allocated = 0;
- screen_allocated = 0;
-
- /* This may look strange, but remember that when running a shell
- the AC_CLOSE does not arrive until we start a GEM application
- which does an appl_init() or evnt_time(0,0). The result is
- that we steal (extra_size + screensize) bytes from every .prg
- application, but NOT from .tos or .ttp jobs like TeX and tcc.
- */
- /* I should check that I am not in the desktop, does anyone know
- a trick on how to do this??? */
-
- if ( extra_size )
- {
- if ( ( screen_mem = Malloc( screensize )) > NULL )
- {
- #ifdef DEBUG
- puts("allocated screen ");
- #endif
- screen_allocated = 2;
- strcpy(screen_mem,magic);
- if ( ( extra_mem = Malloc( extra_size )) > NULL )
- {
- #ifdef DEBUG
- puts("allocated extra ");
- #endif
- extra_allocated = 1;
- strcpy(extra_mem,magic);
- }
- }
- }
- }
- }
- /* #] close: */
- }
- /* #] eventloop: */
- /* #[ getscreen: */
-
- int
- getscreen(void)
- {
- if ( !_app )
- {
- if ( !screen_allocated )
- {
- screen_mem = Malloc( screensize + 17000L );
- if ( screen_mem <= NULL )
- {
- form_alert(1,"[3][| Not enough | memory left ][ Back to GEM ]");
- busy = 0;
- return(1);
- }
- Mshrink( 0, screen_mem, screensize );
- #ifdef DEBUG
- puts("Allocated screen");
- #endif
- }
- oldPhysbase = Physbase();
- oldLogbase = Logbase();
- #ifdef REDRAW
- /* copy the menubar to own memory */
- memcpy(screen_mem + 5, oldPhysbase, screensize - 5);
- #else
- /* switch to new screen */
- newBase = (void *)( (long)(screen_mem + 260) & 0xFFFFFF00L);
- Setscreen( newBase, newBase, -1 );
- Vsync();
- #endif
- }
- /* cursor on and clear screen */
- MOUSE_OFF;
- putescape(VT52_CUR_ON);
- putescape(VT52_HOME);
- if ( screen_allocated != 1 )
- {
- #ifndef REDRAW
- putescape(VT52_CLEAR);
- #endif
- putstring(motd);
- newline();
- if ( !_app )
- {
- screen_allocated = 1;
- strcpy(screen_mem,magic);
- }
- }
- return(0);
- }
- /* #] getscreen: */
- /* #[ redrawscreen: */
-
- void
- redrawscreen(void)
- {
- /* cursor off */
- putescape(VT52_CUR_OFF);
- #ifdef REDRAW
- /* copy the menubar back */
- memcpy(oldPhysbase, screen_mem + 5, screensize - 5);
- /* send a redraw to all windows */
- form_dial(FMD_FINISH, 0, 0, 0, 0, 0, 0, screenw, screenh);
- #else
- /* set back the old screen */
- Setscreen( oldLogbase, oldPhysbase, -1 );
- Vsync();
- #endif
- MOUSE_ON;
- }
-
- /* #] redrawscreen: */
- /* #[ getstring: */
-
- void getstring(BYTE *string, int length)
- {
- BYTE *current, *end;
- long key;
- BYTE ascii, scan;
- int i,echo;
- char let10[] = "1234567890";
-
- current = end = string;
- *current = '\0';
-
- while ( 1 )
- {
- /* first use the GemDos buffer (we use the Bios, but a repeat or
- typeahead may have filled this). Hope nobody presses ^c in this time.
- */
- if ( Cconis() )
- {
- key = Cconin();
- if ( key == 0L ) key = 0x00610000L; /*undo*/
- echo = 0;
- }
- else
- {
- key = Bconin(2);
- echo = 1;
- }
- ascii = (char)(key & 0x000000FFl);
- scan = (char)( ( key >> 16 ) & 0x000000FFl);
- if ( ascii == '\x00' )
- {
- switch ( scan )
- {
- case 0x61:
- case 0x5d:
- strcpy(string,"lo");
- return;
- case 0x48:
- strcpy(string,oudstring);
- backspace((int)(current-string));
- if ( string != end ) putescape(VT52_CLRLINE);
- putstring(string);
- current = end = string + (int)strlen(string);
- break;
- case 0x50:
- if ( string != end )
- {
- backspace((int)(current-string));
- putescape(VT52_CLRLINE);
- current = end = string;
- *current = '\0';
- }
- break;
- case 0x4b:
- if ( current > string )
- {
- --current;
- putletter('\b');
- }
- break;
- case 0x4d:
- if ( current < end )
- {
- current++;
- putescape(VT52_RIGHT);
- }
- break;
- case 0x47:
- if ( current == string )
- {
- strcpy(string,"clear");
- return;
- }
- case 0x62:
- if ( current == string )
- {
- putstring(motd);
- newline();
- putstring(PROMPT);
- }
- break;
- }
- if ( current == string && scan >= 0x3b && scan < 0x44 )
- {
- strcpy(string,"if($?PF1 )echo $PF1 ;$PF1 ");
- string[7] = string[18] = string[24] = let10[scan - 0x3b];
- return;
- }
- if ( current == string && scan >= 0x54 && scan < 0x5d )
- {
- strcpy(string,"if($?PF1 )echo $PF1 ;$PF1 ");
- string[8] = string[19] = string[25] = let10[scan - 0x3b];
- return;
- }
- }
- else
- {
- switch( scan )
- {
- case 0x4b:
- if ( !echo ) putletter('\b');
- backspace((int)(current-string));
- current = string;
- continue;
- case 0x4d:
- if ( !echo ) putletter('\b');
- for ( i=(int)(end-current); i; --i) putescape(VT52_RIGHT);
- current = end;
- continue;
- }
- switch ( ascii )
- {
- case '\b':
- if ( current == string ) break;
- if ( echo ) putescape(VT52_LEFT);
- --current;
- case '\x7f':
- if ( current == end ) break;
- memcpy(current, current+1, (int)(end-current));
- putstring(current);
- putletter(' ');
- backspace((int)(--end - current + 1));
- break;
- case '\x0d':
- if ( scan == 0x72 ) current = end;
- *current = '\0';
- if ( current != end ) putescape(VT52_CLRLINE);
- strcpy(oudstring,string);
- newline();
- return;
- case '\x15':
- backspace((int)(current-string));
- putescape(VT52_CLRLINE);
- current = end = string;
- *current = '\0';
- break;
- case '\x14':
- if ( current - string > 1 )
- {
- scan = *(current-2);
- *(current - 2) = *(current - 1);
- *(current - 1) = scan;
- backspace(2);
- putstring(current - 2);
- backspace(end-current);
- }
- break;
- default:
- if ( (int)(end-string) < length-2 )
- {
- memcpy(current + 1, current, (int)(end-current)+1);
- *current = ascii;
- end++;
- if ( echo ) putstring(current);
- backspace((int)(end - ++current));
- }
- else
- putletter('\a');
- }
- }
- if ( current == end ) clearcursor();
- }
- }
- /* #] getstring: */
- /* #[ putthings: */
-
- void
- putstring(char *string)
- {
- char *p;
- p = string;
- while ( *p ) Bconout(5,(int)(*p++));
- }
- void
- putletter(char letter)
- {
- Bconout(2,(int)letter);
- }
- void
- putescape(char letter)
- {
- Bconout(2,0x1b);
- Bconout(2,(int)letter);
- }
- void
- clearcursor(void)
- {
- putletter(' ');
- putescape(VT52_LEFT);
- }
- void
- newline(void)
- {
- putletter('\x0d');
- putletter('\n');
- }
- void
- backspace(int n)
- {
- int i;
- for( i=n; i; --i) putescape(VT52_LEFT);
- }
- /* #] putthings: */
- /* #[ mysystem: */
- int mysystem(char *string)
- {
- char arg[82],env[200],*p,*q;
- long l;
- int i,j;
-
- strcpy(arg,"x-c ");
- strcat(arg,string);
- arg[0] = strlen(arg+1);
- #ifdef DEBUG
- printf("mysytem calls Pexec with argument %s\n",arg+1);
- #endif
- p = env;
- q = "unixpath=";
- while ( *p++ = *q++ );
- q = home;
- while ( *p++ = *q++ );
- q = "_PBP=";
- while ( *p++ = *q++ );
- l = (long)_BasPag;
- p += 7;
- for( i=0; i<8; i++)
- {
- j = l & 0x0000000FL;
- *--p = "0123456789ABCDEF"[j];
- l >>= 4;
- }
- p += 8;
- *p++ = 0;
- q = "ARGV=CCC?????????????????????????";
- while ( *p++ = *q++ );
- q = shell;
- while ( *p++ = *q++ );
- q = "-c";
- while ( *p++ = *q++ );
- q = string;
- while ( *p++ = *q++ );
- *p = 0;
- #ifdef DEBUG
- p = env;
- putstring("environment:");
- newline();
- while (*p)
- {
- while(*p++) putletter(*p);
- newline();
- }
- #endif
- l = Pexec(0, shell, arg, env);
- putescape(VT52_CUR_ON);
- return( (int)l);
- }
- /* #] mysystem: */
- /* #[ zero_shell_p: */
- void zero_shell_p(void)
- {
- long *p;
- p = 0x4f6;
- *p = 0L;
- }
- /* #] zero_shell_p: */
-
-