Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!utgpu!water!watmath!clyde!rutgers!ames!hao!gatech!seismo!mcvax!nikhefh!gert From: gert@nikhefh.UUCP Newsgroups: comp.sys.atari.st Subject: Re: Correct use of _shell_p (Csh-like shell, fast editor, make...) Message-ID: <279@nikhefh.UUCP> Date: Wed, 20-May-87 06:30:34 EDT Article-I.D.: nikhefh.279 Posted: Wed May 20 06:30:34 1987 Date-Received: Thu, 21-May-87 07:13:30 EDT References: <276@nikhefh.UUCP> <1019@viper.Lynx.MN.ORG> Reply-To: gert@nikhefh.UUCP (Gert Poletiek) Organization: Nikhef-H, Amsterdam (the Netherlands). Lines: 207 Keywords: _shell_p, shell In article <1019@viper.Lynx.MN.ORG> john@viper.UUCP (John Stanley) writes: >In article <276@nikhefh.UUCP> gert@nikhefh.UUCP (Gert Poletiek) writes: [..] > Thanks for this information Gert. One "small" problem. We need a way >of checking to see if this pointer is functional. The sample code you >gave as part of your message should only be called if a command shell >has been installed. We can't expect lots of people to write software >that uses _shell_p unless they have some way of checking to see if it >is functional or not. Is _shell_p initialized to anything at boot >time? At re(warm)boot??? If not, this could be pose a serious >problem/limitation... > [..] >--- >John Stanley (john@viper.UUCP) >Software Consultant - DynaSoft Systems >UUCP: ...{amdahl,ihnp4,rutgers}!{meccts,dayton}!viper!john If you have a standard system, i.e Tos in rom, any ST, with or without a harddisk, and GemBoot NOT installed then _shell_p will contain a long 0. This will not change during uptime. If you have system with (the current version of) GemBoot _shell_p will be made to point to a 'PATH' string. This use of _shell_p is not correct. The only program that uses _shell_p as intended by atari is the shell I wrote. (This remark is pretty useles for most of you, since I didn't market my shell yet, however the following description is valid for any program that uses _shell_p correctly). When my shell is started it installs a pointer to a function in the shell that will handle user program requests. When the shell exits, it will put the old value of _shell_p back, in order not to crash the program(s) that may eventually try to use _shell_p with my shell being installed. As a matter of fact the current version of GemBoot and my shell can be used together, as long as the shell is run after GemBoot. Finding out if the value _shell_p is correct should be done like this: (Code taken from a message from Allan Pratt @ atari.uucp, additions by me) *************** CODE EXAMPLE FOR USE OF _shell_p VARIABLE ***************** /* * Example of use of _shell_p variable. * * The value at _shell_p is the address of a procedure which takes a * string pointer as an argument, executes the string as if it were * typed at the shell prompt, and returns the exit status of the command. * * This code checks to see of the value at _shell_p is null (no shell * around) or points to the word "PATH" (adulterated by GEMBOOT). */ #include main() { long oldstack; long *shell_p = (long *)0x4f6; long (*shell)(); long status; char buf[256]; oldstack = Super(0L); /* get into Super mode */ shell = *shell_p; /* get value of _shell_p */ Super(oldstack); /* get back to user mode */ /* validate _shell_p */ if (shell == 0L) { printf("No shell available to execute a command\n"); Pterm(-1); } /* * Code added by Gert Poletiek * * Test whether _shell_p has a value that is smaller than the * base page of your own program. * This has to be done differently for the different C compiler * system: * */ #ifdef ALCYON /* digital research C or alcyon C */ if ( (long)shell > (long)_base ) { printf ( "_shell_p has invalid value\n" ); Pterm ( -1 ); } #endif ALCYON #ifdef MWC /* mark williams C */ if ( (long)shell > (long)_start ) { printf ( "_shell_p has invalid value\n" ); Pterm ( -1 ); } #endif MWC #ifdef MEGAMAX /* megamax C */ if ( (long)shell > (long)_base ) { printf ( "_shell_p has invalid value\n" ); Pterm ( -1 ); } #endif MEGAMAX if (strncmp(shell,"PATH",4) == 0) { printf("_shell_p has been adulterated: it points to \"PATH\"\n"); Pterm(-1); } /* get a line from the keyboard using Cconrs() */ printf("Enter a command line for the shell to execute: "); buf[0] = 253; Cconrs(buf); buf[2+buf[1]] = '\0'; /* null-terminate the line */ /* execute the command */ status = (*shell)(&buf[2]); printf("Return status is %ld\n",status); Pterm0(); } Alternatively the following assembler code can be used from C (this version is for alcyon, but can be easily adapted) xdef _system * * * Get a command executed by the GP shell. * * (C) 1987 Gert Poletiek * * * * Calling syntax from a C program: * * system ( command ) * char *command * * and from assembly language * * pea command * jsr _system (or bsr) * addq.l #4,sp * * * Not that only the a3 register is used here and saved here. * All other registers are saved and restored by the shell. * The free stack must be at least 100 bytes (that's where the * the shell saves your registers). The shell will allocate it's * own stack on the fly. * * _system: move.l a3,-(sp) * save a3 move sr,d0 * test if we're in supervisor mode btst #13,d0 * in supervisore mode? bne sys_error * don't call this from supervisor mode clr.l -(sp) * get into supervisor mode move.w #$20,-(sp) trap #1 addq.l #6,sp * now we're in supervisor mode move.l d0,-(sp) * save old value of ssp movea.l $4f6,a3 * get function pointer move.l a3,d0 * move to d0 just to test it beq sys_nosh * ain't no use dereferencing a null pointer move.w #$20,-(sp) * get back into user mode trap #1 addq.l #6,sp move.l 8(sp),-(sp) * push our string argument jsr (a3) * call the shell addq.l #4,sp * restore stack move.l (sp)+,a3 * restore a3 rts * done: shell returnvalue is in d0 sys_nosh: move.w #$20,-(sp) * get back into user mode trap #1 addq.l #6,sp sys_error: move.w #-1,d0 * return general mishap move.l (sp)+,a3 * restore a3 rts end NOTE: This code is only useful if you have the GP-shell (sorry for the ad) Gert Poletiek.