home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / comm / tcp / amitcp / src / devs / netinfo / entries.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-19  |  10.0 KB  |  459 lines

  1. /*
  2.  * General DB routines
  3.  *
  4.  * Author: ppessi <Pekka.Pessi@hut.fi>
  5.  *
  6.  * Copyright © 1993 AmiTCP/IP Group, <AmiTCP-group@hut.fi>
  7.  *                  Helsinki University of Technology, Finland.
  8.  *
  9.  * Created      : Fri Jan 14 20:46:20 1994 ppessi
  10.  * Last modified: Thu May 19 04:09:10 1994 ppessi
  11.  */
  12.  
  13. #include "entries.h"
  14. #include <string.h>
  15. #include <assert.h>
  16.  
  17. static struct NetInfoPointer *FindPointer(struct List *list, struct Ent*to);
  18. void GetByNameCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim);
  19. void GetByIDCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim);
  20. void ResetCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim);
  21. void ReadCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim);
  22. void WriteCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim);
  23. void UpdateCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim);
  24. void MembersCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim);
  25.  
  26. const static DeviceCmd_t map_cmds[NI_END] =
  27. {
  28.   /* Standard commands */
  29.   UnknownCommand,        /* CMD_INVALID */
  30.   ResetCmd,            /* CMD_RESET */
  31.   ReadCmd,            /* CMD_READ */
  32.   WriteCmd,            /* CMD_WRITE */
  33.   UpdateCmd,            /* CMD_UPDATE */
  34.   UnknownCommand,        /* CMD_CLEAR */
  35.   UnknownCommand,        /* CMD_STOP */
  36.   UnknownCommand,        /* CMD_START */
  37.   UnknownCommand,        /* CMD_FLUSH */
  38.   /* NetInfo commands */
  39.   GetByIDCmd,            /* NI_GETBYID */
  40.   GetByNameCmd,            /* NI_GETBYNAME */
  41.   MembersCmd,            /* NI_MEMBERS */
  42. };
  43.  
  44. static const init_map_func_t initMapFuncs[NETINFO_UNITS] = 
  45. {
  46.   InitPasswdMap,
  47.   InitGroupMap,
  48. };
  49.  
  50. struct NetInfoMap *InitNetInfoMap(BASE, struct MsgPort * mp, ULONG mapno)
  51. {
  52.   struct NetInfoMap *nim;
  53.   assert(mapno < 2);
  54.  
  55.   if (nim = initMapFuncs[mapno](nid)) {
  56.     nim->nim_Port = mp;
  57.     nim->nim_Commands = map_cmds;
  58.   
  59.     InitSemaphore(nim->nim_ReqLock);
  60.     InitList(nim->nim_Rx);
  61.     InitList(nim->nim_Wx);
  62.  
  63.     InitSemaphore(nim->nim_EntLock);
  64.     InitList(nim->nim_Ent);
  65.   
  66.     InitSemaphore(nim->nim_PointerLock);
  67.     InitList(nim->nim_Pointer);
  68.   }
  69.   return nim;
  70. }
  71.  
  72. void DeInitNetInfoMap(BASE, struct NetInfoMap *nim)
  73. {
  74.   if (Method(cleanup, nim) != NULL) 
  75.     Method(cleanup, nim)(nid, nim);
  76.   
  77.   FreeVec(nim);
  78. }
  79.  
  80. /*
  81.  * NI_GETBYNAME, search an entry by name
  82.  */
  83. void GetByNameCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim)
  84. {
  85.   struct Ent *e = InternalSetEnts(nid, nim);
  86.   const UBYTE *name = (const UBYTE *)
  87.     ((struct NetInfoEnt*)req->io_Data)->nie_name;
  88.   LONG retval = NIERR_NOTFOUND;
  89.  
  90.   while (e = GetNextEnt(e)) {
  91.     if (strcmp(e->e_name, name) == 0) {
  92.       if (Method(copy_out, nim)(req, e)) {
  93.     retval = 0;
  94.       } else {
  95.     retval = NIERR_TOOSMALL;
  96.       }
  97.       break;
  98.     }
  99.   }
  100.   
  101.   req->io_Error = retval;
  102.  
  103.   InternalEndEnts(nid, nim);
  104.   TermIO(req);
  105. }
  106.  
  107. /*
  108.  * NI_GETBYID, Search an entry by ID
  109.  */
  110. void GetByIDCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim)
  111. {
  112.   struct Ent *e = InternalSetEnts(nid, nim);
  113.   LONG id = ((struct NetInfoEnt*)req->io_Data)->nie_id;
  114.   BYTE retval = NIERR_NOTFOUND;
  115.  
  116.   while (e = GetNextEnt(e)) {
  117.     if (e->e_id == id) {
  118.       if (Method(copy_out, nim)(req, e)) {
  119.     retval = 0;
  120.       } else {
  121.     retval = NIERR_TOOSMALL;
  122.       }
  123.       break;
  124.     }
  125.   }
  126.  
  127.   req->io_Error = retval;
  128.  
  129.   InternalEndEnts(nid, nim);
  130.   TermIO(req);
  131. }
  132.  
  133. /*
  134.  * CMD_RESET, start reading the database in sequential order
  135.  */
  136. void ResetCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim)
  137. {
  138.   struct NetInfoPointer *p = (struct NetInfoPointer *)req->io_Unit;
  139.  
  140.   p->nip_Ent = (void *)InternalSetEnts(nid, nim);
  141.   InternalEndEnts(nid, nim);
  142.   req->io_Error = 0;
  143.   TermIO(req);
  144. }
  145.  
  146. /*
  147.  * CMD_READ, get next entry  
  148.  */
  149. void ReadCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim)
  150. {
  151.   struct NetInfoPointer *p = (struct NetInfoPointer *)req->io_Unit;
  152.   struct Ent *e;
  153.   BYTE retval;
  154.  
  155.   InternalSetEnts(nid, nim);
  156.   e = p->nip_Ent;
  157.   if (p->nip_Ent && (p->nip_Ent = GetNextEnt(e))) {
  158.     if (Method(copy_out, nim)(req, p->nip_Ent)) {
  159.       retval = 0;
  160.     } else {
  161.       retval = NIERR_TOOSMALL;
  162.     }
  163.   } else {
  164.     retval = NIERR_NOTFOUND;
  165.   }
  166.   InternalEndEnts(nid, nim);
  167.  
  168.   req->io_Error = retval;
  169.   TermIO(req);
  170. }
  171.  
  172. /*
  173.  * CMD_WRITE
  174.  */
  175. void WriteCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim)
  176. {
  177.   struct Ent *e, *new_e;
  178.   const UBYTE *name = ((struct NetInfoPasswd *)req->io_Data)->pw_name;
  179.  
  180.   if (new_e = Method(copy_in, nim)(nid, req)) {
  181.     /* Exclusive lock for writing */
  182.     DbMapLock(nim);
  183.  
  184.     e = InternalSetEnts(nid, nim);
  185.  
  186.     while (e = GetNextEnt(e)) {
  187.       if (strcmp(e->e_name, name) == 0) {
  188.     /* A match was found - add new */ 
  189.     Insert(nim->nim_Ent, new_e, e);
  190.  
  191.     /* Remove old */
  192.     Remove((struct Node *)e);
  193.  
  194.     /* Update pointers */
  195.     ObtainSemaphore(nim->nim_PointerLock);
  196.     {
  197.       struct NetInfoPointer *nip;
  198.       if (nip = FindPointer(nim->nim_Pointer, e)) {
  199.         nip->nip_Ent = (void *)new_e;
  200.       }
  201.     }
  202.     ReleaseSemaphore(nim->nim_PointerLock);
  203.  
  204.     /* Free old */
  205.     FreeVec(e);
  206.  
  207.     new_e = NULL;
  208.     break;
  209.       }
  210.     }
  211.     
  212.     /*
  213.      * A new entry?
  214.      */
  215.     if (new_e != NULL) {
  216.       AddTail(nim->nim_Ent, new_e);
  217.     }
  218.  
  219.     req->io_Error = 0;
  220.     InternalEndEnts(nid, nim);
  221.   
  222.     nim->nim_Flags |= NIMF_CHANGED;
  223.     DbMapUnlock(nim);
  224.   } else {
  225.     /* copy_in method will set the io_Error */
  226.   }
  227.  
  228.   TermIO(req);
  229. }
  230.  
  231. /*
  232.  * CMD_UPDATE
  233.  */
  234. void UpdateCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim)
  235. {
  236.   BYTE retval = 0;
  237.  
  238.   if ((nim->nim_Flags & NIMF_CHANGED) != 0) {
  239.     UBYTE newname[128], oldname[128];
  240.     BPTR newfile;
  241.     DbMapLock(nim);
  242.     if ((nim->nim_Flags & NIMF_CHANGED) == 0)
  243.       goto exit;
  244.  
  245.     newname[sizeof(newname)-1] = '\0';
  246.     strncpy(newname, nim->nim_Filename, sizeof(newname)-1);
  247.     strncat(newname, ".new", sizeof(newname)-1);
  248.  
  249.     oldname[sizeof(oldname)-1] = '\0';
  250.     strncpy(oldname, nim->nim_Filename, sizeof(oldname)-1);
  251.     strncat(oldname, ".old", sizeof(oldname)-1);
  252.  
  253.     if (newfile = Open(newname, MODE_NEWFILE)) {
  254.       struct Node *entry, *next;
  255.  
  256.       retval = 0;
  257.  
  258.       for (entry = nim->nim_Ent->lh_Head;
  259.        next = entry->ln_Succ;
  260.        entry = next) {
  261.     retval = Method(print_out, nim)(nid, newfile, (struct Ent *)entry);
  262.     if (retval) 
  263.       break;
  264.       }
  265.       Close(newfile);
  266.  
  267.       if (retval == 0) {
  268.     /* Now we are supposed to move newfile to file */
  269.     DeleteFile(oldname);
  270.     Rename(nim->nim_Filename, oldname);
  271.     if (Rename(newname, nim->nim_Filename))
  272.       nim->nim_Flags &= NIMF_CHANGED;
  273.     else
  274.       retval = NIERR_ACCESS;
  275.       }
  276.     } else {
  277.       retval = NIERR_ACCESS;
  278.     }
  279.   exit:
  280.     DbMapUnlock(nim);
  281.   }
  282.  
  283.   req->io_Error = retval;
  284.   TermIO(req);
  285. }
  286.  
  287. /*
  288.  * NI_MEMBERS
  289.  */
  290. void MembersCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim)
  291. {
  292.   if (Method(membercmd, nim) != NULL) {
  293.     Method(membercmd, nim)(nid, req, nim);
  294.   } else {
  295.     req->io_Error = IOERR_NOCMD;
  296.     TermIO(req);
  297.   }
  298. }
  299.  
  300. /*
  301.  * Find a pointer to this entry
  302.  */
  303. static struct NetInfoPointer *FindPointer(struct List *list, struct Ent *to)
  304. {
  305.   struct NetInfoPointer *entry, *next;
  306.  
  307.   for (entry = (struct NetInfoPointer *)list->lh_Head;
  308.        next = (struct NetInfoPointer *)entry->nip_Node->ln_Succ;
  309.        entry = next) 
  310.     if (entry->nip_Ent == to) {
  311.       return entry;
  312.     }
  313.  
  314.   return NULL;
  315. }
  316.  
  317. /*
  318.  * Search for map
  319.  */
  320. struct NetInfoMap *CheckUnit(BASE, struct Unit *u) 
  321. {
  322.   struct NetInfoPointer *nip = (struct NetInfoPointer *)u;
  323.  
  324.   if (nip != NULL)
  325.     return nip->nip_Map;
  326.   else
  327.     return NULL;
  328. }
  329.  
  330.  
  331. /*
  332.  * Parse group database if needed
  333.  */
  334. struct Ent *InternalSetEnts(BASE, struct NetInfoMap *nim)
  335. {
  336.   DbMapLockShared(nim);
  337.  
  338.   if ((nim->nim_Flags & NIMF_PARSED) == 0) {
  339.     int was_too_long = 0;
  340.     UBYTE *p, *line = NULL;
  341.     BPTR fh = NULL;
  342.     struct Ent *ent;
  343.  
  344.     /* We can not get exclusive lock if we have shared lock */
  345.     DbMapUnlock(nim);
  346.     /* Exclusive lock for writing */
  347.     DbMapLock(nim);
  348.     if ((nim->nim_Flags & NIMF_PARSED) != 0)
  349.       goto error;
  350.  
  351.     line = AllocVec(MAXLINELENGTH + 1, MEMF_PUBLIC); 
  352.     fh = Open((STRPTR)nim->nim_Filename, MODE_OLDFILE);
  353.  
  354.     if (!line || !fh)
  355.       goto error;
  356.     
  357.     /* Free old entries */
  358.     FreeListVec(nid, nim->nim_Ent);
  359.  
  360.     /* Invalidate pointers to old database */
  361.     ObtainSemaphore(nim->nim_PointerLock);
  362.     {
  363.       struct NetInfoPointer *nip, *next;
  364.  
  365.       for (nip = (struct NetInfoPointer *)nim->nim_Pointer->lh_Head; 
  366.        next = (struct NetInfoPointer *)nip->nip_Node->ln_Succ; 
  367.        nip = next) {
  368.     nip->nip_Ent = NULL;
  369.       }
  370.     }
  371.     ReleaseSemaphore(nim->nim_PointerLock);
  372.  
  373.     line[MAXLINELENGTH] = '\0';
  374.     
  375.     while (p = FGets(fh, line, MAXLINELENGTH)) {
  376.       while (*p && *p != '\n')
  377.     p++;
  378.       if (!*p) {
  379.     /* Line is too long */
  380.     was_too_long = 1;
  381.     continue;
  382.       }
  383.       if (was_too_long) {
  384.     /* Rest of a line */
  385.     was_too_long = 0;
  386.     continue;
  387.       }
  388.       if (ent = Method(parse_ent, nim)(nid, line))
  389.     AddTail(nim->nim_Ent, (struct Node *)ent);
  390.     }
  391.     nim->nim_Flags |= NIMF_PARSED;
  392.  
  393.     /* Ask for notifies */ 
  394.     if (nim->nim_Methods->notify != NULL &&
  395.     nim->nim_Notify->nr_UserData == NULL) {
  396.       memset(nim->nim_Notify, 0, sizeof *nim->nim_Notify);
  397.       nim->nim_Notify->nr_Name = (STRPTR)nim->nim_Filename;
  398.       nim->nim_Notify->nr_Flags = NRF_SEND_MESSAGE;
  399.       nim->nim_Notify->nr_stuff.nr_Msg.nr_Port = nid->nid_NotifyPort;
  400.       nim->nim_Notify->nr_UserData = (ULONG) nim;
  401.       StartNotify(nim->nim_Notify);
  402.     }
  403.  
  404.   error:
  405.     if (line) FreeVec(line);
  406.     if (fh) Close(fh);
  407.  
  408.     /* Downgrade to a shared lock */ 
  409.     DbMapUnlock(nim);
  410.     DbMapLockShared(nim);
  411.   }
  412.  
  413.   return (struct Ent *)nim->nim_Ent;
  414. }
  415.  
  416. void InternalEndEnts(BASE, struct NetInfoMap *nim)
  417. {
  418.   DbMapUnlock(nim);
  419. }
  420.  
  421. /*
  422.  * Return next entry
  423.  */
  424. struct Ent *GetNextEnt(struct Ent *e)
  425. {
  426.   e = (struct Ent *)e->e_node.ln_Succ;
  427.  
  428.   if (e->e_node.ln_Succ)
  429.     return e;
  430.   else
  431.     return NULL;
  432. }
  433.  
  434. /*
  435.  * Mark as unparsed (when map has received DOS notify)
  436.  */
  437. void EntHandleNotify(BASE, struct NetInfoMap *nim)
  438. {
  439.   DbMapLockShared(nim);
  440.   nim->nim_Flags &= ~NIMF_PARSED;
  441.   DbMapUnlock(nim);
  442. }
  443.  
  444. /*
  445.  * Free all entries
  446.  */
  447. void EntCleanup(BASE, struct NetInfoMap *nim)
  448. {
  449.   DbMapLock(nim);
  450.   FreeListVec(nid, nim->nim_Ent);
  451.   /* End notifies */ 
  452.   if (nim->nim_Notify->nr_UserData != NULL) {
  453.     EndNotify(nim->nim_Notify);
  454.     nim->nim_Notify->nr_UserData = NULL;
  455.   }
  456.   DbMapUnlock(nim);
  457. }
  458.  
  459.