I have tried to modified the code below found on the net
- so as to compile for gcc
- so as tot always return a Lock on the fullpath (if it can be found) of the file that could be somewhere in the path ( i suppressed the "if (file > 0)
block)
/* SAS/C compatibility This function locates a file in the currently defined path. If the process is not a Shell process, it uses the path in effect when Workbench was loaded. If the findpath function finds the file, it returns a lock on that directory even if it is the current directory. The lock must be unlocked with the AmigaDOS UnLock function. If the findpath function cannot find the file, it returns a -1. The value NULL is not used because NULL is a valid lock. */ #include <proto/dos.h> void* findpath(const char *filename) { BPTR file = Lock(filename, SHARED_LOCK); if (file <= 0) { struct CommandLineInterface *cli = Cli(); BPTR oldCurDir = CurrentDir(NULL); BPTR *paths = BADDR(cli->cli_CommandDir); if (IoErr() == ERROR_OBJECT_IN_USE) return -1; for (; !file && paths; paths = BADDR(paths[0])) { CurrentDir(paths[1]); file = Lock(filename, SHARED_LOCK); } CurrentDir(oldCurDir); } if (file > 0) { BPTR dir = ParentOfFH(file); UnLock(file); file = dir; } return file ? file : -1; }
1. I had a strange crash in my version below, see the comments anq question marks
#define __USE_INLINE__ #define ZERO ((BPTR)NULL) //OS4 added #include <proto/dos.h> #include <dos/dosextens.h> /// added BPTR findpath(const char *filename) /// filename used is Gui4Cli and we expect this file to be { struct CommandLineInterface *cli; BPTR file; BPTR *paths; BPTR oldCurDir; char dirname[200]; oldCurDir = CurrentDir(ZERO); NameFromLock(oldCurDir, dirname, 180); Printf("current dir %s\n",dirname); /// prints datas:Gui4Cli, wher Gui4Cli lives Printf("filename %s\n", filename); /// prints Gui4Cli if ((file = Lock(filename, SHARED_LOCK))) { Printf("Lock ok\n"); /// not seen ???? why ????????? UnLock(file); } if (!(file = Lock(filename, SHARED_LOCK))) /// not in the current Dir or in the path { PrintFault(IoErr(),NULL); /// no output Printf("could not lock %s\n", filename); //// this is printed out ???? if ((cli = Cli())) { ///oldCurDir = CurrentDir(ZERO); // was NULL); paths = BADDR(cli->cli_CommandDir); // used to crash in some cases } if (IoErr() == ERROR_OBJECT_IN_USE) //only possible value ? why return ((BPTR)(-1)) ; //-1; ///else PrintFault(IoErr(),NULL); for (; !file && paths; paths = BADDR(paths[0])) ///searchin in the path till Lock ok { CurrentDir(paths[1]); file = Lock(filename, SHARED_LOCK); ///>>>>> crash here now } CurrentDir(oldCurDir); // the original current directory } return file ? file : ((BPTR)(-1));//-1; }
Maybe there is an explanation in the code above, that i don't see. I hope so.
Otherwise it may be due to the following :
findpath() is used in the Gui4Cli launcher (name 'Gui' gui.c source is available) which uses Olaf Barthel's wbpath.c that Thomas was able to dig out.
findpath() could be a SAS/C provided function. The findpath.c is my reconstruction based on a non SAS/C findpath.c source.
If somebody has the latter source that would help too of course
2. I wondered for the first source what IoErr() really could detect. (where a significant IoErr() was set. Indeed, the autodocs neither for Lock() Cli() nor CurrentDir() mention even IoErr().
I don't know why it crashes. But I see this:
1. you set CurrentDir to ZERO and then wonder why it is still zero whyn you call it again?
2. you search the file in the current dir while current dir is zero. This will always fail. If the file *is* in the (old) current dir, then the function will not find it
3. why do you return -1 in case of failure? How do you check for failure in your main program? If you return -1 you need to check for -1.
Here is a reworked version:
Note that it still has at least two flaws:
1. it also finds directories
2. it does not handle multi-assigns, so it does not find files in further components of C:.
@Thomas, thanks for your help.
The problem is not solved yet though, when using my gui4 launcher as standard tool to a Gui4Cli sscript's icon on line 28
It works OK when launched from shell
>> gui4 Myscript.gc // Myscript.gc is in the same directory
>> gui4 Mypath/Myscript.gc
I'll investigate further
@JosDuchIt
When you run the program from Workbench Cli() will return a NULL pointer because the program doesn't have a CLI structure causing NULL pointer accesses later in your program since you don't check the return value from this function before using it.
May I ask what you try to use this routine for? If you use your program as default tool in a project icon, then sm_ArgList[0] points to program and sm_ArgList[1] points to the script. What do you search in the path?
@salass00
Thanks for help. That explains the crash when i use findäth() from thomas example & his main()
However the original source gui4.c is compiled together with findpath.c and wbpath.c (provided by thomas too)
Main() therefor begins with
and later has the lines
and later
I still have the crash as if the path was not known to findpath.
I am of course not sure if the gui4 source i inherited was correct
and if the reconstructed findpath() is doing what is expected.
Thinking about your remark:
shouldn't findpath() get the cloned 'path' as argument?
(obviously the original gui4source does not think so.)
wbpath.h states:
When a program is launched via the »Execute Command ...«
menu item provided by Workbench, Workbench passes the CLI
command path that was active at the time LoadWb was invoked
to the application. Regular Workbench processes, however, do
not operate in a CLI environment, so they cannot inherit the
Workbench path, and new shells spawned by such processes via
SystemTagList() start with an »empty« path (i.e. just »C:«
and the current directory).
The function CloneWorkbenchPath() creates a local copy of
the current Workbench path, usually for the purpose of it
being passed to SystemTagList() or to CreateNewProc() via
the NP_Path tag; the WBStartup parameter passed to
CloneWorkbenchPath() must be valid and non-NULL. The path is
deallocated automatically by the OS upon the termination of
the newly created process; if the CreateNewProc() or
SystemTagList() call fails, however, the cloned path must be
freed explicitly by calling FreeWorkbenchPath().
The reason it doesn't work is that while you use CloneWorkbenchPath to clone the WB path, in findpath() you're still trying to get the path from the CLI structure which doesn't exist because your program was started from WB.
What you need to do is change this:
so that it uses a cloned WB path if CLI structure isn't available:
@salas00
Many thanks, that did it.
@thomas too for all your help
Endresult