home *** CD-ROM | disk | FTP | other *** search
- /*
- * General DB routines
- *
- * Author: ppessi <Pekka.Pessi@hut.fi>
- *
- * Copyright © 1993 AmiTCP/IP Group, <AmiTCP-group@hut.fi>
- * Helsinki University of Technology, Finland.
- *
- * Created : Fri Jan 14 20:46:20 1994 ppessi
- * Last modified: Thu May 19 04:09:10 1994 ppessi
- */
-
- #include "entries.h"
- #include <string.h>
- #include <assert.h>
-
- static struct NetInfoPointer *FindPointer(struct List *list, struct Ent*to);
- void GetByNameCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim);
- void GetByIDCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim);
- void ResetCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim);
- void ReadCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim);
- void WriteCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim);
- void UpdateCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim);
- void MembersCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim);
-
- const static DeviceCmd_t map_cmds[NI_END] =
- {
- /* Standard commands */
- UnknownCommand, /* CMD_INVALID */
- ResetCmd, /* CMD_RESET */
- ReadCmd, /* CMD_READ */
- WriteCmd, /* CMD_WRITE */
- UpdateCmd, /* CMD_UPDATE */
- UnknownCommand, /* CMD_CLEAR */
- UnknownCommand, /* CMD_STOP */
- UnknownCommand, /* CMD_START */
- UnknownCommand, /* CMD_FLUSH */
- /* NetInfo commands */
- GetByIDCmd, /* NI_GETBYID */
- GetByNameCmd, /* NI_GETBYNAME */
- MembersCmd, /* NI_MEMBERS */
- };
-
- static const init_map_func_t initMapFuncs[NETINFO_UNITS] =
- {
- InitPasswdMap,
- InitGroupMap,
- };
-
- struct NetInfoMap *InitNetInfoMap(BASE, struct MsgPort * mp, ULONG mapno)
- {
- struct NetInfoMap *nim;
- assert(mapno < 2);
-
- if (nim = initMapFuncs[mapno](nid)) {
- nim->nim_Port = mp;
- nim->nim_Commands = map_cmds;
-
- InitSemaphore(nim->nim_ReqLock);
- InitList(nim->nim_Rx);
- InitList(nim->nim_Wx);
-
- InitSemaphore(nim->nim_EntLock);
- InitList(nim->nim_Ent);
-
- InitSemaphore(nim->nim_PointerLock);
- InitList(nim->nim_Pointer);
- }
- return nim;
- }
-
- void DeInitNetInfoMap(BASE, struct NetInfoMap *nim)
- {
- if (Method(cleanup, nim) != NULL)
- Method(cleanup, nim)(nid, nim);
-
- FreeVec(nim);
- }
-
- /*
- * NI_GETBYNAME, search an entry by name
- */
- void GetByNameCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim)
- {
- struct Ent *e = InternalSetEnts(nid, nim);
- const UBYTE *name = (const UBYTE *)
- ((struct NetInfoEnt*)req->io_Data)->nie_name;
- LONG retval = NIERR_NOTFOUND;
-
- while (e = GetNextEnt(e)) {
- if (strcmp(e->e_name, name) == 0) {
- if (Method(copy_out, nim)(req, e)) {
- retval = 0;
- } else {
- retval = NIERR_TOOSMALL;
- }
- break;
- }
- }
-
- req->io_Error = retval;
-
- InternalEndEnts(nid, nim);
- TermIO(req);
- }
-
- /*
- * NI_GETBYID, Search an entry by ID
- */
- void GetByIDCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim)
- {
- struct Ent *e = InternalSetEnts(nid, nim);
- LONG id = ((struct NetInfoEnt*)req->io_Data)->nie_id;
- BYTE retval = NIERR_NOTFOUND;
-
- while (e = GetNextEnt(e)) {
- if (e->e_id == id) {
- if (Method(copy_out, nim)(req, e)) {
- retval = 0;
- } else {
- retval = NIERR_TOOSMALL;
- }
- break;
- }
- }
-
- req->io_Error = retval;
-
- InternalEndEnts(nid, nim);
- TermIO(req);
- }
-
- /*
- * CMD_RESET, start reading the database in sequential order
- */
- void ResetCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim)
- {
- struct NetInfoPointer *p = (struct NetInfoPointer *)req->io_Unit;
-
- p->nip_Ent = (void *)InternalSetEnts(nid, nim);
- InternalEndEnts(nid, nim);
- req->io_Error = 0;
- TermIO(req);
- }
-
- /*
- * CMD_READ, get next entry
- */
- void ReadCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim)
- {
- struct NetInfoPointer *p = (struct NetInfoPointer *)req->io_Unit;
- struct Ent *e;
- BYTE retval;
-
- InternalSetEnts(nid, nim);
- e = p->nip_Ent;
- if (p->nip_Ent && (p->nip_Ent = GetNextEnt(e))) {
- if (Method(copy_out, nim)(req, p->nip_Ent)) {
- retval = 0;
- } else {
- retval = NIERR_TOOSMALL;
- }
- } else {
- retval = NIERR_NOTFOUND;
- }
- InternalEndEnts(nid, nim);
-
- req->io_Error = retval;
- TermIO(req);
- }
-
- /*
- * CMD_WRITE
- */
- void WriteCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim)
- {
- struct Ent *e, *new_e;
- const UBYTE *name = ((struct NetInfoPasswd *)req->io_Data)->pw_name;
-
- if (new_e = Method(copy_in, nim)(nid, req)) {
- /* Exclusive lock for writing */
- DbMapLock(nim);
-
- e = InternalSetEnts(nid, nim);
-
- while (e = GetNextEnt(e)) {
- if (strcmp(e->e_name, name) == 0) {
- /* A match was found - add new */
- Insert(nim->nim_Ent, new_e, e);
-
- /* Remove old */
- Remove((struct Node *)e);
-
- /* Update pointers */
- ObtainSemaphore(nim->nim_PointerLock);
- {
- struct NetInfoPointer *nip;
- if (nip = FindPointer(nim->nim_Pointer, e)) {
- nip->nip_Ent = (void *)new_e;
- }
- }
- ReleaseSemaphore(nim->nim_PointerLock);
-
- /* Free old */
- FreeVec(e);
-
- new_e = NULL;
- break;
- }
- }
-
- /*
- * A new entry?
- */
- if (new_e != NULL) {
- AddTail(nim->nim_Ent, new_e);
- }
-
- req->io_Error = 0;
- InternalEndEnts(nid, nim);
-
- nim->nim_Flags |= NIMF_CHANGED;
- DbMapUnlock(nim);
- } else {
- /* copy_in method will set the io_Error */
- }
-
- TermIO(req);
- }
-
- /*
- * CMD_UPDATE
- */
- void UpdateCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim)
- {
- BYTE retval = 0;
-
- if ((nim->nim_Flags & NIMF_CHANGED) != 0) {
- UBYTE newname[128], oldname[128];
- BPTR newfile;
- DbMapLock(nim);
- if ((nim->nim_Flags & NIMF_CHANGED) == 0)
- goto exit;
-
- newname[sizeof(newname)-1] = '\0';
- strncpy(newname, nim->nim_Filename, sizeof(newname)-1);
- strncat(newname, ".new", sizeof(newname)-1);
-
- oldname[sizeof(oldname)-1] = '\0';
- strncpy(oldname, nim->nim_Filename, sizeof(oldname)-1);
- strncat(oldname, ".old", sizeof(oldname)-1);
-
- if (newfile = Open(newname, MODE_NEWFILE)) {
- struct Node *entry, *next;
-
- retval = 0;
-
- for (entry = nim->nim_Ent->lh_Head;
- next = entry->ln_Succ;
- entry = next) {
- retval = Method(print_out, nim)(nid, newfile, (struct Ent *)entry);
- if (retval)
- break;
- }
- Close(newfile);
-
- if (retval == 0) {
- /* Now we are supposed to move newfile to file */
- DeleteFile(oldname);
- Rename(nim->nim_Filename, oldname);
- if (Rename(newname, nim->nim_Filename))
- nim->nim_Flags &= NIMF_CHANGED;
- else
- retval = NIERR_ACCESS;
- }
- } else {
- retval = NIERR_ACCESS;
- }
- exit:
- DbMapUnlock(nim);
- }
-
- req->io_Error = retval;
- TermIO(req);
- }
-
- /*
- * NI_MEMBERS
- */
- void MembersCmd(BASE, struct NetInfoReq *req, struct NetInfoMap *nim)
- {
- if (Method(membercmd, nim) != NULL) {
- Method(membercmd, nim)(nid, req, nim);
- } else {
- req->io_Error = IOERR_NOCMD;
- TermIO(req);
- }
- }
-
- /*
- * Find a pointer to this entry
- */
- static struct NetInfoPointer *FindPointer(struct List *list, struct Ent *to)
- {
- struct NetInfoPointer *entry, *next;
-
- for (entry = (struct NetInfoPointer *)list->lh_Head;
- next = (struct NetInfoPointer *)entry->nip_Node->ln_Succ;
- entry = next)
- if (entry->nip_Ent == to) {
- return entry;
- }
-
- return NULL;
- }
-
- /*
- * Search for map
- */
- struct NetInfoMap *CheckUnit(BASE, struct Unit *u)
- {
- struct NetInfoPointer *nip = (struct NetInfoPointer *)u;
-
- if (nip != NULL)
- return nip->nip_Map;
- else
- return NULL;
- }
-
-
- /*
- * Parse group database if needed
- */
- struct Ent *InternalSetEnts(BASE, struct NetInfoMap *nim)
- {
- DbMapLockShared(nim);
-
- if ((nim->nim_Flags & NIMF_PARSED) == 0) {
- int was_too_long = 0;
- UBYTE *p, *line = NULL;
- BPTR fh = NULL;
- struct Ent *ent;
-
- /* We can not get exclusive lock if we have shared lock */
- DbMapUnlock(nim);
- /* Exclusive lock for writing */
- DbMapLock(nim);
- if ((nim->nim_Flags & NIMF_PARSED) != 0)
- goto error;
-
- line = AllocVec(MAXLINELENGTH + 1, MEMF_PUBLIC);
- fh = Open((STRPTR)nim->nim_Filename, MODE_OLDFILE);
-
- if (!line || !fh)
- goto error;
-
- /* Free old entries */
- FreeListVec(nid, nim->nim_Ent);
-
- /* Invalidate pointers to old database */
- ObtainSemaphore(nim->nim_PointerLock);
- {
- struct NetInfoPointer *nip, *next;
-
- for (nip = (struct NetInfoPointer *)nim->nim_Pointer->lh_Head;
- next = (struct NetInfoPointer *)nip->nip_Node->ln_Succ;
- nip = next) {
- nip->nip_Ent = NULL;
- }
- }
- ReleaseSemaphore(nim->nim_PointerLock);
-
- line[MAXLINELENGTH] = '\0';
-
- while (p = FGets(fh, line, MAXLINELENGTH)) {
- while (*p && *p != '\n')
- p++;
- if (!*p) {
- /* Line is too long */
- was_too_long = 1;
- continue;
- }
- if (was_too_long) {
- /* Rest of a line */
- was_too_long = 0;
- continue;
- }
- if (ent = Method(parse_ent, nim)(nid, line))
- AddTail(nim->nim_Ent, (struct Node *)ent);
- }
- nim->nim_Flags |= NIMF_PARSED;
-
- /* Ask for notifies */
- if (nim->nim_Methods->notify != NULL &&
- nim->nim_Notify->nr_UserData == NULL) {
- memset(nim->nim_Notify, 0, sizeof *nim->nim_Notify);
- nim->nim_Notify->nr_Name = (STRPTR)nim->nim_Filename;
- nim->nim_Notify->nr_Flags = NRF_SEND_MESSAGE;
- nim->nim_Notify->nr_stuff.nr_Msg.nr_Port = nid->nid_NotifyPort;
- nim->nim_Notify->nr_UserData = (ULONG) nim;
- StartNotify(nim->nim_Notify);
- }
-
- error:
- if (line) FreeVec(line);
- if (fh) Close(fh);
-
- /* Downgrade to a shared lock */
- DbMapUnlock(nim);
- DbMapLockShared(nim);
- }
-
- return (struct Ent *)nim->nim_Ent;
- }
-
- void InternalEndEnts(BASE, struct NetInfoMap *nim)
- {
- DbMapUnlock(nim);
- }
-
- /*
- * Return next entry
- */
- struct Ent *GetNextEnt(struct Ent *e)
- {
- e = (struct Ent *)e->e_node.ln_Succ;
-
- if (e->e_node.ln_Succ)
- return e;
- else
- return NULL;
- }
-
- /*
- * Mark as unparsed (when map has received DOS notify)
- */
- void EntHandleNotify(BASE, struct NetInfoMap *nim)
- {
- DbMapLockShared(nim);
- nim->nim_Flags &= ~NIMF_PARSED;
- DbMapUnlock(nim);
- }
-
- /*
- * Free all entries
- */
- void EntCleanup(BASE, struct NetInfoMap *nim)
- {
- DbMapLock(nim);
- FreeListVec(nid, nim->nim_Ent);
- /* End notifies */
- if (nim->nim_Notify->nr_UserData != NULL) {
- EndNotify(nim->nim_Notify);
- nim->nim_Notify->nr_UserData = NULL;
- }
- DbMapUnlock(nim);
- }
-
-