Subject: Vixie cron (finally) arrives in 2.11BSD (#421 - 2 of 3)
Index:	usr.sbin/cron 2.11BSD

Description:
	The cron(8) program only allows for a single system wide
	crontab file.  Individual users can not maintain their own
	crontab files.

Repeat-By:
	Observation for many years ;)

Fix:
	This is a 3 part update.  This (#421) is part 2 of 3 and contains
	the first half of the new cron sources.  The instructions are in
	part 1.

	As always this and previous updates to 2.11BSD are available via
	anonymous FTP to either FTP.IIPO.GTEGSC.COM or MOE.2BSD.COM in the
	directory /pub/2.11BSD.
-----------------------------cut here--------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	cron/grot/CHANGES
#	cron/grot/CONVERSION
#	cron/grot/FEATURES
#	cron/grot/INSTALL
#	cron/grot/MAIL
#	cron/grot/MANIFEST
#	cron/grot/THANKS
#	cron/grot/diffs
#	cron/README.2BSD
#	cron/Makefile
#	cron/README
#	cron/bitstring.3
#	cron/bitstring.h
#	cron/compat.c
#	cron/compat.h
#	cron/config.h
# This archive created: Tue Jul 20 20:07:45 1999
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'cron/grot/CHANGES'
then
	echo shar: "will not over-write existing file 'cron/grot/CHANGES'"
else
sed 's/^Z//' << \SHAR_EOF > 'cron/grot/CHANGES'
ZVixie Cron		Changes from V2 to V3
ZPaul Vixie
Z29-Dec-1993
Z
ZThe crontab command now conforms to POSIX 1003.2.  This means that when you
Zinstall it, if you have any "crontab" command lines floating around in shell
Zscripts (such as /etc/rc or /etc/rc.local), you will need to change them.
Z
ZI have integrated several changes made by BSDi for their BSD/386 operating
Zsystem; these were offerred to me before I started consulting for them, so
Zit is safe to say that they were intended for publication.  Most notably,
Zthe name of the cron daemon has changed from "crond" to "cron".  This was
Zdone for compatibility with 4.3BSD.  Another change made for the same reason
Zis the ability to read in an /etc/crontab file which has an extra field in
Zeach entry, between the time fields and the command.  This field is a user
Zname, and it permits the /etc/crontab command to contain commands which are
Zto be run by any user on the system.  /etc/crontab is not "installed" via
Zthe crontab(1) command; it is automatically read at startup time and it will
Zbe reread whenever it changes.
Z
ZI also added a "-e" option to crontab(1).  Nine people also sent me diffs
Zto add this option, but I had already implemented it on my own.  I actually
Zreleased an interrim version (V2.2, I think) for limited testing, and got a
Zchance to fix a bad security bug in the "-e" option thanks to XXX.
Z
ZThe daemon used to be extraordinarily sloppy in its use of file descriptors.
ZA heck of a lot of them were left open in spawned jobs, which caused problems
Zfor the daemon and also caused problems with the spawned jobs if they were 
Zshell scripts since "sh" and "csh" have traditionally used hidden file
Zdescriptors to pass information to subshells, and cron was causing them to
Zthink they were subshells.  If you had trouble with "sh" or "csh" scripts in
ZV2, chances are good that V3 will fix your problems.
Z
ZAbout a dozen people have reminded me that I forgot to initialize
Z"crontab_fd" in database.c.  Keith Cantrell was the first, so he gets the
Zpoint.
Z
ZSteve Simmons reminded me that once an account has been deleted from the
Zsystem, "crontab -u USER -d" will not work.  My solution is to suggest to
Zall of you that before you delete a user's account, you first delete that
Zuser's crontab file if any.  From cron's point of view, usernames can never
Zbe treated as arbitrary strings.  Either they are valid user names, or they
Zare not.  I will not make an exception for the "-d" case, for security
Zreasons that I consider reasonable.  It is trivial for a root user to delete
Zthe entry by hand if necessary.
Z
ZDan O'Neil reminded me that I forgot to reset "log_fd" in misc.c.  A lot of
Zothers also reminded me of this, but Dan gets the point.  I didn't fix it
Zthere, since the real bug was that it should have been open in the parent.
Z
ZPeter Kabal reminded me that I forgot to "#ifdef DEBUGGING" some code in
Zmisc.c.  Hans Trompert actually told me first, but Peter sent the patch so
Zhe gets the point.
Z
ZRussell Nelson told me that I'd forgotten to "#include <syslog.h>" in misc.c,
Zwhich explains why a lot of other people complained that it wasn't using
Zsyslog even when they configured it that way :-).  Steve Simmons told me
Zfirst, though, so he gets the point.
Z
ZAn interrim version of the daemon tried to "stat" every file before
Zexecuting it; this turned out to be a horribly bad idea since finding the
Zname of a file from a shell command is a hard job (that's why we have
Zshells, right?)  I removed this bogus code.  Dave Burgess gets the point.
Z
ZDennis R. Conley sent a suggestion for MMDF systems, which I've added to the
Zcomments in cron.h.
Z
ZMike Heisler noted that I use comments in the CONVERSION file which are
Zdocumented as illegal in the man pages.  Thanks, Mike.
Z
ZIrving Wolfe sent me some very cheerful changes for a NeXT system, but I
Zconsider the system itself broken and I can't bring myself to #ifdef for
Zsomething as screwed up as this system seems to be.  However, various others
Zdid send me smaller patches which appear to have cause cron to build and run
Zcorrectly on (the latest) NeXT machines, with or without the "-posix" CFLAG.
ZIrving also asked for a per-job MAILTO, and this was finally added later when
ZI integrated the BSD/386 changes contributed by BSDi, and generalized some of
Zthe parsing.
Z
ZLots of folks complained that the autogenerated "Date:" header wasn't in
ZARPA format.  I didn't understand this -- either folks will use Sendmail and
Znot generate a Date:  at all (since Sendmail will do it), or folks will use
Zsomething other than Sendmail which won't care about Date: formats.  But
ZI've "fixed" it anyway...
Z
ZSeveral people suggested that "*" should be able to take a "/step".  One person
Zsuggested that "N/step" ought to mean "N-last/step", but that's stretching things
Za bit far.  "*/step" seems quite intuitive to me, so I've added it.  Colin Plumb
Zsent in the first and most polite request for this feature.
Z
ZAs with every release of Cron, BIND, and seemingly everything else I do, one
Zuser stands out with the most critical but also the most useful analysis.
ZCron V3's high score belongs to Peter Holzer, who sent in the nicest looking
Zpatch for the "%" interpretation problem and also helped me understand a
Ztricky bit of badness in the "log_fd" problem.
Z
Zagulbra@flode.nvg.unit.no wins the honors for being the first to point out the
Znasty security hole in "crontab -r".  'Nuff said.
Z
ZSeveral folks pointed out that log_it() needed to exist even if logging was
Zdisabled.  Some day I will create a tool that will compile a subsystem with
Zevery possible combination and permutation of #ifdef options, but meanwhile
Zthanks to everybody.
Z
Zjob_runqueue() was using storage after freeing it, since Jordan told me back
Zin 1983 that C let you do that, and I believed him in 1986 when I wrote all
Zthis junk.  Linux was the first to die from this error, and the Linux people
Zsent me the most amazing, um, collection of patches for this problem.  Thanks
Zfor all the fish.
Z
ZJeremy Bettis reminded me that popen() isn't safe.  I grabbed Ken Arnold's 
Zversion of popen/pclose from the ftpd and hacked it to taste.  We're safe now,
Zfrom this at least.
Z
ZBranko Lankester sent me a very timely and helpful fix for a looming security
Zproblem in my "crontab -e" implementation.
Z
Z--------
Z
ZVixie Cron		Changes from V1 to V2
ZPaul Vixie
Z8-Feb-1988
Z
ZMany changes were made in a rash of activity about six months ago, the exact
Zlist of which is no longer clear in my memory.  I know that V1 used a file
Zcalled POKECRON in /usr/spool/cron to tell it that it was time to re-read
Zall the crontab files; V2 uses the modtime the crontab directory as a flag to
Zcheck out the crontab files; those whose modtime has changed will be re-read,
Zand the others left alone.  Note that the crontab(1) command will do a utimes
Zcall to make sure the mtime of the dir changes, since the filename/inode will
Zoften remain the same after a replacement and the mtime wouldn't change in
Zthat case.
Z
Z8-Feb-88: made it possible to use much larger environment variable strings.
Z	V1 allowed 100 characters; V2 allows 1000.  This was needed for PATH
Z	variables on some systems.  Thanks to Toerless Eckert for this idea.
Z	E-mail: UUCP: ...pyramid!fauern!faui10!eckert
Z
Z16-Feb-88: added allow/deny, moved /usr/spool/cron/crontabs to
Z	/usr/lib/cron/tabs.  allow and deny are /usr/lib/cron/{allow,deny},
Z	since the sysv naming for this depends on 'at' using the same
Z	dir, which would be stupid (hint: use /usr/{lib,spool}/at).
Z
Z22-Feb-88: made it read the spool directory for crontabs and look each one
Z	up using getpwnam() rather than reading all passwds with getpwent()
Z	and trying to open each crontab.
Z
Z9-Dec-88: made it sync to :00 after the minute, makes cron predictable.
Z	added logging to /var/cron/log.
Z
Z14-Apr-90: (actually, changes since December 1989)
Z	fixed a number of bugs reported from the net and from John Gilmore.
Z	added syslog per Keith Bostic.  security features including not
Z	being willing to run a command owned or writable by other than
Z	the owner of the crontab 9not working well yet)
SHAR_EOF
chmod 644 'cron/grot/CHANGES'
fi
if test -f 'cron/grot/CONVERSION'
then
	echo shar: "will not over-write existing file 'cron/grot/CONVERSION'"
else
sed 's/^Z//' << \SHAR_EOF > 'cron/grot/CONVERSION'
Z$Id: CONVERSION,v 2.2 1993/12/28 08:34:43 vixie Exp $
Z
ZConversion of BSD 4.[23] crontab files:
Z
ZEdit your current crontab (/usr/lib/crontab) into little pieces, with each
Zusers' commands in a different file.  This is different on 4.2 and 4.3,
Zbut I'll get to that below.  The biggest feature of this cron is that you
Zcan move 'news' and 'uucp' cron commands into files owned and maintainable
Zby those two users.  You also get to rip all the fancy 'su' footwork out
Zof the cron commands.  On 4.3, there's no need for the 'su' stuff since the
Zuser name appears on each command -- but I'd still rather have separate
Zcrontabs with seperate environments and so on.
Z
ZLeave the original /usr/lib/crontab!  This cron doesn't use it, so you may
Zas well keep it around for a while in case something goes wakko with this
Zfancy version.
Z
ZMost commands in most crontabs are run by root, have to run by root, and
Zshould continue to be run by root.  They still have to be in their own file;
ZI recommend /etc/crontab.src or /usr/adm/crontab.src.
Z
Z'uucp's commands need their own file; how about /usr/lib/uucp/crontab.src?
Z'news' also, perhaps in /usr/lib/news/crontab.src...
Z
ZI say `how about' and `perhaps' because it really doesn't matter to anyone
Z(except you) where you put the crontab source files.  The `crontab' command
ZCOPIES them into a protected directory (CRONDIR/SPOOL_DIR in cron.h), named
Zafter the user whose crontab it is.  If you want to examine, replace, or
Zdelete a crontab, the `crontab' command does all of those things.  The
Zvarious `crontab.src' (my suggested name for them) files are just source
Zfiles---they have to be copied to SPOOLDIR using `crontab' before they'll be
Zexecuted.
Z
ZOn 4.2, your crontab might have a few lines like this:
Z
Z	5 * * * *   su uucp < /usr/lib/uucp/uudemon.hr
Z	10 4 * * *  su uucp < /usr/lib/uucp/uudemon.day
Z	15 5 * * 0  su uucp < /usr/lib/uucp/uudemon.wk
Z
Z...or like this:
Z
Z	5 * * * *   echo /usr/lib/uucp/uudemon.hr | su uucp
Z	10 4 * * *  echo /usr/lib/uucp/uudemon.day | su uucp
Z	15 5 * * 0  echo /usr/lib/uucp/uudemon.wk | su uucp
Z
ZOn 4.3, they'd look a little bit better, but not much:
Z
Z	5 * * * *   uucp  /usr/lib/uucp/uudemon.hr
Z	10 4 * * *  uucp  /usr/lib/uucp/uudemon.day
Z	15 5 * * 0  uucp  /usr/lib/uucp/uudemon.wk
Z
ZFor this cron, you'd create /usr/lib/uucp/crontab.src (or wherever you want
Zto keep uucp's commands) which would look like this:
Z
Z	# /usr/lib/uucp/crontab.src - uucp's crontab
Z	#
Z	PATH=/usr/lib/uucp:/bin:/usr/bin
Z	SHELL=/bin/sh
Z	HOME=/usr/lib/uucp
Z	#
Z	5 * * * *   uudemon.hr
Z	10 4 * * *  uudemon.day
Z	15 5 * * 0  uudemon.wk
Z
ZThe application to the `news' cron commands (if any) is left for you to
Zfigure out.  Likewise if there are any other cruddy-looking 'su' commands in
Zyour crontab commands, you don't need them anymore: just find a good place
Zto put the `crontab.src' (or whatever you want to call it) file for that
Zuser, put the cron commands into it, and install it using the `crontab'
Zcommand (probably with "-u USERNAME", but see the man page).
Z
ZIf you run a 4.2-derived cron, you could of course just install your current
Zcrontab in toto as root's crontab.  It would work exactly the way your
Zcurrent one does, barring the extra steps in installing or changing it.
ZThere would still be advantages to this cron, mostly that you get mail if
Zthere is any output from your cron commands.
Z
ZOne note about getting mail from cron: you will probably find, after you
Zinstall this version of cron, that your cron commands are generating a lot
Zof irritating output.  The work-around for this is to redirect all EXPECTED
Zoutput to a per-execution log file, which you can examine if you want to
Zsee the output from the "last time" a command was executed; if you get any
ZUNEXPECTED output, it will be mailed to you.  This takes a while to get
Zright, but it's amazingly convenient.  Trust me.
Z
SHAR_EOF
chmod 644 'cron/grot/CONVERSION'
fi
if test -f 'cron/grot/FEATURES'
then
	echo shar: "will not over-write existing file 'cron/grot/FEATURES'"
else
sed 's/^Z//' << \SHAR_EOF > 'cron/grot/FEATURES'
Z$Id: FEATURES,v 2.1 1993/12/28 08:34:43 vixie Exp $
Z
ZFeatures of Vixie's cron relative to BSD 4.[23] and SysV crons:
Z
Z--	Environment variables can be set in each crontab.  SHELL, USER,
Z	LOGNAME, and HOME are set from the user's passwd entry; all except
Z	USER can be changed in the crontab.  PATH is especially useful to
Z	set there.  TZ can be set, but cron ignores it other than passing
Z	it on through to the commands it runs.  Format is
Z
Z		variable=value
Z
Z	Blanks surrounding the '=' will be eaten; other blanks in value are
Z	okay.  Leading or trailing blanks can be preserved by quoting, single
Z	or double quotes are okay, just so they match.
Z
Z		PATH=.:/bin:/usr/bin
Z		SHELL=/bin/sh
Z		FOOBAR = this is a long blanky example
Z
Z	Above, FOOBAR would get "this is a long blanky example" as its value.
Z
Z	SHELL and HOME will be used when it's time to run a command; if
Z	you don't set them, HOME defaults to your /etc/passwd entry
Z	and SHELL defaults to /bin/sh.
Z
Z	MAILTO, if set to the login name of a user on your system, will be the
Z	person that cron mails the output of commands in that crontab.  This is
Z	useful if you decide on BINMAIL when configuring cron.h, since binmail
Z	doesn't know anything about aliasing.
Z
Z--	Weekdays can be specified by name.  Case is not significant, but only
Z	the first three letters should be specified.
Z
Z--	Months can likewise be specified by name.  Three letters only.
Z
Z--	Ranges and lists can be mixed.  Standard crons won't allow '1,3-5'.
Z
Z--	Ranges can specify 'step' values.  '10-16/2' is like '10,12,14,16'.
Z
Z--	Sunday is both day 0 and day 7 -- apparently BSD and ATT disagree
Z	about this.
Z
Z--	Each user gets their own crontab file.  This is a win over BSD 4.2,
Z	where only root has one, and over BSD 4.3, where they made the crontab
Z	format incompatible and although the commands can be run by non-root
Z	uid's, root is still the only one who can edit the crontab file.  This
Z	feature mimics the SysV cron.
Z
Z--	The 'crontab' command is loosely compatible with SysV, but has more
Z	options which just generally make more sense.  Running crontab with
Z	no arguments will print a cute little summary of the command syntax.
Z
Z--	Comments and blank lines are allowed in the crontab file.  Comments
Z	must be on a line by themselves; leading whitespace is ignored, and
Z	a '#' introduces the comment.
Z
Z--	(big win) If the `crontab' command changes anything in any crontab,
Z	the 'cron' daemon will reload all the tables before running the
Z	next iteration.  In some crons, you have to kill and restart the
Z	daemon whenever you change a crontab.  In other crons, the crontab
Z	file is reread and reparsed every minute even if it didn't change.
Z
Z--	In order to support the automatic reload, the crontab files are not
Z	readable or writable except by 'crontab' or 'cron'.  This is not a
Z	problem, since 'crontab' will let you do pretty much whatever you
Z	want to your own crontab, or if you are root, to anybody's crontab.
Z
Z--	If any output is generated by a command (on stdout OR stderr), it will
Z	be mailed to the owner of the crontab that contained the command (or
Z	MAILTO, see discussion of environment variables, above).  The headers
Z	of the mail message will include the command that was run, and a
Z	complete list of the environment that was passed to it, which will
Z	contain (at least) the USER (LOGNAME on SysV), HOME, and SHELL.
Z
Z--	the dom/dow situation is odd.  '* * 1,15 * Sun' will run on the
Z	first and fifteenth AND every Sunday;  '* * * * Sun' will run *only*
Z	on Sundays;  '* * 1,15 * *' will run *only* the 1st and 15th.  this
Z	is why we keep 'e->dow_star' and 'e->dom_star'.  I didn't think up
Z	this behaviour; it's how cron has always worked but the documentation
Z	hasn't been very clear.  I have been told that some AT&T crons do not
Z	act this way and do the more reasonable thing, which is (IMHO) to "or"
Z	the various field-matches together.  In that sense this cron may not
Z	be completely similar to some AT&T crons.
SHAR_EOF
chmod 644 'cron/grot/FEATURES'
fi
if test -f 'cron/grot/INSTALL'
then
	echo shar: "will not over-write existing file 'cron/grot/INSTALL'"
else
sed 's/^Z//' << \SHAR_EOF > 'cron/grot/INSTALL'
Z/* Copyright 1993,1994 by Paul Vixie
Z * All rights reserved
Z *
Z * Distribute freely, except: don't remove my name from the source or
Z * documentation (don't take credit for my work), mark your changes (don't
Z * get me blamed for your possible bugs), don't alter or remove this
Z * notice.  May be sold if buildable source is provided to buyer.  No
Z * warrantee of any kind, express or implied, is included with this
Z * software; use at your own risk, responsibility for damages (if any) to
Z * anyone resulting from the use of this software rests entirely with the
Z * user.
Z *
Z * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
Z * I'll try to keep a version up to date.  I can be reached as follows:
Z * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
Z */
Z
Z$Id: INSTALL,v 2.5 1994/01/15 20:43:43 vixie Exp $
Z
ZRead the comments at the top of the Makefile, then edit the area marked
Z'configurable stuff'.
Z
ZEdit config.h.  The stuff I expect you to change is down a bit from the
Ztop of the file, but it's clearly marked.  Also look at pathnames.h.
Z
ZYou don't have to create the /var/cron or /var/cron/tabs directories, since
Zboth the daemon and the `crontab' program will do this the first time they
Zrun if they don't exist.  You do need to have a /var, though -- just "mkdir
Z/var" if you don't have one, or you can "mkdir /usr/var; ln -s /usr/var /var"
Zif you expect your /var to have a lot of stuff in it.
Z
ZYou will also need /usr/local/etc and /usr/local/bin directories unless you
Zchange the Makefile.  These will have to be created by hand, but if you are
Za long-time Usenet user you probably have them already.  /usr/local/man is
Zwhere I keep my man pages, but I have the source for `man' and you probably
Zdo not.  Therefore you may have to put the man pages into /usr/man/manl,
Zwhich will be hard since there will be name collisions.  (Note that the man
Zcommand was originally written by Bill Joy before he left Berkeley, and it
Zcontains no AT&T code, so it is in UUNET's archive of freely-distributable
ZBSD code.)
Z
ZLINUX note: /usr/include/paths.h on some linux systems shows _PATH_SENDMAIL
Z	to be /usr/bin/sendmail even though sendmail is installed in /usr/lib.
Z	you should check this out.
Z
Zsay:
Z	make all
Z
Zsu and say:
Z	make install
Z
ZNote that if I can get you to "su and say" something just by asking, you have
Za very serious security problem on your system and you should look into it.
Z
ZEdit your /usr/lib/crontab file into little pieces -- see the CONVERSION file
Zfor help on this.
Z
ZUse the `crontab' command to install all the little pieces you just created.
ZSome examples (see below before trying any of these!)
Z
Z	crontab -u uucp -r /usr/lib/uucp/crontab.src
Z	crontab -u news -r /usr/lib/news/crontab.src
Z	crontab -u root -r /usr/adm/crontab.src
Z
ZNotes on above examples: (1) the .src files are copied at the time the
Zcommand is issued; changing the source files later will have no effect until
Zthey are reinstalled with another `crontab -r' command.  (2) The crontab
Zcommand will affect the crontab of the person using the command unless `-u
ZUSER' is given; `-u' only works for root.  When using most `su' commands
Zunder most BSD's, `crontab' will still think of you as yourself even though
Zyou may think of yourself as root -- so use `-u' liberally.  (3) the `-r'
Zoption stands for `replace'; check the man page for crontab(1) for other
Zpossibilities.
Z
ZKill your existing cron daemon -- do `ps aux' and look for /etc/cron.
Z
ZEdit your /etc/rc or /etc/rc.local, looking for the line that starts up
Z/etc/cron.  Comment it out and add a line to start the new cron daemon
Z-- usually /usr/local/etc/cron, unless you changed it in the Makefile.
Z
ZStart up this cron daemon yourself as root.  Just type /usr/local/etc/cron
Z(or whatever); no '&' is needed since the daemon forks itself and the
Zprocess you executed returns immediately.
Z
ZATT notes: for those people unfortunate enough to be stuck on a AT&T UNIX,
Zyou will need the public-domain "libndir", found in the B News source and in
Zany comp.sources.unix archive.  You will also need to hack the code some.
SHAR_EOF
chmod 644 'cron/grot/INSTALL'
fi
if test -f 'cron/grot/MAIL'
then
	echo shar: "will not over-write existing file 'cron/grot/MAIL'"
else
sed 's/^Z//' << \SHAR_EOF > 'cron/grot/MAIL'
Z[ this is really old mail that came to me in response to my 1986 posting
Z  to usenet asking for feature suggestions before releasing the first 
Z  version of cron.  it is presented here for its entertainment value.
Z  --vix ]
Z
Z$Id: MAIL,v 1.1 1993/12/28 08:30:36 vixie Exp $
Z
ZFrom ptsfa!lll-crg!ames!acornrc!bob Wed Dec 31 10:07:08 1986
ZDate: Wed, 31 Dec 86 08:59:31 pst
ZFrom: lll-crg!ames!acornrc!bob (Bob Weissman)
ZTo: ptsfa!vixie!paul
ZStatus: RO
Z
ZSure, here's a suggestion: I'd like to be able to run a program, say,
Zevery two hours.  Current cron requires me to write
Z0,2,4,6,8,10,12,14,16,18,20,22 in the hours field.  How about a notation
Zto handle this more elegantly?
Z
Z<<	Okay, I've allowed 0-22/2 as a means of handling this.
Z	The time specification for my cron is as follows:
Z		specification = range {"," range}
Z		range = (start "-" finish ["/" step]) | single-unit
Z	This allows "1,3,5-7", which the current cron doesn't (it won't
Z	do a range inside a list), and handles your specific need.	>>
Z
ZFrom drw@mit-eddie Wed Dec 31 18:25:27 1986
ZDate: Wed, 31 Dec 86 14:28:19 est
ZFrom: drw@mit-eddie (Dale Worley)
ZTo: mit-eddie!vixie!paul
ZStatus: RO
Z
ZWe have a lot of lines in our crontab of the form
Z
Z	00 12 * * * su user < /usr/users/user/script.file
Z
ZThis barfs (silently!) on our system (Dec Ultrix 1.2 == 4.2bsd) if
Zuser's shell is csh.  This, I am told, is because csh requires that
Zthe environment be set up in certain ways, which cron doesn't do.
Z(Actually, I believe, it is because /etc/rc, which runs cron, doesn't
Zset up the environment enough for csh to run, and cron just inherits
Zthe situation.)  Anyway, the point is that if you find out what csh
Zreally needs in its environment, you might want to set up cron to
Zprovide some reasonable defaults (if it isn't supplied by cron's
Zparent).  Also, could you tell me what csh needs, if you find out, so
Zwe can hack our /etc/rc?
Z
Z<<	well, the environment IS a problem. processes that cron forks
Z	will inherit the environment of the person who ran the cron
Z	daemon... I plan to edit out such useless things as TERMCAP,
Z	TERM, and the like; supply correct values for HOME, USER, CWD,
Z	and whatever else comes to mind.  I'll make sure csh works...	>>
ZFrom ptsfa!ames!seismo!dgis!generous Thu Jan  1 07:33:17 1987
ZDate: Thu Jan 1 10:29:20 1987
ZFrom: ames!seismo!dgis!generous (Curtis Generous)
ZTo: nike!ptsfa!vixie!paul
ZStatus: RO
Z
ZPaul:
Z
ZOne of the limitations of the present versions of cron is the lack
Zof the capability of specifying a way to execute a command every
Zn units of time.
Z
ZHere is a good example:
Z
Z# Present method to start up uucico
Z02,12,22,32,42,52 * * * * 	exec /usr/lib/uucp/uucico -r1
Z
Z# New method ?? (the ':' here is just one possibility for syntax)
Z02:10 * * * *			exec /usr/lib/uucp/uucico -r1
Z
ZThis method would prove very helpful for those programs that get started
Zevery few minutes, making the entry long and not easily readable.  The first
Znumber would specify the base time, and the second number the repetition
Zinterval.
Z
Z<<	Good idea, but bob@acornrc beat you to it.  I used '/' instead of
Z	':'.  This is my personal preference, and seems intuitive when you
Z	think of the divide operator in C... Does anyone have a preference? >>
Z
ZFrom ptsfa!lll-lcc!seismo!decuac!c3pe!c3engr!charles Thu Jan  1 17:04:24 1987
ZFrom: lll-lcc!seismo!c3pe!c3engr!charles (Charles Green)
ZTo: c3pe!decuac!dolqci!vrdxhq!seismo!lll-lcc!ptsfa!vixie!paul
ZDate: Thu Jan  1 19:22:47 1987
ZStatus: RO
Z
ZWell, this isn't a compatible extension, but I have in times past wondered
Zabout a facility to let you start a process at intervals of, say, 17 minutes,
Zinstead of particular minutes out of each hour.
Z
Z<<	This was a popular request!	>>
Z
ZFrom seismo!uwvax!astroatc!nicmad!norvax!mann Sun Jan  4 13:04:01 1987
ZDate: Fri, 2 Jan 87 09:23:53 cst
ZFrom: lll-lcc!seismo!uwvax!astroatc!nicmad!norvax!mann (Tom Mann)
ZTo: ptsfa!vixie!paul
ZStatus: RO
Z
ZI'm not sure if it is in cron (either SysV or BSD ... if it is, I haven't
Zfigured it out ) but a comment feature would SURE BE NICE!.
ZThere are times when I want to comment out an entry
Zfor a period of time; it might also make it a lot more legible.
Z
Z<<	My cron allows blank lines and standard #-type comments.  I know
Z	that one BSD4.2 cron I've used had it.  I don't know about SysV.  >>
Z
ZFrom ptsfa!hoptoad!hugh Mon Jan  5 10:26:46 1987
ZDate: Mon, 5 Jan 87 01:22:17 PST
ZFrom: hoptoad!hugh (Hugh Daniel)
ZTo: ptsfa!vixie!paul
ZStatus: RO
Z
Z  Hi, I do have a BIG one that I would like.  I want to log ALL output
Zfrom command lines into a file for each line.  Thus I might have a chance
Zof finding out why my crontab entry did not work.
Z  This would seem to work best if done by cron, as it is now I have a google
Zof shell scripts laying about just to put the error output where I can see
Zit.
Z
Z<<	My cron (and the SysV cron) will send mail to the owner of the
Z	particular crontab file if a command generates any output on stdout
Z	or stderr.  This can be irritating, but if you write a script such
Z	that any output means a problem occurred, you can avoid most logfile
Z	needs, and not generate mail except in unforeseen circumstances.   >>
Z
ZFrom ptsfa!dual!ucbvax!ihnp4!anvil!es!Robert_Toxen Mon Jan  5 13:08:46 1987
ZFrom: dual!ucbvax!ihnp4!anvil!es!Robert_Toxen
ZDate: Fri,  2 Jan 87 14:25:29 EST
ZTo: anvil!ihnp4!ucbvax!dual!ptsfa!vixie!paul
ZStatus: RO
Z
ZHere are some suggestions:
Z1. Run it through the C preprocessor via "/lib/<whatever>".
Z
Z<<	hmmm. this seems of limited utility, and if you really wanted
Z	to do it that way, you could do it yourself (since users can
Z	write to their own crontab files).  I'll add '-' (read stdin)
Z	to the crontab installer program to facilitate this.		>>
Z
Z2. Allow specifying every Nth day of week, i.e., every second Wednesday.
Z   I did this to calendar by separating the day of week (Wed=4, which one
Z   to start on and N with slashes).  I took modulo the day of year as a
Z   starting point so that someone with a desk calendar documenting such
Z   things can easily determine the offset (second number).  I did this
Z   while at SGI; alas I don't have a copy of the code.
Z
Z<<	I can see how this could be useful, but I'm not sure how I'd
Z	implement it.  Cron currently doesn't keep track of the last time
Z	a given command was run; whether the current Wednesday is the first
Z	or second since the command was last run would be pretty hard to
Z	figure out.  I'd have to keep a database of commands and their
Z	execution around, and purge it when the crontab was overwritten.
Z	This is too much work for me, but if someone adds it, let me know.  >>
Z
ZFrom ptsfa!ames!seismo!cbmvax!devon!paul Tue Jan  6 05:50:17 1987
ZFrom: ames!seismo!cbmvax!devon!paul
ZTo: cbmvax!seismo!nike!ptsfa!vixie!paul
ZDate: Mon Jan  5 09:29:57 1987
ZStatus: RO
Z
ZOne problem that has always plagued me with cron is the assumed ORing.
ZI'd like to see some type of ANDing implemented.  I guess I can best
Zdescribe this by example.  Say I have the following line in my crontab
Zfile:
Z
Z*  *  4-31  *  1-6	/usr/bin/command
Z
ZWhat this does is run 'command' on the 4th thru 31st days of the
Zmonth, AND on Monday thru Saturday; which probably means running it
Zevery day of the month (unless Sunday falls on days 1-3).  This
Zhappens because cron runs the command if the day-of-month OR the
Zday-of-week is true.
Z
ZWhat I'd like to happen with the above line is to run the command ONLY
Zon Monday thru Saturday any time after the 3rd of the month, e.g. if
Zthe day-of-month AND the day-of-week are true.
Z
ZMy proposal to you is to implement some special chars for the first
Zfive fields.  Examples:
Z
Z*  *  !1-3  *  1-6	/usr/bin/command
Z
Z(run command Mon-Sat, but NOT [!] on the first 3 days of the month)
Z
Z*  *  &4-31 *  &1-6	/usr/bin/command
Z
Z(run command if day-of-month AND day-of-week are true)
Z
ZGet the picture?  This would be compatable with existing versions of
Zcron (which wouldn't currently be using any special characters, so
Zthat old crontabs would be handled correctly).
Z
Z<<	This message made me aware of the actual boolean expression involved
Z	in a crontab entry.  I'd assumed that it was
Z		(minute && hour && DoM && month && DoW)
Z	But it's really
Z		(minute && hour && month && (DoM || DoW))
Z
Z	I can see some value in changing this, but with a fixed order of
Z	fields, operators get to be kindof unary, which && and || really
Z	aren't.  If someone has an idea on a syntax that allows useful
Z	variations to the standard (&& && && (||)) default, please suggest. >>
Z
ZFrom bobkat!pedz Tue Jan  6 20:02:10 1987
ZFrom: pedz@bobkat.UUCP (Pedz Thing)
ZDate: 2 Jan 87 17:34:44 GMT
ZStatus: RO
Z
ZLog files!  It would be nice to be able to specify a log for cron
Zitself and also a log for each program's stdout and stderr to go to.
ZThe latter can of course be done with > and 2> but it would be nice if
Zthere could be a single line with some sort of pattern like
Z`> /usr/spool/log/%' and the command would be substituted for the %.
ZAnother thing which would be nice is to be able to specify which shell
Zto call to give the command to.
Z
Z<<	Log files are done with mail.  The '%' idea could be useful if
Z	a different character were used (% is special to cron, see man
Z	page); a different directory would have to be chosen, since each
Z	user has their own crontab file; and something intelligent would
Z	have to be done in the file naming, since the first word of the
Z	command might be ambiguous (with other commands).  In short, it's
Z	too much work.  Sorry.						  >>
Z
ZFrom guy%gorodish@sun Tue Jan  6 20:03:13 1987
ZFrom: guy%gorodish@sun (Guy Harris)
ZMessage-ID: <10944@sun.uucp>
ZDate: 5 Jan 87 12:09:09 GMT
ZReferences: <429@vixie.UUCP> <359@bobkat.UUCP>
ZSender: news@sun.uucp
ZStatus: RO
Z
Z> Another thing which would be nice is to be able to specify which shell
Z> to call to give the command to.
Z
ZWell, the obvious choice would be the user's shell, but this wouldn't work
Zfor accounts like "uucico".
Z
Z<<	I use the owning user's shell, and to handle "uucico" I check a
Z	list of "acceptable shells" (currently compiled in, does anybody
Z	mind?), substituting a default (compiled in) shell if the user's
Z	shell isn't on the list.
Z
Z	BTW, "compiled in" means that it's in a .h file, easily changed
Z	during installation, but requiring recompilation to modify.  You
Z	don't have to go digging through the code to find it...		  >>
Z
ZFrom qantel!hplabs!ucbvax!mwm@violet.berkeley.edu Tue Jan  6 21:24:48 1987
ZTo: hplabs!qantel!vixie!paul (Paul Vixie Esq)
ZDate: 04 Jan 87 00:42:35 PST (Sun)
ZFrom: Mike Meyer <mwm@violet.berkeley.edu>
ZStatus: RO
Z
Z<<[Discussion of RMS/FSF, and mwm's GNU Cron deleted]>>
Z
ZOh, yeah - here are the extensions on my cron:
Z
Z1) Sunday is both day 0 and day 7, so it complies with both SysV and
ZBSD cron.
Z
Z<<	Good idea. I did it too, thanks for informing me.	>>
Z
Z2) At is integrated into the cron. Instead of atrun to scan the
Z/usr/spool/at directory, at files are put into the /usr/lib/cron
Zdirectory along with users cron files, and cron fabricates a line from
Za crontab file to run them. This is considered a major win by all who
Zuse it.
Z
Z<<	I don't use 'at', and my cron doesn't do anything with it.  To run
Z	'at', I use 'atrun' the same way the current BSD cron does.  My
Z	crontab files are in /usr/spool/cron/crontabs, in the SysV
Z	tradition -- not in /usr/lib/cron.  This is a configuration
Z	parameter, of course.						>>
Z
ZThere are two known restrictions:
Z
Z1) I don't support any of the SysV security hooks. I don't have a use
Zfor them, and RMS didn't like the idea at all :-).
Z
Z<<	This means cron.allow and cron.deny.  I plan to support them, as
Z	they've been quite helpful at various HPUX sites I've administered. >>
Z
Z2) Cron expects to be able to create files with names longer than 14
Zcharacters, which makes it hard to run on SysV. At least one person
Zwas working on a port, but I don't know how it's going. That might
Zmake for a good reason for releasing yours, right there.
Z
Z<<	If someone has SysV (with the 14-character limit), they probably
Z	won't want my cron, since it doesn't add much to the standard
Z	version (which they may have support for).  My cron is not currently
Z	portable to non-BSD systems, since it relies on interval timers (I
Z	needed to sleep for intervals more granular than seconds alone would
Z	allow).  The port would be trivial, and I will do it if a lot of
Z	people ask for it...						>>
Z
ZOh, yeah - I'm going to see about getting this cron integrated into
Zthe next 4BSD release.
Z
Z<<	How does one go about this?  I have a few nifty gadgets I'd like
Z	to contribute, this cron being one of them...			>>
Z
Z<<[more FSF/GNU discussion deleted]>>
Z
ZFrom qantel!hplabs!ames!ut-sally!ut-ngp!melpad!bigtex!james Tue Jan  6 21:24:57 1987
ZPosted-Date: Fri, 2 Jan 87 19:26:16 est
ZDate: Fri, 2 Jan 87 19:26:16 est
ZFrom: hplabs!ames!ut-sally!ut-ngp!bigtex!james
ZTo: vixie!paul
ZStatus: RO
Z
ZYes!!!  There are several critical failures in System V cron...
Z
Z1. Pass all variables in cron's environment into the environment of things
Z   cron starts up, or at least into the crontab entries started up (at jobs
Z   will inherit the environment of the user).  If nothing else it is critically
Z   important that the TZ variable be passed on.  PATH should be passed on too.
Z   Basically, passing environment values allows one to design a standard
Z   environment with TZ and PATH and have that run by everything.  If anyone
Z   tells you this is no big deal, consider what happens when uucico is
Z   started by cron in CA to make a long distance phone link...  Unless the
Z   administrator is really on his/her toes, calls scheduled at 5pm will really
Z   go at two in the afternoon, needlessly incurring huge phone bills, all
Z   because System V refuses to pass the TZ from its environment down.  There
Z   are work arounds, but only putting it in cron will really work.  This is
Z   not a security hole.
Z
Z<<	delete TERM and TERMCAP; modify HOME, USER, and CWD; pass TZ and
Z	PATH through undisturbed.  any other requests out there?
Z
Z	BSD doesn't have this problem -- TZ is passed right on through if
Z	you define it in the shell before starting my cron daemon.  However,
Z	the BSD I'm running this on doesn't need TZ to be defined anyway...
Z	The default in the kernel has been just fine so far...  But just the
Z	same, if/when I port to SysV (I guess I really should), I'll make
Z	sure this works right.
Z
Z	I guess I've been spoiled.  HPUX is SysV-based, and I never had a
Z	problem with cron and TZ when I used it.			  >>
Z
Z2. A way to avoid logging stuff in /usr/lib/cron/log.  I have a cron entry
Z   run uudemon.hr every 10 minutes.  This is 144 times/day.  Each run generates
Z   three lines of text, for a total of 432 lines of text I don't want to see.
Z   Obviously this should be optional, but it would be nice if there were a
Z   way to flag an entry so that it wasn't logged at all unless there was an
Z   error.
Z
Z<<	I don't know nothin' 'bout no /usr/lib/cron/log.  What is this file?
Z	I don't see any reason to create log entries, given the mail-the-
Z	output behaviour.  Opinions, anyone?				>>
Z
ZI will come up with other ideas no doubt, but I can always implement them
Zmyself.
Z
Z<<	That's what I like about PD software.  Please send me the diffs!  >>
Z
ZThe other problem you have is making sure you can run standard
Zcrontabs.  I would suggest something like this: if the command part of the
Zentry starts with an unescaped -, then flags and options follow immediately
Zthereafter.  As in:
Z
Z2,12,22,32,42,52 * * * * -q /usr/lib/uucp/uudemon.hr
Z
ZThis could mean do not log the uudemon.hr run unless there is a problem of
Zsome kind.  This is probably safe as not many filenames start with "-", and
Zthose that do are already a problem for people.
Z
Z<<	Since I don't plan on supporting /usr/lib/cron/log in ANY form unless
Z	many people request it, I won't be needing -q as you've defined it.
Z	I could use something like this to avoid sending mail on errors, for
Z	the occasional script that you don't want to bullet-proof.
Z
Z	The compatibility issue is CRITICAL.  The 4.3BSD crontab format is
Z	a crime against the whole philosophy of Unix(TM), in my opinion.   >>
Z
ZOne other minor thing to consider is the ulimit: can different users get
Zdifferent ulimits for their crontab entries?
Z
Z<<	Boy I'm ignorant today.  What's a ulimit, and what should I do with
Z	it in a crontab?  Suggestions, enlightenment, etc ??		   >>
Z
ZFrom qantel!lll-crg!ames!uw-beaver!uw-nsr!john Tue Jan  6 23:32:44 1987
ZDate: Thu, 1 Jan 87 10:53:05 pst
ZFrom: lll-crg!ames!uw-beaver!uw-nsr!john (John Sambrook 5-7433)
ZTo: vixie!paul
ZStatus: RO
Z
ZHow about not hardwiring the default environment that cron builds for its
Zchildren in the cron program itself?  Our cron does this and it's the pits
Zbecause we are TZ=PST8PDT not TZ=EST5EDT !
Z
Z<<	yeachk.  I assure you, I will not hardwire the TZ!		>>
ZFrom ptsfa!well!dv Fri Jan  9 04:01:50 1987
ZDate: Thu, 8 Jan 87 23:50:40 pst
ZFrom: well!dv (David W. Vezie)
ZTo: ptsfa!vixie!paul
ZStatus: RO
Z
Z6, have a special notation called 'H' which would expand to weekends
Z   and holidays (you'd have to keep a database somewhere of real
Z   holidays), and also 'W' for workdays (neither weekend or holiday).
Z
Z<<	Too much work.  There should be a standard way to define and
Z	detect holidays under Unix(TM); if there were, I'd use it.  As
Z	it is, I'll leave this for someone else to add.
Z
Z	I can see the usefulness; it just doesn't quite seem worth it.    >>
ZFrom qantel!gatech!akgua!blnt1!jat Wed Jan 14 20:00:40 1987
ZDate: Tue, 13 Jan 87 16:39:38 EST
ZFrom: gatech!akgua!blnt1!jat
ZStatus: RO
Z
Z1) Add some way to tell cron to reread the files, say kill -1 <pid>
Z
Z<<	whenever the 'crontab' program is run and updates a crontab file,
Z	a file /usr/spool/cron/POKECRON is created; next time the cron
Z	daemon wakes up, it sees it, and re-reads the crontab files.
Z
Z	I thought of handling the signal; even implemented it.  Then this
Z	clever idea hit me and I ripped it all out and added a single
Z	IF-statement to handle the POKECRON file.			>>
Z
Z2) Have some kind of retry time so that if a command fails, cron will try to
Z   execute it again after a certain period.  This is useful if you have some
Z   type of cleanup program that can run at the scheduled time for some reason
Z   (such as locked device, unmounted filesystem, etc).
Z
Z<<	Hmmm, sounds useful.  I could do this by submitting an 'at' job...
Z	I'll think about it.						>>
ZFrom ptsfa!dual!ucbvax!ihnp4!mtuxo!ender Sat Jan  3 16:54:00 1987
ZFrom: dual!ucbvax!ihnp4!mtuxo!ender
ZDate: Sat, 3 Jan 87 14:05:13 PST
ZTo: ucbvax!dual!ptsfa!vixie!paul
ZStatus: RO
Z
ZIt would be nice if nonprivileged users can setup personal crontab files
Z(~/.cronrc, say) and be able to run personal jobs at regular intervals.
Z	
Z<<	this is done, but in the SysV style: the 'crontab' program installs
Z	a new crontab file for the executing user (can be overridden by root
Z	for setup of uucp and news).  the advantage of this is that (1) when
Z	a crontab is changed, the daemon can be informed automatically; and
Z	(2) the file can be syntax-checked before installation.		>>
ZFrom ptsfa!ames!seismo!ihnp4!lcc!richard Fri Jan 16 04:47:33 1987
ZDate: Fri, 16 Jan 87 07:44:57 EST
ZTo: nike!ptsfa!vixie!paul
ZStatus: RO
Z
ZThe System V cron is nice, but it has a few annoying features.  One is that
Zits mail files will say that the previous message is the output of "one of your
Zcron commands."  I wish it would say WHICH cron commmand.
Z
Z<<	Done.  Also which shell, which user (useful when the mail gets
Z	forwarded), which home directory, and other useful crud.	>>
Z
ZAnother problem is with timezones.  It is necessary to specify TZ=PST8PDT (or
Zwhatever) when you invoke cron (from inittab, or /etc/rc) and it is also
Znecessary to add TZ=PST8PDT to each crontab line which might need it.  Cron
Zshould automatically export its idea of the "TZ" to each invoked command, and
Zit should be possible to put a line in the crontab file which overrides that
Zfor every command in the file (e.g., most users are on EST, so cron is run
Zwith TZ=EST5EDT; but one user is usually on PST and wants all of his cron
Zcommands to run with TZ=PST8PDT).  This might be extended to allow any
Zenvironment variable to be specified once for the whole crontab file (e.g.,
ZPATH).
Z
Z<<	Well, since I run the user's shell, you could put this into .cshrc.
Z	generic environment-variable setting could be useful, though.  Since
Z	I have to modify the environment anyway, I'll consider this.	  >>
Z
ZA log file might be a nice idea, but the System V cron log is too verbose.
ZI seem to remember that cron keeps it open, too; so you can't even have
Zsomething go and periodically clean it out.
Z
Z<<	I don't do /usr/lib/cron/log.  I wasn't aware of this file until I
Z	got all these suggestions.  Do people want this file?  Tell me!    >>
SHAR_EOF
chmod 644 'cron/grot/MAIL'
fi
if test -f 'cron/grot/MANIFEST'
then
	echo shar: "will not over-write existing file 'cron/grot/MANIFEST'"
else
sed 's/^Z//' << \SHAR_EOF > 'cron/grot/MANIFEST'
Z   File Name		Archive #	Description
Z-----------------------------------------------------------
Z CHANGES                    2	
Z CONVERSION                 1	
Z FEATURES                   1	
Z INSTALL                    1	
Z MAIL                       2	
Z MANIFEST                   1	This shipping list
Z Makefile                   1	
Z README                     1	
Z THANKS                     1	
Z bitstring.3                1	
Z bitstring.h                1	
Z compat.c                   1	
Z compat.h                   1	
Z config.h                   1	
Z cron.8                     1	
Z cron.c                     1	
Z cron.h                     1	
Z crontab.1                  1	
Z crontab.5                  1	
Z crontab.c                  2	
Z database.c                 1	
Z do_command.c               2	
Z entry.c                    2	
Z env.c                      1	
Z externs.h                  1	
Z job.c                      1	
Z misc.c                     2	
Z pathnames.h                1	
Z popen.c                    1	
Z putman.sh                  1	
Z user.c                     1	
SHAR_EOF
chmod 644 'cron/grot/MANIFEST'
fi
if test -f 'cron/grot/THANKS'
then
	echo shar: "will not over-write existing file 'cron/grot/THANKS'"
else
sed 's/^Z//' << \SHAR_EOF > 'cron/grot/THANKS'
Z15 January 1990
ZPaul Vixie
Z
ZMany people have contributed to cron.  Many more than I can remember, in fact.
ZRich Salz and Carl Gutekunst were each of enormous help to me in V1; Carl for
Zhelping me understand UNIX well enough to write it, and Rich for helping me
Zget the features right.
Z
ZJohn Gilmore wrote me a wonderful review of V2, which took me a whole year to
Zanswer even though it made me clean up some really awful things in the code.
Z(According to John the most awful things are still in here, of course.)
Z
ZPaul Close made a suggestion which led to /etc/crond.pid and the mutex locking
Zon it.  Kevin Braunsdorf of Purdue made a suggestion that led to @reboot and
Zits brothers and sisters; he also sent some diffs that lead cron toward compil-
Zability with System V, though without at(1) capabilities, this cron isn't going
Zto be that useful on System V.  Bob Alverson fixed a silly bug in the line
Znumber counting.  Brian Reid made suggestions which led to the run queue and
Zthe source-file labelling in installed crontabs.
Z
ZScott Narveson ported V2 to a Sequent, and sent in the most useful single batch
Zof diffs I got from anybody.  Changes attributable to Scott are:
Z	-> sendmail won't time out if the command is slow to generate output
Z	-> day-of-week names aren't off by one anymore
Z	-> crontab says the right thing if you do something you shouldn't do
Z	-> crontab(5) man page is longer and more informative
Z	-> misc changes related to the side effects of fclose()
Z	-> Sequent "universe" support added (may also help on Pyramids)
Z	-> null pw_shell is dealt with now; default is /bin/sh
SHAR_EOF
chmod 644 'cron/grot/THANKS'
fi
if test -f 'cron/grot/diffs'
then
	echo shar: "will not over-write existing file 'cron/grot/diffs'"
else
sed 's/^Z//' << \SHAR_EOF > 'cron/grot/diffs'
Zdiff -c -r /tmp/cron/Makefile cron/Makefile
Z*** /tmp/cron/Makefile	Fri Jun 18 19:37:52 1999
Z--- cron/Makefile	Tue Jun 15 20:53:11 1999
Z***************
Z*** 45,96 ****
Z  #
Z  #	there's more configuration info in config.h; edit that first!
Z  
Z- #################################### begin configurable stuff
Z- #<<DESTROOT is assumed to have ./etc, ./bin, and ./man subdirectories>>
Z  DESTROOT	=	$(DESTDIR)/usr
Z  DESTSBIN	=	$(DESTROOT)/sbin
Z  DESTBIN		=	$(DESTROOT)/bin
Z! DESTMAN		=	$(DESTROOT)/share/man
Z! #<<need bitstring.h>>
Z  INCLUDE		=	-I.
Z- #INCLUDE	=
Z- #<<need getopt()>>
Z  LIBS		=
Z! #<<optimize or debug?>>
Z! #OPTIM		=	-O
Z! OPTIM		=	-g
Z! #<<ATT or BSD or POSIX?>>
Z! # (ATT untested)
Z! #COMPAT		=	-DATT
Z! #(BSD is only needed if <sys/params.h> does not define it, as on ULTRIX)
Z! #COMPAT		=	-DBSD
Z! # (POSIX)
Z! #COMPAT		=	-DPOSIX
Z  #<<lint flags of choice?>>
Z! LINTFLAGS	=	-hbxa $(INCLUDE) $(COMPAT) $(DEBUGGING)
Z! #<<want to use a nonstandard CC?>>
Z! #CC		=	vcc
Z! #<<manifest defines>>
Z  DEFS		=
Z! #(SGI IRIX systems need this)
Z! #DEFS		=	-D_BSD_SIGNALS -Dconst=
Z! #<<the name of the BSD-like install program>>
Z! #INSTALL = installbsd
Z! INSTALL = install
Z! #<<any special load flags>>
Z! LDFLAGS		=
Z  #################################### end configurable stuff
Z  
Z  SHELL		=	/bin/sh
Z! CFLAGS		=	$(OPTIM) $(INCLUDE) $(COMPAT) $(DEFS)
Z  
Z- INFOS		=	README CHANGES FEATURES INSTALL CONVERSION THANKS MAIL
Z- MANPAGES	=	bitstring.3 crontab.5 crontab.1 cron.8 putman.sh
Z- HEADERS		=	bitstring.h cron.h config.h pathnames.h \
Z- 			externs.h compat.h
Z- SOURCES		=	cron.c crontab.c database.c do_command.c entry.c \
Z- 			env.c job.c user.c popen.c misc.c compat.c
Z- SHAR_SOURCE	=	$(INFOS) $(MANPAGES) Makefile $(HEADERS) $(SOURCES)
Z  LINT_CRON	=	cron.c database.c user.c entry.c compat.c \
Z  			misc.c job.c do_command.c env.c popen.c
Z  LINT_CRONTAB	=	crontab.c misc.c entry.c env.c compat.c
Z--- 45,68 ----
Z  #
Z  #	there's more configuration info in config.h; edit that first!
Z  
Z  DESTROOT	=	$(DESTDIR)/usr
Z  DESTSBIN	=	$(DESTROOT)/sbin
Z  DESTBIN		=	$(DESTROOT)/bin
Z! DESTMAN		=	$(DESTROOT)/man
Z  INCLUDE		=	-I.
Z  LIBS		=
Z! OPTIM		=	-O
Z  #<<lint flags of choice?>>
Z! LINTFLAGS	=	-hbxa $(INCLUDE)
Z! CC		=	cc
Z  DEFS		=
Z! INSTALL 	= install
Z! LDFLAGS		= -i
Z  #################################### end configurable stuff
Z  
Z  SHELL		=	/bin/sh
Z! CFLAGS		=	$(OPTIM) $(INCLUDE) $(DEFS)
Z  
Z  LINT_CRON	=	cron.c database.c user.c entry.c compat.c \
Z  			misc.c job.c do_command.c env.c popen.c
Z  LINT_CRONTAB	=	crontab.c misc.c entry.c env.c compat.c
Z***************
Z*** 98,128 ****
Z  			misc.o env.o popen.o compat.o
Z  CRONTAB_OBJ	=	crontab.o misc.o entry.o env.o compat.o
Z  
Z! all		:	cron crontab
Z  
Z! lint		:
Z! 			lint $(LINTFLAGS) $(LINT_CRON) $(LIBS) \
Z! 			|grep -v "constant argument to NOT" 2>&1
Z! 			lint $(LINTFLAGS) $(LINT_CRONTAB) $(LIBS) \
Z! 			|grep -v "constant argument to NOT" 2>&1
Z  
Z! cron		:	$(CRON_OBJ)
Z! 			$(CC) $(LDFLAGS) -o cron $(CRON_OBJ) $(LIBS)
Z  
Z! crontab		:	$(CRONTAB_OBJ)
Z! 			$(CC) $(LDFLAGS) -o crontab $(CRONTAB_OBJ) $(LIBS)
Z  
Z! install		:	all
Z! 			$(INSTALL) -c -m  111 -o root -s cron    $(DESTSBIN)/
Z! 			$(INSTALL) -c -m 4111 -o root -s crontab $(DESTBIN)/
Z! 			sh putman.sh crontab.1 $(DESTMAN)
Z! 			sh putman.sh cron.8    $(DESTMAN)
Z! 			sh putman.sh crontab.5 $(DESTMAN)
Z  
Z! clean		:;	rm -f *.o cron crontab a.out core tags *~ #*
Z! 
Z! kit		:	$(SHAR_SOURCE)
Z! 			makekit -m -s99k $(SHAR_SOURCE)
Z  
Z  $(CRON_OBJ)	:	cron.h compat.h config.h externs.h pathnames.h Makefile
Z  $(CRONTAB_OBJ)	:	cron.h compat.h config.h externs.h pathnames.h Makefile
Z--- 70,98 ----
Z  			misc.o env.o popen.o compat.o
Z  CRONTAB_OBJ	=	crontab.o misc.o entry.o env.o compat.o
Z  
Z! all:	cron crontab
Z  
Z! lint:
Z! 	lint $(LINTFLAGS) $(LINT_CRON) $(LIBS) \
Z! 		|grep -v "constant argument to NOT" 2>&1
Z! 	lint $(LINTFLAGS) $(LINT_CRONTAB) $(LIBS) \
Z! 		|grep -v "constant argument to NOT" 2>&1
Z  
Z! cron:	$(CRON_OBJ)
Z! 	$(CC) $(LDFLAGS) -o cron $(CRON_OBJ) $(LIBS)
Z  
Z! crontab:	$(CRONTAB_OBJ)
Z! 	$(CC) $(LDFLAGS) -o crontab $(CRONTAB_OBJ) $(LIBS)
Z  
Z! install:	all
Z! 	$(INSTALL) -c -m  111 -o root -s cron    $(DESTSBIN)/cron
Z! 	$(INSTALL) -c -m 4111 -o root -s crontab $(DESTBIN)/crontab
Z! 	sh putman.sh crontab.1 $(DESTMAN)
Z! 	sh putman.sh cron.8    $(DESTMAN)
Z! 	sh putman.sh crontab.5 $(DESTMAN)
Z  
Z! clean:
Z! 	rm -f *.o cron crontab a.out core tags *~ #*
Z  
Z  $(CRON_OBJ)	:	cron.h compat.h config.h externs.h pathnames.h Makefile
Z  $(CRONTAB_OBJ)	:	cron.h compat.h config.h externs.h pathnames.h Makefile
Zdiff -c -r /tmp/cron/compat.c cron/compat.c
Z*** /tmp/cron/compat.c	Fri Jun 18 19:37:52 1999
Z--- cron/compat.c	Tue Jun 15 22:04:11 1999
Z***************
Z*** 25,233 ****
Z  
Z  
Z  #include "cron.h"
Z- #ifdef NEED_GETDTABLESIZE
Z- # include <limits.h>
Z- #endif
Z- #if defined(NEED_SETSID) && defined(BSD)
Z- # include <sys/ioctl.h>
Z- #endif
Z- #include <errno.h>
Z  
Z  
Z! /* the code does not depend on any of vfork's
Z!  * side-effects; it just uses it as a quick
Z!  * fork-and-exec.
Z!  */
Z! #ifdef NEED_VFORK
Z! PID_T
Z! vfork() {
Z! 	return (fork());
Z! }
Z! #endif
Z! 
Z! 
Z! #ifdef NEED_STRDUP
Z! char *
Z! strdup(str)
Z! 	char	*str;
Z! {
Z! 	char	*temp;
Z! 
Z! 	temp = malloc(strlen(str) + 1);
Z! 	(void) strcpy(temp, str);
Z! 	return temp;
Z! }
Z! #endif
Z! 
Z! 
Z! #ifdef NEED_STRERROR
Z! char *
Z! strerror(error)
Z! 	int error;
Z! {
Z! 	extern char *sys_errlist[];
Z! 	extern int sys_nerr;
Z! 	static char buf[32];
Z! 
Z! 	if ((error <= sys_nerr) && (error > 0)) {
Z! 		return sys_errlist[error];
Z! 	}
Z! 
Z! 	sprintf(buf, "Unknown error: %d", error);
Z! 	return buf;
Z! }
Z! #endif
Z! 
Z! 
Z! #ifdef NEED_STRCASECMP
Z  int
Z- strcasecmp(left, right)
Z- 	char	*left;
Z- 	char	*right;
Z- {
Z- 	while (*left && (MkLower(*left) == MkLower(*right))) {
Z- 		left++;
Z- 		right++;
Z- 	}
Z- 	return MkLower(*left) - MkLower(*right);
Z- }
Z- #endif
Z- 
Z- 
Z- #ifdef NEED_SETSID
Z- int
Z  setsid()
Z  {
Z  	int	newpgrp;
Z! # if defined(BSD)
Z! 	int	fd;
Z! #  if defined(POSIX)
Z! 	newpgrp = setpgid((pid_t)0, getpid());
Z! #  else
Z  	newpgrp = setpgrp(0, getpid());
Z! #  endif
Z! 	if ((fd = open("/dev/tty", 2)) >= 0)
Z! 	{
Z  		(void) ioctl(fd, TIOCNOTTY, (char*)0);
Z  		(void) close(fd);
Z! 	}
Z! # else /*BSD*/
Z! 	newpgrp = setpgrp();
Z! 
Z! 	(void) close(STDIN);	(void) open("/dev/null", 0);
Z! 	(void) close(STDOUT);	(void) open("/dev/null", 1);
Z! 	(void) close(STDERR);	(void) open("/dev/null", 2);
Z! # endif /*BSD*/
Z  	return newpgrp;
Z  }
Z- #endif /*NEED_SETSID*/
Z- 
Z- 
Z- #ifdef NEED_GETDTABLESIZE
Z- int
Z- getdtablesize() {
Z- #ifdef _SC_OPEN_MAX
Z- 	return sysconf(_SC_OPEN_MAX);
Z- #else
Z- 	return _POSIX_OPEN_MAX;
Z- #endif
Z- }
Z- #endif
Z- 
Z- 
Z- #ifdef NEED_FLOCK
Z- /* The following flock() emulation snarfed intact *) from the HP-UX
Z-  * "BSD to HP-UX porting tricks" maintained by
Z-  * system@alchemy.chem.utoronto.ca (System Admin (Mike Peterson))
Z-  * from the version "last updated: 11-Jan-1993"
Z-  * Snarfage done by Jarkko Hietaniemi <Jarkko.Hietaniemi@hut.fi>
Z-  * *) well, almost, had to K&R the function entry, HPUX "cc"
Z-  * does not grok ANSI function prototypes */
Z-  
Z- /*
Z-  * flock (fd, operation)
Z-  *
Z-  * This routine performs some file locking like the BSD 'flock'
Z-  * on the object described by the int file descriptor 'fd',
Z-  * which must already be open.
Z-  *
Z-  * The operations that are available are:
Z-  *
Z-  * LOCK_SH  -  get a shared lock.
Z-  * LOCK_EX  -  get an exclusive lock.
Z-  * LOCK_NB  -  don't block (must be ORed with LOCK_SH or LOCK_EX).
Z-  * LOCK_UN  -  release a lock.
Z-  *
Z-  * Return value: 0 if lock successful, -1 if failed.
Z-  *
Z-  * Note that whether the locks are enforced or advisory is
Z-  * controlled by the presence or absence of the SETGID bit on
Z-  * the executable.
Z-  *
Z-  * Note that there is no difference between shared and exclusive
Z-  * locks, since the 'lockf' system call in SYSV doesn't make any
Z-  * distinction.
Z-  *
Z-  * The file "<sys/file.h>" should be modified to contain the definitions
Z-  * of the available operations, which must be added manually (see below
Z-  * for the values).
Z-  */
Z- 
Z- /* this code has been reformatted by vixie */
Z- 
Z- int
Z- flock(fd, operation)
Z- 	int fd;
Z- 	int operation;
Z- {
Z- 	int i;
Z- 
Z- 	switch (operation) {
Z- 	case LOCK_SH:		/* get a shared lock */
Z- 	case LOCK_EX:		/* get an exclusive lock */
Z- 		i = lockf (fd, F_LOCK, 0);
Z- 		break;
Z- 
Z- 	case LOCK_SH|LOCK_NB:	/* get a non-blocking shared lock */
Z- 	case LOCK_EX|LOCK_NB:	/* get a non-blocking exclusive lock */
Z- 		i = lockf (fd, F_TLOCK, 0);
Z- 		if (i == -1)
Z- 			if ((errno == EAGAIN) || (errno == EACCES))
Z- 				errno = EWOULDBLOCK;
Z- 		break;
Z- 
Z- 	case LOCK_UN:		/* unlock */
Z- 		i = lockf (fd, F_ULOCK, 0);
Z- 		break;
Z-  
Z- 	default:		/* can't decipher operation */
Z- 		i = -1;
Z- 		errno = EINVAL;
Z- 		break;
Z- 	}
Z-  
Z- 	return (i);
Z- }
Z- #endif /*NEED_FLOCK*/
Z- 
Z- 
Z- #ifdef NEED_SETENV
Z- int
Z- setenv(name, value, overwrite)
Z- 	char *name, *value;
Z- 	int overwrite;
Z- {
Z- 	char *tmp;
Z- 
Z- 	if (overwrite && getenv(name))
Z- 		return -1;
Z- 
Z- 	if (!(tmp = malloc(strlen(name) + strlen(value) + 2))) {
Z- 		errno = ENOMEM;
Z- 		return -1;
Z- 	}
Z- 
Z- 	sprintf("%s=%s", name, value);
Z- 	return putenv(tmp);	/* intentionally orphan 'tmp' storage */
Z- }
Z- #endif
Z--- 25,57 ----
Z  
Z  
Z  #include "cron.h"
Z  
Z+ #include <fcntl.h>
Z+ #include <sys/ioctl.h>
Z  
Z! /*
Z!  * Ripped off from daemon(3) - differences are this sets the process group
Z!  * and does not fork (because that has been done already).
Z! */
Z  int
Z  setsid()
Z  {
Z  	int	newpgrp;
Z! 	register int	fd;
Z! 
Z  	newpgrp = setpgrp(0, getpid());
Z! 	if	((fd = open(_PATH_TTY, 2)) >= 0)
Z! 		{
Z  		(void) ioctl(fd, TIOCNOTTY, (char*)0);
Z  		(void) close(fd);
Z! 		}
Z! 	if	((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1)
Z! 		{
Z! 		(void)dup2(fd, 0);
Z! 		(void)dup2(fd, 1);
Z! 		(void)dup2(fd, 2);
Z! 		if	(fd > 2)
Z! 			(void)close(fd);
Z! 		}
Z  	return newpgrp;
Z  }
Zdiff -c -r /tmp/cron/compat.h cron/compat.h
Z*** /tmp/cron/compat.h	Fri Jun 18 19:37:52 1999
Z--- cron/compat.h	Tue Jun 15 20:32:58 1999
Z***************
Z*** 20,137 ****
Z   */
Z  
Z  #ifndef __P
Z! # ifdef __STDC__
Z! #  define __P(x) x
Z! # else
Z! #  define __P(x) ()
Z! #  define const
Z! # endif
Z  #endif
Z  
Z- #if defined(UNIXPC) || defined(unixpc)
Z- # define UNIXPC 1
Z- # define ATT 1
Z- #endif
Z- 
Z- #if defined(hpux) || defined(_hpux) || defined(__hpux)
Z- # define HPUX 1
Z- # define seteuid(e) setresuid(-1,e,-1)
Z- # define setreuid(r,e)	setresuid(r,e,-1)
Z- #endif
Z- 
Z- #if defined(_IBMR2)
Z- # define AIX 1
Z- #endif
Z- 
Z- #if defined(__convex__)
Z- # define CONVEX 1
Z- #endif
Z- 
Z- #if defined(sgi) || defined(_sgi) || defined(__sgi)
Z- # define IRIX 1
Z- /* IRIX 4 hdrs are broken: one cannot #include both <stdio.h>
Z-  * and <stdlib.h> because they disagree on system(), perror().
Z-  * Therefore we must zap the "const" keyword BEFORE including
Z-  * either of them.
Z-  */
Z- # define const
Z- #endif
Z- 
Z- #if defined(_UNICOS)
Z- # define UNICOS 1
Z- #endif
Z- 
Z- #ifndef POSIX
Z- # if (BSD >= 199103) || defined(__linux) || defined(ultrix) || defined(AIX) ||\
Z- 	defined(HPUX) || defined(CONVEX) || defined(IRIX)
Z- #  define POSIX
Z- # endif
Z- #endif
Z- 
Z- #ifndef BSD
Z- # if defined(ultrix)
Z- #  define BSD 198902
Z- # endif
Z- #endif
Z- 
Z  /*****************************************************************/
Z  
Z! #if !defined(BSD) && !defined(HPUX) && !defined(CONVEX) && !defined(__linux)
Z! # define NEED_VFORK
Z! #endif
Z! 
Z! #if (!defined(BSD) || (BSD < 198902)) && !defined(__linux) && \
Z! 	!defined(IRIX) && !defined(NeXT) && !defined(HPUX)
Z! # define NEED_STRCASECMP
Z! #endif
Z! 
Z! #if (!defined(BSD) || (BSD < 198911)) && !defined(__linux) &&\
Z! 	!defined(IRIX) && !defined(UNICOS) && !defined(HPUX)
Z! # define NEED_STRDUP
Z! #endif
Z! 
Z! #if (!defined(BSD) || (BSD < 198911)) && !defined(POSIX) && !defined(NeXT)
Z! # define NEED_STRERROR
Z! #endif
Z! 
Z! #if defined(HPUX) || defined(AIX) || defined(UNIXPC)
Z! # define NEED_FLOCK
Z! #endif
Z! 
Z! #ifndef POSIX
Z! # define NEED_SETSID
Z! #endif
Z! 
Z! #if (defined(POSIX) && !defined(BSD)) && !defined(__linux)
Z! # define NEED_GETDTABLESIZE
Z! #endif
Z! 
Z! #if (BSD >= 199103)
Z! # define HAVE_SAVED_UIDS
Z! #endif
Z! 
Z! #if !defined(ATT) && !defined(__linux) && !defined(IRIX) && !defined(UNICOS)
Z! # define USE_SIGCHLD
Z! #endif
Z! 
Z! #if !defined(AIX) && !defined(UNICOS)
Z! # define SYS_TIME_H 1
Z! #else
Z! # define SYS_TIME_H 0
Z! #endif
Z! 
Z! #if defined(BSD) && !defined(POSIX)
Z! # define USE_UTIMES
Z! #endif
Z! 
Z! #if defined(AIX) || defined(HPUX) || defined(IRIX)
Z! # define NEED_SETENV
Z! #endif
Z! 
Z! #if !defined(UNICOS) && !defined(UNIXPC)
Z! # define HAS_FCHOWN
Z! #endif
Z! 
Z! #if !defined(UNICOS) && !defined(UNIXPC)
Z! # define HAS_FCHMOD
Z! #endif
Z--- 20,31 ----
Z   */
Z  
Z  #ifndef __P
Z! #define __P(x) ()
Z! #define const
Z  #endif
Z  
Z  /*****************************************************************/
Z  
Z! #define	WAIT_T	union wait
Z! #define	PID_T	pid_t
Z! #define	TIME_T	time_t
Zdiff -c -r /tmp/cron/cron.c cron/cron.c
Z*** /tmp/cron/cron.c	Fri Jun 18 19:37:52 1999
Z--- cron/cron.c	Tue Jun 15 21:11:15 1999
Z***************
Z*** 25,45 ****
Z  
Z  #include "cron.h"
Z  #include <sys/signal.h>
Z! #if SYS_TIME_H
Z! # include <sys/time.h>
Z! #else
Z! # include <time.h>
Z! #endif
Z  
Z- 
Z  static	void	usage __P((void)),
Z  		run_reboot_jobs __P((cron_db *)),
Z  		cron_tick __P((cron_db *)),
Z  		cron_sync __P((void)),
Z  		cron_sleep __P((void)),
Z- #ifdef USE_SIGCHLD
Z  		sigchld_handler __P((int)),
Z- #endif
Z  		sighup_handler __P((int)),
Z  		parse_args __P((int c, char *v[]));
Z  
Z--- 25,38 ----
Z  
Z  #include "cron.h"
Z  #include <sys/signal.h>
Z! #include <sys/time.h>
Z  
Z  static	void	usage __P((void)),
Z  		run_reboot_jobs __P((cron_db *)),
Z  		cron_tick __P((cron_db *)),
Z  		cron_sync __P((void)),
Z  		cron_sleep __P((void)),
Z  		sigchld_handler __P((int)),
Z  		sighup_handler __P((int)),
Z  		parse_args __P((int c, char *v[]));
Z  
Z***************
Z*** 60,77 ****
Z  
Z  	ProgramName = argv[0];
Z  
Z- #if defined(BSD)
Z  	setlinebuf(stdout);
Z  	setlinebuf(stderr);
Z- #endif
Z  
Z  	parse_args(argc, argv);
Z  
Z- #ifdef USE_SIGCHLD
Z  	(void) signal(SIGCHLD, sigchld_handler);
Z- #else
Z- 	(void) signal(SIGCLD, SIG_IGN);
Z- #endif
Z  	(void) signal(SIGHUP, sighup_handler);
Z  
Z  	acquire_daemonlock(0);
Z--- 53,64 ----
Z***************
Z*** 78,86 ****
Z  	set_cron_uid();
Z  	set_cron_cwd();
Z  
Z- #if defined(POSIX)
Z  	setenv("PATH", _PATH_DEFPATH, 1);
Z- #endif
Z  
Z  	/* if there are no debug flags turned on, fork as a daemon should.
Z  	 */
Z--- 65,71 ----
Z***************
Z*** 244,250 ****
Z  }
Z  
Z  
Z- #ifdef USE_SIGCHLD
Z  static void
Z  sigchld_handler(x) {
Z  	WAIT_T		waiter;
Z--- 229,234 ----
Z***************
Z*** 251,261 ****
Z  	PID_T		pid;
Z  
Z  	for (;;) {
Z- #ifdef POSIX
Z  		pid = waitpid(-1, &waiter, WNOHANG);
Z- #else
Z- 		pid = wait3(&waiter, WNOHANG, (struct rusage *)0);
Z- #endif
Z  		switch (pid) {
Z  		case -1:
Z  			Debug(DPROC,
Z--- 235,241 ----
Z***************
Z*** 272,279 ****
Z  		}
Z  	}
Z  }
Z- #endif /*USE_SIGCHLD*/
Z- 
Z  
Z  static void
Z  sighup_handler(x) {
Z--- 252,257 ----
Zdiff -c -r /tmp/cron/cron.h cron/cron.h
Z*** /tmp/cron/cron.h	Fri Jun 18 19:37:52 1999
Z--- cron/cron.h	Tue Jun 15 20:31:36 1999
Z***************
Z*** 112,119 ****
Z  			;
Z  #endif /* DEBUGGING */
Z  
Z- #define	MkLower(ch)	(isupper(ch) ? tolower(ch) : ch)
Z- #define	MkUpper(ch)	(islower(ch) ? toupper(ch) : ch)
Z  #define	Set_LineNum(ln)	{Debug(DPARS|DEXT,("linenum=%d\n",ln)); \
Z  			 LineNumber = ln; \
Z  			}
Z--- 112,117 ----
Zdiff -c -r /tmp/cron/crontab.c cron/crontab.c
Z*** /tmp/cron/crontab.c	Fri Jun 18 19:48:38 1999
Z--- cron/crontab.c	Tue Jun 15 21:11:42 1999
Z***************
Z*** 33,52 ****
Z  #include <fcntl.h>
Z  #include <sys/file.h>
Z  #include <sys/stat.h>
Z! #ifdef USE_UTIMES
Z! # include <sys/time.h>
Z! #else
Z! # include <time.h>
Z! # include <utime.h>
Z! #endif
Z! #if defined(POSIX)
Z! # include <locale.h>
Z! #endif
Z  
Z- 
Z  #define NHEADER_LINES 3
Z  
Z- 
Z  enum opt_t	{ opt_unknown, opt_list, opt_delete, opt_edit, opt_replace };
Z  
Z  #if DEBUGGING
Z--- 33,42 ----
Z  #include <fcntl.h>
Z  #include <sys/file.h>
Z  #include <sys/stat.h>
Z! #include <sys/time.h>
Z  
Z  #define NHEADER_LINES 3
Z  
Z  enum opt_t	{ opt_unknown, opt_list, opt_delete, opt_edit, opt_replace };
Z  
Z  #if DEBUGGING
Z***************
Z*** 95,107 ****
Z  	Pid = getpid();
Z  	ProgramName = argv[0];
Z  
Z- #if defined(POSIX)
Z- 	setlocale(LC_ALL, "");
Z- #endif
Z- 
Z- #if defined(BSD)
Z  	setlinebuf(stderr);
Z! #endif
Z  	parse_args(argc, argv);		/* sets many globals, opens a file */
Z  	set_cron_uid();
Z  	set_cron_cwd();
Z--- 85,92 ----
Z  	Pid = getpid();
Z  	ProgramName = argv[0];
Z  
Z  	setlinebuf(stderr);
Z! 
Z  	parse_args(argc, argv);		/* sets many globals, opens a file */
Z  	set_cron_uid();
Z  	set_cron_cwd();
Z***************
Z*** 242,248 ****
Z  static void
Z  list_cmd() {
Z  	char	n[MAX_FNAME];
Z! 	FILE	*f;
Z  	int	ch;
Z  
Z  	log_it(RealUser, Pid, "LIST", User);
Z--- 227,233 ----
Z  static void
Z  list_cmd() {
Z  	char	n[MAX_FNAME];
Z! 	register FILE	*f;
Z  	int	ch;
Z  
Z  	log_it(RealUser, Pid, "LIST", User);
Z***************
Z*** 293,300 ****
Z  static void
Z  edit_cmd() {
Z  	char		n[MAX_FNAME], q[MAX_TEMPSTR], *editor;
Z! 	FILE		*f;
Z! 	int		ch, t, x;
Z  	struct stat	statbuf;
Z  	time_t		mtime;
Z  	WAIT_T		waiter;
Z--- 278,286 ----
Z  static void
Z  edit_cmd() {
Z  	char		n[MAX_FNAME], q[MAX_TEMPSTR], *editor;
Z! 	register FILE	*f;
Z! 	register int	ch;
Z! 	int		t, x;
Z  	struct stat	statbuf;
Z  	time_t		mtime;
Z  	WAIT_T		waiter;
Z***************
Z*** 320,330 ****
Z  		perror(Filename);
Z  		goto fatal;
Z  	}
Z- #ifdef HAS_FCHOWN
Z  	if (fchown(t, getuid(), getgid()) < 0) {
Z- #else
Z- 	if (chown(Filename, getuid(), getgid()) < 0) {
Z- #endif
Z  		perror("fchown");
Z  		goto fatal;
Z  	}
Z--- 306,312 ----
Z***************
Z*** 490,497 ****
Z  static int
Z  replace_cmd() {
Z  	char	n[MAX_FNAME], envstr[MAX_ENVSTR], tn[MAX_FNAME];
Z! 	FILE	*tmp;
Z! 	int	ch, eof;
Z  	entry	*e;
Z  	time_t	now = time(NULL);
Z  	char	**envp = env_init();
Z--- 472,480 ----
Z  static int
Z  replace_cmd() {
Z  	char	n[MAX_FNAME], envstr[MAX_ENVSTR], tn[MAX_FNAME];
Z! 	register FILE	*tmp;
Z! 	register int	ch;
Z! 	int	eof;
Z  	entry	*e;
Z  	time_t	now = time(NULL);
Z  	char	**envp = env_init();
Z***************
Z*** 557,583 ****
Z  		return (-1);
Z  	}
Z  
Z- #ifdef HAS_FCHOWN
Z  	if (fchown(fileno(tmp), ROOT_UID, -1) < OK)
Z! #else
Z! 	if (chown(tn, ROOT_UID, -1) < OK)
Z! #endif
Z! 	{
Z  		perror("chown");
Z  		fclose(tmp);  unlink(tn);
Z  		return (-2);
Z! 	}
Z  
Z- #ifdef HAS_FCHMOD
Z  	if (fchmod(fileno(tmp), 0600) < OK)
Z! #else
Z! 	if (chmod(tn, 0600) < OK)
Z! #endif
Z! 	{
Z  		perror("chown");
Z  		fclose(tmp);  unlink(tn);
Z  		return (-2);
Z! 	}
Z  
Z  	if (fclose(tmp) == EOF) {
Z  		perror("fclose");
Z--- 540,558 ----
Z  		return (-1);
Z  	}
Z  
Z  	if (fchown(fileno(tmp), ROOT_UID, -1) < OK)
Z! 		{
Z  		perror("chown");
Z  		fclose(tmp);  unlink(tn);
Z  		return (-2);
Z! 		}
Z  
Z  	if (fchmod(fileno(tmp), 0600) < OK)
Z! 		{
Z  		perror("chown");
Z  		fclose(tmp);  unlink(tn);
Z  		return (-2);
Z! 		}
Z  
Z  	if (fclose(tmp) == EOF) {
Z  		perror("fclose");
Z***************
Z*** 603,613 ****
Z  
Z  static void
Z  poke_daemon() {
Z- #ifdef USE_UTIMES
Z  	struct timeval tvs[2];
Z- 	struct timezone tz;
Z  
Z! 	(void) gettimeofday(&tvs[0], &tz);
Z  	tvs[1] = tvs[0];
Z  	if (utimes(SPOOL_DIR, tvs) < OK) {
Z  		fprintf(stderr, "crontab: can't update mtime on spooldir\n");
Z--- 578,586 ----
Z  
Z  static void
Z  poke_daemon() {
Z  	struct timeval tvs[2];
Z  
Z! 	(void) gettimeofday(&tvs[0], NULL);
Z  	tvs[1] = tvs[0];
Z  	if (utimes(SPOOL_DIR, tvs) < OK) {
Z  		fprintf(stderr, "crontab: can't update mtime on spooldir\n");
Z***************
Z*** 614,624 ****
Z  		perror(SPOOL_DIR);
Z  		return;
Z  	}
Z- #else
Z- 	if (utime(SPOOL_DIR, NULL) < OK) {
Z- 		fprintf(stderr, "crontab: can't update mtime on spooldir\n");
Z- 		perror(SPOOL_DIR);
Z- 		return;
Z- 	}
Z- #endif /*USE_UTIMES*/
Z  }
Z--- 587,590 ----
Zdiff -c -r /tmp/cron/database.c cron/database.c
Z*** /tmp/cron/database.c	Fri Jun 18 19:37:52 1999
Z--- cron/database.c	Sat Jun 12 16:04:08 1999
Z***************
Z*** 44,50 ****
Z  	DIR		*dir;
Z  	struct stat	statbuf;
Z  	struct stat	syscron_stat;
Z! 	DIR_T   	*dp;
Z  	cron_db		new_db;
Z  	user		*u, *nu;
Z  
Z--- 44,50 ----
Z  	DIR		*dir;
Z  	struct stat	statbuf;
Z  	struct stat	syscron_stat;
Z! 	register DIR_T   *dp;
Z  	cron_db		new_db;
Z  	user		*u, *nu;
Z  
Z***************
Z*** 145,152 ****
Z  
Z  void
Z  link_user(db, u)
Z! 	cron_db	*db;
Z! 	user	*u;
Z  {
Z  	if (db->head == NULL)
Z  		db->head = u;
Z--- 145,152 ----
Z  
Z  void
Z  link_user(db, u)
Z! 	register cron_db	*db;
Z! 	register user	*u;
Z  {
Z  	if (db->head == NULL)
Z  		db->head = u;
Z***************
Z*** 160,167 ****
Z  
Z  void
Z  unlink_user(db, u)
Z! 	cron_db	*db;
Z! 	user	*u;
Z  {
Z  	if (u->prev == NULL)
Z  		db->head = u->next;
Z--- 160,167 ----
Z  
Z  void
Z  unlink_user(db, u)
Z! 	register cron_db	*db;
Z! 	register user	*u;
Z  {
Z  	if (u->prev == NULL)
Z  		db->head = u->next;
Z***************
Z*** 178,187 ****
Z  user *
Z  find_user(db, name)
Z  	cron_db	*db;
Z! 	char	*name;
Z  {
Z  	char	*env_get();
Z! 	user	*u;
Z  
Z  	for (u = db->head;  u != NULL;  u = u->next)
Z  		if (!strcmp(u->name, name))
Z--- 178,187 ----
Z  user *
Z  find_user(db, name)
Z  	cron_db	*db;
Z! 	register char	*name;
Z  {
Z  	char	*env_get();
Z! 	register user	*u;
Z  
Z  	for (u = db->head;  u != NULL;  u = u->next)
Z  		if (!strcmp(u->name, name))
Z***************
Z*** 201,207 ****
Z  {
Z  	struct passwd	*pw = NULL;
Z  	int		crontab_fd = OK - 1;
Z! 	user		*u;
Z  
Z  	if (strcmp(fname, "*system*") && !(pw = getpwnam(uname))) {
Z  		/* file doesn't have a user in passwd file.
Z--- 201,207 ----
Z  {
Z  	struct passwd	*pw = NULL;
Z  	int		crontab_fd = OK - 1;
Z! 	register user		*u;
Z  
Z  	if (strcmp(fname, "*system*") && !(pw = getpwnam(uname))) {
Z  		/* file doesn't have a user in passwd file.
Zdiff -c -r /tmp/cron/do_command.c cron/do_command.c
Z*** /tmp/cron/do_command.c	Fri Jun 18 19:37:56 1999
Z--- cron/do_command.c	Tue Jun 15 21:24:29 1999
Z***************
Z*** 19,39 ****
Z  static char rcsid[] = "$Id: do_command.c,v 2.12 1994/01/15 20:43:43 vixie Exp $";
Z  #endif
Z  
Z- 
Z  #include "cron.h"
Z  #include <sys/signal.h>
Z- #if defined(sequent)
Z- # include <sys/universe.h>
Z- #endif
Z  #if defined(SYSLOG)
Z  # include <syslog.h>
Z  #endif
Z  
Z  
Z- static void		child_process __P((entry *, user *)),
Z- 			do_univ __P((user *));
Z- 
Z- 
Z  void
Z  do_command(e, u)
Z  	entry	*e;
Z--- 19,32 ----
Z  static char rcsid[] = "$Id: do_command.c,v 2.12 1994/01/15 20:43:43 vixie Exp $";
Z  #endif
Z  
Z  #include "cron.h"
Z  #include <sys/signal.h>
Z  #if defined(SYSLOG)
Z  # include <syslog.h>
Z  #endif
Z  
Z+ static void		child_process __P((entry *, user *));
Z  
Z  void
Z  do_command(e, u)
Z  	entry	*e;
Z***************
Z*** 76,82 ****
Z  	int		stdin_pipe[2], stdout_pipe[2];
Z  	register char	*input_data;
Z  	char		*usernm, *mailto;
Z! 	int		children = 0;
Z  
Z  	Debug(DPROC, ("[%d] child_process('%s')\n", getpid(), e->cmd))
Z  
Z--- 69,76 ----
Z  	int		stdin_pipe[2], stdout_pipe[2];
Z  	register char	*input_data;
Z  	char		*usernm, *mailto;
Z! 	register int ch;
Z! 	int		children = 0, escaped;
Z  
Z  	Debug(DPROC, ("[%d] child_process('%s')\n", getpid(), e->cmd))
Z  
Z***************
Z*** 83,101 ****
Z  	/* mark ourselves as different to PS command watchers by upshifting
Z  	 * our program name.  This has no effect on some kernels.
Z  	 */
Z! 	/*local*/{
Z! 		register char	*pch;
Z  
Z- 		for (pch = ProgramName;  *pch;  pch++)
Z- 			*pch = MkUpper(*pch);
Z- 	}
Z- 
Z  	/* discover some useful and important environment settings
Z  	 */
Z  	usernm = env_get("LOGNAME", e->envp);
Z  	mailto = env_get("MAILTO", e->envp);
Z  
Z- #ifdef USE_SIGCHLD
Z  	/* our parent is watching for our death by catching SIGCHLD.  we
Z  	 * do not care to watch for our children's deaths this way -- we
Z  	 * use wait() explictly.  so we have to disable the signal (which
Z--- 77,90 ----
Z  	/* mark ourselves as different to PS command watchers by upshifting
Z  	 * our program name.  This has no effect on some kernels.
Z  	 */
Z! 	for (input_data = ProgramName;  ch = *input_data;  input_data++)
Z! 		*input_data = (islower(ch) ? toupper(ch) : ch);
Z  
Z  	/* discover some useful and important environment settings
Z  	 */
Z  	usernm = env_get("LOGNAME", e->envp);
Z  	mailto = env_get("MAILTO", e->envp);
Z  
Z  	/* our parent is watching for our death by catching SIGCHLD.  we
Z  	 * do not care to watch for our children's deaths this way -- we
Z  	 * use wait() explictly.  so we have to disable the signal (which
Z***************
Z*** 102,114 ****
Z  	 * was inherited from the parent).
Z  	 */
Z  	(void) signal(SIGCHLD, SIG_IGN);
Z- #else
Z- 	/* on system-V systems, we are ignoring SIGCLD.  we have to stop
Z- 	 * ignoring it now or the wait() in cron_pclose() won't work.
Z- 	 * because of this, we have to wait() for our children here, as well.
Z- 	 */
Z- 	(void) signal(SIGCLD, SIG_DFL);
Z- #endif /*BSD*/
Z  
Z  	/* create some pipes to talk to our future child
Z  	 */
Z--- 91,96 ----
Z***************
Z*** 123,146 ****
Z  	 * the command.  Subsequent %'s will be transformed into newlines,
Z  	 * but that happens later.
Z  	 */
Z! 	/*local*/{
Z! 		register int escaped = FALSE;
Z! 		register int ch;
Z! 
Z! 		for (input_data = e->cmd;  ch = *input_data;  input_data++) {
Z! 			if (escaped) {
Z! 				escaped = FALSE;
Z! 				continue;
Z! 			}
Z! 			if (ch == '\\') {
Z! 				escaped = TRUE;
Z! 				continue;
Z! 			}
Z! 			if (ch == '%') {
Z! 				*input_data++ = '\0';
Z! 				break;
Z! 			}
Z  		}
Z  	}
Z  
Z  	/* fork again, this time so we can exec the user's command.
Z--- 105,124 ----
Z  	 * the command.  Subsequent %'s will be transformed into newlines,
Z  	 * but that happens later.
Z  	 */
Z! 	escaped = FALSE;
Z! 	for (input_data = e->cmd;  ch = *input_data;  input_data++) {
Z! 		if (escaped) {
Z! 			escaped = FALSE;
Z! 			continue;
Z  		}
Z+ 		if (ch == '\\') {
Z+ 			escaped = TRUE;
Z+ 			continue;
Z+ 		}
Z+ 		if (ch == '%') {
Z+ 			*input_data++ = '\0';
Z+ 			break;
Z+ 		}
Z  	}
Z  
Z  	/* fork again, this time so we can exec the user's command.
Z***************
Z*** 197,215 ****
Z  		close(stdin_pipe[READ_PIPE]);
Z  		close(stdout_pipe[WRITE_PIPE]);
Z  
Z- 		/* set our login universe.  Do this in the grandchild
Z- 		 * so that the child can invoke /usr/lib/sendmail
Z- 		 * without surprises.
Z- 		 */
Z- 		do_univ(u);
Z- 
Z  		/* set our directory, uid and gid.  Set gid first, since once
Z  		 * we set uid, we've lost root privledges.
Z  		 */
Z  		setgid(e->gid);
Z- # if defined(BSD)
Z  		initgroups(env_get("LOGNAME", e->envp), e->gid);
Z- # endif
Z  		setuid(e->uid);		/* we aren't root after this... */
Z  		chdir(env_get("HOME", e->envp));
Z  
Z--- 175,185 ----
Z***************
Z*** 460,501 ****
Z  			Debug(DPROC, (", dumped core"))
Z  		Debug(DPROC, ("\n"))
Z  	}
Z- }
Z- 
Z- 
Z- static void
Z- do_univ(u)
Z- 	user	*u;
Z- {
Z- #if defined(sequent)
Z- /* Dynix (Sequent) hack to put the user associated with
Z-  * the passed user structure into the ATT universe if
Z-  * necessary.  We have to dig the gecos info out of
Z-  * the user's password entry to see if the magic
Z-  * "universe(att)" string is present.
Z-  */
Z- 
Z- 	struct	passwd	*p;
Z- 	char	*s;
Z- 	int	i;
Z- 
Z- 	p = getpwuid(u->uid);
Z- 	(void) endpwent();
Z- 
Z- 	if (p == NULL)
Z- 		return;
Z- 
Z- 	s = p->pw_gecos;
Z- 
Z- 	for (i = 0; i < 4; i++)
Z- 	{
Z- 		if ((s = strchr(s, ',')) == NULL)
Z- 			return;
Z- 		s++;
Z- 	}
Z- 	if (strcmp(s, "universe(att)"))
Z- 		return;
Z- 
Z- 	(void) universe(U_ATT);
Z- #endif
Z  }
Z--- 430,433 ----
Zdiff -c -r /tmp/cron/entry.c cron/entry.c
Z*** /tmp/cron/entry.c	Fri Jun 18 19:37:56 1999
Z--- cron/entry.c	Tue Jun 15 21:11:55 1999
Z***************
Z*** 55,61 ****
Z  
Z  void
Z  free_entry(e)
Z! 	entry	*e;
Z  {
Z  	free(e->cmd);
Z  	env_free(e->envp);
Z--- 55,61 ----
Z  
Z  void
Z  free_entry(e)
Z! 	register entry	*e;
Z  {
Z  	free(e->cmd);
Z  	env_free(e->envp);
Z***************
Z*** 70,76 ****
Z  load_entry(file, error_func, pw, envp)
Z  	FILE		*file;
Z  	void		(*error_func)();
Z! 	struct passwd	*pw;
Z  	char		**envp;
Z  {
Z  	/* this function reads one crontab entry -- the next -- from a file.
Z--- 70,76 ----
Z  load_entry(file, error_func, pw, envp)
Z  	FILE		*file;
Z  	void		(*error_func)();
Z! 	register struct passwd	*pw;
Z  	char		**envp;
Z  {
Z  	/* this function reads one crontab entry -- the next -- from a file.
Z***************
Z*** 87,93 ****
Z  	 */
Z  
Z  	ecode_e	ecode = e_none;
Z! 	entry	*e;
Z  	int	ch;
Z  	char	cmd[MAX_COMMAND];
Z  	char	envstr[MAX_ENVSTR];
Z--- 87,93 ----
Z  	 */
Z  
Z  	ecode_e	ecode = e_none;
Z! 	register entry	*e;
Z  	int	ch;
Z  	char	cmd[MAX_COMMAND];
Z  	char	envstr[MAX_ENVSTR];
Z***************
Z*** 262,271 ****
Z  	}
Z  	sprintf(envstr, "%s=%s", "LOGNAME", pw->pw_name);
Z  	e->envp = env_set(e->envp, envstr);
Z- #if defined(BSD)
Z  	sprintf(envstr, "%s=%s", "USER", pw->pw_name);
Z  	e->envp = env_set(e->envp, envstr);
Z- #endif
Z  
Z  	Debug(DPARS, ("load_entry()...about to parse command\n"))
Z  
Z--- 262,269 ----
Z***************
Z*** 309,315 ****
Z  	int		low, high;	/* bounds, impl. offset for bitstr */
Z  	char		*names[];	/* NULL or *[] of names for these elements */
Z  	int		ch;		/* current character being processed */
Z! 	FILE		*file;		/* file being read */
Z  {
Z  	register int	done;
Z  
Z--- 307,313 ----
Z  	int		low, high;	/* bounds, impl. offset for bitstr */
Z  	char		*names[];	/* NULL or *[] of names for these elements */
Z  	int		ch;		/* current character being processed */
Z! 	register FILE		*file;		/* file being read */
Z  {
Z  	register int	done;
Z  
Z***************
Z*** 355,361 ****
Z  	bitstr_t	*bits;		/* one bit per flag, default=FALSE */
Z  	int		low, high;	/* bounds, impl. offset for bitstr */
Z  	char		*names[];	/* NULL or names of elements */
Z! 	int		ch;		/* current character being processed */
Z  	FILE		*file;		/* file being read */
Z  {
Z  	/* range = number | number "-" number [ "/" number ]
Z--- 353,359 ----
Z  	bitstr_t	*bits;		/* one bit per flag, default=FALSE */
Z  	int		low, high;	/* bounds, impl. offset for bitstr */
Z  	char		*names[];	/* NULL or names of elements */
Z! 	register int	ch;		/* current character being processed */
Z  	FILE		*file;		/* file being read */
Z  {
Z  	/* range = number | number "-" number [ "/" number ]
Z***************
Z*** 440,446 ****
Z  	int	*numptr;	/* where does the result go? */
Z  	int	low;		/* offset applied to result if symbolic enum used */
Z  	char	*names[];	/* symbolic names, if any, for enums */
Z! 	int	ch;		/* current character */
Z  	FILE	*file;		/* source */
Z  {
Z  	char	temp[MAX_TEMPSTR], *pc;
Z--- 438,444 ----
Z  	int	*numptr;	/* where does the result go? */
Z  	int	low;		/* offset applied to result if symbolic enum used */
Z  	char	*names[];	/* symbolic names, if any, for enums */
Z! 	register int	ch;	/* current character */
Z  	FILE	*file;		/* source */
Z  {
Z  	char	temp[MAX_TEMPSTR], *pc;
Zdiff -c -r /tmp/cron/env.c cron/env.c
Z*** /tmp/cron/env.c	Fri Jun 18 19:48:38 1999
Z--- cron/env.c	Sat Jun 12 16:11:43 1999
Z***************
Z*** 37,43 ****
Z  env_free(envp)
Z  	char	**envp;
Z  {
Z! 	char	**p;
Z  
Z  	for (p = envp;  *p;  p++)
Z  		free(*p);
Z--- 37,43 ----
Z  env_free(envp)
Z  	char	**envp;
Z  {
Z! 	register char	**p;
Z  
Z  	for (p = envp;  *p;  p++)
Z  		free(*p);
Z***************
Z*** 47,53 ****
Z  
Z  char **
Z  env_copy(envp)
Z! 	register char	**envp;
Z  {
Z  	register int	count, i;
Z  	register char	**p;
Z--- 47,53 ----
Z  
Z  char **
Z  env_copy(envp)
Z! 	char	**envp;
Z  {
Z  	register int	count, i;
Z  	register char	**p;
Z***************
Z*** 162,169 ****
Z  
Z  char *
Z  env_get(name, envp)
Z! 	register char	*name;
Z! 	register char	**envp;
Z  {
Z  	register int	len = strlen(name);
Z  	register char	*p, *q;
Z--- 162,169 ----
Z  
Z  char *
Z  env_get(name, envp)
Z! 	char	*name;
Z! 	char	**envp;
Z  {
Z  	register int	len = strlen(name);
Z  	register char	*p, *q;
Zdiff -c -r /tmp/cron/externs.h cron/externs.h
Z*** /tmp/cron/externs.h	Fri Jun 18 19:37:52 1999
Z--- cron/externs.h	Tue Jun 15 20:32:34 1999
Z***************
Z*** 15,145 ****
Z   * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
Z   */
Z  
Z! #if defined(POSIX) || defined(ATT)
Z! # include <stdlib.h>
Z! # include <unistd.h>
Z! # include <string.h>
Z! # include <dirent.h>
Z! # define DIR_T	struct dirent
Z! # define WAIT_T	int
Z! # define WAIT_IS_INT 1
Z! extern char *tzname[2];
Z! # define TZONE(tm) tzname[(tm).tm_isdst]
Z! #endif
Z  
Z! #if defined(UNIXPC)
Z! # undef WAIT_T
Z! # undef WAIT_IS_INT
Z! # define WAIT_T	union wait
Z! #endif
Z  
Z- #if defined(POSIX)
Z- # define SIG_T	sig_t
Z- # define TIME_T	time_t
Z- # define PID_T pid_t
Z- #endif
Z- 
Z- #if defined(ATT)
Z- # define SIG_T	void
Z- # define TIME_T	long
Z- # define PID_T int
Z- #endif
Z- 
Z- #if !defined(POSIX) && !defined(ATT)
Z- /* classic BSD */
Z- extern	time_t		time();
Z- extern	unsigned	sleep();
Z- extern	struct tm	*localtime();
Z- extern	struct passwd	*getpwnam();
Z- extern	int		errno;
Z- extern	void		perror(), exit(), free();
Z- extern	char		*getenv(), *strcpy(), *strchr(), *strtok();
Z- extern	void		*malloc(), *realloc();
Z- # define SIG_T	void
Z- # define TIME_T	long
Z- # define PID_T int
Z- # define WAIT_T	union wait
Z- # define DIR_T	struct direct
Z- # include <sys/dir.h>
Z- # define TZONE(tm) (tm).tm_zone
Z- #endif
Z- 
Z- /* getopt() isn't part of POSIX.  some systems define it in <stdlib.h> anyway.
Z-  * of those that do, some complain that our definition is different and some
Z-  * do not.  to add to the misery and confusion, some systems define getopt()
Z-  * in ways that we cannot predict or comprehend, yet do not define the adjunct
Z-  * external variables needed for the interface.
Z-  */
Z- #if (!defined(BSD) || (BSD < 198911)) && !defined(ATT) && !defined(UNICOS)
Z- int	getopt __P((int, char * const *, const char *));
Z- #endif
Z- 
Z- #if (!defined(BSD) || (BSD < 199103))
Z- extern	char *optarg;
Z- extern	int optind, opterr, optopt;
Z- #endif
Z- 
Z- #if WAIT_IS_INT
Z- # ifndef WEXITSTATUS
Z- #  define WEXITSTATUS(x) (((x) >> 8) & 0xff)
Z- # endif
Z- # ifndef WTERMSIG
Z- #  define WTERMSIG(x)	((x) & 0x7f)
Z- # endif
Z- # ifndef WCOREDUMP
Z- #  define WCOREDUMP(x)	((x) & 0x80)
Z- # endif
Z- #else /*WAIT_IS_INT*/
Z- # ifndef WEXITSTATUS
Z- #  define WEXITSTATUS(x) ((x).w_retcode)
Z- # endif
Z- # ifndef WTERMSIG
Z- #  define WTERMSIG(x)	((x).w_termsig)
Z- # endif
Z- # ifndef WCOREDUMP
Z- #  define WCOREDUMP(x)	((x).w_coredump)
Z- # endif
Z- #endif /*WAIT_IS_INT*/
Z- 
Z- #ifndef WIFSIGNALED
Z- #define WIFSIGNALED(x)	(WTERMSIG(x) != 0)
Z- #endif
Z- #ifndef WIFEXITED
Z- #define WIFEXITED(x)	(WTERMSIG(x) == 0)
Z- #endif
Z- 
Z- #ifdef NEED_STRCASECMP
Z- extern	int		strcasecmp __P((char *, char *));
Z- #endif
Z- 
Z- #ifdef NEED_STRDUP
Z- extern	char		*strdup __P((char *));
Z- #endif
Z- 
Z- #ifdef NEED_STRERROR
Z- extern	char		*strerror __P((int));
Z- #endif
Z- 
Z- #ifdef NEED_FLOCK
Z- extern	int		flock __P((int, int));
Z- # define LOCK_SH 1
Z- # define LOCK_EX 2
Z- # define LOCK_NB 4
Z- # define LOCK_UN 8
Z- #endif
Z- 
Z- #ifdef NEED_SETSID
Z  extern	int		setsid __P((void));
Z- #endif
Z- 
Z- #ifdef NEED_GETDTABLESIZE
Z- extern	int		getdtablesize __P((void));
Z- #endif
Z- 
Z- #ifdef NEED_SETENV
Z- extern	int		setenv __P((char *, char *, int));
Z- #endif
Z- 
Z- #ifdef NEED_VFORK
Z- extern	PID_T		vfork __P((void));
Z- #endif
Z--- 15,28 ----
Z   * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
Z   */
Z  
Z! #include <stdlib.h>
Z! #include <unistd.h>
Z! #include <string.h>
Z! #include <sys/dir.h>
Z  
Z! #define DIR_T struct direct
Z! #define	WEXITSTATUS(x)	((x).w_retcode)
Z! #define	WTERMSIG(x)	((x).w_termsig)
Z! #define	WCOREDUMP(x)	((x).w_coredump)
Z  
Z  extern	int		setsid __P((void));
Zdiff -c -r /tmp/cron/misc.c cron/misc.c
Z*** /tmp/cron/misc.c	Fri Jun 18 19:37:56 1999
Z--- cron/misc.c	Fri Jun 18 20:55:14 1999
Z***************
Z*** 25,35 ****
Z  
Z  
Z  #include "cron.h"
Z! #if SYS_TIME_H
Z! # include <sys/time.h>
Z! #else
Z! # include <time.h>
Z! #endif
Z  #include <sys/file.h>
Z  #include <sys/stat.h>
Z  #include <errno.h>
Z--- 25,31 ----
Z  
Z  
Z  #include "cron.h"
Z! #include <sys/time.h>
Z  #include <sys/file.h>
Z  #include <sys/stat.h>
Z  #include <errno.h>
Z***************
Z*** 44,57 ****
Z  #define LOG_CRON LOG_DAEMON
Z  #endif
Z  
Z- 
Z  static int		LogFD = ERR;
Z  
Z- 
Z  int
Z  strcmp_until(left, right, until)
Z! 	char	*left;
Z! 	char	*right;
Z  	int	until;
Z  {
Z  	register int	diff;
Z--- 40,51 ----
Z  #define LOG_CRON LOG_DAEMON
Z  #endif
Z  
Z  static int		LogFD = ERR;
Z  
Z  int
Z  strcmp_until(left, right, until)
Z! 	register char	*left;
Z! 	register char	*right;
Z  	int	until;
Z  {
Z  	register int	diff;
Z***************
Z*** 76,84 ****
Z   */
Z  int
Z  strdtb(s)
Z! 	char	*s;
Z  {
Z! 	char	*x = s;
Z  
Z  	/* scan forward to the null
Z  	 */
Z--- 70,78 ----
Z   */
Z  int
Z  strdtb(s)
Z! 	register char	*s;
Z  {
Z! 	register char	*x = s;
Z  
Z  	/* scan forward to the null
Z  	 */
Z***************
Z*** 120,126 ****
Z  
Z  #else /* DEBUGGING */
Z  
Z! 	char	*pc = flags;
Z  
Z  	DebugFlags = 0;
Z  
Z--- 114,120 ----
Z  
Z  #else /* DEBUGGING */
Z  
Z! 	register char	*pc = flags;
Z  
Z  	DebugFlags = 0;
Z  
Z***************
Z*** 173,189 ****
Z  void
Z  set_cron_uid()
Z  {
Z- #if defined(BSD) || defined(POSIX)
Z  	if (seteuid(ROOT_UID) < OK) {
Z  		perror("seteuid");
Z  		exit(ERROR_EXIT);
Z  	}
Z- #else
Z- 	if (setuid(ROOT_UID) < OK) {
Z- 		perror("setuid");
Z- 		exit(ERROR_EXIT);
Z- 	}
Z- #endif
Z  }
Z  
Z  
Z--- 167,176 ----
Z***************
Z*** 302,310 ****
Z   */
Z  int
Z  get_char(file)
Z! 	FILE	*file;
Z  {
Z! 	int	ch;
Z  
Z  	ch = getc(file);
Z  	if (ch == '\n')
Z--- 289,297 ----
Z   */
Z  int
Z  get_char(file)
Z! 	register FILE	*file;
Z  {
Z! 	register int	ch;
Z  
Z  	ch = getc(file);
Z  	if (ch == '\n')
Z***************
Z*** 317,324 ****
Z   */
Z  void
Z  unget_char(ch, file)
Z! 	int	ch;
Z! 	FILE	*file;
Z  {
Z  	ungetc(ch, file);
Z  	if (ch == '\n')
Z--- 304,311 ----
Z   */
Z  void
Z  unget_char(ch, file)
Z! 	register int	ch;
Z! 	register FILE	*file;
Z  {
Z  	ungetc(ch, file);
Z  	if (ch == '\n')
Z***************
Z*** 334,345 ****
Z   */
Z  int
Z  get_string(string, size, file, terms)
Z! 	char	*string;
Z  	int	size;
Z  	FILE	*file;
Z  	char	*terms;
Z  {
Z! 	int	ch;
Z  
Z  	while (EOF != (ch = get_char(file)) && !strchr(terms, ch)) {
Z  		if (size > 1) {
Z--- 321,332 ----
Z   */
Z  int
Z  get_string(string, size, file, terms)
Z! 	register char	*string;
Z  	int	size;
Z  	FILE	*file;
Z  	char	*terms;
Z  {
Z! 	register int	ch;
Z  
Z  	while (EOF != (ch = get_char(file)) && !strchr(terms, ch)) {
Z  		if (size > 1) {
Z***************
Z*** 359,367 ****
Z   */
Z  void
Z  skip_comments(file)
Z! 	FILE	*file;
Z  {
Z! 	int	ch;
Z  
Z  	while (EOF != (ch = get_char(file))) {
Z  		/* ch is now the first character of a line.
Z--- 346,354 ----
Z   */
Z  void
Z  skip_comments(file)
Z! 	register FILE	*file;
Z  {
Z! 	register int	ch;
Z  
Z  	while (EOF != (ch = get_char(file))) {
Z  		/* ch is now the first character of a line.
Z***************
Z*** 475,481 ****
Z  #if defined(LOG_FILE)
Z  	/* we assume that MAX_TEMPSTR will hold the date, time, &punctuation.
Z  	 */
Z! 	msg = malloc(strlen(username)
Z  		     + strlen(event)
Z  		     + strlen(detail)
Z  		     + MAX_TEMPSTR);
Z--- 462,468 ----
Z  #if defined(LOG_FILE)
Z  	/* we assume that MAX_TEMPSTR will hold the date, time, &punctuation.
Z  	 */
Z! 	msg = (char *)malloc(strlen(username)
Z  		     + strlen(event)
Z  		     + strlen(detail)
Z  		     + MAX_TEMPSTR);
Z***************
Z*** 518,528 ****
Z  		 * our client may not be our own.  therefore we want to
Z  		 * print the pid ourselves.
Z  		 */
Z- # ifdef LOG_DAEMON
Z  		openlog(ProgramName, LOG_PID, LOG_CRON);
Z- # else
Z- 		openlog(ProgramName, LOG_PID);
Z- # endif
Z  		syslog_open = TRUE;		/* assume openlog success */
Z  	}
Z  
Z--- 505,511 ----
Z***************
Z*** 555,561 ****
Z  char *
Z  first_word(s, t)
Z  	register char *s;	/* string we want the first word of */
Z! 	register char *t;	/* terminators, implicitly including \0 */
Z  {
Z  	static char retbuf[2][MAX_TEMPSTR + 1];	/* sure wish C had GC */
Z  	static int retsel = 0;
Z--- 538,544 ----
Z  char *
Z  first_word(s, t)
Z  	register char *s;	/* string we want the first word of */
Z! 	char *t;		/* terminators, implicitly including \0 */
Z  {
Z  	static char retbuf[2][MAX_TEMPSTR + 1];	/* sure wish C had GC */
Z  	static int retsel = 0;
Z***************
Z*** 617,626 ****
Z   */
Z  char *
Z  mkprints(src, len)
Z! 	register unsigned char *src;
Z! 	register unsigned int len;
Z  {
Z! 	register char *dst = malloc(len*4 + 1);
Z  
Z  	mkprint(dst, src, len);
Z  
Z--- 600,609 ----
Z   */
Z  char *
Z  mkprints(src, len)
Z! 	unsigned char *src;
Z! 	unsigned int len;
Z  {
Z! 	register char *dst = (char *)malloc(len*4 + 1);
Z  
Z  	mkprint(dst, src, len);
Z  
Z***************
Z*** 653,664 ****
Z  }
Z  #endif /*MAIL_DATE*/
Z  
Z- 
Z- #ifdef HAVE_SAVED_SUIDS
Z  static int save_euid;
Z! int swap_uids() { save_euid = geteuid(); return seteuid(getuid()); }
Z! int swap_uids_back() { return seteuid(save_euid); }
Z! #else /*HAVE_SAVED_UIDS*/
Z! int swap_uids() { return setreuid(geteuid(), getuid()); }
Z! int swap_uids_back() { return swap_uids(); }
Z! #endif /*HAVE_SAVED_UIDS*/
Z--- 636,649 ----
Z  }
Z  #endif /*MAIL_DATE*/
Z  
Z  static int save_euid;
Z! int swap_uids()
Z! 	{
Z! 	save_euid = geteuid();
Z! 	return(seteuid(getuid()));
Z! 	}
Z! 
Z! int swap_uids_back()
Z! 	{
Z! 	return(seteuid(save_euid));
Z! 	}
Zdiff -c -r /tmp/cron/pathnames.h cron/pathnames.h
Z*** /tmp/cron/pathnames.h	Fri Jun 18 19:37:52 1999
Z--- cron/pathnames.h	Fri Jun 18 20:56:50 1999
Z***************
Z*** 19,27 ****
Z   * $Id: pathnames.h,v 1.3 1994/01/15 20:43:43 vixie Exp $
Z   */
Z  
Z! #if (defined(BSD)) && (BSD >= 199103) || defined(__linux) || defined(AIX)
Z! # include <paths.h>
Z! #endif /*BSD*/
Z  
Z  #ifndef CRONDIR
Z  			/* CRONDIR is where crond(8) and crontab(1) both chdir
Z--- 19,25 ----
Z   * $Id: pathnames.h,v 1.3 1994/01/15 20:43:43 vixie Exp $
Z   */
Z  
Z! #include <paths.h>
Z  
Z  #ifndef CRONDIR
Z  			/* CRONDIR is where crond(8) and crontab(1) both chdir
Z***************
Z*** 49,55 ****
Z  			 */
Z  #define	ALLOW_FILE	"allow"		/*-*/
Z  #define DENY_FILE	"deny"		/*-*/
Z! #define LOG_FILE	"log"		/*-*/
Z  
Z  			/* where should the daemon stick its PID?
Z  			 */
Z--- 47,53 ----
Z  			 */
Z  #define	ALLOW_FILE	"allow"		/*-*/
Z  #define DENY_FILE	"deny"		/*-*/
Z! #undef	LOG_FILE			/* "log" */
Z  
Z  			/* where should the daemon stick its PID?
Z  			 */
Zdiff -c -r /tmp/cron/putman.sh cron/putman.sh
Z*** /tmp/cron/putman.sh	Fri Jun 18 19:37:52 1999
Z--- cron/putman.sh	Tue Jun 15 21:04:25 1999
Z***************
Z*** 9,23 ****
Z  DIR=$2
Z  
Z  SECT=`expr $PAGE : '[a-z]*.\([0-9]\)'`
Z  
Z! [ -d $DIR/man$SECT ] && {
Z! 	set -x
Z! 	cp $PAGE $DIR/man$SECT/$PAGE
Z! 	set +x
Z! } || {
Z! 	set -x
Z! 	nroff -man $PAGE >$DIR/cat$SECT/`basename $PAGE .$SECT`.0
Z! 	set +x
Z! }
Z  
Z  exit 0
Z--- 9,26 ----
Z  DIR=$2
Z  
Z  SECT=`expr $PAGE : '[a-z]*.\([0-9]\)'`
Z+ MDIR="$DIR/cat$SECT"
Z+ DEST="$MDIR/`basename $PAGE .$SECT`.0"
Z  
Z! set -x
Z! if [ ! -d $MDIR ]; then
Z! 	rm -f $MDIR
Z! 	mkdir -p $MDIR
Z! 	chmod 755 $MDIR
Z! fi
Z! 
Z! nroff -man $PAGE >$DEST
Z! chmod 444 $DEST
Z! set +x
Z  
Z  exit 0
Zdiff -c -r /tmp/cron/user.c cron/user.c
Z*** /tmp/cron/user.c	Fri Jun 18 19:37:52 1999
Z--- cron/user.c	Sat Jun 12 16:16:24 1999
Z***************
Z*** 30,36 ****
Z  free_user(u)
Z  	user	*u;
Z  {
Z! 	entry	*e, *ne;
Z  
Z  	free(u->name);
Z  	for (e = u->crontab;  e != NULL;  e = ne) {
Z--- 30,36 ----
Z  free_user(u)
Z  	user	*u;
Z  {
Z! 	register entry	*e, *ne;
Z  
Z  	free(u->name);
Z  	for (e = u->crontab;  e != NULL;  e = ne) {
Z***************
Z*** 49,56 ****
Z  {
Z  	char	envstr[MAX_ENVSTR];
Z  	FILE	*file;
Z! 	user	*u;
Z! 	entry	*e;
Z  	int	status;
Z  	char	**envp;
Z  
Z--- 49,56 ----
Z  {
Z  	char	envstr[MAX_ENVSTR];
Z  	FILE	*file;
Z! 	register user	*u;
Z! 	register entry	*e;
Z  	int	status;
Z  	char	**envp;
Z  
SHAR_EOF
chmod 644 'cron/grot/diffs'
fi
if test -f 'cron/README.2BSD'
then
	echo shar: "will not over-write existing file 'cron/README.2BSD'"
else
sed 's/^Z//' << \SHAR_EOF > 'cron/README.2BSD'
Z	This is the 2.11BSD port of the 'Vixie cron-3.0 patch1'.  
Z	
Z	The files Part01, Part02 and Patch01 were retrieved from 
Z	ftp://ftp.vix.com/pub/vixie/cron-3.0/ 
Z
Z	In an attempt to 'mark my changes' (so Paul Vixie doesn't get
Z	blamed for my mistakes) this file (README.2BSD) has been created
Z	and the following paragraph added:
Z
Z	"DO NOT SEND BUG OR PROBLEM REPORTS to Paul Vixie!    If 'cron'
Z	misbehaves under 2.11BSD use the 'sendbug' program OR look for the
Z	mail address in that script and send mail there."
Z
Z	The major change made was to remove the '#ifdef' statements.
Z	The removal of the ifdefs was prompted by several factors:
Z
Z		2.11BSD defines the symbol 'BSD' as "211".  Thus the
Z		datestamp based ifdefs ("#if BSD > 930811" for example) were
Z		wrong - 2.11 has almost all of the capabilities of later
Z		systems.
Z
Z		2.11BSD has all but one of the capabilities ('setsid') that 
Z		were conditionalized on "POSIX" .  Thus POSIX could not be
Z		defined.  Neither could POSIX be left undefined because
Z		that left out too much.  Sigh.
Z
Z		Conditionalized code is messy to read.
Z
Z		The probability that this version will ever be ported back 
Z		to a 'sequent', 'convex'  or 'att' system is not at this
Z		time distinguishable from 0.
Z
Z	Other changes include:
Z	
Z		Adding a lot more 'register' declarations (which helps
Z		code size - this cron is still over twice as big as the
Z		old one).
Z
Z		Revised the Makefile and 'putman.sh' script to fit in better 
Z		with 2BSD's philosophy of life.
Z
Z		Moved a few files into a 'grot' subdirectory to avoid 
Z		cluttering the main build area.  The file "diffs" is the
Z		summary of the changes made.
SHAR_EOF
chmod 644 'cron/README.2BSD'
fi
if test -f 'cron/Makefile'
then
	echo shar: "will not over-write existing file 'cron/Makefile'"
else
sed 's/^Z//' << \SHAR_EOF > 'cron/Makefile'
Z#/* Copyright 1988,1990,1993,1994 by Paul Vixie
Z# * All rights reserved
Z# *
Z# * Distribute freely, except: don't remove my name from the source or
Z# * documentation (don't take credit for my work), mark your changes (don't
Z# * get me blamed for your possible bugs), don't alter or remove this
Z# * notice.  May be sold if buildable source is provided to buyer.  No
Z# * warrantee of any kind, express or implied, is included with this
Z# * software; use at your own risk, responsibility for damages (if any) to
Z# * anyone resulting from the use of this software rests entirely with the
Z# * user.
Z# *
Z# * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
Z# * I'll try to keep a version up to date.  I can be reached as follows:
Z# * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
Z# */
Z
Z# Makefile for vixie's cron
Z#
Z# $Id: Makefile,v 2.9 1994/01/15 20:43:43 vixie Exp $
Z#
Z# vix 03mar88 [moved to RCS, rest of log is in there]
Z# vix 30mar87 [goodbye, time.c; hello, getopt]
Z# vix 12feb87 [cleanup for distribution]
Z# vix 30dec86 [written]
Z
Z# NOTES:
Z#	'make' can be done by anyone
Z#	'make install' must be done by root
Z#
Z#	this package needs getopt(3), bitstring(3), and BSD install(8).
Z#
Z#	the configurable stuff in this makefile consists of compilation
Z#	options (use -O, cron runs forever) and destination directories.
Z#	SHELL is for the 'augumented make' systems where 'make' imports
Z#	SHELL from the environment and then uses it to run its commands.
Z#	if your environment SHELL variable is /bin/csh, make goes real
Z#	slow and sometimes does the wrong thing.  
Z#
Z#	this package needs the 'bitstring macros' library, which is
Z#	available from me or from the comp.sources.unix archive.  if you
Z#	put 'bitstring.h' in a non-standard place (i.e., not intuited by
Z#	cc(1)), you will have to define INCLUDE to set the include
Z#	directory for cc.  INCLUDE should be `-Isomethingorother'.
Z#
Z#	there's more configuration info in config.h; edit that first!
Z
ZDESTROOT	=	$(DESTDIR)/usr
ZDESTSBIN	=	$(DESTROOT)/sbin
ZDESTBIN		=	$(DESTROOT)/bin
ZDESTMAN		=	$(DESTROOT)/man
ZINCLUDE		=	-I.
ZLIBS		=
ZOPTIM		=	-O
Z#<<lint flags of choice?>>
ZLINTFLAGS	=	-hbxa $(INCLUDE)
ZCC		=	cc
ZDEFS		=
ZINSTALL 	= install
ZLDFLAGS		= -i
Z#################################### end configurable stuff
Z
ZSHELL		=	/bin/sh
ZCFLAGS		=	$(OPTIM) $(INCLUDE) $(DEFS)
Z
ZLINT_CRON	=	cron.c database.c user.c entry.c compat.c \
Z			misc.c job.c do_command.c env.c popen.c
ZLINT_CRONTAB	=	crontab.c misc.c entry.c env.c compat.c
ZCRON_OBJ	=	cron.o database.o user.o entry.o job.o do_command.o \
Z			misc.o env.o popen.o compat.o
ZCRONTAB_OBJ	=	crontab.o misc.o entry.o env.o compat.o
Z
Zall:	cron crontab
Z
Zlint:
Z	lint $(LINTFLAGS) $(LINT_CRON) $(LIBS) \
Z		|grep -v "constant argument to NOT" 2>&1
Z	lint $(LINTFLAGS) $(LINT_CRONTAB) $(LIBS) \
Z		|grep -v "constant argument to NOT" 2>&1
Z
Zcron:	$(CRON_OBJ)
Z	$(CC) $(LDFLAGS) -o cron $(CRON_OBJ) $(LIBS)
Z
Zcrontab:	$(CRONTAB_OBJ)
Z	$(CC) $(LDFLAGS) -o crontab $(CRONTAB_OBJ) $(LIBS)
Z
Zinstall:	all
Z	$(INSTALL) -c -m  111 -o root -s cron    $(DESTSBIN)/cron
Z	$(INSTALL) -c -m 4111 -o root -s crontab $(DESTBIN)/crontab
Z	sh putman.sh crontab.1 $(DESTMAN)
Z	sh putman.sh cron.8    $(DESTMAN)
Z	sh putman.sh crontab.5 $(DESTMAN)
Z
Zclean:
Z	rm -f *.o cron crontab a.out core tags *~ #*
Z
Z$(CRON_OBJ)	:	cron.h compat.h config.h externs.h pathnames.h Makefile
Z$(CRONTAB_OBJ)	:	cron.h compat.h config.h externs.h pathnames.h Makefile
SHAR_EOF
chmod 644 'cron/Makefile'
fi
if test -f 'cron/README'
then
	echo shar: "will not over-write existing file 'cron/README'"
else
sed 's/^Z//' << \SHAR_EOF > 'cron/README'
Z#/* Copyright 1988,1990,1993 by Paul Vixie
Z# * All rights reserved
Z# *
Z# * Distribute freely, except: don't remove my name from the source or
Z# * documentation (don't take credit for my work), mark your changes (don't
Z# * get me blamed for your possible bugs), don't alter or remove this
Z# * notice.  May be sold if buildable source is provided to buyer.  No
Z# * warrantee of any kind, express or implied, is included with this
Z# * software; use at your own risk, responsibility for damages (if any) to
Z# * anyone resulting from the use of this software rests entirely with the
Z# * user.
Z# *
Z# * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
Z# * I'll try to keep a version up to date.  I can be reached as follows:
Z# * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
Z# */
Z
ZVixie Cron V3.0
ZDecember 27, 1993
Z[V2.2 was some time in 1992]
Z[V2.1 was May 29, 1991]
Z[V2.0 was July 5, 1990]
Z[V2.0-beta was December 9, 1988]
Z[V1.0 was May 6, 1987]
ZPaul Vixie
Z
ZThis is a version of 'cron' that is known to run on BSD 4.[23] systems.  It
Zis functionally based on the SysV cron, which means that each user can have
Ztheir own crontab file (all crontab files are stored in a read-protected
Zdirectory, usually /var/cron/tabs).  No direct support is provided for
Z'at'; you can continue to run 'atrun' from the crontab as you have been
Zdoing.  If you don't have atrun (i.e., System V) you are in trouble.
Z
ZA messages is logged each time a command is executed; also, the files
Z"allow" and "deny" in /var/cron can be used to control access to the
Z"crontab" command (which installs crontabs).  It hasn't been tested on
ZSysV, although some effort has gone into making the port an easy one.
Z
ZThis is more or less the copyright that USENET contributed software usually
Zhas.  Since ATT couldn't use this version if they had to freely distribute
Zsource, and since I'd love to see them use it, I'll offer some rediculously
Zlow license fee just to have them take it.  In the unlikely event that they
Zdo this, I will continue to support and distribute the pseudo-PD version, so
Zplease, don't flame me for wanting my work to see a wider distribution.
Z
ZTo use this: Sorry, folks, there is no cutesy 'Configure' script.  You'll
Zhave to go edit a couple of files... So, here's the checklist:
Z
Z	Read all the FEATURES, INSTALL, and CONVERSION files
Z	Edit config.h
Z	Edit Makefile
Z		(both of these files have instructions inside; note that
Z		 some things in config.h are definable in Makefile and are
Z		 therefore surrounded by #ifndef...#endif)
Z	'make'
Z	'su' and 'make install'
Z		(you may have to install the man pages by hand)
Z	kill your existing cron process
Z		(actually you can run your existing cron if you want, but why?)
Z	build new crontabs using /usr/lib/{crontab,crontab.local}
Z		(either put them all in "root"'s crontab, or divide it up
Z		 and rip out all the 'su' commands, collapse the lengthy
Z		 lists into ranges with steps -- basically, this step is
Z		 as much work as you want to make it)
Z	start up the new cron
Z		(must be done as root)
Z	watch it. test it with 'crontab -r' and watch the daemon track your
Z		changes.
Z	if you like it, change your /etc/{rc,rc.local} to use it instead of
Z		the old one.
Z
Z$Id: README,v 2.3 1993/12/28 08:34:43 vixie Exp $
SHAR_EOF
chmod 644 'cron/README'
fi
if test -f 'cron/bitstring.3'
then
	echo shar: "will not over-write existing file 'cron/bitstring.3'"
else
sed 's/^Z//' << \SHAR_EOF > 'cron/bitstring.3'
Z.\" Copyright (c) 1989 The Regents of the University of California.
Z.\" All rights reserved.
Z.\"
Z.\" This code is derived from software contributed to Berkeley by
Z.\" Paul Vixie.
Z.\"
Z.\" Redistribution and use in source and binary forms are permitted
Z.\" provided that the above copyright notice and this paragraph are
Z.\" duplicated in all such forms and that any documentation,
Z.\" advertising materials, and other materials related to such
Z.\" distribution and use acknowledge that the software was developed
Z.\" by the University of California, Berkeley.  The name of the
Z.\" University may not be used to endorse or promote products derived
Z.\" from this software without specific prior written permission.
Z.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
Z.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
Z.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
Z.\"
Z.\"	@(#)bitstring.3	5.1 (Berkeley) 12/13/89
Z.\"
Z.TH BITSTRING 3  "December 13, 1989"
Z.UC 4
Z.SH NAME
Zbit_alloc, bit_clear, bit_decl, bit_ffs, bit_nclear, bit_nset,
Zbit_set, bitstr_size, bit_test \- bit-string manipulation macros
Z.SH SYNOPSIS
Z.ft B
Z.nf
Z#include <bitstring.h>
Z
Zname = bit_alloc(nbits)
Zbitstr_t *name;
Zint nbits;
Z
Zbit_decl(name, nbits)
Zbitstr_t name;
Zint nbits;
Z
Zbit_clear(name, bit)
Zbitstr_t name;
Zint bit;
Z
Zbit_ffc(name, nbits, value)
Zbitstr_t name;
Zint nbits, *value;
Z
Zbit_ffs(name, nbits, value)
Zbitstr_t name;
Zint nbits, *value;
Z
Zbit_nclear(name, start, stop)
Zbitstr_t name;
Zint start, stop;
Z
Zbit_nset(name, start, stop)
Zbitstr_t name;
Zint start, stop;
Z
Zbit_set(name, bit)
Zbitstr_t name;
Zint bit;
Z
Zbitstr_size(nbits)
Zint nbits;
Z
Zbit_test(name, bit)
Zbitstr_t name;
Zint bit;
Z.fi
Z.ft R
Z.SH DESCRIPTION
ZThese macros operate on strings of bits.
Z.PP
Z.I Bit_alloc
Zreturns a pointer of type
Z.I bitstr_t\ *
Zto sufficient space to store
Z.I nbits
Zbits, or NULL if no space is available.
Z.PP
Z.I Bit_decl
Zis a macro for allocating sufficient space to store
Z.I nbits
Zbits on the stack.
Z.PP
Z.I Bitstr_size
Zreturns the number of elements of type
Z.I bitstr_t
Znecessary to store
Z.I nbits
Zbits.
ZThis is useful for copying bit strings.
Z.PP
Z.I Bit_clear
Zand
Z.I bit_set
Zclear or set the zero-based numbered bit
Z.IR bit ,
Zin the bit string
Z.IR name .
Z.PP
Z.I Bit_nset
Zand
Z.I bit_nclear
Zset or clear the zero-based numbered bits from
Z.I start
Zto
Z.I stop
Zin the bit string
Z.IR name .
Z.PP
Z.I Bit_test
Zevaluates to zero if the zero-based numbered bit
Z.I bit
Zof bit string
Z.I name
Zis set, and non-zero otherwise.
Z.PP
Z.I Bit_ffs
Zsets
Z.I *value
Zto the zero-based number of the first bit set in the array of
Z.I nbits
Zbits referenced by
Z.IR name .
ZIf no bits are set,
Z.I *value
Zis set to -1.
Z.PP
Z.I Bit_ffc
Zsets
Z.I *value
Zto the zero-based number of the first bit not set in the array of
Z.I nbits
Zbits referenced by
Z.IR name .
ZIf all bits are set,
Z.I value
Zis set to -1.
Z.SH EXAMPLE
Z.nf
Z.in +5
Z#include <limits.h>
Z#include <bitstring.h>
Z
Z...
Z#define	LPR_BUSY_BIT		0
Z#define	LPR_FORMAT_BIT		1
Z#define	LPR_DOWNLOAD_BIT	2
Z...
Z#define	LPR_AVAILABLE_BIT	9
Z#define	LPR_MAX_BITS		10
Z
Zmake_lpr_available()
Z{
Z	bitstr_t bit_decl(bitlist, LPR_MAX_BITS);
Z	...
Z	bit_nclear(bitlist, 0, LPR_MAX_BITS - 1);
Z	...
Z	if (!bit_test(bitlist, LPR_BUSY_BIT)) {
Z		bit_clear(bitlist, LPR_FORMAT_BIT);
Z		bit_clear(bitlist, LPR_DOWNLOAD_BIT);
Z		bit_set(bitlist, LPR_AVAILABLE_BIT);
Z	}
Z}
Z.fi
Z.SH "SEE ALSO"
Zmalloc(3)
SHAR_EOF
chmod 644 'cron/bitstring.3'
fi
if test -f 'cron/bitstring.h'
then
	echo shar: "will not over-write existing file 'cron/bitstring.h'"
else
sed 's/^Z//' << \SHAR_EOF > 'cron/bitstring.h'
Z/*
Z * Copyright (c) 1989 The Regents of the University of California.
Z * All rights reserved.
Z *
Z * This code is derived from software contributed to Berkeley by
Z * Paul Vixie.
Z *
Z * Redistribution and use in source and binary forms are permitted
Z * provided that the above copyright notice and this paragraph are
Z * duplicated in all such forms and that any documentation,
Z * advertising materials, and other materials related to such
Z * distribution and use acknowledge that the software was developed
Z * by the University of California, Berkeley.  The name of the
Z * University may not be used to endorse or promote products derived
Z * from this software without specific prior written permission.
Z * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
Z * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
Z * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
Z *
Z *	@(#)bitstring.h	5.2 (Berkeley) 4/4/90
Z */
Z
Ztypedef	unsigned char bitstr_t;
Z
Z/* internal macros */
Z				/* byte of the bitstring bit is in */
Z#define	_bit_byte(bit) \
Z	((bit) >> 3)
Z
Z				/* mask for the bit within its byte */
Z#define	_bit_mask(bit) \
Z	(1 << ((bit)&0x7))
Z
Z/* external macros */
Z				/* bytes in a bitstring of nbits bits */
Z#define	bitstr_size(nbits) \
Z	((((nbits) - 1) >> 3) + 1)
Z
Z				/* allocate a bitstring */
Z#define	bit_alloc(nbits) \
Z	(bitstr_t *)malloc(1, \
Z	    (unsigned int)bitstr_size(nbits) * sizeof(bitstr_t))
Z
Z				/* allocate a bitstring on the stack */
Z#define	bit_decl(name, nbits) \
Z	(name)[bitstr_size(nbits)]
Z
Z				/* is bit N of bitstring name set? */
Z#define	bit_test(name, bit) \
Z	((name)[_bit_byte(bit)] & _bit_mask(bit))
Z
Z				/* set bit N of bitstring name */
Z#define	bit_set(name, bit) \
Z	(name)[_bit_byte(bit)] |= _bit_mask(bit)
Z
Z				/* clear bit N of bitstring name */
Z#define	bit_clear(name, bit) \
Z	(name)[_bit_byte(bit)] &= ~_bit_mask(bit)
Z
Z				/* clear bits start ... stop in bitstring */
Z#define	bit_nclear(name, start, stop) { \
Z	register bitstr_t *_name = name; \
Z	register int _start = start, _stop = stop; \
Z	register int _startbyte = _bit_byte(_start); \
Z	register int _stopbyte = _bit_byte(_stop); \
Z	if (_startbyte == _stopbyte) { \
Z		_name[_startbyte] &= ((0xff >> (8 - (_start&0x7))) | \
Z				      (0xff << ((_stop&0x7) + 1))); \
Z	} else { \
Z		_name[_startbyte] &= 0xff >> (8 - (_start&0x7)); \
Z		while (++_startbyte < _stopbyte) \
Z			_name[_startbyte] = 0; \
Z		_name[_stopbyte] &= 0xff << ((_stop&0x7) + 1); \
Z	} \
Z}
Z
Z				/* set bits start ... stop in bitstring */
Z#define	bit_nset(name, start, stop) { \
Z	register bitstr_t *_name = name; \
Z	register int _start = start, _stop = stop; \
Z	register int _startbyte = _bit_byte(_start); \
Z	register int _stopbyte = _bit_byte(_stop); \
Z	if (_startbyte == _stopbyte) { \
Z		_name[_startbyte] |= ((0xff << (_start&0x7)) & \
Z				    (0xff >> (7 - (_stop&0x7)))); \
Z	} else { \
Z		_name[_startbyte] |= 0xff << ((_start)&0x7); \
Z		while (++_startbyte < _stopbyte) \
Z	    		_name[_startbyte] = 0xff; \
Z		_name[_stopbyte] |= 0xff >> (7 - (_stop&0x7)); \
Z	} \
Z}
Z
Z				/* find first bit clear in name */
Z#define	bit_ffc(name, nbits, value) { \
Z	register bitstr_t *_name = name; \
Z	register int _byte, _nbits = nbits; \
Z	register int _stopbyte = _bit_byte(_nbits), _value = -1; \
Z	for (_byte = 0; _byte <= _stopbyte; ++_byte) \
Z		if (_name[_byte] != 0xff) { \
Z			_value = _byte << 3; \
Z			for (_stopbyte = _name[_byte]; (_stopbyte&0x1); \
Z			    ++_value, _stopbyte >>= 1); \
Z			break; \
Z		} \
Z	*(value) = _value; \
Z}
Z
Z				/* find first bit set in name */
Z#define	bit_ffs(name, nbits, value) { \
Z	register bitstr_t *_name = name; \
Z	register int _byte, _nbits = nbits; \
Z	register int _stopbyte = _bit_byte(_nbits), _value = -1; \
Z	for (_byte = 0; _byte <= _stopbyte; ++_byte) \
Z		if (_name[_byte]) { \
Z			_value = _byte << 3; \
Z			for (_stopbyte = _name[_byte]; !(_stopbyte&0x1); \
Z			    ++_value, _stopbyte >>= 1); \
Z			break; \
Z		} \
Z	*(value) = _value; \
Z}
SHAR_EOF
chmod 644 'cron/bitstring.h'
fi
if test -f 'cron/compat.c'
then
	echo shar: "will not over-write existing file 'cron/compat.c'"
else
sed 's/^Z//' << \SHAR_EOF > 'cron/compat.c'
Z/* Copyright 1988,1990,1993,1994 by Paul Vixie
Z * All rights reserved
Z *
Z * Distribute freely, except: don't remove my name from the source or
Z * documentation (don't take credit for my work), mark your changes (don't
Z * get me blamed for your possible bugs), don't alter or remove this
Z * notice.  May be sold if buildable source is provided to buyer.  No
Z * warrantee of any kind, express or implied, is included with this
Z * software; use at your own risk, responsibility for damages (if any) to
Z * anyone resulting from the use of this software rests entirely with the
Z * user.
Z *
Z * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
Z * I'll try to keep a version up to date.  I can be reached as follows:
Z * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
Z */
Z
Z#if !defined(lint) && !defined(LINT)
Zstatic char rcsid[] = "$Id: compat.c,v 1.6 1994/01/15 20:43:43 vixie Exp $";
Z#endif
Z
Z/* vix 30dec93 [broke this out of misc.c - see RCS log for history]
Z * vix 15jan87 [added TIOCNOTTY, thanks csg@pyramid]
Z */
Z
Z
Z#include "cron.h"
Z
Z#include <fcntl.h>
Z#include <sys/ioctl.h>
Z
Z/*
Z * Ripped off from daemon(3) - differences are this sets the process group
Z * and does not fork (because that has been done already).
Z*/
Zint
Zsetsid()
Z{
Z	int	newpgrp;
Z	register int	fd;
Z
Z	newpgrp = setpgrp(0, getpid());
Z	if	((fd = open(_PATH_TTY, 2)) >= 0)
Z		{
Z		(void) ioctl(fd, TIOCNOTTY, (char*)0);
Z		(void) close(fd);
Z		}
Z	if	((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1)
Z		{
Z		(void)dup2(fd, 0);
Z		(void)dup2(fd, 1);
Z		(void)dup2(fd, 2);
Z		if	(fd > 2)
Z			(void)close(fd);
Z		}
Z	return newpgrp;
Z}
SHAR_EOF
chmod 644 'cron/compat.c'
fi
if test -f 'cron/compat.h'
then
	echo shar: "will not over-write existing file 'cron/compat.h'"
else
sed 's/^Z//' << \SHAR_EOF > 'cron/compat.h'
Z/* Copyright 1993,1994 by Paul Vixie
Z * All rights reserved
Z *
Z * Distribute freely, except: don't remove my name from the source or
Z * documentation (don't take credit for my work), mark your changes (don't
Z * get me blamed for your possible bugs), don't alter or remove this
Z * notice.  May be sold if buildable source is provided to buyer.  No
Z * warrantee of any kind, express or implied, is included with this
Z * software; use at your own risk, responsibility for damages (if any) to
Z * anyone resulting from the use of this software rests entirely with the
Z * user.
Z *
Z * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
Z * I'll try to keep a version up to date.  I can be reached as follows:
Z * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
Z */
Z
Z/*
Z * $Id: compat.h,v 1.8 1994/01/15 20:43:43 vixie Exp $
Z */
Z
Z#ifndef __P
Z#define __P(x) ()
Z#define const
Z#endif
Z
Z/*****************************************************************/
Z
Z#define	WAIT_T	union wait
Z#define	PID_T	pid_t
Z#define	TIME_T	time_t
SHAR_EOF
chmod 644 'cron/compat.h'
fi
if test -f 'cron/config.h'
then
	echo shar: "will not over-write existing file 'cron/config.h'"
else
sed 's/^Z//' << \SHAR_EOF > 'cron/config.h'
Z/* Copyright 1988,1990,1993,1994 by Paul Vixie
Z * All rights reserved
Z *
Z * Distribute freely, except: don't remove my name from the source or
Z * documentation (don't take credit for my work), mark your changes (don't
Z * get me blamed for your possible bugs), don't alter or remove this
Z * notice.  May be sold if buildable source is provided to buyer.  No
Z * warrantee of any kind, express or implied, is included with this
Z * software; use at your own risk, responsibility for damages (if any) to
Z * anyone resulting from the use of this software rests entirely with the
Z * user.
Z *
Z * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
Z * I'll try to keep a version up to date.  I can be reached as follows:
Z * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
Z */
Z
Z/* config.h - configurables for Vixie Cron
Z *
Z * $Id: config.h,v 2.6 1994/01/15 20:43:43 vixie Exp $
Z */
Z
Z#if !defined(_PATH_SENDMAIL)
Z# define _PATH_SENDMAIL "/usr/lib/sendmail"
Z#endif /*SENDMAIL*/
Z
Z/*
Z * these are site-dependent
Z */
Z
Z#ifndef DEBUGGING
Z#define DEBUGGING 1	/* 1 or 0 -- do you want debugging code built in? */
Z#endif
Z
Z			/*
Z			 * choose one of these MAILCMD commands.  I use
Z			 * /bin/mail for speed; it makes biff bark but doesn't
Z			 * do aliasing.  /usr/lib/sendmail does aliasing but is
Z			 * a hog for short messages.  aliasing is not needed
Z			 * if you make use of the MAILTO= feature in crontabs.
Z			 * (hint: MAILTO= was added for this reason).
Z			 */
Z
Z#define MAILCMD _PATH_SENDMAIL					/*-*/
Z#define MAILARGS "%s -FCronDaemon -odi -oem -or0s %s"		/*-*/
Z			/* -Fx	 = set full-name of sender
Z			 * -odi	 = Option Deliverymode Interactive
Z			 * -oem	 = Option Errors Mailedtosender
Z			 * -or0s = Option Readtimeout -- don't time out
Z			 */
Z
Z/* #define MAILCMD "/bin/mail"			/*-*/
Z/* #define MAILARGS "%s -d  %s"			/*-*/
Z			/* -d = undocumented but common flag: deliver locally?
Z			 */
Z
Z/* #define MAILCMD "/usr/mmdf/bin/submit"	/*-*/
Z/* #define MAILARGS "%s -mlrxto %s"		/*-*/
Z
Z/* #define MAIL_DATE				/*-*/
Z			/* should we include an ersatz Date: header in
Z			 * generated mail?  if you are using sendmail
Z			 * for MAILCMD, it is better to let sendmail
Z			 * generate the Date: header.
Z			 */
Z
Z			/* if ALLOW_FILE and DENY_FILE are not defined or are
Z			 * defined but neither exists, should crontab(1) be
Z			 * usable only by root?
Z			 */
Z/*#define ALLOW_ONLY_ROOT			/*-*/
Z
Z			/* if you want to use syslog(3) instead of appending
Z			 * to CRONDIR/LOG_FILE (/var/cron/log, e.g.), define
Z			 * SYSLOG here.  Note that quite a bit of logging
Z			 * info is written, and that you probably don't want
Z			 * to use this on 4.2bsd since everything goes in
Z			 * /usr/spool/mqueue/syslog.  On 4.[34]bsd you can
Z			 * tell /etc/syslog.conf to send cron's logging to
Z			 * a separate file.
Z			 *
Z			 * Note that if this and LOG_FILE in "pathnames.h"
Z			 * are both defined, then logging will go to both
Z			 * places.
Z			 */
Z#define SYSLOG	 			/*-*/
SHAR_EOF
chmod 644 'cron/config.h'
fi
exit 0
#	End of shell archive
