use m4_normalize on the output strings to remove trailing spaces/tabs and consolidate...
[AROS.git] / workbench / c / shellcommands / Path.c
blob3c9fe8fa935bed29ea009ddafff485aa0261d0f8
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 */
7 /*****************************************************************************
9 NAME
11 Path [{<dir>}] [ADD] [SHOW] [RESET] [REMOVE] [QUIET] [HEAD]
13 SYNOPSIS
15 PATH/M,ADD/S,SHOW/S,RESET/S,REMOVE/S,QUIET/S,HEAD/S
17 LOCATION
21 FUNCTION
23 Changes the search path for commands. Without arguments it shows the path.
25 INPUTS
27 PATH -- path
28 ADD -- adds path
29 SHOW -- shows path
30 RESET -- removes existing path and replaces it by new path
31 REMOVE -- removes the given path
32 QUIET -- suppresses dialog when a path is not found
33 HEAD -- inserts path at beginning of path list
35 RESULT
37 NOTES
39 EXAMPLE
41 path dh0:work add
43 BUGS
45 SEE ALSO
47 INTERNALS
49 HISTORY
52 ******************************************************************************/
54 #include <exec/memory.h>
55 #include <proto/exec.h>
57 #include <dos/dos.h>
58 #include <dos/dosextens.h>
60 #include <proto/dos.h>
61 #include "dos_commanderrors.h"
63 #include <aros/shcommands.h>
65 #include <aros/debug.h>
67 typedef struct CommandLineInterface* CommandLineInterfacePtr;
69 typedef struct
71 BPTR next;
72 BPTR lock;
73 } PathEntry, *PathEntryPtr;
75 #define PE(x) ((PathEntry *)(BADDR(x)))
77 static PathEntryPtr FindPathEntry(CommandLineInterfacePtr cli, STRPTR pathName,
78 PathEntryPtr* predStorage, APTR DOSBase);
80 static PathEntryPtr InsertPathEntry(PathEntryPtr predecessor, STRPTR pathName, APTR SysBase, APTR DOSBase);
82 static BOOL IsDirectory(BPTR lock, APTR DOSBase);
84 AROS_SH7(Path, 45.4,
85 AROS_SHA(STRPTR *, ,PATH,/M,NULL),
86 AROS_SHA(BOOL, ,ADD,/S,NULL),
87 AROS_SHA(BOOL, ,SHOW,/S,NULL),
88 AROS_SHA(BOOL, ,RESET,/S,NULL),
89 AROS_SHA(BOOL, ,REMOVE,/S,NULL),
90 AROS_SHA(BOOL, ,QUIET,/S,NULL),
91 AROS_SHA(BOOL, ,HEAD,/S,NULL))
93 AROS_SHCOMMAND_INIT
95 CommandLineInterfacePtr
96 cli = Cli();
98 if(!cli)
100 PrintFault(ERROR_SCRIPT_ONLY, "Path");
102 return RETURN_ERROR;
105 if (SHArg(RESET))
107 PathEntryPtr
108 cur = PE(cli->cli_CommandDir);
110 while (cur)
112 PathEntryPtr
113 next = PE(cur->next);
115 UnLock(cur->lock);
117 FreeVec(BADDR(cur->next));
119 cur = next;
122 cli->cli_CommandDir = BNULL;
125 STRPTR*
126 names = SHArg(PATH);
128 if (names && *names)
131 idx;
133 if (SHArg(REMOVE) && !SHArg(RESET))
135 PathEntryPtr
136 pred = NULL,
137 entry = NULL;
139 for (idx = 0; names[idx]; ++idx)
141 entry = FindPathEntry(cli, names[idx], &pred, DOSBase);
143 /* free the path entry */
144 if (NULL != entry)
146 if (NULL != pred)
148 pred->next = entry->next;
150 else
152 cli->cli_CommandDir = entry->next;
155 if (BNULL != entry->lock)
157 UnLock(entry->lock);
160 FreeVec(entry);
164 else /* add */
166 PathEntryPtr
167 insertAfter = (PathEntryPtr)&cli->cli_CommandDir;
169 if (!SHArg(HEAD))
171 /* Search last entry */
172 while (BNULL != insertAfter->next)
174 insertAfter = PE(insertAfter->next);
178 for (idx = 0; names[idx]; ++idx)
180 if (NULL != FindPathEntry(cli, names[idx], NULL, DOSBase))
182 /* don't add if already in path */
183 continue;
185 else
187 insertAfter = InsertPathEntry(insertAfter, names[idx], SysBase, DOSBase);
192 else
194 SHArg(SHOW) = SHArg(RESET) == 0;
197 if (SHArg(SHOW))
199 UBYTE Buffer[2048];
201 PutStr("Current Directory\n");
203 PathEntryPtr
204 cur = NULL;
206 for (cur = PE(cli->cli_CommandDir); cur; cur = PE(cur->next))
208 NameFromLock (cur->lock, Buffer, sizeof (Buffer));
210 PutStr(Buffer);
211 PutStr("\n");
214 PutStr("C:\n");
217 return RETURN_OK;
219 AROS_SHCOMMAND_EXIT
223 /** find the specfied path name in the specified CLI's path list.
225 * @autodoc:function if the path specified by pathName is in the path list of
226 * the specified CLI the corresponding path entry is returned. the path entry's
227 * predecessor is stored in the specified location if the storage pointer is
228 * not NULL.
231 static PathEntryPtr
232 FindPathEntry(CommandLineInterfacePtr cli, STRPTR pathName,
233 PathEntryPtr* predStorage, APTR DOSBase)
235 PathEntryPtr
236 entry = NULL;
238 if (NULL != cli && BNULL != cli->cli_CommandDir && NULL != pathName)
240 BPTR
241 pathLock = Lock(pathName, ACCESS_READ);
243 if (BNULL != pathLock)
245 PathEntryPtr
246 pred = NULL,
247 curr = PE(cli->cli_CommandDir);
249 while (NULL != curr)
251 LONG
252 value = SameLock(pathLock, curr->lock);
254 if (LOCK_SAME == value)
256 entry = curr;
258 if (NULL != predStorage)
260 *predStorage = pred;
262 break;
264 else
266 pred = curr;
267 curr = PE(curr->next);
271 UnLock(pathLock);
273 else
274 PrintFault(IoErr(), pathName);
277 return(entry);
281 /* insert a path entry for the specified path
283 * create and insert a path entry for the specified path name. the new path
284 * entry is inserted after the specified predecessor.
286 * returns the path entry or NULL for failure.
288 static PathEntryPtr
289 InsertPathEntry(PathEntryPtr predecessor, STRPTR pathName, APTR SysBase, APTR DOSBase)
291 PathEntryPtr
292 pathEntry = NULL;
295 PathEntryPtr
296 newEntry = AllocVec(sizeof(PathEntry), MEMF_ANY);
298 BPTR
299 lock = Lock(pathName, SHARED_LOCK);
301 BOOL
302 isDirectory = (BNULL != lock)
303 ? IsDirectory(lock, DOSBase)
304 : FALSE;
306 if (newEntry != NULL && lock != BNULL && isDirectory)
308 newEntry->lock = lock;
309 newEntry->next = predecessor->next;
311 predecessor->next = MKBADDR(newEntry);
313 pathEntry = newEntry;
315 else
317 if (lock != BNULL)
319 if (!isDirectory)
321 PrintFault(ERROR_OBJECT_WRONG_TYPE, pathName);
324 UnLock(lock);
327 if (newEntry != NULL)
329 FreeVec(newEntry);
334 return(pathEntry);
338 /* check if the object specified is a directory */
339 static BOOL
340 IsDirectory(BPTR lock, APTR DOSBase)
342 BOOL
343 isDirectory = FALSE;
345 struct FileInfoBlock*
346 fib = AllocDosObject(DOS_FIB, NULL);
348 if (Examine(lock, fib))
350 LONG
351 entryType = fib->fib_EntryType;
353 if (entryType >= ST_ROOT && entryType <= ST_LINKDIR)
355 if (entryType != ST_SOFTLINK)
357 isDirectory = TRUE;
359 else
361 BPTR
362 dupLock = DupLock(lock);
364 if (BNULL != dupLock)
366 BPTR
367 file = OpenFromLock(dupLock);
369 if (BNULL != file)
371 /* lock was on a file. dupLock is relinquished by OpenFromLock */
372 Close(file);
374 isDirectory = FALSE;
376 else
378 UnLock(dupLock);
381 else
383 isDirectory = FALSE;
388 FreeDosObject(DOS_FIB, fib);
391 return(isDirectory);