/************************************************************************
* IRC - Internet Relay Chat, iauth/mod_pipe.c
* Copyright (C) 1999 Christophe Kalt
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 1, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef lint
static char rcsid[] = "@(#)$Id: mod_pipe.c,v 1.3 1999/03/11 19:53:20 kalt Exp $";
#endif
#include "os.h"
#include "a_defines.h"
#define MOD_PIPE_C
#include "a_externs.h"
#undef MOD_PIPE_C
/*
* pipe_init
*
* This procedure is called when a particular module is loaded.
* Returns NULL if everything went fine,
* an error message otherwise.
*/
char *
pipe_init(self)
AnInstance *self;
{
if (self->opt == NULL)
return "Aie! no option(s): nothing to be done!";
if (strncasecmp(self->opt, "prog=", 5))
return "Aie! unknown option(s): nothing to be done!";
self->popt = self->opt + 5;
return self->popt;
}
/*
* pipe_release
*
* This procedure is called when a particular module is unloaded.
void
pipe_release(self)
AnInstance *self;
{
}
*/
/*
* pipe_stats
*
* This procedure is called regularly to update statistics sent to ircd.
void
pipe_stats(self)
AnInstance *self;
{
}
*/
/*
* pipe_start
*
* This procedure is called to start an authentication.
* Returns 0 if everything went fine,
* -1 otherwise (nothing to be done, or failure)
*
* It is responsible for sending error messages where appropriate.
* In case of failure, it's responsible for cleaning up (e.g. pipe_clean
* will NOT be called)
*/
int
pipe_start(cl)
u_int cl;
{
int pp[2], rc;
DebugLog((ALOG_DPIPE, 0, "pipe_start(%d): Forking for %s %u", cl,
cldata[cl].itsip, cldata[cl].itsport));
if (pipe(pp) == -1)
{
DebugLog((ALOG_DPIPE, 0,
"pipe_start(%d): Error creating pipe: %s",
cl, strerror(errno)));
return -1;
}
switch (rc = vfork())
{
case -1 :
DebugLog((ALOG_DPIPE, 0,
"pipe_start(%d): Error forking: %s",
cl, strerror(errno)));
return -1;
case 0 :
{
(void)close(pp[0]);
for (rc = 2; rc < MAXCONNECTIONS; rc++)
if (rc != pp[1])
(void)close(rc);
if (pp[1] != 2)
(void)dup2(pp[1], 2);
(void)dup2(2, 1);
if (pp[1] != 2 && pp[1] != 1)
(void)close(pp[1]);
(void)execlp(cldata[cl].instance->popt,
cldata[cl].instance->popt,
cldata[cl].itsip, cldata[cl].itsport);
_exit(-1);
}
default :
(void)close(pp[1]);
break;
}
cldata[cl].rfd = pp[0];
return 0;
}
/*
* pipe_work
*
* This procedure is called whenever there's new data in the buffer.
* Returns 0 if everything went fine, and there is more work to be done,
* Returns -1 if the module has finished its work (and cleaned up).
*
* It is responsible for sending error messages where appropriate.
*/
int
pipe_work(cl)
u_int cl;
{
DebugLog((ALOG_DPIPE, 0, "pipe_work(%d): %d %d buflen=%d %c", cl,
cldata[cl].rfd, cldata[cl].wfd, cldata[cl].buflen,
cldata[cl].inbuffer[0]));
switch (cldata[cl].inbuffer[0])
{
case 'Y':
break;
case 'N':
cldata[cl].state |= A_DENY;
sendto_ircd("K %d %s %u ", cl, cldata[cl].itsip,
cldata[cl].itsport);
break;
#if 0
/* hm.. need deeper mods to ircd */
case 'y':
/* restricted connection only */
cldata[cl].state |= A_RESTRICT;
sendto_ircd("k %d %s %u ", cl, cldata[cl].itsip,
cldata[cl].itsport);
break;
#endif
default :
/* error */
sendto_log(ALOG_FLOG|ALOG_IRCD, LOG_WARNING,
"pipe: unexpected %c for %s[%s]",
cldata[cl].inbuffer[0],
cldata[cl].host,
cldata[cl].itsip);
break;
}
/* We're done */
close(cldata[cl].rfd);
cldata[cl].rfd = 0;
return -1;
}
/*
* pipe_clean
*
* This procedure is called whenever the module should interrupt its work.
* It is responsible for cleaning up any allocated data, and in particular
* closing file descriptors.
*/
void
pipe_clean(cl)
u_int cl;
{
DebugLog((ALOG_DPIPE, 0, "pipe_clean(%d): cleaning up", cl));
if (cldata[cl].rfd)
close(cldata[cl].rfd);
cldata[cl].rfd = 0;
}
/*
* pipe_timeout
*
* This procedure is called whenever the timeout set by the module is
* reached.
*
* Returns 0 if things are okay, -1 if authentication was aborted.
*/
int
pipe_timeout(cl)
u_int cl;
{
DebugLog((ALOG_DPIPE, 0, "pipe_timeout(%d): calling pipe_clean ",
cl));
pipe_clean(cl);
return -1;
}
aModule Module_pipe =
{ "pipe", pipe_init, NULL, NULL,
pipe_start, pipe_work, pipe_timeout, pipe_clean };
syntax highlighted by Code2HTML, v. 0.9.1