[comp.sys.atari.st.tech] The program's name and path - how can I get them?

klute@heike.informatik.uni-dortmund.de (Rainer Klute) (10/08/90)

Due to public demand I would like to integrate a functionality into Arcgsh
(you know - the GEM shell for Arc, Zoo, LHarc etc.) that allows you to
doubleclick on e. g. FOO.ZOO which causes Arcgsh to be executed and
immediately showing the Zoo parameter dialog box with FOO.ZOO already
filled in as the archive name.

However, what I need to know is the complete path of the executing program.
This is neccessary to read (resp. write) the configuration file which is in
the same directory as the program itself. I played around a bit (using TOS
1.4) with shel_read() and shel_find(), but I am not satisfied with the
results:

- Shel_read() works reliably only when the program is called from the
  desktop. When it is called from a shell it may return the name of
  that shell.

- Shel_find() needs to know the program's name in order to find out its
  path. It works alright if I hardcode the program's name, like
	strcpy (buffer, "ARCGSH.PRG");
	shel_find (buffer);
  but will fail if the program is renamed.

Another observation is that loading the resource file always worked with
rsrc_load ("ARCGSH.RSC").

Does someone have a general solution? It would be sufficient to get only
the directory where the program is located - without knowing the program's
name. Even better would be a possibility to retrieve the program's name
also, and the best would be if this could be done without GEM functions.
And yes, of course only legal solutions are useful.

--
  Dipl.-Inform. Rainer Klute      klute@irb.informatik.uni-dortmund.de
  Univ. Dortmund, IRB             klute@unido.uucp, klute@unido.bitnet
  Postfach 500500         |)|/    Tel.: +49 231 755-4663
D-4600 Dortmund 50        |\|\    Fax : +49 231 755-2386

7103_2622@uwovax.uwo.ca (Eric Smith) (10/08/90)

> Does someone have a general solution? It would be sufficient to get only
> the directory where the program is located - without knowing the program's
> name. Even better would be a possibility to retrieve the program's name
> also, and the best would be if this could be done without GEM functions.
> And yes, of course only legal solutions are useful.
> 

I don't think there is a legal solution that always works (and the illegal
ones involving looking for variables in the parent's basepage certainly
break under multitasking systems, and probably on the TT as well).
However, a combination of legal solutions may work most of the time:

What I usually do is look at argv[0] in main(); gcc, MWC, and many other
compilers will fill this in with the program name if run from a shell that
supports the Atari ARGV= extended argument passing scheme. Note: some
shells will put only the program name (e.g. "arcgsh") in argv[0]; if so,
then you'll have to search the directories given in the PATH variable
to find the complete program.

If argv[0] is invalid (see below), then the best bet may be to look for
a PATH environment variable and search along it for your configuration file,
and/or use shel_find or shel_read. Almost all shells will set PATH, so if
no PATH is found and an invalid argv[0] is present then the program was
probably run from the desktop, and so the shel_* functions ought to work.

The ANSI standard says that argv[0] should be an empty string if the program
name is not available; the new gcc library does this. The old (1.27) gcc
library used to put "a.prg" in argv[0] by default, and some compilers may
put "a.out" there.

--
Eric R. Smith                     email:
Dept. of Mathematics            ersmith@uwovax.uwo.ca
University of Western Ontario   ersmith@uwovax.bitnet
London, Ont. Canada N6A 5B7
ph: (519) 661-3638

david@doe.utoronto.ca (David Megginson) (10/08/90)

THIS INFORMATION IS IMPORTANT ENOUGH THAT I AM POSTING IT INSTEAD
OF REPLYING PERSONALLY.

In article <1990Oct8.085411@heike.informatik.uni-dortmund.de> klute@heike.informatik.uni-dortmund.de (Rainer Klute) writes:
>
>However, what I need to know is the complete path of the executing program.
>This is neccessary to read (resp. write) the configuration file which is in
>the same directory as the program itself. 

[Stuff omitted]

>Does someone have a general solution? It would be sufficient to get only
>the directory where the program is located - without knowing the program's
>name. Even better would be a possibility to retrieve the program's name
>also, and the best would be if this could be done without GEM functions.
>And yes, of course only legal solutions are useful.

DO NOT (repeat) DO NOT use the horrible hack introduced in the dlibs
startup code. It dies completely under RTX, and MiNT takes precautions
to make sure that it does not work. There is _no_ legal way that I know
of that you will always be able to do this. You can check to see if
the program was started from a shell which supports the ARGV= protocol,
but that's about it.


David Megginson
-- 
////////////////////////////////////////////////////////////////////////
/  David Megginson                      david@doe.utoronto.ca          /
/  Centre for Medieval Studies          meggin@vm.epas.utoronto.ca     /
////////////////////////////////////////////////////////////////////////

leo@ehviea.ine.philips.nl (Leo de Wit) (10/09/90)

In article <1990Oct8.144907.12697@doe.utoronto.ca> david@doe.utoronto.ca (David Megginson) writes:
|In article <1990Oct8.085411@heike.informatik.uni-dortmund.de> klute@heike.informatik.uni-dortmund.de (Rainer Klute) writes:
|>
|>However, what I need to know is the complete path of the executing program.
|>This is neccessary to read (resp. write) the configuration file which is in
|>the same directory as the program itself. 
|
|                                    There is _no_ legal way that I know
|of that you will always be able to do this. You can check to see if
|the program was started from a shell which supports the ARGV= protocol,
|but that's about it.

Well, there _is_ a legal way that I know of, but you may not like the
implications. Just write a TSR that traps Pexec calls and saves the
filename in a private buffer before letting GEMDOS take over. By some
communication with the TSR (various ways to do this) the newly started
program can find out its real name.

Some potential problems (and solutions) with this scheme:
a) In case of a relative pathname the TSR must prepend the current
directory in the private buffer. Piece of cake.
b) the application must check for the TSR to be present, and if it is
not, (perhaps install it and) exit with an error message to do a retry.
Not so big a problem, since the user will probably put the TSR in his
AUTO folder if he needs it frequently.
c) In case of a multiTOSking environment, there is a potential race
condition between the new program getting its full path and another
program being Pexec'ed at the same time (overwriting the static
buffer). If you want to solve this, you'll probably need multiple name
slots.
d) With Pexec(4,...) (go) you don't supply a name, so you can either
take the easy way out by aborting the program, saying you don't support
preloading, or keep the name supplied by Pexec(3,...) (load) together
with the basepage address - this might imply maintaining a list.
e) If the executing program is not a disk file, it will not even have a
complete path (take the Desktop for example). This is really not a
problem for most application programs.

    Leo.

klute@heike.informatik.uni-dortmund.de (Rainer Klute) (10/17/90)

Thanks to all how replied to my query. Here is an outline of what I think
is the best solution. I implemented in Arcgsh 3.2 coming soon on
comp.binaries.atari.st.

First I try to find the program's path with the shel_find() function. The
parameter is the basename of the resource file.  (I know at this point that
the resource file exists because it has been loaded with rsrc_load()
already.)

If shel_find() succeeds it returns either a full path or the filename as I
handed it to shel_find. In the latter case the file is in the current
directory on the current drive, and I can construct the full path myself.

If shel_find() fails I do the same as shel_find() for the directories in
the PATH environment variable: PathFind() takes a filename and searches all
directories in the PATH for that file. If it is found its full path is
returned.

Here is a piece of source code from Arcgsh 3.2 showing the principle:

        strcpy (buffer, "arcgsh.rsc");
        if (shel_find (buffer) != 0)
           {
           if (buffer[1] != ':')
              getpath (arcgshDirectory);
           else
              strcpy (arcgshDirectory, dirname (buffer));
           i = strlen (arcgshDirectory) - 1;
           if (arcgshDirectory[i] != '\\')
              strcat (arcgshDirectory, "\\");
           }
        else
           {
           if (PathFind (buffer) != 0)
              {
              strcpy (arcgshDirectory, dirname (buffer));
              strcat (arcgshDirectory, "\\");
              }
           else
              *arcgshDirectory = '\0';
           };

-- 
  Dipl.-Inform. Rainer Klute      klute@irb.informatik.uni-dortmund.de
  Univ. Dortmund, IRB             klute@unido.uucp, klute@unido.bitnet
  Postfach 500500         |)|/    Tel.: +49 231 755-4663
D-4600 Dortmund 50        |\|\    Fax : +49 231 755-2386