home *** CD-ROM | disk | FTP | other *** search
- /************************************************************
- * MultiUser - MultiUser Task/File Support System *
- * --------------------------------------------------------- *
- * Assign Clone for Non-Binding Assigns *
- * --------------------------------------------------------- *
- * © Copyright 1993-1994 Geert Uytterhoeven *
- * All Rights Reserved. *
- ************************************************************/
-
-
- #include <exec/memory.h>
- #include <exec/execbase.h>
- #include <dos/dos.h>
- #include <dos/dosextens.h>
- #include <proto/exec.h>
- #include <proto/dos.h>
- #include <libraries/multiuser.h>
- #include <proto/multiuser.h>
- #include <string.h>
-
- #include "MAssign_rev.h"
-
- #include "Locale.h"
-
- char __VersTag__[] = VERSTAG;
-
-
- #define MAXPATHLEN 512
-
-
- static BOOL AddAssign(char *name, char *target, BOOL volume, BOOL create, struct ExecBase *SysBase,
- struct DosLibrary *DOSBase, struct muBase *muBase);
- static struct DosPacket *WaitPktPort(struct MsgPort *port, struct ExecBase *SysBase);
- static ULONG GetPktOwner(struct DosPacket *pkt, struct muBase *muBase);
- static BPTR LockTarget(char *target, struct muUserInfo *uinfo, struct muGroupInfo *ginfo, BOOL create,
- LONG *error, struct DosLibrary *DOSBase);
- static void StripDevName(unsigned char *old, unsigned char *new);
- static void Handler(struct DosList *dlist, struct DosList *vlist, char *target, struct MsgPort *pubport,
- BOOL create, struct ExecBase *SysBase, struct DosLibrary *DOSBase,
- struct muBase *muBase);
-
-
- int __saveds Start(char *arg)
- {
- struct ExecBase *SysBase;
- struct DosLibrary *DOSBase;
- struct muBase *muBase = NULL;
- struct RDArgs *args;
- LONG argarray[] = {
- #define argNAME 0
- #define argTARGET 1
- #define argVOLUME 2
- #define argCREATE 3
- NULL, NULL, NULL, NULL
- };
- LONG error = NULL;
- int rc = RETURN_OK;
- struct muExtOwner *owner;
- char *name;
- int i;
-
- SysBase = *(struct ExecBase **)4;
-
- if ((!(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 37))) ||
- (!(muBase = (struct muBase *)OpenLibrary("multiuser.library", 39)))) {
- rc = ERROR_INVALID_RESIDENT_LIBRARY;
- goto Exit;
- }
- owner = muGetTaskExtOwner(NULL);
- if (muGetRelationshipA(owner, NULL, NULL) & muRelF_ROOT_UID) {
- args = ReadArgs("NAME/A,TARGET/A,VOLUME/S,CREATE/S", argarray, NULL);
- if (!args)
- error = IoErr();
- else {
- for (i = 0; ((char *)argarray[argNAME])[i] && (((char *)argarray[argNAME])[i] != ':'); i++);
- if (((char *)argarray[argNAME])[i] != ':') {
- VPrintf(GetLocStr(MSG_INVALID_DEVICE), (char **)&argarray[argNAME]);
- rc = RETURN_ERROR;
- } else if (name = AllocVec(i+1, MEMF_CLEAR|MEMF_PUBLIC)) {
- memcpy(name, (char *)argarray[argNAME], i);
- if (!AddAssign(name, (char *)argarray[argTARGET], (BOOL)argarray[argVOLUME],
- (BOOL)argarray[argCREATE], SysBase, DOSBase, muBase))
- rc = RETURN_ERROR;
- FreeVec(name);
- } else
- error = IoErr();
- }
- FreeArgs(args);
- } else {
- PutStr(GetLocStr(MSG_MUSTBEROOT));
- rc = RETURN_ERROR;
- }
- muFreeExtOwner(owner);
- if (error) {
- PrintFault(error, NULL);
- rc = RETURN_ERROR;
- }
-
- Exit:
- CloseLibrary((struct Library *)muBase);
- CloseLibrary((struct Library *)DOSBase);
-
- return(rc);
- }
-
-
- /*
- * Add the Non-Binding Assign
- */
-
- static BOOL AddAssign(char *name, char *target, BOOL volume, BOOL create, struct ExecBase *SysBase,
- struct DosLibrary *DOSBase, struct muBase *muBase)
- {
- struct DosList *dlist, *vlist = NULL;
- struct MsgPort *port;
- BOOL res = FALSE;
-
- if ((port = CreateMsgPort()) && (dlist = MakeDosEntry(name, DLT_DEVICE))) {
- if (!volume || (vlist = MakeDosEntry(name, DLT_VOLUME))) {
- dlist->dol_Task = port;
- dlist->dol_misc.dol_handler.dol_SegList = -1;
- dlist->dol_misc.dol_handler.dol_GlobVec = -1;
- if (vlist)
- vlist->dol_Task = port;
- Forbid();
- if (AddDosEntry(dlist))
- if (!vlist || AddDosEntry(vlist)) {
- Permit();
- Handler(dlist, vlist, target, port, create, SysBase, DOSBase, muBase);
- res = TRUE;
- } else {
- RemDosEntry(dlist);
- Permit();
- }
- else
- Permit();
- if (!res)
- VPrintf(GetLocStr(MSG_ASSIGNCONFLICT), (LONG *)&name);
- if (vlist)
- FreeDosEntry(vlist);
- }
- FreeDosEntry(dlist);
- } else
- PrintFault(IoErr(), NULL);
-
- DeleteMsgPort(port);
- return(res);
- }
-
-
- /*
- * Wait for a DosPacket at a specified MsgPort
- */
-
- static struct DosPacket *WaitPktPort(struct MsgPort *port, struct ExecBase *SysBase)
- {
- struct Message *msg;
- struct DosPacket *pkt = NULL;
-
- do
- if (msg = GetMsg(port))
- pkt = (struct DosPacket *)msg->mn_Node.ln_Name;
- else
- WaitPort(port);
- while (!pkt);
- return(pkt);
- }
-
-
- /*
- * Get the Owner of a DosPacket
- */
-
- static ULONG GetPktOwner(struct DosPacket *pkt, struct muBase *muBase)
- {
- struct MsgPort *port;
- struct Task *task;
- ULONG owner = NULL;
-
- if ((port = pkt->dp_Port) && (port->mp_Flags == PA_SIGNAL) && (task = port->mp_SigTask))
- owner = muGetTaskOwner(task);
- return(owner);
- }
-
-
- /*
- * Lock the Target (and create it if necessary), resolving all Format Specifiers
- */
-
- static BPTR LockTarget(char *target, struct muUserInfo *uinfo, struct muGroupInfo *ginfo, BOOL create,
- LONG *error, struct DosLibrary *DOSBase)
- {
- BPTR lock = NULL;
- char path[MAXPATHLEN];
- int len = 0, i = 0, slen;
- char *str;
-
- *error = NULL;
- while (len < MAXPATHLEN)
- if (target[i])
- if (target[i] == '%') {
- switch (target[i+1]) {
- case 'u':
- if (uinfo) {
- str = uinfo->UserID;
- Copy: if ((slen = strlen(str)) <= MAXPATHLEN-len) {
- memcpy(&path[len], str, slen);
- len += slen;
- } else {
- *error = ERROR_LINE_TOO_LONG;
- return(NULL);
- }
- } else {
- NotFound: *error = ERROR_OBJECT_NOT_FOUND;
- return(NULL);
- }
- break;
-
- case 'h':
- if (uinfo) {
- str = uinfo->HomeDir;
- goto Copy;
- } else
- goto NotFound;
-
- case 'g':
- if (ginfo) {
- str = ginfo->GroupID;
- goto Copy;
- } else
- goto NotFound;
-
- case '%':
- path[len++] = '%';
- break;
-
- default:
- *error = ERROR_BAD_TEMPLATE;
- return(NULL);
- }
- i += 2;
- } else
- path[len++] = target[i++];
- else
- break;
- if (len < MAXPATHLEN) {
- path[len] = '\0';
- if (!(lock = Lock(path, ACCESS_READ)))
- if (!create || !(lock = CreateDir(path)))
- *error = IoErr();
- else {
- UnLock(lock);
- if (!(lock = Lock(path, ACCESS_READ)))
- *error = IoErr();
- }
- } else
- *error = ERROR_LINE_TOO_LONG;
- return(lock);
- }
-
-
- /*
- * Strip the Device Name off of a File Name
- *
- * Note: both old and new are CPTRs to a BSTR!
- */
-
- static void StripDevName(unsigned char *old, unsigned char *new)
- {
- int len, i;
-
- len = old[0];
- for (i = 0; (i < len) && (old[i+1] != ':'); i++);
- if (i == len)
- memcpy(new, old, len+1);
- else {
- memcpy(new+1, old+i+2, len-i-1);
- new[0] = len-i-1;
- }
- }
-
-
- /*
- * Our pseudo File System
- */
-
- static void Handler(struct DosList *dlist, struct DosList *vlist, char *target, struct MsgPort *pubport,
- BOOL create, struct ExecBase *SysBase, struct DosLibrary *DOSBase,
- struct muBase *muBase)
- {
- BOOL die = FALSE;
- char *newpath = NULL;
- struct Task *task;
- BYTE oldpri;
- struct muUserInfo *uinfo;
- struct muGroupInfo *ginfo = NULL, *ginfo2;
- struct MsgPort *privport, *port;
- struct DosPacket *pubpkt, *privpkt;
- BPTR lock;
- ULONG owner;
- struct TagItem tags[3];
- LONG type, arg1, arg2, arg3, arg4, res1, res2;
-
- if ((uinfo = muAllocUserInfo()) && (ginfo = muAllocGroupInfo()) &&
- (newpath = AllocVec(256, MEMF_CLEAR|MEMF_PUBLIC)) &&
- (privpkt = AllocDosObject(DOS_STDPKT, NULL))) {
- task = SysBase->ThisTask;
- oldpri = SetTaskPri(task, 5);
- privport = &((struct Process *)task)->pr_MsgPort;
-
- do {
- pubpkt = WaitPktPort(pubport, SysBase);
- type = pubpkt->dp_Type;
- arg1 = pubpkt->dp_Arg1;
- arg2 = pubpkt->dp_Arg2;
- arg3 = pubpkt->dp_Arg3;
- arg4 = pubpkt->dp_Arg4;
- switch (type) {
- case ACTION_DIE:
- die = TRUE;
- ReplyPkt(pubpkt, DOSTRUE, NULL);
- break;
-
- case ACTION_FINDINPUT:
- case ACTION_FINDOUTPUT:
- case ACTION_FINDUPDATE:
- case ACTION_SET_PROTECT:
- case ACTION_SET_COMMENT:
- case ACTION_SET_DATE:
- case ACTION_SET_OWNER:
- case ACTION_LOCATE_OBJECT:
- case ACTION_CREATE_DIR:
- case ACTION_DELETE_OBJECT:
- case ACTION_RENAME_OBJECT:
- case ACTION_MAKE_LINK:
- case ACTION_READ_LINK:
- case ACTION_DISK_CHANGE:
- case ACTION_IS_FILESYSTEM:
- case ACTION_CURRENT_VOLUME:
- case ACTION_FLUSH:
- case ACTION_MORE_CACHE:
- owner = GetPktOwner(pubpkt, muBase);
- uinfo->uid = (owner & muMASK_UID)>>16;
- if (muGetUserInfo(uinfo, muKeyType_uid)) {
- ginfo->gid = owner & muMASK_GID;
- ginfo2 = muGetGroupInfo(ginfo, muKeyType_gid);
- if (lock = LockTarget(target, uinfo, ginfo2, create, &res2, DOSBase)) {
- port = ((struct FileLock *)BADDR(lock))->fl_Task;
- tags[0].ti_Tag = muT_UserID;
- tags[0].ti_Data = (LONG)uinfo->UserID;
- tags[1].ti_Tag = muT_NoLog;
- tags[1].ti_Data = (LONG)TRUE;
- tags[2].ti_Tag = TAG_DONE;
- if (muLoginA(tags)) {
- switch (type) {
- case ACTION_FINDINPUT:
- case ACTION_FINDOUTPUT:
- case ACTION_FINDUPDATE:
- ((struct FileHandle *)BADDR(arg1))->fh_Type = port;
- case ACTION_SET_PROTECT:
- case ACTION_SET_COMMENT:
- case ACTION_SET_DATE:
- case ACTION_SET_OWNER:
- StripDevName(BADDR(arg3), newpath);
- arg2 = lock;
- arg3 = MKBADDR(newpath);
- PassPkt: privpkt->dp_Type = type;
- privpkt->dp_Arg1 = arg1;
- privpkt->dp_Arg2 = arg2;
- privpkt->dp_Arg3 = arg3;
- privpkt->dp_Arg4 = arg4;
- SendPkt(privpkt, port, privport);
- WaitPkt();
- res1 = privpkt->dp_Res1;
- res2 = privpkt->dp_Res2;
- break;
-
- case ACTION_LOCATE_OBJECT:
- case ACTION_CREATE_DIR:
- case ACTION_DELETE_OBJECT:
- case ACTION_RENAME_OBJECT:
- case ACTION_MAKE_LINK:
- case ACTION_READ_LINK:
- StripDevName(BADDR(arg2), newpath);
- arg1 = lock;
- arg2 = MKBADDR(newpath);
- goto PassPkt;
-
- case ACTION_IS_FILESYSTEM:
- case ACTION_CURRENT_VOLUME:
- case ACTION_FLUSH:
- case ACTION_MORE_CACHE:
- goto PassPkt;
- }
- tags[0].ti_Tag = muT_Quiet;
- tags[0].ti_Data = TRUE;
- tags[1].ti_Tag = TAG_DONE;
- muLogoutA(tags);
- } else {
- res1 = DOSFALSE;
- res2 = ERROR_OBJECT_NOT_FOUND;
- }
- UnLock(lock);
- ReplyPkt(pubpkt, res1, res2);
- } else
- ReplyPkt(pubpkt, DOSFALSE, res2);
- } else
- ReplyPkt(pubpkt, DOSFALSE, ERROR_OBJECT_NOT_FOUND);
- break;
-
- default:
- ReplyPkt(pubpkt, DOSFALSE, ERROR_ACTION_NOT_KNOWN);
- break;
- }
- if (die) {
- if (dlist && AttemptLockDosList(LDF_DEVICES|LDF_WRITE)) {
- if (RemDosEntry(dlist))
- dlist = NULL;
- UnLockDosList(LDF_DEVICES|LDF_WRITE);
- }
- if (vlist && AttemptLockDosList(LDF_VOLUMES|LDF_WRITE)) {
- if (RemDosEntry(vlist))
- vlist = NULL;
- UnLockDosList(LDF_VOLUMES|LDF_WRITE);
- }
- }
- } while (!die || dlist || vlist);
- SetTaskPri(task, oldpri);
- FreeDosObject(DOS_STDPKT, privpkt);
- } else
- PrintFault(IoErr(), NULL);
-
- muFreeUserInfo(uinfo);
- muFreeGroupInfo(ginfo);
- FreeVec(newpath);
- }
-