home *** CD-ROM | disk | FTP | other *** search
/ Aminet 3 / Aminet 3 - July 1994.iso / Aminet / util / misc / MUser17src.lha / MultiUser / src / Support / MAssign.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-07  |  11.1 KB  |  436 lines

  1. /************************************************************
  2. * MultiUser - MultiUser Task/File Support System                *
  3. * ---------------------------------------------------------    *
  4. * Assign Clone for Non-Binding Assigns                                *
  5. * ---------------------------------------------------------    *
  6. * © Copyright 1993-1994 Geert Uytterhoeven                        *
  7. * All Rights Reserved.                                                    *
  8. ************************************************************/
  9.  
  10.  
  11. #include <exec/memory.h>
  12. #include <exec/execbase.h>
  13. #include <dos/dos.h>
  14. #include <dos/dosextens.h>
  15. #include <proto/exec.h>
  16. #include <proto/dos.h>
  17. #include <libraries/multiuser.h>
  18. #include <proto/multiuser.h>
  19. #include <string.h>
  20.  
  21. #include "MAssign_rev.h"
  22.  
  23.  
  24. char __VersTag__[] = VERSTAG;
  25.  
  26.  
  27. #define MAXPATHLEN    512
  28.  
  29.  
  30. static BOOL AddAssign(char *name, char *target, BOOL volume, BOOL create, struct ExecBase *SysBase,
  31.                              struct DosLibrary *DOSBase, struct muBase *muBase);
  32. static struct DosPacket *WaitPktPort(struct MsgPort *port, struct ExecBase *SysBase);
  33. static ULONG GetPktOwner(struct DosPacket *pkt, struct muBase *muBase);
  34. static BPTR LockTarget(char *target, struct muUserInfo *uinfo, struct muGroupInfo *ginfo, BOOL create,
  35.                               LONG *error, struct DosLibrary *DOSBase);
  36. static void StripDevName(unsigned char *old, unsigned char *new);
  37. static void Handler(struct DosList *dlist, struct DosList *vlist, char *target, struct MsgPort *pubport,
  38.                           BOOL create, struct ExecBase *SysBase, struct DosLibrary *DOSBase,
  39.                           struct muBase *muBase);
  40.  
  41.  
  42. int __saveds Start(char *arg)
  43. {
  44.     struct ExecBase *SysBase;
  45.     struct DosLibrary *DOSBase;
  46.     struct muBase *muBase = NULL;
  47.     struct RDArgs *args;
  48.     LONG argarray[] = {
  49. #define argNAME    0
  50. #define argTARGET    1
  51. #define argVOLUME    2
  52. #define argCREATE    3
  53.         NULL, NULL, NULL, NULL
  54.     };
  55.     LONG error = NULL;
  56.     int rc = RETURN_OK;
  57.     struct muExtOwner *owner;
  58.     char *name;
  59.     int i;
  60.  
  61.     SysBase = *(struct ExecBase **)4;
  62.     
  63.     if ((!(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 37))) ||
  64.          (!(muBase = (struct muBase *)OpenLibrary("multiuser.library", 39)))) {
  65.         rc = ERROR_INVALID_RESIDENT_LIBRARY;
  66.         goto Exit;
  67.     }
  68.     owner = muGetTaskExtOwner(NULL);
  69.     if (muGetRelationshipA(owner, NULL, NULL) & muRelF_ROOT_UID) {
  70.         args = ReadArgs("NAME/A,TARGET/A,VOLUME/S,CREATE/S", argarray, NULL);
  71.         if (!args)
  72.             error = IoErr();
  73.         else {
  74.             for (i = 0; ((char *)argarray[argNAME])[i] && (((char *)argarray[argNAME])[i] != ':'); i++);
  75.             if (((char *)argarray[argNAME])[i] != ':') {
  76.                 VPrintf("Invalid device name %s\n", (char **)&argarray[argNAME]);
  77.                 rc = RETURN_ERROR;
  78.             } else if (name = AllocVec(i+1, MEMF_CLEAR|MEMF_PUBLIC)) {
  79.                 memcpy(name, (char *)argarray[argNAME], i);
  80.                 if (!AddAssign(name, (char *)argarray[argTARGET], (BOOL)argarray[argVOLUME],
  81.                                     (BOOL)argarray[argCREATE], SysBase, DOSBase, muBase))
  82.                     rc = RETURN_ERROR;
  83.                 FreeVec(name);
  84.             } else
  85.                 error = IoErr();
  86.         }
  87.         FreeArgs(args);
  88.     } else {
  89.         PutStr("MAssign must be run by root\n");
  90.         rc = RETURN_ERROR;
  91.     }
  92.     muFreeExtOwner(owner);
  93.     if (error) {
  94.         PrintFault(error, NULL);
  95.         rc = RETURN_ERROR;
  96.     }
  97.  
  98. Exit:
  99.     CloseLibrary((struct Library *)muBase);
  100.     CloseLibrary((struct Library *)DOSBase);
  101.  
  102.     return(rc);
  103. }
  104.  
  105.  
  106.     /*
  107.      *        Add the Non-Binding Assign
  108.      */
  109.  
  110. static BOOL AddAssign(char *name, char *target, BOOL volume, BOOL create, struct ExecBase *SysBase,
  111.                              struct DosLibrary *DOSBase, struct muBase *muBase)
  112. {
  113.     struct DosList *dlist, *vlist = NULL;
  114.     struct MsgPort *port;
  115.     BOOL res = FALSE;
  116.  
  117.     if ((port = CreateMsgPort()) && (dlist = MakeDosEntry(name, DLT_DEVICE))) {
  118.         if (!volume || (vlist = MakeDosEntry(name, DLT_VOLUME))) {
  119.             dlist->dol_Task = port;
  120.             dlist->dol_misc.dol_handler.dol_SegList = -1;
  121.             dlist->dol_misc.dol_handler.dol_GlobVec = -1;
  122.             if (vlist)
  123.                 vlist->dol_Task = port;
  124.             Forbid();
  125.             if (AddDosEntry(dlist))
  126.                 if (!vlist || AddDosEntry(vlist)) {
  127.                     Permit();
  128.                     Handler(dlist, vlist, target, port, create, SysBase, DOSBase, muBase);
  129.                     res = TRUE;
  130.                 } else {
  131.                     RemDosEntry(dlist);
  132.                     Permit();
  133.                 }
  134.             else
  135.                 Permit();
  136.             if (!res)
  137.                 VPrintf("%s conflicts with another assign\n", (LONG *)&name);
  138.             if (vlist)
  139.                 FreeDosEntry(vlist);
  140.         }
  141.         FreeDosEntry(dlist);
  142.     } else
  143.         PrintFault(IoErr(), NULL);
  144.  
  145.     DeleteMsgPort(port);
  146.     return(res);
  147. }
  148.  
  149.  
  150.     /*
  151.      *        Wait for a DosPacket at a specified MsgPort
  152.      */
  153.  
  154. static struct DosPacket *WaitPktPort(struct MsgPort *port, struct ExecBase *SysBase)
  155. {
  156.     struct Message *msg;
  157.     struct DosPacket *pkt = NULL;
  158.  
  159.     do
  160.         if (msg = GetMsg(port))
  161.             pkt = (struct DosPacket *)msg->mn_Node.ln_Name;
  162.         else
  163.             WaitPort(port);
  164.     while (!pkt);
  165.     return(pkt);
  166. }
  167.  
  168.  
  169.     /*
  170.      *        Get the Owner of a DosPacket
  171.      */
  172.  
  173. static ULONG GetPktOwner(struct DosPacket *pkt, struct muBase *muBase)
  174. {
  175.     struct MsgPort *port;
  176.     struct Task *task;
  177.     ULONG owner = NULL;
  178.  
  179.     if ((port = pkt->dp_Port) && (port->mp_Flags == PA_SIGNAL) && (task = port->mp_SigTask))
  180.         owner = muGetTaskOwner(task);
  181.     return(owner);
  182. }
  183.  
  184.  
  185.     /*
  186.      *        Lock the Target (and create it if necessary), resolving all Format Specifiers
  187.      */
  188.  
  189. static BPTR LockTarget(char *target, struct muUserInfo *uinfo, struct muGroupInfo *ginfo, BOOL create,
  190.                               LONG *error, struct DosLibrary *DOSBase)
  191. {
  192.     BPTR lock = NULL;
  193.     char path[MAXPATHLEN];
  194.     int len = 0, i = 0, slen;
  195.     char *str;
  196.  
  197.     *error = NULL;
  198.     while (len < MAXPATHLEN)
  199.         if (target[i])
  200.             if (target[i] == '%') {
  201.                 switch (target[i+1]) {
  202.                     case 'u':
  203.                         if (uinfo) {
  204.                             str = uinfo->UserID;
  205. Copy:                        if ((slen = strlen(str)) <= MAXPATHLEN-len) {
  206.                                 memcpy(&path[len], str, slen);
  207.                                 len += slen;
  208.                             } else {
  209.                                 *error = ERROR_LINE_TOO_LONG;
  210.                                 return(NULL);
  211.                             }
  212.                         } else {
  213. NotFound:                *error = ERROR_OBJECT_NOT_FOUND;
  214.                             return(NULL);
  215.                         }
  216.                         break;
  217.  
  218.                     case 'h':
  219.                         if (uinfo) {
  220.                             str = uinfo->HomeDir;
  221.                             goto Copy;
  222.                         } else
  223.                             goto NotFound;
  224.  
  225.                     case 'g':
  226.                         if (ginfo) {
  227.                             str = ginfo->GroupID;
  228.                             goto Copy;
  229.                         } else
  230.                             goto NotFound;
  231.  
  232.                     case '%':
  233.                         path[len++] = '%';
  234.                         break;
  235.  
  236.                     default:
  237.                         *error = ERROR_BAD_TEMPLATE;
  238.                         return(NULL);
  239.                 }
  240.                 i += 2;
  241.             } else
  242.                 path[len++] = target[i++];
  243.         else
  244.             break;
  245.     if (len < MAXPATHLEN) {
  246.         path[len] = '\0';
  247.         if (!(lock = Lock(path, ACCESS_READ)))
  248.             if (!create || !(lock = CreateDir(path)))
  249.                 *error = IoErr();
  250.             else {
  251.                 UnLock(lock);
  252.                 if (!(lock = Lock(path, ACCESS_READ)))
  253.                     *error = IoErr();
  254.             }
  255.     } else
  256.         *error = ERROR_LINE_TOO_LONG;
  257.     return(lock);
  258. }
  259.  
  260.  
  261.     /*
  262.      *        Strip the Device Name off of a File Name
  263.      *
  264.      *        Note: both old and new are CPTRs to a BSTR!
  265.      */
  266.  
  267. static void StripDevName(unsigned char *old, unsigned char *new)
  268. {
  269.     int len, i;
  270.  
  271.     len = old[0];
  272.     for (i = 0; (i < len) && (old[i+1] != ':'); i++);
  273.     if (i == len)
  274.         memcpy(new, old, len+1);
  275.     else {
  276.         memcpy(new+1, old+i+2, len-i-1);
  277.         new[0] = len-i-1;
  278.     }
  279. }
  280.  
  281.  
  282.     /*
  283.      *        Our pseudo File System
  284.      */
  285.  
  286. static void Handler(struct DosList *dlist, struct DosList *vlist, char *target, struct MsgPort *pubport,
  287.                           BOOL create, struct ExecBase *SysBase, struct DosLibrary *DOSBase,
  288.                           struct muBase *muBase)
  289. {
  290.     BOOL die = FALSE;
  291.     char *newpath = NULL;
  292.     struct Task *task;
  293.     BYTE oldpri;
  294.     struct muUserInfo *uinfo;
  295.     struct muGroupInfo *ginfo = NULL, *ginfo2;
  296.     struct MsgPort *privport, *port;
  297.     struct DosPacket *pubpkt, *privpkt;
  298.     BPTR lock;
  299.     ULONG owner;
  300.     struct TagItem tags[3];
  301.     LONG type, arg1, arg2, arg3, arg4, res1, res2;
  302.  
  303.     if ((uinfo = muAllocUserInfo()) && (ginfo = muAllocGroupInfo()) &&
  304.          (newpath = AllocVec(256, MEMF_CLEAR|MEMF_PUBLIC)) &&
  305.          (privpkt = AllocDosObject(DOS_STDPKT, NULL))) {
  306.         task = SysBase->ThisTask;
  307.         oldpri = SetTaskPri(task, 5);
  308.         privport = &((struct Process *)task)->pr_MsgPort;
  309.  
  310.         do {
  311.             pubpkt = WaitPktPort(pubport, SysBase);
  312.             type = pubpkt->dp_Type;
  313.             arg1 = pubpkt->dp_Arg1;
  314.             arg2 = pubpkt->dp_Arg2;
  315.             arg3 = pubpkt->dp_Arg3;
  316.             arg4 = pubpkt->dp_Arg4;
  317.             switch (type) {
  318.                 case ACTION_DIE:
  319.                     die = TRUE;
  320.                     ReplyPkt(pubpkt, DOSTRUE, NULL);
  321.                     break;
  322.  
  323.                 case ACTION_FINDINPUT:
  324.                 case ACTION_FINDOUTPUT:
  325.                 case ACTION_FINDUPDATE:
  326.                 case ACTION_SET_PROTECT:
  327.                 case ACTION_SET_COMMENT:
  328.                 case ACTION_SET_DATE:
  329.                 case ACTION_SET_OWNER:
  330.                 case ACTION_LOCATE_OBJECT:
  331.                 case ACTION_CREATE_DIR:
  332.                 case ACTION_DELETE_OBJECT:
  333.                 case ACTION_RENAME_OBJECT:
  334.                 case ACTION_MAKE_LINK:
  335.                 case ACTION_READ_LINK:
  336.                 case ACTION_DISK_CHANGE:
  337.                 case ACTION_IS_FILESYSTEM:
  338.                 case ACTION_CURRENT_VOLUME:
  339.                 case ACTION_FLUSH:
  340.                 case ACTION_MORE_CACHE:
  341.                     owner = GetPktOwner(pubpkt, muBase);
  342.                     uinfo->uid = (owner & muMASK_UID)>>16;
  343.                     if (muGetUserInfo(uinfo, muKeyType_uid)) {
  344.                         ginfo->gid = owner & muMASK_GID;
  345.                         ginfo2 = muGetGroupInfo(ginfo, muKeyType_gid);
  346.                         if (lock = LockTarget(target, uinfo, ginfo2, create, &res2, DOSBase)) {
  347.                             port = ((struct FileLock *)BADDR(lock))->fl_Task;
  348.                             tags[0].ti_Tag = muT_UserID;
  349.                             tags[0].ti_Data = (LONG)uinfo->UserID;
  350.                             tags[1].ti_Tag = muT_NoLog;
  351.                             tags[1].ti_Data = (LONG)TRUE;
  352.                             tags[2].ti_Tag = TAG_DONE;
  353.                             if (muLoginA(tags)) {
  354.                                 switch (type) {
  355.                                     case ACTION_FINDINPUT:
  356.                                     case ACTION_FINDOUTPUT:
  357.                                     case ACTION_FINDUPDATE:
  358.                                         ((struct FileHandle *)BADDR(arg1))->fh_Type = port;
  359.                                     case ACTION_SET_PROTECT:
  360.                                     case ACTION_SET_COMMENT:
  361.                                     case ACTION_SET_DATE:
  362.                                     case ACTION_SET_OWNER:
  363.                                         StripDevName(BADDR(arg3), newpath);
  364.                                         arg2 = lock;
  365.                                         arg3 = MKBADDR(newpath);
  366. PassPkt:                                privpkt->dp_Type = type;
  367.                                         privpkt->dp_Arg1 = arg1;
  368.                                         privpkt->dp_Arg2 = arg2;
  369.                                         privpkt->dp_Arg3 = arg3;
  370.                                         privpkt->dp_Arg4 = arg4;
  371.                                         SendPkt(privpkt, port, privport);
  372.                                         WaitPkt();
  373.                                         res1 = privpkt->dp_Res1;
  374.                                         res2 = privpkt->dp_Res2;
  375.                                         break;
  376.  
  377.                                     case ACTION_LOCATE_OBJECT:
  378.                                     case ACTION_CREATE_DIR:
  379.                                     case ACTION_DELETE_OBJECT:
  380.                                     case ACTION_RENAME_OBJECT:
  381.                                     case ACTION_MAKE_LINK:
  382.                                     case ACTION_READ_LINK:
  383.                                         StripDevName(BADDR(arg2), newpath);
  384.                                         arg1 = lock;
  385.                                         arg2 = MKBADDR(newpath);
  386.                                         goto PassPkt;
  387.  
  388.                                     case ACTION_IS_FILESYSTEM:
  389.                                     case ACTION_CURRENT_VOLUME:
  390.                                     case ACTION_FLUSH:
  391.                                     case ACTION_MORE_CACHE:
  392.                                         goto PassPkt;
  393.                                 }
  394.                                 tags[0].ti_Tag = muT_Quiet;
  395.                                 tags[0].ti_Data = TRUE;
  396.                                 tags[1].ti_Tag = TAG_DONE;
  397.                                 muLogoutA(tags);
  398.                             } else {
  399.                                 res1 = DOSFALSE;
  400.                                 res2 = ERROR_OBJECT_NOT_FOUND;
  401.                             }
  402.                             UnLock(lock);
  403.                             ReplyPkt(pubpkt, res1, res2);
  404.                         } else
  405.                             ReplyPkt(pubpkt, DOSFALSE, res2);
  406.                     } else
  407.                         ReplyPkt(pubpkt, DOSFALSE, ERROR_OBJECT_NOT_FOUND);
  408.                     break;
  409.  
  410.                 default:
  411.                     ReplyPkt(pubpkt, DOSFALSE, ERROR_ACTION_NOT_KNOWN);
  412.                     break;
  413.             }
  414.             if (die) {
  415.                 if (dlist && AttemptLockDosList(LDF_DEVICES|LDF_WRITE)) {
  416.                     if (RemDosEntry(dlist))
  417.                         dlist = NULL;
  418.                     UnLockDosList(LDF_DEVICES|LDF_WRITE);
  419.                 }
  420.                 if (vlist && AttemptLockDosList(LDF_VOLUMES|LDF_WRITE)) {
  421.                     if (RemDosEntry(vlist))
  422.                         vlist = NULL;
  423.                     UnLockDosList(LDF_VOLUMES|LDF_WRITE);
  424.                 }
  425.             }
  426.         } while (!die || dlist || vlist);
  427.         SetTaskPri(task, oldpri);
  428.         FreeDosObject(DOS_STDPKT, privpkt);
  429.     } else
  430.         PrintFault(IoErr(), NULL);
  431.  
  432.     muFreeUserInfo(uinfo);
  433.     muFreeGroupInfo(ginfo);
  434.     FreeVec(newpath);
  435. }
  436.