[comp.sys.atari.st] Calling callgulam from TC

av74381@korppi.tut.fi (Vesterinen Arto) (02/28/90)

I have been developing a Turbo-C program which will transfer
usenet articles to my BBS. They are received as packets which
are archieved using zoo. Host will send them using zmodem.

I decided to do the receiving using my humble servant Gulam.
Gulam would start zmodem at receiving end and then extract
articles from zoo.

Unfortunately have not been able to call gulam from a Turbo-C
program. I have tried out Michal Jaegermann's method for
MWC but it does not work out for TC. If anyone has figured out
how to call gulam from TC, please e-mail me how to do it.

I just do not understand why my example works for MWC but not
with TC, it gives me two warning messages when I compile it:
Call to function with no prototype in main. Lines where
I get the warnings are those where I call gulam (* gcp) ("command");.
When I try to run the program It prints out "-Start of test-" and
then comes out two bombs (bus error).
 
-----------This is what I tried out with Turbo C ----------------	 

#include <stdio.h>
#include <stdlib.h>
#include <tos.h>
#include <string.h>
#define  SHELLP         ((char **) 0x04f6L)
#define  G_MAGIC        0x0135


int main()
{
       long save_ssp;
       short sh_magic;
       char *tgptr;            /* storage for togu_         */
       /* if you really would like to have it right, then   */
       /* tgptr should be a pointer to void - 		    */
       /* a bit of overkill on ST :-)			    */
       int  (* cgp)();          /* pointer to callgulam()    */
                                /* also contains togu_, but  */
                                /* a type is different       */
       			   
       fprintf(stderr, "Welcome to callgulam demo.\n");
       
       save_ssp = Super(0L);
    	   tgptr = *SHELLP;
       Super((void *)save_ssp);
       
       if (G_MAGIC != (sh_magic = *((short *)(tgptr - 8)))) {
               fprintf (stderr, "wrong magic value %x\n", sh_magic);
               return(1);
       }

       cgp = *((int (*)()) tgptr);
       printf("-Start of test-\n");
       (* cgp)("echo 'executing ls'");
       (* cgp)("ls");
       printf("-End of test-\n");
       return(0);
}


---------- Michal's original posting follows --------------------------

# this example is for Mark Williams C

From myrias!mj Thu Oct 20 15:44:19 EDT 1988
X-RN-Article: 12125 of comp.sys.atari.st
>From: mj@myrias.UUCP (Michal Jaegermann)
Newsgroups: comp.sys.atari.st
Subject: Calling callgulam - explanation and example
keywords: gulam, shell
Date: 19 Oct 88 23:47:47 GMT
Organization: Myrias Research, Edmonton

(Whatever is described below was checked for a gulam version
which identifies itself as:
xD
	beta test version 1.03.04.05 121887 of
	yet another shell for AtariST/TOS

Your mileage may vary!!)

   As you may not know, a very popular Gulam shell (many thanks to
Prabhaker Mateti and Jwahar R. Bammi). includes quite powerful facility
to invoke gulam services from a program started from gulam.  In contrast
to many others shells floating aroung this is not done by executing
the next incarnation of gulam. Instead there are provided two pointers
which provide execution 'hooks' for all gulam commands.  A bright sight
is that this approach does not take any extra memory and a start-up
time is negligible. A dark side is that documentation describing this
facility is either misleading or plainly wrong.  (As an aside - this
is, alas, not the only place in documentation requiring touch-up.
For this version, gulam.hlp, for example, does not correspond very well
tp reality).

   This note is a kind of erratum, which, hopefuly, will help to clarify
an ensuing confusion, which seems to be quite widespread.

   When you are running Gulam a TOS variable '_shell_p', at 0x4f6,
contains an address of a location named 'togu_', which is the last entry
in a 16 byte long table. The format of the table is (this is mostly quoted
from the documentation):

               .long   0x86420135        / our magic number (4 bytes)
               jmp     getlineviaue_     / 0x4ef9,address   (6 bytes)
       togu_:  jmp     callgulam_        / 0x4ef9,address   (6 bytes)

It clearly follows from that that magic number is located 10 bytes before
'togu_' and not, the documentation suggested, 12.  What's more, the magic 
number should be equal *(long *)(*(char **)0x4f6 - 10), instead of a
given *((long *)0x46fL - 12L), which will produce a value from an address
way off.  On the top of it, an actual magic number in my copy of Gulam
is not like the documented but it equals 0x00420135.  Use Gulam 'peekw'
to check what you got. To be on a safe side, until the matter
is fully clarified, I am using only a lower half of the magic number,
which seems to be correct; i.e. short_magic = *(short *)(*(char **)0x4f6-8).

  Two other items in the table are entry points to two functions
'getlineviaue' and 'callgulam'.  The information given in the documentation
about them is mostly correct, with a similar mix-up in a calculation
of an address of entry to 'getlineviaue', like the one described above.
Also, strictly speaking, 'getlinevalue' does not return anything, since
it is declared as 'void'. As a side effect it modifies a contents of
a user supplied buffer, copying there a contents of a command line. It
would be probably more convenient if, instead of being void, it would return
something useful, say a number of copied characters, but it doesn't,
so we may have to live with that.  Just to make our life more
interesting, the other function, 'callgulam', returns 'int' - the return
status of an executed command.  This makes wonders to types of your
pointers.  See the supplied program example for to see how to cast.
All of this to ensure that your C-compiler will not get totally lost.
If you have a compiler which accepts the stuff in a form from an original
docs - replace your compiler. Fast!
(As an aside - all this pointer play would be easier in assembler, 
if you feel so inclined).

  While experimenting whith the program example try the following.
Call 'ue' on some file, position cursor somewher down the text and
stop editor with ^Z. Try some other commands and upon return to Gulam
type 'fg'.  Repeat experiment stopping the editor in Gulam and typing
'fg' from the demo program prompt. Don't you think that this is a nice
way to run editor for your, say, Lisp interpreter?

  Some things are still missing. One cannot tell 'ue', on a command
line, to load a file and go to the line 247.  Or there is a way and I
am simply not aware of it?  And I know of no way to grab a result of
a command, stuff it into a variable and use it for a test of conditional
script execution.  Oh well, maybe in some future release...

  Two other, non-interactive, ways of calling Gulam are also mentioned
in docs.  I did not try 'Pexec method', but attempts to execute 
gulam as a program with arguments, as described, produced only
nonsensical error messages about 'invalid regexp' and error number -33.
Can anybody shed some light on that matter?


   Michal Jaegermann
   Myrias Research Corporation
   Edmonton, Alberta, CANADA
   ...alberta!myrias!mj
   (or you may try mj@myrias.UUCP)

------------------------------------------------------------------------------

/* 
* A demo program to show a usage of Gulam 'hooks' - call from
* Gulam shell!  When asked, try different gulam commands, ue
* in particular.
*
* A numbers of pointers floating around is a little bit higher
* than necessary, but we will waiste some memore for the sake
* of clarity.
*
* Michal Jaegermann, October 1988
*/

#include <stdio.h>
#include <osbind.h>
#include <string.h>
#define  SHELLP         ((char **) 0x04f6L)
#define  G_MAGIC        0x0135

main()
{
       long save_ssp;
       short sh_magic;
       char buf[258];
       char *tgptr;            /* storage for togu_         */
       /* if you really would like to have it right, then   */
       /* tgptr should be a pointer to void - 		    */
       /* a bit of overkill on ST :-)			    */
       
       			   
       int  (* cgp)();         /* pointer to callgulam()    */
                               /* also contains togu_, but  */
                               /* a type is different       */
       void (* glp)();         /* pointer to getlineviaue() */

       fprintf(stderr, "Welcome to callgulam demo.\n");
       save_ssp = Super(0L);
       tgptr = *SHELLP;
       Super(save_ssp);

       if (G_MAGIC != (sh_magic = *((short *)(tgptr - 8)))) {
               fprintf (stderr, "wrong magic value %x\n", sh_magic);
               exit (1);
       }

       cgp = *((int (*)()) tgptr);
       glp = *((void (*)()) (tgptr - 6));
       (* cgp)("echo 'test of Gulam'");
       (* cgp)("echo 'executing ls -l'");
       (* cgp)("ls -l");
       (* cgp)("echo '-----------------'");
       (* cgp)("ls -R -t a:\\ ");
       (* cgp)("echo ' '");
       (* cgp)("echo ' '");
       (* cgp)("set tmp_old_prompt $prompt");
       (* cgp)("set prompt 'At your service, Sir!'");
               /* change a gender if a need will arise */
       (* cgp)("echo 'Awaiting your commands!!'");
       /* the following loop will cycle until it will get an empty line */
       while ((* glp)(buf), putchar('\n'), 0 != strlen(buf)) {
                                       /* the new line not supplied */
                                       /* by Gulam - DIY, mate       */
               (* cgp)(buf);
       }
       (* cgp)("set prompt $tmp_old_prompt");
       (* cgp)("unset tmp_old_prompt");
       fprintf (stderr,"\nNice talking to you, see you later.\n");
       exit(0);
}
/* -----------------/ that is all for today /--------------------- */

-- 
	Michal Jaegermann
	Myrias Research Corporation
	Edmonton, Alberta, CANADA
	...{ihnp4, ubc-vision}!elberta!myrias!mj


-------------------------------------------------------------------
I  Arto Vesterinen                   I  Internet  av74381@tut.fi  I
I  Tampere University of Technology  I  UUCP      tut!av74381     I
I  Finland                           I  Bitnet    av74381@fintut  I

bammi@dsrgsun.ces.CWRU.Edu (Jwahar R. Bammi) (03/01/90)

In article <11368@etana.tut.fi> av74381@korppi.tut.fi (Vesterinen Arto) writes:

> Unfortunately have not been able to call gulam from a Turbo-C
> program. I have tried out Michal Jaegermann's method for
> MWC but it does not work out for TC. If anyone has figured out
> how to call gulam from TC, please e-mail me how to do it.
> 
> I just do not understand why my example works for MWC but not
> with TC, it gives me two warning messages when I compile it:

	your example is correct. the reason it does'nt work from Turbo C 
is that Turbo C passed the arguements in registers by default, while
gulam is expecting them to be on the stack (like the normal C stack
frame conventions). (is there a option in TC to do this??)

	on a related note: the correct way to check Gulam's magic
number is to get the long at addr (*shell_p - 10), mask out the upper nibble
of the long with 0x00FFFFFFL, and compare the value against
0x00420135L. The reason for this discrepancy is that there seem to be
two flavors of gulam: one with magic # 0x86420135L and one with 0x00420135L.
This way should be a little more reliable than testing just the second
half of the magic number by testing the short value at addr (*shell_p - 8).

hope that helps,
--
--
bang:   {any internet host}!dsrgsun.ces.CWRU.edu!bammi	jwahar r. bammi
domain: bammi@dsrgsun.ces.CWRU.edu
GEnie:	J.Bammi

jimh@ultra.com (Jim Hurley) (03/02/90)

bammi@dsrgsun.ces.CWRU.Edu (Jwahar R. Bammi) writes:

>In article <11368@etana.tut.fi> av74381@korppi.tut.fi (Vesterinen Arto) writes:

>> Unfortunately have not been able to call gulam from a Turbo-C
>> program. I have tried out Michal Jaegermann's method for
>> MWC but it does not work out for TC. If anyone has figured out
>> how to call gulam from TC, please e-mail me how to do it.

>	your example is correct. the reason it does'nt work from Turbo C 
>is that Turbo C passed the arguements in registers by default, while
>gulam is expecting them to be on the stack (like the normal C stack
>frame conventions). (is there a option in TC to do this??)

>	on a related note: .....

>--
>bang:   {any internet host}!dsrgsun.ces.CWRU.edu!bammi	jwahar r. bammi
>domain: bammi@dsrgsun.ces.CWRU.edu
>GEnie:	J.Bammi


There are some gulam parameters that can be set in a startup file.
They are called, I believe: 'set env_style <style>' where
style can be three separate flavors. (Here my memory is faulty about
the types, but I use 'gulam' style).
 
I don't know quite what this means, I don't recall reading a description
in the docs. Anyone know more about this?
-- 
Jim Hurley --> jimh@ultra.com  ...!ames!ultra!jimh  (408) 922-0100
Ultra Network Technologies / 101 Daggett Drive / San Jose CA 95134

bammi@curie.ces.CWRU.Edu (Jwahar R. Bammi) (03/02/90)

In article <1990Mar1.175045.3607@ultra.com> jimh@ultra.com (Jim Hurley) writes:
   >>bammi@dsrgsun.ces.CWRU.Edu (Jwahar R. Bammi) writes:
   >>>In article <11368@etana.tut.fi> av74381@korppi.tut.fi (Vesterinen Arto) writes:

   >>> Unfortunately have not been able to call gulam from a Turbo-C
   >>> program. I have tried out Michal Jaegermann's method for

   >>	your example is correct. the reason it does'nt work from Turbo C 
   >>is that Turbo C passed the arguements in registers by default, while

   >There are some gulam parameters that can be set in a startup file.
   >They are called, I believe: 'set env_style <style>' where
   >style can be three separate flavors. (Here my memory is faulty about
   >the types, but I use 'gulam' style).

	env_style has nothing to do with this. env_style determines
how the environment variables are setup, and how  the 
command lines/environment programs are setup before a program is lauched
via Pexec(). the possible value are
	'bk'	beckemeyer
	'gu'	gulam
	'mw'	mark williams
gulam.doc talks about what each of these means.
--
bang:   {any internet host}!dsrgsun.ces.CWRU.edu!bammi	jwahar r. bammi
domain: bammi@dsrgsun.ces.CWRU.edu
GEnie:	J.Bammi

hyc@math.lsa.umich.edu (Howard Chu) (03/02/90)

In article <1990Mar1.175045.3607@ultra.com> jimh@ultra.com (Jim Hurley) writes:
>There are some gulam parameters that can be set in a startup file.
>They are called, I believe: 'set env_style <style>' where
>style can be three separate flavors. (Here my memory is faulty about
>the types, but I use 'gulam' style).
> 
>I don't know quite what this means, I don't recall reading a description
>in the docs. Anyone know more about this?

The env_style controls the format of environment variables in memory. The
"gulam" or "mw" style is the format used by the Mark Williams C runtime support.
In this format, an extended command line is passed to called programs by
sticking a variable "ARGV=" in the environment, etc.

I've never used any of the other style(s?) and don't know what they represent...
--
  -- Howard Chu @ University of Michigan

av74381@tut.fi (Vesterinen Arto Tapio) (03/02/90)

In article <BAMMI.90Mar1044130@dsrgsun.ces.CWRU.Edu> bammi@dsrgsun.ces.CWRU.Edu (Jwahar R. Bammi) writes:
>	your example is correct. the reason it does'nt work from Turbo C 
>is that Turbo C passed the arguements in registers by default, while
>gulam is expecting them to be on the stack (like the normal C stack
>frame conventions). (is there a option in TC to do this??)
>

There is a TC compiler option Standard stack frames. I tried it out, but
I still get two bombs, oh well... :-(

roeder@sbsvax.cs.uni-sb.de (Edgar Roeder) (03/02/90)

In article <11368@etana.tut.fi>, av74381@korppi.tut.fi (Vesterinen Arto) writes:
> Unfortunately have not been able to call gulam from a Turbo-C
> program. I have tried out Michal Jaegermann's method for
> MWC but it does not work out for TC. If anyone has figured out
> how to call gulam from TC, please e-mail me how to do it.

Remember that Turbo-C passes function arguments in registers. Since gulam is
not written in Turbo-C it expects the parameter to the callgulam()-function on
the stack. If you compile your program with the option to pass parameters
on the stack, it should run. You can also declare the variable cgp as

        cdecl int  (*cgp)(const char *);       /* pointer to callgulam() */

  - Edgar
-- 

Mail:  Edgar R\"oder			E-Mail: roeder@cs.uni-sb.de
       Liesbet-Dill-Stra\ss e 3
D-6602 Dudweiler                               -o-   -o-
       W-Germany                                   ^
Phone: 06897/74643                     	       	 '---'

buggs@cup.portal.com (William Edward JuneJr) (03/04/90)

I'm sure I've asked this before, but can't remember, so here goes......

Since there's no English docs to Turbo C for the ST, can one buy a book
 <of there's many to choose from> on Turbo C for the PC and still you it?
What would be the best book(s) to this with.
I'd really like to get a reply on this 'n'. I wish there was an English versio


Ed June

david.megginson@canremote.uucp (DAVID MEGGINSON) (03/05/90)

>        your example is correct. the reason it does'nt work from
>Turbo C  is that Turbo C passed the arguements in registers by
>default, while gulam is expecting them to be on the stack (like the
>normal C stack frame conventions). (is there a option in TC to do
>this??)

The cdecl keyword in Turbo C forces arguments to be passed on the stack 
rather than in the registers. ie:

int cdecl (*_shell_p)( char * cmd );

If you could pass this on to the net, I'd appreciate it.

David Megginson, Centre for Medieval Studies
BITNET: meggin@vm.epas.utoronto.ca
---
 * Via ProDoor 3.1R