|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T t
Length: 7490 (0x1d42)
Types: TextFile
Names: »tofilter.c«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
└─⟦6429e39db⟧ »EurOpenD3/news/tmnn.7.8.tar.Z«
└─⟦b5a65d78b⟧
└─⟦this⟧ »src/D.filt/tofilter.c«
/*****************************************************************************
NAME
tofilter.c -- comm primitives for reader/newsfilter transactions
SYNOPSIS
#include "libfilt.h"
char *fltinfo;
int fltinit(filter, flang, fversion) -- initialize filter, check version
char *filter, *flang, *fversion;
int fltarticle(id, file) -- return `interest score' of article
char *id, *file;
int fltnewsgroup(name) -- return `interest score' of group
char *name;
int fltprogram(command) -- program the filter
char *command;
int fltbye(filter) -- drop the named filter
char *filter;
DESCRIPTION
These functions may be used by a reader to communicate with a news
filter program.
The fltinit() function invokes the filter process. The arguments are a
filter process name and an expected version level. The function returns
FAIL if the process cannot be invoked, TRUE if the newsfilter returns a
language name different than the elang one given, or if the version string
lexically greater than the expect string, FALSE otherwise.
The fltarticle() function conducts all necessary dialogue with the
newsfilter to determine the `interest score' of an article, which it returns.
If fltinit() failed or the filter process has died it returns a constant value
of 0. The filename argument is optional; if NULL, the protocol will exchange
portions of the article over pipes or some other form of IPC to the filter.
The fltnewsgroup() function performs a similar service for newsgroups. A
score of zero designates a newsgroup for which fltarticle() should be called
individually on each article.
The fltprogram() function downloads filter-command code to the newsfilter.
Interpretation of this code is entirely up to the newsfilter, which may conduct
a query dialogue with the reader (as with the fltarticle() function) to obtain
portions of the article needed to interpret the command. The filename argument
is optional; if NULL, the protocol will exchange portions of the article over
pipes or some other form of IPC to the filter.
The fltbye() command disconnects from a named filter. If the argument is
NULL, all filters are dropped.
NOTE
This code can be exercised from newsdb(1).
At present, only one filter process per reader is supported. Someday
this library will support filter stacks; for this reasion, fltbye() takes
a filter name argument which is currently not used.
AUTHOR
Eric S. Raymond, from a protocol spec developed with Brad Templeton.
This software is Copyright (C) 1989 by Eric S. Raymond for the sole purpose
of protecting free redistribution; see the LICENSE file for details.
*****************************************************************************/
/* LINTLIBRARY */
#include "news.h"
#include "vio.h"
#include "header.h"
#include "active.h"
#include "procopts.h"
#include "server.h"
#include "transact.h"
#include "libfilt.h"
#define STARTTIME 20 /* allow this many seconds of startup time */
char *fltinfo;
static bool filteron = FALSE;
static fresp_t resp;
static int ftransact(type, code, arg1, arg2, arg3, arg4, arg5)
char type;
char code;
char *arg1, *arg2, *arg3, *arg4, *arg5;
{
static int seqno = 0;
if (ftransmit(type, code, ++seqno, arg1, arg2, arg3, arg4, arg5)==FAIL)
return(FAIL);
else if (freceive(&resp) == FAIL)
return(FAIL);
else
return(seqno);
}
static catch_t deadkid()
{
msg0("Newsfilter process aborted!");
filteron = FALSE;
}
int fltinit(filt, flang, fversion)
char *filt, *flang, *fversion;
{
server_t *srv;
int ansok;
catch_t (*oalarm)();
char *largv[MAXARGS], *defilt, *deflang, *p;
char pathbuf[BUFLEN];
/* figure out who we ought to be invoking */
if ((defilt = getenv("NEWSFILTER")) == (char *)NULL)
defilt = "rnkill";
if ((deflang = strchr(defilt, ':')) != (char *)NULL)
*deflang++ = '\0';
else
deflang = defilt;
if (filt == (char *)NULL)
filt = defilt;
if (flang == (char *)NULL)
flang = deflang;
/* in case child dies, avoid this signal */
(void) signal(SIGPIPE, deadkid);
/* OK, let's go open the relevant process now */
#ifdef DEBUG
if (debug)
(void) sprintf(bfr, "%s -D -p", filt);
else
#endif /* DEBUG */
(void) sprintf(bfr, "%s -p", filt);
(void) vcrack(bfr, largv, MAXARGS);
/* wedge the user's dot-file directory into his/her execution path */
if ((p = getenv("DOTDIR")) == (char *)NULL)
p = userhome;
(void) strcpy(pathbuf, p);
if (p = getenv("PATH"))
{
if (*p != ':')
(void) strcat(pathbuf, ":");
(void) strcat(pathbuf, p);
}
(void) setenv("PATH", pathbuf);
if ((srv = srvopen(filt, largv)) == (server_t *)NULL)
return(FAIL);
/* tell the packet level about it */
fconnect(srv->readsrv, srv->writesrv);
/* expect the initial 'version' pseudo-response from the filter */
oalarm = signal(SIGALRM, SIG_IGN);
(void) alarm(STARTTIME); /* give process time to start */
ansok = freceive(&resp); /* look for a 'response' */
(void) signal(SIGALRM, oalarm); /* we got one, or were alarmed */
(void) alarm(0);
fltinfo = "";
if (ansok == FAIL || resp.code != 'O')
{
msg1("Filter \"%s\" could not be spawned.", filt);
(void) kill(srv->pid, SIGKILL);
return(FAIL);
}
else if (ftransact('C','V',VPROTO, NOARG,NOARG,NOARG,NOARG) == FAIL)
{
msg1("Filter \"%s\" is not responding!", filt);
(void) kill(srv->pid, SIGKILL);
return(FAIL);
}
else if (resp.code != 'V')
{
msg1("Filter \"%s\" sent back an incorrect Version response!", filt);
(void) kill(srv->pid, SIGKILL);
return(FAIL);
}
else if (strcmp(flang, resp.arg4))
{
msg1("Filter \"%s\" did not return the expected language!", filt);
(void) kill(srv->pid, SIGKILL);
return(FAIL);
}
else if (atoi(resp.arg1 + 1) < atoi(fversion + 1))
{
msg3("%s protocol version (%s) doesn't match reader's (%s)!",
filt, resp.arg1, fversion);
(void) kill(srv->pid, SIGKILL);
return(FAIL);
}
else
{
filteron = TRUE;
return(SUCCEED);
}
}
int fltarticle(id, fn)
/* get an accept-reject status for a given article */
char *id, *fn;
{
if (!filteron)
{
fltinfo = "";
return(0);
}
(void) ftransact('C','A', id, "F", fn, NOARG, NOARG);
if (resp.code == 'A' || resp.code == 'R')
{
fltinfo = resp.arg2;
return(atoi(resp.arg1));
}
else
{
fltinfo = resp.arg1;
return(0);
}
}
int fltnewsgroup(name)
/* get an accept-reject status for a newsgroup */
char *name;
{
if (!filteron)
{
fltinfo = "";
return(0);
}
(void) ftransact('C', 'N', name, NOARG, NOARG, NOARG, NOARG);
if (resp.code == 'O')
{
fltinfo = resp.arg1;
return(0);
}
else
{
fltinfo = resp.arg2;
return(atoi(resp.arg1));
}
}
int fltprogram(command)
/* program the filter */
char *command;
{
if (!filteron)
{
fltinfo = "";
return(FAIL);
}
(void) ftransact('C', 'P', command, NOARG, NOARG, NOARG, NOARG);
fltinfo = resp.arg1;
if (resp.code == 'O') /* everything is OK */
return(SUCCEED);
else
return(FAIL); /* we returned an error */
}
/*ARGSUSED1*/
int fltbye(filtername)
/* drop the filter */
char *filtername;
{
if (!filteron)
{
fltinfo = "";
return(0);
}
(void) ftransact('C', 'Q', NOARG, NOARG, NOARG, NOARG, NOARG);
fltinfo = resp.arg1;
if (resp.code == 'O')
return(SUCCEED);
else
return(FAIL);
}
/* tofilter.c ends here */