[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference hydra::axp-developer

Title:Alpha Developer Support
Notice:[email protected], 800-332-4786
Moderator:HYDRA::SYSTEM
Created:Mon Jun 06 1994
Last Modified:Fri Jun 06 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:3722
Total number of notes:11359

3308.0. "Nectar - Point 22462" by KZIN::ASAP () Wed Mar 12 1997 05:00

    Company Name :  Nectar - Point 22462
    Contact Name :  Mats Nilsson
    Phone        :  +46 (0)451 893 00
    Fax          :  +46 (0)451 817 30
    Email        :  [email protected]
    Date/Time in :  12-MAR-1997 09:59:54
    Entered by   :  Nick Hudson
    SPE center   :  REO

    Category     :  vms
    OS Version   :  7.1
    System H/W   :  


    Brief Description of Problem:
    -----------------------------

From:	ESSB::ESSB::MRGATE::"ILO::ESSC::dlennon" 12-MAR-1997 09:02:37.63
To:	RDGENG::ASAP
CC:	
Subj:	POINT No. 22462, Nectar

From:	NAME: ESCTECH@ILO          
	TEL: (822-)6704          
	ADDR: ILO                  <dlennon@ESSC@ILO>
To:	ASAP@RDGENG@MRGATE


Hello - 

POINT Log Number	22462 

Company Name 	Nectar

Engineers name	Mats Nilsson

Telephone Number 	+46 (0)451 893 00

Fax Number		+46 (0)451 817 30  

E-mail Address		[email protected]

Operating System, Version	OpenVMS V7.1

Platform			

Problem Statement		

                               INTEROFFICE MEMORANDUM
  
                                          Date: 11-Mar-1997 02:41pm
                                          From: [email protected]@PMDF@INTERNET
                                          Dept: 
                                          Tel No:   
  
  Subject:  arguments C-ADA
  
  
     Platform: OpenVMS 7.1, DECC 5.3, VAX Ada 2.3


     How to access C argument vector from Ada main program ?
     =======================================================

     I have written an Ada program that is executed by an other
     program written in C. The C program assumes that it is starting
     another C program and supplies one or more arguments.

     If the second program was written in C it would look
     something like this :

        int main (int argc, char **argv)
        {
          ...
        }

     VMS copies the arguments from the calling program to the argv
     parameter in the second program. My problem is that I need to write
     the second program in Ada, and Ada has no argc/argv support. How do I
     retrieve the arguments ?

     From C point of view it doesn't matter HOW the second program was
     called (from DCL, spawned, fork/execed etc.), but to receive
arguments
     in program that doesn't support argc/argv you must know how to
     receive them. If the program is called from DCL - no problem, the
     arguments can be read using lib$get_foreign. If the program is
     called using vfork/exec however, I'm not able to find the arguments !



     Mats Nilsson
+----------------------------------------------+
!                                              !
!    oooooo     ooooo  Nectar Systems AB       !
!    ooooooo    ooooo  Mats Nilsson            !
!      oooooo   ooo    Development Manager     !
!      ooooooo  ooo    [email protected]           !
!      ooo oooo ooo    Box 124                 !
!      ooo  ooooooo    S-281 22 H_ssleholm     !
!    ooooo   oooooooo  Tel. +46 (0)451 893 00  !
!    ooooo    ooooooo  Fax. +46 (0)451 817 30  !
!                                              !
! -For excellence in 4GL-                      !
!                                              !
+----------------------- http://www.nectar.se -+
T.RTitleUserPersonal
Name
DateLines
3308.1KZIN::HUDSONThat&#039;s what I thinkThu Mar 13 1997 06:53205
From:	DEC:.REO.REOVTX::HUDSON       "[email protected] - UK Software
Partner Engineering 830-4121" 13-MAR-1997 11:53:02.82
To:	nm%vbormc::"[email protected]"
CC:	HUDSON
Subj:	RE: POINT No. 22462, Nectar, command line args

Hello Mats Nilsson

Thank-you for your ASAP question on retrieving command line arguments.

When I started to read your question, I thought "A-ha! use LIB$GET_FOREIGN". 
But as I read further I realised you've been down this route and you're asking
something a little more difficult!

As you say, you can use LIB$GET_FOREIGN if the program was executed by a
foreign command (e.g. "$ fred :== $disk:[dir]fred.exe").  This is because
foreign commands are not specific to C, and VMS knows how to get them.

>     VMS copies the arguments from the calling program to the argv
>     parameter in the second program. My problem is that I need to write
>     the second program in Ada, and Ada has no argc/argv support. How do I
>     retrieve the arguments ?

Unfortunately, in the case of C doing fork/etc., it is not VMS that is copying
the arguments, it is the C RTL, which uses a mailbox to pass information from
the parent to the child.

When any C program starts, the C RTL gets in there first and looks to see if a
specific mailbox is there ("VAXC$EXECMBX").  If it isn't there, then the C RTL
uses LIB$GET_FOREIGN to populate "argc" and "argv", before transferring control
to your "main()".  If the mailbox is found, then the RTL reads info from it
(which the parent will be writing) and creates "argc" and "argv" that way (as
well as setting up some other stuff like environment variables.

So as far as your C program is concerned, it just received argc and argv as
soon as it begins, but in fact a lot of work has gone on behind the scenes that
you didn't know about.

Looking at the source code for the C RTL you can see what it is doing, and I
wrote a small piece of Pascal (sorry but I can't do Ada!) which will retrieve
command line arguments by imitating what the C RTL does (look for the mailbox
and read stuff).  But this doesn't work all the time for me and so I don't
think it's really a good basis for a proper solution (parent process sometimes
hangs).  

I suspect there may be other things which my program should do to communicate
back to its parent, which the C RTL would obviously take care of.

I include the program below for your interest; you are welcome to use it if you
think it might be useful but if you wanted to go this route I would suggest you
get a copy of the VMS sources so you can check for yourself what else you may
need to do.

I think a more sturdy solution would be to have a C program executing as your
child, which then invokes the Ada program and passes "command line" arguments
to it in a well-defined way.  

I hope this information is useful to you

Regards

Nick Hudson
Digital Software Partner Engineering


[inherit ('sys$share:pascal$lib_routines','sys$share:starlet')]

(* Program demonstrates that it is possible to read "command line arguments"
   when executed by a C parent which forks

   Nick Hudson, Digital, Mar-97.
   This code is intended as a demonstration only!

*)

program paschild(input,output);
const
  	NUMARGS = 0;	(* specify number of command line args *)
	ARGSTRG = 1;	(* specifies a command line argument *)
	ENDFILE = 6;	(* signifies no more messages *)

type
	str = packed array [1..255] of char;
	uword = [word] 0..65535;
	ubyte = [byte] 0..255;

(* The C parent will send messages to the child through a mailbox.  The
   first byte of each message defines its type.  The only three we're 
   interested in are NUMARGS, ARGSTRG and ENDFILE.  See F_ENVIRON.LIS
   in the C RTL sources for a list of all the other message types
*)

	fork_msg_block = packed record
		field_type : [byte] 0..255;
		case integer of
			0 : ( textbuf : packed array [1..511] of char; );
	(* NUMARGS *)	1 : ( arg_count : integer; 
				fill1 : packed array [1..507] of char; );
	(* ARGSTRG *)	2 : ( byte_count : ubyte;
				fill2 : packed array [1..510] of char; );
	end;

	itmlst = packed record
		buflen : uword;
		itmcod : uword;
		bufadr : [unsafe] unsigned;
		retlen : [unsafe] unsigned;
		mbz : unsigned;
	end;

	iosb = packed record
		cond_val : uword;
		trans_cnt : uword;
		devdepend : unsigned;
	end;


var
	stat : unsigned;
	my_itmlst : itmlst;
	my_iosb : iosb;
	msg_buf : fork_msg_block;

	arg_count : integer;	(* number of args we've shown to user *)

	argline : packed array [1..132] of char;
	arglen : uword;		(* used for return from lib$get_foreign *)

	translation : str;	(* used to get logname translation *)
	trans_len : uword;

	mbx_chan : uword;

procedure check(stat : unsigned; msg : packed array [a..b:integer] of char);
begin
	if not odd(stat) then
	begin
		writeln('Failure at ',msg);
		lib$stop(stat);
	end;
end;

begin
	arg_count := 0;
	writeln('pascal child here');

	(* if the logical VAXC$EXECMBX is defined, then that should mean we've
	   been fork'd by a C parent, and we can use the mailbox that the
	   logical name points at to retrieve command line args
	*)
		 
	with my_itmlst do
	begin
		buflen := 100;
		itmcod := LNM$_STRING;
		bufadr := iaddress(translation);
		retlen := iaddress(trans_len);
		mbz := 0;
	end;
	stat := $trnlnm(tabnam := 'LNM$PROCESS',
		 	lognam := 'VAXC$EXECMBX',
		 	itmlst := my_itmlst);
	if (stat = SS$_NORMAL) then (* we've been forked from C *)
	begin
		writeln('Forked from C:');
		stat := $assign(devnam := translation,
				chan := mbx_chan);
		check(stat,'assign to VAXC$EXECMBX');

		msg_buf.field_type := 0;
		while (msg_buf.field_type <> ENDFILE) do
		begin
			stat := $qiow(	chan := mbx_chan,
				func := IO$_READVBLK,
				iosb := my_iosb,
				p1 := msg_buf,
				p2 := 512);

			check(stat,'$qiow read from mbx');
			check(my_iosb.cond_val,'$qiow (iosb) read from mbx');

			if (msg_buf.field_type = NUMARGS) then
			begin
				write('Number of arguments = ');
				writeln(msg_buf.arg_count);
			end;
			if (msg_buf.field_type = ARGSTRG) then
			begin	
				arg_count := arg_count + 1;
				write('Argument #', arg_count:1, ' ->');
			    	writeln(msg_buf.fill2:msg_buf.byte_count,'<-'); 
			end;
		end;


	end
	else	(* use lib$get_foreign *)
	begin
		stat := lib$get_foreign(argline,,arglen);
		check(stat,'lib$get_foreign');
		write('Using LIB$GET_FOREIGN, argline is ->');
		writeln(argline:arglen,'<-');
	end;
end.