grub2: bring back build of aros-side grub2 tools
[AROS.git] / workbench / c / shellcommands / Resident.c
blob076ee0309bc500bcb4ce4f2a1d534e8e1f098376
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, TRUE);
123 if (!found)
125 Permit();
126 SetIoErr(ERROR_OBJECT_NOT_FOUND);
128 else
129 if (!RemSegment(found))
131 if (found->seg_UC == CMD_INTERNAL)
132 found->seg_UC = CMD_DISABLED;
133 else
134 SetIoErr(ERROR_OBJECT_IN_USE);
137 if (IoErr())
139 PrintFault(IoErr(), SHArg(NAME));
140 return RETURN_FAIL;
143 return RETURN_OK;
146 if (SHArg(REPLACE))
148 struct Segment *found;
150 Forbid();
151 found = FindSegment(name, NULL, TRUE);
152 if (found && found->seg_UC == CMD_DISABLED)
154 found->seg_UC = CMD_INTERNAL;
155 Permit();
156 return RETURN_OK;
158 Permit();
161 if (!SHArg(ADD)) SHArg(REPLACE) = TRUE;
163 if (!SHArg(FORCE) && (fib = (struct FileInfoBlock *)AllocDosObject(DOS_FIB, NULL)))
165 BPTR lock;
167 if ((lock = Lock(file, SHARED_LOCK)))
169 if (Examine(lock, fib))
171 if ((fib->fib_Protection & FIBF_PURE) == 0)
172 SetIoErr(ERROR_OBJECT_WRONG_TYPE);
175 UnLock(lock);
178 FreeDosObject(DOS_FIB, fib);
181 if (IoErr() || !(seglist = LoadSeg(file)))
183 PrintFault(IoErr(), file);
184 return RETURN_FAIL;
187 if (SHArg(REPLACE))
189 struct Segment *found;
191 Forbid();
192 found = FindSegment(name, NULL, FALSE);
194 if (found)
196 if (found->seg_UC != 0)
198 Permit();
199 PrintFault(ERROR_OBJECT_IN_USE, file);
200 UnLoadSeg(seglist);
201 return RETURN_FAIL;
204 UnLoadSeg(found->seg_Seg);
205 found->seg_Seg = seglist;
206 Permit();
208 return RETURN_OK;
210 /* Fall through */
213 /* WB1.x backwards compatibility hack, do not allow
214 * override of built-in resident or to add l:shell-seg (CLI) */
215 if (!stricmp(name, "resident") || !stricmp(name, "cli")) {
216 SetIoErr(ERROR_OBJECT_WRONG_TYPE);
217 UnLoadSeg(seglist);
218 return 1; /* yes, return code = 1 in this special case */
221 if (!AddSegment(name, seglist, SHArg(SYSTEM)?CMD_SYSTEM:0))
223 UnLoadSeg(seglist);
224 PrintFault(IoErr(), "Resident");
225 return RETURN_FAIL;
228 else
231 struct MinList l;
232 struct Segment *curr;
233 struct SegNode *n;
234 struct DosInfo *dinf = BADDR(DOSBase->dl_Root->rn_Info);
235 BOOL isbreak = FALSE;
237 NEWLIST((struct List *)&l);
239 SetIoErr(0);
240 Forbid();
241 curr = (struct Segment *)BADDR(dinf->di_ResList);
242 while (curr)
244 n = NewSegNode(SysBase, AROS_BSTR_ADDR(MKBADDR(&curr->seg_Name[0])), curr->seg_UC);
246 if (!n)
248 SetIoErr(ERROR_NO_FREE_STORE);
249 break;
252 AddTail((struct List *)&l, (struct Node *)n);
253 curr = (struct Segment *)BADDR(curr->seg_Next);
255 Permit();
257 if (IoErr())
259 PrintFault(IoErr(), "Resident");
260 return RETURN_FAIL;
263 PutStr("NAME USECOUNT\n\n");
264 while ((n = (struct SegNode *)RemHead((struct List *)&l)))
266 if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
267 isbreak = TRUE;
268 if (!isbreak) {
269 if (n->data[1] == CMD_SYSTEM)
270 Printf("%-30s SYSTEM\n", (CONST_STRPTR)n->data[0]);
271 else
272 if (n->data[1] == CMD_INTERNAL)
273 Printf("%-30s INTERNAL\n", (CONST_STRPTR)n->data[0]);
274 else
275 if (n->data[1] == CMD_DISABLED)
276 Printf("%-30s DISABLED\n", (CONST_STRPTR)n->data[0]);
277 else
278 Printf("%-30s %-ld\n", (CONST_STRPTR)n->data[0], (ULONG)n->data[1]);
280 FreeVec((APTR)n->data[0]);
281 FreeVec(n);
283 if (isbreak) {
284 SetIoErr(ERROR_BREAK);
285 PrintFault(IoErr(), "Resident");
286 return RETURN_FAIL;
290 return RETURN_OK;
292 AROS_SHCOMMAND_EXIT
295 static STRPTR myStrDup(struct ExecBase *SysBase, STRPTR str)
297 size_t len = strlen(str)+1;
298 STRPTR ret = (STRPTR) AllocVec(len, MEMF_ANY);
300 if (ret)
302 CopyMem(str, ret, len);
305 return ret;
309 static struct SegNode *NewSegNode(struct ExecBase *SysBase, STRPTR name,
310 LONG uc)
312 struct SegNode *sn = AllocVec(sizeof (struct SegNode), MEMF_ANY);
314 if (sn)
316 sn->data[0] = (IPTR) myStrDup(SysBase, name);
317 if (sn->data[0])
319 sn->data[1] = uc;
320 return sn;
323 FreeVec(sn);
326 return NULL;