#!/usr/local/bin/perl 'di'; 'ig00'; # # $Header$ # # $Log$ # # A perl script to connect to the 'weather server' at # Michigan and get the forcast for whatever city # you want (3 letter code -- columbus 'cmh' by default). # # Alternatively, you can get the current information for # a state if you enter a 2 letter code. # # Thanks to J Greely for the original network code, and # Tom Fine for assistance and harassment. # # Copyright 1991 Frank Adelstein. All Rights Reserved. # # Permission to use, copy, modify, and distribute this # software is hereby granted without fee, provided that # the copyright notice and permission notice are not removed. # # --FNA 6/28/91 # # Hacked by George Ferguson (ferguson@cs.rochester.edu) to include # Canadian forecasts by zone number. # # From the README (which you should have read already): # While I (gf) welcome reports of bugs in the program, I have neither the # time nor the desire to constantly maintain this program. The script # can get confused when the weather server's menu change, and I'd prefer # to not be flooded with messages about the script being broken every # time this happens. If something like that happens, and if I fix the # script to handle it, you can be sure I will post the changes. However, # please do not mail me requesting new versions. The Perl script is # simple enough for you to have a go at fixing it yourself and posting # the changes. Both the Net and I will love you for it. # # ferguson@cs.rochester.edu, 26 Jun 1992: Mods for new weather service menus. # I ripped lots of stuff out of this version, some of it may have to be # put back, but it works fine for me. # It's much easier to navigate the system now (for US forecasts, anyway), # so the interaction loop is considerably simplified. The Canadian stuff # is relatively straightforward also. # kenr@storage.tandem.com 29 Jun 1992: Handle severe weather statements. # gf 29 Jun 1992: More severe weather stuff for Canadian forecasts. # gf 30 Jun 1992: Use <<...>> stuff in weatherT.pl then generate weather.pl. # 8 Jul 1992: # gf: Started version numbering at 2.1. # frank@cis.ohio-state.edu: Show message if connection refused. # 16 Sep 1992: Version 2.2 # bruce@cs.ualberta.ca: Some continue patterns changed # $VERSION = "2.2"; $SERVER = "downwind.sprl.umich.edu"; $PORT = "3000"; $| = 1; # so "connecting...." gets out # # Parse argument, if any # $CITY = $ARGV[0] || "DEN"; # No arg -> use default city # # Allow 4-char symbolic names for Canadian reports. # %canNames = ("salt","1", "SALT","1", "calt","2", "CALT","2", "nalt","3", "NALT","3", "nebc","3", "NEBC","3", "cobc","4", "COBC","4", "inbc","5", "INBC","5", "sman","6", "SMAN","6", "nman","7", "NMAN","7", "nova","8", "NOVA","8", "pedi","9", "PEDI","9", "newb","10", "NEWB","10", "labr","11", "LABR","11", "nfld","12", "NFLD","12", "sont","13", "SONT","13", "nont","14", "NONT","14", "nwon","15", "NWON","15", "ssas","16", "SSAS","16", "nsas","17", "NSAS","17", "yukn","18", "YUKN","18", "sque","19", "SQUE","19", "ottw","19", "OTTW","19", "nque","20", "NQUE","20"); # # If we're given one of these names, use the number instead. # if ($t=$canNames{$CITY}) { $CITY = $t; } # # Check argument # if ($CITY =~ /[0-9]+/) { $ISCAN = 1; } elsif (length ($CITY) == 3 ) { $ISCAN = 0; } elsif (length ($CITY) == 2 ) { $ISCAN = 0; } else { print "Must be either a 2 letter state code or 3 letter city code.\n"; print "Can also be a numeric Canadian zone number or symbolic name.\n"; exit (1); } # # Connect to the server # print "\nWeather retrieval script, version $VERSION\n"; local($sockaddr,$here,$there,$response,$tries) = ("Snc4x8"); $here = pack($sockaddr,2,0,&getaddress("localhost")); $there = pack($sockaddr,2,$PORT,&getaddress($SERVER)); print "Connecting to $SERVER.."; die "socket: $!\n" if (!socket(SOCK,2,1,6)); print "."; die "connect: $!\n" if (!connect(SOCK,$there)); print "connected\n"; select(SOCK); $| = 1; select(STDOUT); $| = 1; # make unbuffered # # Initialize # $SHOWIT = 0; # Should we print? $MAINMENU = 0; # Seen main menu once already? $CANMENU = 0; # See Canadian menu once already? sub PLUMBER { exit; } $SIG{'PIPE'} = 'PLUMBER'; # # Interact... # while (read(SOCK,$c,1)) { # Get a character if ($c eq "\n") { # Newline -> maybe print, start new line if ($SHOWIT == 1) { $curline =~ s/^[\cC\s]+$//; $curline =~ tr/A-Z/a-z/; print $curline, "\n" unless $curline =~ /^$/ && $was_blank; $was_blank = $curline =~ /^$/; } $curline = ""; next; } if ($c eq "\r") { next; } # Return -> ignore $curline .= $c; # Else add char to current line # # Now test the current line so far to see what action to take, if any. # if ($curline =~ /Press Return for menu, or enter 3 letter forecast city code:/) { # At first prompt... if ($ISCAN) { printf SOCK "\n"; # For Canadian forecast, go via main menu } else { printf SOCK "%s\n", $CITY; # For US, bypass menu $curline = ""; &showiton("us city/state"); } } elsif ($curline =~ / Selection:/) { # In main menu... if ($ISCAN) { # Canadian forecast... if (!$MAINMENU) { # At main menu, select Canadian forecasts $MAINMENU = 1; printf SOCK "2\n"; # Canadian forecast is item 2!! $curline = ""; } elsif (!$CANMENU) { # At Canadian menu, select region $CANMENU = 1; printf SOCK "%s\n", $CITY; &showiton("canadian region"); $curline = ""; } else { printf SOCK "X\n"; # Otherwise exit } } else { printf SOCK "X\n"; # Otherwise exit } } elsif ($curline =~ / Invalid 3-letter city code./) { printf SOCK "X\n"; printf "%s is an invalid 3 letter city code.\n", $CITY; &showitoff("3-letter"); } elsif ($curline =~ / Invalid city or state code./) { printf SOCK "X\n"; printf "%s is an invalid city or state code.\n", $CITY; &showitoff("invalid"); } elsif ($curline =~ / CITY FORECAST MENU/) { &showitoff("city forecast"); } elsif ($curline =~ / CURRENT WEATHER MENU/) { &showitoff("city forecast"); } elsif ($curline =~ / CANADIAN FORECASTS/) { &showitoff("canadian forecasts"); } elsif ($curline =~ / Press Return for menu: /) { printf SOCK "\n"; $curline = ""; &showiton("Return for menu"); } elsif ($curline =~ / Press Return to continue, M to return to menu, X to exit: /) { printf SOCK "\n"; $curline = ""; &showiton("Return to continue printing"); } elsif ($curline =~ / Press Return to display statement, M for menu: /) { # kenr@storage.tandem.com: Handle severe weather statement in city printf SOCK "\n"; $curline = ""; &showiton("Return to display statment (city)"); } elsif ($curline =~ / Press [rR]eturn to display statement, M to display main menu: /) { # gf: Similarly for severe Michigan weather and Canadian forecasts if ($ISCAN) { printf SOCK "M\n"; &showitoff("Return to display statement (main)"); } else { printf SOCK "\n"; &showiton("Return to display statement (main)"); } $curline = ""; } elsif ($curline =~ /The Weather Underground is fully loaded. Try again later./) { # frank@cis.ohio-state.edu: Show message if connection refused print "Weather server fully loaded, try again later.\n"; } } # # Clean up and done # close(SOCK); exit(0); ##################################################### sub getaddress { local($host) = @_; local(@ary); @ary = gethostbyname($host); return(unpack("C4",$ary[4])); } sub showitoff { local($txt) = @_; &maybeprint ("showit off ($txt)\n"); $SHOWIT = 0; } sub showiton { local($txt) = @_; &maybeprint ("showit on ($txt)\n"); $SHOWIT = 1; } sub maybeprint { # print @_; } ############################################################### # These next few lines are legal in both Perl and nroff. .00; # finish .ig 'di \" finish diversion--previous line must be blank .nr nl 0-1 \" fake up transition to first page again .nr % 0 \" start at page 1 '; __END__ ##### From here on it's a standard manual page ##### .TH WEATHER 1 "30 Jun 1992" .SH NAME weather - display current weather for a city or state .SH SYNOPSIS .B "weather" [city, state, or canadian zone code] .SH DESCRIPTION .PP .I Weather is program that will print the current weather conditions for an area. .I Weather is a Perl(1) script that connects to the Weather Underground weather server from The University of Michigan, sends the appropriate request, ignores the inappropriate text, and prints out the weather data. .PP If no code is given on the command-line, then the forecast for the default city (DEN ) is retrieved. .SH OPTIONS .TP .B city code The 3 letter airport style city code will cause .I weather to display the weather for that specified city. The weather server can display the city codes for a given state using the interactive interface described below. .TP .B state code The 2 letter state abbreviation will cause .I weather to display (a brief version of) the current weather for that specified state. .TP .B Canadian zone code The following list of codes are understood for Canadian weather reports: .nf .na 1. SALT (Southern Alberta) 11 LABR (Labrador) 2. CALT (Central Alberta) 12 NFLD (Newfoundland) 3. NALT|NEBC (N. Alta - NE BC) 13 SONT (Southern Ontario) 4. COBC (Coastal BC) 14 NONT (Northern Ontario) 5. INBC (Interior BC) 15 NWON (Northwest Ontario) 6. SMAN (Southern Manitoba) 16 SSAS (Southern Saskatchewan) 7. NMAN (Northern Manitoba) 17 NSAS (Northern Saskatchewan) 8. NOVA (Nova Scotia) 18 YUKN (Yukon) 9. PEDI (Prince Edward Island) 19 SQUE|OTTW (S. Quebec - Ottawa) 10. NEWB (New Brunswick) 20 NQUE (Northern Quebec) .ad .fi A vertical bar (`|') denotes alternate names for the region. Either the four-character symbolic name (in upper- or lowercase) or the zone number can be given to .IR weather . .SH "WEATHER SERVER" The Weather Underground provides more detailed information using an interactive interface than can be extracted automatically by this script. Use the command .ce % telnet downwind.sprl.umich.edu 3000 to connect interactively. Please limit your connection time to help lower server load. .SH BUGS Every time the menus on the server changes, .I weather will usually wind up hanging, or printing the same text infinitely. .PP Please *don't* send me mail if this happens. If I update the script you can be sure I will post the changes. However, please do not mail me requesting new versions. The Perl script is simple enough for you to have a go at fixing it yourself and posting the changes. Both the Net and I will love you for it. .SH SEE ALSO xforecast(1), Perl(1) .SH AUTHOR .na Frank Adelstein, frank@cis.ohio-state.edu. .PP Canadian support added by George Ferguson, ferguson@cs.rochester.edu. .PP Updated for new weather server menus by George Ferguson, 26 Jun 1992. .SH COPYRIGHT Copyright 1991, Frank Adelstein.