1
0
mirror of https://github.com/deadw00d/AROS.git synced 2025-12-06 13:11:35 +00:00
Files
AROS-v0/workbench/devs/netinfo/netinfo.c
2025-10-17 08:30:10 +02:00

333 lines
9.3 KiB
C

/*
* netinfo.c --- netinfo.device main functions
*
* Author: ppessi <Pekka.Pessi@hut.fi>
*
* Copyright © 1993 AmiTCP/IP Group, <AmiTCP-Group@hut.fi>
* Helsinki University of Technology, Finland.
*/
/****** netinfo.device/--background-- **************************************
PURPOSE
The netinfo.device is intended to access various information from
network database. It provides an uniform and well-defined interface
to databases, so it is easy to adopt clients to different
environments. There is a separate unit for each database.
Currently the netinfo.device supports access to local password and
group files. As a new feature since last release it supports file
notification.
The device file is located to "AmiTCP:devs/netinfo.device". It is
recommended that the OpenDevice() call is given the macro NETINFONAME
as device name.
OVERVIEW
Short overview of implemented IO commands is as follows:
CMD_RESET - reset sequential access
This command restarts the sequential database reading.
Inputs: none
Results:
* io_Error contains possaible error code or 0 if command was
successfull
CMD_READ - read next entry
Inputs:
* io_Data contains buffer for database entry. The buffer will
be filled wtih entry data upon successfull execution.
* io_Length contains database len
Results:
* io_Actual contains length of the database entry
* io_Error contains possaible error code or 0 if command was
successfull
CMD_WRITE - alter the database
This command adds a new database entry or replace an old entry.
If a matching entry with same name is found, it is replaced with
the new entry.
Inputs:
* io_Data contains pointer for database entry structure
Results:
* io_Actual contains length of the database entry
* io_Error contains possible error code or 0 if command was
successfull
CMD_UPDATE - copy the previous changes to permanent store
This command updates the permanent copies of database. The
netinfo.device does not ensure that entries updated with
CMD_WRITE will be available by CMD_READ or written to permanent
store before the CMD_UPDATE is executed.
Inputs: none
Results:
* io_Error contains possible error code or 0 if command was
successfull
NI_BYNAME - search by name
Inputs:
* io_Data contains buffer for database entry. The buffer will
be filled wtih entry data upon successfull execution. The name
member of structure should be pointer to a C string containing
the name of desired entry
* io_Length contains database len
Results:
* io_Actual contains length of the database entry
* io_Error contains possaible error code or 0 if command was
successfull
NI_BYUID - search by ID
Inputs:
* io_Data contains buffer for database entry. The buffer will
be filled wtih entry data upon successfull execution. The ID
member of structure should be set to desired value.
* io_Length contains database len
Results:
* io_Actual contains length of the database entry
* io_Error contains possaible error code or 0 if command was
successfull
NI_MEMBERS - find out memberships
This command is implemented only for group unit. It collects
the IDs of groups which have a given user as member.
Inputs:
* io_Data is address to LONG array which is filled with group
IDs
* io_Length is the length of the array in bytes
* io_Offset is a pointer to C string containing the name of
user whose memberships are desired
Results:
* io_Actual contains length of the group ID array in bytes
* io_Error contains possaible error code or 0 if command was
successfull.
****************************************************************************
*/
#ifdef DEBUG
#undef DEBUG
#endif
#define DEBUG 0
#include <aros/debug.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include "base.h"
#include <dos/dostags.h>
#if defined(LC_LIBDEFS_FILE)
#include LC_LIBDEFS_FILE
/*
* Device initialization routine
* Do only things that won't Wait()
*/
static int NetInfo__DevInit(LIBBASETYPEPTR LIBBASE)
{
D(bug("[NetInfo] %s()\n", __func__));
LIBBASE->nid_Task = NULL;
InitSemaphore(LIBBASE->nid_Lock);
return TRUE;
}
static int NetInfo__DevOpen(LIBBASETYPEPTR LIBBASE,
struct IORequest *req,
ULONG unit,
ULONG flags
)
{
D(bug("[NetInfo] %s()\n", __func__));
req->io_Error = IOERR_OPENFAIL;
/* Enforce single threading so we can Wait() */
ObtainSemaphore(LIBBASE->nid_Lock);
if (unit >= NETINFO_UNITS)
goto zap;
/*
* Create device task if necessary
*/
while (LIBBASE->nid_Task == NULL) {
struct MsgPort *mp;
struct Message *msg;
struct Process *task;
LIBBASE->nid_DOSBase = OpenLibrary("dos.library",37L);
if (LIBBASE->nid_DOSBase == NULL)
break;
mp = CreateMsgPort();
if (mp == NULL)
break;
msg = CreateIORequest(mp, sizeof(*msg));
if (msg) {
/* Create new process, wait for the message */
msg->mn_Node.ln_Type = NT_MESSAGE;
msg->mn_Node.ln_Name = (void *)LIBBASE;
task = CreateNewProcTags(NP_Entry, NetInfoStartup,
NP_Priority, NID_PRIORITY,
NP_Name, MOD_NAME_STRING,
NP_ExitData, msg,
TAG_END);
do {
Wait(1L << mp->mp_SigBit);
} while (GetMsg(mp) != msg);
DeleteIORequest(msg);
}
DeleteMsgPort(mp);
break;
}
if (LIBBASE->nid_Task == NULL)
goto zap;
D(bug("[NetInfo] %s: initializing unit...\n", __func__));
/* OK, create a new unit structure, fill in a request and return */
req->io_Device = (struct Device *) LIBBASE;
if ((req->io_Unit = CreateNewUnit(LIBBASE, unit)) != NULL) {
D(bug("[NetInfo] %s: unit @ 0x%p\n", __func__, req->io_Unit));
req->io_Error = 0;
}
zap:
if (req->io_Error != 0) {
req->io_Unit = (struct Unit *) -1;
req->io_Device = (struct Device *) -1;
}
ReleaseSemaphore(LIBBASE->nid_Lock);
D(bug("[NetInfo] %s: returning %s\n", __func__, req->io_Error ? "FALSE" : "TRUE"));
return req->io_Error ? FALSE : TRUE;
}
static int NetInfo__DevClose(LIBBASETYPEPTR LIBBASE,
struct IORequest *req
)
{
int retval = FALSE;
D(bug("[NetInfo] %s()\n", __func__));
ObtainSemaphore(LIBBASE->nid_Lock);
{
ExpungeUnit(LIBBASE, req->io_Unit);
retval = TRUE;
}
ReleaseSemaphore(LIBBASE->nid_Lock);
return retval;
}
/*
* Device expunge
*/
static int NetInfo__DevExpunge(LIBBASETYPEPTR LIBBASE)
{
D(bug("[NetInfo] %s()\n", __func__));
if (AttemptSemaphore(LIBBASE->nid_Lock)) {
if (LIBBASE->nid_Task) {
if (LIBBASE->nid_Death && LIBBASE->nid_Death->mn_Node.ln_Type == NT_MESSAGE)
ReplyMsg(LIBBASE->nid_Death);
}
ReleaseSemaphore(LIBBASE->nid_Lock);
}
return TRUE;
}
ADD2OPENDEV(NetInfo__DevOpen, 0)
ADD2CLOSEDEV(NetInfo__DevClose, 0)
ADD2INITLIB(NetInfo__DevInit, 0)
ADD2EXPUNGELIB(NetInfo__DevExpunge, 0)
#endif
/*
* Queue requests
*/
#define IMMEDIATE_CMDS 0L
AROS_LH1(void, BeginIO,
AROS_LHA(struct NetInfoReq *, req, A1),
struct NetInfoDevice *, nid, 5, NetInfo)
{
AROS_LIBFUNC_INIT
D(bug("[NetInfo] %s()\n", __func__));
req->io_Message.mn_Node.ln_Type = NT_MESSAGE;
if (req->io_Command >= NI_END) {
req->io_Error = IOERR_NOCMD;
TermIO(req);
#if IMMEDIATE_CMDS
} else if ((req->io_Flags & IOF_QUICK) &&
(1L << req->io_Command) & IMMEDIATE_CMDS) {
PerformIO(nid, req);
#endif
} else {
req->io_Flags &= ~IOF_QUICK;
PutMsg(nid->nid_Port, (struct Message *)req);
}
AROS_LIBFUNC_EXIT
}
/*
* The device AbortIO() entry point.
*
* A1 - The IO request to be aborted.
* A6 - The device base.
*/
AROS_LH1(LONG, AbortIO,
AROS_LHA(struct NetInfoReq *, ni, A1),
struct NetInfoDevice *, nid, 6, NetInfo)
{
AROS_LIBFUNC_INIT
ULONG result = 0L;
struct NetInfoMap *nim;
D(bug("[NetInfo] %s()\n", __func__));
if (ni->io_Unit == NULL)
return NIERR_NULL_POINTER;
nim = CheckUnit(nid, ni->io_Unit);
if (nim == NULL)
return IOERR_BADADDRESS;
ObtainSemaphore(nim->nim_ReqLock);
if (ni->io_Message.mn_Node.ln_Type != NT_REPLYMSG) {
switch (ni->io_Command) {
case CMD_READ:
result = AbortReq(nid, nim->nim_Rx, ni);
break;
case CMD_WRITE:
result = AbortReq(nid, nim->nim_Wx, ni);
break;
default:
result = IOERR_NOCMD;
break;
}
}
ReleaseSemaphore(nim->nim_ReqLock);
return(result);
AROS_LIBFUNC_EXIT
}