Resident Segments¶
AmigaDOS keeps a list of resident segments: loaded seglists registered under a name, so that the Shell can run a command without loading it from disk and system components can find each other's code. Resident commands made with the Resident command, the Shell's built-in commands, the ROM handlers and the Shell itself all live on this list. It is a DOS structure (struct Segment, dos/dosextens.h) and has nothing to do with exec's ROMTag list in SysBase->ResModules (struct Resident), even though the purpose is similar.
The functions are FindSegment(), AddSegment() and RemSegment() (V36). There is no locking: the list must be used under Forbid().
How segments get on the list¶
| Source | Entry type (seg_UC) |
|---|---|
Resident command on a file with the p (pure) bit |
1 (unused user segment) |
Shell: a command with p and h (hold) set is made resident the first time it runs (V39, removed in V40, back in V45) |
1 |
Shell built-in commands (CD, Execute, …) added when the Shell starts |
CMD_INTERNAL |
System-Startup: FileHandler (FFS), CON-Handler, RAM-Handler |
CMD_SYSTEM |
System-Startup: the Shell as shell, BootShell and CLI |
system entries |
The p bit claims the code is re-entrant and can run in several processes at once. AmigaDOS does not check this; a wrongly flagged command will crash when two shells run it.
The three shell entries¶
| Name | Use |
|---|---|
shell |
Default user shell: Shell icon, NewShell, Run, System() with SYS_UserShell. May be replaced by a custom shell. |
BootShell |
The shell that booted the system; used by System() by default and always by Execute(). Leave it alone. |
CLI |
Same shell with BCPL binding; legacy, used only if requested with SYS_CustomShell. |
To install a custom shell as the user shell:
Resident shell MyShell REPLACE SYSTEM
See Shell Internals for how such a shell must start.
struct Segment¶
struct Segment {
BPTR seg_Next; /* next segment, ZERO at the end */
LONG seg_UC; /* use count or type */
BPTR seg_Seg; /* the seglist, as from LoadSeg() */
UBYTE seg_Name[4]; /* BSTR name, really variable length */
};
Never allocate one yourself; AddSegment() builds it. seg_Name is a BSTR of any length, not 4 characters. seg_Next must not be modified.
seg_UC¶
| Value | Constant | Meaning | Found by the Shell |
|---|---|---|---|
| 1 | Disk-based command, not in use | yes | |
| > 1 | In use by seg_UC − 1 users; cannot be removed |
yes | |
| −1 | CMD_SYSTEM |
System component (handler, file system); not executable | no |
| −2 | CMD_INTERNAL |
Shell built-in, code in ROM | yes |
| ≤ −999 | CMD_DISABLED |
Disabled system or built-in entry (what Resident REMOVE does to them) |
no |
An unused user segment has seg_UC = 1, not 0. The Shell increments the count when it starts a resident command and decrements it when the command ends. The Resident command prints seg_UC − 1, so it shows 0 for an idle command.
FindSegment¶
struct Segment *FindSegment(CONST_STRPTR name, CONST struct Segment *seg, LONG system); /* V36 */
- Case-insensitive search for
name, from the start of the list (seg= NULL) or afterseg(to find further entries of the same name). system= FALSE finds only user entries (seg_UC> 0);system= TRUE finds only entries with negativeseg_UC, including disabled ones: filterCMD_DISABLEDyourself.- Returns a
struct Segment *(a real pointer), not a seglist BPTR. - Does not increment
seg_UC. Call it underForbid()and incrementseg_UCof a user segment beforePermit(). System entries cannot go away (they can only be disabled), so they need no count. - Sets
IoErr()toERROR_OBJECT_NOT_FOUNDwhen nothing matches; leaves it alone on success.
/* Use a resident command if one is there. */
struct Segment *seg;
BPTR code = 0;
Forbid();
seg = FindSegment("MyTool", NULL, FALSE);
if (seg) {
seg->seg_UC++; /* keep it from being removed */
code = seg->seg_Seg;
}
Permit();
if (code) {
LONG rc = RunCommand(code, 8192, "\n", 1);
Forbid();
seg->seg_UC--; /* release our use */
Permit();
}
AddSegment¶
LONG AddSegment(CONST_STRPTR name, BPTR seg, LONG system); /* V36; BOOL result */
Adds seg under a copy of name; seg_UC is set to the third argument.
| Third argument | For |
|---|---|
| 1 | A pure command made resident |
CMD_SYSTEM 2.0+ |
A non-command system segment. It can never be safely unloaded and stays for the life of the system. |
CMD_INTERNAL 2.0+ |
Only for the ROM Shell's built-ins |
CMD_DISABLED 2.0+ |
Only used by Resident when removing system or internal entries |
Returns non-zero on success (IoErr() untouched); DOSFALSE with ERROR_NO_FREE_STORE on failure. The seglist now belongs to the list.
Note: the NDK 3.2 autodoc says the type is "normally 0"; neither the Shell nor the
Residentcommand uses 0.
/* Make C:MyTool resident, like "Resident C:MyTool". */
BPTR seglist = LoadSeg("C:MyTool");
if (seglist && !AddSegment("MyTool", seglist, 1)) {
PrintFault(IoErr(), "AddSegment");
UnLoadSeg(seglist);
}
RemSegment¶
LONG RemSegment(struct Segment *seg); /* V36; BOOL result */
Removes a user segment and unloads its seglist with UnLoadSeg(), releasing all its resources. It fails with DOSFALSE and ERROR_OBJECT_IN_USE for a system or internal segment, or for a user segment that is in use (seg_UC > 1).
Another process may remove the same segment at the same time, so find and remove it in one Forbid():
struct Segment *seg;
LONG ok = DOSFALSE;
Forbid();
if ((seg = FindSegment("MyTool", NULL, FALSE)) != NULL)
ok = RemSegment(seg);
Permit();
Because of a defect in the current dos.library, RemSegment() sets IoErr() to ERROR_OBJECT_IN_USE even on success: test the return value, not IoErr().
Note: the NDK 3.2 autodoc says RemSegment() "will only succeed if the seg_UC (usecount) is 0".
Where the list is¶
The head of the list is in DosInfo.di_NetHand, which is really a BPTR to the first Segment. di_McName (alias di_ResList) is not used. Programs should not walk the list through either field; use FindSegment(). See AmigaDOS Library Internals.
Note: the NDK 3.2
dos/dosextens.hcommentsdi_McNameas "system resident module list" anddi_NetHandas "Network handler processid; currently zero".
See Also¶
- Shell Internals
- The AmigaDOS Shell
- AmigaDOS Library Internals
- Hunk Binary Format
- dos.library (autodoc)
Sources: Thomas Richter, Amiga ROM Kernel Reference Manual: AmigaDOS (2024, v1.27), §15.6 (pp. 346–349), §15.7 (p. 349), §17.3 (p. 369); NDK 3.2 R4 Include_H/dos/dosextens.h; Autodocs/dos.doc (AddSegment, RemSegment, FindSegment); SFD/dos_lib.sfd Updated: 2026-11-13