[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference nyoss1::market_investing

Title:Market Investing
Moderator:2155::michaud
Created:Thu Jan 23 1992
Last Modified:Thu Jun 05 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:1060
Total number of notes:10477

776.0. "WWW Hack to quickly get quotes" by NETRIX::michaud (Jeff Michaud, PATHWORKS for Win. NT) Fri Oct 14 1994 21:50

	The following reply contains the source to a WWW hack that
	uses the SQL Security Quote Server to obtain via the command
	line (vs. using Mosaic or Lynx) one or more [time delayed]
	stock quotes.

	Mosaic/Lynx used to be fine when I was only following a couple
	of stocks, but it was time consuming when the list grew.

	It should also be easy enough to expand this hack to poll the
	server automatically every so often and only print out the
	info for a given symbol only if the info has changed since the
	last poll.

	Oh yea, this has only been tested on DEC OSF/1 and ULTRIX.  Since
	it uses BSD socket ism's it's obviously going to need changes
	to work on OpenVMS.  If you do get it to work on OpenVMS let
	us know ....
T.RTitleUserPersonal
Name
DateLines
776.2Many thanks for a handy toolENQUE::TAMERMon Oct 17 1994 18:001
    Thanks Jeff. Real handy to keep track of a couple of dozens of symbols.
776.3ZENDIA::FERGUSONThe Janitor of CodingMon Oct 17 1994 20:526
do you have a version that works on WNT?

i have it compiled, but it instantly returns with:

	can't connect to server src-www.pa.dec.com.8080

776.4What is time delay?SUBSYS::DONADTTue Nov 08 1994 15:233
    Works great, Jeff. What is the time delay? 15 minutes?
    
    Ray
776.512368::michaudJeff Michaud, UC1Tue Nov 08 1994 20:1511
> Works great, Jeff. What is the time delay? 15 minutes?

	The following is from the servers Frequently Asked Questions
	(at http://www.secapl.com/secapl/quoteserver/faq.html)

===============
Can you add a timestamp to the quotes so I know how current the information is?
   Sorry we don't have this information. While advertised as 15 minute
   delayed, in reality any particular quote could be anywhere from 15 -
   60 minutes delayed. This is the type of information that a
   professional quote service may be able to provide (See first question above).
776.6Is quote on djia possible?SUBSYS::DONADTWed Nov 09 1994 11:079
    Thanks for your quick reply. Yes, I was thinking about a time stamp
    too, would be nice, but guess we have to settle for what we have.
    Sure beats quote_v0!
    
    Is it possible to get a quote on a market average such as the Dow Jones
    Industrial Averages? I've tried djia and dji but they don't work. Dj
    give you a quote on the Dow Jones Co.
    
    Ray
776.7LJSRV2::MAYERATG/Internet Business GroupWed Nov 09 1994 14:313
	Check out INDU

		Danny
776.8Delay is about 5 minutes.TALLIS::KOCHKevin Koch AKO2-1/G3 DTN244-7845Wed Nov 09 1994 18:278
>Can you add a timestamp to the quotes so I know how current the information is?
>   Sorry we don't have this information. While advertised as 15 minute
>   delayed, in reality any particular quote could be anywhere from 15 -
>   60 minutes delayed. This is the type of information that a
>   professional quote service may be able to provide (See first question above).

     This is baloney.  The delay is described somewhere in their web pages 
as about 5 minutes and thats what I've verified with a broker.
776.9Unless your broker is "Security APL" how would your broker know?12368::michaudJeff Michaud, UC1Wed Nov 09 1994 19:509
>      This is baloney.  The delay is described somewhere in their web pages 
> as about 5 minutes and thats what I've verified with a broker.

	How would your broker be able to verify the delay from the "Security
	APL Quoteserver"?  Also please provide the URL of the web page that
	says 5 minutes.

	From my personal experience, the delay can be min. 15 minutes
	(especially in the 1st hour of trading).
776.1015+MROA::BONVALLATWed Nov 09 1994 20:236
Right.  I've also experienced 15 mins or more.

It says "Equity quotes are exchange-delayed 15 minutes" on this page...

http://www.secapl.com/dtn/info/quotes.html

776.11Don't confuse the free [WWW] service with DTN Wall St.'s service12368::michaudJeff Michaud, UC1Wed Nov 09 1994 21:0511
> It says "Equity quotes are exchange-delayed 15 minutes" on this page...
> http://www.secapl.com/dtn/info/quotes.html

	Ok, I see the confusion .8 and .10 are having.  The above referened
	URL is part of the "Data Transmission Network Wall Street" service
	information.  DTN Wall St. is the service/co. that provides the
	Security APL Quoteserver with the quote info.  However because of
	the nature of the "free" service I believe the agreement Security
	APL has with DTN Wall St. is that quotes are no more recent than
	15 minutes.  If you subscribed directly to DTN Wall St. then you could
	get the mix of real-time and delayed quotes, but it will cost you.
776.12Clarification: 5 minute delay is for SPX, not equities.TALLIS::KOCHKevin Koch AKO2-1/G3 DTN244-7845Thu Nov 10 1994 14:2713
>>      This is baloney.  The delay is described somewhere in their web pages 
>> as about 5 minutes and thats what I've verified with a broker.
>
>How would your broker be able to verify the delay from the "Security
>APL Quoteserver"?  Also please provide the URL of the web page that
>says 5 minutes.

     I should have clarified that the 5 minute delay is for the SPX quote, 
which is all I care about.

     I keep my broker on the phone and keep reloading the quote.  The 
delay between when the broker gives a number and when it shows up on 
Sec/APL is about 5 minutes.
776.13SPX?12368::michaudJeff Michaud, UC1Thu Nov 10 1994 14:397
> I should have clarified that the 5 minute delay is for the SPX quote, ....

	SPX?

> I keep my broker on the phone and keep reloading the quote....

	Your broker has too much time on their hands :-)
776.14Request for VAX version ?38728::AGUPTAThu Nov 10 1994 20:467
    Hi,
    	I would appreciate if someone can port the program in VAX C and
    post it in this file.
    
    Thanks
    Abhijit
    
776.15Some observationsSUBSYS::DONADTFri Nov 11 1994 14:5114
    A few more observations:
    
    You can get quotes on Mutual Funds
    
    Quotes on stock options don't seem to work
    
    INDU (Dow Jones Industrial Average) seems to be updated very
    frequently. If you ask for a number of quotes on INDU within a 15
    minute period, each quote is different. Also, the "u" and "d" on the
    current djia quote seems to indicate the current direction of movement
    (tick?) of the average. The INDU quote is probably close to real time
    since you can get a quote right after the market opens.
    
    Ray
776.16KEPTIN::GRANOFFKeptin! Klingon wessel decloaking...Fri Nov 11 1994 18:4915
Piece of cake.  Next reply contains modified .1 to compile on OpenVMS VAX,
using DEC C V4.0. (This modified version will not compile with VAX C).

Compile and link thus:

	$ cc/standard=vaxc getquote.c
	$ link getquote.c

This worked on OpenVMS VAX V6.0 system.  Now, to incorporate this into
MXquote... :-) See KEPTIN::X-TOYS for more information; press KP7 to add
the conference to your notebook...

Thanks, Jeff!

-Mark
776.17OpenVMS & DEC C getquote.cKEPTIN::GRANOFFKeptin! Klingon wessel decloaking...Fri Nov 11 1994 18:49203
/*
 *	Quickie Get Quote
 *
 *	Provides command line (vs. Mosaic, Lynx, etc) access to the
 *	"Security APL Quote Server" WWW service.
 *
 *	Usage: getquote symbol ....
 *
 *	Author: Jeff Michaud, Oct. 14, 1994
 *
 *	Note: ANSI C comiler is assumed
 *
 *	Modification History
 *	Date	    Who		    What
 *	----------- --------------- -----------------------------------------
 *	11-Nov-94   Mark Granoff    Modifications for OpenVMS VAX & DEC C.
 *				    Compile using CC/STAND=VAXC.
 */

#define DIGITAL	/* Comment this line out if you have direct Internet access */

#if VMS
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/file.h>
#include <fcntl.h>
#include <socket.h>
/* #include <sys/ioctl.h> */
/* #include <netdnet/dn.h> */
#include <in.h>
#include <netdb.h>
/* #include <sysexits.h> */
#define EX_CANTCREAT 0
#define EX_UNAVAILABLE 0
#define EX_USAGE 0
#define EX_OK 1
#else
#include <stdio.h>
#include <errno.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/file.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netdnet/dn.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sysexits.h>
#endif

#ifdef DIGITAL
# define SERVER	"src-www.pa.dec.com"
# define PORT	"8080"
#else
# define SERVER	"www.secapl.com"
# define PORT	"http"
#endif

int
inet_conn(host, port)
    char *host;
    char *port;
{
    /* Local Vars */
    int                sock;      /* Socket to use for the connection */
    unsigned short     portn;     /* TCP port number                  */
    struct hostent     *hostent;  /* Destination host entry           */
    struct servent     *servent;  /* Destination service entry        */
    struct sockaddr_in addr;      /* Formated destination for connect */

    portn = htons(atoi(port));
    if( portn == 0 ) {
	servent = getservbyname(port, "tcp");
	if( ! servent )
	    return -1;
	else
	    portn = servent->s_port;
    }

    hostent = gethostbyname(host);

    /* No host entry, or host is not Internet, error! */
    if( hostent == NULL || hostent->h_addrtype != AF_INET )
	return -1;

    /* Get a socket from the system to use for the connection */
    if( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
	return -1;

    /* Make sure we start with a clean address structure ... */
    memset(&addr, 0, sizeof addr);

    /* ... then fill in the required fields */
    addr.sin_family = AF_INET;
    addr.sin_port   = portn;
    memcpy(&addr.sin_addr, hostent->h_addr, hostent->h_length);

    /* Now try to connection to the destination */
    if( connect(sock, &addr, sizeof(addr)) < 0 ) {
	/* No go, release the socket, and then return error! */
	close(sock);
	return -1;
    }

    /* Success.  Return the connected socket descriptor */
    return sock;
}

char requestprefix[] =
#ifdef DIGITAL
"POST http://www.secapl.com/cgi-bin/qsx HTTP/1.0\r\n"
#else
"POST /cgi-bin/qsx HTTP/1.0\r\n"
#endif
"Accept: www/source\r\n\
Accept: text/plain\r\n\
Accept: text/html\r\n\
Accept: application/postscript\r\n\
User-Agent:  Quickie Get Quote by Jeff Michaud\r\n\
Referer:  http://www.secapl.com/cgi-bin/qs\r\n\
Content-type: application/x-www-form-urlencoded\r\n";

void
getquote(char *symbol)
{
    FILE *tf;
    int server;
    char reply[1024];
    int len;

    tf = tmpfile();
    if( ! tf ) {
	fprintf(stderr, "Can't create tmpfile\n");
	exit(EX_CANTCREAT);
    }

    server = inet_conn(SERVER, PORT);
    if( server < 0 ) {
	fprintf(stderr, "Can't connect to server %s.%s\n", SERVER, PORT);
	exit(EX_UNAVAILABLE);
    }

    write(server, requestprefix, strlen(requestprefix));

    sprintf(reply, "Content-length: %d\r\n\r\ntick940904=%s\r\n",
				    11 + strlen(symbol), symbol);

    write(server, reply, strlen(reply));

    while( (len = read(server, reply, sizeof reply)) > 0 )
	fwrite(reply, 1, len, tf);

    rewind(tf);

    while( fgets(reply, sizeof reply, tf) )
	if( strstr(reply, "Query Results") )
	    break;

    if( feof(tf) ) {
	/* If we can't find what we're looking for, just print the
           whole response out since it should contain an error message */
	rewind(tf);
	while( fgets(reply, sizeof reply, tf) )
	    fputs(reply, stdout);
	return;
    }

    while( fgets(reply, sizeof reply, tf) )
	if( strstr(reply, "<pre>") )
	    break;

    while( fgets(reply, sizeof reply, tf) )
	if( strstr(reply, "</pre>") )
	    break;
	else
	    fputs(reply, stdout);

    fclose(tf);
}

main(int argc, char *argv[])
{
    int i;

    if( argc < 2 ) {
	fprintf(stderr, "Usage: %s symbol ...\n", argv[0]);
	exit(EX_USAGE);
    }

    for( i = 1 ; i < argc ; i++ ) {
	if( i > 1 )
	    putchar('\n');
	getquote(argv[i]);
	fflush(stdout);
    }

    exit(EX_OK);
}

776.1812368::michaudJeff Michaud, UC1Wed Nov 23 1994 17:5014
	Well the quote server now gives expanded quote information!
	Including what appears to be timestamps for the quotes!
	Only problem so far is that it doesn't know about DEC-A or
	INDU anymore :-(

Symbol        : DEC          Exchange    : New York Stock Exchange (NYSE)
Description   : DIGITAL EQUIPMENT CORP
Last Traded at: 33.750       Date/Time   : Nov 23  2:31:30
$ Change      : -0.500       % Change    : -1.46   

Volume        : 963600       # of Trades : 324      
Bid           : 33.500       Ask         : 33.625   
Day Low       : 33.500       Day High    : 34.375   
52 Week Low   : 18.250       52 Week High: 38.125   
776.1912368::michaudJeff Michaud, UC1Wed Nov 23 1994 18:1221
	Me thinks I found out why after the new quote information appeared
	that it doesn't reconize the symbols DEC-A and INDU anymore.
	Looking at the Security APL Quoteserver home page it looks like
	they switched to a different quote provider.  Here's the new
	FAQ page .....

You switched quote providers, what's going on?
   Security APL and North American Quotations (NAQ) have now begun a
   relationship to provide free 15 minute delayed quotes over the Internet. We
   (Security APL) would like to applaud Data Transmission Network (DTN) for
   their generous support of this project over the last six months. We will
   soon be using DTN for other kinds of financial information that we will
   provide to you on the WWW.  As part of the conversion to NAQ we have added
   several new features to our quoteserver: timestamp on all quotes, bid/ask
   information on most stocks, immediate pickup of new or changed symbols
   (although the description may lag), day high/low information and we have
   replaced the SP500 index with the Dow Jones Industrials index on the quote
   page. Look for the following features in the near future: quotes on
   Canadian stocks, quotes on US and Canadian options and futures, a Market
   Watch page consisting of many popular indicies and indicators, and pages
   showing top gainers/losers and most active issues.
776.20Quote Server UnavailableMR1MI1::SHERWINJim SherwinTue Nov 29 1994 23:5923
    I don't know this for certain  ....
    
    but based upon what I've read in this string on notes, it would appear
    that this or similar utility has made the quote service unavailable
    to the Digital community or portions thereof.
    
    I tried to access the quote server and received the following
    
    >Permission Denied :-(

    
    >Unfortunately we've had a real problem with scripts overloading our
    >quoteserver. There was one posted to the net the other day called pf
    >that was almost crippling. The gateway machine from your site was on
    >our list of abusers and we sent a message to the sys-op stating the
    >problem. As soon as this is cleared up you will be readmitted to our site. 

    >In the mean time you can use the quoteserver within our portfolio
    >management game (http://pawws.secapl.com), you'll find the quote-server
    >in the trade entry screen. 

    >andrew@secapl.com
    
776.22STAR::PARKETrue Engineers Combat ObfuscationWed Nov 30 1994 13:467
    re: .21
    
    Yes, you have to register fo rthe game.  You are given $200000 play
    money to invest for the current portion of the game, but you don't
    HAVE to play to get the quotes.
    
    
776.23Need a fix to get quotes ???CSCMA::BALICHThu Mar 16 1995 12:5024
    
    
    I tried to get quotes using http://www.secapl.com/cgi-bin/qs  ... I am
    now getting the following ... can someone explain what I need to do ...
    I'm only a novice with this stuff ... THANKS in advance!!!
    
    
    
    Sorry, www-relay.pa.dec.com is no longer a SOCKS
    relay
    
    (I'm sorry for this rather crude method of shutting down this service,
    but
    I don't know how else to reach all of you users.)
    
    As announced on Dec 26, 1994 in a note on internet_tools
    conference, www-relay.pa.dec.com is no longer in service as a SOCKS
    protocol based relay for the WWW. The approved way for getting
    out through the corporate firewall is to use the proxy protocol. Look
    at the my documentation on the proxy protocol for converting over.
    
    steveg@pa.dec.com (Steve Glassman) 
    Systems Research Center 
    
776.1getquote.cNETRIX::michaudJeff Michaud, That GroupThu Mar 16 1995 15:45255
/*
 *	Quickie Get Quote
 *
 *	Provides command line (vs. Mosaic, Lynx, etc) access to the
 *	"Security APL Quote Server" WWW service.
 *
 *	Usage: getquote symbol ....
 *
 *	Author: Jeff Michaud, Oct. 14, 1994
 *	Last updated: March 14, 1995
 *
 *	Note: ANSI C comiler is assumed
 */

#define DIGITAL	/* Comment this line out if you have direct Internet access */

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/file.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netdnet/dn.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sysexits.h>

int debug = 0;
int verbose = 0;

#ifdef DIGITAL
char *proxyservers[] = {
    "www-proxy.crl.dec.com\08080",	// CRL (US East Coast)
    "email.mko.dec.com\08080",		// MKO (US Southern NH)
    "www-proxy.pa.dec.com\08080",	// SRC (US West Coast)
    "dws-proxy.mro.dec.com\08080",	// MRO (US Marlboro Mass.)
    "www-proxy.ljo.dec.com\08080",	// LJO (field test s/w)
    "www-proxy.det.dec.com\08080",	// OHF (US, Detroit)
    0
};
# define PORT	"8080"
#else
# define SERVER	"www.secapl.com"
# define PORT	"http"
#endif

int
inet_conn(host, port)
    char *host;
    char *port;
{
    /* Local Vars */
    int                sock;      /* Socket to use for the connection */
    unsigned short     portn;     /* TCP port number                  */
    struct hostent     *hostent;  /* Destination host entry           */
    struct servent     *servent;  /* Destination service entry        */
    struct sockaddr_in addr;      /* Formated destination for connect */

    if( verbose )
	fprintf(stderr, "Attempting connection to %s:%s\n", host, port);

    portn = htons(atoi(port));
    if( portn == 0 ) {
	servent = getservbyname(port, "tcp");
	if( ! servent )
	    return -1;
	else
	    portn = servent->s_port;
    }

    hostent = gethostbyname(host);

    if( ! hostent  &&  verbose )
	fprintf(stderr, "...... hostname lookup failed\n");

    /* No host entry, or host is not Internet, error! */
    if( hostent == NULL || hostent->h_addrtype != AF_INET )
	return -1;

    /* Get a socket from the system to use for the connection */
    if( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
	return -1;

    /* Make sure we start with a clean address structure ... */
    memset(&addr, 0, sizeof addr);

    /* ... then fill in the required fields */
    addr.sin_family = AF_INET;
    addr.sin_port   = portn;
    memcpy(&addr.sin_addr, hostent->h_addr, hostent->h_length);

    /* Now try to connection to the destination */
    if( connect(sock, &addr, sizeof(addr)) < 0 ) {
	perror(host);
	/* No go, release the socket, and then return error! */
	close(sock);
	return -1;
    }

    if( verbose )
	fprintf(stderr, "...... connected\n");

    /* Success.  Return the connected socket descriptor */
    return sock;
}

char requestprefix[] =
#ifdef DIGITAL
"POST http://www.secapl.com:%s/cgi-bin/qsx HTTP/1.0\r\n"
#else
"POST /cgi-bin/qsx HTTP/1.0\r\n"
#endif
"Accept: www/source\r\n\
Accept: text/plain\r\n\
Accept: text/html\r\n\
Accept: application/postscript\r\n\
User-Agent:  Quickie Get Quote by Jeff Michaud\r\n\
Referer:  http://www.secapl.com/cgi-bin/qs\r\n\
Content-type: application/x-www-form-urlencoded\r\n";

void
getquote(char *symbol)
{
    FILE *tf;
    int server;
    char reply[1024];
    int len;
    char *servname;
    char *pport;
    char port[20];
#ifdef DIGITAL
    char **pps;
#endif

    tf = tmpfile();
    if( ! tf ) {
	fprintf(stderr, "Can't create tmpfile\n");
	exit(EX_CANTCREAT);
    }

    sprintf(port, "%2d", 80 + (random() % 4));

    servname = getenv("QGQ_SERVER");

#ifdef DIGITAL
    if( servname ) {
	pport = strchr(servname, ':');
	if( pport )
	    *pport++ = '\0';
	else
	    pport = PORT;

	server = inet_conn(servname, pport);
    }
    else
	for( pps = proxyservers ; *pps ; pps++ ) {
	    servname = *pps;
	    pport = strchr(*pps, '\0') + 1;
	    server = inet_conn(servname, pport);
	    if( server >= 0 )
		break;
	}
#else
    if( ! servname )
	servname = SERVER;
    pport = PORT;

    server = inet_conn(servname, pport);
#endif
    if( server < 0 ) {
	fprintf(stderr, "Can't connect to server %s:%s\n", servname, pport);
	exit(EX_UNAVAILABLE);
    }

    if( verbose )
	fprintf(stderr, "...... using http port %s\n", port);

#ifdef DIGITAL
    sprintf(reply, requestprefix, port);
    write(server, reply, strlen(reply));
#else
    write(server, requestprefix, strlen(requestprefix));
#endif

    sprintf(reply, "Content-length: %d\r\n\r\ntick940904=%s\r\n",
				    11 + strlen(symbol), symbol);

    write(server, reply, strlen(reply));

    while( (len = read(server, reply, sizeof reply)) > 0 ) {
	if( debug )
	    fwrite(reply, 1, len, stderr);
	fwrite(reply, 1, len, tf);
    }

    rewind(tf);

    while( fgets(reply, sizeof reply, tf) )
	if( strstr(reply, "Query Results") )
	    break;

    if( feof(tf) ) {
	/* If we can't find what we're looking for, just print the
           whole response out since it should contain an error message */
	rewind(tf);
	while( fgets(reply, sizeof reply, tf) )
	    fputs(reply, stdout);
	return;
    }

    while( fgets(reply, sizeof reply, tf) )
	if( strstr(reply, "<pre>") )
	    break;

    while( fgets(reply, sizeof reply, tf) )
	if( strstr(reply, "</pre>") )
	    break;
	else
	    fputs(reply, stdout);

    fclose(tf);
}

main(int argc, char *argv[])
{
    int i;

    srandom(time(0));

    if( argc < 2 ) {
	fprintf(stderr, "Usage: %s symbol ...\n", argv[0]);
	exit(EX_USAGE);
    }

    for( i = 1 ; i < argc ; i++ ) {
	if( strcmp(argv[i], "-v") == 0 ) {
	    verbose++;
	    continue;
	}
	else if( strcmp(argv[i], "-d") == 0 ) {
	    debug++;
	    continue;
	}

	if( i > 1 )
	    putchar('\n');
	getquote(argv[i]);
	fflush(stdout);
    }

    exit(EX_OK);
}
776.24NETRIX::michaudJeff Michaud, That GroupThu Mar 16 1995 15:485
	Hmm, interesting.  The program uses the PROXY support, not the
	SOCKS gateway protocol.  I'd try a different proxy server.

	FYI, I've posted a new version of the program to .1 that contains a
	list of proxy servers.
776.25LJSRV2::MAYERATG/Internet Business GroupMon Apr 10 1995 15:1210
	Re:.23.  If you are using an old version of Lynx (2.3 or earlier) or
  Mosaic (2.4 or esrlier) you are using an obsolete version that used the
  SOCKS relay instead of the Proxy relay.  The latest versions are available
  from TECO::SYS$PUBLIC: as LYNX*.EXE and MOSAIC*.EXE and (for Mosaic)
  MOSAIC.DAT.

	If you have questions about this post in the Internet_Tools notes
  Conference or send me mail as I don't normally read this notes conference.

	Danny
776.26How does it know I am running getquote, not lynx ??HELIX::SONTAKKEMon Apr 10 1995 20:5920
HTTP/1.0 200 OK
Server: Netscape-Commerce/1.1b1
Date: Monday, 10-Apr-95 20:51:31 GMT
Content-type: text/html

<html><head>
<title>Too Many Scripts</title>
<link rev="made" href="dhp@secapl.com"></head>
<body>
<center><h1>Too Many Quotes Requested via Scripts</h1></center><hr>
<p>Your site (192.58.206.21) has requested 114 quotes today with an automated
script
out of a maximum of 100 allowed.<p>
Please do not use automated programs to access this free service.
The agreements with our quote provider and the stock exchanges 
only allow us to provide quotes to individuals in a direct
query method.  While scripts can be used in this way we've
been finding that they are most often used to download a large
number of stocks or to query a particular stock on a frequent
interval (or both).<p>
776.27NETRIX::michaudJeff Michaud, That GroupMon Apr 10 1995 23:3013
Re: .26

	I've already reversed engineered how they know and have a new
	version of getquote.c.  However I do not want to release it
	because I don't want them disallowing Digital requests altogether
	(ie. even from real web browsers).

	A hint for other hackers, it only takes 3-5 lines of code changes
	from what I last posted in .1 to hack around the servers hack.
	Another hint, use a real browser, pull up the APL quote server
	page, then view the HTML source (vs. rendered view).  If you figure
	it out, please do not post the answer, nor distribute modified source
	or binaries.
776.28problem getting quote via wwwMSBCS::HURLEYTue May 16 1995 15:4614
    I used to be able to access http://www.secapl.com:86/cgi-bin/qszz url
    Title: Untitled, URL http://www.secapl.com:86/cgi-bin/qszz thru mosaic
    with no  problem up to a week ago. Now when I try to get a stock quote
    I get the following error message
    
    Requested document (URL http://www.secapl.com:86/cgi-bin/qszz) could
    not
    be accessed.
    
    The information server either is not accessible or is refusing to serve
    the
    document to you.
    
    Any ideas??
776.29maybe the servers...WONDER::BENTOI've got TV but I want T-Rex...Thu May 18 1995 15:348
    Working for me John!
    
    Sometimes the Proxy servers are out-to-snack for a minute or two...
    A retry usually does the trick.
    
    Stop by 
    
    -TB
776.30NETRIX::michaudJeff Michaud, That GroupWed May 24 1995 23:275
	FWIW for anyone still using .0, seems the server has changed
	the returned output slightly, including on of the fields
	the program used to key off where the returned quote was
	in the HTML.  Simply replace the string "Query Results" with
	"FORM METHOD" to match the new output.
776.31NT and OPENVMS Version of GETQUOTE.CALFAXP::KENDRIXJohn Kendrix - DTN: 343-1739Thu May 25 1995 22:23386
/*  Here is a version of this utility that will work on OpenVMS VAX,
OpenVMS AXP, and Windows NT...  I used the GETDEC.C code that someone posted to
the conference as a guide for building this one.  I have tested this with both
OpenVMS 6.1, and NT 3.5 with VC++ v2.0.  The make file for VC++ v2.0 is in the
next reply to this note.  

Many thanks to Jeff and the others who have built these fine utilities!!

Regards,

John Kendrix
*/


/*
 *	Quickie Get Quote
 *
 *	Provides command line (vs. Mosaic, Lynx, etc) access to the
 *	"Security APL Quote Server" WWW service.
 *
 *	Usage: getquote symbol ....
 *
 *	Author: Jeff Michaud, Oct. 14, 1994
 *
 *	Note: ANSI C comiler is assumed
 */

#define DIGITAL	/* Comment this line out if you have direct Internet access */

#ifdef DIGITAL
char *proxyservers[] = {
	"www-proxy.det.dec.com\08080",  /* OHF (US, Detroit)  */
    "email.mko.dec.com\08080",      /* MKO (US Southern NH)   */
    "www-proxy.pa.dec.com\08080",   /* SRC (US West Coast)  */
    "www-proxy.crl.dec.com\08080",  /*  CRL (US East Coast) */
    "dws-proxy.mro.dec.com\08080",  /* MRO (US Marlboro Mass.) */
	0
};
# define SERVER "www.secapl.com"
# define PORT   "8080"
#else
# define SERVER	"www.secapl.com"
# define PORT	"http"
#endif

#ifdef VMS
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <types.h>
#include <file.h>
#include <fcntl.h>
#include <socket.h>
#include <UCX$RPCXDR.H>
#include <UCX$INETDEF.H>
/* #include <dn.h>         */
#define EX_CANTCREAT 0
#define EX_UNAVAILABLE 0
#define EX_USAGE 0
#define EX_OK 1
#include <in.h>
#include <unixio.h>
#include <unixlib.h>
#include <netdb.h>
#endif

									
#ifdef WIN32
#include <stdio.h>
#include <stdlib.h>
#include <errno.h> 
#include <time.h>
#include <string.h>
#include <sys/types.h> 
#include <math.h>
#include <fcntl.h>
#include <winsock.h>
#include <io.h>
#include <memory.h>
#include <process.h>
#define EX_CANTCREAT 0
#define EX_UNAVAILABLE 0
#define EX_USAGE 0
#define EX_OK 1
#endif

#ifdef UNIX
#include <sys/types.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netdnet/dn.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sysexits.h>
#endif

int debug = 0;
int verbose = 0;
int rawhtml = 0;

int
inet_conn(host, port)
    char *host;
    char *port;
{
    /* Local Vars */
    int                sock;      /* Socket to use for the connection */
    unsigned short     portn;     /* TCP port number                  */
#ifdef WIN32    
    struct hostent far  *hostent;  /* Destination host entry           */
#else
    struct hostent     *hostent;  /* Destination host entry           */
#endif   
    struct servent     *servent;  /* Destination service entry        */
    struct sockaddr_in addr;      /* Formated destination for connect */

    if( verbose )
	fprintf(stderr, "Attempting connection to %s:%s\n", host, port);

    portn = htons(atoi(port));
    if( portn == 0 ) {
	servent = getservbyname(port, "tcp");
	if( ! servent )
	    return -1;
	else
	    portn = servent->s_port;
    }

    hostent = gethostbyname(host);

    /* No host entry, or host is not Internet, error! */
    if( hostent == NULL || hostent->h_addrtype != AF_INET )
	return -1;

    /* Get a socket from the system to use for the connection */
    if( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
	return -1;

    /* Make sure we start with a clean address structure ... */
    memset(&addr, 0, sizeof addr);

    /* ... then fill in the required fields */
    addr.sin_family = AF_INET;
    addr.sin_port   = portn;
    memcpy(&addr.sin_addr, hostent->h_addr, hostent->h_length);
    /* Now try to connection to the destination */
#ifdef WIN32
    if( connect(sock, ((struct sockaddr far *) &addr), sizeof(addr)) < 0 ) {
	perror(host);
#else
 if( connect(sock, &addr, sizeof(addr)) < 0 ) {
	/* No go, release the socket, and then return error! */
#endif

#ifdef WIN32
	closesocket(sock);
#else
	close(sock);
#endif

	return -1;
    }

    if( verbose )
	fprintf(stderr, "...... connected\n");

    /* Success.  Return the connected socket descriptor */
    return sock;
}



char requestprefix[] =
#ifdef DIGITAL
"POST http://www.secapl.com/cgi-bin/qs80 HTTP/1.0\r\n"
#else
"POST /cgi-bin/qsx HTTP/1.0\r\n"
#endif
"Accept: www/source\r\n\
Accept: text/plain\r\n\
Accept: text/html\r\n\
Accept: application/postscript\r\n\
User-Agent: Quickie Get Quote by Jeff Michaud\r\n\
Referer: http:%/%/www.secapl.com/cgi-bin/qsx\r\n\
Content-type: application/x-www-form-urlencoded\r\n";

void
getquote(char *symbol)
{
    FILE *tf;
    int server;
    char reply[1048];
    int len;
    char *servname;
    char *pport;
    char port[20];
#ifdef DIGITAL
    char **pps;
#endif

    tf = tmpfile();
    if( ! tf ) {
	fprintf(stderr, "Can't create tmpfile\n");
	exit(EX_CANTCREAT);
    }

#ifndef VMS	
    sprintf(port, "%2d", 80 + (rand(time(0)) % 4));
      servname = getenv("QGQ_SERVER");
#endif

#ifdef VMS	
    sprintf(port, "%2d", 80 + (rand(time(0)) % 4));
      servname = getenv("QGQ_SERVER");
#endif
   
#ifdef DIGITAL
    if( servname ) {
    pport = strchr(servname, ':');
    if( pport )
        *pport++ = '\0';
    else
        pport = PORT;

    server = inet_conn(servname, pport);
    }
    else
    for( pps = proxyservers ; *pps ; pps++ ) {
        servname = *pps;
        pport = strchr(*pps, '\0') + 1;
        server = inet_conn(servname, pport);
        if( server >= 0 )
        break;
    }
#else
    if( ! servname )
    servname = SERVER;
    pport = PORT;

    server = inet_conn(servname, pport);
#endif
   
   
    
    if( server < 0 ) {
	fprintf(stderr, "Can't connect to server %s.%s\n", SERVER, PORT);
	exit(EX_UNAVAILABLE);
    }

      if( verbose )
	     fprintf(stderr, "...... using http port %s\n", PORT);

#ifdef DIGITAL
    sprintf(reply, requestprefix, port);
#ifdef WIN32
   send(server, reply, strlen(reply),0);
#else
   write(server, reply, strlen(reply));
#endif
#endif


    sprintf(reply, "Content-length: %d\r\n\r\ntick940904=%s\r\n",
				    11 + strlen(symbol), symbol);

    send(server, reply, strlen(reply),0);

#ifdef WIN32
   while( (len = recv(server, reply, sizeof (reply),0)) > 0 ) {
#else
   while( (len = read(server, reply, sizeof reply)) > 0 ) {
#endif
	if( debug )
	    fwrite(reply, 1, len, stderr);
	fwrite(reply, 1, len, tf);
    }

#ifdef WIN32
    closesocket(server);
#else
    close(server);
#endif

    rewind(tf);

    while( fgets(reply, sizeof reply, tf) )
	if( strstr(reply, "FORM METHOD") )
	    break;

    if( feof(tf) ) {
	/* If we can't find what we're looking for, just print the
           whole response out since it should contain an error message */
	rewind(tf);
	while( fgets(reply, sizeof reply, tf) )
	    fputs(reply, stdout);
	fclose(tf);
	return;
    }

    while( fgets(reply, sizeof reply, tf) )
	if( strstr(reply, "<pre>") )
	    break;

    while( fgets(reply, sizeof reply, tf) )
	if( strstr(reply, "</pre>") )
	    break;
	else
	    fputs(reply, stdout);
    while( fgets(reply, sizeof reply, tf) ) {
	char *djia = strstr(reply, "is at");

	if( djia ) {
	    fprintf(stdout, "\nDJIA %s", djia);
	    break;
	}

    }

    fclose(tf);
}

int main(int argc, char *argv[])
{
    int i;

#ifdef WIN32
    int PASCAL FAR WSAStartup ( WORD wVersionRequired, LPWSADATA lpWSAData );
    WORD wVersionRequested;
    WSADATA wsaData;
    int err;

wVersionRequested = 0x0101;

err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
    /* Tell the user that we couldn't find a useable */
    /* winsock.dll.                                  */
    return;
}

/* Confirm that the Windows Sockets DLL supports 1.1.*/
/* Note that if the DLL supports versions greater    */
/* than 1.1 in addition to 1.1, it will still return */
/* 1.1 in wVersion since that is the version we      */
/* requested.                                        */

if ( LOBYTE( wsaData.wVersion ) != 1 ||
         HIBYTE( wsaData.wVersion ) != 1 ) {
    /* Tell the user that we couldn't find a useable */
    /* winsock.dll.                                  */
    WSACleanup( );
    return;   

}

/* The Windows Sockets DLL is acceptable.  Proceed.  */
#endif

rand(time(0));
    for( i = 1 ; i < argc ; i++ )
	if( strcmp(argv[i], "-v") == 0 )
	    verbose++;
	else if( strcmp(argv[i], "-d") == 0 )
	    debug++;
	else if( strcmp(argv[i], "-r") == 0 )
	    rawhtml++;
	else {	    putchar('\n');
	getquote(argv[i]);
	fflush(stdout);
    }
	
   if( argc < 2 ) {
	fprintf(stderr, "Usage: %s symbol ...\n", argv[0]);
	exit(-1);
    }

 

#ifdef WIN32
    WSACleanup( );
#endif

    exit(EX_OK); 

}
776.32GETQUOTE.MAK file for NT and VC++ 2.0ALFAXP::KENDRIXJohn Kendrix - DTN: 343-1739Thu May 25 1995 22:24272
# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00
# ** DO NOT EDIT **

# TARGTYPE "Win32 (ALPHA) Console Application" 0x0603

!IF "$(CFG)" == ""
CFG=Win32 Debug
!MESSAGE No configuration specified.  Defaulting to Win32 Debug.
!ENDIF 

!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" && "$(CFG)" !=\
 "Hermes" && "$(CFG)" != "HermesD"
!MESSAGE Invalid configuration "$(CFG)" specified.
!MESSAGE You can specify a configuration when running NMAKE on this makefile
!MESSAGE by defining the macro CFG on the command line.  For example:
!MESSAGE 
!MESSAGE NMAKE /f "getquote.mak" CFG="Win32 Debug"
!MESSAGE 
!MESSAGE Possible choices for configuration are:
!MESSAGE 
!MESSAGE "Win32 Release" (based on "Win32 (ALPHA) Console Application")
!MESSAGE "Win32 Debug" (based on "Win32 (ALPHA) Console Application")
!MESSAGE "Hermes" (based on "Win32 (ALPHA) Console Application")
!MESSAGE "HermesD" (based on "Win32 (ALPHA) Console Application")
!MESSAGE 
!ERROR An invalid configuration is specified.
!ENDIF 

################################################################################
# Begin Project
# PROP Target_Last_Scanned "Win32 Debug"
CPP=cl.exe
RSC=rc.exe

!IF  "$(CFG)" == "Win32 Release"

# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP Use_MFC 2
# PROP Use_Debug_Libraries 0
OUTDIR=.
INTDIR=.

ALL : $(OUTDIR)/getquote.exe $(OUTDIR)/getquote.bsc

# ADD BASE CPP /nologo /Gt0 /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c
# ADD CPP /nologo /MD /Gt0 /W3 /GX /Zi /YX /Od /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_AFXDLL" /D "_MBCS" /FR /c
CPP_PROJ=/nologo /MD /Gt0 /W3 /GX /Zi /YX /Od /D "WIN32" /D "NDEBUG" /D\
 "_CONSOLE" /D "_AFXDLL" /D "_MBCS" /FR$(INTDIR)/ /Fp$(OUTDIR)/"getquote.pch"\
 /Fo$(INTDIR)/ /Fd$(OUTDIR)/"getquote.pdb" /c 
CPP_OBJS=
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
BSC32_FLAGS=/nologo /o$(OUTDIR)/"getquote.bsc" 
BSC32_SBRS= \
	$(INTDIR)/getquote.sbr

$(OUTDIR)/getquote.bsc : $(OUTDIR)  $(BSC32_SBRS)
    $(BSC32) @<<
  $(BSC32_FLAGS) $(BSC32_SBRS)
<<

LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /NOLOGO /SUBSYSTEM:console /MACHINE:ALPHA
# ADD LINK32 wsock32.lib /NOLOGO /SUBSYSTEM:console /PROFILE /MACHINE:ALPHA
LINK32_FLAGS=wsock32.lib /NOLOGO /SUBSYSTEM:console /PROFILE /MACHINE:ALPHA\
 /OUT:$(OUTDIR)/"getquote.exe" 
DEF_FILE=
LINK32_OBJS= \
	$(INTDIR)/getquote.obj

$(OUTDIR)/getquote.exe : $(OUTDIR)  $(DEF_FILE) $(LINK32_OBJS)
    $(LINK32) @<<
  $(LINK32_FLAGS) $(LINK32_OBJS)
<<

!ELSEIF  "$(CFG)" == "Win32 Debug"

# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP Use_MFC 2
# PROP Use_Debug_Libraries 1
OUTDIR=.
INTDIR=.

ALL : $(OUTDIR)/getquote.exe $(OUTDIR)/getquote.bsc

# ADD BASE CPP /nologo /Gt0 /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c
# ADD CPP /nologo /MD /Gt0 /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_AFXDLL" /D "_MBCS" /FR /c
CPP_PROJ=/nologo /MD /Gt0 /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D\
 "_CONSOLE" /D "_AFXDLL" /D "_MBCS" /FR$(INTDIR)/ /Fp$(OUTDIR)/"getquote.pch"\
 /Fo$(INTDIR)/ /Fd$(OUTDIR)/"getquote.pdb" /c 
CPP_OBJS=
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
BSC32_FLAGS=/nologo /o$(OUTDIR)/"getquote.bsc" 
BSC32_SBRS= \
	$(INTDIR)/getquote.sbr

$(OUTDIR)/getquote.bsc : $(OUTDIR)  $(BSC32_SBRS)
    $(BSC32) @<<
  $(BSC32_FLAGS) $(BSC32_SBRS)
<<

LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:ALPHA
# ADD LINK32 wsock32.lib /NOLOGO /SUBSYSTEM:console /PROFILE /DEBUG /MACHINE:ALPHA
LINK32_FLAGS=wsock32.lib /NOLOGO /SUBSYSTEM:console /PROFILE /DEBUG\
 /MACHINE:ALPHA /OUT:$(OUTDIR)/"getquote.exe" 
DEF_FILE=
LINK32_OBJS= \
	$(INTDIR)/getquote.obj

$(OUTDIR)/getquote.exe : $(OUTDIR)  $(DEF_FILE) $(LINK32_OBJS)
    $(LINK32) @<<
  $(LINK32_FLAGS) $(LINK32_OBJS)
<<

!ELSEIF  "$(CFG)" == "Hermes"

# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Hermes0"
# PROP BASE Intermediate_Dir "Hermes0"
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Hermes0"
# PROP Intermediate_Dir "Hermes0"
OUTDIR=.\Hermes0
INTDIR=.\Hermes0

ALL : $(OUTDIR)/getquote.exe $(OUTDIR)/getquote.bsc

$(OUTDIR) : 
    if not exist $(OUTDIR)/nul mkdir $(OUTDIR)

# ADD BASE CPP /nologo /Gt0 /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c
# ADD CPP /nologo /Gt0 /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c
CPP_PROJ=/nologo /Gt0 /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\
 /FR$(INTDIR)/ /Fp$(OUTDIR)/"getquote.pch" /Fo$(INTDIR)/ /c 
CPP_OBJS=.\Hermes0/
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
BSC32_FLAGS=/nologo /o$(OUTDIR)/"getquote.bsc" 
BSC32_SBRS= \
	$(INTDIR)/getquote.sbr

$(OUTDIR)/getquote.bsc : $(OUTDIR)  $(BSC32_SBRS)
    $(BSC32) @<<
  $(BSC32_FLAGS) $(BSC32_SBRS)
<<

LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /NOLOGO /SUBSYSTEM:console /MACHINE:ALPHA
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib wsock32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:ALPHA
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
 advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib wsock32.lib /NOLOGO\
 /SUBSYSTEM:console /PDB:$(OUTDIR)/"getquote.pdb" /MACHINE:ALPHA\
 /OUT:$(OUTDIR)/"getquote.exe" 
DEF_FILE=
LINK32_OBJS= \
	$(INTDIR)/getquote.obj

$(OUTDIR)/getquote.exe : $(OUTDIR)  $(DEF_FILE) $(LINK32_OBJS)
    $(LINK32) @<<
  $(LINK32_FLAGS) $(LINK32_OBJS)
<<

!ELSEIF  "$(CFG)" == "HermesD"

# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "HermesD"
# PROP BASE Intermediate_Dir "HermesD"
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "HermesD"
# PROP Intermediate_Dir "HermesD"
OUTDIR=.\HermesD
INTDIR=.\HermesD

ALL : $(OUTDIR)/getquote.exe $(OUTDIR)/getquote.map $(OUTDIR)/getquote.bsc

$(OUTDIR) : 
    if not exist $(OUTDIR)/nul mkdir $(OUTDIR)

# ADD BASE CPP /nologo /Gt0 /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c
# ADD CPP /nologo /Gt0 /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c
CPP_PROJ=/nologo /Gt0 /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\
 /FR$(INTDIR)/ /Fp$(OUTDIR)/"getquote.pch" /Fo$(INTDIR)/\
 /Fd$(OUTDIR)/"getquote.pdb" /c 
CPP_OBJS=.\HermesD/
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
BSC32_FLAGS=/nologo /o$(OUTDIR)/"getquote.bsc" 
BSC32_SBRS= \
	$(INTDIR)/getquote.sbr

$(OUTDIR)/getquote.bsc : $(OUTDIR)  $(BSC32_SBRS)
    $(BSC32) @<<
  $(BSC32_FLAGS) $(BSC32_SBRS)
<<

LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:ALPHA
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib wsock32.lib /NOLOGO /SUBSYSTEM:console /MAP /DEBUG /MACHINE:ALPHA
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
 advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib wsock32.lib /NOLOGO\
 /SUBSYSTEM:console /PDB:$(OUTDIR)/"getquote.pdb" /MAP:$(INTDIR)/"getquote.map"\
 /DEBUG /MACHINE:ALPHA /OUT:$(OUTDIR)/"getquote.exe" 
DEF_FILE=
LINK32_OBJS= \
	$(INTDIR)/getquote.obj

$(OUTDIR)/getquote.exe : $(OUTDIR)  $(DEF_FILE) $(LINK32_OBJS)
    $(LINK32) @<<
  $(LINK32_FLAGS) $(LINK32_OBJS)
<<

!ENDIF 

.c{$(CPP_OBJS)}.obj:
   $(CPP) $(CPP_PROJ) $<  

.cpp{$(CPP_OBJS)}.obj:
   $(CPP) $(CPP_PROJ) $<  

.cxx{$(CPP_OBJS)}.obj:
   $(CPP) $(CPP_PROJ) $<  

################################################################################
# Begin Group "Source Files"

################################################################################
# Begin Source File

SOURCE=.\getquote.c

!IF  "$(CFG)" == "Win32 Release"

$(INTDIR)/getquote.obj :  $(SOURCE)  $(INTDIR)

!ELSEIF  "$(CFG)" == "Win32 Debug"

$(INTDIR)/getquote.obj :  $(SOURCE)  $(INTDIR)

!ELSEIF  "$(CFG)" == "Hermes"

$(INTDIR)/getquote.obj :  $(SOURCE)  $(INTDIR)

!ELSEIF  "$(CFG)" == "HermesD"

$(INTDIR)/getquote.obj :  $(SOURCE)  $(INTDIR)

!ENDIF 

# End Source File
# End Group
# End Project
################################################################################
776.33funds only, not stocks?NETCAD::FLOWERSHigh Performance Networking; DanTue Dec 26 1995 13:2112
Hi Jeff,

I'm still using the getquote.c in .1 (with the right mods you mentioned
a couple replies back)...

But I've noticed a new problem the last week or so.  It only returns data
for mutual funds -- not stocks.

I haven't had time to debug it - has anyone else seen this problem?

Thanks,
Dan
776.342155::michaudJeff Michaud - ObjectBrokerTue Dec 26 1995 14:1512
	I'm no longer providing updates as they change the server for
	fear it will have the same result as the original version (ie.
	they restrict access to the server).  Sorry.  However ...

	I can tell you that to get it working again it's a one
	line fix ..... I do ask the anyone who does hack their local
	copy to not re-distribute, thanks!

ps: my guess is they will phase out the old HTML format all together
    once they have worked the problems out of the new format.  The
    new format is a little more complex to parse, but does return
    more info and allows you to request multiple quotes in one request.
776.35What's going on?SMURF::SWARDCommon sense is not that commonWed Feb 07 1996 16:218
    
    I have been fooling around with the getquote.c sources and I think that
    I got it to work BUT, the data I get back today is dated jan 30 and it
    says invalid name for a number of stock that the browser shows
    correctly.
    
    /Peter
    
776.362155::michaudJeff Michaud - ObjectBrokerWed Feb 07 1996 17:043
	It could be their continued support for the old format
	(using the URL http://..../qso vs. .../qs) is being phased
	out and isn't getting fed by their feeder :-((
776.37SMURF::SWARDCommon sense is not that commonWed Feb 07 1996 19:537
    
    re .-1 
    
    I get a correct quote using the browser and asking for the old format.
    Besides I get the same old quote using both the qs and qso...
    
    /Peter
776.382155::michaudJeff Michaud - ObjectBrokerWed Feb 07 1996 21:1122
> I get a correct quote using the browser and asking for the old format.
> Besides I get the same old quote using both the qs and qso...

	Ah, I see what it is now.  I forgot they had changed over
	to another machine (or it was a recent change and I didn't
	know).  Looks like the old machine is still up and running a Web
	server but stopped getting a quote feed on Jan. 30th.

	Change the URL to:	http://qs.secapl.com/cgi-bin/qso

	Notice the other difference from .0 is the :%s appended to
	the hostname is gone as the random port # they were using
	to handle a high load of requests is no longer needed.

	Also note that like the new table format server, the old non-table
	format flavor also accepts returning multiple quotes in a single
	response.

	And as you'll discover, you'll also need to change the program
	to check for a successful response by changing the string passed
	to strstr from "Query Results" to something like "FORM METHOD"
	(however that may not sense invalid symbol lookups).
776.40SMURF::SWARDCommon sense is not that commonThu Feb 08 1996 13:4411
    
    Thanks Jeff,
    
    I looked and looked at the location using the browser since the program
    returned unknown symbol for this server for some stocks and never
    noticed the change from www. to qs.
    
    Amazing what we don't see.
    
    Thanks
    	/Peter
776.41HELIX::SONTAKKEThu Feb 08 1996 17:5914
    RE: .39
    
    There is a bug in.  It eats the first symbol.  
    
    $ getquote dec
    $ getquote dec ibm
    		IBM returned
    $ getquote dec ibm msft
    		IBM returned
    		MSFT returned
    
    The code which looks for the option swallows the first argv.
    
    - Vikas
776.39new version of getquote.c2155::michaudJeff Michaud - ObjectBrokerThu Feb 08 1996 18:03256
/*
 *	Quickie Get Quote
 *
 *	Provides command line (vs. Mosaic, Lynx, etc) access to the
 *	"Security APL Quote Server" WWW service.
 *
 *	Usage: getquote symbol ....
 *
 *	Author: Jeff Michaud, Oct. 14, 1994
 *	Last updated: March 14, 1995
 *
 *	Note: ANSI C comiler is assumed
 */

#define DIGITAL	/* Comment this line out if you have direct Internet access */

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/file.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netdnet/dn.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sysexits.h>

int debug = 0;
int verbose = 0;

int qcount = 0;

#ifdef DIGITAL
char *proxyservers[] = {
    "www-proxy.crl.dec.com\08080",	// CRL (US East Coast)
    "www-proxy.pa.dec.com\08080",	// SRC (US West Coast)
    0
};
# define PORT	"8080"
#else
# define SERVER	"www.secapl.com"
# define PORT	"http"
#endif

int
inet_conn(host, port)
    char *host;
    char *port;
{
    /* Local Vars */
    int                sock;      /* Socket to use for the connection */
    unsigned short     portn;     /* TCP port number                  */
    struct hostent     *hostent;  /* Destination host entry           */
    struct servent     *servent;  /* Destination service entry        */
    struct sockaddr_in addr;      /* Formated destination for connect */

    if( verbose )
	fprintf(stderr, "Attempting connection to %s:%s\n", host, port);

    portn = htons(atoi(port));
    if( portn == 0 ) {
	servent = getservbyname(port, "tcp");
	if( ! servent )
	    return -1;
	else
	    portn = servent->s_port;
    }

    hostent = gethostbyname(host);

    if( ! hostent  &&  verbose )
	fprintf(stderr, "...... hostname lookup failed\n");

    /* No host entry, or host is not Internet, error! */
    if( hostent == NULL || hostent->h_addrtype != AF_INET )
	return -1;

    /* Get a socket from the system to use for the connection */
    if( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
	return -1;

    /* Make sure we start with a clean address structure ... */
    memset(&addr, 0, sizeof addr);

    /* ... then fill in the required fields */
    addr.sin_family = AF_INET;
    addr.sin_port   = portn;
    memcpy(&addr.sin_addr, hostent->h_addr, hostent->h_length);

    /* Now try to connection to the destination */
    if( connect(sock, &addr, sizeof(addr)) < 0 ) {
	perror(host);
	/* No go, release the socket, and then return error! */
	close(sock);
	return -1;
    }

    if( verbose )
	fprintf(stderr, "...... connected\n");

    /* Success.  Return the connected socket descriptor */
    return sock;
}

char requestprefix[] =
#ifdef DIGITAL
"POST http://qs.secapl.com/cgi-bin/qso HTTP/1.0\r\n"
#else
"POST /cgi-bin/qso HTTP/1.0\r\n"
#endif
"Accept: www/source\r\n\
Accept: text/plain\r\n\
Accept: text/html\r\n\
Accept: application/postscript\r\n\
Referer:  http://www.secapl.com/cgi-bin/qs\r\n\
Content-type: application/x-www-form-urlencoded\r\n";

/*User-Agent:  Quickie Get Quote by Jeff Michaud\r\n\ */

void
getquote(char *symbol)
{
    FILE *tf;
    int server;
    char reply[1024];
    int len;
    char *servname;
    char *pport;
#ifdef DIGITAL
    char **pps;
#endif

    tf = tmpfile();
    if( ! tf ) {
	fprintf(stderr, "Can't create tmpfile\n");
	exit(EX_CANTCREAT);
    }

    servname = getenv("QGQ_SERVER");

#ifdef DIGITAL
    if( servname ) {
	pport = strchr(servname, ':');
	if( pport )
	    *pport++ = '\0';
	else
	    pport = PORT;

	server = inet_conn(servname, pport);
    }
    else
	for( pps = proxyservers ; *pps ; pps++ ) {
	    servname = *pps;
	    pport = strchr(*pps, '\0') + 1;
	    server = inet_conn(servname, pport);
	    if( server >= 0 )
		break;
	}
#else
    if( ! servname )
	servname = SERVER;
    pport = PORT;

    server = inet_conn(servname, pport);
#endif
    if( server < 0 ) {
	fprintf(stderr, "Can't connect to server %s:%s\n", servname, pport);
	exit(EX_UNAVAILABLE);
    }

    write(server, requestprefix, strlen(requestprefix));

    sprintf(reply, "Content-length: %d\r\n\r\ntick950812=%s\r\n",
				    11 + strlen(symbol), symbol);

    write(server, reply, strlen(reply));

    while( (len = read(server, reply, sizeof reply)) > 0 ) {
	if( debug )
	    fwrite(reply, 1, len, stderr);
	fwrite(reply, 1, len, tf);
    }

    rewind(tf);

    while( fgets(reply, sizeof reply, tf) )
	if( strstr(reply, "FORM METHOD") )
	    break;

    if( feof(tf) ) {
	/* If we can't find what we're looking for, just print the
           whole response out since it should contain an error message */
	rewind(tf);
	while( fgets(reply, sizeof reply, tf) )
	    fputs(reply, stdout);
	return;
    }

    do {
	while( fgets(reply, sizeof reply, tf) )
	    if( strstr(reply, "<pre>") ) {
		if( qcount++ > 0 )
		    putchar('\n');
		break;
	    }

	while( fgets(reply, sizeof reply, tf) )
	    if( strstr(reply, "</pre>") )
		break;
	    else if( ! strchr("\r\n", reply[0]) )
		fputs(reply, stdout);
    } while( ! feof(tf) );

    fclose(tf);
}

main(int argc, char *argv[])
{

    if( argc < 2 ) {
	fprintf(stderr, "Usage: %s symbol ...\n", argv[0]);
	exit(EX_USAGE);
    }

    for( argc--, argv++ ; argc > 0 && **argv == '-' ; argc--, argv++ )
	if( strcmp(*argv, "-v") == 0 )
	    verbose++;
	else if( strcmp(*argv, "-d") == 0 )
	    debug++;
	else
	    fprintf(stderr, "unknown option: %s\n", *argv);

    for( ; argc > 0 ; ) {
	int len = 0;
	char symbols[51];

	symbols[0] = '\0';

	do {
	    if( len ) {
		strcat(symbols, " ");
		len++;
	    }

	    strcat(symbols, *argv);
	    len += strlen(*argv);
	} while( --argc > 0 && (len + strlen(*++argv) + 1) <= 50 );

	getquote(symbols);
    }

    exit(EX_OK);
}
776.422155::michaudJeff Michaud - ObjectBrokerThu Feb 08 1996 18:056
>     There is a bug in.  It eats the first symbol.  
>     The code which looks for the option swallows the first argv.

	what do you want for free :-)).  i guess i only tested it
	when i always gave an option.  cut & paste of the for loop
	error.  I've fixed it and reposted it back as .39 again.
776.43I'm trying, but not there yet...USDEV::CLEMENTSmells like NirvanaMon Mar 11 1996 16:348
    I pulled the latest version in .39.  I am new to both C and Unix.  
    I compiled using "cc getquote.c -o getquote"
    
    I ran for the first time by typing in "getquote dec ibm emc"
    
    after hitting return it just sits there with nothing happening.
    
    Any pointers on what to try next?  Thanks, Mark
776.44swagsNETCAD::FLOWERSHigh Performance Networking; DanMon Mar 11 1996 17:3613
>    I compiled using "cc getquote.c -o getquote"

Hmm, I thought the flags are supposed to go first...

I used:                          
	cc -g3 -O0 -o getquote getquote.c

(The -g and -O options trun on optimization.)

Also, did you have have to "chmod +x getquote" to make the output
executable?

Dan
776.45Sadly we only have two (2) Digital wide proxy servers2155::michaudJeff Michaud - ObjectBrokerMon Mar 11 1996 18:5213
> after hitting return it just sits there with nothing happening.

	use the -v option to see if it's hanging on the connect to
	the proxy server.  The CRL proxy server seems to be having
	problems today.  If it's not hanging on the connect, it could
	then be hanging waiting for a response.  For some reason
	today CRL seems to be gettings lots of "connection timed
	out" (which take a while over TCP/IP) when the proxy server
	tries to connect to the destination url.

	Change the order of the two proxy servers in the source code
	or use the QGQ_SERVER environment variable to select the
	name of a proxy server (ie. the Palo Alto [pa-x] one).
776.46ZENDIA::FERGUSONMr. Plumber's coding servicesTue Mar 12 1996 12:394
Jeff,
Will this work on NT?
thanks,
jc
776.47see .312155::michaudJeff Michaud - ObjectBrokerTue Mar 12 1996 14:539
> Will this work on NT?

	didn't you ask that back in .3 :-)

	i haven't tried it on NT, but the author of .31/.32 made changes
	(and posted to those notes) update sources to compile/link it on
	NT (as well as VMS it says).  Doing a diff of .31 with .1 you
	should be able to use that to make appropriate changes to the
	new version of getquote.c to compile on NT.
776.48still tryingUSDEV::CLEMENTSmells like NirvanaTue Mar 12 1996 17:5113
    another try...
    
    compiled it with 
    
    cc -g3 -O0 -o getquote getquote.c
    
    Ran with -v option...  result is
    
    Attempting connection to www-proxy.crl.dec.com:8080
    ...... connected
    
    This is as far as it gets.  Still trying, still learning, please send
    more help!  Thanks, Mark
776.492155::michaudJeff Michaud - ObjectBrokerTue Mar 12 1996 20:096
>     Attempting connection to www-proxy.crl.dec.com:8080
                                         ^^^

	did you read .47 (ie. the one right before the note you just posted)?
	the CRL server has been acting up the last couple of days.  use
	the Palo Alto proxy (ie. ...pa-x.dec.com)
776.50ZENDIA::FERGUSONMr. Plumber's coding servicesWed Mar 13 1996 11:5212
re       <<< Note 776.47 by 2155::michaud "Jeff Michaud - ObjectBroker" >>>
                                  -< see .31 >-

>	didn't you ask that back in .3 :-)

Sorry, i don't have a ton of time to grope 
notes for all my past replies.

thanks for the tips, hopefully someday i'll get it to
work on NT.

jc
776.51Notes primer 2022155::michaudJeff Michaud - ObjectBrokerWed Mar 13 1996 12:537
> Sorry, i don't have a ton of time to grope 
> notes for all my past replies.

	And you think I have the time?  I was using "SEARCH/NOTES=776.* NT"
	looking for you when I came across your previous request (and then
	came across the reply with the NT port).  Took only a couple of
	minutes when you know how to use the tools :-)