Initial Import from SVN

This commit is contained in:
Matt Jenkins
2014-04-09 14:27:18 +01:00
parent 8976e834c4
commit 895f96d2f7
3153 changed files with 748589 additions and 0 deletions

166
src/cmd/uucp/CHANGES Normal file
View File

@@ -0,0 +1,166 @@
List of Changes to UUCP
CHANGES 5.7 86/02/12
Added support for Eunice.
Added new dialers:
Racal Vadic 212
Racal Vadic 811 dialer with 831 adaptor
Racal Vadic 820 dialer with 831 adaptor
Racal Vadic MACS, 811 dialer with 831 adaptor
Racal Vadic MACS, 820 dialer with 831 adaptor
Dec DF112
4.2BSD style networking on top of tcp/ip ('t' protocol)
X.25/PAD support ('f' protocol)
Novation
Penril
Hayes 2400 Smartmodem
Concord Data Systems CDS 224
ATT 2224 2400 baud modem
Running uucico with debugging on requires read access to L.sys.
If "NOSTRANGERS" is defined in uucp.h, the remote site
must be in you L.sys or the call will be rejected.
Lock files may be kept in a subdirectory if desired.
STST files are kept in a subdirectory.
CORRUPT subdirectory contains corrupted C. and X. files that could
not be processed. (Instead of just exiting)
You can specify a maximum grade to send either on the command line (-gX)
or in the L.sys file (Any/C|Evening will only send class C [usually
mail] or higher during the day and will send everything in the evening)
See UUAIDS/L.sys for examples.
L.sys (and any of the files in lib/uucp) can contain comments by
putting a # as the first character on a line. Lines may be
continued by placing a \ as the last character of the line.
-R flag reverses role. (Lets the remote system be master first instead
of slave)
-L flag only calls "local" sites. Local sites are those sites having
one of LOCAL,TCP or DIRECT in the ACU field of L.sys.
If /etc/nologin is present (usually created by a graceful shutdown),
uucico and uuxqt will gracefully exit instead of getting killed
off when the system goes down.
Does an exponential backoff on retry time if call fails instead
of always waiting the default 5 minutes. The default may be
overridden by adding ",TIME" to the time field in L.sys. e.g.
"seismo Any,2" will use a default retry time of 2 minutes.
If uucico receives a SIGFPE while running, it will toggle debugging
on and off.
Better status messages provided for uustat.
New program uuq to give more decriptive information on status of
jobs in uucp queue.
Don't send files to remote system if it is returning out of
temp space error.
Correctly does the closing hangup sequence.
condevs.c was broken into a file for each dialer in the
directory aculib for much easier maintenance.
Only try at most TRYCALLS to dial a site instead of one try
for each dialer (lost big on systems with many dialers)
Add ABORT sequence to the expect/send sequence so don't have
to wait for timeout if can't get through dataswitch. e.g.
noao Evening ACU 1200 6021234565 "" \d\r CLASS NOAOUUCP ABORT Down GO \d\r ogin:-\b-ogin: uucplogin word: uucppassword
will only call noao in the evening (evening is defined by the phone rates).
It will expect nothing and then wait 1 second (\d) and send a carriage return.
Look for CLASS, then send NOAOUUCP. From then on, if it sees the word Down
before finishing logging in, it will hang up immediately. In the mean time,
it looks for GO and if it sees it, delays 1 second and sends a CR. Looks
for ogin:, etc. This abort sequence is very useful if you must go through a
dataswitch to get to the computer.
The time field in L.sys now handles "Evening" and "Night" in addition
to Any, Mo,Tu,We,Th,Fr,Sa,Su. Evening and Night are defined to
be when the phone rates are cheaper.
Evening = Wk1700-0800|Sa|Su
Night = Any2300-0800|Sa|Su0800-1700
The expect/send code now supports:
\s space
\d delay 1 second
\r carriage return with no linefeed
\b break
\c don't send a CR after these characters
\xxx the octal character xxx (e.g. \s == \040
L-devices now handles "chat" scripts (like HoneyDanber) to get
through local port selectors and smart modems more easily
without mucking up every line of L.sys. See UUAIDs/L-devices for
details.
The 'g' protocol code was cleaned up a lot and is now almost
readable.
If you need a parity other than even (the default) to login to
another system, you can change it in L.sys by putting in a
sequence like "" P_ZERO (expect nothing, send zero parity).
Odd Parity P_ODD
Even Parity P_EVEN
Zero Parity P_ZERO
One Parity P_ONE
If DONTCOPY is defined in uucp.h, uucp will not make a copy
of the source file by default. (This is the way System 3 does it).
If an X. request fails, the notification is returned to the
originator of the request instead of "uucp" on the previous
system.
The man pages are actually accurate!
If LOGBYSITE is defined, uucp logging is done with
a log file per site instead of one LOGFILE. (Like Honey DanBer does)
There is a new file (optional) L.aliases that makes life simpler when
a site changes it's name. uucp, uux, uucico, etc all check it so
when a site is renamed (e.g convex <- parsec) all you have to do is add
an entry in L.aliases of the form:
newname oldname
uucico will not try and resend files it has already sent (when the
files are specified in one C. file)
Incorporated Bill Sebok's code to dial in and out on the same modem.
NOTE: acucntrl is heavily Vax/4.xbsd specific and will require work to
run on any other system.
For compatibility with Honey DanBer, in the Date fields of L.sys,
| was changed to , (| is supported, but not encouraged)
, was changed to ; (to allow , to be the date seperator)
For Honey DanBer compatibility, the Grade flag is now passed as
-vgrade=X instead of the old -pX
Don't truncate site names to 7 characters (truncate to 14 if
anyone gets that absurd) for HDB compatibility. L.aliases may
be used to map host with longer names in L.sys to 7 character
names that some hosts send. Entries should be
fullname 7-char-name
You can specify a time for the expect send sequences with ~ instead
of getting the default MAXMSGTIME. E.g.
system Any ACU 1200 1234567 ogin~20-\r-ogin~10-\b-ogin user password pw
will look for ogin for 20 seconds, send CR, look for ogin for 10
seconds, send a BREAK and look for ogin for MAXMSGTIME seconds
Added code to support GTEs PC Pursuit service. It's mainly the handling of the
dialback they use.
Added time "NonPeak" for Tymnet/Telenet services that charge lower
rates from 6pm-7am M-F and Sat & Sun.

142
src/cmd/uucp/Makefile Normal file
View File

@@ -0,0 +1,142 @@
# Makefile 5.11.3 (2.11BSD GTE) 1996/11/17
#
# LIBS can be set to reference other object modules and libraries needed
# by uucico, such as -lunet (needed when UNET is defined).
#
# Common object files are assembled into a library {uulib.a}
#
TOPSRC = $(shell cd ../../..; pwd)
include $(TOPSRC)/target.mk
ALL= uucico uucp uux uuxqt uulog uuclean uuname uupoll uusnap \
uuencode uudecode uusend uuq
LIBOBJ = logent.o ulockf.o uucpdefs.o subdir.o gename.o assert.o expfile.o \
chkpth.o cpmv.o uucpname.o getpwinfo.o versys.o xqt.o getargs.o \
cfgets.o prefix.o lastpart.o getprm.o anyread.o anlwrk.o gnamef.o \
mailst.o systat.o cntrl.o imsg.o gio.o sysacct.o pk0.o pk1.o \
conn.o condevs.o chksum.o setline.o gnsys.o
CC = $(GCCPREFIX)gcc -mips16 -EL -msoft-float -nostdinc -fshort-double -I$(TOPSRC)/include $(INCLUDES)
OWNER= uucp
GROUP= daemon
CFLAGS += -Os -Werror
SBINDIR= ${DESTDIR}/usr/sbin
LIBEXECDIR= ${DESTDIR}/usr/libexec
BIN= ${DESTDIR}/usr/bin
PUBDIR= ${DESTDIR}/usr/spool/uucppublic
SPOOL= ${DESTDIR}/usr/spool/uucp
XQTDIR= ${SPOOL}/XTMP
CORRUPT= ${SPOOL}/CORRUPT
AUDIT= ${SPOOL}/AUDIT
LCK= ${SPOOL}/LCK
LOG= ${SPOOL}/LOG
STST= ${SPOOL}/STST
# The six subdirs {not counting XTMP}.
HOSTNAME=`uuname -l | sed 's/\(.......\).*/\1/'`
SUBDIRS=C. D.${HOSTNAME}X D.${HOSTNAME} D. X. TM.
all: libacu $(ALL)
libacu:
cd aculib && make
uuencode: uuencode.o
${CC} ${LDFLAGS} -o uuencode.elf uuencode.o ${LIBS}
${OBJDUMP} -S uuencode.elf > uuencode.dis
${SIZE} uuencode.elf
${ELF2AOUT} uuencode.elf $@
uudecode: uudecode.o
${CC} ${LDFLAGS} -o uudecode.elf uudecode.o ${LIBS}
${OBJDUMP} -S uudecode.elf > uudecode.dis
${SIZE} uudecode.elf
${ELF2AOUT} uudecode.elf $@
uucp: uucp.o libuucp.a
${CC} ${LDFLAGS} -o uucp.elf uucp.o -L. -luucp ${LIBS}
${OBJDUMP} -S uucp.elf > uucp.dis
${SIZE} uucp.elf
${ELF2AOUT} uucp.elf $@
uux: uux.o libuucp.a
${CC} ${LDFLAGS} -o uux.elf uux.o -L. -luucp ${LIBS}
${OBJDUMP} -S uux.elf > uux.dis
${SIZE} uux.elf
${ELF2AOUT} uux.elf $@
uuxqt: uuxqt.o libuucp.a
${CC} ${LDFLAGS} -o uuxqt.elf uuxqt.o -L. -luucp ${LIBS}
${OBJDUMP} -S uuxqt.elf > uuxqt.dis
${SIZE} uuxqt.elf
${ELF2AOUT} uuxqt.elf $@
uulog: uulog.o libuucp.a
${CC} ${LDFLAGS} -o uulog.elf uulog.o -L. -luucp ${LIBS}
${OBJDUMP} -S uulog.elf > uulog.dis
${SIZE} uulog.elf
${ELF2AOUT} uulog.elf $@
uuclean: uuclean.o libuucp.a
${CC} ${LDFLAGS} -o uuclean.elf uuclean.o -L. -luucp ${LIBS}
${OBJDUMP} -S uuclean.elf > uuclean.dis
${SIZE} uuclean.elf
${ELF2AOUT} uuclean.elf $@
uuname: uuname.o libuucp.a
${CC} ${LDFLAGS} -o uuname.elf uuname.o -L. -luucp ${LIBS}
${OBJDUMP} -S uuname.elf > uuname.dis
${SIZE} uuname.elf
${ELF2AOUT} uuname.elf $@
uupoll: uupoll.o libuucp.a
${CC} ${LDFLAGS} -o uupoll.elf uupoll.o -L. -luucp ${LIBS}
${OBJDUMP} -S uupoll.elf > uupoll.dis
${SIZE} uupoll.elf
${ELF2AOUT} uupoll.elf $@
uusnap: uusnap.o libuucp.a
${CC} ${LDFLAGS} -o uusnap.elf uusnap.o -L. -luucp ${LIBS}
${OBJDUMP} -S uusnap.elf > uusnap.dis
${SIZE} uusnap.elf
${ELF2AOUT} uusnap.elf $@
uusend: uusend.o libuucp.a
${CC} ${LDFLAGS} -o uusend.elf uusend.o -L. -luucp ${LIBS}
${OBJDUMP} -S uusend.elf > uusend.dis
${SIZE} uusend.elf
${ELF2AOUT} uusend.elf $@
uuq: uuq.o libuucp.a
${CC} ${LDFLAGS} -o uuq.elf uuq.o -L. -luucp ${LIBS}
${OBJDUMP} -S uuq.elf > uuq.dis
${SIZE} uuq.elf
${ELF2AOUT} uuq.elf $@
uucico: cico.o libuucp.a
${CC} ${LDFLAGS} -o uucico.elf cico.o -L. -Laculib -luucp -lacu ${LIBS}
${OBJDUMP} -S uucico.elf > uucico.dis
${SIZE} uucico.elf
${ELF2AOUT} uucico.elf $@
libuucp.a: $(LIBOBJ)
$(AR) r libuucp.a $(LIBOBJ)
$(RANLIB) libuucp.a
install: uuencode uuencode
cp $(ALL) $(TOPSRC)/bin
clean:
rm -f *.o $(ALL) libuucp.a *.dis *.elf
cd aculib; make ${MFLAGS} clean
depend:
mkdep ${CFLAGS} *.c

216
src/cmd/uucp/README Normal file
View File

@@ -0,0 +1,216 @@
INSTALLATION GUIDE
README 5.6.1 (2.11BSD) 1996/10/23
This version is based on the "rti uucp" that was on the 4.2BSD tape.
It contains many additional features and fixes from Usenet,
Tom Truscott, Guy Harris, Lou Salkind, and many others.
A few new subdirectories have been added. Do a "make mkdirs" to make
sure that you have all of them.
I recommend that you change the uucp mail handler in your sendmail.cf
to something like:
# Muucp, P=/usr/bin/uux, F=sDFMhuU, S=13, R=23, M=100000,
# A=uux - -r $h!rmail ($u)
Muucp, P=/usr/bin/uux, F=sDFMmhuU, S=13, R=23, M=100000,
A=uux - -r -z -a$g -gC $h!rmail ($u)
The -a$g provides a return address in case mail fails (So It
won't go to yourmachine!uucp anymore.) The -gC specifies a grade
for mail. C is a good choice for mail. News should run at 'd'. This
way, mail gets sent before news. The 'm' flag specifies that this
mail can send to multiple addresses, which uux can.
The man pages now describe all the options for the various commands.
Make sure you read them. A list of the functional differences is in "Changes".
You should also look through the UUAIDS directory. There are some useful
programs and hints therein.
The maximum length of a site name has been changed from the old 7 to the
14. This is the be compatible with the HoneyDanBer uucp (aka BNU 1) which
is as close to a standard uucp as there is. Sites which have sitenames
longer than 7 characters that only send you the first 7 characters are
broken and should be fixed. However, there is a way of compensating for
this until they fix their problem. For each site you talk to that has a
name longer that 7 characters, put a line in /etc/uucp/L.aliases of
the form:
fullname name-truncated-to-7-characters.
E.g:
tektronix tektron
lbl-csam lbl-csa
rochester rochest
ut-sally ut-sall
(See UUAIDS/L.aliases for more details on aliasing uucp names.) If the site
name is <= 7 characters, you don't have to do anything.
Rick Adams
rick@seismo.ARPA
June 19, 1985
Tom Truscott, rti!trt,decvax!duke!trt (919)541-6488 Research Triangle Institute
Bob Gray, gray@berkeley, duke!adiron!bob (315) 336-4989
This is a variant of the uucp used at decvax, ittvax, rti, mcnc, adiron,
duke and others. There have been tons of bug fixes and enhancements
from people on the usenet (thank you). Speed is substantially
improved. This version fixes essentially all of the McGeady's bug list.
Enhancements:
Dialers Lots of dialers included.
Subdirectories /usr/spool/uucp is now split into 7 subdirectories.
This is a huge help on busy systems.
/etc/uucp/L.cmds List of commands permitted for remote execution.
A line of form 'PATH=...' sets the search path.
expect-send sequence Escape characters now permitted: \r, \n.
\r, not \n, is default char sent at end of string.
\c (put at end of string). Dont send ending \r.
\d pause 1 second (\d\d pauses 2 seconds)
"" P_ZERO `expect nothing, start sending zero parity.'
P_EVEN (default), P_ODD, P_ONE other parity modes.
\05 Send a control-E
"" "" `expect nothing, send a \r'.
uupoll [sysname] Polls named system.
uusnap Displays spooled files, and pending uuxqts.
This version runs on all VAXen and PDPs under UNIX-V7 and 4.1bsd, 4.2BSD.
It also runs on Gould/SEL Concept series machines (e.g. 32/8750),
DUAL 68000 unisoft.
It also runns on BTL system III, IV, and V.
UUCP installers should read the two papers (by Dave Nowitz)
in Vol 2B of version 7 manuals and UUAIDS/setup.tblms.
Understand each step below before executing.
Some steps will vary slightly from system to system.
**** INSTALLATION *******
1. If you are currently running uucp, save the old programs!:
su root
cd /usr/bin
for i in uucp uux uulog uuname (csh: foreach i (uucp ....) )
do
cp $i $i.old
done (csh: end )
cp -p /usr/sbin/uucico /usr/sbin/uucico.old
cp -p /usr/libexec/uuxqt /usr/libexec/uuxqt.old
cp -p /usr/sbin/uuclean /usr/sbin/uuclean.old
2. Editing Makefile and uucp.h
4.2 sites using the supported dialers are all set with defaults.
non-4.2
a) sites need to install the Berkeley directory reading library.
Try (cd libndir; make install).
Edit Makefile to have LIBNDIR= -lndir
define NDIR in uucp.h.
b) Check LDFLAGS, OWNER, GROUP, and LIBUUCICO.
c) pick a method to allow uucp to know its system:
Check out GETHOSTNAME/UNAME/WHOAMI/CCWHOAMI in uucp.h
d) define SYSIII if appropriate in uucp.h.
e) Your "make" may fail because the Makefile is so large.
If so, in /usr/src/cmds/make/defs, change
'#define NFLEFTS 60' to 512, and re-make make.
3. Make the new commands.
make
4. WAIT UNTIL THE UUCP SYSTEM IS IDLE!! Single-user is best.
su root (it is important that chmod, chown and chgrp work below)
5. Install the new commands:
make install
(If you are chicken, type 'make -n install' first).
6. Edit and install the control files:
Look in UUAIDS. Edit and install into /etc/uucp if necessary
USERFILE, L.cmds, L.sys, L-devices, L-dialcodes.
THESE FILES MUST BE OWNED BY THE SAME OWNER AND GROUP AS
THE UUCP COMMANDS AND UUCP SPOOL FILES!!! (probably uucp, daemon).
The format for dialers is slightly different so that any dialer
can be handled.
7. Make new subdirectories:
For safety: cd /usr/spool/uucp; tar c . (save Qed files on tape)
The following assumes your site name is produced by `uuname -l`.
make mkdirs
If your system is duke, then the subdirectories created are
named C., D., D.duke, D.dukeX, TM., XTMP and X..
rmdir /etc/uucp/.XQTDIR
which is obsolete (XTMP replaces it).
8. Move old Qed files:
If you have spooled files, they must be moved into the subdirectories.
Assuming all spool files are in /usr/spool/uucp
(i.e. you did not have subdirs before)
the following command will move the spool files
to the right subdirectories:
make mvspoolfiles; ??? does this work now??????????
Files beginning C. are put in the C. subdirectory, and so on.
Files begining D.dukeX are put in that directory, *not* D..
(Note: if you already had a subdirectory version of uucp,
you need only create the new subdirectories mentioned above
and move the relevant files there.
Delete other old directories if you had any (e.g. "LOG.")
9. Compact /usr/spool/uucp:
cd /usr/spool
mkdir nuucp
chown uucp nuucp
chgrp daemon nuucp
for i in uucp/* (csh: foreach i (uucp/*) )
do
mv $i nuucp
done (csh: end )
rmdir uucp
mv nuucp uucp
(Note: this does *not* work if a filesystem is mounted on
/usr/spool/uucp! If that is the case, you should 'tar'
/usr/spool/uucp somewhere, unmount, re-mkfs, and re-mount
the filesystem, and tar the uucp files back.)
10. Test the new system
Test by mailing a letter somewhere and back.
If it works, the new system is probably fine.
Otherwise, figure out what is wrong.
Start by examining LOGFILE. Try /usr/sbin/uucico -r1 -sname -x7
If things are no-go, you can back out the changes by restoring the
old uu programs and the spooled files.
NOTE: The subdirectories foul up a non-subdir version,
so be sure that subdirectories exist/do not exist as appropriate.
11. Install handy UUAIDS
Look in uuaids for handy other stuff. In particular, uu.* are
shell scripts that can be run via cron hourly, daily, and weekly
to keep uucp trim. L-devices, L-dialcodes, L.cmds, L.sys, USERFILE
are sample files. THEY MOST LIKELY NEED TO BE MODIFIED TO USE
THEM ON YOUR OWN SYSTEM!
uu.hourly Makes sure sites are polled.
uu.daily Runs uuclean to clean up /usr/spool/uucp.
**IT HANDLES SUBDIRECTORIES!!
Renames LOGFILE to LOGFILE.old.
uu.weekly Renames SYSLOG to SYSLOG.old.
The above scripts should be run via cron.
uucpsummary
Summarizes LOGFILE and SYSLOG. It's very helpful in telling
what is going on and who is calling who.
uucp.daily
Daily shell script run at ittvax. Manages SYSLOG files in
a convenient form for uuusage. Not integrated in time
for this distribution.
Comments, bug reports, *and improved code* are welcome.
Tom Truscott
Bob Gray

56
src/cmd/uucp/README.TCP Normal file
View File

@@ -0,0 +1,56 @@
The rest of this file is oriented to updating a vanilla 4.2 system.
As 4.3 comes configured, all you have to do is uncomment the "uucpd"
line in /etc/inetd.conf (and of course update your L.sys as needed).
If you want to turn off logging uucp logins in wtmp, set the "user"
field in inetd.conf to "uucp", who doesn't have write permission on wtmp.
----------------------------------------------------------------------
Basically, to run UUCP on top of TCP, the code had to be changed to
not do ioctl's on sockets,etc. Also, a new protocl 't' was added.
This is because the 'g' protocol maxes out at about 9000 baud
regardless of the physical medium. The 't' protocol presumes an
error free channel, and is essentially the 'g' protocol with the
checksumming and packetizing ripped out.
To install it, make uucp with BSD4_2 defined in uucp.h.
Add a line in /etc/services that looks like:
uucp 540/tcp uucpd
Add lines to /etc/rc.local that looks something like:
if [ -f /usr/libexec/uucpd ]; then
/usr/libexec/uucpd & echo -n ' uucpd' >/dev/console
fi
The L.sys entry should look something like:
uucpname time-to-call TCP port networkname standard uucp login chat
This is how it would look for rochester.
rochester Any TCP uucp ur-seneca "" uucplogin "" uucppasswd
UUCP site rochester is arpanet site ur-seneca (and there is a
arpanet site rochester that is a different machine)
The "port" field is either a word or a number. It is a number,
that number is used as the port. If it is a word, the word is
looked up in /etc/services and the port is taken from there.
Another example would be:
seismo Any TCP 33 seismo "" uucplogin "" uucppassword
In almost every case, the networkname field will be the same as the
uucpname field. Similarly, the port field will usually be "uucp", which
says to use the standard uucp port from the services file.
The daemon expects the incoming site to send its login and password
for authentication.
If you have any problems feel free to call me:
Rick Adams
Center for Seismic Studies
1300 North 17th Street, Suite 1450
Arlington, VA 22209
(703) 276-7900
rick@seismo.ARPA
seismo!rick

View File

@@ -0,0 +1,28 @@
We started to use uucp after the dialin lines had been in place for a while.
It would have been very unpopular here to remove one of lines from public use
to let uucp dial out. The first version of these changes ran here early in
1983.
Having this ability is very useful way to make full use of your modems. For
one thing, I can smile when a neighoring site complains that their one dialer
is tied up from news backed up to one of their neighbors which has been down
for a while and has just come back up. For another thing some of our neighbors
seem to be reachable better by some modems than by others. For example, I can
only reach rocky2 with a Racal Vadic. I can only reach akgua, burl, and
sjuvax with a Hayes. When our 2400 baud modem arrives so I can make special
note of that --- and I don't have to buy two 2400 baud modems to have two-way
2400 baud capability.
The key to this is a program is provided in the file acucntrl.c . This should
be installed suid to root in the file /usr/libexec/acucntrl .
uucp notes:
The 3rd field of the L-devices file should contain "inout" for all devices
intended for dialin/out use. Devices without the "inout" specification will
be used like before: for dialout only.
Good luck. I want to never go back to reserving modems for dialout.
Bill Sebok Princeton University, Astrophysics
{allegra,akgua,burl,cbosgd,decvax,ihnp4,noao,princeton,vax135}!astrovax!wls

View File

@@ -0,0 +1,63 @@
# The format of the L-devices file is:
# Caller Line Useful Class Dialer [Chat ...]
#
# A line beginning with a # is a comment
# If the last character of a line is \
# the next line is considered to be a continuation of the first.
#
# The following lines are hard-wired
#
DIR ttyh3 unused 300 direct
DIR ttyh3 unused 1200 direct
#
# The following lines are ACUs
#
ACU cul0 cua0 1200 dn11
ACU cul1 cua1 1200 dn11
ACU tty49 unused 1200 ventel
ACU tty49 unused 300 ventel
ACU tty48 unused V1200 vadic
#
# For hayes smartmodems, specify 'hayestone' for touch tone,
# 'hayespulse' for pulse dialing. 'hayes' means 'hayespulse'
#
ACU tty47 unused 1200 hayestone
#
# The following port is to a Develcon DataSwitch.
# The 'DIR' line is used to talk to other machines on the switch.
# See how it is used in L.sys.
# The 'ACU' line is used to talk to a call-out modem on the switch.
# In this case the modem is a hayes. The 'chat' script
# makes the connection to the modem so the normal hayes modem code
# in condevs.c can be used. Here the chat script
# 'expects nothing', 'sends a return', 'expects uest:'
# (the DataSwitch's prompt), 'sends outmodem',
# and expects control-g (the DataSwitch's connection prompt).
# Note, it is a current nit that the control-g has to be typed as is
# rather than as ^g or as \07. Sorry.
#
DIR tty50 unused 9600 direct
ACU tty50 unused 1200 hayespulse "" "" uest: outmodem 
#
#
# PC Pursuit line
#
# callback_modem is the device that you have connected to
# callback_number. callback_number is the phone number of your
# modem that PCPursuit will call back on.
# their_phone is the number of PC Pursuits computer
# my_baud is the baudrate to call them at (it is assumed the
# callback will be at the same rate)
# my_modem_type is the brand of modem you are using on the
# callback number. This is used to hang up the modem in case of
# error.
#
# Currently, the outgoing call is made on an available ACU.
#
# PCP callback_modem their_phone my_baud my_modem_type my_callback_number
PCP tty07 6592863 1200 hayes 5281234
PCP tty07 6592881 1200 hayes 5281234

View File

@@ -0,0 +1,15 @@
# This is basically used for string matching
# You do not need to use it. Some sites prefer
# to put "chicago2486706" in their L.sys instead of
# "13122486707"
#
#
# A line beginning with a # is a comment
# If the last character of a line is \
# the next line is considered to be a continuation of the first.
#
# Example L-dialcodes
#
chicago 1312
dc 1202
sandiego 1714

View File

@@ -0,0 +1,19 @@
#
# This is useful when a site changes its uucp name.
# the file format is "newname" space "oldname"
kobold helios
ucadmus cadmus
decuac grendel
#
# it is also useful when dealing with sites that are not properly sending
# you their full sitename
#
ut-sally ut-sall
nbs-amrf nbs-amr
turtlevax turtlev
cal-unix cal-uni
prometheus prometh
lbl-csam lbl-csa
rochester rochest
#
# here, as in all the other L files, a line beginning with # is a comment

View File

@@ -0,0 +1,25 @@
# This is the list of commands that uuxqt will execute.
#
# A line beginning with a # is a comment
# If the last character of a line is \
# the next line is considered to be a continuation of the first.
#
# A line of from PATH=... changes the path used to locate the commands.
#
# Example L.cmds
#
PATH=/bin:/usr/bin:/usr/ucb
# If there is a suffix of ,Error, a message will only be returned if
# the exit status is non-zero. If there is a suffix on ,No, there
# will never be a return message from uuxqt.
rmail
# Only return the status of a rnews if it is non-zero
rnews,Error
ruusend
# Never return the status of an nfrcv
nfrcv,No
# These next programs are security holes, but noone seems to care
lpr
who
uusend
finger

121
src/cmd/uucp/UUAIDS/L.sys Normal file
View File

@@ -0,0 +1,121 @@
# This file contains the majority of the information used to call
# the destination system. It should not be readable to the world, as
# there are logins and passwords stored here
#
# A line beginning with a # is a comment
# If the last character of a line is \
# the next line is considered to be a continuation of the first.
#
# If the time is suffixed with ";N", then N is used as the retry time
# insterad of the default. E.g. Any;1 or Evening;60
#
# If the time is suffixed with "/X", then only files of grade X or
# lower will be sent during this time period.
# Multiple grades may be used in conjunction with the ",". E.g.
# Any/C,Evening/a,Night
# which send grades C and lower anytime, grades a and lower in the Evening
# and everything at Night
#
# The time may be any of the following:
# Any Anytime
# Evening When Evening rates are in effect
# NonPeak Tymnet/Telenets non-peak rates
# Night When Nighttime Phone rates are in effect
# Wk Any Week Day
# Mo Mondays
# Tu Tuesdays
# We Wednesdays
# Th Thursdays
# Fr Fridays
# Sa Saturdays
# Su Sundays
# These time may be suffixed with a time range nnnn-mmmm in thge 24 hour clock
# E.g.
# Evening = Wk1700-0800,Sa,Su
# NonPeak = Wk1800-0700,Sa,Su
# Night = Any2300-0800,Sa,Su0800-1700
# Wk = Mo,Tu,We,Th,Fr
#
# If the expect part of the expect/send sequence is suffixed with a ~number,
# then that number will be used for the timeout instead of the default
# MAXMSGTIME, which is delivered as 45 seconds.
# E.g. ogin~10-\r-ogin~15-\b-ogin
# will look for ogin for 10 seconds and if it doesn't find it, send a CR
# then look for ogin for 15 seconds and if it doesn't fint it send a break
# then look for ogin for MAXMSTIME seconds then exit
#
#
# Example L.sys file
#
# The following entry indicates that system 'mcnc' can be called any time,
# and is accessible over a hard-wired tty line (tty01) at 4800 baud.
# The login sequence is:
# "" expect nothing (sort of a kludge)
# "" send carriage return
# ogin:--ogin: look for 'login:', if not received send carriage return
# and look again.
# Urti login as Urti
# ssword: look for Password:
# fatchance supply the password.
#
mcnc Any DIR 4800 tty01 "" "" ogin:--ogin:--ogin: Urti ssword: fatchance
#
# The following entry shows that the machine 'rti-sel' can be called any time
# via /dev/tty02 at 300 baud. The send-expect sequence is complex
# because it is operating a Racal-Vadic auto-dialer. An easier method would
# be to use the code supplied for a Vadic auto-dialer. See the Notes.L.sys
# and L-devices files.
# This is an unusual use of send-expect, but shows its capabilities.
# "" expect nothing
# \05 send ^E return (activate auto-dialer)
# *~2-\05-*~2 look for *, wait 2 seconds, if no such reactivate
# dialer, and look again for 2 seconds
# d send 'd' to enter a phone number
# NUMBER?~3-d... look for prompt from auto-dialer
# 7654321\r\d send number, then return, then pause, then return
# LINE wait for modem to say 'ON LINE'
# \r\d\r send return, pause, then send return again
# ogin:-\b-... look for login, if not found send a 'break'
# look again, if still not found send another 'break'
# and look one more time before giving up.
#
rti-sel Any ttyh3 300 ttyh3 "" \05 *~2-\05~2-* d NUMBER?~3-d-NUMBER?~3 7654321\r\d LINE \r\d\r ogin:-\b-ogin:-\b-ogin: Urti ssword: fatchance
#
# The next entry is for a normal ACU. uucp normally handles only a DN11.
# However, the 'condevs.c' routine can be modified to handle any kind
# of auto-dialer desired. (This is, however, an awful part of uucp.)
# Calls can be placed any day but only between 11pm and 8am.
# The connection is 300 baud.
#
rti-sel Any2300-0800 ACU 300 13057654321 ogin:--ogin: Urti ssword: fatchance
#
# The next entry is for a 4.2BSD TCP-IP connection.
# There must be a #define BSDTCP in uucp.h, and you must install
# a 'uucpd' uucico server daemon in /usr/libexec.
# Also, add an entry to /etc/services, such as:
# uucp 540/tcp uucpd
# The '540' is the port number chosen for uucpd.
# The fields are: remote uucpname, time-to-call, TCP, portnumber, networkname.
# Sane installations will have identical uucp and networknames. However,
# arpanet machines will probably have to add their domain. Make sure that
# the network name (in this case seismo.CSS.GOV) is the entry returned for
# the sites hostname by gethostbyaddr(). An alias will not (always) work.
# This is mandatory if you are running the domain name server.
#
seismo Any TCP uucp seismo.CSS.GOV ogin: uucplogin ssword: uucppassword
#
# If ncsu cannot be raised by the method above, use the ACU.
# uucico tries each entry for ncsu in turn, until one of them connects.
# Calls on the ACU are only permitted when phone rates are cheap.
# Send grade Z or lower in the evening and if you fail retry as
# fast as 1 minute. send everything else at night.
#
ncsu Evening/Z;1,Night ACU unused 987-6543 ogin:--ogin: Urti ssword: fatchance
#
# Connect to ihnp4 using PC Pursuit
#
# chicago is the PCPursuit City name.
# 6907171 is the phone number for ihnp4
#
ihnp4 NonPeak PCP chicago 6907171 "" \d@ ogin:~5-BREAK-ogin:~5-\r-ogin: UULOGIN ssword: PASWORD

View File

@@ -0,0 +1,84 @@
This file describes the layout of the L.sys and L-devices files.
Here's my interpretation of L.sys:
Site When Caller Class CallCode Login
The nominal value for Caller is ACU, but it can be the code for any
device that places calls, e.g., micom, datakit, ethernet, etc. The
CallCode field contains the dope needed by the caller to complete the
connection, e.g., for an ACU, CallCode is the phone number, while for,
say, a micom, CallCode is the micom code for Site. Class is nominally
speed, but circumstances sometimes make it necessary to encode other
information here. E.g., at Bell Labs many sites distinguish centrex and
dimension. Some use it to identify sites that answer vadic only.
For ACU Callers, this is the old interpretation. Some examples:
lento Any ACU D1200 MHd7464 ...
lento Any ACU C1200 MH2057 ...
lento Any MICOM 9600 lento ...
lento Any DK unused mh/tempo/lento ...
lento Any UNET lento 33 ...
lento Any DIR 9600 tty42 ...
lento Any DIR 2400 tty43 ...
i.e., to get to lento, dial on an ACU, or open a micom port and whisper
"lento" down it, or open a datakit port and shout "mh/tempo/lento" down
it, or open Unet server 33 on Unet host 'lento', or call on tty42.
Here's my interpretation of L-devices:
Caller Line Useful Class Dialer
Caller and Class are as above. Line identifies the device on which the
call is placed. The Useful field is a place to identify something else
needed to dial, e.g., the name of a dialing device, or a code to get
past a sentry. The (new) Dialer field identifies the type of dialer
being used so that the right dialing function can be called. Some examples:
ACU cul0 cua0 1200 dn11
ACU cul1 cua1 1200 dn11
ACU tty49 unused 1200 ventel
ACU tty49 unused 300 ventel
ACU tty48 unused V1200 vadic
ACU tty47 unused 1200 hayes
ACU tty47 unused 300 hayes
MICOM micom unused 9600 micom
DIR tty42 unused 9600 direct
If you wish to add another dialer/caller type, you must add a line to the
condevs structure definded in condevs.c. There is a line in the condevs
table for each device type listed in the L-devices file. The condev structure
looks like:
struct condev {
char *CU_meth; /* method, such as "ACU" or "DIR" */
char *CU_brand; /* brand, such as "vadic" or "ventel" */
int (*CU_gen)(); /* what to call to search for brands */
int (*CU_open)(); /* what to call to open brand */
int (*CU_clos)(); /* what to call to close brand */
} condevs[];
The line for the Ventel might look like:
{ "ACU", "ventel", Acuopn, ventopn, ventcls },
While the line for the UNET interface might look like:
{ "UNET", "unet", unetopn, nulldev, unetcls },
There can be many 'brands' of the same kind of device, such as auto-dialers.
The condevs array is searched for a method that matches the one in the L.sys
file. The string comparison is done without regard to case, so "Acu" will
match "ACU". Once a match is found, the routine pointed to by CU_gen is
called. It is passed a pointer to the flds array, the array of pointers to
strings derived from the L.sys entry.
Typically, the CU_gen vector goes through the L-device table looking for
a entry that is available, then trys to connect on that brand via the
CU_open vector. If that fails, it might go on to the next brand.
When it succeeds in opening a line, it should assign the brand closing
vector (CU_clos) to the global symbol CU_end (i.e. CU_end = cd->CU_clos).
The routine pointed to by CU_end is called when the line is to be shutdown.
It is passed a file descriptor which it is to close.
Another ACU can be added by writing the code for the CU_open and CU_clos
and adding a line in the condevs[] table. The routine pointed to by
CU_open is passed a pointer to the phone number; a pointer to the flds array;
and a pointer to the dev structure, which contains the information from the
L-devices entry. It should return a file descriptor that can be used to
communicate with the other machine, or CF_DIAL if the connection was not made.

View File

@@ -0,0 +1,12 @@
# Example USERFILE
# Lines are of form 'loginname,uucpname fileprefix[, ...]
# It is recommended that each site have a unique login name and password.
# fileprefix is typically / or /usr/spool/uucppublic.
#
Umcnc,mcnc /
Uillia,illia /
# This last line is recommended to reduce aggravation.
# Security minded sites woulr probably use:
# , /usr/spool
# instead
, /

View File

@@ -0,0 +1,269 @@
.TL
Setting up the Net
.AU
Tom Truscott
.AI
Duke University
(now at the Research Triangle Institute, NC)
January 1980
(revised 1983 to better reflect reality)
.SH
Installing files and Programs.
.PP
This paper describes how to get the system named "xyz" on the uucp net.
If you are on the net, stop reading!
In chosing your system name, keep it short (no more than 7 characters long)
and make it specific.
That is, 'physics' is a poor uucp name!
The University of California at Berkeley names their machines
ucbvax, ucbcad, ucbmone, etc.
A standard Seventh Edition
.UX
system is assumed.
[Yup, this is ancient! I have deleted useless paragraphs -- trt]
The v7 C compiler MUST be used to recompile uucp;
the Phototypesetter version fails.
It is necessary to compile and install the mail, uucp, and news programs.
In what follows, "/bin/..." can be replaced by "/usr/bin/...".
.SH
MAIL
.PP
Ignore this section if you machine already has a network
mail program in place.
First, you must tell your machine its name.
Modern versions of UNIX use gethostname(II) or uname(II).
Ancient versions use include files.
If you are in the dark ages, edit /usr/include/whoami.h
and change the system name to xyz.
Do the same to /usr/include/ident.h
(not currently used, by the way).
Then recompile mail:
.DS
cd /usr/src/cmd
cmake mail
.DE
and copy it to /bin.
It should be setuid to root.
The network uses a restricted version of mail,
which is actually mail but invoked with a different name:
.DS
ln /bin/mail /bin/rmail
.DE
Mail should now be ready for the net.
A newer version of mail, called Mail, should be used if you have it.
It invokes a mail delivery program called delivermail
or the newer one called sendmail.
.SH
UUCP
.PP
Read the documents on uucp and uucp implementation in the
.I
.UX
Programmer's Manual.
.R
Also read the manual pages for uucp and uux.
.NH 1
Getting ready to install uucp
.PP
Edit /etc/passwd to add the user "uucp" to your system.
Uucp should have unique user and group ids (for security).
Duke's uucp and daemon have the same group id,
so they can both access /dev/dn?
which is not accessible by "others."
Uucp will own the directories and other files of the uucp system.
Actually, it is nice to also add the user "UUCP" as a synonym for "uucp",
and put "UUCP" earlier in /etc/passwd.
That way uucp will identified as UUCP in mail messages, etc.,
which highlights the fact that the messages are machine generated.
Here are typical lines:
.DS L
UUCP:iPkI/ZUX3YX2Y:4:19::/usr/spool/uucppublic:/usr/sbin/uucico
uucp:iPkI/ZUX3YX2Y:4:19::/usr/spool/uucppublic:/usr/sbin/uucico
.DE
.NH 1
Installing uucp programs
.PP
To install uucp, read the INSTALL file in the uucp directory
and follow the instructions.
It references other documentation, which should also be read.
.NH 1
Files in /etc/uucp
.PP
All of these files should have the uid and gid of uucp,
and should not be readable (or writable) by others.
The files "L-devices" and "L-dialcodes"
are needed only if xyz calls other systems.
The file formats are described in the documentation
and are straightforward.
The USERFILE file should have one line for each system which calls xyz:
.DS
Uduke,duke /usr/spool/uucppublic
,xyz /
.DE
The first line of the sample USERFILE indicates
that the duke system uses login name Uduke
and can access the public directory.
Here is a typical "Uduke" line in /etc/passwd:
.DS L
Uduke:PSB8EZ5w2tQ4I:4:19::/usr/spool/uucppublic:/usr/sbin/uucico
.DE
This line differs from that for uucp
only in having a different login name and password.
The last line of USERFILE should be ",xyz /",
which permits local users but not remote systems
to access anything on xyz.
[Actually, USERFILE is a real botch. If you want security,
never given anyone permission from '/'.]
.PP
The file L.sys has a line for each system
with which xyz communicates.
If xyz DOES NOT place calls to Duke
then the L.sys line for Duke might be:
.DS
duke None ACU 300 123-4567 ogin Uxyz ssword fooha
.DE
This line indicates that xyz should never ("None") call Duke.
If xyz DOES place calls to Duke
then the line must be altered to so indicate.
The documentation explains that case fairly well.
.NH 1
Getting it running
.PP
Uucp is now ready for execution.
If Duke is to call xyz,
the xyz system can request that Duke send mail
to test its operation.
/usr/spool/uucp/LOGFILE, SYSLOG, and ERRLOG
are useful logs of uucp activity.
If uucp does not work, and the problems cannot be resolved,
xyz could give Duke another login on xyz
so someone here can poke around
and see what the problem might be.
The login should have the same uid and gid as uucp
but without a uucico "shell".
.PP
If xyz can place calls to another system,
a good test is to try to place the call.
Suppose xyz has both a call-out and a call-in line.
Then an entry for the mythical system "foo"
can be put in the L.sys and USERFILE files,
and xyz can call itself as follows:
.DS
echo "test 1" | mail foo!root
echo "test 2" | mail foo!xyz!root
echo "test 3" | mail foo!foo!root
.DE
Mail sent from system xyz to itself
causes a local invocation of mail.
Mail sent to the mythical system "foo" will,
however, place a call to send the mail.
Uucp will complain about locking,
and shell metacharacters may not work,
but the communication should still succeed.
Even if xyz has only a call-in or call-out unit
it may be possible to fake the other one
by putting a null modem between the two lines.
[Unfortunately, the newest version of uucp
botches loop testing fairly badly.
But you can observe it successful connect.]
.PP
Also helpful is use of the "-x" debugging option.
The debugging information produced by
this blatant security hole
is truly a wonder to behold.
When it is in effect, the /usr/spool/uucp/AUDIT
file at the remote end will also collect debugging information.
.NH 1
Cleaning up after uucp
.PP
Uucp will run okay without any cleanup;
however, the uucp files can become immense.
Duke runs several shell files via cron(8).
These are in uuaids/uu.*.
Systems which call Duke should run the following script occasionally:
.DS
/usr/sbin/uucico -r1 -sduke
.DE
Systems which call-out can
request uucp to transmit waiting files:
.DS
/usr/sbin/uucico -r1
.DE
The standard version of cron runs with uid "daemon"
which may not be able to run the cleanup or uucico scripts.
The scripts could be run via at(1),
or you could remove the "setuid(1);" at the start of cron.
Then cron gives superuser privileges to its children.
As a precaution, we run a program
which does a setuid to uucp before invoking the scripts.
.NH 1
Obscure problems that can happen
.PP
When uucp logs in, it is greeted (in standard V7 systems)
with the message of the day, "you have mail.", and so forth.
Sometimes these messages cause uucp to fail.
One cure is for login to suppress the messages
when the user has a non-standard shell (e.g. uucico).
.PP
If you have implemented your own tty handler,
be sure it supports 8 bit RAW input and output.
You should compare your own handler
with that of the standard tty.c,
and make sure the RAW mode execution is the same.
[This version does not yet support 7 bit datapath.]
.SH
USING THE NET
.PP
The simplest and least error-prone use of the net
is that of sending mail from one system to another.
A user on xyz can send a letter to Duke as follows:
.DS
echo "xyz lives" | mail duke!root
.DE
A letter can be sent to unc as follows:
.DS
echo "xyz lives on" | mail duke!unc!root
.DE
Here are some local network enthusiasts:
[I only kept this around for historical interest.]
.TS
l l l.
duke!swd Steve Daniel C version of news
duke!jte duke system administrator
duke!trt Tom Truscott network enthusiast
duke!unc!smb Steve Bellovin network news architecture
duke!phs!dennis Dennis Rockwell V6/PWB UNIX enthusiast
.TE
.PP
Uucp provides a convenient way
to transfer files between systems.
Files may be transferred by mailing them,
but that can get annoying.
Here are some hints for using uucp.
.IP 1.
By convention, the name "~uucp" may be used to access
the public directory on any system.
Thus,
.ti +5
uucp -m -d x.c duke!~uucp/xyz/
.br
copies the file x.c to the subdirectory xyz
of Duke's public directory (/usr/spool/uucppublic).
The "-m" option requests that mail be sent when x.c is transmitted.
The "-d" option requests that the remote system
create any directories that are needed
(in this case, the subdirectory xyz).
The final "/" in ".../xyz/"
informs uucp that xyz is a directory and not an ordinary file.
.IP 2.
uucp -d -m x.c duke!unc!~uucp/xyz/
.br
will not work since uucp cannot handle "duke!unc!".
Uucp and uux work only between two systems;
they do not handle a system-pathname sequence as does mail.
[See uusend for a uucp-like multi-hop copy program.]
.SH
NEWS
.PP
You are not running the distributed bulletin board?!
Poor innocent. Don't start. You can never go back.

View File

@@ -0,0 +1,33 @@
: Daily uucp script
: assumes you have subdirectories.
: If you do not have them, delete the '-d....' options below.
: someone should use shell variables to do this
: Much better to have subdirectories, however.
PATH=/bin:/usr/bin:/usr/sbin:/usr/ucb
#
umask 2
deadtime=`expr 24 \* 7`
(
uuclean -pLTMP. -n24
uuclean -p/usr/spool/uucp/STST -n24
uuclean -d/usr/spool/uucp/AUDIT -n48
uuclean -d/usr/spool/uucp/TM. -pTM. -n24
uuclean -d/usr/spool/uucp/XTMP -n24
uuclean -d/usr/spool/uucp/X. -pX. -n$deadtime
uuclean -d/usr/spool/uucp/C. -pC. -n$deadtime
uuclean -d/usr/spool/uucp/D. -pD. -n$deadtime
uuclean -d/usr/spool/uucp/D.`uuname -l` -pD. -n$deadtime
uuclean -d/usr/spool/uucp/D.`uuname -l`X -pD. -n$deadtime
) >/dev/null 2>&1
/etc/uucp/uucpsummary | /usr/ucb/Mail -s "UUCP Summary" uucplist
cd /usr/spool/uucp
#
# Ma Bell's uudemon.day saves a week's worth of log file information;
# obviously, the site that came up with that never ran netnews.
#
mv LOGFILE Log-DAY
mv SYSLOG Syslog-DAY
# remove old junk from our public directory
cd /usr/spool/uucppublic
find . -type f -mtime +30 -exec rm -f {} \;

View File

@@ -0,0 +1,36 @@
PATH=/bin:/usr/sbin:/usr/bin:/usr/ucb
#
umask 2
# give them 7 days to get through
deadtime=`expr 24 \* 7`
(
uuclean -d/usr/spool/uucp/LCK -n24
uuclean -d/usr/spool/uucp/STST -n24
uuclean -d/usr/spool/uucp/AUDIT -n48
rm -f /usr/spool/uucp/AUDIT/[0-9]*
uuclean -d/usr/spool/uucp/TM. -pTM. -n24
uuclean -d/usr/spool/uucp/XTMP -n24
uuclean -d/usr/spool/uucp/X. -pX. -n$deadtime
uuclean -d/usr/spool/uucp/C. -pC. -n$deadtime
uuclean -d/usr/spool/uucp/D. -pD. -n$deadtime
uuclean -d/usr/spool/uucp/D.`uuname -l` -pD. -n$deadtime
uuclean -d/usr/spool/uucp/D.`uuname -l`X -pD. -n$deadtime
) >/dev/null 2>&1
cd /usr/spool/uucp
/etc/uucp/uucpsummary | /usr/ucb/Mail -s "UUCP Summary" uucplist
cd /usr/spool/uucp/LOG
for i in uucico uux uuxqt uucp xferstats
do
cd $i
for j in *
do
mv $j .$j
done
cd ..
done
find . -type f -mtime +7 -exec rm -f {} \;
cd /usr/spool/uucppublic
find . -type f -mtime +30 -exec rm -f {} \;

View File

@@ -0,0 +1,10 @@
: Hourly uucp script
: uulog; : uulog no longer needed
: hourly poll of certain sites
: /usr/sbin/uucico -r1 -smcnc
: /usr/sbin/uucico -r1 -sillia
: attempt to ship remaining files
/usr/sbin/uucico -r1

View File

@@ -0,0 +1,4 @@
: Weekly uucp script
SPOOL=/usr/spool/uucp
mv $SPOOL/SYSLOG $SPOOL/SYSLOG.old

View File

@@ -0,0 +1,89 @@
#!/bin/sh
: '/*********************************************************************
uucp.daily
Sccsid=@(#)uucp.daily 1.1.1 (2.11BSD) 1996/10/25
usage:
Called from cron in the wee early hours of the morning
arguments:
none.
history:
long time ago original version
07/02/82 revisions to month change handling
*********************************************************************/'
: 'daily UUCP cleanup'
: 'called in the morning'
spool=/usr/spool/uucp
olddir="$spool/OLD"
PATH="/usr/new:/usr/ucb:/usr/local:/bin:/usr/bin" ; export PATH
/usr/bin/uulog
/usr/sbin/uuclean -m -p LCK. -p X. -p D. -p C. -p TM.
/usr/sbin/uuclean -p STST. -n 12
set `date`
day=$1
month=$2
daymon=$3
: '************************************************************
Old spool/log files are kept by the naming scheme:
LOGFILE.${day}${daymon} where ${day} is the day of
the week (Sun-Sat), and ${daymon} is the numerical
day of the month. SYSLOG files are kept by the scheme:
SYSLOG.week: the current weeks: totals; SYSLOG.month:
the current months totals; SYSLOG.${month} where
${month} is the first three letters of the month: the
totals for that month.
************************************************************'
cd $spool
mv LOGFILE $olddir/LOGFILE.${day}${daymon}
mv SYSLOG SYSLOG.$$
cat SYSLOG.$$ >>$olddir/SYSLOG.week
rm -f SYSLOG.$$
: 'clean up UUCP logfiles'
cd $olddir
: 'save the current SYSLOG in a monthly summary
each Monday.
'
case $day in
Mon) cat SYSLOG.week >>SYSLOG.month
rm -f SYSLOG.week
;;
esac
: 'Create monthly name file if necessary'
if [ ! -f logmonth ]
then
echo $month >logmonth
curmonth=$month
else
curmonth=`cat logmonth`
fi
: 'If the month has wrapped around, save the monthly
summary by the name of the month
'
if [ $month != $curmonth ]
then
if [ -f SYSLOG.week ]
then
cat SYSLOG.week >>SYSLOG.month
rm -f SYSLOG.week
fi
mv SYSLOG.month SYSLOG.$curmonth
echo $month >logmonth
uuusage $curmonth >UUUSAGE.${curmonth}
fi
: 'Remove LOGFILEs older than three days; save SYSLOG
files forever (remove manually)
'
find . -name 'LOGFILE.*' -mtime +3 -exec rm -f {} \;

View File

@@ -0,0 +1,41 @@
/*
* UNET (3Com) TCP-IP server for uucico.
* uucico's UNET channel causes this server to be run at the remote end.
* An argument, if present, is the local port number.
* This server does a tcpopen(III) to establish the connection,
* renames file descriptors 0,1, and 2 to be the UNET connection,
* and then exec(II)s uucico.
*/
#include <stdio.h>
#include <UNET/unetio.h>
#include <UNET/tcp.h>
/* Default port of uucico server */
#define DFLTPORT 33
main(argc, argv)
int argc;
char **argv;
{
register int lport, fd;
register FILE *fp;
extern int errno;
lport = DFLTPORT;
if (argc >= 2)
lport = atoi(argv[1]);
if (lport <= 0 || lport > 255)
lport = DFLTPORT;
fd = tcpopen((char *)0, 0, lport, TO_PASSIVE, "rw");
if (fd == -1) {
perror("uucico server: tcpopen");
exit(1);
}
close(0); close(1);
dup(fd); dup(fd);
execl("/usr/sbin/uucico", "uucico", (char *)0);
perror("uucico server: execl");
exit(1);
}

View File

@@ -0,0 +1,240 @@
#!/bin/sh
PATH=:/bin:/usr/bin:/usr/ucb
export PATH
rm -f /tmp/cmds /tmp/callsto /tmp/callsfrom /tmp/inuse /tmp/outuse
touch /tmp/cmds /tmp/inuse /tmp/outuse
cd /usr/spool/uucp
if [ $# -gt 0 ]
then
what="$1/uucico/* $1/uux*/* $1/xferstats/*"
else
if [ -f LOGFILE ]
then
what="LOGFILE SYSLOG"
else
what="LOG/uucico/* LOG/uux*/* LOG/xferstats/*"
fi
fi
sed -e "s/PATH=.*PATH;//
/REQUEST/d" $what |
/bin/awk '
BEGIN { fmon = fday = ftime = 99
lmon = lday = ltime = 0 }
$4 ~ /SUCCEEDED|OK/ {
t = substr($3,index($3,"-")+1,5)
split(t,time,":")
if($5 !~ /conversation/) {
startup[$2] = time[1]*60+time[2]
date[$2] = substr($3, 2, index($3,"-")-2)
}
}
$4 ~ /FAILED|CAUGHT|OK|TIMEOUT/ {
if(startup[$2] == 0 || $5 ~ /startup/)
continue
t = substr($3,index($3,"-")+1,5)
split(t,time,":")
elapsed = time[1]*60+time[2] - startup[$2]
if (elapsed < 0 )
elapsed += 24*60
if (elapsed == 0)
elapsed = 1
if(callto[$2] ){
totcallto[$2] += elapsed
numcallto[$2]++
printf("%s\t%s\t%02d:%02d - %02d:%02d\n",$2,date[$2],startup[$2]/60,startup[$2]%60,time[1],time[2])>>"/tmp/callsto"
}else{
totcallby[$2] += elapsed
numcallby[$2]++
printf("%s\t%s\t%02d:%02d - %02d:%02d\n",$2,date[$2],startup[$2]/60,startup[$2]%60,time[1],time[2])>>"/tmp/callsfrom"
}
callto[$2] = 0
startup[$2] = 0
}
$4 ~ /SUCCEEDED/{
if ($5 ~ /call/)
callto[$2]++
}
$4 ~ /FAILED|CAUGHT/{
if ($5 ~ /call|conversation|SIGNAL/ )
failed[$2]++
}
$5 ~ /sent/{
sentbytes[$2] += $7
sentfiles[$2] ++
seconds[$2] += $9
retries[$2] += $11
havout = 1
outuse[$1] = $1
outusebytes[$1] += $7
outusefiles[$1] ++
outusesecs[$1] += $9
}
$5 ~ /received/{
recbytes[$2] += $7
recfiles[$2] ++
seconds[$2] += $9
retries[$2] += $11
havin = 1
inuse[$2 "!" $1] = $2 "!" $1
inusebytes[$2 "!" $1] += $7
inusefiles[$2 "!" $1] ++
inusesecs[$2 "!" $1] += $9
}
$5 ~/XQT/{
if( $7 ~ /!|@/ && $6 ~ /rmail/)
printf("%s\t%s\t%-8s\t%s\n",substr($3,2,index($3,"-")-2),substr($3,index($3,"-")+1,5),$2 "!" $4,$7)>>"/tmp/cmds"
}
$4 ~/XQT/{
if ($1 ~ /uucp|daemon|root|news/ || $7 != "rmail")
continue
printf("%s\t%s\t%-8s\t%s!%s\n",substr($3,2,index($3,"-")-2),substr($3,index($3,"-")+1,5),$1,$2,$7)>>"/tmp/cmds"
}
$10 ~/secs/ {
curtime = substr($4, 5, 6)
dtmp = curtime - int($9) - lasttime[$2]
if (dtmp > 0 && dtmp < 20)
dead[$2] += dtmp
lasttime[$2] = curtime
live[$2] += $9
}
{
n = index ($3, "/")
thismon = 0
if (n > 0 ) {
thismon = int(substr($3, 2, n-2))
if (lmon < thismon)
lmon = thismon
if (thismon < fmon)
fmon = thismon
}
m = index ($3, "-")
n++
thisday = 0
if( (m-n) > 0 ) {
thisday = int(substr($3, n, m-n))
if ((lday < thisday) && (lmon == thismon) || ldaymon != lmon) {
lday = thisday
ldaymon = thismon
}
if ((thisday < fday) && (fmon == thismon) || fdaymon != fmon) {
fday = thisday
fdaymon = thismon
}
}
thistime = substr($3,m+1,5)
if ((ltime < thistime) && (lmon == thismon) && (lday == thisday))
ltime = thistime
if ((thistime < ftime) && (fmon == thismon) && (fday == thisday))
ftime = thistime
}
END{
printf("\n\t\t\t\tUUCP Traffic Summary\n\n")
printf("\t\t\t\tFrom %d/%d %s To %d/%d %s\n\n",fmon,fday,ftime,lmon,lday,ltime)
printf("\t Calls Minutes Files Bytes Effective Unused\n")
printf("Site[Failed] To/From To/From To/From Sent/Received Baudrate Bandwidth\n")
for( i in startup ){
if(seconds[i]== 0)seconds[i]++
if(dead[i]+live[i])
percent = dead[i]*100/(dead[i]+live[i])
else
percent = 0
if (failed[i] || retries[i]) {
temp = i "[" failed[i]
if (retries[i])
temp = temp "/" retries[i] "]"
else
temp = temp "]"
} else
temp = i
printf("%-12s %3d/%-3d %5d/%-5d %4d/%-4d %8d/%-8d %6d %5d%%\n",\
temp,numcallto[i],numcallby[i],\
totcallto[i],totcallby[i],\
sentfiles[i],recfiles[i],\
sentbytes[i],recbytes[i],\
(recbytes[i]+sentbytes[i])*8/seconds[i],\
percent)
}
printf("\n\n\n\t\t\t\tOriginating Users\n\n")
printf("User\t\t Minutes Files Bytes\n\n")
if (havout == 1) {
for (i in outuse) {
printf("%-21s %5d %7d %8d\n", i,\
(outusesecs[i]+30)/60,\
outusefiles[i], outusebytes[i]) >> "/tmp/outuse"
}
}
if (havin == 1) {
for (i in inuse) {
printf("%-21s %5d %7d %8d\n", i,\
(inusesecs[i]+30)/60,\
inusefiles[i], inusebytes[i]) >> "/tmp/inuse"
}
}
}'
sort /tmp/outuse
echo " "
sort /tmp/inuse
echo " "
echo " "
echo " "
echo " Long Distance Calls"
echo
echo "To Day Start - End From Day Start - End"
cat >/tmp/$$local<<!!!
/^ut/d
!!!
sed -f /tmp/$$local /tmp/callsto | /bin/awk '
{
if (last == $1)
pr = ""
else {
last = $1
pr = $1
}
if (pr == "" && date == $2)
pd = ""
else {
date = $2
pd = $2
}
printf("%s\t%s\t%s - %s\n",pr,pd,$3,$5)
}'>/tmp/$$a
sed -f /tmp/$$local /tmp/callsfrom | /bin/awk '
{
if (last == $1)
pr = ""
else {
last = $1
pr = $1
}
if (pr == "" && date == $2)
pd = ""
else {
date = $2
pd = $2
}
printf("%s\t%s\t%s - %s\n",pr,pd,$3,$5)
}'>/tmp/$$b
pr -t -m /tmp/$$a /tmp/$$b | uniq
rm -f /tmp/$$[ab]
sed -e "
/rmail seismo!/d
/rmail rlgvax!/d
/rmail rochester!/d
/rmail umcp-cs!/d
/rmail brl-tgr!/d
/rmail brl-vgr!/d
s/)$//
" /tmp/cmds >/tmp/$$c
if [ -s /tmp/$$c ]
then
echo " "
echo " "
echo " "
echo " Outgoing Mail from Other Sites"
echo
echo "Day Time From To"
cat /tmp/$$c
fi
rm -f /tmp/cmds /tmp/$$* /tmp/callsto /tmp/callsfrom /tmp/inuse /tmp/outuse

View File

@@ -0,0 +1,130 @@
cat <<'E_O_F' >/tmp/$$a
BEGIN {
printf("\n\t\t\t\tUUCP Traffic Summary\n\n")
printf("\t\t\t\tFor the previous 30 days\n\n")
printf("\t Calls Minutes Files Bytes Effective Unused\n")
printf("Site To/From To/From To/From Sent/Received Baudrate Bwidth\n")
E_O_F
awk '$1 !~ /#/ && $1 !~ /xxx/{print $1,$3}' /etc/uucp/L.sys | sort -u |
sed 's/\(.*\) \(.*\)/ type["\1"] = "\2"/' >>/tmp/$$a
cat <<'E_O_F' >>/tmp/$$a
}
{
how = type[$1]
tcallsto[how] += $2
tcallsfrom[how] += $3
tminto[how] += $4
tminfrom[how] += $5
tfilesto[how] += $6
tfilesfrom[how] += $7
tbytesto[how] += $8
tbytesfrom[how] += $9
tbaudrate[how] += $10
tpercent[how] += $11
tfailed[how] += $12
tretry[how] += $13
tn[how]++
}
name == $1 {
callsto += $2
callsfrom += $3
minto += $4
minfrom += $5
filesto += $6
filesfrom += $7
bytesto += $8
bytesfrom += $9
baudrate += $10
percent += $11
failed += $12
retry += $13
n++
}
name != $1 {
if (NR > 1) {
s = name
if (failed > 0) {
s = s "[" failed
if (retry > 0)
s = s "/" retry "]"
else
s = s "]"
} else {
if (retry > 0)
s = s "[/" retry "]"
}
printf("%-12s %4d/%-4d %5d/%-5d %5d/%-5d %9d/%-9d %6d %5d%%\n", \
s, callsto, callsfrom, minto, minfrom, filesto, \
filesfrom, bytesto, bytesfrom, baudrate/n, percent/n)
}
callsto = $2
callsfrom = $3
minto = $4
minfrom = $5
filesto = $6
filesfrom = $7
bytesto = $8
bytesfrom = $9
baudrate = $10
percent = $11
failed = $12
retry = $13
n = 1
name = $1
}
END {
printf("%-12s %4d/%-4d %5d/%-5d %5d/%-5d %9d/%-9d %6d %5d%%\n", \
name, callsto, callsfrom, minto, minfrom, filesto, \
filesfrom, bytesto, bytesfrom, baudrate/n, percent/n)
printf("------------ ----/---- -----/----- -----/----- ---------/--------- ------ -----\n")
for (i in tn) {
s = i
if (tfailed[i] > 0) {
s = s "[" tfailed[i]
if (tretry[i] > 0)
s = s "/" tretry[i] "]"
else
s = s "]"
} else {
if (tretry[i] > 0)
s = s "[/" tretry[i] "]"
}
printf("%-12s %4d/%-4d %5d/%-5d %5d/%-5d %10d/%-10d %6d %3d%%\n", \
s, tcallsto[i], tcallsfrom[i], tminto[i], tminfrom[i], \
tfilesto[i], tfilesfrom[i], tbytesto[i], tbytesfrom[i], \
tbaudrate[i]/tn[i], tpercent[i]/tn[i])
totcallsto += tcallsto[i]
totcallsfrom += tcallsfrom[i]
totminto += tminto[i]
totminfrom += tminfrom[i]
totfilesto += tfilesto[i]
totfilesfrom += tfilesfrom[i]
totbytesto += tbytesto[i]
totbytesfrom += tbytesfrom[i]
totbaudrate += tbaudrate[i]
totpercent += tpercent[i]
totfailed += tfailed[i]
totretry += tretry[i]
totn += tn[i]
}
printf("%-12s %4d/%-4d %5d/%-5d %5d/%-5d %10d/%-10d %6d %3d%%\n", \
"Total", totcallsto, totcallsfrom, totminto, \
totminfrom, totfilesto, totfilesfrom, totbytesto, \
totbytesfrom , totbaudrate/totn, totpercen/totn)
}
E_O_F
for i in `grep -l 'UUCP Summary' /usr/msgs/*`
do
sed '1,/^Site/d
/^[ ]*$/,$d
s;\[/;[0/;
s;\[\([0-9]*\)\];[\1/0];
/\[/s;\([^\[]*\)\[\(.*\)/\(.*\)\]\(.*\);\1 \4 \2 \3;
s!/! !g
s/ */ /g
s/%//
' $i
done | sort | awk -f /tmp/$$a
rm -f /tmp/$$*

View File

@@ -0,0 +1,37 @@
case $# in
0)
FILE=/usr/spool/uucp/SYSLOG
;;
1)
FILE=$*
;;
*)
echo "usage: uustat [syslog]"
;;
esac
awk ' \
$5 ~ /received/ {ftotal++; fcount[$2]++; fbytes[$2] += $7; \
fsecs[$2] += $9} \
$5 ~ /sent/ {ttotal++; tcount[$2]++; tbytes[$2] += $7; \
tsecs[$2] += $9} \
{ curtime = substr($4, 5, 6); \
dtmp = curtime - int($9) - lasttime[$2]; \
if (dtmp > 0) if (dtmp < 20) \
dead[$2] += dtmp; \
lasttime[$2] = curtime; \
live[$2] += $9 ; \
} \
END { if (ftotal) for (i in fbytes) { \
printf "got from %8s %4d files %7d bytes %5d secs", i, \
fcount[i], fbytes[i], fsecs[i]; \
if (fsecs[i]) printf " %.2f bytes/sec", fbytes[i]/fsecs[i]; \
printf "\n"; } \
if (ttotal) for (i in tbytes) { \
printf "sent to %8s %4d files %7d bytes %5d secs", i, \
tcount[i], tbytes[i], tsecs[i]; \
if (tsecs[i]) printf " %.2f bytes/sec", tbytes[i]/tsecs[i]; \
printf "\n"; } \
for (i in live) { \
printf "%8s live%5d secs dead%5d secs\n", i, live[i], dead[i]; } \
}' \
$FILE

42
src/cmd/uucp/UUAIDS/uutbl Normal file
View File

@@ -0,0 +1,42 @@
#! /bin/sh
: '/*********************************************************************
program: uutbl
description: Make a "tbl" entry from output of uuusage command.
Produces tbl commands to make a centered display
table suitable for inclusion in monthly report.
programmer: Alan S. Watt
Sccsid=@(#)uutbl.sh 1.1
usage:
uuusage [options] | uutbl
history:
03/28/82 original version
05/27/82 Fix to eliminate "mangled record" diagnostics
from input.
*********************************************************************/'
: 'delete all the information on user usage and just report
the system usage summary. Leave the first line (the banner
heading) in.
'
grep -v "uuusage: mangled record" \
| sed '
1i\
.DS\
.TS\
center, tab(:);\
c s s s s s s\
l r r r r r r\
_ _ _ _ _ _ _\
l n n n n n n.
1a\
.sp
s/^[ ]*//
2,$s/ */:/g
$a\
.DE\
.TE
'

272
src/cmd/uucp/UUAIDS/uuusage Normal file
View File

@@ -0,0 +1,272 @@
#! /bin/sh
: '/*********************************************************************
uuusage
Print summary of UUCP usage
Alan S. Watt
Sccsid=@(#)uuusage.sh 1.1.1 (2.11BSD) 1996/10/25
usage:
uuusage [-s] [-t] [period]
arguments:
-s Just produce the system summary; dont include
individual user statistics.
-t Produce tbl(1) output.
period One of:
today Just print todays activities
week Week to date totals
month Month to date totals
m_name Totals for month <m_name> which
is a three letter abbreviation
for the month name.
history:
02/28/83 original version
*********************************************************************/'
: 'format of SYSLOG is:'
: 'cox onyxasw (4/16-18:24) received data 98 bytes 1 secs'
: 'format for newer version of UUCP stuff is:'
: 'swatt decvax (12/30-21:15) (378612944) sent data 64 bytes 0 secs'
: 'array usage:'
: ' files[name] == total number of files transferred'
: ' bytes[name] == total number of bytes sent'
: ' time[name] == total time spent by user'
: ' totfiles,tottime,totbytes are like above, but totals'
: ' sfiles[sname] == files transferred at request of system sname'
: ' sbytes[sname] == bytes sent/received at request of sname'
: ' stime[sname] == time spent at request of sname'
uudir=/usr/spool/uucp
uutbl=/usr/sbin/uutbl
slogprefix="$uudir/OLD/SYSLOG"
ologprefix="$uudir/OLD/UUUSAGE"
month=
tbloutput=0
systmonly=0
for arg
do
case $arg in
-s) : 'Only print system usage'
systmonly=1
;;
-t) : 'Generate TBL commands'
tbloutput=1 ; systmonly=1
;;
today) files="$uudir/SYSLOG"
;;
week) files="$slogprefix.week $uudir/SYSLOG"
;;
month) files="$slogprefix.month $slogprefix.week $uudir/SYSLOG"
;;
[Jj]an) month=Jan
;;
[Ff]eb) month=Feb
;;
[Mm]ar) month=Mar
;;
[Aa]pr) month=Apr
;;
[Mm]ay) month=May
;;
[Jj]un) month=Jun
;;
[Jj]ul) month=Jul
;;
[Aa]ug) month=Aug
;;
[Ss]ep) month=Sep
;;
[Oo]ct) month=Oct
;;
[Nn]ov) month=Nov
;;
[Dd]ec) month=Dec
;;
*) files="$files $arg"
;;
esac
done
: 'look for short cut on monthly summaries. If we have one,
just dump the summary, deleting the user information part if
-s set; running output through $utbl if -t set.
'
case $month in
'') ;;
*) \
if [ -s ${ologprefix}.${month} ]
then
case $systmonly$tbloutput in
"00") grep -v "uuusage: mangled record" \
${ologprefix}.${month}
;;
"10") grep -v "uuusage: mangled record" \
${ologprefix}.${month} \
| sed -e '2,/^$/d'
;;
"01"|"11") \
uuusage -s ${month} | $uutbl
;;
esac
exit
else
files=${slogprefix}.${month}
fi ;;
esac
: 'Default report: today"s transfers'
case $files in
'') files="$uudir/SYSLOG"
;;
esac
case $tbloutput in
1) uuusage -s ${files} | $uutbl
exit ;;
esac
flist=
for f in $files
do
if [ -r $f ]
then
flist="$flist $f"
else
echo "$f: Cannot read file"
fi
done
set " " $flist ; shift
case $# in
0) echo "no files to process" ; exit 1 ;;
esac
awk '
BEGIN {
systmonly='"$systmonly"'
fmon = 1000; lmon = -1000
oldnf = 9; newnf = 10
# User Format:
# user files bytes time Avgsiz Avgtim
dfmt = "%-10s%6d%10d%8d%7d%7d\n"
sfmt = "%-10s%6s%10s%8s%7s%7s\n"
# System Format:
# system files bytes time Avgsiz Avgtim rate
sfmt1 = "%-10s%6s%10s%8s%7s%7s%7s\n"
dfmt1 = "%-10s%6d%10d%8d%7d%7d%7d\n"
space = ""
# width of output for centering purposes
width = 52
}
(NR == 1) {
# Protect against partial records
maxfields = NF
if (NF == oldnf)
oldfmt++
else if (NF == newnf)
newfmt++
else {
# cant seem to get awk to really exit here
# it still tries to produce the report
printf "uuusage: mangled format of 1st record\n"
printf "must be either %d or %d fields\n", oldnf, newnf
exit (1)
}
}
(NF != maxfields) {
printf "uuusage: mangled record #%d in file %s (ignored)\n", \
NR, FILENAME
}
(NF == maxfields) {
# protect against format changes
D_name = $1
D_sname = $2
D_date = $3
# Old (V7/32V format vs. system III format)
if (oldfmt) {
D_bytes = $6
D_time = $8
}
else if (newfmt) {
D_bytes = $7
D_time = $9
}
# protect against division by 0
if (D_time == 0)
D_time = 1
# stash user usage info
if (!systmonly) {
name[D_name] = D_name; bytes[D_name] += D_bytes
time[D_name] += D_time; files[D_name] += 1
}
# stash system usage info
sname[D_sname] = D_sname; sbytes[D_sname] += D_bytes
stime[D_sname] += D_time
sfiles[D_sname] += 1
# get the date of the transfer
n = index (D_date, "/")
cmon = substr (D_date, 2, n-2)
m = index (D_date, "-")
n++
cday = substr (D_date, n, m-n)
# keep earliest and latest dates (naive about new year)
if (int(cmon) < int(fmon) || (cmon == fmon && int(cday) < int(fday))) {
fmon = cmon
fday = cday
}
if (int(cmon) > int(lmon) || (cmon == lmon && int(cday) > int(lday))) {
lmon = cmon
lday = cday
}
}
END {
banner = sprintf "UUCP Usage from %s/%s to %s/%s", \
fmon,fday,lmon,lday
precision = (width-length(banner))/2
format = sprintf "%%%ds\n", precision + length(banner)
printf format, banner
if (!systmonly) {
printf sfmt, "user", "files", "bytes", "time", \
"Avgsiz", "Avgtim"
totfiles=0; totbytes=0; tottime=0
for (n in name) {
printf dfmt, n, files[n], bytes[n], time[n], \
bytes[n]/files[n], time[n]/files[n]
totfiles += files[n]
totbytes += bytes[n]
tottime += time[n]
}
printf dfmt, "total", totfiles, totbytes, tottime, \
totbytes/totfiles, tottime/totfiles
print space
}
# now print system usage info
printf sfmt1, "system", "files", "bytes", "time", \
"Avgsiz", "Avgtim", "rate"
totfiles=0; totbytes=0; tottime=0
for (n in sname) {
printf dfmt1, n, sfiles[n], sbytes[n], stime[n], \
sbytes[n]/sfiles[n], stime[n]/sfiles[n], \
sbytes[n]/stime[n]
totfiles += sfiles[n]
totbytes += sbytes[n]
tottime += stime[n]
}
printf dfmt1, "total", totfiles, totbytes, tottime, \
totbytes/totfiles, tottime/totfiles, totbytes/tottime
} ' $flist

132
src/cmd/uucp/acucntrl.8 Normal file
View File

@@ -0,0 +1,132 @@
.\" @(#)acucntrl.8 6.2.1 (2.11BSD) 1996/11/27
.\"
.TH acucntrl 8 "November 27, 1996"
.UC 6
.SH NAME
acucntrl \- turn around tty line between dialin and dialout
.SH SYNOPSIS
.B /usr/libexec/acucntrl
keyword ttyline
.SH DESCRIPTION
.PP
.I Acucntrl
turns around terminal line, enabling it to be used for both dialin and dialout.
On dialin a terminal line is assumed to have modem control enabled and a getty
process in existence waiting for logins. On dialout modem control is disabled
and there is no getty process.
.PP
This program must be run setuid to root.
.PP
.I keyword
is chosen from the list:
.I disable
or
.IR dialout ,
to condition a line for dialout;
and
.I enable
or
.IR dialin ,
to condition a line for dialin.
.PP
When the line is conditioned for dialing out, the login name of the real uid
of the process is placed in /var/run/utmp in capitals.
This declares that the line is in use and acts as an additional locking
mechanism.
.I Acucntrl
will refuse to act if the /var/run/utmp entry for the line is not null,
is not the the user's login name (capitalized or not),
and if the process is not running as the superuser.
The last condition is to allow the superuser to clear the state of the line.
.PP
Turning modem control on or off is handled by poking into /dev/kmem.
It is currently implemented for dz, dh, and dmf lines.
.PP
Under 4.2 BSD the program will also refuse to disable a line if carrier is
sensed on it. This is to avoid the dead period where someone has just dialed
in and made the connection but has not yet logged in.
.PP
.I Ttyline
can be either of the form tty* or /dev/tty*.
Enabling/disabling a line whose name does not begin with ttyd? is prohibited
unless the real uid of the process is 0 or if the login name corresponding to
the real uid is uucp. This is a security precaution.
.PP
Steps taken when disabling
.RI ( i . e .
setup for dialing out)
.IP 1)
check input arguments
.IP 2)
look in /var/run/utmp to check that the line is not in use by another user
.IP 3)
disable modem control on line
.IP 4)
check for carrier on device
.IP 5)
change owner of device to real uid
.IP 6)
edit /etc/ttys, changing the first character of the appropriate line to 0
.IP 7)
send a hangup to process 1 to poke init to disable getty
.IP 8)
post uid name in capitals in /var/run/utmp to let world know device has been grabbed
.IP 9)
make sure that DTR is on
.PP
Steps taken when enabling
.RI ( i . e .
setup for dialin)
.IP 1)
check input arguments
.IP 2)
look in /var/run/utmp to check that the line is not in use by another user
.IP 3)
make sure modem control on line is disabled
.IP 4)
turn off DTR to make sure line is hung up
.IP 5)
condition line: clear exclusive use and set hangup on close modes
.IP 6)
turn on modem control
.IP 7)
edit /etc/ttys, changing the first character of the appropriate line to 1
.IP 8)
send a hangup to process 1 to poke init to enable getty
.IP 9)
clear uid name for /var/run/utmp
.SH HISTORY
.PP
First written by Allan Wilkes (fisher!allan)
.PP
Modified June 8,1983 by W.Sebok (astrovax!wls) to poke the kernel rather
than use a kernel hack to turn on/off modem control, using a subroutine
stolen from a program written by Tsutomu Shimomura {astrovax,escher}!tsutomu
.PP
Worked over many times by W.Sebok
.RI ( i . e .
hacked to death)
.SH FILES
/dev/kmem, /vmunix, /etc/ttys, /var/run/utmp, /dev/tty*
.SH BUGS
.PP
Sensing carrier requires the 4.2 BSD TIOCMGET ioctl call. Unfortunately this
ioctl is not implemented in the vanilla 4.2 BSD dh driver even though the
dz and dmf drivers use an emulation of the DH11's modem control bits. This
has been fixed here.
.PP
Some time (currently 2 seconds) is required between disabling modem control
and opening the device. This is probably because of a race with getty whose
open is finally being allowed to complete. This time interval may not be
enough on a loaded system. Because of this problem and the above problem with
the dh driver there is deliberately no error message given when the TIOCMGET
ioctl fails.
.PP
Previously there was similar synchronization problem with the init process.
When dialins are disabled the capitalized name of the process cannot be posted
into /var/run/utmp until init has finished clearing /var/run/utmp. However one does
not know how long that will take, and, on a loaded system, it can take quite
a while. This was solved by the strategy of 1) posting the name, 2) poking
init, 3) going into a loop where the process repeatedly waits a second and
checks whether the entry has been cleared from /var/run/utmp, and 4) posting the
name again.

774
src/cmd/uucp/acucntrl.c Normal file
View File

@@ -0,0 +1,774 @@
#if defined(DOSCCS) && !defined(lint)
static char sccsid[] = "@(#)acucntrl.c 5.8.2 (2.11BSD GTE) 1996/3/22";
#endif
/* acucntrl - turn around tty line between dialin and dialout
*
* Usage: acucntrl {enable,disable} /dev/ttydX
*
* History:
* First written by Allan Wilkes (fisher!allan)
*
* Modified June 8,1983 by W.Sebok (astrovax!wls) to poke kernel rather
* than use kernel hack to turn on/off modem control, using subroutine
* stolen from program written by Tsutomu Shimomura
* {astrovax,escher}!tsutomu
*
* Worked over many times by W.Sebok (i.e. hacked to death)
*
* Operation:
* disable (i.e. setup for dialing out)
* (1) check input arguments
* (2) look at the utmp file that the line is not in use
* (3) disable modem control on terminal
* (4) check for carrier on device
* (5) change owner of device to real id
* (6) edit /etc/ttys, changing the first character of the appropriate
* line to 0
* (7) send a hangup to process 1 to poke init to disable getty
* (8) post uid name in capitals in utmp to let world know device has
* been grabbed
* (9) make sure that DTR is on
*
* enable (i.e.) restore for dialin
* (1) check input arguments
* (2) look in utmp to check that the line is not in use by another
* (3) make sure modem control on terminal is disabled
* (4) turn off DTR to make sure line is hung up
* (5) condition line: clear exclusive use and set hangup on close modes
* (6) turn on modem control
* (7) edit /etc/ttys, changing the first character of the appropriate
* line to 1
* (8) send a hangup to process 1 to poke init to enable getty
* (9) clear uid name for utmp file
*/
/* #define SENSECARRIER */
#include "uucp.h"
#include <sys/buf.h>
#include <signal.h>
#include <sys/conf.h>
#ifdef pdp11
#include <pdpuba/ubavar.h>
#else
#ifdef BSD4_2
//#include <vaxuba/ubavar.h>
#else
#include <sys/ubavar.h>
#endif
#endif
#include <sys/stat.h>
#include <nlist.h>
#include <sgtty.h>
#include <utmp.h>
#include <pwd.h>
#include <stdio.h>
#include <sys/file.h>
#include <errno.h>
#include <string.h>
#define NDZLINE 8 /* lines/dz */
#define NDHLINE 16 /* lines/dh */
#define NDMFLINE 8 /* lines/dmf */
#define DZ11 1
#define DH11 2
#define DMF 3
#define NLVALUE(val) (nl[val].n_value)
struct nlist nl[] = {
#define CDEVSW 0
{ "_cdevsw" },
#define DZOPEN 1
{ "_dzopen" },
#define DZINFO 2
{ "_dzinfo" },
#define NDZ11 3
{ "_dz_cnt" },
#define DZSCAR 4
{ "_dzsoftCAR" },
#define DHOPEN 5
{ "_dhopen" },
#define DHINFO 6
{ "_dhinfo" },
#define NDH11 7
{ "_ndh11" },
#define DHSCAR 8
{ "_dhsoftCAR" },
#define DMFOPEN 9
{ "_dmfopen" },
#define DMFINFO 10
{ "_dmfinfo" },
#define NDMF 11
{ "_ndmf" },
#define DMFSCAR 12
{ "_dmfsoftCAR" },
{ "\0" }
};
#define ENABLE 1
#define DISABLE 0
char Etcutmp[] = _PATH_UTMP;
char Etcttys[] = "/etc/ttys";
#ifdef BSD4_3
FILE *ttysfile, *nttysfile;
char NEtcttys[] = "/etc/ttys.new";
extern long ftell();
#endif
char Devhome[] = "/dev";
char usage[] = "Usage: acucntrl {dis|en}able ttydX\n";
struct utmp utmp;
char resettty, resetmodem;
int etcutmp;
off_t utmploc;
off_t ttyslnbeg;
#define NAMSIZ sizeof(utmp.ut_name)
#define LINSIZ sizeof(utmp.ut_line)
main(argc, argv)
int argc; char *argv[];
{
register char *p;
register int i;
char uname[NAMSIZ], Uname[NAMSIZ];
int enable ;
char *device;
int devfile;
int uid, gid;
off_t lseek();
struct passwd *getpwuid();
char *rindex();
/* check input arguments */
if (argc!=3) {
fprintf(stderr, usage);
exit(1);
}
/* interpret command type */
if (prefix(argv[1], "disable") || strcmp(argv[1], "dialout")==0)
enable = 0;
else if (prefix(argv[1], "enable") || strcmp(argv[1], "dialin")==0)
enable = 1;
else {
fprintf(stderr, usage);
exit(1);
}
device = rindex(argv[2], '/');
device = (device == NULL) ? argv[2]: device+1;
/* only recognize devices of the form ttydX */
if (strncmp(device, "ttyd", 4)!=0) {
fprintf(stderr, "Bad Device Name %s", device);
exit(1);
}
opnttys(device);
/* Get nlist info */
nlist("/vmunix", nl);
/* Chdir to /dev */
if(chdir(Devhome) < 0) {
fprintf(stderr, "Cannot chdir to %s: %s\r\n",
Devhome, strerror(errno));
exit(1);
}
/* Get uid information */
uid = getuid();
gid = getgid();
p = getpwuid(uid)->pw_name;
if (p==NULL) {
fprintf(stderr, "cannot get uid name\n");
exit(1);
}
/* to upper case */
i = 0;
do {
uname[i] = *p;
Uname[i] = (*p>='a' && *p<='z') ? (*p - ('a'-'A')) : *p;
i++; p++;
} while (*p && i<NAMSIZ);
/* check to see if line is being used */
if( (etcutmp = open(Etcutmp, 2)) < 0) {
fprintf(stderr, "On open %s open: %s\n",
Etcutmp, strerror(errno));
exit(1);
}
(void)lseek(etcutmp, utmploc, 0);
i = read(etcutmp, (char *)&utmp, sizeof(struct utmp));
if(
i == sizeof(struct utmp) &&
utmp.ut_line[0] != '\0' &&
utmp.ut_name[0] != '\0' &&
(
!upcase(utmp.ut_name, NAMSIZ) ||
(
uid != 0 &&
strncmp(utmp.ut_name, Uname, NAMSIZ) != 0
)
)
) {
fprintf(stderr, "%s in use by %s\n", device, utmp.ut_name);
exit(2);
}
/* Disable modem control */
if (setmodem(device, DISABLE) < 0) {
fprintf(stderr, "Unable to disable modem control\n");
exit(1);
}
if (enable) {
if((devfile = open(device, 1)) < 0) {
fprintf(stderr, "On open of %s: %s\n",
device, strerror(errno));
(void)setmodem(device, resetmodem);
exit(1);
}
/* Try one last time to hang up */
if (ioctl(devfile, TIOCCDTR, (char *)0) < 0)
fprintf(stderr, "On TIOCCDTR ioctl: %s\n",
strerror(errno));
if (ioctl(devfile, TIOCNXCL, (char *)0) < 0)
fprintf(stderr,
"Cannot clear Exclusive Use on %s: %s\n",
device, strerror(errno));
if (ioctl(devfile, TIOCHPCL, (char *)0) < 0)
fprintf(stderr,
"Cannot set hangup on close on %s: %s\n",
device, strerror(errno));
i = resetmodem;
if (setmodem(device, ENABLE) < 0) {
fprintf(stderr, "Cannot Enable modem control\n");
(void)setmodem(device, i);
exit(1);
}
resetmodem=i;
if (settys(ENABLE)) {
fprintf(stderr, "%s already enabled\n", device);
} else {
pokeinit(device, Uname, enable);
}
post(device, "");
} else {
#if defined(TIOCMGET) && defined(SENSECARRIER)
if (uid!=0) {
int linestat = 0;
/* check for presence of carrier */
sleep(2); /* need time after modem control turnoff */
if((devfile = open(device, 1)) < 0) {
fprintf(stderr, "On open of %s: %s\n",
device, strerror(errno));
(void)setmodem(device, resetmodem);
exit(1);
}
(void)ioctl(devfile, TIOCMGET, &linestat);
if (linestat&TIOCM_CAR) {
fprintf(stderr, "%s is in use (Carrier On)\n",
device);
(void)setmodem(device, resetmodem);
exit(2);
}
(void)close(devfile);
}
#endif
/* chown device */
if(chown(device, uid, gid) < 0)
fprintf(stderr, "Cannot chown %s: %s\n",
device, strerror(errno));
/* poke init */
if(settys(DISABLE)) {
fprintf(stderr, "%s already disabled\n", device);
} else {
pokeinit(device, Uname, enable);
}
post(device, Uname);
if((devfile = open(device, O_RDWR|O_NDELAY)) < 0) {
fprintf(stderr, "On %s open: %s\n",
device, strerror(errno));
} else {
if(ioctl(devfile, TIOCSDTR, (char *)0) < 0)
fprintf(stderr,
"Cannot set DTR on %s: %s\n",
device, strerror(errno));
}
}
exit(0);
}
/* return true if no lower case */
upcase(str, len)
register char *str;
register int len;
{
for (; *str, --len >= 0 ; str++)
if (*str>='a' && *str<='z')
return(0);
return(1);
}
/* Post name to public */
post(device, name)
char *device, *name;
{
(void)time((time_t *)&utmp.ut_time);
strncpy(utmp.ut_line, device, LINSIZ);
strncpy(utmp.ut_name, name, NAMSIZ);
if (lseek(etcutmp, utmploc, 0) < 0)
fprintf(stderr, "on lseek in %s: %s", Etcutmp,
strerror(errno));
if (write(etcutmp, (char *)&utmp, sizeof(utmp)) < 0)
fprintf(stderr, "on write in %s: %s", Etcutmp,
strerror(errno));
}
/* poke process 1 and wait for it to do its thing */
pokeinit(device, uname, enable)
char *uname, *device; int enable;
{
struct utmp utmp;
register int i;
post(device, uname);
/* poke init */
if (kill(1, SIGHUP)) {
fprintf(stderr,
"Cannot send hangup to init process: %s\n",
strerror(errno));
(void)settys(resettty);
(void)setmodem(device, resetmodem);
exit(1);
}
if (enable)
return;
/* wait till init has responded, clearing the utmp entry */
i = 100;
do {
sleep(1);
if (lseek(etcutmp, utmploc, 0) < 0)
fprintf(stderr, "On lseek in %s: %s", Etcutmp,
strerror(errno));
if (read(etcutmp, (char *)&utmp, sizeof utmp) < 0)
fprintf(stderr, "On read from %s: %s", Etcutmp,
strerror(errno));
} while (utmp.ut_name[0] != '\0' && --i > 0);
}
#ifdef BSD4_3
/* identify terminal line in ttys */
opnttys(device)
char *device;
{
register int ndevice;
register char *p;
char *index();
char linebuf[BUFSIZ];
ttysfile = NULL;
do {
if (ttysfile != NULL) {
fclose(ttysfile);
sleep(5);
}
ttysfile = fopen(Etcttys, "r");
if(ttysfile == NULL) {
fprintf(stderr, "Cannot open %s: %s\n", Etcttys,
strerror(errno));
exit(1);
}
} while (flock(fileno(ttysfile), LOCK_NB|LOCK_EX) < 0);
nttysfile = fopen(NEtcttys, "w");
if(nttysfile == NULL) {
fprintf(stderr, "Cannot open %s: %s\n", Etcttys,
strerror(errno));
exit(1);
}
ndevice = strlen(device);
#ifndef BRL4_2
utmploc = sizeof(utmp);
#else
utmploc = 0;
#endif
while(fgets(linebuf, sizeof(linebuf) - 1, ttysfile) != NULL) {
if(strncmp(device, linebuf, ndevice) == 0)
return;
ttyslnbeg += strlen(linebuf);
if (linebuf[0] != '#' && linebuf[0] != '\n')
utmploc += sizeof(utmp);
if (fputs(linebuf, nttysfile) == NULL) {
fprintf(stderr, "On %s write: %s\n",
Etcttys, strerror(errno));
exit(1);
}
}
fprintf(stderr, "%s not found in %s\n", device, Etcttys);
exit(1);
}
/* modify appropriate line in /etc/ttys to turn on/off the device */
settys(enable)
int enable;
{
register char *cp, *cp2;
char lbuf[BUFSIZ];
int i;
char c1, c2;
(void) fseek(ttysfile, ttyslnbeg, 0);
if(fgets(lbuf, BUFSIZ, ttysfile) == NULL) {
fprintf(stderr, "On %s read: %s\n",
Etcttys, strerror(errno));
exit(1);
}
/* format is now */
/* ttyd0 std.100 dialup on secure # comment */
/* except, 2nd item may have embedded spaces inside quotes, Hubert */
cp = lbuf;
for (i=0;*cp && i<3;i++) {
if (*cp == '"') {
cp++;
while (*cp && *cp != '"')
cp++;
if (*cp != '\0')
cp++;
}else {
while (*cp && *cp != ' ' && *cp != '\t')
cp++;
}
while (*cp && (*cp == ' ' || *cp == '\t'))
cp++;
}
if (*cp == '\0') {
fprintf(stderr,"Badly formatted line in /etc/ttys:\n%s", lbuf);
exit(1);
}
c1 = *--cp;
*cp++ = '\0';
cp2 = cp;
while (*cp && *cp != ' ' && *cp != '\t' && *cp != '\n')
cp++;
if (*cp == '\0') {
fprintf(stderr,"Badly formatted line in /etc/ttys:\n%s", lbuf);
exit(1);
}
c2 = *cp;
*cp++ = '\0';
while (*cp && (*cp == ' ' || *cp == '\t'))
cp++;
resettty = strcmp("on", cp2) != 0;
fprintf(nttysfile,"%s%c%s%c%s", lbuf, c1, enable ? "on" : "off", c2, cp);
if (ferror(nttysfile)) {
fprintf(stderr, "On %s fprintf: %s\n",
NEtcttys, strerror(errno));
exit(1);
}
while(fgets(lbuf, sizeof(lbuf) - 1, ttysfile) != NULL) {
if (fputs(lbuf, nttysfile) == NULL) {
fprintf(stderr, "On %s write: %s\n",
NEtcttys, strerror(errno));
exit(1);
}
}
if (enable^resettty)
(void) unlink(NEtcttys);
else {
struct stat statb;
if (stat(Etcttys, &statb) == 0) {
fchmod(fileno(nttysfile) ,statb.st_mode);
fchown(fileno(nttysfile), statb.st_uid, statb.st_gid);
}
(void) rename(NEtcttys, Etcttys);
}
(void) fclose(nttysfile);
(void) fclose(ttysfile);
return enable^resettty;
}
#else
/* identify terminal line in ttys */
opnttys(device)
char *device;
{
register FILE *ttysfile;
register int ndevice, lnsiz;
register char *p;
char *index();
char linebuf[BUFSIZ];
ttysfile = fopen(Etcttys, "r");
if(ttysfile == NULL) {
fprintf(stderr, "Cannot open %s: %s\n", Etcttys,
strerror(errno));
exit(1);
}
ndevice = strlen(device);
ttyslnbeg = 0;
utmploc = 0;
while(fgets(linebuf, sizeof(linebuf) - 1, ttysfile) != NULL) {
lnsiz = strlen(linebuf);
if ((p = index(linebuf, '\n')) != NULL)
*p = '\0';
if(strncmp(device, &linebuf[2], ndevice) == 0) {
(void)fclose(ttysfile);
return;
}
ttyslnbeg += lnsiz;
utmploc += sizeof(utmp);
}
fprintf(stderr, "%s not found in %s\n", device, Etcttys);
exit(1);
}
/* modify appropriate line in /etc/ttys to turn on/off the device */
settys(enable)
int enable;
{
int ittysfil;
char out, in;
ittysfil = open(Etcttys, 2);
if(ittysfil < 0) {
fprintf(stderr, "Cannot open %s for output: %s\n",
Etcttys, strerror(errno));
exit(1);
}
(void)lseek(ittysfil, ttyslnbeg, 0);
if(read(ittysfil, &in, 1)<0) {
fprintf(stderr, "On %s write: %s\n",
Etcttys, strerror(errno));
exit(1);
}
resettty = (in == '1');
out = enable ? '1' : '0';
(void)lseek(ittysfil, ttyslnbeg, 0);
if(write(ittysfil, &out, 1)<0) {
fprintf(stderr, "On %s write: %s\n",
Etcttys, strerror(errno));
exit(1);
}
(void)close(ittysfil);
return(in==out);
}
#endif
/*
* Excerpted from (June 8, 1983 W.Sebok)
* > ttymodem.c - enable/disable modem control for tty lines.
* >
* > Knows about DZ11s and DH11/DM11s.
* > 23.3.83 - TS
* > modified to know about DMF's (hasn't been tested) Nov 8, 1984 - WLS
*/
/*
* 2.11BSD NOTE: 2.11BSD doesn't use ui_flags. We've included the code
* for correctness in case someone decides to change the way the 2.11BSD
* tty drivers work. Mostly what needs to be done is have the tty drivers
* do something like:
*
* if ((minor(dev)&0200) || (XXinfo[unit].ui_flags&(1L<<line))) {
* XXsoftCAR[unit] |= 1L << line;
* tp->t_state |= TS_CARR_ON;
* }
* else
* XXsoftCAR[unit] &= ~(1L << line);
*
* (2.11BSD uses a bit 0200 in the minor device number of a tty /dev node
* to indicate soft carrier as opposed to compiling it into the kernel as
* 4.3BSD does.) This code minus the check of ui_flags is already present
* in all 2.11BSD drivers.
*/
setmodem(ttyline, enable)
char *ttyline; int enable;
{
dev_t dev;
int kmem;
int unit, line, nlines;
int addr;
int devtype=0;
char cflags;
unsigned short sflags;
#ifdef BSD4_2
long flags, tflags;
#else
short flags, tflags;
#endif
struct uba_device *ubinfo;
struct stat statb;
struct cdevsw cdevsw;
if(nl[CDEVSW].n_type == 0) {
fprintf(stderr, "No namelist.\n");
return(-1);
}
if((kmem = open("/dev/kmem", 2)) < 0) {
fprintf(stderr, "/dev/kmem open: %s\n", strerror(errno));
return(-1);
}
if(stat(ttyline, &statb) < 0) {
fprintf(stderr, "%s stat: %s\n", ttyline, strerror(errno));
return(-1);
}
if((statb.st_mode&S_IFMT) != S_IFCHR) {
fprintf(stderr, "%s is not a character device.\n",ttyline);
return(-1);
}
dev = statb.st_rdev;
(void)lseek(kmem,
(off_t) &(((struct cdevsw *)NLVALUE(CDEVSW))[major(dev)]),0);
(void)read(kmem, (char *) &cdevsw, sizeof cdevsw);
if((int)(cdevsw.d_open) == NLVALUE(DZOPEN)) {
devtype = DZ11;
unit = minor(dev) / NDZLINE;
line = minor(dev) % NDZLINE;
#ifdef pdp11
ubinfo = &(((struct uba_device *)NLVALUE(DZINFO))[unit]);
#else
addr = (int) &(((int *)NLVALUE(DZINFO))[unit]);
#endif
(void)lseek(kmem, (off_t) NLVALUE(NDZ11), 0);
} else if((int)(cdevsw.d_open) == NLVALUE(DHOPEN)) {
devtype = DH11;
unit = minor(dev) / NDHLINE;
line = minor(dev) % NDHLINE;
#ifdef pdp11
ubinfo = &(((struct uba_device *)NLVALUE(DHINFO))[unit]);
#else
addr = (int) &(((int *)NLVALUE(DHINFO))[unit]);
#endif
(void)lseek(kmem, (off_t) NLVALUE(NDH11), 0);
} else if((int)(cdevsw.d_open) == NLVALUE(DMFOPEN)) {
devtype = DMF;
unit = minor(dev) / NDMFLINE;
line = minor(dev) % NDMFLINE;
#ifdef pdp11
ubinfo = &(((struct uba_device *)NLVALUE(DMFINFO))[unit]);
#else
addr = (int) &(((int *)NLVALUE(DMFINFO))[unit]);
#endif
(void)lseek(kmem, (off_t) NLVALUE(NDMF), 0);
} else {
fprintf(stderr, "Device %s (%d/%d) unknown.\n", ttyline,
major(dev), minor(dev));
return(-1);
}
(void)read(kmem, (char *) &nlines, sizeof nlines);
if(minor(dev) >= nlines) {
fprintf(stderr, "Sub-device %d does not exist (only %d).\n",
minor(dev), nlines);
return(-1);
}
#ifndef pdp11
(void)lseek(kmem, (off_t)addr, 0);
(void)read(kmem, (char *) &ubinfo, sizeof ubinfo);
#endif
(void)lseek(kmem, (off_t) &(ubinfo->ui_flags), 0);
(void)read(kmem, (char *) &flags, sizeof flags);
#ifdef BSD4_2
tflags = 1L<<line;
#else
tflags = 1<<line;
#endif
resetmodem = ((flags&tflags) == 0);
flags = enable ? (flags & ~tflags) : (flags | tflags);
(void)lseek(kmem, (off_t) &(ubinfo->ui_flags), 0);
(void)write(kmem, (char *) &flags, sizeof flags);
#ifndef pdp11
switch(devtype) {
case DZ11:
if((addr = NLVALUE(DZSCAR)) == 0) {
fprintf(stderr, "No dzsoftCAR.\n");
return(-1);
}
cflags = flags;
(void)lseek(kmem, (off_t) &(((char *)addr)[unit]), 0);
(void)write(kmem, (char *) &cflags, sizeof cflags);
break;
case DH11:
if((addr = NLVALUE(DHSCAR)) == 0) {
fprintf(stderr, "No dhsoftCAR.\n");
return(-1);
}
sflags = flags;
(void)lseek(kmem, (off_t) &(((short *)addr)[unit]), 0);
(void)write(kmem, (char *) &sflags, sizeof sflags);
break;
case DMF:
if((addr = NLVALUE(DMFSCAR)) == 0) {
fprintf(stderr, "No dmfsoftCAR.\n");
return(-1);
}
cflags = flags;
(void)lseek(kmem, (off_t) &(((char *)addr)[unit]), 0);
(void)write(kmem, (char *) &flags, sizeof cflags);
break;
default:
fprintf(stderr, "Unknown device type\n");
return(-1);
}
#endif
return(0);
}
prefix(s1, s2)
register char *s1, *s2;
{
register char c;
while ((c = *s1++) == *s2++)
if (c == '\0')
return (1);
return (c == '\0');
}

View File

@@ -0,0 +1,22 @@
# Makefile 4.4 86/02/12
TOPSRC = $(shell cd ../../../..; pwd)
include $(TOPSRC)/target.mk
DEBUG =
CFLAGS = -Os -Werror ${DEBUG}
OBJS = bsdtcp.o df2.o df12.o dk.o dn.o hys.o hysq.o mic.o nov.o pen.o pnet.o \
rvmacs.o sy.o unet.o va212.o va811.o va820.o vad.o vent.o vmacs.o \
hys24.o cds224.o att2224.o
libacu.a: ${OBJS}
$(AR) cr libacu.a ${OBJS}
-$(RANLIB) libacu.a
${OBJS}: ../uucp.h ../condevs.h
install: libacu.a
clean:
rm -f *.o core errs libacu.a

View File

@@ -0,0 +1,156 @@
#ifndef lint
static char sccsid[] = "@(#)att2224.c 1.1 (Berkeley) 2/12/86";
#endif
#include "../condevs.h"
#ifdef ATT2224
attopn(telno, flds, dev)
char *telno, *flds[];
struct Devices *dev;
{
char dcname[20], phone[MAXPH+10], c = 0;
int dnf, failret = 0, timelim;
sprintf(dcname, "/dev/%s", dev->D_line);
if (setjmp(Sjbuf)) {
delock(dev->D_line);
logent("DEVICE", "NO");
DEBUG(4, "Open timed out %s", dcname);
alarm (0);
return CF_NODEV;
}
signal(SIGALRM, alarmtr);
getnextfd();
alarm(10);
if ((dnf = open(dcname, 2)) <= 0) {
delock(dev->D_line);
logent("DEVICE", "NO");
DEBUG(4, "Can't open %s", dcname);
alarm (0);
return CF_NODEV;
}
alarm(0);
next_fd = -1;
fixline(dnf, dev->D_speed);
DEBUG(4, "modem port - %s\n", dcname);
if (setjmp(Sjbuf)) {
delock(dev->D_line);
logent("ACU WRITE", "FAILED");
return CF_DIAL;
}
signal(SIGALRM, alarmtr);
alarm(10);
do {
slowrite(dnf, "\r"); /* wake up modem */
} while (expect(":~3", dnf));
alarm(0);
sprintf (phone, "atzt%s\r", telno);
slowrite (dnf, phone); /* type telno string to modem */
if ((expect(phone, dnf)) != SUCCESS) {
delock(dev->D_line);
logent("ACU READ", "FAILED");
return CF_DIAL;
}
if (setjmp(Sjbuf)) {
delock(dev->D_line);
logent("NO ANSWER", "FAILED");
alarm (0);
return CF_DIAL;
}
timelim = strlen(telno) * 4;
signal(SIGALRM, alarmtr);
alarm(timelim > 30 ? timelim : 30);
readchar:
if ((read(dnf, &c, 1)) != 1) {
delock(dev->D_line);
logent("ACU READ", "FAILED");
return CF_DIAL;
}
switch (c) {
case 'D': /* no dial tone */
logent("NO DIAL TONE", "FAILED");
failret++;
break;
case 'B': /* line busy */
logent("LINE BUSY", "FAILED");
failret++;
break;
case 'N': /* no answer */
logent("NO ANSWER", "FAILED");
failret++;
break;
case 'H': /* handshake failed */
logent("MODEM HANDSHAKE", "FAILED");
failret++;
break;
case '3': /* 2400 baud */
DEBUG(4, "Baudrate set to 2400 baud", CNULL);
fixline(dnf, 2400);
break;
case '2': /* 1200 baud */
DEBUG(4, "Baudrate set to 1200 baud", CNULL);
fixline(dnf, 1200);
break;
case '1': /* 300 baud */
DEBUG(4, "Baudrate set to 300 baud", CNULL);
fixline(dnf, 300);
break;
default: /* Not one of the above, so must be garbage */
goto readchar;
}
if (failret) {
alarm (0);
delock(dev->D_line);
return CF_DIAL;
}
alarm (0);
return dnf;
}
attcls(fd)
int fd;
{
char dcname[20];
#ifdef USG
struct termio hup, sav;
#else !USG
struct sgttyb hup, sav;
#endif
if (fd > 0) {
sprintf(dcname, "/dev/%s", devSel);
DEBUG(4, "Hanging up fd = %d\n", fd);
/*
* code to drop DTR -- change to 0 baud then back to default.
*/
gtty(fd, &hup);
gtty(fd, &sav);
#ifdef USG
hup.c_cflag = B0;
#else !USG
hup.sg_ispeed = B0;
hup.sg_ospeed = B0;
#endif
stty(fd, &hup);
sleep(2);
stty(fd, &sav);
/*
* now raise DTR -- close the device
*/
sleep(2);
close(fd);
delock(devSel);
}
}
#endif

View File

@@ -0,0 +1,96 @@
#if defined(DOSCCS) && !defined(lint)
static char sccsid[] = "@(#)bsdtcp.c 4.3.2 (2.11BSD GTE) 1996/3/22";
#endif
#include "../condevs.h"
#ifdef BSDTCP
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
/*
* bsdtcpopn -- make a tcp connection
*
* return codes:
* >0 - file number - ok
* FAIL - failed
*/
bsdtcpopn(flds)
register char *flds[];
{
struct servent *sp;
struct hostent *hp;
struct sockaddr_in hisctladdr;
int s = -1, port;
extern int errno;
sp = getservbyname(flds[F_CLASS], "tcp");
if (sp == NULL) {
port = htons(atoi(flds[F_CLASS]));
if (port == 0) {
logent(_FAILED, "UNKNOWN PORT NUMBER");
return CF_SYSTEM;
}
} else
port = sp->s_port;
DEBUG(4, "bsdtcpopn host %s, ", flds[F_PHONE]);
DEBUG(4, "port %d\n", ntohs(port));
if (setjmp(Sjbuf)) {
bsdtcpcls(s);
logent("tcpopen", "TIMEOUT");
return CF_DIAL;
}
bzero((char *)&hisctladdr, sizeof (hisctladdr));
hp = gethostbyname(flds[F_PHONE]);
if (hp == NULL) {
logent("tcpopen","UNKNOWN HOST");
return CF_DIAL;
}
signal(SIGALRM, alarmtr);
alarm(30);
hisctladdr.sin_family = hp->h_addrtype;
#ifdef BSD2_9
s = socket(SOCK_STREAM, 0, &hisctladdr, 0);
#else BSD4_2
s = socket(hp->h_addrtype, SOCK_STREAM, 0);
#endif
if (s < 0)
goto bad;
#ifndef BSD2_9
if (bind(s, (char *)&hisctladdr, sizeof (hisctladdr), 0) < 0)
goto bad;
#endif
bcopy(hp->h_addr, (char *)&hisctladdr.sin_addr, hp->h_length);
hisctladdr.sin_port = port;
#ifdef BSD2_9
if (connect(s, (char *)&hisctladdr) < 0)
#else BSD4_2
if (connect(s, (char *)&hisctladdr, sizeof (hisctladdr), 0) < 0)
#endif
goto bad;
alarm(0);
CU_end = bsdtcpcls;
return s;
bad:
alarm(0);
bsdtcpcls(s);
DEBUG(5, "tcpopen failed: errno %d\n", errno);
logent(strerror(errno), _FAILED);
return CF_DIAL;
}
/*
* bsdtcpcls -- close tcp connection
*/
bsdtcpcls(fd)
register int fd;
{
DEBUG(4, "TCP CLOSE called\n", 0);
if (fd > 0) {
close(fd);
DEBUG(4, "closed fd %d\n", fd);
}
}
#endif

View File

@@ -0,0 +1,110 @@
#ifndef lint
static char sccsid[] = "@(#)cds224.c 1.1 (Berkeley) 1/13/86";
#endif
#include "../condevs.h"
#ifdef CDS224
/*
* conopn: establish dial-out connection through a Concord CDS 224.
* Returns descriptor open to tty for reading and writing.
* Negative values (-1...-7) denote errors in connmsg.
* Be sure to disconnect tty when done, via HUPCL or stty 0.
*/
#define TRYS 5 /* number of trys */
cdsopn224(telno, flds, dev)
char *telno;
char *flds[];
struct Devices *dev;
{
int dh = -1;
int i, ok, er = 0, delay;
extern errno;
char dcname[20];
char *tempbuf[20];
sprintf(dcname, "/dev/%s", dev->D_line);
if (setjmp(Sjbuf)) {
DEBUG(1, "timeout concord open\n", "");
logent("concord open", "TIMEOUT");
if (dh >= 0)
cdscls224(dh);
delock(dev->D_line);
return CF_NODEV;
}
signal(SIGALRM, alarmtr);
getnextfd();
alarm(10);
dh = open(dcname, 2);
alarm(0);
/* modem is open */
next_fd = -1;
if (dh < 0) {
delock(dev->D_line);
return CF_NODEV;
}
fixline(dh, dev->D_speed);
DEBUG(4, "calling %s -> ", telno);
if (dochat(dev, flds, dh)) {
logent(dcname, "CHAT FAILED");
cdscls224(dh);
return CF_DIAL;
}
for(i = 0; i < TRYS; ++i) {
/* wake up Concord */
write(dh, "\r\r", 2);
DEBUG(4, "wanted CDS >", CNULL);
ok = expect("CDS >", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok != 0)
continue;
write(dh, "\r", 2);
DEBUG(4, "wanted CDS >", CNULL);
ok = expect("CDS >", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok != 0)
continue;
/* send telno \r */
sprintf(tempbuf,"D%s\r",telno);
write(dh, tempbuf, strlen(tempbuf));
DEBUG(4, "wanted DIALING ", CNULL);
ok = expect("DIALING ", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok == 0)
break;
}
if (ok == 0) {
sleep(10); /* give concord some time */
DEBUG(4, "wanted INITIATING " , CNULL);
ok = expect("INITIATING", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
}
if (ok != 0) {
if (dh > 2)
close(dh);
DEBUG(4, "conDial failed\n", CNULL);
delock(dev->D_line);
return CF_DIAL;
}
DEBUG(4, "concord ok\n", CNULL);
return dh;
}
cdscls224(fd)
{
if (fd > 0) {
close(fd);
sleep(5);
delock(devSel);
}
}
#endif

156
src/cmd/uucp/aculib/df12.c Normal file
View File

@@ -0,0 +1,156 @@
#ifndef lint
static char sccsid[] = "@(#)df12.c 4.1 (Berkeley) 4/3/85";
#endif
#include "../condevs.h"
#ifdef DF112
/*
* df12popn(telno, flds, dev) connect to df12 modem (pulse call)
* df12topn(telno, flds, dev) connect to df12 modem (tone call)
* char *flds[], *dev[];
*
* return codes:
* >0 - file number - ok
* CF_DIAL,CF_NODEV - failed
*/
df12popn (telno, flds, dev)
char *telno,
*flds[];
struct Devices *dev;
{
return df12opn (telno, flds, dev, 0);
}
df12topn (telno, flds, dev)
char *telno,
*flds[];
struct Devices *dev;
{
return df12opn (telno, flds, dev, 1);
}
/* ARGSUSED */
df12opn (telno, flds, dev, toneflag)
char *telno;
char *flds[];
struct Devices *dev;
int toneflag;
{
int phindex, dh = -1;
extern errno;
char dcname[20], newphone[64];
sprintf (dcname, "/dev/%s", dev -> D_line);
DEBUG (4, "dc - %s\n", dcname);
if (setjmp (Sjbuf))
{
logent (dcname, "TIMEOUT");
if (dh >= 0)
close (dh);
return CF_DIAL;
}
signal (SIGALRM, alarmtr);
getnextfd ();
alarm (10);
dh = open (dcname, 2);/* read/write */
alarm (0);
/* modem is open */
/* First, adjust our phone number string. These modems don't
* like any characters but digits and "=" signs (for delay)
*/
for (phindex = 0; *telno; telno++)
{
if (*telno == '=' || (*telno >= '0' && *telno <= '9'))
newphone[phindex++] = *telno;
if (phindex == 64)
{
logent (dcname, "Phone number too long");
close (dh);
return CF_DIAL;
}
}
newphone[phindex] = '\0';
next_fd = -1;
if (dh >= 0)
{
fixline (dh, dev -> D_speed);
if (dochat (dev, flds, dh))
{
logent (dcname, "CHAT FAILED");
close (dh);
return CF_DIAL;
}
slowrite (dh, "\02");
if (expect ("Ready\r\n", dh) != 0)
{
DEBUG (4, "Didn't get 'Ready' response.\n", NULL);
logent (dcname, "Modem not responding");
close (dh);
return CF_DIAL;
}
DEBUG (4, "Got 'Ready' response\n", NULL);
DEBUG (7, "Writing control select flag %c\n", toneflag ? 'T' : 'P');
slowrite (dh, toneflag ? "T" : "P");
DEBUG (4, "Writing telephone number %s\n", newphone);
slowrite (dh, newphone);
DEBUG (7, "Telephone number written\n", NULL);
slowrite (dh, "#");
DEBUG (7, "Writing # sign\n", NULL);
if (expect ("Attached\r\n", dh) != 0)
{
logent (dcname, "No carrier");
strcpy (devSel, dev -> D_line);
df12cls (dh);
return CF_DIAL;
}
}
if (dh < 0)
{
logent (dcname, "CAN'T OPEN");
return CF_NODEV;
}
else
{
DEBUG (4, "df12 ok\n", CNULL);
return dh;
}
}
df12cls (fd)
int fd;
{
char dcname[20];
struct sgttyb hup,
sav;
if (fd > 0)
{
sprintf (dcname, "/dev/%s", devSel);
DEBUG (4, "Hanging up fd = %d\n", fd);
/*
* code to drop DTR -- change to 0 baud then back to default.
*/
gtty (fd, &hup);
gtty (fd, &sav);
hup.sg_ispeed = B0;
hup.sg_ospeed = B0;
stty (fd, &hup);
sleep (2);
stty (fd, &sav);
/*
* now raise DTR -- close the device & open it again.
*/
sleep (2);
close (fd);
sleep (2);
delock (devSel);
}
}
#endif

146
src/cmd/uucp/aculib/df2.c Normal file
View File

@@ -0,0 +1,146 @@
#ifndef lint
static char sccsid[] = "@(#)df2.c 4.2 (Berkeley) 6/23/85";
#endif
#include "../condevs.h"
#ifdef DF02
/*
* df2opn(ph, flds, dev) dial remote machine
*
* return codes:
* file descriptor - succeeded
* FAIL - failed
*/
df2opn(ph, flds, dev)
char *ph;
char *flds[];
struct Devices *dev;
{
char dcname[20], dnname[20], phone[MAXPH+2], c = 0;
#ifdef USG
struct termio ttbuf;
#endif
int dcf, dnf;
int nw, lt, pid, st, status;
unsigned timelim;
#ifdef TIOCFLUSH
int zero = 0;
#endif TIOCFLUSH
sprintf(dnname, "/dev/%s", dev->D_calldev);
if (setjmp(Sjbuf)) {
logent(dnname, "CAN'T OPEN");
DEBUG(4, "%s Open timed out\n", dnname);
return CF_NODEV;
}
signal(SIGALRM, alarmtr);
getnextfd();
errno = 0;
alarm(10);
dnf = open(dnname, 2 );
alarm(0);
next_fd = -1;
if (dnf < 0 && errno == EACCES) {
logent(dnname, "CAN'T OPEN");
delock(dev->D_line);
logent("DEVICE", "NO");
return CF_NODEV;
}
fioclex(dnf);
sprintf(dcname, "/dev/%s", dev->D_line);
fixline(dnf, dev->D_speed);
sprintf(phone, "\02%s", ph);
DEBUG(4, "dc - %s, ", dcname);
DEBUG(4, "acu - %s\n", dnname);
pid = 0;
if (setjmp(Sjbuf)) {
logent("DIALUP DN write", "TIMEOUT");
if (pid)
kill(pid, 9);
delock(dev->D_line);
if (dnf)
close(dnf);
return CF_DIAL;
}
signal(SIGALRM, alarmtr);
timelim = 5 * strlen(phone);
alarm(timelim < 30 ? 30 : timelim);
if ((pid = fork()) == 0) {
sleep(2);
fclose(stdin);
fclose(stdout);
#ifdef TIOCFLUSH
ioctl(dnf, TIOCFLUSH, &zero);
#endif
write(dnf, "\01", 1);
sleep(1);
nw = write(dnf, phone, lt = strlen(phone));
if (nw != lt) {
logent("DIALUP ACU write", _FAILED);
exit(1);
}
DEBUG(4, "ACU write ok%s\n", CNULL);
exit(0);
}
/* open line - will return on carrier */
/* RT needs a sleep here because it returns immediately from open */
#if RT
sleep(15);
#endif
if (read(dnf, &c, 1) != 1 || c != 'A')
dcf = -1;
else
dcf = 0;
DEBUG(4, "dcf is %d\n", dcf);
if (dcf < 0) {
logent("DIALUP LINE open", _FAILED);
alarm(0);
kill(pid, 9);
close(dnf);
delock(dev->D_line);
return CF_DIAL;
}
dcf = dnf;
dnf = 0;
while ((nw = wait(&lt)) != pid && nw != -1)
;
#ifdef USG
ioctl(dcf, TCGETA, &ttbuf);
if(!(ttbuf.c_cflag & HUPCL)) {
ttbuf.c_cflag |= HUPCL;
ioctl(dcf, TCSETA, &ttbuf);
}
#endif
alarm(0);
fflush(stdout);
fixline(dcf, dev->D_speed);
DEBUG(4, "Fork Stat %o\n", lt);
if (lt != 0) {
close(dcf);
if (dnf)
close(dnf);
delock(dev->D_line);
return CF_DIAL;
}
return dcf;
}
/*
* df2cls() close the DF02/DF03 call unit
*
* return codes: none
*/
df2cls(fd)
register int fd;
{
if (fd > 0) {
close(fd);
sleep(5);
delock(devSel);
}
}
#endif

42
src/cmd/uucp/aculib/dk.c Normal file
View File

@@ -0,0 +1,42 @@
#ifndef lint
static char sccsid[] = "@(#)dk.c 4.1 (Berkeley) 1/22/85";
#endif
#include "../condevs.h"
#ifdef DATAKIT
#include <dk.h>
#define DKTRIES 2
/***
* dkopn(flds) make datakit connection
*
* return codes:
* >0 - file number - ok
* FAIL - failed
*/
dkopn(flds)
char *flds[];
{
int dkphone;
register char *cp;
register ret, i;
if (setjmp(Sjbuf))
return CF_DIAL;
signal(SIGALRM, alarmtr);
dkphone = 0;
cp = flds[F_PHONE];
while(*cp)
dkphone = 10 * dkphone + (*cp++ - '0');
DEBUG(4, "dkphone (%d) ", dkphone);
for (i = 0; i < DKTRIES; i++) {
getnextfd();
ret = dkdial(D_SH, dkphone, 0);
next_fd = -1;
DEBUG(4, "dkdial (%d)\n", ret);
if (ret > -1)
break;
}
return ret;
}
#endif

144
src/cmd/uucp/aculib/dn.c Normal file
View File

@@ -0,0 +1,144 @@
#ifndef lint
static char sccsid[] = "@(#)dn.c 4.2 (Berkeley) 6/23/85";
#endif
#include "../condevs.h"
#ifdef DN11
#define ACULAST "-<"
/***
* dnopn(ph, flds, dev) dial remote machine
*
* return codes:
* file descriptor - succeeded
* FAIL - failed
*/
dnopn(ph, flds, dev)
char *ph;
char *flds[];
struct Devices *dev;
{
char dcname[20], dnname[20], phone[MAXPH+2], c = 0;
#ifdef USG
struct termio ttbuf;
#endif
int dnf, dcf;
int nw, lt, pid, status;
unsigned timelim;
#ifdef TIOCFLUSH
int zero = 0;
#endif
sprintf(dnname, "/dev/%s", dev->D_calldev);
errno = 0;
if (setjmp(Sjbuf)) {
logent(dnname, "CAN'T OPEN");
DEBUG(4, "%s Open timed out\n", dnname);
return(CF_NODEV);
}
signal(SIGALRM, alarmtr);
getnextfd();
alarm(10);
dnf = open(dnname, 1);
alarm(0);
next_fd = -1;
if (dnf < 0 && errno == EACCES) {
logent(dnname, "CAN'T OPEN");
logent("DEVICE", "NO");
return CF_NODEV;
}
fioclex(dnf);
sprintf(dcname, "/dev/%s", dev->D_line);
sprintf(phone, "%s%s", ph, ACULAST);
DEBUG(4, "dc - %s, ", dcname);
DEBUG(4, "acu - %s\n", dnname);
pid = 0;
if (setjmp(Sjbuf)) {
logent("DIALUP DN write", "TIMEOUT");
if (pid)
kill(pid, 9);
delock(dev->D_line);
if (dnf)
close(dnf);
return CF_DIAL;
}
signal(SIGALRM, alarmtr);
timelim = 5 * strlen(phone);
alarm(timelim < 30 ? 30 : timelim);
if ((pid = fork()) == 0) {
sleep(2);
fclose(stdin);
fclose(stdout);
#ifdef TIOCFLUSH
ioctl(dnf, TIOCFLUSH, &zero);
#endif TIOCFLUSH
nw = write(dnf, phone, lt = strlen(phone));
if (nw != lt) {
logent("DIALUP ACU write", _FAILED);
exit(1);
}
DEBUG(4, "ACU write ok\n", CNULL);
exit(0);
}
/* open line - will return on carrier */
/* RT needs a sleep here because it returns immediately from open */
#if RT
sleep(15);
#endif
getnextfd();
errno = 0;
dcf = open(dcname, 2);
next_fd = -1;
if (dcf < 0 && errno == EACCES)
logent(dcname, "CAN'T OPEN");
DEBUG(4, "dcf is %d\n", dcf);
if (dcf < 0) {
logent("DIALUP LINE open", _FAILED);
alarm(0);
kill(pid, 9);
close(dnf);
delock(dev->D_line);
return CF_DIAL;
}
while ((nw = wait(&lt)) != pid && nw != -1)
;
#ifdef USG
ioctl(dcf, TCGETA, &ttbuf);
if(!(ttbuf.c_cflag & HUPCL)) {
ttbuf.c_cflag |= HUPCL;
ioctl(dcf, TCSETA, &ttbuf);
}
#endif
alarm(0);
fflush(stdout);
fixline(dcf, dev->D_speed);
DEBUG(4, "Fork Stat %o\n", lt);
if (lt != 0) {
close(dcf);
if (dnf)
close(dnf);
delock(dev->D_line);
return CF_DIAL;
}
return dcf;
}
/***
* dncls() close dn type call unit
*
* return codes: None
*/
dncls(fd)
register int fd;
{
if (fd > 0) {
close(fd);
sleep(5);
delock(devSel);
}
}
#endif

191
src/cmd/uucp/aculib/hys.c Normal file
View File

@@ -0,0 +1,191 @@
#ifndef lint
static char sccsid[] = "@(#)hys.c 4.6 (Berkeley) 2/12/86";
#endif
#include "../condevs.h"
#ifdef HAYES
#ifdef USR2400
#define DROPDTR
/*
* The "correct" switch settings for a USR Courier 2400 are
* Dialin/out: 0 0 1 1 0 0 0 1 0 0
* Dialout only: 0 0 1 1 1 1 0 1 0 0
* where 0 = off and 1 = on
*/
#endif
/*
* hyspopn(telno, flds, dev) connect to hayes smartmodem (pulse call)
* hystopn(telno, flds, dev) connect to hayes smartmodem (tone call)
* char *flds[], *dev[];
*
* return codes:
* >0 - file number - ok
* CF_DIAL,CF_DEVICE - failed
*/
hyspopn(telno, flds, dev)
char *telno, *flds[];
struct Devices *dev;
{
return hysopn(telno, flds, dev, 0);
}
hystopn(telno, flds, dev)
char *telno, *flds[];
struct Devices *dev;
{
return hysopn(telno, flds, dev, 1);
}
/* ARGSUSED */
hysopn(telno, flds, dev, toneflag)
char *telno;
char *flds[];
struct Devices *dev;
int toneflag;
{
extern errno;
char dcname[20];
char cbuf[MAXPH];
register char *cp;
register int i;
int dh = -1, nrings = 0;
sprintf(dcname, "/dev/%s", dev->D_line);
DEBUG(4, "dc - %s\n", dcname);
if (setjmp(Sjbuf)) {
logent(dcname, "TIMEOUT");
if (dh >= 0)
hyscls(dh);
return CF_DIAL;
}
signal(SIGALRM, (sig_t)alarmtr);
getnextfd();
alarm(10);
dh = open(dcname, 2); /* read/write */
alarm(0);
/* modem is open */
next_fd = -1;
if (dh >= 0) {
fixline(dh, dev->D_speed);
if (dochat(dev, flds, dh)) {
logent(dcname, "CHAT FAILED");
hyscls(dh);
return CF_DIAL;
}
write(dh, "ATV1E0H\r", 8);
if (expect("OK\r\n", dh) != 0) {
logent(dcname, "HSM seems dead");
hyscls(dh);
return CF_DIAL;
}
#ifdef USR2400
write(dh, "ATX6S7=44\r", 10);
if (expect("OK\r\n", dh) != 0) {
logent(dcname, "HSM seems dead");
hyscls(dh);
return CF_DIAL;
}
#endif
if (toneflag)
write(dh, "\rATDT", 5);
else
#ifdef USR2400
write(dh, "\rATD", 4);
#else
write(dh, "\rATDP", 5);
#endif
write(dh, telno, strlen(telno));
write(dh, "\r", 1);
if (setjmp(Sjbuf)) {
logent(dcname, "TIMEOUT");
strcpy(devSel, dev->D_line);
hyscls(dh);
return CF_DIAL;
}
signal(SIGALRM, (sig_t)alarmtr);
alarm(2*MAXMSGTIME);
do {
cp = cbuf;
while (read(dh, cp ,1) == 1)
if (*cp >= ' ')
break;
while (++cp < &cbuf[MAXPH] && read(dh, cp, 1) == 1 && *cp != '\n')
;
alarm(0);
*cp-- = '\0';
if (*cp == '\r')
*cp = '\0';
DEBUG(4,"\nGOT: %s", cbuf);
alarm(MAXMSGTIME);
} while (strncmp(cbuf, "RING", 4) == 0 && nrings++ < 5);
if (strncmp(cbuf, "CONNECT", 7) != 0) {
logent(cbuf, _FAILED);
strcpy(devSel, dev->D_line);
hyscls(dh);
return CF_DIAL;
}
i = atoi(&cbuf[8]);
if (i > 0 && i != dev->D_speed) {
DEBUG(4,"Baudrate reset to %d\n", i);
fixline(dh, i);
}
}
if (dh < 0) {
logent(dcname, "CAN'T OPEN");
return dh;
}
DEBUG(4, "hayes ok\n", CNULL);
return dh;
}
hyscls(fd)
int fd;
{
char dcname[20];
#ifdef DROPDTR
struct sgttyb hup, sav;
#endif
if (fd > 0) {
sprintf(dcname, "/dev/%s", devSel);
DEBUG(4, "Hanging up fd = %d\n", fd);
#ifdef DROPDTR
/*
* code to drop DTR -- change to 0 baud then back to default.
*/
gtty(fd, &hup);
gtty(fd, &sav);
hup.sg_ispeed = B0;
hup.sg_ospeed = B0;
stty(fd, &hup);
sleep(2);
stty(fd, &sav);
/*
* now raise DTR -- close the device & open it again.
*/
sleep(2);
close(fd);
sleep(2);
fd = open(dcname, 2);
stty(fd, &sav);
#else
sleep(3);
write(fd, "+++", 3);
#endif
sleep(3);
write(fd, "ATZ\r", 4);
if (expect("OK",fd) != 0)
logent(devSel, "HSM did not respond to ATZ");
write(fd, "ATH\r", 4);
sleep(1);
close(fd);
delock(devSel);
}
}
#endif

126
src/cmd/uucp/aculib/hys24.c Normal file
View File

@@ -0,0 +1,126 @@
#ifndef lint
static char sccsid[] = "@(#)hys24.c 1.1 (Berkeley) 1/13/86";
#endif
#include "../condevs.h"
#ifdef HAYES2400
/*
* hyspopn24(telno, flds, dev) connect to hayes smartmodem (pulse call)
* hystopn24(telno, flds, dev) connect to hayes smartmodem (tone call)
* char *flds[], *dev[];
*
* return codes:
* >0 - file number - ok
* CF_DIAL,CF_DEVICE - failed
*/
hyspopn24(telno, flds, dev)
char *telno, *flds[];
struct Devices *dev;
{
return hysopn24(telno, flds, dev, 0);
}
hystopn24(telno, flds, dev)
char *telno, *flds[];
struct Devices *dev;
{
return hysopn24(telno, flds, dev, 1);
}
/* ARGSUSED */
hysopn24(telno, flds, dev, toneflag)
char *telno;
char *flds[];
struct Devices *dev;
int toneflag;
{
int dh = -1;
char *ii;
extern errno;
char dcname[20];
sprintf(dcname, "/dev/%s", dev->D_line);
DEBUG(4, "dc - %s\n", dcname);
if (setjmp(Sjbuf)) {
logent(dcname, "TIMEOUT");
if (dh >= 0)
hyscls24(dh);
return CF_DIAL;
}
signal(SIGALRM, alarmtr);
getnextfd();
alarm(10);
dh = open(dcname, 2); /* read/write */
alarm(0);
for (ii = telno; *ii; ii++)
if (*ii == '=')
*ii = ',';
/* modem is open */
next_fd = -1;
if (dh >= 0) {
fixline(dh, dev->D_speed);
write(dh, "\rATZH\r", 6);
sleep(2);
if (dochat(dev, flds, dh)) {
logent(dcname, "CHAT FAILED");
hyscls24(dh);
return CF_DIAL;
}
write(dh, "AT&F&D3&C1E0X1\r", 15);
if (expect("OK\r\n", dh) != 0) {
logent(dcname, "HSM not responding OK");
hyscls24(dh);
return CF_DIAL;
}
if (toneflag)
write(dh, "\rATDT", 5);
else
write(dh, "\rATDP", 5);
write(dh, telno, strlen(telno));
write(dh, "\r", 1);
if (expect("CONNECT", dh) != 0) {
logent("HSM no carrier", _FAILED);
strcpy(devSel, dev->D_line);
hyscls24(dh);
return CF_DIAL;
}
}
if (dh < 0) {
logent(dcname, "CAN'T OPEN");
return dh;
}
DEBUG(4, "hayes ok\n", CNULL);
return dh;
}
hyscls24(fd)
int fd;
{
char dcname[20];
if (fd > 0) {
sprintf(dcname, "/dev/%s", devSel);
DEBUG(4, "Hanging up fd = %d\n", fd);
sleep(1);
/*
* Since we have a getty sleeping on this line, when it wakes up it sends
* all kinds of garbage to the modem. Unfortunatly, the modem likes to
* execute the previous command when it sees the garbage. The previous
* command was to dial the phone, so let's make the last command reset
* the modem.
*/
write(fd, "\r+++", 4);
sleep(2);
write(fd, "\rATH\rATZ\r", 9);
sleep(2);
close(fd);
delock(devSel);
}
}
#endif

159
src/cmd/uucp/aculib/hysq.c Normal file
View File

@@ -0,0 +1,159 @@
#ifndef lint
static char sccsid[] = "@(#)hysq.c 4.1 (Berkeley) 1/22/85";
#endif
#include "../condevs.h"
#ifdef HAYESQ
/*
* New dialout routine to work with Hayes' SMART MODEM
* 13-JUL-82, Mike Mitchell
* Modified 23-MAR-83 to work with Tom Truscott's (rti!trt)
* version of UUCP (ncsu!mcm)
*
* The modem should be set to NOT send any result codes to
* the system (switch 3 up, 4 down). This end will figure out
* what is wrong.
*
* I had lots of problems with the modem sending
* result codes since I am using the same modem for both incomming and
* outgoing calls. I'd occasionally miss the result code (getty would
* grab it), and the connect would fail. Worse yet, the getty would
* think the result code was a user name, and send garbage to it while
* it was in the command state. I turned off ALL result codes, and hope
* for the best. 99% of the time the modem is in the correct state.
* Occassionally it doesn't connect, or the phone was busy, etc., and
* uucico sits there trying to log in. It eventually times out, calling
* clsacu() in the process, so it resets itself for the next attempt.
*/
/*
* NOTE: this version is not for the faint-hearted.
* Someday it would be nice to have a single version of hayes dialer
* with a way to specify the switch settings that are on the dialer
* as well as tone/pulse.
* In the meantime, using HAYES rather than HAYESQ is probably best.
*/
hysqpopn(telno, flds, dev)
char *telno, *flds[];
struct Devices *dev;
{
return hysqopn(telno, flds, dev, 0);
}
hysqtopn(telno, flds, dev)
char *telno, *flds[];
struct Devices *dev;
{
return hysqopn(telno, flds, dev, 1);
}
hysqopn(telno, flds, dev, toneflag)
char *telno, *flds[];
struct Devices *dev;
int toneflag;
{
char dcname[20], phone[MAXPH+10], c = 0;
#ifdef USG
struct termio ttbuf;
#endif
int status, dnf;
unsigned timelim;
signal(SIGALRM, alarmtr);
sprintf(dcname, "/dev/%s", dev->D_line);
getnextfd();
if (setjmp(Sjbuf)) {
logent("DEVICE", "NO");
DEBUG(4, "Open timed out %s", dcname);
return CF_NODEV;
}
alarm(10);
if ((dnf = open(dcname, 2)) <= 0) {
logent("DEVICE", "NO");
DEBUG(4, "Can't open %s", dcname);
return CF_NODEV;
}
alarm(0);
next_fd = -1;
fixline(dnf, dev->D_speed);
DEBUG(4, "Hayes port - %s, ", dcname);
if (toneflag)
sprintf(phone, "\rATDT%s\r", telno);
else
sprintf(phone, "\rATDP%s\r", telno);
write(dnf, phone, strlen(phone));
/* calculate delay time for the other system to answer the phone.
* Default is 15 seconds, add 2 seconds for each comma in the phone
* number.
*/
timelim = 150;
while(*telno) {
c = *telno++;
if (c == ',')
timelim += 20;
else if (toneflag)
timelim += 2; /* .2 seconds per tone */
else {
if (c == '0') timelim += 10; /* .1 sec per digit */
else if (c > '0' && c <= '9')
timelim += (c - '0');
}
}
alarm(timelim/10 + 1);
if (setjmp(Sjbuf) == 0) {
read(dnf, &c, 1);
alarm(0);
}
return dnf;
}
hysqcls(fd)
int fd;
{
char dcname[20];
struct sgttyb hup, sav;
if (fd > 0) {
sprintf(dcname, "/dev/%s", devSel);
DEBUG(4, "Hanging up fd = %d\n", fd);
/*
* code to drop DTR -- change to 0 baud then back to default.
*/
gtty(fd, &hup);
gtty(fd, &sav);
hup.sg_ispeed = B0;
hup.sg_ospeed = B0;
stty(fd, &hup);
sleep(2);
stty(fd, &sav);
/*
* now raise DTR -- close the device & open it again.
*/
sleep(2);
close(fd);
sleep(2);
fd = open(dcname, 2);
/*
* Since we have a getty sleeping on this line, when it wakes up it sends
* all kinds of garbage to the modem. Unfortunatly, the modem likes to
* execute the previous command when it sees the garbage. The previous
* command was to dial the phone, so let's make the last command reset
* the modem.
*/
sleep(2);
write(fd, "\rATZ\r", 5);
close(fd);
delock(devSel);
}
}
#endif

110
src/cmd/uucp/aculib/mic.c Normal file
View File

@@ -0,0 +1,110 @@
#ifndef lint
static char sccsid[] = "@(#)mic.c 4.1 (Berkeley) 1/22/85";
#endif
#include "../condevs.h"
#ifdef MICOM
/*
* micopn: establish connection through a micom.
* Returns descriptor open to tty for reading and writing.
* Negative values (-1...-7) denote errors in connmsg.
* Be sure to disconnect tty when done, via HUPCL or stty 0.
*/
micopn(flds)
register char *flds[];
{
extern errno;
char *rindex(), *fdig(), dcname[20];
int dh, ok = 0, speed;
register struct condev *cd;
register FILE *dfp;
struct Devices dev;
dfp = fopen(DEVFILE, "r");
ASSERT(dfp != NULL, "Can't open", DEVFILE, 0);
signal(SIGALRM, alarmtr);
dh = -1;
for(cd = condevs; ((cd->CU_meth != NULL)&&(dh < 0)); cd++) {
if (snccmp(flds[F_LINE], cd->CU_meth) == SAME) {
fseek(dfp, (off_t)0, 0);
while(rddev(dfp, &dev) != FAIL) {
if (strcmp(flds[F_CLASS], dev.D_class) != SAME)
continue;
if (snccmp(flds[F_LINE], dev.D_type) != SAME)
continue;
if (mlock(dev.D_line) == FAIL)
continue;
sprintf(dcname, "/dev/%s", dev.D_line);
getnextfd();
alarm(10);
if (setjmp(Sjbuf)) {
delock(dev.D_line);
logent(dev.D_line,"micom open TIMEOUT");
dh = -1;
break;
}
dh = open(dcname, 2);
alarm(0);
next_fd = -1;
if (dh > 0) {
break;
}
devSel[0] = '\0';
delock(dev.D_line);
}
}
}
fclose(dfp);
if (dh < 0)
return CF_NODEV;
speed = atoi(fdig(flds[F_CLASS]));
fixline(dh, speed);
sleep(1);
/* negotiate with micom */
if (speed != 4800) /* damn their eyes! */
write(dh, "\r", 1);
else
write(dh, " ", 1);
DEBUG(4, "wanted %s ", "SELECTION");
ok = expect("SELECTION", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok == 0) {
write(dh, flds[F_PHONE], strlen(flds[F_PHONE]));
sleep(1);
write(dh, "\r", 1);
DEBUG(4, "wanted %s ", "GO");
ok = expect("GO", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
}
if (ok != 0) {
if (dh > 2)
close(dh);
DEBUG(4, "micom failed\n", "");
delock(dev.D_line);
return(CF_DIAL);
}
else
DEBUG(4, "micom ok\n", "");
CU_end = cd->CU_clos;
strcat(devSel, dev.D_line); /* for later unlock */
return dh;
}
miccls(fd)
register int fd;
{
if (fd > 0) {
close(fd);
delock(devSel);
}
}
#endif

122
src/cmd/uucp/aculib/nov.c Normal file
View File

@@ -0,0 +1,122 @@
#ifndef lint
static char sccsid[] = "@(#)nov.c 4.1 (Berkeley) 1/22/85";
#endif
#include "../condevs.h"
#ifdef NOVATION
/***
* novopn(telno, flds, dev) connect to novation Smart-Cat
* (similar to hayes smartmodem)
* char *flds[], *dev[];
*
* return codes:
* >0 - file number - ok
* CF_DIAL,CF_DEVICE - failed
*/
novopn(telno, flds, dev)
char *telno;
char *flds[];
struct Devices *dev;
{
int dh = -1;
extern errno;
char dcname[20];
int pulse = 0;
sprintf(dcname, "/dev/%s", dev->D_line);
DEBUG(4, "dc - %s\n", dcname);
if (strcmp(dev->D_calldev, "pulse") == 0)
pulse = 1;
if (setjmp(Sjbuf)) {
DEBUG(1, "timeout novation open %s\n", dcname);
logent("novation open", "TIMEOUT");
if (dh >= 0)
close(dh);
delock(dev->D_line);
return CF_DIAL;
}
signal(SIGALRM, alarmtr);
getnextfd();
alarm(10);
dh = open(dcname, 2); /* read/write */
alarm(0);
/* modem is open */
next_fd = -1;
if (dh >= 0) {
fixline(dh, dev->D_speed);
/* set guard time small so line is in transparant mode */
slowrite(dh, "\rATS12=1\r");
if (expect("OK", dh) != 0) {
logent("NOV no line", _FAILED);
strcpy(devSel, dev->D_line);
novcls(dh);
return CF_DIAL;
}
if (pulse)
slowrite(dh, "ATDP");
else
slowrite(dh, "ATDT");
slowrite(dh, telno);
slowrite(dh, "\r");
if (expect("CONNECT", dh) != 0) {
logent("NOV no carrier", _FAILED);
strcpy(devSel, dev->D_line);
novcls(dh);
return CF_DIAL;
}
}
if (dh < 0) {
DEBUG(4, "novation failed\n", CNULL);
delock(dev->D_line);
}
DEBUG(4, "novation ok\n", CNULL);
return dh;
}
novcls(fd)
int fd;
{
char dcname[20];
struct sgttyb hup, sav;
if (fd > 0) {
sprintf(dcname, "/dev/%s", devSel);
DEBUG(4, "Hanging up fd = %d\n", fd);
/*
* code to drop DTR -- change to 0 baud then back to default.
*/
gtty(fd, &hup);
gtty(fd, &sav);
hup.sg_ispeed = B0;
hup.sg_ospeed = B0;
stty(fd, &hup);
sleep(2);
stty(fd, &sav);
/*
* now raise DTR -- close the device & open it again.
*/
sleep(2);
close(fd);
sleep(2);
fd = open(dcname, 2);
/*
* Since we have a getty sleeping on this line, when it wakes up it sends
* all kinds of garbage to the modem. Unfortunatly, the modem likes to
* execute the previous command when it sees the garbage. The previous
* command was to dial the phone, so let's make the last command reset
* the modem.
*/
sleep(2);
slowrite(fd, "\rATZ\r");
close(fd);
delock(devSel);
}
}
#endif

103
src/cmd/uucp/aculib/pen.c Normal file
View File

@@ -0,0 +1,103 @@
#ifndef lint
static char sccsid[] = "@(#)pen.c 4.2 (Berkeley) 10/10/85";
#endif
/*
* Speaker's quick and dirty penril hack. STA 4/1/85.
*/
#include "../condevs.h"
#ifdef PENRIL
penopn(telno, flds, dev)
char *flds[], *telno;
struct Devices *dev;
{
int dh;
int i, ok = -1;
char dcname[20];
sprintf(dcname, "/dev/%s", dev->D_line);
if (setjmp(Sjbuf)) {
DEBUG(1, "timeout penril open\n", "");
logent("penril open", "TIMEOUT");
if (dh >= 0)
close(dh);
delock(dev->D_line);
return CF_NODEV;
}
signal(SIGALRM, alarmtr);
getnextfd();
alarm(10);
dh = open(dcname, 2);
alarm(0);
next_fd = -1;
if (dh < 0) {
DEBUG(4,"%s\n", errno == 4 ? "no carrier" : "can't open modem");
delock(dev->D_line);
return errno == 4 ? CF_DIAL : CF_NODEV;
}
/* modem is open */
fixline(dh, dev->D_speed);
/* translate - to P and = to W for Penril */
DEBUG(4, "calling %s -> ", telno);
for (i = 0; i < strlen(telno); ++i) {
switch(telno[i]) {
case '-': /* delay */
telno[i] = 'P';
break;
case '=': /* await dial tone */
telno[i] = 'W';
break;
case '<':
telno[i] = 'P';
break;
}
}
DEBUG(4, "%s\n", telno);
sleep(1);
for(i = 0; i < 5; ++i) { /* make up to 5 tries */
slowrite(dh, "\r");/* awake, thou lowly Penril! */
DEBUG(4, "wanted %s ", ">");
ok = expect(">", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok != 0)
continue;
slowrite(dh, "K"); /* "K" (enter number) command */
DEBUG(4, "wanted %s ", "NO.: ");
ok = expect("NO.: ", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok == 0)
break;
}
if (ok == 0) {
slowrite(dh, telno); /* send telno, send \r */
slowrite(dh, "\r");
DEBUG(4, "wanted %s ", "OK");
ok = expect("OK", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
}
if (ok != 0) {
if (dh > 2)
close(dh);
DEBUG(4, "penDial failed\n", "");
return CF_DIAL;
}
else
DEBUG(4, "penDial ok\n", "");
return dh;
}
pencls(fd)
int fd;
{
if (fd > 0) {
close(fd);
sleep(5);
delock(devSel);
}
}
#endif

View File

@@ -0,0 +1,47 @@
#ifndef lint
static char sccsid[] = "@(#)pnet.c 4.2 (Berkeley) 6/23/85";
#endif
#include "../condevs.h"
#ifdef PNET
/***
* pnetopn(flds)
*
* call remote machine via Purdue network
* use dial string as host name, speed as socket number
* - Steve Bellovin
*/
pnetopn(flds)
char *flds[];
{
int fd;
int socket;
register char *cp;
fd = pnetfile();
DEBUG(4, "pnet fd - %d\n", fd);
if (fd < 0) {
logent("AVAILABLE DEVICE", "NO");
return CF_NODEV;
}
socket = 0;
for (cp = flds[F_CLASS]; *cp; cp++)
socket = 10*socket + (*cp - '0');
DEBUG(4, "socket - %d\n", socket);
if (setjmp(Sjbuf)) {
DEBUG(4, "pnet timeout - %s\n", flds[F_PHONE]);
return CF_DIAL;
}
signal(SIGALRM, (sig_t)alarmtr);
DEBUG(4, "host - %s\n", flds[F_PHONE]);
alarm(15);
if (pnetscon(fd, flds[F_PHONE], socket) < 0) {
DEBUG(4, "pnet connect failed - %s\n", flds[F_PHONE]);
alarm(0);
return CF_DIAL;
}
alarm(0);
return fd;
}
#endif

View File

@@ -0,0 +1,183 @@
#ifndef lint
static char sccsid[] = "@(#)rvmacs.c 4.4 (Berkeley) 6/7/86";
#endif
#include "../condevs.h"
#ifdef RVMACS
/*
* Racal-Vadic 'RV820' MACS system with 831 adaptor.
* A typical 300 baud L-devices entry is
* ACU tty10 tty11,48 300 rvmacs
* where tty10 is the communication line (D_Line),
* tty11 is the dialer line (D_calldev),
* the '4' is the dialer address + modem type (viz. dialer 0, Bell 103),
* the '8' is the communication port,
* We assume the dialer speed is 1200 baud unless MULTISPEED is defined.
* We extended the semantics of the L-devices entry to allow you
* to set the speed at which the computer talks to the dialer:
* ACU cul0 cua0,0<,2400 1200 rvmacs
* This is interpreted as above, except that the number following the second
* comma in the third field is taken to be the speed at which the computer
* must communicate with the dialer. (If omitted, it defaults to the value
* in the fourth field.) Note -- just after the call completes and you get
* carrier, the line speed is reset to the speed indicated in the fourth field.
* To get this ability, define "MULTISPEED", as below.
*
*/
#define MULTISPEED /* for dialers which work at various speeds */
#define STX 02 /* Access Adaptor */
#define ETX 03 /* Transfer to Dialer */
#define SI 017 /* Buffer Empty (end of phone number) */
#define ABORT 01 /* Abort */
#define pc(fd, x) (c = x, write(fd, &c, 1))
rvmacsopn(ph, flds, dev)
char *ph, *flds[];
struct Devices *dev;
{
register int va, i, child;
register char *p;
char c, acu[20], com[20];
int baudrate;
int timelim;
int pid, status;
int zero = 0;
#ifdef MULTISPEED
char *pp;
#else !MULTISPEED
struct sgttyb sg;
#endif
child = -1;
sprintf(com, "/dev/%s", dev->D_line);
sprintf(acu, "/dev/%s", dev->D_calldev);
if ((p = index(acu, ',')) == NULL) {
DEBUG(2, "No dialer/modem specification\n", 0);
return CF_DIAL;
}
*p++ = '\0';
#ifdef MULTISPEED
baudrate = dev->D_speed;
if ((pp = index(p, ',')) != NULL){
baudrate = atoi(pp+1);
DEBUG(5, "Using speed %d baud\n", baudrate);
}
#endif
if (setjmp(Sjbuf)) {
logent("rvmacsopn", "TIMEOUT");
goto failret;
}
DEBUG(4, "STARTING CALL\n", 0);
getnextfd();
signal(SIGALRM, alarmtr);
timelim = 5 * strlen(ph);
alarm(timelim < 45 ? 45 : timelim);
if ((va = open(acu, 2)) < 0) {
logent(acu, "CAN'T OPEN");
alarm(0);
return CF_DIAL;
}
/* rti!trt: avoid passing acu file descriptor to children */
next_fd = -1;
fioclex(va);
if ((child = fork()) == 0) {
/* create child to do dialing */
sleep(2);
fclose(stdin);
fclose(stdout);
#ifdef MULTISPEED
fixline(va, baudrate);
#else
sg.sg_flags = RAW|ANYP;
sg.sg_ispeed = sg.sg_ospeed = B1200;
ioctl(va, TIOCSETP, &sg);
#endif
pc(va, ABORT);
sleep(1);
ioctl(va, TIOCFLUSH, &zero);
pc(va, STX); /* access adaptor */
pc(va, *p++); /* Send Dialer Address Digit */
pc(va, *p); /* Send Modem Address Digit */
while (*ph && *ph != '<') {
switch (*ph) {
case '_':
case '-':
case '=':
pc(va, '=');
break;
default:
if (*ph >= '0' && *ph <= '9')
pc(va, *ph);
break;
}
ph++;
}
pc(va, '<'); /* Transfer Control to Modem (sigh) */
pc(va, SI); /* Send Buffer Empty */
pc(va, ETX); /* Initiate Call */
sleep(1);
if (read(va, &c, 1) != 1) {
close(va);
logent("ACU READ", _FAILED);
exit(1);
}
if (c == 'B' || c == 'G') {
char cc;
pc(va, ABORT);
read(va, &cc, 1);
}
DEBUG(4, "Dialer returned %c\n", c);
close(va);
exit(c != 'A');
}
/*
* open line - will return on carrier
*/
if ((i = open(com, 2)) < 0) {
if (errno == EIO)
logent("carrier", "LOST");
else
logent("dialup open", _FAILED);
goto failret;
}
while ((pid = wait(&status)) != child && pid != -1)
;
alarm(0);
if (status) {
close(i);
close(va); /* XXX */
return CF_DIAL;
}
fixline(i, dev->D_speed);
return i;
failret:
alarm(0);
close(va);
if (child != -1)
kill(child, SIGKILL);
return CF_DIAL;
}
rvmacscls(fd)
register int fd;
{
if (fd > 0) {
char c;
pc(fd, ABORT);
ioctl(fd, TIOCCDTR, STBNULL);
sleep(1);
ioctl(fd, TIOCNXCL, STBNULL);
close(fd);
delock(devSel);
}
}
#endif

163
src/cmd/uucp/aculib/sy.c Normal file
View File

@@ -0,0 +1,163 @@
#ifndef lint
static char sccsid[] = "@(#)sy.c 4.1 (Berkeley) 1/22/85";
#endif
#include "../condevs.h"
#ifdef SYTEK
/*
* sykopn: establish connection through a sytek port.
* Returns descriptor open to tty for reading and writing.
* Negative values (-1...-7) denote errors in connmsg.
* Will try to change baud rate of local port to match
* that of the remote side.
*/
char sykspeed[50]; /* speed to reset to on close */
sykopn(flds)
register char *flds[];
{
extern errno;
char *rindex(), *fdig(), dcname[20];
int dh, ok = 0, speed;
register FILE *dfp;
struct Devices dev;
char speedbuf[50];
dfp = fopen(DEVFILE, "r");
ASSERT(dfp != NULL, "Can't open", DEVFILE, 0);
signal(SIGALRM, alarmtr);
dh = -1;
while(rddev(dfp, &dev) != FAIL) {
/* we'll set our own speed; F_CLASS is how cynthia configures it every night
if (strcmp(flds[F_CLASS], dev.D_class) != SAME)
continue;
*/
if (snccmp(flds[F_LINE], dev.D_type) != SAME)
continue;
if (mlock(dev.D_line) == FAIL)
continue;
sprintf(dcname, "/dev/%s", dev.D_line);
getnextfd();
alarm(10);
if (setjmp(Sjbuf)) {
delock(dev.D_line);
logent(dev.D_line,"sytek open TIMEOUT");
dh = -1;
break;
}
dh = open(dcname, 2);
alarm(0);
next_fd = -1;
if (dh > 0) {
break;
}
devSel[0] = '\0';
delock(dev.D_line);
}
fclose(dfp);
if (dh < 0)
return(CF_NODEV);
speed = atoi(fdig(dev.D_class));
fixline(dh, speed);
sleep(1);
/* negotiate with sytek */
genbrk(dh, 3);
DEBUG(4, "wanted %s ", "#");
ok = expect("#", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if(ok != 0){
if(atoi(fdig(dev.D_class)) == 9600){
fixline(dh, 2400);
speed = 2400;
} else {
fixline(dh, 9600);
speed = 9600;
}
sleep(1);
genbrk(dh, 3);
ok = expect("#", dh);
if(ok){
close(dh);
DEBUG(4, "sytek BREAK failed\n", "");
delock(dev.D_line);
return(CF_DIAL);
}
}
write(dh, "done \r", 6);
ok = expect("#", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if(speed != atoi(fdig(flds[F_CLASS]))){
DEBUG(4, "changing speed\n", "");
sprintf(speedbuf, "baud %s\r", fdig(flds[F_CLASS]));
write(dh, speedbuf, strlen(speedbuf));
sleep(1);
speed = atoi(fdig(flds[F_CLASS]));
fixline(dh, speed);
genbrk(dh, 3);
ok = expect("#", dh);
DEBUG(4, "speed set %s\n", ok ? "failed" : flds[F_CLASS]);
}
strcpy(sykspeed, dev.D_class);
write(dh, "command break\r", 14);
ok = expect("#", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok == 0) {
write(dh, "call ", 5);
write(dh, flds[F_PHONE], strlen(flds[F_PHONE]));
write(dh, "\r", 1);
DEBUG(4, "sytek dial %s\n", flds[F_PHONE]);
DEBUG(4, "wanted %s ", "COMPLETED TO ");
ok = expect("COMPLETED TO ", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
}
if (ok != 0) {
close(dh);
DEBUG(4, "sytek failed\n", "");
delock(dev.D_line);
return(CF_DIAL);
} else
DEBUG(4, "sytek ok\n", "");
CU_end = sykcls;
strcpy(devSel, dev.D_line); /* for later unlock */
return(dh);
}
sykcls(fd)
register int fd;
{
register int ok, speed;
if (fd > 0) {
genbrk(fd, 3);
ok = expect("#", fd);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if(ok != 0){
genbrk(fd, 3);
ok = expect("#", fd);
}
if(ok == 0){
write(fd, "done 1\r", 7);
ok = expect("#", fd);
DEBUG(4, "got %s\n", ok ? "?" : "that");
DEBUG(4, "reset baud to %s\n", sykspeed);
write(fd, "baud ", 5);
write(fd, sykspeed, strlen(sykspeed));
write(fd, "\r", 1);
sleep(1);
}
close(fd);
delock(devSel);
}
}
#endif

View File

@@ -0,0 +1,66 @@
#ifndef lint
static char sccsid[] = "@(#)unet.c 4.1 (Berkeley) 1/22/85";
#endif
#include "../condevs.h"
#ifdef UNETTCP
/*
* unetopn -- make UNET (tcp-ip) connection
*
* return codes:
* >0 - file number - ok
* FAIL - failed
*/
/* Default port of uucico server */
#define DFLTPORT 33
unetopn(flds)
register char *flds[];
{
register int ret, port;
int unetcls();
port = atoi(flds[F_PHONE]);
if (port <= 0 || port > 255)
port = DFLTPORT;
DEBUG(4, "unetopn host %s, ", flds[F_NAME]);
DEBUG(4, "port %d\n", port);
if (setjmp(Sjbuf)) {
logent("tcpopen", "TIMEOUT");
endhnent(); /* see below */
return CF_DIAL;
}
signal(SIGALRM, alarmtr);
alarm(30);
ret = tcpopen(flds[F_NAME], port, 0, TO_ACTIVE, "rw");
alarm(0);
endhnent(); /* wave magic wand at 3com and incant "eat it, bruce" */
if (ret < 0) {
DEBUG(5, "tcpopen failed: errno %d\n", errno);
logent("tcpopen", _FAILED);
return CF_DIAL;
}
CU_end = unetcls;
return ret;
}
/*
* unetcls -- close UNET connection.
*/
unetcls(fd)
register int fd;
{
DEBUG(4, "UNET CLOSE called\n", 0);
if (fd > 0) {
#ifdef notdef
/* disable this until a timeout is put in */
if (ioctl(fd, UIOCCLOSE, STBNULL))
logent("UNET CLOSE", _FAILED);
#endif
close(fd);
DEBUG(4, "closed fd %d\n", fd);
}
}
#endif

126
src/cmd/uucp/aculib/va212.c Normal file
View File

@@ -0,0 +1,126 @@
#ifndef lint
static char sccsid[] = "@(#)va212.c 4.2 (Berkeley) 6/23/85";
#endif
#include "../condevs.h"
#ifdef VA212
va212opn(telno, flds, dev)
char *telno;
char *flds[];
struct Devices *dev;
{
int dh = -1;
int i, ok, er = 0, delay;
extern errno;
char dcname[20];
sprintf(dcname, "/dev/%s", dev->D_line);
if (setjmp(Sjbuf)) {
DEBUG(1, "timeout va212 open\n", 0);
logent("va212 open", "TIMEOUT");
if (dh >= 0)
close(dh);
delock(dev->D_line);
return CF_NODEV;
}
signal(SIGALRM, alarmtr);
getnextfd();
alarm(10);
dh = open(dcname, 2);
alarm(0);
/* modem is open */
next_fd = -1;
if (dh < 0) {
DEBUG (4, errno == 4 ? "%s: no carrier\n" : "%s: can't open\n",
dcname);
delock(dev->D_line);
return errno == 4 ? CF_DIAL : CF_NODEV;
}
fixline(dh, dev->D_speed);
/* translate - to K for Vadic */
DEBUG(4, "calling %s -> ", telno);
delay = 0;
for (i = 0; i < strlen(telno); ++i) {
switch(telno[i]) {
case '=': /* await dial tone */
case '-': /* delay */
case '<':
telno[i] = 'K';
delay += 5;
break;
}
}
DEBUG(4, "%s\n", telno);
for(i = 0; i < TRYCALLS; ++i) { /* make TRYCALLS tries */
/* wake up Vadic */
sendthem("\005\\d", dh);
DEBUG(4, "wanted * ", CNULL);
ok = expect("*", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok != 0)
continue;
sendthem("D\\d", dh); /* "D" (enter number) command */
DEBUG(4, "wanted NUMBER? ", CNULL);
ok = expect("NUMBER?", dh);
if (ok == 0)
ok = expect("\n", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok != 0)
continue;
/* send telno, send \r */
sendthem(telno, dh);
DEBUG(4, "wanted %s ", telno);
ok = expect(telno, dh);
if (ok == 0)
ok = expect("\n", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok != 0)
continue;
sendthem("", dh); /* confirm number */
DEBUG(4, "wanted %s ", "DIALING...");
ok = expect("DIALING...", dh);
if (ok == 0) {
ok = expect("\n", dh);
DEBUG(4, "wanted ANSWER TONE", CNULL);
ok = expect("ANSWER TONE", dh);
if (ok == 0)
ok = expect("\n", dh);
}
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok == 0)
break;
}
if (ok == 0) {
DEBUG(4, "wanted ON LINE\\r\\n ", CNULL);
ok = expect("ON LINE\r\n", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
}
if (ok != 0) {
sendthem("I\\d", dh); /* back to idle */
if (dh > 2)
close(dh);
DEBUG(4, "vadDial failed\n", CNULL);
delock(dev->D_line);
return CF_DIAL;
}
DEBUG(4, "va212 ok\n", 0);
return dh;
}
va212cls(fd)
{
if (fd > 0) {
close(fd);
sleep(5);
delock(devSel);
}
}
#endif

123
src/cmd/uucp/aculib/va811.c Normal file
View File

@@ -0,0 +1,123 @@
#ifndef lint
static char sccsid[] = "@(#)va811.c 4.1 (Berkeley) 1/22/85";
#endif
#include "../condevs.h"
#ifdef VA811S
/*
* Racal-Vadic VA811 dialer with 831 adaptor.
* A typical 300 baud L-devices entry is
* ACU /dev/tty10 unused 300 va811s
* where tty10 is the communication line (D_Line),
* and 300 is the line speed.
* This is almost identical to RVMACS except that we don't need to
* send addresses and modem types, and don't need the fork.
* Joe Kelsey, fluke!joe, vax4.1526, Apr 11 1984.
*/
#define STX 02 /* Access Adaptor */
#define ETX 03 /* Transfer to Dialer */
#define SI 017 /* Buffer Empty (end of phone number) */
#define SOH 01 /* Abort */
va811opn(ph, flds, dev)
char *ph, *flds[];
struct Devices *dev;
{
int va;
register int i, tries;
char c, dcname[20];
char vabuf[35]; /* STX, 31 phone digits, SI, ETX, NUL */
va = 0;
sprintf(dcname, "/dev/%s", dev->D_line);
if (setjmp(Sjbuf)) {
DEBUG(1, "timeout va811 open\n", 0);
logent("va811opn", "TIMEOUT");
if (va >= 0)
close(va);
delock(dev->D_line);
return CF_NODEV;
}
DEBUG(4, "va811: STARTING CALL\n", 0);
getnextfd();
signal(SIGALRM, alarmtr);
alarm(10);
va = open(dcname, 2);
alarm(0);
/* line is open */
next_fd = -1;
if (va < 0) {
DEBUG(4, errno == 4 ? "%s: no carrier\n" : "%s: can't open\n",
dcname);
delock(dev->D_line);
logent(dcname, "CAN'T OPEN");
return(errno == 4 ? CF_DIAL : CF_NODEV);
}
fixline(va, dev->D_speed);
/* first, reset everything */
sendthem("\\01\\c", va);
DEBUG(4, "wanted %c ", 'B');
i = expect("B", va);
DEBUG(4, "got %s\n", i ? "?" : "that");
if (i != 0) {
DEBUG(4, "va811: NO RESPONSE\n", 0);
logent("va811 reset", "TIMEOUT");
close(va);
delock(dev->D_line);
return CF_DIAL;
}
sprintf(vabuf, "%c%.31s%c%c\\c", STX, ph, SI, SOH);
sendthem(vabuf, va);
DEBUG(4, "wanted %c ", 'B');
i = expect("B", va);
DEBUG(4, "got %s\n", i ? "?" : "that");
if (i != 0) {
DEBUG(4, "va811: STORE NUMBER\n", 0);
logent("va811 STORE", _FAILED);
close(va);
delock(dev->D_line);
return CF_DIAL;
}
for (tries = 0; tries < TRYCALLS; tries++) {
sprintf(vabuf, "%c%c\\c", STX, ETX);
sendthem(vabuf, va);
DEBUG(4, "DIALING...", CNULL);
i = expect("A", va);
DEBUG(4, " %s\n", i ? _FAILED : "SUCCEEDED");
if (i != 0) {
DEBUG(4, "va811: RESETTING\n", CNULL);
logent("va811 DIAL", _FAILED);
sendthem("\\01\\c", va);
expect("B", va);
}
else
break;
}
if (tries >= TRYCALLS) {
close(va);
delock(dev->D_line);
return CF_DIAL;
}
DEBUG(4, "va811 ok\n", CNULL);
return va;
}
va811cls(fd)
register int fd;
{
DEBUG(2, "va811 close %d\n", fd);
p_chwrite(fd, SOH);
/* ioctl(fd, TIOCCDTR, NULL);*/
close(fd);
delock(devSel);
}
#endif

167
src/cmd/uucp/aculib/va820.c Normal file
View File

@@ -0,0 +1,167 @@
#ifndef lint
static char sccsid[] = "@(#)va820.c 4.3 (Berkeley) 10/10/85";
#endif
#include "../condevs.h"
#ifdef VA820
/*
* Racal-Vadic 'RV820' with 831 adaptor.
* BUGS:
* dialer baud rate is hardcoded
*/
#define MAXDIG 30 /* set by switches inside adapter */
char c_abort = '\001';
char c_start = '\002';
char c_empty = '\017';
char c_end = '\003';
va820opn(ph, flds, dev)
char *ph, *flds[];
struct Devices *dev;
{
register int va, i, child;
char c, acu[20], com[20];
char vadbuf[MAXDIG+2];
int nw, lt;
unsigned timelim;
struct sgttyb sg;
child = -1;
if (strlen(ph) > MAXDIG) {
DEBUG(4, "BAD PHONE NUMBER %s\n", ph);
logent("rvadopn", "BAD PHONE NUMBER");
i = CF_DIAL;
goto ret;
}
if (setjmp(Sjbuf)) {
logent("rvadopn", "TIMEOUT");
i = CF_DIAL;
goto ret;
}
DEBUG(4, "ACU %s\n", dev->D_calldev);
DEBUG(4, "LINE %s\n", dev->D_line);
sprintf(acu, "/dev/%s", dev->D_calldev);
getnextfd();
signal(SIGALRM, alarmtr);
alarm(10);
va = open(acu, 2);
alarm(0);
next_fd = -1;
if (va < 0) {
DEBUG(4, "ACU OPEN FAIL %d\n", errno);
logent(acu, "CAN'T OPEN");
i = CF_NODEV;
goto ret;
}
/*
* Set speed and modes on dialer and clear any
* previous requests
*/
DEBUG(4, "SETTING UP VA831 (%d)\n", va);
ioctl(va, TIOCGETP, &sg);
sg.sg_ispeed = sg.sg_ospeed = B1200;
sg.sg_flags |= RAW;
sg.sg_flags &= ~ECHO;
ioctl(va, TIOCSETP, &sg);
DEBUG(4, "CLEARING VA831\n", 0);
if ( write(va, &c_abort, 1) != 1) {
DEBUG(4,"BAD VA831 WRITE %d\n", errno);
logent(acu, "CAN'T CLEAR");
i = CF_DIAL;
goto ret;
}
sleep(1); /* XXX */
read(va, &c, 1);
if (c != 'B') {
DEBUG(4,"BAD VA831 RESPONSE %c\n", c);
logent(acu, "CAN'T CLEAR");
i = CF_DIAL;
goto ret;
}
/*
* Build the dialing sequence for the adapter
*/
DEBUG(4, "DIALING %s\n", ph);
sprintf(vadbuf, "%c%s<%c%c", c_start, ph, c_empty, c_end);
timelim = 5 * strlen(ph);
alarm(timelim < 30 ? 30 : timelim);
nw = write(va, vadbuf, strlen(vadbuf)); /* Send Phone Number */
if (nw != strlen(vadbuf)) {
DEBUG(4,"BAD VA831 WRITE %d\n", nw);
logent(acu, "BAD WRITE");
goto failret;
}
sprintf(com, "/dev/%s", dev->D_line);
/* create child to open comm line */
if ((child = fork()) == 0) {
signal(SIGINT, SIG_DFL);
open(com, 0);
sleep(5);
_exit(1);
}
DEBUG(4, "WAITING FOR ANSWER\n", 0);
if (read(va, &c, 1) != 1) {
logent("ACU READ", _FAILED);
goto failret;
}
switch(c) {
case 'A':
/* Fine! */
break;
case 'B':
DEBUG(2, "Line Busy / No Answer\n", 0);
goto failret;
case 'D':
DEBUG(2, "Dialer format error\n", 0);
goto failret;
case 'E':
DEBUG(2, "Dialer parity error\n", 0);
goto failret;
case 'F':
DEBUG(2, "Phone number too long\n", 0);
goto failret;
case 'G':
DEBUG(2, "Modem Busy\n", 0);
goto failret;
default:
DEBUG(2, "Unknown MACS return code '%c'\n", c&0177);
goto failret;
}
/*
* open line - will return on carrier
*/
if ((i = open(com, 2)) < 0) {
if (errno == EIO)
logent("carrier", "LOST");
else
logent("dialup open", _FAILED);
goto failret;
}
DEBUG(2, "RVADIC opened %d\n", i);
fixline(i, dev->D_speed);
goto ret;
failret:
i = CF_DIAL;
ret:
alarm(0);
if (child != -1)
kill(child, SIGKILL);
close(va);
while ((nw = wait(&lt)) != child && nw != -1)
;
return i;
}
va820cls(fd)
register int fd;
{
DEBUG(2, "RVADIC close %d\n", fd);
close(fd);
}
#endif

132
src/cmd/uucp/aculib/vad.c Normal file
View File

@@ -0,0 +1,132 @@
#ifndef lint
static char sccsid[] = "@(#)vad.c 4.2 (Berkeley) 10/10/85";
#endif
#include "../condevs.h"
#ifdef VADIC
/*
* vadopn: establish dial-out connection through a Racal-Vadic 3450.
* Returns descriptor open to tty for reading and writing.
* Negative values (-1...-7) denote errors in connmsg.
* Be sure to disconnect tty when done, via HUPCL or stty 0.
*/
vadopn(telno, flds, dev)
char *telno;
char *flds[];
struct Devices *dev;
{
int dh = -1;
int i, ok, er = 0, delay;
extern errno;
char dcname[20];
sprintf(dcname, "/dev/%s", dev->D_line);
if (setjmp(Sjbuf)) {
DEBUG(1, "timeout vadic open\n", "");
logent("vadic open", "TIMEOUT");
if (dh >= 0)
close(dh);
delock(dev->D_line);
return CF_NODEV;
}
signal(SIGALRM, alarmtr);
getnextfd();
alarm(10);
dh = open(dcname, 2);
alarm(0);
/* modem is open */
next_fd = -1;
if (dh < 0) {
delock(dev->D_line);
return CF_NODEV;
}
fixline(dh, dev->D_speed);
DEBUG(4, "calling %s -> ", telno);
if (dochat(dev, flds, dh)) {
logent(dcname, "CHAT FAILED");
close(dh);
return CF_DIAL;
}
delay = 0;
for (i = 0; i < strlen(telno); ++i) {
switch(telno[i]) {
case '=': /* await dial tone */
case '-':
case ',':
case '<':
case 'K':
telno[i] = 'K';
delay += 5;
break;
}
}
DEBUG(4, "%s\n", telno);
for(i = 0; i < 5; ++i) { /* make 5 tries */
/* wake up Vadic */
write(dh, "\005", 1);
sleep(1);
write(dh, "\r", 1);
DEBUG(4, "wanted * ", CNULL);
ok = expect("*~5", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok != 0)
continue;
write(dh, "D\r", 2); /* "D" (enter number) command */
DEBUG(4, "wanted NUMBER?\\r\\n ", CNULL);
ok = expect("NUMBER?\r\n~5", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok != 0)
continue;
/* send telno, send \r */
write(dh, telno, strlen(telno));
sleep(1);
write(dh, "\r", 1);
DEBUG(4, "wanted %s ", telno);
ok = expect(telno, dh);
if (ok == 0)
ok = expect("\r\n", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok != 0)
continue;
write(dh, "\r", 1); /* confirm number */
DEBUG(4, "wanted DIALING: ", CNULL);
ok = expect("DIALING: ", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok == 0)
break;
}
if (ok == 0) {
sleep(10 + delay); /* give vadic some time */
DEBUG(4, "wanted ON LINE\\r\\n ", CNULL);
ok = expect("ON LINE\r\n", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
}
if (ok != 0) {
if (dh > 2)
close(dh);
DEBUG(4, "vadDial failed\n", CNULL);
delock(dev->D_line);
return CF_DIAL;
}
DEBUG(4, "vadic ok\n", CNULL);
return dh;
}
vadcls(fd)
{
if (fd > 0) {
close(fd);
sleep(5);
delock(devSel);
}
}
#endif

100
src/cmd/uucp/aculib/vent.c Normal file
View File

@@ -0,0 +1,100 @@
#ifndef lint
static char sccsid[] = "@(#)vent.c 4.2 (Berkeley) 10/10/85";
#endif
#include "../condevs.h"
#ifdef VENTEL
ventopn(telno, flds, dev)
char *flds[], *telno;
struct Devices *dev;
{
int dh;
int i, ok = -1;
char dcname[20];
sprintf(dcname, "/dev/%s", dev->D_line);
if (setjmp(Sjbuf)) {
DEBUG(1, "timeout ventel open\n", "");
logent("ventel open", "TIMEOUT");
if (dh >= 0)
close(dh);
delock(dev->D_line);
return CF_NODEV;
}
signal(SIGALRM, alarmtr);
getnextfd();
alarm(10);
dh = open(dcname, 2);
next_fd = -1;
alarm(0);
if (dh < 0) {
DEBUG(4,"%s\n", errno == 4 ? "no carrier" : "can't open modem");
delock(dev->D_line);
return errno == 4 ? CF_DIAL : CF_NODEV;
}
/* modem is open */
fixline(dh, dev->D_speed);
/* translate - to % and = to & for VenTel */
DEBUG(4, "calling %s -> ", telno);
for (i = 0; i < strlen(telno); ++i) {
switch(telno[i]) {
case '-': /* delay */
telno[i] = '%';
break;
case '=': /* await dial tone */
telno[i] = '&';
break;
case '<':
telno[i] = '%';
break;
}
}
DEBUG(4, "%s\n", telno);
sleep(1);
for(i = 0; i < 5; ++i) { /* make up to 5 tries */
slowrite(dh, "\r\r");/* awake, thou lowly VenTel! */
DEBUG(4, "wanted %s ", "$");
ok = expect("$", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok != 0)
continue;
slowrite(dh, "K"); /* "K" (enter number) command */
DEBUG(4, "wanted %s ", "DIAL: ");
ok = expect("DIAL: ", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok == 0)
break;
}
if (ok == 0) {
slowrite(dh, telno); /* send telno, send \r */
slowrite(dh, "\r");
DEBUG(4, "wanted %s ", "ONLINE");
ok = expect("ONLINE!", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
}
if (ok != 0) {
if (dh > 2)
close(dh);
DEBUG(4, "venDial failed\n", "");
return CF_DIAL;
}
else
DEBUG(4, "venDial ok\n", "");
return dh;
}
ventcls(fd)
int fd;
{
if (fd > 0) {
close(fd);
sleep(5);
delock(devSel);
}
}
#endif

168
src/cmd/uucp/aculib/vmacs.c Normal file
View File

@@ -0,0 +1,168 @@
#ifndef lint
static char sccsid[] = "@(#)vmacs.c 4.3 (Berkeley) 10/10/85";
#endif
#include "../condevs.h"
#ifdef VMACS
/*
* Racal-Vadic 'RV811' MACS system with 831 adaptor.
*
* A typical 300 baud L-devices entry is
* ACU /dev/tty10 /dev/tty11,48,1200 300 vmacs
* where tty10 is the communication line (D_Line),
* tty11 is the dialer line (D_calldev),
* the '4' is the dialer address + modem type (viz. dialer 0, Bell 103),
* and the '8' is the communication port
* (Note: Based on RVMACS version for 820 dialer. This version
* developed by Doug Kingston @ BRL, 13 December 83.)
*/
#define SOH 01 /* Abort */
#define STX 02 /* Access Adaptor */
#define ETX 03 /* Transfer to Dialer */
#define SI 017 /* Buffer Empty (end of phone number) */
vmacsopn(ph, flds, dev)
char *ph, *flds[];
struct Devices *dev;
{
register int va, i, child;
register char *p;
char c, acu[20], com[20];
char modem, dialer;
int dialspeed;
char c_STX = STX;
char c_ETX = ETX;
char c_SI = SI;
char c_SOH = SOH;
/* create child to open comm line */
child = -1;
sprintf(com, "/dev/%s", dev->D_line);
if ((child = fork()) == 0) {
signal(SIGINT, SIG_DFL);
open(com, 0);
DEBUG(5, "%s Opened.", com);
sleep(5);
exit(1);
}
if ((p = index(dev->D_calldev, ',')) == NULL) {
DEBUG(2, "No dialer/modem specification\n", 0);
goto failret;
}
*p++ = '\0';
if (*p < '0' || *p > '7') {
logent(p, "Bad dialer address/modem type");
goto failret;
}
dialer = *p++;
if (*p < '0' || *p > '>') {
logent(p, "Bad modem address");
goto failret;
}
modem = *p++;
if (*p++ == ',')
dialspeed = atoi (p);
else
dialspeed = dev->D_speed;
if (setjmp(Sjbuf)) {
logent("vmacsopn", "TIMEOUT");
i = CF_DIAL;
goto ret;
}
DEBUG(4, "STARTING CALL\n", 0);
sprintf(acu, "/dev/%s", dev->D_calldev);
getnextfd();
signal(SIGALRM, alarmtr);
alarm(60);
if ((va = open(acu, 2)) < 0) {
logent(acu, "CAN'T OPEN");
i = CF_NODEV;
goto ret;
}
DEBUG(5, "ACU %s opened.\n", acu);
next_fd = -1;
fixline(va, dialspeed);
write(va, &c_SOH, 1); /* abort, reset the dialer */
do {
if (read (va, &c, 1) != 1) {
logent ("MACS initialization", _FAILED);
goto failret;
}
} while ((c&0177) != 'B');
DEBUG(5, "ACU initialized\n", 0);
write(va, &c_STX, 1); /* start text, access adaptor */
write(va, &dialer, 1); /* send dialer address digit */
write(va, &modem, 1); /* send modem address digit */
for (p=ph; *p; p++) {
if (*p == '=' || (*p >= '0' && *p <= '9'))
write(va, p, 1);
}
write(va, &c_SI, 1); /* send buffer empty */
write(va, &c_ETX, 1); /* end of text, initiate call */
if (read(va, &c, 1) != 1) {
logent("ACU READ", _FAILED);
goto failret;
}
switch(c) {
case 'A':
/* Fine! */
DEBUG(5, "Call connected\n", 0);
break;
case 'B':
DEBUG(2, "Dialer Timeout or Abort\n", 0);
goto failret;
case 'D':
DEBUG(2, "Dialer format error\n", 0);
goto failret;
case 'E':
DEBUG(2, "Dialer parity error\n", 0);
goto failret;
case 'F':
DEBUG(2, "Phone number too long\n", 0);
goto failret;
case 'G':
DEBUG(2, "Busy signal\n", 0);
goto failret;
default:
DEBUG(2, "Unknown MACS return code '%c'\n", i);
goto failret;
}
/*
* open line - will return on carrier
*/
if ((i = open(com, 2)) < 0) {
if (errno == EIO)
logent("carrier", "LOST");
else
logent("dialup open", _FAILED);
goto failret;
}
fixline(i, dev->D_speed);
goto ret;
failret:
i = CF_DIAL;
ret:
alarm(0);
if (child > 1)
kill(child, SIGKILL);
close(va);
sleep(2);
return i;
}
vmacscls(fd)
register int fd;
{
char c_SOH = SOH;
DEBUG(2, "MACS close %d\n", fd);
write(fd, &c_SOH, 1);
/* ioctl(fd, TIOCCDTR, NULL);*/
close(fd);
}
#endif

362
src/cmd/uucp/anlwrk.c Normal file
View File

@@ -0,0 +1,362 @@
#if !defined(lint) && defined(DOSCCS)
static char sccsid[] = "@(#)anlwrk.c 5.5.1 (2.11BSD) 1997/10/2";
#endif
#include "uucp.h"
#include <sys/stat.h>
#include <strings.h>
#include "uust.h"
#ifdef NDIR
#include "ndir.h"
#else
#include <sys/dir.h>
#endif
#include <ctype.h>
#define TLIMIT (5*60L)
#define NITEMS(X) (sizeof (X) / sizeof ((X)[0]))
int Nfiles = 0;
char Filent[LLEN][NAMESIZE];
extern int TransferSucceeded;
/*LINTLIBRARY*/
/*
* create a vector of command arguments
*
* return codes:
* 0 - no more work in this file
* positive number - number of arguments
*/
/* LOCAL only */
int
anlwrk(file, wvec)
register char *file, **wvec;
{
static char str[MAXRQST], nstr[MAXRQST], lastfile[MAXFULLNAME] = "";
static FILE *fp = NULL;
static long nextread, nextwrite;
/*
* If called with a null string, force a shutdown
* of the current work file.
*/
if (file[0] == '\0') {
if (fp != NULL)
fclose (fp);
fp = NULL;
return 0;
}
if (fp == NULL) {
if (strncmp(file, lastfile, MAXFULLNAME) == 0) {
DEBUG(5,"Workfilename repeated: %s\n", file);
return 0;
}
strncpy(lastfile, file, MAXFULLNAME);
fp = fopen(subfile(file), "r+w");
if (fp == NULL) {
char *bnp, rqstr[MAXFULLNAME];
bnp = rindex(file, '/');
sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : file);
xmv(file, rqstr);
logent(subfile(file), "CMD FILE UNREADABLE");
unlink(subfile(file));
return 0;
}
Usrf = 0;
nstr[0] = '\0';
nextread = nextwrite = 0L;
}
if (nstr[0] != '\0' && TransferSucceeded) {
fseek(fp, nextwrite, 0);
fputs(nstr, fp);
fseek(fp, nextread, 0);
}
do {
nextwrite = ftell(fp);
if (fgets(str, MAXRQST, fp) == NULL) {
fclose(fp);
if (TransferSucceeded)
unlink(subfile(file));
USRF(USR_COMP);
US_RRS(file, Usrf);
Usrf = 0;
file[0] = '\0';
nstr[0] = '\0';
fp = NULL;
return 0;
}
} while (!isupper(str[0]));
nextread = ftell(fp);
strncpy(nstr, str, MAXRQST);
nstr[0] = tolower(nstr[0]);
return getargs(str, wvec, 20);
}
/*
* build list of work files for given system
*
* return value - 1 if work was found, else 0
*
*/
/* LOCAL only */
int
bldflst (reqst, dir, pre)
char *reqst;
register char *dir, *pre;
{
static DIR *dirp = NULL;
register nfound;
char filename[NAMESIZE];
int plen = strlen (pre);
int flen;
extern char MaxGrade;
if (dirp == NULL) {
if ((dirp = opendir(subdir(dir,pre[0]))) == NULL) {
DEBUG(1,"opendir(%s) FAILS\n",subdir(dir,pre[0]));
return 0;
}
}
else
rewinddir(dirp);
for (nfound = 0, Nfiles = 0; gnamef(dirp, filename);) {
/* Check for two systems with the same prefix.
* Magic number "5" is 1 for "grade" character plus
* 4 for sequence number. The point here is to not
* send work for a system which has as a prefix the
* name of the system called for.
* Special case: prefix "X." does not do this check
* so uuxqt can use bldflst.
*/
flen = strlen(filename);
if (!prefix(pre, filename) || (plen != 2 && flen-plen != 5)) {
DEBUG(99,"bldflst rejects %s\n",filename);
continue;
}
if (filename[flen-5] > MaxGrade ) {
DEBUG(8,"bldflst rejects %s, grade too low\n",filename);
continue;
}
nfound++;
if (*reqst == 'c')
return 1;
entflst(filename);
}
return nfound? 1: 0;
}
/*
* put new name if list is not full or new name is less than the MAX
* now in the list.
*
*/
/* LOCAL only */
int
entflst(file)
register char *file;
{
register int i;
/* locate position for the new file and make room for it */
for (i = Nfiles; i > 0; i--) {
if (pcompar(file, Filent[i-1]) <= 0)
break;
if (i <LLEN)
strcpy(Filent[i], Filent[i-1]);
}
/* add new file (if there is room), and increase Nfiles if need be */
if (i < LLEN) {
strcpy(Filent[i], file);
if (Nfiles < LLEN)
Nfiles++;
}
}
/*
Compare priority of filenames p1 and p2. Return:
* < 0 if p1 "has lower priority than" p2.
* = 0 if p1 "has priority equal to" p2.
* > 0 if p1 "has greater priority than" p2.
* Priority:
* lower grade wins.
* lower sequence number wins (unless wrap-around is suspected).
*
*/
/* LOCAL only */
int
pcompar(p1, p2)
register char *p1, *p2;
{
register int rc;
/* assert: strlen(p1) and strlen(p2) are >= 5 */
p1 += strlen(p1)-5;
p2 += strlen(p2)-5;
/* check 'grade' */
if (rc = *p2++ - *p1++)
return rc;
/* check for sequence wrap-around */
if (rc = *p2++ - *p1++)
if (rc < -10 || rc > 10)
return -rc;
else
return rc;
/* check remaining digits */
return strcmp(p2, p1);
}
/*
* get next work file
*
* return value:
*
* 0 - No file gotten
* 1 - File successfully gotten.
*
*/
/* LOCAL only */
gtwrkf(dir, file)
char *file, *dir;
{
register int i;
if (Nfiles-- <= 0) {
Nfiles = 0;
return 0;
}
sprintf(file, "%s/%s", dir, Filent[0]);
for (i=0; i<Nfiles;i++)
strcpy(Filent[i], Filent[i+1]);
return 1;
}
/*
* get work vector
*
* return codes:
* positive number - number of arguments
* 0 - no arguments - fail
*/
/* EXTERNALLY CALLED */
int
gtwvec(file, dir, wkpre, wrkvec)
char *dir, *wkpre, **wrkvec;
register char *file;
{
register int nargs, n;
n = 0;
while ((nargs = anlwrk(file, wrkvec)) == 0) {
if (++n > 3 || !iswrk(file, "get", dir, wkpre))
return 0;
}
return nargs;
}
/*
* iswrk - this routine will check the work list (list).
* If it is empty or the present work is exhausted, it
* will call bldflst to generate a new list.
* The "reqst" field will be the string "chk" or "get" to
* check for work, or get the next work file respectively.
*
* return codes:
* 0 - no more work (or some error)
* 1 - there is work
*
*/
/* EXTERNALLY CALLED */
int
iswrk(file, reqst, dir, pre)
register char *file, *reqst, *dir, *pre;
{
static char *lastpre = 0;
register ret;
/* Starting new system; re-init */
if (lastpre == 0 || strcmp(lastpre,pre) != 0) {
anlwrk ("", (char **)0); /* Force close of work file */
/* Save last worked-on prefix */
if (lastpre != 0)
free (lastpre);
lastpre = (char *)malloc((unsigned)(strlen(pre)+1));
strcpy (lastpre, pre);
/* Set the external indexes properly
*/
Nfiles = 0;
}
/* If the list is empty or new files have entered
* the spool area, call "bldflst" to read
* some file names into it. Because names can
* be put in the list that later turn out to
* be unusable (from "gtwrkf"), this operation
* continues until either "bldflst" can't find
* any new files, or "gtwrkf" signals success.
*/
for (;;) {
ret = 0;
if (Nfiles <= 0 || newspool((time_t)TLIMIT)) {
ret = bldflst (reqst, dir, pre);
DEBUG(99,"bldflst returns %d\n",ret);
}
/* If they only wanted to check, return
* boolean list not empty. NB: the list
* will be forcibly emptied as soon as
* a new system name is mentioned.
*/
if (*reqst == 'c')
return ret;
if (Nfiles <= 0)
return 0;
if (gtwrkf(dir, file))
return 1;
}
}
/* Return non-zero if there is new work in the spool
* area since last check. Assumes that if the sequence
* file has been modified, there is new work. This is
* not absolutely correct, but should be close enough.
* Only checks every <limit> seconds at most. Called
* from "iswrk()" when a new work file is requested.
*/
/* LOCAL only */
int
newspool(limit)
time_t limit;
{
static time_t lastcheck = 0, lastmod = 0;
time_t check;
struct stat mod;
register int ret = 0;
/* (void) */ time (&check);
if (check - lastcheck > limit || lastcheck - check > limit) {
mod.st_mtime = 0;
/* (void) */ stat (SEQFILE, &mod);
if (mod.st_mtime != lastmod)
ret = 1;
lastmod = mod.st_mtime;
}
lastcheck = check;
return ret;
}

25
src/cmd/uucp/anyread.c Normal file
View File

@@ -0,0 +1,25 @@
#ifndef lint
static char sccsid[] = "@(#)anyread.c 5.4 (Berkeley) 6/19/85";
#endif
#include "uucp.h"
#include <sys/stat.h>
/*LINTLIBRARY*/
/*
* anyread check if anybody can read
* return SUCCESS ok: FAIL not ok
*/
anyread(file)
char *file;
{
struct stat s;
if (stat(subfile(file), &s) < 0)
/* for security check a non existant file is readable */
return SUCCESS;
if (!(s.st_mode & ANYREAD))
return FAIL;
return SUCCESS;
}

51
src/cmd/uucp/assert.c Normal file
View File

@@ -0,0 +1,51 @@
#ifndef lint
static char sccsid[] = "@(#)assert.c 5.5 (Berkeley) 6/19/85";
#endif
#include "uucp.h"
#include <sys/time.h>
#include <errno.h>
/*LINTLIBRARY*/
/*
* print out assetion error
*/
assert(s1, s2, i1)
char *s1, *s2;
{
register FILE *errlog;
register struct tm *tp;
extern struct tm *localtime();
time_t clock;
int pid;
errlog = NULL;
if (!Debug) {
int savemask;
savemask = umask(LOGMASK);
errlog = fopen(ERRLOG, "a");
umask(savemask);
}
if (errlog == NULL)
errlog = stderr;
pid = getpid();
fprintf(errlog, "ASSERT ERROR (%.9s) ", Progname);
fprintf(errlog, "pid: %d ", pid);
clock = time(NULL);
tp = localtime(&clock);
#ifdef USG
fprintf(errlog, "(%d/%d-%2.2d:%2.2d) ", tp->tm_mon + 1,
tp->tm_mday, tp->tm_hour, tp->tm_min);
#endif
#ifndef USG
fprintf(errlog, "(%d/%d-%02d:%02d) ", tp->tm_mon + 1,
tp->tm_mday, tp->tm_hour, tp->tm_min);
#endif
fprintf(errlog, "%s %s (%d)\n", s1 ? s1 : "", s2 ? s2 : "", i1);
if (errlog != stderr)
(void) fclose(errlog);
return;
}

61
src/cmd/uucp/cfgets.c Normal file
View File

@@ -0,0 +1,61 @@
#ifndef lint
static char sccsid[] = "@(#)cfgets.c 5.3 (Berkeley) 6/19/85";
#endif
/*
* get nonblank, non-comment, (possibly continued) line. Alan S. Watt
*/
#include <stdio.h>
#include <string.h>
#define COMMENT '#'
#define CONTINUE '\\'
#define EOLN '\n'
#define EOS '\0'
/*LINTLIBRARY*/
char *
cfgets(buf, siz, fil)
register char *buf;
int siz;
FILE *fil;
{
register char *s;
register i, c, len;
char *fgets();
for (i=0,s=buf; i = (fgets(s, siz-i, fil) != NULL); i = s - buf) {
/* get last character of line */
c = s[len = (strlen(s) - 1)];
/* skip comments; make sure end of comment line seen */
if (*s == COMMENT) {
while (c != EOLN && c != EOF)
c = getc(fil);
*s = EOS;
}
/* skip blank lines */
else if (*s != EOLN) {
s += len;
/* continue lines ending with CONTINUE */
if (c != EOLN || *--s != CONTINUE)
break;
}
}
return i ? buf : NULL;
}
#ifdef TEST
main()
{
char buf[512];
while (cfgets(buf, sizeof buf, stdin))
fputs(buf, stdout);
}
#endif

250
src/cmd/uucp/chkpth.c Normal file
View File

@@ -0,0 +1,250 @@
#if !defined(lint) && defined(DOSCCS)
static char sccsid[] = "@(#)chkpth.c 5.4.1 (2.11BSD) 1997/10/2";
#endif
#include "uucp.h"
#include <sys/stat.h>
#include <strings.h>
struct userpath {
char *us_lname;
char *us_mname;
char us_callback;
char **us_path;
struct userpath *unext;
};
struct userpath *Uhead = NULL;
struct userpath *Mchdef = NULL, *Logdef = NULL;
int Uptfirst = 1;
/*LINTLIBRARY*/
/*
* this routine will check the path table for the
* machine or log name (non-null parameter) to see if the
* input path (path) starts with an acceptable prefix.
*
* return codes: 0 | FAIL
*/
chkpth(logname, mchname, path)
char *path, *logname, *mchname;
{
register struct userpath *u;
extern char *lastpart();
register char **p, *s;
/* Allow only rooted pathnames. Security wish. rti!trt */
if (*path != '/') {
DEBUG(4, "filename doesn't begin with /\n", CNULL);
return FAIL;
}
if (Uptfirst) {
rdpth();
ASSERT(Uhead != NULL, "INIT USERFILE, No entrys!", CNULL, 0);
Uptfirst = 0;
}
for (u = Uhead; u != NULL; ) {
if (*logname != '\0' && strcmp(logname, u->us_lname) == SAME)
break;
if (*mchname != '\0' && strncmp(mchname, u->us_mname, MAXBASENAME) == SAME)
break;
u = u->unext;
}
if (u == NULL) {
if (*logname == '\0')
u = Mchdef;
else
u = Logdef;
if (u == NULL)
return FAIL;
}
/* check for /../ in path name */
for (s = path; *s != '\0'; s++) {
if (prefix("/../",s)) {
DEBUG(4, "filename has /../ in it\n", CNULL);
return FAIL;
}
}
/* Check for access permission */
for (p = u->us_path; *p != NULL; p++)
if (prefix(*p, path))
return SUCCESS;
DEBUG(4, "filename not in list\n", CNULL);
/* path name not valid */
return FAIL;
}
/***
* rdpth()
*
* rdpth - this routine will read the USERFILE and
* construct the userpath structure pointed to by (u);
*
*/
rdpth()
{
char buf[100 + 1], *pbuf[50 + 1];
register struct userpath *u;
register char *pc, **cp;
FILE *uf;
if ((uf = fopen(USERFILE, "r")) == NULL) {
/* can not open file */
return;
}
while (cfgets(buf, sizeof(buf), uf) != NULL) {
int nargs, i;
u = (struct userpath *)malloc(sizeof (struct userpath));
if (u == NULL) {
DEBUG (1, "*** Userpath malloc failed\n", 0);
fclose (uf);
return;
}
if ((pc = (char *)calloc((unsigned)strlen(buf) + 1, sizeof (char)))
== NULL) {
/* can not allocate space */
DEBUG (1, "Userpath calloc 1 failed\n", 0);
fclose(uf);
return;
}
strcpy(pc, buf);
nargs = getargs(pc, pbuf, 50);
u->us_lname = pbuf[0];
pc = index(u->us_lname, ',');
if (pc != NULL)
*pc++ = '\0';
else
pc = u->us_lname + strlen(u->us_lname);
u->us_mname = pc;
if (strlen(u->us_mname) > MAXBASENAME)
u->us_mname[MAXBASENAME] = '\0';
if (*u->us_lname == '\0' && Logdef == NULL)
Logdef = u;
if (*u->us_mname == '\0' && Mchdef == NULL)
Mchdef = u;
i = 1;
if (strcmp(pbuf[1], "c") == SAME) {
u->us_callback = 1;
i++;
}
else
u->us_callback = 0;
cp = (char **)calloc((unsigned)(nargs-i+1), sizeof(char *));
if (cp == NULL) {
/* can not allocate space */
DEBUG (1, "Userpath calloc 2 failed!\n", 0);
fclose(uf);
return;
}
u->us_path = cp;
while (i < nargs)
*cp++ = pbuf[i++];
*cp = NULL;
u->unext = Uhead;
Uhead = u;
}
fclose(uf);
return;
}
/***
* callback(name) check for callback
* char *name;
*
* return codes:
* 0 - no call back
* 1 - call back
*/
callback(name)
register char *name;
{
register struct userpath *u;
if (Uptfirst) {
rdpth();
ASSERT(Uhead != NULL, "INIT USERFILE, No Users!", CNULL, 0);
Uptfirst = 0;
}
for (u = Uhead; u != NULL; ) {
if (strcmp(u->us_lname, name) == SAME)
/* found user name */
return u->us_callback;
u = u->unext;
}
/* userid not found */
return 0;
}
/***
* chkperm(file, mopt) check write permission of file
* char *mopt; none NULL - create directories
*
* if mopt != NULL and permissions are ok,
* a side effect of this routine is to make
* directories up to the last part of the
* filename (if they do not exist).
*
* return SUCCESS | FAIL
*/
chkperm(file, mopt)
char *file, *mopt;
{
struct stat s;
int ret;
char dir[MAXFULLNAME];
extern char *lastpart();
if (stat(subfile(file), &s) == 0) {
if ((s.st_mode & ANYWRITE) == 0) {
DEBUG(4,"file is not writable: mode %o\n", s.st_mode);
return FAIL;
}
return SUCCESS;
}
strcpy(dir, file);
*lastpart(dir) = '\0';
if ((ret = stat(subfile(dir), &s)) == -1 && mopt == NULL) {
DEBUG(4, "can't stat directory %s\n", subfile(dir));
return FAIL;
}
if (ret != -1) {
if ((s.st_mode & ANYWRITE) == 0)
return FAIL;
else
return SUCCESS;
}
/* make directories */
return mkdirs(file);
}
/*
* Check for sufficient privilege to request debugging.
*/
chkdebug()
{
if (access(SYSFILE, 04) < 0) {
fprintf(stderr, "Sorry, you must be able to read L.sys for debugging\n");
cleanup(1);
exit(1); /* Just in case */
}
}

56
src/cmd/uucp/chksum.c Normal file
View File

@@ -0,0 +1,56 @@
#ifndef lint
static char sccsid[] = "@(#)chksum.c 4.2 (Berkeley) 6/19/85";
#endif
#ifndef pdp11
chksum (s, n)
register char *s;
register n;
{
register long sum, x, t;
sum = 0xffff;
x = 0;
do {
/* Rotate left, copying bit 15 to bit 0 */
sum <<= 1;
if (sum & 0x10000)
sum ^= 0x10001;
t = sum;
sum = (sum + (*s++ & 0377)) & 0xffff;
x += sum ^ n;
if (sum <= t)
sum = (sum ^ x) & 0xffff;
} while (--n > 0);
return (long) (short) sum;
}
#else
chksum(s,n)
register char *s;
register n;
{
register unsigned sum, t;
register x;
sum = -1;
x = 0;
do {
if (sum&0x8000) {
sum <<= 1;
sum++;
} else
sum <<= 1;
t = sum;
sum += (unsigned)*s++ & 0377;
x += sum^n;
if ((sum&0xffff) <= (t&0xffff)) {
sum ^= x;
}
} while (--n > 0);
return sum & 0xffff;
}
#endif

896
src/cmd/uucp/cico.c Normal file
View File

@@ -0,0 +1,896 @@
#if !defined(lint) && defined(DOSCCS)
static char sccsid[] = "@(#)cico.c 5.14.1 (2.11BSD) 1997/10/2";
#endif
#include <signal.h>
#include "uucp.h"
#include <setjmp.h>
#ifdef USG
#include <termio.h>
#endif
#ifndef USG
#include <sgtty.h>
#endif
#ifdef BSDTCP
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#endif
#include <sys/stat.h>
#include "uust.h"
#include "uusub.h"
#if defined(VMS) && defined(BSDTCP)
#define NOGETPEER
#endif
#ifdef BSD2_9
#define NOGETPEER
#endif
jmp_buf Sjbuf;
jmp_buf Pipebuf;
/* call fail text */
char *Stattext[] = {
"",
"BAD SYSTEM",
"WRONG TIME TO CALL",
"SYSTEM LOCKED",
"NO DEVICE",
"CALL FAILED",
"LOGIN FAILED",
"BAD SEQUENCE"
};
/* call fail codes */
int Stattype[] = {
0,
0,
SS_WRONGTIME,
0,
SS_NODEVICE,
SS_FAIL,
SS_FAIL,
SS_BADSEQ
};
/* Arguments to setdebug(): */
#define DBG_TEMP 0 /* Create a temporary audit file */
#define DBG_PERM 1 /* Create a permanent audit file */
#define DBG_CLEAN 2 /* Cleanup, discard temp file */
int ReverseRole = 0;
int Role = SLAVE;
int onesys = 0;
int turntime = 30 * 60; /* 30 minutes expressed in seconds */
char *ttyn = NULL;
extern int LocalOnly;
extern int errno;
extern char MaxGrade, DefMaxGrade;
extern char Myfullname[];
#ifdef USG
struct termio Savettyb;
#endif
#ifndef USG
struct sgttyb Savettyb;
#endif
/*
* this program is used to place a call to a
* remote machine, login, and copy files between the two machines.
*/
main(argc, argv)
int argc;
register char *argv[];
{
register int ret;
int seq;
char wkpre[NAMESIZE], file[NAMESIZE];
char msg[MAXFULLNAME], *q;
register char *p;
extern onintr(), timeout(), dbg_signal();
extern char *pskip();
char rflags[MAXFULLNAME];
#ifdef NOGETPEER
u_long Hostnumber = 0;
#endif
strcpy(Progname, "uucico");
#ifdef BSD4_2
sigsetmask(0L); /* in case we inherit blocked signals */
#endif
signal(SIGINT, (sig_t)onintr);
signal(SIGHUP, (sig_t)onintr);
signal(SIGQUIT, (sig_t)onintr);
signal(SIGTERM, (sig_t)onintr);
signal(SIGPIPE, (sig_t)onintr); /* 4.1a tcp-ip stupidity */
signal(SIGFPE, (sig_t)dbg_signal);
ret = guinfo(getuid(), User, msg);
strcpy(Loginuser, User);
uucpname(Myname);
ASSERT(ret == 0, "BAD UID", CNULL, ret);
setbuf (stderr, CNULL);
rflags[0] = '\0';
umask(WFMASK);
strcpy(Rmtname, Myname);
Ifn = Ofn = -1;
while(argc>1 && argv[1][0] == '-'){
switch(argv[1][1]){
case 'd':
Spool = &argv[1][2];
break;
case 'g':
case 'p':
MaxGrade = DefMaxGrade = argv[1][2];
break;
case 'r':
Role = atoi(&argv[1][2]);
break;
case 'R':
ReverseRole++;
Role = MASTER;
break;
case 's':
strncpy(Rmtname, &argv[1][2], MAXBASENAME);
Rmtname[MAXBASENAME] = '\0';
if (Rmtname[0] != '\0')
onesys = 1;
break;
case 'x':
Debug = atoi(&argv[1][2]);
if (Debug <= 0)
Debug = 1;
strcat(rflags, argv[1]);
break;
case 't':
turntime = atoi(&argv[1][2])*60;/* minutes to seconds */
break;
case 'L': /* local calls only */
LocalOnly++;
break;
#ifdef NOGETPEER
case 'h':
Hostnumber = inet_addr(&argv[1][2]);
break;
#endif
default:
printf("unknown flag %s (ignored)\n", argv[1]);
break;
}
--argc; argv++;
}
while (argc > 1) {
fprintf(stderr, "unknown argument %s (ignored)\n", argv[1]);
--argc; argv++;
}
if (Debug && Role == MASTER)
chkdebug();
/* Try to run as uucp */
setgid(getegid());
setuid(geteuid());
#ifdef TIOCNOTTY
/*
* detach uucico from controlling terminal
* to defend against rlogind sending us a SIGKILL (!!!)
*/
if (Role == MASTER && (ret = open("/dev/tty", 2)) >= 0) {
ioctl(ret, TIOCNOTTY, STBNULL);
close(ret);
}
#endif
#ifdef BSD4_2
if (getpgrp(0) == 0) { /* We have no controlling terminal */
setpgrp(0, getpid());
}
#endif
ret = subchdir(Spool);
ASSERT(ret >= 0, "CHDIR FAILED", Spool, ret);
strcpy(Wrkdir, Spool);
if (Debug) {
setdebug ((Role == SLAVE) ? DBG_TEMP : DBG_PERM);
if (Debug > 0)
logent ("Local Enabled", "DEBUG");
}
/*
* First time through: If we're the slave, do initial checking.
*/
if (Role == SLAVE) {
/* check for /etc/nologin */
if (access(NOLOGIN, 0) == 0) {
logent(NOLOGIN, "UUCICO SHUTDOWN");
if (Debug > 4)
logent("DEBUGGING", "continuing anyway");
else
cleanup(1);
}
Ifn = 0;
Ofn = 1;
#ifdef TCPIP
/*
* Determine if we are on TCPIP
*/
if (isatty(Ifn) < 0) {
IsTcpIp = 1;
DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL);
} else
IsTcpIp = 0;
#endif
/* initial handshake */
onesys = 1;
if (!IsTcpIp) {
#ifdef USG
ret = ioctl(Ifn, TCGETA, &Savettyb);
Savettyb.c_cflag = (Savettyb.c_cflag & ~CS8) | CS7;
Savettyb.c_oflag |= OPOST;
Savettyb.c_lflag |= (ISIG|ICANON|ECHO);
#else
ret = ioctl(Ifn, TIOCGETP, &Savettyb);
Savettyb.sg_flags |= ECHO;
Savettyb.sg_flags &= ~RAW;
#endif
ttyn = ttyname(Ifn);
}
fixmode(Ifn);
/*
* Initial Message -- tell them we're here, and who we are.
*/
sprintf(msg, "here=%s", Myfullname);
omsg('S', msg, Ofn);
signal(SIGALRM, (sig_t)timeout);
alarm(MAXMSGTIME);
if (setjmp(Sjbuf)) {
/* timed out */
if (!IsTcpIp) {
#ifdef USG
ret = ioctl(Ifn, TCSETA, &Savettyb);
#else
ret = ioctl(Ifn, TIOCSETP, &Savettyb);
#endif
}
cleanup(0);
}
for (;;) {
ret = imsg(msg, Ifn);
if (ret != SUCCESS) {
alarm(0);
if (!IsTcpIp) {
#ifdef USG
ret = ioctl(Ifn, TCSETA, &Savettyb);
#else
ret = ioctl(Ifn, TIOCSETP, &Savettyb);
#endif
}
cleanup(0);
}
if (msg[0] == 'S')
break;
}
alarm(0);
q = &msg[1];
p = pskip(q);
strncpy(Rmtname, q, MAXBASENAME);
Rmtname[MAXBASENAME] = '\0';
/*
* Now that we know who they are, give the audit file the right
* name.
*/
setdebug (DBG_PERM);
DEBUG(4, "sys-%s\n", Rmtname);
/* The versys will also do an alias on the incoming name */
if (versys(&Rmtname)) {
/* If we don't know them, we won't talk to them... */
#ifdef NOSTRANGERS
logent(Rmtname, "UNKNOWN HOST");
omsg('R', "You are unknown to me", Ofn);
cleanup(0);
#endif
}
#ifdef BSDTCP
/* we must make sure they are really who they say they
* are. We compare the hostnumber with the number in the hosts
* table for the site they claim to be.
*/
if (IsTcpIp) {
struct hostent *hp;
char *cpnt, *inet_ntoa();
int fromlen;
struct sockaddr_in from;
extern char PhoneNumber[];
#ifdef NOGETPEER
from.sin_addr.s_addr = Hostnumber;
from.sin_family = AF_INET;
#else
fromlen = sizeof(from);
if (getpeername(Ifn, &from, &fromlen) < 0) {
logent(Rmtname, "NOT A TCP CONNECTION");
omsg('R', "NOT TCP", Ofn);
cleanup(0);
}
#endif
hp = gethostbyaddr(&from.sin_addr,
sizeof (struct in_addr), from.sin_family);
if (hp == NULL) {
/* security break or just old host table? */
logent(Rmtname, "UNKNOWN IP-HOST Name =");
cpnt = inet_ntoa(from.sin_addr),
logent(cpnt, "UNKNOWN IP-HOST Number =");
sprintf(wkpre, "%s/%s isn't in my host table",
Rmtname, cpnt);
omsg('R' ,wkpre ,Ofn);
cleanup(0);
}
if (Debug > 99)
logent(Rmtname,"Request from IP-Host name =");
/*
* The following is to determine if the name given us by
* the Remote uucico matches any of the names
* given its network number (remote machine) in our
* host table.
* We could check the aliases, but that won't work in
* all cases (like if you are running the domain
* server, where you don't get any aliases). The only
* reliable way I can think of that works in ALL cases
* is too look up the site in L.sys and see if the
* sitename matches what we would call him if we
* originated the call.
*/
/* PhoneNumber contains the official network name of the host we are checking. (set in versys.c) */
if (sncncmp(PhoneNumber, hp->h_name, SYSNSIZE) == 0) {
if (Debug > 99)
logent(q,"Found in host Tables");
} else {
logent(hp->h_name, "FORGED HOSTNAME");
logent(inet_ntoa(from.sin_addr), "ORIGINATED AT");
logent(PhoneNumber, "SHOULD BE");
sprintf(wkpre, "You're not who you claim to be: %s != %s", hp->h_name, PhoneNumber);
omsg('R', wkpre, Ofn);
cleanup(0);
}
}
#endif
if (mlock(Rmtname)) {
omsg('R', "LCK", Ofn);
cleanup(0);
}
else if (callback(Loginuser)) {
signal(SIGINT, SIG_IGN);
signal(SIGHUP, SIG_IGN);
omsg('R', "CB", Ofn);
logent("CALLBACK", "REQUIRED");
/* set up for call back */
systat(Rmtname, SS_CALLBACK, "CALLING BACK");
gename(CMDPRE, Rmtname, 'C', file);
close(creat(subfile(file), 0666));
xuucico(Rmtname);
cleanup(0);
}
seq = 0;
while (*p == '-') {
q = pskip(p);
switch(*(++p)) {
case 'x':
if (Debug == 0) {
Debug = atoi(++p);
if (Debug <= 0)
Debug = 1;
setdebug(DBG_PERM);
if (Debug > 0)
logent("Remote Enabled", "DEBUG");
} else {
DEBUG(1, "Remote debug request ignored\n",
CNULL);
}
break;
case 'Q':
seq = atoi(++p);
break;
case 'p':
MaxGrade = DefMaxGrade = *++p;
DEBUG(4, "MaxGrade set to %c\n", MaxGrade);
break;
case 'v':
if (strncmp(p, "grade", 5) == 0) {
p += 6;
MaxGrade = DefMaxGrade = *p++;
DEBUG(4, "MaxGrade set to %c\n", MaxGrade);
}
break;
default:
break;
}
p = q;
}
if (callok(Rmtname) == SS_BADSEQ) {
logent("BADSEQ", "PREVIOUS");
omsg('R', "BADSEQ", Ofn);
cleanup(0);
}
#ifdef GNXSEQ
if ((ret = gnxseq(Rmtname)) == seq) {
omsg('R', "OK", Ofn);
cmtseq();
} else {
#else
if (seq == 0)
omsg('R', "OK", Ofn);
else {
#endif
systat(Rmtname, Stattype[7], Stattext[7]);
logent("BAD SEQ", "FAILED HANDSHAKE");
#ifdef GNXSEQ
ulkseq();
#endif
omsg('R', "BADSEQ", Ofn);
cleanup(0);
}
if (ttyn != NULL)
chmod(ttyn, 0600);
}
loop:
if(setjmp(Pipebuf)) { /* come here on SIGPIPE */
clsacu();
close(Ofn);
close(Ifn);
Ifn = Ofn = -1;
rmlock(CNULL);
sleep(3);
}
if (!onesys) {
ret = gnsys(Rmtname, Spool, CMDPRE);
setdebug(DBG_PERM);
if (ret == FAIL)
cleanup(100);
if (ret == SUCCESS)
cleanup(0);
} else if (Role == MASTER && callok(Rmtname) != 0) {
logent("SYSTEM STATUS", "CAN NOT CALL");
cleanup(0);
}
sprintf(wkpre, "%c.%.*s", CMDPRE, SYSNSIZE, Rmtname);
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
if (Role == MASTER) {
/* check for /etc/nologin */
if (access(NOLOGIN, 0) == 0) {
logent(NOLOGIN, "UUCICO SHUTDOWN");
if (Debug > 4)
logent("DEBUGGING", "continuing anyway");
else
cleanup(1);
}
/* master part */
signal(SIGHUP, SIG_IGN);
if (Ifn != -1 && Role == MASTER) {
write(Ofn, EOTMSG, strlen(EOTMSG));
clsacu();
close(Ofn);
close(Ifn);
Ifn = Ofn = -1;
rmlock(CNULL);
sleep(3);
}
sprintf(msg, "call to %s ", Rmtname);
if (mlock(Rmtname) != SUCCESS) {
logent(msg, "LOCKED");
US_SST(us_s_lock);
goto next;
}
Ofn = Ifn = conn(Rmtname);
if (Ofn < 0) {
if (Ofn != CF_TIME)
logent(msg, _FAILED);
/* avoid excessive 'wrong time' info */
if (Stattype[-Ofn] != SS_WRONGTIME){
systat(Rmtname, Stattype[-Ofn], Stattext[-Ofn]);
US_SST(-Ofn);
UB_SST(-Ofn);
}
goto next;
} else {
logent(msg, "SUCCEEDED");
US_SST(us_s_cok);
UB_SST(ub_ok);
}
#ifdef TCPIP
/*
* Determine if we are on TCPIP
*/
if (isatty(Ifn) == 0) {
IsTcpIp = 1;
DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL);
} else
IsTcpIp = 0;
#endif
if (setjmp(Sjbuf))
goto next;
signal(SIGALRM, (sig_t)timeout);
alarm(2 * MAXMSGTIME);
for (;;) {
ret = imsg(msg, Ifn);
if (ret != 0) {
alarm(0);
logent("imsg 1", _FAILED);
goto Failure;
}
if (msg[0] == 'S')
break;
}
alarm(MAXMSGTIME);
#ifdef GNXSEQ
seq = gnxseq(Rmtname);
#else
seq = 0;
#endif
if (MaxGrade != '\177') {
DEBUG(2, "Max Grade this transfer is %c\n", MaxGrade);
sprintf(msg, "%s -Q%d -p%c -vgrade=%c %s",
Myname, seq, MaxGrade, MaxGrade, rflags);
} else
sprintf(msg, "%s -Q%d %s", Myname, seq, rflags);
omsg('S', msg, Ofn);
for (;;) {
ret = imsg(msg, Ifn);
DEBUG(4, "msg-%s\n", msg);
if (ret != SUCCESS) {
alarm(0);
#ifdef GNXSEQ
ulkseq();
#endif
logent("imsg 2", _FAILED);
goto Failure;
}
if (msg[0] == 'R')
break;
}
alarm(0);
if (msg[1] == 'B') {
/* bad sequence */
logent("BAD SEQ", "FAILED HANDSHAKE");
US_SST(us_s_hand);
systat(Rmtname, SS_BADSEQ, Stattext[SS_BADSEQ]);
#ifdef GNXSEQ
ulkseq();
#endif
goto next;
}
if (strcmp(&msg[1], "OK") != SAME) {
logent(&msg[1], "FAILED HANDSHAKE");
US_SST(us_s_hand);
#ifdef GNXSEQ
ulkseq();
#endif
systat(Rmtname, SS_INPROGRESS,
strcmp(&msg[1], "CB") == SAME?
"AWAITING CALLBACK": "FAILED HANDSHAKE");
goto next;
}
#ifdef GNXSEQ
cmtseq();
#endif
}
DEBUG(1, "Rmtname %s, ", Rmtname);
DEBUG(1, "Role %s, ", Role ? "MASTER" : "SLAVE");
DEBUG(1, "Ifn - %d, ", Ifn);
DEBUG(1, "Loginuser - %s\n", Loginuser);
ttyn = ttyname(Ifn);
alarm(MAXMSGTIME);
if (ret=setjmp(Sjbuf))
goto Failure;
ret = startup(Role);
alarm(0);
if (ret != SUCCESS) {
logent("startup", _FAILED);
Failure:
US_SST(us_s_start);
systat(Rmtname, SS_FAIL, ret > 0 ? "CONVERSATION FAILED" :
"STARTUP FAILED");
goto next;
} else {
if (ttyn != NULL) {
char startupmsg[BUFSIZ];
extern int linebaudrate;
sprintf(startupmsg, "startup %s %d baud", &ttyn[5],
linebaudrate);
logent(startupmsg, "OK");
} else
logent("startup", "OK");
US_SST(us_s_gress);
systat(Rmtname, SS_INPROGRESS, "TALKING");
ret = cntrl(Role, wkpre);
DEBUG(1, "cntrl - %d\n", ret);
signal(SIGINT, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGALRM, (sig_t)timeout);
if (ret == SUCCESS) {
logent("conversation complete", "OK");
US_SST(us_s_ok);
rmstat(Rmtname);
} else {
logent("conversation complete", _FAILED);
US_SST(us_s_cf);
systat(Rmtname, SS_FAIL, "CONVERSATION FAILED");
}
alarm(MAXMSGTIME);
DEBUG(4, "send OO %d,", ret);
if (!setjmp(Sjbuf)) {
for (;;) {
omsg('O', "OOOOO", Ofn);
ret = imsg(msg, Ifn);
if (ret != 0)
break;
if (msg[0] == 'O')
break;
}
}
alarm(0);
clsacu();
rmlock(CNULL);
}
next:
if (!onesys) {
goto loop;
}
cleanup(0);
}
#ifndef USG
struct sgttyb Hupvec;
#endif
/*
* cleanup and exit with "code" status
*/
cleanup(code)
register int code;
{
signal(SIGINT, SIG_IGN);
signal(SIGHUP, SIG_IGN);
rmlock(CNULL);
sleep(5); /* Wait for any pending output */
clsacu();
logcls();
if (Role == SLAVE) {
if (!IsTcpIp) {
#ifdef USG
Savettyb.c_cflag |= HUPCL;
(void) ioctl(0, TCSETA, &Savettyb);
#else
(void) ioctl(0, TIOCHPCL, STBNULL);
#ifdef TIOCSDTR
(void) ioctl(0, TIOCCDTR, STBNULL);
sleep(2);
(void) ioctl(0, TIOCSDTR, STBNULL);
#else
(void) ioctl(0, TIOCGETP, &Hupvec);
Hupvec.sg_ispeed = B0;
Hupvec.sg_ospeed = B0;
(void) ioctl(0, TIOCSETP, &Hupvec);
#endif
sleep(2);
(void) ioctl(0, TIOCSETP, &Savettyb);
/* make *sure* exclusive access is off */
(void) ioctl(0, TIOCNXCL, STBNULL);
#endif
}
if (ttyn != NULL)
chmod(ttyn, 0600);
}
if (Ofn != -1) {
if (Role == MASTER)
write(Ofn, EOTMSG, strlen(EOTMSG));
close(Ifn);
close(Ofn);
}
#ifdef DIALINOUT
/* reenable logins on dialout */
reenable();
#endif
if (code == 0)
xuuxqt();
else
DEBUG(1, "exit code %d\n", code);
setdebug (DBG_CLEAN);
exit(code);
}
/*
* on interrupt - remove locks and exit
*/
onintr(inter)
register int inter;
{
char str[30];
signal(inter, SIG_IGN);
sprintf(str, "SIGNAL %d", inter);
logent(str, "CAUGHT");
US_SST(us_s_intr);
if (*Rmtname && strncmp(Rmtname, Myname, MAXBASENAME))
systat(Rmtname, SS_FAIL, str);
if (inter == SIGPIPE && !onesys)
longjmp(Pipebuf, 1);
cleanup(inter);
}
/*
* Catch a special signal
* (SIGFPE, ugh), and toggle debugging between 0 and 30.
* Handy for looking in on long running uucicos.
*/
dbg_signal()
{
Debug = (Debug == 0) ? 30 : 0;
setdebug(DBG_PERM);
if (Debug > 0)
logent("Signal Enabled", "DEBUG");
}
/*
* Check debugging requests, and open RMTDEBUG audit file if necessary. If an
* audit file is needed, the parm argument indicates how to create the file:
*
* DBG_TEMP - Open a temporary file, with filename = RMTDEBUG/pid.
* DBG_PERM - Open a permanent audit file, filename = RMTDEBUG/Rmtname.
* If a temp file already exists, it is mv'ed to be permanent.
* DBG_CLEAN - Cleanup; unlink temp files.
*
* Restrictions - this code can only cope with one open debug file at a time.
* Each call creates a new file; if an old one of the same name exists it will
* be overwritten.
*/
setdebug(parm)
int parm;
{
char buf[BUFSIZ]; /* Buffer for building filenames */
static char *temp = NULL; /* Ptr to temporary file name */
static int auditopen = 0; /* Set to 1 when we open a file */
struct stat stbuf; /* File status buffer */
/*
* If movement or cleanup of a temp file is indicated, we do it no
* matter what.
*/
if (temp != CNULL && parm == DBG_PERM) {
sprintf(buf, "%s/%s", RMTDEBUG, Rmtname);
unlink(buf);
if (link(temp, buf) != 0) {
Debug = 0;
assert("RMTDEBUG LINK FAIL", temp, errno);
cleanup(1);
}
parm = DBG_CLEAN;
}
if (parm == DBG_CLEAN) {
if (temp != CNULL) {
unlink(temp);
free(temp);
temp = CNULL;
}
return;
}
if (Debug == 0)
return; /* Gotta be in debug to come here. */
/*
* If we haven't opened a file already, we can just return if it's
* alright to use the stderr we came in with. We can if:
*
* Role == MASTER, and Stderr is a regular file, a TTY or a pipe.
*
* Caution: Detecting when stderr is a pipe is tricky, because the 4.2
* man page for fstat(2) disagrees with reality, and System V leaves it
* undefined, which means different implementations act differently.
*/
if (!auditopen && Role == MASTER) {
if (isatty(fileno(stderr)))
return;
else if (fstat(fileno(stderr), &stbuf) == 0) {
#ifdef USG
/* Is Regular File or Fifo */
if ((stbuf.st_mode & 0060000) == 0)
return;
#else
#ifdef BSD4_2
/* Is Regular File */
if ((stbuf.st_mode & S_IFMT) == S_IFREG ||
stbuf.st_mode == 0) /* Is a pipe */
return;
#else
/* Is Regular File or Pipe */
if ((stbuf.st_mode & S_IFMT) == S_IFREG)
return;
#endif
#endif
}
}
/*
* We need RMTDEBUG directory to do auditing. If the file doesn't exist,
* then we forget about debugging; if it exists but has improper owner-
* ship or modes, we gripe about it in ERRLOG.
*/
if (stat(RMTDEBUG, &stbuf) != SUCCESS) {
Debug = 0;
return;
}
if ((geteuid() != stbuf.st_uid) || /* We must own it */
((stbuf.st_mode & 0170700) != 040700)) { /* Directory, rwx */
Debug = 0;
assert("INVALID RMTDEBUG DIRECTORY:", RMTDEBUG, stbuf.st_mode);
return;
}
if (parm == DBG_TEMP) {
sprintf(buf, "%s/%d", RMTDEBUG, getpid());
temp = (char *)malloc(strlen (buf) + 1);
if (temp == CNULL) {
Debug = 0;
assert("RMTDEBUG MALLOC ERROR:", temp, errno);
cleanup(1);
}
strcpy(temp, buf);
} else
sprintf(buf, "%s/%s", RMTDEBUG, Rmtname);
unlink(buf);
if (freopen(buf, "w", stderr) != stderr) {
Debug = 0;
assert("FAILED RMTDEBUG FILE OPEN:", buf, errno);
cleanup(1);
}
setbuf(stderr, CNULL);
auditopen = 1;
}
/*
* catch SIGALRM routine
*/
timeout()
{
extern int HaveSentHup;
if (!HaveSentHup) {
logent(Rmtname, "TIMEOUT");
if (*Rmtname && strncmp(Rmtname, Myname, MAXBASENAME)) {
US_SST(us_s_tmot);
systat(Rmtname, SS_FAIL, "TIMEOUT");
}
}
longjmp(Sjbuf, 1);
}
char *
pskip(p)
register char *p;
{
while(*p && *p != ' ')
++p;
while(*p && *p == ' ')
*p++ = 0;
return p;
}

942
src/cmd/uucp/cntrl.c Normal file
View File

@@ -0,0 +1,942 @@
#ifndef lint
static char sccsid[] = "@(#)cntrl.c 5.8 (Berkeley) 1/24/86";
#endif
#include "uucp.h"
#include <sys/stat.h>
#include <strings.h>
#include "uust.h"
extern int errno;
extern int turntime;
int willturn;
int HaveSentHup = 0;
struct Proto {
char P_id;
int (*P_turnon)();
int (*P_rdmsg)();
int (*P_wrmsg)();
int (*P_rddata)();
int (*P_wrdata)();
int (*P_turnoff)();
};
extern int gturnon(), gturnoff();
extern int grdmsg(), grddata();
extern int gwrmsg(), gwrdata();
extern int imsg(), omsg(), nullf();
#ifdef TCPIP
extern int twrmsg(), trdmsg();
extern int twrdata(), trddata();
#endif
#ifdef PAD
extern int fturnon(), fturnoff();
extern int frdmsg(), frddata();
extern int fwrmsg(), fwrdata();
#endif
struct Proto Ptbl[]={
#ifdef TCPIP
't', nullf, trdmsg, twrmsg, trddata, twrdata, nullf,
#endif
#ifdef PAD
'f', fturnon, frdmsg, fwrmsg, frddata, fwrdata, fturnoff,
#endif
'g', gturnon, grdmsg, gwrmsg, grddata, gwrdata, gturnoff,
'\0'
};
int (*Imsg)() = imsg, (*Omsg)() = omsg;
int (*Rdmsg)()=imsg, (*Rddata)();
int (*Wrmsg)()=omsg, (*Wrdata)();
int (*Turnon)()=nullf, (*Turnoff)() = nullf;
struct timeb Now, LastTurned, LastCheckedNoLogin;
static char *YES = "Y";
static char *NO = "N";
int TransferSucceeded = 1;
/* failure messages */
#define EM_MAX 6
#define EM_LOCACC "N1" /* local access to file denied */
#define EM_RMTACC "N2" /* remote access to file/path denied */
#define EM_BADUUCP "N3" /* a bad uucp command was generated */
#define EM_NOTMP "N4" /* remote error - can't create temp */
#define EM_RMTCP "N5" /* can't copy to remote directory - file in public */
#define EM_LOCCP "N6" /* can't copy on local system */
char *Em_msg[] = {
"COPY FAILED (reason not given by remote)",
"local access to file denied",
"remote access to path/file denied",
"system error - bad uucp command generated",
"remote system can't create temp file",
"can't copy to file/directory - file left in PUBDIR/user/file",
"can't copy to file/directory on local system - file left in PUBDIR/user/file"
};
#define XUUCP 'X' /* execute uucp (string) */
#define SLTPTCL 'P' /* select protocol (string) */
#define USEPTCL 'U' /* use protocol (character) */
#define RCVFILE 'R' /* receive file (string) */
#define SNDFILE 'S' /* send file (string) */
#define RQSTCMPT 'C' /* request complete (string - yes | no) */
#define HUP 'H' /* ready to hangup (string - yes | no) */
#define RESET 'X' /* reset line modes */
#define W_TYPE wrkvec[0]
#define W_FILE1 wrkvec[1]
#define W_FILE2 wrkvec[2]
#define W_USER wrkvec[3]
#define W_OPTNS wrkvec[4]
#define W_DFILE wrkvec[5]
#define W_MODE wrkvec[6]
#define W_NUSER wrkvec[7]
#define XFRRATE 35000L
#define RMESG(m, s, n) if (rmesg(m, s, n) != 0) {(*Turnoff)(); return FAIL;} else
#define RAMESG(s, n) if (rmesg('\0', s, n) != 0) {(*Turnoff)(); return FAIL;} else
#define WMESG(m, s) if(wmesg(m, s) != 0) {(*Turnoff)(); return FAIL;} else
char Wfile[MAXFULLNAME] = {'\0'};
char Dfile[MAXFULLNAME];
/*
* To avoid a huge backlog of X. files, start uuxqt every so often.
*/
static int nXfiles = 0; /* number of X files since last uuxqt start */
static char send_or_receive;
struct stat stbuf;
/*
* cntrl - this routine will execute the conversation
* between the two machines after both programs are
* running.
*
* return codes
* SUCCESS - ok
* FAIL - failed
*/
cntrl(role, wkpre)
int role;
char *wkpre;
{
char msg[BUFSIZ], rqstr[BUFSIZ];
register FILE *fp;
int filemode;
char filename[MAXFULLNAME], wrktype, *wrkvec[20];
extern (*Rdmsg)(), (*Wrmsg)();
extern char *index(), *lastpart();
int status = 1;
register int i, narg;
int mailopt, ntfyopt;
int ret;
static int pnum, tmpnum = 0;
extern int ReverseRole;
pnum = getpid();
Wfile[0] = '\0';
willturn = turntime > 0;
remaster:
#ifdef USG
time(&LastTurned.time);
LastTurned.millitm = 0;
#else
ftime(&LastTurned);
#endif
send_or_receive = RESET;
HaveSentHup = 0;
top:
for (i = 0; i < sizeof wrkvec / sizeof wrkvec[0]; i++)
wrkvec[i] = 0;
DEBUG(4, "*** TOP *** - role=%s\n", role ? "MASTER" : "SLAVE");
setupline(RESET);
if (Now.time > (LastCheckedNoLogin.time+60)) {
LastCheckedNoLogin = Now;
if (access(NOLOGIN, 0) == 0) {
logent(NOLOGIN, "UUCICO SHUTDOWN");
if (Debug > 4)
logent("DEBUGGING", "continuing anyway");
else {
WMESG(HUP, YES);
RMESG(HUP, msg, 1);
goto process;
}
}
}
if (role == MASTER) {
/* get work */
if (ReverseRole || (narg = gtwvec(Wfile, Spool, wkpre, wrkvec)) == 0) {
ReverseRole = 0;
WMESG(HUP, "");
RMESG(HUP, msg, 1);
goto process;
}
wrktype = W_TYPE[0];
msg[0] = '\0';
for (i = 1; i < narg; i++) {
strcat(msg, " ");
strcat(msg, wrkvec[i]);
}
if (wrktype == XUUCP) {
sprintf(rqstr, "X %s", msg);
logent(rqstr, "REQUEST");
goto sendmsg;
}
mailopt = index(W_OPTNS, 'm') != NULL;
ntfyopt = index(W_OPTNS, 'n') != NULL;
if (narg < 5) {
char *bnp;
bnp = rindex(Wfile, '/');
sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : Wfile);
xmv(Wfile, rqstr);
logent(Wfile, "CMD FILE CORRUPTED");
Wfile[0] = '\0';
goto top;
}
sprintf(User, "%.9s", W_USER);
sprintf(rqstr, "%s %s %s %s", W_TYPE, W_FILE1,
W_FILE2, W_USER);
logent(rqstr, "REQUEST");
if (wrktype == SNDFILE ) {
strcpy(filename, W_FILE1);
i = expfile(filename);
DEBUG(4, "expfile type - %d, ", i);
if (i != 0 && chkpth(User, "", filename))
goto e_access;
strcpy(Dfile, W_DFILE);
fp = NULL;
if (index(W_OPTNS, 'c') == NULL) {
fp = fopen(subfile(Dfile), "r");
if (fp != NULL)
i = 0;
}
if (fp == NULL &&
(fp = fopen(subfile(filename), "r")) == NULL) {
/* can not read data file */
logent("CAN'T READ DATA", _FAILED);
TransferSucceeded = 1; /* else will keep sending */
USRF(USR_LOCACC);
unlinkdf(Dfile);
lnotify(User, filename, "can't access");
goto top;
}
/* if file exists but is not generally readable... */
if (i != 0 && fstat(fileno(fp), &stbuf) == 0
&& (stbuf.st_mode & ANYREAD) == 0) {
e_access:;
/* access denied */
fclose(fp);
fp = NULL;
TransferSucceeded = 1; /* else will keep sending */
logent("DENIED", "ACCESS");
USRF(USR_LOCACC);
unlinkdf(W_DFILE);
lnotify(User, filename, "access denied");
goto top;
}
setupline(SNDFILE);
}
if (wrktype == RCVFILE) {
strcpy(filename, W_FILE2);
expfile(filename);
if (chkpth(User, "", filename)
|| chkperm(filename, index(W_OPTNS, 'd'))) {
/* access denied */
logent("DENIED", "ACCESS");
TransferSucceeded = 1; /* else will keep trying */
USRF(USR_LOCACC);
lnotify(User, filename, "access denied");
goto top;
}
sprintf(Dfile, "%s/TM.%05d.%03d", Spool, pnum, tmpnum++);
if ((fp = fopen(subfile(Dfile), "w")) == NULL) {
/* can not create temp */
logent("CAN'T CREATE TM", _FAILED);
USRF(USR_LNOTMP);
unlinkdf(Dfile);
goto top;
}
setupline(RCVFILE);
}
sendmsg:
DEBUG(4, "wrktype - %c\n", wrktype);
WMESG(wrktype, msg);
RMESG(wrktype, msg, 1);
goto process;
}
/* role is slave */
RAMESG(msg, 1);
if (willturn < 0)
willturn = msg[0] == HUP;
process:
DEBUG(4, "PROCESS: msg - %s\n", msg);
switch (msg[0]) {
case RQSTCMPT:
DEBUG(4, "RQSTCMPT:\n", CNULL);
if (msg[1] == 'N') {
i = atoi(&msg[2]);
if (i<0 || i>EM_MAX)
i = 0;
USRF( 1 << i );
logent(Em_msg[i], "REQUEST FAILED");
TransferSucceeded = 1; /* He had his chance */
}
if (msg[1] == 'Y') {
USRF(USR_COK);
TransferSucceeded = 1;
}
if (role == MASTER) {
notify(mailopt, W_USER, W_FILE1, Rmtname, &msg[1]);
}
if (msg[2] == 'M') {
extern int Nfiles;
WMESG(HUP, "");
RMESG(HUP, msg, 1);
logent(Rmtname, "TURNAROUND");
#ifdef USG
time(&LastTurned.time);
LastTurned.millitm = 0;
#else
ftime(&LastTurned);
#endif
Nfiles = 0; /* force rescan of queue for work */
goto process;
}
goto top;
case HUP:
DEBUG(4, "HUP:\n", CNULL);
HaveSentHup = 1;
if (msg[1] == 'Y') {
if (role == MASTER)
WMESG(HUP, YES);
(*Turnoff)();
Rdmsg = Imsg;
Wrmsg = Omsg;
return SUCCESS;
}
if (msg[1] == 'N') {
ASSERT(role == MASTER, "WRONG ROLE - HUP", CNULL, role);
role = SLAVE;
goto remaster;
}
/* get work */
if (!iswrk(Wfile, "chk", Spool, wkpre)) {
WMESG(HUP, YES);
RMESG(HUP, msg, 1);
goto process;
}
WMESG(HUP, NO);
role = MASTER;
goto remaster;
case XUUCP:
if (role == MASTER) {
goto top;
}
/* slave part */
i = getargs(msg, wrkvec, 20);
strcpy(filename, W_FILE1);
if (index(filename, ';') != NULL || index(W_FILE2, ';') != NULL
|| i < 3) {
WMESG(XUUCP, NO);
goto top;
}
expfile(filename);
if (chkpth("", Rmtname, filename)) {
WMESG(XUUCP, NO);
logent("XUUCP DENIED", filename);
USRF(USR_XUUCP);
goto top;
}
sprintf(rqstr, "%s %s", filename, W_FILE2);
xuucp(rqstr);
WMESG(XUUCP, YES);
goto top;
case SNDFILE:
/* MASTER section of SNDFILE */
DEBUG(4, "%s\n", "SNDFILE:");
if (msg[1] == 'N') {
i = atoi(&msg[2]);
if (i < 0 || i > EM_MAX)
i = 0;
logent(Em_msg[i], "REQUEST FAILED");
USRF( 1 << i );
fclose(fp);
fp = NULL;
/* dont send him files he can't save */
if (strcmp(&msg[1], EM_NOTMP) == 0) {
WMESG(HUP, "");
RMESG(HUP, msg, 1);
goto process;
}
notify(mailopt, W_USER, W_FILE1, Rmtname, &msg[1]);
ASSERT(role == MASTER, "WRONG ROLE - SN", CNULL, role);
if (msg[1] != '4')
unlinkdf(W_DFILE);
goto top;
}
if (msg[1] == 'Y') {
/* send file */
ASSERT(role == MASTER, "WRONG ROLE - SY", CNULL, role);
ret = fstat(fileno(fp), &stbuf);
ASSERT(ret != -1, "STAT FAILED", filename, 0);
i = 1 + (int)(stbuf.st_size / XFRRATE);
if (send_or_receive != SNDFILE) {
send_or_receive = SNDFILE;
systat(Rmtname, SS_INPROGRESS, "SENDING");
}
ret = (*Wrdata)(fp, Ofn);
fclose(fp);
fp = NULL;
if (ret != SUCCESS) {
(*Turnoff)();
USRF(USR_CFAIL);
return FAIL;
}
RMESG(RQSTCMPT, msg, i);
unlinkdf(W_DFILE);
goto process;
}
/* SLAVE section of SNDFILE */
ASSERT(role == SLAVE, "WRONG ROLE - SLAVE", CNULL, role);
/* request to receive file */
/* check permissions */
i = getargs(msg, wrkvec, 20);
if (i < 5) {
char *bnp;
bnp = rindex(Wfile, '/');
sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : Wfile);
xmv(Wfile, rqstr);
logent(Wfile, "CMD FILE CORRUPTED");
Wfile[0] = '\0';
goto top;
}
sprintf(rqstr, "%s %s %s %s", W_TYPE, W_FILE1, W_FILE2, W_USER);
logent(rqstr, "REQUESTED");
DEBUG(4, "msg - %s\n", msg);
strcpy(filename, W_FILE2);
/* Run uuxqt occasionally */
if (filename[0] == XQTPRE) {
if (++nXfiles > 10) {
nXfiles = 0;
/*
* want to create an orphan uuxqt,
* so a double-fork is needed.
*/
if (fork() == 0) {
xuuxqt();
_exit(0);
}
wait((int *)0);
}
}
/* expand filename, i is set to 0 if this is
* is a vanilla spool file, so no stat(II)s are needed */
i = expfile(filename);
DEBUG(4, "expfile type - %d\n", i);
if (i != 0) {
if (chkpth("", Rmtname, filename)
|| chkperm(filename, index(W_OPTNS, 'd'))) {
WMESG(SNDFILE, EM_RMTACC);
logent("DENIED", "PERMISSION");
goto top;
}
if (isdir(filename)) {
strcat(filename, "/");
strcat(filename, lastpart(W_FILE1));
}
}
sprintf(User, "%.9s", W_USER);
DEBUG(4, "chkpth ok Rmtname - %s\n", Rmtname);
/* speed things up by OKing file before
* creating TM file. If the TM file cannot be created,
* then the conversation bombs, but that seems reasonable,
* as there are probably serious problems then.
*/
WMESG(SNDFILE, YES);
sprintf(Dfile, "%s/TM.%05d.%03d", Spool, pnum, tmpnum++);
if((fp = fopen(subfile(Dfile), "w")) == NULL) {
/* WMESG(SNDFILE, EM_NOTMP);*/
logent("CAN'T OPEN", "TM FILE");
unlinkdf(Dfile);
(*Turnoff)();
return FAIL;
}
if (send_or_receive != RCVFILE) {
send_or_receive = RCVFILE;
systat(Rmtname, SS_INPROGRESS, "RECEIVING");
}
ret = (*Rddata)(Ifn, fp);
fflush(fp);
if (ferror(fp) || fclose(fp))
ret = FAIL;
if (ret != SUCCESS) {
(void) unlinkdf(Dfile);
(*Turnoff)();
return FAIL;
}
/* copy to user directory */
ntfyopt = index(W_OPTNS, 'n') != NULL;
status = xmv(Dfile, filename);
if (willturn && Now.time > (LastTurned.time+turntime)
&& iswrk(Wfile, "chk", Spool, wkpre)) {
WMESG(RQSTCMPT, status ? EM_RMTCP : "YM");
willturn = -1;
} else
WMESG(RQSTCMPT, status ? EM_RMTCP : YES);
if (i == 0)
; /* vanilla file, nothing to do */
else if (status == 0) {
if (W_MODE == 0 || sscanf(W_MODE, "%o", &filemode) != 1)
filemode = BASEMODE;
chmod(subfile(filename), (filemode|BASEMODE)&0777);
arrived(ntfyopt, filename, W_NUSER, Rmtname, User);
} else {
logent(_FAILED, "COPY");
status = putinpub(filename, Dfile, W_USER);
DEBUG(4, "->PUBDIR %d\n", status);
if (status == 0)
arrived(ntfyopt, filename, W_NUSER, Rmtname, User);
}
goto top;
case RCVFILE:
/* MASTER section of RCVFILE */
DEBUG(4, "%s\n", "RCVFILE:");
if (msg[1] == 'N') {
i = atoi(&msg[2]);
if (i < 0 || i > EM_MAX)
i = 0;
logent(Em_msg[i], "REQUEST FAILED");
USRF( 1 << i );
fclose(fp);
fp = NULL;
notify(mailopt, W_USER, W_FILE1, Rmtname, &msg[1]);
ASSERT(role == MASTER, "WRONG ROLE - RN", CNULL, role);
unlinkdf(Dfile);
goto top;
}
if (msg[1] == 'Y') {
/* receive file */
ASSERT(role == MASTER, "WRONG ROLE - RY", CNULL, role);
if (send_or_receive != RCVFILE) {
send_or_receive = RCVFILE;
systat(Rmtname, SS_INPROGRESS, "RECEIVING");
}
ret = (*Rddata)(Ifn, fp);
fflush(fp);
if (ferror(fp) || fclose(fp))
ret = FAIL;
if (ret != SUCCESS) {
unlinkdf(Dfile);
(*Turnoff)();
USRF(USR_CFAIL);
return FAIL;
}
/* copy to user directory */
if (isdir(filename)) {
strcat(filename, "/");
strcat(filename, lastpart(W_FILE1));
}
status = xmv(Dfile, filename);
if (willturn && Now.time > (LastTurned.time+turntime)
&& iswrk(Wfile, "chk", Spool, wkpre)) {
WMESG(RQSTCMPT, status ? EM_RMTCP : "YM");
willturn = -1;
} else
WMESG(RQSTCMPT, status ? EM_RMTCP : YES);
notify(mailopt, W_USER, filename, Rmtname,
status ? EM_LOCCP : YES);
if (status == 0) {
sscanf(&msg[2], "%o", &filemode);
if (filemode <= 0)
filemode = BASEMODE;
chmod(subfile(filename), (filemode|BASEMODE)&0777);
USRF(USR_COK);
} else {
logent(_FAILED, "COPY");
putinpub(filename, Dfile, W_USER);
USRF(USR_LOCCP);
}
goto top;
}
/* SLAVE section of RCVFILE */
ASSERT(role == SLAVE, "WRONG ROLE - SLAVE RCV", CNULL, role);
/* request to send file */
strcpy(rqstr, msg);
logent(rqstr, "REQUESTED");
/* check permissions */
i = getargs(msg, wrkvec, 20);
if (i < 4) {
char *bnp;
bnp = rindex(Wfile, '/');
sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : Wfile);
xmv(Wfile, rqstr);
logent(Wfile, "CMD FILE CORRUPTED");
Wfile[0] = '\0';
goto top;
}
DEBUG(4, "msg - %s\n", msg);
DEBUG(4, "W_FILE1 - %s\n", W_FILE1);
strcpy(filename, W_FILE1);
expfile(filename);
if (isdir(filename)) {
strcat(filename, "/");
strcat(filename, lastpart(W_FILE2));
}
sprintf(User, "%.9s", W_USER);
if (chkpth("", Rmtname, filename) || anyread(filename)) {
WMESG(RCVFILE, EM_RMTACC);
logent("DENIED", "PERMISSION");
goto top;
}
DEBUG(4, "chkpth ok Rmtname - %s\n", Rmtname);
if ((fp = fopen(subfile(filename), "r")) == NULL) {
WMESG(RCVFILE, EM_RMTACC);
logent("CAN'T OPEN", "DENIED");
goto top;
}
/* ok to send file */
ret = fstat(fileno(fp), &stbuf);
ASSERT(ret != -1, "STAT FAILED", filename, 0);
i = 1 + (int)(stbuf.st_size / XFRRATE);
sprintf(msg, "%s %o", YES, (int)stbuf.st_mode & 0777);
WMESG(RCVFILE, msg);
if (send_or_receive != SNDFILE) {
send_or_receive = SNDFILE;
systat(Rmtname, SS_INPROGRESS, "SENDING");
}
ret = (*Wrdata)(fp, Ofn);
fclose(fp);
if (ret != SUCCESS) {
(*Turnoff)();
return FAIL;
}
RMESG(RQSTCMPT, msg, i);
goto process;
}
(*Turnoff)();
return FAIL;
}
/*
* read message 'c'. try 'n' times
*
* return code: SUCCESS | FAIL
*/
rmesg(c, msg, n)
register char *msg, c;
register int n;
{
char str[MAXFULLNAME];
DEBUG(4, "rmesg - '%c' ", c);
while ((*Rdmsg)(msg, Ifn) != SUCCESS) {
if (--n > 0) {
sprintf(str, "%d", n);
logent(str, "PATIENCE");
continue;
}
DEBUG(4, "got FAIL\n", CNULL);
if (c != '\0')
sprintf(str, "expected '%c' got FAIL (%d)", c, errno);
else
sprintf(str, "expected ANY got FAIL (%d)", errno);
logent(str, "BAD READ");
return FAIL;
}
if (c != '\0' && msg[0] != c) {
DEBUG(4, "got %s\n", msg);
sprintf(str, "expected '%c' got %s", c, msg);
logent(str, "BAD READ");
return FAIL;
}
DEBUG(4, "got %s\n", msg);
return SUCCESS;
}
/*
* write a message (type m)
*
* return codes: SUCCESS - ok | FAIL - ng
*/
wmesg(m, s)
register char *s, m;
{
DEBUG(4, "wmesg '%c' ", m);
DEBUG(4, "%s\n", s);
return (*Wrmsg)(m, s, Ofn);
}
/*
* mail results of command
*
* return codes: none
*/
notify(mailopt, user, file, sys, msgcode)
char *user, *file, *sys, *msgcode;
{
char str[BUFSIZ];
int i;
char *msg;
if (!mailopt && *msgcode == 'Y')
return;
if (*msgcode == 'Y')
msg = "copy succeeded";
else {
i = atoi(msgcode + 1);
if (i < 1 || i > EM_MAX)
i = 0;
msg = Em_msg[i];
}
sprintf(str, "file %s!%s -- %s\n",
sys,file, msg);
mailst(user, str, CNULL);
return;
}
/*
* local notify
*
* return code - none
*/
lnotify(user, file, mesg)
char *user, *file, *mesg;
{
char mbuf[200];
sprintf(mbuf, "file %s!%s -- %s\n", Myname, file, mesg);
mailst(user, mbuf, CNULL);
return;
}
/*
* converse with the remote machine, agree upon a protocol (if possible)
* and start the protocol.
*
* return codes:
* SUCCESS - successful protocol selection
* FAIL - can't find common or open failed
*/
startup(role)
int role;
{
extern (*Rdmsg)(), (*Wrmsg)();
extern char *blptcl(), fptcl();
char msg[BUFSIZ], str[MAXFULLNAME];
Rdmsg = Imsg;
Wrmsg = Omsg;
if (role == MASTER) {
RMESG(SLTPTCL, msg, 1);
if ((str[0] = fptcl(&msg[1])) == NULL) {
/* no protocol match */
WMESG(USEPTCL, NO);
return FAIL;
}
str[1] = '\0';
WMESG(USEPTCL, str);
if (stptcl(str) != 0)
return FAIL;
DEBUG(4, "protocol %s\n", str);
return SUCCESS;
}
else {
WMESG(SLTPTCL, blptcl(str));
RMESG(USEPTCL, msg, 1);
if (msg[1] == 'N') {
return FAIL;
}
if (stptcl(&msg[1]) != 0)
return FAIL;
DEBUG(4, "Protocol %s\n", msg);
return SUCCESS;
}
}
/*
* choose a protocol from the input string (str) and return the it
*
* return codes:
* '\0' - no acceptable protocol
* any character - the chosen protocol
*/
char
fptcl(str)
register char *str;
{
register struct Proto *p;
extern char LineType[];
for (p = Ptbl; p->P_id != '\0'; p++) {
#ifdef TCPIP
/* Only use 't' on TCP/IP */
if (p->P_id == 't' && strcmp("TCP", LineType))
continue;
#endif
#ifdef PAD
/* only use 'f' protocol on PAD */
if (p->P_id == 'f' && strcmp("PAD", LineType))
continue;
#endif
if (index(str, p->P_id) != NULL) {
return p->P_id;
}
}
return '\0';
}
/*
* build a string of the letters of the available protocols
*/
char *
blptcl(str)
register char *str;
{
register struct Proto *p;
register char *s;
for (p = Ptbl, s = str; (*s++ = p->P_id) != '\0'; p++)
;
*s = '\0';
return str;
}
/*
* this routine will set up the six routines
* (Rdmsg, Wrmsg, Rddata, Wrdata, Turnon, Turnoff) for the
* desired protocol.
*
* return codes:
* SUCCESS - ok
* FAIL - no find or failed to open
*
*/
stptcl(c)
register char *c;
{
register struct Proto *p;
for (p = Ptbl; p->P_id != '\0'; p++) {
if (*c == p->P_id) {
/* found protocol - set routines */
Rdmsg = p->P_rdmsg;
Wrmsg = p->P_wrmsg;
Rddata = p->P_rddata;
Wrdata = p->P_wrdata;
Turnon = p->P_turnon;
Turnoff = p->P_turnoff;
if ((*Turnon)() != SUCCESS)
return FAIL;
DEBUG(4, "Proto started %c\n", *c);
return SUCCESS;
}
}
DEBUG(4, "Proto start-fail %c\n", *c);
return FAIL;
}
/*
* put file in public place. if successful, filename is modified
*
* return code SUCCESS | FAIL
*/
putinpub(file, tmp, user)
register char *file, *tmp, *user;
{
char fullname[MAXFULLNAME];
char *lastpart();
int status;
sprintf(fullname, "%s/%s/", PUBDIR, user);
if (mkdirs(fullname) != 0) {
/* can not make directories */
DEBUG(1, "Cannot mkdirs(%s)\n", fullname);
return FAIL;
}
strcat(fullname, lastpart(file));
status = xmv(tmp, fullname);
if (status == 0) {
strcpy(file, fullname);
chmod(subfile(fullname), BASEMODE);
}
return status;
}
/*
* unlink D. file
*
* return code - none
*/
unlinkdf(file)
register char *file;
{
if (strlen(file) > 6)
unlink(subfile(file));
return;
}
/*
* notify receiver of arrived file
*
* return code - none
*/
arrived(opt, file, nuser, rmtsys, rmtuser)
char *file, *nuser, *rmtsys, *rmtuser;
{
char mbuf[200];
if (!opt)
return;
sprintf(mbuf, "%s from %s!%s arrived\n", file, rmtsys, rmtuser);
mailst(nuser, mbuf, CNULL);
return;
}
nullf()
{
return SUCCESS;
}

564
src/cmd/uucp/condevs.c Normal file
View File

@@ -0,0 +1,564 @@
#if !defined(lint) && defined(DOSCCS)
static char sccsid[] = "@(#)condevs.c 5.15.2 (2.11BSD) 1997/10/2";
#endif
/*
* Here are various dialers to establish the machine-machine connection.
* conn.c/condevs.c was glued together by Mike Mitchell.
* The dialers were supplied by many people, to whom we are grateful.
*
* ---------------------------------------------------------------------
* NOTE:
* There is a bug that occurs at least on PDP11s due to a limitation of
* setjmp/longjmp. If the routine that does a setjmp is interrupted
* and longjmp-ed to, it loses its register variables (on a pdp11).
* What works is if the routine that does the setjmp
* calls a routine and it is the *subroutine* that is interrupted.
*
* Anyway, in conclusion, condevs.c is plagued with register variables
* that are used inside
* if (setjmp(...)) {
* ....
* }
*
* THE FIX: Don't declare variables to be register
*/
#include "condevs.h"
struct condev condevs[] = {
{ "DIR", "direct", diropn, nulldev, dircls },
#ifdef DATAKIT
{ "DK", "datakit", dkopn, nulldev, nulldev },
#endif
#ifdef PNET
{ "PNET", "pnet", pnetopn, nulldev, nulldev },
#endif
#ifdef UNETTCP
{ "TCP", "TCP", unetopn, nulldev, unetcls },
#endif
#ifdef BSDTCP
{ "TCP", "TCP", bsdtcpopn, nulldev, bsdtcpcls },
#endif
#ifdef MICOM
{ "MICOM", "micom", micopn, nulldev, miccls },
#endif
#ifdef DN11
{ "ACU", "dn11", Acuopn, dnopn, dncls },
#endif
#ifdef HAYES
{ "ACU", "hayes", Acuopn, hyspopn, hyscls },
{ "ACU", "hayespulse", Acuopn, hyspopn, hyscls },
{ "ACU", "hayestone", Acuopn, hystopn, hyscls },
{ "WATS", "hayestone", Acuopn, hystopn, hyscls },
#endif
#ifdef HAYES2400
{ "ACU", "hayes2400", Acuopn, hyspopn24, hyscls24 },
{ "ACU", "hayes2400pulse", Acuopn, hyspopn24, hyscls24 },
{ "ACU", "hayes2400tone", Acuopn, hystopn24, hyscls24 },
#endif
#ifdef HAYESQ /* a version of hayes that doesn't use result codes */
{ "ACU", "hayesq", Acuopn, hysqpopn, hysqcls },
{ "ACU", "hayesqpulse", Acuopn, hysqpopn, hysqcls },
{ "ACU", "hayesqtone", Acuopn, hysqtopn, hysqcls },
#endif
#ifdef CDS224
{ "ACU", "cds224", Acuopn, cdsopn224, cdscls224},
#endif
#ifdef NOVATION
{ "ACU", "novation", Acuopn, novopn, novcls},
#endif
#ifdef DF02
{ "ACU", "DF02", Acuopn, df2opn, df2cls },
#endif
#ifdef DF112
{ "ACU", "DF112P", Acuopn, df12popn, df12cls },
{ "ACU", "DF112T", Acuopn, df12topn, df12cls },
#endif
#ifdef VENTEL
{ "ACU", "ventel", Acuopn, ventopn, ventcls },
#endif
#ifdef PENRIL
{ "ACU", "penril", Acuopn, penopn, pencls },
#endif
#ifdef VADIC
{ "ACU", "vadic", Acuopn, vadopn, vadcls },
#endif
#ifdef VA212
{ "ACU", "va212", Acuopn, va212opn, va212cls },
#endif
#ifdef VA811S
{ "ACU", "va811s", Acuopn, va811opn, va811cls },
#endif
#ifdef VA820
{ "ACU", "va820", Acuopn, va820opn, va820cls },
{ "WATS", "va820", Acuopn, va820opn, va820cls },
#endif
#ifdef RVMACS
{ "ACU", "rvmacs", Acuopn, rvmacsopn, rvmacscls },
#endif
#ifdef VMACS
{ "ACU", "vmacs", Acuopn, vmacsopn, vmacscls },
#endif
#ifdef SYTEK
{ "SYTEK", "sytek", sykopn, nulldev, sykcls },
#endif
#ifdef ATT2224
{ "ACU", "att", Acuopn, attopn, attcls },
#endif
/* Insert new entries before this line */
{ NULL, NULL, NULL, NULL, NULL }
};
/*
* nulldev a null device (returns CF_DIAL)
*/
nulldev()
{
return CF_DIAL;
}
/*
* nodev a null device (returns CF_NODEV)
*/
nodev()
{
return CF_NODEV;
}
/*
* Generic devices look through L-devices and call the CU_open routines for
* appropriate devices. Some things, like the tcp/ip interface, or direct
* connect, do not use the CU_open entry. ACUs must search to find the
* right routine to call.
*/
/*
* diropn(flds) connect to hardware line
*
* return codes:
* > 0 - file number - ok
* FAIL - failed
*/
diropn(flds)
register char *flds[];
{
register int dcr, status;
struct Devices dev;
char dcname[20];
FILE *dfp;
#ifdef VMSDTR /* Modem control on vms(works dtr) */
int modem_control;
short iosb[4];
int sys$qiow(); /* use this for long reads on vms */
int ret;
long mode[2];
modem_control = 0;
#endif
dfp = fopen(DEVFILE, "r");
ASSERT(dfp != NULL, "CAN'T OPEN", DEVFILE, 0);
while ((status = rddev(dfp, &dev)) != FAIL) {
#ifdef VMSDTR /* Modem control on vms(works dtr) */
/* If we find MOD in the device type field we go into action */
if (strcmp(dev.D_type, "MOD") == SAME) {
modem_control = 1;
DEBUG(7, "Setting Modem control to %d",modem_control);
}
if (strcmp(flds[F_CLASS], dev.D_class) != SAME)
continue;
/*
* Modem control on vms(works dtr) Take anything in MOD class.
* It probably should work differently anyway so we can have
* multiple hardwired lines.
*/
if (!modem_control&&strcmp(flds[F_PHONE], dev.D_line) != SAME)
#else
if (strcmp(flds[F_CLASS], dev.D_class) != SAME)
continue;
if (strcmp(flds[F_PHONE], dev.D_line) != SAME)
#endif
continue;
if (mlock(dev.D_line) != FAIL)
break;
}
fclose(dfp);
if (status == FAIL) {
logent("DEVICE", "NO");
return CF_NODEV;
}
sprintf(dcname, "/dev/%s", dev.D_line);
if (setjmp(Sjbuf)) {
DEBUG(4, "Open timed out\n", CNULL);
delock(dev.D_line);
return CF_DIAL;
}
signal(SIGALRM, (sig_t)alarmtr);
/* For PC Pursuit, it could take a while to call back */
alarm( strcmp(flds[F_LINE], "PCP") ? 10 : MAXMSGTIME*4 );
getnextfd();
errno = 0;
DEBUG(4,"Opening %s\n",dcname);
dcr = open(dcname, 2); /* read/write */
#ifdef VMSDTR /* Modem control on vms(works dtr) */
fflush(stdout);
if (modem_control) { /* Did we have MOD in the device type field ? */
/* Sense the current terminal setup and save it */
if ((ret = sys$qiow(_$EFN,(fd_fab_pointer[dcr]->fab).fab$l_stv,
IO$_SENSEMODE,iosb,0,0,mode,8,0,0,0,0))
!= SS$_NORMAL) {
DEBUG(7, "ret status on sense failed on Modem sense=%x<", ret);
return CF_DIAL;
}
mode[1] |= TT$M_MODEM; /* Or in modem control(DTR) */
/* Now set the new terminal characteristics */
/* This is temporary and will go away when we let go of it */
if ((ret = sys$qiow(_$EFN,(fd_fab_pointer[dcr]->fab).fab$l_stv,
IO$_SETMODE,iosb,0,0,mode,8,0,0,0,0))
!= SS$_NORMAL) {
DEBUG(7, "ret status on sense failed on Modem setup=%x<", ret);
return CF_DIAL;
}
}
#endif
next_fd = -1;
alarm(0);
if (dcr < 0) {
if (errno == EACCES)
logent(dev.D_line, "CANT OPEN");
DEBUG(4, "OPEN FAILED: errno %d\n", errno);
delock(dev.D_line);
return CF_DIAL;
}
fflush(stdout);
if (fixline(dcr, dev.D_speed) == FAIL) {
DEBUG(4, "FIXLINE FAILED\n", CNULL);
return CF_DIAL;
}
strcpy(devSel, dev.D_line); /* for latter unlock */
CU_end = dircls;
return dcr;
}
dircls(fd)
register int fd;
{
if (fd > 0) {
close(fd);
delock(devSel);
}
}
/*
* open an ACU and dial the number. The condevs table
* will be searched until a dialing unit is found that is free.
*
* return codes: >0 - file number - o.k.
* FAIL - failed
*/
char devSel[20]; /* used for later unlock() */
Acuopn(flds)
register char *flds[];
{
char phone[MAXPH+1];
register struct condev *cd;
register int fd, acustatus;
register FILE *dfp;
struct Devices dev;
int retval = CF_NODEV;
char nobrand[MAXPH], *line;
exphone(flds[F_PHONE], phone);
if (snccmp(flds[F_LINE], "LOCAL") == SAME)
line = "ACU";
else
line = flds[F_LINE];
devSel[0] = '\0';
nobrand[0] = '\0';
DEBUG(4, "Dialing %s\n", phone);
dfp = fopen(DEVFILE, "r");
ASSERT(dfp != NULL, "Can't open", DEVFILE, 0);
acustatus = 0; /* none found, none locked */
while (rddev(dfp, &dev) != FAIL) {
/*
* for each ACU L.sys line, try at most twice
* (TRYCALLS) to establish carrier. The old way tried every
* available dialer, which on big sites takes forever!
* Sites with a single auto-dialer get one try.
* Sites with multiple dialers get a try on each of two
* different dialers.
* To try 'harder' to connect to a remote site,
* use multiple L.sys entries.
*/
if (acustatus > TRYCALLS)
break;
if (strcmp(flds[F_CLASS], dev.D_class) != SAME)
continue;
if (snccmp(line, dev.D_type) != SAME)
continue;
if (dev.D_brand[0] == '\0') {
logent("Acuopn","No 'brand' name on ACU");
continue;
}
for(cd = condevs; cd->CU_meth != NULL; cd++) {
if (snccmp(line, cd->CU_meth) == SAME) {
if (snccmp(dev.D_brand, cd->CU_brand) == SAME)
break;
strncpy(nobrand, dev.D_brand, sizeof nobrand);
}
}
if (mlock(dev.D_line) == FAIL) {
acustatus++;
continue;
}
if (acustatus < 1)
acustatus = 1; /* has been found */
#ifdef DIALINOUT
#ifdef ALLACUINOUT
if (1) {
#else
if (snccmp("inout", dev.D_calldev) == SAME) {
#endif
if (disable(dev.D_line) == FAIL) {
delock(dev.D_line);
continue;
}
} else
reenable();
#endif
DEBUG(4, "Using %s\n", cd->CU_brand);
acustatus++;
fd = (*(cd->CU_open))(phone, flds, &dev);
if (fd > 0) {
CU_end = cd->CU_clos; /* point CU_end at close func */
fclose(dfp);
strcpy(devSel, dev.D_line); /* save for later unlock() */
return fd;
} else
delock(dev.D_line);
retval = CF_DIAL;
}
fclose(dfp);
if (acustatus == 0) {
if (nobrand[0])
logent(nobrand, "unsupported ACU type");
else
logent("L-devices", "No appropriate ACU");
}
if (acustatus == 1)
logent("DEVICE", "NO");
return retval;
}
/*
* intervaldelay: delay execution for numerator/denominator seconds.
*/
#ifdef INTERVALTIMER
#define uucpdelay(num,denom) intervaldelay(num,denom)
intervaldelay(num,denom)
int num, denom;
{
struct timeval tv;
tv.tv_sec = num / denom;
tv.tv_usec = (num * 1000000L / denom ) % 1000000L;
(void) select (0, (fd_set*)0, (fd_set*)0, (fd_set*)0, &tv);
}
#endif
#ifdef FASTTIMER
#define uucpdelay(num,denom) nap(60*num/denom)
/* Sleep in increments of 60ths of second. */
nap (time)
register int time;
{
static int fd;
if (fd == 0)
fd = open (FASTTIMER, 0);
read (fd, 0, time);
}
#endif
#ifdef FTIME
#define uucpdelay(num,denom) ftimedelay(1000*num/denom)
ftimedelay(n)
{
static struct timeb loctime;
register i = loctime.millitm;
ftime(&loctime);
while (abs((int)(loctime.millitm - i))<n) ftime(&loctime)
;
}
#endif
#ifdef BUSYLOOP
#define uucpdelay(num,denom) busyloop(CPUSPEED*num/denom)
#define CPUSPEED 1000000 /* VAX 780 is 1MIPS */
#define DELAY(n) { register long N = (n); while (--N > 0); }
busyloop(n)
{
DELAY(n);
}
#endif
slowrite(fd, str)
register char *str;
{
DEBUG(6, "slowrite ", CNULL);
while (*str) {
DEBUG(6, "%c", *str);
uucpdelay(1, 10); /* delay 1/10 second */
write(fd, str, 1);
str++;
}
DEBUG(6, "\n", CNULL);
}
#define BSPEED B150
/*
* send a break
*/
genbrk(fn, bnulls)
register int fn, bnulls;
{
#ifdef USG
if (ioctl(fn, TCSBRK, STBNULL) < 0)
DEBUG(5, "break TCSBRK %s\n", strerror(errno));
#else
# ifdef TIOCSBRK
if (ioctl(fn, TIOCSBRK, STBNULL) < 0)
DEBUG(5, "break TIOCSBRK %s\n", strerror(errno));
# ifdef TIOCCBRK
uucpdelay(bnulls, 10);
if (ioctl(fn, TIOCCBRK, STBNULL) < 0)
DEBUG(5, "break TIOCCBRK %s\n", strerror(errno));
# endif
DEBUG(4, "ioctl %f second break\n", (float) bnulls/10 );
# else
struct sgttyb ttbuf;
register int sospeed;
if (ioctl(fn, TIOCGETP, &ttbuf) < 0)
DEBUG(5, "break TIOCGETP %s\n", strerror(errno));
sospeed = ttbuf.sg_ospeed;
ttbuf.sg_ospeed = BSPEED;
if (ioctl(fn, TIOCSETP, &ttbuf) < 0)
DEBUG(5, "break TIOCSETP %s\n", strerror(errno));
if (write(fn, "\0\0\0\0\0\0\0\0\0\0\0\0", bnulls) != bnulls) {
badbreak:
logent(strerror(errno), "BAD WRITE genbrk");
alarm(0);
longjmp(Sjbuf, 3);
}
ttbuf.sg_ospeed = sospeed;
if (ioctl(fn, TIOCSETP, &ttbuf) < 0)
DEBUG(5, "break ioctl %s\n", strerror(errno));
if (write(fn, "@", 1) != 1)
goto badbreak;
DEBUG(4, "sent BREAK nulls - %d\n", bnulls);
#endif
#endif
}
#ifdef DIALINOUT
/* DIALIN/OUT CODE (WLS) */
/*
* disable and reenable: allow a single line to be use for dialin/dialout
*
*/
char enbdev[16];
disable(dev)
register char *dev;
{
register char *rdev;
/* strip off directory prefixes */
rdev = dev;
while (*rdev)
rdev++;
while (--rdev >= dev && *rdev != '/')
;
rdev++;
if (enbdev[0]) {
if (strcmp(enbdev, rdev) == SAME)
return SUCCESS; /* already disabled */
delock(enbdev);
reenable(); /* else, reenable the old one */
}
DEBUG(4, "Disable %s\n", rdev);
if (enbcall("disable", rdev) == FAIL)
return FAIL;
strcpy(enbdev, rdev);
return SUCCESS;
}
reenable()
{
if (enbdev[0] == '\0')
return;
DEBUG(4, "Reenable %s\n", enbdev);
(void) enbcall("enable", enbdev);
enbdev[0] = '\0';
}
enbcall(type, dev)
char *type, *dev;
{
int pid;
register char *p;
int fildes[2];
int status;
FILE *fil;
char buf[80];
fflush(stderr);
fflush(stdout);
pipe(fildes);
if ((pid = fork()) == 0) {
DEBUG(4, DIALINOUT, CNULL);
DEBUG(4, " %s", type);
DEBUG(4, " %s\n", dev);
close(fildes[0]);
close(0); close(1); close(2);
open("/dev/null",0);
dup(fildes[1]); dup(fildes[1]);
setuid(geteuid()); /* for chown(uid()) in acu program */
execl(DIALINOUT, "acu", type, dev, 0);
exit(-1);
}
if (pid<0)
return FAIL;
close(fildes[1]);
fil = fdopen(fildes[0],"r");
if (fil!=NULL) {
#ifdef BSD4_2
setlinebuf(fil);
#endif
while (fgets(buf, sizeof buf, fil) != NULL) {
p = buf + strlen(buf) - 1;
if (*p == '\n')
*p = '\0';
logent(buf,"ACUCNTRL:");
}
}
while(wait(&status) != pid)
;
fclose(fil);
return status ? FAIL : SUCCESS;
}
#endif

114
src/cmd/uucp/condevs.h Normal file
View File

@@ -0,0 +1,114 @@
/* condevs.h 4.7.1 1996/3/22 */
#include "uucp.h"
#include <errno.h>
#include <setjmp.h>
#include <signal.h>
#include <sgtty.h>
#ifdef VMSDTR /* Modem control on vms(works dtr) */
#include <eunice/eunice.h>
#define TT$M_MODEM 0x00200000 /* These should be in a '.h' somewhere */
#define SS$_NORMAL 0x00000001
#define IO$_SETMODE 0x00000023
#define IO$_SENSEMODE 0x00000027
#endif
extern char devSel[]; /* name to pass to delock() in close */
extern int next_fd;
extern jmp_buf Sjbuf;
extern int alarmtr();
int nulldev(), nodev(), Acuopn(), diropn(), dircls();
#ifdef DATAKIT
int dkopn();
#endif
#ifdef DN11
int dnopn(), dncls();
#endif
#ifdef HAYES
int hyspopn(), hystopn(), hyscls();
#endif
#ifdef HAYES2400
int hyspopn24(), hystopn24(), hyscls24();
#endif
#ifdef HAYESQ
int hysqopn(), hysqcls(); /* a version of hayes that doesn't use ret codes */
#endif
#ifdef NOVATION
int novopn(), novcls();
#endif
#ifdef CDS224
int cdsopn224(), cdscls224();
#endif
#ifdef DF02
int df2opn(), df2cls();
#endif
#ifdef DF112
int df12popn(), df12topn(), df12cls();
#endif
#ifdef PNET
int pnetopn();
#endif
#ifdef VENTEL
int ventopn(), ventcls();
#endif
#ifdef PENRIL
int penopn(), pencls();
#endif
#ifdef UNETTCP
#define TO_ACTIVE 0
int unetopn(), unetcls();
#endif
#ifdef BSDTCP
int bsdtcpopn(), bsdtcpcls();
#endif
#ifdef VADIC
int vadopn(), vadcls();
#endif
#ifdef VA212
int va212opn(), va212cls();
#endif
#ifdef VA811S
int va811opn(), va811cls();
#endif
#ifdef VA820
int va820opn(), va820cls();
#endif
#ifdef RVMACS
int rvmacsopn(), rvmacscls();
#endif
#ifdef VMACS
int vmacsopn(), vmacscls();
#endif
#ifdef MICOM
int micopn(), miccls();
#endif
#ifdef SYTEK
int sykopn(), sykcls();
#endif
#ifdef ATT2224
int attopn(), attcls();
#endif

1143
src/cmd/uucp/conn.c Normal file

File diff suppressed because it is too large Load Diff

72
src/cmd/uucp/cpmv.c Normal file
View File

@@ -0,0 +1,72 @@
#ifndef lint
static char sccsid[] = "@(#)cpmv.c 5.5 (Berkeley) 10/9/85";
#endif
#include "uucp.h"
#include <sys/stat.h>
/*LINTLIBRARY*/
/*
* copy f1 to f2
*
* return - SUCCESS | FAIL
*/
xcp(f1, f2)
char *f1, *f2;
{
char buf[BUFSIZ];
register int len;
register int fp1, fp2;
char *lastpart();
char full[MAXFULLNAME];
struct stat s;
if ((fp1 = open(subfile(f1), 0)) < 0)
return FAIL;
strcpy(full, f2);
if (stat(subfile(f2), &s) == 0) {
/* check for directory */
if ((s.st_mode & S_IFMT) == S_IFDIR) {
strcat(full, "/");
strcat(full, lastpart(f1));
}
}
DEBUG(4, "full %s\n", full);
if ((fp2 = creat(subfile(full), 0666)) < 0) {
close(fp1);
return FAIL;
}
while((len = read(fp1, buf, BUFSIZ)) > 0)
if (write(fp2, buf, len) != len) {
len = -1;
break;
}
close(fp1);
close(fp2);
return len < 0 ? FAIL: SUCCESS;
}
/*
* move f1 to f2
*
* return 0 ok | FAIL failed
*/
xmv(f1, f2)
register char *f1, *f2;
{
register int ret;
(void) unlink(subfile(f2));
if (link(subfile(f1), subfile(f2)) < 0) {
/* copy file */
ret = xcp(f1, f2);
if (ret == 0)
unlink(subfile(f1));
return ret;
}
(void) unlink(subfile(f1));
return 0;
}

128
src/cmd/uucp/expfile.c Normal file
View File

@@ -0,0 +1,128 @@
#ifndef lint
static char sccsid[] = "@(#)expfile.c 5.5 (Berkeley) 6/19/85";
#endif
#include "uucp.h"
#include <sys/stat.h>
#include <strings.h>
/*LINTLIBRARY*/
/*
* expand file name
*
* return codes: 0 - Ordinary spool area file
* 1 - Other normal file
* FAIL - no Wrkdir name available
*/
expfile(file)
char *file;
{
register char *fpart, *p;
char user[WKDSIZE], *up;
char full[MAXFULLNAME];
int uid;
switch(file[0]) {
case '/':
return 1;
case '~':
for (fpart = file + 1, up = user; *fpart != '\0'
&& *fpart != '/'; fpart++)
*up++ = *fpart;
*up = '\0';
if (!*user || gninfo(user, &uid, full) != 0) {
strcpy(full, PUBDIR);
}
strcat(full, fpart);
strcpy(file, full);
return 1;
default:
p = index(file, '/');
strcpy(full, Wrkdir);
strcat(full, "/");
strcat(full, file);
strcpy(file, full);
if (Wrkdir[0] == '\0')
return FAIL;
else if (p != NULL)
return 1;
return 0;
}
}
/*
* check if directory name
*
* return codes: 0 - not directory | 1 - is directory
*/
isdir(name)
char *name;
{
register int ret;
struct stat s;
ret = stat(subfile(name), &s);
if (ret < 0)
return 0;
if ((s.st_mode & S_IFMT) == S_IFDIR)
return 1;
return 0;
}
/*
* make all necessary directories
*
* return SUCCESS | FAIL
*/
mkdirs(name)
char *name;
{
int ret, mask;
char dir[MAXFULLNAME];
register char *p;
for (p = dir + 1;; p++) {
strcpy(dir, name);
if ((p = index(p, '/')) == NULL)
return SUCCESS;
*p = '\0';
if (isdir(dir))
continue;
DEBUG(4, "mkdir - %s\n", dir);
mask = umask(0);
ret = mkdir(dir, 0777);
umask(mask);
if (ret != 0)
return FAIL;
}
/* NOTREACHED */
}
/*
* expfile and check return
* print error if it failed.
*
* return code - SUCCESS - ok; FAIL if expfile failed
*/
ckexpf(file)
register char *file;
{
if (expfile(file) != FAIL)
return SUCCESS;
/* could not expand file name */
/* the gwd routine failed */
logent("CAN'T EXPAND FILENAME - PWD FAILED", file+1);
return FAIL;
}

549
src/cmd/uucp/fio.c Normal file
View File

@@ -0,0 +1,549 @@
#ifndef lint
static char sccsid[] = "@(#)fio.c 5.3 (Berkeley) 10/9/85";
#endif
/*
* flow control protocol.
*
* This protocol relies on flow control of the data stream.
* It is meant for working over links that can (almost) be
* guaranteed to be errorfree, specifically X.25/PAD links.
* A sumcheck is carried out over a whole file only. If a
* transport fails the receiver can request retransmission(s).
* This protocol uses a 7-bit datapath only, so it can be
* used on links that are not 8-bit transparent.
*
* When using this protocol with an X.25 PAD:
* Although this protocol uses no control chars except CR,
* control chars NULL and ^P are used before this protocol
* is started; since ^P is the default char for accessing
* PAD X.28 command mode, be sure to disable that access
* (PAD par 1). Also make sure both flow control pars
* (5 and 12) are set. The CR used in this proto is meant
* to trigger packet transmission, hence par 3 should be
* set to 2; a good value for the Idle Timer (par 4) is 10.
* All other pars should be set to 0.
*
* Normally a calling site will take care of setting the
* local PAD pars via an X.28 command and those of the remote
* PAD via an X.29 command, unless the remote site has a
* special channel assigned for this protocol with the proper
* par settings.
*
* Additional comments for hosts with direct X.25 access:
* - the global variable IsTcpIp, when set, excludes the ioctl's,
* so the same binary can run on X.25 and non-X.25 hosts;
* - reads are done in small chunks, which can be smaller than
* the packet size; your X.25 driver must support that.
*
*
* Author:
* Piet Beertema, CWI, Amsterdam, Sep 1984
* Modified for X.25 hosts:
* Robert Elz, Melbourne Univ, Mar 1985
*/
#include "uucp.h"
#include <signal.h>
#ifdef USG
#include <termio.h>
#else !USG
#include <sgtty.h>
#endif !USG
#include <setjmp.h>
#define FIBUFSIZ 256 /* for X.25 interfaces: set equal to packet size,
* but see comment above
*/
#define FOBUFSIZ 256 /* for X.25 interfaces: set equal to packet size;
* otherwise make as large as feasible to reduce
* number of write system calls
*/
#ifndef MAXMSGLEN
#define MAXMSGLEN BUFSIZ
#endif MAXMSGLEN
static int fchksum;
static jmp_buf Ffailbuf;
static
falarm()
{
signal(SIGALRM, falarm);
longjmp(Ffailbuf, 1);
}
static int (*fsig)();
#ifndef USG
#define TCGETA TIOCGETP
#define TCSETA TIOCSETP
#define termio sgttyb
#endif USG
fturnon()
{
int ret;
struct termio ttbuf;
if (!IsTcpIp) {
ioctl(Ifn, TCGETA, &ttbuf);
#ifdef USG
ttbuf.c_iflag = IXOFF|IXON|ISTRIP;
ttbuf.c_cc[VMIN] = FIBUFSIZ > 64 ? 64 : FIBUFSIZ;
ttbuf.c_cc[VTIME] = 5;
#else !USG
ttbuf.sg_flags = ANYP|CBREAK|TANDEM;
#endif USG
ret = ioctl(Ifn, TCSETA, &ttbuf);
ASSERT(ret >= 0, "STTY FAILED", "", ret);
}
fsig = signal(SIGALRM, falarm);
/* give the other side time to perform its ioctl;
* otherwise it may flush out the first data this
* side is about to send.
*/
sleep(2);
return SUCCESS;
}
fturnoff()
{
(void) signal(SIGALRM, fsig);
return SUCCESS;
}
fwrmsg(type, str, fn)
register char *str;
int fn;
char type;
{
register char *s;
char bufr[MAXMSGLEN];
s = bufr;
*s++ = type;
while (*str)
*s++ = *str++;
if (*(s-1) == '\n')
s--;
*s++ = '\r';
*s = 0;
(void) write(fn, bufr, s - bufr);
return SUCCESS;
}
frdmsg(str, fn)
register char *str;
register int fn;
{
register char *smax;
if (setjmp(Ffailbuf))
return FAIL;
smax = str + MAXMSGLEN - 1;
(void) alarm(2*MAXMSGTIME);
for (;;) {
if (read(fn, str, 1) <= 0)
goto msgerr;
*str &= 0177;
if (*str == '\r')
break;
if (*str < ' ') {
continue;
}
if (str++ >= smax)
goto msgerr;
}
*str = '\0';
(void) alarm(0);
return SUCCESS;
msgerr:
(void) alarm(0);
return FAIL;
}
fwrdata(fp1, fn)
FILE *fp1;
int fn;
{
register int alen, ret;
register char *obp;
char ack, ibuf[MAXMSGLEN];
int flen, mil, retries = 0;
long abytes, fbytes;
struct timeb t1, t2;
ret = FAIL;
retry:
fchksum = 0xffff;
abytes = fbytes = 0L;
ack = '\0';
#ifdef USG
time(&t1.time);
t1.millitm = 0;
#else !USG
ftime(&t1);
#endif !USG
do {
alen = fwrblk(fn, fp1, &flen);
fbytes += flen;
if (alen <= 0) {
abytes -= alen;
goto acct;
}
abytes += alen;
} while (!feof(fp1) && !ferror(fp1));
DEBUG(8, "\nchecksum: %04x\n", fchksum);
if (frdmsg(ibuf, fn) != FAIL) {
if ((ack = ibuf[0]) == 'G')
ret = SUCCESS;
DEBUG(4, "ack - '%c'\n", ack);
}
acct:
#ifdef USG
time(&t2.time);
t2.millitm = 0;
#else !USG
ftime(&t2);
#endif !USG
Now = t2;
t2.time -= t1.time;
mil = t2.millitm - t1.millitm;
if (mil < 0) {
--t2.time;
mil += 1000;
}
sprintf(ibuf, "sent data %ld bytes %ld.%02d secs",
fbytes, (long)t2.time, mil / 10);
sysacct(abytes, t2.time);
if (retries > 0)
sprintf(&ibuf[strlen(ibuf)], ", %d retries", retries);
DEBUG(1, "%s\n", ibuf);
syslog(ibuf);
if (ack == 'R') {
DEBUG(4, "RETRY:\n", 0);
fseek(fp1, 0L, 0);
retries++;
goto retry;
}
#ifdef SYSACCT
if (ret == FAIL)
sysaccf(NULL); /* force accounting */
#endif SYSACCT
return ret;
}
/* max. attempts to retransmit a file: */
#define MAXRETRIES (fbytes < 10000L ? 2 : 1)
frddata(fn, fp2)
register int fn;
register FILE *fp2;
{
register int flen;
register char eof;
char ibuf[FIBUFSIZ];
int ret, mil, retries = 0;
long alen, abytes, fbytes;
struct timeb t1, t2;
ret = FAIL;
retry:
fchksum = 0xffff;
abytes = fbytes = 0L;
#ifdef USG
time(&t1.time);
t1.millitm = 0;
#else !USG
ftime(&t1);
#endif !USG
do {
flen = frdblk(ibuf, fn, &alen);
abytes += alen;
if (flen < 0)
goto acct;
if (eof = flen > FIBUFSIZ)
flen -= FIBUFSIZ + 1;
fbytes += flen;
if (fwrite(ibuf, sizeof (char), flen, fp2) != flen)
goto acct;
} while (!eof);
ret = SUCCESS;
acct:
#ifdef USG
time(&t2.time);
t2.millitm = 0;
#else !USG
ftime(&t2);
#endif !USG
Now = t2;
t2.time -= t1.time;
mil = t2.millitm - t1.millitm;
if (mil < 0) {
--t2.time;
mil += 1000;
}
sprintf(ibuf, "received data %ld bytes %ld.%02d secs",
fbytes, (long)t2.time, mil/10);
if (retries > 0)
sprintf(&ibuf[strlen(ibuf)]," %d retries", retries);
sysacct(abytes, t2.time);
DEBUG(1, "%s\n", ibuf);
syslog(ibuf);
if (ret == FAIL) {
if (retries++ < MAXRETRIES) {
DEBUG(8, "send ack: 'R'\n", 0);
fwrmsg('R', "", fn);
fseek(fp2, 0L, 0);
DEBUG(4, "RETRY:\n", 0);
goto retry;
}
DEBUG(8, "send ack: 'Q'\n", 0);
fwrmsg('Q', "", fn);
#ifdef SYSACCT
sysaccf(NULL); /* force accounting */
#endif SYSACCT
}
else {
DEBUG(8, "send ack: 'G'\n", 0);
fwrmsg('G', "", fn);
}
return ret;
}
static
frdbuf(blk, len, fn)
register char *blk;
register int len;
register int fn;
{
static int ret = FIBUFSIZ / 2;
if (setjmp(Ffailbuf))
return FAIL;
(void) alarm(MAXMSGTIME);
ret = read(fn, blk, len);
alarm(0);
return ret <= 0 ? FAIL : ret;
}
#if !defined(BSD4_2) && !defined(USG)
/* call ultouch every TC calls to either frdblk or fwrblk */
#define TC 20
static int tc = TC;
#endif !defined(BSD4_2) && !defined(USG)
/* Byte conversion:
*
* from pre to
* 000-037 172 100-137
* 040-171 040-171
* 172-177 173 072-077
* 200-237 174 100-137
* 240-371 175 040-171
* 372-377 176 072-077
*/
static
fwrblk(fn, fp, lenp)
int fn;
register FILE *fp;
int *lenp;
{
register char *op;
register int c, sum, nl, len;
char obuf[FOBUFSIZ + 8];
int ret;
#if !defined(BSD4_2) && !defined(USG)
/* call ultouch occasionally */
if (--tc < 0) {
tc = TC;
ultouch();
}
#endif !defined(BSD4_2) && !defined(USG)
op = obuf;
nl = 0;
len = 0;
sum = fchksum;
while ((c = getc(fp)) != EOF) {
len++;
if (sum & 0x8000) {
sum <<= 1;
sum++;
} else
sum <<= 1;
sum += c;
sum &= 0xffff;
if (c & 0200) {
c &= 0177;
if (c < 040) {
*op++ = '\174';
*op++ = c + 0100;
} else
if (c <= 0171) {
*op++ = '\175';
*op++ = c;
}
else {
*op++ = '\176';
*op++ = c - 0100;
}
nl += 2;
} else {
if (c < 040) {
*op++ = '\172';
*op++ = c + 0100;
nl += 2;
} else
if (c <= 0171) {
*op++ = c;
nl++;
} else {
*op++ = '\173';
*op++ = c - 0100;
nl += 2;
}
}
if (nl >= FOBUFSIZ - 1) {
/*
* peek at next char, see if it will fit
*/
c = getc(fp);
if (c == EOF)
break;
(void) ungetc(c, fp);
if (nl >= FOBUFSIZ || c < 040 || c > 0171)
goto writeit;
}
}
/*
* At EOF - append checksum, there is space for it...
*/
sprintf(op, "\176\176%04x\r", sum);
nl += strlen(op);
writeit:
*lenp = len;
fchksum = sum;
DEBUG(8, "%d/", len);
DEBUG(8, "%d,", nl);
ret = write(fn, obuf, nl);
return ret == nl ? nl : ret < 0 ? 0 : -ret;
}
static
frdblk(ip, fn, rlen)
register char *ip;
int fn;
long *rlen;
{
register char *op, c;
register int sum, len, nl;
char buf[5], *erbp = ip;
int i;
static char special = 0;
#if !defined(BSD4_2) && !defined(USG)
/* call ultouch occasionally */
if (--tc < 0) {
tc = TC;
ultouch();
}
#endif !defined(BSD4_2) && !defined(USG)
if ((len = frdbuf(ip, FIBUFSIZ, fn)) == FAIL) {
*rlen = 0;
goto dcorr;
}
*rlen = len;
DEBUG(8, "%d/", len);
op = ip;
nl = 0;
sum = fchksum;
do {
if ((*ip &= 0177) >= '\172') {
if (special) {
DEBUG(8, "%d", nl);
special = 0;
op = buf;
if (*ip++ != '\176' || (i = --len) > 5)
goto dcorr;
while (i--)
*op++ = *ip++ & 0177;
while (len < 5) {
i = frdbuf(&buf[len], 5 - len, fn);
if (i == FAIL) {
len = FAIL;
goto dcorr;
}
DEBUG(8, ",%d", i);
len += i;
*rlen += i;
while (i--)
*op++ &= 0177;
}
if (buf[4] != '\r')
goto dcorr;
sscanf(buf, "%4x", &fchksum);
DEBUG(8, "\nchecksum: %04x\n", sum);
if (fchksum == sum)
return FIBUFSIZ + 1 + nl;
else {
DEBUG(8, "\n", 0);
DEBUG(4, "Bad checksum\n", 0);
return FAIL;
}
}
special = *ip++;
} else {
if (*ip < '\040') {
/* error: shouldn't get control chars */
goto dcorr;
}
switch (special) {
case 0:
c = *ip++;
break;
case '\172':
c = *ip++ - 0100;
break;
case '\173':
c = *ip++ + 0100;
break;
case '\174':
c = *ip++ + 0100;
break;
case '\175':
c = *ip++ + 0200;
break;
case '\176':
c = *ip++ + 0300;
break;
}
*op++ = c;
if (sum & 0x8000) {
sum <<= 1;
sum++;
} else
sum <<= 1;
sum += c & 0377;
sum &= 0xffff;
special = 0;
nl++;
}
} while (--len);
fchksum = sum;
DEBUG(8, "%d,", nl);
return nl;
dcorr:
DEBUG(8, "\n", 0);
DEBUG(4, "Data corrupted\n", 0);
while (len != FAIL) {
if ((len = frdbuf(erbp, FIBUFSIZ, fn)) != FAIL)
*rlen += len;
}
return FAIL;
}

86
src/cmd/uucp/gename.c Normal file
View File

@@ -0,0 +1,86 @@
#ifndef lint
static char sccsid[] = "@(#)gename.c 5.6 (Berkeley) 10/9/85";
#endif
#include "uucp.h"
#include <strings.h>
#define SEQLEN 4
#define SLOCKTIME 10L
#define SLOCKTRIES 5
/*
* the alphabet can be anything, but if it's not in ascii order,
* sequence ordering is not preserved
*/
static char alphabet[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
#ifdef BSD4_2
#include <sys/file.h>
#endif
/*LINTLIBRARY*/
/*
* generate file name
*/
gename(pre, sys, grade, file)
char pre, *sys, grade, *file;
{
register int i, fd;
static char snum[5];
static char *lastchar = NULL;
if (lastchar == NULL || (snum[SEQLEN-1] = *(lastchar++)) == '\0') {
#ifndef BSD4_2
for (i = 0; i < SLOCKTRIES; i++) {
if (!ulockf(SEQLOCK, SLOCKTIME))
break;
sleep(5);
}
if (i >= SLOCKTRIES) {
logent(SEQLOCK, "CAN NOT LOCK");
goto getrandseq;
}
#endif
if ((fd = open(SEQFILE, 2)) >= 0) {
register char *p;
#ifdef BSD4_2
flock(fd, LOCK_EX);
#endif
read(fd, snum, SEQLEN);
/* increment the penultimate character */
for (i = SEQLEN - 2; i >= 0; --i) {
if ((p = index(alphabet, snum[i])) == NULL)
goto getrandseq;
if (++p < &alphabet[sizeof alphabet - 1]) {
snum[i] = *p;
break;
} else /* carry */
snum[i] = alphabet[0]; /* continue */
}
snum[SEQLEN-1] = alphabet[0];
} else {
extern int errno;
fd = creat(SEQFILE, 0666);
getrandseq: srand((int)time((time_t *)0));
assert(SEQFILE, "is missing or trashed\n", errno);
for (i = 0; i < SEQLEN; i++)
snum[i] = alphabet[rand() % (sizeof alphabet - 1)];
snum[SEQLEN-1] = alphabet[0];
}
if (fd >= 0) {
lseek(fd, 0L, 0);
write(fd, snum, SEQLEN);
close(fd);
}
#ifndef BSD4_2
rmlock(SEQLOCK);
#endif
lastchar = alphabet + 1;
}
sprintf(file,"%c.%.*s%c%.*s", pre, SYSNSIZE, sys, grade, SEQLEN, snum);
DEBUG(4, "file - %s\n", file);
}

98
src/cmd/uucp/getargs.c Normal file
View File

@@ -0,0 +1,98 @@
#ifndef lint
static char sccsid[] = "@(#)getargs.c 5.3 (Berkeley) 6/19/85";
#endif
#include "uucp.h"
/*LINTLIBRARY*/
/*
* getargs - this routine will generate a vector of
* pointers (arps) to the substrings in string "s".
* Each substring is separated by blanks and/or tabs.
*
* If FANCYARGS is defined, you get the following:
* Strings containing blanks may be specified by quoting,
* in a manner similar to using the shell.
* Control characters are entered by ^X where X is any
* character; ^? gets you a rubout and ^^ is a real ^.
* Warning (rti!trt): I doubt FANCYARGS is wise, since getargs
* is used all over the place. Its features may be useful
* but a separate fancy_getargs() should be called instead.
*
* return - the number of subfields, or -1 if >= maxargs.
*/
getargs(s, arps, maxargs)
register char *s;
char *arps[];
int maxargs;
{
register int i;
#ifdef FANCYARGS
register char *sp;
register char qchar;
#endif
i = 0;
#ifndef FANCYARGS
while (i < maxargs) {
while (*s == ' ' || *s == '\t')
*s++ = '\0';
if (*s == '\n')
*s = '\0';
if (*s == '\0')
break;
arps[i++] = s++;
while (*s != '\0' && *s != ' '
&& *s != '\t' && *s != '\n')
s++;
}
#else
while (i < maxargs) {
while (*s == ' ' || *s == '\t')
++s;
if (*s == '\n' || *s == '\0')
break;
arps[i++] = sp = s;
qchar = 0;
while(*s != '\0' && *s != '\n') {
if (qchar == 0 && (*s == ' ' || *s == '\t')) {
++s;
break;
}
switch(*s) {
default:
*sp++ = *s++;
break;
case '^':
if(*++s == '^')
*sp++ = '^';
else if(*s == '?')
*sp++ = 0177;
else
*sp++ = *s & 037;
s++;
break;
case '"':
case '\'':
if(qchar == *s) {
qchar = 0;
++s;
break;
}
if(qchar)
*sp++ = *s++;
else
qchar = *s++;
break;
}
}
*sp++ = 0;
}
#endif
if (i >= maxargs)
return FAIL;
arps[i] = NULL;
return i;
}

68
src/cmd/uucp/getprm.c Normal file
View File

@@ -0,0 +1,68 @@
#ifndef lint
static char sccsid[] = "@(#)getprm.c 5.4 (Berkeley) 10/9/85";
#endif
#include "uucp.h"
#include <strings.h>
#define LQUOTE '('
#define RQUOTE ')'
/*LINTLIBRARY*/
/*
* get next parameter from s
*
* return - pointer to next character in s
*/
char *
getprm(s, prm)
register char *s, *prm;
{
register char *c;
while (*s == ' ' || *s == '\t' || *s == '\n')
s++;
*prm = '\0';
if (*s == '\0')
return NULL;
if (*s == '>' || *s == '<' || *s == '|'
|| *s == ';' || *s == '&') {
*prm++ = *s++;
*prm = '\0';
return s;
}
/* look for quoted argument */
if (*s == LQUOTE) {
if ((c = index(s + 1, RQUOTE)) != NULL) {
c++;
while (c != s)
*prm++ = *s++;
*prm = '\0';
return s;
}
}
/* look for ` ` string */
if (*s == '`') {
if ((c = index(s + 1, '`')) != NULL) {
c++;
while (c != s)
*prm++ = *s++;
*prm = '\0';
return s;
}
}
while (*s != ' ' && *s != '\t' && *s != '<'
&& *s != '>' && *s != '|' && *s != '\0'
&& *s != '&' && *s != ';' && *s != '\n')
*prm++ = *s++;
*prm = '\0';
return s;
}

67
src/cmd/uucp/getpwinfo.c Normal file
View File

@@ -0,0 +1,67 @@
#if !defined(lint) && defined(DOSCCS)
static char sccsid[] = "@(#)getpwinfo.c 5.3.1 (2.11BSD) 1997/10/2";
#endif
#include "uucp.h"
#include <pwd.h>
/*LINTLIBRARY*/
/*
* get passwd file info for uid
*
* return codes: SUCCESS | FAIL
*
*/
guinfo(uid, name, path)
int uid;
register char *path, *name;
{
register struct passwd *pwd;
char *l;
if ((l = getlogin()) == NULL) {
l = getenv("USER");
}
if (l != NULL) {
pwd = getpwnam(l);
if (pwd != NULL && pwd->pw_uid == uid)
goto setup;
}
if ((pwd = getpwuid(uid)) == NULL) {
/* can not find uid in passwd file */
*name = '\0';
*path = '\0';
return FAIL;
}
setup:
strcpy(path, pwd->pw_dir);
strcpy(name, pwd->pw_name);
return SUCCESS;
}
/*
* get passwd file info for name
*
* return codes: SUCCESS | FAIL
*/
gninfo(name, uid, path)
char *path, *name;
int *uid;
{
register struct passwd *pwd;
if ((pwd = getpwnam(name)) == NULL) {
/* can not find name in passwd file */
*path = '\0';
return FAIL;
}
strcpy(path, pwd->pw_dir);
*uid = pwd->pw_uid;
return SUCCESS;
}

236
src/cmd/uucp/gio.c Normal file
View File

@@ -0,0 +1,236 @@
#ifndef lint
static char sccsid[] = "@(#)gio.c 5.6 (Berkeley) 10/9/85";
#endif
#include "uucp.h"
#include "pk.h"
#include <setjmp.h>
jmp_buf Failbuf;
int Retries = 0;
struct pack *Pk;
pkfail()
{
longjmp(Failbuf, 1);
}
gturnon()
{
struct pack *pkopen();
if (setjmp(Failbuf))
return FAIL;
Pk = pkopen(Ifn, Ofn);
if (Pk == NULL)
return FAIL;
return SUCCESS;
}
gturnoff()
{
if(setjmp(Failbuf))
return(FAIL);
pkclose(Pk);
return SUCCESS;
}
gwrmsg(type, str, fn)
char type;
register char *str;
{
char bufr[BUFSIZ];
register char *s;
int len, i;
if(setjmp(Failbuf))
return(FAIL);
bufr[0] = type;
s = &bufr[1];
while (*str)
*s++ = *str++;
*s = '\0';
if (*(--s) == '\n')
*s = '\0';
len = strlen(bufr) + 1;
if ((i = len % PACKSIZE)) {
len = len + PACKSIZE - i;
bufr[len - 1] = '\0';
}
gwrblk(bufr, len, fn);
return SUCCESS;
}
/*ARGSUSED*/
grdmsg(str, fn)
register char *str;
{
unsigned len;
if(setjmp(Failbuf))
return FAIL;
for (;;) {
len = pkread(Pk, str, PACKSIZE);
if (len == 0)
continue;
str += len;
if (*(str - 1) == '\0')
break;
}
return SUCCESS;
}
gwrdata(fp1, fn)
FILE *fp1;
{
char bufr[BUFSIZ];
register int len;
int ret, mil;
struct timeb t1, t2;
long bytes;
char text[BUFSIZ];
if(setjmp(Failbuf))
return FAIL;
bytes = 0L;
Retries = 0;
#ifdef USG
time(&t1.time);
t1.millitm = 0;
#else
ftime(&t1);
#endif
while ((len = read(fileno(fp1), bufr, BUFSIZ)) > 0) {
bytes += len;
ret = gwrblk(bufr, len, fn);
if (ret != len) {
return FAIL;
}
if (len != BUFSIZ)
break;
}
ret = gwrblk(bufr, 0, fn);
#ifdef USG
time(&t2.time);
t2.millitm = 0;
#else
ftime(&t2);
#endif
Now = t2;
t2.time -= t1.time;
mil = t2.millitm - t1.millitm;
if (mil < 0) {
--t2.time;
mil += 1000;
}
sprintf(text, "sent data %ld bytes %ld.%02d secs",
bytes, (long)t2.time, mil/10);
sysacct(bytes, t2.time);
if (Retries > 0)
sprintf((char *)text+strlen(text)," %d retries", Retries);
DEBUG(1, "%s\n", text);
syslog(text);
return SUCCESS;
}
grddata(fn, fp2)
FILE *fp2;
{
register int len;
char bufr[BUFSIZ];
struct timeb t1, t2;
int mil;
long bytes;
char text[BUFSIZ];
if(setjmp(Failbuf))
return FAIL;
bytes = 0L;
Retries = 0;
#ifdef USG
time(&t1.time);
t1.millitm = 0;
#else
ftime(&t1);
#endif
for (;;) {
len = grdblk(bufr, BUFSIZ, fn);
if (len < 0) {
return FAIL;
}
bytes += len;
if (write(fileno(fp2), bufr, len) != len)
return FAIL;
if (len < BUFSIZ)
break;
}
#ifdef USG
time(&t2.time);
t2.millitm = 0;
#else
ftime(&t2);
#endif
Now = t2;
t2.time -= t1.time;
mil = t2.millitm - t1.millitm;
if (mil < 0) {
--t2.time;
mil += 1000;
}
sprintf(text, "received data %ld bytes %ld.%02d secs",
bytes, (long)t2.time, mil/10);
sysacct(bytes, t2.time);
if (Retries > 0)
sprintf((char *)text+strlen(text)," %d retries", Retries);
DEBUG(1, "%s\n", text);
syslog(text);
return SUCCESS;
}
#if !defined(BSD4_2) && !defined(USG)
/* call ultouch every TC calls to either grdblk or gwrblk */
#define TC 20
static int tc = TC;
#endif
/*ARGSUSED*/
grdblk(blk, len, fn)
register int len;
char *blk;
{
register int i, ret;
#if !defined(BSD4_2) && !defined(USG)
/* call ultouch occasionally */
if (--tc < 0) {
tc = TC;
ultouch();
}
#endif
for (i = 0; i < len; i += ret) {
ret = pkread(Pk, blk, len - i);
if (ret < 0)
return FAIL;
blk += ret;
if (ret == 0)
return i;
}
return i;
}
/*ARGSUSED*/
gwrblk(blk, len, fn)
register char *blk;
{
#if !defined(BSD4_2) && !defined(USG)
/* call ultouch occasionally */
if (--tc < 0) {
tc = TC;
ultouch();
}
#endif
return pkwrite(Pk, blk, len);
}

41
src/cmd/uucp/gnamef.c Normal file
View File

@@ -0,0 +1,41 @@
#ifndef lint
static char sccsid[] = "@(#)gnamef.c 5.4 (Berkeley) 6/20/85";
#endif
#include "uucp.h"
#ifdef NDIR
#include "ndir.h"
#else
#include <sys/dir.h>
#endif
/*LINTLIBRARY*/
/*
* get next file name from directory
*
* return codes:
* 0 - end of directory read
* 1 - returned name
*/
gnamef(dirp, filename)
register DIR *dirp;
register char *filename;
{
register struct direct *dentp;
for (;;) {
if ((dentp = readdir(dirp)) == NULL) {
return 0;
}
if (dentp->d_ino != 0)
break;
}
/* Truncate filename. This may become a problem someday. */
strncpy(filename, dentp->d_name, NAMESIZE-1);
filename[NAMESIZE-1] = '\0';
DEBUG(99,"gnamef returns %s\n",filename);
return 1;
}

137
src/cmd/uucp/gnsys.c Normal file
View File

@@ -0,0 +1,137 @@
#if !defined(lint) && defined(DOSCCS)
static char sccsid[] = "@(#)gnsys.c 5.4.1 (2.11BSD) 1997/10/31";
#endif
#include "uucp.h"
#include <strings.h>
#ifdef NDIR
#include "ndir.h"
#else
#include <sys/dir.h>
#endif
#define LSIZE 128 /* number of systems to store */
#define WSUFSIZE 6 /* work file name suffix size */
/*LINTLIBRARY*/
/*
* this routine will return the next system name which has work to be done.
* "sname" is a string of size DIRSIZ - WSUFSIZE.
* "pre" is the prefix for work files.
* "dir" is the directory to search.
*
* return codes:
* 1 - name returned in sname
* SUCCESS - no more names
* FAIL - bad directory
*/
gnsys(sname, dir, pre)
char *sname, *dir, pre;
{
register char *s, *p1, *p2;
char px[3];
static char *list[LSIZE];
static int nitem=0, n=0, base=0;
char systname[NAMESIZE], filename[NAMESIZE];
DIR *dirp;
retry:
px[0] = pre;
px[1] = '.';
px[2] = '\0';
if (nitem == base) {
/* get list of systems with work */
int i;
dirp = opendir(subdir(dir,pre));
ASSERT(dirp != NULL, "BAD DIRECTORY", dir, 0);
for (i = base; i < LSIZE; i++)
list[i] = NULL;
while (gnamef(dirp, filename) != 0) {
if (!prefix(px, filename))
continue;
p2 = filename + strlen(filename)
- WSUFSIZE;
p1 = filename + strlen(px);
for(s = systname; p1 <= p2; p1++)
*s++ = *p1;
*s = '\0';
if (systname[0] == '\0')
continue;
nitem = srchst(systname, list, nitem);
if (LSIZE <= nitem) break;
}
closedir(dirp);
}
if (nitem == base) {
for (n = 0; n < nitem; n++)
if (list[n] != NULL)
free(list[n]);
return SUCCESS;
}
while(nitem > n) {
/* We only have at most a SYSNSIZE character site name encoded
* in the file. However, we would like to use the full sitename
* if possible. If the number of chars in list[n] is < SYSNSIZE
* then the sitename could not have been truncated and
* we don't bother to check. Otherwise, we scan SYSFILE
* looking for the fullname and return it if we find it
*/
strcpy(sname, list[n++]);
if (strlen(sname) >= SYSNSIZE) {
register FILE *fp;
register char *p;
char line[MAXFULLNAME];
fp = fopen(SYSFILE, "r");
ASSERT(fp != NULL, CANTOPEN, SYSFILE, 0);
while (cfgets(line, sizeof(line), fp) != NULL) {
p = index(line, ' ');
if (p)
*p = '\0';
if (strncmp(sname, line, SYSNSIZE) == SAME) {
strncpy(sname, line, MAXBASENAME);
break;
}
}
fclose(fp);
}
if (callok(sname) == 0)
return 1;
}
base = n = nitem;
goto retry;
}
/*
* this routine will do a linear search of list (list) to find name (name).
* If the name is not found, it is added to the list.
* The number of items in the list (n) is returned (incremented if a
* name is added).
*
* return codes:
* n - the number of items in the list
*/
srchst(name, list, n)
char *name;
register char **list;
int n;
{
register int i;
register char *p;
for (i = 0; i < n; i++)
if (strcmp(name, list[i]) == 0)
break;
if (i >= n) {
if ((p = (char *)calloc(strlen(name) + 1, sizeof (char)))
== NULL)
return n;
strcpy(p, name);
list[n++] = p;
}
return n;
}

122
src/cmd/uucp/gnxseq.c Normal file
View File

@@ -0,0 +1,122 @@
#ifndef lint
static char sccsid[] = "@(#)gnxseq.c 5.4 (Berkeley) 6/20/85";
#endif
#include "uucp.h"
#ifdef BSD4_2
#include <sys/time.h>
#else sane
#include <time.h>
#endif sane
/*LINTLIBRARY*/
#ifdef GNXSEQ
/*
* get next conversation sequence number
*
* return - 0 no entry | >0 sequence number
*/
gnxseq(rmtname)
char *rmtname;
{
int count = 0, ct, ret, i;
register struct tm *tp;
extern struct tm *localtime();
time_t clock;
register FILE *fp0, *fp1;
char buf[BUFSIZ], name[NAMESIZE];
if (access(SQFILE, 0) != 0) /* nothing to do here */
return(0);
for (i = 0; i < 5; i++) {
if ((ret = ulockf(SQLOCK, (time_t) SQTIME)) == 0)
break;
sleep(5);
}
if (ret != 0) {
logent("CAN'T LOCK", SQLOCK);
DEBUG(4, "can't lock %s\n", SQLOCK);
return(0);
}
if ((fp0 = fopen(SQFILE, "r")) == NULL)
return(0);
if ((fp1 = fopen(SQTMP, "w")) == NULL) {
fclose(fp0);
return(0);
}
chmod(SQTMP, 0400);
while (fgets(buf, BUFSIZ, fp0) != NULL) {
ret = sscanf(buf, "%s%d", name, &ct);
if (ret < 2)
ct = 0;
name[MAXBASENAME] = '\0';
if (ct > 9998)
ct = 0;
if (strncmp(rmtname, name, MAXBASENAME) != SAME) {
fputs(buf, fp1);
continue;
}
/* found name */
count = ++ct;
time(&clock);
tp = localtime(&clock);
#ifdef USG
fprintf(fp1, "%s %d %d/%d-%2.2d:%2.2d\n", name, ct,
tp->tm_mon + 1, tp->tm_mday, tp->tm_hour,
tp->tm_min);
#endif
#ifndef USG
fprintf(fp1, "%s %d %d/%d-%02d:%02d\n", name, ct,
tp->tm_mon + 1, tp->tm_mday, tp->tm_hour,
tp->tm_min);
#endif
while (fgets(buf, BUFSIZ, fp0) != NULL)
fputs(buf, fp1);
}
fclose(fp0);
fclose(fp1);
if (count == 0) {
rmlock(SQLOCK);
unlink(SQTMP);
}
return(count);
}
/***
* cmtseq() commit sequence update
*
* return 0 ok | other - link failed
*/
cmtseq()
{
register int ret;
if ((ret = access(SQTMP, 04)) != 0) {
rmlock(SQLOCK);
return(0);
}
unlink(SQFILE);
ret = link(SQTMP, SQFILE);
unlink(SQTMP);
rmlock(SQLOCK);
return(ret);
}
/***
* ulkseq() unlock sequence file
*/
ulkseq()
{
unlink(SQTMP);
rmlock(SQLOCK);
}
#endif GNXSEQ

101
src/cmd/uucp/imsg.c Normal file
View File

@@ -0,0 +1,101 @@
#ifndef lint
static char sccsid[] = "@(#)imsg.c 5.3 (Berkeley) 1/6/86";
#endif
#include "uucp.h"
#include <ctype.h>
char Msync[2] = "\020";
/* to talk to both eunice and x.25 without also screwing up tcp/ip
* we must adaptively choose what character to end the msg with
*
* The idea is that initially we send ....\000\n
* Then, after they have sent us a message, we use the first character
* they send.
*/
int seenend = 0;
char Mend = '\0';
/*
* this is the initial read message routine -
* used before a protocol is agreed upon.
*
* return codes:
* FAIL - no more messages
* SUCCESS - message returned
*/
imsg(amsg, fn)
char *amsg;
register int fn;
{
register char *msg = amsg;
int foundsync = FAIL;
char c;
DEBUG(5, "imsg looking for SYNC<", CNULL);
for (;;) {
if (read(fn, &c, 1) != 1)
return FAIL;
c &= 0177;
if (c == '\n' || c == '\r')
DEBUG(5, "%c", c);
else
DEBUG(5, (isprint(c) || isspace(c)) ? "%c" : "\\%o",
c & 0377);
if (c == Msync[0]) {
DEBUG(5, ">\nimsg input<", CNULL);
msg = amsg;
foundsync = SUCCESS;
continue;
} else if (foundsync != SUCCESS)
continue;
if (c == '\n' || c == '\0') {
if (!seenend) {
Mend = c;
seenend++;
DEBUG(9, "\nUsing \\%o as End of message char\n", Mend);
}
break;
}
*msg++ = c;
fflush(stderr);
}
*msg = '\0';
DEBUG(5, ">got %d characters\n", strlen(amsg));
return foundsync;
}
/*
* this is the initial write message routine -
* used before a protocol is agreed upon.
*
* return code: always 0
*/
omsg(type, msg, fn)
register char *msg;
char type;
int fn;
{
char buf[MAXFULLNAME];
register char *c;
c = buf;
*c = '\0'; /* avoid pdp 11/23,40 auto-incr stack trap bug */
*c++ = Msync[0];
*c++ = type;
while (*msg)
*c++ = *msg++;
*c++ = '\0';
DEBUG(5, "omsg <%s>\n", buf);
if (seenend)
c[-1] = Mend;
else
*c++ = '\n';
write(fn, buf, (int)(c - buf));
return 0;
}

27
src/cmd/uucp/lastpart.c Normal file
View File

@@ -0,0 +1,27 @@
#ifndef lint
static char sccsid[] = "@(#)lastpart.c 5.4 (Berkeley) 6/20/85";
#endif
#include <strings.h>
#include "uucp.h"
/*LINTLIBRARY*/
/*
* find last part of file name
*
* return - pointer to last part
*/
char *
lastpart(file)
register char *file;
{
register char *c;
c = rindex(file, '/');
if (c++)
return c;
else
return file;
}

235
src/cmd/uucp/logent.c Normal file
View File

@@ -0,0 +1,235 @@
#ifndef lint
static char sccsid[] = "@(#)logent.c 5.6 (Berkeley) 10/9/85";
#endif
#include "uucp.h"
#ifdef BSD4_2
#include <sys/time.h>
#else
#include <time.h>
#endif
#if defined(USG) || defined(BSD4_2)
#include <fcntl.h>
#endif
static FILE *Lp = NULL;
static FILE *Sp = NULL;
static Ltried = 0;
static Stried = 0;
/*LINTLIBRARY*/
/*
* make log entry
*/
logent(text, status)
char *text, *status;
{
#ifdef LOGBYSITE
char lfile[MAXFULLNAME];
static char LogRmtname[64];
#endif
if (Rmtname[0] == '\0')
strcpy(Rmtname, Myname);
/* Open the log file if necessary */
#ifdef LOGBYSITE
if (strcmp(Rmtname, LogRmtname)) {
if (Lp != NULL)
fclose(Lp);
Lp = NULL;
Ltried = 0;
}
#endif
if (Lp == NULL) {
if (!Ltried) {
int savemask;
#ifdef F_SETFL
int flags;
#endif
savemask = umask(LOGMASK);
#ifdef LOGBYSITE
(void) sprintf(lfile, "%s/%s/%s", LOGBYSITE, Progname, Rmtname);
strcpy(LogRmtname, Rmtname);
Lp = fopen (lfile, "a");
#else
Lp = fopen (LOGFILE, "a");
#endif
umask(savemask);
#ifdef F_SETFL
flags = fcntl(fileno(Lp), F_GETFL, 0);
fcntl(fileno(Lp), F_SETFL, flags|O_APPEND);
#endif
}
Ltried = 1;
if (Lp == NULL)
return;
fioclex(fileno(Lp));
}
/* make entry in existing temp log file */
mlogent(Lp, status, text);
}
/*
* make a log entry
*/
mlogent(fp, status, text)
char *text, *status;
register FILE *fp;
{
static pid = 0;
register struct tm *tp;
extern struct tm *localtime();
if (text == NULL)
text = "";
if (status == NULL)
status = "";
if (!pid)
pid = getpid();
#ifdef USG
time(&Now.time);
Now.millitm = 0;
#else
ftime(&Now);
#endif
tp = localtime(&Now.time);
#ifdef USG
fprintf(fp, "%s %s (%d/%d-%2.2d:%2.2d-%d) ",
#else
fprintf(fp, "%s %s (%d/%d-%02d:%02d-%d) ",
#endif
User, Rmtname, tp->tm_mon + 1, tp->tm_mday,
tp->tm_hour, tp->tm_min, pid);
fprintf(fp, "%s (%s)\n", status, text);
/* Since it's buffered */
#ifndef F_SETFL
lseek (fileno(fp), (long)0, 2);
#endif
fflush (fp);
if (Debug) {
fprintf(stderr, "%s %s ", User, Rmtname);
#ifdef USG
fprintf(stderr, "(%d/%d-%2.2d:%2.2d-%d) ", tp->tm_mon + 1,
tp->tm_mday, tp->tm_hour, tp->tm_min, pid);
#else
fprintf(stderr, "(%d/%d-%02d:%02d-%d) ", tp->tm_mon + 1,
tp->tm_mday, tp->tm_hour, tp->tm_min, pid);
#endif
fprintf(stderr, "%s (%s)\n", status, text);
}
}
/*
* close log file
*/
logcls()
{
if (Lp != NULL)
fclose(Lp);
Lp = NULL;
Ltried = 0;
if (Sp != NULL)
fclose (Sp);
Sp = NULL;
Stried = 0;
}
/*
* make system log entry
*/
syslog(text)
char *text;
{
register struct tm *tp;
extern struct tm *localtime();
#ifdef LOGBYSITE
char lfile[MAXFULLNAME];
static char SLogRmtname[64];
if (strcmp(Rmtname, SLogRmtname)) {
if (Sp != NULL)
fclose(Sp);
Sp = NULL;
Stried = 0;
}
#endif
if (Sp == NULL) {
if (!Stried) {
int savemask;
#ifdef F_SETFL
int flags;
#endif
savemask = umask(LOGMASK);
#ifdef LOGBYSITE
(void) sprintf(lfile, "%s/xferstats/%s", LOGBYSITE, Rmtname);
strcpy(SLogRmtname, Rmtname);
Sp = fopen (lfile, "a");
#else
Sp = fopen (SYSLOG, "a");
#endif
umask(savemask);
#ifdef F_SETFL
flags = fcntl(fileno(Sp), F_GETFL, 0);
fcntl(fileno(Sp), F_SETFL, flags|O_APPEND);
#endif
}
Stried = 1;
if (Sp == NULL)
return;
fioclex(fileno(Sp));
}
#ifdef USG
time(&Now.time);
Now.millitm = 0;
#else
ftime(&Now);
#endif
tp = localtime(&Now.time);
fprintf(Sp, "%s %s ", User, Rmtname);
#ifdef USG
fprintf(Sp, "(%d/%d-%2.2d:%2.2d) ", tp->tm_mon + 1,
tp->tm_mday, tp->tm_hour, tp->tm_min);
fprintf(Sp, "(%ld) %s\n", Now.time, text);
#else
fprintf(Sp, "(%d/%d-%02d:%02d) ", tp->tm_mon + 1,
tp->tm_mday, tp->tm_hour, tp->tm_min);
fprintf(Sp, "(%ld.%02u) %s\n", Now.time, Now.millitm/10, text);
#endif
/* Position at end and flush */
#ifndef F_SETFL
lseek (fileno(Sp), (long)0, 2);
#endif
fflush (Sp);
}
/*
* Arrange to close fd on exec(II).
* Otherwise unwanted file descriptors are inherited
* by other programs. And that may be a security hole.
*/
#ifndef USG
#include <sgtty.h>
#endif
fioclex(fd)
int fd;
{
register int ret;
#if defined(USG) || defined(BSD4_2)
ret = fcntl(fd, F_SETFD, 1); /* Steve Bellovin says this does it */
#else
ret = ioctl(fd, FIOCLEX, STBNULL);
#endif
if (ret)
DEBUG(2, "CAN'T FIOCLEX %d\n", fd);
}

105
src/cmd/uucp/mailst.c Normal file
View File

@@ -0,0 +1,105 @@
#if !defined(lint) && defined(DOSCCS)
static char sccsid[] = "@(#)mailst.c 5.6.1 (2.11BSD GTE) 6/11/94";
#endif
#include <signal.h>
#include "uucp.h"
#ifdef USG
#include <fcntl.h>
#endif
/*LINTLIBRARY*/
/*
* mailst - this routine will fork and execute
* a mail command sending string (str) to user (user).
* If file is non-null, the file is also sent.
* (this is used for mail returned to sender.)
*/
mailst(user, str, file)
char *user, *str, *file;
{
register FILE *fp, *fi;
char buf[BUFSIZ];
register int c;
sprintf(buf, "%s '%s'", _PATH_SENDMAIL, user);
if ((fp = rpopen(buf, "w")) != NULL) {
fprintf(fp, "From: uucp\nTo: %s\nSubject: %s\n\n", user, str);
if (file && *file != '\0' && (fi = fopen(subfile(file), "r")) != NULL) {
while ((c = getc(fi)) != EOF)
putc(c, fp);
putc('\n', fp);
fclose(fi);
}
rpclose(fp);
}
}
/*
* 'reverting' version of popen
* which runs process with permissions of real gid/uid
* rather than the effective gid/uid.
*/
#define tst(a,b) (*mode == 'r'? (b) : (a))
#define RDR 0
#define WTR 1
static int popen_pid[20];
FILE *
rpopen(cmd, mode)
char *cmd;
char *mode;
{
int p[2];
register myside, hisside, pid;
if(pipe(p) < 0)
return NULL;
myside = tst(p[WTR], p[RDR]);
hisside = tst(p[RDR], p[WTR]);
if((pid = fork()) == 0) {
/* myside and hisside reverse roles in child */
close(myside);
#ifdef USG
close(tst(0, 1));
fcntl(hisside, F_DUPFD, tst(0, 1));
#else
dup2(hisside, tst(0, 1));
#endif
close(hisside);
/* revert permissions */
setgid(getgid());
setuid(getuid());
execl("/bin/sh", "sh", "-c", cmd, (char *)0);
_exit(1);
}
if(pid == -1)
return NULL;
popen_pid[myside] = pid;
close(hisside);
return(fdopen(myside, mode));
}
rpclose(ptr)
FILE *ptr;
{
register f, r;
register sig_t hstat, istat, qstat;
int status;
f = fileno(ptr);
fclose(ptr);
istat = signal(SIGINT, SIG_IGN);
qstat = signal(SIGQUIT, SIG_IGN);
hstat = signal(SIGHUP, SIG_IGN);
while((r = wait(&status)) != popen_pid[f] && r != -1)
;
if(r == -1)
status = -1;
signal(SIGINT, (sig_t)istat);
signal(SIGQUIT, (sig_t)qstat);
signal(SIGHUP, (sig_t)hstat);
return status;
}

128
src/cmd/uucp/pk.h Normal file
View File

@@ -0,0 +1,128 @@
/* pk.h 5.4 86/01/06 */
struct header {
char sync;
char ksize;
unsigned short sum;
char cntl;
char ccntl;
};
#define HDRSIZ 6 /* Packet header size */
#define PACKSIZE 64 /* Standard packet size */
#define WINDOWS 7
#define TAILSIZE 2 /* Number of trailing nulls after packet */
struct pack {
short p_state; /* line state */
short p_bits; /* mask for getepack */
short p_rsize; /* input packet size */
short p_xsize; /* output packet size */
struct header p_ihbuf; /* input header */
struct header p_ohbuf; /* output header */
char *p_rptr;
char p_mode;
char **p_ipool;
char p_xcount; /* # active output buffers */
char p_rcount;
char p_nout,p_tout;
char p_lpsize; /* log(psize/32) */
char p_timer;
char p_obusy;
char p_srxmit;
char p_rwindow; /* window size */
char p_swindow;
char p_msg; /* control msg */
char p_rmsg; /* repeated control msg */
char p_ps,p_pr; /* last packet sent, recv'd */
char p_rpr;
char p_nxtps; /* next output seq number */
char p_imap; /* bit map of input buffers */
char p_pscopy; /* newest output packet */
char *p_ob[8]; /* output buffers */
char *p_ib[8]; /* input buffers */
char p_os[8]; /* output buffer status */
char p_is[8]; /* input buffer status */
short p_osum[8]; /* output checksums */
short p_isum[8]; /* input checksums */
int p_ifn, p_ofn;
};
#define CHECK 0125252
#define SYN 020
#define MOD8 7
#define ISCNTL(a) ((a & 0300)==0)
/* MIN may have been defined in <sys/param.h> */
#undef MIN
#define MIN(a,b) ((a<b)? a:b)
extern char next[8];
extern char mask[8];
/*
* driver state
*/
#define DEAD 0
#define INITa 1
#define INITb 2
#define INITab 3
#define LIVE 010
#define RXMIT 020
#define RREJ 040
#define PDEBUG 0200
#define DRAINO 0400
#define WAITO 01000
#define DOWN 02000
#define RCLOSE 04000
#define BADFRAME 020000
/*
* io buffer states
*/
#define B_NULL 0
#define B_READY 1
#define B_SENT 2
#define B_RESID 010
#define B_COPY 020
#define B_MARK 040
#define B_SHORT 0100
/* read or write */
#define B_WRITE 0
#define B_READ 1
/*
* control messages
*/
#define CLOSE 1
#define RJ 2
#define SRJ 3
#define RR 4
#define INITC 5
#define INITB 6
#define INITA 7
#define M_CLOSE 002
#define M_RJ 004
#define M_SRJ 010
#define M_RR 020
#define M_INITC 040
#define M_INITA 0200
#define M_INITB 0100
#define NPLINES 20
/*
* packet ioctl buf
*/
struct piocb {
unsigned t;
short psize;
short mode;
short state;
char window;
};
extern int pksizes[];

573
src/cmd/uucp/pk0.c Normal file
View File

@@ -0,0 +1,573 @@
#if !defined(lint) && defined(DOSCCS)
static char sccsid[] = "@(#)pk0.c 5.7.1 (2.11BSD) 1997/10/2";
#endif
#include "uucp.h"
#include "pk.h"
/*
* packet driver
*/
char next[8] = { 1, 2, 3, 4, 5, 6, 7, 0}; /* packet sequence numbers */
char mask[8] = { 1, 2, 4, 010, 020, 040, 0100, 0200 };
struct pack *pklines[NPLINES];
int Reacks;
#define PKRTIME 4
#define PKWTIME 4
#define PKRSKEW 3
#define PKWSKEW 2
extern int pktimeout, pktimeskew, Ntimeout;
/*
* receive control messages
*/
pkcntl(c, pk)
register struct pack *pk;
{
register cntl, val;
val = c & MOD8;
cntl = (c>>3) & MOD8;
if (!ISCNTL(c)) {
logent("PK0", "not cntl");
return;
}
switch(cntl) {
case INITB:
val++;
pk->p_xsize = pksizes[val];
pk->p_lpsize = val;
pk->p_bits = 1;
if (pk->p_state & LIVE) {
pk->p_msg |= M_INITC;
break;
}
pk->p_state |= INITb;
if ((pk->p_state & INITa)==0) {
break;
}
pk->p_rmsg &= ~M_INITA;
pk->p_msg |= M_INITC;
break;
case INITC:
if ((pk->p_state&INITab)==INITab) {
pk->p_state = LIVE;
pk->p_rmsg &= ~M_INITB;
} else
pk->p_msg |= M_INITB;
if (val)
pk->p_swindow = val;
break;
case INITA:
if (val == 0 && pk->p_state&LIVE) {
logent("PK0", "alloc change not implemented");
break;
}
if (val) {
pk->p_state |= INITa;
pk->p_msg |= M_INITB;
pk->p_rmsg |= M_INITB;
pk->p_swindow = val;
}
break;
case RJ:
pk->p_state |= RXMIT;
pk->p_msg |= M_RR;
pk->p_rpr = val;
(void) pksack(pk);
break;
case RR:
pk->p_rpr = val;
if (pk->p_rpr == pk->p_ps) {
DEBUG(9, "Reack count is %d\n", ++Reacks);
if (Reacks >= 4) {
DEBUG(6, "Reack overflow on %d\n", val);
pk->p_state |= RXMIT;
pk->p_msg |= M_RR;
Reacks = 0;
}
} else {
Reacks = 0;
(void) pksack(pk);
}
break;
case SRJ:
logent("PK0", "srj not implemented");
break;
case CLOSE:
pk->p_state = DOWN+RCLOSE;
return;
}
if (pk->p_msg)
pkoutput(pk);
}
pkaccept(pk)
register struct pack *pk;
{
register x, seq;
char m, cntl, *p, imask, **bp;
int bad, accept, skip, t, cc;
unsigned short sum;
bad = accept = skip = 0;
/*
* wait for input
*/
x = next[pk->p_pr];
while ((imask=pk->p_imap) == 0 && pk->p_rcount == 0) {
pkgetpack(pk);
}
pk->p_imap = 0;
/*
* determine input window in m.
*/
t = (~(-1<<(int)(pk->p_rwindow))) <<x;
m = t;
m |= t>>8;
/*
* mark newly accepted input buffers
*/
for(x=0; x<8; x++) {
if ((imask & mask[x]) == 0)
continue;
if (((cntl=pk->p_is[x])&0200) == 0) {
bad++;
free:
bp = (char **)pk->p_ib[x];
*bp = (char *)pk->p_ipool;
pk->p_ipool = bp;
pk->p_is[x] = 0;
continue;
}
pk->p_is[x] = ~(B_COPY+B_MARK);
sum = (unsigned)chksum(pk->p_ib[x], pk->p_rsize) ^ (unsigned)(cntl&0377);
sum += pk->p_isum[x];
if (sum == CHECK) {
seq = (cntl>>3) & MOD8;
if (m & mask[seq]) {
if (pk->p_is[seq] & (B_COPY | B_MARK)) {
dup:
pk->p_msg |= M_RR;
skip++;
goto free;
}
if (x != seq) {
p = pk->p_ib[x];
pk->p_ib[x] = pk->p_ib[seq];
pk->p_is[x] = pk->p_is[seq];
pk->p_ib[seq] = p;
}
pk->p_is[seq] = B_MARK;
accept++;
cc = 0;
if (cntl&B_SHORT) {
pk->p_is[seq] = B_MARK+B_SHORT;
p = pk->p_ib[seq];
cc = (unsigned)*p++ & 0377;
if (cc & 0200) {
cc &= 0177;
cc |= *p << 7;
}
}
pk->p_isum[seq] = pk->p_rsize - cc;
} else {
goto dup;
}
} else {
bad++;
goto free;
}
}
/*
* scan window again turning marked buffers into
* COPY buffers and looking for missing sequence
* numbers.
*/
accept = 0;
t = -1;
for(x=next[pk->p_pr]; m & mask[x]; x = next[x]) {
if (pk->p_is[x] & B_MARK)
pk->p_is[x] |= B_COPY;
if (pk->p_is[x] & B_COPY) {
if (t >= 0) {
bp = (char **)pk->p_ib[x];
*bp = (char *)pk->p_ipool;
pk->p_ipool = bp;
pk->p_is[x] = 0;
skip++;
} else
accept++;
} else {
if (t<0)
t = x;
}
}
if (bad) {
pk->p_msg |= M_RJ;
}
if (skip) {
pk->p_msg |= M_RR;
}
pk->p_rcount = accept;
return accept;
}
/*ARGSUSED*/
pkread(pk, ibuf, icount)
register struct pack *pk;
char *ibuf;
int icount;
{
register x;
int is, cc, xfr, count;
char *cp, **bp;
xfr = 0;
count = 0;
pktimeout = PKRTIME;
pktimeskew = PKRSKEW;
Ntimeout = 0;
while (pkaccept(pk) == 0)
;
while (icount) {
x = next[pk->p_pr];
is = pk->p_is[x];
if (is & B_COPY) {
cc = MIN(pk->p_isum[x], icount);
if (cc==0 && xfr) {
break;
}
if (is & B_RESID)
cp = pk->p_rptr;
else {
cp = pk->p_ib[x];
if (is & B_SHORT) {
if (*cp++ & 0200)
cp++;
}
}
pkmove(cp, ibuf, cc, B_READ);
ibuf += cc;
icount -= cc;
count += cc;
xfr++;
pk->p_isum[x] -= cc;
if (pk->p_isum[x] == 0) {
pk->p_pr = x;
bp = (char **)pk->p_ib[x];
*bp = (char *)pk->p_ipool;
pk->p_ipool = bp;
pk->p_is[x] = 0;
pk->p_rcount--;
pk->p_msg |= M_RR;
} else {
pk->p_rptr = cp+cc;
pk->p_is[x] |= B_RESID;
}
if (cc==0)
break;
} else
break;
}
pkoutput(pk);
return count;
}
/*ARGSUSED*/
pkwrite(pk, ibuf, icount)
register struct pack *pk;
char *ibuf;
int icount;
{
register x;
int partial;
caddr_t cp;
int cc, fc, count;
if (pk->p_state&DOWN || !pk->p_state&LIVE) {
return -1;
}
pktimeout = PKWTIME;
pktimeskew = PKWSKEW;
Ntimeout = 0;
count = icount;
do {
while (pk->p_xcount>=pk->p_swindow) {
pkoutput(pk);
pkgetpack(pk);
}
x = next[pk->p_pscopy];
while (pk->p_os[x]!=B_NULL) {
pkgetpack(pk);
}
pk->p_os[x] = B_MARK;
pk->p_pscopy = x;
pk->p_xcount++;
cp = pk->p_ob[x] = (char *)malloc((unsigned)pk->p_xsize);
partial = 0;
if ((int)icount < pk->p_xsize) {
cc = icount;
fc = pk->p_xsize - cc;
*cp = fc&0177;
if (fc > 127) {
*cp++ |= 0200;
*cp++ = fc>>7;
} else
cp++;
partial = B_SHORT;
} else
cc = pk->p_xsize;
pkmove(cp, ibuf, cc, B_WRITE);
ibuf += cc;
icount -= cc;
pk->p_osum[x] = chksum(pk->p_ob[x], pk->p_xsize);
pk->p_os[x] = B_READY+partial;
pkoutput(pk);
} while (icount);
return count;
}
pksack(pk)
register struct pack *pk;
{
register x, i;
i = 0;
for(x=pk->p_ps; x!=pk->p_rpr; ) {
x = next[x];
if (pk->p_os[x]&B_SENT) {
i++;
pk->p_os[x] = B_NULL;
pk->p_state &= ~WAITO;
pk->p_xcount--;
free((char *)pk->p_ob[x]);
pk->p_ps = x;
}
}
return i;
}
pkoutput(pk)
register struct pack *pk;
{
register x;
int i;
char bstate;
if (pk->p_obusy++) {
pk->p_obusy--;
return;
}
/*
* find seq number and buffer state
* of next output packet
*/
if (pk->p_state&RXMIT) {
pk->p_nxtps = next[pk->p_rpr];
}
x = pk->p_nxtps;
bstate = pk->p_os[x];
/*
* Send control packet if indicated
*/
if (pk->p_msg) {
if (pk->p_msg & ~M_RR || !(bstate&B_READY) ) {
x = pk->p_msg;
for(i=0; i<8; i++)
if (x&1)
break;
else
x >>= 1;
x = i;
x <<= 3;
switch(i) {
case CLOSE:
break;
case RJ:
case RR:
x += pk->p_pr;
break;
case SRJ:
break;
case INITB:
x += pksize(pk->p_rsize);
break;
case INITC:
x += pk->p_rwindow;
break;
case INITA:
x += pk->p_rwindow;
break;
}
pk->p_msg &= ~mask[i];
pkxstart(pk, x, -1);
goto out;
}
}
/*
* Don't send data packets if line is marked dead.
*/
if (pk->p_state&DOWN) {
goto out;
}
/*
* Start transmission (or retransmission) of data packets.
*/
if (bstate & (B_READY|B_SENT)) {
char seq;
bstate |= B_SENT;
seq = x;
pk->p_nxtps = next[x];
x = 0200+pk->p_pr+(seq<<3);
if (bstate & B_SHORT)
x |= 0100;
pkxstart(pk, x, seq);
pk->p_os[seq] = bstate;
pk->p_state &= ~RXMIT;
pk->p_nout++;
goto out;
}
/*
* enable timeout if there's nothing to send
* and transmission buffers are languishing
*/
if (pk->p_xcount) {
pk->p_timer = 2;
pk->p_state |= WAITO;
} else
pk->p_state &= ~WAITO;
out:
pk->p_obusy = 0;
}
/*
* shut down line by
* ignoring new input
* letting output drain
* releasing space and turning off line discipline
*/
/*ARGSUSED*/
pkclose(pk)
register struct pack *pk;
{
register i;
char **bp;
int rcheck = 0;
pk->p_state |= DRAINO;
/*
* try to flush output
*/
i = 0;
pk->p_timer = 2;
while (pk->p_xcount && pk->p_state&LIVE) {
if (pk->p_state&(RCLOSE+DOWN) || ++i > 2)
break;
pkoutput(pk);
}
pk->p_timer = 0;
pk->p_state |= DOWN;
/*
* try to exchange CLOSE messages
*/
i = 0;
while ((pk->p_state&RCLOSE)==0 && i<2) {
pk->p_msg = M_CLOSE;
pk->p_timer = 2;
pkoutput(pk);
i++;
}
for(i=0;i<NPLINES;i++)
if (pklines[i]==pk) {
pklines[i] = NULL;
}
/*
* free space
*/
rcheck = 0;
for (i=0;i<8;i++) {
if (pk->p_os[i] != B_NULL) {
free((char *)pk->p_ob[i]);
pk->p_xcount--;
}
if (pk->p_is[i] != B_NULL) {
free((char *)pk->p_ib[i]);
rcheck++;
}
}
while (pk->p_ipool != NULL) {
bp = pk->p_ipool;
pk->p_ipool = (char **)*bp;
rcheck++;
free((char *)bp);
}
if (rcheck != pk->p_rwindow) {
char buf[256];
sprintf(buf, "PK0: rc %d rw %d", rcheck, pk->p_rwindow);
logent(buf, "pkclose rcheck != p_rwindow");
}
free((char *)pk);
}
pkreset(pk)
register struct pack *pk;
{
pk->p_ps = pk->p_pr = pk->p_rpr = 0;
pk->p_nxtps = 1;
}
#ifndef BSD4_2
bzero(s,n)
register char *s;
register n;
{
while (n--)
*s++ = 0;
}
#endif
pksize(n)
register n;
{
register k;
n >>= 5;
for(k=0; n >>= 1; k++)
;
return k;
}

431
src/cmd/uucp/pk1.c Normal file
View File

@@ -0,0 +1,431 @@
#if !defined(lint) && defined(DOSCCS)
static char sccsid[] = "@(#)pk1.c 5.9.2 (2.11BSD) 1997/10/2";
#endif
#include <signal.h>
#include <strings.h>
#include "uucp.h"
#include "pk.h"
#include <setjmp.h>
#include <errno.h>
#include <string.h>
#ifdef BSD4_2
#include <sys/time.h>
#endif
#ifdef VMS
#include <eunice/eunice.h>
#include <vms/iodef.h>
#include <vms/ssdef.h>
int iomask[2];
#endif
#define PKMAXSTMSG 40
#define MAXPKTIME 32 /* was 16 */
#define CONNODATA 10
#define MAXTIMEOUT 32
extern int Retries;
extern jmp_buf Sjbuf;
int Connodata = 0;
int Ntimeout = 0;
int pktimeout = 4;
int pktimeskew = 2;
/*
* packet driver support routines
*
*/
extern struct pack *pklines[];
/*
* start initial synchronization.
*/
struct pack *
pkopen(ifn, ofn)
int ifn, ofn;
{
register struct pack *pk;
register char **bp;
register int i;
if ((pk = (struct pack *) malloc(sizeof (struct pack))) == NULL)
return NULL;
bzero((caddr_t) pk, sizeof (struct pack));
pk->p_ifn = ifn;
pk->p_ofn = ofn;
pk->p_xsize = pk->p_rsize = PACKSIZE;
pk->p_rwindow = pk->p_swindow = WINDOWS;
/* allocate input windows */
for (i = 0; i < pk->p_rwindow; i++) {
if ((bp = (char **) malloc((unsigned)pk->p_xsize)) == NULL)
break;
*bp = (char *) pk->p_ipool;
pk->p_ipool = bp;
}
if (i == 0) {
DEBUG(1, "pkopen: can't malloc i = 0\n", CNULL);
return NULL;
}
pk->p_rwindow = i;
/* start synchronization */
pk->p_msg = pk->p_rmsg = M_INITA;
for (i = 0; i < NPLINES; i++) {
if (pklines[i] == NULL) {
pklines[i] = pk;
break;
}
}
if (i >= NPLINES) {
DEBUG(1,"pkopen: i>=NPLINES\n", CNULL);
return NULL;
}
pkoutput(pk);
for (i = 0; i < PKMAXSTMSG; i++) {
pkgetpack(pk);
if ((pk->p_state & LIVE) != 0)
break;
}
if (i >= PKMAXSTMSG) {
DEBUG(1, "pkopen: i>= PKMAXSTMSG\n", CNULL);
return NULL;
}
pkreset(pk);
return pk;
}
/*
* input framing and block checking.
* frame layout for most devices is:
*
* S|K|X|Y|C|Z| ... data ... |
*
* where S == initial synch byte
* K == encoded frame size (indexes pksizes[])
* X, Y == block check bytes
* C == control byte
* Z == XOR of header (K^X^Y^C)
* data == 0 or more data bytes
*
*/
int pksizes[] = {
1, 32, 64, 128, 256, 512, 1024, 2048, 4096, 1
};
#define GETRIES 10
/*
* Pseudo-dma byte collection.
*/
pkgetpack(pk)
register struct pack *pk;
{
int k, tries, noise;
register char *p;
register struct header *h;
unsigned short sum;
int ifn;
char **bp;
char hdchk;
if ((pk->p_state & DOWN) || Connodata > CONNODATA || Ntimeout > MAXTIMEOUT)
pkfail();
ifn = pk->p_ifn;
/* find HEADER */
for (tries = 0, noise = 0; tries < GETRIES; ) {
p = (caddr_t) &pk->p_ihbuf;
if (pkcget(ifn, p, 1) == SUCCESS) {
if (*p++ == SYN) {
if (pkcget(ifn, p, HDRSIZ-1) == SUCCESS)
break;
} else {
if (noise++ < 10 || noise < (3*pk->p_rsize))
continue;
}
DEBUG(4, "Noisy line - set up RXMIT\n", CNULL);
noise = 0;
}
/* set up retransmit or REJ */
tries++;
Retries++;
pk->p_msg |= pk->p_rmsg;
if (pk->p_msg == 0)
pk->p_msg |= M_RR;
if ((pk->p_state & LIVE) == LIVE)
pk->p_state |= RXMIT;
pkoutput(pk);
}
if (tries >= GETRIES) {
DEBUG(4, "tries = %d\n", tries);
pkfail();
}
Connodata++;
h = (struct header *) &pk->p_ihbuf;
p = (caddr_t) h;
hdchk = p[1] ^ p[2] ^ p[3] ^ p[4];
p += 2;
sum = (unsigned) *p++ & 0377;
sum |= (unsigned) *p << 8;
h->sum = sum;
DEBUG(7, "rec h->cntl 0%o\n", h->cntl&0xff);
k = h->ksize;
if (hdchk != h->ccntl) {
/* bad header */
DEBUG(7, "bad header 0%o,", hdchk&0xff);
DEBUG(7, "h->ccntl 0%o\n", h->ccntl&0xff);
return;
}
if (k == 9) {
if (((h->sum + h->cntl) & 0xffff) == CHECK) {
pkcntl(h->cntl, pk);
DEBUG(7, "state - 0%o\n", pk->p_state);
} else {
/* bad header */
pk->p_state |= BADFRAME;
DEBUG(7, "bad header (k==9) 0%o\n", h->cntl&0xff);
}
return;
}
if (k && pksizes[k] == pk->p_rsize) {
pk->p_rpr = h->cntl & MOD8;
DEBUG(7, "end pksack 0%o\n", pk->p_rpr);
pksack(pk);
bp = pk->p_ipool;
if (bp == NULL) {
DEBUG(7, "bp NULL %s\n", "");
return;
}
pk->p_ipool = (char **) *bp;
Connodata = 0;
} else
return;
if (pkcget(pk->p_ifn, (char *) bp, pk->p_rsize) == SUCCESS) {
pkdata(h->cntl, h->sum, pk, (char **) bp);
} else {
*bp = (char *)pk->p_ipool;
pk->p_ipool = bp;
}
}
pkdata(c, sum, pk, bp)
char c;
unsigned short sum;
register struct pack *pk;
char **bp;
{
register x;
int t;
char m;
if (pk->p_state & DRAINO || !(pk->p_state & LIVE)) {
pk->p_msg |= pk->p_rmsg;
pkoutput(pk);
goto drop;
}
t = next[pk->p_pr];
for(x=pk->p_pr; x!=t; x = (x-1)&7) {
if (pk->p_is[x] == 0)
goto slot;
}
drop:
*bp = (char *)pk->p_ipool;
pk->p_ipool = bp;
return;
slot:
m = mask[x];
pk->p_imap |= m;
pk->p_is[x] = c;
pk->p_isum[x] = sum;
pk->p_ib[x] = (char *)bp;
}
/*
* setup input transfers
*/
#define PKMAXBUF 128
/*
* Start transmission on output device associated with pk.
* For asynch devices (t_line==1) framing is
* imposed. For devices with framing and crc
* in the driver (t_line==2) the transfer is
* passed on to the driver.
*/
pkxstart(pk, cntl, x)
register struct pack *pk;
char cntl;
register x;
{
register char *p;
short checkword;
char hdchk;
p = (caddr_t) &pk->p_ohbuf;
*p++ = SYN;
if (x < 0) {
*p++ = hdchk = 9;
checkword = cntl;
} else {
*p++ = hdchk = pk->p_lpsize;
checkword = pk->p_osum[x] ^ (unsigned)(cntl & 0377);
}
checkword = CHECK - checkword;
*p = checkword;
hdchk ^= *p++;
*p = checkword>>8;
hdchk ^= *p++;
*p = cntl;
hdchk ^= *p++;
*p = hdchk;
/* writes */
DEBUG(7, "send 0%o\n", cntl&0xff);
p = (caddr_t) & pk->p_ohbuf;
if (x < 0) {
if(write(pk->p_ofn, p, HDRSIZ) != HDRSIZ) {
alarm(0);
logent("PKXSTART write failed", strerror(errno));
longjmp(Sjbuf, 4);
}
} else {
char buf[PKMAXBUF + HDRSIZ + TAILSIZE], *b;
int i;
for (i = 0, b = buf; i < HDRSIZ; i++)
*b++ = *p++;
for (i = 0, p = pk->p_ob[x]; i < pk->p_xsize; i++)
*b++ = *p++;
#if TAILSIZE != 0
for (i = 0; i < TAILSIZE; i++)
*b++ = '\0';
#endif
if (write(pk->p_ofn, buf, pk->p_xsize + HDRSIZ + TAILSIZE)
!= (HDRSIZ + TAILSIZE + pk->p_xsize)) {
alarm(0);
logent("PKXSTART write failed", strerror(errno));
longjmp(Sjbuf, 5);
}
Connodata = 0;
}
if (pk->p_msg)
pkoutput(pk);
}
pkmove(p1, p2, count, flag)
char *p1, *p2;
int count, flag;
{
register char *s, *d;
register int i;
if (flag == B_WRITE) {
s = p2;
d = p1;
} else {
s = p1;
d = p2;
}
for (i = 0; i < count; i++)
*d++ = *s++;
}
/*
* get n characters from input
*
* return codes:
* n - number of characters returned
* 0 - end of file
*/
jmp_buf Getjbuf;
cgalarm()
{
longjmp(Getjbuf, 1);
}
pkcget(fn, b, n)
int fn;
register char *b;
register int n;
{
register int ret;
extern int linebaudrate;
#ifdef BSD4_2
long r, itime = 100000L; /* guess it's been 1/10th second since we
last read the line */
struct timeval tv;
#endif
#ifdef VMS
short iosb[4];
int SYS$QioW(); /* use this for long reads on vms */
#endif
if (setjmp(Getjbuf)) {
Ntimeout++;
DEBUG(4, "pkcget: alarm %d\n", pktimeout * 1000 + Ntimeout);
pktimeout += pktimeskew;
if (pktimeout > MAXPKTIME)
pktimeout = MAXPKTIME;
return FAIL;
}
signal(SIGALRM, (sig_t)cgalarm);
alarm(pktimeout);
while (n > 0) {
#ifdef BSD4_2
if (linebaudrate > 0) {
r = n * 100000L;
r = r / linebaudrate;
r = (r * 100) - itime;
itime = 0;
/* we predict that more than 1/50th of a
second will go by before the read will
give back all that we want. */
if (r > 20000) {
tv.tv_sec = r / 1000000L;
tv.tv_usec = r % 1000000L;
DEBUG(11, "PKCGET stall for %d", tv.tv_sec);
DEBUG(11, ".%06d sec\n", tv.tv_usec);
(void) select (0, (fd_set*)0, (fd_set*)0, (fd_set*)0, &tv);
}
}
#endif
#ifndef VMS
ret = read(fn, b, n);
#else
_$Cancel_IO_On_Signal = FD_FAB_Pointer[fn];
ret = SYS$QioW(_$EFN,(FD_FAB_Pointer[fn]->fab).fab$l_stv,
IO$_READVBLK|IO$M_NOFILTR|IO$M_NOECHO,
iosb,0,0,b,n,0,
iomask,0,0);
_$Cancel_IO_On_Signal = 0;
if (ret == SS$_NORMAL)
ret = iosb[1]+iosb[3]; /* get length of transfer */
else
ret = 0;
#endif
if (ret == 0) {
alarm(0);
return FAIL;
}
if (ret <= 0) {
alarm(0);
logent(strerror(errno),"FAILED pkcget Read");
longjmp(Sjbuf, 6);
}
b += ret;
n -= ret;
}
alarm(0);
return SUCCESS;
}

41
src/cmd/uucp/prefix.c Normal file
View File

@@ -0,0 +1,41 @@
#ifndef lint
static char sccsid[] = "@(#)prefix.c 5.3 (Berkeley) 6/20/85";
#endif
/*LINTLIBRARY*/
/*
* check s2 for prefix s1
*
* return 0 - !=
* return 1 - ==
*/
prefix(s1, s2)
register char *s1, *s2;
{
register char c;
while ((c = *s1++) == *s2++)
if (c == '\0')
return 1;
return c == '\0';
}
/*
* check s2 for prefix s1 with a wildcard character ?
*
* return 0 - !=
* return 1 - ==
*/
wprefix(s1, s2)
register char *s1, *s2;
{
register char c;
while ((c = *s1++) != '\0')
if (*s2 == '\0' || (c != *s2++ && c != '?'))
return 0;
return 1;
}

50
src/cmd/uucp/setline.c Normal file
View File

@@ -0,0 +1,50 @@
#ifndef lint
static char sccsid[] = "@(#)setline.c 5.3 (Berkeley) 6/20/85";
#endif
#include "uucp.h"
#ifdef USG
#include <termio.h>
#endif
#define PACKSIZE 64
#define SNDFILE 'S'
#define RCVFILE 'R'
#define RESET 'X'
/*LINTLIBRARY*/
/*
* optimize line setting for sending or receiving files
*
* return code - none
*/
/*ARGSUSED*/
setupline(type)
char type;
{
#ifdef USG
static struct termio tbuf, sbuf;
static int set = 0;
DEBUG(2, "setline - %c\n", type);
if (IsTcpIp)
return;
switch(type) {
case SNDFILE:
break;
case RCVFILE:
ioctl(Ifn, TCGETA, &tbuf);
sbuf = tbuf;
tbuf.c_cc[VMIN] = PACKSIZE;
ioctl(Ifn, TCSETAW, &tbuf);
set++;
break;
case RESET:
if (set == 0) break;
set = 0;
ioctl(Ifn, TCSETAW, &sbuf);
break;
}
#endif
}

108
src/cmd/uucp/subdir.c Normal file
View File

@@ -0,0 +1,108 @@
#ifndef lint
static char sccsid[] = "@(#)subdir.c 5.4 (Berkeley) 6/23/85";
#endif
#include "uucp.h"
/*LINTLIBRARY*/
/*
* By Tom Truscott, March 1983
*
* Prefix table.
* If a prefix is "abc", for example,
* then any file Spool/abc... is mapped to Spool/abc/abc... .
* The first prefix found is used, so D.foo should preceed D. in table.
*
* Each prefix must be a subdirectory of Spool, owned by uucp!
* Remember: use cron to uuclean these directories daily,
* and check them manually every now and then. Beware complacency!
*/
static char *dprefix[] = {
DLocalX, /* Outbound 'xqt' request files */
DLocal, /* Outbound data files */
"D.", /* Other "D." files (remember the "."!) */
"C.", /* "C." subdirectory */
"X.", /* "X." subdirectory */
"TM.", /* Temporaries for inbound files */
0
};
/*
* filename mapping kludges to put uucp work files in other directories.
*/
#define BUFLEN 50
static char fn1[BUFLEN], fn2[BUFLEN]; /* remapped filename areas */
static int inspool; /* true iff working dir is Spool */
/*
* return (possibly) remapped string s
*/
char *
subfile(as)
char *as;
{
register char *s, **p;
register int n;
static char *tptr = NULL;
/* Alternate buffers so "link(subfile(a), subfile(b))" works */
if (tptr != fn1)
tptr = fn1;
else
tptr = fn2;
s = as;
tptr[0] = '\0';
/* if s begins with Spool/, copy that to tptr and advance s */
if (strncmp(s, Spool, n = strlen(Spool)) == 0 && s[n] == '/') {
if (!inspool) {
strcpy(tptr, Spool);
strcat(tptr, "/");
}
s += n + 1;
}
else
if (!inspool)
return as;
/* look for first prefix which matches, and make subdirectory */
for (p = &dprefix[0]; *p; p++) {
if (strncmp(s, *p, n = strlen(*p))==0 && s[n] && s[n] != '/') {
strcat(tptr, *p);
strcat(tptr, "/");
strcat(tptr, s);
return tptr;
}
}
return as;
}
/*
* save away filename
*/
subchdir(s)
register char *s;
{
inspool = (strcmp(s, Spool) == 0);
return chdir(s);
}
/*
* return possibly corrected directory for searching
*/
char *
subdir(d, pre)
register char *d, pre;
{
if (strcmp(d, Spool) == 0)
if (pre == CMDPRE)
return CMDSDIR;
else if (pre == XQTPRE)
return XEQTDIR;
return d;
}

19
src/cmd/uucp/sysacct.c Normal file
View File

@@ -0,0 +1,19 @@
#ifndef lint
static char sccsid[] = "@(#)sysacct.c 5.3 (Berkeley) 6/23/85";
#endif
#include <sys/types.h>
/*LINTLIBRARY*/
/*
* output accounting info
*/
/*ARGSUSED*/
sysacct(bytes, time)
time_t time;
long bytes;
{
return;
}

149
src/cmd/uucp/systat.c Normal file
View File

@@ -0,0 +1,149 @@
#ifndef lint
static char sccsid[] = "@(#)systat.c 5.4 (Berkeley) 6/23/85";
#endif
#include "uucp.h"
#define STATNAME(f, n) sprintf(f, "%s/%s/%s", Spool, "STST", n)
#define S_SIZE 100
/*LINTLIBRARY*/
/*
* make system status entry
* return codes: none
*/
systat(name, type, text)
char *name, *text;
int type;
{
char filename[MAXFULLNAME], line[S_SIZE];
int count, oldtype;
register FILE *fp;
time_t prestime, rtry;
if (type == 0)
return;
line[0] = '\0';
time(&prestime);
count = 0;
STATNAME(filename, name);
fp = fopen(filename, "r");
if (fp != NULL) {
fgets(line, S_SIZE, fp);
sscanf(line, "%d %d", &oldtype, &count);
if (count <= 0)
count = 0;
fclose(fp);
/* If merely 'wrong time', don't change existing STST */
if (type == SS_WRONGTIME && oldtype != SS_INPROGRESS)
return;
}
rtry = Retrytime;
/* if failures repeat, don't try so often,
* to forstall a 'MAX RECALLS' situation.
*/
if (type == SS_FAIL) {
count++;
if (count > 5) {
rtry = rtry * (count-5);
if (rtry > ONEDAY/2)
rtry = ONEDAY/2;
}
}
#ifdef VMS
unlink(filename);
#endif
fp = fopen(filename, "w");
ASSERT(fp != NULL, "SYSTAT OPEN FAIL", filename, 0);
fprintf(fp, "%d %d %ld %ld %s %s\n", type, count, prestime, rtry, text, name);
fclose(fp);
return;
}
/***
* rmstat(name) remove system status entry
* char *name;
*
* return codes: none
*/
rmstat(name)
char *name;
{
char filename[MAXFULLNAME];
STATNAME(filename, name);
unlink(filename);
}
/*
* check system status for call
*
* return codes 0 - ok | >0 system status
*/
callok(name)
char *name;
{
char filename[MAXFULLNAME], line[S_SIZE];
register FILE *fp;
time_t lasttime, prestime, retrytime;
long t1, t2;
int count, type;
STATNAME(filename, name);
fp = fopen(filename, "r");
if (fp == NULL)
return(SS_OK);
if (fgets(line, S_SIZE, fp) == NULL) {
/* no data */
fclose(fp);
unlink(filename);
return(SS_OK);
}
fclose(fp);
time(&prestime);
sscanf(line, "%d%d%ld%ld", &type, &count, &t1, &t2);
lasttime = t1;
retrytime = t2;
switch(type) {
case SS_BADSEQ:
case SS_CALLBACK:
case SS_NODEVICE:
case SS_INPROGRESS: /*let LCK take care of it */
return(SS_OK);
case SS_FAIL:
if (count > MAXRECALLS) {
logent("MAX RECALLS", "NO CALL");
DEBUG(4, "MAX RECALL COUNT %d\n", count);
if (Debug) {
logent("debugging", "continuing anyway");
return SS_OK;
}
return type;
}
if (prestime - lasttime < retrytime) {
logent("RETRY TIME NOT REACHED", "NO CALL");
DEBUG(4, "RETRY TIME (%ld) NOT REACHED\n", retrytime);
if (Debug) {
logent("debugging", "continuing anyway");
return SS_OK;
}
return type;
}
return SS_OK;
default:
return SS_OK;
}
}

264
src/cmd/uucp/tio.c Normal file
View File

@@ -0,0 +1,264 @@
#ifndef lint
static char sccsid[] = "@(#)tio.c 4.6 (Berkeley) 1/24/86";
#endif
#include <signal.h>
#include "uucp.h"
#include <setjmp.h>
#include <sys/stat.h>
#include <netinet/in.h>
extern int pkfail();
#define TPACKSIZE 512
#define TBUFSIZE 1024
#define LBUFSIZE 128
#define min(a,b) (((a)<(b))?(a):(b))
/*
* htonl is a function that converts a long from host
* order to network order
* ntohl is a function that converts a long from network
* order to host order
*
* network order is 0 1 2 3 (bytes in a long)
* host order on a vax is 3 2 1 0
* host order on a pdp11 is 1 0 3 2
* host order on a 68000 is 0 1 2 3
* most other machines are 0 1 2 3
*/
struct tbuf {
long t_nbytes;
char t_data[TBUFSIZE];
};
extern jmp_buf Failbuf;
twrmsg(type, str, fn)
char type;
register char *str;
{
char bufr[TBUFSIZE];
register char *s;
int len, i;
if(setjmp(Failbuf))
return FAIL;
signal(SIGALRM, pkfail);
alarm(MAXMSGTIME);
bufr[0] = type;
s = &bufr[1];
while (*str)
*s++ = *str++;
*s = '\0';
if (*(--s) == '\n')
*s = '\0';
len = strlen(bufr) + 1;
if ((i = len % TPACKSIZE)) {
len = len + TPACKSIZE - i;
bufr[len - 1] = '\0';
}
twrblk(bufr, len, fn);
alarm(0);
return SUCCESS;
}
trdmsg(str, fn)
register char *str;
{
int len, cnt = 0;
if(setjmp(Failbuf))
return FAIL;
signal(SIGALRM, pkfail);
alarm(MAXMSGTIME);
for (;;) {
len = read(fn, str, TPACKSIZE);
if (len == 0)
continue;
if (len < 0) {
alarm(0);
return FAIL;
}
str += len;
cnt += len;
if (*(str - 1) == '\0' && (cnt % TPACKSIZE) == 0)
break;
}
alarm(0);
return SUCCESS;
}
twrdata(fp1, fn)
FILE *fp1;
{
struct tbuf bufr;
register int len;
int ret, mil;
struct timeb t1, t2;
long bytes;
char text[LBUFSIZE];
if(setjmp(Failbuf))
return FAIL;
signal(SIGALRM, pkfail);
bytes = 0L;
#ifdef USG
time(&t1.time);
t1.millitm = 0;
#else !USG
ftime(&t1);
#endif !USG
while ((len = read(fileno(fp1), bufr.t_data, TBUFSIZE)) > 0) {
bytes += len;
#if defined(vax) || defined(pdp11) || defined(ns32000)
bufr.t_nbytes = htonl((long)len);
#else !vax and !pdp11 and !ns32000
bufr.t_nbytes = len;
#endif !vax and !pdp11 and !ns32000
DEBUG(8,"twrdata sending %d bytes\n",len);
len += sizeof(long);
alarm(MAXMSGTIME);
ret = twrblk((char *)&bufr, len, fn);
alarm(0);
if (ret != len)
return FAIL;
if (len != TBUFSIZE+sizeof(long))
break;
}
bufr.t_nbytes = 0;
len = sizeof(long);
alarm(MAXMSGTIME);
ret = twrblk((char *)&bufr, len, fn);
alarm(0);
if (ret != len)
return FAIL;
#ifdef USG
time(&t2.time);
t2.millitm = 0;
#else !USG
ftime(&t2);
#endif !USG
Now = t2;
t2.time -= t1.time;
mil = t2.millitm - t1.millitm;
if (mil < 0) {
--t2.time;
mil += 1000;
}
sprintf(text, "sent data %ld bytes %ld.%02d secs",
bytes, (long)t2.time, mil/10);
sysacct(bytes, t2.time);
DEBUG(1, "%s\n", text);
syslog(text);
return SUCCESS;
}
trddata(fn, fp2)
FILE *fp2;
{
register int len, nread;
char bufr[TBUFSIZE];
struct timeb t1, t2;
int mil;
long bytes, Nbytes;
if(setjmp(Failbuf))
return FAIL;
signal(SIGALRM, pkfail);
#ifdef USG
time(&t1.time);
t1.millitm = 0;
#else !USG
ftime(&t1);
#endif !USG
bytes = 0L;
for (;;) {
alarm(MAXMSGTIME);
len = trdblk((char *)&Nbytes,sizeof Nbytes,fn);
alarm(0);
if (len != sizeof Nbytes)
return FAIL;
#if defined(vax) || defined(pdp11) || defined(ns32000)
Nbytes = ntohl(Nbytes);
#endif vax or pdp11 or ns32000
DEBUG(8,"trddata expecting %ld bytes\n",Nbytes);
nread = Nbytes;
if (nread == 0)
break;
alarm(MAXMSGTIME);
len = trdblk(bufr, nread, fn);
alarm(0);
if (len < 0) {
return FAIL;
}
bytes += len;
DEBUG(11,"trddata got %ld\n",bytes);
if (write(fileno(fp2), bufr, len) != len) {
alarm(0);
return FAIL;
}
}
#ifdef USG
time(&t2.time);
t2.millitm = 0;
#else !USG
ftime(&t2);
#endif !USG
Now = t2;
t2.time -= t1.time;
mil = t2.millitm - t1.millitm;
if (mil < 0) {
--t2.time;
mil += 1000;
}
sprintf(bufr, "received data %ld bytes %ld.%02d secs",
bytes, (long)t2.time, mil/10);
sysacct(bytes, t2.time - t1.time);
DEBUG(1, "%s\n", bufr);
syslog(bufr);
return SUCCESS;
}
#if !defined(BSD4_2) && !defined(USG)
#define TC 1024
static int tc = TC;
#endif !BSD4_2 && !USG
trdblk(blk, len, fn)
register int len;
char *blk;
{
register int i, ret;
#if !defined(BSD4_2) && !defined(USG)
/* call ultouch occasionally */
if (--tc < 0) {
tc = TC;
ultouch();
}
#endif !BSD4_2 && !USG
for (i = 0; i < len; i += ret) {
ret = read(fn, blk, len - i);
if (ret < 0)
return FAIL;
blk += ret;
if (ret == 0)
return i;
}
return i;
}
twrblk(blk, len, fn)
register char *blk;
{
#if !defined(BSD4_2) && !defined(USG)
/* call ultouch occasionally */
if (--tc < 0) {
tc = TC;
ultouch();
}
#endif !BSD4_2 && !USG
return write(fn, blk, len);
}

197
src/cmd/uucp/ulockf.c Normal file
View File

@@ -0,0 +1,197 @@
#if !defined(lint) && defined(DOSCCS)
static char sccsid[] = "@(#)ulockf.c 5.5.1 (2.11BSD) 1997/10/2";
#endif
#include "uucp.h"
#include <sys/stat.h>
#include <errno.h>
#define LCKMODE 0444 /* File mode for lock files */
#define MAXLOCKS 16 /* Maximum number of lock files */
char *Lockfile[MAXLOCKS];
char *LockDirectory = LOCKDIR;
int Nlocks = 0;
/*LINTLIBRARY*/
/*
* This routine will attempt to create a lock file (file).
* It makes sure that the lock file is valid if it already exists.
*
* return codes: SUCCESS | FAIL
*/
ulockf(hfile, atime)
char *hfile;
time_t atime;
{
register char *p;
register int i;
static char tempfile[NAMESIZE];
char file[NAMESIZE];
static int pid = -1;
extern int errno;
if (pid < 0) {
pid = getpid();
sprintf(tempfile, "%s/LTMP.%d", LockDirectory, pid);
}
sprintf(file, "%s/LCK..%s", LockDirectory, hfile);
i = 0;
while (onelock(pid, tempfile, file) == -1) { /* lock file exists */
#if !defined(BSD4_2) && !defined(USG)
struct stat stbuf;
time_t ptime;
/* get status to check age of the lock file */
if (stat(file, &stbuf) == 0) {
(void) time(&ptime);
if ((ptime - stbuf.st_ctime) < atime)
return FAIL; /* file not old enough to delete */
}
#else
register int fd;
fd = open(file, 0);
if (fd >= 0) {
int upid, ret;
ret = read(fd, &upid, sizeof upid);
close(fd);
if (ret == sizeof upid && (kill(upid, 0) == 0
|| errno != ESRCH))
return FAIL; /* process is still running */
}
#endif
assert("DEAD LOCK", file, errno);
logent(file, "DEAD LOCK");
(void) unlink(file);
sleep(5); /* avoid a possible race */
ASSERT(i++ < 5, "CAN'T GET LOCKFILE", tempfile, errno);
}
for (i = 0; i < Nlocks; i++) {
if (Lockfile[i] == NULL)
break;
}
ASSERT(i < MAXLOCKS, "TOO MANY LOCKS", CNULL, i);
if (i >= Nlocks)
i = Nlocks++;
p = (char *)malloc((unsigned)(strlen(file)+1));
ASSERT(p != NULL, "CAN NOT ALLOCATE FOR", file, 0);
strcpy(p, file);
Lockfile[i] = p;
return SUCCESS;
}
/*
* remove all lock files in list or name
*/
rmlock(name)
register char *name;
{
register int i;
char file[MAXFULLNAME];
if (name != NULL) {
sprintf(file, "%s/LCK..%s", LockDirectory, name);
name = file;
}
for (i = 0; i < Nlocks; i++) {
if (Lockfile[i] == NULL)
continue;
if (name == NULL || strcmp(name, Lockfile[i]) == SAME) {
unlink(Lockfile[i]);
free(Lockfile[i]);
Lockfile[i] = NULL;
}
}
}
/*
* makes lock a name on behalf of pid. Tempfile must be in the same
* file system as name.
*/
onelock(pid, tempfile, name)
int pid;
char *tempfile, *name;
{
register int fd, ret;
extern int errno;
#ifdef VMS
fd = creat(name, LCKMODE, "1version");
#else
fd = creat(tempfile, LCKMODE);
#endif
if (fd < 0) {
DEBUG(1,"Can't creat temp file %s ", tempfile);
DEBUG(1,"-- errno %d", errno);
return FAIL;
}
ret = write(fd, (char *)&pid, sizeof(int));
(void) close(fd);
if (ret != sizeof(int)) {
DEBUG(1,"Temp file write failed -- errno %d\n", errno);
#ifdef VMS
(void) unlink(name);
#else
(void) unlink(tempfile);
#endif
return FAIL;
}
#ifndef VMS
if (link(tempfile, name) < 0) {
(void) unlink(tempfile);
return FAIL;
}
unlink(tempfile);
#endif
return SUCCESS;
}
#if !defined(BSD4_2) && !defined(USG)
/*
* update 'change' time for lock files
*
* Only update ctime, not mtime or atime.
* The 'chmod' method permits cu(I)-like programs
* to determine how long uucp has been on the line.
* The old "change access, mod, and change time" method
* can be had by defining OLDTOUCH
*
* return code - none
*/
ultouch()
{
static time_t lasttouch = 0;
register int i;
struct ut {
time_t actime;
time_t modtime;
} ut;
#ifdef USG
time(&Now.time);
t1.millitm = 0;
#else
ftime(&Now);
#endif
ut.actime = ut.modtime = Now.time;
/* Do not waste time touching locking files too often */
/* (But, defend against backward time changes) */
if (ut.actime >= lasttouch && ut.actime < lasttouch+60)
return;
lasttouch = ut.actime;
DEBUG(4, "ultouch\n", 0);
for (i = 0; i < Nlocks; i++) {
if (Lockfile[i] == NULL)
continue;
#ifdef OLDTOUCH
utime(Lockfile[i], &ut);
#else
chmod(Lockfile[i], LCKMODE);
#endif
}
}
#endif

231
src/cmd/uucp/uuclean.c Normal file
View File

@@ -0,0 +1,231 @@
#ifndef lint
static char sccsid[] = "@(#)uuclean.c 5.6 (Berkeley) 10/9/85";
#endif
#include <signal.h>
#include "uucp.h"
#include <pwd.h>
#include <sys/stat.h>
#ifdef NDIR
#include "ndir.h"
#else
#include <sys/dir.h>
#endif
/*
*
* this program will search through the spool
* directory (Spool) and delete all files with a requested
* prefix which are older than (nomtime) seconds.
* If the -m option is set, the program will try to
* send mail to the usid of the file.
*
* options:
* -m - send mail for deleted file
* -d - directory to clean
* -n - time to age files before delete (in hours)
* -p - prefix for search
* -x - turn on debug outputs
* exit status:
* 0 - normal return
* 1 - can not read directory
*/
#define NOMTIME 72 /* hours to age files before deletion */
int checkprefix = 0;
struct timeb Now;
main(argc, argv)
char *argv[];
{
DIR *dirp;
char file[NAMESIZE];
time_t nomtime, ptime;
struct stat stbuf;
int mflg=0;
strcpy(Progname, "uuclean");
uucpname(Myname);
nomtime = NOMTIME * (time_t)3600;
while (argc>1 && argv[1][0] == '-') {
switch (argv[1][1]) {
case 'd':
Spool = &argv[1][2];
break;
case 'm':
mflg = 1;
break;
case 'n':
nomtime = atoi(&argv[1][2]) * (time_t)3600;
break;
case 'p':
checkprefix = 1;
if (&argv[1][2] != '\0')
stpre(&argv[1][2]);
break;
case 'x':
chkdebug();
Debug = atoi(&argv[1][2]);
if (Debug <= 0)
Debug = 1;
break;
default:
printf("unknown flag %s\n", argv[1]); break;
}
--argc; argv++;
}
DEBUG(4, "DEBUG# %s\n", "START");
if (chdir(Spool) < 0) { /* NO subdirs in uuclean! rti!trt */
printf("%s directory inaccessible\n", Spool);
exit(1);
}
if ((dirp = opendir(Spool)) == NULL) {
printf("%s directory unreadable\n", Spool);
exit(1);
}
time(&ptime);
while (gnamef(dirp, file)) {
if (checkprefix && !chkpre(file))
continue;
if (stat(file, &stbuf) == -1) {
DEBUG(4, "stat on %s failed\n", file);
continue;
}
if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
continue;
if ((ptime - stbuf.st_mtime) < nomtime)
continue;
if (file[0] == CMDPRE)
notfyuser(file);
DEBUG(4, "unlink file %s\n", file);
unlink(file);
if (mflg)
sdmail(file, stbuf.st_uid);
}
closedir(dirp);
exit(0);
}
#define MAXPRE 10
char Pre[MAXPRE][NAMESIZE];
int Npre = 0;
/***
* chkpre(file) check for prefix
* char *file;
*
* return codes:
* 0 - not prefix
* 1 - is prefix
*/
chkpre(file)
char *file;
{
int i;
for (i = 0; i < Npre; i++) {
if (prefix(Pre[i], file))
return(1);
}
return(0);
}
/***
* stpre(p) store prefix
* char *p;
*
* return codes: none
*/
stpre(p)
char *p;
{
if (Npre < MAXPRE - 2)
strcpy(Pre[Npre++], p);
return;
}
/***
* notfyuser(file) - notfiy requestor of deleted requres
*
* return code - none
*/
notfyuser(file)
char *file;
{
FILE *fp;
int numrq;
char frqst[100], lrqst[100];
char msg[BUFSIZ];
char *args[10];
if ((fp = fopen(file, "r")) == NULL)
return;
if (fgets(frqst, 100, fp) == NULL) {
fclose(fp);
return;
}
numrq = 1;
while (fgets(lrqst, 100, fp))
numrq++;
fclose(fp);
sprintf(msg,
"File %s delete. \nCould not contact remote. \n%d requests deleted.\n", file, numrq);
if (numrq == 1) {
strcat(msg, "REQUEST: ");
strcat(msg, frqst);
} else {
strcat(msg, "FIRST REQUEST: ");
strcat(msg, frqst);
strcat(msg, "\nLAST REQUEST: ");
strcat(msg, lrqst);
}
getargs(frqst, args, 10);
mailst(args[3], msg, CNULL);
}
/***
* sdmail(file, uid)
*
* sdmail - this routine will determine the owner
* of the file (file), create a message string and
* call "mailst" to send the cleanup message.
* This is only implemented for local system
* mail at this time.
*/
sdmail(file, uid)
char *file;
{
static struct passwd *pwd;
struct passwd *getpwuid();
char mstr[40];
sprintf(mstr, "uuclean deleted file %s\n", file);
if (pwd != NULL && pwd->pw_uid == uid) {
mailst(pwd->pw_name, mstr, CNULL);
return;
}
setpwent();
if ((pwd = getpwuid(uid)) != NULL)
mailst(pwd->pw_name, mstr, CNULL);
}
cleanup(code)
int code;
{
exit(code);
}

468
src/cmd/uucp/uucp.c Normal file
View File

@@ -0,0 +1,468 @@
#ifndef lint
static char sccsid[] = "@(#)uucp.c 5.5 (Berkeley) 10/9/85";
#endif
#include "uucp.h"
#include <sys/stat.h>
#include <strings.h>
#include "uust.h"
/*
* uucp
*/
int Uid;
char *Ropt = " ";
char Path[100], Optns[10], Ename[MAXBASENAME+1];
char Grade = 'n';
#ifdef DONTCOPY
int Copy = 0;
#else
int Copy = 1;
#endif
char Nuser[32];
struct timeb Now;
/* variables used to check if talking to more than one system. */
int xsflag = -1;
char xsys[MAXBASENAME+1];
long Nbytes = 0;
#define MAXBYTES 50000 /* maximun number of bytes of data per C. file */
#define MAXCOUNT 15 /* maximun number of files per C. file */
main(argc, argv)
char *argv[];
{
int ret;
char *sysfile1, *sysfl2;
register char *cp;
char file1[MAXFULLNAME], file2[MAXFULLNAME];
int avoidgwd = 0;
strcpy(Progname, "uucp");
uucpname(Myname);
umask(WFMASK);
Optns[0] = '-';
Optns[1] = 'd';
#ifdef DONTCOPY
Optns[2] = 'c';
#else
Optns[2] = 'C';
#endif
Ename[0] = Nuser[0] = Optns[3] = '\0';
while(argc>1 && argv[1][0] == '-'){
switch(argv[1][1]){
case 'a':
/* efficiency hack; avoid gwd call */
avoidgwd = 1;
break;
case 'C':
Copy = 1;
Optns[2] = 'C';
break;
case 'c':
Copy = 0;
Optns[2] = 'c';
break;
case 'd':
break;
case 'f':
Optns[1] = 'f';
break;
case 'e':
strncpy(Ename, &argv[1][2], MAXBASENAME);
break;
case 'g':
Grade = argv[1][2];
break;
case 'm':
strcat(Optns, "m");
break;
case 'n':
sprintf(Nuser, "%.31s", &argv[1][2]);
break;
case 'r':
Ropt = argv[1];
break;
case 's':
Spool = &argv[1][2]; break;
case 'x':
chkdebug();
Debug = atoi(&argv[1][2]);
if (Debug <= 0)
Debug = 1;
break;
default:
printf("unknown flag %s\n", argv[1]); break;
}
--argc; argv++;
}
DEBUG(4, "\n\n** %s **\n", "START");
if (!avoidgwd) {
cp = getwd(Wrkdir);
ASSERT(cp != 0, "GETWD FAILED", Wrkdir, cp);
}
ret = subchdir(Spool);
ASSERT(ret >= 0, "CHDIR FAILED", Spool, ret);
Uid = getuid();
ret = guinfo(Uid, User, Path);
ASSERT(ret == 0, "CAN NOT FIND UID", CNULL, Uid);
DEBUG(4, "UID %d, ", Uid);
DEBUG(4, "User %s,", User);
DEBUG(4, "Ename (%s) ", Ename);
DEBUG(4, "PATH %s\n", Path);
if (argc < 3) {
fprintf(stderr, "usage uucp from ... to\n");
cleanup(1);
}
/* set up "to" system and file names */
if ((cp = index(argv[argc - 1], '!')) != NULL) {
sysfl2 = argv[argc - 1];
*cp = '\0';
if (*sysfl2 == '\0')
sysfl2 = Myname;
else
strncpy(Rmtname, sysfl2, MAXBASENAME);
if (versys(&sysfl2) != 0) {
fprintf(stderr, "bad system name: %s\n", sysfl2);
cleanup(1);
}
if (Rmtname[0] != '\0')
strncpy(Rmtname, sysfl2, MAXBASENAME);
/* block multi-hop requests immediately */
if (index(cp+1, '!') != NULL) {
fprintf(stderr, "uucp handles only adjacent sites.\n");
fprintf(stderr, "Try uusend for multi-hop delivery.\n");
cleanup(1);
}
strcpy(file2, cp + 1);
}
else {
sysfl2 = Myname;
strcpy(file2, argv[argc - 1]);
}
if (strlen(sysfl2) > MAXBASENAME)
sysfl2[MAXBASENAME] = '\0';
/* do each from argument */
while (argc > 2) {
if ((cp = index(argv[1], '!')) != NULL) {
sysfile1 = argv[1];
*cp = '\0';
if (strlen(sysfile1) > MAXBASENAME)
sysfile1[MAXBASENAME] = '\0';
if (*sysfile1 == '\0')
sysfile1 = Myname;
else
strncpy(Rmtname, sysfile1, MAXBASENAME);
if (versys(&sysfile1) != 0) {
fprintf(stderr, "bad system name: %s\n", sysfile1);
cleanup(0);
}
if (Rmtname[0] != '\0')
strncpy(Rmtname, sysfl2, MAXBASENAME);
strcpy(file1, cp + 1);
}
else {
sysfile1 = Myname;
strcpy(file1, argv[1]);
}
DEBUG(4, "file1 - %s\n", file1);
copy(sysfile1, file1, sysfl2, file2);
--argc;
argv++;
}
clscfile();
if (*Ropt != '-' && xsflag >= 0)
xuucico(xsys);
cleanup(0);
}
cleanup(code)
int code;
{
logcls();
rmlock(CNULL);
if (code)
fprintf(stderr, "uucp failed. code %d\n", code);
exit(code);
}
/*
* generate copy files
*
* return codes 0 | FAIL
*/
copy(s1, f1, s2, f2)
register char *s1, *f1, *s2, *f2;
{
int type, statret;
struct stat stbuf, stbuf1;
char dfile[NAMESIZE];
char file1[MAXFULLNAME], file2[MAXFULLNAME];
FILE *cfp, *gtcfile();
char opts[100];
type = 0;
opts[0] = '\0';
strcpy(file1, f1);
strcpy(file2, f2);
if (strcmp(s1, Myname) != SAME)
type = 1;
if (strcmp(s2, Myname) != SAME)
type += 2;
if (type & 01)
if ((index(f1, '*') != NULL
|| index(f1, '?') != NULL
|| index(f1, '[') != NULL))
type = 4;
switch (type) {
case 0:
/* all work here */
DEBUG(4, "all work here %d\n", type);
if (ckexpf(file1))
return FAIL;
if (ckexpf(file2))
return FAIL;
if (stat(subfile(file1), &stbuf) != 0) {
fprintf(stderr, "can't get file status %s \n copy failed\n",
file1);
return SUCCESS;
}
statret = stat(subfile(file2), &stbuf1);
if (statret == 0
&& stbuf.st_ino == stbuf1.st_ino
&& stbuf.st_dev == stbuf1.st_dev) {
fprintf(stderr, "%s %s - same file; can't copy\n", file1, file2);
return SUCCESS;
}
if (chkpth(User, "", file1) != 0
|| chkperm(file2, index(Optns, 'd'))
|| chkpth(User, "", file2) != 0) {
fprintf(stderr, "permission denied\n");
cleanup(1);
}
if ((stbuf.st_mode & ANYREAD) == 0) {
fprintf(stderr, "can't read file (%s) mode (%o)\n",
file1, (int)stbuf.st_mode);
return FAIL;
}
if (statret == 0 && (stbuf1.st_mode & ANYWRITE) == 0) {
fprintf(stderr, "can't write file (%s) mode (%o)\n",
file2, (int)stbuf.st_mode);
return FAIL;
}
xcp(file1, file2);
logent("WORK HERE", "DONE");
return SUCCESS;
case 1:
/* receive file */
DEBUG(4, "receive file - %d\n", type);
chsys(s1);
if (file1[0] != '~')
if (ckexpf(file1))
return FAIL;
if (ckexpf(file2))
return FAIL;
if (chkpth(User, "", file2) != 0) {
fprintf(stderr, "permission denied\n");
return FAIL;
}
if (Ename[0] != '\0') {
/* execute uux - remote uucp */
xuux(Ename, s1, file1, s2, file2, opts);
return SUCCESS;
}
cfp = gtcfile(s1);
fprintf(cfp, "R %s %s %s %s\n", file1, file2, User, Optns);
break;
case 2:
/* send file */
if (ckexpf(file1))
return FAIL;
if (file2[0] != '~')
if (ckexpf(file2))
return FAIL;
DEBUG(4, "send file - %d\n", type);
chsys(s2);
if (chkpth(User, "", file1) != 0) {
fprintf(stderr, "permission denied %s\n", file1);
return FAIL;
}
if (stat(subfile(file1), &stbuf) != 0) {
fprintf(stderr, "can't get status for file %s\n", file1);
return FAIL;
}
if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
fprintf(stderr, "directory name illegal - %s\n",
file1);
return FAIL;
}
if ((stbuf.st_mode & ANYREAD) == 0) {
fprintf(stderr, "can't read file (%s) mode (%o)\n",
file1, (int)stbuf.st_mode);
return FAIL;
}
if ((Nuser[0] != '\0') && (index(Optns, 'n') == NULL))
strcat(Optns, "n");
if (Ename[0] != '\0') {
/* execute uux - remote uucp */
if (Nuser[0] != '\0')
sprintf(opts, "-n%s", Nuser);
xuux(Ename, s1, file1, s2, file2, opts);
return SUCCESS;
}
Nbytes += stbuf.st_size;
if (Copy) {
gename(DATAPRE, Myname, Grade, dfile);
if (xcp(file1, dfile) != 0) {
fprintf(stderr, "can't copy %s\n", file1);
return FAIL;
}
}
else {
/* make a dummy D. name */
/* cntrl.c knows names < 6 chars are dummy D. files */
strcpy(dfile, "D.0");
}
cfp = gtcfile(s2);
fprintf(cfp, "S %s %s %s %s %s %o %s\n", file1, file2,
User, Optns, dfile, (int)stbuf.st_mode & 0777, Nuser);
break;
case 3:
case 4:
/* send uucp command for execution on s1 */
DEBUG(4, "send uucp command - %d\n", type);
chsys(s1);
if (strcmp(s2, Myname) == SAME) {
if (ckexpf(file2))
return FAIL;
if (chkpth(User, "", file2) != 0) {
fprintf(stderr, "permission denied\n");
return FAIL;
}
}
if (Ename[0] != '\0') {
/* execute uux - remote uucp */
xuux(Ename, s1, file1, s2, file2, opts);
return SUCCESS;
}
cfp = gtcfile(s1);
fprintf(cfp, "X %s %s!%s %s %s\n", file1, s2, file2, User, Optns);
break;
}
return SUCCESS;
}
/*
* execute uux for remote uucp
*
* return code - none
*/
xuux(ename, s1, f1, s2, f2, opts)
char *ename, *s1, *s2, *f1, *f2, *opts;
{
char cmd[200];
DEBUG(4, "Ropt(%s) ", Ropt);
DEBUG(4, "ename(%s) ", ename);
DEBUG(4, "s1(%s) ", s1);
DEBUG(4, "f1(%s) ", f1);
DEBUG(4, "s2(%s) ", s2);
DEBUG(4, "f2(%s)\n", f2);
sprintf(cmd, "uux %s %s!uucp %s %s!%s \\(%s!%s\\)",
Ropt, ename, opts, s1, f1, s2, f2);
DEBUG(4, "cmd (%s)\n", cmd);
system(cmd);
return;
}
FILE *Cfp = NULL;
char Cfile[NAMESIZE];
/*
* get a Cfile descriptor
*
* return an open file descriptor
*/
FILE *
gtcfile(sys)
register char *sys;
{
static char presys[8] = "";
static int cmdcount = 0;
register int savemask;
if (strcmp(presys, sys) != SAME /* this is !SAME on first call */
|| Nbytes > MAXBYTES
|| ++cmdcount > MAXCOUNT) {
cmdcount = 1;
Nbytes = 0;
if (presys[0] != '\0') {
clscfile();
}
gename(CMDPRE, sys, Grade, Cfile);
#ifdef VMS
savemask = umask(~0600); /* vms must have read permission */
#else
savemask = umask(~0200);
#endif
Cfp = fopen(subfile(Cfile), "w");
umask(savemask);
ASSERT(Cfp != NULL, CANTOPEN, Cfile, 0);
strcpy(presys, sys);
}
return Cfp;
}
/*
* close cfile
*
* return code - none
*/
clscfile()
{
if (Cfp == NULL)
return;
fclose(Cfp);
chmod(subfile(Cfile), ~WFMASK & 0777);
logent(Cfile, "QUE'D");
US_CRS(Cfile);
Cfp = NULL;
}
/*
* compile a list of all systems we are referencing
*/
chsys(s1)
register char *s1;
{
if (xsflag < 0)
xsflag = 0;
else if (xsflag > 0)
return;
if (xsys[0] == '\0') {
strncpy(xsys, s1, MAXBASENAME);
return;
}
if (strncmp(xsys, s1, MAXBASENAME) == SAME)
return;
xsflag++;
xsys[0] = '\0';
}

424
src/cmd/uucp/uucp.h Normal file
View File

@@ -0,0 +1,424 @@
/* uucp.h 5.11.6 1997/10/2 */
#include <stdio.h>
#include <paths.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
struct timeb {
time_t time;
u_short millitm;
short timezone;
short dstflag;
};
/*
* Determine local uucp name of this machine.
* Define one of the following:
*
* For UCB 4.1A and later systems, you will have the gethostname(2) call.
* If this call exists, define GETHOSTNAME.
*
* For USG 3.0 and later systems, you will have the uname(2) call.
* If this call exists, define UNAME.
*
* Some systems have a line of the form '#define sysname "myuucpname",'
* in the file /usr/include/whoami.h, to identify their machine.
* If your site does that, define WHOAMI.
*
* If your site has <whoami.h>, but you do not want to read
* that file every time uucp runs, you can compile sysname into uucp.
* This is faster and more reliable, but binaries do not port.
* If you want to do that, define CCWHOAMI.
*
* Some systems put the local uucp name in a single-line file
* named /etc/uucpname or /local/uucpname.
* If your site does that, define UUNAME.
*
* Systems running 3Com's UNET will have the getmyhname() call.
* If you want to, define GETMYHNAME.
*
* You should also define MYNAME to be your uucp name.
*
* For each of the above that are defined, uucp checks them in order.
* It stops on the first method that returns a non null name.
* If everything fails, it uses "unknown" for the system name.
*/
#define GETHOSTNAME /**/
/* #define UNAME /**/
/* #define WHOAMI /**/
/* #define CCWHOAMI /**/
/* #define UUNAME /**/
/* #define GETMYHNAME /**/
/* If the above fails ... */
#define MYNAME "wlonex"
/*
* If you have it, include <sysexits.h> to use exit
* codes that will be understood by sendmail.
* Otherwise, define EX_NOHOST, EX_CANTCREAT, and EX_NOINPUT.
*/
#include <sysexits.h>
/*#define EX_NOINPUT 66 /**/
/*#define EX_NOHOST 68 /**/
/*#define EX_CANTCREAT 73 /**/
/*
* Define the various kinds of connections to include.
* The complete list is in the condevs array in condevs.c
*/
/* #define ATT2224 /* AT&T 2224 */
//#define BSDTCP /* 4.2bsd or 2.9bsd TCP/IP */
/* #define CDS224 /* Concord Data Systems 2400 */
/* #define DATAKIT /* ATT's datakit */
/* #define DF02 /* Dec's DF02/DF03 */
/* #define DF112 /* Dec's DF112 */
/* #define DN11 /* "standard" DEC dialer */
#define HAYES /* Hayes' Smartmodem */
/* #define HAYES2400 /* Hayes' 2400 baud Smartmodem */
/* #define MICOM /* Micom Mux port */
/* #define NOVATION /* Novation modem */
/* #define PAD /* X.25 PAD */
/* #define PENRIL /* PENRIL Dialer */
/* #define PNET /* Purdue network */
/* #define RVMACS /* Racal-Vadic MACS 820 dialer, 831 adaptor */
/* #define SYTEK /* Sytek Local Area Net */
/* #define UNETTCP /* 3Com's UNET */
/* #define USR2400 /* USRobotics Courier 2400 */
/* #define VA212 /* Racal-Vadic 212 */
/* #define VA811S /* Racal-Vadic 811S dialer, 831 adaptor */
/* #define VA820 /* Racal-Vadic 820 dialer, 831 adaptor */
/* #define VADIC /* Racal-Vadic 345x */
/* #define VENTEL /* Ventel Dialer */
/* #define VMACS /* Racal-Vadic MACS 811 dialer, 831 adaptor */
#if defined(USR2400) && !defined(HAYES)
#define HAYES
#endif
#if defined(UNETTCP) || defined(BSDTCP)
#define TCPIP
#endif
/*
* We need a timer to write slowly to certain modems.
* and for generating breaks.
*
* define INTERVALTIMER to use 4.[23] bsd interval timer.
* define FASTTIMER if you have the nap() system call.
* define FTIME if you have the ftime() system call.
* define BUSYLOOP if you must do a busy loop.
* Look at uucpdelay() in condevs.c for details.
*/
#define INTERVALTIMER /**/
/*#define FASTTIMER /**/
/*#define FTIME /**/
/*#define BUSYLOOP /**/
/*
* If your site is using "ndir.h" to retrofit the Berkeley
* directory reading routines, define NDIR.
* You will probably also have to set LIBNDIR in Makefile.
* Otherwise, <dir.h> is assumed to have the Berkeley directory definitions.
*/
/*#define NDIR /**/
/*
* If yours is a BTL system III, IV, V or so-on site, define USG.
*/
/*#define USG /**/
/*
* If you are running 4.3bsd, define BSD4_3 and BSD4_2
* If you are just running 4.2bsd, define BSD4_2
* If you are running 2.11bsd, define BSD4_3 and BSD4_2
* If you are running the BRL version of 4.2BSD define BRL4_2, NOT BSD4_3
*/
#define BSD4_3 /**/
#define BSD4_2 /**/
/*#define BRL4_2 /**/
#if defined(BRL4_2) && !defined(BSD4_2)
#define BSD4_2
#undef BSD4_3
#endif
/*
* If you are running 2.9bsd define BSD2_9
*/
/*#define BSD2_9 /**/
/*
* If you are using 'inetd' with 4.2bsd, define BSDINETD
*/
/* #define BSDINETD /**/
/*
* If you are running 4.3bsd, 2.11bsd or BRL 4.2, you are running 'inetd'
*/
#if (defined(BSD4_3) || defined(BRL4_2)) && !defined(BSDINETD)
#define BSDINETD
#endif
/*#define VMSDTR /* Turn on modem control on vms(works DTR) for
develcon and gandalf ports to gain access */
/*
* If you want to use the same modem for dialing in and out define
* DIALINOUT to be the localtion of the acucntrl program
*/
/* #define DIALINOUT "/usr/libexec/acucntrl" /**/
/*
* If you want all ACU lines to be DIALINOUT, define ALLACUINOUT
*/
/* #define ALLACUINOUT /**/
/* define the value of WFMASK - for umask call - used for all uucp work files */
#define WFMASK 0137
/* define the value of LOGMASK - for LOGFILE, SYSLOG, ERRLOG */
#define LOGMASK 0133
/* All files are given at least the following at the final destination */
/* It is also the default mode, so '666' is recommended */
/* and 444 is minimal (minimally useful, maximally annoying) */
#define BASEMODE 0666
/*
* Define NOSTRANGERS if you don't want to accept transactions from
* sites that are not in your L.sys file (see cico.c)
*/
#define NOSTRANGERS /**/
/*
* Traditionally LCK (lock) files have been kept in /usr/spool/uucp.
* If you want that define LOCKDIR to be ".".
* If you want the locks kept in a subdirectory, define LOCKDIR as "LCK".
* Good news about LCK. subdirectory: the directory can be mode 777 so
* unprivileged programs can share the uucp locking system,
* and the subdirectory keeps down clutter in the main directory.
* The BAD news: you have to change 'tip' and another programs that
* know where the LCK files are kept, and you have to change your /etc/rc
* if your rc cleans out the lock files (as it should).
*/
/*#define LOCKDIR "LCK" /**/
#define LOCKDIR "." /**/
/*
* If you want uucp and uux to copy the data files by default,
* don't define DONTCOPY (This is the way older 4bsd uucps worked)
* If you want uucp and uux to use the original files instead of
* copies, define DONTCOPY (This is the way System III and V work)
*/
#define DONTCOPY /**/
/*
* Very few (that I know of) systems use the sequence checking feature.
* If you are not going to use it (hint: you are not),
* do not define GNXSEQ. This saves precious room on PDP11s.
*/
/*#define GNXSEQ /* comment this out to save space */
/*
* If you want the logfile stored in a file for each site instead
* of one file
* define LOGBYSITE as the directory to put the files in
*/
/*#define LOGBYSITE "/usr/spool/uucp/LOG" /**/
#define XQTDIR "/usr/spool/uucp/XTMP"
#define SQFILE "/etc/uucp/SQFILE"
#define SQTMP "/etc/uucp/SQTMP"
#define SLCKTIME 5400 /* system/device timeout (LCK.. files) */
#define SEQFILE "/etc/uucp/SEQF"
#define SYSFILE "/etc/uucp/L.sys"
#define DEVFILE "/etc/uucp/L-devices"
#define DIALFILE "/etc/uucp/L-dialcodes"
#define USERFILE "/etc/uucp/USERFILE"
#define CMDFILE "/etc/uucp/L.cmds"
#define ALIASFILE "/etc/uucp/L.aliases"
#define SPOOL "/usr/spool/uucp"
#define SYSLOG "/usr/spool/uucp/SYSLOG"
#define PUBDIR "/usr/spool/uucppublic"
#define SQLOCK "SQ"
#define SEQLOCK "SEQL"
#define CMDPRE 'C'
#define DATAPRE 'D'
#define XQTPRE 'X'
#define LOGFILE "/usr/spool/uucp/LOGFILE"
#define ERRLOG "/usr/spool/uucp/ERRLOG"
#define CMDSDIR "/usr/spool/uucp/C."
#define DATADIR "/usr/spool/uucp/D."
#define XEQTDIR "/usr/spool/uucp/X."
#define RMTDEBUG "AUDIT"
#define CORRUPT "CORRUPT"
#define SQTIME 60
#define TRYCALLS 2 /* number of tries to dial call */
#define LLEN 50
#define MAXRQST 250
#define DEBUG(l, f, s) if (Debug >= l) fprintf(stderr, f, s); else
#define ASSERT(e, s1, s2, i1) if (!(e)) {assert(s1, s2, i1);cleanup(FAIL);}else
#define delock(dev) rmlock(dev)
#define mlock(dev) ulockf(dev, SLCKTIME)
#define SAME 0
#define ANYREAD 0004
#define ANYWRITE 02
#define FAIL -1
#define SUCCESS 0
#define CNULL (char *) 0
#define STBNULL (struct sgttyb *) 0
#define MASTER 1
#define SLAVE 0
#define MAXFULLNAME 255
#define MAXMSGTIME 45
#define NAMESIZE 255
#define MAXBASENAME 14
#define SYSNSIZE (MAXBASENAME-1-1-1-4)
#define EOTMSG "\04\n\04\n"
#define CALLBACK 1
#define ONEDAY 86400L
/* commands */
#define SHELL "/bin/sh"
#define UUCICO "/usr/sbin/uucico"
#define UUXQT "/usr/libexec/uuxqt"
#define UUCP "uucp"
/* call connect fail stuff */
#define CF_SYSTEM -1
#define CF_TIME -2
#define CF_LOCK -3
#define CF_NODEV -4
#define CF_DIAL -5
#define CF_LOGIN -6
#define F_NAME 0
#define F_TIME 1
#define F_LINE 2
#define F_CLASS 3 /* an optional prefix and the speed */
#define F_PHONE 4
#define F_LOGIN 5
#define MAXPH 60 /* maximum length of a phone number */
/* This structure tells how to get to a device */
struct condev {
char *CU_meth; /* method, such as 'ACU' or 'DIR' */
char *CU_brand; /* brand, such as 'Hayes' or 'Vadic' */
int (*CU_gen)(); /* what to call to search for brands */
int (*CU_open)(); /* what to call to open brand */
int (*CU_clos)(); /* what to call to close brand */
};
/* This structure tells about a device */
struct Devices {
#define D_type D_arg[0]
#define D_line D_arg[1]
#define D_calldev D_arg[2]
#define D_class D_arg[3]
#define D_brand D_arg[4]
#define D_CHAT 5
int D_numargs;
int D_speed;
char *D_arg[20];
char D_argbfr[100];
};
/* system status stuff */
#define SS_OK 0
#define SS_NODEVICE 1
#define SS_CALLBACK 2
#define SS_INPROGRESS 3
#define SS_FAIL 4
#define SS_BADSEQ 5
#define SS_WRONGTIME 6
/* fail/retry parameters */
#define RETRYTIME 600
#define MAXRECALLS 25
/* stuff for command execution */
#define X_RQDFILE 'F'
#define X_STDIN 'I'
#define X_STDOUT 'O'
#define X_CMD 'C'
#define X_USER 'U'
#define X_SENDFILE 'S'
#define X_NONOTI 'N'
#define X_RETURNTO 'R'
#define X_NONZERO 'Z'
#define X_LOCK "XQT"
#define X_LOCKTIME 3600L
#define WKDSIZE 100 /* size of work dir name */
#include <sys/types.h>
#ifndef USG
//#include <sys/timeb.h>
#else
struct timeb
{
time_t time;
unsigned short millitm;
short timezone;
short dstflag;
};
#define rindex strrchr
#define index strchr
#endif
extern struct timeb Now;
extern int Ifn, Ofn;
extern char *Rmtname;
extern char User[];
extern char Loginuser[];
extern char *Spool;
extern char Myname[];
extern char Myfullname[];
extern int Debug;
extern int Bspeed;
extern char Wrkdir[];
extern time_t Retrytime;
extern short Usrf;
extern int IsTcpIp;
extern char Progname[];
extern int (*CU_end)();
extern struct condev condevs[];
extern char NOLOGIN[];
extern char DLocal[], DLocalX[], *subfile(), *subdir();
/* Commonly called routines which return non-int value */
extern char *fdig(), *cfgets();
extern FILE *rpopen();
extern char _FAILED[], CANTOPEN[], DEVNULL[];
#ifdef lint
/* This horrible gross kludge is the only way I know to
* convince lint that signal(SIGINT,SIG_IGN) is legal. It hates SIG_IGN.
*/
#ifdef SIG_IGN
#undef SIG_IGN
#endif
#define SIG_IGN main
extern int main();
#ifdef DEBUG
#undef DEBUG
#endif
#define DEBUG(a,b,c)
#endif

303
src/cmd/uucp/uucpd.c Normal file
View File

@@ -0,0 +1,303 @@
#if defined(DOSCCS) && !defined(lint)
static char sccsid[] = "@(#)uucpd.c 5.4.1 (2.11BSD GTE) 1/1/94";
#endif
/*
* 4.2BSD or 2.9BSD TCP/IP server for uucico
* uucico's TCP channel causes this server to be run at the remote end.
*/
#include "uucp.h"
#ifdef BSD2_9
#include <sys/localopts.h>
#include <sys/file.h>
#endif BSD2_9
#include <signal.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <pwd.h>
#include <lastlog.h>
#if !defined(BSD4_2) && !defined(BSD2_9)
--- You must have either BSD4_2 or BSD2_9 defined for this to work
#endif
#if defined(BSD4_2) && defined(BSD2_9)
--- You may not have both BSD4_2 and BSD2_9 defined for this to work
#endif
char lastlog[] = "/usr/adm/lastlog";
struct sockaddr_in hisctladdr;
int hisaddrlen = sizeof hisctladdr;
struct sockaddr_in myctladdr;
int mypid;
char Username[64];
char *nenv[] = {
Username,
NULL,
};
extern char **environ;
main(argc, argv)
int argc;
char **argv;
{
#ifndef BSDINETD
register int s, tcp_socket;
struct servent *sp;
#endif !BSDINETD
extern int errno;
int dologout();
environ = nenv;
#ifdef BSDINETD
close(1); close(2);
dup(0); dup(0);
hisaddrlen = sizeof (hisctladdr);
if (getpeername(0, &hisctladdr, &hisaddrlen) < 0) {
fprintf(stderr, "%s: ", argv[0]);
perror("getpeername");
_exit(1);
}
if (fork() == 0)
doit(&hisctladdr);
dologout();
exit(1);
#else !BSDINETD
sp = getservbyname("uucp", "tcp");
if (sp == NULL){
perror("uucpd: getservbyname");
exit(1);
}
if (fork())
exit(0);
if ((s=open("/dev/tty", 2)) >= 0){
ioctl(s, TIOCNOTTY, (char *)0);
close(s);
}
bzero((char *)&myctladdr, sizeof (myctladdr));
myctladdr.sin_family = AF_INET;
myctladdr.sin_port = sp->s_port;
#ifdef BSD4_2
tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
if (tcp_socket < 0) {
perror("uucpd: socket");
exit(1);
}
if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr)) < 0) {
perror("uucpd: bind");
exit(1);
}
listen(tcp_socket, 3); /* at most 3 simultaneuos uucp connections */
signal(SIGCHLD, dologout);
for(;;) {
s = accept(tcp_socket, &hisctladdr, &hisaddrlen);
if (s < 0){
if (errno == EINTR)
continue;
perror("uucpd: accept");
exit(1);
}
if (fork() == 0) {
close(0); close(1); close(2);
dup(s); dup(s); dup(s);
close(tcp_socket); close(s);
doit(&hisctladdr);
exit(1);
}
close(s);
}
#endif BSD4_2
#ifdef BSD2_9
for(;;) {
signal(SIGCHLD, dologout);
s = socket(SOCK_STREAM, 0, &myctladdr,
SO_ACCEPTCONN|SO_KEEPALIVE);
if (s < 0) {
perror("uucpd: socket");
exit(1);
}
if (accept(s, &hisctladdr) < 0) {
if (errno == EINTR) {
close(s);
continue;
}
perror("uucpd: accept");
exit(1);
}
if (fork() == 0) {
close(0); close(1); close(2);
dup(s); dup(s); dup(s);
close(s);
doit(&hisctladdr);
exit(1);
}
}
#endif BSD2_9
#endif !BSDINETD
}
doit(sinp)
struct sockaddr_in *sinp;
{
char user[64], passwd[64];
char *xpasswd, *crypt();
struct passwd *pw, *getpwnam();
alarm(60);
printf("login: "); fflush(stdout);
if (readline(user, sizeof user) < 0) {
fprintf(stderr, "user read\n");
return;
}
/* truncate username to 8 characters */
user[8] = '\0';
pw = getpwnam(user);
if (pw == NULL) {
fprintf(stderr, "user unknown\n");
return;
}
if (strcmp(pw->pw_shell, UUCICO)) {
fprintf(stderr, "Login incorrect.");
return;
}
if (pw->pw_passwd && *pw->pw_passwd != '\0') {
printf("Password: "); fflush(stdout);
if (readline(passwd, sizeof passwd) < 0) {
fprintf(stderr, "passwd read\n");
return;
}
xpasswd = crypt(passwd, pw->pw_passwd);
if (strcmp(xpasswd, pw->pw_passwd)) {
fprintf(stderr, "Login incorrect.");
return;
}
}
alarm(0);
sprintf(Username, "USER=%s", user);
dologin(pw, sinp);
setgid(pw->pw_gid);
#ifdef BSD4_2
initgroups(pw->pw_name, pw->pw_gid);
#endif BSD4_2
chdir(pw->pw_dir);
setuid(pw->pw_uid);
#ifdef BSD4_2
execl(UUCICO, "uucico", (char *)0);
#endif BSD4_2
#ifdef BSD2_9
sprintf(passwd, "-h%s", inet_ntoa(sinp->sin_addr));
execl(UUCICO, "uucico", passwd, (char *)0);
#endif BSD2_9
perror("uucico server: execl");
}
readline(p, n)
register char *p;
register int n;
{
char c;
while (n-- > 0) {
if (read(0, &c, 1) <= 0)
return(-1);
c &= 0177;
if (c == '\n' || c == '\r') {
*p = '\0';
return(0);
}
*p++ = c;
}
return(-1);
}
#include <utmp.h>
#ifdef BSD4_2
#include <fcntl.h>
#endif BSD4_2
#ifdef BSD2_9
#define O_APPEND 0 /* kludge */
#define wait3(a,b,c) wait2(a,b)
#endif BSD2_9
#define SCPYN(a, b) strncpy(a, b, sizeof (a))
struct utmp utmp;
dologout()
{
union wait status;
int pid, wtmp;
#ifdef BSDINETD
while ((pid=wait(&status)) > 0) {
#else !BSDINETD
while ((pid=wait3(&status,WNOHANG,0)) > 0) {
#endif !BSDINETD
wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
if (wtmp >= 0) {
sprintf(utmp.ut_line, "uucp%.4d", pid);
SCPYN(utmp.ut_name, "");
SCPYN(utmp.ut_host, "");
(void) time(&utmp.ut_time);
#ifdef BSD2_9
(void) lseek(wtmp, 0L, 2);
#endif BSD2_9
(void) write(wtmp, (char *)&utmp, sizeof (utmp));
(void) close(wtmp);
}
}
}
/*
* Record login in wtmp file.
*/
dologin(pw, sin)
struct passwd *pw;
struct sockaddr_in *sin;
{
char line[32];
char remotehost[32];
int wtmp, f;
struct hostent *hp = gethostbyaddr(&sin->sin_addr,
sizeof (struct in_addr), AF_INET);
if (hp) {
strncpy(remotehost, hp->h_name, sizeof (remotehost));
endhostent();
} else
strncpy(remotehost, inet_ntoa(sin->sin_addr),
sizeof (remotehost));
wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
if (wtmp >= 0) {
/* hack, but must be unique and no tty line */
sprintf(line, "uucp%.4d", getpid());
SCPYN(utmp.ut_line, line);
SCPYN(utmp.ut_name, pw->pw_name);
SCPYN(utmp.ut_host, remotehost);
time(&utmp.ut_time);
#ifdef BSD2_9
(void) lseek(wtmp, 0L, 2);
#endif BSD2_9
(void) write(wtmp, (char *)&utmp, sizeof (utmp));
(void) close(wtmp);
}
if ((f = open(lastlog, 2)) >= 0) {
struct lastlog ll;
time(&ll.ll_time);
lseek(f, (long)pw->pw_uid * sizeof(struct lastlog), 0);
strcpy(line, remotehost);
SCPYN(ll.ll_line, line);
SCPYN(ll.ll_host, remotehost);
(void) write(f, (char *) &ll, sizeof ll);
(void) close(f);
}
}

31
src/cmd/uucp/uucpdefs.c Normal file
View File

@@ -0,0 +1,31 @@
#if !defined(lint) && defined(DOSCCS)
static char sccsid[] = "@(#)uucpdefs.c 5.5.1 (2.11BSD) 1996/11/27";
#endif
#include "uucp.h"
char Progname[64];
int Ifn, Ofn;
char RRmtname[MAXFULLNAME];
char *Rmtname = RRmtname;
char User[128];
char Loginuser[16];
char Myname[MAXBASENAME+1];
char Wrkdir[WKDSIZE];
char *Spool = SPOOL;
char DLocal[64];
char DLocalX[64];
int Debug = 0;
time_t Retrytime;
short Usrf = 0; /* Uustat global flag */
int IsTcpIp = 0; /* 1 == TCP/IP connection, else 0. kludge to suppress ioctl */
char MaxGrade = '\177';
char DefMaxGrade = '\177';
int nologinflag = 0;
char NOLOGIN[] = _PATH_NOLOGIN;
/* Save some data space */
char DEVNULL[] = _PATH_DEVNULL;
char CANTOPEN[] = "CAN'T OPEN";
char _FAILED[] = "FAILED";

227
src/cmd/uucp/uucpname.c Normal file
View File

@@ -0,0 +1,227 @@
#ifndef lint
static char sccsid[] = "@(#)uucpname.c 5.5 (Berkeley) 10/9/85";
#endif
#include "uucp.h"
#include <sys/stat.h>
#include <strings.h>
/*LINTLIBRARY*/
#ifdef GETMYHNAME
#include <UNET/unetio.h>
#endif
#ifdef UNAME
/* Use USG uname() library routine */
#include <sys/utsname.h>
#endif
#ifdef CCWHOAMI
/* Compile in 'sysname' as found in standard(!) include file */
#include <whoami.h>
#endif
char Myfullname[64];
/*
* uucpname(name) get the uucp name
*
* return code - none
*/
uucpname(name)
register char *name;
{
register char *s;
/*
* Since some UNIX systems do not honor the set-user-id bit
* when the invoking user is root, we must change the uid here.
* So uucp files are created with the correct owner.
*/
if (geteuid() == 0 && getuid() == 0) {
struct stat stbuf;
stbuf.st_uid = 0; /* In case the stat fails */
stbuf.st_gid = 0;
stat(UUCICO, &stbuf); /* Assume uucico is correctly owned */
setgid(stbuf.st_gid);
setuid(stbuf.st_uid);
}
s = NULL; /* system name unknown, so far */
#ifdef GETHOSTNAME
if (s == NULL || *s == '\0') {
#ifdef VMS
int i = sizeof(Myfullname);
#endif
s = Myfullname;
#ifdef VMS
if(gethostname(Myfullname, &i) == -1) {
#else
if(gethostname(Myfullname, sizeof(Myfullname)) == -1) {
#endif
DEBUG(1, "gethostname", _FAILED);
s = NULL;
}
}
#endif
#ifdef UNAME
/* Use USG library routine */
if (s == NULL || *s == '\0') {
struct utsname utsn;
if (uname(&utsn) == -1) {
DEBUG(1, "uname", _FAILED);
s = NULL;
} else {
strncpy(Myfullname, utsn.nodename, sizeof Myfullname);
s = Myfullname;
}
}
#endif
#ifdef WHOAMI
/* Use fake gethostname() routine */
if (s == NULL || *s == '\0') {
s = Myfullname;
if (fakegethostname(Myfullname, sizeof(Myfullname)) == -1) {
DEBUG(1, "whoami search", _FAILED);
s = NULL;
}
}
#endif
#ifdef CCWHOAMI
/* compile sysname right into uucp */
if (s == NULL || *s == '\0') {
s = sysname;
strncpy(Myfullname, s, sizeof Myfullname);
}
#endif
#ifdef UUNAME
/* uucp name is stored in /etc/uucpname or /local/uucpname */
if (s == NULL || *s == '\0') {
FILE *uucpf;
s = Myfullname;
if (((uucpf = fopen("/etc/uucpname", "r")) == NULL &&
(uucpf = fopen("/local/uucpname", "r")) == NULL) ||
fgets(Myfullname, sizeof Myfullname, uucpf) == NULL) {
DEBUG(1, "uuname search", _FAILED);
s = NULL;
}
if (s == Myfullname) {
register char *p;
p = index(s, '\n');
if (p)
*p = '\0';
}
if (uucpf != NULL)
fclose(uucpf);
}
#endif
#ifdef GETMYHNAME
/* Use 3Com's getmyhname() routine */
if (s == NULL || *s == '\0') {
if ((s = getmyhname()) == NULL)
DEBUG(1, "getmyhname", _FAILED);
else
strncpy(Myfullname, s, sizeof Myfullname);
}
#endif
#ifdef MYNAME
if (s == NULL || *s == '\0') {
s = MYNAME;
strncpy(Myfullname, s, sizeof Myfullname);
}
#endif
if (s == NULL || *s == '\0') {
/*
* As a last ditch thing, we *could* search Spool
* for D.<uucpname> and use that,
* but that is too much trouble, isn't it?
*/
logent("SYSTEM NAME", "CANNOT DETERMINE");
strcpy(Myfullname, "unknown");
}
/*
* copy uucpname back to caller-supplied buffer,
* truncating to MAXBASENAME characters.
* Also set up subdirectory names
* Truncate names at '.' if found to handle cases like
* seismo.css.gov being returned by gethostname().
* uucp sites should not have '.' in their name anyway
*/
s = index(Myfullname, '.');
if (s != NULL)
*s = '\0';
strncpy(name, Myfullname, MAXBASENAME);
name[MAXBASENAME] = '\0';
DEBUG(1, "My uucpname = %s\n", name);
sprintf(DLocal, "D.%.*s", SYSNSIZE, name);
sprintf(DLocalX, "D.%.*sX", SYSNSIZE, name);
}
#ifdef WHOAMI
/*
* simulate the 4.2 bsd system call by reading /usr/include/whoami.h
* and looking for the #define sysname
*/
#define HDRFILE "/usr/include/whoami.h"
fakegethostname(name, len)
char *name;
int len;
{
char buf[BUFSIZ];
char bname[32];
char hname[32];
char nname[128];
register char *p, *q, *nptr;
int i;
register FILE *fd;
fd = fopen(HDRFILE, "r");
if (fd == NULL)
return(-1);
hname[0] = 0;
nname[0] = 0;
nptr = nname;
while (fgets(buf, sizeof buf, fd) != NULL) { /* each line in the file */
if (sscanf(buf, "#define sysname \"%[^\"]\"", bname) == 1) {
strcpy(hname, bname);
} else if (sscanf(buf, "#define nickname \"%[^\"]\"", bname) == 1) {
strcpy(nptr, bname);
nptr += strlen(bname) + 1;
} else if (sscanf(buf, "#define nickname%d \"%[^\"]\"", &i, bname) == 2) {
strcpy(nptr, bname);
nptr += strlen(bname) + 1;
}
}
fclose(fd);
if (hname[0] == 0)
return FAIL;
strncpy(name, hname, len);
p = nname;
i = strlen(hname) + 1;
q = name + i;
while (i < len && (p[0] != 0 || p[1] != 0)) {
*q++ = *p++;
i++;
}
*q++ = 0;
return SUCCESS;
}
#endif

175
src/cmd/uucp/uudecode.c Normal file
View File

@@ -0,0 +1,175 @@
#ifndef lint
static char sccsid[] = "@(#)uudecode.c 5.3 (Berkeley) 4/10/85";
#endif
/*
* uudecode [input]
*
* create the specified file, decoding as you go.
* used with uuencode.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/stat.h>
/* single character decode */
#define DEC(c) (((c) - ' ') & 077)
main(argc, argv)
char **argv;
{
FILE *in, *out;
int mode;
char dest[128];
char buf[80];
/* optional input arg */
if (argc > 1) {
if ((in = fopen(argv[1], "r")) == NULL) {
perror(argv[1]);
exit(1);
}
argv++; argc--;
} else
in = stdin;
if (argc != 1) {
printf("Usage: uudecode [infile]\n");
exit(2);
}
/* search for header line */
for (;;) {
if (fgets(buf, sizeof buf, in) == NULL) {
fprintf(stderr, "No begin line\n");
exit(3);
}
if (strncmp(buf, "begin ", 6) == 0)
break;
}
sscanf(buf, "begin %o %s", &mode, dest);
/* handle ~user/file format */
if (dest[0] == '~') {
char *sl;
struct passwd *getpwnam();
char *index();
struct passwd *user;
char dnbuf[100];
sl = index(dest, '/');
if (sl == NULL) {
fprintf(stderr, "Illegal ~user\n");
exit(3);
}
*sl++ = 0;
user = getpwnam(dest+1);
if (user == NULL) {
fprintf(stderr, "No such user as %s\n", dest);
exit(4);
}
strcpy(dnbuf, user->pw_dir);
strcat(dnbuf, "/");
strcat(dnbuf, sl);
strcpy(dest, dnbuf);
}
/* create output file */
out = fopen(dest, "w");
if (out == NULL) {
perror(dest);
exit(4);
}
chmod(dest, mode);
decode(in, out);
if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) {
fprintf(stderr, "No end line\n");
exit(5);
}
exit(0);
}
/*
* copy from in to out, decoding as you go along.
*/
decode(in, out)
FILE *in;
FILE *out;
{
char buf[80];
char *bp;
int n;
for (;;) {
/* for each input line */
if (fgets(buf, sizeof buf, in) == NULL) {
printf("Short file\n");
exit(10);
}
n = DEC(buf[0]);
if (n <= 0)
break;
bp = &buf[1];
while (n > 0) {
outdec(bp, out, n);
bp += 4;
n -= 3;
}
}
}
/*
* output a group of 3 bytes (4 input characters).
* the input chars are pointed to by p, they are to
* be output to file f. n is used to tell us not to
* output all of them at the end of the file.
*/
outdec(p, f, n)
char *p;
FILE *f;
{
int c1, c2, c3;
c1 = DEC(*p) << 2 | DEC(p[1]) >> 4;
c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
c3 = DEC(p[2]) << 6 | DEC(p[3]);
if (n >= 1)
putc(c1, f);
if (n >= 2)
putc(c2, f);
if (n >= 3)
putc(c3, f);
}
/* fr: like read but stdio */
int
fr(fd, buf, cnt)
FILE *fd;
char *buf;
int cnt;
{
int c, i;
for (i=0; i<cnt; i++) {
c = getc(fd);
if (c == EOF)
return(i);
buf[i] = c;
}
return (cnt);
}
/*
* Return the ptr in sp at which the character c appears;
* NULL if not found
*/
#define NULL 0

110
src/cmd/uucp/uuencode.c Normal file
View File

@@ -0,0 +1,110 @@
#ifndef lint
static char sccsid[] = "@(#)uuencode.c 5.3 (Berkeley) 1/22/85";
#endif
/*
* uuencode [input] output
*
* Encode a file so it can be mailed to a remote system.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
/* ENC is the basic 1 character encoding function to make a char printing */
#define ENC(c) ((c) ? ((c) & 077) + ' ': '`')
main(argc, argv)
char **argv;
{
FILE *in;
struct stat sbuf;
int mode;
/* optional 1st argument */
if (argc > 2) {
if ((in = fopen(argv[1], "r")) == NULL) {
perror(argv[1]);
exit(1);
}
argv++; argc--;
} else
in = stdin;
if (argc != 2) {
printf("Usage: uuencode [infile] remotefile\n");
exit(2);
}
/* figure out the input file mode */
fstat(fileno(in), &sbuf);
mode = sbuf.st_mode & 0777;
printf("begin %o %s\n", mode, argv[1]);
encode(in, stdout);
printf("end\n");
exit(0);
}
/*
* copy from in to out, encoding as you go along.
*/
encode(in, out)
FILE *in;
FILE *out;
{
char buf[80];
int i, n;
for (;;) {
/* 1 (up to) 45 character line */
n = fr(in, buf, 45);
putc(ENC(n), out);
for (i=0; i<n; i += 3)
outdec(&buf[i], out);
putc('\n', out);
if (n <= 0)
break;
}
}
/*
* output one group of 3 bytes, pointed at by p, on file f.
*/
outdec(p, f)
char *p;
FILE *f;
{
int c1, c2, c3, c4;
c1 = *p >> 2;
c2 = (*p << 4) & 060 | (p[1] >> 4) & 017;
c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03;
c4 = p[2] & 077;
putc(ENC(c1), f);
putc(ENC(c2), f);
putc(ENC(c3), f);
putc(ENC(c4), f);
}
/* fr: like read but stdio */
int
fr(fd, buf, cnt)
FILE *fd;
char *buf;
int cnt;
{
int c, i;
for (i=0; i<cnt; i++) {
c = getc(fd);
if (c == EOF)
return(i);
buf[i] = c;
}
return (cnt);
}

94
src/cmd/uucp/uulog.c Normal file
View File

@@ -0,0 +1,94 @@
#ifndef lint
static char sccsid[] = "@(#)uulog.c 5.4 (Berkeley) 6/23/85";
#endif
#include "uucp.h"
#ifndef SYSBUF
static char SYSBUF[BUFSIZ];
#endif
main(argc, argv)
char *argv[];
{
FILE *plogf;
char *sys, *user;
char buf[BUFSIZ], u[64], s[64];
setbuf(stdout, SYSBUF);
strcpy(Progname, "uulog");
sys = user = NULL;
while (argc>1 && argv[1][0] == '-') {
switch (argv[1][1]) {
case 's':
sys = &argv[1][2];
if (*sys == NULL && argc > 2 && argv[2][0] != '-') {
sys = &argv[2][0];
argv++;
argc--;
}
if (strlen(sys) > MAXBASENAME)
sys[MAXBASENAME] = '\0';
if (versys(&sys) != SUCCESS){
fprintf(stderr,"uulog: unknown system %s\n", sys);
sys = NULL;
}
break;
case 'u':
user = &argv[1][2];
if (*user == NULL && argc > 2 && argv[2][0] != '-') {
user = &argv[2][0];
argv++;
argc--;
}
break;
default:
printf("unknown flag %s\n", argv[1]); break;
}
--argc; argv++;
}
if (user == NULL && sys == NULL) {
fprintf(stderr, "usage: uulog [-u user] [-s sys]\n");
exit(1);
}
#ifdef LOGBYSITE
if (chdir(SPOOL) < 0) {
perror(SPOOL);
exit(1);
}
/* this program is really obsolete, this is a rude backward compat */
if (user) {
sprintf(buf, "exec cat LOG/uu*/* | egrep '^%s '", user);
system(buf);
}
if (sys) {
sprintf(buf,"exec cat LOG/uu*/%s", sys);
system(buf);
}
#else
plogf = fopen(LOGFILE, "r");
ASSERT(plogf != NULL, "CAN NOT OPEN", LOGFILE, 0);
while (fgets(buf, BUFSIZ, plogf) != NULL) {
sscanf(buf, "%s%s", u, s);
if (user != NULL && !prefix(user, u))
continue;
if (sys != NULL && !prefix(sys, s))
continue;
fputs(buf, stdout);
fflush(stdout);
}
#endif
exit(0);
}
cleanup(code)
int code;
{
exit(code);
}

78
src/cmd/uucp/uuname.c Normal file
View File

@@ -0,0 +1,78 @@
#ifndef lint
static char sccsid[] = "@(#)uuname.c 5.3 (Berkeley) 10/9/85";
#endif
#include "uucp.h"
#include <signal.h>
/*
* return list of all remote systems
* recognized by uucp, or (with -l) the local uucp name.
*
* return codes: 0 | 1 (can't read)
*/
struct timeb Now;
main(argc,argv)
char *argv[];
int argc;
{
int ret;
int i;
int intrEXIT();
FILE *np;
/* Increase buffers for s and prev. cornell!pavel */
char prev[1000];
char s[1000];
ret = chdir(Spool);
ASSERT(ret >= 0, "CHDIR FAILED", Spool, ret);
strcpy(Progname, "uuname");
signal(SIGILL, (sig_t)intrEXIT);
signal(SIGTRAP, (sig_t)intrEXIT);
signal(SIGIOT, (sig_t)intrEXIT);
signal(SIGEMT, (sig_t)intrEXIT);
signal(SIGFPE, (sig_t)intrEXIT);
signal(SIGBUS, (sig_t)intrEXIT);
signal(SIGSEGV, (sig_t)intrEXIT);
signal(SIGSYS, (sig_t)intrEXIT);
signal(SIGINT, (sig_t)intrEXIT);
signal(SIGHUP, (sig_t)intrEXIT);
signal(SIGQUIT, (sig_t)intrEXIT);
signal(SIGTERM, (sig_t)intrEXIT);
if(argc > 1 && argv[1][0] == '-' && argv[1][1] == 'l') {
uucpname(s);
printf("%s\n",s);
exit(0);
}
if(argc != 1) {printf("Usage: uuname [-l]\n"); exit(1);}
if((np = fopen(SYSFILE,"r")) == NULL) {
printf("%s (name file) protected\n",SYSFILE);
exit(1);
}
while ( cfgets(s,sizeof(s),np) != NULL ) {
for(i=0; s[i]!=' ' && s[i]!='\t'; i++)
;
s[i]='\0';
if (strcmp(s, prev) == SAME)
continue;
if(s[0]=='x' && s[1]=='x' && s[2]=='x')
continue;
printf("%s\n",s);
strcpy(prev, s);
}
exit(0);
}
intrEXIT(inter)
{
exit(inter);
}
cleanup(code)
int code;
{
exit(code);
}

79
src/cmd/uucp/uupoll.c Normal file
View File

@@ -0,0 +1,79 @@
#ifndef lint
static char sccsid[] = "@(#)uupoll.c 5.5 (Berkeley) 10/9/85";
#endif
/*
* Poll named system(s).
*
* The poll occurs even if recent attempts have failed,
* but not if L.sys prohibits the call (e.g. wrong time of day).
*
* AUTHOR
* Tom Truscott (rti!trt)
*/
#include "uucp.h"
int TransferSucceeded = 1;
struct timeb Now;
main(argc, argv)
register int argc;
register char **argv;
{
int ret;
char wrkpre[MAXFULLNAME];
char file[MAXFULLNAME];
char grade = 'A';
int nocall = 0;
if (argc < 2) {
fprintf(stderr, "usage: uupoll [-gX] [-n] system ...\n");
cleanup(1);
}
ret = chdir(Spool);
ASSERT(ret >= 0, "CHDIR FAILED", Spool, ret);
strcpy(Progname, "uupoll");
uucpname(Myname);
for (--argc, ++argv; argc > 0; --argc, ++argv) {
if (strcmp(argv[0], Myname) == SAME) {
fprintf(stderr, "This *is* %s!\n", Myname);
continue;
}
if (strncmp(argv[0],"-g",2) == SAME) {
grade = argv[0][2];
continue;
}
if (strcmp(argv[0],"-n") == SAME) {
nocall++;
continue;
}
if (versys(&argv[0])) {
fprintf(stderr, "%s: unknown system.\n", argv[0]);
continue;
}
/* Remove any STST file that might stop the poll */
sprintf(wrkpre, "%s/LCK..%.*s", LOCKDIR, MAXBASENAME, argv[0]);
if (access(wrkpre, 0) < 0)
rmstat(argv[0]);
sprintf(wrkpre, "%c.%.*s", CMDPRE, SYSNSIZE, argv[0]);
if (!iswrk(file, "chk", Spool, wrkpre)) {
sprintf(file, "%s/%c.%.*s%cPOLL", subdir(Spool, CMDPRE),
CMDPRE, SYSNSIZE, argv[0], grade);
close(creat(file, 0666));
}
/* Attempt the call */
if (!nocall)
xuucico(argv[0]);
}
cleanup(0);
}
cleanup(code)
int code;
{
exit(code);
}

379
src/cmd/uucp/uuq.c Normal file
View File

@@ -0,0 +1,379 @@
#if !defined(lint) && defined(DOSCCS)
static char sccsid[] = "@(#)uuq.c 4.6.1 (2.11BSD) 1997/10/2";
#endif
/*
* uuq - looks at uucp queues
*
* Lou Salkind
* New York University
*
*/
#include "uucp.h"
#include <stdio.h>
#include <strings.h>
#ifdef NDIR
#include "libndir/ndir.h"
#else
#include <sys/dir.h>
#endif
#include <sys/stat.h>
#define NOSYS (struct sys *)0
#define W_TYPE wrkvec[0]
#define W_FILE1 wrkvec[1]
#define W_FILE2 wrkvec[2]
#define W_USER wrkvec[3]
#define W_OPTNS wrkvec[4]
#define W_DFILE wrkvec[5]
#define W_MODE wrkvec[6]
#define WSUFSIZE 5 /* work file name suffix size */
struct sys {
char s_name[8];
int s_njobs;
off_t s_bytes;
struct job *s_jobp;
struct sys *s_sysp;
};
struct job {
int j_files;
int j_flags;
char j_jobno[WSUFSIZE];
char j_user[22];
char j_fname[128];
char j_grade;
off_t j_bytes;
time_t j_date;
struct job *j_jobp;
};
struct sys *syshead;
struct sys *getsys();
int jcompare();
char *sysname;
char *user;
char *rmjob;
int hflag;
int lflag;
float baudrate = 1200.;
char Username[BUFSIZ];
char Filename[BUFSIZ];
int Maxulen = 0;
struct timeb Now;
main(argc, argv)
char **argv;
{
register i;
register struct sys *sp;
register struct job *jp;
struct job **sortjob;
int nsys;
strcpy(Progname, "uuq");
uucpname(Myname);
while (--argc > 0) {
argv++;
if (argv[0][0] == '-') switch (argv[0][1]) {
case 'r':
Spool = &argv[0][2];
break;
case 's':
sysname = &argv[0][2];
if (strlen(sysname) > SYSNSIZE)
sysname[SYSNSIZE] = '\0';
break;
case 'u':
user = &argv[0][2];
break;
case 'd':
rmjob = &argv[0][2];
break;
case 'b':
baudrate = atof(&argv[0][2]);
break;
case 'h':
hflag++;
break;
case 'l':
lflag++;
break;
default:
fprintf(stderr,
"usage: uuq [-l] [-h] [-ssystem] [-uuser] [-djobno] [-rspool] [-bbaudrate]\n");
exit(0);
}
}
subchdir(Spool);
baudrate *= 0.7; /* reduce speed because of protocol overhead */
baudrate *= 6.; /* convert to chars/minute (60/10) */
gather();
nsys = 0;
for (sp = syshead; sp; sp = sp->s_sysp) {
if (sp->s_njobs == 0)
continue;
if (!hflag && nsys++ > 0)
putchar('\n');
printf("%s: %d %s", sp->s_name,
sp->s_njobs, sp->s_njobs > 1 ? "jobs" : "job");
if (lflag) {
float minutes;
int hours;
/* The 80 * njobs is because of the uucp handshaking */
minutes = (float)(sp->s_bytes + 80 * sp->s_njobs)/baudrate;
hours = minutes/60;
printf(", %ld bytes, ", sp->s_bytes);
if (minutes > 60){
printf("%d hour%s, ",hours,
hours > 1 ? "s": "");
minutes -= 60 * hours;
}
printf("%3.1f minutes (@ effective baudrate of %ld)",
minutes,(long)(baudrate/6));
}
putchar('\n');
if (hflag)
continue;
/* sort them babies! */
sortjob = (struct job **)calloc(sp->s_njobs, sizeof (struct job
*));
for (i=0, jp=sp->s_jobp; i < sp->s_njobs; i++, jp=jp->j_jobp)
sortjob[i] = jp;
qsort(sortjob, sp->s_njobs, sizeof (struct job *), jcompare);
for (i = 0; i < sp->s_njobs; i++) {
jp = sortjob[i];
if (lflag) {
printf("%s %2d %-*s%7ld%5.1f %-12.12s %c %.*s\n",
jp->j_jobno, jp->j_files, Maxulen, jp->j_user, jp->j_bytes, jp->j_bytes/baudrate,
ctime(&jp->j_date) + 4, jp->j_flags, sizeof (jp->j_fname), jp->j_fname
);
} else {
printf("%s", jp->j_jobno);
putchar((i+1)%10 ? '\t' : '\n');
}
/* There's no need to keep the force poll if jobs > 1*/
if (sp->s_njobs > 1 && strcmp("POLL", jp->j_jobno)==0) {
char pbuf[BUFSIZ];
sprintf(pbuf,"%s/%c.%szPOLL", subdir(Spool, CMDPRE), CMDPRE,sp->s_name);
unlink(pbuf);
}
}
if (!lflag && (sp->s_njobs%10))
putchar('\n');
}
exit(0);
}
jcompare(j1, j2)
struct job **j1, **j2;
{
int delta;
delta = (*j1)->j_grade - (*j2)->j_grade;
if (delta)
return delta;
return(strcmp((*j1)->j_jobno,(*j2)->j_jobno));
}
/*
* Get all the command file names
*/
gather()
{
struct direct *d;
DIR *df;
/*
* Find all the spool files in the spooling directory
*/
if ((df = opendir(subdir(Spool, CMDPRE))) == NULL) {
fprintf(stderr, "can't examine spooling area");
exit(1);
}
for (;;) {
if ((d = readdir(df)) == NULL)
break;
if (d->d_namlen <= 2 || d->d_name[0] != CMDPRE ||
d->d_name[1] != '.')
continue;
if (analjob(d->d_name) < 0) {
fprintf(stderr, "out of memory\n");
break;
}
}
closedir(df);
}
/*
* analjob does the grunge work of verifying jobs
*/
analjob(filename)
char *filename;
{
struct job *jp;
struct sys *sp;
char sbuf[MAXNAMLEN+1], str[256], nbuf[256];
char *jptr, *wrkvec[20];
char grade;
FILE *fp, *df;
struct stat statb;
int files, gotname, i;
off_t bytes;
strncpy(sbuf, filename, MAXNAMLEN);
sbuf[MAXNAMLEN] = '\0';
jptr = sbuf + strlen(sbuf) - WSUFSIZE;
grade = *jptr;
*jptr++ = 0;
/*
* sbuf+2 now points to sysname name (null terminated)
* jptr now points to job number (null terminated)
*/
if (rmjob) {
if (strcmp(rmjob, jptr))
return(0);
} else {
if ((sp = getsys(sbuf+2)) == NOSYS)
return(0);
if (!lflag) {
/* SHOULD USE A SMALLER STRUCTURE HERE */
jp = (struct job *)malloc(sizeof(struct job));
if (jp == (struct job *)0)
return(-1);
strcpy(jp->j_jobno, jptr);
jp->j_jobp = sp->s_jobp;
jp->j_grade = grade;
sp->s_jobp = jp;
sp->s_njobs++;
return(1);
}
}
if ((fp = fopen(subfile(filename), "r")) == NULL) {
perror(subfile(filename));
return(0);
}
files = 0;
bytes = 0;
gotname = 0;
while (fgets(str, sizeof str, fp)) {
if (getargs(str, wrkvec, 20) <= 0)
continue;
if (rmjob) {
if (W_TYPE[0] == 'S' && !index(W_OPTNS, 'c')) {
unlink(subfile(W_DFILE));
fprintf(stderr, "Removing data file %s\n", W_DFILE);
}
continue;
}
if (user && (W_TYPE[0] == 'X' || !prefix(user, W_USER))) {
fclose(fp);
return(0);
}
files++;
if (W_TYPE[0] == 'S') {
if (strcmp(W_DFILE, "D.0") &&
stat(subfile(W_DFILE), &statb) >= 0)
bytes += statb.st_size;
else if (stat(subfile(W_FILE1), &statb) >= 0)
bytes += statb.st_size;
}
/* amusing heuristic */
#define isXfile(s) (s[0]=='D' && s[strlen(s)-WSUFSIZE]=='X')
if (gotname == 0 && isXfile(W_FILE1)) {
if ((df = fopen(subfile(W_FILE1), "r")) == NULL)
continue;
while (fgets(nbuf, sizeof nbuf, df)) {
nbuf[strlen(nbuf) - 1] = '\0';
if (nbuf[0] == 'C' && nbuf[1] == ' ') {
strcpy(Filename, nbuf+2);
gotname++;
} else if (nbuf[0] == 'R' && nbuf[1] == ' ') {
register char *p, *q, *r;
r = q = p = nbuf+2;
do {
if (*p == '!' || *p == '@'){
r = q;
q = p+1;
}
} while (*p++);
strcpy(Username, r);
W_USER = Username;
}
}
fclose(df);
}
}
fclose(fp);
if (rmjob) {
unlink(subfile(filename));
fprintf(stderr, "Removing command file %s\n", filename);
exit(0);
}
if (files == 0) {
static char *wtype = "X";
static char *wfile = "forced poll";
if (strcmp("POLL", &filename[strlen(filename)-4])) {
fprintf(stderr, "%.14s: empty command file\n", filename);
return(0);
}
W_TYPE = wtype;
W_FILE1 = wfile;
}
jp = (struct job *)malloc(sizeof(struct job));
if (jp == (struct job *)0)
return(-1);
strcpy(jp->j_jobno, jptr);
jp->j_files = files;
jp->j_bytes = bytes;
jp->j_grade = grade;
jp->j_flags = W_TYPE[0];
strncpy(jp->j_user, W_TYPE[0]=='X' ? "---" : W_USER, 20 );
jp->j_user[20] = '\0';
i = strlen(jp->j_user);
if (i > Maxulen)
Maxulen = i;
/* SHOULD ADD ALL INFORMATION IN THE WHILE LOOP */
if (gotname)
strncpy(jp->j_fname, Filename, sizeof jp->j_fname);
else
strncpy(jp->j_fname, W_FILE1, sizeof jp->j_fname);
stat(subfile(filename), &statb);
jp->j_date = statb.st_mtime;
jp->j_jobp = sp->s_jobp;
sp->s_jobp = jp;
sp->s_njobs++;
sp->s_bytes += jp->j_bytes;
return(1);
}
struct sys *
getsys(s)
register char *s;
{
register struct sys *sp;
for (sp = syshead; sp; sp = sp->s_sysp)
if (strcmp(s, sp->s_name) == 0)
return(sp);
if (sysname && !prefix(sysname, s))
return(NOSYS);
sp = (struct sys *)malloc(sizeof(struct sys));
if (sp == NOSYS)
return(NOSYS);
strcpy(sp->s_name, s);
sp->s_njobs = 0;
sp->s_jobp = (struct job *)0;
sp->s_sysp = syshead;
sp->s_bytes = 0;
syshead = sp;
return(sp);
}

357
src/cmd/uucp/uusend.c Normal file
View File

@@ -0,0 +1,357 @@
#if !defined(lint) && defined(DOSCCS)
static char sccsid[] = "@(#)uusend.c 5.2.1 (2.11BSD) 1996/10/24";
#endif
/*
* uusend: primitive operation to allow uucp like copy of binary files
* but handle indirection over systems.
*
* usage: uusend [-r] [-m ooo] localfile sysname1!sysname2!...!destfile
* uusend [-r] [-m ooo] - sysname1!sysname2!...!destfile
*
* Author: Mark Horton, May 1980.
*
* "-r" switch added. Has same effect as "-r" in uux. 11/82 CCW
*
* Error recovery (a la uucp) added & ifdefs for ruusend (as in rmail).
* Checks for illegal access to /etc/uucp.
* February 1983 Christopher Woodbury
* Fixed mode set[ug]id loophole. 4/8/83 CCW
*
* Add '-f' to make uusend syntax more similar to UUCP. "destname"
* can now be a directory. June 1983 CCW
*/
#include <stdio.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <strings.h>
/*
* define RECOVER to permit requests like 'uusend file sys1!sys2!~uucp'
* (abbreviation for 'uusend file sys1!sys2!~uucp/file').
* define DEBUG to keep log of uusend uusage.
* define RUUSEND if neighboring sites permit 'ruusend',
* which they certainly should to avoid security holes
*/
#define RECOVER
/*#define DEBUG "/usr/spool/uucp/uusend.log"/**/
FILE *in, *out;
FILE *dout;
extern FILE *popen();
extern char *index(), *strcpy(), *strcat(), *ctime();
#ifdef RUUSEND
int rsend;
#endif
int mode = -1; /* mode to chmod new file to */
char *nextsys; /* next system in the chain */
char dnbuf[200]; /* buffer for result of ~user/file */
char cmdbuf[256]; /* buffer to build uux command in */
char *rflg = ""; /* default value of rflg ccw -- 1 Nov '82 */
struct passwd *user; /* entry in /etc/passwd for ~user */
struct passwd *getpwnam();
struct stat stbuf;
char *excl; /* location of first ! in destname */
char *sl; /* location of first / in destname */
char *sourcename; /* argv[1] */
char *destname; /* argv[2] */
char *UULIB = "/etc/uucp"; /* UUCP lib directory */
#ifdef RECOVER
char *UUPUB = "/usr/spool/uucppublic/"; /* public UUCP directory */
char *filename; /* file name from end of destname */
char *getfname(); /* routine to get filename from destname */
int fflg;
char f[100]; /* name of default output file */
#else
char *f = ""; /* so we waste a little space */
#endif
main(argc, argv)
int argc;
char **argv;
{
register int c;
long count;
extern char **environ;
#ifdef DEBUG
long t;
umask(022);
dout = fopen(DEBUG, "a");
if (dout == NULL) {
printf("Cannot append to %s\n", DEBUG);
exit(1);
}
freopen(DEBUG, "a", stdout);
fprintf(dout, "\nuusend run: ");
for (c=0; c<argc; c++)
fprintf(dout, "%s ", argv[c]);
time(&t);
fprintf(dout, "%s", ctime(&t));
#endif
#ifdef RUUSEND
if(argv[0][0] == 'r')
rsend++;
#endif
while (argc > 1 && argv[1][0] == '-' && argv[1][1]) {
switch(argv[1][1]) {
case 'm':
sscanf(argv[2], "%o", &mode);
mode &= 0777; /* fix set[ug]id loophole */
argc--; argv++;
break;
case 'r': /* -r flag for uux */
rflg = "-r ";
break;
#ifdef RECOVER
case 'f':
fflg++;
strcpy(f, argv[1]);
break;
#endif
default:
fprintf(stderr, "Bad flag: %s\n", argv[1]);
break;
}
argc--; argv++;
}
if (argc != 3) {
fprintf(stderr, "Usage: uusend [-m ooo] [-r] -/file sys!sys!..!rfile\n");
exit(1);
}
sourcename = argv[1];
destname = argv[2];
if (sourcename[0] == '-')
in = stdin;
else {
#ifdef RUUSEND
if (rsend) {
fprintf(stderr, "illegal input\n");
exit(2);
}
#endif
in = fopen(sourcename, "r");
if (in == NULL) {
perror(argv[1]);
exit(2);
}
if (!fflg || f[2] == '\0') {
strcpy(f, "-f");
strcat(f, getfname(sourcename));
fflg++;
}
}
excl = index(destname, '!');
if (excl) {
/*
* destname is on a remote system.
*/
nextsys = destname;
*excl++ = 0;
destname = excl;
if (mode < 0) {
fstat(fileno(in), &stbuf);
mode = stbuf.st_mode & 0777;
}
#ifdef RUUSEND
sprintf(cmdbuf,"uux -gn -z %s- \"%s!ruusend %s -m %o - (%s)\"",
#else
sprintf(cmdbuf, "uux -gn -z %s- \"%s!uusend %s -m %o - (%s)\"",
#endif
rflg, nextsys, f, mode, destname);
#ifdef DEBUG
fprintf(dout, "remote: nextsys='%s', destname='%s', cmd='%s'\n", nextsys, destname, cmdbuf);
#endif
out = popen(cmdbuf, "w");
} else {
/*
* destname is local.
*/
if (destname[0] == '~') {
#ifdef DEBUG
fprintf(dout, "before ~: '%s'\n", destname);
fflush(dout);
#endif
sl = index(destname, '/');
#ifdef RECOVER
if (sl == NULL && !fflg) {
fprintf(stderr, "Illegal ~user\n");
exit(3);
}
for (sl = destname; *sl != '\0'; sl++)
; /* boy, is this a hack! */
#else
if (sl == NULL) {
fprintf(stderr, "Illegal ~user\n");
exit(3);
}
*sl++ = 0;
#endif
user = getpwnam(destname+1);
if (user == NULL) {
fprintf(stderr, "No such user as %s\n",
destname);
#ifdef RECOVER
if ((filename =getfname(sl)) == NULL &&
!fflg)
exit(4);
strcpy(dnbuf, UUPUB);
if (fflg)
strcat(dnbuf, &f[2]);
else
strcat(dnbuf, filename);
}
else {
strcpy(dnbuf, user->pw_dir);
strcat(dnbuf, "/");
strcat(dnbuf, sl);
}
#else
exit(4);
}
strcpy(dnbuf, user->pw_dir);
strcat(dnbuf, "/");
strcat(dnbuf, sl);
#endif
destname = dnbuf;
}
#ifdef RECOVER
else
destname = strcpy(dnbuf, destname);
#endif
if(strncmp(UULIB, destname, strlen(UULIB)) == 0) {
fprintf(stderr, "illegal file: %s", destname);
exit(4);
}
#ifdef RECOVER
if (stat(destname, &stbuf) == 0 &&
(stbuf.st_mode & S_IFMT) == S_IFDIR &&
fflg) {
strcat(destname, "/");
strcat(destname, &f[2]);
}
#endif
out = fopen(destname, "w");
#ifdef DEBUG
fprintf(dout, "local, file='%s'\n", destname);
#endif
if (out == NULL) {
perror(destname);
#ifdef RECOVER
if (strncmp(destname,UUPUB,strlen(UUPUB)) == 0)
exit(5); /* forget it! */
filename = getfname(destname);
if (destname == dnbuf) /* cmdbuf is scratch */
filename = strcpy(cmdbuf, filename);
destname = strcpy(dnbuf, UUPUB);
if (user != NULL) {
strcat(destname, user->pw_name);
if (stat(destname, &stbuf) == -1) {
mkdir(destname, 0777);
}
strcat(destname, "/");
}
if (fflg)
strcat(destname, &f[2]);
else
strcat(destname, filename);
if ((out = fopen(destname, "w")) == NULL)
exit(5); /* all for naught! */
#else
exit(5);
#endif
}
if (mode > 0)
chmod(destname, mode); /* don't bother to check it */
}
/*
* Now, in any case, copy from in to out.
*/
count = 0;
while ((c=getc(in)) != EOF) {
putc(c, out);
count++;
}
#ifdef DEBUG
fprintf(dout, "count %ld bytes\n", count);
fclose(dout);
#endif
fclose(in);
fclose(out); /* really should pclose in that case */
exit(0);
}
/*
* Return the ptr in sp at which the character c appears;
* NULL if not found. Included so I don't have to fight the
* index/strchr battle.
*/
#define NULL 0
#ifdef RECOVER
char *
getfname(p)
register char *p;
{
register char *s;
s = p;
while (*p != '\0')
p++;
if (p == s)
return (NULL);
for (;p != s; p--)
if (*p == '/') {
p++;
break;
}
return (p);
}
#ifndef BSD4_2
makedir(dirname, mode)
char *dirname;
int mode;
{
register int pid;
int retcode, status;
switch ((pid = fork())) {
case -1: /* error */
return (-1);
case 0: /* child */
umask(0);
execl("/bin/mkdir", "mkdir", dirname, (char *)0);
exit(1);
/* NOTREACHED */
default: /* parent */
while ((retcode=wait(&status)) != pid && retcode != -1)
;
if (retcode == -1)
return -1;
else {
chmod(dirname, mode);
return status;
}
}
/* NOTREACHED */
}
#endif
#endif

285
src/cmd/uucp/uusnap.c Normal file
View File

@@ -0,0 +1,285 @@
#ifndef lint
static char sccsid[] = "@(#)uusnap.c 5.7 (Berkeley) 10/9/85";
#endif
/*
* Uusnap - displays a snapshot of the uucp system.
* originally by RJKing WECo-MG6565 May 83
*/
#include "uucp.h"
#include <sys/stat.h>
#include <strings.h>
#ifdef NDIR
#include "ndir.h"
#else
#include <sys/dir.h>
#endif
#include <ctype.h>
#ifndef SYSBUF
char SYSBUF[BUFSIZ];
#endif
#define NSYSTEM 100 /* max # of systems queued */
#define CMDSLEN 5 /* Length of trailer */
#define DATALEN 5 /* Length of trailer */
#define XEQTLEN 5 /* Length of trailer */
#define NUMCTRS 3 /* # file types to count */
#define CMDTYPE 0 /* Index into scnt.cntr */
#define DATTYPE 1 /* Index into scnt.cntr */
#define XEQTYPE 2 /* Index into scnt.cntr */
struct scnt { /* System count structure */
char name[MAXBASENAME+1]; /* Name of system */
short cntr[NUMCTRS]; /* Count */
char stst[32]; /* STST Message */
time_t locked; /* If LCK..sys present */
int st_type; /* STST Type */
int st_count; /* STST Count */
time_t st_lastime; /* STST Last time tried */
time_t st_retry; /* STST Secs to retry */
};
int sndx; /* Number of systems */
struct scnt sys[NSYSTEM]; /* Systems queued */
int xqtisrunning = 0;
main()
{ register int i, j, nlen = 0;
time_t curtime, t;
setbuf(stdout, SYSBUF);
scandir(CMDSDIR, "C.", CMDSLEN, NULL, CMDTYPE);
scandir(DATADIR, "D.", DATALEN, NULL, DATTYPE);
scandir(XEQTDIR, "X.", XEQTLEN, 'X', XEQTYPE);
getstst(SPOOL);
time(&curtime);
for(i=0; i<sndx; ++i)
if((j = strlen(sys[i].name)) > nlen)
nlen = j;
for(i=0; i<sndx; ++i) {
t = (sys[i].st_lastime +sys[i].st_retry) - curtime;
/* decide if STST text is worth printing */
if (-t < ONEDAY*2 && sys[i].st_type == SS_WRONGTIME) {
sys[i].stst[0] = '\0';
if (sys[i].cntr[0]+sys[i].cntr[1]+sys[i].cntr[2] == 0)
continue; /* ignore entire line */
}
printf("%-*.*s ", nlen, nlen, sys[i].name);
if(sys[i].cntr[CMDTYPE])
printf("%3.d Cmd%s ", sys[i].cntr[CMDTYPE],
sys[i].cntr[CMDTYPE]>1?"s":" ");
else
printf(" --- ");
if(sys[i].cntr[DATTYPE])
printf("%3.d Data ", sys[i].cntr[DATTYPE]);
else
printf(" --- ");
if(sys[i].cntr[XEQTYPE])
printf("%3.d Xqt%s ", sys[i].cntr[XEQTYPE],
sys[i].cntr[XEQTYPE]>1?"s":" ");
else
printf(" --- ");
if(*sys[i].stst == NULL || sys[i].locked > sys[i].st_lastime) {
if(sys[i].locked)
printf("LOCKED\n");
else
printf("\n");
continue;
}
printf("%s ", sys[i].stst);
/* decide if STST info is worth pursuing */
if (-t < ONEDAY*2 && (sys[i].st_count == 0
|| sys[i].st_type == SS_WRONGTIME
|| (sys[i].st_type == SS_INPROGRESS && sys[i].locked))) {
printf("\n");
continue;
}
t = (sys[i].st_lastime +sys[i].st_retry) - curtime;
if (-t < ONEDAY*2 && sys[i].st_type != SS_FAIL)
t = 0;
if (sys[i].st_count > MAXRECALLS)
printf("at MAX RECALLS");
else if (-t >= ONEDAY*2)
printf("%ld days ago", (long)-t/ONEDAY);
else if (t <= 0)
printf("Retry time reached");
else if (t < 60)
printf("Retry time %ld sec%s", (long)(t%60),
(t%60)!=1? "s": "");
else
printf("Retry time %ld min%s", (long)(t/60),
(t/60)!=1? "s": "");
if(sys[i].st_count > 1)
printf(" Count: %d\n", sys[i].st_count);
else
printf("\n");
}
if (xqtisrunning)
printf("\nUuxqt is running\n");
exit(0);
}
scandir(dnam, prfx, flen, fchr, type)
char *dnam, *prfx, fchr;
{
register struct direct *dentp;
register DIR *dirp;
register int i, fnamlen, plen;
char fnam[MAXNAMLEN+1];
plen = strlen(prfx);
if(chdir(dnam) < 0) {
perror(dnam);
exit(1);
}
if ((dirp = opendir(".")) == NULL) {
perror(dnam);
exit(1);
}
while((dentp = readdir(dirp)) != NULL) {
if(*dentp->d_name == '.')
continue;
if(strncmp(dentp->d_name, prfx, plen) != SAME) {
fprintf(stderr, "strange file (%s) in %s\n",
dentp->d_name, dnam);
continue;
}
strcpy(fnam, &dentp->d_name[plen]);
fnamlen = strlen(fnam);
if(flen > 0) {
char c;
fnamlen -= flen;
c = fnam[fnamlen];
if (islower(c))
c = toupper(c);
if (type == DATTYPE && (c != 'S' && c != 'B')) {
fnamlen -= 2; /* For Honey DanBer */
fnam[fnamlen] = NULL;
} else {
fnam[fnamlen] = NULL;
fnamlen = MAXBASENAME; /* yes, after = NULL*/
}
} else {
for(; fnamlen>0; --fnamlen) {
if(fnam[fnamlen] == fchr) {
fnam[fnamlen] = NULL;
break;
}
}
fnamlen = MAXBASENAME;
}
for(i=0; i<sndx; ++i) {
if(strncmp(fnam, sys[i].name, fnamlen) == SAME) {
++sys[i].cntr[type];
break;
}
}
if(i == sndx) {
strcpy(sys[i].name, fnam);
++sys[i].cntr[type];
++sndx;
}
}
closedir(dirp);
}
getstst(sdir)
char *sdir;
{
register int i, csys;
register char *tp;
char fnam[MAXNAMLEN+1], buff[128];
register struct direct *dentp;
register DIR *dirp;
register FILE *st;
struct stat stbuf;
long atol();
if (chdir(sdir) < 0) {
perror(sdir);
exit(1);
}
if ((dirp = opendir(LOCKDIR)) == NULL) {
perror(sdir);
exit(1);
}
while ((dentp = readdir(dirp)) != NULL) {
if (strcmp(&dentp->d_name[5], X_LOCK) == SAME) {
xqtisrunning++;
continue;
}
if(strncmp(dentp->d_name, "LCK..", 5) == SAME) {
if(strncmp(&dentp->d_name[5], "tty", 3) == SAME ||
strncmp(&dentp->d_name[5], "cul", 3) == SAME)
continue;
strcpy(fnam, dentp->d_name);
for(csys=0; csys<sndx; ++csys) {
if(strncmp(&fnam[5], sys[csys].name, SYSNSIZE)
== SAME)
break;
}
strcpy(sys[csys].name, &fnam[5]);
if(csys == sndx) {
++sndx;
}
if (stat(fnam, &stbuf) < 0)
sys[csys].locked = 1;
else
sys[csys].locked = stbuf.st_mtime;
continue;
}
}
closedir(dirp);
if (chdir("STST") < 0) {
perror("STST");
exit(1);
}
if ((dirp = opendir(".")) == NULL) {
perror("STST");
exit(1);
}
while ((dentp = readdir(dirp)) != NULL) {
if(*dentp->d_name == '.')
continue;
strcpy(fnam, dentp->d_name);
for(csys=0; csys<sndx; ++csys) {
if(strncmp(fnam, sys[csys].name, SYSNSIZE) == SAME)
break;
}
strcpy(sys[csys].name, fnam);
if(csys == sndx) {
++sndx;
}
if((st = fopen(fnam, "r")) == NULL) {
sys[csys].stst[0] = '\0';
continue;
}
buff[0] = '\0';
fgets(buff, sizeof(buff), st);
fclose(st);
if(tp = rindex(buff, ' '))
*tp = NULL; /* drop system name */
else
continue;
for(i=0, tp=buff; i<4; ++i, ++tp)
if((tp = index(tp, ' ')) == NULL)
break;
if(i != 4)
continue;
strncpy(sys[csys].stst, tp, sizeof(sys[csys].stst));
tp = buff;
sys[csys].st_type = atoi(tp);
tp = index(tp+1, ' ');
sys[csys].st_count = atoi(tp+1);
tp = index(tp+1, ' ');
sys[csys].st_lastime = atol(tp+1);
tp = index(tp+1, ' ');
sys[csys].st_retry = atol(tp+1);
}
}

Some files were not shown because too many files have changed in this diff Show More