Intial commit
This commit is contained in:
1
prospero/lib/psrv/gopher_gw/.gitignore
vendored
Normal file
1
prospero/lib/psrv/gopher_gw/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Makefile
|
||||
6
prospero/lib/psrv/gopher_gw/FILES
Normal file
6
prospero/lib/psrv/gopher_gw/FILES
Normal file
@@ -0,0 +1,6 @@
|
||||
FILES
|
||||
Makefile
|
||||
glalloc.c
|
||||
goph_gw_dsdb.c
|
||||
goph_gw_mutex.c
|
||||
gopher.h
|
||||
47
prospero/lib/psrv/gopher_gw/Makefile.in
Executable file
47
prospero/lib/psrv/gopher_gw/Makefile.in
Executable file
@@ -0,0 +1,47 @@
|
||||
SOURCEBASE = ../../..
|
||||
include $(SOURCEBASE)/Makefile.config
|
||||
|
||||
CFILES = \
|
||||
glalloc.c \
|
||||
goph_gw_dsdb.c \
|
||||
goph_gw_mutex.c
|
||||
|
||||
OBJECTS = \
|
||||
glalloc.o \
|
||||
goph_gw_dsdb.o \
|
||||
goph_gw_mutex.o
|
||||
|
||||
OTHERTARGETS = ${GOPHER_GW_LIB}
|
||||
|
||||
all: ${GOPHER_GW_LIB}
|
||||
|
||||
${GOPHER_GW_LIB}: ${OBJECTS}
|
||||
rm -f ${GOPHER_GW_LIB}
|
||||
ar r${AR_FLAGS} ${GOPHER_GW_LIB} ${OBJECTS}
|
||||
$(RANLIB) ${GOPHER_GW_LIB}
|
||||
|
||||
# Dependencies
|
||||
glalloc.o : ../../../include/pfs.h \
|
||||
../../../include/pfs_utils.h ../../../include/ardp.h \
|
||||
../../../include/pfs_threads.h \
|
||||
../../../include/list_macros.h \
|
||||
../../../include/../lib/ardp/flocks.h ../../../include/implicit_fixes.h \
|
||||
../../../include/pmachine.h \
|
||||
../../../include/psrv.h ../../../include/pparse.h \
|
||||
gopher.h ../../../include/mitra_macros.h
|
||||
goph_gw_dsdb.o : \
|
||||
../../../include/pmachine.h \
|
||||
../../../include/pserver.h \
|
||||
../../../include/ardp.h \
|
||||
../../../include/pfs_threads.h ../../../include/pfs_utils.h \
|
||||
../../../include/list_macros.h \
|
||||
../../../include/../lib/ardp/flocks.h ../../../include/pfs.h \
|
||||
../../../include/implicit_fixes.h \
|
||||
../../../include/psrv.h ../../../include/pparse.h \
|
||||
../../../include/perrno.h ../../../include/plog.h gopher.h
|
||||
goph_gw_mutex.o : gopher.h \
|
||||
../../../include/pfs_threads.h \
|
||||
../../../include/pfs_utils.h ../../../include/pfs.h ../../../include/ardp.h \
|
||||
../../../include/list_macros.h \
|
||||
../../../include/../lib/ardp/flocks.h ../../../include/implicit_fixes.h \
|
||||
../../../include/pmachine.h
|
||||
58
prospero/lib/psrv/gopher_gw/glalloc.c
Normal file
58
prospero/lib/psrv/gopher_gw/glalloc.c
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-license.h>.
|
||||
*/
|
||||
|
||||
#include <usc-license.h>
|
||||
#include <pfs.h>
|
||||
#include <psrv.h>
|
||||
#include "gopher.h"
|
||||
#include <mitra_macros.h>
|
||||
|
||||
static GLINK lfree = NULL;
|
||||
int glink_count = 0;
|
||||
int glink_max = 0;
|
||||
|
||||
|
||||
/*
|
||||
glalloc(): Allocate and initialize GLINK structure.
|
||||
Signal out_of_memory() on failure.
|
||||
*/
|
||||
|
||||
GLINK
|
||||
glalloc(void)
|
||||
{
|
||||
GLINK gl;
|
||||
|
||||
TH_STRUC_ALLOC(glink,GLINK,gl);
|
||||
/* Initialize and fill in default values */
|
||||
gl->type = '0';
|
||||
gl->name = NULL;
|
||||
gl->selector = NULL;
|
||||
gl->host = NULL;
|
||||
gl->port = 0;
|
||||
gl->protocol_mesg = NULL;
|
||||
return gl;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
glfree(GLINK gl)
|
||||
{
|
||||
/* Free any bits of memory pointed to by members of the structure. */
|
||||
if (gl->name) stfree(gl->name);
|
||||
if (gl->host) stfree(gl->host);
|
||||
if (gl->selector) stfree(gl->selector);
|
||||
if (gl->protocol_mesg) stfree(gl->protocol_mesg);
|
||||
/* Free the structure itself. */
|
||||
TH_STRUC_FREE(glink,GLINK,gl);
|
||||
}
|
||||
|
||||
void
|
||||
gllfree(GLINK gl)
|
||||
{
|
||||
TH_STRUC_LFREE(GLINK,gl,glfree)
|
||||
}
|
||||
|
||||
867
prospero/lib/psrv/gopher_gw/goph_gw_dsdb.c
Normal file
867
prospero/lib/psrv/gopher_gw/goph_gw_dsdb.c
Normal file
@@ -0,0 +1,867 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-license.h>.
|
||||
*/
|
||||
|
||||
#include <usc-license.h>
|
||||
|
||||
/* Definitions of constants */
|
||||
#define MAX_NUM_GOPHER_LINKS 3000 /* maximum # of directory links to
|
||||
return before giving up. */
|
||||
|
||||
/* Archie server we redirect ftp:hostname@ queries to. */
|
||||
/* Don't define this for now, since it can lead to odd results. */
|
||||
/* #define ARCHIE_SERVER "ARCHIE.SURA.NET" */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h> /* includes SOL_SOCKET */
|
||||
#include <netinet/in.h>
|
||||
#include <sys/uio.h> /* for writev(), struct iovec */
|
||||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
#include <pmachine.h>
|
||||
|
||||
#include <pserver.h>
|
||||
#include <ardp.h> /* unixerrstr() prototype. */
|
||||
#include <pfs.h> /* assert, internal_error, prototypes */
|
||||
#include <psrv.h>
|
||||
#include <perrno.h>
|
||||
#include <plog.h>
|
||||
#include "gopher.h"
|
||||
#include <string.h>
|
||||
#ifdef PSRV_WAIS_GW
|
||||
#include <wais-source.h>
|
||||
#include <psite.h> /* For WAIS_SOURCE_DIR */
|
||||
#endif
|
||||
|
||||
/* 5 secs seems a bit short for this */
|
||||
#ifndef G_OPEN_TIMEOUT
|
||||
#define G_OPEN_TIMEOUT 10
|
||||
#endif
|
||||
#ifndef G_READ_TIMEOUT
|
||||
#define G_READ_TIMEOUT 10
|
||||
#endif
|
||||
|
||||
#ifndef GFTP_READ_TIMEOUT
|
||||
#define GFTP_READ_TIMEOUT 20
|
||||
#endif
|
||||
|
||||
#ifndef GSEARCH_READ_TIMEOUT
|
||||
#define GSEARCH_READ_TIMEOUT 30
|
||||
#endif
|
||||
|
||||
extern char hostwport[];
|
||||
extern int quick_open_tcp_stream(char host[], int port, int timeout);
|
||||
extern char *quick_fgets(char *s, int n, FILE *stream, int timeout);
|
||||
|
||||
static GLINK quick_get_menu(char *host, int port, char *selector, int tme);
|
||||
static void glinks_to_dirob(GLINK glist, P_OBJECT ob);
|
||||
static void atput(VLINK vl, char *name,...);
|
||||
static void ftp_check_am(GLINK gl, VLINK r, char *textorbin);
|
||||
static void ftp_check_dir(GLINK gl, VLINK r);
|
||||
static int wais_check_dir(GLINK gl, VLINK r);
|
||||
static void zap_trailing_spaces(char *host);
|
||||
|
||||
|
||||
/* This function is passed an empty object which has been initialized with
|
||||
oballoc(). It returns a possibly populated directory and
|
||||
DIRSRV_NOT_FOUND or PSUCCESS. Note that the directory will need
|
||||
to have links within it freed, even if an error code is returned. */
|
||||
|
||||
/* This sets p_warn_string and pwarn if an unrecognized gopher line is
|
||||
received. That is good. */
|
||||
|
||||
/* This code needs to return attributes in response to a GET-OBJECT-INFO query.
|
||||
*/
|
||||
int
|
||||
gopher_gw_dsdb(RREQ req, /* Request pointer (unused) */
|
||||
char *hsoname, /* Name of the directory */
|
||||
long version,/* Version #; currently ignored */
|
||||
long magic_no, /* Magic #; currently ignored */
|
||||
int flags, /* Currently only recognize DRO_VERIFY */
|
||||
struct dsrobject_list_options *listopts, /* options (use *remcompp
|
||||
and *thiscompp) */
|
||||
P_OBJECT ob)
|
||||
{ /* Object to be filled in */
|
||||
int tmp;
|
||||
char *cp;
|
||||
AUTOSTAT_CHARPP(hostp); /* For threads. */
|
||||
int port;
|
||||
char type;
|
||||
char *selectorcp; /* a character pointer that might point to the
|
||||
first part of the selector or possibly the
|
||||
complete selector. */
|
||||
char *selector; /* the final selector */
|
||||
GLINK glist; /* list of gopher links */
|
||||
int timeout; /* Timeout for lines (not connect) */
|
||||
|
||||
ob->version = 0; /* unversioned */
|
||||
ob->inc_native = VDIN_PSEUDO;
|
||||
ob->flags = P_OBJECT_DIRECTORY;
|
||||
ob->magic_no = 0;
|
||||
ob->acl = NULL;
|
||||
tmp = qsscanf(hsoname, "GOPHER-GW/%&[^(](%d)/%c%r/%r",
|
||||
hostp, &port, &type, &cp, &selectorcp);
|
||||
if (tmp < 4)
|
||||
return DIRSRV_NOT_FOUND;
|
||||
|
||||
if (type == '1') {
|
||||
if (tmp < 5)
|
||||
return DIRSRV_NOT_FOUND;
|
||||
selector = selectorcp;
|
||||
} else if (type == '7') {
|
||||
AUTOSTAT_CHARPP(sp); /* Memory allocated for selector */
|
||||
if (tmp < 4)
|
||||
return DIRSRV_NOT_FOUND;
|
||||
else if (tmp == 4) {
|
||||
selectorcp = "";
|
||||
} /* if tmp = 5, selectorcp already set. */
|
||||
/* Now set the selector. */
|
||||
if (!listopts || !listopts->thiscompp || !*listopts->thiscompp ||
|
||||
strequal(*listopts->thiscompp, "")
|
||||
|| strequal(*listopts->thiscompp, "*"))
|
||||
/* last test against * might be inappropriate */
|
||||
return PSUCCESS; /* Display no contents for the directory */
|
||||
/* Set the selector. */
|
||||
selector = *sp = qsprintf_stcopyr(*sp, "%s%s%s", selectorcp,
|
||||
(*selectorcp) ? "\t" : "", *listopts->thiscompp);
|
||||
/* We just used up thiscompp, so we'd better reset it. */
|
||||
/* Oops - && here was meaningless */
|
||||
/* I changed this so that the else is not done if listopts->remcompp
|
||||
is null, in that case (as in when called by get_object_info)
|
||||
listopts->thiscompp is also null so "*listopts->thiscompp = NULL"
|
||||
generates a segment violation, if this is the case then we didnt
|
||||
use a component anyway, so no need to advance to the next */
|
||||
if (listopts->remcompp) {
|
||||
if (*listopts->remcompp) {
|
||||
*listopts->thiscompp = (*listopts->remcompp)->token;
|
||||
*listopts->remcompp = (*listopts->remcompp)->next;
|
||||
} else {
|
||||
*listopts->thiscompp = NULL;
|
||||
}
|
||||
}
|
||||
/* Now that the selector is set, fall through. */
|
||||
} else { /* unknown type for gatewaying */
|
||||
return DIRSRV_NOT_FOUND;
|
||||
}
|
||||
/* don't bother retrieving the contents if just verifying. */
|
||||
if (flags & DRO_VERIFY)
|
||||
return PSUCCESS;
|
||||
if (type == '7') {
|
||||
timeout = GSEARCH_READ_TIMEOUT;
|
||||
} else {
|
||||
if (strncmp(selector,"ftp:",4)== 0 ) {
|
||||
timeout = GFTP_READ_TIMEOUT;
|
||||
} else {
|
||||
timeout = G_READ_TIMEOUT;
|
||||
}
|
||||
}
|
||||
if ((glist = quick_get_menu(*hostp, port, selector, timeout))
|
||||
== NULL && perrno)
|
||||
return perrno;
|
||||
glinks_to_dirob(glist, ob);
|
||||
gllfree(glist);
|
||||
return PSUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static GLINK quick_next_menu_item(FILE * fp, int timeout);
|
||||
extern int p_open_tcp_stream(const char host[], int port);
|
||||
|
||||
/* Returns NULL & sets perrno on error. */
|
||||
static GLINK
|
||||
quick_get_menu(char *host, int port, char *selector, int timeout)
|
||||
{
|
||||
GLINK retval = NULL;
|
||||
GLINK gl;
|
||||
FILE *fp; /* used for reading only. Tried to use it for
|
||||
reading & writing without success; see
|
||||
comment below. */
|
||||
int fd;
|
||||
int tmp; /* return value from write() and read()*/
|
||||
int nlinks = 0; /* # of links in directory */
|
||||
#ifndef NO_IOVEC
|
||||
struct iovec iov[2];
|
||||
#endif
|
||||
|
||||
fd = quick_open_tcp_stream(host, port, G_OPEN_TIMEOUT);
|
||||
/* Copied from vcache */
|
||||
if (fd < 0) {
|
||||
perrno = DIRSRV_GOPHER; /* work on error reporting */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if ! defined(NO_IOVEC) && ! defined(PFS_THREADS)
|
||||
/* Current implementation of threads does not include writev(). */
|
||||
iov[0].iov_base = selector;
|
||||
iov[0].iov_len = strlen(selector);
|
||||
iov[1].iov_base = "\r\n";
|
||||
iov[1].iov_len = 2;
|
||||
tmp = writev(fd, iov, 2);
|
||||
if (tmp != iov[0].iov_len + iov[1].iov_len) {
|
||||
#else
|
||||
tmp = write(fd, selector, strlen(selector));
|
||||
if (tmp != strlen(selector)) {
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"Couldn't send selector to gopher \
|
||||
connection to %s: Call to write(%d,%s,%d) failed: errno %d: \
|
||||
%s", host, fd, selector, strlen(selector), errno, unixerrstr());
|
||||
redo_close:
|
||||
if(close(fd) == -1 && errno == EINTR) goto redo_close;
|
||||
perrno = DIRSRV_GOPHER;
|
||||
return NULL;
|
||||
}
|
||||
tmp = write(fd, "\r\n", 2);
|
||||
if (tmp != 2) {
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"Couldn't send selector to gopher \
|
||||
connection to %s: Call to write(%d, \"\\r\\n\", 2) failed: errno %d: %s",
|
||||
host, fd, errno, unixerrstr());
|
||||
#endif
|
||||
redo_close2:
|
||||
if(close(fd) == -1 && errno == EINTR) goto redo_close2;
|
||||
perrno = DIRSRV_GOPHER;
|
||||
return NULL;
|
||||
}
|
||||
fp = fdopen(fd, "r"); /* open fp just for reading */
|
||||
/* Comment from Alan Emtage of Bunyip Information Systems which explains
|
||||
why I'm treating the writing end as a raw file descriptor and the
|
||||
reading end through the stdio library:
|
||||
|
||||
From: bajan@bunyip.com (Alan Emtage)
|
||||
Date: Sat, 28 Aug 1993 10:01:32 -0400
|
||||
|
||||
Hi Steve,
|
||||
You have a comment in the gopher GW code to the effect that "this
|
||||
experiment didn't work.... if you know why, tell me". Well I will :-)
|
||||
|
||||
For some reason which I haven't figured out, you can't a _socket_ file
|
||||
descriptor with fdopen in any form of update mode (you were trying to do
|
||||
it with "r+"). However it can be done if you open the fd _twice_. One
|
||||
FILE * for reading one for writing. Then everything works fine. What is
|
||||
going on in the underlying layers I don't know, but I'd bet that the
|
||||
symptoms you got was that you were reading things that you had
|
||||
previously written to the FILE * (and thought had just gone down the
|
||||
pipe to the remote connection).
|
||||
|
||||
Hope this helps.
|
||||
|
||||
-Alan
|
||||
*/
|
||||
perrno = PSUCCESS;
|
||||
while (gl = quick_next_menu_item(fp,timeout)) {
|
||||
if (++nlinks > MAX_NUM_GOPHER_LINKS) {
|
||||
perrno = DIRSRV_TOO_MANY;
|
||||
gllfree(retval);
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
APPEND_ITEM(gl, retval);
|
||||
}
|
||||
fclose(fp);
|
||||
redo_close3:
|
||||
if(close(fd) == -1 && errno == EINTR) goto redo_close3;
|
||||
if (perrno != PSUCCESS) {
|
||||
gllfree(retval);
|
||||
return(NULL); /* Return error code from next_menu_item*/
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* This client opens a TCP stream to the host/port & returns a FILE pointer. */
|
||||
/* Returns NULL on failure; sets p_err_string */
|
||||
FILE *
|
||||
fopen_stream(char *host, int port)
|
||||
{
|
||||
int fd = quick_open_tcp_stream(host, port, G_OPEN_TIMEOUT);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
return fdopen(fd, "r+");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Reads the next valid menu item from the stream FP. Returns NULL if
|
||||
no more, or if more than 3 erroneous lines go by. If a line is sent
|
||||
longer than 1024 characters, it is definitely illegal according to the
|
||||
Gopher spec, which requests no more than 255 chars for the selector and 80
|
||||
for the description. */
|
||||
/* Need to work on the error reporting. */
|
||||
static GLINK
|
||||
quick_next_menu_item(FILE * fp, int timeout)
|
||||
{
|
||||
GLINK r;
|
||||
char buf[1024];
|
||||
int buflen; /* # of characters in this buffer. */
|
||||
int nbad = 0;
|
||||
|
||||
|
||||
again:
|
||||
if (nbad > 3)
|
||||
return NULL;
|
||||
|
||||
if (!quick_fgets(buf, sizeof buf, fp, timeout)) {
|
||||
if (errno = ETIMEDOUT) {
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"Timed out after %d secs waiting for response", timeout);
|
||||
perrno = DIRSRV_GOPHER;
|
||||
return NULL;
|
||||
}
|
||||
assert(FALSE);
|
||||
}
|
||||
buflen = strlen(buf);
|
||||
if (sizeof buf - 1 == buflen) { /* line too long; missed CRLF */
|
||||
++nbad;
|
||||
goto again;
|
||||
}
|
||||
r = glalloc();
|
||||
/* The standard specifies a trailing CR, but apparantly
|
||||
e.g. archive.egr.msu.edu(70) this is not guarranteed */
|
||||
assert(buf[buflen -1] == '\n');
|
||||
if (buf[buflen - 1] == '\n')
|
||||
buf[--buflen] = '\0';
|
||||
if (buf[buflen - 1] == '\r')
|
||||
buf[--buflen] = '\0';
|
||||
/* Check for end of menu */
|
||||
if (strequal(buf, ".")) {
|
||||
glfree(r);
|
||||
return NULL; /* the end has been spotted. */
|
||||
}
|
||||
#if 0
|
||||
if (qsscanf(buf, "%c%&[^\t]%*1[\t]%&(^\t)%*1[\t]%&[^\t]%*1[\t]%d",
|
||||
&r->type, &r->name, &r->selector, &r->host, &r->port) < 5) {
|
||||
/* Note that %&( is not yet implemented, so we're doing it this way
|
||||
instead. */
|
||||
#else
|
||||
if ((qsscanf(buf, "%c%&[^\t]%*1[\t]%&[^\t]%*1[\t]%&[^\t]%*1[\t]%d",
|
||||
&r->type, &r->name, &r->selector, &r->host, &r->port) < 5)
|
||||
&& ((r->selector = stcopyr("", r->selector)),
|
||||
(qsscanf(buf, "%c%&[^\t]%*1[\t]%*1[\t]%&[^\t]%*1[\t]%d",
|
||||
&r->type, &r->name, &r->host, &r->port) < 4))) {
|
||||
#endif
|
||||
++nbad;
|
||||
p_warn_string = qsprintf_stcopyr(p_warn_string,
|
||||
"Encountered unrecognized Gopher message: %s", buf);
|
||||
pwarn = PWARNING;
|
||||
glfree(r);
|
||||
goto again;
|
||||
}
|
||||
nbad = 0;
|
||||
/* Some special cases, for error messages that appear to be menus */
|
||||
if(strncmp(r->name,"Server error",12) == 0) {
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,r->name);
|
||||
perrno = DIRSRV_GOPHER;
|
||||
return NULL;
|
||||
}
|
||||
r->protocol_mesg = stcopy(buf);
|
||||
return r;
|
||||
}
|
||||
|
||||
static VLINK gltovl(GLINK gl);
|
||||
static void add_collation_order(int linknum, VLINK vl);
|
||||
|
||||
/* It is ok to modify the GLINKs, as long as glist is left at the head of a
|
||||
list of stuff to be freed with gllfree() by the caller of this function.
|
||||
|
||||
A lot of the hair in this function is here because we must make sure that
|
||||
Gopher replicas are returned as Prospero replicas. For now, the only way to
|
||||
make sure two objects are treated as replicas is for them to be links with
|
||||
the same positive ID REMOTE value. */
|
||||
static void
|
||||
glinks_to_dirob(GLINK glist, P_OBJECT ob)
|
||||
{
|
||||
int menu_entry_number = 0; /* # of menu entries read */
|
||||
int replica_list = 0; /* nonzero if handling replica list */
|
||||
long current_magic_no = 0L; /* set magic starting hash */
|
||||
VLINK vl = NULL; /* last vlink processed */
|
||||
GLINK gl; /* index */
|
||||
for (gl = glist; gl; gl = gl->next) {
|
||||
/* If we found this link is a replica, put a magic # on the head of the
|
||||
list. */
|
||||
if (!replica_list && gl->type == '+') {
|
||||
if (!vl)
|
||||
continue; /* no previous gopher link for this to be a
|
||||
replica of; perhaps we could not convert the
|
||||
gopher link to a virtual link. */
|
||||
if (!current_magic_no)
|
||||
current_magic_no = generate_magic(vl);
|
||||
while (magic_no_in_list(++current_magic_no, ob->links)) {
|
||||
/* Check for numeric overflow */
|
||||
if (current_magic_no <= 0)
|
||||
current_magic_no = 1;
|
||||
}
|
||||
vl->f_magic_no = ++current_magic_no; /* new magic no */
|
||||
}
|
||||
if (gl->type != '+')
|
||||
replica_list = 0;
|
||||
else {
|
||||
assert(gl->previous);
|
||||
gl->type = gl->previous->type; /* gets type from head of list. */
|
||||
}
|
||||
if ((vl = gltovl(gl)) == NULL) {
|
||||
replica_list = 0; /* break the chain of replicas */
|
||||
continue; /* can't convert it */
|
||||
}
|
||||
if (replica_list) {
|
||||
vl->f_magic_no = current_magic_no;
|
||||
add_collation_order(menu_entry_number, vl);
|
||||
} else {
|
||||
add_collation_order(++menu_entry_number, vl);
|
||||
}
|
||||
APPEND_ITEM(vl, ob->links);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef NEVERDEFINED
|
||||
/* I intend using this to return attributes for GIET-OBJECT-INFO calsl
|
||||
but I need docs on what to return first */
|
||||
/* Converts a hsoname back to a gl */
|
||||
static GLINK
|
||||
hsoname2gl(char *hsoname)
|
||||
{
|
||||
GLINK gl = glalloc();
|
||||
|
||||
tmp = qsscanf(hsoname, "GOPHER-GW/%&[^(](%d)/%c/%r",
|
||||
&gl->host, &gl->port, &gl->type, &gl->selectorcp);
|
||||
switch (&gl->type) {
|
||||
'0': if (tmp < 4) goto hsoname2gl_bad;
|
||||
break;
|
||||
'1': if (tmp < 4) goto hsoname2gl_bad;
|
||||
break;
|
||||
'7': if (tmp < 3) goto hsoname2gl_bad;
|
||||
break;
|
||||
default:
|
||||
return NULL; /* Unsupported type */
|
||||
}
|
||||
/* name,selector,protocol_mesg arent set by this */
|
||||
return gl;
|
||||
|
||||
hsoname2gl_bad:
|
||||
glfree(gl);
|
||||
return gl;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Returns NULL if couldn't convert the gopher link GL to a Prospero link VL.
|
||||
Otherwise returns a new VLINK. */
|
||||
static VLINK
|
||||
gltovl(GLINK gl)
|
||||
{
|
||||
VLINK r = vlalloc();
|
||||
PATTRIB at;
|
||||
/* check if something is an AFTP link. If so, handle it appropriately.*/
|
||||
/* add AFTP Access method */
|
||||
|
||||
r->name = gl->name;
|
||||
gl->name = NULL;
|
||||
atput(r, "GOPHER-MENU-ITEM", gl->protocol_mesg, (char *) 0);
|
||||
|
||||
switch (gl->type) {
|
||||
case '0': /* Text files */
|
||||
case 'c': /* Calendar Text files (not in RFC1436) */
|
||||
case 'e': /* Event Text files (not in RFC1436) */
|
||||
/* This comes first because, in the current client implementation,
|
||||
the server is expected to return access methods in what it believes
|
||||
the preferred order is. We prefer direct AFTP connections to
|
||||
overloading the intermediary Gopher gateways. */
|
||||
r->target = stcopyr("EXTERNAL", r->target);
|
||||
ftp_check_am(gl, r, "TEXT");
|
||||
atput(r, "ACCESS-METHOD", "GOPHER", "", "", "", "", "TEXT",
|
||||
(char *) 0);
|
||||
r->host = qsprintf_stcopyr(r->host, "%s(%d)", gl->host, gl->port);
|
||||
r->hsoname = gl->selector;
|
||||
gl->selector = NULL;
|
||||
atput(r, "OBJECT-INTERPRETATION", "DOCUMENT", "TEXT", "ASCII",
|
||||
(char *) 0);
|
||||
break;
|
||||
case '1': /* Directories */
|
||||
r->host = stcopy(hostwport);
|
||||
r->target = stcopyr("DIRECTORY", r->target);
|
||||
r->hsoname = qsprintf_stcopyr(r->hsoname,
|
||||
"GOPHER-GW/%s(%d)/%c/%s", gl->host,
|
||||
gl->port, gl->type, gl->selector);
|
||||
atput(r, "OBJECT-INTERPRETATION", "DIRECTORY", (char *) 0);
|
||||
ftp_check_dir(gl, r);
|
||||
break;
|
||||
case '4': /* Macintosh BinHex (.hqx) text file */
|
||||
r->target = stcopyr("EXTERNAL", r->target);
|
||||
ftp_check_am(gl, r, "TEXT");
|
||||
atput(r, "ACCESS-METHOD", "GOPHER", "", "", "", "", "TEXT",
|
||||
(char *) 0);
|
||||
r->host = qsprintf_stcopyr(r->host, "%s(%d)", gl->host, gl->port);
|
||||
r->hsoname = gl->selector;
|
||||
gl->selector = NULL;
|
||||
atput(r, "OBJECT-INTERPRETATION", "EMBEDDED", "BINHEX", "DATA",
|
||||
(char *) 0);
|
||||
break;
|
||||
case '5': /* PC-Dos binary files. */
|
||||
case '9': /* Generic binary files */
|
||||
r->target = stcopyr("EXTERNAL", r->target);
|
||||
ftp_check_am(gl, r, "BINARY");
|
||||
atput(r, "ACCESS-METHOD", "GOPHER", "", "", "", "", "BINARY",
|
||||
(char *) 0);
|
||||
r->host = qsprintf_stcopyr(r->host, "%s(%d)", gl->host, gl->port);
|
||||
r->hsoname = gl->selector;
|
||||
gl->selector = NULL;
|
||||
atput(r, "OBJECT-INTERPRETATION", "DATA", (char *) 0);
|
||||
break;
|
||||
case '6': /* UNIX UUencoded file. */
|
||||
r->target = stcopyr("EXTERNAL", r->target);
|
||||
ftp_check_am(gl, r, "TEXT");
|
||||
atput(r, "ACCESS-METHOD", "GOPHER", "", "", "", "", "TEXT",
|
||||
(char *) 0);
|
||||
r->host = qsprintf_stcopyr(r->host, "%s(%d)", gl->host, gl->port);
|
||||
r->hsoname = gl->selector;
|
||||
gl->selector = NULL;
|
||||
atput(r, "OBJECT-INTERPRETATION", "EMBEDDED", "UUENCODE", "DATA",
|
||||
(char *) 0);
|
||||
break;
|
||||
case '7': /* Gopher searches */
|
||||
r->target = stcopyr("DIRECTORY", r->target);
|
||||
r->host = stcopy(hostwport);
|
||||
atput(r, "OBJECT-INTERPRETATION", "SEARCH", (char *) 0);
|
||||
#ifdef PSRV_WAIS_GW
|
||||
/* wais_check_dir() rewrites wais searches as appropriate, and
|
||||
reformats the link to be a WAIS one. */
|
||||
if (wais_check_dir(gl, r))
|
||||
break; /* done */
|
||||
#endif
|
||||
/* Write the link as a gopher search link. */
|
||||
r->hsoname =
|
||||
qsprintf_stcopyr(r->hsoname, "GOPHER-GW/%s(%d)/7/%s",
|
||||
gl->host, gl->port, gl->selector);
|
||||
atput(r, "QUERY-METHOD", "gopher-query(search-words)",
|
||||
"${search-words}", "", (char *) 0);
|
||||
atput(r, "QUERY-ARGUMENT", "search-words",
|
||||
"Index word(s) to search for", "mandatory char*", "%s", "",
|
||||
(char *) 0);
|
||||
atput(r, "QUERY-DOCUMENTATION", "gopher-query()", "This is a Gopher \
|
||||
protocol query exported through Prospero. Since it is not a native Prospero \
|
||||
query, we have very little documentation available for you.", (char *) 0);
|
||||
atput(r, "QUERY-DOCUMENTATION", "search-words", "This string says \
|
||||
what you're searching for or what information you're specifying.",
|
||||
"Type any string. Sometimes SPACEs are treated as implied \
|
||||
'and' operators. Sometimes the words 'and', 'or', and 'not' are recognized \
|
||||
as boolean operators.", (char *) 0);
|
||||
break;
|
||||
case '8':{ /* TELNET session */
|
||||
char *m = ""; /* message */
|
||||
r->target = stcopyr("EXTERNAL", r->target);
|
||||
if (*(gl->selector))
|
||||
m = qsprintf_stcopyr((char *) NULL,
|
||||
"Use the account name \"%s\" to log in",
|
||||
gl->selector);
|
||||
atput(r, "ACCESS-METHOD", "TELNET", "", "", "", "", m, (char *) 0);
|
||||
zap_trailing_spaces(gl->host);
|
||||
/* Gopher uses a telnet port of 0 to mean the default telnet port. */
|
||||
if (gl->port == 0) {
|
||||
r->host = gl->host;
|
||||
gl->host = NULL;
|
||||
} else {
|
||||
r->host = qsprintf_stcopyr(r->host, "%s(%d)", gl->host, gl->port);
|
||||
}
|
||||
atput(r, "OBJECT-INTERPRETATION", "PORTAL", (char *) 0);
|
||||
if (*m)
|
||||
stfree(m);
|
||||
break;
|
||||
}
|
||||
case 'I': /* Generic Image. */
|
||||
case ':': /* Gopher+ bitmap image type; not in RFC1436 */
|
||||
r->target = stcopyr("EXTERNAL", r->target);
|
||||
ftp_check_am(gl, r, "BINARY");
|
||||
atput(r, "ACCESS-METHOD", "GOPHER", "", "", "", "", "BINARY",
|
||||
(char *) 0);
|
||||
r->host = qsprintf_stcopyr(r->host, "%s(%d)", gl->host, gl->port);
|
||||
r->hsoname = gl->selector;
|
||||
gl->selector = NULL;
|
||||
atput(r, "OBJECT-INTERPRETATION", "IMAGE", (char *) 0);
|
||||
break;
|
||||
case 'M': /* MIME. Not in RFC1436. */
|
||||
r->target = stcopyr("EXTERNAL", r->target);
|
||||
ftp_check_am(gl, r, "TEXT");
|
||||
atput(r, "ACCESS-METHOD", "GOPHER", "", "", "", "", "TEXT", (char *) 0);
|
||||
r->host = qsprintf_stcopyr(r->host, "%s(%d)", gl->host, gl->port);
|
||||
r->hsoname = gl->selector;
|
||||
gl->selector = NULL;
|
||||
atput(r, "OBJECT-INTERPRETATION", "DOCUMENT", "MIME", (char *) 0);
|
||||
break;
|
||||
|
||||
case 'T':{ /* TN3270 session */
|
||||
char *m = ""; /* message */
|
||||
r->target = stcopyr("EXTERNAL", r->target);
|
||||
zap_trailing_spaces(gl->host);
|
||||
/* Gopher uses a telnet port of 0 to mean the default telnet port. */
|
||||
if (gl->port == 0) {
|
||||
r->host = gl->host;
|
||||
gl->host = NULL;
|
||||
} else {
|
||||
r->host = qsprintf_stcopyr(r->host, "%s(%d)", gl->host, gl->port);
|
||||
}
|
||||
if (*(gl->selector))
|
||||
m = qsprintf_stcopyr((char *) NULL,
|
||||
"Use the account name \"%s\" to log in",
|
||||
gl->selector);
|
||||
atput(r, "ACCESS-METHOD", "TN3270", "", "", "", "", m, (char *) 0);
|
||||
atput(r, "OBJECT-INTERPRETATION", "PORTAL", (char *) 0);
|
||||
if (*m)
|
||||
stfree(m);
|
||||
break;
|
||||
}
|
||||
case 'g': /* Gif */
|
||||
r->target = stcopyr("EXTERNAL", r->target);
|
||||
ftp_check_am(gl, r, "BINARY");
|
||||
atput(r, "ACCESS-METHOD", "GOPHER", "", "", "", "", "BINARY",
|
||||
(char *) 0);
|
||||
r->host = qsprintf_stcopyr(r->host, "%s(%d)", gl->host, gl->port);
|
||||
r->hsoname = gl->selector;
|
||||
gl->selector = NULL;
|
||||
atput(r, "OBJECT-INTERPRETATION", "IMAGE", "GIF", (char *) 0);
|
||||
break;
|
||||
case 's': /* SOUND. Not in RFC1436. */
|
||||
case '<': /* Gopher+ sound type; not in RFC1436 */
|
||||
r->target = stcopyr("EXTERNAL", r->target);
|
||||
ftp_check_am(gl, r, "BINARY");
|
||||
atput(r, "ACCESS-METHOD", "GOPHER", "", "", "", "", "BINARY",
|
||||
(char *) 0);
|
||||
r->host = qsprintf_stcopyr(r->host, "%s(%d)", gl->host, gl->port);
|
||||
r->hsoname = gl->selector;
|
||||
gl->selector = NULL;
|
||||
atput(r, "OBJECT-INTERPRETATION", "SOUND", (char *) 0);
|
||||
break;
|
||||
case 'i': /* the uncommon i type exists in the University
|
||||
of Iowa gopher variant, Panda. */
|
||||
r->name = gl->name;
|
||||
gl->name = NULL;
|
||||
r->target = stcopyr("NULL", r->target);
|
||||
r->hosttype = stcopyr("NULL", r->hosttype);
|
||||
r->host = stcopyr("NULL", r->host);
|
||||
r->hsonametype = stcopyr("NULL", r->hsonametype);
|
||||
r->hsoname = stcopyr("NULL", r->hsoname);
|
||||
r->target = stcopyr("NULL", r->target);
|
||||
atput(r, "OBJECT-INTERPRETATION", "VOID", (char *) 0);
|
||||
break;
|
||||
case ';': /* Gopher+ MOVIE type. It is not at all clear
|
||||
whether this is being used yet.*/
|
||||
r->target = stcopyr("EXTERNAL", r->target);
|
||||
ftp_check_am(gl, r, "BINARY");
|
||||
atput(r, "ACCESS-METHOD", "GOPHER", "", "", "", "", "BINARY",
|
||||
(char *) 0);
|
||||
r->host = qsprintf_stcopyr(r->host, "%s(%d)", gl->host, gl->port);
|
||||
r->hsoname = gl->selector;
|
||||
gl->selector = NULL;
|
||||
atput(r, "OBJECT-INTERPRETATION", "VIDEO", (char *) 0);
|
||||
break;
|
||||
case '.': /* End of directory. */
|
||||
goto ignore;
|
||||
break; /* go on */
|
||||
case '2': /* CSO nameserver; No gateway (yet) */
|
||||
p_warn_string = qsprintf_stcopyr(p_warn_string,
|
||||
"Encountered gopher link to CSO nameserver; we don't support \
|
||||
this type yet: %s", gl->protocol_mesg);
|
||||
pwarn = PWARNING;
|
||||
goto ignore;
|
||||
break;
|
||||
case '3': /* Mitra thinks the error type should be
|
||||
ignored. I am willing to go along with
|
||||
this, given that the standard UNIX Gopher
|
||||
client ignores it. */
|
||||
goto ignore;
|
||||
break;
|
||||
case 'w': /* whois server */
|
||||
p_warn_string = qsprintf_stcopyr(p_warn_string,
|
||||
"Encountered gopher link to WHOIS server; we don't support \
|
||||
this type yet: %s", gl->protocol_mesg);
|
||||
case '-': /* error message type? */
|
||||
default: /* unknown type or type we can't process */
|
||||
p_warn_string = qsprintf_stcopyr(p_warn_string,
|
||||
"Encountered unrecognized Gopher message: %s",
|
||||
gl->protocol_mesg);
|
||||
pwarn = PWARNING;
|
||||
ignore:
|
||||
vlfree(r);
|
||||
r = NULL;
|
||||
break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/* Check if we're an AFTP link. If so, add an AFTP access method. */
|
||||
/* This check should be made before other access methods are added.
|
||||
The server is expected to return access methods in what it believes the
|
||||
preferred order is. We prefer direct AFTP connections to overloading the
|
||||
intermediary Gopher gateways. */
|
||||
/* Gopher AFTP links to files use the HSONAME format:
|
||||
ftp:<aftp-hostname>@/file-path (no trailing slash) */
|
||||
static void
|
||||
ftp_check_am(GLINK gl, VLINK r, char *textorbin)
|
||||
{
|
||||
static char *ftp_hostname = NULL;
|
||||
char *ftp_rest; /* rest of string */
|
||||
if (qsscanf(gl->selector, "ftp:%&[^@]@%r", &ftp_hostname, &ftp_rest) == 2) {
|
||||
int len = strlen(ftp_rest);
|
||||
if (ftp_rest[len - 1] != '/')
|
||||
atput(r, "ACCESS-METHOD", "AFTP", "", ftp_hostname, "", ftp_rest,
|
||||
textorbin, (char *) 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we're an AFTP link. If so, rewrite the HOST and HSONAME to go
|
||||
through the Prospero server at ARCHIE_SERVER (this can be changed). */
|
||||
/* Gopher AFTP links to directories use the HSONAME format:
|
||||
ftp:<aftp-hostname>@/directory.../ */
|
||||
static void
|
||||
ftp_check_dir(GLINK gl, VLINK r)
|
||||
{
|
||||
static char *ftp_hostname = NULL;
|
||||
int len;
|
||||
char *ftp_rest; /* rest of string */
|
||||
if (qsscanf(gl->selector, "ftp:%&[^@]@%r", &ftp_hostname, &ftp_rest) == 2
|
||||
#if 0
|
||||
/* Commented out, doesnt need to be / after @ if gatewaying thru gopher*/
|
||||
&& *ftp_rest == '/'
|
||||
#endif
|
||||
) {
|
||||
len = strlen(ftp_rest);
|
||||
if (ftp_rest[len - 1] == '/') {
|
||||
#if 0 /* commented out because of problem:not all
|
||||
archie servers index all AFTP sites. */
|
||||
#ifdef ARCHIE_SERVER
|
||||
ftp_rest[len - 1] = '\0';
|
||||
r->host = stcopyr(ARCHIE_SERVER, r->host);
|
||||
r->hsoname = qsprintf_stcopyr(r->hsoname, "ARCHIE/HOST/%s%s",
|
||||
ftp_hostname, ftp_rest);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef GOPHER_GW_NEARBY_GOPHER_SERVER
|
||||
r->hsoname = qsprintf_stcopyr(r->hsoname,
|
||||
"GOPHER-GW/%s/1/ftp:%s@%s", GOPHER_GW_NEARBY_GOPHER_SERVER,
|
||||
ftp_hostname, ftp_rest);
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PSRV_WAIS_GW
|
||||
static int
|
||||
wais_check_dir(GLINK gl, VLINK r)
|
||||
{
|
||||
char *w_db = NULL; /* Pointer into gl->selector e.g. zzz */
|
||||
char *w_path = NULL; /* Pointer into gl->selector e.g. xxx/yyy/zzz */
|
||||
AUTOSTAT_CHARPP(w_db_srcp); /* e.g. zzz.src */
|
||||
char *cp = NULL; /* temporary pointer */
|
||||
WAISSOURCE thissource; /* Points to source structure */
|
||||
if (qsscanf(gl->selector, "waissrc:%r", &w_path) != 1) {
|
||||
return FALSE;
|
||||
}
|
||||
if ((w_db = strrchr(w_path, '/')) == NULL) {
|
||||
w_db = w_path;
|
||||
} else {
|
||||
w_db++;
|
||||
}
|
||||
|
||||
if ((cp = strstr(w_db, ".src")) == NULL) {
|
||||
*w_db_srcp = qsprintf_stcopyr(*w_db_srcp, "%s%s", w_db, ".src");
|
||||
} else {
|
||||
*w_db_srcp = stcopyr(w_db, *w_db_srcp); /* *w_db_srcp = zzz.src */
|
||||
}
|
||||
/*!! Open and parse local src file */
|
||||
/* While this may s_alloc the source DONT free it, its on
|
||||
a linked list of sources which persists while the server is up*/
|
||||
if ((thissource = findsource(*w_db_srcp, WAIS_SOURCE_DIR)) == NULL)
|
||||
return FALSE;
|
||||
|
||||
if ((cp = strstr(w_db, ".src")) != NULL) {
|
||||
/* Need to do this AFTER findsource, otherwise can modify gl->selector
|
||||
of non matching source */
|
||||
cp[0] = '\0'; /* w_db = zzz */
|
||||
}
|
||||
r->hsoname = qsprintf_stcopyr(r->hsoname, "WAIS-GW/%s(%s)/QUERY/%s",
|
||||
thissource->server, thissource->service, w_db);
|
||||
if (thissource->subjects)
|
||||
atput(r, "WAIS-SUBJECTS", thissource->subjects, (char *) 0);
|
||||
if (thissource->cost)
|
||||
atput(r, "WAIS-COST-NUM", thissource->cost, (char *) 0);
|
||||
if (thissource->units)
|
||||
atput(r, "WAIS-COST-UNIT", thissource->units, (char *) 0);
|
||||
if (thissource->maintainer)
|
||||
atput(r, "WAIS-COST-MAINTAINER", thissource->maintainer, (char *) 0);
|
||||
atput(r, "QUERY-METHOD", "wais-query(search-words)",
|
||||
"${search-words}", "", (char *) 0);
|
||||
atput(r, "QUERY-ARGUMENT", "search-words",
|
||||
"Index word(s) to search for", "mandatory char*", "%s", "",
|
||||
(char *) 0);
|
||||
if (thissource->description)
|
||||
atput(r, "QUERY-DOCUMENTATION", "wais-query()",
|
||||
thissource->description, (char *) 0);
|
||||
atput(r, "QUERY-DOCUMENTATION", "search-words", "This string says \
|
||||
what you're searching for or what information you're specifying.",
|
||||
"Type any string. Sometimes SPACEs are treated as implied \
|
||||
'and' operators. Sometimes the words 'and', 'or', and 'not' are recognized \
|
||||
as boolean operators.", (char *) 0);
|
||||
return (TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
zap_trailing_spaces(char *host)
|
||||
{
|
||||
int len = strlen(host);
|
||||
while (--len >= 0) {
|
||||
if (host[len] == ' ')
|
||||
host[len] = '\0';
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a collation-order attribute of the form NUMERIC <linknum> to the link
|
||||
VL */
|
||||
static void
|
||||
add_collation_order(int linknum, VLINK vl)
|
||||
{
|
||||
PATTRIB ca = atalloc();
|
||||
char buf[40]; /* long enough to hold the ASCII
|
||||
representation of any int for the
|
||||
foreseeable future. */
|
||||
ca->precedence = ATR_PREC_LINK;
|
||||
ca->nature = ATR_NATURE_APPLICATION;
|
||||
ca->avtype = ATR_SEQUENCE;
|
||||
ca->aname = stcopy("COLLATION-ORDER");
|
||||
ca->value.sequence = tkappend("NUMERIC", ca->value.sequence);
|
||||
assert(qsprintf(buf, sizeof buf, "%d", linknum) <= sizeof buf);
|
||||
ca->value.sequence = tkappend(buf, ca->value.sequence);
|
||||
APPEND_ITEM(ca, vl->lattrib);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
atput(VLINK vl, char *name,...)
|
||||
{
|
||||
va_list ap;
|
||||
char *s;
|
||||
PATTRIB at = atalloc();
|
||||
|
||||
va_start(ap, name);
|
||||
at->aname = stcopy(name);
|
||||
at->avtype = ATR_SEQUENCE;
|
||||
if (strequal(name, "ACCESS-METHOD"))
|
||||
at->nature = ATR_NATURE_FIELD;
|
||||
else
|
||||
at->nature = ATR_NATURE_APPLICATION;
|
||||
if (strequal(vl->target, "EXTERNAL"))
|
||||
at->precedence = ATR_PREC_REPLACE; /* still not clear what to use */
|
||||
else
|
||||
at->precedence = ATR_PREC_OBJECT;
|
||||
while (s = va_arg(ap, char *)) {
|
||||
at->value.sequence =
|
||||
tkappend(s, at->value.sequence);
|
||||
}
|
||||
APPEND_ITEM(at, vl->lattrib);
|
||||
va_end(ap);
|
||||
}
|
||||
39
prospero/lib/psrv/gopher_gw/goph_gw_mutex.c
Normal file
39
prospero/lib/psrv/gopher_gw/goph_gw_mutex.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 1991-1994 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-license.h>.
|
||||
*/
|
||||
|
||||
#include <usc-license.h>
|
||||
#include "gopher.h"
|
||||
#include <pfs.h>
|
||||
#include <pfs_threads.h>
|
||||
|
||||
/* This file is used by lib/psrv. So libpgoph_gw.a should follow psrv. */
|
||||
|
||||
|
||||
#ifdef PFS_THREADS
|
||||
p_th_mutex p_th_mutexGLINK; /* declaration */
|
||||
#endif
|
||||
|
||||
void
|
||||
gopher_gw_init_mutexes(void)
|
||||
{
|
||||
#ifdef PFS_THREADS
|
||||
p_th_mutex_init(p_th_mutexGLINK);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void
|
||||
gopher_gw_diagnose_mutexes(void)
|
||||
{
|
||||
printf("{gopher_gw_init_mutexes ");
|
||||
#ifdef PFS_THREADS
|
||||
DIAGMUTEX(GLINK,"GLINK");
|
||||
#endif
|
||||
printf("}");
|
||||
}
|
||||
#endif /*NDEBUG*/
|
||||
|
||||
34
prospero/lib/psrv/gopher_gw/gopher.h
Normal file
34
prospero/lib/psrv/gopher_gw/gopher.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-copyr.h>.
|
||||
*/
|
||||
|
||||
#include <usc-copyr.h>
|
||||
|
||||
#include <pfs_threads.h>
|
||||
|
||||
struct glink {
|
||||
#ifdef ALLOCATOR_CONSISTENCY_CHECK
|
||||
int consistency;
|
||||
#endif
|
||||
char type;
|
||||
char *name;
|
||||
char *selector;
|
||||
char *host;
|
||||
int port;
|
||||
char *protocol_mesg; /* raw item description -- the Gopher
|
||||
protocol message. */
|
||||
struct glink *previous;
|
||||
struct glink *next;
|
||||
};
|
||||
typedef struct glink *GLINK;
|
||||
typedef struct glink GLINK_ST;
|
||||
|
||||
extern GLINK glalloc(void);
|
||||
extern void glfree(GLINK);
|
||||
extern void gllfree(GLINK);
|
||||
#ifdef PFS_THREADS
|
||||
extern p_th_mutex p_th_mutexGLINK; /* declared in goph_gw_mutex.c */
|
||||
#endif
|
||||
Reference in New Issue
Block a user