home *** CD-ROM | disk | FTP | other *** search
- /************************************************************
- * MultiUser - MultiUser Task/File Support System *
- * --------------------------------------------------------- *
- * Task Management Routines *
- * --------------------------------------------------------- *
- * © Copyright 1993-1994 Geert Uytterhoeven *
- * All Rights Reserved. *
- ************************************************************/
-
-
- #include <exec/execbase.h>
- #include <exec/alerts.h>
- #include <intuition/intuitionbase.h>
- #include <proto/exec.h>
- #include <proto/dos.h>
- #include <proto/intuition.h>
-
- #include "Memory.h"
- #include "Task.h"
- #include "Config.h"
- #include "Misc.h"
- #include "Locale.h"
- #include "LibHeader.h"
- #include "Monitor.h"
- #include "UserInfo.h"
-
-
- /*
- * Static Routines
- */
-
- static struct muTaskLevel *AllocTaskLevel(struct muExtOwner *owner);
- static void FreeTaskLevel(struct muTaskLevel *level);
- static struct muTaskNode *AllocTaskNode(struct Task *task, ULONG defprotection);
- static void FreeTaskNode(struct muTaskNode *node);
- static struct muTaskNode *FindTaskNode(struct Task *task);
- static void AddTaskLevel(struct muTaskLevel *level, struct muTaskLevel *dest);
- static void RemTaskLevel(struct muTaskLevel *level);
- static void MoveTaskLevel(struct muTaskLevel *level, struct muTaskLevel *dest);
- static void MoveAll(struct muTaskLevel *source, struct muTaskLevel *dest);
- static void AddTaskNode(struct muTaskNode *node, struct muTaskLevel *dest);
- static void RemTaskNode(struct muTaskNode *node);
- static void MoveTaskNode(struct muTaskNode *node, struct muTaskLevel *dest);
- static void CleanUpTaskLevel(struct muTaskLevel *level);
- static void __saveds CleanUpBody(void);
-
-
- /*
- * Extended Owner Information Structure for root
- */
-
- struct muExtOwner RootExtOwner = {
- muROOT_UID, muROOT_GID, 0
- };
-
-
- /*
- * Allocate a Task Level
- */
-
- static struct muTaskLevel *AllocTaskLevel(struct muExtOwner *owner)
- {
- struct muTaskLevel *level;
- ULONG size;
-
- size = sizeof(struct muTaskLevel);
- if (owner)
- size += owner->NumSecGroups*sizeof(UWORD);
- if (level = MAlloc(size)) {
- NewList((struct List *)&level->Tasks);
- NewList((struct List *)&level->Children);
- if (owner)
- CopyMem(owner, &level->Owner, size-sizeof(struct muTaskLevel)+sizeof(struct muExtOwner));
- }
- return(level);
- }
-
-
- /*
- * Deallocate a Task Level
- */
-
- static void __inline FreeTaskLevel(struct muTaskLevel *level)
- {
- Free(level, sizeof(struct muTaskLevel)+level->Owner.NumSecGroups*sizeof(UWORD));
- }
-
-
- /*
- * Allocate a Task Node
- *
- * Make sure you have access to the list (via ObtainSemaphore(Shared))!!
- */
-
- static struct muTaskNode *AllocTaskNode(struct Task *task, ULONG defprotection)
- {
- struct muTaskNode *node;
-
- if (node = MAlloc(sizeof(struct muTaskNode))) {
- node->Task = task;
- node->DefProtection = defprotection;
- }
- return(node);
- }
-
-
- /*
- * Deallocate a Task Node
- *
- * Make sure you have access to the list (via ObtainSemaphore(Shared))!!
- */
-
- static void __inline FreeTaskNode(struct muTaskNode *node)
- {
- Free(node, sizeof(struct muTaskNode));
- }
-
-
- /*
- * Find the Task Node for a given Task
- *
- * Make sure you have access to the list (via ObtainSemaphore(Shared))!!
- */
-
- static struct muTaskNode *FindTaskNode(struct Task *task)
- {
- struct MinNode *node;
- struct muTaskNode *tnode;
-
- for (node = muBase->TaskOwnerList[(ULONG)task%TASKHASHVALUE].mlh_Head;
- (node->mln_Succ &&
- ((tnode = (struct muTaskNode *)((ULONG)node-
- (ULONG)&((struct muTaskNode *)NULL)->ListNode))->Task != task));
- node = node->mln_Succ);
- return(node->mln_Succ ? tnode : NULL);
- }
-
-
- /*
- * Add a Task Level
- *
- * Make sure you have access to the list (via ObtainSemaphore(Shared))!!
- */
-
- static void AddTaskLevel(struct muTaskLevel *level, struct muTaskLevel *dest)
- {
- AddHead((struct List *)&dest->Children, (struct Node *)&level->Node);
- level->Parent = dest;
- }
-
-
- /*
- * Remove a Task Level
- *
- * Make sure you have access to the list (via ObtainSemaphore(Shared))!!
- */
-
- static void __inline RemTaskLevel(struct muTaskLevel *level)
- {
- Remove((struct Node *)&level->Node);
- }
-
-
- /*
- * Move a Task Level to another Task Level
- */
-
- static void MoveTaskLevel(struct muTaskLevel *level, struct muTaskLevel *dest)
- {
- Remove((struct Node *)&level->Node);
- AddHead((struct List *)&dest->Children, (struct Node *)&level->Node);
- level->Parent = dest;
- }
-
-
- /*
- * Move all TaskNodes and TaskLevels to another Task Level
- */
-
- static void MoveAll(struct muTaskLevel *source, struct muTaskLevel *dest)
- {
- struct muTaskNode *node;
- struct muTaskLevel *level;
-
- while ((node = (struct muTaskNode *)source->Tasks.mlh_Head) && node->LevelNode.mln_Succ)
- MoveTaskNode(node, dest);
- while ((level = (struct muTaskLevel *)source->Children.mlh_Head) && level->Node.mln_Succ)
- MoveTaskLevel(level, dest);
- }
-
-
- /*
- * Add a Task Node to a Task Level
- *
- * Make sure you have access to the list (via ObtainSemaphore(Shared))!!
- */
-
- static void AddTaskNode(struct muTaskNode *node, struct muTaskLevel *dest)
- {
- AddHead((struct List *)&dest->Tasks, (struct Node *)&node->LevelNode);
- AddHead((struct List *)&muBase->TaskOwnerList[(ULONG)node->Task%TASKHASHVALUE],
- (struct Node *)&node->ListNode);
- node->Level = dest;
- CallMonitors(muTrgB_OwnerChange, muNOBODY_UID, dest->Owner.uid, NULL);
- }
-
-
- /*
- * Remove a Task Node from a Task Level
- *
- * Make sure you have access to the list (via ObtainSemaphore(Shared))!!
- */
-
- static void __inline RemTaskNode(struct muTaskNode *node)
- {
- Remove((struct Node *)&node->LevelNode);
- Remove((struct Node *)&node->ListNode);
- CallMonitors(muTrgB_OwnerChange, node->Level->Owner.uid, muNOBODY_UID, NULL);
- }
-
-
- /*
- * Move a Task Node to another TaskLevel
- *
- * Make sure you have access to the list (via ObtainSemaphore(Shared))!!
- */
-
- static void MoveTaskNode(struct muTaskNode *node, struct muTaskLevel *dest)
- {
- Remove((struct Node *)&node->LevelNode);
- AddHead((struct List *)&dest->Tasks, (struct Node *)&node->LevelNode);
- node->Level = dest;
- CallMonitors(muTrgB_OwnerChange, node->Level->Owner.uid, dest->Owner.uid, NULL);
- }
-
-
- /*
- * Clean Up a Task Level
- *
- * Make sure you have access to the list (via ObtainSemaphore(Shared))!!
- */
-
- static void CleanUpTaskLevel(struct muTaskLevel *level)
- {
- struct muTaskLevel *parent;
-
- while (level && IsListEmpty((struct List *)&level->Tasks) &&
- IsListEmpty((struct List *)&level->Children)) {
- if (parent = level->Parent)
- RemTaskLevel(level);
- FreeTaskLevel(level);
- level = parent;
- };
- }
-
-
- /*
- * Init Task List
- */
-
- void InitTaskList(void)
- {
- ULONG i;
-
- ObtainSemaphore(&muBase->TaskOwnerSem);
- for (i = 0; i < TASKHASHVALUE; i++)
- NewList((struct List *)&muBase->TaskOwnerList[i]);
- ReleaseSemaphore(&muBase->TaskOwnerSem);
- }
-
-
- /*
- * Create an Orphan Task Node
- */
-
- struct muTaskNode *CreateOrphanTask(struct Task *task, ULONG defprotection)
- {
- struct muTaskLevel *level;
- struct muTaskNode *node;
-
- ObtainSemaphore(&muBase->TaskOwnerSem);
- if (level = AllocTaskLevel(NULL))
- if (node = AllocTaskNode(task, defprotection))
- AddTaskNode(node, level);
- else
- FreeTaskLevel(level);
- ReleaseSemaphore(&muBase->TaskOwnerSem);
- return(node);
- }
-
-
- /*
- * Remove all Task Nodes
- */
-
- void RemAllTaskNodes(void)
- {
- struct muTaskNode *node;
- struct muTaskLevel *level;
- ULONG i;
-
- ObtainSemaphore(&muBase->TaskOwnerSem);
- for (i = 0; i < TASKHASHVALUE; i++)
- while ((node = (struct muTaskNode *)muBase->TaskOwnerList[i].mlh_Head) && node->ListNode.mln_Succ) {
- level = node->Level;
- RemTaskNode(node);
- FreeTaskNode(node);
- CleanUpTaskLevel(level);
- }
- ReleaseSemaphore(&muBase->TaskOwnerSem);
- }
-
-
- /*
- * Push a Task to a new Owner
- */
-
- BOOL PushTask(struct Task *task, struct muExtOwner *owner)
- {
- BOOL res = FALSE;
- struct muTaskNode *node;
- struct muTaskLevel *child, *parent;
-
- ObtainSemaphore(&muBase->TaskOwnerSem);
- if ((node = FindTaskNode(task)) || (node = CreateOrphanTask(task, DEFPROTECTION))) {
- parent = node->Level;
- if (child = AllocTaskLevel(owner)) {
- MoveTaskNode(node, child);
- AddTaskLevel(child, parent);
- res = TRUE;
- }
- }
- ReleaseSemaphore(&muBase->TaskOwnerSem);
- return(res);
- }
-
-
- /*
- * Push a Task Level to a new Owner
- */
-
- BOOL PushTaskLevel(struct Task *task, struct muExtOwner *owner)
- {
- BOOL res = FALSE;
- struct muTaskNode *node;
- struct muTaskLevel *child, *parent;
-
- ObtainSemaphore(&muBase->TaskOwnerSem);
- if ((node = FindTaskNode(task)) || (node = CreateOrphanTask(task, DEFPROTECTION))) {
- parent = node->Level;
- if (child = AllocTaskLevel(owner)) {
- MoveAll(parent, child);
- AddTaskLevel(child, parent);
- res = TRUE;
- }
- }
- ReleaseSemaphore(&muBase->TaskOwnerSem);
- return(res);
- }
-
-
- /*
- * Pop a Task to the previous Owner
- */
-
- BOOL PopTask(struct Task *task)
- {
- BOOL res = FALSE;
- struct muTaskNode *node;
- struct muTaskLevel *child, *parent;
-
- ObtainSemaphore(&muBase->TaskOwnerSem);
- if (node = FindTaskNode(task)) {
- child = node->Level;
- if (parent = child->Parent) {
- MoveTaskNode(node, parent);
- CleanUpTaskLevel(child);
- if (parent->Parent)
- res = TRUE;
- }
- } else
- CreateOrphanTask(task, DEFPROTECTION);
- ReleaseSemaphore(&muBase->TaskOwnerSem);
- return(res);
- }
-
-
- /*
- * Pop a Task to the previous Owner and Detach when the Root of the Tree is reached
- */
-
- BOOL PopTaskDetach(struct Task *task)
- {
- BOOL res = FALSE;
- struct muTaskNode *node;
- struct muTaskLevel *child, *parent;
-
- ObtainSemaphore(&muBase->TaskOwnerSem);
- if (node = FindTaskNode(task)) {
- child = node->Level;
- if ((parent = child->Parent) && parent->Parent) {
- MoveTaskNode(node, parent);
- CleanUpTaskLevel(child);
- res = TRUE;
- } else if (parent = AllocTaskLevel(NULL)) {
- MoveTaskNode(node, parent);
- CleanUpTaskLevel(child);
- }
- } else
- CreateOrphanTask(task, DEFPROTECTION);
- ReleaseSemaphore(&muBase->TaskOwnerSem);
- return(res);
- }
-
-
- /*
- * Pop a Task Level to the previous Owner and Detach when the Root of the Tree is reached
- */
-
- BOOL PopTaskLevelDetach(struct Task *task)
- {
- BOOL res = FALSE;
- struct muTaskNode *node;
- struct muTaskLevel *child, *parent;
-
- ObtainSemaphore(&muBase->TaskOwnerSem);
- if (node = FindTaskNode(task)) {
- child = node->Level;
- if ((parent = child->Parent) && parent->Parent) {
- MoveAll(child, parent);
- CleanUpTaskLevel(child);
- res = TRUE;
- } else if (parent = AllocTaskLevel(NULL)) {
- MoveAll(child, parent);
- CleanUpTaskLevel(child);
- }
- } else
- CreateOrphanTask(task, DEFPROTECTION);
- ReleaseSemaphore(&muBase->TaskOwnerSem);
- return(res);
- }
-
-
- /*
- * Get the Owner (uid:gid) of a Task
- */
-
- ULONG GetTaskOwner(struct Task *task)
- {
- ULONG owner = muOWNER_NOBODY;
- struct muTaskNode *node;
-
- if (!muBase->SecurityViolation) {
- ObtainSemaphoreShared(&muBase->TaskOwnerSem);
- if (node = FindTaskNode(task))
- owner = muExtOwner2ULONG(&node->Level->Owner);
- ReleaseSemaphore(&muBase->TaskOwnerSem);
- }
- return(owner);
- }
-
-
- /*
- * Get the Owner (struct muExtOwner *) of a Task
- */
-
- struct muExtOwner *GetTaskExtOwner(struct Task *task)
- {
- struct muExtOwner *owner = NULL;
- struct muTaskNode *node;
- ULONG size;
-
- if (!muBase->SecurityViolation) {
- ObtainSemaphoreShared(&muBase->TaskOwnerSem);
- if (node = FindTaskNode(task)) {
- size = sizeof(struct muExtOwner)+node->Level->Owner.NumSecGroups*sizeof(UWORD);
- if (owner = (struct muExtOwner *)MAlloc(size))
- CopyMem(&node->Level->Owner, owner, size);
- }
- ReleaseSemaphore(&muBase->TaskOwnerSem);
- }
- return(owner);
- }
-
-
- /*
- * Get the Default Protection Bits for a Task
- */
-
- ULONG GetTaskDefProtect(struct Task *task)
- {
- ULONG defprotection = DEFPROTECTION;
- struct muTaskNode *node;
-
- ObtainSemaphoreShared(&muBase->TaskOwnerSem);
- if (node = FindTaskNode(task))
- defprotection = node->DefProtection;
- ReleaseSemaphore(&muBase->TaskOwnerSem);
- return(defprotection);
- }
-
-
- /*
- * Set the Default Protection Bits for a Task
- */
-
- BOOL SetTaskDefProtect(struct Task *task, ULONG defprotection)
- {
- BOOL result;
- struct muTaskNode *node;
-
- ObtainSemaphore(&muBase->TaskOwnerSem);
- if (node = FindTaskNode(task)) {
- node->DefProtection = defprotection;
- result = TRUE;
- } else
- result = (BOOL)CreateOrphanTask(task, defprotection);
- ReleaseSemaphore(&muBase->TaskOwnerSem);
- return(result);
- }
-
-
- /*
- * Set the Default Protection Bits for a Level
- */
-
- BOOL SetLevelDefProtect(struct Task *task, ULONG defprotection)
- {
- BOOL result;
- struct muTaskLevel *level;
- struct muTaskNode *node;
-
- ObtainSemaphore(&muBase->TaskOwnerSem);
- if (node = FindTaskNode(task)) {
- level = node->Level;
- for (node = (struct muTaskNode *)level->Tasks.mlh_Head; node->LevelNode.mln_Succ;
- node = (struct muTaskNode *)node->LevelNode.mln_Succ)
- node->DefProtection = defprotection;
- result = TRUE;
- } else
- result = (BOOL)CreateOrphanTask(task, defprotection);
- ReleaseSemaphore(&muBase->TaskOwnerSem);
- return(result);
- }
-
-
- /*
- * Replacement for the exec.library AddTask() function
- */
-
- APTR __asm __saveds NEWAddTask(register __a1 struct Task *task, register __a2 APTR initpc,
- register __a3 APTR finalpc, register __a6 struct ExecBase *sysbase)
- {
- struct muTaskNode *node;
- struct muTaskLevel *level;
-
- ObtainSemaphore(&muBase->TaskOwnerSem);
- if (node = FindTaskNode(sysbase->ThisTask)) {
- level = node->Level;
- if (node = AllocTaskNode(task, node->DefProtection))
- AddTaskNode(node, level);
- } else
- CreateOrphanTask(task, DEFPROTECTION);
- ReleaseSemaphore(&muBase->TaskOwnerSem);
- return(muBase->OLDAddTask(task, initpc, finalpc, sysbase));
- }
-
-
- /*
- * Replacement for the exec.library RemTask() function
- */
-
- void __asm __saveds NEWRemTask(register __a1 struct Task *task, register __a6 struct ExecBase *sysbase)
- {
- struct muTaskNode *node;
- struct muTaskLevel *level;
-
- if (!task)
- task = sysbase->ThisTask;
- ObtainSemaphore(&muBase->TaskOwnerSem);
- if (node = FindTaskNode(task)) {
- level = node->Level;
- RemTaskNode(node);
- FreeTaskNode(node);
- CleanUpTaskLevel(level);
- }
- ReleaseSemaphore(&muBase->TaskOwnerSem);
- muBase->OLDRemTask(task, sysbase);
- }
-
-
- /*
- * Get the Owner (uid:gid) of a Task
- *
- * Public Library Function
- */
-
- ULONG __asm __saveds muGetTaskOwner(register __d0 struct Task *task)
- {
- if (!task)
- task = SysBase->ThisTask;
- return(GetTaskOwner(task));
- }
-
-
- /*
- * Get the Owner (struct muExtOwner *) of a Task
- *
- * Public Library Function
- */
-
- struct muExtOwner __asm __saveds *muGetTaskExtOwner(register __d0 struct Task *task)
- {
- if (!task)
- task = SysBase->ThisTask;
- return(GetTaskExtOwner(task));
- }
-
-
- /*
- * Free an Extended Owner structure
- *
- * Public Library Function
- */
-
- void __asm __saveds muFreeExtOwner(register __a0 struct muExtOwner *owner)
- {
- ULONG size;
-
- if (owner) {
- size = sizeof(struct muExtOwner)+owner->NumSecGroups*sizeof(UWORD);
- Free(owner, size);
- }
- }
-
-
- /*
- * Kill a task or process
- *
- * Public Library Function
- *
- * This function may be called by root only!
- */
-
- BOOL __asm __saveds muKill(register __d0 struct Task *task)
- {
- BOOL res = FALSE;
- UBYTE *sp;
- ULONG size;
- struct muExtOwner *xowner;
-
- xowner = GetTaskExtOwner(SysBase->ThisTask);
- if (task && (task != SysBase->ThisTask) && (task != muBase->Server) &&
- (muGetRelationshipA(xowner, NULL, NULL) & muRelF_ROOT_UID)) {
- Disable();
- switch (task->tc_Node.ln_Type) {
- case NT_TASK:
- RemTask(task);
- res = TRUE;
- break;
-
- case NT_PROCESS:
- Remove(task);
- task->tc_State = TS_READY;
- sp = task->tc_SPReg;
- if (SysBase->AttnFlags & AFF_68881) {
- if (size = *(ULONG *)sp) {
- sp += 110;
- if (size == 0x90)
- sp += 12;
- if ((SysBase->LibNode.lib_Version > 37) || ((SysBase->LibNode.lib_Version == 37) &&
- (SysBase->LibNode.lib_Revision >= 132)))
- sp += 2;
- size = sp[1];
- sp += size;
- }
- sp += 4;
- }
- *(ULONG *)sp = (ULONG)CleanUpBody;
- AddHead(&SysBase->TaskReady, task);
- res = TRUE;
- break;
- }
- Enable();
- }
- muFreeExtOwner(xowner);
- return(res);
- }
-
-
- /*
- * Clean up a dead process
- */
-
- static void __saveds CleanUpBody(void)
- {
- struct Task *task;
- struct Screen *scr, *t;
- struct Window *win;
- struct MsgPort *port;
- struct Requester *req;
- BOOL doclose;
-
- task = SysBase->ThisTask;
- Forbid();
- scr = IntuitionBase->FirstScreen;
- while (scr) {
- doclose = FALSE;
- win = scr->FirstWindow;
- while (win)
- if ((port = win->UserPort) && (port->mp_SigTask == task)) {
- ModifyIDCMP(win, NULL);
- ClearDMRequest(win);
- ClearMenuStrip(win);
- ClearPointer(win);
- while (req = win->FirstRequest)
- EndRequest(req, win);
- CloseWindow(win);
- doclose = TRUE;
- win = scr->FirstWindow;
- } else
- win = win->NextWindow;
- t = scr->NextScreen;
- if (doclose && ((scr->Flags & SCREENTYPE) != WBENCHSCREEN))
- CloseScreen(scr);
- scr = t;
- }
- Exit(NULL);
- }
-
-
- /*
- * Freeze a task or process
- *
- * Public Library Function
- *
- * This function may be called by root only!
- */
-
- BOOL __asm __saveds muFreeze(register __d0 struct Task *task)
- {
- BOOL res = FALSE;
- struct muExtOwner *xowner;
-
- xowner = GetTaskExtOwner(SysBase->ThisTask);
- if (task && (task != SysBase->ThisTask) && (task != muBase->Server) &&
- (muGetRelationshipA(xowner, NULL, NULL) & muRelF_ROOT_UID)) {
- Disable();
- switch (task->tc_Node.ln_Type) {
- case NT_TASK:
- case NT_PROCESS:
- if (task->tc_State < 7) {
- Remove(task);
- AddHead((struct List *)&muBase->Frozen, task);
- task->tc_State += 7;
- res = TRUE;
- }
- break;
- }
- Enable();
- }
- muFreeExtOwner(xowner);
- return(res);
- }
-
-
- /*
- * Unfreeze a task or process
- *
- * Public Library Function
- *
- * This function may be called by root only!
- */
-
- BOOL __asm __saveds muUnfreeze(register __d0 struct Task *task)
- {
- BOOL res = FALSE;
- struct muExtOwner *xowner;
-
- xowner = GetTaskExtOwner(SysBase->ThisTask);
- if (task && (muGetRelationshipA(xowner, NULL, NULL) & muRelF_ROOT_UID)) {
- Disable();
- switch (task->tc_Node.ln_Type) {
- case NT_TASK:
- case NT_PROCESS:
- if (task->tc_State >= 7) {
- Remove(task);
- if ((task->tc_State -= 7) == TS_READY)
- Enqueue(&SysBase->TaskReady, task);
- else
- Enqueue(&SysBase->TaskWait, task);
- res = TRUE;
- }
- break;
- }
- Enable();
- }
- muFreeExtOwner(xowner);
- return(res);
- }
-