How check if a DOS command exists?

13 posts / 0 new
Last post
ChrisH
ChrisH's picture
Offline
Last seen: 4 years 4 months ago
Joined: 2010-12-07 20:22
How check if a DOS command exists?

Is there an easy way to check that an AmigaDOS command exists? In my particular case, I wish to check that "Curl" exists in the command path, so that I can check before hand if executing "Run >NIL: Curl ..." should work or not (and if not then warn the user it is missing).

I canNOT just try to Lock() the command's name, because AmigaDOS will search the command path, but Lock() will not!

I just tried using LoadSeg(), but that doesn't seem to search the command path either.

Please don't tell me I need to get the AmigaDOS command path (somehow!) & search it myself!?!

gazelle
gazelle's picture
Offline
Last seen: 1 year 10 months ago
Joined: 2011-04-13 12:52
How

How about:

  1. dos.library/SearchCmdPathList
  2.  
  3. SearchCmdPathList -- Try to locate an object along a shell search path. (V50)

edit: Ok, you'll still have to do some work on the hook.

Other than that, you may run "which <command>" and check the return code.

ChrisH
ChrisH's picture
Offline
Last seen: 4 years 4 months ago
Joined: 2010-12-07 20:22
@gazelle Thanks for the

@gazelle
Thanks for the suggestions! It's a shame SearchCmdPathList() is OS4-only, but I guess trying to do the same on OS3 will be much more difficult. Using the "Which" command is an kludge, but possibly the best I can hope for.


Author of the PortablE programming language.

I love using Amiga OS4.1 on my X1000 & Sam440 :-D

thomas
thomas's picture
Offline
Last seen: 3 months 3 weeks ago
Joined: 2011-05-16 14:23
Check this:

Check this: http://thomas-rapp.homepage.t-online.de/examples/which.c

ChrisH
ChrisH's picture
Offline
Last seen: 4 years 4 months ago
Joined: 2010-12-07 20:22
@thomas Thanks! That looks

@thomas
Thanks! That looks almost exactly what I was looking for. (Maybe I'll use a #ifdef so OS4 executables can use the new OS function instead.)


Author of the PortablE programming language.

I love using Amiga OS4.1 on my X1000 & Sam440 :-D

ChrisH
ChrisH's picture
Offline
Last seen: 4 years 4 months ago
Joined: 2010-12-07 20:22
@thomas Part of your code

@thomas
Part of your code worries me:

  1. dl = LockDosList (LDF_ASSIGNS|LDF_READ);
  2. if (dl = FindDosEntry (dl,"C",LDF_ASSIGNS)) /* because C: may be a multi-assign we cannot just Lock("C:") */
  3. {
  4. cmdlock = check_dir (dl->dol_Lock,command);
  5. for (al = dl->dol_misc.dol_assign.dol_List; !cmdlock && al; al = al->al_Next)
  6. cmdlock = check_dir (al->al_Lock,command);
  7. }
  8. UnLockDosList (LDF_ASSIGNS|LDF_READ);

Specifically I am worried about the check_dir() calls, which uses CurrentDir(), Lock() & Examine(). Unfortunately AmigaOS4's autodocs say the following about using what is returned by FindDosEntry():

/*
* Add this entry to your private list of volumes to process later
* or break out of the while loop.
*
* For simple processing, you could also use it inside here,
* but for anything else I strongly advise against it unless you
* understand the semantics about avoiding semaphore deadlocks.
* It is never acceptable to call functions that involve sending
* dospackets to any handler currently in the doslist while the
* doslist is locked.

*/

This is more stringent than the AmigaOS3 autodocs, which advised against it "for compatibility reasons", but then go on to suggest trying it anyway to see if it works(!).

However, I'm not sure how to follow AmigaOS4's advice, because it's not clear that I can keep a copy of dol_Lock or al_Lock & expect it to work after unlocking the list...


Author of the PortablE programming language.

I love using Amiga OS4.1 on my X1000 & Sam440 :-D

ChrisH
ChrisH's picture
Offline
Last seen: 4 years 4 months ago
Joined: 2010-12-07 20:22
A possible alternative to

A possible alternative to LockDosList()+FindDosEntry() is GetDeviceProc()+SetFileSysTask(), but I suspect that may be even less desirable (although I do have code which uses it...).

However, OS4's autodocs do say "Application programmers should rarely need this function except ... possibly for an application that needs to walk multi-assignments."


Author of the PortablE programming language.

I love using Amiga OS4.1 on my X1000 & Sam440 :-D

thomas
thomas's picture
Offline
Last seen: 3 months 3 weeks ago
Joined: 2011-05-16 14:23
I checked another source of

I checked another source of mine and it uses this:

  1. struct DevProc *dvp = NULL;
  2.  
  3. while (!cmdlock && (dvp = GetDeviceProc ("C:",dvp)))
  4. cmdlock = check_dir (dvp->dvp_Lock,command);
  5.  
  6. FreeDeviceProc (dvp);
ChrisH
ChrisH's picture
Offline
Last seen: 4 years 4 months ago
Joined: 2010-12-07 20:22
@thomas Your code using

@thomas
Your code using GetDeviceProc() APPEARS to me to be slightly faulty: I would call SetFileSysTask(dvp->dvp_Port) before check_dir(), and then after check_dir() call SetFileSysTask() again to restore the original filesystem task. Otherwise if dvp_Lock is NULL, your code will assume dvp_Lock points to SYS: (which may not be correct). I don't know under what circumstances it can be NULL, so maybe you can prove that is never the case here?

There may also be other reasons for calling SetFileSysTask() that I am not aware of!

@thomas
To make your code using LockDosList() technically correct, I think one needs to use DupLock() on all entries in the returned list (storing the results in a private list), call UnLockDosList(), and only then call check_dir() on the private list.

Overall the GetDeviceProc() solution appears less complicated, but surely there must be some reason why LockDosList() exists, otherwise one would always use GetDeviceProc() anyway!


Author of the PortablE programming language.

I love using Amiga OS4.1 on my X1000 & Sam440 :-D

ChrisH
ChrisH's picture
Offline
Last seen: 4 years 4 months ago
Joined: 2010-12-07 20:22
@gazelle I've attempted to

@gazelle
I've attempted to use SearchCmdPathList() to implement my own version of "Which", but it crashes. EDIT: I suck. Forgot to convert BCPL address to proper address.


Author of the PortablE programming language.

I love using Amiga OS4.1 on my X1000 & Sam440 :-D

thomas
thomas's picture
Offline
Last seen: 3 months 3 weeks ago
Joined: 2011-05-16 14:23
SetFileSysTask: I don't see a

SetFileSysTask: I don't see a reason for any application whatsoever to call this function. Which reason do you see?

Certainly the 0 lock points to SYS:, it is supposed to do so. As 0 is a valid lock, CurrentDir(0) is valid, too.

Anyhow, how shall a 0 lock appear in a C: multi assign? Even by assign c: sys: add you don't get the 0 lock but a lock to the current resolution of the sys: assign.

ChrisH
ChrisH's picture
Offline
Last seen: 4 years 4 months ago
Joined: 2010-12-07 20:22
SetFileSysTask: I don't see a

SetFileSysTask: I don't see a reason for any application whatsoever to call this function. Which reason do you see?

I'm hardly an AmigaOS expert, so I can't give you any good reasons:

Other code I've seen using GetDeviceProc() also uses SetFileSysTask(). Example code I've recently seen from the main developer of AmigaOS4's AmigaDOS also used SetFileSysTask(). And when I previously wrote code without SetFileSysTask() it didn't always work as expect (I don't recall details).

My vague understanding is that a lock of 0 should NOT point to SYS: when it is in the context of a device handler. Don't ask me why! My own source code comments don't say where/who I got this info from.

I would also point to the AmigaOS wiki, which currently seems down so here's Google's cache of it:
http://webcache.googleusercontent.com/search?q=cache:http://wiki.amigaos.net/wiki/Multiple_Assigns&strip=1
It contains the following code fragment:

  1. old_fsport = SetFileSysTask(dp->dvp_Port); /* in case dp->dvp_Lock is NULL. */
  2. old_curdir = CurrentDir(dp->dvp_Lock); /* Lock() locks relative to the */
  3. /* current directory and falls back to the root of */
  4. /* the current file system if dp->dvp_Lock is NULL. */
  5.  
  6. lock = Lock(rest_of_path,SHARED_LOCK);

This may provide a partial explanation.

Anyhow, how shall a 0 lock appear in a C: multi assign?

I have no idea, but the above code (and more that I have seen) contains SetFileSysTask() to handle that case.


Author of the PortablE programming language.

I love using Amiga OS4.1 on my X1000 & Sam440 :-D

thomas
thomas's picture
Offline
Last seen: 3 months 3 weeks ago
Joined: 2011-05-16 14:23
It's a good idea to check the

It's a good idea to check the documentation. But you should not only look at the example but also read the text above it because it describes in which situations dvp_Lock may be NULL.

And we should keep in mind that we talk about OS3 because in OS4 you can use SearchCmdPathList. OS3 has a fixed set of features and this includes some limitations, for example that the combination of PATH or DEFER with ADD is not allowed for the Assign command. This probably means that a multi-assign can only contain true locks and no late- or non-binding assignments.

Furthermore we should consider that we examine not just any path given to GetDeviceProc but we use hardcoded "C:" only to resolve a multi-assign which is known to always be an assign. (Certainly it would be possible to remove the C: assign from the DOS list and add a handler instead, but this would most likely break the installation of many people.)

Finally I made some experiments and I was not able to get a 0 lock from GetDeviceProc for anything else but ser:, par: and so on which never appear in a C: assign. Even if I add a floppy disk to C: and then remove the floppy from the drive, it still gives me a lock.

Here is the program I used for experimenting: http://thomas-rapp.homepage.t-online.de/examples/devproc.c

Log in or register to post comments