home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 2
/
goldfish_vol2_cd1.bin
/
files
/
util
/
misc
/
multiuser
/
src
/
support
/
massign.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-03-03
|
11KB
|
437 lines
/************************************************************
* 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);
}