My previous commit caused that parent directory wasn't set,
[aros:aros.git] / AROS / workbench / libs / workbench / openworkbenchobjecta.c
1 /*
2     Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3     $Id$
4
5     Open a drawer or launch a program.
6 */
7
8 #define DEBUG 0
9 #include <aros/debug.h>
10
11 #include <exec/types.h>
12 #include <exec/ports.h>
13 #include <utility/tagitem.h>
14 #include <intuition/intuition.h>
15 #include <workbench/workbench.h>
16 #include <proto/utility.h>
17 #include <proto/dos.h>
18
19 #include <string.h>
20
21 #include "workbench_intern.h"
22 #include "support.h"
23 #include "support_messages.h"
24 #include "handler.h"
25 #include "handler_support.h"
26 #include "uae_integration.h"
27
28 /*** Prototypes *************************************************************/
29 static BOOL   CLI_LaunchProgram(CONST_STRPTR command, struct TagItem *tags, struct WorkbenchBase *WorkbenchBase);
30 static STRPTR CLI_BuildCommandLine(CONST_STRPTR command, struct TagItem *tags, struct WorkbenchBase *WorkbenchBase);
31 static BOOL   WB_LaunchProgram(BPTR lock, CONST_STRPTR name, struct TagItem *tags, struct WorkbenchBase *WorkbenchBase);
32 static BOOL   WB_BuildArguments(struct WBStartup *startup, BPTR lock, CONST_STRPTR name, struct TagItem *tags, struct WorkbenchBase *WorkbenchBase);
33 static BOOL   HandleDrawer(STRPTR name, struct WorkbenchBase *WorkbenchBase);
34 static BOOL   HandleTool(STRPTR name, LONG isDefaultIcon, struct DiskObject *icon, struct TagItem *tags, struct WorkbenchBase *WorkbenchBase);
35 static BOOL   HandleProject(STRPTR name, LONG isDefaultIcon, struct DiskObject *icon, struct TagItem *tags, struct WorkbenchBase *WorkbenchBase);
36
37 /*****************************************************************************
38
39     NAME */
40
41         #include <proto/workbench.h>
42
43         AROS_LH2(BOOL, OpenWorkbenchObjectA,
44
45 /*  SYNOPSIS */
46         AROS_LHA(STRPTR,           name, A0),
47         AROS_LHA(struct TagItem *, tags, A1),
48
49 /*  LOCATION */
50         struct WorkbenchBase *, WorkbenchBase, 16, Workbench)
51
52 /*  FUNCTION
53
54     INPUTS
55
56     RESULT
57
58     NOTES
59
60     EXAMPLE
61
62     BUGS
63
64     SEE ALSO
65
66     INTERNALS
67
68 ******************************************************************************/
69 {
70     AROS_LIBFUNC_INIT
71
72     BOOL                  success       = FALSE;
73     LONG                  isDefaultIcon = 42;
74
75     struct DiskObject    *icon          = GetIconTags
76     (
77         name,
78         ICONGETA_FailIfUnavailable,        FALSE,
79         ICONGETA_IsDefaultIcon,     (IPTR) &isDefaultIcon,
80         TAG_DONE
81     );
82
83     ASSERT_VALID_PTR(name);
84     ASSERT_VALID_PTR_OR_NULL(tags);
85
86     D(bug("[WBLIB] OpenWorkbenchObjectA: name = %s\n", name));
87     D(bug("[WBLIB] OpenWorkbenchObjectA: isDefaultIcon = %ld\n", isDefaultIcon));
88
89     if( j_uae_running() && is_68k(name, WorkbenchBase) ) 
90     {
91
92         D(bug("[WBLIB] OpenWorkbenchObjectA: forward %s to uae\n", name));
93
94         forward_to_uae(tags, name, WorkbenchBase);
95         success = TRUE;
96     }
97     else 
98     {
99         if (icon != NULL)
100         {
101             switch (icon->do_Type)
102             {
103                 case WBDISK:
104                 case WBDRAWER:
105                 case WBGARBAGE:
106                     success = HandleDrawer(name, WorkbenchBase);
107                     break;
108
109                 case WBTOOL:
110                     success = HandleTool(name, isDefaultIcon, icon, tags, WorkbenchBase);
111                     break;
112
113                 case WBPROJECT:
114                     success = HandleProject(name, isDefaultIcon, icon, tags, WorkbenchBase);
115                     break;
116             }
117
118             FreeDiskObject(icon);
119         }
120         else
121         {
122             /*
123                 Getting (a possibly default) icon for the path failed, and
124                 therefore there is no such file. We need to search the default
125                 search path for an executable of that name and launch it. This
126                 only makes sense if the name is *not* an (absolute or relative)
127                 path: that is, it must not contain any ':' or '/'.
128             */
129
130             if (strpbrk(name, "/:") == NULL)
131             {
132                 struct CommandLineInterface *cli = Cli();
133                 if (cli != NULL)
134                 {
135                     BPTR *paths;          /* Path list */
136                     BOOL  running = TRUE;
137
138                     /* Iterate over all paths in the path list */
139                     for
140                     (
141                         paths = (BPTR *) BADDR(cli->cli_CommandDir);
142                         running == TRUE && paths != NULL;
143                         paths = (BPTR *) BADDR(paths[0]) /* next path */
144                     )
145                     {
146                         BPTR cd   = CurrentDir(paths[1]);
147                         BPTR lock = Lock(name, SHARED_LOCK);
148
149                         if (lock != BNULL)
150                         {
151                             success = OpenWorkbenchObjectA(name, tags);
152                             running = FALSE;
153
154                             UnLock(lock);
155                         }
156
157                         CurrentDir(cd);
158                     }
159                 }
160             }
161         }
162     }
163
164     D(bug("[WBLIB] OpenWorkbenchObjectA: success = %d\n", success));
165
166     return success;
167
168     AROS_LIBFUNC_EXIT
169 } /* OpenWorkbenchObjectA() */
170
171 /****************************************************************************/
172
173 static STRPTR CLI_BuildCommandLine
174 (
175     CONST_STRPTR command, struct TagItem *tags,
176     struct WorkbenchBase *WorkbenchBase
177 )
178 {
179     struct TagItem *tstate   = tags;
180     struct TagItem *tag      = NULL;
181     BPTR            lastLock = BNULL;
182     STRPTR          buffer   = NULL;
183     ULONG           length   = strlen(command) + 3 /* NULL + 2 '"' */;
184
185     /*-- Calculate length of resulting string ------------------------------*/
186     while ((tag = NextTagItem(&tstate)) != NULL)
187     {
188         switch (tag->ti_Tag)
189         {
190             case WBOPENA_ArgLock:
191                 lastLock = (BPTR) tag->ti_Data;
192                 break;
193
194             case WBOPENA_ArgName:
195                 if (lastLock != BNULL)
196                 {
197                     BPTR cd   = CurrentDir(lastLock);
198                     BPTR lock = Lock((STRPTR) tag->ti_Data, ACCESS_READ);
199                     if (lock != BNULL)
200                     {
201                         STRPTR path = AllocateNameFromLock(lock);
202                         if (path != NULL)
203                         {
204                             length += 3 /* space + 2 '"' */ + strlen(path);
205                             FreeVec(path);
206                         }
207
208                         UnLock(lock);
209                     }
210
211                     CurrentDir(cd);
212                 }
213                 break;
214         }
215     }
216
217     /*-- Allocate space for command line string ----------------------------*/
218     buffer = AllocVec(length, MEMF_ANY);
219
220     if (buffer != NULL)
221     {
222         buffer[0] = '\0';
223
224         /*-- Build command line --------------------------------------------*/
225         strcat(buffer, "\"");
226         strcat(buffer, command);
227         strcat(buffer, "\"");
228
229         tstate = tags; lastLock = BNULL;
230         while ((tag = NextTagItem(&tstate)) != NULL )
231         {
232             switch (tag->ti_Tag)
233             {
234                 case WBOPENA_ArgLock:
235                     lastLock = (BPTR) tag->ti_Data;
236                     break;
237
238                 case WBOPENA_ArgName:
239                     if (lastLock != BNULL)
240                     {
241                         BPTR cd   = CurrentDir(lastLock);
242                         BPTR lock = Lock((STRPTR) tag->ti_Data, ACCESS_READ);
243                         if (lock != BNULL)
244                         {
245                             STRPTR path = AllocateNameFromLock(lock);
246                             if (path != NULL)
247                             {
248                                 strcat(buffer, " \"");
249                                 strcat(buffer, path);
250                                 strcat(buffer, "\"");
251                                 FreeVec(path);
252                             }
253
254                             UnLock(lock);
255                         }
256
257                         CurrentDir(cd);
258                     }
259                     break;
260             }
261         }
262     }
263     else
264     {
265         SetIoErr(ERROR_NO_FREE_STORE);
266     }
267
268     return buffer;
269 }
270
271 /****************************************************************************/
272
273 static BOOL CLI_LaunchProgram
274 (
275     CONST_STRPTR command, struct TagItem *tags,
276     struct WorkbenchBase *WorkbenchBase
277 )
278 {
279     BPTR   input       = BNULL;
280     STRPTR commandline = NULL;
281     IPTR                stacksize = WorkbenchBase->wb_DefaultStackSize;
282     LONG                priority = 0;
283     struct TagItem      *foundTag = NULL;
284
285     input = Open("CON:////Output Window/CLOSE/AUTO/WAIT", MODE_OLDFILE);
286     if (input == BNULL) goto error;
287
288     commandline = CLI_BuildCommandLine(command, tags, WorkbenchBase);
289     if (commandline == NULL) goto error;
290
291     if (tags)
292     {
293         foundTag = FindTagItem(NP_StackSize, tags);
294         if (foundTag != NULL)
295         {
296             stacksize = foundTag->ti_Data;
297         }
298
299         foundTag = FindTagItem(NP_Priority, tags);
300         if (foundTag != NULL)
301         {
302             priority = foundTag->ti_Data;
303         }
304     }
305
306     if
307     (
308         /*
309             Launch the program. Note that there is no advantage of doing this
310             in the handler, since we need to wait for the return value anyway
311             (and thus we cannot cut down the blocking time by returning before
312             the program is loaded from disk).
313         */
314
315         SystemTags
316         (
317             commandline,
318             SYS_Asynch,          TRUE,
319             SYS_Input,    (IPTR) input,
320             SYS_Output,   (IPTR) NULL,
321             SYS_Error,    (IPTR) NULL,
322             NP_StackSize,        stacksize,
323             NP_Priority,         priority,
324             TAG_DONE
325         ) == -1
326     )
327     {
328         goto error;
329     }
330     FreeVec(commandline);
331
332     return TRUE;
333
334 error:
335     if (input != BNULL) Close(input);
336     if (commandline != NULL) FreeVec(commandline);
337
338     return FALSE;
339 }
340
341 /****************************************************************************/
342
343 static BOOL WB_BuildArguments
344 (
345     struct WBStartup *startup, BPTR lock, CONST_STRPTR name, struct TagItem *tags,
346     struct WorkbenchBase *WorkbenchBase
347 )
348 {
349     struct TagItem *tstate   = tags,
350                    *tag      = NULL;
351     BPTR            lastLock = BNULL;
352     struct WBArg   *args     = NULL;
353
354     /*-- Calculate the number of arguments ---------------------------------*/
355     startup->sm_NumArgs = 1;
356     while ((tag = NextTagItem(&tstate)) != NULL)
357     {
358         switch (tag->ti_Tag)
359         {
360             case WBOPENA_ArgLock:
361                 lastLock = (BPTR) tag->ti_Data;
362                 break;
363
364             case WBOPENA_ArgName:
365                 /*
366                     Filter out args where both lock AND name are NULL, since
367                     they are completely worthless to the application.
368                 */
369                 if (lastLock != BNULL || (STRPTR) tag->ti_Data != NULL)
370                 {
371                     startup->sm_NumArgs++;
372                 }
373                 break;
374         }
375     }
376
377     /*-- Allocate memory for the arguments ---------------------------------*/
378     args = AllocMem(sizeof(struct WBArg) * startup->sm_NumArgs, MEMF_ANY | MEMF_CLEAR);
379     if (args != NULL)
380     {
381         LONG i = 0;
382
383         startup->sm_ArgList = args;
384
385         /*-- Build the argument list ---------------------------------------*/
386         if
387         (
388                (args[i].wa_Lock = DupLock(lock)) == BNULL
389             || (args[i].wa_Name = StrDup(name))  == NULL
390         )
391         {
392             goto error;
393         }
394         i++;
395
396         tstate = tags; lastLock = BNULL;
397         while ((tag = NextTagItem(&tstate)) != NULL)
398         {
399             switch (tag->ti_Tag)
400             {
401                 case WBOPENA_ArgLock:
402                     lastLock = (BPTR) tag->ti_Data;
403                     break;
404
405                 case WBOPENA_ArgName:
406                     /*
407                         Filter out args where both lock AND name are NULL,
408                         since they are completely worthless to the application.
409                     */
410                     if (lastLock != BNULL || (STRPTR) tag->ti_Data != NULL)
411                     {
412                         STRPTR name = (STRPTR) tag->ti_Data;
413
414                         /* Duplicate the lock */
415                         if (lastLock != BNULL)
416                         {
417                             args[i].wa_Lock = DupLock(lastLock);
418
419                             if (args[i].wa_Lock == BNULL)
420                             {
421                                 D(bug("[WBLIB] WB_BuildArguments: Failed to duplicate lock!\n"));
422                                 goto error;
423                                 break;
424                             }
425                         }
426                         else
427                         {
428                             args[i].wa_Lock = BNULL;
429                         }
430
431                         /* Duplicate the name */
432                         if (name != NULL)
433                         {
434                             args[i].wa_Name = StrDup(name);
435
436                             if (args[i].wa_Name == NULL)
437                             {
438                                 D(bug("[WBLIB] WB_BuildArguments: Failed to duplicate string!\n"));
439                                 goto error;
440                                 break;
441                             }
442                         }
443                         else
444                         {
445                             args[i].wa_Name = NULL;
446                         }
447
448                         i++;
449                     }
450                     break;
451             }
452         }
453
454         return TRUE;
455     }
456     else
457     {
458         D(bug("[WBLIB] WB_BuildArguments: Failed to allocate memory for argument array\n"));
459     }
460
461 error:
462     D(bug("[WBLIB] WB_BuildArguments: Freeing resources after error...\n"));
463     /* Free allocated resources */
464     if (args != NULL)
465     {
466         int i;
467
468         for (i = 0; i < startup->sm_NumArgs; i++)
469         {
470             if (args[i].wa_Lock != BNULL) UnLock(args[i].wa_Lock);
471             if (args[i].wa_Name != NULL) FreeVec(args[i].wa_Name);
472         }
473
474         FreeMem(args, sizeof(struct WBArg) * startup->sm_NumArgs);
475     }
476
477     startup->sm_NumArgs = 0;
478     startup->sm_ArgList = NULL;
479
480     return FALSE;
481 }
482
483 /****************************************************************************/
484
485 static BOOL WB_LaunchProgram
486 (
487     BPTR lock, CONST_STRPTR name, struct TagItem *tags,
488     struct WorkbenchBase *WorkbenchBase
489 )
490 {
491     struct WBStartup        *startup = NULL;
492     struct WBCommandMessage *message = NULL;
493     struct TagItem          *stackTag = NULL;
494     struct TagItem          *prioTag = NULL;
495
496     /*-- Allocate memory for messages --------------------------------------*/
497     startup = CreateWBS();
498     if (startup == NULL)
499     {
500         D(bug("[WBLIB] WB_LaunchProgram: Failed to allocate memory for startup message\n"));
501         SetIoErr(ERROR_NO_FREE_STORE);
502         goto error;
503     }
504
505     message = CreateWBCM(WBCM_TYPE_LAUNCH);
506     if (message == NULL)
507     {
508         D(bug("[WBLIB] WB_LaunchProgram: Failed to allocate memory for launch message\n"));
509         SetIoErr(ERROR_NO_FREE_STORE);
510         goto error;
511     }
512
513     if (tags)
514     {
515         stackTag = FindTagItem(NP_StackSize, tags);
516         prioTag = FindTagItem(NP_Priority, tags);
517
518         if (stackTag || prioTag)
519         {
520             message->wbcm_Tags =  AllocateTagItems(3);
521
522             message->wbcm_Tags[0].ti_Tag = stackTag ? stackTag->ti_Tag : TAG_IGNORE;
523             message->wbcm_Tags[0].ti_Data = stackTag->ti_Data;
524
525             message->wbcm_Tags[1].ti_Tag = prioTag ? prioTag->ti_Tag : TAG_IGNORE;
526             message->wbcm_Tags[1].ti_Data = prioTag->ti_Data;
527
528             message->wbcm_Tags[2].ti_Tag = TAG_DONE;
529         }
530     }
531
532     /*-- Build the arguments array -----------------------------------------*/
533     if (!WB_BuildArguments(startup, lock, name, tags, WorkbenchBase))
534     {
535         D(bug("[WBLIB] WB_LaunchProgram: Failed to build arguments\n"));
536         goto error;
537     }
538
539     /*-- Send message to handler -------------------------------------------*/
540     /* NOTE: The handler will deallocate all resources of this message! */
541     message->wbcm_Data.Launch.Startup = startup;
542
543     PutMsg(&(WorkbenchBase->wb_HandlerPort), (struct Message *) message);
544
545     D(bug("[WBLIB]  WB_LaunchProgram: Success\n"));
546
547     return TRUE;
548
549 error:
550     if (startup != NULL) DestroyWBS(startup);
551     if (message != NULL) DestroyWBCM(message);
552
553     D(bug("[WBLIB] WB_LaunchProgram: Failure\n"));
554
555     return FALSE;
556 }
557
558 /****************************************************************************/
559
560 static BOOL HandleDrawer(STRPTR name, struct WorkbenchBase *WorkbenchBase)
561 {
562     /*
563         Since it's a directory or volume, tell the Workbench
564         Application to open the corresponding drawer.
565     */
566
567     D(bug("[WBLIB] OpenWorkbenchObjectA: it's a DISK, DRAWER or GARBAGE\n"));
568
569     BOOL success                      = FALSE;
570     struct WBCommandMessage *wbcm     = NULL;
571     struct WBHandlerMessage *wbhm     = NULL;
572     CONST_STRPTR             namecopy = NULL;
573
574     if
575     (
576            (wbcm     = CreateWBCM(WBCM_TYPE_RELAY)) != NULL
577         && (wbhm     = CreateWBHM(WBHM_TYPE_OPEN))  != NULL
578         && (namecopy = StrDup(name))                != NULL
579
580     )
581     {
582         wbhm->wbhm_Data.Open.Name     = namecopy;
583         wbcm->wbcm_Data.Relay.Message = wbhm;
584
585         PutMsg(&(WorkbenchBase->wb_HandlerPort), (struct Message *) wbcm);
586         success = TRUE;
587     }
588     else
589     {
590         FreeVec((STRPTR)namecopy);
591         DestroyWBHM(wbhm);
592         DestroyWBCM(wbcm);
593     }
594     return success;
595 }
596
597 /****************************************************************************/
598
599 static BOOL HandleTool
600 (
601     STRPTR name, LONG isDefaultIcon, struct DiskObject *icon,
602     struct TagItem *tags, struct WorkbenchBase *WorkbenchBase
603 )
604 {
605     /*
606         It's an executable. Before I launch it, I must check
607         whether it is a Workbench program or a CLI program.
608     */
609
610     BOOL success = FALSE;
611
612     D(bug("[WBLIB] OpenWorkbenchObjectA: it's a TOOL\n"));
613
614     if
615     (
616            !isDefaultIcon
617         && FindToolType(icon->do_ToolTypes, "CLI") == NULL
618     )
619     {
620         /* It's a Workbench program */
621         BPTR lock = Lock(name, ACCESS_READ);
622
623         D(bug("[WBLIB] OpenWorkbenchObjectA: it's a WB program\n"));
624
625         if (lock != BNULL)
626         {
627             BPTR parent = ParentDir(lock);
628
629             if (parent != BNULL)
630             {
631                 IPTR stacksize = icon->do_StackSize;
632
633                 if (stacksize < WorkbenchBase->wb_DefaultStackSize)
634                     stacksize = WorkbenchBase->wb_DefaultStackSize;
635
636                 /* check for TOOLPRI */
637                 LONG priority = 0;
638                 STRPTR prio_tt = FindToolType(icon->do_ToolTypes, "TOOLPRI");
639                 if (prio_tt)
640                 {
641                     StrToLong(prio_tt, &priority);
642                     if (priority < -128)
643                         priority = -128;
644                     if (priority > 127)
645                         priority = 127;
646                 }
647                 
648                 D(bug("[WBLIB] OpenWorkbenchObjectA: stack size: %d Bytes, priority %d\n", stacksize, priority));
649
650                 struct TagItem wbp_Tags[] =
651                 {
652                     { NP_StackSize,   stacksize },
653                     { NP_Priority,    priority  },
654                     { TAG_MORE, (IPTR)tags      },
655                     { TAG_DONE,       0         }
656                 };
657
658                 if (tags == NULL)
659                     wbp_Tags[2].ti_Tag = TAG_IGNORE;
660
661                 success = WB_LaunchProgram
662                 (
663                     parent, FilePart(name), wbp_Tags, WorkbenchBase
664                 );
665
666                 if (!success)
667                 {
668                     /*
669                         Fallback to launching it as a CLI program.
670                         Most likely it will also fail, but we
671                         might get lucky.
672                     */
673                     success = CLI_LaunchProgram(name, wbp_Tags, WorkbenchBase);
674                 }
675
676                 UnLock(parent);
677             }
678
679             UnLock(lock);
680         }
681     }
682     else
683     {
684         /* It's a CLI program */
685
686         D(bug("[WBLIB] OpenWorkbenchObjectA: it's a CLI program\n"));
687
688         success = CLI_LaunchProgram(name, tags, WorkbenchBase);
689     }
690
691     return success;
692 }
693
694 /****************************************************************************/
695
696 static BOOL HandleProject
697 (
698     STRPTR name, LONG isDefaultIcon, struct DiskObject *icon,
699     struct TagItem *tags, struct WorkbenchBase *WorkbenchBase
700 )
701 {
702     /* It's a project; try to launch it via its default tool. */
703
704     BOOL success = FALSE;
705
706     D(bug("[WBLIB] OpenWorkbenchObjectA: it's a PROJECT\n"));
707     D(bug("[WBLIB] OpenWorkbenchObjectA: default tool: %s\n", icon->do_DefaultTool));
708
709     if
710     (
711            icon->do_DefaultTool != NULL
712         && strlen(icon->do_DefaultTool) > 0
713     )
714     {
715         BPTR lock = BNULL, parent = BNULL;
716
717         lock = Lock(name, ACCESS_READ);
718         if (lock != BNULL)
719             parent = ParentDir(lock);
720         else
721         /* 
722          *  A project icon (without a project file) is actually enough for
723          *  original Workbench (ie to launch the supplied tool)
724          */
725         {
726             STRPTR iconname;
727             if ((iconname = AllocVec(strlen(name) + 5, MEMF_ANY)) == NULL)
728                 return success;
729             iconname[0] = '\0';
730             strcat(iconname, name);
731             strcat(iconname, ".info");
732             if ((lock = Lock(iconname, ACCESS_READ)) != BNULL)
733                 parent = ParentDir(lock);
734             FreeVec(iconname);
735         }
736         if (parent != BNULL)
737         {
738             IPTR stacksize = icon->do_StackSize;
739
740             if (stacksize < WorkbenchBase->wb_DefaultStackSize)
741                 stacksize = WorkbenchBase->wb_DefaultStackSize;
742
743             /* check for TOOLPRI */
744             LONG priority = 0;
745             STRPTR prio_tt = FindToolType(icon->do_ToolTypes, "TOOLPRI");
746             if (prio_tt)
747             {
748                 StrToLong(prio_tt, &priority);
749                 if (priority < -128)
750                     priority = -128;
751                 if (priority > 127)
752                     priority = 127;
753             }
754             
755             D(bug("[WBLIB] OpenWorkbenchObjectA: stack size: %d Bytes, priority %d\n", stacksize, priority));
756
757             struct TagItem deftool_tags[] =
758             {
759                 { NP_StackSize    ,        stacksize      },
760                 { NP_Priority     ,        priority       },
761                 { WBOPENA_ArgLock , (IPTR) parent         },
762                 { WBOPENA_ArgName , (IPTR) FilePart(name) },
763                 { TAG_MORE        , (IPTR) tags           },
764                 { TAG_DONE        ,        0              }
765             };
766
767             if (tags == NULL)
768                 deftool_tags[4].ti_Tag = TAG_IGNORE;
769             
770             if (FindToolType(icon->do_ToolTypes, "CLI") == NULL)
771             {
772                 BPTR deftool_lock = BNULL, deftool_parent = BNULL, old_parent = BNULL;
773                 BOOL found = FALSE;
774
775                 /* try current dir / absolute path first */
776                 deftool_lock = Lock(icon->do_DefaultTool, ACCESS_READ);
777                 if (deftool_lock != BNULL)
778                     deftool_parent = ParentDir(deftool_lock);
779
780                 if (deftool_parent != BNULL)
781                 {
782                     found = TRUE;
783                     success = WB_LaunchProgram
784                     (
785                         deftool_parent, FilePart(icon->do_DefaultTool), deftool_tags, WorkbenchBase
786                     );
787                 }
788                 UnLock(deftool_parent);
789                 UnLock(deftool_lock);
790
791                 if (!found && strpbrk(icon->do_DefaultTool, "/:") == NULL) /* relative path */
792                 {
793                     struct CommandLineInterface *cli = Cli();
794                     if (cli != NULL)
795                     {
796                         BPTR *paths;          /* Path list */
797                         BOOL  running = TRUE;
798
799                         /* Iterate over all paths in the path list */
800                         for
801                         (
802                             paths = (BPTR *) BADDR(cli->cli_CommandDir);
803                             running == TRUE && paths != NULL;
804                             paths = (BPTR *) BADDR(paths[0]) /* next path */
805                         )
806                         {
807                             old_parent  = CurrentDir(paths[1]);
808                             deftool_parent = DupLock(paths[1]);
809                             deftool_lock = Lock(icon->do_DefaultTool, SHARED_LOCK);
810
811                             if (deftool_lock != BNULL)
812                             {
813                                 success = WB_LaunchProgram
814                                 (
815                                     deftool_parent, icon->do_DefaultTool, deftool_tags, WorkbenchBase
816                                 );
817  
818                                 running = FALSE;
819
820                                 UnLock(deftool_lock);
821                                 UnLock(deftool_parent);
822                             }
823                             CurrentDir(old_parent);
824                         }
825                     }
826                 }
827             }
828             else
829             {
830                 success = CLI_LaunchProgram
831                 (
832                     icon->do_DefaultTool, tags, WorkbenchBase
833                 );
834             }
835
836             UnLock(parent);
837             UnLock(lock);
838         }
839         else
840             D(bug("[WBLIB] OpenWorkbenchObjectA: Couldn't get parent dir!\n"));
841     }
842
843     if (!success)
844     {
845         // FIXME: open ExecuteCommand?
846     }
847     
848     return success;
849 }