/*
 
 wr v1.1B, 1993-07-28
 wr v1.1,  1993-05-25
 wr v1.0,  1993-05-18
 
 Copyright (c) 1993, Brian McKeever (McKeever@CSTP.UMKC.EDU)
 
This program may be freely redistributed at no charge provided that this
notice is left intact.  Modified copies must preserve this notice.  It is
also requested that any useful changes you make to it be sent to the author.
 
  			    S p e c i a l   N o t e
 
National Weather Service data is made available courtesy of the National
Science Foundation-funded UNIDATA project and the University of Michigan.
 
 			     D e s c r i p t i o n
 
This is a C port of the "wx" Bourne shell script.  Below is the Copyright
notice from the Author of "wx":
 
 # Copyright (C) 1992, Peter St.Wecker (pswecker@med.unc.edu)
 #
 # This script may be freely re-distributed at no charge provided that
 # this notice is left intact.  Modified copies must preserve this notice.
 # It is requested that any useful changes you make be sent to the author.
 # 
 # Thanks to: Dale A. Harris (rodmur@ecst.csuchico.edu)
 #            Kevin Bluml (kevin@ferris.cray.com)
 #
 # Special thanks to Jeff Masters (jmasters@madlab.sprl.umich.edu) for all
 # his work on the Weather Underground.

The program compiles and runs on VMS (VAX & AXP) with Multinet; Ultrix with
gcc, cc & c89; on SunOS with gcc and cc; and on a NEXTstation with gcc.

 			    C o m p i l a t i o n

 VAXC, OpenVMS/VAX & Multinet

	$ CC WR
	$ LINK WR, SYS$INPUT/OPT
	MULTINET:MULTINET_SOCKET_LIBRARY/SHARE
	SYS$SHARE:VAXCRTL/SHARE
	<CTRL-Z>
	$ WR :== $<device>:<directory>WR.EXE

 DEC C, OpenVMS/AXP & Multinet

	$ CC WR		! Expect some implicit funtion declaration
			! informational messages.  You can ignore them.
	$ LINK WR, SYS$INPUT/OPT
	MULTINET:MULTINET_SOCKET_LIBRARY/SHARE
	<CTRL-Z>
	$ WR :== $<device>:<directory>:WR.EXE
 
 GCC - OpenVMS/VAX & Multinet

	$ GCC WR
	$ LINK WR, SYS$INPUT/OPT
	GNU_CC:[000000]GCCLIB/LIB
	MULTINET:MULTINET_SOCKET_LIBRARY/SHARE
	SYS$SHARE:VAXCRTL/SHARE
	<CTRL-Z>
	$ WR :== $<device>:<directory>:WR.EXE

 VAXC, OpenVMS/VAX & TCPware

	$ CC WR/DEFINE=TCPWARE
	$ LINK WR, SYS$INPUT/OPT
	SYS$SHARE:TCPWARE_SOCKLIB_SHR/SHARE
	SYS$SHARE:VAXCRTL/SHARE
	<CTRL-Z>
	$ WR :== $<device>:<directory>WR.EXE

 DEC C, OpenVMS/AXP & TCPware

	$ CC WR/DEFINE=TCPWARE
	$ LINK WR, SYS$INPUT/OPT
	SYS$SHARE:TCPWARE_SOCKLIB_SHR/SHARE
	<CTRL-Z>
	$ WR :== $<device>:<directory>:WR.EXE

 GCC - Ultrix, SunOs, NEXT

	% gcc wr.c -o wr

 CC - Ultrix, SunOS

	% cc wr.c -o wr

 C89 - Ultrix

	% c89 wr.c -o wr

			      S y n o p s i s

Basically, the program works by connecting to a default port at a default
site and emulating a human reading and responding to the menus that the
weather system displays.  It looks for a prompt, sends a response, waits
for a prompt, sends a response,... and so forth.  It allocates MAXTALK
TALKLINEs to record the "conversation".  The array of TALK lines is
interpreted as paired prompts and responses.  The even lines (0, 2, 4,
6,...) are prompt strings it looks for and the odd lines (1, 3, 5, 7,...)
are the command responses it sends when it recognizes a prompt.

Programmers should be able to add their own options to the program easily
as it is not that sophisticated.  It's a functional solution, not
necessarily an elegant one.

VMS compiled versions have two options that the UN*X flavors won't:  -PG
and -OUT.  These were provided because VMS does not currently support pipes
or output redirection to a file.  -PG works by writing the output to a
temporary file and then making a `system' call to TYPE/PAGE the temporary
file.  Not particularily efficient, but it works.  UN*X's support for pipes
and output redirection make these options unnecessary.

	------ VMS ---------		------ UN*X --------
	$ WR -ALL MCI -PG		% wr -all mci | more
	$ WR -ALL MCI -OUT SAVE.DAT	% wr -all mci > save.dat

There are also two options to WR that are not documented when you invoke it
without arguments or with -h:  -SITE and -PORT.  The default site and port
can be found in "#define" lines in the code.  These can be over-ridden using
the above two options.  They would be useful for debugging purposes or for
using alternate weather hosts.

			  M o d i f i c a t i o n s

							Brian, 1993-07-28.01

V1.1B - The format of the lines from the Weather Underground changed.  They
started sending CR,LF,CR,CR.  Since WR uses CR's to denote line breaks, it
translates the new format into tripple spacing.  I changed it to use LF's
for line breaks.  CRs are just ignored by WR.
							B. Volz, 1993-05-28.01

Added support for TCPware.

							Brian, 1993-05-27.01

Modified the -STATE option to request unlimited scrolling before it
requested a city report for a state.  California had so many possible
reporting stations that the server was paginating the output and causing
the client to lock up.

							Brian, 1993-05-25.01

Created version 1.1 by adding the option -NS for near shore observations. 
I used -NS instead of -M like `wx' syntax so I could add offshore and
marine observations at a later date (version 1.2 probably).  -NS with no
parameter returns the list of near shore stations that report conditions.

Fixed some logic that allowed syntactically incorrect commands like `wr -us
mci' to cause the program to hang.  Also, multiple options now replace each
other.  A command like `wr -us -cc mci' caused V1.0 to hang.  Version 1.1
uses just the last option.  The previous example performs the same function
as a `wr -cc mci' command.

							Brian, 1993-05-20.02

Changed the logic so that the -H option allowed users to save the help
information out to a file when used in conjunction with -OUT.

							Brian, 1993-05-20.01

Major changes:

    o	Data from the network is broken into lines before it is displayed.
    o	Implemented -PG and -OUT for VMS.  Added supporting comments and
	help entries.
    o	The `for' loop that translates all command line arguments into
	upper-case was changed so that the program would work properly
	with GCC on VMS.  It's `toupper' function was translating hyphens
	into carriage returns.  Bummer.

							Brian, 1993-05-19.04

Changed to explicit variable initializations so that even the default
compilers that come with SunOS and Ultrix will compile the program.

							Brian, 1993-05-19.03

Added -CC option for current weather information.

							Brian, 1993-05-19.02

Added comments, copyrights and compilation instructions.

 							Brian, 1993-05-19.01
 
Changed initializations of strings to standard syntax after suggestions
made by CC/STANDARD=PORTABLE.
 
Added initialization for TALK line.  This makes sure the program will will
compile on VAXC and Alpha C.  The lack of initialization was causing the
program to work sometimes and not at others.  ALWAYS INITIALIZE YOUR
VARIABLES!

 */

#include <stdio.h>
/*#include <stdlib.h>*/
#include <string.h>
#include <ctype.h>

#ifdef   VMS
#ifdef   TCPWARE
#include "tcpware_include:types.h"
#include "tcpware_include:socket.h"
#include "tcpware_include:in.h"
#include "tcpware_include:netdb.h"
#define	 SOCKET_READ	socket_read
#define	 SOCKET_WRITE	socket_write
#define	 SOCKET_PERROR	perror
#else
#include "multinet_root:[multinet.include.sys]types.h"
#include "multinet_root:[multinet.include.sys]socket.h"
#include "multinet_root:[multinet.include.netinet]in.h"
#include "multinet_root:[multinet.include]netdb.h"
#define	 SOCKET_READ	socket_read
#define	 SOCKET_WRITE	socket_write
#define	 SOCKET_PERROR	socket_perror
#endif
#else
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define	 SOCKET_READ	read
#define	 SOCKET_WRITE	write
#define	 SOCKET_PERROR	perror
#endif

#define  WEATHER_SITE	"downwind.sprl.umich.edu"
#define  WEATHER_PORT	3000
#ifdef	 VMS
#define	 OUTFILE	"SYS$SCRATCH:WEATHER-REPORT.TXT"
#endif

#define	 MAXCHAR 256
#define	 TRUE	1
#define	 FALSE	0
#define	 CR	13
#define  LF	10
#define  CITY_CODE_LEN	3	/* Needed for rudimentary verification */
#define  STATE_CODE_LEN	2
#define  MAXTALK	12	/* Allows for 6 call & response pairs  */
#define  EXITLEN	3

static	char	*help_screen[] = {
" ",
" National Weather Service data is made available courtesy of the National",
" Science Foundation-funded UNIDATA project and the University of Michigan",
" ",
" Syntax:",
" ",
"  wr <state> (MO, KS, etc.)              | wr -s <city> (Severe Weather)",
"  wr <city> (NYC, MCI, etc.)             | wr -c <city> (Climatic Data)",
"  wr -can (Canadian Codes)               | wr -e <city> (Extended Forecast)",
"  wr -all <city> (All a City's Data)     | wr -q (Earthquake Report)",
"  wr -f <city> (1-2 day forcast)         | wr -cc <city> (Current Conditions)",
"  wr -ns [<code>] (Near Shore Codes, [Near Shore Report for <code>])",
"  wr -us (National Weather Summary)",
"  wr -ski [<zone>] (Ski Zones, [Zone Report])",
"  wr -state [<state>] (State Abbreviations, [City Codes in <state>])",
"  wr -ocean [<zone>] (Ocean Zones, [Zone Hurricane Information])",
"  wr -int [<int-code>] (International Codes, [Weather Info. for <int-code>])",
"  wr -x (Connect interactively with Weather Underground)",
"  wr -h (Show Help Message)",
#ifdef	VMS
"  wr -pg (Display output a page at a time)",
"  wr -out [<file>] (Save output to SYS$SCRATCH:WEATHER-REPORT.TXT or <file>)",
#endif
NULL};

main(argc, argv)

int	argc;
char	**argv;

{
    FILE
	*stdio;

    int
	i, s, n;

    unsigned short
	port = WEATHER_PORT;

    typedef char TALKLINE[MAXCHAR];

    char
	buf[MAXCHAR + 1],
	break_text[MAXCHAR],
	line[MAXCHAR + 1],
	exit_text[EXITLEN],
	weather_site[MAXCHAR],
#ifdef	VMS
	outfile[MAXCHAR],
#endif
	*default_site = weather_site,
	*loc,
	*loc1,			/* Probably could get rid of some of these */
	*tmp1,			/* but I decided to let the compilers      */
	*tmp2,			/* optomize them away.                     */
	*command,
	*prompt_text,
	*tmp_ptr,
	do_help		= FALSE,
	has_parameter	= FALSE,
	option_chosen	= FALSE,
#ifdef	VMS
	save_output	= FALSE,
	pg		= FALSE,
#endif
	shunt_read	= FALSE;	/* This is needed if you want to   */
					/* stop displaying information     */
					/* before the end of a menu.  Like */
					/* for the WR -OCEAN display       */
    TALKLINE
	talk[MAXTALK],
	*talk_line;

    struct sockaddr_in sin;
    struct hostent *hp;

	if (argc < 2) {

	    char **lines;

	  syntax:
	    for (lines = help_screen; *lines; lines++)
		fprintf(stderr, "%s\n", *lines);
	    fprintf(stderr, "\n");
	    exit(1);
	}

/*
 *  Initializations for less capable C compilers...
 */
	*buf = *break_text = *line = 0;

/*
 *  All data is written to whatever is pointed to by stdio.  `stdio' could
 *  point to a file or the terminal.  By default, it points to the standard
 *  output device.  This is so it can be redirected in support of the -PG
 *  and -OUT options for the VMS version.  UN*X versions will always point
 *  to `stdout'.
 */
	stdio = stdout;

	strcpy(exit_text, "X\n");
	strcpy(weather_site, WEATHER_SITE);

#ifdef	VMS
	strcpy(outfile, OUTFILE);
#endif

	for (i=0; i < MAXTALK; i++) *talk[i] = 0;

/*
 *  Initialize the call/response array...
 */
	strcpy(talk[0], "city code:");
	i        = 1;
	*talk[i] = 0;

/*
 *  Process the options.  There are a LOT of if...else... statements in here.
 *  If each one had been indented as dependant conditionals often are, the
 *  source would be way too wide.  With this method, it's easy to cut &
 *  paste new options into the program.
 */

	option_chosen = FALSE;

	while (*++argv) {
	    for (loc = *argv; *loc; loc++)
		if (*loc != '-')		/* This IF is needed by	*/
		    *loc = toupper(*loc);	/* GCC under VMS.	*/

	    tmp_ptr       = *(argv + 1);
	    has_parameter = FALSE;
	    if (tmp_ptr) {
		if (*tmp_ptr != '-') {
		    has_parameter = TRUE;
		}
	    }

	    if (!strcmp(*argv, "-SITE")) {
		if (*++argv) {
		    default_site = *argv;
		}
		else {
		    fprintf(stderr, "  Syntax:  wr -site <host-name>\n");
		    exit(1);
		}
	    }
#ifdef	VMS
	    else if (!strcmp(*argv, "-PG")) {
		    pg    = TRUE;
		    if (!save_output) {
			stdio = fopen(outfile, "w");
			if (!stdio) {
			    fprintf(stderr, "  fopen(\"%s\", \"w\") failed\n",
				outfile);
			    exit(1);
			}
		    }
		 }
	    else if (!strcmp(*argv, "-OUT")) {
		    if (has_parameter) {
			if (!pg) {
			    strcpy(outfile, *++argv);
			}
			else {
			    fprintf(stderr, "  wr:  %s ignored.\n\
       %s is the output file.\n", *++argv, outfile);
			}
		    }
		    save_output = TRUE;
		    if (!pg) {
			stdio = fopen(outfile, "w");
			if (!stdio) {
			    fprintf(stderr, "  fopen(\"%s\", \"w\") failed\n",
				    outfile);
			    exit(1);
			}
		    }
		 }
#endif
	    else if (!strcmp(*argv, "-PORT")) {
		    if (*++argv) {
			port = atol(*argv);
			if (port == 0) {
			    fprintf(stderr, "  Bad port number %u\n", port);
			    exit(1);
			}
		    }
		    else {
			fprintf(stderr, "  Syntax:  wr -port <port>\n");
			exit(1);
		    }
		 }
/*
 *  The code that prints the help screen is duplicated here so that the user
 *  can change save it to a file when it's used in conjunction with the -OUT
 *  and -PG options.  The help is written to `stdio' not to `stderr' if no
 *  option is passed to wr.
 */
	    else if (!strcmp(*argv, "-H")) {
		    if (option_chosen)
			i = 1;
			
		    option_chosen = TRUE;
		    do_help = TRUE;
		 }
	    else if (!strncmp(*argv, "-NS", 3)) {
		    if (option_chosen)
			i = 1;
			
		    option_chosen = TRUE;

		    if (has_parameter) {
			sprintf(talk[i++], "%sm\n", *++argv);
			*talk[i++] = 0;
			strcpy(break_text, "CITY FORECAST MENU");
		    }
		    else {
			strcpy(talk[i++], "\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "c\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "4\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "11\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "4\n");
			*talk[i++] = 0;
			strcpy(break_text, "MARINE FORECASTS AND OBSERVATIONS");
		    }
		 }
	    else if (!strncmp(*argv, "-ST", 3)) {
		    if (option_chosen)
			i = 1;
			
		    option_chosen = TRUE;

		    if (has_parameter) {
			strcpy(talk[i++], "\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "c\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "4\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "1\n");
			strcpy(talk[i++], "Selection:");
			sprintf(talk[i++], "%s\n", *++argv);
			*talk[i++] = 0;
			strcpy(break_text, "CITY FORECAST MENU");
		    }
		    else {
			strcpy(talk[i++], "\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "c\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "4\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "1\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "4\n");
			*talk[i++] = 0;
			strcpy(break_text, "CITY FORECAST MENU");
		    }
		 }
/*
 *  Since VMS has another option that starts with -O, the first 3 characters
 *  must be used to make sure that all the options are unique.  UN*X versions
 *  can still use -O for -OCEANS.
 */

#ifdef	VMS
	    else if (!strncmp(*argv, "-OCEAN", 3)) {
#else
	    else if (!strncmp(*argv, "-OCEAN", 2)) {
#endif
		    if (option_chosen)
			i = 1;
			
		    option_chosen = TRUE;

		    if (has_parameter) {
			strcpy(talk[i++], "\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "c\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "4\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "8\n");
			strcpy(talk[i++], "Selection:");
			sprintf(talk[i++], "%s\n", *++argv);
			*talk[i++] = 0;
			strcpy(break_text, "HURRICANE ADVISORIES");
		    }
		    else {
			strcpy(talk[i++], "\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "8\n");
			*talk[i++] = 0;
			strcpy(break_text, "M) Return to main menu");
			shunt_read = TRUE;
		    }
		 }
	    else if (!strcmp(*argv, "-INT")) {
		    if (option_chosen)
			i = 1;
			
		    option_chosen = TRUE;

		    if (has_parameter) {
			strcpy(talk[i++], "\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "c\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "4\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "10\n");
			strcpy(talk[i++], "Selection:");
			sprintf(talk[i++], "%s\n", *++argv);
			*talk[i++] = 0;
			strcpy(break_text, "CURRENT INTERNATIONAL");
		    }
		    else {
			strcpy(talk[i++], "\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "10\n");
			*talk[i++] = 0;
			strcpy(break_text, "M) Return to main menu");
			shunt_read = TRUE;
		    }
		 }
	    else if (!strcmp(*argv, "-SKI")) {
		    if (option_chosen)
			i = 1;
			
		    option_chosen = TRUE;

		    if (has_parameter) {
			strcpy(talk[i++], "\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "c\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "4\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "4\n");
			strcpy(talk[i++], "Selection:");
			sprintf(talk[i++], "%s\n", *++argv);
			*talk[i++] = 0;
			strcpy(break_text, "SKI REPORTS");
		    }
		    else {
			strcpy(talk[i++], "\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "4\n");
			*talk[i++] = 0;
			strcpy(break_text, "X) Exit program");
			shunt_read = TRUE;
		    }
		 }
	    else if (!strncmp(*argv, "-A", 2)) {
		    if (option_chosen)
			i = 1;
			
		    option_chosen = TRUE;

		    if (*++argv) {
			sprintf(talk[i++], "%s+f\n", *argv);
			*talk[i++] = 0;
			strcpy(break_text, "CITY FORECAST MENU");
			}
		    else {
			fprintf(stderr, "  Syntax:  wr -all <city>\n");
			exit(1);
		    }
		 }
	    else if (!strcmp(*argv, "-US")) {
		    if (option_chosen)
			i = 1;
			
		    option_chosen = TRUE;

		    if (has_parameter) {
			fprintf(stderr, "  Syntax:  wr -us\n");
			exit(1);
		    }
		    else {
			strcpy(talk[i++], "\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "c\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "4\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "9\n");
			*talk[i++] = 0;
			strcpy(break_text, "MAIN MENU");
		    }
		 }
	    else if (!strcmp(*argv, "-CAN")) {
		    if (option_chosen)
			i = 1;
			
		    option_chosen = TRUE;

		    if (has_parameter) {
			fprintf(stderr, "  Syntax:  wr -can\n");
			exit(1);
		    }
		    else {
			strcpy(talk[i++], "\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "2\n");
			strcpy(break_text, "X) Exit program");
			*talk[i++] = 0;
			shunt_read = TRUE;
		    }
		 }
	    else if (!strcmp(*argv, "-Q")) {
		    if (option_chosen)
			i = 1;
			
		    option_chosen = TRUE;

		    if (has_parameter) {
			fprintf(stderr, "  Syntax:  wr -q [option]\n");
			exit(1);
		    }
		    else {
			strcpy(talk[i++], "\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "c\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "4\n");
			strcpy(talk[i++], "Selection:");
			strcpy(talk[i++], "6\n");
			*talk[i++] = 0;
			strcpy(break_text, "MAIN MENU");
		    }
		 }
	    else if (!strcmp(*argv, "-S")) {
		    if (option_chosen)
			i = 1;
			
		    option_chosen = TRUE;

		    if (*++argv) {
			sprintf(talk[i++], "%ss\n", *argv);
			*talk[i++] = 0;
			strcpy(break_text, "CITY FORECAST MENU");
		    }
		    else {
			fprintf(stderr, "  Syntax:  wr -s <city>\n");
			exit(1);
		    }
		 }
	    else if (!strcmp(*argv, "-E")) {
		    if (option_chosen)
			i = 1;
			
		    option_chosen = TRUE;

		    if (*++argv) {
			sprintf(talk[i++], "%se\n", *argv);
			*talk[i++] = 0;
			strcpy(break_text, "CITY FORECAST MENU");
		    }
		    else {
			fprintf(stderr, "  Syntax:  wr -e <city>\n");
			exit(1);
		    }
		 }
	    else if (!strcmp(*argv, "-CC")) {
		    if (option_chosen)
			i = 1;
			
		    option_chosen = TRUE;

		    if (*++argv) {
			sprintf(talk[i++], "%so\n", *argv);
			*talk[i++] = 0;
			strcpy(break_text, "CITY FORECAST MENU");
		    }
		    else {
			fprintf(stderr, "  Syntax:  wr -cc <city>\n");
			exit(1);
		    }
		 }
	    else if (!strcmp(*argv, "-F")) {
		    if (option_chosen)
			i = 1;
			
		    option_chosen = TRUE;

		    if (*++argv) {
			sprintf(talk[i++], "%sf\n", *argv);
			*talk[i++] = 0;
			strcpy(break_text, "CITY FORECAST MENU");
		    }
		    else {
			fprintf(stderr, "  Syntax:  wr -f <city>\n");
			exit(1);
		    }
		 }
	    else if (!strcmp(*argv, "-C")) {
		    if (option_chosen)
			i = 1;
			
		    option_chosen = TRUE;

		    if (*++argv) {
			sprintf(talk[i++], "%sc\n", *argv);
			*talk[i++] = 0;
			strcpy(break_text, "CITY FORECAST MENU");
		    }
		    else {
			fprintf(stderr, "  Syntax:  wr -c <city>\n");
			exit(1);
		    }
		 }
	    else if (!strcmp(*argv, "-X")) {
#ifdef	VMS
#ifdef	TCPWARE
		    sprintf(line, "$ TELNET %s %u", default_site, port);
#else
		    sprintf(line, "$ TELNET/PORT=%u %s", port, default_site);
#endif
#else
		    sprintf(line, "/usr/ucb/telnet %s %u",  default_site, port);
#endif
		    system(line);
		    exit(1);
		 }
	    else {
		if (**argv == '-') {
		    fprintf(stderr, "  Bad option %s\n  Use 'wr -h' for \
a list of options.\n", *argv);
		    exit(1);
		}
		else {
		    if (strlen(*argv) == CITY_CODE_LEN) {
			sprintf(talk[i++], "%su\n", *argv);
			strcpy(break_text, "CITY FORECAST MENU");
		    }
		    else {
			if (strlen(*argv) == STATE_CODE_LEN) {
			    if (atol(*argv))
				strcpy(break_text, "CANADIAN FORECASTS");
			    else
				strcpy(break_text, "CURRENT WEATHER MENU");
			    sprintf(talk[i++], "%s+\n", *argv);
			}
			else {
			    if (atol(*argv)) {
				strcpy(break_text, "CANADIAN FORECASTS");
				sprintf(talk[i++], "%s+\n", *argv);
			    }
			    else {
				fprintf(stderr, "  %s is not a valid code.\n",
					*argv);
				exit(1);
			    }
			}
		    }
		}
	    }
	}	/* while argv */


	if (do_help) {
		char **lines;

	    for (lines = help_screen; *lines; lines++)
		fprintf(stdio, "%s\n", *lines);
	    fprintf(stdio, "\n");
	    goto quick_exit;
	}

	if (*talk[1] == 0) {
	    fprintf(stderr, "  wr:  nothing to do\n");
	    exit(1);
	}

	hp = gethostbyname(default_site);
	if (hp == NULL) {
		fprintf(stderr, "wr: %s unknown\n", default_site);
		exit(0x10000000);
	}

/*
 *  Create an IP-family socket on which to make the connection
 */

	s = socket(hp->h_addrtype, SOCK_STREAM, 0);
	if (s < 0) {
		SOCKET_PERROR("wr: socket");
		exit(0x10000000);
	}

/*
 *  Create a "sockaddr_in" structure which describes the remote
 *  IP address we want to connect to (from gethostbyname()) and
 *  the remote TCP port number (from getservbyname()).
 */

	sin.sin_family = hp->h_addrtype;
	bcopy(hp->h_addr, &sin.sin_addr, hp->h_length);
	sin.sin_port = htons(port);

/*
 *  Connect to that address...
 */

	if (connect(s, &sin, sizeof (sin)) < 0) {
		SOCKET_PERROR("wr: connect");
		exit(0x10000000);
	}

/*
 *  Talk to the weather server, wait for it's messages and then send
 *  back a response.  The `for' loop gets us down to the data that we
 *  want screen by screen.  Data from the network is just eaten after
 *  it is scanned for prompts.  When it's done talking, it should be
 *  time to read and display the data the user requested.
 */
	*line = 0;

	for (talk_line = talk; **talk_line; talk_line++) {

	    prompt_text = *talk_line;
	    command     = *++talk_line;

	    while ((n = SOCKET_READ(s, buf, MAXCHAR)) > 0) {

		buf[n] = 0;

		loc = loc1 = buf;

		while (loc = strchr(loc, CR)) {	/* Find EOL		*/
		    *loc++ = 0;			/* Mark end of string	*/
		    strcat(line, loc1);		/* Save it...		*/
		    *line  = 0;
		    loc1   = loc;
		}

		strcat(line, loc1);
		if (strstr(line, prompt_text)) break;
	    }
	    SOCKET_WRITE(s, command, strlen(command));
	}

/*
 *  Now start reading & displaying the data the user requested.  The data
 *  is broken up into discrete records and then written to `stdio'.  Any
 *  line that contains `break_text' is not displayed and this loop exits.
 *  All data up to the line containing `break_text' is displayed.
 *
 *  The internal `while' loop just before the data is displayed is
 *  necessary because CRs and LFs do not necessarily appear in neat
 *  CR/LF pairs from the weather server.  Sometimes they come in
 *  LF/CR pairs instead.  And sometimes even in CR/LF/CR tupples.
 *  This algorithm interprets CRs as end-of-line.  All non-control
 *  characters are stripped out of each line before it is sent to the
 *  output as a fresh record with a new `\n' on the end.  It's a brute
 *  force type of approach.
 */
	*line   = 0;

	while ((n = SOCKET_READ(s, buf, sizeof(buf))) > 0) {

	    buf[n]     = 0;

	    loc = loc1 = buf;

	    while (loc = strchr(loc, LF)) {	/* Find EOL		*/
		*loc++ = 0;			/* Mark end of string	*/
		strcat(line, loc1);		/* Save it...		*/
		if (strstr(line, break_text))	/* Is this what we are	*/
		   break;			/* looking for?		*/
		else {
		    tmp1 = tmp2 = line;		/* Nope.  Display it.	*/
		    while (*tmp1) {		/* But first get rid of	*/
			if (!iscntrl(*tmp1))	/* all the LFs and CRs	*/
			    *tmp2++ = *tmp1;
			tmp1++;
		    }
		    *tmp2 = 0;			/* Null terminate it.	*/
		    fprintf(stdio, "%s\n",	/* Write the line as a	*/
			    line);		/* fresh record.	*/
		}

		*line  = 0;
		loc1 = loc;
	    }

	    if (strstr(line, break_text))	/* Check lines not	*/
		break;				/* ending in a CR	*/
	    else {
		strcat(line, loc1);		/* Data may span more	*/
	    }					/* than one packet.	*/
	}

/*
 * Are we stopping displaying data before the end of the menu?
 */
	if (shunt_read)				/* So I used a goto?	*/
	    goto skip_selection_read;

/*
 * Now wait for the "Selection:" prompt from the main menu.  This is
 * probably not necessary, but it seemed reasonable to me to read all
 * the available data whether it was displayed or not.
 */
	while ((n = SOCKET_READ(s, buf, sizeof(buf))) > 0) {

	    buf[n] = 0;

	    loc = loc1 = buf;

	    while (loc = strchr(loc, CR)) {	/* Find EOL		*/
		*loc++ = 0;			/* Mark end of string	*/
		strcat(line, loc1);		/* Save it...		*/
		*line  = 0;
		loc1   = loc;
	    }

	    strcat(line, loc1);
	    if (strstr(line, "Selection:")) break;
	}
/*
 * Tell the weather host we are done...
 */

    skip_selection_read:
	SOCKET_WRITE(s, exit_text, strlen(exit_text));

/*
 * Read all the data that is sent back after the exit command.  The
 * weather server will close the connection.
 */
	while ((n = SOCKET_READ(s, buf, sizeof(buf))) > 0);

	if (n < 0) {
	    SOCKET_PERROR("wr: SOCKET_READ");
	    exit(0x10000000);
	}

/*
 * Implement the -PG and -OUT options.
 */
    quick_exit:

#ifdef	VMS
	if (stdio != stdout) {
	    fclose(stdio);
	    if (pg) {
		sprintf(line, "$ TYPE/PAGE %s", outfile);
		system(line);
	    }
	    if (!save_output) {
		sprintf(line, "%s", outfile);
		remove(line);
	    }
	}
#endif

	exit(1);
}


