home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume27 / vixie-cron / part01 next >
Text File  |  1994-01-16  |  108KB  |  3,575 lines

  1. Newsgroups: comp.sources.unix
  2. From: paul@vix.com (Paul Vixie)
  3. Subject: v27i196: vixie-cron - Vixie's Cron, V3.0, Part01/02
  4. Message-id: <1.758778125.12895@gw.home.vix.com>
  5. Sender: unix-sources-moderator@gw.home.vix.com
  6. Approved: vixie@gw.home.vix.com
  7.  
  8. Submitted-By: paul@vix.com (Paul Vixie)
  9. Posting-Number: Volume 27, Issue 196
  10. Archive-Name: vixie-cron/part01
  11.  
  12. This is version 3.0 of vixie-cron.  Previous versions are contained in
  13. BSD/386, NetBSD, FreeBSD, 386BSD, Linux, and thousands of Usenet systems
  14. where the local sysadmin has replaced the vendor's cron with this one. It is
  15. essential that all systems using any previous version of this cron be
  16. upgraded, since there are three major security holes in all previous
  17. versions.  (Two of the security holes have been well-publicized; one has
  18. not; the Linux/NetBSD fix for one of the publicized security holes actually 
  19. adds a new hole, so even those systems ought to be upgraded to this cron.)
  20.  
  21. The other major difference between this and previous versions is that this one
  22. has support for the 4.3BSD-style "/etc/crontab" file -- that's the one that has
  23. an extra field between the time specification and the command; that field is a
  24. user name.  Thus commands can be made to run as non-root users without the old
  25. "* * * * * echo /usr/bin/rnews -U | su news" trick.  The support for this was
  26. done by BSDi and contributed back to the public version of cron.
  27.  
  28. I have run an extensive beta test of this software using the alt.sources group;
  29. this version of cron is known to compile and run on *BSD*, Linux, SunOS, OSF/1,
  30. HP-UX, and several flavours of System V including the one running on Convex's
  31. hardware.  I have run it in production here for many months, and it is part of
  32. the upcoming 1.1 release of BSDi's BSD/386 operating system.
  33.  
  34. Briefly, this cron is better than the older BSD/V7 cron since it permits each
  35. user on the system to have their own private crontab. It also logs each command
  36. as it is run (using syslog or a local log file, depending on how you configure
  37. it).  It does not contain "atrun" as does System V cron, and since those
  38. systems do not have a separate "atrun" that this cron can run, it is unlikely
  39. that any System V system will want to run this cron.
  40.  
  41. This cron complies with POSIX 1003.1.  Actually, this cron predates POSIX
  42. 1003.1's specification by a several years, but since the interface for this
  43. cron and POSIX's cron are both based on AT&T System V's cron, the differences
  44. were small and this latest version has been changed to the POSIX interface
  45. where they differed.
  46.  
  47.     Paul Vixie
  48.     paul@vix.com
  49.  
  50. #! /bin/sh
  51. # This is a shell archive.  Remove anything before this line, then unpack
  52. # it by saving it into a file and typing "sh file".  To overwrite existing
  53. # files, type "sh file -c".  You can also feed this as standard input via
  54. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  55. # will see the following message at the end:
  56. #        "End of archive 1 (of 2)."
  57. # Contents:  CONVERSION FEATURES INSTALL MANIFEST Makefile README
  58. #   THANKS bitstring.3 bitstring.h compat.c compat.h config.h cron.8
  59. #   cron.c cron.h crontab.1 crontab.5 database.c env.c externs.h job.c
  60. #   pathnames.h popen.c putman.sh user.c
  61. # Wrapped by vixie@gw.home.vix.com on Sun Jan 16 19:20:50 1994
  62. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  63. if test -f 'CONVERSION' -a "${1}" != "-c" ; then 
  64.   echo shar: Will not clobber existing file \"'CONVERSION'\"
  65. else
  66. echo shar: Extracting \"'CONVERSION'\" \(3853 characters\)
  67. sed "s/^X//" >'CONVERSION' <<'END_OF_FILE'
  68. X$Id: CONVERSION,v 2.2 1993/12/28 08:34:43 vixie Exp $
  69. X
  70. XConversion of BSD 4.[23] crontab files:
  71. X
  72. XEdit your current crontab (/usr/lib/crontab) into little pieces, with each
  73. Xusers' commands in a different file.  This is different on 4.2 and 4.3,
  74. Xbut I'll get to that below.  The biggest feature of this cron is that you
  75. Xcan move 'news' and 'uucp' cron commands into files owned and maintainable
  76. Xby those two users.  You also get to rip all the fancy 'su' footwork out
  77. Xof the cron commands.  On 4.3, there's no need for the 'su' stuff since the
  78. Xuser name appears on each command -- but I'd still rather have separate
  79. Xcrontabs with seperate environments and so on.
  80. X
  81. XLeave the original /usr/lib/crontab!  This cron doesn't use it, so you may
  82. Xas well keep it around for a while in case something goes wakko with this
  83. Xfancy version.
  84. X
  85. XMost commands in most crontabs are run by root, have to run by root, and
  86. Xshould continue to be run by root.  They still have to be in their own file;
  87. XI recommend /etc/crontab.src or /usr/adm/crontab.src.
  88. X
  89. X'uucp's commands need their own file; how about /usr/lib/uucp/crontab.src?
  90. X'news' also, perhaps in /usr/lib/news/crontab.src...
  91. X
  92. XI say `how about' and `perhaps' because it really doesn't matter to anyone
  93. X(except you) where you put the crontab source files.  The `crontab' command
  94. XCOPIES them into a protected directory (CRONDIR/SPOOL_DIR in cron.h), named
  95. Xafter the user whose crontab it is.  If you want to examine, replace, or
  96. Xdelete a crontab, the `crontab' command does all of those things.  The
  97. Xvarious `crontab.src' (my suggested name for them) files are just source
  98. Xfiles---they have to be copied to SPOOLDIR using `crontab' before they'll be
  99. Xexecuted.
  100. X
  101. XOn 4.2, your crontab might have a few lines like this:
  102. X
  103. X    5 * * * *   su uucp < /usr/lib/uucp/uudemon.hr
  104. X    10 4 * * *  su uucp < /usr/lib/uucp/uudemon.day
  105. X    15 5 * * 0  su uucp < /usr/lib/uucp/uudemon.wk
  106. X
  107. X...or like this:
  108. X
  109. X    5 * * * *   echo /usr/lib/uucp/uudemon.hr | su uucp
  110. X    10 4 * * *  echo /usr/lib/uucp/uudemon.day | su uucp
  111. X    15 5 * * 0  echo /usr/lib/uucp/uudemon.wk | su uucp
  112. X
  113. XOn 4.3, they'd look a little bit better, but not much:
  114. X
  115. X    5 * * * *   uucp  /usr/lib/uucp/uudemon.hr
  116. X    10 4 * * *  uucp  /usr/lib/uucp/uudemon.day
  117. X    15 5 * * 0  uucp  /usr/lib/uucp/uudemon.wk
  118. X
  119. XFor this cron, you'd create /usr/lib/uucp/crontab.src (or wherever you want
  120. Xto keep uucp's commands) which would look like this:
  121. X
  122. X    # /usr/lib/uucp/crontab.src - uucp's crontab
  123. X    #
  124. X    PATH=/usr/lib/uucp:/bin:/usr/bin
  125. X    SHELL=/bin/sh
  126. X    HOME=/usr/lib/uucp
  127. X    #
  128. X    5 * * * *   uudemon.hr
  129. X    10 4 * * *  uudemon.day
  130. X    15 5 * * 0  uudemon.wk
  131. X
  132. XThe application to the `news' cron commands (if any) is left for you to
  133. Xfigure out.  Likewise if there are any other cruddy-looking 'su' commands in
  134. Xyour crontab commands, you don't need them anymore: just find a good place
  135. Xto put the `crontab.src' (or whatever you want to call it) file for that
  136. Xuser, put the cron commands into it, and install it using the `crontab'
  137. Xcommand (probably with "-u USERNAME", but see the man page).
  138. X
  139. XIf you run a 4.2-derived cron, you could of course just install your current
  140. Xcrontab in toto as root's crontab.  It would work exactly the way your
  141. Xcurrent one does, barring the extra steps in installing or changing it.
  142. XThere would still be advantages to this cron, mostly that you get mail if
  143. Xthere is any output from your cron commands.
  144. X
  145. XOne note about getting mail from cron: you will probably find, after you
  146. Xinstall this version of cron, that your cron commands are generating a lot
  147. Xof irritating output.  The work-around for this is to redirect all EXPECTED
  148. Xoutput to a per-execution log file, which you can examine if you want to
  149. Xsee the output from the "last time" a command was executed; if you get any
  150. XUNEXPECTED output, it will be mailed to you.  This takes a while to get
  151. Xright, but it's amazingly convenient.  Trust me.
  152. X
  153. END_OF_FILE
  154. if test 3853 -ne `wc -c <'CONVERSION'`; then
  155.     echo shar: \"'CONVERSION'\" unpacked with wrong size!
  156. fi
  157. # end of 'CONVERSION'
  158. fi
  159. if test -f 'FEATURES' -a "${1}" != "-c" ; then 
  160.   echo shar: Will not clobber existing file \"'FEATURES'\"
  161. else
  162. echo shar: Extracting \"'FEATURES'\" \(4071 characters\)
  163. sed "s/^X//" >'FEATURES' <<'END_OF_FILE'
  164. X$Id: FEATURES,v 2.1 1993/12/28 08:34:43 vixie Exp $
  165. X
  166. XFeatures of Vixie's cron relative to BSD 4.[23] and SysV crons:
  167. X
  168. X--    Environment variables can be set in each crontab.  SHELL, USER,
  169. X    and HOME are set from the user's passwd entry; all except USER
  170. X    can be changed in the crontab.  PATH is especially useful to
  171. X    set there.  TZ can be set, but cron ignores it other than passing
  172. X    it on through to the commands it runs.  Format is
  173. X
  174. X        variable=value
  175. X
  176. X    Blanks surrounding the '=' will be eaten; other blanks in value are
  177. X    okay.  Leading or trailing blanks can be preserved by quoting, single
  178. X    or double quotes are okay, just so they match.
  179. X
  180. X        PATH=.:/bin:/usr/bin
  181. X        SHELL=/bin/sh
  182. X        FOOBAR = this is a long blanky example
  183. X
  184. X    Above, FOOBAR would get `this is a long blanky example' as its value.
  185. X
  186. X    SHELL and HOME will be examined when it's time to run a command; if
  187. X    you don't change them, they default to your /etc/passwd entry.
  188. X
  189. X    *DANGER*, WILL ROBINSON! This means that all 'uucp' logins should set
  190. X    SHELL=/bin/sh or cron will try to use /usr/lib/uucp/uucico as the
  191. X    shell.  This won't work.
  192. X
  193. X    MAILTO, if set to the login name of a user on your system, will be the
  194. X    person that cron mails the output of commands in that crontab.  This is
  195. X    useful if you decide on BINMAIL when configuring cron.h, since binmail
  196. X    doesn't know anything about aliasing.
  197. X
  198. X    Setting SHELL=/bin/sh will in general speed up your commands since it
  199. X    is a much smaller shell than the one you probably use normally (csh
  200. X    or ksh) and has enough features to work non-interactively.
  201. X
  202. X--    Weekdays can be specified by name.  Case is not significant, but only
  203. X    the first three letters should be specified.
  204. X
  205. X--    Months can likewise be specified by name.  Three letters only.
  206. X
  207. X--    Ranges and lists can be mixed.  Standard crons won't allow '1,3-5'.
  208. X
  209. X--    Ranges can specify 'step' values.  '10-16/2' is like '10,12,14,16'.
  210. X
  211. X--    Sunday is both day 0 and day 7 -- apparently BSD and ATT disagree
  212. X    about this.
  213. X
  214. X--    Each user gets their own crontab file.  This is a win over BSD 4.2,
  215. X    where only root has one, and over BSD 4.3, where they made the crontab
  216. X    format incompatible and although the commands can be run by non-root
  217. X    uid's, root is still the only one who can edit the crontab file.  This
  218. X    feature mimics the SysV cron.
  219. X
  220. X--    The 'crontab' command is loosely compatible with SysV, but has more
  221. X    options which just generally make more sense.  Running crontab with
  222. X    no arguments will print a cute little summary of the command syntax.
  223. X
  224. X--    Comments and blank lines are allowed in the crontab file.  Comments
  225. X    must be on a line by themselves; leading whitespace is ignored, and
  226. X    a '#' introduces the comment.
  227. X
  228. X--    (big win) If the `crontab' command changes anything in any crontab, it
  229. X    tells the 'cron' daemon, who reloads all the tables before running the
  230. X    next iteration.  In some crons, you have to kill and restart the
  231. X    daemon whenever you change a crontab.  In other crons, the crontab
  232. X    file is reread and reparsed every minute even if it didn't change.
  233. X
  234. X--    In order to support the automatic reload, the crontab files are not
  235. X    readable or writable except by 'crontab' or 'cron'.  This is not a
  236. X    problem, since 'crontab' will let you do pretty much whatever you
  237. X    want to your own crontab, or if you are root, to anybody's crontab.
  238. X
  239. X--    If any output is generated by a command (on stdout OR stderr), it will
  240. X    be mailed to the owner of the crontab that contained the command (or
  241. X    MAILTO, see discussion of environment variables, above).  The headers
  242. X    of the mail message will include the command that was run, and a
  243. X    complete list of the environment that was passed to it, which will
  244. X    contain (at least) the USER (LOGNAME on SysV), HOME, and SHELL.
  245. X
  246. X--    the dom/dow situation is odd.  '* * 1,15 * Sun' will run on the
  247. X    first and fifteenth AND every Sunday;  '* * * * Sun' will run *only*
  248. X    on Sundays;  '* * 1,15 * *' will run *only* the 1st and 15th.  this
  249. X    is why we keep 'e->dow_star' and 'e->dom_star'.  I didn't think up
  250. X    this behaviour; it's how cron has always worked but the documentation
  251. X    hasn't been very clear.
  252. END_OF_FILE
  253. if test 4071 -ne `wc -c <'FEATURES'`; then
  254.     echo shar: \"'FEATURES'\" unpacked with wrong size!
  255. fi
  256. # end of 'FEATURES'
  257. fi
  258. if test -f 'INSTALL' -a "${1}" != "-c" ; then 
  259.   echo shar: Will not clobber existing file \"'INSTALL'\"
  260. else
  261. echo shar: Extracting \"'INSTALL'\" \(4106 characters\)
  262. sed "s/^X//" >'INSTALL' <<'END_OF_FILE'
  263. X/* Copyright 1993,1994 by Paul Vixie
  264. X * All rights reserved
  265. X *
  266. X * Distribute freely, except: don't remove my name from the source or
  267. X * documentation (don't take credit for my work), mark your changes (don't
  268. X * get me blamed for your possible bugs), don't alter or remove this
  269. X * notice.  May be sold if buildable source is provided to buyer.  No
  270. X * warrantee of any kind, express or implied, is included with this
  271. X * software; use at your own risk, responsibility for damages (if any) to
  272. X * anyone resulting from the use of this software rests entirely with the
  273. X * user.
  274. X *
  275. X * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
  276. X * I'll try to keep a version up to date.  I can be reached as follows:
  277. X * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
  278. X */
  279. X
  280. X$Id: INSTALL,v 2.5 1994/01/15 20:43:43 vixie Exp $
  281. X
  282. XRead the comments at the top of the Makefile, then edit the area marked
  283. X'configurable stuff'.
  284. X
  285. XEdit config.h.  The stuff I expect you to change is down a bit from the
  286. Xtop of the file, but it's clearly marked.  Also look at pathnames.h.
  287. X
  288. XYou don't have to create the /var/cron or /var/cron/tabs directories, since
  289. Xboth the daemon and the `crontab' program will do this the first time they
  290. Xrun if they don't exist.  You do need to have a /var, though -- just "mkdir
  291. X/var" if you don't have one, or you can "mkdir /usr/var; ln -s /usr/var /var"
  292. Xif you expect your /var to have a lot of stuff in it.
  293. X
  294. XYou will also need /usr/local/etc and /usr/local/bin directories unless you
  295. Xchange the Makefile.  These will have to be created by hand, but if you are
  296. Xa long-time Usenet user you probably have them already.  /usr/local/man is
  297. Xwhere I keep my man pages, but I have the source for `man' and you probably
  298. Xdo not.  Therefore you may have to put the man pages into /usr/man/manl,
  299. Xwhich will be hard since there will be name collisions.  (Note that the man
  300. Xcommand was originally written by Bill Joy before he left Berkeley, and it
  301. Xcontains no AT&T code, so it is in UUNET's archive of freely-distributable
  302. XBSD code.)
  303. X
  304. XLINUX note: /usr/include/paths.h on some linux systems shows _PATH_SENDMAIL
  305. X    to be /usr/bin/sendmail even though sendmail is installed in /usr/lib.
  306. X    you should check this out.
  307. X
  308. Xsay:
  309. X    make all
  310. X
  311. Xsu and say:
  312. X    make install
  313. X
  314. XNote that if I can get you to "su and say" something just by asking, you have
  315. Xa very serious security problem on your system and you should look into it.
  316. X
  317. XEdit your /usr/lib/crontab file into little pieces -- see the CONVERSION file
  318. Xfor help on this.
  319. X
  320. XUse the `crontab' command to install all the little pieces you just created.
  321. XSome examples (see below before trying any of these!)
  322. X
  323. X    crontab -u uucp -r /usr/lib/uucp/crontab.src
  324. X    crontab -u news -r /usr/lib/news/crontab.src
  325. X    crontab -u root -r /usr/adm/crontab.src
  326. X
  327. XNotes on above examples: (1) the .src files are copied at the time the
  328. Xcommand is issued; changing the source files later will have no effect until
  329. Xthey are reinstalled with another `crontab -r' command.  (2) The crontab
  330. Xcommand will affect the crontab of the person using the command unless `-u
  331. XUSER' is given; `-u' only works for root.  When using most `su' commands
  332. Xunder most BSD's, `crontab' will still think of you as yourself even though
  333. Xyou may think of yourself as root -- so use `-u' liberally.  (3) the `-r'
  334. Xoption stands for `replace'; check the man page for crontab(1) for other
  335. Xpossibilities.
  336. X
  337. XKill your existing cron daemon -- do `ps aux' and look for /etc/cron.
  338. X
  339. XEdit your /etc/rc or /etc/rc.local, looking for the line that starts up
  340. X/etc/cron.  Comment it out and add a line to start the new cron daemon
  341. X-- usually /usr/local/etc/cron, unless you changed it in the Makefile.
  342. X
  343. XStart up this cron daemon yourself as root.  Just type /usr/local/etc/cron
  344. X(or whatever); no '&' is needed since the daemon forks itself and the
  345. Xprocess you executed returns immediately.
  346. X
  347. XATT notes: for those people unfortunate enough to be stuck on a AT&T UNIX,
  348. Xyou will need the public-domain "libndir", found in the B News source and in
  349. Xany comp.sources.unix archive.  You will also need to hack the code some.
  350. END_OF_FILE
  351. if test 4106 -ne `wc -c <'INSTALL'`; then
  352.     echo shar: \"'INSTALL'\" unpacked with wrong size!
  353. fi
  354. # end of 'INSTALL'
  355. fi
  356. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  357.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  358. else
  359. echo shar: Extracting \"'MANIFEST'\" \(1075 characters\)
  360. sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  361. X   File Name        Archive #    Description
  362. X-----------------------------------------------------------
  363. X CHANGES                    2    
  364. X CONVERSION                 1    
  365. X FEATURES                   1    
  366. X INSTALL                    1    
  367. X MAIL                       2    
  368. X MANIFEST                   1    This shipping list
  369. X Makefile                   1    
  370. X README                     1    
  371. X THANKS                     1    
  372. X bitstring.3                1    
  373. X bitstring.h                1    
  374. X compat.c                   1    
  375. X compat.h                   1    
  376. X config.h                   1    
  377. X cron.8                     1    
  378. X cron.c                     1    
  379. X cron.h                     1    
  380. X crontab.1                  1    
  381. X crontab.5                  1    
  382. X crontab.c                  2    
  383. X database.c                 1    
  384. X do_command.c               2    
  385. X entry.c                    2    
  386. X env.c                      1    
  387. X externs.h                  1    
  388. X job.c                      1    
  389. X misc.c                     2    
  390. X pathnames.h                1    
  391. X popen.c                    1    
  392. X putman.sh                  1    
  393. X user.c                     1    
  394. END_OF_FILE
  395. if test 1075 -ne `wc -c <'MANIFEST'`; then
  396.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  397. fi
  398. # end of 'MANIFEST'
  399. fi
  400. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  401.   echo shar: Will not clobber existing file \"'Makefile'\"
  402. else
  403. echo shar: Extracting \"'Makefile'\" \(4544 characters\)
  404. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  405. X#/* Copyright 1988,1990,1993,1994 by Paul Vixie
  406. X# * All rights reserved
  407. X# *
  408. X# * Distribute freely, except: don't remove my name from the source or
  409. X# * documentation (don't take credit for my work), mark your changes (don't
  410. X# * get me blamed for your possible bugs), don't alter or remove this
  411. X# * notice.  May be sold if buildable source is provided to buyer.  No
  412. X# * warrantee of any kind, express or implied, is included with this
  413. X# * software; use at your own risk, responsibility for damages (if any) to
  414. X# * anyone resulting from the use of this software rests entirely with the
  415. X# * user.
  416. X# *
  417. X# * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
  418. X# * I'll try to keep a version up to date.  I can be reached as follows:
  419. X# * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
  420. X# */
  421. X
  422. X# Makefile for vixie's cron
  423. X#
  424. X# $Id: Makefile,v 2.9 1994/01/15 20:43:43 vixie Exp $
  425. X#
  426. X# vix 03mar88 [moved to RCS, rest of log is in there]
  427. X# vix 30mar87 [goodbye, time.c; hello, getopt]
  428. X# vix 12feb87 [cleanup for distribution]
  429. X# vix 30dec86 [written]
  430. X
  431. X# NOTES:
  432. X#    'make' can be done by anyone
  433. X#    'make install' must be done by root
  434. X#
  435. X#    this package needs getopt(3), bitstring(3), and BSD install(8).
  436. X#
  437. X#    the configurable stuff in this makefile consists of compilation
  438. X#    options (use -O, cron runs forever) and destination directories.
  439. X#    SHELL is for the 'augumented make' systems where 'make' imports
  440. X#    SHELL from the environment and then uses it to run its commands.
  441. X#    if your environment SHELL variable is /bin/csh, make goes real
  442. X#    slow and sometimes does the wrong thing.  
  443. X#
  444. X#    this package needs the 'bitstring macros' library, which is
  445. X#    available from me or from the comp.sources.unix archive.  if you
  446. X#    put 'bitstring.h' in a non-standard place (i.e., not intuited by
  447. X#    cc(1)), you will have to define INCLUDE to set the include
  448. X#    directory for cc.  INCLUDE should be `-Isomethingorother'.
  449. X#
  450. X#    there's more configuration info in config.h; edit that first!
  451. X
  452. X#################################### begin configurable stuff
  453. X#<<DESTROOT is assumed to have ./etc, ./bin, and ./man subdirectories>>
  454. XDESTROOT    =    $(DESTDIR)/usr
  455. XDESTSBIN    =    $(DESTROOT)/sbin
  456. XDESTBIN        =    $(DESTROOT)/bin
  457. XDESTMAN        =    $(DESTROOT)/share/man
  458. X#<<need bitstring.h>>
  459. XINCLUDE        =    -I.
  460. X#INCLUDE    =
  461. X#<<need getopt()>>
  462. XLIBS        =
  463. X#<<optimize or debug?>>
  464. X#OPTIM        =    -O
  465. XOPTIM        =    -g
  466. X#<<ATT or BSD or POSIX?>>
  467. X# (ATT untested)
  468. X#COMPAT        =    -DATT
  469. X#(BSD is only needed if <sys/params.h> does not define it, as on ULTRIX)
  470. X#COMPAT        =    -DBSD
  471. X# (POSIX)
  472. X#COMPAT        =    -DPOSIX
  473. X#<<lint flags of choice?>>
  474. XLINTFLAGS    =    -hbxa $(INCLUDE) $(COMPAT) $(DEBUGGING)
  475. X#<<want to use a nonstandard CC?>>
  476. X#CC        =    vcc
  477. X#<<manifest defines>>
  478. XDEFS        =
  479. X#(SGI IRIX systems need this)
  480. X#DEFS        =    -D_BSD_SIGNALS -Dconst=
  481. X#<<the name of the BSD-like install program>>
  482. X#INSTALL = installbsd
  483. XINSTALL = install
  484. X#<<any special load flags>>
  485. XLDFLAGS        =
  486. X#################################### end configurable stuff
  487. X
  488. XSHELL        =    /bin/sh
  489. XCFLAGS        =    $(OPTIM) $(INCLUDE) $(COMPAT) $(DEFS)
  490. X
  491. XINFOS        =    README CHANGES FEATURES INSTALL CONVERSION THANKS MAIL
  492. XMANPAGES    =    bitstring.3 crontab.5 crontab.1 cron.8 putman.sh
  493. XHEADERS        =    bitstring.h cron.h config.h pathnames.h \
  494. X            externs.h compat.h
  495. XSOURCES        =    cron.c crontab.c database.c do_command.c entry.c \
  496. X            env.c job.c user.c popen.c misc.c compat.c
  497. XSHAR_SOURCE    =    $(INFOS) $(MANPAGES) Makefile $(HEADERS) $(SOURCES)
  498. XLINT_CRON    =    cron.c database.c user.c entry.c compat.c \
  499. X            misc.c job.c do_command.c env.c popen.c
  500. XLINT_CRONTAB    =    crontab.c misc.c entry.c env.c compat.c
  501. XCRON_OBJ    =    cron.o database.o user.o entry.o job.o do_command.o \
  502. X            misc.o env.o popen.o compat.o
  503. XCRONTAB_OBJ    =    crontab.o misc.o entry.o env.o compat.o
  504. X
  505. Xall        :    cron crontab
  506. X
  507. Xlint        :
  508. X            lint $(LINTFLAGS) $(LINT_CRON) $(LIBS) \
  509. X            |grep -v "constant argument to NOT" 2>&1
  510. X            lint $(LINTFLAGS) $(LINT_CRONTAB) $(LIBS) \
  511. X            |grep -v "constant argument to NOT" 2>&1
  512. X
  513. Xcron        :    $(CRON_OBJ)
  514. X            $(CC) $(LDFLAGS) -o cron $(CRON_OBJ) $(LIBS)
  515. X
  516. Xcrontab        :    $(CRONTAB_OBJ)
  517. X            $(CC) $(LDFLAGS) -o crontab $(CRONTAB_OBJ) $(LIBS)
  518. X
  519. Xinstall        :    all
  520. X            $(INSTALL) -c -m  111 -o root -s cron    $(DESTSBIN)/
  521. X            $(INSTALL) -c -m 4111 -o root -s crontab $(DESTBIN)/
  522. X            sh putman.sh crontab.1 $(DESTMAN)
  523. X            sh putman.sh cron.8    $(DESTMAN)
  524. X            sh putman.sh crontab.5 $(DESTMAN)
  525. X
  526. Xclean        :;    rm -f *.o cron crontab a.out core tags *~ #*
  527. X
  528. Xkit        :    $(SHAR_SOURCE)
  529. X            makekit -m -s99k $(SHAR_SOURCE)
  530. X
  531. X$(CRON_OBJ)    :    cron.h compat.h config.h externs.h pathnames.h Makefile
  532. X$(CRONTAB_OBJ)    :    cron.h compat.h config.h externs.h pathnames.h Makefile
  533. END_OF_FILE
  534. if test 4544 -ne `wc -c <'Makefile'`; then
  535.     echo shar: \"'Makefile'\" unpacked with wrong size!
  536. fi
  537. # end of 'Makefile'
  538. fi
  539. if test -f 'README' -a "${1}" != "-c" ; then 
  540.   echo shar: Will not clobber existing file \"'README'\"
  541. else
  542. echo shar: Extracting \"'README'\" \(3278 characters\)
  543. sed "s/^X//" >'README' <<'END_OF_FILE'
  544. X#/* Copyright 1988,1990,1993 by Paul Vixie
  545. X# * All rights reserved
  546. X# *
  547. X# * Distribute freely, except: don't remove my name from the source or
  548. X# * documentation (don't take credit for my work), mark your changes (don't
  549. X# * get me blamed for your possible bugs), don't alter or remove this
  550. X# * notice.  May be sold if buildable source is provided to buyer.  No
  551. X# * warrantee of any kind, express or implied, is included with this
  552. X# * software; use at your own risk, responsibility for damages (if any) to
  553. X# * anyone resulting from the use of this software rests entirely with the
  554. X# * user.
  555. X# *
  556. X# * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
  557. X# * I'll try to keep a version up to date.  I can be reached as follows:
  558. X# * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
  559. X# */
  560. X
  561. XVixie Cron V3.0
  562. XDecember 27, 1993
  563. X[V2.2 was some time in 1992]
  564. X[V2.1 was May 29, 1991]
  565. X[V2.0 was July 5, 1990]
  566. X[V2.0-beta was December 9, 1988]
  567. X[V1.0 was May 6, 1987]
  568. XPaul Vixie
  569. X
  570. XThis is a version of 'cron' that is known to run on BSD 4.[23] systems.  It
  571. Xis functionally based on the SysV cron, which means that each user can have
  572. Xtheir own crontab file (all crontab files are stored in a read-protected
  573. Xdirectory, usually /var/cron/tabs).  No direct support is provided for
  574. X'at'; you can continue to run 'atrun' from the crontab as you have been
  575. Xdoing.  If you don't have atrun (i.e., System V) you are in trouble.
  576. X
  577. XA messages is logged each time a command is executed; also, the files
  578. X"allow" and "deny" in /var/cron can be used to control access to the
  579. X"crontab" command (which installs crontabs).  It hasn't been tested on
  580. XSysV, although some effort has gone into making the port an easy one.
  581. X
  582. XThis is more or less the copyright that USENET contributed software usually
  583. Xhas.  Since ATT couldn't use this version if they had to freely distribute
  584. Xsource, and since I'd love to see them use it, I'll offer some rediculously
  585. Xlow license fee just to have them take it.  In the unlikely event that they
  586. Xdo this, I will continue to support and distribute the pseudo-PD version, so
  587. Xplease, don't flame me for wanting my work to see a wider distribution.
  588. X
  589. XTo use this: Sorry, folks, there is no cutesy 'Configure' script.  You'll
  590. Xhave to go edit a couple of files... So, here's the checklist:
  591. X
  592. X    Read all the FEATURES, INSTALL, and CONVERSION files
  593. X    Edit config.h
  594. X    Edit Makefile
  595. X        (both of these files have instructions inside; note that
  596. X         some things in config.h are definable in Makefile and are
  597. X         therefore surrounded by #ifndef...#endif)
  598. X    'make'
  599. X    'su' and 'make install'
  600. X        (you may have to install the man pages by hand)
  601. X    kill your existing cron process
  602. X        (actually you can run your existing cron if you want, but why?)
  603. X    build new crontabs using /usr/lib/{crontab,crontab.local}
  604. X        (either put them all in "root"'s crontab, or divide it up
  605. X         and rip out all the 'su' commands, collapse the lengthy
  606. X         lists into ranges with steps -- basically, this step is
  607. X         as much work as you want to make it)
  608. X    start up the new cron
  609. X        (must be done as root)
  610. X    watch it. test it with 'crontab -r' and watch the daemon track your
  611. X        changes.
  612. X    if you like it, change your /etc/{rc,rc.local} to use it instead of
  613. X        the old one.
  614. X
  615. X$Id: README,v 2.3 1993/12/28 08:34:43 vixie Exp $
  616. END_OF_FILE
  617. if test 3278 -ne `wc -c <'README'`; then
  618.     echo shar: \"'README'\" unpacked with wrong size!
  619. fi
  620. # end of 'README'
  621. fi
  622. if test -f 'THANKS' -a "${1}" != "-c" ; then 
  623.   echo shar: Will not clobber existing file \"'THANKS'\"
  624. else
  625. echo shar: Extracting \"'THANKS'\" \(1598 characters\)
  626. sed "s/^X//" >'THANKS' <<'END_OF_FILE'
  627. X15 January 1990
  628. XPaul Vixie
  629. X
  630. XMany people have contributed to cron.  Many more than I can remember, in fact.
  631. XRich Salz and Carl Gutekunst were each of enormous help to me in V1; Carl for
  632. Xhelping me understand UNIX well enough to write it, and Rich for helping me
  633. Xget the features right.
  634. X
  635. XJohn Gilmore wrote me a wonderful review of V2, which took me a whole year to
  636. Xanswer even though it made me clean up some really awful things in the code.
  637. X(According to John the most awful things are still in here, of course.)
  638. X
  639. XPaul Close made a suggestion which led to /etc/crond.pid and the mutex locking
  640. Xon it.  Kevin Braunsdorf of Purdue made a suggestion that led to @reboot and
  641. Xits brothers and sisters; he also sent some diffs that lead cron toward compil-
  642. Xability with System V, though without at(1) capabilities, this cron isn't going
  643. Xto be that useful on System V.  Bob Alverson fixed a silly bug in the line
  644. Xnumber counting.  Brian Reid made suggestions which led to the run queue and
  645. Xthe source-file labelling in installed crontabs.
  646. X
  647. XScott Narveson ported V2 to a Sequent, and sent in the most useful single batch
  648. Xof diffs I got from anybody.  Changes attributable to Scott are:
  649. X    -> sendmail won't time out if the command is slow to generate output
  650. X    -> day-of-week names aren't off by one anymore
  651. X    -> crontab says the right thing if you do something you shouldn't do
  652. X    -> crontab(5) man page is longer and more informative
  653. X    -> misc changes related to the side effects of fclose()
  654. X    -> Sequent "universe" support added (may also help on Pyramids)
  655. X    -> null pw_shell is dealt with now; default is /bin/sh
  656. END_OF_FILE
  657. if test 1598 -ne `wc -c <'THANKS'`; then
  658.     echo shar: \"'THANKS'\" unpacked with wrong size!
  659. fi
  660. # end of 'THANKS'
  661. fi
  662. if test -f 'bitstring.3' -a "${1}" != "-c" ; then 
  663.   echo shar: Will not clobber existing file \"'bitstring.3'\"
  664. else
  665. echo shar: Extracting \"'bitstring.3'\" \(3395 characters\)
  666. sed "s/^X//" >'bitstring.3' <<'END_OF_FILE'
  667. X.\" Copyright (c) 1989 The Regents of the University of California.
  668. X.\" All rights reserved.
  669. X.\"
  670. X.\" This code is derived from software contributed to Berkeley by
  671. X.\" Paul Vixie.
  672. X.\"
  673. X.\" Redistribution and use in source and binary forms are permitted
  674. X.\" provided that the above copyright notice and this paragraph are
  675. X.\" duplicated in all such forms and that any documentation,
  676. X.\" advertising materials, and other materials related to such
  677. X.\" distribution and use acknowledge that the software was developed
  678. X.\" by the University of California, Berkeley.  The name of the
  679. X.\" University may not be used to endorse or promote products derived
  680. X.\" from this software without specific prior written permission.
  681. X.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  682. X.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  683. X.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  684. X.\"
  685. X.\"    @(#)bitstring.3    5.1 (Berkeley) 12/13/89
  686. X.\"
  687. X.TH BITSTRING 3  "December 13, 1989"
  688. X.UC 4
  689. X.SH NAME
  690. Xbit_alloc, bit_clear, bit_decl, bit_ffs, bit_nclear, bit_nset,
  691. Xbit_set, bitstr_size, bit_test \- bit-string manipulation macros
  692. X.SH SYNOPSIS
  693. X.ft B
  694. X.nf
  695. X#include <bitstring.h>
  696. X
  697. Xname = bit_alloc(nbits)
  698. Xbitstr_t *name;
  699. Xint nbits;
  700. X
  701. Xbit_decl(name, nbits)
  702. Xbitstr_t name;
  703. Xint nbits;
  704. X
  705. Xbit_clear(name, bit)
  706. Xbitstr_t name;
  707. Xint bit;
  708. X
  709. Xbit_ffc(name, nbits, value)
  710. Xbitstr_t name;
  711. Xint nbits, *value;
  712. X
  713. Xbit_ffs(name, nbits, value)
  714. Xbitstr_t name;
  715. Xint nbits, *value;
  716. X
  717. Xbit_nclear(name, start, stop)
  718. Xbitstr_t name;
  719. Xint start, stop;
  720. X
  721. Xbit_nset(name, start, stop)
  722. Xbitstr_t name;
  723. Xint start, stop;
  724. X
  725. Xbit_set(name, bit)
  726. Xbitstr_t name;
  727. Xint bit;
  728. X
  729. Xbitstr_size(nbits)
  730. Xint nbits;
  731. X
  732. Xbit_test(name, bit)
  733. Xbitstr_t name;
  734. Xint bit;
  735. X.fi
  736. X.ft R
  737. X.SH DESCRIPTION
  738. XThese macros operate on strings of bits.
  739. X.PP
  740. X.I Bit_alloc
  741. Xreturns a pointer of type
  742. X.I bitstr_t\ *
  743. Xto sufficient space to store
  744. X.I nbits
  745. Xbits, or NULL if no space is available.
  746. X.PP
  747. X.I Bit_decl
  748. Xis a macro for allocating sufficient space to store
  749. X.I nbits
  750. Xbits on the stack.
  751. X.PP
  752. X.I Bitstr_size
  753. Xreturns the number of elements of type
  754. X.I bitstr_t
  755. Xnecessary to store
  756. X.I nbits
  757. Xbits.
  758. XThis is useful for copying bit strings.
  759. X.PP
  760. X.I Bit_clear
  761. Xand
  762. X.I bit_set
  763. Xclear or set the zero-based numbered bit
  764. X.IR bit ,
  765. Xin the bit string
  766. X.IR name .
  767. X.PP
  768. X.I Bit_nset
  769. Xand
  770. X.I bit_nclear
  771. Xset or clear the zero-based numbered bits from
  772. X.I start
  773. Xto
  774. X.I stop
  775. Xin the bit string
  776. X.IR name .
  777. X.PP
  778. X.I Bit_test
  779. Xevaluates to zero if the zero-based numbered bit
  780. X.I bit
  781. Xof bit string
  782. X.I name
  783. Xis set, and non-zero otherwise.
  784. X.PP
  785. X.I Bit_ffs
  786. Xsets
  787. X.I *value
  788. Xto the zero-based number of the first bit set in the array of
  789. X.I nbits
  790. Xbits referenced by
  791. X.IR name .
  792. XIf no bits are set,
  793. X.I *value
  794. Xis set to -1.
  795. X.PP
  796. X.I Bit_ffc
  797. Xsets
  798. X.I *value
  799. Xto the zero-based number of the first bit not set in the array of
  800. X.I nbits
  801. Xbits referenced by
  802. X.IR name .
  803. XIf all bits are set,
  804. X.I value
  805. Xis set to -1.
  806. X.SH EXAMPLE
  807. X.nf
  808. X.in +5
  809. X#include <limits.h>
  810. X#include <bitstring.h>
  811. X
  812. X...
  813. X#define    LPR_BUSY_BIT        0
  814. X#define    LPR_FORMAT_BIT        1
  815. X#define    LPR_DOWNLOAD_BIT    2
  816. X...
  817. X#define    LPR_AVAILABLE_BIT    9
  818. X#define    LPR_MAX_BITS        10
  819. X
  820. Xmake_lpr_available()
  821. X{
  822. X    bitstr_t bit_decl(bitlist, LPR_MAX_BITS);
  823. X    ...
  824. X    bit_nclear(bitlist, 0, LPR_MAX_BITS - 1);
  825. X    ...
  826. X    if (!bit_test(bitlist, LPR_BUSY_BIT)) {
  827. X        bit_clear(bitlist, LPR_FORMAT_BIT);
  828. X        bit_clear(bitlist, LPR_DOWNLOAD_BIT);
  829. X        bit_set(bitlist, LPR_AVAILABLE_BIT);
  830. X    }
  831. X}
  832. X.fi
  833. X.SH "SEE ALSO"
  834. Xmalloc(3)
  835. END_OF_FILE
  836. if test 3395 -ne `wc -c <'bitstring.3'`; then
  837.     echo shar: \"'bitstring.3'\" unpacked with wrong size!
  838. fi
  839. # end of 'bitstring.3'
  840. fi
  841. if test -f 'bitstring.h' -a "${1}" != "-c" ; then 
  842.   echo shar: Will not clobber existing file \"'bitstring.h'\"
  843. else
  844. echo shar: Extracting \"'bitstring.h'\" \(3957 characters\)
  845. sed "s/^X//" >'bitstring.h' <<'END_OF_FILE'
  846. X/*
  847. X * Copyright (c) 1989 The Regents of the University of California.
  848. X * All rights reserved.
  849. X *
  850. X * This code is derived from software contributed to Berkeley by
  851. X * Paul Vixie.
  852. X *
  853. X * Redistribution and use in source and binary forms are permitted
  854. X * provided that the above copyright notice and this paragraph are
  855. X * duplicated in all such forms and that any documentation,
  856. X * advertising materials, and other materials related to such
  857. X * distribution and use acknowledge that the software was developed
  858. X * by the University of California, Berkeley.  The name of the
  859. X * University may not be used to endorse or promote products derived
  860. X * from this software without specific prior written permission.
  861. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  862. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  863. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  864. X *
  865. X *    @(#)bitstring.h    5.2 (Berkeley) 4/4/90
  866. X */
  867. X
  868. Xtypedef    unsigned char bitstr_t;
  869. X
  870. X/* internal macros */
  871. X                /* byte of the bitstring bit is in */
  872. X#define    _bit_byte(bit) \
  873. X    ((bit) >> 3)
  874. X
  875. X                /* mask for the bit within its byte */
  876. X#define    _bit_mask(bit) \
  877. X    (1 << ((bit)&0x7))
  878. X
  879. X/* external macros */
  880. X                /* bytes in a bitstring of nbits bits */
  881. X#define    bitstr_size(nbits) \
  882. X    ((((nbits) - 1) >> 3) + 1)
  883. X
  884. X                /* allocate a bitstring */
  885. X#define    bit_alloc(nbits) \
  886. X    (bitstr_t *)malloc(1, \
  887. X        (unsigned int)bitstr_size(nbits) * sizeof(bitstr_t))
  888. X
  889. X                /* allocate a bitstring on the stack */
  890. X#define    bit_decl(name, nbits) \
  891. X    (name)[bitstr_size(nbits)]
  892. X
  893. X                /* is bit N of bitstring name set? */
  894. X#define    bit_test(name, bit) \
  895. X    ((name)[_bit_byte(bit)] & _bit_mask(bit))
  896. X
  897. X                /* set bit N of bitstring name */
  898. X#define    bit_set(name, bit) \
  899. X    (name)[_bit_byte(bit)] |= _bit_mask(bit)
  900. X
  901. X                /* clear bit N of bitstring name */
  902. X#define    bit_clear(name, bit) \
  903. X    (name)[_bit_byte(bit)] &= ~_bit_mask(bit)
  904. X
  905. X                /* clear bits start ... stop in bitstring */
  906. X#define    bit_nclear(name, start, stop) { \
  907. X    register bitstr_t *_name = name; \
  908. X    register int _start = start, _stop = stop; \
  909. X    register int _startbyte = _bit_byte(_start); \
  910. X    register int _stopbyte = _bit_byte(_stop); \
  911. X    if (_startbyte == _stopbyte) { \
  912. X        _name[_startbyte] &= ((0xff >> (8 - (_start&0x7))) | \
  913. X                      (0xff << ((_stop&0x7) + 1))); \
  914. X    } else { \
  915. X        _name[_startbyte] &= 0xff >> (8 - (_start&0x7)); \
  916. X        while (++_startbyte < _stopbyte) \
  917. X            _name[_startbyte] = 0; \
  918. X        _name[_stopbyte] &= 0xff << ((_stop&0x7) + 1); \
  919. X    } \
  920. X}
  921. X
  922. X                /* set bits start ... stop in bitstring */
  923. X#define    bit_nset(name, start, stop) { \
  924. X    register bitstr_t *_name = name; \
  925. X    register int _start = start, _stop = stop; \
  926. X    register int _startbyte = _bit_byte(_start); \
  927. X    register int _stopbyte = _bit_byte(_stop); \
  928. X    if (_startbyte == _stopbyte) { \
  929. X        _name[_startbyte] |= ((0xff << (_start&0x7)) & \
  930. X                    (0xff >> (7 - (_stop&0x7)))); \
  931. X    } else { \
  932. X        _name[_startbyte] |= 0xff << ((_start)&0x7); \
  933. X        while (++_startbyte < _stopbyte) \
  934. X                _name[_startbyte] = 0xff; \
  935. X        _name[_stopbyte] |= 0xff >> (7 - (_stop&0x7)); \
  936. X    } \
  937. X}
  938. X
  939. X                /* find first bit clear in name */
  940. X#define    bit_ffc(name, nbits, value) { \
  941. X    register bitstr_t *_name = name; \
  942. X    register int _byte, _nbits = nbits; \
  943. X    register int _stopbyte = _bit_byte(_nbits), _value = -1; \
  944. X    for (_byte = 0; _byte <= _stopbyte; ++_byte) \
  945. X        if (_name[_byte] != 0xff) { \
  946. X            _value = _byte << 3; \
  947. X            for (_stopbyte = _name[_byte]; (_stopbyte&0x1); \
  948. X                ++_value, _stopbyte >>= 1); \
  949. X            break; \
  950. X        } \
  951. X    *(value) = _value; \
  952. X}
  953. X
  954. X                /* find first bit set in name */
  955. X#define    bit_ffs(name, nbits, value) { \
  956. X    register bitstr_t *_name = name; \
  957. X    register int _byte, _nbits = nbits; \
  958. X    register int _stopbyte = _bit_byte(_nbits), _value = -1; \
  959. X    for (_byte = 0; _byte <= _stopbyte; ++_byte) \
  960. X        if (_name[_byte]) { \
  961. X            _value = _byte << 3; \
  962. X            for (_stopbyte = _name[_byte]; !(_stopbyte&0x1); \
  963. X                ++_value, _stopbyte >>= 1); \
  964. X            break; \
  965. X        } \
  966. X    *(value) = _value; \
  967. X}
  968. END_OF_FILE
  969. if test 3957 -ne `wc -c <'bitstring.h'`; then
  970.     echo shar: \"'bitstring.h'\" unpacked with wrong size!
  971. fi
  972. # end of 'bitstring.h'
  973. fi
  974. if test -f 'compat.c' -a "${1}" != "-c" ; then 
  975.   echo shar: Will not clobber existing file \"'compat.c'\"
  976. else
  977. echo shar: Extracting \"'compat.c'\" \(5116 characters\)
  978. sed "s/^X//" >'compat.c' <<'END_OF_FILE'
  979. X/* Copyright 1988,1990,1993,1994 by Paul Vixie
  980. X * All rights reserved
  981. X *
  982. X * Distribute freely, except: don't remove my name from the source or
  983. X * documentation (don't take credit for my work), mark your changes (don't
  984. X * get me blamed for your possible bugs), don't alter or remove this
  985. X * notice.  May be sold if buildable source is provided to buyer.  No
  986. X * warrantee of any kind, express or implied, is included with this
  987. X * software; use at your own risk, responsibility for damages (if any) to
  988. X * anyone resulting from the use of this software rests entirely with the
  989. X * user.
  990. X *
  991. X * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
  992. X * I'll try to keep a version up to date.  I can be reached as follows:
  993. X * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
  994. X */
  995. X
  996. X#if !defined(lint) && !defined(LINT)
  997. Xstatic char rcsid[] = "$Id: compat.c,v 1.6 1994/01/15 20:43:43 vixie Exp $";
  998. X#endif
  999. X
  1000. X/* vix 30dec93 [broke this out of misc.c - see RCS log for history]
  1001. X * vix 15jan87 [added TIOCNOTTY, thanks csg@pyramid]
  1002. X */
  1003. X
  1004. X
  1005. X#include "cron.h"
  1006. X#ifdef NEED_GETDTABLESIZE
  1007. X# include <limits.h>
  1008. X#endif
  1009. X#if defined(NEED_SETSID) && defined(BSD)
  1010. X# include <sys/ioctl.h>
  1011. X#endif
  1012. X#include <errno.h>
  1013. X
  1014. X
  1015. X/* the code does not depend on any of vfork's
  1016. X * side-effects; it just uses it as a quick
  1017. X * fork-and-exec.
  1018. X */
  1019. X#ifdef NEED_VFORK
  1020. XPID_T
  1021. Xvfork() {
  1022. X    return (fork());
  1023. X}
  1024. X#endif
  1025. X
  1026. X
  1027. X#ifdef NEED_STRDUP
  1028. Xchar *
  1029. Xstrdup(str)
  1030. X    char    *str;
  1031. X{
  1032. X    char    *temp;
  1033. X
  1034. X    temp = malloc(strlen(str) + 1);
  1035. X    (void) strcpy(temp, str);
  1036. X    return temp;
  1037. X}
  1038. X#endif
  1039. X
  1040. X
  1041. X#ifdef NEED_STRERROR
  1042. Xchar *
  1043. Xstrerror(error)
  1044. X    int error;
  1045. X{
  1046. X    extern char *sys_errlist[];
  1047. X    extern int sys_nerr;
  1048. X    static char buf[32];
  1049. X
  1050. X    if ((error <= sys_nerr) && (error > 0)) {
  1051. X        return sys_errlist[error];
  1052. X    }
  1053. X
  1054. X    sprintf(buf, "Unknown error: %d", error);
  1055. X    return buf;
  1056. X}
  1057. X#endif
  1058. X
  1059. X
  1060. X#ifdef NEED_STRCASECMP
  1061. Xint
  1062. Xstrcasecmp(left, right)
  1063. X    char    *left;
  1064. X    char    *right;
  1065. X{
  1066. X    while (*left && (MkLower(*left) == MkLower(*right))) {
  1067. X        left++;
  1068. X        right++;
  1069. X    }
  1070. X    return MkLower(*left) - MkLower(*right);
  1071. X}
  1072. X#endif
  1073. X
  1074. X
  1075. X#ifdef NEED_SETSID
  1076. Xint
  1077. Xsetsid()
  1078. X{
  1079. X    int    newpgrp;
  1080. X# if defined(BSD)
  1081. X    int    fd;
  1082. X#  if defined(POSIX)
  1083. X    newpgrp = setpgid((pid_t)0, getpid());
  1084. X#  else
  1085. X    newpgrp = setpgrp(0, getpid());
  1086. X#  endif
  1087. X    if ((fd = open("/dev/tty", 2)) >= 0)
  1088. X    {
  1089. X        (void) ioctl(fd, TIOCNOTTY, (char*)0);
  1090. X        (void) close(fd);
  1091. X    }
  1092. X# else /*BSD*/
  1093. X    newpgrp = setpgrp();
  1094. X
  1095. X    (void) close(STDIN);    (void) open("/dev/null", 0);
  1096. X    (void) close(STDOUT);    (void) open("/dev/null", 1);
  1097. X    (void) close(STDERR);    (void) open("/dev/null", 2);
  1098. X# endif /*BSD*/
  1099. X    return newpgrp;
  1100. X}
  1101. X#endif /*NEED_SETSID*/
  1102. X
  1103. X
  1104. X#ifdef NEED_GETDTABLESIZE
  1105. Xint
  1106. Xgetdtablesize() {
  1107. X#ifdef _SC_OPEN_MAX
  1108. X    return sysconf(_SC_OPEN_MAX);
  1109. X#else
  1110. X    return _POSIX_OPEN_MAX;
  1111. X#endif
  1112. X}
  1113. X#endif
  1114. X
  1115. X
  1116. X#ifdef NEED_FLOCK
  1117. X/* The following flock() emulation snarfed intact *) from the HP-UX
  1118. X * "BSD to HP-UX porting tricks" maintained by
  1119. X * system@alchemy.chem.utoronto.ca (System Admin (Mike Peterson))
  1120. X * from the version "last updated: 11-Jan-1993"
  1121. X * Snarfage done by Jarkko Hietaniemi <Jarkko.Hietaniemi@hut.fi>
  1122. X * *) well, almost, had to K&R the function entry, HPUX "cc"
  1123. X * does not grok ANSI function prototypes */
  1124. X/*
  1125. X * flock (fd, operation)
  1126. X *
  1127. X * This routine performs some file locking like the BSD 'flock'
  1128. X * on the object described by the int file descriptor 'fd',
  1129. X * which must already be open.
  1130. X *
  1131. X * The operations that are available are:
  1132. X *
  1133. X * LOCK_SH  -  get a shared lock.
  1134. X * LOCK_EX  -  get an exclusive lock.
  1135. X * LOCK_NB  -  don't block (must be ORed with LOCK_SH or LOCK_EX).
  1136. X * LOCK_UN  -  release a lock.
  1137. X *
  1138. X * Return value: 0 if lock successful, -1 if failed.
  1139. X *
  1140. X * Note that whether the locks are enforced or advisory is
  1141. X * controlled by the presence or absence of the SETGID bit on
  1142. X * the executable.
  1143. X *
  1144. X * Note that there is no difference between shared and exclusive
  1145. X * locks, since the 'lockf' system call in SYSV doesn't make any
  1146. X * distinction.
  1147. X *
  1148. X * The file "<sys/file.h>" should be modified to contain the definitions
  1149. X * of the available operations, which must be added manually (see below
  1150. X * for the values).
  1151. X */
  1152. X
  1153. X/* this code has been reformatted by vixie */
  1154. X
  1155. Xint
  1156. Xflock(fd, operation)
  1157. X    int fd;
  1158. X    int operation;
  1159. X{
  1160. X    int i;
  1161. X
  1162. X    switch (operation) {
  1163. X    case LOCK_SH:        /* get a shared lock */
  1164. X    case LOCK_EX:        /* get an exclusive lock */
  1165. X        i = lockf (fd, F_LOCK, 0);
  1166. X        break;
  1167. X
  1168. X    case LOCK_SH|LOCK_NB:    /* get a non-blocking shared lock */
  1169. X    case LOCK_EX|LOCK_NB:    /* get a non-blocking exclusive lock */
  1170. X        i = lockf (fd, F_TLOCK, 0);
  1171. X        if (i == -1)
  1172. X            if ((errno == EAGAIN) || (errno == EACCES))
  1173. X                errno = EWOULDBLOCK;
  1174. X        break;
  1175. X
  1176. X    case LOCK_UN:        /* unlock */
  1177. X        i = lockf (fd, F_ULOCK, 0);
  1178. X        break;
  1179. X    default:        /* can't decipher operation */
  1180. X        i = -1;
  1181. X        errno = EINVAL;
  1182. X        break;
  1183. X    }
  1184. X    return (i);
  1185. X}
  1186. X#endif /*NEED_FLOCK*/
  1187. X
  1188. X
  1189. X#ifdef NEED_SETENV
  1190. Xint
  1191. Xsetenv(name, value, overwrite)
  1192. X    char *name, *value;
  1193. X    int overwrite;
  1194. X{
  1195. X    char *tmp;
  1196. X
  1197. X    if (overwrite && getenv(name))
  1198. X        return -1;
  1199. X
  1200. X    if (!(tmp = malloc(strlen(name) + strlen(value) + 2))) {
  1201. X        errno = ENOMEM;
  1202. X        return -1;
  1203. X    }
  1204. X
  1205. X    sprintf("%s=%s", name, value);
  1206. X    return putenv(tmp);    /* intentionally orphan 'tmp' storage */
  1207. X}
  1208. X#endif
  1209. END_OF_FILE
  1210. if test 5116 -ne `wc -c <'compat.c'`; then
  1211.     echo shar: \"'compat.c'\" unpacked with wrong size!
  1212. fi
  1213. # end of 'compat.c'
  1214. fi
  1215. if test -f 'compat.h' -a "${1}" != "-c" ; then 
  1216.   echo shar: Will not clobber existing file \"'compat.h'\"
  1217. else
  1218. echo shar: Extracting \"'compat.h'\" \(3224 characters\)
  1219. sed "s/^X//" >'compat.h' <<'END_OF_FILE'
  1220. X/* Copyright 1993,1994 by Paul Vixie
  1221. X * All rights reserved
  1222. X *
  1223. X * Distribute freely, except: don't remove my name from the source or
  1224. X * documentation (don't take credit for my work), mark your changes (don't
  1225. X * get me blamed for your possible bugs), don't alter or remove this
  1226. X * notice.  May be sold if buildable source is provided to buyer.  No
  1227. X * warrantee of any kind, express or implied, is included with this
  1228. X * software; use at your own risk, responsibility for damages (if any) to
  1229. X * anyone resulting from the use of this software rests entirely with the
  1230. X * user.
  1231. X *
  1232. X * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
  1233. X * I'll try to keep a version up to date.  I can be reached as follows:
  1234. X * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
  1235. X */
  1236. X
  1237. X/*
  1238. X * $Id: compat.h,v 1.8 1994/01/15 20:43:43 vixie Exp $
  1239. X */
  1240. X
  1241. X#ifndef __P
  1242. X# ifdef __STDC__
  1243. X#  define __P(x) x
  1244. X# else
  1245. X#  define __P(x) ()
  1246. X#  define const
  1247. X# endif
  1248. X#endif
  1249. X
  1250. X#if defined(UNIXPC) || defined(unixpc)
  1251. X# define UNIXPC 1
  1252. X# define ATT 1
  1253. X#endif
  1254. X
  1255. X#if defined(hpux) || defined(_hpux) || defined(__hpux)
  1256. X# define HPUX 1
  1257. X# define seteuid(e) setresuid(-1,e,-1)
  1258. X# define setreuid(r,e)    setresuid(r,e,-1)
  1259. X#endif
  1260. X
  1261. X#if defined(_IBMR2)
  1262. X# define AIX 1
  1263. X#endif
  1264. X
  1265. X#if defined(__convex__)
  1266. X# define CONVEX 1
  1267. X#endif
  1268. X
  1269. X#if defined(sgi) || defined(_sgi) || defined(__sgi)
  1270. X# define IRIX 1
  1271. X/* IRIX 4 hdrs are broken: one cannot #include both <stdio.h>
  1272. X * and <stdlib.h> because they disagree on system(), perror().
  1273. X * Therefore we must zap the "const" keyword BEFORE including
  1274. X * either of them.
  1275. X */
  1276. X# define const
  1277. X#endif
  1278. X
  1279. X#if defined(_UNICOS)
  1280. X# define UNICOS 1
  1281. X#endif
  1282. X
  1283. X#ifndef POSIX
  1284. X# if (BSD >= 199103) || defined(__linux) || defined(ultrix) || defined(AIX) ||\
  1285. X    defined(HPUX) || defined(CONVEX) || defined(IRIX)
  1286. X#  define POSIX
  1287. X# endif
  1288. X#endif
  1289. X
  1290. X#ifndef BSD
  1291. X# if defined(ultrix)
  1292. X#  define BSD 198902
  1293. X# endif
  1294. X#endif
  1295. X
  1296. X/*****************************************************************/
  1297. X
  1298. X#if !defined(BSD) && !defined(HPUX) && !defined(CONVEX) && !defined(__linux)
  1299. X# define NEED_VFORK
  1300. X#endif
  1301. X
  1302. X#if (!defined(BSD) || (BSD < 198902)) && !defined(__linux) && \
  1303. X    !defined(IRIX) && !defined(NeXT) && !defined(HPUX)
  1304. X# define NEED_STRCASECMP
  1305. X#endif
  1306. X
  1307. X#if (!defined(BSD) || (BSD < 198911)) && !defined(__linux) &&\
  1308. X    !defined(IRIX) && !defined(UNICOS) && !defined(HPUX)
  1309. X# define NEED_STRDUP
  1310. X#endif
  1311. X
  1312. X#if (!defined(BSD) || (BSD < 198911)) && !defined(POSIX) && !defined(NeXT)
  1313. X# define NEED_STRERROR
  1314. X#endif
  1315. X
  1316. X#if defined(HPUX) || defined(AIX) || defined(UNIXPC)
  1317. X# define NEED_FLOCK
  1318. X#endif
  1319. X
  1320. X#ifndef POSIX
  1321. X# define NEED_SETSID
  1322. X#endif
  1323. X
  1324. X#if (defined(POSIX) && !defined(BSD)) && !defined(__linux)
  1325. X# define NEED_GETDTABLESIZE
  1326. X#endif
  1327. X
  1328. X#if (BSD >= 199103)
  1329. X# define HAVE_SAVED_UIDS
  1330. X#endif
  1331. X
  1332. X#if !defined(ATT) && !defined(__linux) && !defined(IRIX) && !defined(UNICOS)
  1333. X# define USE_SIGCHLD
  1334. X#endif
  1335. X
  1336. X#if !defined(AIX) && !defined(UNICOS)
  1337. X# define SYS_TIME_H 1
  1338. X#else
  1339. X# define SYS_TIME_H 0
  1340. X#endif
  1341. X
  1342. X#if defined(BSD) && !defined(POSIX)
  1343. X# define USE_UTIMES
  1344. X#endif
  1345. X
  1346. X#if defined(AIX) || defined(HPUX) || defined(IRIX)
  1347. X# define NEED_SETENV
  1348. X#endif
  1349. X
  1350. X#if !defined(UNICOS) && !defined(UNIXPC)
  1351. X# define HAS_FCHOWN
  1352. X#endif
  1353. X
  1354. X#if !defined(UNICOS) && !defined(UNIXPC)
  1355. X# define HAS_FCHMOD
  1356. X#endif
  1357. END_OF_FILE
  1358. if test 3224 -ne `wc -c <'compat.h'`; then
  1359.     echo shar: \"'compat.h'\" unpacked with wrong size!
  1360. fi
  1361. # end of 'compat.h'
  1362. fi
  1363. if test -f 'config.h' -a "${1}" != "-c" ; then 
  1364.   echo shar: Will not clobber existing file \"'config.h'\"
  1365. else
  1366. echo shar: Extracting \"'config.h'\" \(2974 characters\)
  1367. sed "s/^X//" >'config.h' <<'END_OF_FILE'
  1368. X/* Copyright 1988,1990,1993,1994 by Paul Vixie
  1369. X * All rights reserved
  1370. X *
  1371. X * Distribute freely, except: don't remove my name from the source or
  1372. X * documentation (don't take credit for my work), mark your changes (don't
  1373. X * get me blamed for your possible bugs), don't alter or remove this
  1374. X * notice.  May be sold if buildable source is provided to buyer.  No
  1375. X * warrantee of any kind, express or implied, is included with this
  1376. X * software; use at your own risk, responsibility for damages (if any) to
  1377. X * anyone resulting from the use of this software rests entirely with the
  1378. X * user.
  1379. X *
  1380. X * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
  1381. X * I'll try to keep a version up to date.  I can be reached as follows:
  1382. X * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
  1383. X */
  1384. X
  1385. X/* config.h - configurables for Vixie Cron
  1386. X *
  1387. X * $Id: config.h,v 2.6 1994/01/15 20:43:43 vixie Exp $
  1388. X */
  1389. X
  1390. X#if !defined(_PATH_SENDMAIL)
  1391. X# define _PATH_SENDMAIL "/usr/lib/sendmail"
  1392. X#endif /*SENDMAIL*/
  1393. X
  1394. X/*
  1395. X * these are site-dependent
  1396. X */
  1397. X
  1398. X#ifndef DEBUGGING
  1399. X#define DEBUGGING 1    /* 1 or 0 -- do you want debugging code built in? */
  1400. X#endif
  1401. X
  1402. X            /*
  1403. X             * choose one of these MAILCMD commands.  I use
  1404. X             * /bin/mail for speed; it makes biff bark but doesn't
  1405. X             * do aliasing.  /usr/lib/sendmail does aliasing but is
  1406. X             * a hog for short messages.  aliasing is not needed
  1407. X             * if you make use of the MAILTO= feature in crontabs.
  1408. X             * (hint: MAILTO= was added for this reason).
  1409. X             */
  1410. X
  1411. X#define MAILCMD _PATH_SENDMAIL                    /*-*/
  1412. X#define MAILARGS "%s -FCronDaemon -odi -oem -or0s %s"        /*-*/
  1413. X            /* -Fx     = set full-name of sender
  1414. X             * -odi     = Option Deliverymode Interactive
  1415. X             * -oem     = Option Errors Mailedtosender
  1416. X             * -or0s = Option Readtimeout -- don't time out
  1417. X             */
  1418. X
  1419. X/* #define MAILCMD "/bin/mail"            /*-*/
  1420. X/* #define MAILARGS "%s -d  %s"            /*-*/
  1421. X            /* -d = undocumented but common flag: deliver locally?
  1422. X             */
  1423. X
  1424. X/* #define MAILCMD "/usr/mmdf/bin/submit"    /*-*/
  1425. X/* #define MAILARGS "%s -mlrxto %s"        /*-*/
  1426. X
  1427. X/* #define MAIL_DATE                /*-*/
  1428. X            /* should we include an ersatz Date: header in
  1429. X             * generated mail?  if you are using sendmail
  1430. X             * for MAILCMD, it is better to let sendmail
  1431. X             * generate the Date: header.
  1432. X             */
  1433. X
  1434. X            /* if ALLOW_FILE and DENY_FILE are not defined or are
  1435. X             * defined but neither exists, should crontab(1) be
  1436. X             * usable only by root?
  1437. X             */
  1438. X/*#define ALLOW_ONLY_ROOT            /*-*/
  1439. X
  1440. X            /* if you want to use syslog(3) instead of appending
  1441. X             * to CRONDIR/LOG_FILE (/var/cron/log, e.g.), define
  1442. X             * SYSLOG here.  Note that quite a bit of logging
  1443. X             * info is written, and that you probably don't want
  1444. X             * to use this on 4.2bsd since everything goes in
  1445. X             * /usr/spool/mqueue/syslog.  On 4.[34]bsd you can
  1446. X             * tell /etc/syslog.conf to send cron's logging to
  1447. X             * a separate file.
  1448. X             *
  1449. X             * Note that if this and LOG_FILE in "pathnames.h"
  1450. X             * are both defined, then logging will go to both
  1451. X             * places.
  1452. X             */
  1453. X#define SYSLOG                 /*-*/
  1454. END_OF_FILE
  1455. if test 2974 -ne `wc -c <'config.h'`; then
  1456.     echo shar: \"'config.h'\" unpacked with wrong size!
  1457. fi
  1458. # end of 'config.h'
  1459. fi
  1460. if test -f 'cron.8' -a "${1}" != "-c" ; then 
  1461.   echo shar: Will not clobber existing file \"'cron.8'\"
  1462. else
  1463. echo shar: Extracting \"'cron.8'\" \(2218 characters\)
  1464. sed "s/^X//" >'cron.8' <<'END_OF_FILE'
  1465. X.\"/* Copyright 1988,1990,1993 by Paul Vixie
  1466. X.\" * All rights reserved
  1467. X.\" *
  1468. X.\" * Distribute freely, except: don't remove my name from the source or
  1469. X.\" * documentation (don't take credit for my work), mark your changes (don't
  1470. X.\" * get me blamed for your possible bugs), don't alter or remove this
  1471. X.\" * notice.  May be sold if buildable source is provided to buyer.  No
  1472. X.\" * warrantee of any kind, express or implied, is included with this
  1473. X.\" * software; use at your own risk, responsibility for damages (if any) to
  1474. X.\" * anyone resulting from the use of this software rests entirely with the
  1475. X.\" * user.
  1476. X.\" *
  1477. X.\" * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
  1478. X.\" * I'll try to keep a version up to date.  I can be reached as follows:
  1479. X.\" * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
  1480. X.\" */
  1481. X.\" 
  1482. X.\" $Id: cron.8,v 2.2 1993/12/28 08:34:43 vixie Exp $
  1483. X.\" 
  1484. X.TH CRON 8 "20 December 1993"
  1485. X.UC 4
  1486. X.SH NAME
  1487. Xcron \- daemon to execute scheduled commands (Vixie Cron)
  1488. X.SH SYNOPSIS
  1489. Xcron
  1490. X.SH DESCRIPTION
  1491. X.I Cron
  1492. Xshould be started from /etc/rc or /etc/rc.local.  It will return immediately,
  1493. Xso you don't need to start it with '&'.
  1494. X.PP
  1495. X.I Cron
  1496. Xsearches /var/cron/tabs for crontab files which are named after accounts in
  1497. X/etc/passwd; crontabs found are loaded into memory.
  1498. X.I Cron
  1499. Xalso searches for /etc/crontab which is in a different format (see
  1500. X.IR crontab(5)).
  1501. X.I Cron
  1502. Xthen wakes up every minute, examining all stored crontabs, checking each
  1503. Xcommand to see if it should be run in the current minute.  When executing
  1504. Xcommands, any output is mailed to the owner of the crontab (or to the user
  1505. Xnamed in the MAILTO environment variable in the crontab, if such exists).
  1506. X.PP
  1507. XAdditionally,
  1508. X.I cron
  1509. Xchecks each minute to see if its spool directory's modtime (or the modtime
  1510. Xon
  1511. X.IR /etc/crontab)
  1512. Xhas changed, and if it has,
  1513. X.I cron
  1514. Xwill then examine the modtime on all crontabs and reload those which have
  1515. Xchanged.  Thus
  1516. X.I cron
  1517. Xneed not be restarted whenever a crontab file is modified.  Note that the
  1518. X.IR Crontab (1)
  1519. Xcommand updates the modtime of the spool directory whenever it changes a
  1520. Xcrontab.
  1521. X.SH "SEE ALSO"
  1522. Xcrontab(1), crontab(5)
  1523. X.SH AUTHOR
  1524. X.nf
  1525. XPaul Vixie <paul@vix.com>
  1526. END_OF_FILE
  1527. if test 2218 -ne `wc -c <'cron.8'`; then
  1528.     echo shar: \"'cron.8'\" unpacked with wrong size!
  1529. fi
  1530. # end of 'cron.8'
  1531. fi
  1532. if test -f 'cron.c' -a "${1}" != "-c" ; then 
  1533.   echo shar: Will not clobber existing file \"'cron.c'\"
  1534. else
  1535. echo shar: Extracting \"'cron.c'\" \(6857 characters\)
  1536. sed "s/^X//" >'cron.c' <<'END_OF_FILE'
  1537. X/* Copyright 1988,1990,1993,1994 by Paul Vixie
  1538. X * All rights reserved
  1539. X *
  1540. X * Distribute freely, except: don't remove my name from the source or
  1541. X * documentation (don't take credit for my work), mark your changes (don't
  1542. X * get me blamed for your possible bugs), don't alter or remove this
  1543. X * notice.  May be sold if buildable source is provided to buyer.  No
  1544. X * warrantee of any kind, express or implied, is included with this
  1545. X * software; use at your own risk, responsibility for damages (if any) to
  1546. X * anyone resulting from the use of this software rests entirely with the
  1547. X * user.
  1548. X *
  1549. X * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
  1550. X * I'll try to keep a version up to date.  I can be reached as follows:
  1551. X * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
  1552. X */
  1553. X
  1554. X#if !defined(lint) && !defined(LINT)
  1555. Xstatic char rcsid[] = "$Id: cron.c,v 2.11 1994/01/15 20:43:43 vixie Exp $";
  1556. X#endif
  1557. X
  1558. X
  1559. X#define    MAIN_PROGRAM
  1560. X
  1561. X
  1562. X#include "cron.h"
  1563. X#include <sys/signal.h>
  1564. X#if SYS_TIME_H
  1565. X# include <sys/time.h>
  1566. X#else
  1567. X# include <time.h>
  1568. X#endif
  1569. X
  1570. X
  1571. Xstatic    void    usage __P((void)),
  1572. X        run_reboot_jobs __P((cron_db *)),
  1573. X        cron_tick __P((cron_db *)),
  1574. X        cron_sync __P((void)),
  1575. X        cron_sleep __P((void)),
  1576. X#ifdef USE_SIGCHLD
  1577. X        sigchld_handler __P((int)),
  1578. X#endif
  1579. X        sighup_handler __P((int)),
  1580. X        parse_args __P((int c, char *v[]));
  1581. X
  1582. X
  1583. Xstatic void
  1584. Xusage() {
  1585. X    fprintf(stderr, "usage:  %s [-x debugflag[,...]]\n", ProgramName);
  1586. X    exit(ERROR_EXIT);
  1587. X}
  1588. X
  1589. X
  1590. Xint
  1591. Xmain(argc, argv)
  1592. X    int    argc;
  1593. X    char    *argv[];
  1594. X{
  1595. X    cron_db    database;
  1596. X
  1597. X    ProgramName = argv[0];
  1598. X
  1599. X#if defined(BSD)
  1600. X    setlinebuf(stdout);
  1601. X    setlinebuf(stderr);
  1602. X#endif
  1603. X
  1604. X    parse_args(argc, argv);
  1605. X
  1606. X#ifdef USE_SIGCHLD
  1607. X    (void) signal(SIGCHLD, sigchld_handler);
  1608. X#else
  1609. X    (void) signal(SIGCLD, SIG_IGN);
  1610. X#endif
  1611. X    (void) signal(SIGHUP, sighup_handler);
  1612. X
  1613. X    acquire_daemonlock(0);
  1614. X    set_cron_uid();
  1615. X    set_cron_cwd();
  1616. X
  1617. X#if defined(POSIX)
  1618. X    setenv("PATH", _PATH_DEFPATH, 1);
  1619. X#endif
  1620. X
  1621. X    /* if there are no debug flags turned on, fork as a daemon should.
  1622. X     */
  1623. X# if DEBUGGING
  1624. X    if (DebugFlags) {
  1625. X# else
  1626. X    if (0) {
  1627. X# endif
  1628. X        (void) fprintf(stderr, "[%d] cron started\n", getpid());
  1629. X    } else {
  1630. X        switch (fork()) {
  1631. X        case -1:
  1632. X            log_it("CRON",getpid(),"DEATH","can't fork");
  1633. X            exit(0);
  1634. X            break;
  1635. X        case 0:
  1636. X            /* child process */
  1637. X            log_it("CRON",getpid(),"STARTUP","fork ok");
  1638. X            (void) setsid();
  1639. X            break;
  1640. X        default:
  1641. X            /* parent process should just die */
  1642. X            _exit(0);
  1643. X        }
  1644. X    }
  1645. X
  1646. X    acquire_daemonlock(0);
  1647. X    database.head = NULL;
  1648. X    database.tail = NULL;
  1649. X    database.mtime = (time_t) 0;
  1650. X    load_database(&database);
  1651. X    run_reboot_jobs(&database);
  1652. X    cron_sync();
  1653. X    while (TRUE) {
  1654. X# if DEBUGGING
  1655. X        if (!(DebugFlags & DTEST))
  1656. X# endif /*DEBUGGING*/
  1657. X            cron_sleep();
  1658. X
  1659. X        load_database(&database);
  1660. X
  1661. X        /* do this iteration
  1662. X         */
  1663. X        cron_tick(&database);
  1664. X
  1665. X        /* sleep 1 minute
  1666. X         */
  1667. X        TargetTime += 60;
  1668. X    }
  1669. X}
  1670. X
  1671. X
  1672. Xstatic void
  1673. Xrun_reboot_jobs(db)
  1674. X    cron_db *db;
  1675. X{
  1676. X    register user        *u;
  1677. X    register entry        *e;
  1678. X
  1679. X    for (u = db->head;  u != NULL;  u = u->next) {
  1680. X        for (e = u->crontab;  e != NULL;  e = e->next) {
  1681. X            if (e->flags & WHEN_REBOOT) {
  1682. X                job_add(e, u);
  1683. X            }
  1684. X        }
  1685. X    }
  1686. X    (void) job_runqueue();
  1687. X}
  1688. X
  1689. X
  1690. Xstatic void
  1691. Xcron_tick(db)
  1692. X    cron_db    *db;
  1693. X{
  1694. X     register struct tm    *tm = localtime(&TargetTime);
  1695. X    register int        minute, hour, dom, month, dow;
  1696. X    register user        *u;
  1697. X    register entry        *e;
  1698. X
  1699. X    /* make 0-based values out of these so we can use them as indicies
  1700. X     */
  1701. X    minute = tm->tm_min -FIRST_MINUTE;
  1702. X    hour = tm->tm_hour -FIRST_HOUR;
  1703. X    dom = tm->tm_mday -FIRST_DOM;
  1704. X    month = tm->tm_mon +1 /* 0..11 -> 1..12 */ -FIRST_MONTH;
  1705. X    dow = tm->tm_wday -FIRST_DOW;
  1706. X
  1707. X    Debug(DSCH, ("[%d] tick(%d,%d,%d,%d,%d)\n",
  1708. X        getpid(), minute, hour, dom, month, dow))
  1709. X
  1710. X    /* the dom/dow situation is odd.  '* * 1,15 * Sun' will run on the
  1711. X     * first and fifteenth AND every Sunday;  '* * * * Sun' will run *only*
  1712. X     * on Sundays;  '* * 1,15 * *' will run *only* the 1st and 15th.  this
  1713. X     * is why we keep 'e->dow_star' and 'e->dom_star'.  yes, it's bizarre.
  1714. X     * like many bizarre things, it's the standard.
  1715. X     */
  1716. X    for (u = db->head;  u != NULL;  u = u->next) {
  1717. X        for (e = u->crontab;  e != NULL;  e = e->next) {
  1718. X            Debug(DSCH|DEXT, ("user [%s:%d:%d:...] cmd=\"%s\"\n",
  1719. X                      env_get("LOGNAME", e->envp),
  1720. X                      e->uid, e->gid, e->cmd))
  1721. X            if (bit_test(e->minute, minute)
  1722. X             && bit_test(e->hour, hour)
  1723. X             && bit_test(e->month, month)
  1724. X             && ( ((e->flags & DOM_STAR) || (e->flags & DOW_STAR))
  1725. X                  ? (bit_test(e->dow,dow) && bit_test(e->dom,dom))
  1726. X                  : (bit_test(e->dow,dow) || bit_test(e->dom,dom))
  1727. X                )
  1728. X               ) {
  1729. X                job_add(e, u);
  1730. X            }
  1731. X        }
  1732. X    }
  1733. X}
  1734. X
  1735. X
  1736. X/* the task here is to figure out how long it's going to be until :00 of the
  1737. X * following minute and initialize TargetTime to this value.  TargetTime
  1738. X * will subsequently slide 60 seconds at a time, with correction applied
  1739. X * implicitly in cron_sleep().  it would be nice to let cron execute in
  1740. X * the "current minute" before going to sleep, but by restarting cron you
  1741. X * could then get it to execute a given minute's jobs more than once.
  1742. X * instead we have the chance of missing a minute's jobs completely, but
  1743. X * that's something sysadmin's know to expect what with crashing computers..
  1744. X */
  1745. Xstatic void
  1746. Xcron_sync() {
  1747. X     register struct tm    *tm;
  1748. X
  1749. X    TargetTime = time((time_t*)0);
  1750. X    tm = localtime(&TargetTime);
  1751. X    TargetTime += (60 - tm->tm_sec);
  1752. X}
  1753. X
  1754. X
  1755. Xstatic void
  1756. Xcron_sleep() {
  1757. X    register int    seconds_to_wait;
  1758. X
  1759. X    do {
  1760. X        seconds_to_wait = (int) (TargetTime - time((time_t*)0));
  1761. X        Debug(DSCH, ("[%d] TargetTime=%ld, sec-to-wait=%d\n",
  1762. X            getpid(), TargetTime, seconds_to_wait))
  1763. X
  1764. X        /* if we intend to sleep, this means that it's finally
  1765. X         * time to empty the job queue (execute it).
  1766. X         *
  1767. X         * if we run any jobs, we'll probably screw up our timing,
  1768. X         * so go recompute.
  1769. X         *
  1770. X         * note that we depend here on the left-to-right nature
  1771. X         * of &&, and the short-circuiting.
  1772. X         */
  1773. X    } while (seconds_to_wait > 0 && job_runqueue());
  1774. X
  1775. X    while (seconds_to_wait > 0) {
  1776. X        Debug(DSCH, ("[%d] sleeping for %d seconds\n",
  1777. X            getpid(), seconds_to_wait))
  1778. X        seconds_to_wait = (int) sleep((unsigned int) seconds_to_wait);
  1779. X    }
  1780. X}
  1781. X
  1782. X
  1783. X#ifdef USE_SIGCHLD
  1784. Xstatic void
  1785. Xsigchld_handler(x) {
  1786. X    WAIT_T        waiter;
  1787. X    PID_T        pid;
  1788. X
  1789. X    for (;;) {
  1790. X#ifdef POSIX
  1791. X        pid = waitpid(-1, &waiter, WNOHANG);
  1792. X#else
  1793. X        pid = wait3(&waiter, WNOHANG, (struct rusage *)0);
  1794. X#endif
  1795. X        switch (pid) {
  1796. X        case -1:
  1797. X            Debug(DPROC,
  1798. X                ("[%d] sigchld...no children\n", getpid()))
  1799. X            return;
  1800. X        case 0:
  1801. X            Debug(DPROC,
  1802. X                ("[%d] sigchld...no dead kids\n", getpid()))
  1803. X            return;
  1804. X        default:
  1805. X            Debug(DPROC,
  1806. X                ("[%d] sigchld...pid #%d died, stat=%d\n",
  1807. X                getpid(), pid, WEXITSTATUS(waiter)))
  1808. X        }
  1809. X    }
  1810. X}
  1811. X#endif /*USE_SIGCHLD*/
  1812. X
  1813. X
  1814. Xstatic void
  1815. Xsighup_handler(x) {
  1816. X    log_close();
  1817. X}
  1818. X
  1819. X
  1820. Xstatic void
  1821. Xparse_args(argc, argv)
  1822. X    int    argc;
  1823. X    char    *argv[];
  1824. X{
  1825. X    int    argch;
  1826. X
  1827. X    while (EOF != (argch = getopt(argc, argv, "x:"))) {
  1828. X        switch (argch) {
  1829. X        default:
  1830. X            usage();
  1831. X        case 'x':
  1832. X            if (!set_debug_flags(optarg))
  1833. X                usage();
  1834. X            break;
  1835. X        }
  1836. X    }
  1837. X}
  1838. END_OF_FILE
  1839. if test 6857 -ne `wc -c <'cron.c'`; then
  1840.     echo shar: \"'cron.c'\" unpacked with wrong size!
  1841. fi
  1842. # end of 'cron.c'
  1843. fi
  1844. if test -f 'cron.h' -a "${1}" != "-c" ; then 
  1845.   echo shar: Will not clobber existing file \"'cron.h'\"
  1846. else
  1847. echo shar: Extracting \"'cron.h'\" \(7715 characters\)
  1848. sed "s/^X//" >'cron.h' <<'END_OF_FILE'
  1849. X/* Copyright 1988,1990,1993,1994 by Paul Vixie
  1850. X * All rights reserved
  1851. X *
  1852. X * Distribute freely, except: don't remove my name from the source or
  1853. X * documentation (don't take credit for my work), mark your changes (don't
  1854. X * get me blamed for your possible bugs), don't alter or remove this
  1855. X * notice.  May be sold if buildable source is provided to buyer.  No
  1856. X * warrantee of any kind, express or implied, is included with this
  1857. X * software; use at your own risk, responsibility for damages (if any) to
  1858. X * anyone resulting from the use of this software rests entirely with the
  1859. X * user.
  1860. X *
  1861. X * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
  1862. X * I'll try to keep a version up to date.  I can be reached as follows:
  1863. X * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
  1864. X */
  1865. X
  1866. X/* cron.h - header for vixie's cron
  1867. X *
  1868. X * $Id: cron.h,v 2.10 1994/01/15 20:43:43 vixie Exp $
  1869. X *
  1870. X * vix 14nov88 [rest of log is in RCS]
  1871. X * vix 14jan87 [0 or 7 can be sunday; thanks, mwm@berkeley]
  1872. X * vix 30dec86 [written]
  1873. X */
  1874. X
  1875. X/* reorder these #include's at your peril */
  1876. X
  1877. X#include <sys/types.h>
  1878. X#include <sys/param.h>
  1879. X#include "compat.h"
  1880. X
  1881. X#include <stdio.h>
  1882. X#include <ctype.h>
  1883. X#include <bitstring.h>
  1884. X#include <pwd.h>
  1885. X#include <sys/wait.h>
  1886. X
  1887. X#include "pathnames.h"
  1888. X#include "config.h"
  1889. X#include "externs.h"
  1890. X
  1891. X    /* these are really immutable, and are
  1892. X     *   defined for symbolic convenience only
  1893. X     * TRUE, FALSE, and ERR must be distinct
  1894. X     * ERR must be < OK.
  1895. X     */
  1896. X#define TRUE        1
  1897. X#define FALSE        0
  1898. X    /* system calls return this on success */
  1899. X#define OK        0
  1900. X    /*   or this on error */
  1901. X#define ERR        (-1)
  1902. X
  1903. X    /* turn this on to get '-x' code */
  1904. X#ifndef DEBUGGING
  1905. X#define DEBUGGING    FALSE
  1906. X#endif
  1907. X
  1908. X#define READ_PIPE    0    /* which end of a pipe pair do you read? */
  1909. X#define WRITE_PIPE    1    /*   or write to? */
  1910. X#define STDIN        0    /* what is stdin's file descriptor? */
  1911. X#define STDOUT        1    /*   stdout's? */
  1912. X#define STDERR        2    /*   stderr's? */
  1913. X#define ERROR_EXIT    1    /* exit() with this will scare the shell */
  1914. X#define    OK_EXIT        0    /* exit() with this is considered 'normal' */
  1915. X#define    MAX_FNAME    100    /* max length of internally generated fn */
  1916. X#define    MAX_COMMAND    1000    /* max length of internally generated cmd */
  1917. X#define    MAX_ENVSTR    1000    /* max length of envvar=value\0 strings */
  1918. X#define    MAX_TEMPSTR    100    /* obvious */
  1919. X#define    MAX_UNAME    20    /* max length of username, should be overkill */
  1920. X#define    ROOT_UID    0    /* don't change this, it really must be root */
  1921. X#define    ROOT_USER    "root"    /* ditto */
  1922. X
  1923. X                /* NOTE: these correspond to DebugFlagNames,
  1924. X                 *    defined below.
  1925. X                 */
  1926. X#define    DEXT        0x0001    /* extend flag for other debug masks */
  1927. X#define    DSCH        0x0002    /* scheduling debug mask */
  1928. X#define    DPROC        0x0004    /* process control debug mask */
  1929. X#define    DPARS        0x0008    /* parsing debug mask */
  1930. X#define    DLOAD        0x0010    /* database loading debug mask */
  1931. X#define    DMISC        0x0020    /* misc debug mask */
  1932. X#define    DTEST        0x0040    /* test mode: don't execute any commands */
  1933. X#define    DBIT        0x0080    /* bit twiddling shown (long) */
  1934. X
  1935. X#define    CRON_TAB(u)    "%s/%s", SPOOL_DIR, u
  1936. X#define    REG        register
  1937. X#define    PPC_NULL    ((char **)NULL)
  1938. X
  1939. X#ifndef MAXHOSTNAMELEN
  1940. X#define MAXHOSTNAMELEN 64
  1941. X#endif
  1942. X
  1943. X#define    Skip_Blanks(c, f) \
  1944. X            while (c == '\t' || c == ' ') \
  1945. X                c = get_char(f);
  1946. X
  1947. X#define    Skip_Nonblanks(c, f) \
  1948. X            while (c!='\t' && c!=' ' && c!='\n' && c != EOF) \
  1949. X                c = get_char(f);
  1950. X
  1951. X#define    Skip_Line(c, f) \
  1952. X            do {c = get_char(f);} while (c != '\n' && c != EOF);
  1953. X
  1954. X#if DEBUGGING
  1955. X# define Debug(mask, message) \
  1956. X            if ( (DebugFlags & (mask) ) == (mask) ) \
  1957. X                printf message;
  1958. X#else /* !DEBUGGING */
  1959. X# define Debug(mask, message) \
  1960. X            ;
  1961. X#endif /* DEBUGGING */
  1962. X
  1963. X#define    MkLower(ch)    (isupper(ch) ? tolower(ch) : ch)
  1964. X#define    MkUpper(ch)    (islower(ch) ? toupper(ch) : ch)
  1965. X#define    Set_LineNum(ln)    {Debug(DPARS|DEXT,("linenum=%d\n",ln)); \
  1966. X             LineNumber = ln; \
  1967. X            }
  1968. X
  1969. X#define    FIRST_MINUTE    0
  1970. X#define    LAST_MINUTE    59
  1971. X#define    MINUTE_COUNT    (LAST_MINUTE - FIRST_MINUTE + 1)
  1972. X
  1973. X#define    FIRST_HOUR    0
  1974. X#define    LAST_HOUR    23
  1975. X#define    HOUR_COUNT    (LAST_HOUR - FIRST_HOUR + 1)
  1976. X
  1977. X#define    FIRST_DOM    1
  1978. X#define    LAST_DOM    31
  1979. X#define    DOM_COUNT    (LAST_DOM - FIRST_DOM + 1)
  1980. X
  1981. X#define    FIRST_MONTH    1
  1982. X#define    LAST_MONTH    12
  1983. X#define    MONTH_COUNT    (LAST_MONTH - FIRST_MONTH + 1)
  1984. X
  1985. X/* note on DOW: 0 and 7 are both Sunday, for compatibility reasons. */
  1986. X#define    FIRST_DOW    0
  1987. X#define    LAST_DOW    7
  1988. X#define    DOW_COUNT    (LAST_DOW - FIRST_DOW + 1)
  1989. X
  1990. X            /* each user's crontab will be held as a list of
  1991. X             * the following structure.
  1992. X             *
  1993. X             * These are the cron commands.
  1994. X             */
  1995. X
  1996. Xtypedef    struct _entry {
  1997. X    struct _entry    *next;
  1998. X    uid_t        uid;    
  1999. X    gid_t        gid;
  2000. X    char        **envp;
  2001. X    char        *cmd;
  2002. X    bitstr_t    bit_decl(minute, MINUTE_COUNT);
  2003. X    bitstr_t    bit_decl(hour,   HOUR_COUNT);
  2004. X    bitstr_t    bit_decl(dom,    DOM_COUNT);
  2005. X    bitstr_t    bit_decl(month,  MONTH_COUNT);
  2006. X    bitstr_t    bit_decl(dow,    DOW_COUNT);
  2007. X    int        flags;
  2008. X#define    DOM_STAR    0x01
  2009. X#define    DOW_STAR    0x02
  2010. X#define    WHEN_REBOOT    0x04
  2011. X} entry;
  2012. X
  2013. X            /* the crontab database will be a list of the
  2014. X             * following structure, one element per user
  2015. X             * plus one for the system.
  2016. X             *
  2017. X             * These are the crontabs.
  2018. X             */
  2019. X
  2020. Xtypedef    struct _user {
  2021. X    struct _user    *next, *prev;    /* links */
  2022. X    char        *name;
  2023. X    time_t        mtime;        /* last modtime of crontab */
  2024. X    entry        *crontab;    /* this person's crontab */
  2025. X} user;
  2026. X
  2027. Xtypedef    struct _cron_db {
  2028. X    user        *head, *tail;    /* links */
  2029. X    time_t        mtime;        /* last modtime on spooldir */
  2030. X} cron_db;
  2031. X
  2032. X
  2033. Xvoid        set_cron_uid __P((void)),
  2034. X        set_cron_cwd __P((void)),
  2035. X        load_database __P((cron_db *)),
  2036. X        open_logfile __P((void)),
  2037. X        sigpipe_func __P((void)),
  2038. X        job_add __P((entry *, user *)),
  2039. X        do_command __P((entry *, user *)),
  2040. X        link_user __P((cron_db *, user *)),
  2041. X        unlink_user __P((cron_db *, user *)),
  2042. X        free_user __P((user *)),
  2043. X        env_free __P((char **)),
  2044. X        unget_char __P((int, FILE *)),
  2045. X        free_entry __P((entry *)),
  2046. X        acquire_daemonlock __P((int)),
  2047. X        skip_comments __P((FILE *)),
  2048. X        log_it __P((char *, int, char *, char *)),
  2049. X        log_close __P((void));
  2050. X
  2051. Xint        job_runqueue __P((void)),
  2052. X        set_debug_flags __P((char *)),
  2053. X        get_char __P((FILE *)),
  2054. X        get_string __P((char *, int, FILE *, char *)),
  2055. X        swap_uids __P((void)),
  2056. X        load_env __P((char *, FILE *)),
  2057. X        cron_pclose __P((FILE *)),
  2058. X        strcmp_until __P((char *, char *, int)),
  2059. X        allowed __P((char *)),
  2060. X        strdtb __P((char *));
  2061. X
  2062. Xchar        *env_get __P((char *, char **)),
  2063. X        *arpadate __P((time_t *)),
  2064. X        *mkprints __P((unsigned char *, unsigned int)),
  2065. X        *first_word __P((char *, char *)),
  2066. X        **env_init __P((void)),
  2067. X        **env_copy __P((char **)),
  2068. X        **env_set __P((char **, char *));
  2069. X
  2070. Xuser        *load_user __P((int, struct passwd *, char *)),
  2071. X        *find_user __P((cron_db *, char *));
  2072. X
  2073. Xentry        *load_entry __P((FILE *, void (*)(),
  2074. X                 struct passwd *, char **));
  2075. X
  2076. XFILE        *cron_popen __P((char *, char *));
  2077. X
  2078. X
  2079. X                /* in the C tradition, we only create
  2080. X                 * variables for the main program, just
  2081. X                 * extern them elsewhere.
  2082. X                 */
  2083. X
  2084. X#ifdef MAIN_PROGRAM
  2085. X# if !defined(LINT) && !defined(lint)
  2086. Xchar    *copyright[] = {
  2087. X        "@(#) Copyright 1988,1989,1990,1993,1994 by Paul Vixie",
  2088. X        "@(#) All rights reserved"
  2089. X    };
  2090. X# endif
  2091. X
  2092. Xchar    *MonthNames[] = {
  2093. X        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  2094. X        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
  2095. X        NULL
  2096. X    };
  2097. X
  2098. Xchar    *DowNames[] = {
  2099. X        "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun",
  2100. X        NULL
  2101. X    };
  2102. X
  2103. Xchar    *ProgramName;
  2104. Xint    LineNumber;
  2105. Xtime_t    TargetTime;
  2106. X
  2107. X# if DEBUGGING
  2108. Xint    DebugFlags;
  2109. Xchar    *DebugFlagNames[] = {    /* sync with #defines */
  2110. X        "ext", "sch", "proc", "pars", "load", "misc", "test", "bit",
  2111. X        NULL        /* NULL must be last element */
  2112. X    };
  2113. X# endif /* DEBUGGING */
  2114. X#else /*MAIN_PROGRAM*/
  2115. Xextern    char    *copyright[],
  2116. X        *MonthNames[],
  2117. X        *DowNames[],
  2118. X        *ProgramName;
  2119. Xextern    int    LineNumber;
  2120. Xextern    time_t    TargetTime;
  2121. X# if DEBUGGING
  2122. Xextern    int    DebugFlags;
  2123. Xextern    char    *DebugFlagNames[];
  2124. X# endif /* DEBUGGING */
  2125. X#endif /*MAIN_PROGRAM*/
  2126. END_OF_FILE
  2127. if test 7715 -ne `wc -c <'cron.h'`; then
  2128.     echo shar: \"'cron.h'\" unpacked with wrong size!
  2129. fi
  2130. # end of 'cron.h'
  2131. fi
  2132. if test -f 'crontab.1' -a "${1}" != "-c" ; then 
  2133.   echo shar: Will not clobber existing file \"'crontab.1'\"
  2134. else
  2135. echo shar: Extracting \"'crontab.1'\" \(3140 characters\)
  2136. sed "s/^X//" >'crontab.1' <<'END_OF_FILE'
  2137. X.\"/* Copyright 1988,1990,1993 by Paul Vixie
  2138. X.\" * All rights reserved
  2139. X.\" *
  2140. X.\" * Distribute freely, except: don't remove my name from the source or
  2141. X.\" * documentation (don't take credit for my work), mark your changes (don't
  2142. X.\" * get me blamed for your possible bugs), don't alter or remove this
  2143. X.\" * notice.  May be sold if buildable source is provided to buyer.  No
  2144. X.\" * warrantee of any kind, express or implied, is included with this
  2145. X.\" * software; use at your own risk, responsibility for damages (if any) to
  2146. X.\" * anyone resulting from the use of this software rests entirely with the
  2147. X.\" * user.
  2148. X.\" *
  2149. X.\" * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
  2150. X.\" * I'll try to keep a version up to date.  I can be reached as follows:
  2151. X.\" * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
  2152. X.\" */
  2153. X.\"
  2154. X.\" $Id: crontab.1,v 2.4 1993/12/31 10:47:33 vixie Exp $
  2155. X.\"
  2156. X.TH CRONTAB 1 "29 December 1993"
  2157. X.UC 4
  2158. X.SH NAME
  2159. Xcrontab \- maintain crontab files for individual users (V3)
  2160. X.SH SYNOPSIS
  2161. Xcrontab [ -u user ] file
  2162. X.br
  2163. Xcrontab [ -u user ] { -l | -r | -e }
  2164. X.SH DESCRIPTION
  2165. X.I Crontab
  2166. Xis the program used to install, deinstall or list the tables
  2167. Xused to drive the
  2168. X.IR cron (8)
  2169. Xdaemon in Vixie Cron.  Each user can have their own crontab, and though
  2170. Xthese are files in /var, they are not intended to be edited directly.
  2171. X.PP
  2172. XIf the
  2173. X.I allow
  2174. Xfile exists, then you must be listed therein in order to be allowed to use
  2175. Xthis command.  If the
  2176. X.I allow
  2177. Xfile does not exist but the
  2178. X.I deny
  2179. Xfile does exist, then you must \fBnot\fR be listed in the
  2180. X.I deny
  2181. Xfile in order to use this command.  If neither of these files exists, then
  2182. Xdepending on site-dependent configuration parameters, only the super user
  2183. Xwill be allowed to use this command, or all users will be able to use this
  2184. Xcommand.
  2185. X.PP
  2186. XIf the
  2187. X.I -u
  2188. Xoption is given, it specifies the name of the user whose crontab is to be
  2189. Xtweaked.  If this option is not given,
  2190. X.I crontab
  2191. Xexamines "your" crontab, i.e., the crontab of the person executing the
  2192. Xcommand.  Note that
  2193. X.IR su (8)
  2194. Xcan confuse
  2195. X.I crontab
  2196. Xand that if you are running inside of
  2197. X.IR su (8)
  2198. Xyou should always use the
  2199. X.I -u
  2200. Xoption for safety's sake.
  2201. X.PP
  2202. XThe first form of this command is used to install a new crontab from some
  2203. Xnamed file or standard input if the pseudo-filename ``-'' is given.
  2204. X.PP
  2205. XThe
  2206. X.I -l
  2207. Xoption causes the current crontab to be displayed on standard output.
  2208. X.PP
  2209. XThe
  2210. X.I -r
  2211. Xoption causes the current crontab to be removed.
  2212. X.PP
  2213. XThe
  2214. X.I -e
  2215. Xoption is used to edit the current crontab using the editor specified by
  2216. Xthe \s-1VISUAL\s+1 or \s-1EDITOR\s+1 environment variables.  After you exit
  2217. Xfrom the editor, the modified crontab will be installed automatically.
  2218. X.SH "SEE ALSO"
  2219. Xcrontab(5), cron(8)
  2220. X.SH FILES
  2221. X.nf
  2222. X/var/cron/allow
  2223. X/var/cron/deny
  2224. X.fi
  2225. X.SH STANDARDS
  2226. XThe
  2227. X.I crontab
  2228. Xcommand conforms to IEEE Std1003.2-1992 (``POSIX'').  This new command syntax
  2229. Xdiffers from previous versions of Vixie Cron, as well as from the classic
  2230. XSVR3 syntax.
  2231. X.SH DIAGNOSTICS
  2232. XA fairly informative usage message appears if you run it with a bad command
  2233. Xline.
  2234. X.SH AUTHOR
  2235. X.nf
  2236. XPaul Vixie <paul@vix.com>
  2237. END_OF_FILE
  2238. if test 3140 -ne `wc -c <'crontab.1'`; then
  2239.     echo shar: \"'crontab.1'\" unpacked with wrong size!
  2240. fi
  2241. # end of 'crontab.1'
  2242. fi
  2243. if test -f 'crontab.5' -a "${1}" != "-c" ; then 
  2244.   echo shar: Will not clobber existing file \"'crontab.5'\"
  2245. else
  2246. echo shar: Extracting \"'crontab.5'\" \(7184 characters\)
  2247. sed "s/^X//" >'crontab.5' <<'END_OF_FILE'
  2248. X.\"/* Copyright 1988,1990,1993,1994 by Paul Vixie
  2249. X.\" * All rights reserved
  2250. X.\" *
  2251. X.\" * Distribute freely, except: don't remove my name from the source or
  2252. X.\" * documentation (don't take credit for my work), mark your changes (don't
  2253. X.\" * get me blamed for your possible bugs), don't alter or remove this
  2254. X.\" * notice.  May be sold if buildable source is provided to buyer.  No
  2255. X.\" * warrantee of any kind, express or implied, is included with this
  2256. X.\" * software; use at your own risk, responsibility for damages (if any) to
  2257. X.\" * anyone resulting from the use of this software rests entirely with the
  2258. X.\" * user.
  2259. X.\" *
  2260. X.\" * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
  2261. X.\" * I'll try to keep a version up to date.  I can be reached as follows:
  2262. X.\" * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
  2263. X.\" */
  2264. X.\"
  2265. X.\" $Id: crontab.5,v 2.4 1994/01/15 20:43:43 vixie Exp $
  2266. X.\" 
  2267. X.TH CRONTAB 5 "7 January 1994"
  2268. X.UC 4
  2269. X.SH NAME
  2270. Xcrontab \- tables for driving cron
  2271. X.SH DESCRIPTION
  2272. XA
  2273. X.I crontab
  2274. Xfile contains instructions to the
  2275. X.IR cron (8)
  2276. Xdaemon of the general form: ``run this command at this time on this date''.
  2277. XEach user has their own crontab, and commands in any given crontab will be
  2278. Xexecuted as the user who owns the crontab.  Uucp and News will usually have
  2279. Xtheir own crontabs, eliminating the need for explicitly running
  2280. X.IR su (1)
  2281. Xas part of a cron command.
  2282. X.PP
  2283. XBlank lines and leading spaces and tabs are ignored.  Lines whose first
  2284. Xnon-space character is a pound-sign (#) are comments, and are ignored.
  2285. XNote that comments are not allowed on the same line as cron commands, since
  2286. Xthey will be taken to be part of the command.  Similarly, comments are not
  2287. Xallowed on the same line as environment variable settings.
  2288. X.PP
  2289. XAn active line in a crontab will be either an environment setting or a cron
  2290. Xcommand.  An environment setting is of the form,
  2291. X.PP
  2292. X    name = value
  2293. X.PP
  2294. Xwhere the spaces around the equal-sign (=) are optional, and any subsequent
  2295. Xnon-leading spaces in
  2296. X.I value
  2297. Xwill be part of the value assigned to
  2298. X.IR name .
  2299. XThe
  2300. X.I value
  2301. Xstring may be placed in quotes (single or double, but matching) to preserve
  2302. Xleading or trailing blanks.
  2303. X.PP
  2304. XSeveral environment variables are set up
  2305. Xautomatically by the
  2306. X.IR cron (8)
  2307. Xdaemon.
  2308. XSHELL is set to /bin/sh, and LOGNAME and HOME are set from the /etc/passwd 
  2309. Xline of the crontab's owner.
  2310. XHOME and SHELL may be overridden by settings in the crontab; LOGNAME may not.
  2311. X.PP
  2312. X(Another note: the LOGNAME variable is sometimes called USER on BSD systems...
  2313. Xon these systems, USER will be set also.)
  2314. X.PP
  2315. XIn addition to LOGNAME, HOME, and SHELL,
  2316. X.IR cron (8)
  2317. Xwill look at MAILTO if it has any reason to send mail as a result of running
  2318. Xcommands in ``this'' crontab.  If MAILTO is defined (and non-empty), mail is
  2319. Xsent to the user so named.  If MAILTO is defined but empty (MAILTO=""), no
  2320. Xmail will be sent.  Otherwise mail is sent to the owner of the crontab.  This
  2321. Xoption is useful if you decide on /bin/mail instead of /usr/lib/sendmail as
  2322. Xyour mailer when you install cron -- /bin/mail doesn't do aliasing, and UUCP
  2323. Xusually doesn't read its mail.
  2324. X.PP
  2325. XThe format of a cron command is very much the V7 standard, with a number of
  2326. Xupward-compatible extensions.  Each line has five time and date fields,
  2327. Xfollowed by a command.  Commands are executed by
  2328. X.IR cron (8)
  2329. Xwhen the minute, hour, and month of year fields match the current time,
  2330. X.I and
  2331. Xwhen at least one of the two day fields (day of month, or day of week)
  2332. Xmatch the current time (see ``Note'' below).
  2333. X.IR cron (8)
  2334. Xexamines cron entries once every minute.
  2335. XThe time and date fields are:
  2336. X.IP
  2337. X.ta 1.5i
  2338. Xfield    allowed values
  2339. X.br
  2340. X-----    --------------
  2341. X.br
  2342. Xminute    0-59
  2343. X.br
  2344. Xhour    0-23
  2345. X.br
  2346. Xday of month    0-31
  2347. X.br
  2348. Xmonth    0-12 (or names, see below)
  2349. X.br
  2350. Xday of week    0-7 (0 or 7 is Sun, or use names)
  2351. X.br
  2352. X.PP
  2353. XA field may be an asterisk (*), which always stands for ``first\-last''.
  2354. X.PP
  2355. XRanges of numbers are allowed.  Ranges are two numbers separated
  2356. Xwith a hyphen.  The specified range is inclusive.  For example,
  2357. X8-11 for an ``hours'' entry specifies execution at hours 8, 9, 10
  2358. Xand 11.
  2359. X.PP
  2360. XLists are allowed.  A list is a set of numbers (or ranges)
  2361. Xseparated by commas.  Examples: ``1,2,5,9'', ``0-4,8-12''.
  2362. X.PP
  2363. XStep values can be used in conjunction with ranges.  Following
  2364. Xa range with ``/<number>'' specifies skips of the number's value
  2365. Xthrough the range.  For example, ``0-23/2'' can be used in the hours
  2366. Xfield to specify command execution every other hour (the alternative
  2367. Xin the V7 standard is ``0,2,4,6,8,10,12,14,16,18,20,22'').  Steps are
  2368. Xalso permitted after an asterisk, so if you want to say ``every two
  2369. Xhours'', just use ``*/2''.
  2370. X.PP
  2371. XNames can also be used for the ``month'' and ``day of week''
  2372. Xfields.  Use the first three letters of the particular
  2373. Xday or month (case doesn't matter).  Ranges or
  2374. Xlists of names are not allowed.
  2375. X.PP
  2376. XThe ``sixth'' field (the rest of the line) specifies the command to be
  2377. Xrun.
  2378. XThe entire command portion of the line, up to a newline or %
  2379. Xcharacter, will be executed by the user's login shell or by the shell
  2380. Xspecified in the SHELL variable of the cronfile.
  2381. XPercent-signs (%) in the command, unless escaped with backslash
  2382. X(\\), will be changed into newline characters, and all data
  2383. Xafter the first % will be sent to the command as standard
  2384. Xinput.
  2385. X.PP
  2386. XNote: The day of a command's execution can be specified by two
  2387. Xfields \(em day of month, and day of week.  If both fields are
  2388. Xrestricted (ie, aren't *), the command will be run when
  2389. X.I either
  2390. Xfield matches the current time.  For example,
  2391. X.br
  2392. X``30 4 1,15 * 5''
  2393. Xwould cause a command to be run at 4:30 am on the 1st and 15th of each
  2394. Xmonth, plus every Friday.
  2395. X.SH EXAMPLE CRON FILE
  2396. X.nf
  2397. X
  2398. X# use /bin/sh to run commands, no matter what /etc/passwd says
  2399. XSHELL=/bin/sh
  2400. X# mail any output to `paul', no matter whose crontab this is
  2401. XMAILTO=paul
  2402. X#
  2403. X# run five minutes after midnight, every day
  2404. X5 0 * * *       $HOME/bin/daily.job >> $HOME/tmp/out 2>&1
  2405. X# run at 2:15pm on the first of every month -- output mailed to paul
  2406. X15 14 1 * *     $HOME/bin/monthly
  2407. X# run at 10 pm on weekdays, annoy Joe
  2408. X0 22 * * 1-5    mail -s "It's 10pm" joe%Joe,%%Where are your kids?%
  2409. X23 0-23/2 * * * echo "run 23 minutes after midn, 2am, 4am ..., everyday"
  2410. X5 4 * * sun     echo "run at 5 after 4 every sunday"
  2411. X.fi
  2412. X.SH SEE ALSO
  2413. Xcron(8), crontab(1)
  2414. X.SH EXTENSIONS
  2415. XWhen specifying day of week, both day 0 and day 7 will be considered Sunday.
  2416. XBSD and ATT seem to disagree about this.
  2417. X.PP
  2418. XLists and ranges are allowed to co-exist in the same field.  "1-3,7-9" would
  2419. Xbe rejected by ATT or BSD cron -- they want to see "1-3" or "7,8,9" ONLY.
  2420. X.PP
  2421. XRanges can include "steps", so "1-9/2" is the same as "1,3,5,7,9".
  2422. X.PP
  2423. XNames of months or days of the week can be specified by name.
  2424. X.PP
  2425. XEnvironment variables can be set in the crontab.  In BSD or ATT, the
  2426. Xenvironment handed to child processes is basically the one from /etc/rc.
  2427. X.PP
  2428. XCommand output is mailed to the crontab owner (BSD can't do this), can be
  2429. Xmailed to a person other than the crontab owner (SysV can't do this), or the
  2430. Xfeature can be turned off and no mail will be sent at all (SysV can't do this
  2431. Xeither).
  2432. X.SH AUTHOR
  2433. X.nf
  2434. XPaul Vixie <paul@vix.com>
  2435. END_OF_FILE
  2436. if test 7184 -ne `wc -c <'crontab.5'`; then
  2437.     echo shar: \"'crontab.5'\" unpacked with wrong size!
  2438. fi
  2439. # end of 'crontab.5'
  2440. fi
  2441. if test -f 'database.c' -a "${1}" != "-c" ; then 
  2442.   echo shar: Will not clobber existing file \"'database.c'\"
  2443. else
  2444. echo shar: Extracting \"'database.c'\" \(6518 characters\)
  2445. sed "s/^X//" >'database.c' <<'END_OF_FILE'
  2446. X/* Copyright 1988,1990,1993,1994 by Paul Vixie
  2447. X * All rights reserved
  2448. X *
  2449. X * Distribute freely, except: don't remove my name from the source or
  2450. X * documentation (don't take credit for my work), mark your changes (don't
  2451. X * get me blamed for your possible bugs), don't alter or remove this
  2452. X * notice.  May be sold if buildable source is provided to buyer.  No
  2453. X * warrantee of any kind, express or implied, is included with this
  2454. X * software; use at your own risk, responsibility for damages (if any) to
  2455. X * anyone resulting from the use of this software rests entirely with the
  2456. X * user.
  2457. X *
  2458. X * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
  2459. X * I'll try to keep a version up to date.  I can be reached as follows:
  2460. X * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
  2461. X */
  2462. X
  2463. X#if !defined(lint) && !defined(LINT)
  2464. Xstatic char rcsid[] = "$Id: database.c,v 2.8 1994/01/15 20:43:43 vixie Exp $";
  2465. X#endif
  2466. X
  2467. X/* vix 26jan87 [RCS has the log]
  2468. X */
  2469. X
  2470. X
  2471. X#include "cron.h"
  2472. X#include <fcntl.h>
  2473. X#include <sys/stat.h>
  2474. X#include <sys/file.h>
  2475. X
  2476. X
  2477. X#define TMAX(a,b) ((a)>(b)?(a):(b))
  2478. X
  2479. X
  2480. Xstatic    void        process_crontab __P((char *, char *, char *,
  2481. X                         struct stat *,
  2482. X                         cron_db *, cron_db *));
  2483. X
  2484. X
  2485. Xvoid
  2486. Xload_database(old_db)
  2487. X    cron_db        *old_db;
  2488. X{
  2489. X    DIR        *dir;
  2490. X    struct stat    statbuf;
  2491. X    struct stat    syscron_stat;
  2492. X    DIR_T       *dp;
  2493. X    cron_db        new_db;
  2494. X    user        *u, *nu;
  2495. X
  2496. X    Debug(DLOAD, ("[%d] load_database()\n", getpid()))
  2497. X
  2498. X    /* before we start loading any data, do a stat on SPOOL_DIR
  2499. X     * so that if anything changes as of this moment (i.e., before we've
  2500. X     * cached any of the database), we'll see the changes next time.
  2501. X     */
  2502. X    if (stat(SPOOL_DIR, &statbuf) < OK) {
  2503. X        log_it("CRON", getpid(), "STAT FAILED", SPOOL_DIR);
  2504. X        (void) exit(ERROR_EXIT);
  2505. X    }
  2506. X
  2507. X    /* track system crontab file
  2508. X     */
  2509. X    if (stat(SYSCRONTAB, &syscron_stat) < OK)
  2510. X        syscron_stat.st_mtime = 0;
  2511. X
  2512. X    /* if spooldir's mtime has not changed, we don't need to fiddle with
  2513. X     * the database.
  2514. X     *
  2515. X     * Note that old_db->mtime is initialized to 0 in main(), and
  2516. X     * so is guaranteed to be different than the stat() mtime the first
  2517. X     * time this function is called.
  2518. X     */
  2519. X    if (old_db->mtime == TMAX(statbuf.st_mtime, syscron_stat.st_mtime)) {
  2520. X        Debug(DLOAD, ("[%d] spool dir mtime unch, no load needed.\n",
  2521. X                  getpid()))
  2522. X        return;
  2523. X    }
  2524. X
  2525. X    /* something's different.  make a new database, moving unchanged
  2526. X     * elements from the old database, reloading elements that have
  2527. X     * actually changed.  Whatever is left in the old database when
  2528. X     * we're done is chaff -- crontabs that disappeared.
  2529. X     */
  2530. X    new_db.mtime = TMAX(statbuf.st_mtime, syscron_stat.st_mtime);
  2531. X    new_db.head = new_db.tail = NULL;
  2532. X
  2533. X    if (syscron_stat.st_mtime) {
  2534. X        process_crontab("root", "*system*",
  2535. X                SYSCRONTAB, &syscron_stat,
  2536. X                &new_db, old_db);
  2537. X    }
  2538. X
  2539. X    /* we used to keep this dir open all the time, for the sake of
  2540. X     * efficiency.  however, we need to close it in every fork, and
  2541. X     * we fork a lot more often than the mtime of the dir changes.
  2542. X     */
  2543. X    if (!(dir = opendir(SPOOL_DIR))) {
  2544. X        log_it("CRON", getpid(), "OPENDIR FAILED", SPOOL_DIR);
  2545. X        (void) exit(ERROR_EXIT);
  2546. X    }
  2547. X
  2548. X    while (NULL != (dp = readdir(dir))) {
  2549. X        char    fname[MAXNAMLEN+1],
  2550. X            tabname[MAXNAMLEN+1];
  2551. X
  2552. X        /* avoid file names beginning with ".".  this is good
  2553. X         * because we would otherwise waste two guaranteed calls
  2554. X         * to getpwnam() for . and .., and also because user names
  2555. X         * starting with a period are just too nasty to consider.
  2556. X         */
  2557. X        if (dp->d_name[0] == '.')
  2558. X            continue;
  2559. X
  2560. X        (void) strcpy(fname, dp->d_name);
  2561. X        sprintf(tabname, CRON_TAB(fname));
  2562. X
  2563. X        process_crontab(fname, fname, tabname,
  2564. X                &statbuf, &new_db, old_db);
  2565. X    }
  2566. X    closedir(dir);
  2567. X
  2568. X    /* if we don't do this, then when our children eventually call
  2569. X     * getpwnam() in do_command.c's child_process to verify MAILTO=,
  2570. X     * they will screw us up (and v-v).
  2571. X     */
  2572. X    endpwent();
  2573. X
  2574. X    /* whatever's left in the old database is now junk.
  2575. X     */
  2576. X    Debug(DLOAD, ("unlinking old database:\n"))
  2577. X    for (u = old_db->head;  u != NULL;  u = nu) {
  2578. X        Debug(DLOAD, ("\t%s\n", u->name))
  2579. X        nu = u->next;
  2580. X        unlink_user(old_db, u);
  2581. X        free_user(u);
  2582. X    }
  2583. X
  2584. X    /* overwrite the database control block with the new one.
  2585. X     */
  2586. X    *old_db = new_db;
  2587. X    Debug(DLOAD, ("load_database is done\n"))
  2588. X}
  2589. X
  2590. X
  2591. Xvoid
  2592. Xlink_user(db, u)
  2593. X    cron_db    *db;
  2594. X    user    *u;
  2595. X{
  2596. X    if (db->head == NULL)
  2597. X        db->head = u;
  2598. X    if (db->tail)
  2599. X        db->tail->next = u;
  2600. X    u->prev = db->tail;
  2601. X    u->next = NULL;
  2602. X    db->tail = u;
  2603. X}
  2604. X
  2605. X
  2606. Xvoid
  2607. Xunlink_user(db, u)
  2608. X    cron_db    *db;
  2609. X    user    *u;
  2610. X{
  2611. X    if (u->prev == NULL)
  2612. X        db->head = u->next;
  2613. X    else
  2614. X        u->prev->next = u->next;
  2615. X
  2616. X    if (u->next == NULL)
  2617. X        db->tail = u->prev;
  2618. X    else
  2619. X        u->next->prev = u->prev;
  2620. X}
  2621. X
  2622. X
  2623. Xuser *
  2624. Xfind_user(db, name)
  2625. X    cron_db    *db;
  2626. X    char    *name;
  2627. X{
  2628. X    char    *env_get();
  2629. X    user    *u;
  2630. X
  2631. X    for (u = db->head;  u != NULL;  u = u->next)
  2632. X        if (!strcmp(u->name, name))
  2633. X            break;
  2634. X    return u;
  2635. X}
  2636. X
  2637. X
  2638. Xstatic void
  2639. Xprocess_crontab(uname, fname, tabname, statbuf, new_db, old_db)
  2640. X    char        *uname;
  2641. X    char        *fname;
  2642. X    char        *tabname;
  2643. X    struct stat    *statbuf;
  2644. X    cron_db        *new_db;
  2645. X    cron_db        *old_db;
  2646. X{
  2647. X    struct passwd    *pw = NULL;
  2648. X    int        crontab_fd = OK - 1;
  2649. X    user        *u;
  2650. X
  2651. X    if (strcmp(fname, "*system*") && !(pw = getpwnam(uname))) {
  2652. X        /* file doesn't have a user in passwd file.
  2653. X         */
  2654. X        log_it(fname, getpid(), "ORPHAN", "no passwd entry");
  2655. X        goto next_crontab;
  2656. X    }
  2657. X
  2658. X    if ((crontab_fd = open(tabname, O_RDONLY, 0)) < OK) {
  2659. X        /* crontab not accessible?
  2660. X         */
  2661. X        log_it(fname, getpid(), "CAN'T OPEN", tabname);
  2662. X        goto next_crontab;
  2663. X    }
  2664. X
  2665. X    if (fstat(crontab_fd, statbuf) < OK) {
  2666. X        log_it(fname, getpid(), "FSTAT FAILED", tabname);
  2667. X        goto next_crontab;
  2668. X    }
  2669. X
  2670. X    Debug(DLOAD, ("\t%s:", fname))
  2671. X    u = find_user(old_db, fname);
  2672. X    if (u != NULL) {
  2673. X        /* if crontab has not changed since we last read it
  2674. X         * in, then we can just use our existing entry.
  2675. X         */
  2676. X        if (u->mtime == statbuf->st_mtime) {
  2677. X            Debug(DLOAD, (" [no change, using old data]"))
  2678. X            unlink_user(old_db, u);
  2679. X            link_user(new_db, u);
  2680. X            goto next_crontab;
  2681. X        }
  2682. X
  2683. X        /* before we fall through to the code that will reload
  2684. X         * the user, let's deallocate and unlink the user in
  2685. X         * the old database.  This is more a point of memory
  2686. X         * efficiency than anything else, since all leftover
  2687. X         * users will be deleted from the old database when
  2688. X         * we finish with the crontab...
  2689. X         */
  2690. X        Debug(DLOAD, (" [delete old data]"))
  2691. X        unlink_user(old_db, u);
  2692. X        free_user(u);
  2693. X        log_it(fname, getpid(), "RELOAD", tabname);
  2694. X    }
  2695. X    u = load_user(crontab_fd, pw, fname);
  2696. X    if (u != NULL) {
  2697. X        u->mtime = statbuf->st_mtime;
  2698. X        link_user(new_db, u);
  2699. X    }
  2700. X
  2701. Xnext_crontab:
  2702. X    if (crontab_fd >= OK) {
  2703. X        Debug(DLOAD, (" [done]\n"))
  2704. X        close(crontab_fd);
  2705. X    }
  2706. X}
  2707. END_OF_FILE
  2708. if test 6518 -ne `wc -c <'database.c'`; then
  2709.     echo shar: \"'database.c'\" unpacked with wrong size!
  2710. fi
  2711. # end of 'database.c'
  2712. fi
  2713. if test -f 'env.c' -a "${1}" != "-c" ; then 
  2714.   echo shar: Will not clobber existing file \"'env.c'\"
  2715. else
  2716. echo shar: Extracting \"'env.c'\" \(3731 characters\)
  2717. sed "s/^X//" >'env.c' <<'END_OF_FILE'
  2718. X/* Copyright 1988,1990,1993,1994 by Paul Vixie
  2719. X * All rights reserved
  2720. X *
  2721. X * Distribute freely, except: don't remove my name from the source or
  2722. X * documentation (don't take credit for my work), mark your changes (don't
  2723. X * get me blamed for your possible bugs), don't alter or remove this
  2724. X * notice.  May be sold if buildable source is provided to buyer.  No
  2725. X * warrantee of any kind, express or implied, is included with this
  2726. X * software; use at your own risk, responsibility for damages (if any) to
  2727. X * anyone resulting from the use of this software rests entirely with the
  2728. X * user.
  2729. X *
  2730. X * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
  2731. X * I'll try to keep a version up to date.  I can be reached as follows:
  2732. X * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
  2733. X */
  2734. X
  2735. X#if !defined(lint) && !defined(LINT)
  2736. Xstatic char rcsid[] = "$Id: env.c,v 2.6 1994/01/15 20:43:43 vixie Exp $";
  2737. X#endif
  2738. X
  2739. X
  2740. X#include "cron.h"
  2741. X
  2742. X
  2743. Xchar **
  2744. Xenv_init()
  2745. X{
  2746. X    register char    **p = (char **) malloc(sizeof(char **));
  2747. X
  2748. X    p[0] = NULL;
  2749. X    return p;
  2750. X}
  2751. X
  2752. X
  2753. Xvoid
  2754. Xenv_free(envp)
  2755. X    char    **envp;
  2756. X{
  2757. X    char    **p;
  2758. X
  2759. X    for (p = envp;  *p;  p++)
  2760. X        free(*p);
  2761. X    free(envp);
  2762. X}
  2763. X
  2764. X
  2765. Xchar **
  2766. Xenv_copy(envp)
  2767. X    register char    **envp;
  2768. X{
  2769. X    register int    count, i;
  2770. X    register char    **p;
  2771. X
  2772. X    for (count = 0;  envp[count] != NULL;  count++)
  2773. X        ;
  2774. X    p = (char **) malloc((count+1) * sizeof(char *));  /* 1 for the NULL */
  2775. X    for (i = 0;  i < count;  i++)
  2776. X        p[i] = strdup(envp[i]);
  2777. X    p[count] = NULL;
  2778. X    return p;
  2779. X}
  2780. X
  2781. X
  2782. Xchar **
  2783. Xenv_set(envp, envstr)
  2784. X    char    **envp;
  2785. X    char    *envstr;
  2786. X{
  2787. X    register int    count, found;
  2788. X    register char    **p;
  2789. X
  2790. X    /*
  2791. X     * count the number of elements, including the null pointer;
  2792. X     * also set 'found' to -1 or index of entry if already in here.
  2793. X     */
  2794. X    found = -1;
  2795. X    for (count = 0;  envp[count] != NULL;  count++) {
  2796. X        if (!strcmp_until(envp[count], envstr, '='))
  2797. X            found = count;
  2798. X    }
  2799. X    count++;    /* for the NULL */
  2800. X
  2801. X    if (found != -1) {
  2802. X        /*
  2803. X         * it exists already, so just free the existing setting,
  2804. X         * save our new one there, and return the existing array.
  2805. X         */
  2806. X        free(envp[found]);
  2807. X        envp[found] = strdup(envstr);
  2808. X        return envp;
  2809. X    }
  2810. X
  2811. X    /*
  2812. X     * it doesn't exist yet, so resize the array, move null pointer over
  2813. X     * one, save our string over the old null pointer, and return resized
  2814. X     * array.
  2815. X     */
  2816. X    p = (char **) realloc((void *) envp,
  2817. X                  (unsigned) ((count+1) * sizeof(char **)));
  2818. X    p[count] = p[count-1];
  2819. X    p[count-1] = strdup(envstr);
  2820. X    return p;
  2821. X}
  2822. X
  2823. X
  2824. X/* return    ERR = end of file
  2825. X *        FALSE = not an env setting (file was repositioned)
  2826. X *        TRUE = was an env setting
  2827. X */
  2828. Xint
  2829. Xload_env(envstr, f)
  2830. X    char    *envstr;
  2831. X    FILE    *f;
  2832. X{
  2833. X    long    filepos;
  2834. X    int    fileline;
  2835. X    char    name[MAX_TEMPSTR], val[MAX_ENVSTR];
  2836. X    int    fields;
  2837. X
  2838. X    filepos = ftell(f);
  2839. X    fileline = LineNumber;
  2840. X    skip_comments(f);
  2841. X    if (EOF == get_string(envstr, MAX_ENVSTR, f, "\n"))
  2842. X        return ERR;
  2843. X
  2844. X    Debug(DPARS, ("load_env, read <%s>\n", envstr))
  2845. X
  2846. X    name[0] = val[0] = '\0';
  2847. X    fields = sscanf(envstr, "%[^ =] = %[^\n#]", name, val);
  2848. X    if (fields != 2) {
  2849. X        Debug(DPARS, ("load_env, not 2 fields (%d)\n", fields))
  2850. X        fseek(f, filepos, 0);
  2851. X        Set_LineNum(fileline);
  2852. X        return FALSE;
  2853. X    }
  2854. X
  2855. X    /* 2 fields from scanf; looks like an env setting
  2856. X     */
  2857. X
  2858. X    /*
  2859. X     * process value string
  2860. X     */
  2861. X    /*local*/{
  2862. X        int    len = strdtb(val);
  2863. X
  2864. X        if (len >= 2) {
  2865. X            if (val[0] == '\'' || val[0] == '"') {
  2866. X                if (val[len-1] == val[0]) {
  2867. X                    val[len-1] = '\0';
  2868. X                    (void) strcpy(val, val+1);
  2869. X                }
  2870. X            }
  2871. X        }
  2872. X    }
  2873. X
  2874. X    (void) sprintf(envstr, "%s=%s", name, val);
  2875. X    Debug(DPARS, ("load_env, <%s> <%s> -> <%s>\n", name, val, envstr))
  2876. X    return TRUE;
  2877. X}
  2878. X
  2879. X
  2880. Xchar *
  2881. Xenv_get(name, envp)
  2882. X    register char    *name;
  2883. X    register char    **envp;
  2884. X{
  2885. X    for (;  *envp;  envp++) {
  2886. X        register char    *p = strchr(*envp, '=');
  2887. X        if (p && !strncmp(*envp, name, p - *envp))
  2888. X            return p+1;
  2889. X    }
  2890. X    return NULL;
  2891. X}
  2892. END_OF_FILE
  2893. if test 3731 -ne `wc -c <'env.c'`; then
  2894.     echo shar: \"'env.c'\" unpacked with wrong size!
  2895. fi
  2896. # end of 'env.c'
  2897. fi
  2898. if test -f 'externs.h' -a "${1}" != "-c" ; then 
  2899.   echo shar: Will not clobber existing file \"'externs.h'\"
  2900. else
  2901. echo shar: Extracting \"'externs.h'\" \(3628 characters\)
  2902. sed "s/^X//" >'externs.h' <<'END_OF_FILE'
  2903. X/* Copyright 1993,1994 by Paul Vixie
  2904. X * All rights reserved
  2905. X *
  2906. X * Distribute freely, except: don't remove my name from the source or
  2907. X * documentation (don't take credit for my work), mark your changes (don't
  2908. X * get me blamed for your possible bugs), don't alter or remove this
  2909. X * notice.  May be sold if buildable source is provided to buyer.  No
  2910. X * warrantee of any kind, express or implied, is included with this
  2911. X * software; use at your own risk, responsibility for damages (if any) to
  2912. X * anyone resulting from the use of this software rests entirely with the
  2913. X * user.
  2914. X *
  2915. X * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
  2916. X * I'll try to keep a version up to date.  I can be reached as follows:
  2917. X * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
  2918. X */
  2919. X
  2920. X#if defined(POSIX) || defined(ATT)
  2921. X# include <stdlib.h>
  2922. X# include <unistd.h>
  2923. X# include <string.h>
  2924. X# include <dirent.h>
  2925. X# define DIR_T    struct dirent
  2926. X# define WAIT_T    int
  2927. X# define WAIT_IS_INT 1
  2928. Xextern char *tzname[2];
  2929. X# define TZONE(tm) tzname[(tm).tm_isdst]
  2930. X#endif
  2931. X
  2932. X#if defined(UNIXPC)
  2933. X# undef WAIT_T
  2934. X# undef WAIT_IS_INT
  2935. X# define WAIT_T    union wait
  2936. X#endif
  2937. X
  2938. X#if defined(POSIX)
  2939. X# define SIG_T    sig_t
  2940. X# define TIME_T    time_t
  2941. X# define PID_T pid_t
  2942. X#endif
  2943. X
  2944. X#if defined(ATT)
  2945. X# define SIG_T    void
  2946. X# define TIME_T    long
  2947. X# define PID_T int
  2948. X#endif
  2949. X
  2950. X#if !defined(POSIX) && !defined(ATT)
  2951. X/* classic BSD */
  2952. Xextern    time_t        time();
  2953. Xextern    unsigned    sleep();
  2954. Xextern    struct tm    *localtime();
  2955. Xextern    struct passwd    *getpwnam();
  2956. Xextern    int        errno;
  2957. Xextern    void        perror(), exit(), free();
  2958. Xextern    char        *getenv(), *strcpy(), *strchr(), *strtok();
  2959. Xextern    void        *malloc(), *realloc();
  2960. X# define SIG_T    void
  2961. X# define TIME_T    long
  2962. X# define PID_T int
  2963. X# define WAIT_T    union wait
  2964. X# define DIR_T    struct direct
  2965. X# include <sys/dir.h>
  2966. X# define TZONE(tm) (tm).tm_zone
  2967. X#endif
  2968. X
  2969. X/* getopt() isn't part of POSIX.  some systems define it in <stdlib.h> anyway.
  2970. X * of those that do, some complain that our definition is different and some
  2971. X * do not.  to add to the misery and confusion, some systems define getopt()
  2972. X * in ways that we cannot predict or comprehend, yet do not define the adjunct
  2973. X * external variables needed for the interface.
  2974. X */
  2975. X#if (!defined(BSD) || (BSD < 198911)) && !defined(ATT) && !defined(UNICOS)
  2976. Xint    getopt __P((int, char * const *, const char *));
  2977. X#endif
  2978. X
  2979. X#if (!defined(BSD) || (BSD < 199103))
  2980. Xextern    char *optarg;
  2981. Xextern    int optind, opterr, optopt;
  2982. X#endif
  2983. X
  2984. X#if WAIT_IS_INT
  2985. X# ifndef WEXITSTATUS
  2986. X#  define WEXITSTATUS(x) (((x) >> 8) & 0xff)
  2987. X# endif
  2988. X# ifndef WTERMSIG
  2989. X#  define WTERMSIG(x)    ((x) & 0x7f)
  2990. X# endif
  2991. X# ifndef WCOREDUMP
  2992. X#  define WCOREDUMP(x)    ((x) & 0x80)
  2993. X# endif
  2994. X#else /*WAIT_IS_INT*/
  2995. X# ifndef WEXITSTATUS
  2996. X#  define WEXITSTATUS(x) ((x).w_retcode)
  2997. X# endif
  2998. X# ifndef WTERMSIG
  2999. X#  define WTERMSIG(x)    ((x).w_termsig)
  3000. X# endif
  3001. X# ifndef WCOREDUMP
  3002. X#  define WCOREDUMP(x)    ((x).w_coredump)
  3003. X# endif
  3004. X#endif /*WAIT_IS_INT*/
  3005. X
  3006. X#ifndef WIFSIGNALED
  3007. X#define WIFSIGNALED(x)    (WTERMSIG(x) != 0)
  3008. X#endif
  3009. X#ifndef WIFEXITED
  3010. X#define WIFEXITED(x)    (WTERMSIG(x) == 0)
  3011. X#endif
  3012. X
  3013. X#ifdef NEED_STRCASECMP
  3014. Xextern    int        strcasecmp __P((char *, char *));
  3015. X#endif
  3016. X
  3017. X#ifdef NEED_STRDUP
  3018. Xextern    char        *strdup __P((char *));
  3019. X#endif
  3020. X
  3021. X#ifdef NEED_STRERROR
  3022. Xextern    char        *strerror __P((int));
  3023. X#endif
  3024. X
  3025. X#ifdef NEED_FLOCK
  3026. Xextern    int        flock __P((int, int));
  3027. X# define LOCK_SH 1
  3028. X# define LOCK_EX 2
  3029. X# define LOCK_NB 4
  3030. X# define LOCK_UN 8
  3031. X#endif
  3032. X
  3033. X#ifdef NEED_SETSID
  3034. Xextern    int        setsid __P((void));
  3035. X#endif
  3036. X
  3037. X#ifdef NEED_GETDTABLESIZE
  3038. Xextern    int        getdtablesize __P((void));
  3039. X#endif
  3040. X
  3041. X#ifdef NEED_SETENV
  3042. Xextern    int        setenv __P((char *, char *, int));
  3043. X#endif
  3044. X
  3045. X#ifdef NEED_VFORK
  3046. Xextern    PID_T        vfork __P((void));
  3047. X#endif
  3048. END_OF_FILE
  3049. if test 3628 -ne `wc -c <'externs.h'`; then
  3050.     echo shar: \"'externs.h'\" unpacked with wrong size!
  3051. fi
  3052. # end of 'externs.h'
  3053. fi
  3054. if test -f 'job.c' -a "${1}" != "-c" ; then 
  3055.   echo shar: Will not clobber existing file \"'job.c'\"
  3056. else
  3057. echo shar: Extracting \"'job.c'\" \(1656 characters\)
  3058. sed "s/^X//" >'job.c' <<'END_OF_FILE'
  3059. X/* Copyright 1988,1990,1993,1994 by Paul Vixie
  3060. X * All rights reserved
  3061. X *
  3062. X * Distribute freely, except: don't remove my name from the source or
  3063. X * documentation (don't take credit for my work), mark your changes (don't
  3064. X * get me blamed for your possible bugs), don't alter or remove this
  3065. X * notice.  May be sold if buildable source is provided to buyer.  No
  3066. X * warrantee of any kind, express or implied, is included with this
  3067. X * software; use at your own risk, responsibility for damages (if any) to
  3068. X * anyone resulting from the use of this software rests entirely with the
  3069. X * user.
  3070. X *
  3071. X * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
  3072. X * I'll try to keep a version up to date.  I can be reached as follows:
  3073. X * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
  3074. X */
  3075. X
  3076. X#if !defined(lint) && !defined(LINT)
  3077. Xstatic char rcsid[] = "$Id: job.c,v 1.6 1994/01/15 20:43:43 vixie Exp $";
  3078. X#endif
  3079. X
  3080. X
  3081. X#include "cron.h"
  3082. X
  3083. X
  3084. Xtypedef    struct _job {
  3085. X    struct _job    *next;
  3086. X    entry        *e;
  3087. X    user        *u;
  3088. X} job;
  3089. X
  3090. X
  3091. Xstatic job    *jhead = NULL, *jtail = NULL;
  3092. X
  3093. X
  3094. Xvoid
  3095. Xjob_add(e, u)
  3096. X    register entry *e;
  3097. X    register user *u;
  3098. X{
  3099. X    register job *j;
  3100. X
  3101. X    /* if already on queue, keep going */
  3102. X    for (j=jhead; j; j=j->next)
  3103. X        if (j->e == e && j->u == u) { return; }
  3104. X
  3105. X    /* build a job queue element */
  3106. X    j = (job*)malloc(sizeof(job));
  3107. X    j->next = (job*) NULL;
  3108. X    j->e = e;
  3109. X    j->u = u;
  3110. X
  3111. X    /* add it to the tail */
  3112. X    if (!jhead) { jhead=j; }
  3113. X    else { jtail->next=j; }
  3114. X    jtail = j;
  3115. X}
  3116. X
  3117. X
  3118. Xint
  3119. Xjob_runqueue()
  3120. X{
  3121. X    register job    *j, *jn;
  3122. X    register int    run = 0;
  3123. X
  3124. X    for (j=jhead; j; j=jn) {
  3125. X        do_command(j->e, j->u);
  3126. X        jn = j->next;
  3127. X        free(j);
  3128. X        run++;
  3129. X    }
  3130. X    jhead = jtail = NULL;
  3131. X    return run;
  3132. X}
  3133. END_OF_FILE
  3134. if test 1656 -ne `wc -c <'job.c'`; then
  3135.     echo shar: \"'job.c'\" unpacked with wrong size!
  3136. fi
  3137. # end of 'job.c'
  3138. fi
  3139. if test -f 'pathnames.h' -a "${1}" != "-c" ; then 
  3140.   echo shar: Will not clobber existing file \"'pathnames.h'\"
  3141. else
  3142. echo shar: Extracting \"'pathnames.h'\" \(2494 characters\)
  3143. sed "s/^X//" >'pathnames.h' <<'END_OF_FILE'
  3144. X/* Copyright 1993,1994 by Paul Vixie
  3145. X * All rights reserved
  3146. X *
  3147. X * Distribute freely, except: don't remove my name from the source or
  3148. X * documentation (don't take credit for my work), mark your changes (don't
  3149. X * get me blamed for your possible bugs), don't alter or remove this
  3150. X * notice.  May be sold if buildable source is provided to buyer.  No
  3151. X * warrantee of any kind, express or implied, is included with this
  3152. X * software; use at your own risk, responsibility for damages (if any) to
  3153. X * anyone resulting from the use of this software rests entirely with the
  3154. X * user.
  3155. X *
  3156. X * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
  3157. X * I'll try to keep a version up to date.  I can be reached as follows:
  3158. X * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
  3159. X */
  3160. X
  3161. X/*
  3162. X * $Id: pathnames.h,v 1.3 1994/01/15 20:43:43 vixie Exp $
  3163. X */
  3164. X
  3165. X#if (defined(BSD)) && (BSD >= 199103) || defined(__linux) || defined(AIX)
  3166. X# include <paths.h>
  3167. X#endif /*BSD*/
  3168. X
  3169. X#ifndef CRONDIR
  3170. X            /* CRONDIR is where crond(8) and crontab(1) both chdir
  3171. X             * to; SPOOL_DIR, ALLOW_FILE, DENY_FILE, and LOG_FILE
  3172. X             * are all relative to this directory.
  3173. X             */
  3174. X#define CRONDIR        "/var/cron"
  3175. X#endif
  3176. X
  3177. X            /* SPOOLDIR is where the crontabs live.
  3178. X             * This directory will have its modtime updated
  3179. X             * whenever crontab(1) changes a crontab; this is
  3180. X             * the signal for crond(8) to look at each individual
  3181. X             * crontab file and reload those whose modtimes are
  3182. X             * newer than they were last time around (or which
  3183. X             * didn't exist last time around...)
  3184. X             */
  3185. X#define SPOOL_DIR    "tabs"
  3186. X
  3187. X            /* undefining these turns off their features.  note
  3188. X             * that ALLOW_FILE and DENY_FILE must both be defined
  3189. X             * in order to enable the allow/deny code.  If neither
  3190. X             * LOG_FILE or SYSLOG is defined, we don't log.  If
  3191. X             * both are defined, we log both ways.
  3192. X             */
  3193. X#define    ALLOW_FILE    "allow"        /*-*/
  3194. X#define DENY_FILE    "deny"        /*-*/
  3195. X#define LOG_FILE    "log"        /*-*/
  3196. X
  3197. X            /* where should the daemon stick its PID?
  3198. X             */
  3199. X#ifdef _PATH_VARRUN
  3200. X# define PIDDIR    _PATH_VARRUN
  3201. X#else
  3202. X# define PIDDIR "/etc/"
  3203. X#endif
  3204. X#define PIDFILE        "%scron.pid"
  3205. X
  3206. X            /* 4.3BSD-style crontab */
  3207. X#define SYSCRONTAB    "/etc/crontab"
  3208. X
  3209. X            /* what editor to use if no EDITOR or VISUAL
  3210. X             * environment variable specified.
  3211. X             */
  3212. X#if defined(_PATH_VI)
  3213. X# define EDITOR _PATH_VI
  3214. X#else
  3215. X# define EDITOR "/usr/ucb/vi"
  3216. X#endif
  3217. X
  3218. X#ifndef _PATH_BSHELL
  3219. X# define _PATH_BSHELL "/bin/sh"
  3220. X#endif
  3221. X
  3222. X#ifndef _PATH_DEFPATH
  3223. X# define _PATH_DEFPATH "/usr/bin:/bin"
  3224. X#endif
  3225. END_OF_FILE
  3226. if test 2494 -ne `wc -c <'pathnames.h'`; then
  3227.     echo shar: \"'pathnames.h'\" unpacked with wrong size!
  3228. fi
  3229. # end of 'pathnames.h'
  3230. fi
  3231. if test -f 'popen.c' -a "${1}" != "-c" ; then 
  3232.   echo shar: Will not clobber existing file \"'popen.c'\"
  3233. else
  3234. echo shar: Extracting \"'popen.c'\" \(4044 characters\)
  3235. sed "s/^X//" >'popen.c' <<'END_OF_FILE'
  3236. X/*
  3237. X * Copyright (c) 1988 The Regents of the University of California.
  3238. X * All rights reserved.
  3239. X *
  3240. X * This code is derived from software written by Ken Arnold and
  3241. X * published in UNIX Review, Vol. 6, No. 8.
  3242. X *
  3243. X * Redistribution and use in source and binary forms are permitted
  3244. X * provided that the above copyright notice and this paragraph are
  3245. X * duplicated in all such forms and that any documentation,
  3246. X * advertising materials, and other materials related to such
  3247. X * distribution and use acknowledge that the software was developed
  3248. X * by the University of California, Berkeley.  The name of the
  3249. X * University may not be used to endorse or promote products derived
  3250. X * from this software without specific prior written permission.
  3251. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  3252. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  3253. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  3254. X *
  3255. X */
  3256. X
  3257. X/* this came out of the ftpd sources; it's been modified to avoid the
  3258. X * globbing stuff since we don't need it.  also execvp instead of execv.
  3259. X */
  3260. X
  3261. X#ifndef lint
  3262. Xstatic char rcsid[] = "$Id: popen.c,v 1.5 1994/01/15 20:43:43 vixie Exp $";
  3263. Xstatic char sccsid[] = "@(#)popen.c    5.7 (Berkeley) 2/14/89";
  3264. X#endif /* not lint */
  3265. X
  3266. X#include "cron.h"
  3267. X#include <sys/signal.h>
  3268. X
  3269. X
  3270. X#define WANT_GLOBBING 0
  3271. X
  3272. X/*
  3273. X * Special version of popen which avoids call to shell.  This insures noone
  3274. X * may create a pipe to a hidden program as a side effect of a list or dir
  3275. X * command.
  3276. X */
  3277. Xstatic PID_T *pids;
  3278. Xstatic int fds;
  3279. X
  3280. XFILE *
  3281. Xcron_popen(program, type)
  3282. X    char *program, *type;
  3283. X{
  3284. X    register char *cp;
  3285. X    FILE *iop;
  3286. X    int argc, pdes[2];
  3287. X    PID_T pid;
  3288. X    char *argv[100];
  3289. X#if WANT_GLOBBING
  3290. X    char **pop, *vv[2];
  3291. X    int gargc;
  3292. X    char *gargv[1000];
  3293. X    extern char **glob(), **copyblk();
  3294. X#endif
  3295. X
  3296. X    if (*type != 'r' && *type != 'w' || type[1])
  3297. X        return(NULL);
  3298. X
  3299. X    if (!pids) {
  3300. X        if ((fds = getdtablesize()) <= 0)
  3301. X            return(NULL);
  3302. X        if (!(pids = (PID_T *)malloc((u_int)(fds * sizeof(PID_T)))))
  3303. X            return(NULL);
  3304. X        bzero((char *)pids, fds * sizeof(PID_T));
  3305. X    }
  3306. X    if (pipe(pdes) < 0)
  3307. X        return(NULL);
  3308. X
  3309. X    /* break up string into pieces */
  3310. X    for (argc = 0, cp = program;; cp = NULL)
  3311. X        if (!(argv[argc++] = strtok(cp, " \t\n")))
  3312. X            break;
  3313. X
  3314. X#if WANT_GLOBBING
  3315. X    /* glob each piece */
  3316. X    gargv[0] = argv[0];
  3317. X    for (gargc = argc = 1; argv[argc]; argc++) {
  3318. X        if (!(pop = glob(argv[argc]))) {    /* globbing failed */
  3319. X            vv[0] = argv[argc];
  3320. X            vv[1] = NULL;
  3321. X            pop = copyblk(vv);
  3322. X        }
  3323. X        argv[argc] = (char *)pop;        /* save to free later */
  3324. X        while (*pop && gargc < 1000)
  3325. X            gargv[gargc++] = *pop++;
  3326. X    }
  3327. X    gargv[gargc] = NULL;
  3328. X#endif
  3329. X
  3330. X    iop = NULL;
  3331. X    switch(pid = vfork()) {
  3332. X    case -1:            /* error */
  3333. X        (void)close(pdes[0]);
  3334. X        (void)close(pdes[1]);
  3335. X        goto pfree;
  3336. X        /* NOTREACHED */
  3337. X    case 0:                /* child */
  3338. X        if (*type == 'r') {
  3339. X            if (pdes[1] != 1) {
  3340. X                dup2(pdes[1], 1);
  3341. X                dup2(pdes[1], 2);    /* stderr, too! */
  3342. X                (void)close(pdes[1]);
  3343. X            }
  3344. X            (void)close(pdes[0]);
  3345. X        } else {
  3346. X            if (pdes[0] != 0) {
  3347. X                dup2(pdes[0], 0);
  3348. X                (void)close(pdes[0]);
  3349. X            }
  3350. X            (void)close(pdes[1]);
  3351. X        }
  3352. X#if WANT_GLOBBING
  3353. X        execvp(gargv[0], gargv);
  3354. X#else
  3355. X        execvp(argv[0], argv);
  3356. X#endif
  3357. X        _exit(1);
  3358. X    }
  3359. X    /* parent; assume fdopen can't fail...  */
  3360. X    if (*type == 'r') {
  3361. X        iop = fdopen(pdes[0], type);
  3362. X        (void)close(pdes[1]);
  3363. X    } else {
  3364. X        iop = fdopen(pdes[1], type);
  3365. X        (void)close(pdes[0]);
  3366. X    }
  3367. X    pids[fileno(iop)] = pid;
  3368. X
  3369. Xpfree:
  3370. X#if WANT_GLOBBING
  3371. X    for (argc = 1; argv[argc] != NULL; argc++) {
  3372. X/*        blkfree((char **)argv[argc]);    */
  3373. X        free((char *)argv[argc]);
  3374. X    }
  3375. X#endif
  3376. X    return(iop);
  3377. X}
  3378. X
  3379. Xint
  3380. Xcron_pclose(iop)
  3381. X    FILE *iop;
  3382. X{
  3383. X    register int fdes;
  3384. X    int omask;
  3385. X    WAIT_T stat_loc;
  3386. X    PID_T pid;
  3387. X
  3388. X    /*
  3389. X     * pclose returns -1 if stream is not associated with a
  3390. X     * `popened' command, or, if already `pclosed'.
  3391. X     */
  3392. X    if (pids == 0 || pids[fdes = fileno(iop)] == 0)
  3393. X        return(-1);
  3394. X    (void)fclose(iop);
  3395. X    omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
  3396. X    while ((pid = wait(&stat_loc)) != pids[fdes] && pid != -1)
  3397. X        ;
  3398. X    (void)sigsetmask(omask);
  3399. X    pids[fdes] = 0;
  3400. X    return (pid == -1 ? -1 : WEXITSTATUS(stat_loc));
  3401. X}
  3402. END_OF_FILE
  3403. if test 4044 -ne `wc -c <'popen.c'`; then
  3404.     echo shar: \"'popen.c'\" unpacked with wrong size!
  3405. fi
  3406. # end of 'popen.c'
  3407. fi
  3408. if test -f 'putman.sh' -a "${1}" != "-c" ; then 
  3409.   echo shar: Will not clobber existing file \"'putman.sh'\"
  3410. else
  3411. echo shar: Extracting \"'putman.sh'\" \(328 characters\)
  3412. sed "s/^X//" >'putman.sh' <<'END_OF_FILE'
  3413. X#!/bin/sh
  3414. X
  3415. X# putman.sh - install a man page according to local custom
  3416. X# vixie 27dec93 [original]
  3417. X#
  3418. X# $Id:$
  3419. X
  3420. XPAGE=$1
  3421. XDIR=$2
  3422. X
  3423. XSECT=`expr $PAGE : '[a-z]*.\([0-9]\)'`
  3424. X
  3425. X[ -d $DIR/man$SECT ] && {
  3426. X    set -x
  3427. X    cp $PAGE $DIR/man$SECT/$PAGE
  3428. X    set +x
  3429. X} || {
  3430. X    set -x
  3431. X    nroff -man $PAGE >$DIR/cat$SECT/`basename $PAGE .$SECT`.0
  3432. X    set +x
  3433. X}
  3434. X
  3435. Xexit 0
  3436. END_OF_FILE
  3437. if test 328 -ne `wc -c <'putman.sh'`; then
  3438.     echo shar: \"'putman.sh'\" unpacked with wrong size!
  3439. fi
  3440. # end of 'putman.sh'
  3441. fi
  3442. if test -f 'user.c' -a "${1}" != "-c" ; then 
  3443.   echo shar: Will not clobber existing file \"'user.c'\"
  3444. else
  3445. echo shar: Extracting \"'user.c'\" \(2195 characters\)
  3446. sed "s/^X//" >'user.c' <<'END_OF_FILE'
  3447. X/* Copyright 1988,1990,1993,1994 by Paul Vixie
  3448. X * All rights reserved
  3449. X *
  3450. X * Distribute freely, except: don't remove my name from the source or
  3451. X * documentation (don't take credit for my work), mark your changes (don't
  3452. X * get me blamed for your possible bugs), don't alter or remove this
  3453. X * notice.  May be sold if buildable source is provided to buyer.  No
  3454. X * warrantee of any kind, express or implied, is included with this
  3455. X * software; use at your own risk, responsibility for damages (if any) to
  3456. X * anyone resulting from the use of this software rests entirely with the
  3457. X * user.
  3458. X *
  3459. X * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
  3460. X * I'll try to keep a version up to date.  I can be reached as follows:
  3461. X * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
  3462. X */
  3463. X
  3464. X#if !defined(lint) && !defined(LINT)
  3465. Xstatic char rcsid[] = "$Id: user.c,v 2.8 1994/01/15 20:43:43 vixie Exp $";
  3466. X#endif
  3467. X
  3468. X/* vix 26jan87 [log is in RCS file]
  3469. X */
  3470. X
  3471. X
  3472. X#include "cron.h"
  3473. X
  3474. X
  3475. Xvoid
  3476. Xfree_user(u)
  3477. X    user    *u;
  3478. X{
  3479. X    entry    *e, *ne;
  3480. X
  3481. X    free(u->name);
  3482. X    for (e = u->crontab;  e != NULL;  e = ne) {
  3483. X        ne = e->next;
  3484. X        free_entry(e);
  3485. X    }
  3486. X    free(u);
  3487. X}
  3488. X
  3489. X
  3490. Xuser *
  3491. Xload_user(crontab_fd, pw, name)
  3492. X    int        crontab_fd;
  3493. X    struct passwd    *pw;        /* NULL implies syscrontab */
  3494. X    char        *name;
  3495. X{
  3496. X    char    envstr[MAX_ENVSTR];
  3497. X    FILE    *file;
  3498. X    user    *u;
  3499. X    entry    *e;
  3500. X    int    status;
  3501. X    char    **envp;
  3502. X
  3503. X    if (!(file = fdopen(crontab_fd, "r"))) {
  3504. X        perror("fdopen on crontab_fd in load_user");
  3505. X        return NULL;
  3506. X    }
  3507. X
  3508. X    Debug(DPARS, ("load_user()\n"))
  3509. X
  3510. X    /* file is open.  build user entry, then read the crontab file.
  3511. X     */
  3512. X    u = (user *) malloc(sizeof(user));
  3513. X    u->name = strdup(name);
  3514. X    u->crontab = NULL;
  3515. X
  3516. X    /* 
  3517. X     * init environment.  this will be copied/augmented for each entry.
  3518. X     */
  3519. X    envp = env_init();
  3520. X
  3521. X    /*
  3522. X     * load the crontab
  3523. X     */
  3524. X    while ((status = load_env(envstr, file)) >= OK) {
  3525. X        switch (status) {
  3526. X        case ERR:
  3527. X            free_user(u);
  3528. X            u = NULL;
  3529. X            goto done;
  3530. X        case FALSE:
  3531. X            e = load_entry(file, NULL, pw, envp);
  3532. X            if (e) {
  3533. X                e->next = u->crontab;
  3534. X                u->crontab = e;
  3535. X            }
  3536. X            break;
  3537. X        case TRUE:
  3538. X            envp = env_set(envp, envstr);
  3539. X            break;
  3540. X        }
  3541. X    }
  3542. X
  3543. X done:
  3544. X    env_free(envp);
  3545. X    fclose(file);
  3546. X    Debug(DPARS, ("...load_user() done\n"))
  3547. X    return u;
  3548. X}
  3549. END_OF_FILE
  3550. if test 2195 -ne `wc -c <'user.c'`; then
  3551.     echo shar: \"'user.c'\" unpacked with wrong size!
  3552. fi
  3553. # end of 'user.c'
  3554. fi
  3555. echo shar: End of archive 1 \(of 2\).
  3556. cp /dev/null ark1isdone
  3557. MISSING=""
  3558. for I in 1 2 ; do
  3559.     if test ! -f ark${I}isdone ; then
  3560.     MISSING="${MISSING} ${I}"
  3561.     fi
  3562. done
  3563. if test "${MISSING}" = "" ; then
  3564.     echo You have unpacked both archives.
  3565.     rm -f ark[1-9]isdone
  3566. else
  3567.     echo You still need to unpack the following archives:
  3568.     echo "        " ${MISSING}
  3569. fi
  3570. ##  End of shell archive.
  3571. exit 0
  3572.