Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (02/04/90)
Submitted-by: overload!dillon (Matt Dillon)
Posting-number: Volume 90, Issue 053
Archive-name: unix/uucp-1.03d/part09
#!/bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 9 (of 16)."
# Contents: man/MAPS src/News060/rnews.c src/getty/getty.c
# Wrapped by tadguy@xanth on Sat Feb 3 20:51:15 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'man/MAPS' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'man/MAPS'\"
else
echo shar: Extracting \"'man/MAPS'\" \(18172 characters\)
sed "s/^X//" >'man/MAPS' <<'END_OF_FILE'
X# The UUCP map is posted to newsgroup comp.mail.maps.
X#
X# From rn, the map can be easily unpacked with a command such as
X# 43-46w | (cd ~uucp/uumap ; sh)
X# or you can use John Quarterman's script to automatically unpack the files.
X# All files intended as pathalias input being with "d." and "u.", thus
X# pathalias Path.* uumap/[du].*
X# is a useful command to run. (You supply Path.* with local additions.)
X#
X# The map is also available on a demand basis at a number of hosts who
X# have volunteered to make their copy available to the general public ;
X# details of this access are posted separately in file "network".
X#
X# The files are organized by country, using the ISO 3166 3 letter country
X# code for each country. Each file has a name like u.iso.r1.r2.s, where
X# "iso" is the country code, r1, r2, etc are regions and subregions
X# (e.g. states in the USA, provinces in Canada, etc.) and s is a sequence
X# number (usually 1, but sometimes 2, 3, and up may be provided to keep
X# individual files down to a reasonable size, thus, u.usa.ca is separated
X# into two regions: [135] for southern, [246] for northern.)
X#
X# The map contains two types of files: u.* and d.* files. The d.* files
X# are for domains registered in the UUCP Zone. The u.* files are for
X# UUCP hosts that do not have officially registered domains, but rather
X# belong to the unofficial ".UUCP domain". Membership in the UUCP Zone
X# allows organizations and individuals to register official, unique,
X# domain names, recognized by all major academic computing networks
X# worldwide. For more information about joining the UUCP Zone, send
X# electronic mail to the UUCP Project at one of the addresses
X# uucp-query@stargate.com
X# {uiucdcs,rutgers}!stargate!uucp-query
X# stargate!uucp-query@rutgers.edu
X# or, if you cannot send electronic mail, telephone
X# +1 213 868 1134
X# We strongly encourage you to send email if at all possible, since it
X# cuts down on telephone tag and is much more efficient on our volunteer
X# workforce.
X#
X# This map can be used to generate mail routes with pathalias. Pathalias
X# was posted to Usenet in January 1986 and will be posted again as needed
X# The map is also useful to determine the person to contact when a problem
X# arises, and to find someone for a new site to connect to.
X#
X# Please check the entry for your host (and any neighbors for whom you know
X# the information and have the time) for correctness and completeness.
X# Please send corrections and additional information to uucpmap@rutgers.UUCP
X# or rutgers!uucpmap or uucpmap@rutgers.EDU.
X#
X# This map is maintained by a group of volunteers, making up part of the UUCP
X# Project. These people devote many hours of their own time to helping out
X# the UUCP community by keeping this map up to date. The volunteers include:
X#
X#
X# Jeff Janock - jeff@necntc.nec.com
X# USA: Conneticut, Maine, Massachusetts, New Hampshire, Rhode Island, Vermont
X#
X#
X# Nicholas (Nike) Horton - horton@reed.uucp
X# USA: Delaware, Maryland, New Jersey, Virginia, Washington DC,
X# West Virginia
X#
X#
X# Rayan Zachariassen rayan@ai.toronto.edu
X# CANADA: All provinces
X#
X#
X# Bill Blue - bblue@crash.uucp
X# USA: Arizona, California (Southern half)
X#
X#
X# Erik Fair - nca-maps@ucbvax.berkeley.edu
X# USA: California (Northern half)
X#
X#
X# David Schmidt - davids@iscuva.iscs.com
X# USA: Alaska, Idaho, Oregon, Montana, Washington, Wyoming
X#
X#
X# Doug McCallum - dougm@ico.isc.com
X# USA: Arkansas, Colorado, Iowa, Kansas, Louisiana, Mississippi, Nebraska,
X# New Mexico, Oklahoma, Texas, Utah
X#
X#
X# Piet Beertema - Europe (piet@cwi.nl)
X# Europe: all countries (unless otherwise noted)
X#
X#
X# Mikel Manitius - map-request@codas.att.com
X# USA: Florida
X#
X#
X# Jeff Lee - jeff@ics.gatech.edu
X# USA: Georgia
X#
X#
X# Tim Thompson - tgt@stargate.com
X# USA: Ohio
X#
X#
X# Dave Zimmerman - dpz@rutgers.edu
X# USA: Alabama, Illinois, Indiana, North Carolina, North Dakota,
X# Pennsylvania, South Carolina, South Dakota, Tennessee, Wisconsin
X#
X#
X# Bob Leffler - bob@rel.eds.com
X# USA: Michigan
X#
X#
X# Rob Robertson - rob@philiabs.philips.com
X# USA: New York
X#
X#
X# Hokey - hokey@plus5.com
X# USA: Missouri
X#
X#
X# David Herron - david@e.ms.uky.edu
X# USA: Kentucky
X#
X#
X# Brian Richter - brianr@rosevax.rosemount.com
X# USA: Minnesota
X#
X#
X# Torben Nielson, Bob Cunningham - torben@uhmanoa.UUCP, bob@uhmanoa.UUCP
X# USA: Hawaii
X#
X#
X# Haesoon Cho - nmc@sorak.kaist.ac.kr
X# Korea: all regions
X#
X#
X# Tohru Asami - asami@kddspeech.kddlabs.jp
X# Japan: all regions
X#
X#
X# Robert Elz, Dave Davey - map-coord@munnari.UUCP
X# Australia: all regions
X#
X#
X# Paul Graham - pjg@unrvax.unr.edu
X# USA: Nevada
X#
X#
X# Susana Lilik - susana@indovax.uucp
X# Indonesia: all regions
X#
X#
X# Mel Pleasant - pleasant@rutgers.edu
X# Singapore: all regions
X# New Zealand: all regions
X#
X#
X
X# Please note that the purpose of this map is to make routers within
X# UUCP work. The eventual direction is to make the map smaller (through
X# the use of domains), not larger. As such, sites with lots of local
X# machines connected together are encouraged to create a few gateway
X# machines and to make arrangements that these gateways can forward mail
X# to your local users. We would prefer not to have information listing
X# the machines on your local area networks, and certainly not your
X# personal computers and workstations. If you need such information for
X# local mail delivery, create a supplement in pathalias form which you
X# do not publish, but which you combine with the published data when you
X# run pathalias. We also do not want information about machines which
X# are not on UUCP, that is, which are not reachable with the ! notation
X# from the main UUCP cluster.
X#
X# If you don't have pathalias, it has been posted to mod.sources most
X# recently in October 1987. If you don't have access to a mod.sources
X# archive, contact the mod.sources moderator (currently Rich Salz,
X# sources@uunet.uu.net.)
X#
X# The remainder of this file describes the format of the UUCP map data.
X# It was written July 9, 1985 by Erik E. Fair <ucbvax!fair>, and last
X# updated July 12, 1985 by Mark Horton <stargate!mark>.
X#
X# The entire map is intended to be processed by pathalias, a program
X# that generates UUCP routes from this data. All lines beginning in `#'
X# are comment lines to pathalias, however the UUCP Project has defined a
X# set of these comment lines to have specific format so that a complete
X# database could be built.
X#
X# The generic form of these lines is
X#
X# #<field id letter><tab><field data>
X#
X# Each host has an entry in the following format. The entry should
X# begin with the #N line, end with a blank line after the pathalias
X# data, and not contain any other blank lines, since there are ed, sed,
X# and awk scripts that use expressions like /^#N $1/,/^$/ for the
X# purpose of separating the map out into files, each containing one site
X# entry.
X#
X# #N UUCP name of site
X# #S manufacturer machine model; operating system & version
X# #O organization name
X# #C contact person's name
X# #E contact person's electronic mail address
X# #T contact person's telephone number
X# #P organization's address
X# #L latitude / longitude
X# #R remarks
X# #U netnews neighbors
X# #W who last edited the entry ; date edited
X# #
X# sitename .domain
X# sitename remote1(FREQUENCY), remote2(FREQUENCY),
X# remote3(FREQUENCY)
X#
X# Example of a completed entry:
X#
X# #N ucbvax
X# #S DEC VAX-11/750; 4.3 BSD UNIX
X# #O University of California at Berkeley
X# #C Robert W. Henry
X# #E ucbvax!postmaster
X# #T +1 415 642 1024
X# #P 573 Evans Hall, Berkeley, CA 94720
X# #L 37 52 29 N / 122 13 44 W
X# #R This is also UCB-VAX.BERKELEY.EDU [10.2.0.78] on the internet
X# #U decvax ibmpa ucsfcgl ucbtopaz ucbcad
X# #W ucbvax!fair (Erik E. Fair); Sat Jun 22 03:35:16 PDT 1985
X# #
X# ucbvax .ucbvax.Berkeley.EDU
X# ucbvax decvax(DAILY/4), ihnp4(DAILY/2),
X# sun(POLLED)
X#
X# Specific Field Descriptions
X#
X# #N system name
X#
X# Your system's UUCP name should go here. Either the uname(1) command
X# from System III or System V UNIX; or the uuname(1) command from
X# Version 7 UNIX will tell you what UUCP is using for the local UUCP
X# name.
X#
X# One of the goals of the UUCP Project is to keep duplicate UUCP host
X# names from appearing because there exist mailers in the world which
X# assume that the UUCP name space contains no duplicates (and attempts
X# UUCP path optimization on that basis), and it's just plain confusing
X# to have two different sites with the same name.
X#
X# At present, the most severe restriction on UUCP names is that the name
X# must be unique somewhere in the first six characters, because of a
X# poor software design decision made by AT&T for the System V release of
X# UNIX.
X#
X# This does not mean that your site name has to be six characters or
X# less in length. Just unique within that length.
X#
X# With regard to choosing system names, HARRIS'S LAMENT:
X#
X# ``All the good ones are taken.''
X#
X# #S machine type; operating system
X#
X# This is a quick description of your equipment. Machine type should be
X# manufacturer and model, and after a semi-colon(;), the operating
X# system name and version number (if you have it). Some examples:
X#
X# DEC PDP-11/70; 2.9 BSD UNIX
X# DEC PDP-11/45; ULTRIX-11
X# DEC VAX-11/780; VMS 4.0
X# SUN 2/150; 4.2 BSD UNIX
X# Pyramid 90x; OSx 2.1
X# CoData 3300; Version 7 UniPlus+
X# Callan Unistar 200; System V UniPlus+
X# IBM PC/XT; Coherent
X# Intel 386; XENIX 3.0
X# CRDS Universe 68; UNOS
X#
X# #O organization name
X#
X# This should be the full name of your organization, squeezed to fit
X# inside 80 columns as necessary. Don't be afraid to abbreviate where
X# the abbreviation would be clear to the entire world (say a famous
X# institution like MIT or CERN), but beware of duplication (In USC the C
X# could be either California or Carolina).
X#
X# #C contact person
X#
X# This should be the full name (or names, separated by commas) of the
X# person responsible for handling queries from the outside world about
X# your machine.
X#
X# #E contact person's electronic address
X#
X# This should be just a machine name, and a user name, like
X# `ucbvax!fair'. It should not be a full path, since we will be able to
X# generate a path to the given address from the data you're giving us.
X# There is no problem with the machine name not being the same as the #N
X# field (i.e. the contact `lives' on another machine at your site).
X#
X# Also, it's a good idea to give a generic address or alias (if your
X# mail system is capable of providing aliases) like `usenet' or
X# `postmaster', so that if the contact person leaves the institution or
X# is re-assigned to other duties, he doesn't keep getting mail about the
X# system. In a perfect world, people would send notice to the UUCP
X# Project, but in practice, they don't, so the data does get out of
X# date. If you give a generic address you can easily change it to point
X# at the appropriate person.
X#
X# Multiple electronic addresses should be separated by commas, and all
X# of them should be specified in the manner described above.
X#
X# #T contact person's telephone number
X#
X# Format: +<country code><space><area code><space><prefix><space><number>
X#
X# Example:
X#
X# #T +1 415 642 1024
X#
X# This is the international format for the representation of phone
X# numbers. The country code for the United States of America (and
X# Canada) is 1. Other country codes should be listed in your telephone
X# book.
X#
X# If you must list an extension (i.e. what to ask the receptionist for,
X# if not the name of the contact person), list it after the main phone
X# number with an `x' in front of it to distinguish it from the rest of
X# the phone number.
X#
X# Example:
X#
X# #T +1 415 549 3854 x37
X#
X# Multiple phone numbers should be separated by commas, and all of them
X# should be completely specified as described above to prevent
X# confusion.
X#
X# #P organization's address
X#
X# This field should be one line filled with whatever else anyone would
X# need after the contact person's name, and your organization's name
X# (given in other fields above), to mail you something by paper mail.
X#
X# #L latitude and longitude
X#
X# This should be in the following format:
X#
X# #L DD MM [SS] "N"|"S" / DDD MM [SS] "E"|"W" ["city"]
X#
X# Two fields, with optional third.
X#
X# First number is Latitude in degrees (NN), minutes (MM), and seconds
X# (SS), and a N or S to indicate North or South of the Equator.
X#
X# A Slash Separator.
X#
X# Second number is Longitude in degrees (DDD), minutes (MM), and seconds
X# (SS), and a E or W to indicate East or West of the Prime Meridian in
X# Greenwich, England.
X#
X# Seconds are optional, but it is worth noting that the more accurate
X# you are, the more accurate maps we can make of the network (including
X# blow-ups of various high density areas, like New Jersey, or the San
X# Francisco Bay Area).
X#
X# If you give the coordinates for your city (i.e. without fudging for
X# where you are relative to that), add the word `city' at the end of the
X# end of the specification, to indicate that. If you know where you are
X# relative to a given coordinate for which you have longitude and
X# latitude data, then the following fudge factors can be useful:
X#
X# 1 degree = 69.2 miles = 111 kilometers
X# 1 minute = 1.15 miles = 1.86 kilometers
X# 1 second = 102 feet = 30.9 meters
X#
X# For LONGITUDE, multiply the above numbers by the cosine of your
X# latitude. For instance, at latitude 35 degrees, a degree of longitude
X# is 69.2*0.819 = 56.7 miles; at latitude 40 degrees, it is 69.2*0.766 =
X# 53.0 miles. If you don't see why the measure of longitude depends on
X# your latitude, just think of a globe, with all those N-S meridians of
X# longitude converging on the poles. You don't do this cosine
X# multiplication for LATITUDE.
X#
X# Here is a short cosine table in case you don't have a trig calculator
X# handy. (But you can always write a short program in C. The cosine
X# function in bc(1) doesn't seem to work as documented.)
X# deg cos deg cos deg cos deg cos deg cos deg cos
X# 0 1.000 5 0.996 10 0.985 15 0.966 20 0.940 25 0.906
X# 30 0.866 35 0.819 40 0.766 45 0.707 50 0.643 55 0.574
X# 60 0.500 65 0.423 70 0.342 75 0.259 80 0.174 85 0.087
X#
X# The Prime Meridian is through Greenwich, England, and longitudes run
X# from 180 degrees West of Greenwich to 180 East. Latitudes run from
X# 90 degrees North of the Equator to 90 degrees South.
X#
X# #R remarks
X#
X# This is for one line of comment. As noted before, all lines beginning
X# with a `#' character are comment lines, so if you need more than one
X# line to tell us something about your site, do so between the end of the
X# map data (the #?\t fields) and the pathalias data.
X#
X# #U netnews neighbors
X#
X# The USENET is the network that moves netnews around, specifically,
X# news.announce.important. If you send news.announce.important to any of
X# your UUCP neighbors, list their names here, delimited by spaces.
X# Example:
X#
X# #U ihnp4 decvax mcvax seismo
X#
X# Since some places have lots of USENET neighbors, continuation lines
X# should be just another #U and more site names.
X#
X# #W who last edited the entry and when
X#
X# This field should contain an email address, a name in parentheses,
X# followed by a semi-colon, and the output of the date program.
X# Example:
X#
X# #W ucbvax!fair (Erik E. Fair); Sat Jun 22 03:35:16 PDT 1985
X#
X# The same rules for email address that apply in the contact's email
X# address apply here also. (i.e. only one system name, and user name).
X# It is intended that this field be used for automatic ageing of the
X# map entries so that we can do more automated checking and updating
X# of the entire map. See getdate(3) from the netnews source for other
X# acceptable date formats.
X#
X# PATHALIAS DATA (or, documenting your UUCP connections & frequency of use)
X#
X# The DEMAND, DAILY, etc., entries represent imaginary connect costs (see
X# below) used by pathalias to calculate lowest cost paths. The cost
X# breakdown is:
X#
X# LOCAL 25 local area network
X# DEDICATED 95 high speed dedicated
X# DIRECT 200 local call
X# DEMAND 300 normal call (long distance, anytime)
X# HOURLY 500 hourly poll
X# EVENING 1800 time restricted call
X# DAILY 5000 daily poll
X# WEEKLY 30000 irregular poll
X# DEAD a very high number - not usable path
X#
X# Additionally, HIGH and LOW (used like DAILY+HIGH) are -5 and +5
X# respectively, for baud-rate or quality bonuses/penalties. Arithmetic
X# expressions can be used, however, you should be aware that the results
X# are often counter-intuitive (e.g. (DAILY*4) means every 4 days, not 4
X# times a day). This is because the numbers represent "cost of connection"
X# rather than "frequency of connection."
X#
X# The numbers are intended to represent cost of transferring mail over
X# the link, measured very rougly in elapsed time, which seems to be
X# far more important than baud rates for this type of
X# traffic. There is an assumed high overhead for each hop; thus,
X# HOURLY is far more than DAILY/24.
X#
X# There are a few other cost names that sometimes appear in the map.
X# Some are synonyms for the preferred names above (e.g. POLLED is assumed
X# to mean overnight and is taken to be the same as DAILY), some are
X# obsolete (e.g. the letters A through F, which are letter grades for
X# connections.) It is not acceptable to make up new names or spellings
X# (pathalias gets very upset when people do that...).
X#
X# LOCAL AREA NETWORKS
X#
X# We do not want local area network information in the published map.
X# If you want to put your LAN in your local Path.* files, read about
X# the LAN syntax in the pathalias.1 manual page.
X#
X# WHAT TO DO WITH THIS STUFF
X#
X# Once you have finished constructing your pathalias entry, mail it off
X# to {uunet|gatech|ucsd|ames}!rutgers!uucpmap, which will be sent to the
X# appropriate regional map coordinator. They maintain assigned
X# geographic sections of the map, and the entire map is posted on a
X# rolling basis in the USENET newsgroups comp.mail.maps over the course
X# of a month.
X#
X# Questions or comments about this specification should also be directed
X# at rutgers!uucpmap.
X#
END_OF_FILE
if test 18172 -ne `wc -c <'man/MAPS'`; then
echo shar: \"'man/MAPS'\" unpacked with wrong size!
fi
# end of 'man/MAPS'
fi
if test -f 'src/News060/rnews.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/News060/rnews.c'\"
else
echo shar: Extracting \"'src/News060/rnews.c'\" \(17361 characters\)
sed "s/^X//" >'src/News060/rnews.c' <<'END_OF_FILE'
X
X/*
X * RNEWS.C
X *
X * Copyright 1988 by William Loftus. All rights reserved.
X * (C) Copyright 1989-1990 by Matthew Dillon, All Rights Reserved.
X *
X * Version 0.60 Beta
X *
X * This is rnews for compressed news. News 2.11 will uux
X * a file to this system that will be in compressed format.
X * This program will strip off the "#! cunbatch", uncompress
X * the news, and call unbatch. If the news is not in compressed
X * format it will just pass it to unbatch.
X */
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X#include <log.h>
X#include "/version.h"
X#include <errno.h>
X#include <ctype.h>
X
X#define MAXGROUPS 1024
X
XIDENT(".01");
X
Xvoid uncompress_news();
Xvoid unbatch_news();
Xvoid writeerr();
Xvoid CreateDirsFor();
Xchar *TmpFileName();
X
Xint Compressed;
Xchar *SeqFile = "UULIB:SeqNews";
Xchar *TmpFile;
X
Xvoid
Xmain (argc, argv)
Xint argc;
Xchar **argv;
X{
X FILE *fp;
X char buf[32];
X int ch;
X int status = 0;
X
X LogProgram = "RNews";
X TmpFile = TmpFileName("T:mail");
X
X fclose(stderr); /* Assume we are running in the background */
X
X fgets(buf, 13, stdin);
X
X if (!strncmp(buf,"#! cunbatch", 11)) {
X Compressed = 1;
X } else if (!strncmp(buf,"#! rnews", 8)) {
X fp = fopen(TmpFile, "w");
X if (fp == (char *)NULL) {
X ulog(-1, "Unable to open %s for output", TmpFile);
X exit(1);
X }
X fprintf(fp, "%s\n", buf);
X while ((ch = getchar()) != EOF) {
X fputc(ch, fp);
X }
X fclose(fp);
X Compressed = 0;
X } else {
X ulog(-1, "News in wrong format");
X remove(TmpFile);
X exit(1);
X }
X
X if (Compressed) {
X uncompress_news();
X }
X
X unbatch_news();
X
X status = remove(TmpFile);
X
X if (status != 0) {
X ulog(-1, "Unable to remove %s", TmpFile);
X exit(1);
X }
X}
X
X/*
X * Unbatch, an Amiga unbatcher.
X *
X * Written by Fred Cassirer, 10/8/88.
X * Some unbatch code originally taken from News2.11 sources.
X *
X * Ported to Lattice 5.0
X * Added config.h file
X * Added use of ERRORFILE
X * 11/23/1988 Dan 'Sneakers' Schein
X *
X * This code (as well as the unbatch stuff) is free for anyone who thinks
X * they can get some use out of it.
X *
X * Articles will only
X * be placed in newsgroups as defined in the "UULIB:NewsGroups"
X * control file. Articles which are not listed in the control file
X * are placed in the "Reject" directory. Articles are sequenced by
X * the sequencer in "UULIB:seqnews". This could possibly be updated
X * to use a sequencer within each of the subdirectories, to more closely
X * resemble the News system under Unix.
X *
X * Unbatch will also take command line args of files to be unbatched.
X * Files on the command line are not removed, they should be removed
X * after running unbatch.
X */
X
Xstatic char *groups[MAXGROUPS];
X
Xvoid
Xunbatch_news()
X{
X if (!freopen(TmpFile, "r", stdin)) {
X ulog(-1, "Can't unbatch, expected file %s to exist", TmpFile);
X exit(1);
X }
X if (unbatch())
X ulog(-1, "Unbatch failed");
X fclose(stdin);
X}
X
X
Xvoid
Xinitgroups(newsgroups)
Xchar *newsgroups;
X{
X static char buf[BUFSIZ];
X static int initflag = 0;
X int i, len;
X FILE *fp;
X
X if (initflag)
X return;
X
X initflag = 1;
X
X if ((fp = fopen(newsgroups, "r")) == NULL) {
X ulog(-1, "Unable to open newsgroup file %s", newsgroups);
X remove(TmpFile);
X exit(2);
X }
X
X i = 0;
X while (fgets(buf, BUFSIZ, fp) && (i < MAXGROUPS)) {
X len = strlen(buf) - 1;
X buf[len] = '\0';
X if ((groups[i] = malloc(len+1)) == NULL) {
X ulog(-1, "malloc failed");
X remove(TmpFile);
X exit(4);
X }
X strcpy(groups[i], buf);
X i++;
X }
X groups[i] = NULL;
X fclose(fp);
X}
X
Xchar *
Xfinddir(dir)
Xchar *dir;
X{
X static char work[40];
X char *p;
X int i;
X
X while (1) {
X p = work;
X while ((*dir != ' ') && (*dir != ',') && *dir)
X *p++ = *dir++;
X
X *p = '\0';
X for (i = 0; groups[i] != NULL; ++i) {
X if (strcmpi(groups[i], work) == 0)
X return(work);
X }
X
X if (!*dir++)
X break;
X }
X return(NULL);
X}
X
X/*
X * unbatchnews: extract news in batched format and process it one article
X * at a time. The format looks like
X * #! rnews 1234
X * article containing 1234 characters
X * #! rnews 4321
X * article containing 4321 characters
X *
X * or
X *
X * #! command [args]
X * calls LIBDIR/command [args] to process the news
X */
X
X#define MAXARGS 20
X#define FILES_PER_LINE 5
X
Xchar buf[BUFSIZ];
Xchar homedir[128];
X
Xunbatch()
X{
X int c;
X FILE *pfn;
X long size;
X FILE *seq;
X char filename[128], tmpname[30];
X int seqno, fcount;
X long atol();
X char *dir;
X
X initgroups("UULIB:Newsgroups");
X
X if ((seq = fopen(SeqFile, "r")) != NULL) {
X fscanf(seq,"%d",&seqno);
X fclose(seq);
X } else {
X ulog(-1, "Sequence file %s not found, creating", SeqFile);
X seqno = 0;
X }
X
X if (gets(buf) == NULL) {
X ulog(-1, "Empty file!");
X return(2);
X }
X
X if (strncmp(buf, "#! rnews ", 9) != 0) {
X ulog(-1, "unbatch: rnews cmd not supported '%s'!", buf);
X return(1);
X }
X
X fcount = 0;
X do {
X if (!fcount) {
X fflush(stdout);
X fcount = FILES_PER_LINE;
X }
X while (strncmp(buf, "#! rnews ", 9) && strncmp(buf, "! rnews ", 8)) { /* kludge for bug */
X char *cp;
X for (cp = buf; *cp != '\0'; ++cp) {
X if (!isascii(*cp) || (!isprint(*cp) && !isspace(*cp)))
X *cp = '?';
X }
X ulog(-1, "out of sync, skipping %s", buf);
X if (gets(buf) == NULL)
X return(0);
X }
X
X size = atol(buf + (buf[0] == '#' ? 9 : 8));
X if (size <= 0) {
X ulog(-1, "nonsense size %ld", size);
X continue;
X }
X
X sprintf(tmpname,"UUNEWS:Tmp%d", ++seqno);
X fcount--;
X fflush(stdout);
X if ((pfn = fopen(tmpname, "w")) == NULL) {
X ulog(-1, "Can't create %s", tmpname);
X exit(3);
X }
X
X while (gets(buf)) {
X fprintf(pfn, "%s\n", buf);
X size -= strlen(buf) + 1;
X if (strncmp(buf, "Newsgroup", 9) == 0) {
X if (!(dir = finddir(buf+12))) {
X ulog(-1, "Articles for %s placed in Rejects", buf+12);
X dir = "Rejects";
X }
X sprintf(filename, "UUNEWS:%s/%d", dir, seqno);
X break; /* Get out of the while */
X }
X }
X
X if (size > 0) {
X while(--size >= 0 && (c = getc(stdin)) != EOF)
X putc(c, pfn);
X if (ferror(pfn) || fclose(pfn)) { /* disk full? */
X ulog(-1, "Error writing to temp file");
X break;
X }
X if (rename(tmpname, filename) < 0) {
X CreateDirsFor(filename);
X rename(tmpname, filename);
X }
X }
X
X /*
X * If we got a truncated batch, don't process the
X * last article; it will probably be received again.
X */
X
X if (size > 0) {
X ulog(-1, "truncated batch");
X break;
X }
X } while (gets(buf) != NULL);
X
X if ((seq = fopen(SeqFile, "w")) == NULL) {
X ulog(-1, "Unable to create %s", SeqFile);
X }
X fprintf(seq, "%d\n", seqno);
X fclose(seq);
X return(0);
X}
X
Xint
XSystem(cmd)
Xchar *cmd;
X{
X long nl;
X int return_value;
X
X if ((nl = (long)Open("null:wpl", 1006)) != NULL) {
X return_value = (Execute(cmd, nl, nl) == -1) ? 0 : -1;
X Close(nl);
X } else {
X ulog(-1, "Unable to open NULL: device, did you mount it?");
X return_value = -1;
X }
X return return_value;
X}
X
X
X/*
X * Set USERMEM to the maximum amount of physical user memory available
X * in bytes. USERMEM is used to determine the maximum BITS that can be used
X * for compression.
X *
X * SACREDMEM is the amount of physical memory saved for others; compress
X * will hog the rest.
X */
X#ifndef SACREDMEM
X#define SACREDMEM 0
X#endif
X
X#ifndef USERMEM
X/*# ifdef AMIGA
X# define USERMEM 200000
X# else*/
X# define USERMEM 450000 /* default user memory */
X/* # endif*/
X#endif
X
X#ifdef interdata /* (Perkin-Elmer) */
X#define SIGNED_COMPARE_SLOW /* signed compare is slower than unsigned */
X#endif
X
X#ifdef pdp11
X# define BITS 12 /* max bits/code for 16-bit machine */
X# define NO_UCHAR /* also if "unsigned char" functions as signed char */
X# undef USERMEM
X#endif /* pdp11 */ /* don't forget to compile with -i */
X
X#ifdef z8000
X# define BITS 12
X# undef vax /* weird preprocessor */
X# undef USERMEM
X#endif /* z8000 */
X
X#ifdef pcxt
X# define BITS 12
X# undef USERMEM
X#endif /* pcxt */
X
X#ifdef USERMEM
X# if USERMEM >= (433484+SACREDMEM)
X# define PBITS 16
X# else
X# if USERMEM >= (229600+SACREDMEM)
X# define PBITS 15
X# else
X# if USERMEM >= (127536+SACREDMEM)
X# define PBITS 14
X# else
X# if USERMEM >= (73464+SACREDMEM)
X# define PBITS 13
X# else
X# define PBITS 12
X# endif
X# endif
X# endif
X# endif
X# undef USERMEM
X#endif /* USERMEM */
X
X#ifdef PBITS /* Preferred BITS for this memory size */
X# ifndef BITS
X# define BITS PBITS
X# endif BITS
X#endif /* PBITS */
X
X#if BITS == 16
X# define HSIZE 69001 /* 95% occupancy */
X#endif
X#if BITS == 15
X# define HSIZE 35023 /* 94% occupancy */
X#endif
X#if BITS == 14
X# define HSIZE 18013 /* 91% occupancy */
X#endif
X#if BITS == 13
X# define HSIZE 9001 /* 91% occupancy */
X#endif
X#if BITS <= 12
X# define HSIZE 5003 /* 80% occupancy */
X#endif
X
X#ifdef M_XENIX /* Stupid compiler can't handle arrays with */
X# if BITS == 16 /* more than 65535 bytes - so we fake it */
X# define XENIX_16
X# else
X# if BITS > 13 /* Code only handles BITS = 12, 13, or 16 */
X# define BITS 13
X# endif
X# endif
X#endif
X
X/*
X * a code_int must be able to hold 2**BITS values of type int, and also -1
X */
X#if BITS > 15
Xtypedef long int code_int;
X#else
Xtypedef int code_int;
X#endif
X
X#ifdef SIGNED_COMPARE_SLOW
Xtypedef unsigned long int count_int;
Xtypedef unsigned short int count_short;
X#else
Xtypedef long int count_int;
X#endif
X
X#ifdef NO_UCHAR
X typedef char char_type;
X#else
X typedef unsigned char char_type;
X#endif /* UCHAR */
Xchar_type magic_header[] = { "\037\235" }; /* 1F 9D */
X
X/* Defines for third byte of header */
X#define BIT_MASK 0x1f
X#define BLOCK_MASK 0x80
X/* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is
X a fourth header byte (for expansion).
X*/
X#define INIT_BITS 9 /* initial number of bits/code */
X
X#include <stdio.h>
X#include <ctype.h>
X
Xint n_bits; /* number of bits/code */
Xint maxbits = BITS; /* user settable max # bits/code */
Xcode_int maxcode; /* maximum code, given n_bits */
Xcode_int maxmaxcode = 1 << BITS; /* should NEVER generate this code */
X#define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
X
Xcount_int htab [HSIZE];
Xunsigned short codetab [HSIZE];
X#define htabof(i) htab[i]
X#define codetabof(i) codetab[i]
Xcode_int hsize = HSIZE; /* for dynamic table sizing */
Xcount_int fsize;
X
X/*
X * To save much memory, we overlay the table used by compress() with those
X * used by decompress(). The tab_prefix table is the same size and type
X * as the codetab. The tab_suffix table needs 2**BITS characters. We
X * get this from the beginning of htab. The output stack uses the rest
X * of htab, and contains characters. There is plenty of room for any
X * possible stack (stack used to be 8000 characters).
X */
X
X#define tab_prefixof(i) codetabof(i)
X#define tab_suffixof(i) (((char_type *)htab)[i])
X#define tab_suffixof1(i) (((long)htab)+(long)(i))
X#define de_stack (char_type *)(tab_suffixof1(1<<BITS))
X
Xcode_int free_ent = 0; /* first unused entry */
Xint exit_stat = 0;
X
Xcode_int getcode();
X
Xvoid _fprintf() { }
X
Xint nomagic = 0; /* Use a 3-byte magic number header, unless old file */
X
X/*
X * block compression parameters -- after all codes are used up,
X * and compression rate changes, start over.
X */
Xint block_compress = BLOCK_MASK;
Xint clear_flg = 0;
Xlong int ratio = 0;
X#define CHECK_GAP 10000 /* ratio check interval */
Xcount_int checkpoint = CHECK_GAP;
X/*
X * the next two codes should not be changed lightly, as they must not
X * lie within the contiguous general code space.
X */
X#define FIRST 257 /* first free entry */
X#define CLEAR 256 /* table clear output code */
X
Xint (*bgnd_flag)();
X
Xstatic void decompress ();
Xstatic void compress ();
X
Xvoid
Xuncompress_news()
X{
X if (freopen(TmpFile, "w", stdout) == NULL) {
X ulog(-1, "Can't open uncompressed file %s", TmpFile);
X exit(1);
X }
X
X maxbits = BITS;
X maxmaxcode = 1 << maxbits;
X
X /* Check the magic number */
X if (nomagic == 0) {
X if ((getchar()!=(magic_header[0] & 0xFF))
X || (getchar()!=(magic_header[1] & 0xFF))) {
X ulog(-1, "stdin: not in compressed format");
X exit(1);
X }
X maxbits = getchar(); /* set -b from file */
X block_compress = maxbits & BLOCK_MASK;
X maxbits &= BIT_MASK;
X maxmaxcode = 1 << maxbits;
X fsize = 100000; /* assume stdin large for USERMEM */
X }
X decompress();
X
X fclose(stdout);
X}
X
Xstatic int offset;
Xlong int in_count = 1; /* length of input */
Xlong int bytes_out; /* length of compressed output */
Xlong int out_count = 0; /* # of codes output (for debugging) */
X
X
X/*
X * Decompress stdin to stdout. This routine adapts to the codes in the
X * file building the "string" table on-the-fly; requiring no table to
X * be stored in the compressed file. The tables used herein are shared
X * with those of the compress() routine. See the definitions above.
X */
X
Xstatic void decompress() {
X register char_type *stackp;
X register int finchar;
X register code_int code, oldcode, incode;
X
X /*
X * As above, initialize the first 256 entries in the table.
X */
X maxcode = MAXCODE(n_bits = INIT_BITS);
X for ( code = 255; code >= 0; code-- ) {
X tab_prefixof(code) = 0;
X tab_suffixof(code) = (char_type)code;
X }
X free_ent = ((block_compress) ? FIRST : 256 );
X
X finchar = oldcode = getcode();
X if(oldcode == -1) /* EOF already? */
X return; /* Get out of here */
X putchar( (char)finchar ); /* first code must be 8 bits = char */
X if(ferror(stdout)) /* Crash if can't write */
X writeerr();
X stackp = de_stack;
X
X while ( (code = getcode()) > -1 ) {
X
X if ( (code == CLEAR) && block_compress ) {
X for ( code = 255; code >= 0; code-- )
X tab_prefixof(code) = 0;
X clear_flg = 1;
X free_ent = FIRST - 1;
X if ( (code = getcode ()) == -1 ) /* O, untimely death! */
X break;
X }
X incode = code;
X /*
X * Special case for KwKwK string.
X */
X if ( code >= free_ent ) {
X *stackp++ = finchar;
X code = oldcode;
X }
X
X /*
X * Generate output characters in reverse order
X */
X#ifdef SIGNED_COMPARE_SLOW
X while ( ((unsigned long)code) >= ((unsigned long)256) ) {
X#else
X while ( code >= 256 ) {
X#endif
X *stackp++ = tab_suffixof(code);
X code = tab_prefixof(code);
X }
X *stackp++ = finchar = tab_suffixof(code);
X
X /*
X * And put them out in forward order
X */
X do
X putchar ( *--stackp );
X while ( stackp > de_stack );
X
X /*
X * Generate the new entry.
X */
X if ( (code=free_ent) < maxmaxcode ) {
X tab_prefixof(code) = (unsigned short)oldcode;
X tab_suffixof(code) = finchar;
X free_ent = code+1;
X }
X /*
X * Remember previous code.
X */
X oldcode = incode;
X }
X
X fflush( stdout );
X if(ferror(stdout))
X writeerr();
X}
X
Xchar_type lmask[9] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
Xchar_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
X
X/*****************************************************************
X * TAG( getcode )
X *
X * Read one code from the standard input. If EOF, return -1.
X * Inputs:
X * stdin
X * Outputs:
X * code or -1 is returned.
X */
X
Xcode_int
Xgetcode() {
X /*
X * On the VAX, it is important to have the register declarations
X * in exactly the order given, or the asm will break.
X */
X register code_int code;
X static int offset = 0, size = 0;
X static char_type buf[BITS];
X register int r_off, bits;
X register char_type *bp = buf;
X
X if ( clear_flg > 0 || offset >= size || free_ent > maxcode ) {
X /*
X * If the next entry will be too big for the current code
X * size, then we must increase the size. This implies reading
X * a new buffer full, too.
X */
X if ( free_ent > maxcode ) {
X n_bits++;
X if ( n_bits == maxbits )
X maxcode = maxmaxcode; /* won't get any bigger now */
X else
X maxcode = MAXCODE(n_bits);
X }
X if ( clear_flg > 0) {
X maxcode = MAXCODE (n_bits = INIT_BITS);
X clear_flg = 0;
X }
X size = fread( buf, 1, n_bits, stdin );
X if ( size <= 0 )
X return -1; /* end of file */
X offset = 0;
X /* Round size down to integral number of codes */
X size = (size << 3) - (n_bits - 1);
X }
X r_off = offset;
X bits = n_bits;
X /*
X * Get to the first byte.
X */
X bp += (r_off >> 3);
X r_off &= 7;
X /* Get first part (low order bits) */
X#ifdef NO_UCHAR
X code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff;
X#else
X code = (*bp++ >> r_off);
X#endif /* NO_UCHAR */
X bits -= (8 - r_off);
X r_off = 8 - r_off; /* now, offset into code word */
X /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
X if ( bits >= 8 ) {
X#ifdef NO_UCHAR
X code |= (*bp++ & 0xff) << r_off;
X#else
X code |= *bp++ << r_off;
X#endif /* NO_UCHAR */
X r_off += 8;
X bits -= 8;
X }
X /* high order bits. */
X code |= (*bp & rmask[bits]) << r_off;
X offset += n_bits;
X
X return code;
X}
X
Xchar *
Xrindex(s, c) /* For those who don't have it in libc.a */
Xchar *s, c;
X{
X char *p;
X for (p = NULL; *s; s++)
X if (*s == c)
X p = s;
X return(p);
X}
X
Xvoid
Xwriteerr()
X{
X perror ( TmpFile );
X unlink ( TmpFile );
X exit ( 1 );
X}
X
X/*
X * assign:path/path/path.../filename
X *
X * creates path directories
X */
X
Xvoid
XCreateDirsFor(filename)
Xchar *filename;
X{
X short i;
X short j;
X
X for (i = 0; ; ++i) {
X for (j = i; filename[j] && filename[j] != ':' && filename[j] != '/'; ++j);
X if (filename[j] == 0)
X break;
X if (filename[j] == ':') {
X i = j;
X continue;
X }
X filename[j] = 0;
X mkdir(filename); /* may fail if parents already exist */
X filename[j] = '/';
X }
X}
X
END_OF_FILE
if test 17361 -ne `wc -c <'src/News060/rnews.c'`; then
echo shar: \"'src/News060/rnews.c'\" unpacked with wrong size!
fi
# end of 'src/News060/rnews.c'
fi
if test -f 'src/getty/getty.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/getty/getty.c'\"
else
echo shar: Extracting \"'src/getty/getty.c'\" \(19742 characters\)
sed "s/^X//" >'src/getty/getty.c' <<'END_OF_FILE'
X
X/*
X * GETTY.C
X *
X * (c)Copyright 1989, Matthew Dillon, All Rights Reserved
X *
X * Uses:
X * GETTY:PASSWD
X * GETTY:LOGFILE
X * GETTY:Getty-Header
X *
X * GETTY <options> <modem-commands>
X *
X * -Sdevicenam Tells GETTY which serial.device to use, default
X * serial.device
X *
X * -Uunitnum Tells GETTY which unit number to use, default 0
X *
X * -A Always talk to the modem at the first baud
X * rate in the -B list and ignore the baud rate
X * in the CONNECT message.
X *
X * -7 use SERF_7WIRE while online.
X *
X * -Bn Set baud rate. If specified multiple times the
X * first one is the default and remaining ones
X * switched to when a BREAK is received after a
X * connect. Also determines how CONNECT messages
X * are interpreted. A CONNECT with no number uses
X * the first -B entry while CONNECTs with numbers
X * use those numbers regardless of any -B entries.
X *
X * -Mc Set modem type:
X * c = m = multimodem
X * h = hays
X * d = dumb (no AT or +++ cmds are ever sent),
X * normally used with only one specified
X * baud rate.
X *
X * -m1 Turn on the modem speaker during dialing/connect
X * (default is -m0)
X *
X * -h0 Ignore CD (carrier detect), default is to use
X * carrier detect.
X *
X * -c0 Ignore CONNECT message (i.e. you are not connected
X * to a modem, usually combined with -h0). Default is
X * to expect a CONNECT message.
X *
X * -d0 do not use DTR to drop connection. Default is
X * to drop DTR to drop a connection. If this option
X * is chosen the +++ and ATH0 sequence will be used
X * to drop a connection.
X *
X * -xn Set debug level. Also causes log output to go
X * to stdout instead of GETTY:LOGFILE
X *
X * -0 QUIT - Kills any running getty for the specified
X * port.
X *
X * Any fields specified without a '-' are considered modem commands
X * used to initialize/reinitialize the modem. Up to 16 fields may
X * be specified (each is sent to the modem in 1 second intervals)
X */
X
X#include <exec/types.h>
X#include <exec/lists.h>
X#include <exec/devices.h>
X#include <devices/timer.h>
X#include <devices/serial.h>
X#include <libraries/dos.h>
X#include <libraries/dosextens.h>
X#include <hardware/cia.h>
X#include <stdio.h>
X#include <stdlib.h>
X#include <proto/all.h>
X#include <pwd.h>
X#include "/version.h"
X
X#include "log.h"
X
XIDENT(".01");
X
X#define arysize(ary) (sizeof(ary)/sizeof((ary)[0]))
X
X#define ST_WAITCD 0
X#define ST_CONNECT 1
X#define ST_LOGIN 2
X#define ST_PASSWD 3
X#define ST_RUN 4
X
Xtypedef struct IORequest IOR;
Xtypedef struct timerequest IOT;
Xtypedef struct IOExtSer IOSER;
Xtypedef struct MsgPort PORT;
Xtypedef struct List LIST;
Xtypedef struct Node NODE;
Xtypedef struct Message MSG;
X
Xtypedef struct GMsg {
X struct Message Msg;
X short Cmd;
X long Data1;
X void *Data2;
X} GMsg;
X
Xextern struct ProcID *RunPasswdEntry();
X
Xchar *CopyRight = "(c)Copyright 1989, Matthew Dillon, All Rights Reserved\r\n";
Xchar *ComPortName;
X
Xchar *DeviceName = "serial.device";
Xlong DeviceUnit = 0;
Xlong NullFH;
Xchar SpeakerLevel = 0;
Xchar AnswerRing = 2; /* default, answer on second ring */
Xchar SpeakerOpt = 0;
Xchar IgnoreCD = 0;
Xchar IgnoreConnect = 0;
Xchar IgnoreDTR = 0;
Xchar BaudAdjust = 0;
Xchar DropOnExit = 1;
Xchar ModemType = 'h';
Xchar ZeroOption = 0;
Xchar Wire7 = 0; /* use 7 wire while online */
Xchar Locked = 0; /* serial port is lcked */
Xlong Bauds[16] = { 9600 }; /* up 16 baud rates */
Xchar *AtFields[16];
X
XPORT *ComPort;
XPORT *IoSink; /* Sink for IO reqs. */
Xlong IoSinkMask;
Xlong ComPortMask;
X
XIOT Iot; /* check-carrier */
XIOSER Iosr; /* serial read-req */
XIOSER Iosw; /* serial write-req */
X
Xchar IotIP; /* Iot0 in progress */
Xchar IosrIP;
X
Xchar ScrBuf[256];
Xchar ConnectBuf[64];
Xchar LoginBuf[32];
Xchar PasswdBuf[32];
Xchar RxBuf[32];
Xchar HaveConnectMsg;
Xchar HaveLogin;
Xchar HavePasswd;
X
Xshort State;
Xshort Index;
Xshort BIndex;
X
Xshort CountDown;
Xshort GotOffPort;
X
Xvoid SerPuts();
Xvoid Set7Wire();
Xvoid xexit();
Xvoid Disconnect();
Xvoid ClearRecv();
Xvoid InitModem();
Xvoid SetParams();
Xvoid DoOptions();
Xvoid SerialOff();
X
XCXBRK()
X{
X return(0);
X}
X
Xmain(ac, av)
Xchar *av[];
X{
X extern int IAmGetty;
X
X IAmGetty = 1; /* for LockSerialPort()/UnLockSerialPort() */
X
X puts(CopyRight);
X fflush(stdout);
X
X LogProgram = "Getty";
X LogWho = LoginBuf;
X LogFile = "Getty:LOGFILE";
X PasswdFile = "Getty:Passwd";
X
X DoOptions(ac, av);
X
X IoSink = CreatePort(NULL, 0);
X IoSinkMask = 1 << IoSink->mp_SigBit;
X
X ComPortName = malloc(strlen(DeviceName) + 20);
X sprintf(ComPortName, "Getty.%s.%d", DeviceName, DeviceUnit);
X
X Forbid();
X if (ComPort = FindPort(ComPortName)) {
X GMsg msg;
X msg.Cmd = 'O';
X msg.Data1 = ac;
X msg.Data2 = (void *)av;
X msg.Msg.mn_ReplyPort = IoSink;
X PutMsg(ComPort, &msg.Msg);
X WaitPort(IoSink);
X Remove(&msg);
X Permit();
X puts("Options updated");
X xexit(0);
X }
X ComPort = CreatePort(ComPortName, 0);
X Permit();
X
X ComPortMask = 1 << ComPort->mp_SigBit;
X
X NullFH = Open("NULL:", 1006);
X if (NullFH == NULL) {
X ulog(-1, "GETTY REQUIRES NULL: HANDLER!");
X puts("Requires NULL: handler!");
X xexit(1);
X }
X if (LogToStdout == 0) {
X freopen("NULL:", "r", stdin);
X freopen("NULL:", "w", stdout);
X freopen("NULL:", "w", stderr);
X }
X
X
X /*
X * Timer Device
X */
X
X Iot.tr_node.io_Message.mn_ReplyPort = IoSink;
X if (OpenDevice("timer.device", UNIT_VBLANK, &Iot, 0)) {
X Iot.tr_node.io_Device = NULL;
X xexit(20);
X }
X Iot.tr_node.io_Command = TR_ADDREQUEST;
X
X /*
X * SERIAL.DEVICE
X */
X
X Iosr.IOSer.io_Message.mn_ReplyPort = IoSink;
X Iosr.io_SerFlags = SERF_XDISABLED | SERF_7WIRE | SERF_RAD_BOOGIE | SERF_SHARED;
X if (OpenDevice(DeviceName, DeviceUnit, &Iosr, 0)) {
X Iosr.IOSer.io_Device = NULL;
X xexit(21);
X }
X
X Iosw = Iosr;
X
X Iosw.io_SerFlags = SERF_XDISABLED | SERF_RAD_BOOGIE | SERF_SHARED;
X Iosw.io_ExtFlags = 0;
X Iosw.io_Baud = Bauds[0];
X Iosw.io_ReadLen = 8;
X Iosw.io_WriteLen = 8;
X Iosw.io_StopBits = 1;
X
X SetParams(&Iosw);
X
X /*
X * Run Operation
X */
X
X State = ST_WAITCD;
X Iot.tr_time.tv_secs = 1;
X Iot.tr_time.tv_micro= 0;
X IotIP = 1;
X SendIO(&Iot);
X
X InitModem();
X
X Signal(FindTask(NULL), IoSinkMask);
X
X for (;;) {
X long mask;
X IOR *ior;
X GMsg *msg;
X mask = Wait(SIGBREAKF_CTRL_C | IoSinkMask | ComPortMask);
X
X ulog(2, "State = %d", State);
X
X if (mask & SIGBREAKF_CTRL_C)
X break;
X
X if (msg = (GMsg *)GetMsg(ComPort)) {
X do {
X switch(msg->Cmd) {
X case 'O':
X DoOptions(msg->Data1, msg->Data2);
X break;
X }
X ReplyMsg((MSG *)msg);
X if (ZeroOption)
X xexit(0);
X } while (msg = (GMsg *)GetMsg(ComPort));
X if (State == ST_WAITCD && !GotOffPort)
X Disconnect(0);
X }
X
X while (ior = (IOR *)GetMsg(IoSink)) {
X if (ior == (IOR *)&Iot) {
X short diu;
X
X IotIP = 0;
X Iot.tr_time.tv_secs = 1;
X Iot.tr_time.tv_micro= 0;
X
X /*
X * If OpenCnt > 1, disable all processing.
X *
X * When returns to <= 1 reset serial port.
X */
X
X diu = DeviceInUse();
X if (diu) {
X if (GotOffPort == 0) {
X ulog(-1, "Device in use");
X if (Locked)
X ulog(-1, "getting off port");
X SerialOff();
X GotOffPort = 1;
X State = ST_WAITCD;
X }
X SendIO(&Iot);
X IotIP = 1;
X continue;
X }
X if (GotOffPort) {
X if (Locked == 0) {
X LockSerialPort(DeviceName, DeviceUnit);
X Locked = 1;
X }
X GotOffPort = 0;
X ulog(-1, "Getty resetting");
X SendIO(&Iot);
X IotIP = 1;
X Disconnect(1);
X continue;
X }
X if (State == ST_WAITCD)
X SerialOff();
X
X if (State != ST_WAITCD && IosrIP == 0) {
X if (Locked == 0)
X LockSerialPort(DeviceName, DeviceUnit);
X Locked = 1;
X ulog(-1, "Serial Port Locked");
X
X Iosr.IOSer.io_Command = CMD_READ;
X Iosr.IOSer.io_Data = (APTR)RxBuf;
X Iosr.IOSer.io_Length = 1;
X SendIO(&Iosr);
X IosrIP = 1;
X ulog(1, "Carrier, Getty getting on port");
X }
X
X Iosw.IOSer.io_Command = SDCMD_QUERY;
X DoIO(&Iosw);
X if (IgnoreCD)
X Iosw.io_Status &= ~CIAF_COMCD;
X
X /*
X * If state connected and we loose carrier, disconnect.
X *
X * If state connected and timeout occurs disconnect.
X */
X
X if (State != ST_WAITCD) {
X if ((Iosw.io_Status & CIAF_COMCD) != 0) {
X ulog(1, "Getty, Carrier lost");
X Disconnect(0);
X } else {
X if (--CountDown == 0) {
X ulog(1, "Getty, Timeout, Disconnecting");
X Disconnect(1);
X Iosw.io_Status |= CIAF_COMCD; /* for below */
X }
X }
X }
X
X switch(State) {
X case ST_WAITCD:
X if ((Iosw.io_Status & CIAF_COMCD) == 0) {
X State = ST_CONNECT;
X CountDown = 60; /* allow 60 seconds */
X ulog(-1, "Carrier Detect");
X } else {
X Iot.tr_time.tv_secs = 2;
X }
X break;
X case ST_CONNECT:
X /*
X * Wait for CONNECT message, then send Login:
X */
X
X if (IgnoreConnect && HaveConnectMsg == 0) {
X if (Wire7)
X Set7Wire(&Iosw);
X HaveConnectMsg = 1;
X ulog(-1, "Connect");
X }
X
X if (HaveConnectMsg) {
X FILE *fi;
X
X Delay(50);
X ClearRecv();
X if (fi = fopen("Getty:Getty-Header", "r")) {
X while (fgets(ScrBuf, sizeof(ScrBuf), fi)) {
X SerPuts(ScrBuf);
X SerPuts("\r");
X }
X fclose(fi);
X }
X SerPuts("Login: ");
X ulog(-1, "Getty, Connect, Login");
X State = ST_LOGIN;
X Index = 0;
X HaveLogin = 0;
X LoginBuf[0] = 0;
X }
X break;
X case ST_LOGIN: /* wait Login: response */
X if (HaveLogin) {
X if (LoginBuf[0] == 0) {
X State = ST_CONNECT;
X break;
X }
X ClearRecv();
X PasswdBuf[0] = 0;
X
X /*
X * If no password required, else request
X * password.
X */
X
X if (CheckLoginAndPassword()) {
X HavePasswd = 1;
X Index = 0;
X State = ST_PASSWD;
X } else {
X SerPuts("Password: ");
X ulog(1, "Getty, Passwd");
X State = ST_PASSWD;
X HavePasswd = 0;
X Index = 0;
X }
X }
X break;
X case ST_PASSWD: /* wait Password: response */
X if (HavePasswd) {
X if (CheckLoginAndPassword()) {
X ulog(-1, "login %s", LoginBuf);
X
X /*
X * Disable read requests but leave serial
X * port locked.
X */
X
X if (IosrIP) {
X AbortIO(&Iosr);
X WaitIO(&Iosr);
X IosrIP = 0;
X }
X
X /*
X * If run successful, leave read req and
X * timer disabled.
X */
X
X RunPasswdEntry();
X
X if (DropOnExit)
X Disconnect(1);
X else
X State = ST_CONNECT;
X ulog(-1, "disconnect");
X } else {
X SerPuts("Login Failed.\r\n\n");
X State = ST_CONNECT;
X ulog(-1, "LoginFailed user=%s pass=%s", LoginBuf, PasswdBuf);
X }
X HaveLogin = 0;
X HavePasswd= 0;
X LoginBuf[0] = 0;
X }
X break;
X }
X
X /*
X * Make no read requests while running 3rd party
X * program, else resend read request.
X */
X
X if (IotIP == 0) {
X IotIP = 1;
X SendIO(&Iot);
X }
X }
X
X /*
X * RECEIVED SERIAL READ DATA
X */
X
X if (ior == (IOR *)&Iosr) {
X IosrIP = 0;
X
X Iosw.IOSer.io_Command = SDCMD_QUERY;
X DoIO(&Iosw);
X if (IgnoreCD)
X Iosw.io_Status &= ~CIAF_COMCD;
X
X /*
X * BREAK used to switch baud rates between allowed
X * values
X */
X
X if (Iosw.io_Status & IO_STATF_READBREAK) {
X if (BaudAdjust == 0 && (State == ST_LOGIN || State == ST_PASSWD)) {
X if (++BIndex == arysize(Bauds))
X BIndex = 0;
X if (Bauds[BIndex] == 0)
X BIndex = 0;
X Iosw.io_Baud = Bauds[BIndex];
X SetParams(&Iosw);
X if (Wire7)
X Set7Wire(&Iosw);
X ulog(1, "<BREAK> to %d baud", Iosw.io_Baud);
X Delay(100);
X ClearRecv();
X Index = 0;
X State = ST_CONNECT;
X }
X } else
X if (Iosr.IOSer.io_Actual == 1) {
X char *ptr;
X UBYTE c = (UBYTE)RxBuf[0];
X
X ulog(2, "Rx %02x %c", c, (c < 32) ? ' ' : c);
X c &= 0x7F;
X
X switch(State) {
X case ST_WAITCD: /* looking for CONNECT msg */
X case ST_CONNECT: /* looking for CONNECT msg */
X ptr = ConnectBuf;
X break;
X case ST_LOGIN: /* looking for login name */
X ptr = LoginBuf;
X break;
X case ST_PASSWD: /* looking for password */
X ptr = PasswdBuf;
X break;
X }
X if (State == ST_LOGIN && HaveLogin)
X c = 0;
X if (State == ST_PASSWD && HavePasswd)
X c = 0;
X
X switch(c) {
X case 0:
X break;
X case 8:
X if (State == ST_LOGIN && HaveLogin)
X break;
X if (Index) {
X if (State == ST_LOGIN)
X SerPuts("\010 \010");
X --Index;
X }
X break;
X case 10:
X case 13:
X ptr[Index] = 0;
X Index = 0;
X switch(State) {
X case ST_WAITCD:
X case ST_CONNECT:
X if (strncmp(ptr, "CONNECT", 7)) {
X ulog(1, "Looking for CONNECT, got '%s'", ptr);
X break;
X }
X Delay(50);
X HaveConnectMsg = 1;
X if (BaudAdjust) {
X ulog(-1, "Connect Auto-Baud %d", Iosw.io_Baud);
X } else {
X char *str = ptr + 7;
X while (*str && (*str == 9 || *str == ' '))
X ++str;
X if (*str >= '0' && *str <= '9')
X Iosw.io_Baud = atoi(str);
X else
X Iosw.io_Baud = Bauds[0];
X SetParams(&Iosw);
X ulog(-1, "Connect at %d baud", Iosw.io_Baud);
X }
X if (Wire7)
X Set7Wire(&Iosw);
X break;
X case ST_LOGIN:
X HaveLogin = 1;
X SerPuts("\r\n");
X ulog(1, "Login: %s", ptr);
X break;
X case ST_PASSWD:
X HavePasswd = 1;
X SerPuts("\r\n");
X ulog(1, "Password: %s", ptr);
X break;
X }
X break;
X default:
X if (Index == 31)
X break;
X if (State == ST_LOGIN) {
X char cc[2];
X cc[0] = c;
X cc[1] = 0;
X SerPuts(cc);
X }
X ptr[Index++] = c;
X break;
X }
X }
X if (IosrIP == 0) {
X Iosr.IOSer.io_Command = CMD_READ;
X Iosr.IOSer.io_Data = (APTR)RxBuf;
X Iosr.IOSer.io_Length = 1;
X SendIO(&Iosr);
X IosrIP = 1;
X }
X }
X }
X }
X xexit(0);
X}
X
Xvoid
XSerialOff()
X{
X if (IosrIP) {
X AbortIO(&Iosr);
X WaitIO(&Iosr);
X IosrIP = 0;
X }
X if (Locked) {
X UnLockSerialPort(DeviceName, DeviceUnit);
X Locked = 0;
X ulog(1, "Serial Port UnLocked");
X }
X}
X
Xvoid
Xxexit(code)
X{
X if (ComPortMask) {
X GMsg *msg;
X Forbid();
X while (msg = (GMsg *)GetMsg(ComPort))
X ReplyMsg((MSG *)msg);
X DeletePort(ComPort);
X Permit();
X }
X if (IotIP) {
X AbortIO(&Iot);
X WaitIO(&Iot);
X }
X if (Iot.tr_node.io_Device)
X CloseDevice(&Iot);
X
X if (IosrIP) {
X AbortIO(&Iosr);
X WaitIO(&Iosr);
X }
X if (Iosr.IOSer.io_Device)
X CloseDevice(&Iosr);
X
X if (IoSink)
X DeletePort(IoSink);
X
X if (NullFH)
X Close(NullFH);
X
X if (Locked)
X UnLockSerialPort(DeviceName, DeviceUnit);
X
X exit(code);
X}
X
Xvoid
XSerPuts(str)
Xchar *str;
X{
X Iosw.IOSer.io_Command = CMD_WRITE;
X Iosw.IOSer.io_Data = (APTR)str;
X Iosw.IOSer.io_Length = strlen(str);
X DoIO(&Iosw);
X}
X
Xstatic short RxDisableIP;
X
Xvoid
XRxDisable()
X{
X RxDisableIP = IosrIP;
X if (IosrIP) {
X AbortIO(&Iosr);
X WaitIO(&Iosr);
X IosrIP = 0;
X }
X}
X
Xvoid
XRxEnable()
X{
X if (RxDisableIP && IosrIP == 0) {
X Iosr.IOSer.io_Command = CMD_READ;
X Iosr.IOSer.io_Data = (APTR)RxBuf;
X Iosr.IOSer.io_Length = 1;
X SendIO(&Iosr);
X IosrIP = 1;
X }
X}
X
Xvoid
XClearRecv()
X{
X RxDisable();
X ulog(1, "Clear beg");
X for (;;) {
X Iosr.IOSer.io_Command = SDCMD_QUERY;
X DoIO(&Iosr);
X if ((Iosr.IOSer.io_Length = Iosr.IOSer.io_Actual) <= 0)
X break;
X if (Iosr.IOSer.io_Length > sizeof(RxBuf))
X Iosr.IOSer.io_Length = sizeof(RxBuf);
X Iosr.IOSer.io_Data = (APTR)RxBuf;
X Iosr.IOSer.io_Command = CMD_READ;
X DoIO(&Iosr);
X }
X ulog(1, "Clear end");
X RxEnable();
X}
X
Xvoid
XSetParams(ior)
XIOSER *ior;
X{
X int error;
X
X if (IosrIP)
X AbortIO(&Iosr);
X ior->IOSer.io_Command = SDCMD_SETPARAMS;
X error = DoIO(ior);
X if (error)
X printf("SetParams, error %d\n", error);
X}
X
Xvoid
XSet7Wire(ior)
XIOSER *ior;
X{
X short error;
X
X if (IosrIP)
X AbortIO(&Iosr);
X ior->IOSer.io_Command = SDCMD_SETPARAMS;
X ior->io_SerFlags |= SERF_7WIRE;
X error = DoIO(ior);
X ior->io_SerFlags &= ~SERF_7WIRE;
X if (error)
X printf("SetParams, error %d\n", error);
X}
X
Xvoid
XDisconnect(dropdtr)
X{
X short retry = (IgnoreDTR) ? 2 : 10;
X
X ulog(1, "Disconnect drop=%d", dropdtr);
X HaveConnectMsg = 0;
X HaveLogin = 0;
X HavePasswd = 0;
X LoginBuf[0] = 0;
X PasswdBuf[0] = 0;
X Index = 0;
X State = ST_WAITCD;
X
X while (dropdtr && DeviceInUse() == 0) {
X short i;
X
X RxDisable();
X
X if (IgnoreDTR) {
X if (ModemType != 'd') {
X Delay(70);
X SerPuts("+++");
X Delay(70);
X SerPuts("\010\010\r");
X Delay(10);
X SerPuts("ATH0\r");
X Delay(120);
X }
X } else {
X CloseDevice(&Iosr);
X Iosr.IOSer.io_Device = NULL; /* so xexit doesn't reclose */
X for (i = 0; i < 5; ++i) { /* 5 seconds */
X Delay(50);
X if (SetSignal(SIGBREAKF_CTRL_C, 0) & SIGBREAKF_CTRL_C)
X xexit(23);
X }
X
X /*
X * Use Iosr to re-open serial device so we don't loose
X * our config.
X */
X
X if (OpenDevice(DeviceName, DeviceUnit, &Iosr, 0)) {
X Iosr.IOSer.io_Device = NULL;
X xexit(22);
X }
X Iosw.IOSer.io_Device = Iosr.IOSer.io_Device;
X Iosw.IOSer.io_Unit = Iosr.IOSer.io_Unit;
X SetParams(&Iosw);
X }
X
X /*
X * Loop until carrier lost
X */
X
X Iosw.IOSer.io_Command = SDCMD_QUERY;
X DoIO(&Iosw);
X if (IgnoreCD)
X Iosw.io_Status &= ~CIAF_COMCD;
X
X RxEnable();
X
X if ((Iosw.io_Status & CIAF_COMCD) != 0)
X break;
X if (--retry == 0) {
X if (IgnoreDTR == 0)
X puts("Getty: unable to disconnect!");
X break;
X }
X }
X if (DeviceInUse() == 0)
X InitModem();
X}
X
Xvoid
XInitModem()
X{
X char buf[64];
X short i;
X
X RxDisable();
X ulog(1, "Init Modem");
X Iosw.io_Baud = Bauds[0]; /* reset baud rate */
X BIndex = 0;
X SetParams(&Iosw);
X RxEnable();
X
X switch(ModemType) {
X case 'm': /* Multi Modem */
X SerPuts("\010\010\r");
X Delay(10);
X SerPuts("AT\r");
X Delay(50);
X sprintf(buf, "ATM%dS0=%dX4$BA%d&E%d\r",
X SpeakerLevel,
X AnswerRing,
X !BaudAdjust,
X (Wire7) ? 4 : 3
X );
X SerPuts(buf);
X break;
X case 'h':
X SerPuts("\010\010\r");
X Delay(10);
X SerPuts("ATZ\r");
X Delay(120);
X strcpy(buf, "AT");
X if (SpeakerOpt)
X sprintf(buf + strlen(buf), "M%d", SpeakerLevel);
X sprintf(buf + strlen(buf), "S0=%d", AnswerRing);
X strcat(buf, "\r");
X SerPuts(buf);
X break;
X case 'd':
X SerPuts("\010\010\r");
X break;
X }
X for (i = 0; i < arysize(AtFields) && AtFields[i]; ++i) {
X Delay(50);
X SerPuts(AtFields[i]);
X SerPuts("\r");
X }
X Delay(20);
X ClearRecv();
X Index = 0;
X}
X
Xvoid
XDoOptions(ac, av)
Xchar *av[];
X{
X short i;
X short bi = 0;
X short fi = 0;
X long v;
X
X for (i = 1; i < ac; ++i) {
X char *ptr = av[i];
X if (*ptr != '-') {
X if (fi != arysize(AtFields))
X AtFields[fi++] = ptr;
X else
X puts("AT field overflow");
X continue;
X }
X if (*++ptr) /* skip - */
X ++ptr; /* and option */
X v = atoi(ptr);
X switch(ptr[-1]) {
X case '0':
X ZeroOption = 1;
X break;
X case '7':
X Wire7 = 1;
X break;
X case 'S':
X DeviceName = ptr;
X break;
X case 'U':
X DeviceUnit = v;
X break;
X case 'M':
X ModemType = *ptr;
X break;
X case 'A':
X BaudAdjust = 1;
X break;
X case 'B':
X if (bi != arysize(Bauds))
X Bauds[bi++] = v;
X else
X puts("-B field overflow");
X break;
X case 'm':
X SpeakerOpt = 1;
X SpeakerLevel = v;
X break;
X case 'r':
X AnswerRing = v;
X break;
X case 'h':
X IgnoreCD = !v;
X break;
X case 'c':
X IgnoreConnect = !v;
X break;
X case 'd':
X IgnoreDTR = !v;
X break;
X case 'x':
X LogLevel = v;
X LogToStdout = (v >= 0);
X break;
X default:
X printf("Warning, Bad option: -%s\n", ptr);
X break;
X }
X }
X if (fi && fi != arysize(AtFields))
X AtFields[fi] = NULL;
X if (bi && bi != arysize(Bauds))
X Bauds[bi] = 0;
X}
X
XDeviceInUse()
X{
X return(Iosr.IOSer.io_Device->dd_Library.lib_OpenCnt > 1);
X}
X
END_OF_FILE
if test 19742 -ne `wc -c <'src/getty/getty.c'`; then
echo shar: \"'src/getty/getty.c'\" unpacked with wrong size!
fi
# end of 'src/getty/getty.c'
fi
echo shar: End of archive 9 \(of 16\).
cp /dev/null ark9isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 16 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
Submissions to comp.sources.amiga and comp.binaries.amiga should be sent to:
amiga@cs.odu.edu
or amiga@xanth.cs.odu.edu ( obsolescent mailers may need this address )
or ...!uunet!xanth!amiga ( very obsolescent mailers need this address )
Comments, questions, and suggestions should be addressed to ``amiga-request''
(please only use ``amiga'' for actual submissions) at the above addresses.