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.