home *** CD-ROM | disk | FTP | other *** search
- Date: Wed, 30 Jan 85 16:20:06 est
- From: allegra!gatech!spaf
- Subject: xfernews software
- Newsgroups: mod.sources
-
- The following software package is the "xfernews" suite for handling
- batched transmission of news articles directly from the source directories.
- These programs were written by Kenneth Almquist and have been used
- by many sites around the net with much success for quite a while.
-
- Everything should be documented as to what you need to do to install
- these programs. I will note that there is rumor that these may be
- included as part of the standard 2.10.3 news release, so you may
- want to wait until then to play with these.
-
- A couple of suggestions:
- 1) there is a naming conflict between the 2.10.2 sendnews and the
- xfernews sendnews. I renamed the latter to be xsendnews. Don't
- get bitten by this one.
- 2) Don't run recvnews too often. The locking mechanism has a bug and
- you'll get multiple versions tromping on each other. We have great
- success running sendnews every 4 hours, and recvnews every 2 or 3 hours.
-
- If you find any bugs, please mail them to me, to ka@hou3c, hokey@plus5 and to
- rick@seismo.
-
- Enjoy!
-
-
- : to unbundle, "sh" this file -- DO NOT use csh
- : SHAR archive format. Archive created Tue Jan 29 15:00:06 EST 1985
- echo x - NROFFME
- sed 's/^X//' > NROFFME <<'+FUNKY+STUFF+'
- X.hy
- X.de p
- X.sp
- X.ti +5
- X..
- X.de Np
- X'bp
- X'sp 5
- X.ns
- X..
- X.wh 61 Np
- X.de h
- X.sp 2
- X.ne 4
- X.nr h +1
- X\\nh)\ \ \\$1
- X.p
- X..
- X.h "What is xfernews?"
- XXfernews is a package of software for transporting news,
- Xand optionally mail, between machines.
- XIt is designed to be efficient, reliable, and to run on top of
- Xvanilla uucp.
- X.p
- XThe memo is divided into five sections.
- XSection 2 documents the protocal used by xfernews.
- XSection 3 gives an overview of how the xfernews software works.
- XSection 4 and 5 discuss the compilation and installation of xfernews.
- XFinally, section 6 talks about error messages.
- X.h "The xfernews protocal"
- XThe two news transport methods described in the
- X.ul
- XUSENET Interchange Standard
- Xare based upon remote execution and mail, respectively.
- XXfernews is based upon file transfer,
- Xwhich is handled better by uucp and many other networks.
- X.p
- XAssuming that two systems communicate using the xfernews
- Xprotocal, each systems has an input directory which the other
- Xsystem sends files to.
- XEach system periodicly checks its input directory and processes
- Xany files which it may find there.
- XThe name of the file identifies its contents.
- XThe first character of the name is the type;
- Xa list of types is given below.
- XThe next 9 characters contain the value in decimal returned by time(2)
- Xwhen the file was queued for transfer.
- XThis should be used by the receiving system to process
- Xnews in the same order that it was queued.
- XThe final character of the filename is a letter chosen to make the
- Xfile name unique.
- X.p
- XThere are three file types currently defined.
- XType 'n' files contain news articles.
- X.p
- XType 'm' files contain mail.
- XThe use of this protocal for mail is optional,
- Xbut is recomended for links which carry large amounts of mail.
- XThe first line of the file contains the three characters "To "
- Xfollowed by the destination of the mail.
- XThe rest of the file contains the letter.
- XType 'a' files are acknowledgement files.
- XAn acknowledgement file contains a list of files received
- Xby the system which sent the acknowledgement file.
- XIf a system fails to acknowledge a file,
- Xthe file should be resent.
- X.h "The Xfernews Software"
- XThis gives an overview of the implementation of the xfernews protocal
- Xfor use with uucp.
- XThree programs are provided.
- XQnews queues news for transmission to another system.
- XSendnews sends the news which has been queued up
- Xto another system.
- XRecvnews processes news files sent from another system.
- X.p
- XFor each system talked to using xfernews,
- Xthere is a spool directory.
- XThe contents of this directory are:
- X.de l
- X.sp
- X.ti 0
- X.ta 16
- X\\$1 \c
- X.ta 8,16,24,32,40,48,56,64,72,80
- X..
- X.in 16
- X.l in
- XThe input directory used by the remote system (see section 2).
- X.l out
- XNews to be sent to the remote system is placed here by queuenews.
- X.l sent
- XWhen sendnews sends news to the remote system, it moves it from
- Xthe out directory to the sent directory.
- XThe news remains in the sent directory
- Xuntil the remote system acknowledges it.
- X.l ackfile
- XThis file contains a list of input files
- Xwhich have been processed.
- XSendnews sends the contents of this file
- Xto the remote system
- Xas an acknowledgement file.
- X.l lastack
- XThis file contains the time of the last file acknowledged
- Xby the remote system.
- XIt is used to avoid resending files which haven't been acknowledged
- Xbecause the remote system is down.
- X.l resentflag
- XWhen sendnews resends some news,
- Xit creates this file.
- XThe next time sendnews is invoked, it will not resned any news
- Xin order to give the remote system time to acknowledge the files
- Xalready resent.
- X.l bad
- XWhen a file is found in one of the directories "in", "out", or "sent"
- Xwhich cannot be processed,
- Xit is moved to this directory
- Xand you are informed of the fact by mail.
- X.in 0
- X.h "Compiling the Xfernews Software"
- XCompiling the xfernews software is simple: all you have to do
- Xis to type "make".
- XHowever, you will probably want to modify
- Xsome compile time parameters first.
- X.p
- XIf you are not running System 3 or System 5,
- Xyou should remove the "#define USG 1" line
- Xfrom common.h.
- XThis will get you code which should run using Version 6 system calls.
- XThe version of the library routines provided with 4.1 BSD should
- Xwork with this code.
- XIf you have 4.2 BSD, the directory format is different;
- Xeliminate the 4.2 compatability routines in dir.c and dir.h,
- Xand use the real routines provided by Berkeley.
- X.p
- XThere are several compile time parameters which you may want to change:
- X.in 16
- X.l RNEWS
- Xis the path name of the rnews program
- Xused for processing news.
- XBe warned that no path search will be performed.
- XFurthermore, the rnews program cannot be a
- Xshell procedure.
- XThe default is "/usr/bin/rnews".
- X.l RMAIL
- Xis the path name of a program for processing mail.
- XIf you don't use xfernews for transferring mail,
- Xthis isn't used.
- XThe default is "/bin/rmail".
- X.l UUCP
- Xis the path name of the uucp command.
- XThe default is "/usr/bin/uucp".
- X.l MAILCMD
- Xis the command passed to popen to inform the system administrator
- Xof problems.
- XThe default is "mail\ usenet".
- X.l RECVLOCK
- Xis the name of the lock file used to prevent two copies of recvnews
- Xfrom running simultaneously.
- XHaving two copies of recvnews running simultaneously in the same directory
- Xwill cause problems.
- XWe have one system wide lock rather than one lock per directory
- Xbecause inews running multiple copies of inews
- Xseems to result in "news system locked up" messages.
- X.l NETNEWS
- Xis the numeric user id which is to be used by sendnews
- Xand recvnews when they are invoked as root.
- XIf they are not invoked as root then this has no effect.
- X.l DESTLEN
- Xis the maximum length of a mail destination.
- X.l MAXARGS
- Xis the maximum number of files which can be processed
- Xby a given invokation of sendnews or recvnews.
- X.l MINACK
- Xspecifies the minimum number of files needing to be acknowledged
- Xbefore an acknowledgement file will be sent.
- XSetting this to zero causes the systems to keep trading acknowledgements
- Xeven when the link is idle. (Each acknowledgement has to be acked.) Note
- Xthat any pending acknowledgements are always sent if a connection has
- Xto be established to transfer news or mail anyway.
- XMINACK is specified as the number of bytes; since each file currently
- Xtakes 12 bytes, divide by 12 to get the number of files.
- X.in 0
- X.h " Installing Xfernews"
- XOnce xfernews is compiled,
- Xyou can set up links to other machines using the xfernews protocal.
- X.p
- XThe first step is to create xfernews spool directories
- Xfor the systems you want to talk to.
- XThe shell procedure mkspool creates xfernews spool directories.
- XBy default, these are created as subdirectories of /usr/spool. This
- Xmay be changed by editing the mkspool script.
- X.p
- XRecvnews is invoked as "recvnews directory...".
- XEach directory is the name of an xfernews spool directory.
- XIt is recomended that xfernews be invoked from cron
- Xquite frequently, say once every 15 minutes,
- Xso that news will be processed as quickly as possible.
- X.p
- XSendnews is invoked as "sendnews [\ -r\ ][\ -c\ ] directory to".
- XDirectory is the name of an xfernews spool directory.
- XTo is the name of the input directory on the remote system
- Xin uucp format (see example below).
- XThe -r and -c options are passed directly to uucp;
- X-r tells uucp not to start up the uucp daemon, and -c tells it
- Xto transfer directly from the source files without making copies in
- Xthe spool directory. This can be particularly beneficial if the
- Xnews and uucp spool directories are on the same file system since
- Xit allows news to be passed on to other systems with practically no
- Xdisk overhead.
- X.p
- XIt is recomended that both systems using xfernews
- Xinvoke sendnews simultaneously.
- XTo avoid extra phone calls, one system should specify
- Xthe -r option.
- XNormally you will want to alternate specifying the -r option
- Xin order to share the phone bill.
- XFor example, if a link exists between spanky and tpsa,
- Xthe crontab entries on spanky might look like
- X.in +4
- X.nf
- X
- X0 * * * * /usr/lib/news/sendnews -c /usr/spool/tpsa tpsa!/usr/spool/spanky/in
- X30 * * * * /usr/lib/news/sendnews -r -c /usr/spool/tpsa tpsa!/usr/spool/spanky/in
- X
- X.fi
- X.in -4
- Xand the corresponding entries on tpsa would be
- X.in +4
- X.nf
- X
- X0 * * * * /usr/lib/news/sendnews -r -c /usr/spool/spanky spanky!/usr/spool/tpsa/in
- X30 * * * * /usr/lib/news/sendnews -c /usr/spool/spanky spanky!/usr/spool/tpsa/in
- X
- X.fi
- X.in -4
- XThis arranges systems to alternate the job of calling each other.
- XIn this example, news is transferred every half hour;
- Xover a long distance telephone connection you would want to
- Xtransfer it less frequently.
- X.p
- XOnce the connection is set up, you can begin feeding news into it
- Xusing the qnews program.
- XFor a normal interface with netnews, place the command
- X"qnews directory/out" in the fourth field of the sys file entry
- Xfor the system you wish to talk to.
- XDirectory should be replaced by the name of the spool directory
- Xfor the system you wish to talk to. For example, if you send news
- Xto a system named spanky, the sys entry might look like this:
- X.in +4
- X.nf
- X
- Xspanky:mod,net,to.spanky:B:/usr/lib/news/qnews /usr/spool/spanky
- X
- X.fi
- X.in -4
- XThis will cause qnews to read its standard input
- Xand copy it to a file in the directory specified as its argument.
- X.p
- XIn version 2.10 of netnews, it is possible to reference the name
- Xof the article as it is stored in the netnews spool directory,
- Xthereby allowing the article to be linked into the spool directory
- Xrather than being copied there.
- XTo use this feature, the netnews spool directory and the xfernews
- Xspool directory must be in the same file system.
- XAdd the U flag to the third field of the entry in the sys file,
- Xand in the fourth field say: "qnews directory/out %s":
- X.in +4
- X.nf
- X
- Xspanky:mod,net,to.spanky:BU:/usr/lib/news/qnews /usr/spool/spanky %s
- X
- X.fi
- X.in -4
- XInews will replace the %s with the name of the article in the spool
- Xdirectory before invoking qnews.
- XIf the article is a control message, the article is not placed in
- Xthe netnews spool directory and the %s is passed to qnews unchanged.
- XQnews checks for this case and reads the article from its standard input.
- XNote that even in this case, inews copies the article to a file,
- Xso you may want to modify inews to pass the name of the file to qnews
- Xeven when it is a control message.
- X.p
- XIf the cost of a phone connection is very high, or you are
- Xhaving problems with mail being lost, you may want to transfer mail
- Xas well as news using xfernews.
- XYou will probably have to modify your mailer code.
- XThe basic idea is you first figure out how your mail system transfers
- Xmail using uux.
- XIt will invoke uux by saying something like:
- X.nf
- X
- X sprintf(cmd, "uux - %s!rnews \\(%s\\)", system, dest) ;
- X fp = popen(cmd, "w") ;
- X
- X.fi
- XAssuming spanky is the system you want to send mail to using xfernews,
- Xchange this to:
- X.nf
- X
- X if (strcmp(system, "spanky") == 0) {
- X sprintf(cmd, "qnews -tm %s /usr/spool/spanky", dest) ;
- X fp = popen(cmd, "w") ;
- X if (fp != NULL)
- X fprintf(fp, "To %s\\n", dest) ;
- X } else {
- X sprintf(cmd, "uux - %s!rnews \\(%s\\)", system, dest) ;
- X fp = popen(cmd) ;
- X }
- X
- X.fi
- XThe -t option to qnews specifies the type of file to be created;
- Xin this case 'm' or mail.
- X.h "Administration of xfernews"
- XWhen an error occurs in the xfernews package,
- Xyou will be informed by mail.
- XIt is important that the mail command work;
- Xtry invoking sendnews without any arguments and see if an error message
- Xis mailed to you.
- XMost error messages refer to errors which "can't happen" (i. e.
- Xthe problem is either a bug in the package or an error in installation).
- XYou may have to grep through the code or contact the aouthor to identify these.
- XYou are also informed when the RNEWS or RMAIL programs exit with non-zero
- Xstatus.
- XWhen one of these programs fails, the mail or news is still acknowledged
- Xand the file is linked into the directory "bad" where you can fix the
- Xproblem manually.
- XThe exit status of the program and any error messages generated by the program
- Xare included in in the message.
- XSometimes the problem is transient, so just running rnews again will fix
- Xthe problem.
- XIf you run 2.10, you may want to inews to exit with an error indication
- Xwhen an unknown newsgroup is received.
- XThis way you can fix the problem and resubmit the article.
- XThe following version of the routine getapproval (in inews.c)
- Xdoes the trick, at least for the beta release:
- X.nf
- X
- Xgetapproval(ng)
- Xchar *ng;
- X{
- X char buf[128] ;
- X sprintf(buf, "inews: unrecognized newsgroup %s\n", ng) ;
- X log(buf) ;
- X printf("%s", buf) ;
- X xxit(4) ;
- X}
- X
- X.fi
- XFiles in the directories "in", "out", and "sent" with unrecognized names
- Xwill also be moved to the directory "bad".
- XIf rnews dies with a core dump, the core file will be left in "in",
- Xand the next invocation of recvnews will move it to "bad".
- +FUNKY+STUFF+
- echo '-rw-r--r-- 1 wan 12678 Nov 29 1983 NROFFME (as sent)'
- chmod u=rw,g=r,o=r NROFFME
- ls -l NROFFME
- echo x - README
- sed 's/^X//' > README <<'+FUNKY+STUFF+'
- XSee NROFFME.OUT for an explanation of how this "batching" scheme
- Xworks.
- X
- XModify common.h and mkspool to suit your configuration. NROFFME
- Xcontains explanations of what various parameters mean.
- X
- XModify the makefile to reference the appropriate directories and
- Xuser/group names, then as root type make install.
- X
- Xnews.send and news.recv are sample shell procedures to be invoked
- Xfrom cron periodically. The applicable crontab entries at gatech
- Xare
- X
- X 4,14,24,34,44,54 * * * * /usr/lib/news/news.recv
- X 18 * * * * /usr/lib/news/news.send
- X
- XNote that the news.send script should be scheduled a few minutes
- Xbefore a uucp contact is expected to minimize the latency of
- Xarticles waiting in the batching queue.
- +FUNKY+STUFF+
- echo '-rw-r--r-- 1 wan 702 Nov 29 1983 README (as sent)'
- chmod u=rw,g=r,o=r README
- ls -l README
- echo x - common.h
- sed 's/^X//' > common.h <<'+FUNKY+STUFF+'
- X#include <stdio.h>
- X#include <sys/types.h>
- X#ifdef USG
- X#define u_short ushort
- X#endif
- X#include "dir.h"
- X#include <sys/stat.h>
- X#include <signal.h>
- X#include <errno.h>
- X#ifdef USG
- X#include <fcntl.h>
- X#endif
- X
- X#define FNLEN 15 /* max file name length (including nul) */
- X#define PATHLEN 100 /* max path name length */
- X#define DESTLEN 256 /* max length of mail destination */
- X#define MAXARGS 200 /* max number of args to uucp */
- X#define SETIN 01 /* flag to run: reset stdin */
- X#define RNEWS "/usr/bin/rnews"
- X#define RMAIL "/bin/rmail"
- X#define UUCP "/usr/bin/uucp"
- X#define MAILCMD "/bin/csmail usenet"
- X#define RECVLOCK "/usr/tmp/recv.lock"
- X#define MINACK (10 * 12)
- X#define NETNEWS 65 /* netnews user id */
- X
- X
- X#ifndef USG
- X#define strchr index
- X#endif
- X
- X/* routine to determine if a process exists */
- X#define procexists(pid) (kill(pid, 0) >= 0 || errno == EPERM)
- X
- Xlong time(), atol() ;
- Xchar *strcpy(), *strchr() ;
- Xchar *malloc() ;
- XFILE *popen() ;
- Xint comp() ;
- X
- Xextern int errno ;
- +FUNKY+STUFF+
- echo '-rw-r--r-- 1 wan 962 Nov 22 1983 common.h (as sent)'
- chmod u=rw,g=r,o=r common.h
- ls -l common.h
- echo x - dir.c
- sed 's/^X//' > dir.c <<'+FUNKY+STUFF+'
- X#include <sys/types.h>
- X#include "dir.h"
- X
- X/*
- X * close a directory.
- X */
- Xvoid
- Xclosedir(dirp)
- X register DIR *dirp;
- X{
- X close(dirp->dd_fd);
- X dirp->dd_fd = -1;
- X dirp->dd_loc = 0;
- X free(dirp);
- X}
- X
- X
- X
- X/*
- X * open a directory.
- X */
- XDIR *
- Xopendir(name)
- X char *name;
- X{
- X register DIR *dirp;
- X register int fd;
- X
- X if ((fd = open(name, 0)) == -1)
- X return NULL;
- X if ((dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
- X close (fd);
- X return NULL;
- X }
- X dirp->dd_fd = fd;
- X dirp->dd_loc = 0;
- X return dirp;
- X}
- X
- X
- X
- X/*
- X * read an old style directory entry and present it as a new one
- X */
- X
- X#define ODIRSIZ 14
- X
- Xstruct olddirect {
- X ino_t od_ino;
- X char od_name[ODIRSIZ];
- X};
- X
- X/*
- X * get next entry in a directory.
- X */
- Xstruct direct *
- Xreaddir(dirp)
- X register DIR *dirp;
- X{
- X register struct olddirect *dp;
- X static struct direct dir;
- X
- X for (;;) {
- X if (dirp->dd_loc == 0) {
- X dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf,
- X DIRBLKSIZ);
- X if (dirp->dd_size <= 0)
- X return NULL;
- X }
- X if (dirp->dd_loc >= dirp->dd_size) {
- X dirp->dd_loc = 0;
- X continue;
- X }
- X dp = (struct olddirect *)(dirp->dd_buf + dirp->dd_loc);
- X dirp->dd_loc += sizeof(struct olddirect);
- X if (dp->od_ino == 0)
- X continue;
- X dir.d_ino = dp->od_ino;
- X strncpy(dir.d_name, dp->od_name, ODIRSIZ);
- X dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */
- X dir.d_namlen = strlen(dir.d_name);
- X dir.d_reclen = DIRBLKSIZ;
- X return (&dir);
- X }
- X}
- +FUNKY+STUFF+
- echo '-rw-r--r-- 1 wan 1382 Nov 22 1983 dir.c (as sent)'
- chmod u=rw,g=r,o=r dir.c
- ls -l dir.c
- echo x - dir.h
- sed 's/^X//' > dir.h <<'+FUNKY+STUFF+'
- X/* dir.h 4.4 82/07/25 */
- X
- X/*
- X * A directory consists of some number of blocks of DIRBLKSIZ
- X * bytes, where DIRBLKSIZ is chosen such that it can be transferred
- X * to disk in a single atomic operation (e.g. 512 bytes on most machines).
- X *
- X * Each DIRBLKSIZ byte block contains some number of directory entry
- X * structures, which are of variable length. Each directory entry has
- X * a struct direct at the front of it, containing its inode number,
- X * the length of the entry, and the length of the name contained in
- X * the entry. These are followed by the name padded to a 4 byte boundary
- X * with null bytes. All names are guaranteed null terminated.
- X * The maximum length of a name in a directory is MAXNAMLEN.
- X *
- X * The macro DIRSIZ(dp) gives the amount of space required to represent
- X * a directory entry. Free space in a directory is represented by
- X * entries which have dp->d_reclen >= DIRSIZ(dp). All DIRBLKSIZ bytes
- X * in a directory block are claimed by the directory entries. This
- X * usually results in the last entry in a directory having a large
- X * dp->d_reclen. When entries are deleted from a directory, the
- X * space is returned to the previous entry in the same directory
- X * block by increasing its dp->d_reclen. If the first entry of
- X * a directory block is free, then its dp->d_ino is set to 0.
- X * Entries other than the first in a directory do not normally have
- X * dp->d_ino set to 0.
- X */
- X#define DIRBLKSIZ 512
- X#define MAXNAMLEN 255
- X
- X#ifdef pdp11
- X#define u_long long
- X#endif
- X
- Xstruct direct {
- X u_long d_ino; /* inode number of entry */
- X u_short d_reclen; /* length of this record */
- X u_short d_namlen; /* length of string in d_name */
- X char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */
- X};
- X
- X/*
- X * The DIRSIZ macro gives the minimum record length which will hold
- X * the directory entry. This requires the amount of space in struct direct
- X * without the d_name field, plus enough space for the name with a terminating
- X * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
- X */
- X#undef DIRSIZ
- X#define DIRSIZ(dp) \
- X ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
- X
- X#ifndef KERNEL
- X/*
- X * Definitions for library routines operating on directories.
- X */
- Xtypedef struct _dirdesc {
- X int dd_fd;
- X long dd_loc;
- X long dd_size;
- X char dd_buf[DIRBLKSIZ];
- X} DIR;
- X#ifndef NULL
- X#define NULL 0
- X#endif
- Xextern DIR *opendir();
- Xextern struct direct *readdir();
- Xextern long telldir();
- Xextern void seekdir();
- X#define rewinddir(dirp) seekdir((dirp), (long)0)
- Xextern void closedir();
- X#endif KERNEL
- +FUNKY+STUFF+
- echo '-rw-r--r-- 1 wan 2546 Nov 22 1983 dir.h (as sent)'
- chmod u=rw,g=r,o=r dir.h
- ls -l dir.h
- echo x - makefile
- sed 's/^X//' > makefile <<'+FUNKY+STUFF+'
- Xall: recvnews xsendnews qnews
- X
- Xrecvnews: recvnews.o dir.o
- X $(CC) -o $@ recvnews.o dir.o
- X
- Xxsendnews: sendnews.o dir.o
- X $(CC) -o $@ sendnews.o dir.o
- X
- Xqnews: qnews.c common.h
- X $(CC) -o $@ $(CFLAGS) qnews.c
- X
- Xsendnews.o recvnews.o: common.h
- X
- Xinstall: all
- X cp mkspool xsendnews recvnews qnews /usr/lib/news
- X cd /usr/lib/news; chown news xsendnews recvnews qnews
- X cd /usr/lib/news; chgrp news xsendnews recvnews qnews
- X chmod ug+s /usr/lib/news/xsendnews /usr/lib/news/recvnews /usr/lib/news/qnews
- +FUNKY+STUFF+
- echo '-rw-r--r-- 1 wan 490 Oct 1 21:52 makefile (as sent)'
- chmod u=rw,g=r,o=r makefile
- ls -l makefile
- echo x - mkspool
- sed 's/^X//' > mkspool <<'+FUNKY+STUFF+'
- X#! /bin/sh
- X# Create an xfernews spool directory
- X
- Xif [ $# = 0 ]
- Xthen
- X echo usage: mkspool sysname ...
- X exit 1
- Xfi
- X
- Xcd /usr/spool
- Xumask 022
- X
- Xfor sys do
- X if [ -z "$sys" -o "$sys" != "`basename \"$sys\"`" ]
- X then
- X echo $sys: bad system name
- X continue
- X elif [ -f $sys -o -d $sys ]
- X then
- X echo $sys: conflicts with existing file or directory
- X continue
- X fi
- X if mkdir $sys
- X then
- X mkdir $sys/in
- X mkdir $sys/sent
- X mkdir $sys/out
- X mkdir $sys/bad
- X echo 0 > $sys/lastack
- X chown news $sys $sys/in $sys/sent $sys/out $sys/bad $sys/lastack
- X chgrp news $sys $sys/in $sys/sent $sys/out $sys/bad $sys/lastack
- X chmod a+w $sys/in
- X ls -ld $sys $sys/*
- X fi
- Xdone
- +FUNKY+STUFF+
- echo '-rwxr-xr-x 1 wan 650 Dec 15 1983 mkspool (as sent)'
- chmod u=rwx,g=rx,o=rx mkspool
- ls -l mkspool
- echo x - news.recv
- sed 's/^X//' > news.recv <<'+FUNKY+STUFF+'
- X#! /bin/sh
- X
- X PATH=/usr/lib/news:/bin:/usr/bin
- X
- X cd /usr/spool
- X umask 022
- X recvnews akgua emory >> /usr/lib/news/recv.log 2>&1
- +FUNKY+STUFF+
- echo '-rwxr-xr-x 1 wan 126 Dec 19 1983 news.recv (as sent)'
- chmod u=rwx,g=rx,o=rx news.recv
- ls -l news.recv
- echo x - news.send
- sed 's/^X//' > news.send <<'+FUNKY+STUFF+'
- X#! /bin/sh
- X
- X PATH=/usr/lib/news:/bin:/usr/bin
- X
- X cd /usr/spool
- X umask 022
- X sendnews -c -r akgua akgua!/usr/spool/gatech/in
- X sendnews -c -r emory emory!/usr/spool/gatech/in
- +FUNKY+STUFF+
- echo '-rwxr-xr-x 1 wan 171 Dec 19 1983 news.send (as sent)'
- chmod u=rwx,g=rx,o=rx news.send
- ls -l news.send
- echo x - qnews.c
- sed 's/^X//' > qnews.c <<'+FUNKY+STUFF+'
- X#include "common.h"
- X
- X
- Xchar *directory ;
- Xchar *file ;
- X
- X
- Xmain(argc, argv)
- X char **argv ;
- X {
- X long t ;
- X char *from, *lastc ;
- X char to[PATHLEN] ;
- X char **ap ;
- X char prefix ;
- X int fd ;
- X
- X prefix = 'n' ;
- X ap = argv + 1 ;
- X if (ap[0][0] == '-' && ap[0][1] == 't') {
- X if ((prefix = ap[0][2]) == '\0')
- Xusage: fatal("usage: qnews [ -tc ] directory [ file ]") ;
- X ap++ ;
- X }
- X if ((directory = *ap++) == NULL)
- X goto usage ;
- X from = *ap ;
- X if (from != NULL && strcmp(from, "%s") == 0)
- X from = NULL ;
- X time(&t) ;
- X sprintf(to, "%s/%c%lda", directory, prefix, t) ;
- X lastc = to + strlen(to) - 1 ;
- X signal(SIGTERM, SIG_IGN) ;
- X for (;;) {
- X if (from != NULL)
- X fd = link(from, to) ;
- X else {
- X#ifdef USG
- X fd = open(to, O_WRONLY | O_CREAT | O_EXCL, 0444) ;
- X#else
- X fd = creat(to, 0444) ;
- X#endif
- X }
- X if (fd >= 0)
- X break ;
- X if (errno != EEXIST && errno != EPERM || *lastc == 'z')
- X fatal("can't create %s", to) ;
- X *lastc += 1 ;
- X }
- X if (from == NULL) {
- X char buf[BUFSIZ] ;
- X int count ;
- X
- X file = to ;
- X while ((count = read(0, buf, BUFSIZ)) > 0) {
- X if (write(fd, buf, count) != count) {
- X fatal("write error") ;
- X }
- X }
- X if (count < 0) {
- X fatal("read error") ;
- X }
- X }
- X exit(0) ;
- X}
- X
- X
- X
- X/*
- X * Fatal error.
- X * Print error message and send mail to administrator.
- X */
- X
- Xfatal(fmt, a1, a2, a3, a4)
- X char *fmt ;
- X {
- X static int reentered = 0 ;
- X
- X if (reentered) {
- X fprintf(stderr, "fatal entered recursively\n") ;
- X fprintf(stderr, fmt, a1, a2, a3, a4) ;
- X if (file != NULL)
- X unlink(file) ;
- X exit(3) ;
- X }
- X reentered = 1 ;
- X msg(fmt, a1, a2, a3, a4) ;
- X if (file != NULL)
- X if (unlink(file) < 0)
- X msg("unlink failed: %s", file) ;
- X exit(2) ;
- X}
- X
- X
- X/*
- X * Send mail to administrator. Flag is set to indicate fatal error.
- X */
- X
- Xmsg(fmt, a1, a2, a3, a4)
- X char *fmt ;
- X {
- X FILE *fp ;
- X int e = errno ;
- X
- X fprintf(stderr, fmt, a1, a2, a3, a4) ;
- X putc('\n', stderr) ;
- X if ((fp = popen(MAILCMD, "w")) == NULL)
- X fatal("popen failed") ;
- X fputs("Subject: error in qnews\n\n", fp) ;
- X fprintf(fp, fmt, a1, a2, a3, a4) ;
- X if (directory != NULL) {
- X fputs("\nprocessing ", fp) ;
- X fputs(directory, fp) ;
- X }
- X putc('\n', fp) ;
- X fprintf(fp, "errno = %d\n", e) ;
- X if (pclose(fp) != 0)
- X fatal("msg failed") ;
- X}
- +FUNKY+STUFF+
- echo '-rw-r--r-- 1 wan 2853 Sep 9 1983 qnews.c (as sent)'
- chmod u=rw,g=r,o=r qnews.c
- ls -l qnews.c
- echo x - recvnews.c
- sed 's/^X//' > recvnews.c <<'+FUNKY+STUFF+'
- X#define RECVNEWS 1
- X#include "common.h"
- X
- X#ifdef USG
- X#include <setjmp.h>
- X#define setexit() setjmp(nextdir)
- X#define reset() longjmp(nextdir, 1)
- Xjmp_buf nextdir ; /* label to jump to on major error */
- X#endif
- X
- Xstruct arglist {
- X int nargs ;
- X char *arg[MAXARGS] ;
- X} ;
- X
- Xchar *directory ; /* directory currently being processed */
- Xint errflag ; /* set if any errors */
- Xchar lockfile[] = RECVLOCK ;
- X
- X
- X
- Xmain(argc, argv)
- Xchar **argv ;
- X{
- X char **ap ;
- X
- X nice(10) ;
- X setuid(NETNEWS) ; /* in case invoked as root by cron */
- X if (setlock(lockfile) == 0) {
- X printf("recvnews locked\n") ;
- X exit(0) ;
- X }
- X ap = argv + 1 ;
- X setexit() ;
- X while (*ap != NULL) {
- X directory = *ap++ ;
- X if (chdir(directory) < 0)
- X fatal("directory nonexistant") ;
- X inputnews() ;
- X if (chdir("..") < 0) {
- X printf("can't chdir to %s/..\n", directory) ;
- X break ;
- X }
- X }
- X if (unlink(lockfile) < 0)
- X msg("can't unlink lock") ;
- X exit(errflag) ;
- X}
- X
- X
- X
- Xinputnews() {
- X struct arglist in ;
- X DIR *dp ;
- X struct direct *d ;
- X int oflow ;
- X int i ;
- X
- X in.nargs = 0 ;
- X oflow = 0 ;
- X if (chdir("in") < 0)
- X fatal("in missing") ;
- X dp = opendir(".") ;
- X if (dp == NULL)
- X fatal("no .") ;
- X while ((d = readdir(dp)) != NULL) {
- X if (d->d_name[0] != '.') {
- X if (in.nargs < MAXARGS)
- X addarg(d->d_name, &in) ;
- X else
- X oflow++ ;
- X }
- X }
- X if (oflow > 0)
- X msg("%d articles not processed", oflow) ;
- X closedir(dp) ;
- X if (in.nargs == 0)
- X goto out ;
- X qsort((char *)in.arg, in.nargs, sizeof(char *), comp) ;
- X sleep(5) ; /* in case any files half written */
- X for (i = 0 ; i < in.nargs ; i++) {
- X procfile(in.arg[i]) ;
- X free(in.arg[i]) ;
- X }
- Xout:
- X if (chdir("..") < 0)
- X fatal("can't chdir ..") ;
- X}
- X
- X
- X
- Xprocfile(name)
- X char *name ;
- X {
- X FILE *fp ;
- X int rc ;
- X
- X if (badname(name)) {
- X msg("bad input file name %s", name) ;
- X movebad(name) ;
- X return ;
- X }
- X if ((fp = fopen(name, "r")) == NULL) {
- X msg("unreadable file %s", name) ;
- X movebad(name) ;
- X return ;
- X }
- X switch (name[0]) {
- X case 'a':
- X rc = procack(name, fp) ;
- X break ;
- X case 'n':
- X rc = procnews(name, fp) ;
- X break ;
- X case 'm':
- X rc = procmail(name, fp) ;
- X break ;
- X default:
- X fatal("can't happen %s", name) ;
- X break ;
- X }
- X if (rc < 0)
- X movebad(name) ;
- X else if (unlink(name) < 0)
- X msg("can't unlink %s", name) ;
- X fclose(fp) ;
- X if ((fp = fopen("../ackfile", "a")) == NULL)
- X fatal("Can't open ackfile") ;
- X fprintf(fp, "%s\n", name) ;
- X fclose(fp) ;
- X}
- X
- X
- X
- Xprocnews(name, fp)
- X char *name ;
- X FILE *fp ;
- X {
- X char *arg[2] ;
- X
- X arg[0] = RNEWS, arg[1] = NULL ;
- X return chkrun(arg, name, fp) ;
- X}
- X
- X
- Xprocmail(name, fp)
- X char *name ;
- X FILE *fp ;
- X {
- X char *arg[4] ;
- X char buf[DESTLEN] ;
- X char *p ;
- X
- X setbuf(fp, NULL) ; /* turn off buffering */
- X if (fgets(buf, DESTLEN, fp) == NULL) {
- X msg("%s: empty file", name) ;
- X return -1 ;
- X }
- X if (strncmp(buf, "To ", 3) != 0) {
- X msg("corrupted mail %s", name) ;
- X return -1 ;
- X }
- X if ((p = strchr(buf, '\n')) == NULL) {
- X msg("destination too long, file %s", name) ;
- X return -1 ;
- X }
- X *p = '\0' ;
- X arg[0] = RMAIL, arg[1] = buf + 3, arg[2] = NULL ;
- X return chkrun(arg, name, fp) ;
- X}
- X
- X
- X
- Xprocack(name, fp)
- X char *name ;
- X FILE *fp ;
- X {
- X char line[FNLEN+2] ;
- X char *p ;
- X
- X if (chdir("../sent") < 0)
- X fatal("no sent dir") ;
- X while (fgets(line, FNLEN + 2, fp) != NULL) {
- X if ((p = strchr(line, '\n')) == NULL) {
- X msg("line too long, file %s", name) ;
- Xbad: if (chdir("../in") < 0)
- X fatal("return to in") ;
- X return -1 ;
- X }
- X *p = '\0' ;
- X if (badname(line)) {
- X msg("bad file %s acked in %s", line, name) ;
- X goto bad ;
- X }
- X if (unlink(line) < 0)
- X printf("Can't unlink %s/in/%s, ack file %s\n",
- X directory, line, name) ;
- X }
- X if (chdir("../in") < 0)
- X fatal("return to in") ;
- X if ((fp = fopen("../lastack", "w")) == NULL)
- X fatal("can't open lastack") ;
- X fprintf(fp, "%.9s\n", line + 1) ;
- X fclose(fp) ;
- X return 0 ;
- X}
- X
- X
- X
- Xbadname(fname)
- X char *fname ;
- X {
- X register c ;
- X
- X if ((c = *fname++) != 'a' && c != 'n' && c != 'm')
- X return -1 ;
- X if ((c = *fname++) < '0' || c > '9')
- X return -1 ;
- X return 0 ;
- X}
- X
- X
- X
- Xmovebad(fname)
- X char *fname ;
- X {
- X char bad[PATHLEN] ;
- X
- X sprintf(bad, "../bad/%s", fname) ;
- X unlink(bad) ;
- X if (link(fname, bad) < 0)
- X fatal("link to bad failed for %s", fname) ;
- X if (unlink(fname) < 0)
- X fatal("unlink bad file %s failed", fname) ;
- X}
- X
- X
- X
- Xcomp(a, b)
- X char **a, **b ;
- X {
- X return strcmp(*a, *b) ;
- X}
- X
- X
- X
- Xaddarg(fname, argl)
- X struct arglist *argl ;
- X char *fname ;
- X {
- X char *p ;
- X
- X if (argl->nargs >= MAXARGS)
- X fatal("too many articles") ;
- X if (fname == NULL)
- X p = NULL ;
- X else {
- X if ((p = malloc(strlen(fname) + 1)) == NULL)
- X fatal("out of space") ;
- X strcpy(p, fname) ;
- X }
- X argl->arg[argl->nargs++] = p ;
- X}
- X
- X
- X
- X/*
- X * Run a program, informing the system administrator if it fails.
- X */
- X
- Xchkrun(arg, name, fp)
- X char *arg[] ;
- X char *name ;
- X FILE *fp ;
- X {
- X char *p ;
- X int outfd ;
- X int rc ;
- X FILE *mailfp ;
- X static char outfile[24] ;
- X
- X if (outfile[0] == '\0')
- X sprintf(outfile, "/tmp/recvnews%d", getpid()) ;
- X if ((outfd = creat(outfile, 0666)) < 0)
- X fatal("Can't create %s", outfile) ;
- X rc = run(arg, fileno(fp), outfd) ;
- X close(outfd) ;
- X if (rc != 0) {
- X if ((mailfp = popen(MAILCMD, "w")) == NULL)
- X fatal("Can't popen MAILCMD") ;
- X fprintf(mailfp, "Subject: error in recvnews\n\n") ;
- X if ((rc & 0177) == 0) {
- X fprintf(mailfp, "exit status %d from %s", rc >> 8, arg[0]) ;
- X } else {
- X fprintf(mailfp, "%s died with signal %d", arg[0], rc & 0177) ;
- X if (rc & 0200)
- X fprintf(mailfp, " - core dumped") ;
- X }
- X fprintf(mailfp, "\nfile %s/bad/%s\n", directory, name) ;
- X if ((fp = fopen(outfile, "r")) == NULL)
- X fprintf(mailfp, "Can't open %s\n", outfile) ;
- X else {
- X fprintf(mailfp, "Output of program:\n") ;
- X while ((rc = getc(fp)) != EOF)
- X putc(rc, mailfp) ;
- X fclose(fp) ;
- X }
- X pclose(mailfp) ;
- X if (unlink(outfile) < 0)
- X msg("can't unlink %s", outfile) ;
- X return -1 ;
- X }
- X if (unlink(outfile) < 0)
- X msg("can't unlink %s", outfile) ;
- X return 0 ;
- X}
- X
- X
- X
- Xrun(args, in, out)
- X char *args[] ;
- X int in, out ;
- X {
- X int pid ;
- X int status ;
- X int i ;
- X
- X#ifdef DEBUG
- X printf("run") ; /*DEBUG*/
- X for (i = 0 ; args[i] != NULL ; i++) /*DEBUG*/
- X printf(" %s", args[i]) ; /*DEBUG*/
- X putchar('\n') ; /*DEBUG*/
- X#endif
- X if ((pid = fork()) == -1)
- X fatal("Cannot fork") ;
- X if (pid == 0) {
- X if (in != 0) {
- X close(0) ;
- X if (dup(in) != 0) {
- X msg("Cannot redirect input") ;
- X exit(127) ;
- X }
- X close(in) ;
- X }
- X if (out != 1) {
- X close(1) ;
- X if (dup(out) != 1) {
- X msg("Cannot redirect output") ;
- X exit(127) ;
- X }
- X close(out) ;
- X close(2) ;
- X if (dup(1) != 2) {
- X msg("Cannot dup 1") ;
- X exit(127) ;
- X }
- X }
- X execv(args[0], args) ;
- X msg("exec failed") ;
- X exit(127) ;
- X }
- X while ((i = wait(&status)) != pid && i != -1) ;
- X return status ;
- X}
- X
- X
- X/*
- X * Fatal error.
- X * Print error message and send mail to administrator.
- X */
- X
- Xfatal(fmt, a1, a2, a3, a4)
- X char *fmt ;
- X {
- X static int reentered = 0 ;
- X
- X if (reentered) {
- X fprintf(stderr, "fatal entered recursively\n") ;
- X fprintf(stderr, fmt, a1, a2, a3, a4) ;
- X exit(3) ;
- X }
- X reentered = 1 ;
- X msg(fmt, a1, a2, a3, a4) ;
- X reentered = 0 ;
- X reset() ;
- X}
- X
- X
- X/*
- X * Send mail to administrator. Flag is set to indicate fatal error.
- X */
- X
- Xmsg(fmt, a1, a2, a3, a4)
- X char *fmt ;
- X {
- X FILE *fp ;
- X int e = errno ;
- X
- X errflag = 1 ;
- X fprintf(stderr, fmt, a1, a2, a3, a4) ;
- X putc('\n', stderr) ;
- X if ((fp = popen(MAILCMD, "w")) == NULL)
- X fatal("popen failed") ;
- X fputs("Subject: error in recvnews\n\n", fp) ;
- X fprintf(fp, fmt, a1, a2, a3, a4) ;
- X if (directory != NULL) {
- X fputs("\nprocessing ", fp) ;
- X fputs(directory, fp) ;
- X }
- X putc('\n', fp) ;
- X fprintf(fp, "errno = %d\n", e) ;
- X if (pclose(fp) != 0)
- X fatal("msg failed") ;
- X}
- X
- X
- X
- Xsetlock(name)
- X char *name ;
- X {
- X FILE *fp ;
- X char buf[10] ;
- X
- X if ((fp = fopen(name, "r")) != NULL) {
- X if (fgets(buf, 10, fp) == NULL) {
- X msg("empty lock file") ;
- X fclose(fp) ;
- X goto lock ;
- X }
- X fclose(fp) ;
- X if (buf[0] < '0' || buf[0] > '9') {
- X msg("no pid in lock file") ;
- X goto lock ;
- X }
- X if (! procexists(atoi(buf))) {
- X msg("previous recvnews didn't remove lock") ;
- X goto lock ;
- X }
- X return 0 ;
- X }
- Xlock:
- X if ((fp = fopen(name, "w")) == NULL)
- X fatal("cannot create lock file") ;
- X fprintf(fp, "%d\n", getpid()) ;
- X fclose(fp) ;
- X return 1 ;
- X}
- +FUNKY+STUFF+
- echo '-rw-r--r-- 1 wan 10786 Dec 15 1983 recvnews.c (as sent)'
- chmod u=rw,g=r,o=r recvnews.c
- ls -l recvnews.c
- echo x - sendnews.c
- sed 's/^X//' > sendnews.c <<'+FUNKY+STUFF+'
- X#define DEBUG
- X#include "common.h"
- X
- X#define ASKIP 4
- X
- Xstruct arglist {
- X int nargs ;
- X char **first ;
- X char *arg[MAXARGS] ;
- X} ;
- X
- Xstruct arglist uuargs ;
- Xchar *directory ;
- Xint errflag ;
- Xchar resentflag[] = "resentflag" ;
- Xchar lastack[] = "lastack" ;
- Xchar ackfile[] = "ackfile" ;
- X#ifndef NOTGATECH
- Xint cflag ;
- X#endif
- X
- X
- X
- Xmain(argc, argv)
- X char **argv ;
- X {
- X register char **ap ;
- X int rflag ;
- X char *p ;
- X int i ;
- X struct stat statb ;
- X
- X setuid(NETNEWS) ;
- X ap = argv + 1 ;
- X rflag = 0 ;
- X while ((p = *ap++) != NULL && *p == '-') {
- X if (strcmp(p, "-r") == 0)
- X rflag++ ;
- X#ifndef NOTGATECH
- X else if (strcmp(p, "-c") == 0)
- X cflag++ ;
- X#endif
- X else
- Xusage: fatal("usage: sendnews [ -r ] from to") ;
- X }
- X if (p == NULL || *ap == NULL)
- X goto usage ;
- X directory = p ;
- X if (chdir(p) < 0)
- X fatal("no directory") ;
- X uuargs.first = &uuargs.arg[ASKIP] ;
- X uuargs.nargs = ASKIP ;
- X if (unlink(resentflag) < 0) {
- X sendnews(1) ;
- X }
- X if (uuargs.nargs > ASKIP) {
- X if ((i = creat(resentflag, 0666)) < 0)
- X msg("can't create resent flag") ;
- X close(i) ;
- X msg("resent %d files", uuargs.nargs - ASKIP) ;
- X }
- X sendnews(0) ;
- X if (stat(ackfile, &statb) >= 0
- X && (uuargs.nargs > ASKIP || statb.st_size >= MINACK)) {
- X long t ;
- X char buf[FNLEN + 5] ;
- X
- X time(&t) ;
- X sprintf(buf, "sent/a%lda", t) ;
- X if (link(ackfile, buf) < 0) {
- X msg("can't link ackfile") ;
- X goto uu ;
- X }
- X if (unlink(ackfile) < 0) {
- X msg("can't unlink ackfile") ;
- X goto uu ;
- X }
- X insarg(buf + 5, &uuargs) ;
- X }
- Xuu:
- X uucp(*ap, rflag) ;
- X exit(errflag) ;
- X}
- X
- X
- X
- Xsendnews(resend) {
- X char *dir ;
- X char sentname[PATHLEN] ;
- X DIR *dp ;
- X FILE *fp ;
- X struct direct *d ;
- X long last ;
- X int oflow ;
- X
- X if (resend == 0) {
- X dir = "out" ;
- X } else {
- X dir = "sent" ;
- X if ((fp = fopen(lastack, "r")) == NULL) {
- X msg("can't open lastack") ;
- X return ;
- X }
- X if (fgets(sentname, FNLEN, fp) == NULL) {
- X /* Can occur bacause no locking done */
- X msg("lastack is empty file") ;
- X fclose(fp) ;
- X return ;
- X }
- X fclose(fp) ;
- X last = atol(sentname) - 3600L ;
- X }
- X if (chdir(dir) < 0)
- X fatal("chdir %s failed", dir) ;
- X if ((dp = opendir(".")) == NULL)
- X fatal("no .") ;
- X oflow = 0 ;
- X while ((d = readdir(dp)) != NULL) {
- X if (d->d_name[0] == '.')
- X continue ;
- X else if (badname(d->d_name)) {
- X msg("bad file %s in %s", d->d_name, dir) ;
- X movebad(d->d_name) ;
- X continue ;
- X }
- X if (resend) {
- X if (atol(d->d_name + 1) > last)
- X continue ;
- X printf("resending %s\n", d->d_name) ;
- X }
- X if (uuargs.nargs >= MAXARGS - 3) {
- X oflow++ ;
- X continue ;
- X }
- X addarg(d->d_name, &uuargs) ;
- X if (! resend) {
- X sprintf(sentname, "../sent/%s", d->d_name) ;
- X if (link(d->d_name, sentname) < 0)
- X msg("link %s failed", d->d_name) ;
- X else if (unlink(d->d_name) < 0)
- X msg("unlink %s failed", d->d_name) ;
- X }
- X }
- X closedir(dp) ;
- X if (oflow > 0)
- X msg("too many files: %d not sent", oflow) ;
- X if (chdir("..") < 0)
- X fatal("no ..") ;
- X}
- X
- X
- X
- Xuucp(to, rflag)
- X char *to ;
- X {
- X if (uuargs.first == uuargs.arg + uuargs.nargs)
- X return ;
- X if (chdir("sent") < 0)
- X fatal("no sent dir") ;
- X qsort((char *)(uuargs.arg + ASKIP), uuargs.nargs - ASKIP, sizeof(char *), comp) ;
- X addarg(to, &uuargs) ;
- X addarg(NULL, &uuargs) ;
- X if (rflag) insarg("-r", &uuargs) ;
- X#ifndef NOTGATECH
- X if (cflag) insarg("-c", &uuargs) ;
- X#endif
- X insarg(UUCP, &uuargs) ;
- X if (run(uuargs.first, 0, 0) != 0)
- X fatal("uucp failed") ;
- X if (chdir("..") < 0)
- X fatal("no ..") ;
- X}
- X
- X
- X
- Xbadname(fname)
- X char *fname ;
- X {
- X register c ;
- X
- X if ((c = *fname++) != 'a' && c != 'n' && c != 'm')
- X return -1 ;
- X if ((c = *fname++) < '0' || c > '9')
- X return -1 ;
- X return 0 ;
- X}
- X
- X
- X
- Xmovebad(fname)
- X char *fname ;
- X {
- X char bad[PATHLEN] ;
- X
- X sprintf(bad, "../bad/%s", fname) ;
- X unlink(bad) ;
- X if (link(fname, bad) < 0)
- X fatal("link to bad failed for %s", fname) ;
- X if (unlink(fname) < 0)
- X fatal("unlink bad file %s failed", fname) ;
- X}
- X
- X
- X
- Xcomp(a, b)
- X char **a, **b ;
- X {
- X return strcmp(*a, *b) ;
- X}
- X
- X
- X
- Xaddarg(fname, argl)
- X struct arglist *argl ;
- X char *fname ;
- X {
- X char *p ;
- X
- X if (argl->nargs >= MAXARGS)
- X fatal("too many articles") ;
- X if (fname == NULL)
- X p = NULL ;
- X else {
- X if ((p = malloc(strlen(fname) + 1)) == NULL)
- X fatal("out of space") ;
- X strcpy(p, fname) ;
- X }
- X argl->arg[argl->nargs++] = p ;
- X}
- X
- X
- Xinsarg(fname, argl)
- X struct arglist *argl ;
- X char *fname ;
- X {
- X char *p ;
- X
- X if (argl->first <= argl->arg)
- X fatal("insarg failed") ;
- X if (fname == NULL)
- X p = NULL ;
- X else {
- X if ((p = malloc(strlen(fname) + 1)) == NULL)
- X fatal("out of space") ;
- X strcpy(p, fname) ;
- X }
- X *--(argl->first) = p ;
- X}
- X
- X
- X
- Xrun(args, flags, fd)
- X char *args[] ;
- X int flags ;
- X int fd ;
- X {
- X int pid ;
- X int status ;
- X int i ;
- X
- X#ifdef DEBUG
- X printf("run") ; /*DEBUG*/
- X for (i = 0 ; args[i] != NULL ; i++) /*DEBUG*/
- X printf(" %s", args[i]) ; /*DEBUG*/
- X putchar('\n') ; /*DEBUG*/
- X#endif
- X if ((pid = fork()) == -1)
- X fatal("Cannot fork") ;
- X if (pid == 0) {
- X if (flags & SETIN) {
- X close(0) ;
- X if (dup(fd) != 0) {
- X msg("Cannot redirect input") ;
- X exit(127) ;
- X }
- X close(fd) ;
- X }
- X execv(args[0], args) ;
- X msg("exec failed") ;
- X exit(127) ;
- X }
- X while ((i = wait(&status)) != pid && i != -1) ;
- X return status ;
- X}
- X
- X
- X/*
- X * Fatal error.
- X * Print error message and send mail to administrator.
- X */
- X
- Xfatal(fmt, a1, a2, a3, a4)
- X char *fmt ;
- X {
- X static int reentered = 0 ;
- X
- X if (reentered) {
- X fprintf(stderr, "fatal entered recursively\n") ;
- X fprintf(stderr, fmt, a1, a2, a3, a4) ;
- X exit(3) ;
- X }
- X reentered = 1 ;
- X msg(fmt, a1, a2, a3, a4) ;
- X exit(2) ;
- X}
- X
- X
- X/*
- X * Send mail to administrator. Flag is set to indicate fatal error.
- X */
- X
- Xmsg(fmt, a1, a2, a3, a4)
- X char *fmt ;
- X {
- X FILE *fp ;
- X
- X errflag = 1 ;
- X fprintf(stderr, fmt, a1, a2, a3, a4) ;
- X putc('\n', stderr) ;
- X if ((fp = popen(MAILCMD, "w")) == NULL)
- X fatal("popen failed") ;
- X fputs("Subject: error in sendnews\n\n", fp) ;
- X fprintf(fp, fmt, a1, a2, a3, a4) ;
- X if (directory != NULL) {
- X fputs("\nprocessing ", fp) ;
- X fputs(directory, fp) ;
- X }
- X putc('\n', fp) ;
- X if (pclose(fp) != 0)
- X fatal("msg failed") ;
- X}
- +FUNKY+STUFF+
- echo '-rw-r--r-- 1 wan 7817 Nov 29 1983 sendnews.c (as sent)'
- chmod u=rw,g=r,o=r sendnews.c
- ls -l sendnews.c
- exit 0
-
-
-