/*
Gopher --> TechInfo Gateway
Copyright November 1992, January 1993 by the University of Pennsylvania.
Export of this software from the United States of America is assumed
to require a specific license from the United States Government. It
is the responsibility of any person or organization contemplating
export to obtain such a license before exporting. Within that
constraint, permission to use, distribute, or copy this software is
granted, provided that this copyright notice appear on all copies.
This software is provided as is, with no explicit nor implicit
warranty.
*/
/* HISTORY:
Mar 1993: version 1.5
Added recognition of telnet and tn3270 file types (TI_TELNETSESS).
Fixed bug which caused NeXT gopher to barf --
Changed "\r\n.\r\n" to ".\r\n" at the end of each element sent.
Commented out various lines which logged extra information.
Took out the test "University of Pennsylvania" system
from techinfo-telnet menu.
Jan 1993: version 1.4
Added ability to point at local Sources document
Jan 1993: version 1.3
Added ability to point at local Gopher server.
Added TechInfo Source to Path (informational only --
the gateway ignores it).
Added Full Text Searching (do #define WAIS or CFLAGS=-DWAIS)
Nov 1992: version 1.2 added GIF.
Feb 1992: Created the gateway.
getreq (char *request, int max, int insock)
{
int idx;
char *cp;
readline (request, max, insock, &idx);
cp = index (request, CR);
if (cp) *cp = 0;
cp = index (request, LF);
if (cp) *cp = 0;
}
write_doc (int gophsock, int readlast, int len, int TextDoc, char *docbuf,
int *totalsent)
{
int wrote;
int towrite;
int pos1, pos2;
/*
if TextDoc is set, then we need to add CR before each LF,
since the TI server doesn't send CR LF at the end of every line
Also, assuming that if TextDoc contains LF . LF, it should
be changed to CF LF . . CF LF
known problem -- if the TI server breaks up the chunks it
sends on a line boundary, and sends a period LF, then
this code will NOT properly quote that period with another one.
*/
if (readlast) /* if these were the last chars to be read */
towrite = len - 4;
else
towrite = len;
if (TextDoc) {
pos1 = 0;
do {
for (pos2=pos1; docbuf[pos2] != LF && pos2 < towrite-1;
pos2++);
if (docbuf[pos2] == LF) { /* found an End of Line */
wrote = write (gophsock, docbuf+pos1, pos2-pos1);
if (wrote < 0)
ErrExit("Error writing document to gopher");
*totalsent = *totalsent + wrote;
write (gophsock, "\r", 1); (*totalsent)++;
write (gophsock, "\n", 1); (*totalsent)++;
else { /* No more LF left in the buffer */
wrote = write (gophsock, docbuf+pos1, towrite-pos1);
if (wrote < 0)
ErrExit ("Error sending document to gopher");
(*totalsent) += wrote;
pos1 = towrite;
}
} while (pos1 < towrite);
}
else { /* Document is not Text, so just send it as it comes from TI */
wrote = write (gophsock, docbuf, towrite);
if (wrote < 0)
ErrExit ("Error sending nontext document to gopher");
(*totalsent) += wrote;
}
}
int send_ti_doc (int tisock, int gophsock, char *nodeid, int TextDoc)
{
char docbuf[12200];
#define DOC_BLKSZ (sizeof(docbuf)-200)
long startat;
long totalchars;
long totalsent = 0;
char *cp;
int len;
int toread;
int red;
cp = strstr (docbuf, TOTCHARSTR);
if (cp) {
cp = cp + sizeof(TOTCHARSTR) - 1;
toread = atoi(cp);
read (tisock, docbuf, 1); /* TI server sends 1 extra character (a LF)
between 1st line & the document */
do {
red = read (tisock, docbuf, toread);
toread = toread - red;
write_doc (gophsock, toread < 1, red, TextDoc, docbuf, &totalsent);
} while (toread > 0);
startat = startat + DOC_BLKSZ;
}
else {
sprintf (tibuf, "Unable to find %s in TI server's response %s\n",
TOTCHARSTR, docbuf);
ErrExit (tibuf);
}
if (isdigit (host[0])) { /* if name begins with a digit, assume IP adr */
ip_addrl = inet_addr (host);
h = gethostbyaddr (&ip_addrl, sizeof(u_long), AF_INET);
return (h);
}
else {
h = gethostbyname (host);
return (h);
}
}
int getportbyn_or_num (str, port)
int *port;
char *str;
{
struct servent *servent;
if ( isdigit(str[0]) ) { /* if its a number, convert ascii to int */
*port = atoi(str);
*port = htons( (u_short) *port);
}
else { /* if not a number, look up name in Ultrix */
servent = getservbyname (str, "tcp");
if (servent == NULL)
return (-1);
*port = servent->s_port;
}
return (1);
}
int
inet_connect(char *hostname, char *service, char **errstr)
{
#define ERRORMSG_SIZE 200
struct hostent *host;
int toport;
struct sockaddr_in sin;
int sock;
extern char *sys_errlist[];
extern int sys_nerr;
if (typ == GO_TELNET || typ == GO_TN3270) {
/* if it's a telnet/tn3270 type of thing, then
need to change it to gopher style information */
/* From TI server: keys format: <type><space><port> E.g.: 8 23 */
cp = index (keys, ' ');
if (cp) portnum = cp+1;
else portnum = "0"; /* DEFAULT TELNET PORT ACCORDING TO GOPHER */
/* From TI server, for Telnet or TN3270 objects:
filename format: <login><space><host> E.g.: gopher dccs.upenn.edu */
cp = rindex (filename, ' ');
if (cp) {
host = cp+1;
*cp = 0;
loginname = filename;
}
else {
host = filename;
loginname = "";
}
/*
Disgusting hack:
The TI nodetype is NOT entirely in one place in the nodes' info string.
Telnet session type files may actually be TN3270 things.
Look in keys to get the scoop.
*/
if (iflags & TI_GIFIMAGE) {
*gophertype = GO_GIF;
*intermedtype = I_GIFIMAGE;
}
else if (iflags & TI_TELNETSESS) {
/* ASSUMPTION: TI Server uses the Gopher characters to indicate
whether it's a Telnet or a TN3270 type of file */
*gophertype = *keys;
*intermedtype = *gophertype;
}
int send_sources_item (char *tiserver)
{
/* Only offer this item if either
1) there's a message file or
2) the server is the local one and there's a LOCAL SOURCES NODEID
*/