diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
commit | d6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch) | |
tree | ece253b876159b39c620e62b6c9b1174642e070e /gnu/libexec/uucp/contrib |
initial import of NetBSD tree
Diffstat (limited to 'gnu/libexec/uucp/contrib')
31 files changed, 10022 insertions, 0 deletions
diff --git a/gnu/libexec/uucp/contrib/Dial.Hayes b/gnu/libexec/uucp/contrib/Dial.Hayes new file mode 100644 index 00000000000..32eef82d347 --- /dev/null +++ b/gnu/libexec/uucp/contrib/Dial.Hayes @@ -0,0 +1,108 @@ +#!xchat +# @(#) dial.hayes V1.1 Tue Sep 1 13:59:58 1992 (Bob Denny) +# +# xchat script for dialing a vanilla Hayes modem +# +# Usage: +# xchat dial.hayes telno +# +# where telno is the telephone number, subject to pause and wait +# character modification. +# +# Uncomment the first two lines after "start:" to get debugging +# in file "Dial.Log" +# +# Flush input, zero counter, set telephone number if supplied, +# else fail if no telephone number given. +# +start: +### dbgfile Dial.Log +### dbgset 15 + zero + flush + ifnstr notelno 0 + telno 0 + goto initmodem +# +# Missing telephone number. +# +notelno: + logerr No telephone number given + failed +# +# Reset the modem to nonvolatile profile. +# Allow 3 sec. for response, as some modems are slow to reset. +# +initmodem: + count + ifgtr cantinit 4 + send ATZ\r + timeout initmodem 3000 + expect setupmodem OK +# +# No response from modem +# +cantinit: + logerr Can't wake modem + failed +# +# Send the stuff needed to initialize the modem to the modes +# needed for the particular modem flavor. The string below +# is provided as a vanilla example. Allow 2 sec. for the +# modem to respond to this command. +# +setupmodem: + sleep 1000 + send ATM0S7=90S11=120\r + timeout setupfail 2000 + expect setupfail ERROR + expect dialnumber OK +# +# Modem barfed or died on setup command. +# +setupfail: + logerr Error in modem setup string + failed +# +# Dial the supplied number. Handle the various errors that +# can come back from the modem by logging the error. +# +dialnumber: + sleep 1000 + send ATDT + dial + send \r + flush + timeout timeout 90000 + expect connected CONNECT + expect busy BUSY + expect nocarrier NO CARRIER + expect noanswer NO ANSWER + expect nodialtone NO DIALTONE +# +# Success! +# +connected: + success +# +# Handle modem dial failures +# +timeout: + logerr Modem or carrier timeout. + failed +busy: + logerr BUSY + failed +nocarrier: + logerr NO CARRIER + failed +noanswer: + logerr NO ANSWER + failed +nodialtone: + logerr NO DIALTONE + failed +# +# end +# + diff --git a/gnu/libexec/uucp/contrib/Hangup.Hayes b/gnu/libexec/uucp/contrib/Hangup.Hayes new file mode 100644 index 00000000000..c111c00fcae --- /dev/null +++ b/gnu/libexec/uucp/contrib/Hangup.Hayes @@ -0,0 +1,57 @@ +#!xchat +# @(#) Hangup.Hayes V1.1 Tue Sep 1 14:04:25 1992 (Bob Denny) +# +# xchat script for hanging up a Hayes-type modem. When used with Taylor +# UUCP, this script should be run as the dialer-complete and dialer-abort +# script with xchat. +# +# Usage: +# xchat Hangup.Hayes [ x ] +# +# where 'x' is any string. If it is present, this script will log the +# modem reset as an ABORT reset, otherwise it will not log anything. +# +# Uncomment the lines starting with '###' to get debugging log. +# +start: +### dbgfile Hangup.Log +### dbgset 15 + zero + sleep 2000 # Wait for trailing garbage + flush # Toss it out + ifnstr wakemodem 0 # No abort indicator + log Hangup on abort +# +# Get modem's attention via Hayes 'escape' protocol. +# +wakemodem: + sleep 4000 + send +++ + sleep 4000 + send \r + timeout reset 2000 + expect reset OK +# +# We're (probably) in command mode. Use ATZ (reset) to hang up +# as some modems don't behave well with ATH0 command. +# +reset: + send ATZ\r + timeout silent 5000 + expect done OK +# +# Finished, modem is back in initial state. +# +done: + success +# +# No response to escape protocol. Log the error and force DTR low +# in an attempt to get control of the modem. Then send ATZ just to +# make sure. +# +silent: + logerr Hangup: no response from modem + hangup # Force DTR low as last gasp + send ATZ\r + sleep 5000 + failed diff --git a/gnu/libexec/uucp/contrib/Login.LAT b/gnu/libexec/uucp/contrib/Login.LAT new file mode 100644 index 00000000000..d557f97e219 --- /dev/null +++ b/gnu/libexec/uucp/contrib/Login.LAT @@ -0,0 +1,137 @@ +#!xchat +# @(#) login.LAT V1.2 Tue Sep 1 13:25:28 1992 +# +# xchat script for logging into a VMS system through a LAT +# terminal server port. If no VMS password parameter supplied, +# skips password phase of VMS login. If LAT-password supplied, +# will log into LAT server using that password. NOTE: does not +# handle the situation where a LAT password is needed but no +# VMS password is needed. +# +# Usage: +# xchat login.LAT sysname username [ password [ LAT-password ] ] +# +# History: +# rbd Fri Aug 14 13:37:06 1992 +# Changes for Lantronix ETS-16. It says "type help at the Local> +# prompt..." then it gives the prompt for real! Prompt may need +# to be something other than "Local>". We match the real Local> +# prompt by matching the leading newline! +# +# rbd Tue Sep 1 13:04:32 1992 +# Remove absolute path name from log file. Now defaults per config. +# +start: + dbgfile Login.Log + dbgset 15 + sleep 2000 # Wait 2 seconds + flush # Flush typeahead + ifnstr svrstart 3 # Skip server password if not given +# +# Starting point if server password supplied. Handle situation +# where the server line may have been left waiting for username +# or at local> prompt. +# +getsvrpwp: + zero +l0: + count # Get server's password prompt + ifgtr deadmux 5 # die if 5 cr's don't do it + send \r + timeout l0 1000 # Wait and try again + expect dosvrpw ssword> + expect svrlogin ername> + expect connect \nLocal> +# +# Send server's password. Fail if don't get Username +# or Local> prompt. +# +dosvrpw: + zero +l2: + sendstr 3 + send \r + timeout badsvrpw 5000 # Die if invalid + expect svrlogin ername> + expect connect \nLocal> +# +# Starting point if NO server password supplied. Handle situation +# where the server line may have been left at local> prompt. +# +svrstart: + zero +l1: + count # Get username> or local> prompt + ifgtr deadmux 5 # Die if 5 cr's don't do it + send \r + timeout l1 1000 # Wait and try again + expect svrlogin ername> + expect connect \nLocal> +# +# Server asked for a username. Just give 'uucp'. +# +svrlogin: + send uucp\r + timeout deadmux 2000 + expect connect \nLocal> +# +# At this point, we have the Local> prompt. Send the connect +# command for the specified LAT host service name, and wait for +# VMS "Username:" prompt. Die after 10 seconds. +# +connect: + send c\s + sendstr 0 + send \r + timeout nologin 10000 + expect gotlogin ername: +# +# Got VMS "Username:" prompt. Send the username. If a password +# was given, wait for the "Password:" prompt. Die after 10 seconds. +# if no password was given, we're done! +# +gotlogin: + sendstr 1 + send \r + ifnstr done 2 + timeout nopasswd 10000 + expect gotpasswd ssword: +# +# Got VMS "Password:" prompt. Send the password and we're done! +# +gotpasswd: + sendstr 2 + send \r +# +# Success! +# +done: + success +# +# ERROR HANDLERS +# +# +# LAT server appears dead. Fail. +# +deadmux: + logerr No response from LAT server + failed +# +# The server password was bad. Fail. +# +badsvrpw: + logerr Invalid LAT server password + failed +# +# VMS system appears to be dead. Fail. +# +nologin: + logerr No VMS Username: prompt + failed +# +# Failed to get "Password:" prompt. Fail. +# +nopasswd: + logerr No VMS Password: prompt. Invalid password? + failed + diff --git a/gnu/libexec/uucp/contrib/Login.PortSel b/gnu/libexec/uucp/contrib/Login.PortSel new file mode 100644 index 00000000000..d8c3a6643a6 --- /dev/null +++ b/gnu/libexec/uucp/contrib/Login.PortSel @@ -0,0 +1,133 @@ +#!xchat +# @(#) Login.PortSelUnix V1.0 Tue Sep 1 14:57:05 1992 (Bob Denny) +# +# NOTE: Untested with xchat V1.1. Taken from DECUS UUCP. +# +# From: "Kent C. Brodie" <moocow!brodie@CSD4.MILW.WISC.EDU> +# uucp: {uunet!marque,csd4.milw.wisc.edu}!moocow!brodie +# special script for "uwmcsd4", have to go through a port selector (and then +# log in via standard Unix procedures). +# +# Also included is the ability to wait in the port selector queue. +# Be forwarned that the debug log can get pretty big depending on +# how many times you "wait" in the queue. +# (C) 1989 Kent C. Brodie - Medical College of Wisconsin + +# P0 is systemname , P1 is username, P2 is password. + + zero + +# send a CR to get the selector's attention. Sleep a little bit +# due to large login text of selector. It sends "Which System?" +# when it's ready. + +getprtslct: + count + ifgtr noprtslct 6 + break + send \r + sleep 2000 + flush + expect prtslctok ystem? + timeout getprtslct 15000 + +noprtslct: + logerr Sent cr, no "Which System?" from port selector + failed + +# Send the system name. We either get "OK" (connected), or we +# get "No ports available, would you like to wait?" (wait in queue) + +prtslctok: + zero + sendstr 0 + send \r + expect connected OK + expect prtslctwait wait? + timeout noconnect 10000 + +# Usually we get "nn Your place in queue" messages. JUST in case we +# get a free port right away, check for 'Are you ready?' as well. + +prtslctwait: + zero + send Y\r + expect prtslctque queue + expect prtslctrdy ready? + timeout prtwaitbad 70000 + +prtwaitbad: + logerr Sent "Y" to wait in queue, did not get valid response. + failed + +# Here's where we wait in the queue. The port selector sends us a status +# message about once a minute. We either get "nn Your place in queue" +# or we get "System Available. Are you Ready?". +# If something goes wrong, we time out waiting for either response. +# The reason we don't sleep for 40-50 seconds is because as SOON as the +# port is ready, it informs us. If we wait too long, it drops us. +# This setup is laid out for a maximum of 20 "tries" which is ABOUT +# 20 minutes. Note: This constant retrying can make log files +# kind of big.... + +prtslctque: + count + ifgtr prtslcttry 20 + expect prtslctque queue + expect prtslctrdy ready? + timeout noportwait 70000 + +prtslcttry: + logerr Too many (20) wait/retries -- queue too busy. + failed + +prtslctrdy: + send Y\r + expect connected OK + timeout noconnect 20000 + + +noportwait: + logerr Timed out awaiting place in port queue + failed + +noconnect: + logerr Sent system name, no "OK" from selector + failed + +# standard Unix login stuff. Send cr, expect "ogin:", if no, send a break +# (which tells Unix to try the next bit rate) and try again. + +connected: + send \r + zero + goto waitlogin + +sendbreak: + count + ifgtr nolgi 6 + flush + break + +waitlogin: + expect gotlogin ogin: + timeout sendbreak 5000 + +nolgi: + logerr No login: prompt + failed + +gotlogin: + sendstr 1 + send \r + expect gotword word: + timeout nopwd 10000 + +nopwd: + logerr No password: prompt + failed + +gotword: + sendstr 2 + send \r + success diff --git a/gnu/libexec/uucp/contrib/Login.VMS b/gnu/libexec/uucp/contrib/Login.VMS new file mode 100644 index 00000000000..d6196cb2aa6 --- /dev/null +++ b/gnu/libexec/uucp/contrib/Login.VMS @@ -0,0 +1,96 @@ +#!xchat +# @(#) Login.VMS V1.1 Tue Sep 1 13:24:54 1992 (Bob Denny) +# +# +# xchat script for logging into a VMS system. If no VMS password +# parameter supplied, skips password phase of VMS login. If syspass +# parameter given, will go through steps needed to log into a VMS +# system where a "system password" was set on the port. +# +# Cannot handle situation where system password is required but +# no password needed. +# +# +# Usage: +# xchat Login.VMS username [ password [ syspass ] ] +# +# Uncomment the lines starting with "###" to get debug logging. +# +start: +### dbgfile Login.Log +### dbgset 15 + sleep 2000 # Wait 2 seconds + zero + flush # Flush typeahead + ifnstr login 2 # Skip sys passwd if not given +# +# Need system password. Send <CR> to get bell. +# Try 5 times at 2 sec. intervals. Skip to do +# username if we see "Username:". +# +syspass: + count + ifgtr nobell 5 # Fail after 5 tries + send \r + timeout syspass 2000 # Wait 2 sec. and try again + expect gotbell \007 + expect gotlogin Username: +# +# Got the bell. Send the system password. Repeat 5 times +# at 2 sec. intervals. Fail if we don't get Username: +# +gotbell: + zero + sleep 2000 +l1: + count + ifgtr nologin 5 # Fail after 5 tries + sendstr 2 + send \r + timeout l1 2000 # Wait 2 sec. and try again + expect gotlogin Username: +# +# Start here if no system password supplied. +# Send <CR> until we get Username: Try 5 times at 2 sec. intervals. +# +login: + count + ifgtr nologin 5 # Fail after 5 tries + send \r + timeout login 2000 # Wait 2 sec. and try again + expect gotlogin Username: +# +# Got VMS "Username:" prompt. Send the username. If a password +# was given, wait for the "Password:" prompt. Die after 10 seconds. +# if no password was given, we're done! +# +gotlogin: + sendstr 0 + send \r + ifnstr done 1 + timeout nopasswd 10000 + expect gotpasswd Password: +# +# Got VMS "Password:" prompt. Send the password and we're done! +# +gotpasswd: + sendstr 1 + send \r +# +# Success! +# +done: + success +# +# ERROR HANDLERS +# +nobell: + logerr No VMS system password prompt (bell) + failed +nologin: + logerr No VMS Username: prompt + failed +nopasswd: + logerr No VMS Password: prompt. + failed + diff --git a/gnu/libexec/uucp/contrib/Makefile.uurt b/gnu/libexec/uucp/contrib/Makefile.uurt new file mode 100644 index 00000000000..8088539f6e5 --- /dev/null +++ b/gnu/libexec/uucp/contrib/Makefile.uurt @@ -0,0 +1,40 @@ +# $Id: Makefile.uurt,v 1.1 1995/10/18 08:38:23 deraadt Exp $ +# Makefile for uurate 1.10 +# + +# Prefix directory for installation directories. +prefix = /usr/local + +# Directory where the needed .h files are installed (uucp.h ...). +uucpsrcs = ../ + +# Where uurate is installed +BIN=$(prefix)/bin +# Where uurate's man is installed +MAN=$(prefix)/man/man1 + +# The directory to look in for Taylor style configuration files +newconfigdir = $(prefix)/conf/uucp + +# Flags to use when compiling uurate +CC=gcc -O2 +CFLAGS=-I.. -Wall +LDFLAGS=-s + +SHELL=/bin/sh +PROGS=uurate + +#----------- +MORECFLAGS= -I. -I$(uucpsrcs) -DNEWCONFIGLIB=\"$(newconfigdir)\" + +all: $(PROGS) + +uurate: uurate.c + $(CC) $(CFLAGS) $(MORECFLAGS) $@.c -o $@ $(LDFLAGS) + +install: $(PROGS) + cp $(PROGS) $(BIN) + cp uurate.man $(MAN)/uurate.1 + +clean: + rm -f $(PROGS) core diff --git a/gnu/libexec/uucp/contrib/Makefile.xchat b/gnu/libexec/uucp/contrib/Makefile.xchat new file mode 100644 index 00000000000..5e9aaa8ffed --- /dev/null +++ b/gnu/libexec/uucp/contrib/Makefile.xchat @@ -0,0 +1,31 @@ +# +# Makefile for xchat 1.1 +# +# Bob Denny - Tue Sep 1 15:58:22 1992 +# +CC=cc +SHELL=/bin/sh +BIN=/usr/local/lib/uucp +PROGS=xchat + +#----------- + +all: $(PROGS) + +install: $(PROGS) + @for i in $(PROGS) ; do \ + echo "Install $$i into $(BIN)..." ; \ + cp $$i $(BIN) ; \ + echo "Set ownership and protection..." ; \ + /bin/chmod 0555 $(BIN)/$$i ; \ + /bin/chown bin $(BIN)/$$i ; \ + /bin/chgrp bin $(BIN)/$$i ; \ + done + +clean: + rm -f $(PROGS) core + + + + + diff --git a/gnu/libexec/uucp/contrib/README b/gnu/libexec/uucp/contrib/README new file mode 100644 index 00000000000..8e4651a9bbd --- /dev/null +++ b/gnu/libexec/uucp/contrib/README @@ -0,0 +1,82 @@ +This is the README file for the Taylor UUCP contrib directory. + +This directory contains contributed shell scripts and programs that +you may find useful. + +Not actually included here, but nonetheless useful, is the TUA program +distributed by Lele Gaifax <lele@nautilus.sublink.org>. It can do +various sorts of analysis of any type of UUCP log file. It should be +available from most FTP sites. + +xchat.c, xchat.man, README-XCHAT, xc-conf.h-dist, Makefile.xchat: + A program by Bob Denny that may be invoked by the ``chat-program'' + command for any of the various types of chat scripts. It is + driven by scripts which are written in its own little language. + It is a powerful program that can add a lot of flexibility to your + chat scripts. + +Dial.Hayes, Hangup.Hayes, Login.LAT, Login.PortSel, Login.VMS: + Sample scripts for xchat. + +uucomp.shar + A set of programs which automatically compresses outgoing data in + the spool directory. The remote system must cooperate when using + this. It can cut down on phone usage when applicable. + Contributed by Ed Carp. + +uurate.c, uurate.man, README-UURATE, Makefile.uurt: + A nifty little program by Bob Denny which analyzes the Log and + Stats file and prints various sorts of reports. This version was + tweaked by Stephan Niemz and Klaus Dahlenburg. + +uutraf: + Another program to produce neat reports from your log files, this + one a perl script by Johan Vromans. + +savelog.sh, savelog.man: + A handy shell script to rename a log file and cycle old versions + through a set of names, throwing away the oldest one. It will + also optionally compress the old log files. I believe that this + is originally from smail. It was written by Ronald S. Karr and + Landon Curt Noll, and was given to me by Bob Denny. + +uureroute.perl: + A perl script to reroute all mail queued up for one host to + another. Written by Bill Campbell and contributed by Francois + Pinard. + +stats.sh: + A gawk script by Zacharias Beckman which reads the Stats file and + prints the last 80 lines as a nicely formatted table. + +uuq.sh: + A uuq workalike shell script by Zacharias Beckman. + +uupoll.shar: + uupoll and autopoll programs contributed by Klaus Dahlenburg. + uupoll can be used to automatically poll all systems, or a list of + systems; autopoll will poll and then retry failed calls. + +uudemon.shar: + An implementation of the HDB uudemon.poll script by Donald Burr. + +uuxconv: + A program by Richard E. Nickle to help convert SPOOLDIR_HDB spool + directories to SPOOLDIR_TAYLOR spool directories (note that it is + not necessary to convert your spool directories at all; the + SPOOLDIR_TAYLOR approach may be slightly more efficient). + +dialHDB.c: + A program by Daniel Hagerty which permits using HDB dialer + programs as chat programs. + +amiga.c: + A wrapper program to run uucico from a cron table under Amiga + SVR4 (apparently a wrapper is required). This was contributed by + Lawrence E. Rosenman. + +tstout.c: + A program to remove a user from utmp and wtmp, essentially logging + them out. I put this together from BSD code. I need it to use + tstuu with the system UUCP on Ultrix 4.0, for reasons that escape + me. Most people will have little use for this. diff --git a/gnu/libexec/uucp/contrib/README-UURATE b/gnu/libexec/uucp/contrib/README-UURATE new file mode 100644 index 00000000000..0ef637514a5 --- /dev/null +++ b/gnu/libexec/uucp/contrib/README-UURATE @@ -0,0 +1,21 @@ +uurate V1.10 - Gather and display Taylor UUCP traffic statistics + +Bob Denny (denny@alisa.com) - Thu Sep 3 19:47:41 1992 (V1.2.1) +Klaus Dahlenburg (kdburg@incoahe.hanse.de) - Tue Sep 28 18:11:34 CET 1993 + +See the man page for documentation. + +Installation: +------------ + +(1) Copy or sym-link Makefile.uurt to Makefile. + +(2) Edit Makefile: set BIN where you want uurate to be installed, + MAN where the man page should go to, and set CFLAGS to point + to the directory containing the UUCP sources (this is .. by + default). Don't forget to set newconfigdir= to point to the + directory where the (Taylor-uucp)config is stored. + +(3) Type ``make'' to compile the program. + +(4) Type ``make install'' to install the program. diff --git a/gnu/libexec/uucp/contrib/README-XCHAT b/gnu/libexec/uucp/contrib/README-XCHAT new file mode 100644 index 00000000000..5f93a284bda --- /dev/null +++ b/gnu/libexec/uucp/contrib/README-XCHAT @@ -0,0 +1,42 @@ +This is xchat V1.1 (Tue Sep 1 15:50:56 1992) + +Introduction: +------------ + +Xchat is a general-purpose dialing and login program designed for use +with Taylor UUCP as a "chat-program", taking the place (or augmenting) +the built-in chat scripting facility. It provides the ability to +closely control timeouts, multiple simultaneous expect strings with +separate actions, extended terminal control, modem command character +pacing, and more. + +When used in conjunction with Taylor UUCP's configuration features, +xchat can provide you the ability to manage the most intricate login, +dial and hangup needs. The scripts are written in a shell-like (well, +sort-of) style with labels, commands, and parameters, easing the task +of writing procedures for complex terminal communications situations. + +Installation: +------------ + +(1) Copy xc-conf.h-dist to xc-conf.h, then edit xc-conf.h to reflect + your condifuration. A description of the settings is in that file. + +(2) Copy Makefile.xchat to Makefile and edit it to set BIN to where + you want xchat installed. + +(2) Do a 'make' to build xchat. + +(3) Do a 'make install' to install it. + +(4) Format and print xchat.8, and install it if you want. + +(5) Print out copies of the scripts in the ./scripts subdirectory. + +(6) Read xchat.8 and the scripts together. + + +Author: +------ + +Robert B. Denny (denny@alisa.com) diff --git a/gnu/libexec/uucp/contrib/amiga.c b/gnu/libexec/uucp/contrib/amiga.c new file mode 100644 index 00000000000..d982364cfd5 --- /dev/null +++ b/gnu/libexec/uucp/contrib/amiga.c @@ -0,0 +1,43 @@ +/* Wrapper code for Taylor UUCP on Amiga Unix (SVR4) for cron invoked UUCP */ +/* processes. */ + +/* The problem: Cron is not a "licensed" process. any process that grabs a + controlling terminal needs to be licensed. Taylor UUCP needs controlling + terminals. Taylor UUCP does relinquish the controlling terminal before + fork(), so the "UUCP" license is appropriate. + This simple program does the "right" thing, but *MUST* be SETUID ROOT */ + +/* Written by: Lawrence E. Rosenman <ler@lerami.lerctr.org> */ + +#include <sys/sysm68k.h> +#include <sys/types.h> +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <pwd.h> + +int main(int argc,char *argv[],char *envp) +{ + struct passwd *pw; + char name[256]; + + strcpy(name,"/usr/local/lib/uucp/uucico"); + if (sysm68k(_m68k_LIMUSER,EUA_GET_LIC) == 0 ) { /* are we unlicensed? */ + if (sysm68k(_m68k_LIMUSER,EUA_UUCP) == -1) { /* yes, get a "uucp" license */ + fprintf(stderr,"sysm68k failed, errno=%d\n",errno); /* we didn't? crab it */ + exit(errno); + } + } + + pw = getpwnam("uucp"); /* get the Password Entry for uucp */ + if (pw == NULL) + { + fprintf(stderr,"User ID \"uucp\" doesn't exist.\n"); + exit(1); + } + setgid(pw->pw_gid); /* set gid to uucp */ + setuid(pw->pw_uid); /* set uid to uucp */ + argv[0]=name; /* have PS not lie... */ + execv("/usr/local/lib/uucp/uucico",argv); /* go to the real program */ + exit(errno); +} diff --git a/gnu/libexec/uucp/contrib/dialHDB.c b/gnu/libexec/uucp/contrib/dialHDB.c new file mode 100644 index 00000000000..cb2662134af --- /dev/null +++ b/gnu/libexec/uucp/contrib/dialHDB.c @@ -0,0 +1,187 @@ +/* +# File: dialHDB.c +# Author: Daniel Hagerty , hag@eddie.mit.edu +# Copyright (C) 1993 +# Date: Fri Nov 26 19:22:31 1993 +# Description: Program for using HDB dialers for dialing modems, exiting + with 0 on success, else failure. +# Version: 1.0 +# Revision History: +###### +### 11/26/93 Hag - File creation +###### +### 1/5/94 Hag - Finally got around to finishing this damn thing. +###### +*/ +/* Basic theory behind this program- + dialHDB forks into two processes, a monitor parent, and a child + that does the exec of the dialer. Child pretty much just execs the + dialer program, unless there's an exec problem, in which case the + child sends the parent a SIGUSR1 to indicate failed execution. +*/ + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <signal.h> + +#define kUsage "Usage:\n\t%s dialerPath device number speed\n\ +%s dialer -h device speed\n" + +#define kExitErrFlag 0x80 /* & in with exit code to determine error */ +#define kErrorMask 0x0f /* Mask to determine error code */ + +/* Error code defines as lifted from an HDB dialer */ +#define RCE_NULL 0 /* general purpose or unknown error code */ +#define RCE_INUSE 1 /* line in use */ +#define RCE_SIG 2 /* signal aborted dialer */ +#define RCE_ARGS 3 /* invalid arguments */ +#define RCE_PHNO 4 /* invalid phone number */ +#define RCE_SPEED 5 /* invalid baud rate -or- bad connect baud */ +#define RCE_OPEN 6 /* can't open line */ +#define RCE_IOCTL 7 /* ioctl error */ +#define RCE_TIMOUT 8 /* timeout */ +#define RCE_NOTONE 9 /* no dial tone */ +#define RCE_BUSY 13 /* phone is busy */ +#define RCE_NOCARR 14 /* no carrier */ +#define RCE_ANSWER 15 /* no answer */ + +/* Structure definition to map error codes to strings */ +typedef struct +{ + int errNum; + char *errString; +} errTable; + +const errTable errors[]= +{ + { RCE_NULL, "Unknown Error" }, + { RCE_INUSE, "Line is being used" }, + { RCE_SIG, "Recieved fatal signal" }, + { RCE_ARGS, "Bad arguments" }, + { RCE_PHNO, "Invalid phone number" }, + { RCE_SPEED, "Invalid baud rate or bad connection" }, + { RCE_OPEN, "Unable to open line" }, + { RCE_IOCTL, "ioctl error" }, + { RCE_TIMOUT, "Timed out" }, + { RCE_NOTONE, "No dialtone" }, + { RCE_BUSY, "Phone number is busy" }, + { RCE_NOCARR, "No carrier" }, + { RCE_ANSWER, "No answer" }, + { 0,NULL} +}; + +/* Function Prototypes */ +int figureStat(int stat); +char *findInTable(int error); +void badExec(void); + +char *dialerName; /* basename of our dialer program */ +char *dialerPath; /* full path of dialer program */ + +main(int argc,char *argv[]) +{ + int parent; /* pid of parent process */ + int child; /* pid of child process */ + int stat; /* exit status of child process */ + char *temp; /* used to get basename of dialer */ + + if(argc!=5) + { + fprintf(stderr,kUsage,argv[0],argv[0]); + exit(1); + } + + dialerPath=argv[1]; + dialerName= (temp=strrchr(argv[1],'/'))!=NULL ? temp+1 : argv[1]; + + parent=getpid(); + + signal(SIGUSR1,badExec); /* set up for possible failed exec */ + + if((child=fork())<0) + { + perror("fork"); + exit(2); + } + if(child>0) /* We're parent, wait for child to exit */ + { + /* Set up to ignore signals so we can report them on stderror */ + signal(SIGHUP,SIG_IGN); + signal(SIGINT,SIG_IGN); + signal(SIGTERM,SIG_IGN); + + wait(&stat); /* wait for child to exit */ + exit(figureStat(stat)); /* figure out our exit code and die */ + } + else /* child process */ + { + close(0); /* close of modem file desc, since HDB */ + close(1); /* doesn't use them */ + dup2(2,1); /* and remap stdout to stderr, just in case */ + if(execvp(argv[1],argv+1)<0) /* exec program with argv shifted by 1 */ + { /* if exec fails, send SIGUSR1 to parent */ + kill(parent,SIGUSR1); + exit(0); + } + } + exit(0); +} + +/* Figure out whether or not dialer ran succesfully, and return +with 0 if it worked, otherwise error */ +int figureStat(int stat) +{ + int exit; + int errFlag; + int error; + + if(WIFSIGNALED(stat)) /* determine if exit was from signal or what */ + { + fprintf(stderr,"Error: Dialer %s recieved signal %d.\n",dialerName, + WTERMSIG(stat)); + return(1); + } + if(WIFSTOPPED(stat)) + { + fprintf(stderr,"Error: Dialer %s recieved signal %d.\n",dialerName, + WSTOPSIG(stat)); + return(1); + } + exit=WEXITSTATUS(stat); + + errFlag=exit&kExitErrFlag; /* Is the error flag set? */ + if(errFlag) + { + char *errString; + + error=exit&kErrorMask; + errString=findInTable(error); /* find it's string, print it on stderr */ + fprintf(stderr,"Error: %s - %s.\n",dialerName,errString); /* and return */ + return(1); + } + return(0); +} + +/* Support routine, look up exit code in error table, and return pointer +to proper string */ +char *findInTable(int error) +{ + int i=0; + + for(i=0;errors[i].errString!=NULL;i++) + { + if(errors[i].errNum==error) + return(errors[i].errString); + } + /* Still here, return the top entry, for unknown error */ + return(errors[0].errString); +} + +/* Called by signal if we recieve SIGUSR 1 */ +void badExec(void) +{ + fprintf(stderr,"Error: %s - Execution problem.\n",dialerPath); + exit(1); +} diff --git a/gnu/libexec/uucp/contrib/savelog.man b/gnu/libexec/uucp/contrib/savelog.man new file mode 100644 index 00000000000..919b94f4ec1 --- /dev/null +++ b/gnu/libexec/uucp/contrib/savelog.man @@ -0,0 +1,130 @@ +.\" @(#)man/man8/savelog.an 1.2 24 Oct 1990 05:18:46 +.de pP +.if n .sp 1 +.if t .sp .4 +.. +.de tP +.pP +.ta \\n(pDu +.ti -\\n(pDu +.. +.TH SAVELOG X_MAN8_EXT_X "31 January 1988" "Local" +.SH NAME +savelog \- cycle and truncate log files +.SH SYNOPSIS +.na +.B X_UTIL_BIN_DIR_X/savelog +[ +.B \-m +.I mode +] [ +.B \-u +.I user +] [ +.B \-g +.I group +] [ +.B \-c +.I cycle +] [ +.B \-t +] [ +.B \-l +] +.I logfile +.br +.ad +.SH DESCRIPTION +The +.I savelog +command renames and optionally compresses a log file and cycles it +through a set of names based on the original log file, removing the +last name in the cycle. +.SH OPTIONS +The +.I savelog +command accepts the following options: +.TP +\fB\-m\fP \fImode\fP +Change the permissions mode for renamed log files to +.IR mode . +By default the mode is unchanged. +.TP +\fB\-u\fP \fIuser\fP +Change the owner for renamed log files to +.IR user . +By default the owner is unchanged. +.TP +\fB\-g\fP \fIgroup\fP +Change the group for renamed log files to +.IR group . +By default the group is unchanged. +.TP +\fB\-c\fP \fIcycle\fP +Save +.I cycle +versions of the logfile, where +.I cycle +is a decimal number. The default value is 7. +.TP +.B \-l +Do not compress log files. By default, a compression program is used, +if one is available. +.TP +.B \-t +Ensure that a new logfile exists when the savelog operation is +complete. Use of +.BR \-m , +.BR \-u +or +.BR \-g +imply this, ensuring that the logfile will have the designated mode. +.SH "OPERATION" +The given logfile is cycled through files named: +.RS + +OLD/\fIfile\fP.\fInumber\fP + +.RE +where +.I file +is the basename for the logfile and where +.I number +ranges from 0 to one less then the +.I cycle +count specified for the command. +The +.I OLD +dirctory is created, as necessary, and is under the same directory as +the logfile itself. +.PP +This cycle operation is accomplished by renaming the file numbered +.IR cycle -2 +to a file numbered +.IR cycle -1 +and so on until the file numbered 0 is renamed to the file numbered 1. +If compression is being used, the first cycle file is compressed after +being renamed to cycle 1. After the cycle files are moved through the +various names, the filefile itself is moved to the cycle 0 file. +This cycle normally occurs once every time +.I savelog +is executed. +If the log file does not exist, savelog ignores it and does +not cycle the OLD files. +.PP +If compression is being used, then compressed log files will have an +additional suffix appropriate for the compression program that is +used. +.SH "SEE ALSO" +.IR smail (X_MAN5_EXT_X) +and +.IR smail (X_MAN8_EXT_X). +.SH COPYRIGHT +Copyright(C)1987, 1988 Ronald S. Karr and Landon Curt Noll +.br +See a file COPYING, +distributed with the source code, +or type +.I "smail \-bc" +for distribution rights and restrictions +associated with this software. diff --git a/gnu/libexec/uucp/contrib/savelog.sh b/gnu/libexec/uucp/contrib/savelog.sh new file mode 100644 index 00000000000..64c989f292b --- /dev/null +++ b/gnu/libexec/uucp/contrib/savelog.sh @@ -0,0 +1,247 @@ +#! /bin/sh +# @(#)util/savelog.sh 1.4 26 Oct 1991 22:49:39 +# +# savelog - save a log file +# +# Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll +# +# See the file COPYING, distributed with smail, for restriction +# and warranty information. +# +# usage: savelog [-m mode] [-u user] [-g group] [-t] [-c cycle] [-l] file... +# +# -m mode - chmod log files to mode +# -u user - chown log files to user +# -g group - chgrp log files to group +# -c cycle - save cycle versions of the logfile (default: 7) +# -t - touch file +# -l - don't compress any log files (default: compress) +# file - log file names +# +# The savelog command saves and optionally compresses old copies of files +# into an 'dir'/OLD sub-directory. The 'dir' directory is determined from +# the directory of each 'file'. +# +# Older version of 'file' are named: +# +# OLD/'file'.<number><compress_suffix> +# +# where <number> is the version number, 0 being the newest. By default, +# version numbers > 0 are compressed (unless -l prevents it). The +# version number 0 is never compressed on the off chance that a process +# still has 'file' opened for I/O. +# +# If the 'file' does not exist or if it is zero length, no further processing +# is performed. However if -t was also given, it will be created. +# +# For files that do exist and have lengths greater than zero, the following +# actions are performed. +# +# 1) Version numered files are cycled. That is version 6 is moved to +# version 7, version is moved to becomes version 6, ... and finally +# version 0 is moved to version 1. Both compressed names and +# uncompressed names are cycled, regardless of -t. Missing version +# files are ignored. +# +# 2) The new OLD/file.1 is compressed and is changed subject to +# the -m, -u and -g flags. This step is skipped if the -t flag +# was given. +# +# 3) The main file is moved to OLD/file.0. +# +# 4) If the -m, -u, -g or -t flags are given, then file is created +# (as an empty file) subject to the given flags. +# +# 5) The new OLD/file.0 is chanegd subject to the -m, -u and -g flags. +# +# Note: If the OLD sub-directory does not exist, it will be created +# with mode 0755. +# +# Note: If no -m, -u or -g flag is given, then the primary log file is +# not created. +# +# Note: Since the version numbers start with 0, version number <cycle> +# is never formed. The <cycle> count must be at least 2. +# +# Bugs: If a process is still writing to the file.0 and savelog +# moved it to file.1 and compresses it, data could be lost. +# Smail does not have this problem in general because it +# restats files often. + +# common location +PATH="X_UTIL_PATH_X:X_SECURE_PATH_X"; export PATH +COMPRESS="X_COMPRESS_X" +COMP_FLAG="X_COMP_FLAG_X" +DOT_Z="X_DOT_Z_X" +CHOWN="X_CHOWN_X" +GETOPT="X_UTIL_BIN_DIR_X/getopt" + +# parse args +exitcode=0 # no problems to far +prog=$0 +mode= +user= +group= +touch= +count=7 +set -- `$GETOPT m:u:g:c:lt $*` +if [ $# -eq 0 -o $? -ne 0 ]; then + echo "usage: $prog [-m mode][-u user][-g group][-t][-c cycle][-l] file ..." 1>&2 + exit 1 +fi +for i in $*; do + case $i in + -m) mode=$2; shift 2;; + -u) user=$2; shift 2;; + -g) group=$2; shift 2;; + -c) count=$2; shift 2;; + -t) touch=1; shift;; + -l) COMPRESS=""; shift;; + --) shift; break;; + esac +done +if [ "$count" -lt 2 ]; then + echo "$prog: count must be at least 2" 1>&2 + exit 2 +fi + +# cycle thru filenames +while [ $# -gt 0 ]; do + + # get the filename + filename=$1 + shift + + # catch bogus files + if [ -b "$filename" -o -c "$filename" -o -d "$filename" ]; then + echo "$prog: $filename is not a regular file" 1>&2 + exitcode=3 + continue + fi + + # if not a file or empty, do nothing major + if [ ! -s $filename ]; then + # if -t was given and it does not exist, create it + if [ ! -z "$touch" -a ! -f $filename ]; then + touch $filename + if [ "$?" -ne 0 ]; then + echo "$prog: could not touch $filename" 1>&2 + exitcode=4 + continue + fi + if [ ! -z "$user" ]; then + $CHOWN $user $filename + fi + if [ ! -z "$group" ]; then + chgrp $group $filename + fi + if [ ! -z "$mode" ]; then + chmod $mode $filename + fi + fi + continue + fi + + # be sure that the savedir exists and is writable + savedir=`expr "$filename" : '\(.*\)/'` + if [ -z "$savedir" ]; then + savedir=./OLD + else + savedir=$savedir/OLD + fi + if [ ! -s $savedir ]; then + mkdir $savedir + if [ "$?" -ne 0 ]; then + echo "$prog: could not mkdir $savedir" 1>&2 + exitcode=5 + continue + fi + chmod 0755 $savedir + fi + if [ ! -d $savedir ]; then + echo "$prog: $savedir is not a directory" 1>&2 + exitcode=6 + continue + fi + if [ ! -w $savedir ]; then + echo "$prog: directory $savedir is not writable" 1>&2 + exitcode=7 + continue + fi + + # deterine our uncompressed file names + newname=`expr "$filename" : '.*/\(.*\)'` + if [ -z "$newname" ]; then + newname=$savedir/$filename + else + newname=$savedir/$newname + fi + + # cycle the old compressed log files + cycle=`expr $count - 1` + rm -f $newname.$cycle $newname.$cycle$DOT_Z + while [ "$cycle" -gt 1 ]; do + # --cycle + oldcycle=$cycle + cycle=`expr $cycle - 1` + # cycle log + if [ -f $newname.$cycle$DOT_Z ]; then + mv -f $newname.$cycle$DOT_Z $newname.$oldcycle$DOT_Z + fi + if [ -f $newname.$cycle ]; then + # file was not compressed for some reason move it anyway + mv -f $newname.$cycle $newname.$oldcycle + fi + done + + # compress the old uncompressed log if needed + if [ -f $newname.0 ]; then + if [ -z "$COMPRESS" ]; then + newfile=$newname.1 + mv $newname.0 $newfile + else + newfile=$newname.1$DOT_Z + $COMPRESS $COMP_FLAG < $newname.0 > $newfile + rm -f $newname.0 + fi + if [ ! -z "$user" ]; then + $CHOWN $user $newfile + fi + if [ ! -z "$group" ]; then + chgrp $group $newfile + fi + if [ ! -z "$mode" ]; then + chmod $mode $newfile + fi + fi + + # move the file into the file.0 holding place + mv -f $filename $newname.0 + + # replace file if needed + if [ ! -z "$touch" -o ! -z "$user" -o \ + ! -z "$group" -o ! -z "$mode" ]; then + touch $filename + fi + if [ ! -z "$user" ]; then + $CHOWN $user $filename + fi + if [ ! -z "$group" ]; then + chgrp $group $filename + fi + if [ ! -z "$mode" ]; then + chmod $mode $filename + fi + + # fix the permissions on the holding place file.0 file + if [ ! -z "$user" ]; then + $CHOWN $user $newname.0 + fi + if [ ! -z "$group" ]; then + chgrp $group $newname.0 + fi + if [ ! -z "$mode" ]; then + chmod $mode $newname.0 + fi +done +exit $exitcode diff --git a/gnu/libexec/uucp/contrib/stats.sh b/gnu/libexec/uucp/contrib/stats.sh new file mode 100644 index 00000000000..ac1d0f556ee --- /dev/null +++ b/gnu/libexec/uucp/contrib/stats.sh @@ -0,0 +1,27 @@ +#!/bin/sh +# +# uuspeed - a script to parse a Taylor UUCP Stats file into pretty results. +# Zacharias J. Beckman. + +grep bytes /usr/spool/uucp/Stats | grep -v 'bytes 0.00 secs' | grep -v 'failed after' | tail -80 | \ +gawk ' + BEGIN { + printf(" UUCP transmission history:\n"); + format=" %8d bytes %8s(%8s) in %7.2f sec = %5.0f baud, %4.1fK / min\n"; + average=0.01; + samples=0; + } + + { + if ($6 > 100) { + printf (format, $6, $5, $2, $9, $6/$9*10, ($6/$9*60)/1000); + + average += ($6/$9*10); + samples += 1; + } + } + + END { + printf (" average speed %d baud\n", average/samples); + } +' diff --git a/gnu/libexec/uucp/contrib/tstout.c b/gnu/libexec/uucp/contrib/tstout.c new file mode 100644 index 00000000000..dd82633c7a0 --- /dev/null +++ b/gnu/libexec/uucp/contrib/tstout.c @@ -0,0 +1,158 @@ +/* tstout.c + Put together by Ian Lance Taylor <ian@airs.com> + + This program is used to logout a program run by the tstuu program. + I needed this because on Ultrix 4.0 I can't get the uucp program + to run without invoking it via /bin/login and having it start up + as a shell. If I don't do it this way, it gets a SIGSEGV trap + for some reason. Most systems probably don't need to do things + this way. It will only work on BSD systems anyhow, I suspect. + + The code for this comes from "UNIX Network Programming" by W. + Richard Stevens, Prentice-Hall 1990. Most of it is from 4.3BSD, as + noted in the comments. + + This program must run suid to root. + */ + +#include <stdio.h> +#include <string.h> + +#include <sys/types.h> +#include <sys/file.h> +#include <sys/time.h> +#include <sys/stat.h> +#include <utmp.h> + +static int logout P((const char *zdev)); +static void logwtmp P((const char *zdev, const char *zname, + const char *zhost)); + +int +main (argc, argv) + int argc; + char **argv; +{ + char *z; + + if (argc != 2 + || strncmp (argv[1], "/dev/", sizeof "/dev/" - 1) != 0) + { + fprintf (stderr, "Usage: tstout device\n"); + exit (EXIT_FAILURE); + } + + z = argv[1] + 5; + + if (logout (z)) + logwtmp (z, "", ""); + + chmod (argv[1], 0666); + chown (argv[1], 0, 0); + + *z = 'p'; + chmod (argv[1], 0666); + chown (argv[1], 0, 0); + + exit (EXIT_SUCCESS); +} + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)logout.c 5.2 (Berkeley) 2/17/89"; +#endif /* LIBC_SCCS and not lint */ + +#define UTMPFILE "/etc/utmp" + +/* 0 on failure, 1 on success */ + +static int +logout(line) + register const char *line; +{ + register FILE *fp; + struct utmp ut; + int rval; + time_t time(); + + if (!(fp = fopen(UTMPFILE, "r+"))) + return(0); + rval = 0; + while (fread((char *)&ut, sizeof(struct utmp), 1, fp) == 1) { + if (!ut.ut_name[0] || + strncmp(ut.ut_line, line, sizeof(ut.ut_line))) + continue; + bzero(ut.ut_name, sizeof(ut.ut_name)); + bzero(ut.ut_host, sizeof(ut.ut_host)); + (void)time((time_t *)&ut.ut_time); + (void)fseek(fp, (long)-sizeof(struct utmp), L_INCR); + (void)fwrite((char *)&ut, sizeof(struct utmp), 1, fp); + (void)fseek(fp, (long)0, L_INCR); + rval = 1; + } + (void)fclose(fp); + return(rval); +} + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)logwtmp.c 5.2 (Berkeley) 9/20/88"; +#endif /* LIBC_SCCS and not lint */ + +#define WTMPFILE "/usr/adm/wtmp" + +static void +logwtmp(line, name, host) + const char *line, *name, *host; +{ + struct utmp ut; + struct stat buf; + int fd; + time_t time(); + char *strncpy(); + + if ((fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0) + return; + if (!fstat(fd, &buf)) { + (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line)); + (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name)); + (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host)); + (void)time((time_t *)&ut.ut_time); + if (write(fd, (char *)&ut, sizeof(struct utmp)) != + sizeof(struct utmp)) + (void)ftruncate(fd, buf.st_size); + } + (void)close(fd); +} diff --git a/gnu/libexec/uucp/contrib/uuclean b/gnu/libexec/uucp/contrib/uuclean new file mode 100644 index 00000000000..1cfb6332bfb --- /dev/null +++ b/gnu/libexec/uucp/contrib/uuclean @@ -0,0 +1,25 @@ +# This is a sample uuclean shell script +# Copyright (C) 1992 Ian Lance Taylor +# Do whatever you like with this script. +# +# Set some variables +bindir=/usr/local/bin +spooldir=/usr/spool/uucp +# +# Warn about all mail over two days old +$(bindir)/uustat -c rmail -o 48 -N -Q -W"Unable to deliver; will try up to one week" +# Return all mail over a week old +$(bindir)/uustat -c rmail -o 168 -K -M -N -Q -W"Could not be delivered for over one week" +# Throw away other requests over a week old +$(bindir)/uustat -o 168 -K -M -N -Q -W"Over one week old" +# Throw away any executions over three days old +$(bindir)/uustat -o 72 -M -N -Q -W"Unable to execute for three days" +# +# Now delete any old spool files +find $(spooldir) -ctime +8 -name '[CDX].*' -print -exec rm -f \{\} \; +# Delete any old temporary files +find $(spooldir) -atime +1 -ctime +1 -name 'TM.*' -print -exec rm -f \{\} \; +# Delete any old preserved files +find $(spooldir)/.Preserve -atime +14 -ctime +14 -print -exec rm -f \{\} \; +# Delete any old failed execution files +find $(spooldir)/.Failed -atime +14 -ctime +14 -print -exec rm -f \{\} \; diff --git a/gnu/libexec/uucp/contrib/uucomp.shar b/gnu/libexec/uucp/contrib/uucomp.shar new file mode 100644 index 00000000000..da131d048c5 --- /dev/null +++ b/gnu/libexec/uucp/contrib/uucomp.shar @@ -0,0 +1,552 @@ +#! /bin/sh +# +# Created by shar, version 0.5 - 04/10/91 +# +# This is a shell archive, meaning: +# 1. Remove everything about the #! /bin/sh line. +# 2. Save the resulting text in a file. +# 3. Execute the file with /bin/sh to create: +# +# length name +# ------ ------------------------------------- +# 128 uucomp-1.1/Compress +# 264 uucomp-1.1/Copyright +# 410 uucomp-1.1/INTERNALS +# 1069 uucomp-1.1/Makefile +# 3528 uucomp-1.1/README +# 632 uucomp-1.1/crmail.c +# 632 uucomp-1.1/crnews.c +# 108 uucomp-1.1/tags +# 3506 uucomp-1.1/uucomp.c +# 383 uucomp-1.1/uucomp.h +# + +if test ! -d uucomp-1.1 ; then + mkdir uucomp-1.1 +fi +# +# Archive number 1 +# This archive created Tue Sep 28 20:21:14 1993 +# + +echo "shar: extracting uucomp-1.1/Compress - (128 characters)" +if test -f 'uucomp-1.1/Compress' ; then + echo shar: will not over-write existing file uucomp-1.1/Compress +else +sed 's/^X//' << \SHAR_EOF > 'uucomp-1.1/Compress' +Xfor i in $* +Xdo +X if [ -d /usr/spool/uucp/$i ] +X then +X# echo Looking at $i +X cd /usr/spool/uucp/$i +X /usr/bin/uucomp C.* +X fi +Xdone +SHAR_EOF +if test 128 -ne "`wc -c < 'uucomp-1.1/Compress'`" ; then + echo "shar: ***** error transmitting file uucomp-1.1/Compress (should have been 128 characters, but was "`wc -c < 'uucomp-1.1/Compress'`" characters) *****" +fi +fi + +touch 0715110393 uucomp-1.1/Compress +chmod 0700 uucomp-1.1/Compress + +echo "shar: extracting uucomp-1.1/Copyright - (264 characters)" +if test -f 'uucomp-1.1/Copyright' ; then + echo shar: will not over-write existing file uucomp-1.1/Copyright +else +sed 's/^X//' << \SHAR_EOF > 'uucomp-1.1/Copyright' +X +X/* +X * +X * Copyright 1993 by Ed Carp (erc@apple.com) All rights reserved. +X * +X * Permission is hereby granted for any non-commercial use of this +X * program, as long as this copyright notice remains intact. Commercial +X * users may contact me - I'm easy. +X * +X */ +X +SHAR_EOF +if test 264 -ne "`wc -c < 'uucomp-1.1/Copyright'`" ; then + echo "shar: ***** error transmitting file uucomp-1.1/Copyright (should have been 264 characters, but was "`wc -c < 'uucomp-1.1/Copyright'`" characters) *****" +fi +fi + +touch 0715174993 uucomp-1.1/Copyright +chmod 0600 uucomp-1.1/Copyright + +echo "shar: extracting uucomp-1.1/INTERNALS - (410 characters)" +if test -f 'uucomp-1.1/INTERNALS' ; then + echo shar: will not over-write existing file uucomp-1.1/INTERNALS +else +sed 's/^X//' << \SHAR_EOF > 'uucomp-1.1/INTERNALS' +XThis is the basic workflow for uucomp: +X +Xfor (every argv) +Xdo +X if not "C." file skip +X if open fail, skip +X read 1 line from C. file +X grab second and 10th field (second is data file name, +X 10th is command name) +X if open fail on second field, skip +X if 10th field isn't "rmail" or "rnews", skip +X execute "gzip -9" on second field +X change "rmail" and "rnews" to "crmail" and "crnews", respectively +X in C. file +Xdone +SHAR_EOF +if test 410 -ne "`wc -c < 'uucomp-1.1/INTERNALS'`" ; then + echo "shar: ***** error transmitting file uucomp-1.1/INTERNALS (should have been 410 characters, but was "`wc -c < 'uucomp-1.1/INTERNALS'`" characters) *****" +fi +fi + +touch 0715174693 uucomp-1.1/INTERNALS +chmod 0600 uucomp-1.1/INTERNALS + +echo "shar: extracting uucomp-1.1/Makefile - (1069 characters)" +if test -f 'uucomp-1.1/Makefile' ; then + echo shar: will not over-write existing file uucomp-1.1/Makefile +else +sed 's/^X//' << \SHAR_EOF > 'uucomp-1.1/Makefile' +X# +X# Makefile generated with genmake - version 1.1 08/22/92 +X# +X# genmake is Copyright 1991 by Edwin R. Carp +X# +X# GENMAKE -B/usr/bin -tsp [files] +X# +X +XCC = gcc -O6 +XCFLAGS = $(INCLUDE) +XSOURCES = crmail.c crnews.c uucomp.c +XOBJECTS = crmail.o crnews.o uucomp.o +XPROGRAMS = /usr/bin/crmail /usr/bin/crnews /usr/bin/uucomp +X +Xall: $(PROGRAMS) tags +X +X/usr/bin/crmail: crmail.o +X $(CC) $(CFLAGS) -o crmail crmail.o $(LDFLAGS) -O +X strip crmail +X chmod 755 crmail +X mv crmail /usr/bin +X +X/usr/bin/crnews: crnews.o +X $(CC) $(CFLAGS) -o crnews crnews.o $(LDFLAGS) -O +X strip crnews +X chmod 755 crnews +X mv crnews /usr/bin +X +X/usr/bin/uucomp: uucomp.o +X $(CC) $(CFLAGS) -o uucomp uucomp.o $(LDFLAGS) -O +X strip uucomp +X chmod 755 uucomp +X mv uucomp /usr/bin +X +Xclean: +X /bin/rm -f $(OBJECTS) MAKELOG eddep makedep +X +Xclobber: +X /bin/rm -f $(OBJECTS) $(PROGRAMS) MAKELOG eddep makedep *~ *.bak *.BAK +X /bin/rm -f tags +X +Xhidden: +X echo "make all > MAKELOG 2>&1 &"|/bin/sh +X +Xmakefile: +X genmake -B/usr/bin -tsp $(SOURCES) & +X +Xmakeall: +X genmake -B/usr/bin -tsp *.c & +X +Xtags: $(SOURCES) +X ctags $(SOURCES) > tags +X +SHAR_EOF +if test 1069 -ne "`wc -c < 'uucomp-1.1/Makefile'`" ; then + echo "shar: ***** error transmitting file uucomp-1.1/Makefile (should have been 1069 characters, but was "`wc -c < 'uucomp-1.1/Makefile'`" characters) *****" +fi +fi + +touch 0714235093 uucomp-1.1/Makefile +chmod 0600 uucomp-1.1/Makefile + +echo "shar: extracting uucomp-1.1/README - (3528 characters)" +if test -f 'uucomp-1.1/README' ; then + echo shar: will not over-write existing file uucomp-1.1/README +else +sed 's/^X//' << \SHAR_EOF > 'uucomp-1.1/README' +XLike most people these days, I'm looking for ways to make my computing +Xenvironment more efficient. This environment consists of a 486, a 386, +Xand a 386SL laptop, all of which run Taylor uucp under Linux. The 386 +Xlaptop gets used a lot, since it goes wherever I go and I answer a lot +Xof news and email every day. Often, I must use other people's facilities +X(phone lines and such) to send out replies and post news if I'm not at home. +XSince it's not fair to the client for them to pay for my zone calls back +Xto my home in Fremont, I place the calls on my phone card. Unfortunately, +XPacBell is very proud of the services they offer, especially in regards +Xto this convenience of automatically charging calls to my house wherever I +Xmay be. Considering that this can be very expensive to do, I searched for +Xa way to cut my phone bill down to something I could afford to pay each +Xmonth without fainting every time I saw the bill. +X +XThe first thing I did was to go out and plunk $195 for a 14.4KB modem. +XThat helped, but C-News is very slow on my laptop, and batching articles +Xis even slower, and email (of course) isn't batched at all. Even with +XMNP5 compression turned on, this doesn't make for a very efficient setup, +Xeven at high speeds. +X +XPlaying around with uucp told me that the line turnaround wasn't that much +Xoverhead, nor was sending the C./X. files (the execute files) - the real +Xoverhead was sending out uncompressed news and especially email, since +XI subscribe to several mailing lists and digests can run quite large. +X +XI looked at uubatch, but the most current version I could find (1.05) was +Xnot compatible with Taylor uucp (and I had no other alternative), so I +Xdecided to write my own. Experiments with "gzip -9" convinced me that +Xthat was the way to go, since gzip gives email and news 60 to 75 percent +Xcompression, which would tend to cut one's phone bill significantly. +X +XYou hold in your mailbox (or news reader) the end result of that effort. +XBear in mind that (1) this is a "first cut" and while it is unlikely that +Xthere are very many bugs, there are certainly places where the programs could +Xbe improved and tuned. Suggestions and comments are welcome! +X +XTo install: +X +X 1. Feed this to shar. +X 2. Look at the Makefile. Make sure that the paths for +X things are set up correctly. +X 3. Look at uucomp.h and make sure that the path and +X options for COMPRESS/UNCOMPRESS are set up properly. +X 3. Type "make". This will make uucomp, crmail, and crnews +X and will place them in /usr/bin. Move Compress into +X /usr/lib/uucp. +X 4. Make an entry in crontab to do +X /usr/lib/uucp/Compress site1 site2 site3... +X occasionally. It is suggested that this be done fairly +X frequently. Alternately, you could set up a login shell +X for selected sites to run uucomp every time that site +X logged in. +X 5. Don't forget to add /usr/bin/crmail and /usr/bin/crnews +X to the list of programs allowed to be executed in your +X Permissions file (if running HDB UUCP), or whatever is +X appropriate for your version of uucp. +X +XEnjoy! Any questions or comments can be sent to erc@apple.com. +X +XNote: This is tuned for Taylor uucp, but would not be particularly +Xdifficult to adapt to other version of uucp. See the file INTERNALS for +Xdetails of how this works. +X +XJuly 15, 1993 +XEd Carp +Xerc@apple.com +X------------------------------------------------------------------------------ +XChanges since 1.0: +X +X Version Date Description +X +X 1.1 08/04/93 Added sanity check in C. file (check that +X 'E' is first char in file, otherwise skip) +SHAR_EOF +if test 3528 -ne "`wc -c < 'uucomp-1.1/README'`" ; then + echo "shar: ***** error transmitting file uucomp-1.1/README (should have been 3528 characters, but was "`wc -c < 'uucomp-1.1/README'`" characters) *****" +fi +fi + +touch 0804224993 uucomp-1.1/README +chmod 0600 uucomp-1.1/README + +echo "shar: extracting uucomp-1.1/crmail.c - (632 characters)" +if test -f 'uucomp-1.1/crmail.c' ; then + echo shar: will not over-write existing file uucomp-1.1/crmail.c +else +sed 's/^X//' << \SHAR_EOF > 'uucomp-1.1/crmail.c' +X/* +X * crmail - get compressed mail from host, uncompress +X * WARNING: This may be insecure! +X */ +X +X/* +X * +X * Copyright 1993 by Ed Carp (erc@apple.com) All rights reserved. +X * +X * Permission is hereby granted for any non-commercial use of this +X * program, as long as this copyright notice remains intact. Commercial +X * users may contact me - I'm easy. +X * +X */ +X +X#include <stdio.h> +X#include "uucomp.h" +Xmain (argc, argv) +Xint argc; +Xchar **argv; +X{ +X char cmd[1024]; +X int i; +X +X sprintf (cmd, "%s|%s ", UNCOMPRESS, RMAIL); +X for (i = 1; i < argc; i++) +X { +X strcat (cmd, argv[i]); +X strcat (cmd, " "); +X } +X system (cmd); +X exit (0); +X} +SHAR_EOF +if test 632 -ne "`wc -c < 'uucomp-1.1/crmail.c'`" ; then + echo "shar: ***** error transmitting file uucomp-1.1/crmail.c (should have been 632 characters, but was "`wc -c < 'uucomp-1.1/crmail.c'`" characters) *****" +fi +fi + +touch 0715195493 uucomp-1.1/crmail.c +chmod 0600 uucomp-1.1/crmail.c + +echo "shar: extracting uucomp-1.1/crnews.c - (632 characters)" +if test -f 'uucomp-1.1/crnews.c' ; then + echo shar: will not over-write existing file uucomp-1.1/crnews.c +else +sed 's/^X//' << \SHAR_EOF > 'uucomp-1.1/crnews.c' +X/* +X * crnews - get compressed news from host, uncompress +X * WARNING: This may be insecure! +X */ +X +X/* +X * +X * Copyright 1993 by Ed Carp (erc@apple.com) All rights reserved. +X * +X * Permission is hereby granted for any non-commercial use of this +X * program, as long as this copyright notice remains intact. Commercial +X * users may contact me - I'm easy. +X * +X */ +X +X#include <stdio.h> +X#include "uucomp.h" +Xmain (argc, argv) +Xint argc; +Xchar **argv; +X{ +X char cmd[1024]; +X int i; +X +X sprintf (cmd, "%s|%s ", UNCOMPRESS, RNEWS); +X for (i = 1; i < argc; i++) +X { +X strcat (cmd, argv[i]); +X strcat (cmd, " "); +X } +X system (cmd); +X exit (0); +X} +SHAR_EOF +if test 632 -ne "`wc -c < 'uucomp-1.1/crnews.c'`" ; then + echo "shar: ***** error transmitting file uucomp-1.1/crnews.c (should have been 632 characters, but was "`wc -c < 'uucomp-1.1/crnews.c'`" characters) *****" +fi +fi + +touch 0715195593 uucomp-1.1/crnews.c +chmod 0600 uucomp-1.1/crnews.c + +echo "shar: extracting uucomp-1.1/tags - (108 characters)" +if test -f 'uucomp-1.1/tags' ; then + echo shar: will not over-write existing file uucomp-1.1/tags +else +sed 's/^X//' << \SHAR_EOF > 'uucomp-1.1/tags' +Xmain crmail.c /^main (argc, argv)$/ +Xmain crnews.c /^main (argc, argv)$/ +Xmain uucomp.c /^main (argc, argv)$/ +SHAR_EOF +if test 108 -ne "`wc -c < 'uucomp-1.1/tags'`" ; then + echo "shar: ***** error transmitting file uucomp-1.1/tags (should have been 108 characters, but was "`wc -c < 'uucomp-1.1/tags'`" characters) *****" +fi +fi + +touch 0804224993 uucomp-1.1/tags +chmod 0600 uucomp-1.1/tags + +echo "shar: extracting uucomp-1.1/uucomp.c - (3506 characters)" +if test -f 'uucomp-1.1/uucomp.c' ; then + echo shar: will not over-write existing file uucomp-1.1/uucomp.c +else +sed 's/^X//' << \SHAR_EOF > 'uucomp-1.1/uucomp.c' +X/* +X * uucomp - compress outgoing news/mail +X * +X * usage: uucomp C.* +X * +X * This works for Taylor uucp (available from prep.ai.mit.edu:/pub/gnu/uucp*), +X * but I don't promise it works for anyone else's uucp package. Basically, this +X * is a quick-n-dirty hack to get compressed mail and news to a uucp site. This +X * becomes important when you're on the other end of a 1200 baud packet radio +X * link, where the throughput can be 60 CPS (or lower). It also tends to hide +X * any nasties that people might want to say to you, since the packets *are* +X * public readable. Yes, I looked at uubatch, but it was too complicated for +X * me to figure out <grin>, and it didn't work with Taylor-uucp. This is almost +X * too simple to work... +X * +X * To use this little guy, do something like this in the .bashrc or .profile +X * or .cshrc of the uucp's login shell: +X * +X * cd /usr/spool/uucp/<wherever the C. and D. files are kept> +X * /usr/bin/uucomp C.* +X * exec /usr/lib/uucp/uucico +X * +X * This program was written by Ed Carp (erc@apple.com). It can be used for any +X * non-commercial purpose. This software is freely redistributable. +X */ +X +X/* +X * +X * Copyright 1993 by Ed Carp (erc@apple.com) All rights reserved. +X * +X * Permission is hereby granted for any non-commercial use of this +X * program, as long as this copyright notice remains intact. Commercial +X * users may contact me - I'm easy. +X * +X */ +X +X#include <stdio.h> +X#include "uucomp.h" +X#undef NULL +X#define NULL (0) +Xmain (argc, argv) +Xint argc; +Xchar **argv; +X{ +X int i, j, sw, ctr = 0, errflag = 0, mctr = 0, nctr = 0, skipctr = 0; +X char scr[64], rcmd[10], line[1024], lineout[1024]; +X char *strtok (), *ptr, *lineptr, compfile[32]; +X FILE *in; +X +X printf ("uucomp 1.1 08/04/93 ... by erc@apple.com\nscanning %d files.", argc - 1); +X for (i = 1; i < argc; i++) +X { +X if (strncmp (argv[i], "C.", 2) != 0) +X { +X skipctr++; +X continue; +X } +X if ((in = fopen (argv[i], "r+")) == (FILE *) NULL) +X { +X skipctr++; +X continue; +X } +X fgets (line, 1022, in); +X if(*line != 'E') +X { +X skipctr++; +X continue; +X } +X line[strlen (line) - 1] = NULL; +X rewind (in); +X *lineout = NULL; +X lineptr = line; +X sw = errflag = 0; +X printf ("."); +X fflush (stdout); +X for (j = 0;; j++) +X { +X ptr = strtok (lineptr, " "); +X if (ptr == NULL) +X break; +X lineptr = NULL; +X if (j == 1) +X { +X if (access (ptr, 4) == EOF) +X { +X#ifdef DEBUG +X printf ("skip: file '%s' doesn't exist\n", ptr); +X#endif +X errflag = 1; +X break; /* +X * skip it if the data file isn't +X * there yet +X */ +X } +X strcpy (compfile, ptr); +X } +X if (j == 9) +X { +X if (strcmp (ptr, "rmail") != 0 && strcmp (ptr, "rnews") != 0) +X { +X#ifdef DEBUG +X printf ("skip: '%s' wrong command\n", ptr); +X#endif +X errflag = 1; +X break; +X } +X if (strcmp (ptr, "rmail") == 0) +X mctr++; +X if (strcmp (ptr, "rnews") == 0) +X nctr++; +X sw = 1; +X strcat (lineout, "c"); +X } +X strcat (lineout, ptr); +X strcat (lineout, " "); +X } +X if (errflag == 1) +X { +X skipctr++; +X fclose (in); +X continue; +X } +X fprintf (in, "%s\n", lineout); +X fclose (in); +X sprintf (line, +X "%s -fc > /tmp/uucomp.%d < %s;cp /tmp/uucomp.%d %s", +X COMPRESS, getpid (), compfile, getpid (), compfile); +X system (line); +X ctr++; +X } +X sprintf (line, "/tmp/uucomp.%d", getpid ()); +X unlink (line); +X printf ("\n%d skipped, %d compressed (%d mail, %d news).\n", +X skipctr, ctr, mctr, nctr); +X exit (0); +X} +SHAR_EOF +if test 3506 -ne "`wc -c < 'uucomp-1.1/uucomp.c'`" ; then + echo "shar: ***** error transmitting file uucomp-1.1/uucomp.c (should have been 3506 characters, but was "`wc -c < 'uucomp-1.1/uucomp.c'`" characters) *****" +fi +fi + +touch 0804224693 uucomp-1.1/uucomp.c +chmod 0600 uucomp-1.1/uucomp.c + +echo "shar: extracting uucomp-1.1/uucomp.h - (383 characters)" +if test -f 'uucomp-1.1/uucomp.h' ; then + echo shar: will not over-write existing file uucomp-1.1/uucomp.h +else +sed 's/^X//' << \SHAR_EOF > 'uucomp-1.1/uucomp.h' +X/* +X * +X * Copyright 1993 by Ed Carp (erc@apple.com) All rights reserved. +X * +X * Permission is hereby granted for any non-commercial use of this +X * program, as long as this copyright notice remains intact. Commercial +X * users may contact me - I'm easy. +X * +X */ +X +X#define COMPRESS "/usr/bin/gzip -9c" +X#define UNCOMPRESS "/usr/bin/gzip -dc" +X#define RMAIL "rmail" +X#define RNEWS "rnews" +SHAR_EOF +if test 383 -ne "`wc -c < 'uucomp-1.1/uucomp.h'`" ; then + echo "shar: ***** error transmitting file uucomp-1.1/uucomp.h (should have been 383 characters, but was "`wc -c < 'uucomp-1.1/uucomp.h'`" characters) *****" +fi +fi + +touch 0715190293 uucomp-1.1/uucomp.h +chmod 0600 uucomp-1.1/uucomp.h +echo End of all shell archives +exit 0 diff --git a/gnu/libexec/uucp/contrib/uudemon.shar b/gnu/libexec/uucp/contrib/uudemon.shar new file mode 100644 index 00000000000..31a8fa60707 --- /dev/null +++ b/gnu/libexec/uucp/contrib/uudemon.shar @@ -0,0 +1,82 @@ +#! /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 shell archive." +# Contents: Poll uudemon.poll +# Wrapped by dburr@sbanet on Fri Jul 23 20:15:18 1993 +PATH=/bin:/usr/bin:/usr/ucb ; export PATH +if test -f 'Poll' -a "${1}" != "-c" ; then + echo shar: Will not clobber existing file \"'Poll'\" +else +echo shar: Extracting \"'Poll'\" \(244 characters\) +sed "s/^X//" >'Poll' <<'END_OF_FILE' +X# HDB-ish poll file +X# +X# Format: <site><tab><hour1> <hour2> ... +X# ONLY ONE TAB BETWEEN FIELDS... more may work, but I have absolutely no +X# idea if it will work at all. +X# +X# comment lines (begin with `#') are ignored. +X +Xdschub 20 21 22 +Xgd 20 21 22 +END_OF_FILE +if test 244 -ne `wc -c <'Poll'`; then + echo shar: \"'Poll'\" unpacked with wrong size! +fi +# end of 'Poll' +fi +if test -f 'uudemon.poll' -a "${1}" != "-c" ; then + echo shar: Will not clobber existing file \"'uudemon.poll'\" +else +echo shar: Extracting \"'uudemon.poll'\" \(941 characters\) +sed "s/^X//" >'uudemon.poll' <<'END_OF_FILE' +X#!/bin/sh +X# +X# This is my impersonation of the HDB uudemon.poll script. +X# Yes, I know, this is very clumsy and clunky... ahh well, I've always +X# been better at C/pascal/etc than Shell programming... :( +X +X# change LIBDIR to where UUCP library/conf. files are +X# change SPOOLDIR to the UUCP spool directory. It must be HDB-ish. +XLIBDIR=/usr/lib/uucp; export LIBDIR +XSPOOLDIR=/usr/spool/uucp; export SPOOLDIR +X +X### no changes needed past here ### +X +XHOUR=`date +%H`; export HOUR +X +Xif [ -f ${LIBDIR}/Poll ]; then +X for SYS in `uuname` +X do +X CHOICES="`grep "^$SYS[ ]" ${LIBDIR}/Poll | awk -F' ' \ +X '{ print $2 }'`" +X DOIT="no" +X for H in $CHOICES +X do +X if [ "$HOUR" = "$H" ]; then +X DOIT="yes" +X fi +X done +X if [ "$DOIT" = "yes" ]; then +X if [ ! -d ${SPOOLDIR}/${SYS} ]; then +X mkdir ${SPOOLDIR}/${SYS} +X fi +X chmod 755 ${SPOOLDIR}/${SYS} +X touch ${SPOOLDIR}/${SYS}/C.${SYS}n0000 +X chmod 644 ${SPOOLDIR}/${SYS}/C.${SYS}n0000 +X fi +X done +Xfi +END_OF_FILE +if test 941 -ne `wc -c <'uudemon.poll'`; then + echo shar: \"'uudemon.poll'\" unpacked with wrong size! +fi +chmod +x 'uudemon.poll' +# end of 'uudemon.poll' +fi +echo shar: End of shell archive. +exit 0 diff --git a/gnu/libexec/uucp/contrib/uupoll.shar b/gnu/libexec/uucp/contrib/uupoll.shar new file mode 100644 index 00000000000..84a95e04e88 --- /dev/null +++ b/gnu/libexec/uucp/contrib/uupoll.shar @@ -0,0 +1,2705 @@ +#!/bin/sh +# This is a shell archive (produced by shar 3.49) +# To extract the files from this archive, save it to a file, remove +# everything above the "!/bin/sh" line above, and type "sh file_name". +# +# made 04/17/1994 02:21 UTC by ian@comton.airs.com +# Source directory /disk4/ian +# +# existing files will NOT be overwritten unless -c is specified +# +# This shar contains: +# length mode name +# ------ ---------- ------------------------------------------ +# 2602 -r--r--r-- uupoll/Makefile +# 3636 -r--r--r-- uupoll/README +# 4718 -r--r--r-- uupoll/autopoll.8c +# 44031 -r--r--r-- uupoll/autopoll.c +# 3884 -r--r--r-- uupoll/conf.h +# 4787 -r--r--r-- uupoll/uupoll.8c +# 27587 -r--r--r-- uupoll/uupoll.c +# +# ============= uupoll/Makefile ============== +if test ! -d 'uupoll'; then + echo 'x - creating directory uupoll' + mkdir 'uupoll' +fi +if test -f 'uupoll/Makefile' -a X"$1" != X"-c"; then + echo 'x - skipping uupoll/Makefile (File already exists)' +else +echo 'x - extracting uupoll/Makefile (Text)' +sed 's/^X//' << 'SHAR_EOF' > 'uupoll/Makefile' && +# This is the Makefile for uupoll and autopoll +# borrowed and hacked from Taylor UUCP 1.04 +X +# Prefix directory for installation directories. +prefix = /usr/local +X +# The user name/group that should own the resulting executables. +# Both should run suid. +owner = uucp.daemon +X +# Which mode should the resulting executables have. +emode = 4111 +X +# Where to install autopoll. This definition requires $(prefix)/lib to exist. +lbindir = $(prefix)/lib/uucp +X +# Where are the sources from uucp-Taylor uucp.h, uuconf.h, policy.h. +# the following assumes that our sources are in uucp-1.05/contrib/uupoll +# and the required .h files are in main directory for uucp-1.05 +uucpsrcs = ../../ +X +# Where to install uupoll +bbindir = $(prefix)/bin +X +# Where to install man pages. Section 8 for daemons. +man8dir = $(prefix)/man/man8 +man8ext = .8c +X +# Define programs and flags +CC = gcc +CFLAGS = -O2 +LDFLAGS = -s +LIBS = +X +INSTALL = /usr/bin/install -c +INSTALL_PROGRAM = $(INSTALL) +INSTALL_DATA = $(INSTALL) -m 644 +X +# +# Nothing else to configure +# +X +SHELL = /bin/sh +X +VERSION = 1.00 +X +MORECFLAGS = -I. -I$(uucpsrcs) -Wall +X +PROGRAMS = uupoll autopoll +X +UUPOLLOBJS = uupoll.o +AUTOOBJS = autopoll.o +X +ALLOBJS = uupoll.o autopoll.o +X +all: $(PROGRAMS) +X +install: $(PROGRAMS) +X if test -d $(lbindir); then true; else mkdir $(lbindir); fi +X if test -d $(bbindir); then true; else mkdir $(bbindir); fi +X -if test -f $(lbindir)/autopoll.old; then rm -f $(lbindir)/autopoll; else mv $(lbindir)/autopoll $(lbindir)/autopoll.old; fi +X -if test -f $(bbindir)/uupoll.old; then rm -f $(bbindir)/uupoll; else mv $(bbindir)/uupoll $(bbindir)/uupoll.old; fi +X $(INSTALL_PROGRAM) autopoll $(lbindir)/autopoll +X $(INSTALL_PROGRAM) uupoll $(bbindir)/uupoll +X chown $(owner) $(lbindir)/autopoll $(bbindir)/uupoll +X chmod $(emode) $(lbindir)/autopoll $(bbindir)/uupoll +X $(INSTALL_DATA) uupoll.8c $(man8dir)/uupoll$(man8ext) +X $(INSTALL_DATA) autopoll.8c $(man8dir)/autopoll$(man8ext) +X +uninstall: +X rm -f $(lbindir)/autopoll $(bbindir)/uupoll +X rm -f $(man8dir)/autopoll$(man8ext) $(man8dir)/uupoll$(man8ext) +X -cp $(lbindir)/autopoll.old $(lbindir)/autopoll +X -cp $(bbindir)/uupoll.old $(bbindir)/uupoll +X -chown $(owner) $(lbindir)/autopoll $(bbindir)/uupoll +X -chmod $(emode) $(lbindir)/autopoll $(bbindir)/uupoll +X +uupoll: $(UUPOLLOBJS) +X $(CC) $(LDFLAGS) -o uupoll $(UUPOLLOBJS) $(LIBS) +X +autopoll: $(AUTOOBJS) +X $(CC) $(LDFLAGS) -o autopoll $(AUTOOBJS) $(LIBS) +X +.c.o: +X $(CC) -c $(CFLAGS) $(MORECFLAGS) $< +X +X +clean: +X rm -f $(ALLOBJS) $(PROGRAMS) +X +mostlyclean: clean +X +TAGS: +X etags *.h *.c +X +# Header file dependencies. These are maintained by hand. +X +$(ALLOBJS): conf.h +X +.NOEXPORT: +SHAR_EOF +chmod 0444 uupoll/Makefile || +echo 'restore of uupoll/Makefile failed' +Wc_c="`wc -c < 'uupoll/Makefile'`" +test 2602 -eq "$Wc_c" || + echo 'uupoll/Makefile: original size 2602, current size' "$Wc_c" +fi +# ============= uupoll/README ============== +if test -f 'uupoll/README' -a X"$1" != X"-c"; then + echo 'x - skipping uupoll/README (File already exists)' +else +echo 'x - extracting uupoll/README (Text)' +sed 's/^X//' << 'SHAR_EOF' > 'uupoll/README' && +X +The package consists of the following files: +X +X - autopoll.c +X - autopoll.8c +X - conf.h +X - Makefile +X - README +X - uupoll.c +X - uupoll.8c +X +CAVEAT: +uupoll as well as autopoll are created, tested and run on +a NeXT running NeXTstep 2.1+ only! Autopoll will take the same arguments +as uucico and may well work with them the same way uucico works but it +has only been tested to call uucico with the options: +X +X -s<site> -S<site> -f -r1 -C -D (as well as the long form of these options) +X +so far. All options given to autopoll will be passed verbatim to uucico. +X +DESCRIPTION: +The program uupoll was created to be a full replacement for the vendor +supplied one on a NeXT computer. That uupoll checked any site name against +the "hardwired" L.sys and did end with a "Bus error" if the site could not +be found. There was no source available to modify so it had to be created +from scratch. +The program autopoll has no equivalent an the NeXT. The intentions behind +it was to automate the task of rescheduling any failed call. It may be +started by an entry in the crontab tables in just the same way uucico is +started (it will start uucico): +X +05 5 * * * uucp /usr/local/lib/uucp/autopoll -r1 >>/tmp/poll.log 2>&1 +X +Any messages go to stderr or a file (if compiled with that option); in case +the file could not be opened it will use stdout to tell you just that and quit. +To catch any output one may place the string +X +X >>/tmp/poll.log 2>&1 +X +into the command line as well. Uupoll as well as autopoll will place only +a start message into the logfiles in case they are invoked manually from +the shell. +If the call fails autopoll will reschedule uucico for a later time by means +of an AT job. +The messages given by uupoll and autopoll carry an indicator to inform about +the nature of an error; they are: +X +- (I) informal message; such as ".. started" ".. ended". +- (W) there might be an error but the program decided to go ahead. +X The exit code will be at least 4. +- (E) a severe error was encountered that either aborts the whole run or +X only the task for one site will be aborted. +X The exit code will be at least 8. +- (C) a catastrophic error has been found such as unable to fork. The run +X is aborted. +X The exit code will be at least 16. +The final message will show the exit code the programm has terminated with. +X +For more information see the man pages or look into the source. +X +INSTALLATION: +all files should be placed in one folder. Then examine and change the files +Makefile and conf.h to meet your needs. To compile uupoll some files of +uucp must be available (see Makefile: uucpsrcs) +If not already there change to the directory which contain the files and type: +X +make +X +this should compile UUPOLL and AUTOPOLL. There should only be a warning +that rcsid is defined but not used. +Before actually installing you should test the programs to be working as +desired. +Then check the Makefile for the final placement of the modules and the man +pages. Make sure the ownership and setuid is what you need on your machine +to run the program(s). +Then su to root and type: +X +make install +X +which should install the above programs and the man pages in the appropriate +directories. +Some word on the coding: have mercy! This is my second project in 'C'; any +suggestions that may improve the style/coding are welcome however. +X +In case of any problems that can't be solved feel free to contact the +author at: +X +Klaus Dahlenburg Timezone : GMT + 2 +P.O.Box 1267 email : kdburg@incoahe.hanse.de +D-21249 Tostedt Fax : +49 4287 676 +X Germany Voice : +49 4287 681 +X +Have fun! +SHAR_EOF +chmod 0444 uupoll/README || +echo 'restore of uupoll/README failed' +Wc_c="`wc -c < 'uupoll/README'`" +test 3636 -eq "$Wc_c" || + echo 'uupoll/README: original size 3636, current size' "$Wc_c" +fi +# ============= uupoll/autopoll.8c ============== +if test -f 'uupoll/autopoll.8c' -a X"$1" != X"-c"; then + echo 'x - skipping uupoll/autopoll.8c (File already exists)' +else +echo 'x - extracting uupoll/autopoll.8c (Text)' +sed 's/^X//' << 'SHAR_EOF' > 'uupoll/autopoll.8c' && +.\" +.\" @(#)autopoll.8c 1.4 (incoahe) 5/09/1993 +.\" +.TH AUTOPOLL 8C "May 09, 1993" +.UC 6 +.SH NAME +autopoll \- automatic \s-1UUCP\s+1 file transfer supervisor +.SH SYNOPSIS +.B autopoll +[ +.BI options +] +.SH DESCRIPTION +file transfer requests placed by +.IR uucp (1) +or +.IR uux (1) +are handled by +.IR uucico (8C). +.IR uucico +will be invoked immediately by the above programs unless the \-r +option is given which queues the request for later processing. This +is typically done by entries in the +.IR crontab +table(s) which will invoke +.IR uucico. +.IR uucico +can also be invoked by +.IR uupoll (8C). +All methods have in common that there is no automatic retry by +.IR uucico +itself in case the call failed for some reason. +Either manual +intervention or some sort of scripts must be used to overcome this +limitation. +.PP +.IR Autopoll +can be used to automate up to a certain degree the task of rescheduling +a call. None of the standard programs already mentioned need to be +modified to get this working. Also not recommended (see BUGS section) +.IR uucico +may be an alias to +.IR autopoll +as all arguments passed to +.IR autopoll +will be copied verbatim to +.IR uucico. +In case this is done by link or other means the original +.I uucio +must still be available in a directory outside of the normal search path +otherwise +.I autopoll +can't do what it's intended to do and will form a loop. +.PP +When +.IR autopoll +is called thre will be a check on the \-s, \-S and \-f option to +see whether this +is a specific call or not. Also the \-S and the \-f option must be checked +to determine the type of call: honor any imposed wait for a site or not. +Any call to ourself or to an unknown site will be refused. The known sites +will be obtained by a call to +.IR uuname(1). +All other options will not be checked in any way. Next to this +.IR uucico +is called and the exit code is checked for a `1' which indicates that the call +failed for some reason whatsoever. A `0' exit code will be interpreted as +a success and +.IR autopoll +ends immediate. If the call seems to be unsuccessful a new call is scheduled +for any site whose .Status files have a retry period greater than 0. The +retry will be scheduled by means of placing an +.IR at +job at the time of the failing call plus any wait time given. For those +sites that have been called with either the \-f or \-S option the retry +time will be the time of the failing call plus 120 seconds. +.PP +In case the time calculated from the values found in a \.Status file is +lower than the current time, the current time plus 60 seconds will be taken +as the retry time. +.PP +A site will +.IR not +be automatically called again if one of the following +conditions is met: +.PP +\- +.IR uucico +is terminated by a signal +.PP +\- either fork() or exec() failed +.PP +\- the +.IR at +command failed for any reasons. +.PP +\- if no wait should be honored and the retry time is found to be zero. +(this may indicate a `Wrong time to call' condition. +.PP +There are other circumstances that may lead to not reschedule a call or +not to call +.IR uucico +at all, all of which should be accompanied by (a) self explanatory message(s). +.SH BUGS +\- invalid options will make +.IR uucico +fail. The exit code for this type is the same as for any other failure; this +can reschedule the call over and over again or never. +.PP +\- +.IR autopoll +may not work as expected when called with options other than \-r1, \-s, +\-S or \-f. +.PP +\- a rescheduled call may fail with `wrong time to call' the second time +but will be rescheduled again. The times to call won't be checked by +.IR autopoll +and the .Status file may not indicate this in case the \-c option is given. +.PP +\- in case the ..._DIR points to an invalid file a `Bus error' my pop up +during the `exec' call. +.PP +\- the `chat-timeout' value may have to be increased when using +.IR autopoll. +An indication to do that is that the call fails short after `CONNECT' +has been received with `Time out in chat script'. +.PP +\- the site names given will be checked aginst the output of +.I uuname +without any alias expansion done. +.PP +\- the text strings whithin the \.Status files will not be used to detect +a failing call. +.SH FILES +.nf +/usr/local/lib/uucp UUCP internal utilities +/usr/lib/uucp +/usr/local/bin UUCP internal utilities +/usr/bin +/usr/spool/uucp/.Status/ Status files for each site +/usr/spool/uucp/ UUCP spool area. one of its sub- +X directories will hold the null jobs. +/tmp/poll.log This file is present only if autopoll +X has been compiled to place the messages +X into a file. Otherwise all messages will +X go to stderr. The directory as well as +X the name may be different. +.fi +.SH SEE ALSO +uucp(1C), uux(1C), uucico(8C), uupoll(8C), uuname(1C), sort(1), uniq(1), +at(1) +SHAR_EOF +chmod 0444 uupoll/autopoll.8c || +echo 'restore of uupoll/autopoll.8c failed' +Wc_c="`wc -c < 'uupoll/autopoll.8c'`" +test 4718 -eq "$Wc_c" || + echo 'uupoll/autopoll.8c: original size 4718, current size' "$Wc_c" +fi +# ============= uupoll/autopoll.c ============== +if test -f 'uupoll/autopoll.c' -a X"$1" != X"-c"; then + echo 'x - skipping uupoll/autopoll.c (File already exists)' +else +echo 'x - extracting uupoll/autopoll.c (Text)' +sed 's/^X//' << 'SHAR_EOF' > 'uupoll/autopoll.c' && +/* ---------------------------------------------------------------------------* +X +X Name: autopoll +X +X Author: Klaus Dahlenburg <kdburg@incoahe.hanse.de> +X +X Status: Public domain +X +X Copyright: none; claiming it to be your work will adversly affect +X your image to be a good programmer. +X +X Function: Autopoll may be called just as uucico is called. The difference +X is that autopoll will call uucico and if the return code is +X not zero a check is made on the status files to see which site's +X call failed. Those sites will be called again at that time found +X in the status file plus any imposed wait. The next call will be +X scheduled via an at job which in turn is handled by cron. +X Atrun depends on the scheduling granularity of cron so the +X actual times may be later than planned. +X Autopoll will check the options -f and -s (-S) as well as the name +X of the site passed. All other options will be passed unchecked. +X The -f and -S options will indicate to autopoll that any wait +X to call a site should be ignored; if the call fails the next +X call to those sites will be at the current time plus 120 secs. +X When the time found plus any wait evaluates to a time that +X passed already the next call will be the current time plus 60 +X secs. The name of the site if given must be a valid one and not +X the host itself otherwise it will be ignored. +X +X Call: autopoll [ options ] +X +X all option that apply to uucico may be given and +X will be passed verbatim. See man uucico(8). +X +X Environment: NeXT 2.1+, Taylor UUCP-1.04+ +X +X I/O: stdin: unused. +X stdout: used only when ALOG_DIR is defined and the file +X can't be opened. It will be a single message to tell +X just that and the run is aborted. +X stderr: all messages go here. +X If ALOG_DIR is defined (see conf.h) all messages will +X be appended to a file autopoll.msglog in that +X directory; the file will be created automatically if +X necessary; a redirection is then no longer possible. +X Needs access to .Status files (see Comments later on). +X +X Called Programs: sort, uniq, uucico, uuname, at +X +X Compile: no special options are needed. Compiled with gcc 2.3.3 -O2. +X Compile with the supplied cc might produce erroneous code +X for the check options switch case 's' code: the break inside +X the first if (..) {... break} is ignored. +X +X Comments: - should run setuid UUCP or whatever userid is necessary to +X access (RDONLY) the .Status files and to run the programs +X named under "Called Programs" above. +X - No alias expansion is done on the given names for the +X check against uuname's output.. +X - Invalid arguments will yield in an exit code > 0 as do +X "normal" failures. It may therefore happen that a site +X is called at the intervals with the same invalid arguments. +X - "Wrong time to call" is not handled properly and may +X call the site at the intervals until the time ban is lifted. +X - human action is necessary as we can't distinguish between +X "normal" failures and "errors" such as wrong password, +X number to dial etc. The logs should be checked periodically. +X - if CICO_DIR points to a non existent program the run may +X end with signal 10: Bus Error. +X - is has been observed that uucico will time out with "Dial +X failed" when called via autopoll; setting chat-timeout to +X value of 40 cured that problem. +X - no rescheduling is done in case uucico fails and this +X is not reported in the .Status file, one should check +X the uucico log; this is to the fact that autopoll will +X not scan the uucico log. +*/ +X +X +#if !defined(lint) +static char rcsid[] = "$Id: uupoll.shar,v 1.1 1995/10/18 08:38:24 deraadt Exp $"; +#endif /* not lint */ +X +/* $Log: uupoll.shar,v $ +/* Revision 1.1 1995/10/18 08:38:24 deraadt +/* Initial revision +/* +/* Revision 1.2 1995/08/24 05:19:19 jtc +/* Upgraded to Taylor UUCP 1.06.1 (Thanks to John Kohl). +/* +X * Revision 2.8 1994/04/14 17:22:54 kdburg +X * corrected misspelled AT_OPTION +X * +X * Revision 2.7 1994/04/11 20:15:48 kdburg +X * major rework done; honor now some of the new option taht came with +X * uucp-1.05 +X * +X * Revision 2.6 1994/03/26 17:40:30 kdburg +X * added support for UNAME_DIR; cleanup of some code; adjusted code after +X * obtaining sitenames via popen() +X * +X * Revision 2.5 1993/07/07 16:49:02 kdburg +X * when used interactivly only the start msg is put into the msg-log +X * so far defined (UULOG) +X * +X * Revision 2.4 1993/06/26 16:17:51 kdburg +X * the -S option wasn't propagated to the command passed to the at pgm +X * +X * Revision 2.3 1993/05/25 12:05:01 kdburg +X * added error check on gettimeofday; added comment in the note section; +X * minor changes not affection code +X * +X * Revision 2.2 1993/05/17 20:47:05 kdburg +X * execution of at cmd also ok always said failed... +X * +X * Revision 2.1 1993/05/16 21:49:13 kdburg +X * changed exit() to _exit() in case the exec fails within child +X * +X * Revision 2.0 1993/05/16 14:12:05 kdburg +X * initial revision +X * */ +X +#define CAT 16 +#define SEVERE 8 +#define WARNING 4 +#define OK 0 +/* Boolean types */ +typedef int bool; +#undef TRUE +#undef FALSE +#define TRUE (1) +#define FALSE (0) +X +#include "conf.h" +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <pwd.h> +#include <unistd.h> +#include <sys/file.h> +#include <sys/time.h> +#include <sys/param.h> +#include <sys/wait.h> +X +#ifdef ALOG_FILE +X static char Msg_Log[] = ALOG_FILE; /* name of msglog filename */ +#endif +X +#ifdef UNAME_DIR +X static char subcmd[] = " | sort | uniq"; /* pipe that follows uuname */ +#else /* ! UNAME_DIR */ +X static char Sort[] = "uuname | sort | uniq"; /* default to obtain site names */ +#endif /*UNAME_DIR */ +X +#ifdef AT_OPTION +X static char at_opt[] = AT_OPTION; +#else +X static char at_opt[] = "-mc"; +#endif /* AT_OPTION */ +X +static char at_cmd[] = "at"; +static char cGrade[] = DEF_GRADE; /* grade as defined in conf.h */ +static char dGrade[] = "A"; /* use this if DEF_GRADE is invalid */ +static char Auto_Dir[] = AUTO_DIR; /* we live here */ +static char Cico_Dir[] = CICO_DIR; /* here lives cico */ +X +struct Sites { +X char name[MAXHOSTNAMELEN+1]; /* name of site as supplied by uuname */ +X char grade[1]; /* as passed or defaulted */ +X bool flag; /* TRUE: call this site only */ +X bool force; /* TRUE: -S or -f option given */ +X int stat_code; +X int stat_retries; +X long stat_lastcall; +X long stat_delay; +X char *stat_errtext; +}; +X struct Common_Stor { +X int maxtab; /* high-water-mark for site tab */ +X int Single_Site_Tab; /* entry into site tab for a site */ +X /* passed via -s or -S option */ +X bool force_any; /* TRUE: -f option without site */ +X bool one_site; /* TRUE: call for a specific site */ +X bool nodetach; /* TRUE: -D or --nodetach found */ +X bool ifwork; /* TRUE: -C or --ifwork found */ +X char *Grade; /* use this as grade for calls */ +X char *Poll_Pgm; /* our name without path */ +X char *called_as; /* but called by this name */ +X int our_pid; /* our process-id */ +X char *Uucico; /* cico's name without path */ +X char This_Site[MAXHOSTNAMELEN+1]; /* our site name */ +X char Single_Site[MAXHOSTNAMELEN+1]; /* name of site found as arg */ +X union wait *W_Stat; +X char *Usort; /* will hold uuname + subcmd */ +X struct passwd *pwd; +X struct timeval tp; +X struct timezone tzp; +X struct Sites Sitetab[SITE_MAX]; +X char mon[3]; +X int day, hh, mm, ss; +X char oname[24]; +X char jname[20]; +X char tstr[20]; +X char ctag[2]; +X char workf[300]; +X char call_args[300]; +X }; +X +/* copied from taylor uucp "uudefs.h" +X * +X **/ +X +/* The tstatus_type enumeration holds the kinds of status information +X we put in the status file. The order of entries here corresponds +X to the order of entries in the azStatus array. */ +enum tstatus_type +{ +X /* Conversation complete. */ +X STATUS_COMPLETE, +X /* Port unavailable. */ +X STATUS_PORT_FAILED, +X /* Dial failed. */ +X STATUS_DIAL_FAILED, +X /* Login failed. */ +X STATUS_LOGIN_FAILED, +X /* Handshake failed. */ +X STATUS_HANDSHAKE_FAILED, +X /* Failed after logging in. */ +X STATUS_FAILED, +X /* Talking to remote system. */ +X STATUS_TALKING, +X /* Wrong time to call. */ +X STATUS_WRONG_TIME, +X /* Number of status values. */ +X STATUS_VALUES +}; +X +/* ----end-- copied from taylor uucp "uudefs.h" */ +X +X +/* define the prototypes +X * */ +X +int set_mlog(FILE **seclog, struct Common_Stor *); +int get_sites(struct Common_Stor *); +int Call_Cico(int argc, char *argv[], struct Common_Stor *); +int get_args(int argc, char *argv[], struct Common_Stor *); +int Housekeeping(int argc, char *argv[], struct Common_Stor *); +int Chk_Status(int argc, char *argv[], +X struct timeval tcc, +X struct timezone tzcc, +X struct Common_Stor *); +int Check_Site(struct Common_Stor *); +int start_at(char *name, struct Common_Stor *); +void *storage(unsigned count, char *errloc, int *Rc, struct Common_Stor *); +X +extern int gethostname(char *name, int namelen); +extern int system(char *cmd); +extern int fork(); +extern int unlink(char *path); +extern void *malloc(size_t byteSize); +extern int execve(char *name, char *argv[], char *envp[]); +extern int execlp(char *name, char *arg0, ...); +extern int chmod(char *path, int mode); +extern int getuid(); +extern int getpid(); +extern int isatty(int); +extern char *ttyname(int); +extern void free(void *ptr); +#ifdef __STRICT_ANSI__ +extern FILE *popen(char *command, char *type); +extern int pclose(FILE *stream); +extern void _exit(int status); +#endif /* __STRICT_ANSI__ */ +#ifdef __STRICT_BSD__ +extern int fprintf(FILE *stream, const char *format, ...); +extern int fclose(FILE *stream); +extern char *strerror(int errnum); +extern int fflush(FILE *stream); +extern void exit(int status); +extern int fscanf(FILE *stream, const char *format, ...); +extern int sscanf(char *s, const char *format, ...); +#endif /* __STRICT_BSD__ */ +X +/* --------------------------------------------------------------------------*/ +/* Main */ +/* --------------------------------------------------------------------------*/ +X +int main(int argc, char *argv[]) +{ +X +X struct Common_Stor *sCom_Sto; +X int Maxrc = OK; /* Max err-code encountered so far */ +X int k = 0; +X +X if ( NULL == (sCom_Sto = malloc(sizeof(struct Common_Stor))) ) { +X fprintf(stderr,"%s: (C) malloc failed (%s). Reason: %i (%s)\n", +X AUTO_DIR,"Common_Stor",errno,strerror(errno)); +X exit (CAT); +X } +X +X Maxrc = Housekeeping(argc, argv, sCom_Sto); +X +/* If any errors popped up so far they are of such a nature that it is very +X * questionable to continue; so we better bail out in this case. +X */ +X if (Maxrc <= WARNING) { +X if ((sCom_Sto->W_Stat = (union wait *)storage (sizeof(union wait), +X "W_Stat",&Maxrc,sCom_Sto)) != NULL) { +X k = Call_Cico(argc, argv, sCom_Sto); +X Maxrc = Maxrc >= k ? Maxrc:k; +X free(sCom_Sto->W_Stat); +X sCom_Sto->W_Stat = NULL; +X } +X } +X k = gettimeofday(&sCom_Sto->tp, &sCom_Sto->tzp); +X fprintf(stderr,"%s: (I) ended with rc = %i on %s\n", +X sCom_Sto->called_as, +X Maxrc,k!=0 ? "time unavailable":ctime(&sCom_Sto->tp.tv_sec)); +X fclose(stderr); +X free(sCom_Sto); +X sCom_Sto = NULL; +X exit (Maxrc); +} +X +/* --------------------------------------------------------------------------*/ +/* Functions */ +/* --------------------------------------------------------------------------*/ +X +/* -------------------------------------------------------------------- +X * housekeeping +X */ +X +int Housekeeping(argc, argv, sCom_Sto) +X int argc; +X char *argv[]; +X struct Common_Stor *sCom_Sto; { +X +X FILE *seclog = NULL; +X int Rc = OK; +X int Rci = OK; /* intermediate rc as returnd by functions */ +X +X sCom_Sto->our_pid = getpid(); +X +/* +X * get our name sans path +X * */ +X +X sCom_Sto->called_as = argv[0] + strlen(*argv); +X for(;sCom_Sto->called_as >= argv[0] && *--sCom_Sto->called_as != '/';) +X ; +X sCom_Sto->called_as++; +X +/* if defined set up the name of the message log file otherwise +X * stderr will be used. Setup the cmd string to obtain all known sitenames +X * which will be sorted in ascending order with duplicates removed +X * */ +X +X Rc = set_mlog(&seclog, sCom_Sto); +X if (Rc > WARNING) +X return (Rc); +X +/* put out the started message including the time and the userid. +X * */ +X +X sCom_Sto->pwd = getpwuid(getuid()); +X +X if ((gettimeofday(&sCom_Sto->tp, &sCom_Sto->tzp)) != 0) { /* unacceptable error */ +X fprintf(stderr,"%s: (C) gettimeofday() failed. Reason: %i (%s)\n", +X sCom_Sto->called_as,errno,strerror(errno)); +X return (Rc >= CAT ? Rc:CAT); +X } +X +X if (seclog != NULL) { +X fprintf(seclog,"\n%s: (I) started by `%s' (%s) on %s", +X sCom_Sto->called_as, +X (sCom_Sto->pwd==NULL) ? "???":sCom_Sto->pwd->pw_name, +X ttyname(0), +X ctime(&sCom_Sto->tp.tv_sec)); +X fclose(seclog); +X } +X fprintf(stderr,"\n%s: (I) started by `%s' on %s", +X sCom_Sto->called_as, +X (sCom_Sto->pwd==NULL) ? "???":sCom_Sto->pwd->pw_name, +X ctime(&sCom_Sto->tp.tv_sec)); +X +/* set up the default grade +X * */ +X +X sCom_Sto->Grade = dGrade; /* set default for now */ +X if (strlen(cGrade) != 1) { +X fprintf(stderr,"%s: (W) grade %s invalid; default `%s' used\n", +X sCom_Sto->called_as,cGrade,sCom_Sto->Grade); +X Rc = Rc >= WARNING ? Rc:WARNING; +X } +X else +X sCom_Sto->Grade = cGrade; /* Ok, take the one from conf.h */ +X +/* get the program to actually call the site. This is normally UUCICO. +X * */ +X +X sCom_Sto->Uucico = Cico_Dir + strlen(Cico_Dir); +X for(;sCom_Sto->Uucico >= Cico_Dir && *--sCom_Sto->Uucico != '/';) +X ; +X sCom_Sto->Uucico++; +X +/* get the path to ourself. +X * */ +X +X sCom_Sto->Poll_Pgm = Auto_Dir + strlen(Auto_Dir); +X for(;sCom_Sto->Poll_Pgm >= Auto_Dir && *--(sCom_Sto->Poll_Pgm) != '/';) +X ; +X sCom_Sto->Poll_Pgm++; +X +/* obtain our sitename +X * */ +X +X if ((gethostname(sCom_Sto->This_Site,MAXHOSTNAMELEN+1)) != 0) { +X fprintf(stderr,"%s: (W) hostname could not be obtained\n", +X sCom_Sto->called_as); +X Rc = (Rc >= WARNING) ? Rc:WARNING; +X } +X +/* obtain all known sitenames +X * */ +X +X Rci = get_sites(sCom_Sto); +X Rc = Rci > Rc ? Rci:Rc; +X +/* check the arguments that we are called with +X * */ +X +X Rci = get_args(argc, argv, sCom_Sto); +X Rc = Rci > Rc ? Rci:Rc; +X +X return (Rc); +} +X +/* -------------------------------------------------------------------- +X * check all relevant arguments that have been passed to us. Those args +X * that may be needed for a recall will be copied to a workfield. +X * */ +X +int get_args(int argc, char *argv[], struct Common_Stor *sCom_Sto) { +X +X int j = 0; +X int Rc = OK; +X int Rci = OK; +X +X strcpy(sCom_Sto->Single_Site,""); +X sCom_Sto->force_any = FALSE; +X sCom_Sto->one_site = FALSE; +X sCom_Sto->nodetach = FALSE; +X +X strcpy(sCom_Sto->call_args,AUTO_DIR); /* specify complete path to us */ +X strcat(sCom_Sto->call_args," "); /* and separate by one space */ +X for (j=1;j<argc;j++) { +X if (strcmp(argv[j],"--nodetach") == 0 || +X strcmp(argv[j],"-D") == 0) { +X sCom_Sto->nodetach = TRUE; +X strcat(sCom_Sto->call_args,"-D "); +X continue; +X } +X if (strcmp(argv[j],"--force") == 0 || +X strcmp(argv[j],"-f") == 0) { +X strcat(sCom_Sto->call_args,"-f "); +X sCom_Sto->force_any = TRUE; +X continue; +X } +X if (strcmp(argv[j],"--ifwork") == 0 || +X strcmp(argv[j],"-C") == 0) { +X sCom_Sto->ifwork = TRUE; +X continue; +X } +X if ( strncmp(argv[j],"-s",2) == 0 || +X strncmp(argv[j],"-S",2) == 0 || +X strcmp(argv[j],"--system") == 0) { +X if (strncmp(argv[j],"-S",2) == 0) +X sCom_Sto->force_any = TRUE; +X +X if (strlen(argv[j]) == 2 || strcmp(argv[j],"--system") == 0) { +X j++; +X if (j>=argc) { +X fprintf(stderr,"%s: (E) System to call is missing\n", +X sCom_Sto->called_as); +X Rc = Rc >= SEVERE ? Rc:SEVERE; +X break; +X } +X else { +X strcpy(sCom_Sto->Single_Site,argv[j]); +X Rci = Check_Site(sCom_Sto); +X if (! Rci) { +X sCom_Sto->one_site = TRUE; /* specific call */ +X strcat(sCom_Sto->call_args,argv[j-1]); +X strcat(sCom_Sto->call_args," "); +X strcat(sCom_Sto->call_args,argv[j]); +X strcat(sCom_Sto->call_args," "); +X } +X } +X Rc = Rci <= Rc ? Rc:Rci; +X } +X else { +X strcpy(sCom_Sto->Single_Site,argv[j]+2); +X Rci = Check_Site(sCom_Sto); +X if (! Rci) { +X sCom_Sto->one_site = TRUE; /* specific call */ +X strcat(sCom_Sto->call_args,argv[j]); +X strcat(sCom_Sto->call_args," "); +X } +X Rc = Rci <= Rc ? Rc:Rci; +X } +X continue; +X } +X strcat(sCom_Sto->call_args,argv[j]); +X strcat(sCom_Sto->call_args," "); +X } /* end copy all arguments */ +X +X if (sCom_Sto->ifwork) { +X if (sCom_Sto->one_site) { +X strcat(sCom_Sto->call_args,"-C "); +X } +X else { +X fprintf(stderr,"%s: (W) no site given, '-C' option is ignored\n", +X sCom_Sto->called_as); +X sCom_Sto->ifwork = FALSE; +X Rc = Rc >= WARNING ? Rc:WARNING; +X } +X } +X +X if (! sCom_Sto->nodetach) { +X strcat(sCom_Sto->call_args,"-D "); +X } +X +X return (Rc); +} +X +/* -------------------------------------------------------------------- +X * call uucico or whatever programm is necessary to get connected +X */ +X +/* Start uucico and wait for completion. In case the return code is '0' +X * we're finished; otherwise we'll have to check the status files for any +X * non successful calls (retry time > 0). +X * Any such site will be called again at the current time plus any wait +X * Note: +X * If the '-D' or '--nodetach' option is missing, uucico will +X * detach immediate. The return-code is 0 in this case and therefore +X * we can't check whether the call is successful or not. No recall +X * is scheduled for such an invocation. If we however get control +X * to schedule a recall we silently add the '-D' option. To add +X * the '-D' option in any case may be undesirable for a specific +X * type of run. +X */ +X +int Call_Cico(int argc, char *argv[], struct Common_Stor *sCom_Sto) { +X +X int W_Ret = 0; +X int pid = 0; +X int Rc = OK; +X struct timeval tcc; +X struct timezone tzcc; +X +X if ((gettimeofday(&tcc, &tzcc)) != 0) { /* unacceptable error */ +X fprintf(stderr,"%s: (C) gettimeofday() failed. Reason: %i (%s)\n", +X sCom_Sto->called_as,errno,strerror(errno)); +X Rc = Rc >= CAT ? Rc:CAT; +X } +X +X if (Rc > WARNING) { +X return (Rc); +X } +X +X fflush(stderr); +X switch(pid = fork()) { +X case -1: +X fprintf(stderr,"%s: (C) could not fork(). Reason-code: %i (%s)\n", +X sCom_Sto->called_as,errno,strerror(errno)); +X return (CAT); +X case 0: +X if ((argv[0] = (char *)storage(strlen(sCom_Sto->Uucico)+1,"argv[0]", +X &Rc,sCom_Sto)) == NULL) { +X _exit (CAT); +X } +X strcpy(argv[0],sCom_Sto->Uucico); /* change name to be uucico */ +X execve(Cico_Dir, argv, NULL); +X fprintf(stderr,"%s: (C) could not start %s. Reason-code: %i (%s)\n", +X sCom_Sto->called_as, +X sCom_Sto->Uucico,errno,strerror(errno)); +X _exit (CAT); /* child: bail out */ +X default: +X fprintf(stderr,"%s: (I) starting %s [%d]\n\n", +X sCom_Sto->called_as,sCom_Sto->Uucico,pid); +X fflush(stderr); /* maybe we come behind uucico's output */ +X /* if any; it's a race condition */ +X W_Ret = wait(sCom_Sto->W_Stat); +X if (sCom_Sto->W_Stat->w_termsig == 0) { +X if (sCom_Sto->W_Stat->w_retcode == 0) { +X fprintf(stderr,"%s: (I) %s [%d] ended normally\n", +X sCom_Sto->called_as,sCom_Sto->Uucico,pid); +X return (OK); +X } +X if (sCom_Sto->W_Stat->w_retcode != CAT) { +X fprintf(stderr,"%s: (I) %s's log may contain further information !\n", +X sCom_Sto->called_as,sCom_Sto->Uucico); +X fprintf(stderr,"\n%s: (W) %s [%d] ended with rc = %i\n", +X sCom_Sto->called_as, +X sCom_Sto->Uucico,pid, +X sCom_Sto->W_Stat->w_retcode); +X return (Chk_Status(argc, argv, +X tcc, tzcc, sCom_Sto)); +X } +X else +X return (CAT); /* we where unable to exec */ +X } +X else { +X fprintf(stderr,"\n%s: (E) %s [%d] terminated by signal %i\n", +X sCom_Sto->called_as, +X sCom_Sto->Uucico, +X pid, +X sCom_Sto->W_Stat->w_termsig); +X return (SEVERE); +X } +X } /* switch (pid = fork()) */ +X return (OK); /* Never reached: silence the compiler */ +} +X +X +/* -------------------------------------------------------------------- +X * check the status after the call has completed and the return code +X * is > zero. The status is checked for all sites found via uuname or +X * for one site only (option -s, -S or --system given on call) +X */ +X +int Chk_Status(int argc, char *argv[], +X struct timeval tcc, +X struct timezone tzcc, +X struct Common_Stor *sCom_Sto) { +X +/* +X * For all sites found in Site_Tab their status files will be checked. +X * The table scan will be bypassed for a call to a specific site. +X * If the call failed the wait period is > 0. We will schedule an at-job +X * to be run at the time found + the delta. In case we find an old entry +X * where the time + delta is lower than the current time we'll advance +X * the current time by 60 secs. and use that value instead. +X * In case we are invoked to call a specific site and either the -f option or +X * the site was given as -S... indicating to disregard any wait, we'll +X * use the time found in the status file increased by 120 secs. +*/ +X +X FILE *infile; +X long secs, retries = 0; +X long add = 0; +X int errind = 0; +X int i = 0; +X int ecnt = 0; +X int recall_cnt = 0; +X char curr_site[MAXHOSTNAMELEN+11] = ""; /* keyword + sitename */ +X bool schedule = TRUE; /* FALSE: no more rescheduling: unspec. + force */ +X int Rc = WARNING; /* uucico got rc = 1 otherwise we were not here */ +X int Rs = 0; /* uucico' reason code from .Status file */ +X +/* +X * Note +X * We have to increase the sum of time and wait by at least one minute. +X * That is because this time denotes the earliest point *after* which +X * we may call again. +X * When a site is called at the wrong time the follwing actions are +X * taken: wait = 0 && ! force --> no further action (indicator: see log) +X * wait = 0 && force --> (W) message generated; no further action +X * wait > 0 && ! force --> normal scheduling at time + wait +X * wait > 0 && force --> normal scheduling at time+120 secs +X * We can't depend on the string "Wrong time to call" because the .Status +X * file may not be updated due to the -c switch. This may lead to a +X * situation where the site will be called over and over again while it's +X * still the wrong time. (No we don't want to go fishing for a message in +X * the uucp LOG!) +X * In case the -s, -S or --system option was given we will only +X * check that site and schedule a recall for it so far the +X * conditions are met. +X * In case the -C or --ifwork switch is given without naming a site a +X * the option is dropped and only an unspecific call is scheduled. +X * */ +X +X if (sCom_Sto->one_site) { +X i = sCom_Sto->Single_Site_Tab; +X if (strncmp(sCom_Sto->Sitetab[i].name, +X sCom_Sto->Single_Site, +X sizeof(sCom_Sto->Single_Site)) != 0) { +X fprintf(stderr,"%s: (C) internal index-error (%d): %s found: %s\n", +X sCom_Sto->called_as, +X i, +X sCom_Sto->Single_Site, +X sCom_Sto->Sitetab[i].name); +X Rc = Rc >= CAT ? Rc:CAT; +X return (Rc); /* break unconditionally */ +X } +X } +X +X for (i = sCom_Sto->Single_Site_Tab; i <= sCom_Sto->maxtab; i++) { +X sprintf(sCom_Sto->workf,"%s%s",STATUS_DIR,sCom_Sto->Sitetab[i].name); +X if ((infile=fopen(sCom_Sto->workf,"r")) == NULL) { +X ecnt++; +X fprintf(stderr,"%s: (W) no access to status file for: %s\n", +X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name); +X Rc = Rc >= WARNING ? Rc:WARNING; +X if (sCom_Sto->one_site) { +X break; +X } +X else { +X continue; +X } +X } +X +X fscanf(infile,"%d %d %ld %ld",&errind,&retries,&secs,&add); +X fclose(infile); +X +X /* +X * in case the .Status file is not updated and we have a call to +X * a specific site we try to give some clues of what went wrong +X * (we won't succeed in any case!) +X */ +X +X if (sCom_Sto->Sitetab[i].stat_lastcall == secs && sCom_Sto->one_site) { +X +X if (errind == 0 && retries == 0 && add == 0) +X break; +X +X if (errind > 0) { +X if (tcc.tv_sec <= (secs+add) && ! sCom_Sto->Sitetab[i].force) { +X fprintf(stderr,"%s: (W) retry time not reached for site: %s\n", +X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name); +X Rc = Rc >= WARNING ? Rc:WARNING; +X } +X else { +X fprintf(stderr,"%s: (E) maybe port/site unavailable site: %s\n", +X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name); +X Rc = Rc >= SEVERE ? Rc:SEVERE; +X } +X } +X else { +X if (sCom_Sto->one_site) { +X fprintf(stderr,"%s: (E) unknown error for call to site: %s\n", +X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name); +X Rc = Rc >= SEVERE ? Rc:SEVERE; +X } +X } +X fprintf(stderr,"%s: (W) no recall scheduled for site: %s\n", +X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name); +X break; /* bail out completely */ +X } +X +X if (sCom_Sto->Sitetab[i].stat_lastcall == secs) { +X if (sCom_Sto->one_site) +X break; +X else +X continue; +X } +X +X Rs = OK; /* if Rs is > WARNING we won't schedule a recall */ +X switch(errind) { +X case STATUS_COMPLETE: +X if (add != 0 || retries != 0) { +X fprintf(stderr,"%s: (E) unknown error for call to site: %s\n", +X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name); +X Rs = Rs >= SEVERE ? Rs:SEVERE; +X } +X break; +X case STATUS_PORT_FAILED: +X fprintf(stderr,"%s: (E) port was unavailable site: %s\n", +X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name); +X break; +X case STATUS_DIAL_FAILED: +X fprintf(stderr,"%s: (E) dail failed for site: %s\n", +X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name); +X break; +X case STATUS_LOGIN_FAILED: +X fprintf(stderr,"%s: (E) login for site: %s failed\n", +X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name); +X Rs = Rs >= SEVERE ? Rs:SEVERE; +X break; +X case STATUS_HANDSHAKE_FAILED: +X fprintf(stderr,"%s: (E) handshake failed site: %s\n", +X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name); +X break; +X case STATUS_FAILED: +X fprintf(stderr,"%s: (E) invalid status after login site: %s \n", +X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name); +X break; +X case STATUS_TALKING: +X break; +X case STATUS_WRONG_TIME: +X fprintf(stderr,"%s: (W) it's the wrong time to call site: %s\n", +X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name); +X Rs = Rs >= SEVERE ? Rs:SEVERE; +X break; +X default: +X fprintf(stderr,"%s: (E) unknown error for call to site: %s\n", +X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name); +X Rs = Rs >= SEVERE ? Rs:SEVERE; +X break; +X } +X Rc = Rs > Rc ? Rs:Rc; +X if (Rs > WARNING) { /* schedule a recall ? */ +X fprintf(stderr,"%s: (W) no recall scheduled for site: %s\n", +X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name); +X if (sCom_Sto->one_site) +X break; +X else +X continue; +X } +X +X if (add == 0) { +X fprintf(stderr,"%s: (W) no delay found for site: %s\n", +X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name); +X Rc = Rc >= WARNING ? Rc:WARNING; +X } +X +X +X if (! schedule) { +X recall_cnt += 1; +X continue; /* scheduling already done: unspec. + force */ +X } +X if ((gettimeofday(&sCom_Sto->tp, &sCom_Sto->tzp)) != 0) { +X fprintf(stderr,"%s: (C) gettimeofday() failed. Reason: %i (%s)\n", +X sCom_Sto->called_as,errno,strerror(errno)); +X fclose(infile); +X Rc = Rc >= CAT ? Rc:CAT; +X break; /* break unconditionally */ +X } +X +X if (sCom_Sto->force_any || sCom_Sto->Sitetab[i].force) { +X add = secs + 120; /* shorten the wait */ +X } +X else { /* ! force */ +X +/* +X * check for an already scheduled recall. For we don't keep +X * a file of already scheduled recalls the only way to recognize +X * this, is to check the current time against that of the .Stats file. +X * In case the current time is >= the .Stats-time + n-secs fuzz value +X * we assume (99.99% correctness) that we have already scheduled a recall +X * for this site. If this assumption is incorrect a call will be +X * scheduled on the next unspecific failing call. This check can't +X * be done for forced call because the .Stats will be updated. +X */ +X if (sCom_Sto->tp.tv_sec >= secs+2) { +X fprintf(stderr,"%s: (W) Retry time not reached for site: %s\n", +X sCom_Sto->called_as, +X sCom_Sto->Sitetab[i].name); +X Rc = Rc >= WARNING ? Rc:WARNING; +X if (sCom_Sto->one_site) +X break; +X else +X continue; +X } +X add += secs + 60; /* if not force then take the full wait */ +X } /* force */ +X +X if (sCom_Sto->tp.tv_sec >= add) { +X add = sCom_Sto->tp.tv_sec + 60; /* time < current time */ +X } +X +X sscanf(ctime(&add),"%*s %s %d %d:%d:%d",sCom_Sto->mon, +X &sCom_Sto->day, +X &sCom_Sto->hh, +X &sCom_Sto->mm, +X &sCom_Sto->ss); +X +X sprintf(sCom_Sto->oname,"/tmp/at.%d.%02d%02d%02d",sCom_Sto->our_pid, +X sCom_Sto->hh, +X sCom_Sto->mm, +X sCom_Sto->ss); +X if (! sCom_Sto->one_site) { +X strcpy(curr_site,"-s"); +X strcat(curr_site,sCom_Sto->Sitetab[i].name); +X } +X +X /* +X * If 'onesite' is FALSE and 'force' is TRUE +X * we will reschedule one unspecific call an let UUCICO decide +X * which site should be called (is there any work?) +X */ +X +X if ( ! sCom_Sto->one_site && sCom_Sto->force_any) { +X recall_cnt += 1; +X schedule = FALSE; +X continue; +X } +X strcat(sCom_Sto->call_args,curr_site); +X Rs = start_at(sCom_Sto->Sitetab[i].name, sCom_Sto); +X Rc = Rs >= Rc ? Rs:Rc; +X unlink(sCom_Sto->oname); +X if (Rc > SEVERE || sCom_Sto->one_site) +X break; +X } /* for (i = Single_Site_Tab; ...) */ +X +X if (ecnt > sCom_Sto->maxtab) { +X fprintf(stderr,"%s: (E) no access to status files; no scheduling done\n", +X sCom_Sto->called_as); +X Rc = Rc >= SEVERE ? Rc:SEVERE; +X } +X else { +X if (! schedule) { +X if (recall_cnt == 1) { +X strcat(sCom_Sto->call_args,curr_site); +X } +X Rs = start_at("any site", sCom_Sto); +X Rc = Rs >= Rc ? Rs:Rc; +X unlink(sCom_Sto->oname); +X } +X } +X return (Rc); +} +X +X /* +X * +X */ +X +int start_at(char *site, struct Common_Stor *sCom_Sto) { +X +FILE *outfile; +int W_Ret = 0; +int Rc = OK; +int pid = 0; +X +/* +X * if we can't open the workfile to be passed to AT we'll abandon +X * this site and set the rc accordingly +X * */ +X +X if ((outfile=fopen(sCom_Sto->oname,"w")) == NULL) { +X fprintf(stderr,"%s: (E) could not open workfile %s. No scheduling for: %s\n", +X sCom_Sto->called_as, +X sCom_Sto->oname, +X site); +X Rc = Rc >= SEVERE ? Rc:SEVERE; +X fclose(outfile); +X unlink(sCom_Sto->oname); +X return (Rc); /* bail out here */ +X } +X sprintf(sCom_Sto->jname,"at.%d.%02d%02d%02d",sCom_Sto->our_pid, +X sCom_Sto->hh, +X sCom_Sto->mm, +X sCom_Sto->ss); +X fprintf(outfile,"%s \n",sCom_Sto->call_args); +X sprintf(sCom_Sto->tstr,"%02d%02d",sCom_Sto->hh, +X sCom_Sto->mm); +X sprintf(sCom_Sto->ctag,"%d",sCom_Sto->day); +X fclose(outfile); +X if ((chmod(sCom_Sto->oname,00644)) != 0) { +X fprintf(stderr,"%s: (W) chmod to %s failed. Reason_code: %i (%s)\n", +X sCom_Sto->called_as, +X sCom_Sto->oname, +X errno, +X strerror(errno)); +X Rc = Rc >= WARNING ? Rc:WARNING; +X } +X +X switch (pid = fork()) { +X case -1: +X fprintf(stderr,"%s: (C) could not fork(). Reason-code: %i (%s)\n", +X sCom_Sto->called_as,errno,strerror(errno)); +X return (Rc >= CAT ? Rc:CAT); +X case 0: +X if (*at_opt == '\0') +X execlp(at_cmd, at_cmd, sCom_Sto->tstr, +X sCom_Sto->mon, sCom_Sto->ctag, +X sCom_Sto->oname, 0); +X else +X execlp(at_cmd, at_cmd, at_opt, sCom_Sto->tstr, +X sCom_Sto->mon, sCom_Sto->ctag, +X sCom_Sto->oname, 0); +X +X fprintf(stderr,"%s: (C) could not start AT-cmd. Reason-code: %i (%s)\n", +X sCom_Sto->called_as, +X errno,strerror(errno)); +X _exit (CAT); /* child: bail out */ +X default: +X fprintf(stderr,"%s: (I) at [%d] started. Job name: %s\n", +X sCom_Sto->called_as, +X pid, +X sCom_Sto->jname); +X W_Ret = wait(sCom_Sto->W_Stat); +X if (sCom_Sto->W_Stat->w_termsig == 0) { +X if (sCom_Sto->W_Stat->w_retcode != 0) { +X if (sCom_Sto->W_Stat->w_retcode != CAT) { +X fprintf(stderr,"%s: (E) at-cmd failed for some reason\n", +X sCom_Sto->called_as); +X Rc = Rc >= SEVERE ? Rc:SEVERE; +X } +X else { +X Rc = Rc >= CAT ? Rc:CAT; +X } +X +X fprintf(stderr,"%s: (I) at [%d] ended with rc = %i\n", +X sCom_Sto->called_as, +X pid, +X sCom_Sto->W_Stat->w_retcode); +X /* bail out in case wait returned > SEVERE */ +X if (Rc > SEVERE) { +X return (Rc); +X } +X } +X else { +X fprintf(stderr,"%s: (I) at-cmd [%d] ended normally\n", +X sCom_Sto->called_as, +X pid); +X } +X } +X else { +X fprintf(stderr,"%s: (E) at [%d] terminated by signal %i\n", +X sCom_Sto->called_as, +X pid, +X sCom_Sto->W_Stat->w_termsig); +X Rc = Rc >= SEVERE ? Rc:SEVERE; +X } +X } /* switch (pid = fork()) */ +X return (Rc); +} +/* ----------------------------------------------------------------- +X * check the site passed via -s or -S option to be a valid one and +X * not to be our hostname. +X * */ +X +int Check_Site(struct Common_Stor *sCom_Sto) { +X +X int i,j = 0; +X sCom_Sto->Single_Site_Tab = 0; +X if (strcmp(sCom_Sto->Single_Site,sCom_Sto->This_Site) == 0) { +X fprintf(stderr,"%s: (E) won't call *ourself* %s\n", +X sCom_Sto->called_as,sCom_Sto->Single_Site); +X return(SEVERE); +X } +X for(i=0;i<=sCom_Sto->maxtab;i++) { +X if ((j=strcmp(sCom_Sto->Sitetab[i].name,sCom_Sto->Single_Site)) >= 0) { +X break; +X } +X } +X if (j != 0) { +X fprintf(stderr,"%s: (E) unknown site: %s\n", +X sCom_Sto->called_as,sCom_Sto->Single_Site); +X return(SEVERE); +X } +X sCom_Sto->Single_Site_Tab = i; +X sCom_Sto->Sitetab[i].flag = TRUE; +X if (sCom_Sto->force_any) { +X sCom_Sto->Sitetab[i].force = TRUE; +X sCom_Sto->force_any = FALSE; +X } +X return(OK); +} +X +X /* ------------------------------------------------------------------ +X * storage - get some memory +X */ +X +void *storage(unsigned count, +X char *location, +X int *Rc, +X struct Common_Stor *sCom_Sto) +{ +X void *p; +X +X if( NULL == (p= malloc(count)) ) { +X fprintf(stderr,"%s: (C) malloc failed (%s). Reason: %i (%s)\n", +X sCom_Sto->called_as,location,errno,strerror(errno)); +X *Rc = *Rc >= CAT ? *Rc:CAT; +X } +X return p; +} +X +/* ------------------------------------------------------------------ +X * if defined open the message log file otherwise all mesages will go +X * to stderr. If UNAME_DIR is defined construct the command to be +X * passed to popen(); if undefined the deafult will be used +X * */ +X +int set_mlog(FILE **seclog, struct Common_Stor *sCom_Sto) { +X +X int Rc = 0; +X +#ifdef ALOG_FILE +X if (!isatty(0)) { +X if ((freopen(Msg_Log,"a",stderr)) == NULL) { +X fprintf(stdout,"%s: (C) Could not open msglog: %s\n", +X sCom_Sto->called_as,Msg_Log); +X return (Rc >= CAT ? Rc:CAT); +X } +X } +X else { +X if ((*seclog = fopen(Msg_Log,"a")) == NULL) { +X fprintf(stderr,"%s: (C) Could not open msglog: %s\n", +X sCom_Sto->called_as,Msg_Log); +X return (Rc >= CAT ? Rc:CAT); +X } +X } +#endif /* ALOG_FILE */ +X +/* set up the pipe together with the complete path to uuname */ +X +#ifdef UNAME_DIR +X if ((sCom_Sto->Usort = (char *)storage (sizeof(UNAME_DIR)+sizeof(subcmd), +X "Sort",&Rc, sCom_Sto)) != NULL) { +X strncpy(sCom_Sto->Usort,UNAME_DIR,strlen(UNAME_DIR)); /* paste in the path */ +X strcat(sCom_Sto->Usort,subcmd); /* chain the pipe to it */ +X } +#else /* ! UNAME_DIR */ +X sCom_Sto->Usort = &Sort; /* set pointer to uuname + sort */ +#endif /* UNAME_DIR */ +X +X return (Rc); +} +X +/* ------------------------------------------------------------------ +X * obtain all active sitenames +X * */ +X +int get_sites(struct Common_Stor *sCom_Sto) { +X +X int i = 0; +X int n; +X int Rc = 0; +X FILE *infile, *statsfile; +X +X if ((infile=popen(sCom_Sto->Usort,"r")) != NULL) { +X while(fgets(sCom_Sto->Sitetab[i].name,MAXHOSTNAMELEN+1,infile)) { +X if (i > SITE_MAX) { /* let'm run so that we can give */ +X i++; /* the user some guidance */ +X continue; /* we'll tell the user later on */ +X } +X n = strlen(sCom_Sto->Sitetab[i].name)-1; /* offset: next to last char */ +X sCom_Sto->Sitetab[i].name[n] = '\0'; /* strip trailing newline */ +X sCom_Sto->Sitetab[i].flag = FALSE; /* TRUE: poll this site only*/ +X sCom_Sto->Sitetab[i].force = FALSE; /* TRUE: force call */ +X strcpy(sCom_Sto->Sitetab[i].grade,sCom_Sto->Grade); +X sprintf(sCom_Sto->workf,"%s%s",STATUS_DIR,sCom_Sto->Sitetab[i].name); +X if ((statsfile=fopen(sCom_Sto->workf,"r")) == NULL) { +X fprintf(stderr,"%s: (W) no access to status file for: %s\n", +X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name); +X Rc = Rc >= WARNING ? Rc:WARNING; +X } +X else { +X fscanf(statsfile,"%d %d %ld %ld %s", +X &sCom_Sto->Sitetab[i].stat_code, +X &sCom_Sto->Sitetab[i].stat_retries, +X &sCom_Sto->Sitetab[i].stat_lastcall, +X &sCom_Sto->Sitetab[i].stat_delay, +X sCom_Sto->workf); +X +X fclose(statsfile); +X if ((sCom_Sto->Sitetab[i].stat_errtext = +X (char *)storage (sizeof(sCom_Sto->workf), +X "stat_errtext",&Rc, sCom_Sto)) == NULL) { +X Rc = Rc >= WARNING ? Rc:WARNING; +X } +X else +X strcpy(sCom_Sto->Sitetab[i].stat_errtext,sCom_Sto->workf); +X } +X sCom_Sto->maxtab = i++; /* set high-water-mark */ +X } +X if (ferror(infile) != 0) { +X fprintf(stderr,"%s: (E) fgets() for sitenames failed reason-code: %i (%s)\n", +X sCom_Sto->called_as,errno,strerror(errno)); +X Rc = Rc >= SEVERE ? Rc:SEVERE; +X } +X pclose(infile); +X +X /* +X * check for an empty table (strange but possible) +X */ +X +X if (sCom_Sto->maxtab == 0) { +X fprintf(stderr,"%s: (E) could not obtain sitenames.\n", +X sCom_Sto->called_as); +X Rc = Rc >= SEVERE ? Rc:SEVERE; +X } +X else { +X +X /* in case the internal table overflows we'll now give notice and tell +X * the user by which amount the table has to be increased to hold all +X * site-names +X */ +X +X if (i > SITE_MAX) { +X fprintf(stderr,"%s: (E) number of sites > internal tab\n", +X sCom_Sto->called_as); +X fprintf(stderr,"%s: (E) increase SITE_MAX to >= %d and recompile\n", +X sCom_Sto->called_as,i); +X Rc = Rc >= SEVERE ? Rc:SEVERE; +X } +X } /* sCom_Sto->maxtab == 0 */ +X +X } +X else /* infile == NULL */ +X { +X fprintf(stderr,"%s: (E) could not sort sitenames. Reason-code: %i (%s)\n", +X sCom_Sto->called_as,errno,strerror(errno)); +X Rc = Rc >= SEVERE ? Rc:SEVERE; +X +X } /* if ((infile=popen(sCom_Sto->Usort,"r")) ... */ +X +X return (Rc); +} +SHAR_EOF +chmod 0444 uupoll/autopoll.c || +echo 'restore of uupoll/autopoll.c failed' +Wc_c="`wc -c < 'uupoll/autopoll.c'`" +test 44031 -eq "$Wc_c" || + echo 'uupoll/autopoll.c: original size 44031, current size' "$Wc_c" +fi +# ============= uupoll/conf.h ============== +if test -f 'uupoll/conf.h' -a X"$1" != X"-c"; then + echo 'x - skipping uupoll/conf.h (File already exists)' +else +echo 'x - extracting uupoll/conf.h (Text)' +sed 's/^X//' << 'SHAR_EOF' > 'uupoll/conf.h' && +#ifndef CONF +X #define CONF +X +/* $Id: uupoll.shar,v 1.1 1995/10/18 08:38:24 deraadt Exp $ */ +/* $Log: uupoll.shar,v $ +/* Revision 1.1 1995/10/18 08:38:24 deraadt +/* Initial revision +/* +/* Revision 1.2 1995/08/24 05:19:19 jtc +/* Upgraded to Taylor UUCP 1.06.1 (Thanks to John Kohl). +/* +X * Revision 1.9 1994/04/14 17:24:58 kdburg +X * added comment to the AT_OPTION +X * +X * Revision 1.8 1994/03/26 17:41:06 kdburg +X * the location of uuname can now be specified. This was added due to +X * the fact that cron (NeXT 3.2 and +) now obeys the path that was active +X * during boot (either /.path or set within /etc/rc) so autopoll/uupoll +X * always got the wrong uuname when called direct fron cron. This is +X * not true when called via a script that does a 'su - user -c ...' +X * +X * Revision 1.7 1993/06/26 16:21:47 kdburg +X * default location for logfiles changed +X * +X * Revision 1.6 1993/05/14 22:32:05 kdburg +X * change to HAVE_SPOOLDIR_TAYLOR +X * +X * Revision 1.5 1993/05/09 13:16:53 kdburg +X * make have-autopoll the default +X * +X * Revision 1.4 1993/05/08 23:17:34 kdburg +X * cleanup and to reflect changes made to autopoll/uupoll +X * +X * Revision 1.3 1993/04/29 10:46:34 kdburg +X * added def for STATUS_DIR +X * +X * Revision 1.2 1993/04/27 15:31:47 kdburg +X * rearranged the defs; changed LOG_DIR to ALOG_DIR in case uupoll +X * will have one too; we need then eventually 2 different dirs. +X * +X * Revision 1.1 1993/04/26 21:20:12 kdburg +X * Initial revision +X * */ +X +/* --------- combined config file for uupoll and autopoll */ +/* --------- change the following defines to meet your needs */ +X +/* define the default grade to be inserted into the pollfile name */ +#define DEF_GRADE "A" +X +/* Define the complete path to the uuname program. +X * If undefined we'll use just the name 'uuname' to call it +X * */ +#define UNAME_DIR "/usr/local/bin/uuname" +X +/* define the path to the directory which does contain uucico */ +#define CICO_DIR "/usr/local/lib/uucp/uucico" +X +/* define the path to the directory which holds all the uucp files. +X * We'll place the poll file in one of it's subdirectories +X * */ +#define SPOOL_DIR "/usr/spool/uucp" +X +/* at least one of the follwing must be defined To use the second or +X * third set of definitions, change the ``#if 1'' to ``#if 0'' +X * and change the appropriate ``#if 0'' to ``#if 1''. +X * */ +#if 0 +#define HAVE_SPOOLDIR_BSD +#endif +#if 0 +#define HAVE_SPOOLDIR_HDB +#endif +#if 1 +#define HAVE_SPOOLDIR_TAYLOR +#endif +X +/* define the maximum number of sites in your config or L.sys */ +#define SITE_MAX 100 +X +/* define the path to the directory which is to contain the +X * message log created by uupoll and the file name itself. +X * change the ``#if 1'' to ``#if 0'' to have the messages on stderr +X * */ +#if 1 +#define ULOG_FILE "/Logfiles/poll.log" +#endif +X +/* change if to 0 if you don't have autopoll installed. */ +#if 1 +#define AUTO_POLL +#endif +X +/* The following defs are irrelevant if you don't have autopoll */ +X +/* define the options to be given to the at cmd (-s -c -m). The default +X * is shown (use csh and send mail after execution) if AT_OPTION is +X * undefined +X * */ +#define AT_OPTION "-mc" +X +/* Define the complete path to the autopoll program. +X * This will assure that we get the one we want +X * The path must be the same as given in Makefile (lbindir) +X * */ +#define AUTO_DIR "/usr/local/lib/uucp/autopoll" +X +/* define the path to the directory which is to contain the +X * message log created by autopoll and the file name itself. +X * change the ``#if 1'' to ``#if 0'' to have the messages on stderr +X * */ +#if 1 +#define ALOG_FILE "/Logfiles/poll.log" +#endif +X +/* define the full path to the directory which holds the status files +X * The name should be given *except* the sitename. A trailing `/' if any +X * must be given. +X * Example: /usr/spool/uucp/.Status/sys.sitename +X * then specify STATUS_DIR as +X * "/usr/spool/uucp/.Status/sys." +X * */ +#define STATUS_DIR "/usr/spool/uucp/.Status/" +#endif +SHAR_EOF +chmod 0444 uupoll/conf.h || +echo 'restore of uupoll/conf.h failed' +Wc_c="`wc -c < 'uupoll/conf.h'`" +test 3884 -eq "$Wc_c" || + echo 'uupoll/conf.h: original size 3884, current size' "$Wc_c" +fi +# ============= uupoll/uupoll.8c ============== +if test -f 'uupoll/uupoll.8c' -a X"$1" != X"-c"; then + echo 'x - skipping uupoll/uupoll.8c (File already exists)' +else +echo 'x - extracting uupoll/uupoll.8c (Text)' +sed 's/^X//' << 'SHAR_EOF' > 'uupoll/uupoll.8c' && +.\" Copyright (c) 1986 Regents of the University of California. +.\" All rights reserved. The Berkeley software License Agreement +.\" specifies the terms and conditions for redistribution. +.\" +.\" @(#)uupoll.8c 6.1 (Berkeley) 4/24/86 +.\" @(#)uupoll.8c 1.11 (incoahe) 5/09/1993 +.\" +.TH UUPOLL 8C "Mai 09, 1993" +.UC 6 +.SH NAME +uupoll \- poll a remote \s-1UUCP\s+1 site +.SH SYNOPSIS +.B uupoll +[ +.BI \-g grade +] [ +.B \-n +] [ +.B \-x +] +.I system ... ... +.SH SUMMARY +This version of +.IR uupoll +can be used to fully replace the vendor supplied +.IR uupoll +that comes with the NeXTStep OS. The original version (up to 3.1) had a +X bug in that +X an unknown site given as argument would yield in a `Bus error' condition. +Using any other type of UUCP like Taylor-UUCP with the option of having +a different file structure as well as a different L.sys will therefore +make it necessary to do maintenance to the (unused) L.sys as well to keep +.IR uupoll +going. This one has been programmed from scratch due to the fact that no +source code was available. Some enhancements have been incorporated into +this version: +.PP +\- the default grade may now be compiled different from `A'. +.PP +\- the options may now be given in any order and the \-g option may be given +more than once. Any option will be used immediately when encountered and +will stay in effect unless reset; this does not apply to the \-x and \-n +option which can't be reset. The processing of options is guaranteed to be +from left to right so that some grouping may be achieved (see below). +.PP +\- +.IR uupoll +may be used to call any program instead of +.IR uucico +namely +.IR autopoll +to ease the task of rescheduling a failed call. +.SH DESCRIPTION +.I Uupoll +is used to force a poll of a remote system. It queues a null job for the +remote system, unless the \-x option has been given, and then invokes +either +.IR uucico (8C) +or +.IR autopoll (8C) +or any other program depending on how +.IR uupoll +is customized. If used in conjunction with +.IR autopoll +the latter will then invoke +.IR uucico. +.SH OPTIONS +The following options are available: +.TP 8 +.BI \-g grade +Only send jobs of grade +.I grade +or higher on this call. The +.I grade +stays in effect until it is changed by a different \-g option. +.TP 8 +.B \-n +Queue the null job, but do not invoke the program that actually calls +the named site(s). +The \-n option once given will apply to all sites following to the +.IR right +of it. +.TP 8 +.B \-x +Do not place a null job for all following sites. This option must be given +before the \-n option. The \-n option will nullify this. Any grade in effect +will not be honored because +.I uucico (Taylor) +does not carry the \-g option at the moment. +.PP +.I Uupoll +is usually run by +.IR cron (5) +or by a user who wants to hurry a job along. A typical entry in +.I crontab +could be: +.PP +.nf +X 0 0,8,16 * * * uucp /usr/bin/uupoll ihnp4 +X 0 4,12,20 * * * uucp /usr/bin/uupoll ucbvax +.fi +This will poll +.B ihnp4 +at midnight, 0800, and 1600, and +.B ucbvax +at 0400, noon, and 2000. +.PP +If the local machine is already running +.I uucico +every +hour and has a limited number of outgoing modems, a better approach +might be: +.PP +.nf +X 0 0,8,16 * * * uucp /usr/bin/uupoll -n ihnp4 +X 0 4,12,20 * * * uucp /usr/bin/uupoll -n ucbvax +X 5 * * * * uucp /usr/lib/uucp/uucico -r1 -D -C +.fi +This will queue null jobs for the remote sites at the top of the hour; they +will be processed by +.I uucico +when it runs five minutes later (the -C option apply to Taylor +uucp-1.05 only, the -D option applies to Talor uucp-1.04 and up) +.SH EXTENDED options +An example of the options and how they interact is given below. The working +order while processing the options is left to right: +.nf +X uupoll -gC site1 -gB site2 -x site3 -n -gA site4 site5 +.fi +.PP +this poll will: +.PP +- call immediate site1 with grade C or higher and will place a null job +.PP +- call immediate site2 with grade B or higher and will place a null job +.PP +- call immediate site3 with grade B or higher without placing a null job +.PP +- just placing a null job for site4 and site5 with grade A or higher. These +sites will be called at the next regular schedule. +.SH BUGS +When more than one site is given on the command line and no \-n option is +given there will be an immediate invocation of +.IR uucico +or +.IR autopoll +for +.IR all +sites given. That may lead to a `No port available' condition. +.SH FILES +.ta \w'/usr/spool/uucp/ 'u +.nf +/etc/uucp/ UUCP internal files/utilities +/usr/spool/uucp/ Spool directory +/tmp/poll.log This file is present only if uupoll has been +X compiled to place the messages into a file. +X Otherwise all messages will go to stderr. +X The directory as well as the name may be +X different. The name may be defined at compile time. +.fi +.SH SEE ALSO +uucp(1C), uux(1C), uucico(8C), autopoll(8C) +SHAR_EOF +chmod 0444 uupoll/uupoll.8c || +echo 'restore of uupoll/uupoll.8c failed' +Wc_c="`wc -c < 'uupoll/uupoll.8c'`" +test 4787 -eq "$Wc_c" || + echo 'uupoll/uupoll.8c: original size 4787, current size' "$Wc_c" +fi +# ============= uupoll/uupoll.c ============== +if test -f 'uupoll/uupoll.c' -a X"$1" != X"-c"; then + echo 'x - skipping uupoll/uupoll.c (File already exists)' +else +echo 'x - extracting uupoll/uupoll.c (Text)' +sed 's/^X//' << 'SHAR_EOF' > 'uupoll/uupoll.c' && +/* ---------------------------------------------------------------------------* +X +X Name: uupoll +X +X Author: Klaus Dahlenburg <kdburg@incoahe.hanse.de> +X +X Status: Public domain +X +X Copyright: none +X +X Funktion: The main intention behind this program was to get a full +X replacement of the uupoll supplied by NeXT when using an +X UUCP or a file structure that is different from that hardwired +X config in NeXT's uupoll. The lack of source made it impossible +X to modify the supplied uupoll. +X +X Call: uupoll [-n] [-x] [-g[A | 0-9,A-Z,a-z]] site ... +X +X -n just place a poll file but do not call uucico; +X This option can be given only once. +X -x meaningful only for sites not affected by the -n +X option. It prevents the creation of a poll file; +X the default is to place one. In case the poll fails +X there will be no attempt to poll those sites on +X the next general (unspecific) poll. If using +X autopoll the site will be called at the next + 1 +X run of autopoll. +X -g any grade may be given to meet the criteria for +X a successful poll. The default being specified +X in conf.h (A). +X This option may be given individually for each +X site to call. +X site the name of the site to be called. As many sites +X as necessary may be specified separated by at least +X one blank. +X Note: any site will be called with the options currently in +X effect. The working order is left to right. Example: +X uupoll -gQ site1 site2 -gZ site3 -n site4 +X site1 and site2 will be called immediate with grade Q +X site3 will be called immediate with grade Z. Site4 will +X have a poll file created with grade Z. +X +X Environment: NeXT 2.1 +X +X Called Programs: sort, uniq, uucico (or autopoll), uuname +X +X Compile: no special options are needed +X +X Comments: - should run setuid UUCP or whatever userid is necessary to +X write to the spool directory with the proper ownership of +X the files and to run uucico. +X - No alias expansion is done on the given names. +*/ +X +#if !defined(lint) +static char rcsid[] = "$Id: uupoll.shar,v 1.1 1995/10/18 08:38:24 deraadt Exp $"; +#endif /* not lint */ +X +/* $Log: uupoll.shar,v $ +/* Revision 1.1 1995/10/18 08:38:24 deraadt +/* Initial revision +/* +/* Revision 1.2 1995/08/24 05:19:19 jtc +/* Upgraded to Taylor UUCP 1.06.1 (Thanks to John Kohl). +/* +X * Revision 2.7 1994/04/14 17:22:04 kdburg +X * major rework done +X * +X * Revision 2.6 1994/03/26 17:38:41 kdburg +X * added support for UNAME_DIR; cleanup of some code; adjusted code after +X * obtaining sitenames via popen() +X * +X * Revision 2.5 1994/03/24 19:01:24 kdburg +X * some minor changes; some calls had their rc not checked +X * +X * Revision 2.4 1993/07/08 07:56:26 kdburg +X * befor invoking autopoll stdin is now closed to avoid blocking of +X * terminal +X * +X * Revision 2.3 1993/07/05 19:43:00 kdburg +X * when used interactivly only the start msg is put into the msg-log +X * so far defined (UULOG) +X * +X * Revision 2.2 1993/05/20 18:50:52 kdburg +X * no execute permission to the poll-pgm (uucico/autopoll) was not +X * reflected in the log; when to start message was not given when -x +X * option was present +X * +X * Revision 2.1 1993/05/16 21:48:15 kdburg +X * changed exit() to _exit() in case the exec fails within child +X * +X * Revision 2.0 1993/05/16 14:11:04 kdburg +X * initial revision +X * */ +X +#define CAT 16 +#define SEVERE 8 +#define WARNING 4 +#define OK 0 +#define P_MODE 00647 /* file-mode for poll-file */ +/* Boolean types */ +typedef int bool; +#undef TRUE +#undef FALSE +#define TRUE (1) +#define FALSE (0) +X +#include "conf.h" +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <sys/file.h> +#include <sys/param.h> +#include <pwd.h> +#include <sys/time.h> +X +#define X_OK 1 /* access: executable ? */ +X +#ifdef ALOG_FILE +X static char Msg_Log[] = ALOG_FILE; /* name of msglog filename */ +#endif +X +#ifdef UNAME_DIR +X static char subcmd[] = " | sort | uniq"; /* pipe that follows uuname */ +#else /* ! UNAME_DIR */ +X static char Sort[] = "uuname | sort | uniq"; /* default to obtain site names */ +#endif /*UNAME_DIR */ +X +static char cGrade[] = DEF_GRADE; /* grade as defined in conf.h */ +static char dGrade[] = "A"; /* use this if DEF_GRADE is invalid */ +#ifdef AUTO_POLL +X static char Auto_Dir[] = AUTO_DIR; /* autopoll lives here */ +#else +X static char Cico_Dir[] = CICO_DIR; /* and here lives cico */ +#endif /* AUTO_POLL */ +X +struct Sites { +X char name[MAXHOSTNAMELEN+1]; /* name of site as supplied by uuname */ +X char grade[1]; /* as passed or defaulted */ +X bool flag; /* TRUE this site should be polled */ +X int asap; /* 1 without -n; 2 with -x option */ +}; +X struct Common_Stor { +X int maxtab; /* high-water-mark for site tab */ +X char *Grade; /* use this as grade for calls */ +X char *Poll_Pgm; /* our name without path */ +X char *called_as; /* but called by this name */ +X int our_pid; /* our process-id */ +X char *Uucico; /* cico's name without path */ +X char This_Site[MAXHOSTNAMELEN+1]; /* our site name */ +X char System[MAXHOSTNAMELEN+1]; /* intermediate to hold sitename */ +X char *Usort; /* will hold uuname + subcmd */ +X struct passwd *pwd; +X struct timeval tp; +X struct timezone tzp; +X struct Sites Sitetab[SITE_MAX]; +X char workf[300]; +X }; +X +/* define the prototypes +X * */ +X +int set_mlog(FILE **seclog, struct Common_Stor *); +int get_sites(struct Common_Stor *); +int Check_Args(int argc, char *argv[], struct Common_Stor *); +int Housekeeping(int argc, char *argv[], struct Common_Stor *); +int Call_Site(struct Common_Stor *); +void *storage(unsigned count, char *errloc, int *Rc, struct Common_Stor *); +X +extern int getpid(); +extern void free(void *ptr); +extern int access(char *path, int mode); +extern int gethostname(char *name, int namelen); +extern int system(char *cmd); +extern int fork(); +extern int execlp(char *name, char *arg0, ...); +extern void *malloc(size_t byteSize); +extern int getuid(); +extern int isatty(int); +extern char *ttyname(int); +extern int open(char *path, int flags, int mode); +extern int close(int fd); +#ifdef __STRICT_ANSI__ +extern FILE *popen(char *command, char *type); +extern int pclose(FILE *stream); +extern void _exit(int status); +#endif /* __STRICT_ANSI__ */ +#ifdef __STRICT_BSD__ +extern int fprintf(FILE *stream, const char *format, ...); +extern int fclose(FILE *stream); +extern char *strerror(int errnum); +extern int fflush(FILE *stream); +extern void exit(int status); +#endif /* __STRICT_BSD__ */ +X +/* --------------------------------------------------------------------------*/ +/* Main */ +/* --------------------------------------------------------------------------*/ +X +int main(int argc, char *argv[]) +{ +X +X struct Common_Stor *sCom_Sto; +X int Maxrc = OK; /* Max err-code encountered so far */ +X int k = 0; +X +X if ( NULL == (sCom_Sto = malloc(sizeof(struct Common_Stor))) ) { +X fprintf(stderr,"%s: (C) malloc failed (%s). Reason: %i (%s)\n", +X argv[0],"Common_Stor",errno,strerror(errno)); +X exit (CAT); +X } +X +X Maxrc = Housekeeping(argc, argv, sCom_Sto); +X +/* If any errors popped up so far they are of such a nature that it is very +X * questionable to continue; so we better bail out in this case. +X */ +X if (Maxrc <= WARNING) { +X k = Call_Site(sCom_Sto); +X Maxrc = Maxrc >= k ? Maxrc:k; +X } +X k = gettimeofday(&sCom_Sto->tp, &sCom_Sto->tzp); +X fprintf(stderr,"%s: (I) ended with rc = %i on %s\n", +X sCom_Sto->called_as, +X Maxrc,k!=0 ? "time unavailable":ctime(&sCom_Sto->tp.tv_sec)); +X fclose(stderr); +X free(sCom_Sto); +X sCom_Sto = NULL; +X exit (Maxrc); +} +X +/* --------------------------------------------------------------------------*/ +/* Functions */ +/* --------------------------------------------------------------------------*/ +X +/* -------------------------------------------------------------------- +X * housekeeping +X */ +X +int Housekeeping(argc, argv, sCom_Sto) +X int argc; +X char *argv[]; +X struct Common_Stor *sCom_Sto; { +X +X FILE *seclog = NULL; +X int Rc = OK; +X int Rci = OK; /* intermediate rc as returnd by functions */ +X +X sCom_Sto->our_pid = getpid(); +X +/* +X * get our name sans path +X * */ +X +X sCom_Sto->called_as = argv[0] + strlen(*argv); +X for(;sCom_Sto->called_as >= argv[0] && *--sCom_Sto->called_as != '/';) +X ; +X sCom_Sto->called_as++; +X +/* if defined set up the name of the message log file otherwise +X * stderr will be used. Setup the cmd string to obtain all known sitenames +X * which will be sorted in ascending order with duplicates removed +X * */ +X +X Rc = set_mlog(&seclog, sCom_Sto); +X if (Rc > WARNING) +X return (Rc); +X +/* put out the started message including the time and the userid. +X * */ +X +X sCom_Sto->pwd = getpwuid(getuid()); +X +X if ((gettimeofday(&sCom_Sto->tp, &sCom_Sto->tzp)) != 0) { /* unacceptable error */ +X fprintf(stderr,"%s: (C) gettimeofday() failed. Reason: %i (%s)\n", +X sCom_Sto->called_as,errno,strerror(errno)); +X return (Rc >= CAT ? Rc:CAT); +X } +X +X if (seclog != NULL) { +X fprintf(seclog,"\n%s: (I) started by `%s' (%s) on %s", +X sCom_Sto->called_as, +X (sCom_Sto->pwd==NULL) ? "???":sCom_Sto->pwd->pw_name, +X ttyname(0), +X ctime(&sCom_Sto->tp.tv_sec)); +X fclose(seclog); +X } +X fprintf(stderr,"\n%s: (I) started by `%s' on %s", +X sCom_Sto->called_as, +X (sCom_Sto->pwd==NULL) ? "???":sCom_Sto->pwd->pw_name, +X ctime(&sCom_Sto->tp.tv_sec)); +X +/* set up the default grade +X * */ +X +X sCom_Sto->Grade = dGrade; /* set default for now */ +X if (strlen(cGrade) != 1) { +X fprintf(stderr,"%s: (W) grade %s invalid; default `%s' used\n", +X sCom_Sto->called_as,cGrade,sCom_Sto->Grade); +X Rc = Rc >= WARNING ? Rc:WARNING; +X } +X else +X sCom_Sto->Grade = cGrade; /* Ok, take the one from conf.h */ +X +/* get the program to actually call the site. This is either UUCICO +X * or AUTOPOLL or something completely different. +X * */ +X +#ifdef AUTO_POLL +X sCom_Sto->Uucico = Auto_Dir + strlen(Auto_Dir); +X for(;sCom_Sto->Uucico >= Auto_Dir && *--sCom_Sto->Uucico != '/';) +X ; +X sCom_Sto->Uucico++; +#else /* ! AUTO_POLL */ +X sCom_Sto->Uucico = Cico_Dir + strlen(Cico_Dir); +X for(;sCom_Sto->Uucico >= Cico_Dir && *--sCom_Sto->Uucico != '/';) +X ; +X sCom_Sto->Uucico++; +#endif /* AUTO_POLL */ +X +/* get the path to ourself. +X * */ +X +X sCom_Sto->Poll_Pgm = argv[0] + strlen(argv[0]); +X for(;sCom_Sto->Poll_Pgm >= argv[0] && *--(sCom_Sto->Poll_Pgm) != '/';) +X ; +X sCom_Sto->Poll_Pgm++; +X +/* obtain our sitename +X * */ +X +X if ((gethostname(sCom_Sto->This_Site,MAXHOSTNAMELEN+1)) != 0) { +X fprintf(stderr,"%s: (W) hostname could not be obtained\n", +X sCom_Sto->called_as); +X Rc = (Rc >= WARNING) ? Rc:WARNING; +X } +X +/* obtain all known sitenames +X * */ +X +X Rci = get_sites(sCom_Sto); +X Rc = Rci > Rc ? Rci:Rc; +X +/* check the arguments that we are called with +X * */ +X +X Rci = Check_Args(argc, argv, sCom_Sto); +X Rc = Rci > Rc ? Rci:Rc; +X +X return (Rc); +} +X +/* -------------------------------------------------------------------- +X * check all relevant arguments that have been passed to us. Those args +X * that may be needed for a recall will be copied to a workfield. +X * */ +X +int Check_Args(int argc, char *argv[], struct Common_Stor *sCom_Sto) { +X int i,s,k,n = 0; +X int Rc = OK; +X int One_Site = 0; /* TRUE: found at least one valid site to call */ +X int poll_file = 1; /* FALSE: after -x option given */ +X int def_flag = 0; /* TRUE: when option -n was encountered */ +X +X /* --------------------------------------------------------------*/ +X /* check the arguments passed to us */ +X /* */ +X /* These are: -n -> place a POLL file but do not start uucico */ +X /* -x -> do not place a poll file (immed. poll only) */ +X /* -g? -> specify a grade with the POLL file. The ? */ +X /* may be: 0-9, A-Z, a-z */ +X /* (validity not checked!) */ +X /* site name of the site to call. There many be as */ +X /* many as necessary separated by at least one */ +X /* blank */ +X /* Note: all options will stay in effect as long as they are'nt */ +X /* changed by a new setting. The options -n and -x can't */ +X /* be negated once given; that means place all sites */ +X /* that should be immediately polled to the left of the */ +X /* -n option; the same applies to the -x option which must */ +X /* be left of the -n option to come into effect! */ +X /* The working order is left to right! */ +X /* --------------------------------------------------------------*/ +X +X for (i = 1, s = 0; i < argc; i++) { +X k = strlen(argv[i]); +X switch (*argv[i]) { +X +X /* ----> handle the options */ +X +X case '-': +X n = 1; +X switch (*(argv[i]+n)) { +X case 'n': +X if (k > 2) { +X fprintf(stderr,"%s: (E) invalid specification %s\n", +X sCom_Sto->called_as,argv[i]); +X Rc = Rc >= SEVERE ? Rc:SEVERE; +X break; +X } +X def_flag = 1; +X break; +X case 'x': +X if (k > 2) { +X fprintf(stderr,"%s: (E) invalid specification %s\n", +X sCom_Sto->called_as,argv[i]); +X Rc = Rc >= SEVERE ? Rc:SEVERE; +X break; +X } +X if (def_flag) { +X fprintf(stderr,"%s: (W) -x after -n has no effect\n", +X sCom_Sto->called_as); +X Rc = Rc >= WARNING ? Rc:WARNING; +X } +X else { +X poll_file = 0; +X } +X break; +X case 'g': +X if (k > 3) { +X fprintf(stderr,"%s: (E) invalid specification %s\n", +X sCom_Sto->called_as,argv[i]); +X Rc = Rc >= SEVERE ? Rc:SEVERE; +X break; +X } +X if (*(argv[i]+n+1) == '\0') { +X fprintf(stderr,"%s: (E) missing grade\n", +X sCom_Sto->called_as); +X Rc = Rc >= SEVERE ? Rc:SEVERE; +X break; +X } +X if (isalnum(*(argv[i]+n+1)) == 0) { +X fprintf(stderr,"%s: (E) invalid grade %s\n", +X sCom_Sto->called_as,argv[i]); +X Rc = Rc >= SEVERE ? Rc:SEVERE; +X break; +X } +X strcpy(sCom_Sto->Grade,(argv[i]+n+1)); +X break; +X default: +X fprintf(stderr,"%s: (W) missing/unknown option `-%s' ignored\n", +X sCom_Sto->called_as,argv[i]+n); +X Rc = Rc >= WARNING ? Rc:WARNING; +X break; +X } /* end of switch (*(argv[i]+n)) */ +X break; +X +X /* ----> handle the sitenames */ +X +X default: +X if (strcmp(argv[i],sCom_Sto->This_Site) == 0) { +X fprintf(stderr,"%s: (W) ignoring to call *ourself* %s\n", +X sCom_Sto->called_as,argv[i]); +X Rc = Rc >= WARNING ? Rc:WARNING; +X break; +X } +X strcpy(sCom_Sto->System,argv[i]); +X for(s=0;s<=sCom_Sto->maxtab;s++) { +X if ((n=strcmp(sCom_Sto->Sitetab[s].name,sCom_Sto->System)) >= 0) { +X break; +X } +X } +X if (n != 0) { +X fprintf(stderr,"%s: (W) unknown site (ignored): %s\n", +X sCom_Sto->called_as,sCom_Sto->System); +X Rc = Rc >= WARNING ? Rc:WARNING; +X break; +X } +X +X /* ----> if there was no error we arrive here to save the data */ +X +X strcpy(sCom_Sto->Sitetab[s].grade,sCom_Sto->Grade); +X One_Site = sCom_Sto->Sitetab[s].flag = 1; /* poll this site */ +X if (def_flag) +X sCom_Sto->Sitetab[s].asap = 0; /* poll on next schedule */ +X else { +X sCom_Sto->Sitetab[s].asap = 1; /* poll immediately */ +X if (! poll_file) +X sCom_Sto->Sitetab[s].asap++; /* and do not place a poll file */ +X } +X s++; +X break; +X } /* end of switch (*argv[i]) */ +X } /* end of for(...) */ +X +/* now let's check what we've gotten so far. If no valid data has been */ +/* entered we will indicate that to prevent further processing */ +X +X if (! One_Site) { +X fprintf(stderr,"%s: (E) found no site to call\n", +X sCom_Sto->called_as); +X Rc = Rc >= SEVERE ? Rc:SEVERE; +X } +X +return (Rc); +} +X +int Call_Site(struct Common_Stor *sCom_Sto) { +X +/* For all sites that carry the -n flag we will place */ +/* a poll file into the appropriate directory. For all others there will */ +/* be an immediate call to uucico (or autopoll) */ +/* Those sites that have been named on the command have the corresponding */ +/* flag byte set to one. */ +X +X int fdpoll; /* fildes for the poll file */ +X int mode = P_MODE; /* mode for poll file */ +X int i = 0; +X int Rc = OK; +X int pid = 0; /* process-id after fork() */ +X +X for(i=0;(i<=sCom_Sto->maxtab);i++) { +X if (sCom_Sto->Sitetab[i].flag == 0) /* should we trigger this one ? */ +X continue; /* nope */ +X +/* processing done for delayed polls only */ +X +X if (sCom_Sto->Sitetab[i].asap <= 1) { /* do not place a poll file */ +X /* for sites that will be polled */ +X /* immediate and carry the -x option */ +#ifdef HAVE_SPOOLDIR_TAYLOR +X sprintf(sCom_Sto->workf,"%s/%s/C./C.%sPOLL", +X SPOOL_DIR, +X sCom_Sto->Sitetab[i].name, +X sCom_Sto->Sitetab[i].grade); +#endif +#ifdef HAVE_SPOOLDIR_HDB +X sprintf(sCom_Sto->workf,"%s/%s/C.%s%sPOLL", +X SPOOL_DIR, +X sCom_Sto->Sitetab[i].name, +X sCom_Sto->Sitetab[i].name, +X sCom_Sto->Sitetab[i].grade); +#endif +#ifdef HAVE_SPOOLDIR_BSD +X sprintf(sCom_Sto->workf,"%s/C./C.%s%sPOLL", +X SPOOL_DIR, +X sCom_Sto->Sitetab[i].name, +X sCom_Sto->Sitetab[i].grade); +#endif +X +X fflush(stderr); +X if ((fdpoll=open(sCom_Sto->workf,O_CREAT,mode)) <= 0) { +X fprintf(stderr,"%s: (E) couldn't place poll file for system: %s. Reason: %s\n", +X sCom_Sto->called_as, +X sCom_Sto->Sitetab[i].name, +X strerror(errno)); +X Rc = Rc >= SEVERE ? Rc:SEVERE; +X } +X else { +X if (close(fdpoll) != 0) { +X fprintf(stderr,"%s: (W) close failed for poll file; system: %s. Reason: %s\n", +X sCom_Sto->called_as, +X sCom_Sto->Sitetab[i].name, +X strerror(errno)); +X Rc = Rc >= WARNING ? Rc:WARNING; +X } +X } +X } +X +/* the following processing is done for immediate polls only +X * there is no wait for the completion of the called program that actually +X * calls the site +X * */ +X +X fflush(stderr); +X if (Rc <= WARNING) { +X fprintf(stderr,"%s: (I) site %s will be called %s\n", +X sCom_Sto->called_as, +X sCom_Sto->Sitetab[i].name, +X sCom_Sto->Sitetab[i].asap == 0 ? +X "upon next poll":"immediately"); +X if (sCom_Sto->Sitetab[i].asap >= 1) +X { +#ifdef AUTO_DIR +X if ( access(Auto_Dir,X_OK) != 0) /* do we have xecute permission ? */ +#else /* ! AUTO_DIR */ +X if ( access(Cico_Dir,X_OK) != 0) /* do we have xecute permission ? */ +#endif /* AUTO_DIR */ +X { +X fprintf(stderr,"%s: (C) could not start %s. Reason-code: %i (%s)\n", +X sCom_Sto->called_as, +X sCom_Sto->Uucico, +X errno,strerror(errno)); +X return (Rc >= CAT ? Rc:CAT); /* abandon the run */ +X } +X switch (pid = fork()) +X { +X case -1: +X fprintf(stderr,"%s: (C) could not fork() Reason-code: %i (%s)\n", +X sCom_Sto->called_as, +X errno,strerror(errno)); +X return (Rc >= CAT ? Rc:CAT); +X case 0: +X if (isatty(0)) +X close(0); /* don't block the terminal by autopoll */ +#ifdef AUTO_DIR +X execlp(Auto_Dir, +#else /* ! AUTO_DIR */ +X execlp(Cico_Dir, +#endif /*AUTO_DIR */ +X sCom_Sto->Uucico, +X "-D", "-r1", "-s", +X sCom_Sto->Sitetab[i].name,0); +X fprintf(stderr,"%s: (C) could not start %s. Reason-code: %i (%s)\n", +X sCom_Sto->called_as, +X sCom_Sto->Uucico, +X errno,strerror(errno)); +X _exit (CAT); /* child: bail out */ +X default: +X fflush(stderr); +X fprintf(stderr,"%s: (I) %s [%d] started; site: %s\n", +X sCom_Sto->called_as, +X sCom_Sto->Uucico, +X pid, +X sCom_Sto->Sitetab[i].name); +X } /* switch (pid = fork()) */ +X } /* if (Sitetab ...) */ +X } /* if (Rc ...) */ +X } /* for(i=0;(i<= ...)) */ +X return (Rc); +} +X +X /* ------------------------------------------------------------------ +X * storage - get some memory +X */ +X +void *storage(unsigned count, +X char *location, +X int *Rc, +X struct Common_Stor *sCom_Sto) +{ +X void *p; +X +X if( NULL == (p= malloc(count)) ) { +X fprintf(stderr,"%s: (C) malloc failed (%s). Reason: %i (%s)\n", +X sCom_Sto->called_as,location,errno,strerror(errno)); +X *Rc = *Rc >= CAT ? *Rc:CAT; +X } +X return p; +} +X +/* ------------------------------------------------------------------ +X * if defined open the message log file otherwise all mesages will go +X * to stderr. If UNAME_DIR is defined construct the command to be +X * passed to popen(); if undefined the default will be used +X * */ +X +int set_mlog(FILE **seclog, struct Common_Stor *sCom_Sto) { +X +X int Rc = 0; +X +#ifdef ALOG_FILE +X if (!isatty(0)) { +X if ((freopen(Msg_Log,"a",stderr)) == NULL) { +X fprintf(stdout,"%s: (C) Could not open msglog: %s\n", +X sCom_Sto->called_as,Msg_Log); +X return (Rc >= CAT ? Rc:CAT); +X } +X } +X else { +X if ((*seclog = fopen(Msg_Log,"a")) == NULL) { +X fprintf(stderr,"%s: (C) Could not open msglog: %s\n", +X sCom_Sto->called_as,Msg_Log); +X return (Rc >= CAT ? Rc:CAT); +X } +X } +#endif /* ALOG_FILE */ +X +/* set up the pipe together with the complete path to uuname */ +X +#ifdef UNAME_DIR +X if ((sCom_Sto->Usort = (char *)storage (sizeof(UNAME_DIR)+sizeof(subcmd), +X "Sort",&Rc, sCom_Sto)) != NULL) { +X strncpy(sCom_Sto->Usort,UNAME_DIR,strlen(UNAME_DIR)); /* paste in the path */ +X strcat(sCom_Sto->Usort,subcmd); /* chain the pipe to it */ +X } +#else /* ! UNAME_DIR */ +X sCom_Sto->Usort = &Sort; /* set pointer to uuname + sort */ +#endif /* UNAME_DIR */ +X +X return (Rc); +} +X +/* ------------------------------------------------------------------ +X * obtain all active sitenames +X * */ +X +int get_sites(struct Common_Stor *sCom_Sto) { +X +X int i = 0; +X int n; +X int Rc = 0; +X FILE *infile; +X +X if ((infile=popen(sCom_Sto->Usort,"r")) != NULL) { +X while(fgets(sCom_Sto->Sitetab[i].name,MAXHOSTNAMELEN+1,infile)) { +X if (i > SITE_MAX) { /* let'm run so that we can give */ +X i++; /* the user some guidance */ +X continue; /* we'll tell the user later on */ +X } +X n = strlen(sCom_Sto->Sitetab[i].name)-1; /* offset: next to last char */ +X sCom_Sto->Sitetab[i].name[n] = '\0'; /* strip trailing newline */ +X sCom_Sto->Sitetab[i].flag = FALSE; /* TRUE: poll this site */ +X sCom_Sto->Sitetab[i].asap = FALSE; /* TRUE: immediate poll */ +X strcpy(sCom_Sto->Sitetab[i].grade,sCom_Sto->Grade); +X sprintf(sCom_Sto->workf,"%s%s",STATUS_DIR,sCom_Sto->Sitetab[i].name); +X sCom_Sto->maxtab = i++; /* set high-water-mark */ +X } +X if (ferror(infile) != 0) { +X fprintf(stderr,"%s: (E) fgets() for sitenames failed reason-code: %i (%s)\n", +X sCom_Sto->called_as,errno,strerror(errno)); +X Rc = Rc >= SEVERE ? Rc:SEVERE; +X } +X pclose(infile); +X +X /* +X * check for an empty table (strange but possible) +X */ +X +X if (sCom_Sto->maxtab == 0) { +X fprintf(stderr,"%s: (E) could not obtain sitenames.\n", +X sCom_Sto->called_as); +X Rc = Rc >= SEVERE ? Rc:SEVERE; +X } +X else { +X +X /* in case the internal table overflows we'll now give notice and tell +X * the user by which amount the table has to be increased to hold all +X * site-names +X */ +X +X if (i > SITE_MAX) { +X fprintf(stderr,"%s: (E) number of sites > internal tab\n", +X sCom_Sto->called_as); +X fprintf(stderr,"%s: (E) increase SITE_MAX to >= %d and recompile\n", +X sCom_Sto->called_as,i); +X Rc = Rc >= SEVERE ? Rc:SEVERE; +X } +X } /* sCom_Sto->maxtab == 0 */ +X +X } +X else /* infile == NULL */ +X { +X fprintf(stderr,"%s: (E) could not sort sitenames. Reason-code: %i (%s)\n", +X sCom_Sto->called_as,errno,strerror(errno)); +X Rc = Rc >= SEVERE ? Rc:SEVERE; +X +X } /* if ((infile=popen(sCom_Sto->Usort,"r")) ... */ +X +X return (Rc); +} +SHAR_EOF +chmod 0444 uupoll/uupoll.c || +echo 'restore of uupoll/uupoll.c failed' +Wc_c="`wc -c < 'uupoll/uupoll.c'`" +test 27587 -eq "$Wc_c" || + echo 'uupoll/uupoll.c: original size 27587, current size' "$Wc_c" +fi +exit 0 diff --git a/gnu/libexec/uucp/contrib/uuq.sh b/gnu/libexec/uucp/contrib/uuq.sh new file mode 100644 index 00000000000..a5d88e95223 --- /dev/null +++ b/gnu/libexec/uucp/contrib/uuq.sh @@ -0,0 +1,125 @@ +#!/bin/sh +# +# uuq - a script to examine and display the Taylor spool directory contents. +# note - uses the uuname script or similar functionality. +# Zacharias Beckman + +SPOOLDIR="/usr/spool/uucp" +SYSTEMS=`uuname` +TMPFILE="/tmp/uuq.tmp" +FORSYSTEM="" +DELETE="" +LONG=0 +SINGLE=0 + +while [ "$1" != "" ] +do + case $1 in + -l) LONG=1 + shift + ;; + -s) shift + SYSTEMS=$argv[1] + SINGLE=1 + shift + ;; + -d) shift + DELETE=$argv[1] + shift + ;; + -h) echo "uuq: usage uuq [options]" + echo " -l long listing (may take a while)" + echo " -s n run uuq only for system n" + echo " -d n delete item n from the queue (required -s)" + exit 1 + ;; + *) echo "uuq: invalid option" + exit 1 + ;; + esac +done + +if [ "${DELETE}" != "" ] && [ ${SINGLE} != 1 ] ; then + echo "uuq: you must specify a system to delete the job from:" + echo " uuq -s wizard -d D.0004" + exit 1 +fi + +cd ${SPOOLDIR} + +# if we are deleting a job, then do that first and exit without showing +# any other queue information + +if [ "${DELETE}" != "" ] ; then + if [ -d ${SYSTEMS}/D. ] ; then + cd ${SYSTEMS}/C. + PACKET=${DELETE} + if [ -f ${PACKET} ] ; then + EXFILE=../D.X/`awk '{if (NR == 2) print $2}' ${PACKET}` + DFILE=../D./`awk '{if (NR == 1) print $2}' ${PACKET}` + echo "deleting job ${PACKET}" + rm ${PACKET} + rm ${EXFILE} + rm ${DFILE} + else + echo "uuq: job ${PACKET} not found" + exit 1 + fi + else + echo "uuq: system ${SYSTEMS} not found" + fi + + exit 1 +fi + +# use the 'uuname' script to obtain a list of systems for the 'sys' file, +# then step through each directory looking for appropriate information. + +if [ ${LONG} -gt 0 ] ; then + echo "system" + echo -n "job# act size command" +fi + +for DESTSYSTEM in ${SYSTEMS} ; do + # if there is an existing directory for the named system, cd into it and + # "do the right thing." + + if [ -d ${DESTSYSTEM} ] ; then + cd ${DESTSYSTEM}/C. + + PACKET=`ls` + + if [ "${PACKET}" != "" ] ; then + # if a long listing has been required, extra information is printed + + echo "" + echo "${DESTSYSTEM}:" + + # now each packet must be examined and appropriate information is + # printed for this system + + if [ ${LONG} -gt 0 ] ; then + for PACKET in * ; do + EXFILE=../D.X/`awk '{if (NR == 2) print $2}' ${PACKET}` + DFILE=../D./`awk '{if (NR == 1) print $2}' ${PACKET}` + echo -n "${PACKET} " > ${TMPFILE} + gawk '{if (NR == 2) printf(" %s ", $1);}' ${PACKET} >> ${TMPFILE} + ls -l ${DFILE}|awk '{printf("%-10d ", $4)}' >> ${TMPFILE} + if [ -f ${EXFILE} ] ; then + gawk '/U / {printf("(%s)", $2);}\ + /C / {print substr($0,2,length($0));}' ${EXFILE} >> ${TMPFILE} + else + echo "---" >> ${TMPFILE} + fi + + cat ${TMPFILE} + done + cat ${SPOOLDIR}/.Status/${DESTSYSTEM} + else + ls + fi + fi + fi + + cd ${SPOOLDIR} +done diff --git a/gnu/libexec/uucp/contrib/uurate.c b/gnu/libexec/uucp/contrib/uurate.c new file mode 100644 index 00000000000..bcefc7b5732 --- /dev/null +++ b/gnu/libexec/uucp/contrib/uurate.c @@ -0,0 +1,1860 @@ +/* + * @(#)uurate.c 1.2 - Thu Sep 3 18:32:46 1992 + * + * This program digests log and stats files in the "Taylor" format + * and outputs various statistical data to standard out. + * + * Author: + * Bob Denny (denny@alisa.com) + * Fri Feb 7 13:38:36 1992 + * + * Original author: + * Mark Pizzolato mark@infopiz.UUCP + * + * Edits: + * Bob Denny - Fri Feb 7 15:04:54 1992 + * Heavy rework for Taylor UUCP. This was the (very old) uurate from + * DECUS UUCP, which had a single logfile for activity and stats. + * Personally, I would have done things differently, with tables + * and case statements, but in the interest of time, I preserved + * Mark Pizzolato's techniques and style. + * + * Bob Denny - Sun Aug 30 14:18:50 1992 + * Changes to report format suggested by Francois Pinard and others. + * Add summary report, format from uutraf.pl (perl script), again + * thanks to Francois. Integrate and checkout with 1.03 of Taylor UUCP. + * + * Stephan Niemz <stephan@sunlab.ka.sub.org> - Fri Apr 9 1993 + * - Print totals in summary report, + * - show all commands in execution report, + * - count incoming calls correctly, + * - suppress empty tables, + * - don't divide by zero in efficiency report, + * - limit the efficiency to 100% (could be more with the i-protocol), + * - suppress some zeros to improve readability, + * - check for failure of calloc, + * - -h option changed to -s for consistency with all other uucp commands + * (but -h was left in for comptibility). + * + * Scott Boyd <scott@futures.com> - Thu Aug 26 13:21:34 PDT 1993 + * - Changed hosts linked-list insertion routine so that hosts + * are always listed in alphabetical order on reports. + * + * Klaus Dahlenburg <kdburg@incoahe.hanse.de> - Fri Jun 18 1993 (1.2.2) + * - redesigned the printed layout (sticked to those 80 column tubes). + * - 'Retry time not ...' and ' ERROR: All matching ports ...' will now be + * counted as calls and will raise the failed-call counter. + * - times now shown as hh:mm:ss; the fields may hold up to 999 hrs + * (a month equals 744 hrs at max). Printing will be as follows: + * + * hrs > 0 hh:mm:ss + * min > 0 mm:ss + * sec > 0 ss + * leading zeroes are suppressed. + * + * - the bytes xfered will be given in thousands only (we're counting + * so 1K is 1000 bytes!). Sums up to 9,999,999.9 thousand can be shown. + * - dropped the fractions of a byte in columns: bytes/second (avg cps). + * - File statistic changed to display in/out in one row instead of 2 + * separate reports. + * - eliminated the goto in command report and tightened the code; also + * the 'goto usage' has been replaced by a call to void usage() with no + * return (exit 1). + * - a totaling is done for all reports now; the total values are held + * within the structure; after finishing read there will be an alloc + * for a site named 'Total' so that the totals line will be printed + * more or less automatically. + * - option -t implemented: that is every possible report will be given. + * - the start and end date/time of the input files are printed; can be + * dropped by the -q option at run time. + * - it is now possible to use Log/Stats files from V2_LOGGING configs. + * They must however not be mixed together (with each other). + * - the Log/Stats files are taken from config which is passed via + * Makefile at compile time. Variable to set is: newconfigdir. If the + * default config can't be read the default values are used + * (the config is optional!). + * Note: keyword/filename must be on the same line (no continuation). + * - -I option implemented to run with a different config file. In case + * the file can't be opened the run is aborted! + * - -q option implemented to run without environment report (default is + * FALSE: print the report). + * - -p option added to print protocol statistics: one for the packets + * and one for the errors encountered + * - reapplied patch by Scott Boyd <scott@futures.com> that I did not + * get knowledge of + */ +/* $Log: uurate.c,v $ +/* Revision 1.1 1995/10/18 08:38:24 deraadt +/* Initial revision +/* +/* Revision 1.3 1995/08/24 05:19:21 jtc +/* Upgraded to Taylor UUCP 1.06.1 (Thanks to John Kohl). +/* + * Revision 1.15 1994/04/07 21:47:11 kdburg + * printed 'no data avail' while there was data; layout chnaged + * (cosmetic only) + * + * Revision 1.14 1994/04/07 21:16:32 kdburg + * the layout of the protocol-used line within the LOGFILE changed + * from 1.04 to 1.05; both formats may be used together; output + * changed for packet report (columns adjusted) + * + * Revision 1.13 1994/04/04 10:04:35 kdburg + * cosmetic change to the packet-report (separator lines) + * + * Revision 1.12 1994/03/30 19:52:04 kdburg + * incorporated patch by Scott Boyd which was missing from this version + * of uurate.c. Left the comment in cronological order. + * + * Revision 1.11 1994/03/28 18:53:22 kdburg + * config not checked properly for 'logfile/statsfile' overwrites, bail-out + * possible; wrong file name written to log for statsfile when found + * + * Revision 1.10 1993/09/28 16:46:51 kdburg + * transmission failures denoted by: failed after ... in stats file + * have not been counted at all. + * + * Revision 1.9 1993/08/17 23:38:36 kdburg + * sometimes a line(site) was missing from the protocol stats due + * to a missing +; added option -d and -v reassing option -h to print + * the help; a zero was returned instead of a null-pointer by + * prot_sum + * + * Revision 1.8 1993/07/03 06:58:55 kdburg + * empty input not handled properly; assigned some buffer to input; msg + * not displayed when no protocol data was available + * + * Revision 1.7 1993/06/27 10:31:53 kdburg + * rindex was replaced by strchr must be strrchr + * + * Revision 1.6 1993/06/26 06:59:18 kdburg + * switch hdr_done not reset at beginning of protocol report + * + * Revision 1.5 1993/06/25 22:22:30 kdburg + * changed rindex to strchr; if there is no NEWCONFIG defined take + * appropriate action + * + * Revision 1.4 1993/06/25 20:04:07 kdburg + * added comment about -p option; inserted proto for rindex + * + * Revision 1.3 1993/06/25 19:31:14 kdburg + * major rework done; added protocol reports (normal/errors) + * + * Revision 1.2 1993/06/21 19:53:54 kdburg + * init + * */ + +char version[] = "@(#) Taylor UUCP Log File Summary Filter, Version 1.2.2"; +static char rcsid[] = "$Id: uurate.c,v 1.1 1995/10/18 08:38:24 deraadt Exp $"; +#include <ctype.h> /* Character Classification */ +#include <math.h> +#include "uucp.h" +/* uucp.h includes string.h or strings.h, no include here. */ + +#if HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif + +#define _DEBUG_ 0 + +/* + * Direction of Calling and Data Transmission + */ + +#define IN 0 /* Inbound */ +#define OUT 1 /* Outbound */ + +/* + * define some limits + */ +#define MAXCOLS 8 /* report has this # of columns incl. 'name' */ +#define MAXREP 6 /* number of reports available */ +#define MAXFNAME 64 /* max input file name length incl. path*/ +#define MAXDNAME 8 /* max display (Hostname) name length */ + +/* + * Data structures used to collect information + */ +struct File_Stats + { + int files; /* Files Transferred */ + unsigned long bytes; /* Data Size Transferred*/ + double time; /* Transmission Time */ + }; + +struct Phone_Call + { + int calls; /* Call Count */ + int succs; /* Successful calls */ + double connect_time; /* Connect Time Spent */ + struct File_Stats flow[2]; /* Rcvd & Sent Data */ + }; + +struct Execution_Command + { + struct Execution_Command *next; + char Commandname[64]; + int count; + }; + +struct Protocol_Summary + { + struct Protocol_Summary *next; + char type[3]; + long int pr_cnt; + long int pr_psent; + long int pr_present; + long int pr_preceived; + long int pr_eheader; + long int pr_echksum; + long int pr_eorder; + long int pr_ereject; + long int pr_pwinmin; + long int pr_pwinmax; + long int pr_psizemin; + long int pr_psizemax; + }; + +struct Host_entry + { + struct Host_entry *next; + char Hostname[32]; + struct Execution_Command *cmds; /* Local Activities */ + struct Phone_Call call[2]; /* In & Out Activities */ + struct Protocol_Summary *proto; + }; + + struct Host_entry *hosts = NULL; + struct Host_entry *tot = NULL; + struct Host_entry *cur = NULL; + struct Execution_Command *cmd, *t_cmds = NULL; + struct Protocol_Summary *prot, *t_prot, *s_prot, *ss_prot = NULL; +/* + * Stuff for getopt() + */ + +extern int optind; /* GETOPT : Option Index */ +extern char *optarg; /* GETOPT : Option Value */ +#if ! HAVE_STDLIB_H + extern pointer *calloc(); +#endif /* HAVE_STDLIB_H */ +/* + * Default files to read. Taken from Taylor compile-time configuration. + * def_logs must look like an argvec, hence the dummy argv[0]. + * Maybe later modified by scanning the config + */ + +static char *def_logs[3] = { NULL, NULL, NULL}; +char *I_conf = NULL; /* points to config lib given by -I option */ +char *D_conf = NULL; /* points to config lib from makefile */ +char *Tlog = NULL; /* points to Log-file */ +char *Tstat = NULL; /* points to Stats-file */ +char Pgm_name[64]; /* our pgm-name */ +char logline[BUFSIZ+1]; /* input area */ +char noConf[] = "- not defined -"; +char buff[16*BUFSIZ]; +char sbuff[2*BUFSIZ]; + +/* + * Boolean switches for various decisions + */ + + int p_done = FALSE; /* TRUE: start date/time of file printed */ + int hdr_done = FALSE; /* TRUE: report header printed */ + int show_files = FALSE; /* TRUE: -f option given */ + int show_calls = FALSE; /* TRUE: -c option given */ + int show_commands = FALSE; /* TRUE: -x option given */ + int show_efficiency = FALSE; /* TRUE: -e option given */ + int show_all = FALSE; /* TRUE: -t option given */ + int show_proto = FALSE; /* TRUE: -p option given */ + int use_stdin = FALSE; /* TRUE: -i option given */ + int be_quiet = FALSE; /* TRUE: -q option given */ + int have_files[2]; /* TRUE: [IN] or [OUT] files found */ + int have_calls = FALSE; /* TRUE: in/out calls found */ + int have_commands = FALSE; /* TRUE: found uuxqt records */ + int have_proto = FALSE; /* TRUE: protocol data found */ + int no_records = TRUE; /* FALSE: got one record from file */ + +/* + * protos + */ + +static pointer *getmem(unsigned n); +static void inc_cmd(struct Execution_Command **, char *name); +static void fmtime(double sec, char *buf); +static void fmbytes(unsigned long n, char *buf); +static void usage(); +static int chk_config(char *conf, int n, int type); +static void hdrprt(char c, int bot); +struct Protocol_Summary *prot_sum(struct Protocol_Summary **, char *, int); + +/* + * BEGIN EXECUTION + */ + +int main(argc, argv) + int argc; + char *argv[]; +{ + FILE *Log = NULL; + int c; + char *p, *s, *stt, *flq = NULL; + char Hostname[MAXHOSTNAMELEN]; /* def taken from <sys/param.h> */ + char Filename[15]; /* filename to be printed */ + char in_date[14]; /* holds the date info of record read*/ + char in_time[14]; /* holds the time info of record read */ + char dt_info[31]; /* holds the date info from the last record read */ + char *logmsg; + int sent, called = IN; + int report = 0; /* if <= 0 give msg that no report was avail. */ + int junk; + + /* -------------------------------------------------------------------- + * P r o l o g + * -------------------------------------------------------------------- + */ + + Hostname[0] = '\0'; + have_files[IN]= have_files[OUT]= FALSE; + setvbuf(stdout,sbuff,_IOFBF,sizeof(sbuff)); + + /* + * get how we've been called isolate the name from the path + */ + + if ((stt = strrchr(argv[0],'/')) != NULL) + strcpy(Pgm_name,++stt); + else + strcpy(Pgm_name,argv[0]); + def_logs[0] = Pgm_name; + + /* + * I wish the compiler had the #error directive! + */ + +#if !HAVE_TAYLOR_LOGGING && !HAVE_V2_LOGGING + fprintf(stderr,"\a%s: (E) %s\n",Pgm_name,"Your config of Taylor UUCP is not yet supported."); + fprintf(stderr,"%s: (E) %s\n",Pgm_name,"Current support is for V2 or TAYLOR logging only."); + puts(" Run aborted due to errors\n") + exit(1); +#endif + + /* + * get some mem to store the default config name (def's are in + * policy.h ) + */ + + if (sizeof(NEWCONFIGLIB) > 1) /* defined at compile time */ + { + D_conf = (char *)getmem((sizeof(NEWCONFIGLIB) + sizeof("/config"))); + strcpy(D_conf,NEWCONFIGLIB); /* passed by makefile */ + strcat(D_conf,"/config"); + } + Tlog = (char *)getmem(sizeof(LOGFILE)); + Tstat = (char *)getmem(sizeof(STATFILE)); + Tlog = LOGFILE; + Tstat = STATFILE; + + /* + * Process the command line arguments + */ + + while((c = getopt(argc, argv, "I:s:cfdexaitphv")) != EOF) + { + switch(c) + { + case 'h': + (void) usage(); + case 's': + strcpy(Hostname, optarg); + break; + case 'c': + show_calls = TRUE; + ++report; + break; + case 'd': + printf("%s: (I) config-file default: %s\n",Pgm_name,D_conf); + exit (0); + break; + case 'f': + show_files = TRUE; + ++report; + break; + case 'x': + show_commands = TRUE; + ++report; + break; + case 'e': + show_efficiency = TRUE; + ++report; + break; + case 'a': + show_calls = show_files = show_commands = show_efficiency = TRUE; + report = 4; + break; + case 'i': + use_stdin = TRUE; + break; + case 't': + show_all = TRUE; + report = MAXREP; + break; + case 'p': + show_proto = TRUE; + ++report; + break; + case 'I': + I_conf = (char *)getmem(sizeof(optarg)); + I_conf = optarg; + break; + case 'q': + be_quiet = TRUE; + break; + case 'v': + printf("%s\n",rcsid); + exit (0); + default : + (void) usage(); + } + } + if (report == 0) /* no options given */ + ++report; /* at least summary can be printed */ + if (! be_quiet) + hdrprt('i',0); /* print header for environment info */ + + /* + * Adjust argv and argc to account for the args processed above. + */ + + argc -= (optind - 1); + argv += (optind - 1); + + /* + * If further args present, Assume rest are logfiles for us to process + * which should be given in pairs (log plus stat) otherwise the results may + * not come out as expected! If no further args are present take input from + * Log and Stat files provided in the compilation environment of Taylor UUCP. + * If -i was given, Log already points to stdin and no file args are accepted. + */ + + if (use_stdin) /* If -i, read from stdin */ + { + if (argc != 1) /* No file arguments allowed */ + { + fprintf(stderr,"\a%s: (E) %s\n",Pgm_name, + "it's not posssible to give file args with '-i'"); + (void) usage(); + } + else + { + argc = 2; + Log = stdin; + if (! be_quiet) + puts(" Input from stdin; no other files will be used\n"); + } + } + else + { + if (argc != 1) /* file arguments are present */ + { + if (! be_quiet) + puts(" No defaults used; will use passed file arguments\n"); + } + else /* Read from current logs */ + { + def_logs[1] = Tlog; /* prime the */ + def_logs[2] = Tstat; /* file names */ + if (! be_quiet) + printf(" Config for this run: "); + + if (I_conf != NULL) + { + junk = 0; + if (! be_quiet) + printf("%s\n",I_conf); + if (0 != (chk_config(I_conf,be_quiet,junk))) + return (8); + } + else + { + if (D_conf != NULL) + { + junk = 1; /* indicate default (compiled) config */ + if (! be_quiet) + printf("%s\n",D_conf); + chk_config(D_conf,be_quiet,junk); + } + else + if (! be_quiet) + printf("%s\n",noConf); + } + def_logs[1] = Tlog; /* final setting of */ + def_logs[2] = Tstat; /* file names */ + argv = def_logs; /* Bash argvec to log/stat files */ + argc = sizeof(def_logs) / sizeof(def_logs[0]); + } + } + + /* -------------------------------------------------------------------- + * MAIN LOGFILE PROCESSING LOOP + * -------------------------------------------------------------------- + */ + + if (!use_stdin) + { + if (argc < 3 && ! be_quiet) + { + puts(" (W) there is only one input file!"); + puts(" (W) some reports may not be printed"); + } + if (! be_quiet) + hdrprt('d',0); /* give subheaderline */ + } + + while (argc > 1) + { + if (!use_stdin && (Log = fopen(argv[1], "r")) == NULL) + { + perror(argv[1]); + exit (8); + } + setvbuf(Log,buff,_IOFBF,sizeof(buff)); + if ((flq = strrchr(argv[1], '/')) == NULL) + strncpy(Filename,argv[1],sizeof(Filename)-1); + else + strncpy(Filename,++flq,sizeof(Filename)-1); + + strcpy(in_date," n/a"); + strcpy(in_time," n/a"); + p_done = FALSE; /* no info printed yet */ + no_records = TRUE; /* not read any record yet */ + + /* + * Read each line of the logfile and collect information + */ + + while (fgets(logline, sizeof(logline), Log)) + { + /* + * The host name of the other end of the connection is + * always the second field of the log line, whether we + * are reading a Log file or a Stats file. Set 'p' to + * point to the second field, null-terminated. Skip + * the line if something is funny. V2 and Taylor ar identical + * up to this part. Put out the start/end date of the files read; + */ + + if (NULL == (p = strchr(logline, ' '))) + continue; + no_records = FALSE; /* got one (usable) record at least */ + ++p; + + if (NULL != (stt = strchr(p, '('))) + { + if (! p_done && ! use_stdin && ! be_quiet) + { + +#if HAVE_TAYLOR_LOGGING + sscanf(++stt,"%s%*c%[^.]",in_date,in_time); +#endif /* HAVE_TAYLOR_LOGGING */ + +#if HAVE_V2_LOGGING + sscanf(++stt,"%[^-]%*c%[1234567890:]",in_date,in_time); +#endif /* HAVE_V2_LOGGING */ + + printf(" %-14s %10s %8s",Filename, in_date, in_time); + strcpy(in_date," n/a"); /* reset to default */ + strcpy(in_time," n/a"); + p_done = TRUE; + } + else + { + if (! use_stdin && ! be_quiet) /* save for last time stamp prt. */ + strncpy(dt_info,++stt,sizeof(dt_info)-1); + } + } + + if (NULL != (s = strchr(p, ' '))) + *s = '\0'; + for (s = p; *s; ++s) + if (isupper(*s)) + *s = tolower(*s); + + /* + * Skip this line if we got -s <host> and + * this line does not contain that host name. + * Don't skip the `incoming call' line with the system name `-'. + */ + + if (Hostname[0] != '\0') + if ( (p[0] != '-' || p[1] != '\0') && 0 != strcmp(p, Hostname) ) + continue; + + /* + * We are within a call block now. If this line is a file + * transfer record, determine the direction. If not then + * skip the line if it is not interesting. + */ + + if ((s = strchr(++s, ')')) == NULL) + continue; + +#if ! HAVE_TAYLOR_LOGGING +#if HAVE_V2_LOGGING + if ((strncmp(s,") (",3)) == 0) /* are we in stats file ?) */ + if ((s = strchr(++s, ')')) == NULL) + continue; /* yes but strange layout */ +#endif /* HAVE_V2_LOGGING */ +#endif /* ! HAVE_TAYLOR_LOGGING */ + + logmsg = s + 2; /* Message is 2 characters after ')' */ + if ((0 != strncmp(logmsg, "Call complete", 13)) && + (0 != strncmp(logmsg, "Calling system", 14)) && + (0 != strncmp(logmsg, "Incoming call", 13)) && + (0 != strncmp(logmsg, "Handshake successful", 20)) && + (0 != strncmp(logmsg, "Retry time not", 14)) && + (0 != strncmp(logmsg, "ERROR: All matching ports", 25)) && + (0 != strncmp(logmsg, "Executing", 9)) && + (0 != strncmp(logmsg, "Protocol ", 9)) && + (0 != strncmp(logmsg, "sent ", 5)) && + (0 != strncmp(logmsg, "received ", 9)) && + (0 != strncmp(logmsg, "failed after ", 13)) && + (0 != strncmp(logmsg, "Errors: ", 8))) + continue; + + /* + * Find the Host_entry for this host, or create a new + * one and link it on to the list. + */ + + if ((cur == NULL) || (0 != strcmp(p, cur->Hostname))) + { + struct Host_entry *e, *last; + + for (e= cur= hosts; cur != NULL ; e= cur, cur= cur->next) + if (0 == strcmp(cur->Hostname, p)) + break; + if (cur == NULL) + { + cur= (struct Host_entry *)getmem(sizeof(*hosts)); + strcpy(cur->Hostname, p); + if (hosts == NULL) + e= hosts= cur; + else { + e = hosts; + last = NULL; + while (e != NULL) { + if (strcmp(e->Hostname, cur->Hostname) <= 0) { + if (e->next == NULL) { + e->next = cur; + break; + } + last = e; + e = e->next; + } + else { + cur->next = e; + if (last == NULL) + hosts = cur; + else + last->next = cur; + break; + } + } /* while (e != NULL) */ + } /* hosts == NULL */ + } /* cur == NULL */ + } + + /* + * OK, if this is a uuxqt record, find the Execution_Command + * structure for the command being executed, or create a new + * one. Then count an execution of this command. + * (Log file only) + */ + + if (0 == strncmp(logmsg, "Executing", 9)) + { + if (NULL == (p = strchr(logmsg, '('))) + continue; + if ((s = strpbrk(++p, " )")) == NULL) + continue; + *s = '\0'; + inc_cmd(&cur->cmds, p); + inc_cmd(&t_cmds, p); + have_commands = TRUE; + continue; + } + + /* + * Count start of outgoing call. + */ + + if ((0 == strncmp(logmsg, "Calling system", 14)) || + (0 == strncmp(logmsg, "Retry time not", 14)) || + (0 == strncmp(logmsg, "ERROR: All matching ports", 25))) + { + called = OUT; + cur->call[OUT].calls++; + have_calls = TRUE; + s_prot = NULL; /* destroy pointer to protocol */ + continue; + } + + /* + * Count start of incoming call. + */ + + if (0 == strncmp(logmsg, "Incoming call", 13)) + { + called = IN; + s_prot = NULL; /* destroy pointer to protocol */ + continue; + } + + /* + * On an incoming call, get system name from the second line. + * Get protocol type and size/window too + */ + + if (0 == strncmp(logmsg, "Handshake successful", 20)) + { + if ( called==IN ) + cur->call[IN].calls++; + have_calls = TRUE; + s_prot = NULL; /* destroy pointer to protocol */ + if (NULL == (p = strchr(logmsg, '('))) + continue; + if (0 == strncmp(p, "(protocol ", 10)) + { + if (NULL == (p = strchr(p, '\''))) + continue; + ss_prot = prot_sum(&cur->proto, ++p, 1); + s_prot = prot_sum(&t_prot, p, 1); + continue; + } + } + + /* + * check protocol type and get stats + * + */ + + if (0 == strncmp(logmsg, "Protocol ", 9)) + { + s_prot = NULL; /* destroy pointer to protocol */ + if (NULL == (p = strchr(logmsg, '\''))) + continue; + ss_prot = prot_sum(&cur->proto, ++p, 2); + s_prot = prot_sum(&t_prot, p, 2); + continue; + } + + /* + * check protocol errors. Unfortunately the line does not contain + * the used protocol, so if any previous line did contain that + * information and we did process that line we will save the pointer + * to that particular segment into s_prot. If this pointer is not set + * the error info is lost for we don't know where to store. + * + */ + + if ((0 == strncmp(logmsg, "Errors: header", 14)) && s_prot != NULL) + { + int i1,i2,i3,i4 = 0; + sscanf(logmsg,"%*s %*s %d%*c%*s %d%*c%*s %d%*c%*s %*s%*c %d",&i1,&i2,&i3,&i4); + ss_prot->pr_eheader += i1; + ss_prot->pr_echksum += i2; + ss_prot->pr_eorder += i3; + ss_prot->pr_ereject += i4; + s_prot->pr_eheader += i1; + s_prot->pr_echksum += i2; + s_prot->pr_eorder += i3; + s_prot->pr_ereject += i4; + s_prot = NULL; + continue; + } + + /* + * Handle end of call. Pick up the connect time. + * position is on the closing paren of date/time info + * i.e: ) text.... + */ + + if (0 == strncmp(logmsg, "Call complete", 13)) + { + cur->call[called].succs++; + s_prot = NULL; /* destroy pointer to protocol */ + if (NULL == (s = strchr(logmsg, '('))) + continue; + cur->call[called].connect_time += atof(s+1); + continue; + } + + /* + * We are definitely in a Stats file now. + * If we reached here, this must have been a file transfer + * record. Count it in the field corresponding to the + * direction of the transfer. Count bytes transferred and + * the time to transfer as well. + * Position within the record is at the word 'received' or 'sent' + * depending on the direction. + */ + + sent = IN; /* give it an initial value */ + if (0 == strncmp(logmsg, "failed after ",13)) + logmsg += 13; /* the transmission failed for any reason */ + /* so advance pointer */ + if (0 == strncmp(logmsg, "sent", 4)) + sent = OUT; + else if (0 == strncmp(logmsg, "received", 8)) + sent = IN; + have_files[sent] = TRUE; + cur->call[called].flow[sent].files++; + if (NULL == (s = strchr(logmsg, ' '))) /* point past keyword */ + continue; /* nothing follows */ + /* we should be at the bytes column now*/ +#if HAVE_TAYLOR_LOGGING + cur->call[called].flow[sent].bytes += atol(++s); +#endif /* HAVE_TAYLOR_LOGGING */ +#if HAVE_V2_LOGGING + if (NULL == (s = strpbrk(s, "0123456789"))) /* point to # bytes */ + continue; + cur->call[called].flow[sent].bytes += atol(s); +#endif /* HAVE_V2_LOGGING */ + if (NULL == (s = strchr(s, ' '))) /* point past # of bytes */ + continue; + if (NULL == (s = strpbrk(s, "0123456789"))) /* point to # of seconds */ + continue; + cur->call[called].flow[sent].time += atof(s); + + } /* end of while (fgets(logline...)) */ + + if (stt != NULL && ! use_stdin && ! be_quiet && ! no_records) + { + +#if HAVE_TAYLOR_LOGGING + sscanf(dt_info,"%s%*c%[^.]",in_date,in_time); +#endif /* HAVE_TAYLOR_LOGGING */ + +#if HAVE_V2_LOGGING + sscanf(dt_info,"%[^-]%*c%[1234567890:]",in_date,in_time); +#endif /* HAVE_V2_LOGGING */ + + printf(" %10s %8s\n",in_date, in_time); + p_done = FALSE; + } + if (Log != stdin) + { + if (0 != ferror(Log)) + { + if (! be_quiet) + printf(" %-14s data is incomplete; read error"," "); + else + fprintf(stderr,"%s (W) data is incomplete; read error on %s\n", + Pgm_name,argv[1]); + } + else + { + if (! be_quiet && no_records) + printf(" %-14s %10s\n",Filename, " is empty "); + } + } + fclose(Log); + + argc--; + argv++; + } /* end of while (for (argv ....) */ + + /* + * do we have *any* data ? + */ + + if (cur == NULL) + { + puts("\n(I) Sorry! No data is available for any requested report\n"); + exit(0); + } + + /* + * truncate hostname, alloc the structure holding the totals and + * collect the totals data + */ + + for (cur = hosts; cur != NULL;cur = cur->next) + { + cur->Hostname[MAXDNAME] = '\0'; + if (cur->next == NULL) /* last so will have to alloc totals */ + { + cur->next = (struct Host_entry *)getmem(sizeof(*hosts)); + strcpy(cur->next->Hostname,"Totals"); + tot = cur->next; + for (cur = hosts; cur != NULL; cur = cur->next) + { + if (cur->next != NULL) /* don't count totals to totals */ + { + tot->call[IN].flow[IN].bytes += cur->call[IN].flow[IN].bytes; + tot->call[OUT].flow[IN].bytes += cur->call[OUT].flow[IN].bytes; + tot->call[IN].flow[OUT].bytes += cur->call[IN].flow[OUT].bytes; + tot->call[OUT].flow[OUT].bytes += cur->call[OUT].flow[OUT].bytes; + tot->call[IN].flow[IN].time += cur->call[IN].flow[IN].time; + tot->call[OUT].flow[IN].time += cur->call[OUT].flow[IN].time; + tot->call[IN].flow[OUT].time += cur->call[IN].flow[OUT].time; + tot->call[OUT].flow[OUT].time += cur->call[OUT].flow[OUT].time; + tot->call[IN].flow[IN].files += cur->call[IN].flow[IN].files; + tot->call[OUT].flow[IN].files += cur->call[OUT].flow[IN].files; + tot->call[IN].flow[OUT].files += cur->call[IN].flow[OUT].files; + tot->call[OUT].flow[OUT].files += cur->call[OUT].flow[OUT].files; + tot->call[OUT].succs += cur->call[OUT].succs; + tot->call[OUT].calls += cur->call[OUT].calls; + tot->call[OUT].connect_time += cur->call[OUT].connect_time; + tot->call[IN].succs += cur->call[IN].succs; + tot->call[IN].calls += cur->call[IN].calls; + tot->call[IN].connect_time += cur->call[IN].connect_time; + } + } + break; /* totals is last in Host_Entry */ + } + } + + /* + * *********** + * * REPORTS * + * *********** + */ + +#if _DEBUG_ + putchar('\n'); +#endif + + /* ------------------------------------------------------------------ + * + * Summary report only when no other report except option -t is given + * + * I know, this code could be tightened (rbd)... + * ------------------------------------------------------------------ + */ + + if ( !(show_calls || show_files || + show_efficiency || show_commands || show_proto) || show_all) + { + if (have_calls || have_files[IN] || have_files[OUT]) + { + char t1[32], t2[32], t3[32], t4[32], t5[32]; + long ib, ob, b, rf, sf; + double it, ot, ir, or; + + hdr_done = FALSE; + for (cur = hosts; cur != NULL; cur = cur->next) + { + ib = (cur->call[IN].flow[IN].bytes + + cur->call[OUT].flow[IN].bytes); + fmbytes(ib, t1); + + ob = (cur->call[IN].flow[OUT].bytes + + cur->call[OUT].flow[OUT].bytes); + fmbytes(ob, t2); + + /* Don't print null-lines. */ + if (( b= ib+ob ) == 0 ) + continue; + /* Don't print the header twice. */ + if (! hdr_done) + { + hdrprt('s',0); /* print the header line(s) */ + hdr_done = TRUE; + } + + fmbytes(b, t3); + + it = cur->call[IN].flow[IN].time + + cur->call[OUT].flow[IN].time; + fmtime(it, t4); + + ot = cur->call[IN].flow[OUT].time + + cur->call[OUT].flow[OUT].time; + fmtime(ot, t5); + + rf = cur->call[IN].flow[IN].files + + cur->call[OUT].flow[IN].files; + + sf = cur->call[IN].flow[OUT].files + + cur->call[OUT].flow[OUT].files; + + ir = (it == 0.0) ? 0.0 : (ib / it); + or = (ot == 0.0) ? 0.0 : (ob / ot); + + if (cur->next == NULL) /* totals line reached ? */ + hdrprt('s',1); /* print the separator line */ + + printf("%-8s %4d %4d %9s %9s %9s %9s %9s %5.0f %5.0f\n", + cur->Hostname, rf, sf, + t1, t2, t3, t4, t5, + ir, or); + } + if (! hdr_done) + { + puts("\n(I) No data found to print Compact summary report"); + } + } + else + { + puts("\n(I) No data available for Compact summary report"); + --report; + } + } + + /* ------------------------------------------------------------------ + * Protocol statistics report + * ------------------------------------------------------------------ + */ + + if (show_proto || show_all) + { + if (have_proto) + { + /* --------------------- */ + /* protocol packet report */ + /* --------------------- */ + + char *type = NULL; + hdr_done = FALSE; + for (cur = hosts; cur != NULL; cur = cur->next) + { + type = cur->Hostname; + if (cur->next == NULL) + { + if (hdr_done) + puts("-------------------------------------------------------------------"); + cur->proto = t_prot; + } + for (prot = cur->proto; prot != NULL; prot = prot->next) + { + if (! hdr_done) + { + hdrprt('p',0); /* print the header line(s) */ + hdr_done = TRUE; + } + printf("%-8s %3s %4d %4d %5d %4d %10d %7d %10d\n", + type == NULL ? " ":cur->Hostname, + prot->type, + prot->pr_psizemin, + prot->pr_psizemax, + prot->pr_pwinmin, + prot->pr_pwinmax, + prot->pr_psent, + prot->pr_present, + prot->pr_preceived); + type = NULL; + } + } + if (! hdr_done) + puts("\n(I) No data found to print Protocol packet report"); + + /* --------------------- */ + /* protocol error report */ + /* --------------------- */ + + type = NULL; + hdr_done = FALSE; + if (t_prot != NULL) + { + for (cur = hosts; cur != NULL; cur = cur->next) + { + type = cur->Hostname; + if (cur->next == NULL) + { + if (hdr_done) + puts("--------------------------------------------------------------"); + cur->proto = t_prot; + } + + for (prot = cur->proto; prot != NULL; prot = prot->next) + { + if ((prot->pr_eheader + prot->pr_echksum + + prot->pr_eorder + prot->pr_ereject) != 0) + { + if (! hdr_done) + { + hdrprt('p',1); /* print the header line(s) */ + hdr_done = TRUE; + } + printf("%-8s %3s %11d %11d %11d %11d\n", + type == NULL ? " ":cur->Hostname, + prot->type, + prot->pr_eheader, + prot->pr_echksum, + prot->pr_eorder, + prot->pr_ereject); + type = NULL; + } + } + } + } + if (! hdr_done) + puts("\n(I) No data found to print Protocol error report"); + } + else + { + puts("\n(I) No data available for Protocol reports"); + --report; + } + } + + /* ------------------------------------------------------------------ + * Call statistics report + * ------------------------------------------------------------------ + */ + + if (show_calls || show_all) + { + if (have_calls) + { + char t1[32], t2[32]; + + hdr_done = FALSE; + for (cur = hosts; cur != NULL; cur = cur->next) + { + if (cur->next == NULL) + { + if (hdr_done) + hdrprt('c',1); /* print the separator line */ + } + else + { + /* Don't print null-lines on deatail lines */ + if ( cur->call[OUT].calls + cur->call[IN].calls == 0 ) + continue; + + /* Don't print the header twice. */ + if (! hdr_done) + { + hdrprt('c',0); /* print the header line(s) */ + hdr_done = TRUE; + } + } + if ( cur->call[OUT].calls > 0 || cur->next == NULL) + { + fmtime(cur->call[OUT].connect_time, t1); + printf( " %-8s %7d %7d %7d %9s", + cur->Hostname, + cur->call[OUT].succs, + cur->call[OUT].calls - cur->call[OUT].succs, + cur->call[OUT].calls, + t1 ); + } + else + { + printf( " %-42s", cur->Hostname ); + } + if ( cur->call[IN].calls > 0 || cur->next == NULL ) + { + fmtime(cur->call[IN].connect_time, t2); + printf( " %7d %7d %7d %9s", + cur->call[IN].succs, + cur->call[IN].calls - cur->call[IN].succs, + cur->call[IN].calls, + t2 ); + } + putchar('\n'); + } + if (! hdr_done) + { + puts("\n(I) No data found to print Call statistics report"); + } + } + else + { + puts("\n(I) No data available for Call statistics report"); + --report; + } + } + + /* ------------------------------------------------------------------ + * File statistics report + * ------------------------------------------------------------------ + */ + + if (show_files || show_all) + { + if (have_files[IN] || have_files[OUT]) + { + char t1[32], t2[32]; + double rate = 0, time = 0; + int b = 0; + int lineOut = 0; + + hdr_done = FALSE; + for (cur = hosts; cur != NULL; cur = cur->next) + { + lineOut = 0; + for (sent= IN; sent <= OUT; ++sent) + { + b = cur->call[IN].flow[sent].bytes + + cur->call[OUT].flow[sent].bytes; + time = cur->call[IN].flow[sent].time + + cur->call[OUT].flow[sent].time; + + /* Don't print null-lines on detail lines. */ + if ( (b != 0 && time != 0.0) || cur->next == NULL) + { + /* Don't print the header twice. */ + if (! hdr_done) + { + hdrprt('f',0); /* print the header line(s) */ + hdr_done = TRUE; + } + fmbytes(b, t1); + rate = (cur->call[IN].flow[sent].bytes + + cur->call[OUT].flow[sent].bytes) / time; + fmtime((cur->call[IN].flow[sent].time + + cur->call[OUT].flow[sent].time), t2); + + if (lineOut == 0) /* first half not printed yet ? */ + { + if (cur->next == NULL) /* totals line ? */ + hdrprt('f',1); /* print the separator line */ + printf(" %-8s", cur->Hostname); + if (sent == OUT) /* can't happen whith totals line */ + printf("%34s", " "); + } + + printf(" %5d %11s %9s %5.0f", + cur->call[IN].flow[sent].files + + cur->call[OUT].flow[sent].files, + t1, t2, rate); + lineOut = 1; + } + } /* end: for (sent ... ) */ + if (lineOut) + printf("\n"); + } /* end: for (cur= ... ) */ + if (! hdr_done) + { + puts("\n(I) No data found to print File statistics report"); + } + } + else + { + puts("\n(I) No data available for File statistics report"); + --report; + } + } + + /* ------------------------------------------------------------------ + * Efficiency report + * ------------------------------------------------------------------ + */ + + if (show_efficiency || show_all) + { + if (have_files[IN] || have_files[OUT]) + { + char t1[32], t2[32], t3[32]; + double total, flow; + + hdr_done = FALSE; + for (cur = hosts; cur != NULL; cur = cur->next) + { + /* Don't print null-lines. */ + if ( 0 == cur->call[IN].flow[IN].files + + cur->call[IN].flow[OUT].files + + cur->call[OUT].flow[IN].files + + cur->call[OUT].flow[OUT].files || + 0.0 == (total= cur->call[IN].connect_time + + cur->call[OUT].connect_time)) + { + continue; + } + + if (! hdr_done) + { + hdrprt('e',0); /* print the header line(s) */ + hdr_done = TRUE; + } + + flow = cur->call[IN].flow[IN].time + + cur->call[IN].flow[OUT].time + + cur->call[OUT].flow[IN].time + + cur->call[OUT].flow[OUT].time; + fmtime(total, t1); + fmtime(flow, t2); + fmtime(total-flow, t3); + + if (cur->next == NULL) + hdrprt('e',1); /* print the separator line */ + + printf(" %-8s %10s %10s %10s %7.2f\n", + cur->Hostname, t1, t2, t3, + flow >= total ? 100.0: flow*100.0/total); + } /* end: for (cur= .. */ + if (! hdr_done) + { + puts("\n(I) No data found to print Efficiency report"); + } + } + else + { + puts("\n(I) No data available for Efficiency report"); + --report; + } + } + + /* ------------------------------------------------------------------ + * Command execution report + * ------------------------------------------------------------------ + */ + + if (show_commands || show_all) + { + if (have_commands) + { + int ncmds, i, match; + + /* + * layout the header line. The column's header is the command name + */ + + hdr_done = FALSE; + for (ncmds= 0, cmd= t_cmds; + cmd != NULL && ncmds <= MAXCOLS-1; + ncmds++, cmd= cmd->next) + { + if (! hdr_done) + { + puts("\nCommand executions:"); + puts("-------------------"); + puts(" Name of "); + fputs(" site ", stdout); + hdr_done = TRUE; + } + printf(" %7s", cmd->Commandname); + } + if (! hdr_done) + { + puts("\n(I) No data found to print Command execution report"); + } + else + { + fputs("\n --------", stdout); + for (i= 0; i<ncmds; i++) + fputs(" ------", stdout); + putchar('\n'); + + /* + * print out the number of executions for each host/command + */ + + for (cur= hosts; cur != NULL; cur= cur->next) + { + if (cur->next == NULL) + break; + + /* Don't print null-lines. */ + + if (cur->cmds == NULL) + continue; + + printf(" %-8s", cur->Hostname); + for (cmd= t_cmds; cmd != NULL; cmd= cmd->next) + { + struct Execution_Command *ec; + match = FALSE; + for(ec= cur->cmds; ec != NULL; ec= ec->next) + { + if ( 0 == strcmp(cmd->Commandname, ec->Commandname) ) + { + printf(" %7d", ec->count); + match = TRUE; + break; + } + } + if (! match) + printf("%8s"," "); /* blank out column */ + } + putchar('\n'); + } + + /* + * print the totals line + */ + + fputs(" --------", stdout); + for (i= 0; i<ncmds; i++) + fputs("--------", stdout); + printf("\n %-8s", cur->Hostname); + for (cmd= t_cmds; cmd != NULL; cmd= cmd->next) + { + printf(" %7d", cmd->count); + } + putchar('\n'); + } + } + else + { + puts("\n(I) No data available for Command execution report"); + --report; + } + } + if (report <= 0 ) /* any reports ? */ + { + puts("\n(I) Sorry! No data is available for any requested report\n"); + exit(1); + } + + puts("\n(I) End of reports\n"); + exit (0); +} /* end of main */ + + /* ------------------------------------------------------------------ + * * Functions * + * ------------------------------------------------------------------ + */ + + /* ------------------------------------------------------------------ + * display the help + * ------------------------------------------------------------------ + */ + +void usage() +{ + fprintf(stderr,"Usage uurate [-acdefhiptvx] [-s hostname] [-I config file] [logfile(s) ... logfile(s)]\n"); + fprintf(stderr,"where:\t-a\tPrint reports c,e,f,x\n"); + fprintf(stderr,"\t-c\tReport call statistics\n"); + fprintf(stderr,"\t-d\tPrint the name of the default config file\n"); + fprintf(stderr,"\t-e\tReport efficiency statistics\n"); + fprintf(stderr,"\t-f\tReport file transfer statistics\n"); + fprintf(stderr,"\t-h\tPrint this help\n"); + fprintf(stderr,"\t-i\tRead log info from standard input\n"); + fprintf(stderr,"\t-p\tReport protocol statistics\n"); + fprintf(stderr,"\t-t\tAll available reports plus compact summary report\n"); + fprintf(stderr,"\t-v\tPrint version number\n"); + fprintf(stderr,"\t-x\tReport command execution statistics\n"); + fprintf(stderr,"\t-s host\tReport activities involving HOST only\n"); + fprintf(stderr,"\t-I config Use config instead of standard config file\n"); + fprintf(stderr,"If no report options given, a compact summary report is printed.\n"); + fprintf(stderr,"log files should be given as pairs that is Log/Stats ... .\n"); + fprintf(stderr,"If neither -i nor logfiles given, those names found in config will be used\n"); + + exit (1); +} + + /* ------------------------------------------------------------------ + * getmem - get some memory + * ------------------------------------------------------------------ + */ + +static pointer *getmem(n) + unsigned n; +{ + pointer *p; + + if( NULL== (p= calloc(1, n)) ) + { + fprintf(stderr,"\a%s (C) %s\n",Pgm_name, "out of memory\n"); + exit (8); + } + return p; +} + + /* ------------------------------------------------------------------ + * inc_cmd - increment command count + * ------------------------------------------------------------------ + */ + +static void inc_cmd(cmds, name) + struct Execution_Command **cmds; + char *name; +{ + int cnt = 0; + struct Execution_Command *cmd, *ec; + + for (ec = cmd = *cmds; cmd != NULL; ec= cmd, cmd= cmd->next, cnt++) + if ( (0 == strcmp(cmd->Commandname, name)) || + (0 == strcmp(cmd->Commandname, "Misc.")) ) + break; + if (cmd == NULL) + { + cmd= (struct Execution_Command *)getmem(sizeof(*cmd)); + if (cnt <= MAXCOLS-1) /* first col prints site name therefore < max-1 */ + { + strcpy(cmd->Commandname, name); + if (*cmds == NULL) + ec = *cmds = cmd; + else + ec->next= cmd; + } + else + { + strcpy(ec->Commandname, "Misc."); /* reached high-water-mark */ + cmd = ec; /* backtrack */ + } + } + cmd->count++; +} + + + /* ------------------------------------------------------------------ + * prot_sum - collect protocol data + * ------------------------------------------------------------------ + */ + + struct Protocol_Summary * + prot_sum(proto, ptype, ind) + struct Protocol_Summary **proto; + char *ptype; + int ind; +{ + int cnt = 0; + int i1, i2, i3 = 0; + struct Protocol_Summary *cur, *first; + + for (first = cur = *proto; cur != NULL; first= cur, cur= cur->next, cnt++) + { + if ( (0 == strncmp(cur->type, ptype,strlen(cur->type)))) + break; + } + if (cur == NULL) + { + cur= (struct Protocol_Summary *)getmem(sizeof(*cur)); + sscanf(ptype,"%[^\' ]3",cur->type); + if (*proto == NULL) + first = *proto = cur; + else + first->next= cur; + } + if (NULL == (ptype = strchr(ptype, ' '))) + return (NULL); + cur->pr_cnt++; + have_proto = TRUE; + ++ptype; + switch(ind) + { + case 1: /* used protocol line */ + /* + * uucp-1.04 format: .... packet size ssss window ww) + * uucp-1.05 format: .... remote packet/window ssss/ww local ssss/ww) + * (the remote packet/window will be used!) + */ + + i1 = i2 = 0; /* reset */ + + if (NULL == (strchr(ptype, '/'))) + sscanf(ptype,"%*s %*s %d %*s %d",&i1,&i2); + else + sscanf(ptype,"%*s %*s %d/%d",&i1,&i2); + + if (i1 > cur->pr_psizemax) + cur->pr_psizemax = i1; + if (i1 < cur->pr_psizemin || cur->pr_psizemin == 0) + cur->pr_psizemin = i1; + + if (i2 > cur->pr_pwinmax) + cur->pr_pwinmax = i2; + if (i2 < cur->pr_pwinmin || cur->pr_pwinmin == 0) + cur->pr_pwinmin = i2; + break; + case 2: /* protocol statistics line */ + i1 = i2 = i3 = 0; /* reset */ + sscanf(ptype,"%*s %*s %d%*c %*s %d%*c %*s %d",&i1,&i2,&i3); + cur->pr_psent += i1; + cur->pr_present += i2; + cur->pr_preceived += i3; + break; + default: + break; + } + return (cur); +} + /* ------------------------------------------------------------------ + * fmtime() - Format time in hours & minutes & seconds; + * ------------------------------------------------------------------ + */ + +static void fmtime(dsec, buf) + double dsec; + char *buf; +{ + long hrs, min, lsec; + + if( dsec <= 0 ) + { + strcpy(buf, "0" ); + return; + } + lsec = fmod(dsec+0.5, 60L); /* round to the next full second */ + hrs = dsec / 3600L; + min = ((long)dsec / 60L) % 60L; + if (hrs == 0) + if (min == 0) + sprintf(buf,"%6s%2ld"," ",lsec); + else + sprintf(buf,"%3s%2ld:%02ld"," ",min,lsec); + else + sprintf(buf,"%2ld:%02ld:%02ld",hrs,min,lsec); + +} + + /* ------------------------------------------------------------------ + * fmbytes - Format size in bytes + * ------------------------------------------------------------------ + */ + +static void fmbytes(n, buf) + unsigned long n; + char *buf; +{ + if ( n == 0 ) + { + strcpy( buf, "0.0" ); + return; + } + sprintf(buf, "%.1f", (double)n / 1000.0); /* Display in Kilobytes */ +} + + + /* ------------------------------------------------------------------ + * chk_config - Read the config file + * check on keywords: logfile and statfile. When found override + * the corresponding default + * ------------------------------------------------------------------ + */ + +int chk_config(char *T_conf,int be_quiet, int type) +{ + FILE *Conf; + char keywrd[9]; + char name[MAXPATHLEN+1]; + char *pos1, *pos2; + int i = 0; + int logf = FALSE; + int statf = FALSE; + + if ((Conf = fopen(T_conf, "r")) == NULL) + { + if (! be_quiet) + { + puts(" Could not open config"); + if (type == 0) + { + puts(" The run will be aborted\n"); + return (8); + } + } + else + { + fprintf(stderr,"%s (E) %s %s \n",Pgm_name, + "could not open config:", + T_conf); + if (type != 0) + fprintf(stderr,"%s (W) defaults used for all files\n", + Pgm_name); + else + { + fprintf(stderr,"%s (C) ended due to errors\n", + Pgm_name); + return (8); + } + } + } + else + { + while (fgets(logline, sizeof(logline), Conf)) + { + if (logline[0] == '#') + continue; + sscanf(logline,"%8s %s",keywrd,name); + if (0 == strncmp(keywrd,"logfile",7)) + { + pos1 = pos2 = name; + for (i=0;(i<=MAXPATHLEN && *pos1 != '\0');pos1++,pos2++,i++) + { + if (*pos1 == '#') /* name immed followed by comment */ + break; + if (*pos1 == '\\') /* quoted comment (filename has #) */ + { + ++pos1; /* skip escape char */ + if (*pos1 != '#') /* continuation ? */ + { + puts(" Config error:"); + puts(" Found filename continuation; bailing out\n"); + exit (8); + } + } + *pos2 = *pos1; /* move char */ + } + *pos2 = '\0'; /* terminate string */ + Tlog = (char *)getmem(strlen(name)+1); + strcpy(Tlog,name); + if (! be_quiet) + printf(" logfile used: %s\n",Tlog); + logf = TRUE; + if (statf) /* statsfile still to come ? */ + break; /* no finished */ + continue; + } + + if (0 == strncmp(keywrd,"statfile",8)) + { + pos1 = pos2 = name; + for (i=0;(i<=MAXPATHLEN && *pos1 != '\0');pos1++,pos2++,i++) + { + if (*pos1 == '#') /* name immed followed by comment */ + break; + if (*pos1 == '\\') /* quoted comment (filename has #) */ + { + ++pos1; /* skip escape char */ + if (*pos1 != '#') /* continuation ? */ + { + puts(" Config error:"); + puts(" Found filename continuation; bailing out\n"); + exit (8); + } + } + *pos2 = *pos1; /* move char */ + } + *pos2 = '\0'; /* terminate string */ + Tstat = (char *)getmem(strlen(name)+1); + strcpy(Tstat,name); + if (! be_quiet) + printf(" statfile used: %s\n",Tstat); + statf = TRUE; + if (logf) /* logfile still to come ? */ + break; /* no finished */ + continue; + } + } + fclose(Conf); + } + + if (! be_quiet) + { + if (! logf) + puts(" logfile used: - default -"); + if (! statf) + puts(" statfile used: - default -"); + } + +return 0; +} + + + /* ------------------------------------------------------------------ + * hdrprt - Print Header/Trailer lines (constant data) + * ------------------------------------------------------------------ + */ + +static void hdrprt(char head, int bot) +{ + switch(head) + { + case('s'): /* standard summary report */ + if (bot == 0) + { + puts("\nCompact summary:"); + puts("----------------"); + puts("\ +Name of + Files + +------- Bytes/1000 --------+ +------ Time -----+ + Avg CPS +\n\ +site in out inbound outbound total inbound outbound in out\n\ +-------- ---- ---- --------- --------- --------- --------- --------- ----- -----"); + } + else + puts("\ +--------------------------------------------------------------------------------"); + break; + + + case('f'): /* file statistic report */ + if (bot == 0) + { + puts("\nFile statistics:"); + puts("----------------"); + puts(" Name of +----------- Inbound -----------+ +---------- Outbound -----------+"); + puts(" site files Bytes/1000 xfr time B/sec files Bytes/1000 xfr time B/sec"); + puts(" -------- ----- ----------- --------- ----- ----- ----------- --------- -----"); + } + else + puts("\ + ----------------------------------------------------------------------------"); + break; + + + case('c'): /* calls statistic report */ + if (bot == 0) + { + puts("\nCall statistics:"); + puts("----------------"); + puts(" Name of +------- Outbound Calls -------+ +-------- Inbound Calls ------+"); + puts(" site succ. failed total time succ. failed total time"); + puts(" -------- ------ ------ ------ --------- ------ ------ ------ ---------"); + } + else + puts("\ + ----------------------------------------------------------------------------"); + break; + + + case('e'): /* efficiency statistic report */ + if (bot == 0) + { + puts("\nEfficiency:"); + puts("-----------"); + puts(" Name of +------ Times inbound/outbound -------+"); + puts(" site connected xfr time overhead eff. %"); + puts(" -------- --------- --------- --------- ------"); + } + else + puts(" -------------------------------------------------"); + break; + + case('i'): /* Environment information */ + if (bot == 0) + { + puts("\nEnvironment Information:"); + puts("------------------------"); + printf(" Default config: %s\n",D_conf == NULL ? + noConf:D_conf); + printf(" Default logfile: %s\n",Tlog); + printf(" Default statfile: %s\n\n",Tstat); + } + break; + + case('d'): /* Date/time coverage */ + if (bot == 0) + { + puts("\n Date coverage of input files:"); + puts(" Name of +----- Start -----+ +------ End ------+"); + puts(" file date time date time"); + puts(" -------- ---------- -------- ---------- --------"); + } + break; + + case('p'): /* Protocol stats */ + if (bot == 0) + { + puts("\nProtocol packet report:"); + puts("-----------------------"); + puts(" +------- protocol -----+ +--------- Packets ----------+"); + puts("Name of packet window "); + puts("site typ min max min max sent resent received"); + puts("-------- --- ---- ---- ---- ---- ----------- ------- ----------"); + } + else + { + puts("\nProtocol error report:"); + puts("----------------------"); + puts("Name of +----------------- Error Types --------------------+"); + puts("site typ header checksum order rem-reject"); + puts("-------- --- ----------- ---------- ----------- ----------"); + } + break; + + default: + if (bot == 0) + { + puts("\nNo header for this report defined:"); + } + else + puts(" "); + break; + } +} diff --git a/gnu/libexec/uucp/contrib/uurate.man b/gnu/libexec/uucp/contrib/uurate.man new file mode 100644 index 00000000000..13f79a313fa --- /dev/null +++ b/gnu/libexec/uucp/contrib/uurate.man @@ -0,0 +1,280 @@ +''' $Id: uurate.man,v 1.1 1995/10/18 08:38:25 deraadt Exp $ +.TH uurate 1 +.SH NAME +uurate \- Report Taylor UUCP statistics +.SH SYNOPSIS +.BR uurate " [ " "\-acdefhipqtvx" " ] [ " "\-s " +.I host +.RI " ] [ " "\-I " +.I config +.RI " ][ " "logfile..." " ] " +.PP +or simply, +.PP +.B uurate +.PP +for a traffic summary report. +.SH DESCRIPTION +The +.I uurate +command provides tabular summary reports on the operation of the +Taylor UUCP system. Data is taken from the currently active log +files, standard input, or from a list of log files given on the +command line. Output is in the form of tabular reports summarizing +call, file transfer, and command execution +.RI "(" "uuxqt" ")" +activity. +.PP +The log and stats files given to +.I uurate +must be in the ``Taylor'' or ``V2'' format. Also, note that call and file +transfer activities are logged in separate files, nominally called +.I Log +and +.I Stats, +respectively. For reports to be meaningful, the +.I Log +and +.I Stats +files should be given to +.I uurate +together, and cover the same time period. +.PP +If neither the +.B \-i +or +.B \-I +option nor any +.I logfile +options are given, +.I uurate +defaults to taking its input from the current Taylor +.I Log +and +.I Stats +files. The names are either as defined at compilation time, in case +there is no config file, or taken from the arguments of the keywords +.I logfile +and +.I statfile +when encountered in the config file. +This is the normal mode of operation. +.PP +The reporting options described below can be used to select +the set of reports desired. If no options are given, a summary +report is displayed. If there is no relevant data for a particular +report or host, that report or host will be suppressed. +.SH OPTIONS +The following options may be given to +.I uurate: +.TP 5 +.B \-a +All reports. Identical to +.B \-cfexp. +.TP 5 +.B \-c +Report on call statistics. Requires data from a +.I Log +file. +.TP 5 +.B \-d +will print the default config file to be used. +.TP 5 +.B \-e +Report on efficiency (total connect time versus time spent transferring +files). Requires data from both a +.I Log +and a +.I Stats +file, and they must span the same time period. +.TP 5 +.B \-f +Report on file transfer statistics. Requires data from a +.I Stats +file. +.TP 5 +.B \-h +will print a short help information. +.TP 5 +.B \-i +tells uurate to read any logfile information from standard input. +.TP 5 +.B \-p +report on protocol errors and packets sent/received +.TP 5 +.B \-q +do not print the Environment information, +.TP 5 +.B \-t +All reports. Identical to +.B \-cfexp. +plus the +.B Compact summary. +.TP 5 +.B \-v +will print the version id string +.TP 5 +.B \-x +Report on remote execution requests (e.g., +.IR rmail ")." +Requires data from a +.I Log +file. +.TP 5 +.BI "\-s " "host" +Restrict report output to +.I host. +.TP 5 +.BI "\-I " "config file" +an alternate config file may be passed by this option. +.SH "DESCRIPTION OF REPORTS" +There are four reports available: the call, file transfer, efficiency, +and remote execution reports. Each may be selected by a command line +option. All reports may be selected via the options +.B \-a +or +.B \-t. +If no report selection options are given, +.I uurate +displays a compact traffic summary report (see below). +.SS "Summary report" +If no report options are given, +.I uurate +displays a traffic summary report. This is particularly useful in daily +.I cron +jobs which report on errors and the like. Traffic statistics for each +active system is reported on a single line. If more than one system was +active, a 'totals' line is included at the end of the report. +.SS "Protocol packet report" +The protocol report gives statistics on min/max packet and window sizes +used during transmission. Further on data is collected for packets +transferred. The data is collected for each host/protocol type. +The fields are described below: +.PP +.br +.nf +.in +.3i +.ta 1.0i +.BR "site " "UUCP node name of neighbor host system," +.BR "typ " "Type of protocol used" +.BR "Min " "minimum packet/window size" +.BR "Max " "maximum packet/window size" +.BR "sent " "packets sent" +.BR "resent " "packets resent" +.BR "received " "packets received" +.in -.3 +.SS "Protocol error report" +The protocol report gives statistics on packet errors +during transmission. The data is collected for each host/protocol type. +The fields are described below: +.PP +.br +.nf +.in +.3i +.ta 1.5i +.BR "site " "UUCP node name of neighbor host system," +.BR "typ " "Type of protocol used" +.BR "header " "number of errors in header" +.BR "checksum " "number of checksum errors" +.BR "order " "number of order errors" +.BR "resent " "number packets resent" +.BR "rem-reject " "packets that the remote site rejected" +.in -.3 +.SS "Call report" +The call report gives statistics on inbound and outbound calls for +each active host system. The fields are described below: +.PP +.br +.nf +.in +.3i +.ta 1.0i +.BR "site " "UUCP node name of neighbor host system," +.BR "succ. " "Successful calls attempted to/by that system," +.BR "failed " "Failed calls to/by that system," +.BR "total " "Total calls to/by that system," +.BR "time " "Collected connect time (hh:mm:ss) for all calls," +.in -.3 +.SS "File transfer reports" +The file transfer reports give statistics on inbound and +outbound file transfers (regardless of which end initiated the transfer) +for each active host system. There are two reports, one for files +sent to the remote system and one for files received from the remote +system. The fields in each report are described below: +.PP +.br +.nf +.in +.3i +.ta 1.0i +.BR "site " "UUCP node name of neighbor host system" +.BR "files " "Number of files transferred" +.BR "Bytes/1000 " "Total size of files transferred given in thousands" +.BR "xfr time " "Total time (hh:mm:ss) spent on transfer the files," +.BR "B/sec " "Average transfer rate (bytes/sec)." +.in -.3 +.SS "Efficiency report" +The efficiency report describes the utilization of the links +to each active remote system, giving the ratio of total connect time +to the time spent actually transferring files. +The fields are described below: +.PP +.br +.nf +.in +.3i +.ta 1.0i +.BR "site " "UUCP node name of neighbor host system" +.BR "connected " "Total connect time for that system (turn-around)" +.BR "xfr time " "Total file transfer time for that system" +.BR "overhead " "Connect time not used to transfer files," +.BR "eff. % " "Ratio of connect time to transfer time (xfer*100/conn)" +.in -.3 +.SS "Command executions report" +The remote execution report describes remotely +requested command executions from each active host system, like +.I rmail +and +.IR rnews "." +Up to eight command names are displayed. If there are more, the +rest will be put together in an `Misc.' column. +The fields are described below: +.PP +.br +.nf +.in +.3i +.ta 1.0i +.BR "site " "UUCP node name of neighbor host system," +.BR "(command) " "Number of requests of this command," +.BR "Misc. " "Number of other requests, if more than eight." +.in -.3i +.SS FILES +The file names below may be changed at compilation time or by the +configuration file, so these are only approximations. +.br +.nf +.in +.3in +.ta 2.2i +.IR "/usr/spool/uucp/Log " "V2/Taylor format call/execution log," +.IR "/usr/spool/uucp/Stats " "V2/Taylor format file transfer log." +.SS "SEE ALSO" +.IR uucico "(8)" +.SS BUGS +Does not understand other than V2/TAYLOR logging formats. Anyone care to +volunteer to add the not mentioned? +.PP +Scanning the arguments of logfile and statfile keywords +in config should handle lines continued with the backslash as well. +.PP +The +.B failfm +field in the call statistics table is always zero, unless +something really serious happens, e.g. uucico got SIGQUIT or +the whole system crashed. +.SS AUTHOR +Robert B. Denny (denny@alisa.com). +.br +Loosely based on the DECUS UUCP program +.I uurate +by Mark Pizzolato. +.br +Modified by Stephan Niemz (stephan@sunlab.ka.sub.org). +.br +Modified by Klaus Dahlenburg (kdburg@incoahe.hanse.de). diff --git a/gnu/libexec/uucp/contrib/uureroute.perl b/gnu/libexec/uucp/contrib/uureroute.perl new file mode 100644 index 00000000000..3eeb654e1e2 --- /dev/null +++ b/gnu/libexec/uucp/contrib/uureroute.perl @@ -0,0 +1,91 @@ +#!/usr/local/bin/perl +eval ' exec /usr/local/bin/perl $0 "$@" ' + if $running_under_some_shell; + +# From a script by <Bill.Campbell@celestial.com> +# Newsgroups: comp.sources.misc +# Subject: v28i073: uureroute - Reroute HDB queued mail, Part01/01 +# Date: 26 Feb 92 02:28:37 GMT +# +# This is a Honey DanBer specific routine written in perl to reroute all +# mail queued up for a specific host. It needs to be run as "root" since +# uucp will not allow itself to remove others requests. +# +# Revision *** 92/21/09: Francois Pinard <pinard@iro.umontreal.ca> +# 1. adapted for Taylor UUCP +# +# Revision 1.3 91/10/08 09:01:21 src +# 1. Rewritten in perl +# 2. Add -v option for debugging. +# +# Revision 1.2 91/10/07 23:57:42 root +# 1. Fix mail program path. +# 2. Truncate directory name to 7 characters + +($progname = $0) =~ s!.*/!!; # save this very early + +$USAGE = " +# Reroute uucp mail +# +# Usage: $progname [-v] host [host...] +# +# Options Argument Description +# -v Verbose (doesn't execute /bin/sh) +# +"; + +$UUSTAT = "/usr/local/bin/uustat"; +$SHELL = "/bin/sh"; +$SMAIL = "/bin/smail"; + +sub usage +{ + die join ("\n", @_) . "\n$USAGE\n"; +} + +do "getopts.pl"; + +&usage ("Invalid Option") unless do Getopts ("vV"); + +$verbose = ($opt_v ? '-v' : ()); +$suffix = ($verbose ? '' : $$); + +&usage ("No system specified") if $#ARGV < 0; + +if (!$verbose) +{ + open (SHELL, "| $SHELL"); + select SHELL; +} + +while ($system = shift) +{ + $sysprefix = substr ($system, 0, 7); + $directory = "/usr/spool/uucp/$sysprefix"; + open (UUSTAT, "$UUSTAT -s $system -c rmail |"); + print "set -ex\n"; + while (<UUSTAT>) + { + ($jobid, ) = split; + ($cfile) = substr ($jobid, length ($jobid) - 5); + $cfilename = "$directory/C./C.$cfile"; + open (CFILE, $cfilename) || die "Cannot open $cfilename\n"; + $_ = <CFILE>; + close CFILE; + if (/^E D\.(....) [^ ]+ [^ ]+ -CR D\.\1 0666 [^ ]+ 0 rmail (.*)/) + { + $datafile = "$directory/D./D.$1"; + $address = $2; + } + else + { + print STDERR; + die "Cannot parse previous line from $cfilename\n"; + } + print "$SMAIL -R $system!$address < $datafile && $UUSTAT -k $jobid\n"; + } + close UUSTAT; +} +close SHELL unless $verbose; + +exit 0; diff --git a/gnu/libexec/uucp/contrib/uusnap.c b/gnu/libexec/uucp/contrib/uusnap.c new file mode 100644 index 00000000000..71092993dc2 --- /dev/null +++ b/gnu/libexec/uucp/contrib/uusnap.c @@ -0,0 +1,321 @@ +/* uusnap.c + (c) 1992 Heiko W.Rupp hwr@pilhuhn.ka.sub.org + uusnap is a tool to display the activities of the connected + systems. + + Put a file uusnap.systems in NEWCONFIGDIR (see Makefile), in which + the systems, you want to monitor are listed, one on a single line. + The sequence of the files there determine the sequence of the + listing. + + At the moment it only works with taylor config and taylor dirs + + compile it form the Makefile or: + cc -c -g -pipe -O -I. -I. -DNEWCONFIGLIB=\"/usr/local/lib/uucp\" uusnap.c + cc -o uusnap uusnap.o + For this, uusnap.[ch] must be in the same directory as uucp.h and so. + + uusnap must have read access to SPOOLDIR/.Status in order to work. +*/ + +#define MAXSYS 30 /* maximum number of systems */ +#define WAIT_NORMAL 10 /* wait period if noone is talking */ +#define WAIT_TALKING 2 /* refresh display every second if */ + /* someone is talking with us */ + +#include "uucp.h" +#if USE_RCS_ID +char uusnap_rcsid[] = "$Id: uusnap.c,v 1.1 1995/10/18 08:38:25 deraadt Exp $"; +#endif + +#include <ctype.h> +#include <time.h> +#include <sys/types.h> +#include <sys/dir.h> + +extern char *ctime(time_t*); + +struct sysInfo { + char sysname[10]; /* name of the system to watch */ + char *statfile; /* name of its status file */ + char *spooldir; /* root of its spooldir */ + int in; /* number of unprocessed in-files */ + int out; /* number of files to send them */ + time_t last; /* last poll time */ + time_t next; /* time of next poll */ + time_t lastidir; /* time of last in-spooldir access */ + time_t lastodir; /* time of last outgoing spd acc */ + time_t laststat; /* time of last status file access */ + int status; /* status of the system */ + int num_retries; /* number of retries */ +}; + +struct sysInfo Systems[MAXSYS]; + + +/* I have extend the system status. If time for the specified system + is Never, I say so. To get this to work, one also should extend + uucico.c. It is not important to do this. With the normal uucico, + one only gets no status. +*/ + +const char *azStatus[] = /* Status codes as defined by uucico */ +{ /* listing them here instead of */ + "Conversation complete", /* including the appropriate file */ + "Port unavailable", /* reduces the size of the executable */ + "Dial failed", + "Login failed", + "Handshake failed", + "Call failed", + "Talking", + "Wrong time to call", + "Time to call = Never !" +}; + +main() +{ + int i; + i=get_systems(); + display_info(i); + + exit(0); +} + +int +get_systems() +{ + char filename[1024]; + char fn[1024]; + char line[80]; + FILE *fp; + int i=0; + int j; + struct stat stbuf; + struct sysInfo sys; + + strcpy(filename,NEWCONFIGLIB); + strcat(filename,"/uusnap.systems"); + if ((fp=fopen(filename,"r"))!=NULL) { + while (fgets(line,80,fp)!=NULL) { + *(rindex(line,'\n'))='\0'; + strcpy(sys.sysname,line); /* get the name of the system */ + strcpy(fn,SPOOLDIR); /* get the name of the statusfile */ + strcat(fn,"/.Status/"); + strcat(fn,line); + sys.statfile=malloc(strlen(fn)+1); + strcpy(sys.statfile,fn); + strcpy(fn,SPOOLDIR); /* get the name of the spooldir */ + strcat(fn,"/"); + strcat(fn,line); + sys.spooldir=malloc(strlen(fn)+1); + strcpy(sys.spooldir,fn); + sys.laststat=0; + sys.lastidir=sys.lastodir=0; + Systems[i]=sys; /* get_stat_for_system needs it */ + get_stat_for_system(i); /* now get the system status */ + get_inq_num(i,TRUE); /* number of unprocessed files */ + get_outq_num(i,TRUE); /* number of files to send */ + i++; + } + fclose(fp); + } + else { + fprintf(stderr,"Can't open %s \n",filename); + exit(1); + } + return i; +} + + + +display_info(int numSys) +{ + char *filename; + int sysnum; + FILE *fp; + char contentline[80]; + char isTalking=FALSE; + struct stat stbuf; + struct sysInfo sys; + time_t time; + + filename = (char*)malloc(1024); + if (filename == NULL) { + fprintf(stderr, "Can't malloc 1024 bytes"); + exit(1); + } + + while(TRUE) { + display_headline(); + for (sysnum=0;sysnum<numSys;sysnum++) { + sys = Systems[sysnum]; + stat(sys.statfile,&stbuf); + if ((time=stbuf.st_atime) > sys.laststat) { + get_stat_for_system(sysnum); + } + if(display_status_line(sysnum)==1) + isTalking=TRUE; + } + if (isTalking) { + sleep(WAIT_TALKING); + isTalking = FALSE; + } + else + sleep(WAIT_NORMAL); /* wait a bit */ + } + return 0; +} + +int +display_status_line(int sn) +{ + char *time_s; + + int sys_stat,num_retries,wait; + int i; + time_t last_time; + time_t next_time; + + struct sysInfo sys; + + sys = Systems[sn]; + + printf("%10s ",sys.sysname); + get_inq_num(sn); + if (sys.in==0) + printf(" "); + else + printf("%3d ",sys.in); + get_outq_num(sn); + if (sys.out==0) + printf(" "); + else + printf("%3d ",sys.out); + time_s = ctime(&sys.last); + time_s = time_s + 11; + *(time_s+8)='\0'; + printf("%8s ",time_s); /* time of last poll */ + time_s = ctime(&sys.next); + time_s = time_s + 11; + *(time_s+8)='\0'; + if (sys.last == sys.next) + printf(" "); + else + printf("%8s ",time_s); /* time of next poll */ + if (sys.num_retries==0) + printf(" "); + else + printf("%2d ",sys.num_retries); + if (sys_stat==6) /* system is talking */ + printf("\E[7m"); /* reverse video on */ + printf("%s",azStatus[sys.status]); + if (sys.status==6) { + printf("\E[m\n"); /* reverse video off */ + return 1; + } + else { + printf("\n"); + return 0; + } +} + + +display_headline() +{ + printf("\E[;H\E[2J"); /* clear screen */ + printf("\E[7muusnap (press CTRL-C to escape)\E[m \n\n"); + printf(" System #in #out last next #ret Status\n"); + return 0; +} + +get_inq_num(int num,char firstTime) +{ + int i=0; + char filename[1024]; + struct stat stbuf; + DIR *dirp; + + strcpy(filename,Systems[num].spooldir); + strcat(filename,"/X./."); + stat(filename,&stbuf); + if ((stbuf.st_mtime > Systems[num].lastidir) || (firstTime)) { + if ((dirp=opendir(filename))!=NULL) { + while(readdir(dirp)) + i++; + closedir(dirp); + stat(filename,&stbuf); + Systems[num].lastidir=stbuf.st_mtime; + } + else { + fprintf(stderr,"Can't open %s \n",filename); + exit(1); + } + if (i>=2) + i-=2; /* correct . and .. */ + Systems[num].in=i; + } + return 0; +} + +get_outq_num(int sys,char firstTime) +{ + int i=0; + char filename[1024]; + struct stat stbuf; + DIR *dirp; + + strcpy(filename,Systems[sys].spooldir); + strcat(filename,"/C./."); + stat(filename,&stbuf); + if ((stbuf.st_mtime > Systems[sys].lastodir) || (firstTime)) { + if ((dirp=opendir(filename))!=NULL) { + while(readdir(dirp)) + i++; + closedir(dirp); + stat(filename,&stbuf); + Systems[sys].lastodir=stbuf.st_mtime; + } + else { + fprintf(stderr,"Can't open %s \n",filename); + exit(1); + } + if (i>=2) + i-=2; /* correct . and .. */ + Systems[sys].out=i; + } + return 0; +} + +get_stat_for_system(int i) +{ + char fn[80]; + struct sysInfo sys; + struct stat stbuf; + FILE *fp; + time_t wait; + + sys = Systems[i]; + stat(sys.statfile,&stbuf); + if (stbuf.st_atime > sys.laststat) { + if ((fp=fopen(sys.statfile,"r"))!=NULL) { + fgets(fn,80,fp); + fclose(fp); + sscanf(fn,"%d %d %ld %d", + &sys.status, + &sys.num_retries, + &sys.last, + &wait); + sys.next=sys.last+wait; + } + else { + sys.status=0; + sys.num_retries=0; + sys.last=0; + sys.next=0; + } + stat(sys.statfile,&stbuf); + sys.laststat=stbuf.st_atime; + } + Systems[i] = sys; + return 0; +} diff --git a/gnu/libexec/uucp/contrib/uutraf b/gnu/libexec/uucp/contrib/uutraf new file mode 100644 index 00000000000..00e4b035f72 --- /dev/null +++ b/gnu/libexec/uucp/contrib/uutraf @@ -0,0 +1,210 @@ +#!/usr/bin/perl +# uutraf.pl -- UUCP Traffic Analyzer +# SCCS Status : @(#)@ uutraf 1.8 +# Author : Johan Vromans +# Created On : *** +# Last Modified By: Johan Vromans +# Last Modified On: Mon Aug 30 15:02:22 1993 +# Update Count : 6 +# Status : OK +# Requires: : Perl V4 or later + +# Reads UUCP syslog, and generates a report from it. +# +# Created by Johan Vromans <jv@mh.nl> +# Loosely based on an idea by Greg Hackney (hack@texbell.swbt.com) + +# Usage: uutraf [-taylor|-hdb|-bnu|-bsd] [syslog] + +# Logfile formats: +# +# BSD: +# +# jv mhres (2/23-5:18) (698818735) received 135 b 2 secs +# root mhres (2/23-5:19) (698818742) sent 2365 b 3 secs, Pk: 38, Rxmt: 0 +# +# HDB: +# +# uunet!uucp M (12/10-09:04:22) (C,16390,1) [ttyXX] <- 2371 / 5.000 secs, \ +# 474 bytes/sec +# +# Taylor: +# +# jv mhres (1992-02-24 20:49:04.06) sent 16234 bytes in 148.780 seconds \ +# (109 bytes/sec) +# jv mhres (1992-02-24 21:04:05.76) received 449 bytes in 6.550 seconds \ +# (68 bytes/sec) + +$uucp_type = "gnu"; + +%hosts = (); # hosts seen +%bytes_in = (); # of bytes received from host +%bytes_out = (); # of bytes sent to host +%secs_in = (); # of seconds connect for recving +%secs_out = (); # of seconds connect for sending +%files_in = (); # of input requests +%files_out = (); # of output requests + +# read info, break the lines and tally + +if ( $ARGV[0] =~ /^-/ ) { + ($uucp_type = substr (shift (@ARGV), 1)) =~ tr/A-Z/a-z/; +} + +if ( $uucp_type eq "taylor" || $uucp_type eq "gnu" ) { + @ARGV = ("/usr/local/spool/uucp/Stats") unless $#ARGV >= 0; + $pat = "^[^ ]+ ([^ ]+) \\(([-0-9:\\/ .]+)\\) " . + "(sent|received) (\\d+) bytes in (\\d+)\\.(\\d+) seconds"; + $uucp_type = 0; + $recv = "received"; +} +elsif ( $uucp_type eq "hdb" || $uucp_type eq "bnu" ) { + @ARGV = ("/usr/spool/uucp/.Admin/xferstats") unless $#ARGV >= 0; + $pat = "^([^!]+)![^(]+\\(([-0-9:\\/]+)\\).+([<>])-? " . + "(\\d+) \\/ (\\d+)\\.(\\d+) secs"; + $uucp_type = 1; + $recv = "<"; +} +elsif ( $uucp_type eq "bsd" || $uucp_type eq "v7" ) { + @ARGV = ("/usr/spool/uucp/SYSLOG") unless $#ARGV >= 0; + $pat = "^[^ ]+ ([^ ]+) \\(([-0-9:\\/]+)\\) \\([^)]+\\) " . + "(sent|received) (\\d+) b (\\d+) secs"; + $uucp_type = 2; + $recv = "received"; +} +else { + die ("FATAL: Unknown UUCP type: $uucp_type\n"); +} + +$garbage = 0; + +while ( <> ) { + unless ( /$pat/o ) { + print STDERR "$_"; + next if /failed/; + if ( $garbage++ > 10 ) { + die ("FATAL: Too much garbage; wrong UUCP type?\n"); + } + next; + } + + # gather timestamps + $last_date = $2; + $first_date = $last_date unless defined $first_date; + + # initialize new hosts + unless ( defined $hosts{$1} ) { + $hosts{$1} = $files_in{$1} = $files_out{$1} = + $bytes_in{$1} = $bytes_out{$1} = + $secs_in{$1} = $secs_out{$1} = 0; + } + + # Taylor and HDB have milliseconds, BSD has not. + $secs = ($uucp_type == 2) ? ($5 + ($5 == 0 ? 0.5 : 0)) : ($5 + $6/1000); + + # tally + if ( $3 eq $recv ) { # recv + $bytes_in{$1} += $4; + $files_in{$1}++; + $secs_in{$1} += $secs; + } + else { # xmit + $bytes_out{$1} += $4; + $files_out{$1}++; + $secs_out{$1} += $secs; + } + $garbage = 0; +} + +@hosts = keys (%hosts); +die ("No info found, stopped\n") if $#hosts < 0; + +################ report section ################ + +$thishost = &gethostname(); +$thishost = (defined $thishost) ? "on node $thishost" : "report"; + +if ( $uucp_type eq 0 ) { # Taylor UUCP + substr ($first_date, 16) = ""; + substr ($last_date, 16) = ""; +} + +format std_head = +@||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +"UUCP traffic $thishost from $first_date to $last_date" + +Remote -----------K-Bytes----------- ----Hours---- --Avg CPS-- --Files-- + Host Recv Sent Total Recv Sent Recv Sent Recv Sent +. +format std_out = +@<<<<<<< @>>>>>>>> @>>>>>>>> @>>>>>>>> @>>>>> @>>>>> @>>>> @>>>> @>>> @>>> +$Zhost, $Zi_bytes, $Zo_bytes, $Zt_bytes, $Zi_hrs, $Zo_hrs, $Zi_acps, $Zo_acps, $Zi_count, $Zo_count +. + +$^ = "std_head"; +$~ = "std_out"; + +&print_dashes (); + +reset "T"; # reset totals + +foreach $host (@hosts) { + &print_line ($host, $bytes_in{$host}, $bytes_out{$host}, + $secs_in{$host}, $secs_out{$host}, + $files_in{$host}, $files_out{$host}); + +} + +&print_dashes (); +&print_line ("Total", $Ti_bytes, $To_bytes, + $Ti_secs, $To_secs, $Ti_count, $To_count); + +################ that's it ################ + +sub print_line { + reset "Z"; # reset print fields + local ($Zhost, + $Zi_bytes, $Zo_bytes, + $Zi_secs, $Zo_secs, + $Zi_count, $Zo_count) = @_; + $Ti_bytes += $Zi_bytes; + $To_bytes += $Zo_bytes; + $Zt_bytes = $Zi_bytes + $Zo_bytes; + $Tt_bytes += $Zt_bytes; + $Zi_acps = ($Zi_secs > 0) ? sprintf ("%.0f", $Zi_bytes/$Zi_secs) : "0"; + $Zo_acps = ($Zo_secs > 0) ? sprintf ("%.0f", $Zo_bytes/$Zo_secs) : "0"; + $Zi_bytes = sprintf ("%.1f", $Zi_bytes/1000); + $Zo_bytes = sprintf ("%.1f", $Zo_bytes/1000); + $Zt_bytes = sprintf ("%.1f", $Zt_bytes/1000); + $Zi_hrs = sprintf ("%.1f", $Zi_secs/3600); + $Zo_hrs = sprintf ("%.1f", $Zo_secs/3600); + $Ti_secs += $Zi_secs; + $To_secs += $Zo_secs; + $Ti_count += $Zi_count; + $To_count += $Zo_count; + write; +} + +sub print_dashes { + $Zhost = $Zi_bytes = $Zo_bytes = $Zt_bytes = + $Zi_hrs = $Zo_hrs = $Zi_acps = $Zo_acps = $Zi_count = $Zo_count = + "------------"; + write; + # easy, isn't it? +} + +################ missing ################ + +sub gethostname { + $ENV{"SHELL"} = "/bin/sh"; + $try = `(hostname) 2>/dev/null`; + chop $try; + return $+ if $try =~ /^[-.\w]+$/; + $try = `uname -n 2>/dev/null`; + chop $try; + return $+ if $try =~ /^[-.\w]+$/; + $try = `uuname -l 2>/dev/null`; + chop $try; + return $+ if $try =~ /^[-.\w]+$/; + return undef; +} diff --git a/gnu/libexec/uucp/contrib/uutry b/gnu/libexec/uucp/contrib/uutry new file mode 100644 index 00000000000..258bb302f09 --- /dev/null +++ b/gnu/libexec/uucp/contrib/uutry @@ -0,0 +1,43 @@ +#!/bin/sh +# +# This script was hacked together by Marc Evans (marc@Synergytics.Com) +# I claim no copyright to it and don't really care what people do +# with it, hence, it is public domain. I take no responsibility for +# for happens if you use this script, providing no warentee. This +# section of the comments may be removed if you so desire. +# +# Usage: +# uutry [-x#] systemname +# where '-x#' has the value [0-9], higher values providing more detail + +# +# The following variables should be gropped from the configuration +# files rather then being hard coded here. +# +Spool=/usr/spool/uucp +Lib=/usr/local/lib/uucp +Status=$Spool/.Status +Debug=$Spool/Debug +Uucico=$Lib/uucico +# +# Default option values +# +x="-x5" +s="" + +for i in $* ; do + case $i in + -x*) x="$i" ;; + *) s="$i" ;; + esac +done + +if [ x$s != x ]; then + rm -f $Status/$s + $Uucico -r1 $x -s$s & + >$Debug + tail -f $Debug +else + echo "Usage: uutry systemname" + exit 1 +fi diff --git a/gnu/libexec/uucp/contrib/uuxconv b/gnu/libexec/uucp/contrib/uuxconv new file mode 100644 index 00000000000..843f9e000fa --- /dev/null +++ b/gnu/libexec/uucp/contrib/uuxconv @@ -0,0 +1,50 @@ +#!/bin/sh +# +# uuxconv +# +# After converting to Taylor from SVR4.03 UUCP, I still had a lot of +# jobs queued up to go out. +# +# This script is a one-shot to mass-requeue a site's spool. +# +# It doesn't go and do your whole spool, nor even all grades. +# you need to go into each grade directory for each site and +# execute this. +# +# i.e.: You have a site named 'foo' +# cd /var/spool/uucp/foo/Z +# uuxconv foo +# +# it does delete the 'D' & 'X' after requeing them, but doesn't remove +# the 'C' files. +# +# I foolishly went and ran this script on all my queued jobs, without +# adding the improvements to recursively go through the entire UUCP spool, +# so now I'm out of files to test with. I don't want to add the code +# to do that since I can't test it, and this worked. +# +# I hereby give this (trivial :-)) program to the GNU Project/FSF +# and Ian Taylor in it's entirety, so that it can be placed in +# the contrib directory of taylor-uucp, and save others the pain +# of rewriting it. +# +# Richard Nickle (rick@trystro.uucp, rnickle@gnu.ai.mit.edu) +# May 27, 1993 +# +if [ $# -eq 0 ] +then + echo "Usage: $0 sitename" + exit 1 +fi +exit 0 +site=$1 +tsite=`echo $site | cut -c1-5` +find . -name "D.$tsite*" -print | +while read file +do + control=`egrep "^C" $file | cut -c3-` + input=`egrep "^I" $file | cut -c3-` + (uux - -r -z $site!$control < $input) && (rm $file $input) + echo "$site!$control < $input" +done +exit 0 diff --git a/gnu/libexec/uucp/contrib/xc-conf.h-dist b/gnu/libexec/uucp/contrib/xc-conf.h-dist new file mode 100644 index 00000000000..8810dd78d92 --- /dev/null +++ b/gnu/libexec/uucp/contrib/xc-conf.h-dist @@ -0,0 +1,38 @@ +/* + * ************* + * * XC-CONF.H * + * ************* + * + * Configuration file for xchat 1.1. Edit this file prior to make-ing + * xchat. + * + * History: + * Bob Denny - Tue Sep 1 11:42:54 1992 + */ + +/* + * Edit this to reflect the relative location of xchat sources to + * the main Taylor UUCP source directory. As distributed, xchat + * is in the ./contrib sub-directory under the main Taylor UUCP + * directory. Therefore, Taylor's conf.h is in our parent directory. + */ +#include "../conf.h" + +/* + * The following definition establishes the default path to the + * scripts used by xchat. You may lleave this blank (""), but + * the command line given to xchat (e.g., in the 'sys' file entry) + * must specify a full (absolute) path name to the script to be + * executed. Normally, this is the same place you put your config + * and system files for UUCP. + */ +#define SCRIPT_DIR "/usr/local/conf/uucp/" /* MUST HAVE TRAILING "/" */ + +/* + * The following definition establishes the default path to the + * log files that are produced by the 'dbgfile' statement. Normally + * this is the same location you configured Taylor UUCP to put its + * log files. + */ +#define LOG_DIR "/usr/spool/uucp/" /* MUST HAVE TRAILING "/" */ + diff --git a/gnu/libexec/uucp/contrib/xchat.c b/gnu/libexec/uucp/contrib/xchat.c new file mode 100644 index 00000000000..b44549e53ed --- /dev/null +++ b/gnu/libexec/uucp/contrib/xchat.c @@ -0,0 +1,1473 @@ +/* + * *********** + * * XCHAT.C * + * *********** + * + * Extended chat processor for Taylor UUCP. See accompanying documentation. + * + * Written by: + * Bob Denny (denny@alisa.com) + * Based on code in DECUS UUCP (for VAX/VMS) + * + * Small modification by: + * Daniel Hagerty (hag@eddie.mit.edu) + * + * History: + * Version 1.0 shipped with Taylor 1.03. No configuration info inside. + * + * Bob Denny - Sun Aug 30 18:41:30 1992 + * V1.1 - long overdue changes for other systems. Rip out interval + * timer code, use timer code from Taylor UUCP, use select() + * for timed reads. Use Taylor UUCP "conf.h" file to set + * configuration for this program. Add defaulting of script + * and log file paths. + * + * Daniel Hagerty - Mon Nov 22 18:17:38 1993 + * V1.2 - Added a new opcode to xchat. "expectstr" is a cross between + * sendstr and expect, looking for a parameter supplied string. + * Useful where a prompt could change for different dial in + * lines and such. + * + * Bugs: + * Does not support BSD terminal I/O. Anyone care to add it? + */ + +#include <sys/types.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <signal.h> +#include <time.h> +#include <sys/ioctl.h> +#include <sys/termio.h> + +#include "xc-conf.h" + +/* + * Pick a timing routine to use, as done in Taylor UUCP. + */ +#if HAVE_USLEEP || HAVE_NAP || HAVE_NAPMS || HAVE_POLL +#define USE_SELECT_TIMER 0 +#else +#define USE_SELECT_TIMER HAVE_SELECT +#if USE_SELECT_TIMER +#include <sys/time.h> +#endif +#endif + +#if HAVE_USLEEP || HAVE_NAP || HAVE_NAPMS +#undef HAVE_POLL +#define HAVE_POLL 0 +#endif + +#if HAVE_USLEEP || HAVE_NAP +#undef HAVE_NAPMS +#define HAVE_NAPMS 0 +#endif + +#if HAVE_USLEEP +#undef HAVE_NAP +#define HAVE_NAP 0 +#endif + +static int ttblind(); +static int ttcd(); + +/* script entry -- "compiled" form of dial, hangup, or login script */ + +struct script { + struct script *next; /* pointer to next entry, or null */ + int opcode; /* numeric opcode */ + char *strprm; /* pointer to string param */ + long intprm; /* integer parameter */ + char *newstate; /* new state name */ +}; + +/* opcode definition array element -- one for each possible opcode */ + +struct script_opdef { + char *opname; + int opcode; /* numeric opcode -- same as array index */ + int prmtype; /* one of SC_NONE, SC_STR, SC_XSTR, SC_INT */ + int newstate; /* one of SC_NONE, SC_NWST */ +}; + + /* values for opcode */ + +#define SC_LABEL 0 /* "label" (state name) */ +#define SC_CDLY 1 /* set char output delay in msec */ +#define SC_PCHR 2 /* pause char for dial string (from P in input) */ +#define SC_PTIM 3 /* seconds to allow for pause char */ +#define SC_WCHR 4 /* wait char for dial string (from W in input) */ +#define SC_WTIM 5 /* seconds to allow for wait char */ +#define SC_ZERO 6 /* zero counter */ +#define SC_INCR 7 /* increment counter */ +#define SC_IFGT 8 /* change state if counter > int param */ +#define SC_WAIT 9 /* wait for int param seconds */ +#define SC_GOTO 10 /* unconditional change to new state */ +#define SC_SEND 11 /* send strparam (after sprintf substitutions) */ +#define SC_BRK 12 /* send a break */ +#define SC_HANG 13 /* drop DTR */ +#define SC_DIAL 14 /* send telno string (after subst PCHR & WCHR) */ +#define SC_DTIM 15 /* time in msec per digit (for timeout calculations) */ + /* default = 100 (one tenth second) */ +#define SC_CTIM 16 /* additional time (in seconds) to wait for carrier */ + /* default = 45 seconds */ +#define SC_EXIT 17 /* script done, success */ +#define SC_FAIL 18 /* script done, failure */ +#define SC_LOG 19 /* write strparam to uucp.log */ +#define SC_LOGE 20 /* write strparam to uucp.log w/error ind */ +#define SC_DBG 21 /* write strparam to debug log if debug lvl = LGI */ +#define SC_DBGE 22 /* write strparam to debug log if debug lvl = LGIE */ +#define SC_DBST 23 /* 'or' intparam into debug mask */ +#define SC_DBCL 24 /* 'bicl' intparam into debug mask */ +#define SC_TIMO 25 /* newstate if no match in intparam secs */ + /* (uses calculated dial time if intparam is 0) */ +#define SC_XPCT 26 /* wait for strparam, goto _newstate if found */ +#define SC_CARR 27 /* goto _newstate if carrier detected */ +#define SC_FLSH 28 /* flush typeahead buffer */ +#define SC_IFBL 29 /* change state if controller is blind w/o CD */ +#define SC_IFBG 30 /* chg state if ctlr is blind and counter > intprm */ +#define SC_SNDP 31 /* send parameter n */ +#define SC_IF1P 32 /* if parameter n present */ +#define SC_IF0P 33 /* if parameter n absent */ +#define SC_DBOF 34 /* open debugging file */ +#define SC_TELN 35 /* Set telno from parameter n */ +#define SC_7BIT 36 /* Set port to 7-bit stripping */ +#define SC_8BIT 37 /* Set port for 8-bit characters */ +#define SC_PNON 38 /* Set port for 8-bit, no parity */ +#define SC_PEVN 39 /* Set port for 7-bit, even parity */ +#define SC_PODD 40 /* Set port for 7-bit, odd parity */ +#define SC_HUPS 41 /* Change state on HUP signal */ +#define SC_XPST 42 /* Expect a param string */ +#define SC_END 43 /* end of array */ + + /* values for prmtype, prm2type */ + +#define SC_NONE 0 /* no parameter */ +#define SC_STR 1 /* simple string */ +#define SC_INT 2 /* integer */ +#define SC_NWST 3 /* new state name */ +#define SC_XSTR 4 /* translated string */ + +/* opcode definition table for dial/login/hangup scripts */ + +static struct script_opdef sc_opdef[] = + { + {"label", SC_LABEL, SC_NONE, SC_NONE}, + {"chrdly", SC_CDLY, SC_INT, SC_NONE}, + {"pchar", SC_PCHR, SC_STR, SC_NONE}, + {"ptime", SC_PTIM, SC_INT, SC_NONE}, + {"wchar", SC_WCHR, SC_STR, SC_NONE}, + {"wtime", SC_WTIM, SC_INT, SC_NONE}, + {"zero", SC_ZERO, SC_NONE, SC_NONE}, + {"count", SC_INCR, SC_NONE, SC_NONE}, + {"ifgtr", SC_IFGT, SC_INT, SC_NWST}, + {"sleep", SC_WAIT, SC_INT, SC_NONE}, + {"goto", SC_GOTO, SC_NONE, SC_NWST}, + {"send", SC_SEND, SC_XSTR, SC_NONE}, + {"break", SC_BRK, SC_NONE, SC_NONE}, + {"hangup", SC_HANG, SC_NONE, SC_NONE}, + {"7bit", SC_7BIT, SC_NONE, SC_NONE}, + {"8bit", SC_8BIT, SC_NONE, SC_NONE}, + {"nopar", SC_PNON, SC_NONE, SC_NONE}, + {"evenpar", SC_PEVN, SC_NONE, SC_NONE}, + {"oddpar", SC_PODD, SC_NONE, SC_NONE}, + {"telno", SC_TELN, SC_INT, SC_NONE}, + {"dial", SC_DIAL, SC_NONE, SC_NONE}, + {"dgttime", SC_DTIM, SC_INT, SC_NONE}, + {"ctime", SC_CTIM, SC_INT, SC_NONE}, + {"success", SC_EXIT, SC_NONE, SC_NONE}, + {"failed", SC_FAIL, SC_NONE, SC_NONE}, + {"log", SC_LOG, SC_XSTR, SC_NONE}, + {"logerr", SC_LOGE, SC_XSTR, SC_NONE}, + {"debug", SC_DBG, SC_XSTR, SC_NONE}, + {"debuge", SC_DBGE, SC_XSTR, SC_NONE}, + {"dbgset", SC_DBST, SC_INT, SC_NONE}, + {"dbgclr", SC_DBCL, SC_INT, SC_NONE}, + {"dbgfile", SC_DBOF, SC_XSTR, SC_NONE}, + {"timeout", SC_TIMO, SC_INT, SC_NWST}, + {"expect", SC_XPCT, SC_XSTR, SC_NWST}, + {"ifcarr", SC_CARR, SC_NONE, SC_NWST}, + {"ifhang", SC_HUPS, SC_NONE, SC_NWST}, + {"flush", SC_FLSH, SC_NONE, SC_NONE}, + {"ifblind", SC_IFBL, SC_NONE, SC_NWST}, + {"ifblgtr", SC_IFBG, SC_INT, SC_NWST}, + {"sendstr", SC_SNDP, SC_INT, SC_NONE}, + {"ifstr", SC_IF1P, SC_INT, SC_NWST}, + {"ifnstr", SC_IF0P, SC_INT, SC_NWST}, + {"expectstr", SC_XPST, SC_INT, SC_NWST}, + {"table end", SC_END, SC_NONE, SC_NONE} + }; + +#define SUCCESS 0 +#define FAIL 1 +#define ERROR -1 +#define MAX_SCLINE 255 /* max length of a line in a script file */ +#define MAX_EXPCT 127 /* max length of an expect string */ +#define CTL_DELIM " \t\n\r" /* Delimiters for tokens */ +#define SAME 0 /* if (strcmp(a,b) == SAME) ... */ +#define SLOP 10 /* Slop space on arrays */ +#define MAX_STRING 200 /* Max length string to send/expect */ + +#define DEBUG_LEVEL(level) \ + (Debug & (1 << level)) + +#define DB_LOG 0 /* error messages and a copy of the LOGFILE output */ +#define DB_LGIE 1 /* dial,login,init trace -- errors only */ +#define DB_LGI 2 /* dial,login,init trace -- nonerrors (incl chr I/O) */ +#define DB_LGII 3 /* script processing internals */ + +#define TRUE 1 +#define FALSE 0 + +#define NONE 0 +#define EVEN 1 +#define ODD 2 + +#define logit(m, p1) fprintf(stderr, "%s %s\n", m, p1) + +static char **paramv; /* Parameter vector */ +static int paramc; /* Parameter count */ +static char telno[64]; /* Telephone number w/meta-chars */ +static int Debug; +static int fShangup = FALSE; /* TRUE if HUP signal received */ +static FILE *dbf = NULL; +static struct termio old, new; + +extern int usignal(); +extern int uhup(); + +static struct siglist +{ + int signal; + int (*o_catcher) (); + int (*n_catcher) (); +} sigtbl[] = { + { SIGHUP, NULL, uhup }, + { SIGINT, NULL, usignal }, + { SIGIOT, NULL, usignal }, + { SIGQUIT, NULL, usignal }, + { SIGTERM, NULL, usignal }, + { SIGALRM, NULL, usignal }, + { 0, NULL, NULL } /* Table end */ + }; + +extern struct script *read_script(); +extern void msleep(); +extern char xgetc(); +extern void charlog(); +extern void setup_tty(); +extern void restore_tty(); +extern void ttoslow(); +extern void ttflui(); +extern void tthang(); +extern void ttbreak(); +extern void tt7bit(); +extern void ttpar(); +extern void DEBUG(); + +extern void *malloc(); + + +/* + * ********************************** + * * BEGIN EXECUTION - MAIN PROGRAM * + * ********************************** + * + * This program is called by Taylor UUCP with a list of + * arguments in argc/argv, and stdin/stdout mapped to the + * tty device, and stderr mapped to the Taylor logfile, where + * anything written to stdout will be logged as an error. + * + */ +int main(argc, argv) +int argc; +char *argv[]; +{ + int i, stat; + FILE *sf; + char sfname[256]; + struct script *script; + struct siglist *sigs; + + /* + * The following is needed because my cpp does not have the + * #error directive... + */ +#if ! HAVE_SELECT + no_select_sorry(); /* Sad way to fail make */ +#endif + + paramv = &argv[2]; /* Parameters start at 2nd arg */ + paramc = argc - 2; /* Number of live parameters */ + + telno[0] = '\0'; + + if (argc < 2) + { + fprintf(stderr, "%s: no script file supplied\n", argv[0]); + exit(FAIL); + } + + /* + * If the script file argument begins with '/', then we assume + * it is an absolute pathname, otherwise, we prepend the + * SCRIPT_DIR path. + */ + *sfname = '\0'; /* Empty name string */ + if(argv[1][0] != '/') /* If relative path */ + strcat(sfname, SCRIPT_DIR); /* Prepend the default dir. */ + strcat(sfname, argv[1]); /* Add the script file name */ + + /* + * Now open the script file. + */ + if ((sf = fopen(sfname, "r")) == NULL) + { + fprintf(stderr, "%s: Failed to open script %s\n", argv[0], sfname); + perror(" "); + exit(FAIL); + } + + /* + * COMPILE SCRIPT + */ + if ((script = read_script(sf)) == NULL) + { + fprintf(stderr, "%s: script error in \"%s\"\n", argv[0], argv[1]); + exit(FAIL); + } + + /* + * Set up a signal catcher so the line can be returned to + * it's current state if something nasty happens. + */ + sigs = &sigtbl[0]; + while(sigs->signal) + { + sigs->o_catcher = (int (*) ())signal(sigs->signal, sigs->n_catcher); + sigs += 1; + } + + /* + * Save current tty settings, then set up raw, single + * character input processing, with 7-bit stripping. + */ + setup_tty(); + + /* + * EXECUTE SCRIPT + */ + if ((stat = do_script(script)) != SUCCESS) + fprintf(stderr, "%s: script %s failed.\n", argv[0], argv[1]); + + /* + * Clean up and exit. + */ + restore_tty(); +#ifdef FIXSIGS + sigs = &sigtbl[0]; + while(sigs->signal) + if(sigs->o_catcher != -1) + signal(sigs->signal, sigs->o_catcher); +#endif + exit(stat); +} + +/* + * deal_script - deallocate a script and all strings it points to + */ +int deal_script(loc) +struct script *loc; +{ + /* + * If pointer is null, just exit + */ + if (loc == (struct script *)NULL) + return SUCCESS; + + /* + * Deallocate the rest of the script + */ + deal_script(loc->next); + + /* + * Deallocate the string parameter, if any + */ + if (loc->strprm != (char *)NULL) + free(loc->strprm); + + /* + * Deallocate the new state name parameter, if any + */ + if (loc->newstate != (char *)NULL) + free(loc->newstate); + + /* + * Deallocate this entry + */ + free(loc); + + return SUCCESS; +} + + +/* + * read_script + * + * Read & compile a script, return pointer to first entry, or null if bad + */ +struct script *read_script(fd) + FILE *fd; +{ + struct script *this = NULL; + struct script *prev = NULL; + struct script *first = NULL; + long len, i; + char inpline[MAX_SCLINE]; + char inpcopy[MAX_SCLINE]; + char *c, *cln, *opc, *cp; + + /* + * MAIN COMPILATION LOOP + */ + while ((c = fgets(inpline, (sizeof inpline - 1), fd)) != (char *)NULL) + { + /* + * Skip comments and blank lines + */ + if (*c == '#' || *c == '\n') + continue; + + /* + * Get rid of the trailing newline, and copy the string + */ + inpline[strlen(inpline)-1] = '\0'; + strcpy(inpcopy, inpline); + + /* + * Look for text starting in the first col (a label) + */ + if ((!isspace(inpline[0])) && + (cln = strchr (inpline, ':')) != (char *)NULL) { + this = (struct script *)malloc (sizeof (struct script)); + if (prev != (struct script *)NULL) + prev->next = this; + prev = this; + if (first == (struct script *)NULL) + first = this; + this->next = (struct script *)NULL; + this->opcode = SC_LABEL; + len = cln - c; + this->strprm = (char *)malloc(len+1); + strncpy(this->strprm, c, len); + (this->strprm)[len] = '\0'; + this->intprm = 0; + this->newstate = (char *)NULL; + c = cln + 1; + } + + /* + * Now handle the opcode. Fold it to lower case. + */ + opc = strtok(c, CTL_DELIM); + if (opc == (char *)NULL) /* If no opcode... */ + continue; /* ...read the next line */ + cp = opc; + while(*cp) + tolower(*cp++); + + /* + * If we have an opcode but we haven't seen anything + * else (like a label) yet, i.e., this is the first + * entry, and there was no label. We need to + * cobble up a label so that read_script is happy + */ + if (first == (struct script *)NULL) + { + this = (struct script *)malloc (sizeof (struct script)); + prev = this; + first = this; + this->next = (struct script *)NULL; + this->opcode = SC_LABEL; + this->strprm = (char *)malloc(2); + strcpy(this->strprm, ":"); + this->intprm = 0; + this->newstate = (char *)NULL; + } + + /* + * Find opcode - ndex through the opcode definition table + */ + for (i=1; sc_opdef[i].opcode != SC_END; i++) + if (strcmp(opc, sc_opdef[i].opname) == SAME) + break; + if ((sc_opdef[i].opcode) == SC_END) + { + logit ("Bad opcode in script", opc); + deal_script(first); + return (struct script *)NULL; + } + + /* + * Found opcode. Allocate a new command node and initialize + */ + this = (struct script *)malloc(sizeof (struct script)); + prev->next = this; + prev = this; + this->next = (struct script *)NULL; + this->opcode = sc_opdef[i].opcode; + this->strprm = (char *)NULL; + this->intprm = 0; + this->newstate = (char *)NULL; + + /* + * Pick up new state parameter, if any + */ + if (sc_opdef[i].newstate == SC_NWST) + { + c = strtok((char *)NULL, CTL_DELIM); + if (c == (char *)NULL) + { + logit("Missing new state", opc); + deal_script(first); + return (struct script *)NULL; + } + else + { + this->newstate = (char *)malloc(strlen(c)+1); + strcpy(this->newstate, c); + } + } + + /* + * Pick up the string or integer parameter. Handle missing + * parameter gracefully. + */ + switch (sc_opdef[i].prmtype) + { + /* + * INT parameter - convert and store in node + */ + case SC_INT: + c = strtok((char *)NULL, CTL_DELIM); + if (c == (char *)NULL) + { + logit("Missing script param", opc); + deal_script(first); + return (struct script *)NULL; + } + /* + * If this is the parameter to DBST or DBCL, force + * base-10 conversion, else convert per parameter. + */ + if (sc_opdef[i].opcode == SC_DBST || + sc_opdef[i].opcode == SC_DBCL) + this->intprm = strtol(c, (char **)NULL, 0); + else + this->intprm = strtol(c, (char **)NULL, 10); + break; + + /* + * STR/XSTR strings. + */ + case SC_STR: + case SC_XSTR: + c = strtok((char *)NULL, CTL_DELIM); + if (c == (char *)NULL) + { + logit("Missing script param", opc); + deal_script(first); + return (struct script *)NULL; + } + /* + * For XSTR opcode, use c to find out where + * the string param begins in the copy of the + * input line, and pick up all that's left of + * the line (to allow imbedded blanks, etc.). + */ + if (sc_opdef[i].prmtype == SC_XSTR) + c = &inpcopy[0] + (c - &inpline[0]); + + /* + * Allocate a buffer for the string parameter + */ + this->strprm = (char *)malloc(strlen(c)+1); + + /* + * For XSTR, Translate the string and store its + * length. Note that, after escape sequences are + * compressed, the resulting string may well be a + * few bytes shorter than the input string (whose + * length was the basis for the malloc above), + * but it will never be longer. + */ + if (sc_opdef[i].prmtype == SC_XSTR) + { + this->intprm = xlat_str(this->strprm, c); + this->strprm[this->intprm] = '\0'; + } + else + strcpy(this->strprm, c); + break; + + } + } + + /* + * EOF + */ + return first; +} + + +/* + * xlat_str + * + * Translate embedded escape characters in a "send" or "expect" string. + * + * Called by read_script(), above. + * + * Returns the actual length of the resulting string. Note that imbedded + * nulls (specified by \000 in the input) ARE allowed in the result. + */ +xlat_str(out, in) + char *out, *in; +{ + register int i = 0, j = 0; + int byte, k; + + while (in[i]) + { + if (in[i] != '\\') + { + out[j++] = in[i++]; + } + else + { + switch (in[++i]) + { + case 'd': /* EOT */ + out[j++] = 0x04; + break; + case 'N': /* null */ + out[j++] = 0x00; + break; + case 'n': /* line feed */ + out[j++] = 0x0a; + break; + case 'r': /* carriage return */ + out[j++] = 0x0d; + break; + case 's': /* space */ + out[j++] = ' '; + break; + case 't': /* tab */ + out[j++] = '\t'; + break; + case '-': /* hyphen */ + out[j++] = '-'; + break; + case '\\': /* back slash */ + out[j++] = '\\'; + break; + case '0': /* '\nnn' format */ + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + byte = in[i] - '0'; + k = 0; + + while (3 > ++k) + if ((in[i+1] < '0') || (in[i+1] > '7')) + break; + else + { + byte = (byte<<3) + in[i+1] - '0'; + ++i; + } + out[j++] = byte; + break; + default: /* don't know so skip it */ + break; + } + ++i; + } + } + return j; +} + + +/* find a state within a script */ + +struct script * + find_state(begin, newstate) +struct script *begin; +char *newstate; +{ + struct script *here; + + for (here=begin; here != (struct script *)NULL; here=here->next) { + if (here->opcode == SC_LABEL && + strcmp(here->strprm, newstate) == SAME) + return here; + } + return (struct script *)NULL; +} + + +/* + * do_script() - execute a script + */ +int do_script(begin) + struct script *begin; +{ + struct script *curstate, *newstate, *curscr; + int dbgsave; + char tempstr[MAX_SCLINE]; + char dfname[256]; + char *c, chr; + int prmlen; + int dbfd; + + time_t sc_carrtime = 45000; /* time to wf carr after dial */ + time_t sc_chrdly = 100; /* delay time for ttoslow */ + time_t sc_ptime = 2000; /* time to allow for pause char */ + time_t sc_wtime = 10000; /* time to allow for wait char */ + time_t sc_dtime = 100; /* time to allow for each digit */ + time_t sc_dtmo; /* total time to dial number */ + int sc_counter; /* random counter */ + char sc_pchar = ','; /* modem pause character */ + char sc_wchar = 'W'; /* modem wait-for-dialtone character */ + time_t sc_begwait; /* time at beg of wait */ + time_t sc_secs; /* timeout period */ + + int expcnt; + int expin; + static char expbuf[MAX_EXPCT]; + + dbgsave = Debug; + curstate = begin; + + if (curstate == (struct script *)NULL) + return SUCCESS; + + _newstate: + /* + * do all of curstate's actions. Enter with curstate pointing + * to a label entry + */ + expin = 0; + + for (curscr = curstate->next; /* point to 1st scr after label */ + (curscr != (struct script *)NULL) && /* do until end of scr */ + (curscr->opcode != SC_LABEL); /* or next label */ + curscr = curscr->next) + { + expcnt = 0; + switch (curscr->opcode) + { + case SC_LABEL: + logit("Script proc err", curstate->strprm); + return FAIL; + + case SC_FLSH: + DEBUG(DB_LGII, "Flushing typeahead buffer\n", 0); + ttflui(); + break; + + case SC_CDLY: + sc_chrdly = curscr->intprm; + DEBUG(DB_LGII, "Set chrdly to %d\n", sc_chrdly); + break; + + case SC_PCHR: + sc_pchar = *(curscr->strprm); + DEBUG(DB_LGII, "Set pause char to %c\n", sc_pchar); + break; + + case SC_PTIM: + sc_ptime = curscr->intprm; + DEBUG(DB_LGII, "Set pause time to %d\n", sc_ptime); + break; + + case SC_WCHR: + sc_wchar = *(curscr->strprm); + DEBUG(DB_LGII, "Set wait char to %c\n", sc_wchar); + break; + + case SC_WTIM: + sc_wtime = curscr->intprm; + DEBUG(DB_LGII, "Set wait time to %d\n", sc_wtime); + break; + + case SC_ZERO: + sc_counter = 0; + DEBUG(DB_LGII, "Set counter to %d\n", sc_counter); + break; + + case SC_INCR: + sc_counter++; + DEBUG(DB_LGII, "Incr counter to %d\n", sc_counter); + break; + + case SC_WAIT: + DEBUG(DB_LGII, "Sleeping %d tenth-secs\n", curscr->intprm); + msleep(curscr->intprm); + break; + + case SC_DTIM: + sc_dtime = curscr->intprm; + DEBUG(DB_LGII, "Digit time is %d\n", sc_dtime); + break; + + case SC_CTIM: + sc_carrtime = curscr->intprm; + DEBUG(DB_LGII, "Carrier time is %d\n", sc_carrtime); + break; + + case SC_EXIT: + Debug = dbgsave; + DEBUG(DB_LGI, "Script ended successfully\n", 0); + return SUCCESS; + + case SC_FAIL: + Debug = dbgsave; + if (DEBUG_LEVEL(DB_LGI) && dbf != NULL) + fprintf(dbf, "Script failed\n"); + else if (expin) + charlog(expbuf, expin, DB_LOG, + "Script failed. Last received data"); + return FAIL; + + case SC_LOG: + logit(curscr->strprm, ""); + break; + + case SC_LOGE: + logit("ERROR: ", curscr->strprm); + break; + + case SC_DBOF: + /* + * If the debug file name does not begin with "/", then + * we prepend the LOG_DIR to the string. Then CREATE the + * file. This WIPES OUT previous logs. + */ + *dfname = '\0'; /* Zero name string */ + if(curscr->strprm[0] != '/') + strcat(dfname, LOG_DIR); /* Prepend default directory */ + strcat(dfname, curscr->strprm); /* Add given string */ + DEBUG(DB_LGII, "Open debug file %s\n", dfname); + if ((dbfd = creat (dfname, 0600)) <= 0) + { + logit("Failed to create debug log %s", dfname); + perror(""); + return FAIL; + } + if ((dbf = fdopen(dbfd, "w")) == NULL) + { + logit("Failed to open debug log fildes.", ""); + perror(""); + return FAIL; + } + break; + + case SC_DBG: + DEBUG(DB_LGI, "<%s>\n", curscr->strprm); + break; + + case SC_DBGE: + DEBUG(DB_LGIE, "ERROR: <%s>\n", curscr->strprm); + break; + + case SC_DBST: + Debug |= curscr->intprm; + DEBUG(DB_LGII, "Debug mask set to %04o (octal)\n", Debug); + break; + + case SC_DBCL: + Debug &= ~(curscr->intprm); + DEBUG(DB_LGII, "Debug mask set to %04o (octal)\n", Debug); + break; + + case SC_BRK: + DEBUG(DB_LGI, "Sending break\n", 0); + ttbreak(); + break; + + case SC_HANG: + DEBUG(DB_LGI, "Dropping DTR\n", 0); + tthang(); + break; + + case SC_7BIT: + DEBUG(DB_LGI, "Enabling 7-bit stripping\n", 0); + tt7bit(TRUE); + break; + + case SC_8BIT: + DEBUG(DB_LGI, "Disabling 7-bit stripping\n", 0); + tt7bit(FALSE); + break; + + case SC_PNON: + DEBUG(DB_LGI, "Setting 8-bit, no parity\n", 0); + ttpar(NONE); + break; + + case SC_PEVN: + DEBUG(DB_LGI, "Setting 7-bit, even parity\n", 0); + ttpar(EVEN); + break; + + case SC_PODD: + DEBUG(DB_LGI, "Setting 7-bit, odd parity\n", 0); + ttpar(ODD); + break; + + case SC_IFBL: + if (ttblind()) + { + DEBUG(DB_LGI, "Blind mux,\n", 0); + goto _chgstate; + } + break; + + case SC_IFBG: + if (ttblind() && sc_counter > curscr->intprm) + { + DEBUG(DB_LGI, "Blind mux & ctr > %d\n", + curscr->intprm); + goto _chgstate; + } + break; + + case SC_IFGT: + if (sc_counter > curscr->intprm) + { + DEBUG(DB_LGI, "Counter > %d\n", curscr->intprm); + goto _chgstate; + } + break; + + case SC_GOTO: + _chgstate: + DEBUG(DB_LGI, "Changing to state %s\n", + curscr->newstate); + curstate = find_state(begin, curscr->newstate); + if (curstate == NULL) + { + logit("New state not found", + curscr->newstate); + return FAIL; + } + goto _newstate; + + case SC_SEND: + ttoslow(curscr->strprm, curscr->intprm, sc_chrdly); + break; + + case SC_TELN: + if (curscr->intprm > paramc - 1) + { + sprintf(tempstr, "telno - param #%d", curscr->intprm); + logit(tempstr, " not present"); + return FAIL; + } + strcpy(telno, paramv[curscr->intprm]); + DEBUG(DB_LGII, "telno set to %s\n", telno); + break; + + case SC_SNDP: + if (curscr->intprm > paramc - 1) + { + sprintf(tempstr, "sendstr - param #%d", curscr->intprm); + logit(tempstr, " not present"); + return FAIL; + } + prmlen = xlat_str(tempstr, paramv[curscr->intprm]); + ttoslow(tempstr, prmlen, sc_chrdly); + break; + + case SC_IF1P: + if (curscr->intprm < paramc) + goto _chgstate; + break; + + case SC_IF0P: + if (curscr->intprm >= paramc) + goto _chgstate; + break; + + case SC_DIAL: + if(telno[0] == '\0') + { + logit("telno not set", ""); + return(FAIL); + } + /* + * Compute and set a default timeout for the 'timeout' + * command. Some parameters in this computation may be + * changed by the script. See the man page xchat(8) for + * details. + */ + sc_dtmo = (sc_dtime+sc_chrdly)*strlen(telno) + + sc_carrtime; + c=strcpy(tempstr, telno); + for (; *c!='\0'; c++) + { + if (*c == 'W') + { + *c = sc_wchar; + sc_dtmo += sc_wtime; + } + else if (*c == 'P') + { + *c = sc_pchar; + sc_dtmo += sc_ptime; + } + } + DEBUG(DB_LGI, "Dialing, default timeout is %d millisecs\n", sc_dtmo); + ttoslow(tempstr, 0, sc_chrdly); + break; + + case SC_TIMO: /* these are "expects", don't bother */ + case SC_XPCT: /* with them yet, other than noting that */ + case SC_CARR: /* they exist */ + case SC_XPST: + expcnt++; + break; + } + + } + + /* we've done the current state's actions, now do its expects, if any */ + + if (expcnt == 0) + { + if (curscr != (struct script *)NULL && + (curscr->opcode == SC_LABEL)) + { + curstate = curscr; + DEBUG(DB_LGI, "Fell through to state %s\n", + curstate->strprm); + goto _newstate; + } + else + { + logit("No way out of state", curstate->strprm); + return FAIL; + } + } + + time(&sc_begwait); /* log time at beg of expect */ + DEBUG(DB_LGI, "Doing expects for state %s\n", curstate->strprm); + charlog((char *)NULL, 0, DB_LGI, "Received"); + + while (1) + { + chr = xgetc(1); /* Returns upon char input or 1 sec. tmo */ + + charlog(&chr, 1, DB_LGI, (char *)NULL); + + if (chr != EOF) + { + if (expin < MAX_EXPCT) + { + expbuf[expin++] = chr & 0x7f; + } + else + { + strncpy(expbuf, &expbuf[1], MAX_EXPCT-1); + expbuf[MAX_EXPCT-1] = chr & 0x7f; + } + } + + /* for each entry in the current state... */ + + for (curscr = curstate->next; + (curscr != (struct script *)NULL) && + (curscr->opcode != SC_LABEL); + curscr = curscr->next) + { + + switch (curscr->opcode) + { + case SC_TIMO: + sc_secs = curscr->intprm; + if (sc_secs == 0) + sc_secs = sc_dtmo; + sc_secs /= 1000; + if (time(NULL)-sc_begwait > sc_secs) + { + DEBUG(DB_LGI, + "\nTimed out (%d secs)\n", sc_secs); + goto _chgstate; + } + break; + + case SC_CARR: + if (ttcd()) + { + DEBUG(DB_LGI, "\nGot carrier\n", 0); + goto _chgstate; + } + break; + + case SC_HUPS: + if (fShangup) + { + DEBUG(DB_LGI, "\nGot data set hangup\n", 0); + goto _chgstate; + } + break; + + case SC_XPCT: + if ((expin >= curscr->intprm) && + (strncmp(curscr->strprm, + &expbuf[expin - curscr->intprm], + curscr->intprm) == SAME)) + { + charlog(curscr->strprm, curscr->intprm, + DB_LGI, "Matched"); + goto _chgstate; + } + break; + + } + } + } +} + /* New opcode added by hag@eddie.mit.edu for expecting a + parameter supplied string */ + case SC_XPST: + if(curscr->intprm >paramc-1) + { + sprintf(tempstr,"expectstr - param#%d",curscr->intprm); + logit(tempstr, " not present"); + return(FAIL); + } + prmlen=xlat_str(tempstr,paramv[curscr->intprm]); + if((expin >= prmlen) && + (strncmp(tempstr,&expbuf[expin-prmlen], + prmlen) == SAME)) + { + charlog(tempstr,prmlen,DB_LGI, "Matched"); + goto _chgstate; + } + break; +/* + * SIGNAL HANDLERS + */ + +/* + * usignal - generic signal catcher + */ +static int usignal(isig) + int isig; +{ + DEBUG(DB_LOG, "Caught signal %d. Exiting...\n", isig); + restore_tty(); + exit(FAIL); +} + +/* + * uhup - HUP catcher + */ +static int uhup(isig) + int isig; +{ + DEBUG(DB_LOG, "Data set hangup.\n"); + fShangup = TRUE; +} + +/* + * TERMINAL I/O ROUTINES + */ + +/* + * xgetc - get a character with timeout + * + * Assumes that stdin is opened on a terminal or TCP socket + * with O_NONBLOCK. + */ +static char xgetc(tmo) +int tmo; /* Timeout, seconds */ +{ + char c; + struct timeval s; + int f = 1; /* Select on stdin */ + int result; + + if(read(0, &c, 1) <= 0) /* If no data available */ + { + s.tv_sec = (long)tmo; + s.tv_usec = 0L; + if(select (1, &f, (int *) NULL, &f, &s) == 1) + read(0, &c, 1); + else + c = '\377'; + } + + return(c); +} + +/* + * Pause for an interval in milliseconds + */ +void msleep(msec) +long msec; +{ + +#if HAVE_USLEEP + if(msec == 0) /* Skip all of this if delay = 0 */ + return; + usleep (msec * (long)1000); +#endif /* HAVE_USLEEP */ + +#if HAVE_NAPMS + if(msec == 0) /* Skip all of this if delay = 0 */ + return; + napms (msec); +#endif /* HAVE_NAPMS */ + +#if HAVE_NAP + if(msec == 0) /* Skip all of this if delay = 0 */ + return; + nap (msec); +#endif /* HAVE_NAP */ + +#if HAVE_POLL + struct pollfd sdummy; + + if(msec == 0) + return; + /* + * We need to pass an unused pollfd structure because poll checks + * the address before checking the number of elements. + */ + poll (&sdummy, 0, msec); +#endif /* HAVE_POLL */ + +#if USE_SELECT_TIMER + struct timeval s; + + if(msec == 0) + return; + s.tv_sec = msec / 1000L; + s.tv_usec = (msec % 1000L) * 1000L; + select (0, (int *) NULL, (int *) NULL, (int *) NULL, &s); +#endif /* USE_SELECT_TIMER */ + +#if ! HAVE_NAPMS && ! HAVE_NAP && ! HAVE_USLEEP && \ + ! HAVE_POLL && ! USE_SELECT_TIMER + if(msec == 0) + return; + sleep (1); /* Sleep for a whole second (UGH!) */ +#endif /* HAVE_ and USE_ nothing */ +} + +/* + * Debugging output + */ +static void DEBUG(level, msg1, msg2) +int level; +char *msg1, *msg2; +{ + if ((dbf != NULL) && DEBUG_LEVEL(level)) + fprintf(dbf, msg1, msg2); +} + +/* + * charlog - log a string of characters + * + * SPECIAL CASE: msg=NULL, len=1 and msg[0]='\377' gets logged + * when read does its 1 sec. timeout. Log "<1 sec.>" + * so user can see elapsed time + */ +static void charlog(buf, len, mask, msg) +char *buf; +int len, mask; +char *msg; +{ + char tbuf[256]; + + if (DEBUG_LEVEL(mask) && dbf != NULL) + { + if(msg == (char *)NULL) + msg = ""; + strncpy(tbuf, buf, len); + tbuf[len] = '\0'; + if(len == 1 && tbuf[0] == '\377') + strcpy(tbuf, "<1 sec.>"); + fprintf(dbf, "%s %s\n", msg, tbuf); + } +} + +/* + * setup_tty() + * + * Save current tty settings, then set up raw, single + * character input processing, with 7-bit stripping. + */ +static void setup_tty() +{ + register int i; + + ioctl(0, TCGETA, &old); + + new = old; + + for(i = 0; i < 7; i++) + new.c_cc[i] = '\0'; + new.c_cc[VMIN] = 0; /* MIN = 0, use requested count */ + new.c_cc[VTIME] = 10; /* TIME = 1 sec. */ + new.c_iflag = ISTRIP; /* Raw mode, 7-bit stripping */ + new.c_lflag = 0; /* No special line discipline */ + + ioctl(0, TCSETA, &new); +} + +/* + * restore_tty() - restore signal handlers and tty modes on exit. + */ +static void restore_tty(sig) +int sig; +{ + ioctl(0, TCSETA, &old); + return; +} + +/* + * ttoslow() - Send characters with pacing delays + */ +static void ttoslow(s, len, delay) + char *s; + int len; + time_t delay; +{ + int i; + + if (len == 0) + len = strlen(s); + + charlog (s, len, DB_LGI, "Sending slowly"); + + for (i = 0; i < len; i++, s++) + { + write(1, s, 1); + msleep(delay); + } +} + +/* + * ttflui - flush input buffer + */ +static void ttflui() +{ + if(isatty(0)) + (void) ioctl ( 0, TCFLSH, 0); +} + +/* + * ttcd - Test if carrier is present + * + * NOT IMPLEMENTED. I don't know how!!! + */ +static int ttcd() +{ + return TRUE; +} + +/* + * tthang - Force DTR low for 1-2 sec. + */ +static void tthang() +{ + if(!isatty()) + return; + +#ifdef TCCLRDTR + (void) ioctl (1, TCCLRDTR, 0); + sleep (2); + (void) ioctl (1, TCSETDTR, 0); +#endif + + return; +} + +/* + * ttbreak - Send a "break" on the line + */ +static void ttbreak() +{ + (void) ioctl (1, TCSBRK, 0); +} + +/* + * ttblind - return TRUE if tty is "blind" + * + * NOT IMPLEMENTED - Don't know how!!! + */ +static int ttblind() +{ + return FALSE; +} + +/* + * tt7bit - enable/disable 7-bit stripping on line + */ +static void tt7bit(enable) + int enable; +{ + if(enable) + new.c_iflag |= ISTRIP; + else + new.c_iflag &= ~ISTRIP; + + ioctl(0, TCSETA, &new); +} + +/* + * ttpar - Set parity mode on line. Ignore parity errors on input. + */ +static void ttpar(mode) + int mode; +{ + switch(mode) + { + case NONE: + new.c_iflag &= ~(INPCK | IGNPAR); + new.c_cflag &= ~(CSIZE | PARENB | PARODD); + new.c_cflag |= CS8; + break; + + case EVEN: + new.c_iflag |= (INPCK | IGNPAR); + new.c_cflag &= ~(CSIZE | PARODD); + new.c_cflag |= (CS7 | PARENB); + + break; + + case ODD: + new.c_iflag |= (INPCK | IGNPAR); + new.c_cflag &= ~(CSIZE); + new.c_cflag |= (CS7 | PARENB | PARODD); + break; + } + + ioctl(0, TCSETA, &new); +} + + + + + + + diff --git a/gnu/libexec/uucp/contrib/xchat.man b/gnu/libexec/uucp/contrib/xchat.man new file mode 100644 index 00000000000..55537be9072 --- /dev/null +++ b/gnu/libexec/uucp/contrib/xchat.man @@ -0,0 +1,628 @@ +.TH xchat 8 +.SH NAME +xchat - Extended chat processor +.SH SYNOPSIS +.BI "xchat " "scriptfile" +.RI " [ " parameter... " ] " +.PP +where +.I scriptfile +is the name of a file containing an +.I xchat +script. If +.I scriptfile +begins with ``/'', then it is assumed to be a full path name for the +script file. If not, a configuration-dependent default directory path +(usually +.B "/usr/local/conf/uucp/" +) is prepended to the script file name. Normally, the default path +is the same as that for the Taylor UUCP configuration files. +.SH DESCRIPTION +.I Xchat +is a general-purpose dialing and login program designed for use +with Taylor UUCP as a ``chat-program'', taking the place (or +augmenting) the built-in chat scripting facility. It provides the +ability to closely control timeouts, multiple simultaneous ``expect'' +strings with separate actions, extended terminal control, modem +command character pacing, and more. +.PP +When used in conjunction with Taylor UUCP's +configuration features, +.I xchat +can provide you the ability to manage the most intricate login, +dial and hangup needs. The scripts are written in a shell-like (well, +sort-of) style with labels, commands, and parameters, easing the task +of writing procedures for complex terminal communications situations. +.PP +Because +.I xchat +assumes that it is connected to the terminal device via stdin/stdout, +you can easily debug scripts by invoking it from the shell and +responding to the script from the keyboard. A debug logging facility +is included, with the debug output going to a separate user-specified +file. This makes it easy to debug connection problems without wading +through large +.I uucico +log and debug files. +.PP +Formally, a script describes a state machine; +.I xchat +interprets the script and does what the state machine +tells it to. This section will be much easier to understand +if you obtain listings of the script files supplied with +.I xchat. +.SH "SCRIPT FILE FORMAT" +Script files are ordinary text files containing comments, labels, +and statements. Blank lines are ignored. +Comments are denoted by leading ``#'' +characters. Some statements (those which do not end with an +``extended string'' argument; see below) can also have trailing +comments. +.PP +.I Labels +begin in column one and are ended by colons (:). A label +specifies a state name. All lines between a pair of labels are +the statements for a single state. +.PP +Processing always begins at the head of the script (no leading +state name is necessary). +.PP +.I Statements +are divided into two categories, ``action'' and ``expect''. +When a state is entered, all of its actions are performed in the +order in which they appear in the file. +.PP +A +.I transition +to another state may occur for any of three reasons: +.IP (1) 5 +One of the actions may cause a transition to +another state, in which case the rest of the +current state's actions are skipped. +Processing resumes with the first action +statement of the new state. +.IP (2) 5 +If none of the actions cause a state +transition, and there are no expects in the +state, processing ``falls through'' to the next +state in the file. +.IP (3) 5 +If none of the actions cause a state +transition, but there are expects in the +state, the state machine pauses until one of +the expects is ``satisfied''. It then transitions +to the state named in the expect +statement. +.PP +Finally, there are two action statements which, when executed, +cause the script to exit. +.SH "SCRIPT FILE STATEMENTS" +This section describes all of the statements that may appear in script +files, except for a few special action statements. Those are described +in a later section, ``Overriding Defaults''. +.PP +Some statements accept one or two arguments, referred to in the +following descriptions as +.IR int ", " ns ", " str ", or " +.IR xstr ", to" +indicate whether the argument is an integer, a new state name, a +string, or an ``extended string'' (described in a later section). +.PP +For all statements that accept two arguments, the first is the +name of a new state, and the second specifies a condition or +reason for changing to the new state. +.SS "Termination And Informational Statements" +These statements are used to place entries into the Taylor UUCP +.I Log +file, and to cause +.I xchat +to exit with successful or failure status. It is also possible to open a +separate +.I debug +log file and control the level of tracing and error reporting that will go +into that log file. This is very useful in debugging +.I xchat +scripts. +.br +.ta 1.0i 1.5i 2.0i +.TP 2.0i +.B failed +Exit script with ``failed'' status. This causes +.I xchat +to exit with status 0. +.TP 2.0i +.B success +Exit script with ``success'' status. This causes +.I xchat +to exit with status 1. +.TP 2.0i +.BI "log " xstr +Send informational message +.I xstr +to standard error. When used with Taylor UUCP, this is the +.I Log +file for the +.I uucico +program. +.TP 2.0i +.BI "logerr " xstr +Send message +.I xstr +to standard error, with ``ERROR:'' indicator. When used +with Taylor UUCP, this is the +.I Log +file for the +.I uucico +program. +.TP 2.0i +.BI "dbgfile " xstr +Open script debugging file +.I xstr. +If +.I xstr +begins with ``/'', it is assumed to be an absolute path name for the +debugging file. If not, then a configuration-dependent default directory +path (usually +.B "/usr/spool/uucp" +) is prepended to +.I xstr. +Normally the default path is that of the directory where Taylor UUCP +puts its log files. +The debugging file is used to capture a detailed log of the data sent +and received, errors encountered, and a trace of script execution. +The various types of logging are controlled by the +.I "debug mask," +described next. +.B Note: +A new log file is created each time +.I xchat +runs. Use the +.B log +and +.B loge +commands to log +continuous information onto standard out, which is connected +to the Taylor UUCP +.I Log +file when +.I xchat +is run by the Taylor +.I uucico. +.TP 2.0i +.BI "dbgset " int +Set the bits specified in +.I int +in the debugging mask. The value in +.I int +is ``or''ed into the mask. Set bit 0 (value \= 1) for error messages, +bit 1 (value \= 2) for dial, login and init errors, bit 2 (value \= 4) +for dial, login and init trace with character I/O, and bit 3 (value \= 8) +for script processing internals. Normally, you will just turn it all on +with a value of 15. +.TP 2.0i +.BI "dbgclr " int +Clear the bits specified in +.I int +from the debugging mask. +.TP 2.0i +.BI "debug " xstr +Write +.I +xstr +into the debug log. The entry will be enclosed in angle brackets. +.TP 2.0i +.BI "debuge " xstr +Write +.I xstr +into the debug log with ``ERROR: '' prepended. The entry will be enclosed +in angle brackets. +.SS "Sending Data" +These statements are used to transmit data to standard out (the tty or TCP +port when used with Taylor UUCP). +.I +No implied carriage returns are sent. +You must include a \\r if you want a carriage return in the string +sent by the +.B send +command. If you want a return sent after +.B dial +or +.B sendstr, +you must send it with a separate +.B send +command. +.TP 2.0i +.B dial +Send the string previously set by the +.B telno +command to the serial port. +.B W +and +.B P +characters in the phone number are +converted as described under +.B +Dial Strings, +below. This statement also sets a default +timeout value, as described under the +.B timeout +statement. +.TP 2.0i +.BI "send " xstr +Send the string +.I xstr +to the serial port. +.TP 2.0i +.BI "sendstr " int +The argument of this statement is a digit from 0 +through 7. Send the corresponding string +parameter as passed to +.I xchat +following the script file name. The parameter is interpreted +as an extended string. +.SS "Special Terminal Control Statements" +These statements are used to cause the terminal port to perform some special action, or to change the mode of the port. +.I +The modes of the port are restored to their original settings +.I +by xchat before it exits. +.TP 2.0i +.B flush +Flush the terminal port's input buffer. +.TP 2.0i +.B break +Send a break signal. +.TP 2.0i +.B hangup +Momentarily drop Data Terminal Ready (DTR) on the +serial port, causing the modem to hang up. (Not +usually needed, since +.I uucico +does this at the end of each call.) +.TP 2.0i +.B 7bit +Change the port to strip incoming characters to 7 bits. +.I +This is the default mode. +This mode +is implied when the port has parity enabled, since parity characters +are 7-bits wide. +.TP 2.0i +.B 8bit +Change the port to allow incoming 8-bit characters to be passed +to the script processor. This mode has no effect if parity is +enabled, since parity characters are 7-bits wide. +.TP 2.0i +.B nopar +Change the port to 8-bits, no parity. +.I +This is the default mode. +.TP 2.0i +.B evenpar +Change the port to 7-bits, even parity. +.I +Incoming characters with parity errors are discarded. +.TP 2.0i +.B oddpar +Change the port to 7-bits, odd parity. +.I +Incoming characters with parity errors are discarded. +.SS "Counting, Branching, Timing and Testing Statements" +These statements are used to control the flow of the +.I xchat +script itself, including branching, delays, and counter manipulation. +.TP 2.0i +.BI "sleep " int +Delay for +.I int +milliseconds. +.TP 2.0i +.B zero +Clear the counter. +.TP 2.0i +.B count +Add one to the counter. +.TP 2.0i +.BI "ifgtr " "ns int" +Go to state +.I ns +if counter greater than +.I int. +.TP 2.0i +.BI "goto " ns +Go to state +.I ns +unconditionally. +.TP 2.0i +.BI "ifstr " "ns int" +Go to state +.I ns +if string parameter +.I int +is nonempty. +.TP 2.0i +.BI "ifnstr " "ns int" +Go to state +.I ns +if string parameter +.I int +is empty. +.TP 2.0i +.BI "ifblind " ns +Change to state +.I ns +if the port is ``blind'' without carrier (CD) asserted. +.I +This is not yet implemented, the test always fails. +.TP 2.0i +.BI "ifblgtr " "ns int" +Change to state +.I ns +if the port is ``blind'' without carrier (CD) asserted, and counter +is greater then +.I int. +.I +This is not yet implemented, the test always fails. +.SS "Expect Statements" +Expect statements are usually the last statements that appear in a +given state, though in fact they can appear anywhere within the +state. Even if they appear at the beginning, the script processor +always does all of the action statements first. As a practical +matter, the order of these statements is not significant; they are +all interpreted ``in parallel''. +.TP 2.0i +.BI "expect " "ns xstr" +Change to state +.I ns +if the string specified by +.I xstr +is received from standard input (usually the serial port). +Case is significant, but high-order bits are not +checked. +.TP 2.0i +.BI "expectstr " "ns int" +Change to state +.I ns +if the string specified in parameter +.I int +is received from standard input (usually the serial port). +.I int +must be in the range 0 to 7. +Case is significant, but high-order bits are not +checked. +Useful where a prompt can change in different dial-in lines. +.TP 2.0i +.BI "ifcarr " ns +Change to state +.I ns +if Carrier Detect (CD) is true. +.I +Not currently implemented. Always changes state. +.TP 2.0i +.BI "ifhang " ns +Change to state +.I ns +if a data set hangup occurs (SIGHUP signal received). +.TP 2.0i +.BI "timeout " "ns int" +Change to state +.I ns +if the time (in milliseconds) +given by +.I int +has elapsed without satisfying any +expects. If the time specified is 0, a default +timeout value (calculated from the length and +other characteristics of the most recent dial +string) is used. +.SH "SCRIPT PROCESSING DETAILS" +.SS "Extended Strings" +In the statements that accept string arguments, the strings are +interpreted as +.I +extended strings. +Extended strings begin with +the first nonblank character and continue, including all imbedded +and trailing blanks and other whitespace, until (but not +including) the end of the line in the script file. (There is no +provision for line continuation.) No trailing spaces should be +present between the last ``desired'' character of the string and the +end of the line, as they will be included in the stored string and +sent or expected, just as they appear in the script file. And, +obviously, no trailing comments are permitted! They will just be +stored as part of the string. +.PP +Within an extended string, the following ``escape sequences'' will +be converted as indicated before being sent or expected: +.br +.nf +.in +0.5i +\fB\\d\fR EOT character (control-D) +\fB\\N\fR null character +\fB\\n\fR line feed +\fB\\r\fR carriage return +\fB\\s\fR space +\fB\\t\fR tab +\fB\\\-\fR hyphen +\fB\\\\\fR backslash +\fB\\ooo\fR character with value ooo (in octal) +.in -0.5i +.fi +.PP +Since extended strings in scripts can include embedded spaces, +tabs, etc., these escape sequences are only required in strings +appearing in systems entries, though they may be used in script +files to improve readability. +.PP +The octal-character specification (\\ooo) may have from one to +three octal digits; it is terminated either after the third digit +or when a non-octal character is encountered. But if you want to +specify one of these followed by something that happens to be a +valid octal character (for example, a control-A followed by a 7) +make sure to include all three digits after the \\ . So \\0017 +would become a control-A followed by the Ascii character ``7'', but +\\17 or \\017 would become a control-Y (decimal value 25). \\1S +would convert to a control-A followed by an ``S''. +.PP +Extended strings are stored without a trailing carriage return +unless one is explicitly present in the string (via \\r). +.SS "String Parameters" +The +.B sendstr +statement sends (after conversion from extended string +format) one of the parameters given on the +.I xchat +command line following the script file name. +The parameter is selected by the integer +argument of the statement. +.PP +This allows ``generic'' script files to serve +for many different systems; the string parameters +provide the phone number, username, password, etc. Character +substitutions described under ``extended strings'' above are +performed on these strings. +.PP +The ifstr and ifnstr statements allow further generality in script +files, by testing whether a particular parameter is present in the +systems entry. For example, a single script can be +used both for those systems that require a password and +those that do not. The password is specified as the last argument +in the +.xchat +command; the script can test for this +parameter's existence and skip the password sequence if +the parameter is empty. +.SS "``Wait'' And ``Pause'' Characters In Dial Strings" +An additional conversion is performed on dial strings. Dial strings +are interpreted as extended strings. Then the characters +.B W +and +.B P +within a dial string are interpreted as ``wait for dial +tone'' and ``pause'', and may be converted to other characters. By +default, +.B W +is left alone, and +.B P +is converted to a comma (,); +these are appropriate for Hayes-type modems. The script may +specify other substitutions (see below). +.PP +.B NOTE: +The Taylor UUCP documentation states that the ``wait'' and ``pause'' +characters are ``='' and ``-'', respectively. These are actual characters +understood by some modems. When using +.I xchat +you should put +.B W +and +.B P +in the dial strings you specify in the Taylor configuration files. +This way, the +.I xchat +processor can make the substitution appropriate for the particular +modem in use. Make a separate +.I xchat +script for each modem type, e.g., +.I "dial.hayes" +and specify the translation there. This way, the phone number strings +in the Taylor configuration files can be used with a variety of modems. +.SS "Default Timeouts For Dial Strings" +When a +.B dial +statement is executed, a default timeout value is set. +This is the timeout value used by a subsequent timeout statement +if the statement specifies a timeout value of 0. +.PP +The default timeout is given by: +.br +.nf +.in +2 +\fIctime\fR + (\fIndigits\fR * \fIdgttime\fR) + (\fInwchar\fR * \fIwtime\fR) + (\fInpchar\fR * \fI ptime\fR) +.in -2 +.fi +.PP +where +.I +ndigits, nwchar, +and +.I npchar +are the number of digits, wait characters, and pause characters in +the dial string, and +.I ctime, dgttime, wtime, +and +.I ptime +are 45 seconds, 0.1 seconds, 10 seconds, and 2 seconds, +respectively. +All of these times may be changed as specified below under +``Overriding Defaults.'' +.SS "Trailing Carriage Returns Not Assumed" +In the +.B dial +and +.B sendstr +statements, the dial string or +parameter is sent with no trailing carriage return; +if a carriage return must be sent after one of these, a separate +send statement must provide it. +.SH "OVERRIDING DEFAULTS" +The script processor sets several default values. The following +statements, which override these defaults, may be useful in +certain circumstances. +.TP 2.0i +.BI "chrdly " int +Since many modems cannot accept dialing commands +at full ``computer speed'', the script processor +sends all strings with a brief inter-character +delay. This statement specifies the delay time, +in milliseconds. The default is 100 (0.1 second). +.TP 2.0i +.BI "pchar " str +Specifies the character to which +.BR P s +in the +dial string should be converted. Default is +``,'', for use with Hayes-type modems. +.TP 2.0i +.BI "ptime " int +Specifies the time, in milliseconds, to allow in +the default timeout for each pause character in +the dial string. Default is 2000 (2 seconds). +.TP 2.0i +.BI "wchar " str +Specifies the character to which +.BR W s +in the +dial string should be converted. Default is +``W'', for Hayes modems. +.TP 2.0i +.BI "wtime " int +Specifies the time, in milliseconds, to allow in +the default timeout for each wait-for-dialtone +character in the dial string. Default is 10000 +(10 seconds). +.TP 2.0i +.BI "dgttime " int +Specifies the time, in milliseconds, to allow in +the default timeout for each digit character in +the dial string. Default is 100 (0.1 second). +.TP 2.0i +.BI "ctime " int +Specifies the time, in milliseconds, to allow in +the default timeout for carrier to appear after +the dial string is sent. Default is 45000 (45 +seconds). +.SH "SEE ALSO" +uucico(8) for Taylor UUCP, and documentation for Taylor UUCP. +.SH AUTHOR +Robert B. Denny (denny@alisa.com) +.SH CONTRIBUTORS +Daniel Hagerty (hag@eddie.mit.edu) +.SH HISTORY +This program is an adaptation of the dial/login script processing +code that is a part of DECUS UUCP for VAX/VMS, written by Jamie +Hanrahan, et. al. +.SH BUGS +This version (1.1) does not support BSD terminal facilities. Anyone +volunteer to add this? + |