	Opening agents on behalf of other applets

<<*>>=
#include "config.h"
#include <Xm/Xm.h>
#include "w3a.h"
#include <errno.h>
#include "str.h"
#include "url.h"
#include "rcfile.e"
#include "globals.e"
#include "dynload.e"

typedef struct _AgentAssoc {
    int agent;
    int fd;
    struct _AgentAssoc *next;
} *AgentAssoc;

static AgentAssoc agent_assoc = NULL;


EXPORT int W3AopenDoc(const char *url, int method, int flags,
    const char *referer)
{
    int a, fd;
    URI uri, base;
    AgentAssoc assoc;
    char *localurl;

    /* Check and maybe expand the URL */
    if (!URL_parse(url, &uri)) {errno = EURL; return -1;}
    if (uri.tp = URI_Rel) {
        if (!URL_parse(url, &base)) {errno = EURL; return -1;};
        URL_expand(&uri, base);
        url = uri2str(uri);
    }
    if (uri.tp != URI_URL) {errno = EURL; return -1;}

    if (appdata.proxy) {
	newarray(localurl, strlen(appdata.proxy) + strlen(url) + 1);
	strcat(strcpy(localurl, appdata.proxy), url);
	a = find_agent("http");
    } else {
	localurl = newstring(url);
	a = find_agent(strip2str(uri.scheme));
    }
    if (a == -1) {errno = ETYPE; return -1;}	/* No matching agent found */
    fd = agent_open(a, url, method, flags, referer); /* New agent instance */
    if (fd == -1) return -1;			/* Agent reported an error */
    dispose(localurl);
    new(assoc);					/* Store fd and agent info */
    assoc->agent = a;
    assoc->fd = fd;
    assoc->next = agent_assoc;
    agent_assoc = assoc;
    return fd;					/* Return file descriptor */
}

EXPORT int W3AreadDoc(int fd, char *buf, size_t nbytes)
{
    AgentAssoc a;

    for (a = agent_assoc; a->fd != fd; a = a->next)  assert(a);
    return agent_read(a->agent, fd, buf, nbytes);
}

EXPORT int W3AwriteDoc(int fd, const char *buf, size_t nbytes)
{
    AgentAssoc a;

    for (a = agent_assoc; a->fd != fd; a = a->next) assert(a);
    return agent_write(a->agent, fd, buf, nbytes);
}

EXPORT Bool W3AcloseDoc(int fd)
{
    AgentAssoc a, h;
    int agent;

    if (agent_assoc->fd == fd) {		/* Remove first assoc */
        agent = agent_assoc->agent;
        h = agent_assoc;
        agent_assoc = agent_assoc->next;
        dispose(h);
    } else {					/* Remove from list */
        for (a = agent_assoc; a->next->fd != fd; a = a->next) assert(a->next);
        h = a->next;
        agent = h->agent;
        a->next = h->next;
        dispose(h);
    }
    return agent_close(agent, fd);
}


EXPORT Bool W3AinfoDoc(int fd, W3ADocumentInfo *info)
{
    AgentAssoc a;

    for (a = agent_assoc; a->fd != fd; a = a->next) assert(a);
    return agent_info(a->agent, fd, info);
}


EXPORT Bool W3AdeleteDoc(const char *url, const char *referer)
{
    int a;
    URI uri, base;

    /* Check and maybe expand URL */
    if (!URL_parse(url, &uri)) {errno = EURL; return -1;}
    if (uri.tp = URI_Rel) {
        if (!URL_parse(url, &base)) {errno = EURL; return -1;};
        URL_expand(&uri, base);
        url = uri2str(uri);
    }
    if (uri.tp != URI_URL) {errno = EURL; return -1;}
    a = find_agent(strip2str(uri.scheme));	/* Find and load agent */
    if (a == -1) {errno = ETYPE; return -1;}	/* No matching agent found */
    return agent_delete(a, url);		/* Use agent to delete doc. */
}


