For example, if I know exactly the path to a weather forecast (not
available via ftp) which is about 7 menus deep from my client, I would like
to retrieve this file without having to tumble down this long series of menus.
If you've got such a naked gopher for VMS, that would be great, but I can
deal with UNIX as well.
Thanks,
Jim Pendleton
Dept. Physics & Astronomy, Northwestern U.
j-pen...@nwu.edu
# History
# Dec 6 cmk - modifed input a bookmark to a directory
# Nov 23-30, 1992 cmk - initial development
require "getopts.pl";
&Getopts("p:l:");
$toppath = $opt_p;
#print STDERR "opt_l=$opt_l\n";
if ($opt_l ne '') {
$line_limit = int($opt_l);
if ($line_limit < 0) {$line_limit=0;}
} else {
$line_limit = 200;
}
($tophost,$topport) = @ARGV;
$topport = 70 if ! $topport;
if (! $tophost) {
print "USAGE: gopher2mbox -pGOPHER-PATH -lLINE-LIMIT HOST PORT > MBOX\n";
print "\n";
print " HOST is required\n";
print " PORT defaults to 70\n";
print " GOPHER-PATH defaults to \"\"\n";
print " LINE-LIMIT defaults to 200\n";
print "\n";
print " MBOX can be read with a text editor, or with\n";
print " nn MBOX\n";
print " or with\n";
print " mail -f MBOX\n";
exit(1);
}
$| = 1;
local(@cltmp3) = &CLIENT($tophost,$topport,"$toppath\r\n",-1);
($lines,$count) = @cltmp3;
#print "lines = $lines\n";
foreach $_ (split("\n",$lines)) {
#print "_ = $_\n";
#chop; # chop off \r
&LOOKUP($_);
}
# Based on "client" on page 344 of _Programming Perl_ by Wall and Schwartz
sub CLIENT {
local($them,$port,$input,$maxlines) = @_;
local($client,$name);
if (($them eq "error.host") || ($maxlines==0)) {
$client="";$maxlines = 0;
local(@cltmp2) = ($client,$maxlines);
return(@cltmp2);
}
# If $maxlines is negative, then no limit.
#open(OUT,$fileout);
$port = 2345 unless $port;
$them = 'localhost' unless $them;
$AF_INET =2;
$SOCK_STREAM = 1;
$SIG{'INT'} = 'dokill';
$sockaddr = 'S n a4 x8';
chop($hostname = `hostname`);
($name,$aliases,$proto) = getprotobyname('tcp');
($name,$aliases,$port) = getservbyname($port,'tcp')
unless $port =~ /^\d+$/;;
($name,$aliases,$type,$len,$thisaddr) = gethostbyname($hostname);
($name,$aliases,$type,$len,$thataddr) = gethostbyname($them);
$this = pack($sockaddr,$AF_INET, 0, $thisaddr);
$that = pack($sockaddr,$AF_INET, $port, $thataddr);
# Make the socket filehandle
if (socket(S, $AF_INET, $SOCK_STREAM, $proto)) {
#print "socket ok\n";
}
else {
die $!;
}
# Give the socket an address.
if (bind(S, $this)) {
#print "bind ok\n";
}
else {
die $!;
}
# Call up the server.
if (connect(S,$that)) {
#print "connect ok\n";
}
else {
print STDERR "CANNOT CONNECT TO $them $port $input $maxlines $!\n";
$client="";$maxlines = 0;
local(@cltmp2) = ($client,$maxlines);
return(@cltmp2);
}
# Set socket to be command buffered.
$oldhandle = select(S); $| = 1; select ($oldhandle);
#select(S); $| = 1; select (STDOUT);
# Avoid deadlock by forking.
#if (!($child = fork)) {
# # child
print S $input;
# exit;
#}
#else {
# # parent
READ: while (<S>) {
last READ if ($maxlines == 0);
$maxlines--;
#print OUT;
chop;chop;
last READ if ($_ eq ".");
$client .= "$_\n";
}
#}
#close(OUT);
local(@cltmp2) = ($client,$maxlines);
@cltmp2;
}
#sub dokill {
# kill 9,$child if $child;
#}
sub LOOKUP {
local($gopherref) = @_;
$*=1;
#print STDERR ">0>$gopherref<0<";
local($type_and_name,$path,$host,$port) = split("\t",@_[0]);
local($type,$name) = $type_and_name =~ /(.)(.*)/;
#print STDERR ">1>",$name,$type,$port,$path,$host,"<1<";
$date = `date`;
chop($date);
#print STDERR $date;
print "From gopher2mbox $date
From: $port ($path)
Subject: $name
";
if ($type == 0) {
#print STDERR "line_limit = $line_limit\n";
local(@cltmp3) = &CLIENT($host,$port,"$path\r\n",$line_limit);
($lines,$count) = @cltmp3;
#print STDERR "count=$count\n";
print "\n$lines";
if ($count ==0){
print "======== ... ================
[This is only the first part of this item. To retrieve the
full item, use gopher.]
";
} else {
print "======== End of \"$name\" ================\n";
}
} else {
print "
$name
is a nontext item in Gopher. To access this item, try
gopher -p \"$path\" $host $port
";
}
print "For reference, the \"bookmark\" for this gopher item is:
Name=$name
Type=$type
Port=$port
Path=$path
Host=$host
";
}
--
Carl Kadie -- I do not represent EFF; this is just me.
=ka...@eff.org, ka...@cs.uiuc.edu =
: For example, if I know exactly the path to a weather forecast (not
: available via ftp) which is about 7 menus deep from my client, I would like
: to retrieve this file without having to tumble down this long series of menus.
: If you've got such a naked gopher for VMS, that would be great, but I can
there are some perl scripts in the distribution that do this - and
if you have a finger client that can be coerced into using a different
port its' doable too. or use the world wide web command line client
from info.cern.ch if you have that running.
--Ed
>Does there exist an evolutionarily deprived gopher which will simply
>connect to a given port on a given machine, execute a single valid
>command string and send the resulting output to a specified file (or
>to standard output...I'm not fussy)?
>For example, if I know exactly the path to a weather forecast (not
>available via ftp) which is about 7 menus deep from my client, I would like
>to retrieve this file without having to tumble down this long series of menus.
>If you've got such a naked gopher for VMS, that would be great, but I can
>deal with UNIX as well.
I don't know about the VMS client, but the Unix curses client allows you
to save any menu item as a book mark. To access the item, you need only
display your menu of bookmarks and choose the one you want to use. Also,
it is possible to fetch some gopher files by telnetting to the desired server
and, once connected, entering the proper selection string for that item. In
order to do so, you must know the domain name (or IP address) and port
number of the server as well as the selction string. Here again, your
Unix client (and many others) can help. Most clients allow you to view
the technical information that lies behind a menu item. With the Unix curses
client, this is done by pressing the equal (=) sign. The results displayed
will look something like this:
Name=Alabama Current Conditions
Type=0
Port=16000
Path=0/Current Conditions/Alabama Current Conditions
Host=garcon.cso.uiuc.edu
To use this information, telnet to garcon.cso.uiuc.edu 16000. Once connected,
enter the selection string (called "path):
0/Current Conditions/Alabama Current Conditions
Garcon will spit back the desired results. The example below shows how this
works (just a capture of my telnet session):
ux1 2> telnet garcon.cso.uiuc.edu 16000
Trying 128.174.5.58...
Connected to garcon.cso.uiuc.edu.
Escape character is '^]'.
0/Current Conditions/Alabama Current Conditions [press return here]
ABUS22 KBHM 132112
ALABAMA STATE WEATHER ROUNDUP
NATIONAL WEATHER SERVICE BIRMINGHAM AL
300 PM CST WED JAN 13 1993
CITY SKY/WX TEMP DEWPT RH WIND PRES REMARKS
ALZ001-002-132200-
NORTH ALABAMA
MUSCLE SHOALS SUNNY 49 29 46 W13 30.20R
HUNTSVILLE SUNNY 51 32 48 W17 30.16R
$$
ALZ006-009-010-132200-
CENTRAL ALABAMA
BIRMINGHAM SUNNY 58 28 32 NW15 30.15S
CENTREVILLE MOSUNNY 59 34 39 NW12 30.17R
MONTGOMERY MOSUNNY 58 38 47 W10 30.17R
MAXWELL AFB PTSUNNY 60 37 42 W6 30.16S
$$
ALZ007-011-017-018-132200-
EAST ALABAMA
ANNISTON MOSUNNY 59 25 27 W8 30.12S
AUBURN N/A 59 37 44 NW9
TROY PTSUNNY 58 38 47 NW5 30.16R
DOTHAN PTSUNNY 62 34 35 N12 30.13S
OZARK PTSUNNY 62 34 35 N5 30.14F
$$
ALZ008-132200-
WEST ALABAMA
TUSCALOOSA SUNNY 58 33 39 NW12 30.17F
$$
ALZ016-132200-
SOUTH ALABAMA
MOBILE CLOUDY 59 36 42 NE12 30.17R
$$
--
Lynn Ward
Network Design Office/Computing and Communications Services Office
1304 W. Springfield Ave., Urbana, IL 61801
e-mail: L-w...@uiuc.edu
This might work with VMS, I dunno. In unix I can run it like this:
echo "1/path" | tcp -h gopher -s 70
or
cat file | tcp -h gopher -s 70
Your mileage may vary, and I don't know VMS much..
/*
* TCP/IP stream emulation for GNU Emacs.
* Copyright (C) 1988, 1989 Fujitsu Laboratories LTD.
* Copyright (C) 1988, 1989 Masanobu UMEDA
* $Header: tcp.c,v 1.3 89/06/19 13:39:12 umerin Locked $
* This file is part of GNU Emacs.
* GNU Emacs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY. No author or distributor
* accepts responsibility to anyone for the consequences of using it
* or for whether it serves any particular purpose or works at all,
* unless he says so in writing. Refer to the GNU Emacs General Public
* License for full details.
* Everyone is granted permission to copy, modify and redistribute
* GNU Emacs, but only under the conditions described in the
* GNU Emacs General Public License. A copy of this license is
* supposed to have been given to you along with GNU Emacs so you
* can know your rights and responsibilities. It should be in a
* file named COPYING. Among other things, the copyright notice
* and this notice must be preserved on all copies.
* If you modify the source for your system, please send me the diffs.
* I'll includes some of them in the future releases.
*
* Yasunari,Itoh at PFU limited contributed for Fujitsu UTS and SX/A.
*
* Thu Apr 6 13:47:37 JST 1989
* USG fixes by Sakaeda <sa...@mickey.trad.pf.fujitsu.junet>
*
* For Fujitsu UTS compile with:
* cc -O -o tcp tcp.c -DFUJITSU_UTS -lu -lsocket
*/
#ifndef lint
static char *rcsId = "$Header: tcp.c,v 1.3 89/06/19 13:39:12 umerin Locked $";
#endif
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/types.h>
#ifdef FUJITSU_UTS
#define USG
#include <sys/ucbtypes.h>
#include <sys/tisp/socket.h>
#include <netdb.h>
#include <sys/tisp/in.h>
#else
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#endif
#ifdef USG
#include <sys/stat.h>
#include <signal.h>
#endif
#if defined FUJITSU_UTS || defined HPUX
#define bcopy(f,t,n) memcpy(t,f,n)
#define bcmp(b1,b2,n) (memcmp(b1,b2,n)!=0)
#define bzero(b,n) memset(b,0,n)
#endif
#ifdef USG
int selectable = 1;
sigout()
{
fcntl(fileno(stdin),F_SETFL,0);
exit(-1);
}
#endif
main(argc, argv)
int argc;
char *argv[];
{
struct hostent *host;
struct sockaddr_in sockin, sockme;
struct servent *serv;
struct linger linger_s;
char *hostname;
char *service = "nntp";
int port;
int readfds;
int writefds;
int server; /* NNTP Server */
int emacsIn = fileno(stdin); /* Emacs intput */
int emacsOut = fileno(stdout); /* Emacs output */
char buffer[1024];
int nbuffer; /* Number of bytes in buffer */
int wret;
char *retry; /* retry bufferp */
while(--argc > 0){
switch(**(++argv)){
case '-':
{
char *p = &argv[0][1];
if(strcmp(p,"s")==0){ /* Service name */
service = *(++argv);
--argc;
} else if(strcmp(p,"h")==0){ /* Host name */
hostname = *(++argv);
--argc;
} else {
fprintf(stderr, "Usage: tcp -h HOST -s SERVICE\n");
exit(1);
}
}
break;
default:
fprintf(stderr, "Usage: tcp -h HOST [-s SERVICE]\n");
exit(1);
break;
}
}
bzero(&sockin, sizeof(sockin));
if (isdigit(hostname[0])) {
sockin.sin_family = AF_INET;
if (-1 == (sockin.sin_addr.s_addr = inet_addr(hostname))) {
perror("inet_addr");
exit(1);
}
} else if((host = gethostbyname(hostname))) {
sockin.sin_family = host->h_addrtype;
bcopy(host->h_addr, &sockin.sin_addr, host->h_length);
} else {
perror("gethostbyname");
exit(1);
}
if(isdigit(service[0]))
port = atoi(service);
else {
serv = getservbyname(service, "tcp");
if(serv == NULL){
perror("getservbyname");
exit(1);
}
port = serv->s_port;
}
sockin.sin_port = htons(port);
if((server = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(1);
}
linger_s.l_onoff = 1;
linger_s.l_linger = 60;
if(setsockopt(server, SOL_SOCKET, SO_LINGER, &linger_s, sizeof(linger_s))) {
perror("setsockopt");
exit(1);
}
bzero(&sockme, sizeof(sockme));
sockme.sin_family = sockin.sin_family;
sockme.sin_addr.s_addr = INADDR_ANY;
if(bind(server, &sockme, sizeof(sockme)) < 0){
perror("bind");
exit(1);
}
if(connect(server, &sockin, sizeof (sockin)) < 0){
perror("connect");
close(server);
exit(1);
}
#ifdef O_NDELAY
fcntl(server, F_SETFL, O_NDELAY);
#ifdef USG
/* USG pipe cannot not select emacsIn */
{
struct stat statbuf;
fstat (emacsIn,&statbuf);
if (statbuf.st_mode & 010000)
selectable = 0;
if (!selectable){
signal(SIGINT,sigout);
fcntl(emacsIn, F_SETFL, O_NDELAY);
}
}
#endif
#endif
/* Connection established. */
while(1){
readfds = (1 << server) | (1 << emacsIn);
if(select(32, &readfds, NULL, NULL, (struct timeval *)NULL) == -1){
perror("select");
exit(1);
}
if(readfds & (1 << emacsIn)){
/* From Emacs */
nbuffer = read(emacsIn, buffer, sizeof buffer -1);
#ifdef USG
if (selectable && nbuffer == 0){
goto finish;
} else if (!(readfds & (1 << server)) && nbuffer == 0){
sleep (1);
} else
#else
if(nbuffer == 0)
goto finish;
#endif
for(retry = buffer; nbuffer > 0; nbuffer -= wret, retry += wret){
writefds = 1 << server;
if(select(server+1,NULL,&writefds,NULL,(struct timeval*)NULL) == -1){
perror("select");
exit(1);
}
wret = write(server, retry, nbuffer);
if(wret < 0) goto finish;
}
}
if(readfds & (1 << server)){
/* From NNTP server */
nbuffer = read(server, buffer, sizeof buffer -1);
if(nbuffer == 0)
goto finish;
for(retry = buffer; nbuffer > 0; nbuffer -= wret, retry += wret){
writefds = 1 << emacsOut;
#ifdef USG
if(selectable)
#endif
if(select(emacsOut+1,NULL,&writefds,NULL,(struct timeval*)NULL) == -1){
perror("select");
exit(1);
}
wret = write(emacsOut, retry, nbuffer);
if(wret < 0) goto finish;
}
}
}
/* End of communication. */
finish:
close(server);
#ifdef USG
if (!selectable) fcntl(emacsIn, F_SETFL,0);
#endif
close(emacsIn);
close(emacsOut);
exit(0);
}
--
+ + + + + + + |sne...@oac.hsc.uth.tmc.edu
You can make it foolproof, |Nobody else speaks for me,
but you can't make it damnfoolproof. |and I speak for no one else.
| + + + + +
Here's another one.
-- Prentiss Riddle ("aprendiz de todo, maestro de nada") rid...@rice.edu
-- Unix Systems Programmer, Office of Networking and Computing Systems
-- Rice University, POB 1892, Houston, TX 77251 / Mudd 208 / 713-285-5327
-- Opinions expressed are not necessarily those of my employer.
-------------------------------------------------------------------------
#!/usr/local/bin/perl
# gophercat - grab a single file from a Gopher server
#
# usage: gophercat host port path
#
# Gophercat can handle both text and binary data types (binary types
# include both type "9" binaries and others such as type "I" images). If
# the path does not include an initial type selector character followed
# by a "/", gophercat will assume type "0" (for text) and supply them.
# In text mode, gophercat will convert final CRLF to LF. The path will
# need to be enclosed in quotation marks if it contains blanks or special
# characters.
#
# Among other uses, gophercat can be called from cron to do automatic
# mirroring of selected data files from a remote Gopher server.
#
# Examples:
# gophercat gopher.micro.umn.edu 70 "0/Information About Gopher/.about"
# gophercat wx.atmos.uiuc.edu 70 Forecast/City_Forecasts/US/TX/Houston-Hobby
# gophercat cwis.rice.edu 70 I/MoreAbout/gopherT.gif
#
#----------------------------------------------------------------------------
# History:
# 12/16/92 PASR Original version, but based on gopherclone by Bob Alberti
# (alb...@boombox.micro.umn.edu) and friends:
# original NNTP client suggested by eci386!clewis
# socket code by c...@obie.cis.pitt.edu (Carl M. Fongheiser)
# adaptation for gopher by e...@msen.com (Edward Vielmetti)
# mods to indexer by Bob Alberti
#----------------------------------------------------------------------------
$host = $ARGV[0];
$port = $ARGV[1];
$path = $ARGV[2];
# Make sure the path has an initial type selector (default "0/").
$path =~ s#^/?#0/# unless ($path =~ m#^./#);
$text = (substr($path, 0, 1) eq "0"); # treat like ASCII text?
if ($#ARGV == 2 && $host && $port && $path) {
# Here's how to make your own socket.ph:
# cp /usr/include/sys/socket.h socket.h
require 'socket.ph'; # h2ph socket
chop($hostname = `hostname`); # get host name in variable
($N) = &tcpconnect($host, $hostname);
if ($N) { # If connection good
send(N,"$path\r\n", 0) || die "Send $d to $host barfed with: $!\n";
while (<N>) {
last if /^\.\r\n$/; # loop til lone period
s#\r\n$#\n# if $text; # change CRLF to LF if in text mode
print "$_"; # print the line
}
} else {
die "Couldn't open tcp connection $N: $!\n";
}
close(N);
} else {
die "usage: gophercat host port path\n";
}
sub tcpconnect { #Get TCP info in place
local($host, $hostname) = @_;
$sockaddr = 'S n a4 x8';
($name,$aliases,$proto) = getprotobyname('tcp');
($name,$aliases,$port) = getservbyname($port, 'tcp')
unless $port =~ /^\d+$/;
($name,$aliases,$type,$len,$thisaddr) = gethostbyname($hostname);
($name,$aliases,$type,$len,$thataddr) = gethostbyname($host);
$this = pack($sockaddr, &AF_INET, 0, $thisaddr);
$that = pack($sockaddr, &AF_INET, $port, $thataddr);
sleep(2);
socket(N, &PF_INET, &SOCK_STREAM, $proto) || die "socket: $!";
bind(N, $this) || die "bind: $!";
connect(N, $that) || die "connect: $!";
return(N);
}