/*
* msg.c
*
* Written by Archie Cobbs <archie@freebsd.org>
* Copyright (c) 1995-1999 Whistle Communications, Inc. All rights reserved.
* See ``COPYRIGHT.whistle''
*/
#include "ppp.h"
#include "msg.h"
/*
* DEFINITIONS
*/
/* Which pipe file descriptor is which */
#define PIPE_READ 0
#define PIPE_WRITE 1
struct mpmsg
{
int type;
void (*func)(int type, void *arg);
void *arg;
};
typedef struct mpmsg *Msg;
struct msghandler
{
void (*func)(int type, void *arg);
};
int msgpipe[2];
EventRef msgevent;
int pipelen = 0;
/*
* INTERNAL FUNCTIONS
*/
static void MsgEvent(int type, void *cookie);
/*
* MsgRegister()
*/
MsgHandler
MsgRegister(void (*func)(int type, void *arg))
{
MsgHandler m;
m = Malloc(MB_UTIL, sizeof(*m));
m->func = func;
if ((msgpipe[0]==0) || (msgpipe[1]==0)) {
if (pipe(msgpipe) < 0)
{
Perror("%s: Can't create message pipe",
__FUNCTION__);
DoExit(EX_ERRDEAD);
}
fcntl(msgpipe[PIPE_READ], F_SETFD, 1);
fcntl(msgpipe[PIPE_WRITE], F_SETFD, 1);
if (fcntl(msgpipe[PIPE_WRITE], F_SETFL, O_NONBLOCK) < 0) {
Perror("%s: fcntl", __FUNCTION__);
}
if (EventRegister(&msgevent, EVENT_READ,
msgpipe[PIPE_READ], EVENT_RECURRING, MsgEvent, NULL) < 0)
{
Perror("%s: Can't register event!", __FUNCTION__);
DoExit(EX_ERRDEAD);
}
}
return(m);
}
/*
* MsgUnRegister()
*/
void
MsgUnRegister(MsgHandler *m)
{
Freee(MB_UTIL, *m);
*m = NULL;
}
/*
* MsgEvent()
*/
static void
MsgEvent(int type, void *cookie)
{
int nread, nrode;
struct mpmsg msg;
for (nrode = 0; nrode < sizeof(msg); nrode += nread) {
if ((nread = read(msgpipe[PIPE_READ],
(u_char *) &msg + nrode, sizeof(msg) - nrode)) < 0) {
Perror("%s: Can't read from message pipe", __FUNCTION__);
DoExit(EX_ERRDEAD);
}
if (nread == 0) {
Log(LG_ERR, ("%s: Unexpected EOF on message pipe!", __FUNCTION__));
DoExit(EX_ERRDEAD);
}
}
SETOVERLOAD(--pipelen);
(*msg.func)(msg.type, msg.arg);
}
/*
* MsgSend()
*/
void
MsgSend(MsgHandler m, int type, void *arg)
{
struct mpmsg msg;
int nw, nwrote, retry;
if (m == NULL)
return;
SETOVERLOAD(++pipelen);
msg.type = type;
msg.func = m->func;
msg.arg = arg;
for (nwrote = 0, retry = 10; nwrote < sizeof(msg) && retry > 0; nwrote += nw, retry--) {
if ((nw = write(msgpipe[PIPE_WRITE],
((u_char *) &msg) + nwrote, sizeof(msg) - nwrote)) < 0) {
Perror("%s: Message pipe write error", __FUNCTION__);
DoExit(EX_ERRDEAD);
}
}
if (nwrote < sizeof(msg)) {
Log(LG_ERR, ("%s: Can't write to message pipe, fatal pipe overflow!",
__FUNCTION__));
DoExit(EX_ERRDEAD);
}
}
/*
* MsgName()
*/
const char *
MsgName(int msg)
{
switch (msg)
{
case MSG_OPEN:
return("OPEN");
case MSG_CLOSE:
return("CLOSE");
case MSG_UP:
return("UP");
case MSG_DOWN:
return("DOWN");
default:
return("???");
}
}
syntax highlighted by Code2HTML, v. 0.9.1