[net.sources] news 2.10.2 src part 1

rick@seismo.UUCP (Rick Adams) (09/08/84)

cat <<'E_O_F'
	Part one apparently got lost somewhere. It
	DID leave seismo. Anyway, here it is again.

	There are 9 total parts. Each part ends with the
	word "exit". Apparently parts 3 & 5 have been truncated
	at several sites.
	---rick
E_O_F
if test ! -d src
then
	mkdir src
fi
echo x - src/Makefile.usg
sed 's/^X//' >src/Makefile.usg <<'*-*-END-of-src/Makefile.usg-*-*'
X# @(#)Makefile.usg	2.25	9/3/84
X# Makefile for System III, System V and other USG based systems
X
X# definitions
X
XNEWSUSR = news
XNEWSGRP = news
X# This is either usg or v7
XOSTYPE= usg
X# HOME is the user name whose home dir has all the news stuff in it.
XHOME=	exptools
X# Use the -DHOME line if you want dynamic lookup in /etc/passwd
X#HOMENAME=	-DHOME=\"$(HOME)\"
XHOMENAME=
XSPOOLDIR = /usr/spool/news
XBATCHDIR = /usr/spool/batch
XLIBDIR = /usr/lib/news
XBINDIR = /usr/bin
XUUXFLAGS = -r -z
X
XDEBUG =
XIBMFLAGS =
XDEFS =	-DRNEWS=\"$(BINDIR)/rnews\" -DSPOOLDIR=\"$(SPOOLDIR)\" \
X	-DBATCHDIR=\"$(BATCHDIR)\" -DLIBDIR=\"$(LIBDIR)\" \
X	-DBINDIR=\"$(BINDIR)\" -DNEWSUSR=\"$(NEWSUSR)\" \
X	-DNEWSGRP=\"$(NEWSGRP)\"
XCFLAGS = ${DEBUG} -O $(IBMFLAGS) -DUSG -Dindex=strchr -Drindex=strrchr ${DEFS}
XLFLAGS = -s -i $(IBMFLAGS)
XLIBS =
XLINTFLAGS = ${DEFS}
X
XMISC = ftime.o
XOBJECTS = funcs.o funcs2.o getdate.o header.o ndir.o $(MISC)
XIOBJECTS = inews.o ifuncs.o iextern.o control.o fullname.o \
X	ipathinit.o $(OBJECTS)
XPOBJECTS = postnews.o rextern.o rpathinit.o funcs.o $(MISC)
XROBJECTS = readnews.o rfuncs.o rfuncs2.o rextern.o readr.o \
X	process.o rpathinit.o digest.o $(OBJECTS)
XVOBJECTS = readnews.o rfuncs.o rfuncs2.o rextern.o process.o rpathinit.o \
X	$(OBJECTS) visual.o virtterm.o
XEXPOBJS=  expire.o header.o funcs.o getdate.o rextern.o epathinit.o \
X	funcs2.o ndir.o $(MISC)
X
XSRCS = funcs.c funcs2.c header.c
XISRCS = inews.c ifuncs.c iextern.c control.c fullname.c  $(SRCS)
XPSRCS = postnews.c rextern.c funcs.c
XRSRCS = readnews.c rfuncs.c rfuncs2.c rextern.c readr.c process.c  \
X	digest.c $(SRCS)
XVSRCS = readnews.c rfuncs.c rfuncs2.c rextern.c process.c $(SRCS) \
X	visual.c virtterm.c
XEXPSRCS = expire.c header.c funcs.c getdate.c rextern.c \
X	funcs2.c
XOSRCS = uurec.c recnews.c sendnews.c batch.c unbatch.c caesar.c \
X	recmail.c compress.c
X
XOTHERS = inews uurec recnews sendnews expire batch unbatch caesar recmail \
X	compress sendbatch csendbatch rmgroup checkgroups
XCOMMANDS = readnews checknews postnews vnews cunbatch
X
X# dependencies
Xall: $(COMMANDS) $(OTHERS)
X
Xcp: all $(LIBDIR) $(BINDIR) help vnews.help
X	cp $(COMMANDS) $(BINDIR)
X	-cd $(BINDIR); chown $(NEWSUSR) $(COMMANDS); chgrp $(NEWSGRP) $(COMMANDS);\
X		chmod 755 $(COMMANDS)
X	@echo "Reminder: uux must permit cunbatch if running over uucp."
X	cp help vnews.help $(OTHERS) $(LIBDIR)
X	cd $(LIBDIR); chown $(NEWSUSR) $(OTHERS); chgrp $(NEWSGRP) $(OTHERS);\
X		chmod 755 $(OTHERS)
X	chmod 6755 $(LIBDIR)/inews
X	-rm -f $(BINDIR)/rnews
X	ln $(LIBDIR)/inews $(BINDIR)/rnews
X
Xdefs.h:	defs.dist localize.sh
X	sh localize.sh
X
XMakefile: Makefile.$(OSTYPE) localize.sh defs.dist
X	sh localize.sh
X
Xinstall: cp install.sh makeactive.sh
X	sh install.sh $(SPOOLDIR) $(LIBDIR) $(NEWSUSR) $(NEWSGRP) $(OSTYPE)
X
Xclean:
X	rm -f $(COMMANDS) $(OTHERS) *.o a.out
X	rm -f core index errs getdate.c
X
Xlint:  ilint vlint rlint elint plint olint
X
Xilint: defs.h params.h iparams.h header.h $(ISRCS)
X	lint $(LINTFLAGS) $(ISRCS)
X
Xvlint: defs.h params.h rparams.h header.h $(VSRCS)
X	lint $(LINTFLAGS) $(VSRCS)
X
Xrlint: defs.h params.h rparams.h header.h $(RSRCS)
X	lint $(LINTFLAGS) $(RSRCS)
X
Xelint: defs.h params.h iparams.h header.h $(ESRCS)
X	lint $(LINTFLAGS) $(ESRCS)
X
Xplint: defs.h params.h iparams.h header.h $(PSRCS)
X	lint $(LINTFLAGS) $(PSRCS)
X
Xolint: defs.h params.h iparams.h header.h $(OSRCS)
X	for i in $(OSRCS); do lint $(LINTFLAGS) $$i; done
X
Xinews:  Makefile $(IOBJECTS)
X	$(CC) $(LFLAGS) $(IOBJECTS) -o inews $(LIBS)
X
Xreadnews:  Makefile $(ROBJECTS)
X	$(CC) $(LFLAGS) $(ROBJECTS) -o readnews $(LIBS)
X
Xfuncs.o:  funcs.c params.h defs.h header.h
X	$(CC) $(CFLAGS) -c funcs.c
X
Xgetdate.o:  getdate.y
X	@echo "expect 6 shift/reduce conflicts"
X	yacc getdate.y
X	mv y.tab.c getdate.c
X	$(CC) $(CFLAGS) -c getdate.c
X	-rm -f getdate.c
X
Xinews.o:  inews.c iparams.h defs.h params.h header.h
X	$(CC) $(CFLAGS) -c inews.c
X
Xifuncs.o:  ifuncs.c iparams.h defs.h params.h header.h
X	$(CC) $(CFLAGS) $(HOMENAME) -c ifuncs.c
X
Xiextern.o:  iextern.c iparams.h defs.h params.h Makefile header.h
X	$(CC) $(CFLAGS) -c iextern.c
X
Xpostnews: Makefile $(POBJECTS)
X	$(CC) $(CFLAGS) $(LFLAGS) $(POBJECTS) -o postnews
X
Xpostnews.o: postnews.c defs.h
X	$(CC) $(CFLAGS) -c postnews.c
X
Xreadnews.o:  readnews.c rparams.h defs.h params.h header.h
X	$(CC) $(CFLAGS) $(HOMENAME) -c readnews.c
X
Xrfuncs.o:  rfuncs.c rparams.h defs.h params.h header.h
X	$(CC) $(CFLAGS) -c rfuncs.c
X
Xrfuncs2.o:  rfuncs2.c rparams.h defs.h params.h header.h
X	$(CC) $(CFLAGS) -c rfuncs2.c
X
Xrextern.o:  rextern.c rparams.h defs.h params.h Makefile header.h
X	$(CC) $(CFLAGS) -c rextern.c
X
Xreadr.o:  readr.c rparams.h defs.h params.h Makefile ndir.h header.h
X	$(CC) $(CFLAGS) -c readr.c
X
Xchecknews.o:  checknews.c defs.h header.h Makefile
X	$(CC) $(CFLAGS) -c checknews.c
X
Xvnews:	$(VOBJECTS)
X	$(CC) $(LFLAGS) $(VOBJECTS) -ltermcap $(LIBS) -o $@
X
Xvisual.o:  visual.c rparams.h defs.h params.h ndir.h header.h
X	$(CC) $(CFLAGS) -c visual.c
X
Xcontrol.o:  control.c defs.h iparams.h params.h header.h
X	$(CC) $(CFLAGS) -c control.c
X
Xlogdir.o: logdir.c
X	$(CC) $(CFLAGS) -c logdir.c
X
Xuname.o:  uname.c defs.h
X	$(CC) $(CFLAGS) -c uname.c
X
Xndir.o: ndir.c ndir.h
X	$(CC) $(CFLAGS) -c ndir.c
X
Xuurec:  uurec.c defs.h
X	$(CC) $(CFLAGS) -s uurec.c -o uurec
X
Xrecnews:  recnews.c defs.h
X	$(CC) $(CFLAGS) -s recnews.c -o recnews
X
Xsendnews:  sendnews.o uname.o
X	$(CC) $(LFLAGS) sendnews.o uname.o -o sendnews
X
Xbatch:  batch.c Makefile
X	$(CC) $(CFLAGS) -s batch.c -o batch
X
Xunbatch:  unbatch.c
X	$(CC) $(CFLAGS) -s unbatch.c -o unbatch
X
Xcaesar:  caesar.c
X	$(CC) $(CFLAGS) -s caesar.c -o caesar -lm
X
X# do NOT compile this with -O on a vax due to a bug in the optimizer
Xcompress: compress.c
X	$(CC) -o compress compress.c
X
Xrecmail:  recmail.c
X	$(CC) $(CFLAGS) -s recmail.c -o recmail
X
Xprocess.o:  process.c rparams.h defs.h params.h header.h
X	$(CC) $(CFLAGS) -c process.c
X
X
Xchecknews:  Makefile checknews.o process.o cpathinit.o
X	$(CC) $(LFLAGS) checknews.o process.o cpathinit.o -o checknews
X
Xcsendbatch: csendbatch.sh Makefile
X	sed -e "s%LIBDIR%$(LIBDIR)%g" \
X	 -e "s%UUXFLAGS%$(UUXFLAGS)%g" \
X	 -e "s%BATCHDIR%$(BATCHDIR)%g" csendbatch.sh > csendbatch
X
Xsendbatch: sendbatch.sh Makefile
X	sed -e "s%LIBDIR%$(LIBDIR)%g" \
X	 -e "s%UUXFLAGS%$(UUXFLAGS)%g" \
X	 -e "s%BATCHDIR%$(BATCHDIR)%g" sendbatch.sh > sendbatch
X
Xcunbatch: cunbatch.sh Makefile
X	sed -e "s%LIBDIR%$(LIBDIR)%g" \
X	 -e "s%BINDIR%$(BINDIR)%g" cunbatch.sh > cunbatch
X
Xrmgroup: rmgroup.sh Makefile
X	sed -e "s%LIBDIR%$(LIBDIR)%g" \
X	 -e "s%SPOOLDIR%$(SPOOLDIR)%g" rmgroup.sh > rmgroup
X
Xcheckgroups: checkgroups.sh Makefile
X	sed -e "s%LIBDIR%$(LIBDIR)%g" checkgroups.sh > checkgroups
X
Xsendnews.o: sendnews.c defs.h
X	$(CC) $(CFLAGS) -c sendnews.c
X
Xfullname.o: defs.h
X
Xexpire: Makefile $(EXPOBJS)
X	$(CC) $(LFLAGS) -o expire $(EXPOBJS) $(LIBS)
X
Xheader.o:  header.c header.h defs.h
X	$(CC) $(CFLAGS) -c header.c
X
Xexpire.o:  expire.c defs.h Makefile params.h ndir.h header.h
X	$(CC) $(CFLAGS) -c expire.c
X
Xdigest.o:  digest.c
X	$(CC) $(CFLAGS) -c digest.c
X
Xparams.h: defs.h header.h
X
X# Some silliness here to get pathinit for both readnews & inews
Xrpathinit.o:  pathinit.c rparams.h header.h params.h
X	$(CC) $(CFLAGS) $(HOMENAME) -DREAD -c pathinit.c
X	mv pathinit.o rpathinit.o
X
Xipathinit.o:  pathinit.c iparams.h header.h params.h
X	$(CC) $(CFLAGS) $(HOMENAME) -DINEW -c pathinit.c
X	mv pathinit.o ipathinit.o
X
Xcpathinit.o:  pathinit.c iparams.h header.h params.h
X	$(CC) $(CFLAGS) $(HOMENAME) -DCHKN -c pathinit.c
X	mv pathinit.o cpathinit.o
X
Xepathinit.o:  pathinit.c iparams.h header.h params.h
X	$(CC) $(CFLAGS) $(HOMENAME) -DEXP -c pathinit.c
X	mv pathinit.o epathinit.o
X
Xtags:	/tmp
X	ctags -w *.h *.c
X
X$(LIBDIR):
X	mkdir $(LIBDIR)
X	chmod 755 $(LIBDIR)
X	chown $(NEWSUSR) $(LIBDIR)
X	chgrp $(NEWSGRP) $(LIBDIR)
X
X$(BINDIR):
X	mkdir $(BINDIR)
X	chmod 755 $(BINDIR)
X	chown $(NEWSUSR) $(BINDIR)
X	chgrp $(NEWSGRP) $(BINDIR)
*-*-END-of-src/Makefile.usg-*-*
echo x - src/Makefile.v7
sed 's/^X//' >src/Makefile.v7 <<'*-*-END-of-src/Makefile.v7-*-*'
X# @(#)Makefile.v7	2.26	9/3/84
X# Makefile for V7, 4.1BSD, and other Research V7 based systems
X
X# definitions
X
XNEWSUSR = news
XNEWSGRP = news
X# This is either usg or v7
XOSTYPE = v7
X# HOME is the user name whose home dir has all the news stuff in it.
XHOME=	exptools
X# Use the -DHOME line if you want dynamic lookup in /etc/passwd
X#HOMENAME=	-DHOME=\"$(HOME)\"
XHOMENAME=
XSPOOLDIR = /usr/spool/news
XBATCHDIR = /usr/spool/batch
XLIBDIR = /usr/lib/news
XBINDIR = /usr/bin
XUUXFLAGS = -r -z
X
XDEBUG =
XIBMFLAGS =
XDEFS =	-DRNEWS=\"$(BINDIR)/rnews\" -DSPOOLDIR=\"$(SPOOLDIR)\" \
X	-DBATCHDIR=\"$(BATCHDIR)\" -DLIBDIR=\"$(LIBDIR)\" \
X	-DBINDIR=\"$(BINDIR)\" -DNEWSUSR=\"$(NEWSUSR)\" \
X	-DNEWSGRP=\"$(NEWSGRP)\"
XCFLAGS = ${DEBUG} -O -DDBM ${DEFS}
XLFLAGS =
XLIBS = -ldbm
XLINTFLAGS = -chba -DDBM ${DEFS}
X
XMISC = uname.o
XOBJECTS = funcs.o funcs2.o getdate.o header.o ndir.o $(MISC)
XIOBJECTS = inews.o ifuncs.o iextern.o control.o fullname.o \
X	ipathinit.o $(OBJECTS)
XPOBJECTS = postnews.o rextern.o rpathinit.o funcs.o $(MISC)
XROBJECTS = readnews.o rfuncs.o rfuncs2.o rextern.o readr.o \
X	process.o rpathinit.o digest.o $(OBJECTS)
XVOBJECTS = readnews.o rfuncs.o rfuncs2.o rextern.o process.o rpathinit.o \
X	$(OBJECTS) visual.o virtterm.o
XEXPOBJS=  expire.o header.o funcs.o getdate.o rextern.o epathinit.o \
X	funcs2.o ndir.o $(MISC)
X
XSRCS = funcs.c funcs2.c header.c
XISRCS = inews.c ifuncs.c iextern.c control.c fullname.c  $(SRCS)
XPSRCS = postnews.c rextern.c funcs.c
XRSRCS = readnews.c rfuncs.c rfuncs2.c rextern.c readr.c process.c  \
X	digest.c $(SRCS)
XVSRCS = readnews.c rfuncs.c rfuncs2.c rextern.c process.c $(SRCS) \
X	visual.c virtterm.c
XEXPSRCS = expire.c header.c funcs.c getdate.c rextern.c \
X	funcs2.c
XOSRCS = uurec.c recnews.c sendnews.c batch.c unbatch.c caesar.c \
X	recmail.c compress.c
X
XOTHERS = inews uurec recnews sendnews expire batch unbatch caesar recmail \
X	compress sendbatch csendbatch rmgroup checkgroups
XCOMMANDS = readnews checknews postnews vnews cunbatch
X
X# dependencies
Xall: $(COMMANDS) $(OTHERS)
X
Xcp: all $(LIBDIR) $(BINDIR) help vnews.help
X	cp $(COMMANDS) $(BINDIR)
X	-cd $(BINDIR); chown $(NEWSUSR) $(COMMANDS); chgrp $(NEWSGRP) $(COMMANDS);\
X		chmod 755 $(COMMANDS)
X	@echo "Reminder: uux must permit cunbatch if running over uucp."
X	cp help vnews.help $(OTHERS) $(LIBDIR)
X	cd $(LIBDIR); chown $(NEWSUSR) $(OTHERS); chgrp $(NEWSGRP) $(OTHERS);\
X		chmod 755 $(OTHERS)
X	chmod 6755 $(LIBDIR)/inews
X	-rm -f $(BINDIR)/rnews
X	ln $(LIBDIR)/inews $(BINDIR)/rnews
X
Xdefs.h:	defs.dist localize.sh
X	sh localize.sh
X
XMakefile: Makefile.$(OSTYPE) localize.sh defs.dist
X	sh localize.sh
X
Xinstall: cp install.sh makeactive.sh
X	sh install.sh $(SPOOLDIR) $(LIBDIR) $(NEWSUSR) $(NEWSGRP) $(OSTYPE)
X
Xclean:
X	rm -f $(COMMANDS) $(OTHERS) *.o a.out
X	rm -f core index errs getdate.c
X
Xlint:  ilint vlint rlint elint plint olint
X
Xilint: defs.h params.h iparams.h header.h $(ISRCS)
X	lint $(LINTFLAGS) $(ISRCS)
X
Xvlint: defs.h params.h rparams.h header.h $(VSRCS)
X	lint $(LINTFLAGS) $(VSRCS)
X
Xrlint: defs.h params.h rparams.h header.h $(RSRCS)
X	lint $(LINTFLAGS) $(RSRCS)
X
Xelint: defs.h params.h iparams.h header.h $(ESRCS)
X	lint $(LINTFLAGS) $(ESRCS)
X
Xplint: defs.h params.h iparams.h header.h $(PSRCS)
X	lint $(LINTFLAGS) $(PSRCS)
X
Xolint: defs.h params.h iparams.h header.h $(OSRCS)
X	for i in $(OSRCS); do lint $(LINTFLAGS) $$i; done
X
Xinews:  Makefile $(IOBJECTS)
X	$(CC) $(LFLAGS) $(IOBJECTS) -o inews $(LIBS)
X
Xreadnews:  Makefile $(ROBJECTS)
X	$(CC) $(LFLAGS) $(ROBJECTS) -o readnews $(LIBS)
X
Xfuncs.o:  funcs.c params.h defs.h header.h
X	$(CC) $(CFLAGS) -c funcs.c
X
Xgetdate.o:  getdate.y
X	@echo "expect 6 shift/reduce conflicts"
X	yacc getdate.y
X	mv y.tab.c getdate.c
X	$(CC) $(CFLAGS) -c getdate.c
X	-rm -f getdate.c
X
Xinews.o:  inews.c iparams.h defs.h params.h header.h
X	$(CC) $(CFLAGS) -c inews.c
X
Xifuncs.o:  ifuncs.c iparams.h defs.h params.h header.h
X	$(CC) $(CFLAGS) $(HOMENAME) -c ifuncs.c
X
Xiextern.o:  iextern.c iparams.h defs.h params.h Makefile header.h
X	$(CC) $(CFLAGS) -c iextern.c
X
Xpostnews: Makefile $(POBJECTS)
X	$(CC) $(CFLAGS) $(LFLAGS) $(POBJECTS) -o postnews
X
Xpostnews.o: postnews.c defs.h
X	$(CC) $(CFLAGS) -c postnews.c
X
Xreadnews.o:  readnews.c rparams.h defs.h params.h header.h
X	$(CC) $(CFLAGS) $(HOMENAME) -c readnews.c
X
Xrfuncs.o:  rfuncs.c rparams.h defs.h params.h header.h
X	$(CC) $(CFLAGS) -c rfuncs.c
X
Xrfuncs2.o:  rfuncs2.c rparams.h defs.h params.h header.h
X	$(CC) $(CFLAGS) -c rfuncs2.c
X
Xrextern.o:  rextern.c rparams.h defs.h params.h Makefile header.h
X	$(CC) $(CFLAGS) -c rextern.c
X
Xreadr.o:  readr.c rparams.h defs.h params.h Makefile ndir.h header.h
X	$(CC) $(CFLAGS) -c readr.c
X
Xchecknews.o:  checknews.c defs.h header.h Makefile
X	$(CC) $(CFLAGS) -c checknews.c
X
Xvnews:	$(VOBJECTS)
X	$(CC) $(LFLAGS) $(VOBJECTS) -ltermcap $(LIBS) -o $@
X
Xvisual.o:  visual.c rparams.h defs.h params.h ndir.h header.h
X	$(CC) $(CFLAGS) -c visual.c
X
Xcontrol.o:  control.c defs.h iparams.h params.h header.h
X	$(CC) $(CFLAGS) -c control.c
X
Xlogdir.o: logdir.c
X	$(CC) $(CFLAGS) -c logdir.c
X
Xuname.o:  uname.c defs.h
X	$(CC) $(CFLAGS) -c uname.c
X
Xndir.o: ndir.c ndir.h
X	$(CC) $(CFLAGS) -c ndir.c
X
Xuurec:  uurec.c defs.h
X	$(CC) $(CFLAGS) -s uurec.c -o uurec
X
Xrecnews:  recnews.c defs.h
X	$(CC) $(CFLAGS) -s recnews.c -o recnews
X
Xsendnews:  sendnews.o uname.o
X	$(CC) $(LFLAGS) sendnews.o uname.o -o sendnews
X
Xbatch:  batch.c Makefile
X	$(CC) $(CFLAGS) -s batch.c -o batch
X
Xunbatch:  unbatch.c
X	$(CC) $(CFLAGS) -s unbatch.c -o unbatch
X
Xcaesar:  caesar.c
X	$(CC) $(CFLAGS) -s caesar.c -o caesar -lm
X
X# do NOT compile this with -O on a vax due to a bug in the optimizer
Xcompress: compress.c
X	$(CC) -o compress compress.c
X
Xrecmail:  recmail.c
X	$(CC) $(CFLAGS) -s recmail.c -o recmail
X
Xprocess.o:  process.c rparams.h defs.h params.h header.h
X	$(CC) $(CFLAGS) -c process.c
X
X
Xchecknews:  Makefile checknews.o process.o cpathinit.o
X	$(CC) $(LFLAGS) checknews.o process.o cpathinit.o -o checknews
X
Xcsendbatch: csendbatch.sh Makefile
X	sed -e "s%LIBDIR%$(LIBDIR)%g" \
X	 -e "s%UUXFLAGS%$(UUXFLAGS)%g" \
X	 -e "s%BATCHDIR%$(BATCHDIR)%g" csendbatch.sh > csendbatch
X
Xsendbatch: sendbatch.sh Makefile
X	sed -e "s%LIBDIR%$(LIBDIR)%g" \
X	 -e "s%UUXFLAGS%$(UUXFLAGS)%g" \
X	 -e "s%BATCHDIR%$(BATCHDIR)%g" sendbatch.sh > sendbatch
X
Xcunbatch: cunbatch.sh Makefile
X	sed -e "s%LIBDIR%$(LIBDIR)%g" \
X	 -e "s%BINDIR%$(BINDIR)%g" cunbatch.sh > cunbatch
X
Xrmgroup: rmgroup.sh Makefile
X	sed -e "s%LIBDIR%$(LIBDIR)%g" \
X	 -e "s%SPOOLDIR%$(SPOOLDIR)%g" rmgroup.sh > rmgroup
X
Xcheckgroups: checkgroups.sh Makefile
X	sed -e "s%LIBDIR%$(LIBDIR)%g" checkgroups.sh > checkgroups
X
Xsendnews.o: sendnews.c defs.h
X	$(CC) $(CFLAGS) -c sendnews.c
X
Xfullname.o: defs.h
X
Xexpire: Makefile $(EXPOBJS)
X	$(CC) $(LFLAGS) -o expire $(EXPOBJS) $(LIBS)
X
Xheader.o:  header.c header.h defs.h
X	$(CC) $(CFLAGS) -c header.c
X
Xexpire.o:  expire.c defs.h Makefile params.h ndir.h header.h
X	$(CC) $(CFLAGS) -c expire.c
X
Xdigest.o:  digest.c
X	$(CC) $(CFLAGS) -c digest.c
X
Xparams.h: defs.h header.h
X
X# Some silliness here to get pathinit for both readnews & inews
Xrpathinit.o:  pathinit.c rparams.h header.h params.h
X	$(CC) $(CFLAGS) $(HOMENAME) -DREAD -c pathinit.c
X	mv pathinit.o rpathinit.o
X
Xipathinit.o:  pathinit.c iparams.h header.h params.h
X	$(CC) $(CFLAGS) $(HOMENAME) -DINEW -c pathinit.c
X	mv pathinit.o ipathinit.o
X
Xcpathinit.o:  pathinit.c iparams.h header.h params.h
X	$(CC) $(CFLAGS) $(HOMENAME) -DCHKN -c pathinit.c
X	mv pathinit.o cpathinit.o
X
Xepathinit.o:  pathinit.c iparams.h header.h params.h
X	$(CC) $(CFLAGS) $(HOMENAME) -DEXP -c pathinit.c
X	mv pathinit.o epathinit.o
X
Xtags:	/tmp
X	ctags -w *.h *.c
X
X$(LIBDIR):
X	mkdir $(LIBDIR)
X	chmod 755 $(LIBDIR)
X	chown $(NEWSUSR) $(LIBDIR)
X	chgrp $(NEWSGRP) $(LIBDIR)
X
X$(BINDIR):
X	mkdir $(BINDIR)
X	chmod 755 $(BINDIR)
X	chown $(NEWSUSR) $(BINDIR)
X	chgrp $(NEWSGRP) $(BINDIR)
*-*-END-of-src/Makefile.v7-*-*
echo x - src/batch.c
sed 's/^X//' >src/batch.c <<'*-*-END-of-src/batch.c-*-*'
X/*
X * Batch: program to batch a list of news articles into an unbatch script.
X * Usage: /usr/lib/news/batch listfile [bytecount]
X *  where listfile is a file containing a list, one per line, of full
X *  path names of files containing articles, e.g. as produced by the F
X *  transmission option in the sys file.
X *  bytecount is the maximum number of bytes to output before exiting
X * Output is placed on standard output.
X *
X * Intended usage:
X *
X *	With the shellfile "sendbatch", with machine names as arguments:
X * 		e.g
X *		sendbatch rlgvax seismo
X *
X * This would be invoked every hour or two from crontab.
X *
X */
X
X#ifndef lint
Xstatic char	*SccsId = "@(#)batch.c	1.11	8/23/84";
X#endif !lint
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <errno.h>
X#include "defs.h"
X#ifdef lint
X#define LIBDIR "something"
X#endif lint
X
X#if defined(USG) || defined(BSD4_2) || defined(BSD4_1C)
X#include <fcntl.h>
X#endif
X
Xstruct stat sbuf;
X
Xextern int errno;
Xextern char *sys_errlist[];
X
Xmain(argc,argv)
Xchar **argv;
X{
X	register FILE *fd, *nfd;
X	register int c;
X	register long n;
X	register char *cp;
X	char *fdstatus;
X	long maxbytes, nbytes;
X	long atol();
X	char fname[512];
X	char workfile[512];
X	char *index(), *fgets();
X
X	if (argc < 2) {
X		fprintf(stderr, "Usage: batch listfile [bytecount]\n");
X		exit(1);
X	}
X
X	/*
X	 * Rename real file to a work name to avoid race conditions.
X	 * If workfile exsists skip the rename in order
X	 * to recover from a crash w/o losing anything.
X	 */
X	strcpy(workfile, argv[1]);
X	strcat(workfile, ".work");
X	if (access(workfile, 0) < 0) {
X		if (access(argv[1], 0) < 0 && errno == ENOENT)
X			exit(0);	/* no news */
X		if (rename(argv[1], workfile) < 0) {
X			logerr("rename(%s,%s) %s", argv[1], workfile,
X				sys_errlist[errno]);
X			exit(1);
X		}
X	}
X	fd = fopen(workfile, "r");
X	if (fd == NULL) {
X		logerr("fopen(%s,r) %s", workfile, sys_errlist[errno]);
X		exit(1);
X	}
X
X	if (argc > 2)
X		maxbytes = atol(argv[2]);
X	else
X		maxbytes = 100000000L; /* backwards compatible */
X	nbytes = 0;
X	while ((fdstatus = fgets(fname, sizeof fname, fd)) != NULL
X	    && nbytes < maxbytes) {
X		cp = index(fname, '\n');
X		if (cp)
X			*cp = '\0';
X		nfd = fopen(fname, "r");
X		if (nfd == NULL) {
X			perror(fname);
X			continue;
X		}
X		fstat(fileno(nfd), &sbuf);
X		printf("#! rnews %ld\n", sbuf.st_size);
X		n = 0;
X		while ((c = getc(nfd)) != EOF) {
X			putchar(c);
X			n++;
X		}
X		fclose(nfd);
X		nbytes += sbuf.st_size;
X		if (n != sbuf.st_size) { /* paranoia */
X			logerr("%s, expected %ld bytes, got %ld", fname,
X				n, sbuf.st_size);
X			/* breaking out of this early will end up resyncing
X			   the batch files (isn't serendipity wonderful?) */
X			break;
X		}
X	}
X	if (fdstatus != NULL) {		/* exceeded maxbytes */
X		char tmpfile[512];
X
X		umask(2);
X		strcpy(tmpfile, argv[1]);
X		strcat(tmpfile, ".tmp");
X	    	nfd = fopen(tmpfile, "w");
X		if (nfd == NULL) {
X			logerr("fopen(%s,w) %s", tmpfile, sys_errlist[errno]);
X			exit(1);
X		}
X		do {
X			fputs(fname, nfd);
X		} while (fgets(fname, sizeof fname, fd) != NULL);
X		fclose(nfd);
X		fclose(fd);
X		/* will pick it up next time thru */
X		if (rename(tmpfile, workfile) < 0) {
X			logerr("rename(%s,%s) %s", tmpfile, workfile,
X				sys_errlist[errno]);
X			exit(1);
X		}
X	}
X	else
X		unlink(workfile);
X	exit(0);
X}
X
X/*
X * Log the given message, with printf strings and parameters allowed,
X * on the log file, if it can be written.
X */
X/* VARARGS1 */
Xlogerr(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
Xchar *fmt;
X{
X	FILE *logfile;
X	char lfname[BUFLEN];		/* the log file */
X	char bfr[BUFLEN];
X	char *logtime, *ctime();
X	time_t t;
X
X	time(&t);
X	logtime = ctime(&t);
X	logtime[16] = 0;
X	logtime += 4;
X
X#ifdef IHCC
X	sprintf(lfname, "%s/%s/errlog", logdir(HOME), LIBDIR);
X#else
X	sprintf(lfname, "%s/errlog", LIBDIR);
X#endif
X
X	sprintf(bfr, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
X	fprintf(stderr, bfr);
X	if (access(lfname, 0) == 0 && (logfile = fopen(lfname, "a")) != NULL) {
X#if defined(USG) || defined(BSD4_2) || defined(BSD4_1C)
X		int flags;
X		flags = fcntl(fileno(logfile), F_GETFL, 0);
X		fcntl(fileno(logfile), F_SETFL, flags|O_APPEND);
X#else v7
X		lseek(fileno(logfile), 0L, 2);
X#endif v7
X		fprintf(logfile, "%s\batch\t%s\n", logtime, bfr);
X		fclose(logfile);
X	}
X}
X
X#if !defined(BSD4_2) && !defined(BSD4_1C)
Xrename(from, to)
Xregister char *from, *to;
X{
X	unlink(to);
X	if (link(from, to) < 0)
X		return -1;
X
X	unlink(from);
X	return 0;
X}
X#endif !BSD4_2 && !BSD4_1C
*-*-END-of-src/batch.c-*-*
echo x - src/berknews.c
sed 's/^X//' >src/berknews.c <<'*-*-END-of-src/berknews.c-*-*'
X/*
X * berknews - send news article via Berknet
X *
X * Synopsis:
X *	berknews [-o] [-n newsgroup] host_net_command machine remote_rnews
X */
X
Xstatic char *SccsId = "@(#)berknews.c	2.4	4/20/84";
X
X#include <stdio.h>
X#include <ctype.h>
X#ifndef USG
X#include <whoami.h>
Xstruct utsname {
X	char	Sysname[9];
X	char	nodename[33];
X	char	release[9];
X	char	version[9];
X};
X#else
X#include <sys/utsname.h>
X#endif
X
X
Xstruct network {
X	char *uucpname;
X	char *berkname;
X} berknet[] = {
X/*	UUCP Net Name	BerkNet Name
X	-------------	------------	*/
X	"ucbvax",	"CSVAX",
X	"populi",	"G",
X	"ucbarpa",	"ARPAVAX",
X	"ucbcfo-c",	"C",
X	"ucbopt",	"ESVAX",
X	"ucbcad",	"ucbcad",
X	"ucbcory",	"Cory",
X	"ucb",		"C70",
X	"ucbmathstat",	"MathStat",
X	"ucbonyx",	"Onyx",
X	"ucbkim",	"Kim",
X	"ucbcfo-a",	"A",
X	"ucbcfo-b",	"B",
X	"ucbcfo-d",	"D",
X	"ucbcfo-e",	"E",
X	"ucbcfo-f",	"F",
X	"ucbingvax",	"IngVAX",
X	"ucbingres",	"Ingres",
X	"ucbeecs40",	"EECS40",
X	"ucbvlsi",	"VLSI",
X	"ucbsrc",	"SRC",
X	"ucbimage",	"Image",
X	'\0',		'\0'
X};
X
Xchar *index();
Xchar buffer[BUFSIZ];
Xint linecount;
X
XFILE *popen();
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X	FILE *out;
X	char sender[BUFSIZ],newsgroup[100];
X	char *punct;
X	char sysn[20];
X	int sysnl;
X	struct utsname ubuf;
X
X	if (argc < 4) {
X		fprintf(stderr, "Too few arguments.\n");
X		exit(1);
X	}
X
X#ifdef debug
X	printf("%s - -m%s %s\n", argv[1], argv[2], argv[3]);
X	sprintf(buffer, "cat");
X#else
X	sprintf(buffer, "%s - -m%s %s", argv[1], argv[2], argv[3]);
X#endif
X	out = popen(buffer, "w");
X	uname(&ubuf);
X	strcpy(sysn, ubuf.nodename);
X	strcat(sysn, "!");
X	sysnl = strlen(sysn);
X
X	while (fgets(buffer, sizeof buffer, stdin)) {
X		if (fromline()) {
X			punct = index(buffer, '!');
X			if (punct == NULL)
X				printf("Bad from line: '%s'\n", buffer);
X			else {
X				*punct = ':';	/* berknet mail delimeter */
X				if (!strncmp("From: ", buffer, 6))
X					punct = &buffer[6];
X				else if (!strncmp("From ",buffer,5))
X					punct = &buffer[5];
X				else
X					punct = buffer;
X				fiddle(punct);
X			}
X		}
X		fputs(buffer, out);
X	}
X	pclose(out);
X	exit(0);
X}
X
Xfromline() {
X	if (!linecount && (!strncmp("From: ", buffer, 6) || !strncmp("From ", buffer, 5)))
X		return ++linecount;
X	return 0;
X}
X
X/*
X * make sure the host name is a correct berknet address, since the
X * internal names are not the berknet host names.
X */
Xfiddle(buf)
Xchar *buf;
X{
X	char uucpname[100];
X	register struct network *netptr;
X	char *rest;
X
X	strcpy(uucpname, buf);
X	rest = index(uucpname, ':');
X	*rest++ = 0;
X#ifdef debug
X	printf("uucpname = '%s', buf = '%s', rest = '%s'\n", uucpname, buf, rest);
X#endif
X	for (netptr = &berknet[0]; strcmp(netptr->uucpname, uucpname) && netptr->uucpname; netptr++)
X		;
X	if (netptr->uucpname)
X		sprintf(buf, "%s:%s", netptr->berkname, rest);
X	else
X		sprintf(buf, "UNKNOWN:%s", rest);
X}
X
X/*
X * Return the ptr in sp at which the character c appears;
X * NULL if not found
X */
X
Xchar *
Xindex(sp, c)
Xregister char *sp, c;
X{
X	do {
X		if (*sp == c)
X			return(sp);
X	} while (*sp++);
X	return(NULL);
X}
*-*-END-of-src/berknews.c-*-*
echo x - src/caesar.c
sed 's/^X//' >src/caesar.c <<'*-*-END-of-src/caesar.c-*-*'
X/*
X * program to to decrypt caesar(tm) cypher
X * (caesar is a trademark of the roman empire)
X *
X * to compile:
X *
X *	cc decrypt.c -lm -o decrypt.c
X *
X * usage:
X *
X *	decrypt [n] < file
X *
X * where n is an optional forced rotation.
X *
X * authors: Stan King, John Eldridge, based on algorithm suggested by
X *		Bob Morris
X * 29-Sep-82
X *
X */
X
X#ifndef lint
Xstatic char	*SccsId = "@(#)caesar.c	1.5	8/14/84";
X#endif !lint
X
X#include <stdio.h>
X#include <ctype.h>
X#include <math.h>
Xextern char *calloc();
X
Xmain( argc, argv )
Xint argc;
Xchar *argv[];
X{
X	/* letter frequencies (taken from some unix(tm) documentation) */
X	/* (unix is a trademark of Bell Laboratories) */
X	static double stdf[ 26 ] =
X	{
X		7.97, 1.35, 3.61, 4.78, 12.37, 2.01, 1.46, 4.49,
X		6.39, 0.04, 0.42, 3.81, 2.69, 5.92, 6.96, 2.91,
X		0.08, 6.63, 8.77, 9.68, 2.62, 0.81, 1.88, 0.23,
X		2.07, 0.06,
X	};
X	int obs[26];
X	int bufsize;
X	int c, i, try;
X	double dot, winnerdot;  /* .. */
X	int winner, forced = 0;
X	char *inbuf;
X
X	bufsize = 0;
X	if( argc > 1 )
X		sscanf( argv[1], "%d", &forced );
X	if( forced == 0 )
X		forced = -1000;
X
X	inbuf = calloc( BUFSIZ, 1 );
X
X	/* adjust frequency table to weight low probs REAL low */
X	for (i=0; i<26; i++)	{
X		stdf[i] = log(stdf[i]) + log(26.0/100.0);
X	}
X
X	/* Decode each line separately */
X	for (;;) {
X		for (i=0; i<=25; obs[i++]=0)
X			;
X
X		/* get a sample of the text */
X		for( i = 0; i < BUFSIZ; i++ ) {
X			if( (c = getchar()) == EOF ) {
X				exit(0);
X			}
X			inbuf[i] = c;
X			if (c == '\n') {
X				bufsize = i+1;
X				break;
X			}
X			if (islower(c))
X				obs[c-'a'] += 1;
X			else if (isupper(c))
X				obs[c-'A'] += 1;
X		}
X
X		/* now "dot" the freqs with the observed letter freqs
X		/*	and keep track of best fit */
X		winner = 0;
X		for (try = 0; try<26; try+=13) {
X			dot = 0;
X			for ( i=0; i<26; i++ ) {
X				dot += obs[i] * stdf[ (i+try) % 26 ];
X				}
X			/* initialize winning score */
X			if( try == 0 )
X				winnerdot = dot;
X			if( dot > winnerdot ) {
X				/* got a new winner! */
X				winner = try;
X				winnerdot = dot;
X			}
X		}
X
X		if (forced != -1000)
X			winner = forced;
X
X		/* print out sample buffer */
X		for( i = 0; i < bufsize; i++ )
X			putchar( rotate( inbuf[i], winner ) );
X	}
X }
X
X
Xstatic int
Xrotate( c, perm )
Xchar c;
Xint perm;
X{
X	if (isupper(c))	{
X		return 'A' + (c - 'A' + perm) % 26 ;
X	}
X	else if (islower(c)) {
X		return 'a' + (c-'a'+perm) % 26 ;
X	}
X	else return c;
X}
*-*-END-of-src/caesar.c-*-*
echo x - src/checknews.c
sed 's/^X//' >src/checknews.c <<'*-*-END-of-src/checknews.c-*-*'
X/*
X * checknews - news checking program
X */
X
X#ifndef lint
Xstatic char	*SccsId = "@(#)checknews.c	2.21	9/3/84";
X#endif !lint
X
Xchar *Progname = "checknews";		/* used by xerror */
X
X#include "params.h"
X
Xchar	bfr[LBUFLEN];			/* general-use scratch area	*/
Xchar	optbuf[BUFLEN];			/* NEWSOPTS buffer		*/
Xint	line = -1, y, e, n, q;
Xint	verbose;			/* For debugging.		*/
Xint	nflag;				/* for spec. newsgroup		*/
Xchar	narggrp[BUFLEN];		/* spec newsgroup		*/
XFILE	*rcfp,*actfp;
Xchar	newsrc[BUFLEN],*rcline[LINES],rcbuf[LBUFLEN],*argvrc[LINES];
Xstruct passwd *getpwuid();
Xchar	*malloc(),*getenv(), *index();
Xstruct hbuf header;
Xchar	coptbuf[BUFLEN],datebuf[BUFLEN];
Xint	mode = 1;
X#ifndef SHELL
Xchar	*SHELL;
X#endif
X
Xmain(argc, argv)
Xint argc;
Xregister char **argv;
X{
X	register char *ptr;	/* pointer to rest of buffer		*/
X	char *user, *home;
X	struct passwd *pw;
X	struct group *gp;
X	int sflag = 0, optflag = FALSE, space = FALSE;
X	int i;
X
X	y = 0;
X	n = 0;
X	e = 0;
X	q = 0;
X	nflag = 0;
X	pathinit();
X	if (--argc > 0) {
X		for (argv++; **argv; ++*argv) {
X			switch(**argv) {
X			case 'y':
X				y++;
X				break;
X			case 'q':
X				q++;
X				break;
X			case 'v':
X				verbose++;
X				break;
X			case 'n':
X				n++;
X				break;
X			case 'N':
X				nflag++;
X				strcpy(narggrp,argv[1]);
X				strcat(narggrp,",");
X				break;
X			case 'e':
X			case 'f':
X				e++;
X				break;
X			}
X		}
X	}
X	if (!n && !e && !y && !q)
X		y++;
X	if (nflag)
X		argv++;
X
X#ifndef V6
X	if ((user = getenv("USER")) == NULL)
X		user = getenv("LOGNAME");
X	if ((home = getenv("HOME")) == NULL)
X		home = getenv("LOGDIR");
X	if (user == NULL || home == NULL)
X		getuser();
X	else {
X		username = AllocCpy(user);
X		userhome = AllocCpy(home);
X	}
X	if (ptr = getenv("NEWSOPTS"))
X		strcpy(rcbuf, ptr);
X	else
X		*rcbuf = '\0';
X	if (*rcbuf) {
X		strcat(rcbuf, " \1");
X		ptr = rcbuf;
X		while (*++ptr)
X			if (isspace(*ptr))
X				*ptr = '\0';
X		for (ptr = rcbuf;; ptr++) {
X			if (!*ptr)
X				continue;
X			if (*ptr == '\1')
X				break;
X			if (++line > LINES)
X				xerror("Too many options.");
X			if ((rcline[line] = malloc(strlen(ptr) + 1)) == NULL)
X				xerror("Not enough memory.");
X			argvrc[line] = rcline[line];
X			strcpy(rcline[line], ptr);
X			while (*ptr)
X				ptr++;
X		}
X	}
X#else
X	getuser();
X#endif
X	ptr = getenv("NEWSRC");
X	if (ptr == NULL)
X		sprintf(newsrc, "%s/%s", userhome, NEWSRC);
X	else
X		strcpy(newsrc, ptr);
X	if ((rcfp = fopen(newsrc, "r")) != NULL) {
X		while (fgets(rcbuf, LBUFLEN, rcfp) != NULL) {
X			if (!(space = isspace(*rcbuf)))
X				optflag = FALSE;
X			if (!strncmp(rcbuf, "options ", 8))
X				optflag = TRUE;
X			if (optflag) {
X				strcat(rcbuf, "\1");
X				if (space)
X					ptr = rcbuf - 1;
X				else
X					ptr = &rcbuf[7];
X				while (*++ptr)
X					if (isspace(*ptr))
X						*ptr = '\0';
X				if (space)
X					ptr = rcbuf;
X				else
X					ptr = &rcbuf[8];
X				for (;; ptr++) {
X					if (!*ptr)
X						continue;
X					if (*ptr == '\1')
X						break;
X					if (++line > LINES)
X						xerror("Too many options.");
X					if ((rcline[line] = malloc(strlen(ptr) + 1)) == NULL)
X						xerror("Not enough memory.");
X					argvrc[line] = rcline[line];
X					strcpy(rcline[line], ptr);
X					while (*ptr)
X						ptr++;
X				}
X			}
X		}
X		fclose(rcfp);
X	}
X	header.nbuf[0] = 0;
X	if (line != -1) {
X#ifdef DEBUG
X		for (i = 0; i <= line; i++)
X			fprintf(stderr, "options:  %s\n", rcline[i]);
X#endif
X		process(line+2, argvrc);
X		do {
X#ifdef DEBUG
X			fprintf(stderr, "Freeing %d\n", line);
X#endif
X			free(rcline[line]);
X		} while (line--);
X	}
X
X	if (!*header.nbuf) {
X		strcpy(header.nbuf, DFLTSUB);
X		ngcat(header.nbuf);
X	}
X	strcat(header.nbuf, ADMSUB);
X	ngcat(header.nbuf);
X	if (*header.nbuf)
X		lcase(header.nbuf);
X	makehimask(header.nbuf, "junk");
X	makehimask(header.nbuf, "control");
X	makehimask(header.nbuf, "test");
X	if (access(newsrc, 0)) {
X		if (verbose > 1)
X			printf("No newsrc\n");
X		yep(argv);
X	}
X	if ((rcfp = fopen(newsrc, "r")) == NULL)
X		xerror("Cannot open .newsrc file");
X	while (fgets(rcbuf, LBUFLEN, rcfp) != NULL) {
X		if (!nstrip(rcbuf))
X			xerror(".newsrc line too long");
X		if (++line >= LINES)
X			xerror("Too many .newsrc lines");
X		if ((rcline[line] = malloc(strlen(rcbuf)+1)) == NULL)
X			xerror("Not enough memory");
X		strcpy(rcline[line], rcbuf);
X	}
X	if ((actfp = fopen(ACTIVE, "r")) == NULL)
X		xerror("Cannot open active newsgroups file");
X
X#ifdef DEBUG
X	fprintf(stderr, "header.nbuf = %s\n", header.nbuf);
X#endif
X	nchk(argv);
X	exit(0);
X}
X
Xnchk(argv)
Xchar **argv;
X{
X	register int i;
X	register char *ptr;
X	long l;
X	long narts;
X	char saveptr;
X	char aline[100];
X
X#ifdef DEBUG
X	fprintf(stderr, "nchk()\n");
X#endif
X	while (fgets(aline, sizeof aline, actfp) != NULL) {
X		sscanf(aline, "%s %ld", bfr, &narts);
X#ifdef DEBUG
X		fprintf(stderr, "bfr = '%s'\n", bfr);
X#endif
X		ngcat(bfr);
X		if (nflag && !ngmatch(bfr,narggrp))
X			continue;
X		else if (!ngmatch(bfr, header.nbuf))
X			continue;
X		ngdel(bfr);
X		i = findrcline(bfr);
X		if (i < 0) {
X			if (verbose>1)
X				printf("No newsrc line for newsgroup %s\n", bfr);
X			strcpy(rcbuf, " 0");
X		} else
X			strcpy(rcbuf, rcline[i]);
X		ptr = rcbuf;
X
X		if (index(rcbuf, '!') != NULL)
X			continue;
X		if (index(rcbuf, ',') != NULL) {
X			if (verbose > 1)
X				printf("Comma in %s newsrc line\n", bfr);
X			yep(argv);
X		}
X		while (*ptr)
X			ptr++;
X		while (!isdigit(*--ptr) && ptr >= rcbuf)
X			;
X		if (ptr < rcbuf) {
X			if (verbose > 1)
X				printf("Ran off beginning of %s newsrc line.\n", bfr);
X			yep(argv);
X		}
X		while (isdigit(*--ptr))
X			;
X		sscanf(++ptr, "%ld", &l);
X		if (narts > l) {
X			if (verbose) {
X				printf("News: %s ...\n", bfr);
X				if (verbose < 2)
X					y = 0;
X			}
X			yep(argv);
X		}
Xcontin:;
X	}
X	if (n)
X		printf("No news is good news.\n");
X}
X
Xyep(argv)
Xchar **argv;
X{
X	if (y) {
X		if (verbose)
X			printf("There is probably news");
X		else
X			printf("There is news");
X		if (nflag) {
X			narggrp[strlen(narggrp)-1] = '.';
X			printf(" in %s\n",narggrp);
X		}
X		else
X			printf(".\n");
X	}
X	if (e) {
X#ifdef V6
X		execv("/usr/bin/readnews", argv);
X#else
X		execvp("readnews", argv);
X#endif
X		perror("Cannot exec readnews.");
X	}
X	if (q)
X		exit(1);
X	else
X		exit(0);
X}
X
Xxerror(message, arg1, arg2)
Xchar *message;
Xint arg1, arg2;
X{
X	char buffer[128];
X
X	sprintf(buffer, message, arg1, arg2);
X	fprintf(stderr, "checknews: %s.\n", buffer);
X	exit(1);
X}
X
X/*
X * Append NGDELIM to string.
X */
Xngcat(s)
Xregister char *s;
X{
X	if (*s) {
X		while (*s++);
X		s -= 2;
X		if (*s++ == NGDELIM)
X			return;
X	}
X	*s++ = NGDELIM;
X	*s = '\0';
X}
X
X/*
X * News group matching.
X *
X * nglist is a list of newsgroups.
X * sublist is a list of subscriptions.
X * sublist may have "meta newsgroups" in it.
X * All fields are NGDELIM separated,
X * and there is an NGDELIM at the end of each argument.
X *
X * Currently implemented glitches:
X * sublist uses 'all' like shell uses '*', and '.' like shell '/'.
X * If subscription X matches Y, it also matches Y.anything.
X */
Xngmatch(nglist, sublist)
Xregister char *nglist, *sublist;
X{
X	register char *n, *s;
X	register int rc;
X
X	rc = FALSE;
X	for (n = nglist; *n != '\0' && rc == FALSE;) {
X		for (s = sublist; *s != '\0';) {
X			if (*s != NEGCHAR)
X				rc |= ptrncmp(s, n);
X			else
X				rc &= ~ptrncmp(s+1, n);
X			while (*s++ != NGDELIM);
X		}
X		while (*n++ != NGDELIM);
X	}
X	return(rc);
X}
X
X/*
X * Compare two newsgroups for equality.
X * The first one may be a "meta" newsgroup.
X */
Xptrncmp(ng1, ng2)
Xregister char *ng1, *ng2;
X{
X	while (*ng1 != NGDELIM) {
X		if (ng1[0]=='a' && ng1[1]=='l' && ng1[2]=='l') {
X			ng1 += 3;
X			while (*ng2 != NGDELIM && *ng2 != '.')
X				if (ptrncmp(ng1, ng2++))
X					return(TRUE);
X			return (ptrncmp(ng1, ng2));
X		} else if (*ng1++ != *ng2++)
X			return(FALSE);
X	}
X	return (*ng2 == '.' || *ng2 == NGDELIM);
X}
X
X/*
X * Get user name and home directory.
X */
Xgetuser()
X{
X	static int flag = TRUE;
X	register struct passwd *p;
X
X	if (flag) {
X		if ((p = getpwuid(getuid())) == NULL)
X			xerror("Cannot get user's name");
X		if (username[0] == 0)
X			strcpy(username, p->pw_name);
X		strcpy(userhome, p->pw_dir);
X		flag = FALSE;
X	}
X}
X
X/*
X * Strip trailing newlines, blanks, and tabs from 's'.
X * Return TRUE if newline was found, else FALSE.
X */
Xnstrip(s)
Xregister char *s;
X{
X	register char *p;
X	register int rc;
X
X	rc = FALSE;
X	p = s;
X	while (*p)
X		if (*p++ == '\n')
X			rc = TRUE;
X	while (--p >= s && (*p == '\n' || *p == ' ' || *p == '\t'));
X	*++p = '\0';
X	return(rc);
X}
X
X/*
X * Delete trailing NGDELIM.
X */
Xngdel(s)
Xregister char *s;
X{
X	if (*s++) {
X		while (*s++);
X		s -= 2;
X		if (*s == NGDELIM)
X			*s = '\0';
X	}
X}
X
Xlcase(s)
Xregister char *s;
X{
X	register char *ptr;
X
X	for (ptr = s; *ptr; ptr++)
X		if (isupper(*ptr))
X			*ptr = tolower(*ptr);
X}
X
X/*
X * finds the line in your .newsrc file (actually the in-core "rcline"
X * copy of it) and returns the index into the array where it was found.
X * -1 means it didn't find it.
X *
X * We play clever games here to make this faster.  It's inherently
X * quadratic - we spend lots of CPU time here because we search through
X * the whole .newsrc for each line.  The "prev" variable remembers where
X * the last match was found; we start the search there and loop around
X * to the beginning, in the hopes that the calls will be roughly in order.
X */
Xint
Xfindrcline(name)
Xchar *name;
X{
X	register char *p, *ptr;
X	register int cur;
X	register int i;
X	register int top;
X	static int prev = 0;
X
X	top = line; i = prev;
Xloop:
X	for (; i <= top; i++) {
X		for (p = name, ptr = rcline[i]; (cur = *p++); ) {
X			if (cur != *ptr++)
X				goto contin2;
X		}
X		if (*ptr != ':' && *ptr != '!')
X			continue;
X		prev = i;
X		return i;
Xcontin2:
X		;
X	}
X	if (i > line && line > prev-1) {
X		i = 0;
X		top = prev-1;
X		goto loop;
X	}
X	return -1;
X}
X
X/*
X * Forbid newsgroup ng, unless he asked for it in nbuf.
X */
Xmakehimask(nbuf, ng)
Xchar *nbuf, *ng;
X{
X	if (!findex(nbuf, ng)) {
X		ngcat(nbuf);
X		strcat(nbuf, "!");
X		strcat(nbuf, ng);
X		ngcat(nbuf);
X	}
X}
X
X/*
X * Return true if the string searchfor is in string, but not if preceeded by !.
X */
Xfindex(string, searchfor)
Xchar *string, *searchfor;
X{
X	register char first;
X	register char *p;
X
X	first = *searchfor;
X	for (p=index(string, first); p; p = index(p+1, first)) {
X		if (p>string && p[-1] != '!' && strncmp(p, searchfor, strlen(searchfor)) == 0)
X			return TRUE;
X	}
X	return FALSE;
X}
X
Xxxit(i)
X{
X	exit(i);
X}
*-*-END-of-src/checknews.c-*-*
echo x - src/control.c
sed 's/^X//' >src/control.c <<'*-*-END-of-src/control.c-*-*'
X/*
X * Control message handling code.  Deal with messages which are to be
X * acted on by netnews itself rather than by people.
X *
X * See defs.h "news_version" for the real version of netnews.
X */
X
X#ifndef lint
Xstatic char	*SccsId = "@(#)control.c	2.29	9/3/84";
X#endif !lint
X
X#include "iparams.h"
X
X#define eq(msg) (strcmp(msg, cargv[0]) == 0)
X
Xint cargc;
Xchar **cargv;
X
XFILE *hfopen();
XFILE *popen(), *mhopen(), *mailhdr();
X
Xchar *senderof();
X
Xcontrol(h)
Xstruct hbuf *h;
X{
X	register char *ctlmsgtext;
X
X	if (strncmp(h->title, "cmsg ", 5) == 0)
X		strcpy(h->title, h->title+5);
X
X	if (*h->ctlmsg)
X		ctlmsgtext = h->ctlmsg;
X	else
X		ctlmsgtext = h->title;
X	log("Ctl Msg %s from %s: %s", h->nbuf, h->path, ctlmsgtext);
X	/*
X	 * Control messages have the standard format
X	 *	command [args]
X	 * much like shell commands.  Each site has the option
X	 * of customizing this code to deal with control messages
X	 * as they see fit, but we would like to buy back the
X	 * code, ifdeffed or otherwise parameterized, to simplify
X	 * the maintenence issues.
X	 */
X	argparse(ctlmsgtext);
X
X	if (eq("cancel"))
X		c_cancel(cargc, cargv);
X	else if (eq("newgroup"))
X		c_newgroup(cargc, cargv);
X	else if (eq("ihave"))
X		c_ihave(cargc, cargv);
X	else if (eq("sendme"))
X		c_sendme(cargc, cargv);
X	else if (eq("sendbad"))
X		c_sendme(cargc, cargv);
X	else if (eq("rmgroup"))
X		c_rmgroup(cargc, cargv);
X	else if (eq("sendsys"))
X		c_sendsys(cargc, cargv);
X	else if (eq("senduuname"))
X		c_senduuname(cargc, cargv);
X	else if (eq("version"))
X		c_version(cargc, cargv);
X	else if (eq("checkgroups"))
X		c_checkgroups(cargc, cargv);
X	else if (eq("delsub"))
X		c_unimp(cargc, cargv);
X	else
X		c_unknown(h, ctlmsgtext);
X}
X
X/*
X * Parse the string str into separate words in cargc and cargv
X * as per the usual UNIX convention.  Nothing fancy here, just
X * blanks and tabs separating words.
X */
Xargparse(str)
Xchar *str;
X{
X	static char *cavpbuf[20];
X	static char cavbuf[256];
X	char *nextfree = cavbuf;
X
X	if (str == '\0')
X		xerror("Control message %s has no title", header.ident);
X	cargc = 0;
X	cargv = cavpbuf;
X	cargv[0] = cavbuf;
X
X	while (*str) {
X		if (*str <= ' ') {
X			*nextfree++ = 0;
X			cargc++;
X			cargv[cargc] = nextfree;
X			/* skip over white space */
X			while (*str != '\0' && *str <= ' ')
X				str++;
X			if (*str == '\0')	/* line ends in white space */
X				return;
X		} else
X			*nextfree++ = *str++;
X	}
X}
X
X/*
X * ihave <artid> <remotesys>
X * The other system is telling you it has article <artid>, in case
X * you decide you want it to transmit it to you.
X */
Xc_ihave(argc, argv)
Xchar **argv;
X{
X	char tl[256], ng[256];
X	struct hbuf htmp;
X
X	if (argc < 2)
X		xerror("ihave: Not enough arguments.");
X	/*
X	 * Check that we haven't already seen it (history)
X	 * and then send back a "sendme" message if we subscribe.
X	 */
X	strncpy(htmp.ident, argv[1], BUFLEN);
X	htmp.oident[0] = '\0';
X	if (history(&htmp) == 0) {
X		/* Should probably check SUBFILE here. */
X		sprintf(tl, "sendme %s %s", argv[1], FULLSYSNAME);
X		sprintf(ng, "to.%s.ctl", argv[2]);
X		xmitmsg(argv[2], tl, ng);
X	}
X}
X
X/*
X * sendme <artid> ... <remotesys>
X * The other system wants me to send him article <artid>.
X */
Xc_sendme(argc, argv)
Xchar **argv;
X{
X	struct srec srec;
X	int i;
X	FILE *fp;
X	struct hbuf h;
X
X	if (argc < 2)
X		xerror("sendme: Not enough arguments.");
X	/* Don't ask for it from myself */
X	if (strncmp(FULLSYSNAME, argv[argc], SNLN) == 0)
X		return;
X	/* Find the sys record */
X	s_openr();
X	while (s_read(&srec)) {
X		if (strncmp(srec.s_name, argv[argc], SNLN))
X			continue;
X		/* It's the right one.  Send them. */
X		for (i=1; i<argc; i++) {
X			fp = hfopen(argv[i]);
X			if (hread(&h, fp, TRUE) == NULL)
X				xerror("Article %s is garbled.", argv[i]);
X			fseek(fp, 0L, 0);
X			if (strcmp(argv[0], "sendme") == 0) {
X				/* check that other sys subscribes. */
X				if (!ngmatch(h.nbuf, srec.s_nbuf) ||
X					!(h.distribution[0] == '\0' ||
X					ngmatch(h.distribution, srec.s_nbuf)))
X					continue;
X			}
X			transmit(&srec, fp, 0);
X			/* transmit does fclose(fp) */
X		}
X		return;
X	}
X	xerror("Cannot find system %s to send article %s to.", argv[argc],
X		argv[1]);
X}
X
X/*
X * newgroup <groupname>
X * A new newsgroup has been created.
X * The body of the article, if present, is a description of the
X * purpose of the newsgroup.
X *
X */
Xc_newgroup(argc, argv)
Xchar **argv;
X{
X	FILE *fd;
X
X	if (argc < 1)
X		xerror("newgroup: Not enough arguments.");
X	if (validng(argv[1]))
X		return;
X
X	strcpy(bfr, dirname(argv[1]));
X	mknewsg(bfr, argv[1]);
X
X#ifdef NOTIFY
X	/*
X	 * Sample code to notify the contact person.
X	 * Probably should dig up the text of the article
X	 * and enclose that, too.  It can be found in the
X	 * file ARTICLE.  Also, there needs to be
X	 * an automatic provision to help you add the newsgroup.
X	 *
X	 */
X	fd = mailhdr((struct hbuf *)NULL, "creation of new newsgroup");
X	if (fd != NULL) {
X		fprintf(fd, "\nA new newsgroup called '%s' has been created by %s.\n\n",
X			argv[1], header.path);
X		mclose(fd);
X	}
X#endif
X}
X
X/*
X * rmgroup <groupname>
X * An old newsgroup is being cancelled on a network wide basis.
X */
Xc_rmgroup(argc, argv)
Xchar **argv;
X{
X	FILE *fd;
X	char *groupname;
X	char groupdir[128];
X#ifndef MANUALLY
X	int rc;
X#endif MANUALLY
X
X	if (argc < 1)
X		xerror("rmgroup: Not enough arguments.");
X	groupname = argv[1];
X	verifyname(groupname);
X	if (groupname[0] == '.' || groupname[0] <= ' ')
X		xerror("Illegal group name in rmgroup");
X
X	strcpy(groupdir, dirname(groupname));
X	if (access(groupdir, 0)) {
X		/*
X		 * If the group already is gone, it's a nonfatal error - we
X		 * want to propagate the message anyway, since what probably
X		 * happened is somebody locally already removed it.
X		 */
X		log("Cannot remove newsgroup '%s'", groupname);
X		return;
X	}
X#ifdef NOTIFY
X	fd = mailhdr((struct hbuf *)NULL, "rmgroup control message");
X	if (fd != NULL) {
X# ifndef MANUALLY
X		fprintf(fd, "\nA newsgroup called '%s' has been removed by %s.\n\n",
X			argv[1], header.path);
X#  ifdef USG
X		fprintf(fd, "You may need to remove the directory %s by hand\n",
X			dirname(argv[1]));
X#  endif
X# else
X		fprintf(fd, "\n%s has requested that newsgroup %s be removed.\n",
X			header.path, argv[1]);
X		fprintf(fd, "You should remove it by hand\n");
X# endif
X		mclose(fd);
X	}
X#endif
X
X#ifndef MANUALLY
X	/* We let the shell do all the work.  See the rmgrp shell script. */
X	setuid(geteuid());	/* otherwise it won't rmdir the dir */
X	sprintf(bfr, "exec %s/rmgroup %s", LIB, groupname);
X	rc = system(bfr);
X	log("system(%s) status %d", bfr, rc);
X#endif
X}
X
X/*
X * cancel <artid>
X * Cancel the named article
X */
Xc_cancel(argc, argv)
Xchar **argv;
X{
X	char *line, *p, *q, *r, *poster;
X	char *findhist();
X	register FILE *fp;
X	char whatsisname[150];
X	char msgng[64];
X	time_t t;
X	int su = 0;
X
X	if (argc < 1)
X		xerror("cancel: Not enough arguments.");
X	strcpy(whatsisname, senderof(&header));
X	strcpy(msgng, header.nbuf);
X	line = findhist(argv[1]);
X	if (line == NULL) {
X		log("Can't cancel %s:  non-existent", argv[1]);
X		(void) time(&t);
X		sprintf(bfr,"%s\t%.12s\tcancelled", argv[1], &ctime(&t)[4]);
X		savehist(bfr);
X		return;
X	}
X
X	q = index(line, '\t');
X	p = index(q+1, '\t');
X	p++;
X	if (strcmp(p, "cancelled") == 0) {
X		*q = '\0';
X		log("Already Cancelled %s", line);
X		return;
X	} else
X		log("Cancelling %s", line);
X	while (*p) {
X		q = index(p, ' ');
X		if (q)
X			*q = '\0';
X		strcpy(filename, dirname(p));
X		fp = xfopen(filename, "r");
X		if (hread(&header, fp, TRUE) == NULL)
X			xerror("Article is garbled.");
X		fclose(fp);
X		if((uid==ROOTID||uid==0) && strncmp(msgng,"to.",3) == 0)
X			su = 1;
X		poster = senderof(&header);
X		/* only compare up to '.' or ' ' */
X		r = index(poster,'.');
X		if (r == NULL)
X			r = index(poster,' ');
X		if (r != NULL)
X			*r = '\0';
X		if (!su && strncmp(whatsisname, poster,strlen(poster))) {
X			xerror("Not contributor: posted by %s, and you are %s", poster, whatsisname);
X		}
X
X		cancel();
X		p = q+1;
X	}
X}
X
X/*
X * sendsys	(no arguments)
X *
X * Mail the sys file to the person submitting the article.
X * POLICY: the contents of your sys file are public information
X * and as such, you should not change this code.  You may feel
X * free to arrange for it to manually notify you, in the event
X * that you want to do something to clean it up before it goes out.
X * Secret sites on the net are expressly frowned on.
X *
X * The purpose of this command is for making a network map.  The
X * details of your link and which newsgroups are forwarded are not
X * important, in case you want to sanitize them.  Since the definition
X * of USENET is those sites getting net.general, you can disable this
X * on sites not getting net articles, but if you take out the list of
X * forwarded newsgroups, and you have sites that only get local newsgroups,
X * you should make this clear, or remove those sites from what you send out.
X */
Xc_sendsys(argc, argv)
Xchar **argv;
X{
X	register FILE *f, *u;
X	int c;
X
X#ifdef lint
X	argc += **argv;
X#endif lint
X
X#ifdef NOTIFY
X	f = mailhdr((struct hbuf *)NULL, "sendsys control message");
X	if (f != NULL) {
X		fprintf(f, "\n%s requested your sys file.\n", header.path);
X		fprintf(f, "It has been sent.\n");
X		mclose(f);
X	}
X#endif
X	f = mailhdr(&header, "Subject: response to your sendsys request\n\n");
X	u = fopen(SUBFILE, "r");
X	if (f != NULL && u != NULL) {
X		while ((c=getc(u)) != EOF)
X			putc(c, f);
X		fclose(u);
X		mclose(f);
X	}
X}
X
X/*
X * senduuname	(no arguments)
X *
X * Run the "uuname" command and send it back to the person who submitted
X * the article.  The purpose of this control message is for attempting to
X * make a uucp net map.
X *
X * POLICY: If you view this information as not public (because you have
X * a connection you consider secret, or know a site that considers itself
X * secret) you can feel free to change this code in whatever way is
X * appropriate, so long as it sends some response back to the sender.  If
X * you don't run uucp, this code does not make sense, and so an error
X * message (or garbage, such as "research") will be mailed back.
X *
X * If you wish to add or remove sites from the output of uuname, you
X * may wish to use the euuname.sh shell script here.
X */
Xc_senduuname(argc, argv)
Xchar **argv;
X{
X	char buf[256];
X	FILE *fd, *u;
X	int c;
X
X#ifdef lint
X	argc += **argv;
X#endif lint
X
X#ifdef NOTIFY
X	fd = mailhdr((struct hbuf *)NULL, "uuname control message");
X	fprintf(fd, "\n%s requested your uuname output\n", header.path);
X	mclose(fd);
X#endif
X	fd = mailhdr(&header, "response to your senduuname request");
X#ifdef UUPROG
X	if (UUPROG[0] == '/')
X		strcpy(buf, UUPROG);
X	else
X		sprintf(buf, "%s/%s", LIB, UUPROG);
X#else
X	strcpy(buf, "uuname");
X#endif
X	u = popen(buf, "r");
X	if (fd != NULL && u != NULL) {
X		while ((c=getc(u)) != EOF)
X			putc(c, fd);
X		pclose(u);
X		mclose(fd);
X	}
X}
X
X/*
X * Send the version number to the right person.
X */
Xc_version(argc, argv)
Xchar **argv;
X{
X	register FILE *f;
X
X#ifdef lint
X	argc += **argv;
X#endif lint
X
X	f = mailhdr(&header, "Our news version");
X	if (f == NULL)
X		xerror("Cannot send back error message");
X	fprintf(f, "\nCurrently running news version %s.\n\n", news_version);
X	fprintf(f, "The header of your message follows:\n");
X	hwrite(&header, f);
X	mclose(f);
X}
X
X/*
X * Check the active file for old or missing newsgroups
X * Body of article is list of valid groups
X */
Xc_checkgroups(argc, argv)
Xchar **argv;
X{
X	int rc;
X
X#ifdef lint
X	argc += **argv;
X#endif lint
X
X	setuid(geteuid());
X	sprintf(bfr, "sed '1,/^$/d' %s | %s/checkgroups %s",
X		ARTICLE, LIB, (TELLME && *TELLME) ? TELLME : NEWSUSR);
X	rc = system(bfr);
X	log("system(%s) status %d", bfr, rc);
X}
X
X/*
X * An unknown control message has been received.
X */
Xc_unknown(h, ctlmsgtext)
Xstruct hbuf *h;
Xchar *ctlmsgtext;
X{
X	register FILE *f;
X
X	log("UNKNOWN Ctl Msg %s from %s", ctlmsgtext, h->path);
X	f = mailhdr(h, "Unrecognized Control Message");
X	if (f == NULL)
X		xerror("Cannot send back error message");
X	fprintf(f, "Currently running news B version %s.\n\n", news_version);
X	fprintf(f, "The header of the message follows:\n");
X	hwrite(h, f);
X	mclose(f);
X}
X
Xc_unimp(argc, argv)
Xchar **argv;
X{
X	register FILE *f;
X
X#ifdef lint
X	argc += **argv;
X#endif lint
X
X	f = mailhdr(&header, "Unimplemented Control Message");
X	if (f == NULL)
X		xerror("Cannot send back error message");
X	fprintf(f, "Currently running news B version %s.\n\n", news_version);
X	fprintf(f, "The header of the message follows:\n");
X	hwrite(&header, f);
X	mclose(f);
X}
X
Xxmitmsg(tosys, title, ng)
Xchar *tosys, *title, *ng;
X{
X	struct hbuf h;
X	struct srec srec;
X	FILE *tfp;
X	char *fname;
X
X	/* Make an article called ARTICLE */
X	sprintf(h.from, "%s@%s%s", "usenet", FULLSYSNAME, MYDOMAIN);
X	strcpy(h.path, NEWSUSR);
X	strcpy(h.nbuf, ng);
X	strcpy(h.title, title);
X	strcpy(h.ctlmsg, title);
X	strcpy(h.subdate, "");
X	strcpy(h.recdate, "");
X	strcpy(h.expdate, "");
X	getident(&h);
X	dates(&h);
X	tfp = xfopen(fname = mktemp("/tmp/xmsgXXXXXX"), "w");
X	hwrite(&h, tfp);
X	fclose(tfp);
X
X	/* Find the sys record */
X	s_openr();
X	while (s_read(&srec)) {
X		if (strncmp(srec.s_name, tosys, SNLN))
X			continue;
X		tfp = xfopen(fname, "r");
X		transmit(&srec, tfp, 0);
X		unlink(fname);
X		return;
X	}
X	log("Can't find sys record for %s", tosys);
X	xerror("Cannot find sys record");
X}
X
X/*
X * This is a modified version of popen, made more secure.  Rather than
X * forking off a shell, you get a bare process.  You must have exactly
X * one argument, and the command must be mail.
X */
X#include <stdio.h>
X#include <signal.h>
X#define	RDR	0
X#define	WTR	1
Xstatic	int	mopen_pid[20];
Xchar *replyname();
X
XFILE *
Xmhopen(hptr)
Xstruct hbuf *hptr;
X{
X	int p[2];
X	register myside, hisside, pid;
X	char *sendto = NULL;
X
X	if (hptr)
X		sendto = replyname(hptr);
X	else {
X#ifdef NOTIFY
X		if (TELLME && *TELLME)
X			sendto = TELLME;
X#endif NOTIFY
X		if (sendto == NULL)
X			return NULL;
X	}
X	verifyname(sendto);
X	if(pipe(p) < 0)
X		return NULL;
X	myside = p[WTR];
X	hisside = p[RDR];
X	if((pid = fork()) == 0) {
X		/* myside and hisside reverse roles in child */
X		close(myside);
X		close(0);
X		dup(hisside);
X		close(hisside);
X		execl("/bin/mail", "mail", sendto, (char *)NULL);
X		execl("/usr/bin/mail", "mail", sendto, (char *)NULL);
X		execl("/usr/ucb/mail", "mail", sendto, (char *)NULL);
X		_exit(1);
X	}
X	if(pid == -1)
X		return NULL;
X	mopen_pid[myside] = pid;
X	close(hisside);
X	return(fdopen(myside, "w"));
X}
X
Xmclose(ptr)
XFILE *ptr;
X{
X	register f, r, (*hstat)(), (*istat)(), (*qstat)();
X	int status;
X
X	f = fileno(ptr);
X	fclose(ptr);
X	istat = signal(SIGINT, SIG_IGN);
X	qstat = signal(SIGQUIT, SIG_IGN);
X	hstat = signal(SIGHUP, SIG_IGN);
X	while((r = wait(&status)) != mopen_pid[f] && r != -1)
X		;
X	if(r == -1)
X		status = -1;
X	signal(SIGINT, istat);
X	signal(SIGQUIT, qstat);
X	signal(SIGHUP, hstat);
X	return(status);
X}
X
X/*
X * mhopen a pipe to mail, write out a std header, and return the file ptr.
X *
X * We don't include a From: field because this is probably uucp, i.e.
X * explicitly routed.  Leave it up to the recipient's mailer.
X * Always include the To: field because if we ge back failed mail, we
X * might be able to deliver it by hand if we know to wom it was addressed.
X * By convention, hptr==NULL means to send the message to the local contact person.
X */
XFILE *
Xmailhdr(hptr, subject)
Xstruct hbuf *hptr;
Xchar  *subject;
X{
X	FILE *fp;
X	time_t now;
X	char *to = "nobody";
X
X	if (hptr)
X		to = replyname(hptr);
X#ifdef NOTIFY
X	if (TELLME && *TELLME)
X		to = TELLME;
X#endif NOTIFY
X	if ((fp = mhopen(hptr)) != NULL) {
X		time(&now);
X		fprintf(fp, "Date: %s\n", arpadate(&now));
X		fprintf(fp, "To: %s\n", to);
X		fprintf(fp, "Subject: %s\n", subject);
X		fprintf(fp, "Responding-System: %s%s\n", FULLSYSNAME, MYDOMAIN);
X	}
X	return fp;
X}
X
X/*
X * verify that the name mail is being sent to does not contain any
X * nasty hooks to invoke funny functions from the shell or the like.
X */
Xverifyname(sendto)
Xchar *sendto;
X{
X	/* Be sure we DO allow alphabetics, !, :, ., -, @. *. */
X	char *nasty = "\"'\\`^|;& <>/~";
X	register char *p;
X
X	if (sendto[0] <= ' ') {
X		log("nasty mail name %s from %s", sendto, header.path);
X		xxit(1);
X	}
X	for (p=sendto; *p; p++) {
X		if (*p == ' ') {
X			*p = 0;
X			break;
X		}
X	}
X	while (*nasty) {
X		if (index(sendto, *nasty++))
X			xerror("nasty mail name %s from %s", sendto, header.path);
X	}
X	for (nasty = sendto; (nasty = index(nasty, '.')) != NULL; ) {
X		if (*++nasty == '.')	/* check for .. */
X			xerror("nasty mail name %s from %s", sendto, header.path);
X	}
X}
X
X/*
X * Checks to make sure the control message is OK to post.
X */
Xctlcheck()
X{
X	char msg[150];
X	char *p;
X
X	if (!is_ctl)
X		return;
X
X	if (header.ctlmsg[0])
X		strcpy(msg, header.ctlmsg);
X	else
X		strcpy(msg, header.title);
X
X	p = index(msg, ' ');
X	if (p)
X		*p = 0;
X
X	if (strcmp(msg, "ihave") == 0) {
X	} else if (strcmp(msg, "sendme") == 0) {
X		return;	/* no restrictions */
X	} else if (strcmp(msg, "newgroup") == 0) {
X		suser();
X	} else if (strcmp(msg, "rmgroup") == 0) {
X		suser();
X		checkpass("mTnyckAVEMXWk");
X	} else if (strcmp(msg, "sendsys") == 0) {
X		suser();
X	} else if (strcmp(msg, "senduuname") == 0) {
X		suser();
X	} else if (strcmp(msg, "checkgroups") == 0) {
X		suser();
X	} else if (strcmp(msg, "version") == 0) {
X		return;	/* no restrictions */
X	} else if (strcmp(msg, "cancel") == 0) {
X		return;	/* no restrictions at this level */
X	} else if (strcmp(msg, "delsub") == 0) {
X		if (!prefix(header.nbuf, "to.")) {
X			printf("Must be in a 'to.system' newsgroup.");
X			xxit(0);
X		}
X		return;
X	} else {
X		printf("Unrecognized control message - %s\n", msg);
X		xxit(0);
X	}
X}
X
X/* Make sure this guy is special. */
Xsuser()
X{
X	if (uid == 0)
X		return;
X	if (uid == ROOTID)
X		return;
X	/*
X	 * We assume that since our real uid is the same as NEWSUSR
X	 * (the euid) we were run by rootid and it did a setuid.
X	 * Too bad we can't set just the effective uid like suid does.
X	 */
X	if (uid == geteuid())
X		return;
X#ifdef IHCC
X	printf("Please use the command:\n\ttoolnews providers\n");
X	printf("then call one of the news people.\n");
X#else
X	printf("Get your local netnews contact to do it for you.\n");
X#endif
X	xxit(0);
X}
X
X/*
X * Demand a password from the user.
X */
Xcheckpass(encpw)
Xchar *encpw;
X{
X	char *crypt(), *getpass();
X
X	if (strcmp(encpw, crypt(getpass("Password:"), "mT"))) {
X		printf("Sorry\n");
X		xxit(0);
X	}
X}
*-*-END-of-src/control.c-*-*
exit