revert between 56095 -> 55830 in arch
[AROS.git] / workbench / c / shellcommands / Resident.c
blob3c2bb68c3461c1a0d33d0e7dfc6fc4120d26ebf2
1 /*
2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Resident CLI command
6 Lang: English
7 */
9 /******************************************************************************
12 NAME
14 Resident
16 SYNOPSIS
18 NAME,FILE,REMOVE/S,ADD/S,REPLACE/S,PURE=FORCE/S,SYSTEM/S
20 LOCATION
24 FUNCTION
26 Handles list of resident commands. Those commands will be
27 loaded once and then executed from memory.
29 Only pure commands can be made resident, i.e. they must
30 be re-entrant and re-executable. Such commands have the "P"
31 protection flag set.
33 If called without arguments it lists the resident commands.
35 INPUTS
37 NAME -- The reference name of the resident command. If no
38 name is given the filepart of the file argument
39 is used.
40 FILE -- The file name of the command. It must be an
41 absolute path.
42 REMOVE -- Deactivates a resident command.
43 ADD -- Adds multiple versions of the same command.
44 REPLACE -- If a resident command already exists, it will be
45 replaced. That's the default option.
46 FORCE -- Add commands which don't have the "P" bit set.
47 SYSTEM -- Adds a command to the system resident list. Those
48 commands can't be removed.
50 RESULT
52 NOTES
54 EXAMPLE
56 RESIDENT C:COPY
58 BUGS
60 SEE ALSO
62 INTERNALS
64 HISTORY
66 ******************************************************************************/
68 #include <proto/dos.h>
69 #include <dos/dosextens.h>
70 #include <string.h>
71 #include <exec/lists.h>
72 #include <exec/nodes.h>
73 #include <exec/memory.h>
75 #include <string.h>
77 #include <aros/shcommands.h>
79 struct SegNode
81 struct MinNode node;
82 IPTR data[2];
85 static struct SegNode *NewSegNode(struct ExecBase *SysBase, STRPTR name, LONG uc);
87 AROS_SH7(Resident, 41.2,
88 AROS_SHA(STRPTR, ,NAME, ,NULL),
89 AROS_SHA(STRPTR, ,FILE, ,NULL),
90 AROS_SHA(BOOL, ,REMOVE,/S,FALSE),
91 AROS_SHA(BOOL, ,ADD,/S,FALSE),
92 AROS_SHA(BOOL, ,REPLACE,/S,FALSE),
93 AROS_SHA(BOOL,PURE=,FORCE,/S,FALSE),
94 AROS_SHA(BOOL, ,SYSTEM,/S,FALSE))
96 AROS_SHCOMMAND_INIT
99 if (SHArg(FILE) || SHArg(NAME))
101 STRPTR name, file;
102 BPTR seglist;
103 struct FileInfoBlock *fib;
105 if (SHArg(FILE))
107 name = SHArg(NAME);
108 file = SHArg(FILE);
110 else
112 name = FilePart(SHArg(NAME));
113 file = SHArg(NAME);
116 SetIoErr(0);
117 if (SHArg(REMOVE))
119 struct Segment *found;
121 Forbid();
122 found = FindSegment(name, NULL, FALSE);
123 if (!found)
124 found = FindSegment(name, NULL, TRUE);
125 if (!found)
127 Permit();
128 SetIoErr(ERROR_OBJECT_NOT_FOUND);
130 else
131 if (!RemSegment(found))
133 if (found->seg_UC == CMD_INTERNAL)
134 found->seg_UC = CMD_DISABLED;
135 else
136 SetIoErr(ERROR_OBJECT_IN_USE);
139 if (IoErr())
141 PrintFault(IoErr(), SHArg(NAME));
142 return RETURN_WARN;
145 return RETURN_OK;
148 if (SHArg(REPLACE))
150 struct Segment *found;
152 Forbid();
153 found = FindSegment(name, NULL, TRUE);
154 if (found && found->seg_UC == CMD_DISABLED)
156 found->seg_UC = CMD_INTERNAL;
157 Permit();
158 return RETURN_OK;
160 Permit();
163 if (!SHArg(ADD)) SHArg(REPLACE) = TRUE;
165 if (!SHArg(FORCE) && (fib = (struct FileInfoBlock *)AllocDosObject(DOS_FIB, NULL)))
167 BPTR lock;
169 if ((lock = Lock(file, SHARED_LOCK)))
171 if (Examine(lock, fib))
173 if ((fib->fib_Protection & FIBF_PURE) == 0)
174 SetIoErr(ERROR_OBJECT_WRONG_TYPE);
177 UnLock(lock);
180 FreeDosObject(DOS_FIB, fib);
183 if (IoErr() || !(seglist = LoadSeg(file)))
185 PrintFault(IoErr(), file);
186 return RETURN_FAIL;
189 if (SHArg(REPLACE))
191 struct Segment *found;
193 Forbid();
194 found = FindSegment(name, NULL, FALSE);
196 if (found)
198 if (found->seg_UC != 0)
200 Permit();
201 PrintFault(ERROR_OBJECT_IN_USE, file);
202 UnLoadSeg(seglist);
203 return RETURN_FAIL;
206 UnLoadSeg(found->seg_Seg);
207 found->seg_Seg = seglist;
208 Permit();
210 return RETURN_OK;
212 /* Fall through */
215 /* WB1.x backwards compatibility hack, do not allow
216 * override of built-in resident or to add l:shell-seg (CLI) */
217 if (!stricmp(name, "resident") || !stricmp(name, "cli")) {
218 SetIoErr(ERROR_OBJECT_WRONG_TYPE);
219 UnLoadSeg(seglist);
220 return 1; /* yes, return code = 1 in this special case */
223 if (!AddSegment(name, seglist, SHArg(SYSTEM)?CMD_SYSTEM:0))
225 UnLoadSeg(seglist);
226 PrintFault(IoErr(), "Resident");
227 return RETURN_FAIL;
230 else
233 struct MinList l;
234 struct Segment *curr;
235 struct SegNode *n;
236 struct DosInfo *dinf = BADDR(DOSBase->dl_Root->rn_Info);
237 BOOL isbreak = FALSE;
239 NEWLIST((struct List *)&l);
241 SetIoErr(0);
242 Forbid();
243 curr = (struct Segment *)BADDR(dinf->di_ResList);
244 while (curr)
246 n = NewSegNode(SysBase, AROS_BSTR_ADDR(MKBADDR(&curr->seg_Name[0])), curr->seg_UC);
248 if (!n)
250 SetIoErr(ERROR_NO_FREE_STORE);
251 break;
254 AddTail((struct List *)&l, (struct Node *)n);
255 curr = (struct Segment *)BADDR(curr->seg_Next);
257 Permit();
259 if (IoErr())
261 PrintFault(IoErr(), "Resident");
262 return RETURN_FAIL;
265 PutStr("NAME USECOUNT\n\n");
266 while ((n = (struct SegNode *)RemHead((struct List *)&l)))
268 if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
269 isbreak = TRUE;
270 if (!isbreak) {
271 if (n->data[1] == CMD_SYSTEM)
272 Printf("%-30s SYSTEM\n", (CONST_STRPTR)n->data[0]);
273 else
274 if (n->data[1] == CMD_INTERNAL)
275 Printf("%-30s INTERNAL\n", (CONST_STRPTR)n->data[0]);
276 else
277 if (n->data[1] == CMD_DISABLED)
278 Printf("%-30s DISABLED\n", (CONST_STRPTR)n->data[0]);
279 else
280 Printf("%-30s %-ld\n", (CONST_STRPTR)n->data[0], (ULONG)n->data[1]);
282 FreeVec((APTR)n->data[0]);
283 FreeVec(n);
285 if (isbreak) {
286 SetIoErr(ERROR_BREAK);
287 PrintFault(IoErr(), "Resident");
288 return RETURN_FAIL;
292 return RETURN_OK;
294 AROS_SHCOMMAND_EXIT
297 static STRPTR myStrDup(struct ExecBase *SysBase, STRPTR str)
299 size_t len = strlen(str)+1;
300 STRPTR ret = (STRPTR) AllocVec(len, MEMF_ANY);
302 if (ret)
304 CopyMem(str, ret, len);
307 return ret;
311 static struct SegNode *NewSegNode(struct ExecBase *SysBase, STRPTR name,
312 LONG uc)
314 struct SegNode *sn = AllocVec(sizeof (struct SegNode), MEMF_ANY);
316 if (sn)
318 sn->data[0] = (IPTR) myStrDup(SysBase, name);
319 if (sn->data[0])
321 sn->data[1] = uc;
322 return sn;
325 FreeVec(sn);
328 return NULL;