Hi,
first a disclaimer: I’m neither a C-wizard nor do I have any idea of Aztec C and its specifics.
That said, i you want to use execv()
, on UNIX/Linux this has the following signature:
int execv( const char * path, char * const argv[] );
Meaning, it takes a pointer to an array of char(acters) as the first argument for the path of the program to be called, and a second pointer to an array for the arguments.
So the first argument is your command, like mbasic
(or rather the full path to this program).
The second agrument is used as the ARGV for this program, i.e., first the program name, then any options and/or any “normal” arguments for this program, etc. This array is NULL
terminated, meaning it MUST have NULL
as the last element. (Otherwise, there will be a run-away at the attempt to parse the ARGV.) The first argument must always be the program name (which is always provided in ARGV[0].) Otherwise, this array may consist of multiple strings, e.g., for providing options and/or arguments (much like on the command line, where you use space-separated strings).
Your problem is that you attempt to re-use the ARGV of your C prorgam, rather than providing an array of its own for the called program. (This is also, why you have to type 8 random charactwers, as you need 8 characters for “GAME.BAS
” to fit.)
So, how do we define such an array and how do we pass a pointer?
An array is defined by the variable name followed immediately by square brackets []
, and the value part is provided in curly brackets ‘{}’. A pointer to a variable is denoted by an asterisk in front (*
).
We can do this in a single definition (mind the program name as the first and NULL
as last element of the array.)
main()
{
char * arr[] = { "mbasic", "GAME.BAS", NULL };
execv("mbasic", arr);
}
to understand the mechanism, consider this example (equivalent to “ls -aF
” on the command line):
char * arr[] = { "ls", "-a", "-F", NULL };
execv("/bin/ls", arr);
(The first argument, “ls” in our array “arr” is the call name passed to the program. If we set it to “dir”, bin/ls
would behave, as if we had set an alias in the shell and called it by this.)
Another – and probably simpler – way to do this is using execl()
, where you just provide these arguments without packing them into arrays:
execl( "/bin/ls", "ls", "-a", "-F", NULL );
Mind how we do not have to define an array at all, since the call constructs one for us in order to pass the arguments.
In your case (on UNIX/Linux):
main()
{
execl( "mbasic", "mbasic", "GAME.BAS", NULL );
}
Mind that the first "mbasic"
should be the full path.
Edit, I had a look at Aztec C 1.06 for C/PM [1].
[1] https://usermanual.wiki/Document/AztecCCPM106UserManualMar84.2457848702/help
The sigature of our call is:
execl(name, arg0, arg1, ..., argN, 0)
(The terminating 0
is equivalent to NULL
in the above examples.)
Mind that CP/M has no directories, so the path is equal to the program name on Unix. But what is the program name on Unix (arg0) is never passed to the called program (and thus a dummy).
From the manual:
For execl (…) the arguments are arg1 arg1, … , argn. For execv (…) the arguments are argv[1], argv[2], … , argv[n]. Note that arg0 and argv[0] aren’t passed to the new program: on Unix these strings are conventionally the name 'of the program being executed.
So, I guess, it’s still:
main()
{
execl( "mbasic", "mbasic", "GAME.BAS", 0 );
}