[comp.lang.ada] Making EXECL Unix call from Ada

cstein@jarthur.claremont.edu (Clifford Stein) (12/10/90)

I'm trying to laser print a file from an ada program by calling the program
enscript with the execl function.  I've been having problems, though.
Sometimes I can print a file, other times I cannot (if it doesn't
print, it [enscript] will give me a file not found message).

When enscript does print, however, it prints garbage which doesn't resemble
my file at all, and it [enscript] won't even print a filename at the top of
the printout like it usually does.

I've included the source code here, does anyone have any suggestions?
(I'm using VADS serial on a Sequent running Dynix)

If I compile this program the way it is right now I will get a 

"/hmc2/guest/lsdada/cliffie/hello4: file not found"

even though hello does exist.

Please respond via email.

			Thank you for any help.

				Clifford Stein


with c_strings; use c_strings;
with a_strings;use a_strings;
with unix_prcs; use unix_prcs;
with text_io; use text_io;
procedure print is
status:integer;
name:string(1..23);
argv:string(1..33);
a_name:c_string;
the_name:a_string;
nll:character;
begin

	argv(1..33):="/hmc2/guests/lsdada/cliffie/hello";
	nll:=ascii.nul;
	name:="/usr/local/bin/enscript";
	status:=execl(name'address,argv'address,nll'address);
	if status/=0 then
		put_line("True.");
	else
		put_line("False");
	end if;
end print;

emery@linus.mitre.org (David Emery) (12/10/90)

I suspect the problem is that Unix is running off the end of your
string and/or your parameter list.  Try the following:

	with system;
	  -- assumed to provide the object "null_address"
	  -- (also known as "address_zero" or "no_addr" on some compilers)
	with text_io;
	procedure print
	    function execl (name : system.address;
			    arg0 : system.address;
			    arg1 : system.address)	-- all we need
	    return integer;	-- assumed to be the same size as C "int"
	    pragma interface (C, execl);
	    
	    program_name : constant string
			 := "/usr/local/bin/enscript" & Ascii.nul;
	    file_name    : constant string
		         := "/hmc2/guests/lsdada/cliffie/hello" & Ascii.nul;
	    status : integer;
	begin
	    status := execl (name => program_name(program_name'first)'address,
			     arg0 => file_name(file_name'first)'address,
			     arg1 => system.null_address);
	    if status/=0 then
		put_line("True.");
  	    else
		put_line("False");
	    end if;
	end print;

Remember, that in C strings are null-terminated, and represented by
the address of the first element.  Also, from the C definition of the
parameters for execl, the last parameter is of type "address", with
value 0, not the address of an object with value 0.  There's a subtle
difference, in that the former is "0", and the latter is not "0", but
some (non-zero) address.  

Here are the changes to print a user-supplied file.  Append a null to
the end of the user-supplied string, and pass this to C:

	procedure print (file_to_print : string) is
	    ...
	    file_name : constant string
		      := file_to_print & Ascii.nul;
	    ...
	end print;

				dave emery
				emery@aries.mitre.org

<for more tricks like this, see my paper in Tri-Ada on the POSIX Ada
binding prototype.>