chimera2/ext/ext.c

317 lines
5.8 KiB
C

/*
* ext.c
*
* Copyright (c) 1995-1997, John Kilburg <john@cs.unlv.edu>
*
* 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 2 of the License, 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.
*/
#include "port_before.h"
#include <stdio.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include <signal.h>
#include <errno.h>
#include "port_after.h"
#include "Chimera.h"
typedef struct
{
char *use;
char *incontent;
char *outcontent;
char *command;
} ConvertEntry;
typedef struct
{
MemPool mp;
ChimeraSink wp;
ChimeraRender wn;
ChimeraGUI wd;
ChimeraRender own;
ChimeraRenderHooks *orh;
ConvertEntry *c;
int fd[2];
size_t i;
} ExtInfo;
typedef struct
{
MemPool mp;
GList list;
} ExtModuleInfo;
static void ExtDestroy _ArgProto((void *));
static void *ExtInit _ArgProto((ChimeraRender, void *));
static void ExtAdd _ArgProto((void *));
static void ExtEnd _ArgProto((void *));
static void ExtCancel _ArgProto((void *));
static GList ReadConvertFiles _ArgProto((MemPool, char *));
/*
* ExtDestroy
*/
static void
ExtDestroy(closure)
void *closure;
{
ExtInfo *ei = (ExtInfo *)closure;
MPDestroy(ei->mp);
return;
}
/*
* ExtAdd
*/
static void
ExtAdd(closure)
void *closure;
{
ExtInfo *ei = (ExtInfo *)closure;
byte *data;
size_t len;
GList mimelist;
ssize_t rval;
SinkGetData(ei->wp, &data, &len, &mimelist);
if (len <= ei->i) return;
if ((rval = write(ei->fd[0], data + ei->i, len - ei->i)) <= 0)
{
perror("ext write add");
return;
}
ei->i += rval;
return;
}
/*
* ExtEnd
*/
static void
ExtEnd(closure)
void *closure;
{
ExtInfo *ei = (ExtInfo *)closure;
byte *data;
size_t len;
GList mimelist;
ssize_t rval;
char buffer[BUFSIZ];
SinkGetData(ei->wp, &data, &len, &mimelist);
while (len > ei->i)
{
if ((rval = write(ei->fd[0], data + ei->i, len - ei->i)) <= 0)
{
perror("ext write end");
return;
}
ei->i += rval;
}
close(ei->fd[0]);
/*
while (read(ei->fd[1], buffer, sizeof(buffer)) > 0)
;
*/
close(ei->fd[1]);
return;
}
/*
* ExtCancel
*/
static void
ExtCancel(closure)
void *closure;
{
return;
}
/*
* ExtInit
*/
static void *
ExtInit(wn, closure)
ChimeraRender wn;
void *closure;
{
SinkData wp;
char *content;
ConvertEntry *c;
ExtModuleInfo *emi = (ExtModuleInfo *)closure;
ExtInfo *ei;
MemPool mp;
ChimeraRenderHooks *orh;
wp = RenderToSink(wn);
content = SinkGetInfo(wp, "content-type");
for (c = (ConvertEntry *)GListGetHead(emi->list); c != NULL;
c = (ConvertEntry *)GListGetNext(emi->list))
{
if (strcasecmp(content, c->incontent) == 0) break;
}
if (c == NULL) return(NULL);
/*
orh = WWWGetRenderHooks(WWWGetRenderContext(wn), c->outcontent);
if (orh == NULL) return(NULL);
*/
mp = MPCreate();
ei = (ExtInfo *)MPCGet(mp, sizeof(ExtInfo));
ei->mp = mp;
ei->c = c;
ei->wd = RenderToGUI(wn);
ei->wp = wp;
ei->wn = wn;
ei->orh = orh;
if (PipeCommand(c->command, ei->fd) == -1)
{
MPDestroy(mp);
return(NULL);
}
return(ei);
}
/*
* ReadConvertFiles
*
* Reads in the convert entries in a list of files separated by colons.
* For example,
*
* ~/.chimera_convert:~john/lib/convert:/local/infosys/lib/convert
*/
GList
ReadConvertFiles(mp, filelist)
MemPool mp;
char *filelist;
{
ConvertEntry *c;
char *f;
char *filename;
char buffer[BUFSIZ];
char use[BUFSIZ];
char incontent[BUFSIZ];
char outcontent[BUFSIZ];
char command[BUFSIZ];
FILE *fp;
GList list;
list = GListCreateX(mp);
f = filelist;
while ((filename = mystrtok(f, ':', &f)) != NULL)
{
filename = FixPath(mp, filename);
if (filename == NULL) continue;
fp = fopen(filename, "r");
if (fp == NULL) continue;
while (fgets(buffer, sizeof(buffer), fp) != NULL)
{
if (buffer[0] == '#' || buffer[0] == '\n') continue;
if (sscanf(buffer, "%s %s %s %[^\n]",
use, incontent, outcontent, command) == 4)
{
c = (ConvertEntry *)MPCGet(mp, sizeof(ConvertEntry));
c->use = MPStrDup(mp, use);
c->incontent = MPStrDup(mp, incontent);
c->outcontent = MPStrDup(mp, outcontent);
c->command = strcasecmp(command, "none") == 0 ?
NULL:MPStrDup(mp, command);
GListAddTail(list, c);
}
}
fclose(fp);
}
return(list);
}
void
InitModule_Ext(cres)
ChimeraResources cres;
{
ChimeraRenderHooks rh;
char *clist;
ExtModuleInfo *emi;
GList list;
MemPool mp;
ConvertEntry *c;
if ((clist = ResourceGetString(cres, "convert.convertFiles")) == NULL)
{
clist = "~/.chimera/convert";
}
mp = MPCreate();
list = ReadConvertFiles(mp, clist);
if (GListEmpty(list))
{
MPDestroy(mp);
return;
}
emi = (ExtModuleInfo *)MPCGet(mp, sizeof(ExtModuleInfo));
emi->mp = mp;
emi->list = list;
for (c = (ConvertEntry *)GListGetHead(list); c != NULL;
c = (ConvertEntry *)GListGetNext(list))
{
memset(&rh, 0, sizeof(ChimeraRenderHooks));
rh.content = c->incontent;
rh.class_context = emi;
rh.class_destroy = ExtDestroy;
rh.init = ExtInit;
rh.add = ExtAdd;
rh.end = ExtEnd;
rh.destroy = ExtDestroy;
rh.cancel = ExtCancel;
RenderAddHooks(cres, &rh);
}
return;
}