Imported Upstream version 1.5.4

This commit is contained in:
Mario Fetka 2019-08-06 18:08:05 +02:00
parent 886d9ad08e
commit e379c52a76
71 changed files with 20279 additions and 1805 deletions

29
.gitignore vendored
View File

@ -1,29 +0,0 @@
Makefile.in
Makefile
anacron/anacron
anacron/anacron-paths.h
anacron/Makefile
anacron/Makefile.in
aclocal.m4
autom4te.cache
config.guess
config.h
config.h.in
config.log
config.status
config.sub
configure
depcomp
install-sh
man/Makefile
man/Makefile.in
missing
stamp-h1
tags
.deps
*.o
src/crond
src/crontab
src/cron-paths.h
*~
*.tar.*

View File

@ -1,2 +1,8 @@
Original vixie-cron was written by Paul Vixie. Original vixie-cron was written by Paul Vixie.
Significant contributors:
Marcela Mašláňová <mmaslano@redhat.com>
Colin Dean <colin@colin-dean.org>
Tomáš Mráz <tmraz@fedoraproject.org>
Marco Migliori <sgerwk@aol.com>
Sami Kerola <kerolasa@iki.fi>

339
COPYING
View File

@ -76,3 +76,342 @@
* *
* @(#)bitstring.h 8.1 (Berkeley) 7/19/93 * @(#)bitstring.h 8.1 (Berkeley) 7/19/93
*/ */
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -1,340 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

890
ChangeLog
View File

@ -1,3 +1,893 @@
2019-03-18 Tomas Mraz <tmraz@fedoraproject.org>
* crond: Fix regression from last release
Only first job from a crontab was being run.
2019-03-15 Tomas Mraz <tmraz@fedoraproject.org>
* Release new version 1.5.3
2019-03-15 Tomas Mraz <tmraz@fedoraproject.org>
* Fix warnings in anacron and crond code.
2019-03-15 Tomas Mraz <tmraz@fedoraproject.org>
* Fix CVE-2019-9704 and CVE-2019-9705
2019-03-15 Tomas Mraz <tmraz@fedoraproject.org>
* Remove leftover debugging message.
2019-03-11 Marcel Plch <mplch@redhat.com>
* Make crond run after autofs mounts
2019-02-15 Tomas Mraz <tmraz@fedoraproject.org>
* crontab: Make crontab without arguments fail.
2018-12-07 Marcel Plch <mplch@redhat.com>
* Use system-auth instead of password-auth for PAM authentication (#25)
2018-11-23 Marcel Plch <mplch@redhat.com>
* Restart crond if it fails
2018-11-19 Tomas Mraz <tmraz@fedoraproject.org>
* load_env: parse the environment variables in-place
2018-11-19 Tomáš Mráz <t8m@users.noreply.github.com>
* Update readme.md with the latest release and better link to Fedora
2018-11-18 Oliver Kurz <okurz@suse.de>
* readme.md: Replace dead link to openSUSE ML with package link
2018-10-18 Tomas Mraz <tmraz@fedoraproject.org>
* Use the role from the crond context for system job contexts.
2018-08-28 Marcel Plch <mplch@redhat.com>
* Fix unsafe code
2018-08-28 Marcel Plch <mplch@redhat.com>
* Fix possible memory leaks
2018-05-03 Tomas Mraz <tmraz@fedoraproject.org>
* Release new version 1.5.2
2018-05-03 Tomas Mraz <tmraz@fedoraproject.org>
* Silence may be used uninitialized warning.
2018-05-03 Tomas Mraz <tmraz@fedoraproject.org>
* crontab: do not try to replace the crontab with a directory
2018-01-24 Tomas Mraz <tmraz@fedoraproject.org>
* Support the MAILFROM also in anacron.
2017-11-28 Tomas Mraz <tmraz@fedoraproject.org>
* Document that in range the first number must be less than second.
2017-10-28 sgerwk <sgerwk@aol.com>
* round time on the minute
2017-10-28 sgerwk <sgerwk@aol.com>
* print all jobs executed in interval
2017-10-28 sgerwk <sgerwk@aol.com>
* new options -l and -q
2017-10-28 sgerwk <sgerwk@aol.com>
* output in yaml format
2017-10-28 sgerwk <sgerwk@aol.com>
* print the job(s) that is going to be executed next
2017-10-28 sgerwk <sgerwk@aol.com>
* allow checking a time interval
2017-10-28 sgerwk <sgerwk@aol.com>
* print format for flags
2017-11-02 Marco Migliori <sgerwk@aol.com>
* cronnext can read additional crontabs from files
2017-09-14 Tomas Mraz <tmraz@fedoraproject.org>
* Use proper variable types.
2017-09-14 Tomas Mraz <tmraz@fedoraproject.org>
* Add myself as author.
2017-09-14 Tomas Mraz <tmraz@fedoraproject.org>
* Log startup even when started in non-forking mode.
2017-07-14 Mark Montague <mark@catseye.org>
* Fix SELinux denial when running under Docker
2017-07-01 Sami Kerola <kerolasa@iki.fi>
* build-sys: use silent build rule
2017-06-11 Sami Kerola <kerolasa@iki.fi>
* cronnext: improve manual page
2017-06-11 Sami Kerola <kerolasa@iki.fi>
* all: add version printing option -V
2017-06-11 Sami Kerola <kerolasa@iki.fi>
* cronnext: use same style in usage() with other commands
2017-06-10 Sami Kerola <kerolasa@iki.fi>
* various files: fix indentation
2017-06-10 Sami Kerola <kerolasa@iki.fi>
* crond: never define unused cron_start_pam()
2017-05-01 SjonHortensius <SjonHortensius@users.noreply.github.com>
* Add Arch Linux to list of distributions
2017-04-28 Tomas Mraz <tmraz@fedoraproject.org>
* Fix misleading indentation.
2017-04-28 Tomas Mraz <tmraz@fedoraproject.org>
* Make cronnext build and work with additional features enabled.
2017-04-18 Tomas Mraz <tmraz@fedoraproject.org>
* Add MIME-Version header also to mails generated by anacron.
2017-04-18 Tomas Mraz <tmraz@fedoraproject.org>
* Add MIME-Version header to generated mails.
2017-03-29 Tomas Mraz <tmraz@fedoraproject.org>
* The output might not be mailed, make the message more precise.
2017-03-29 Tomas Mraz <tmraz@fedoraproject.org>
* Allow empty environment values in crontab.
2017-03-29 Tomáš Mráz <t8m@users.noreply.github.com>
* Point releases to the GitHub cronie releases page
2017-03-29 Kristýna Streitová <kstreitova@suse.com>
* crontab.5: Add a mention about disabling logging
2017-03-29 Kristýna Streitová <kstreitova@suse.com>
* Avoid creating pid files when crond doesn't fork
2017-01-20 Tomas Mraz <tmraz@fedoraproject.org>
* readme.md: remove CRs
2017-01-20 Tomas Mraz <tmraz@fedoraproject.org>
* Add readme.md for github
2016-09-08 Tomas Mraz <tmraz@fedoraproject.org>
* Make it clear that one of the reasons for getpwnam() failure is unknown user.
2016-09-05 Tomas Mraz <tmraz@fedoraproject.org>
* On some machines the power supply is named ADP0.
2016-08-23 Tomas Mraz <tmraz@fedoraproject.org>
* Query power supply status directly from kernel.
2016-06-27 Tomas Mraz <tmraz@fedoraproject.org>
* cronnext: Fix warnings
2016-06-27 Tomas Mraz <tmraz@fedoraproject.org>
* cronnext: Print usage and error on stderr.
2016-06-27 Marco Migliori <sgerwk@aol.com>
* Added useful utility cronnext to find out time of the next job run.
2016-06-23 Tomas Mraz <tmraz@fedoraproject.org>
* anacron: Check return value of fchdir.
2016-06-23 Tomas Mraz <tmraz@fedoraproject.org>
* Release new version 1.5.1
2016-06-23 Tomas Mraz <tmraz@fedoraproject.org>
* Remove unneeded obsolete SELinux include.
2016-06-23 Tomas Mraz <tmraz@fedoraproject.org>
* Remove unneeded obsolete SELinux includes.
2016-06-23 Tomas Mraz <tmraz@fedoraproject.org>
* Rename timeval time to tv so time function can be used.
2016-06-23 Tomas Mraz <tmraz@fedoraproject.org>
* Fix longstanding race condition on crontab modification.
If crontab is modified twice at the same second the crond reads it
which means the timestamp will not change, the latest content will
never be read.
2016-06-10 Tomas Mraz <tmraz@fedoraproject.org>
* Fix misleading comment in pam configuration file.
2016-05-13 Tomas Mraz <tmraz@fedoraproject.org>
* anacron: use mkstemp() instead of tempnam()
Although the use of tempnam() seemed to be safeguarded
better to not use it at all.
2016-05-13 Tomas Mraz <tmraz@fedoraproject.org>
* anacron: Drop potentially unsafe umask setting.
2016-05-13 Tomas Mraz <tmraz@fedoraproject.org>
* anacron: Do not try to mail to empty address.
2016-04-25 Tomas Mraz <tmraz@fedoraproject.org>
* Clarify the crontab(1) documentation.
2016-04-23 Gary Tierney <gary.tierney@gmx.com>
* Remove hardcoded "system_u" SELinux user
This gets rid of the hardcoded reference to the ref-policy system_u user
and instead relies on the user that cronie is currently running as.
2016-04-25 Tomas Mraz <tmraz@fedoraproject.org>
* Clarify return value.
2016-03-15 Tomas Mraz <tmraz@fedoraproject.org>
* Correct instructions for disabling Anacron.
2015-11-07 Ville Skyttä <ville.skytta@iki.fi>
* Man page syntax fixes
2015-11-05 Robert Byrnes <Robert.Byrnes@deshaw.com>
* Inherit PATH from the crond environment if -P option is used.
2015-07-13 Tomas Mraz <tmraz@fedoraproject.org>
* In crontab command use a temporary filename that is ignored by crond.
2015-05-28 Tomas Mraz <tmraz@fedoraproject.org>
* Add *.patch and *.orig to .gitignore
2015-05-28 Tomas Mraz <tmraz@fedoraproject.org>
* Add compile to .gitignore.
2015-05-28 Tomas Mraz <tmraz@fedoraproject.org>
* Release new version 1.5.0
properly create dist tarball even with anacron and PAM disabled
2015-05-28 Tomas Mraz <tmraz@fedoraproject.org>
* Pass the job environment also when executing the sendmail.
2015-01-31 Felix Janda <felix.janda@posteo.de>
* database.c: Use POSIX NAME_MAX instead of BSD MAXNAMLEN
2015-04-21 Tomas Mraz <tmraz@fedoraproject.org>
* Prevent adding duplicate orphans on reload.
2015-02-05 Tomas Mraz <tmraz@fedoraproject.org>
* Do not overwrite the last zero-byte.
2015-02-03 Tomas Mraz <tmraz@fedoraproject.org>
* Log the crond shutdown.
2015-01-28 Tomas Mraz <tmraz@fedoraproject.org>
* No need to call strcmp on already matched variables.
2015-01-28 Tomas Mraz <tmraz@fedoraproject.org>
* Use unbiased random number for RANDOM_DELAY.
2015-01-28 Tomas Mraz <tmraz@fedoraproject.org>
* Call PAM only when it makes sense.
2015-01-28 Tomas Mraz <tmraz@fedoraproject.org>
* Fix broken test for match_rx() failure.
2014-11-04 Tomas Mraz <tmraz@fedoraproject.org>
* Properly check the existence of the user at the time the job is run.
2014-09-17 Marcela Mašláňová <mmaslano@redhat.com>
* contrib/cronie.systemd: Services must be running before starting
crond, otherwise many jobs is not running properly for no obvious
reason. nss-user-lookup.target should help when people are authenticated
through nss/sssd. Based on: https://bugzilla.redhat.com/show_bug.cgi?id=1067236
2014-07-30 Marcela Mašláňová <mmaslano@redhat.com>
* src/cron.c: More logging when getpwnam fails. Based on: rhbz#1123984 Signed-off-by: Marcela Mašláňová <mmaslano@redhat.com>
2014-07-25 Marcela Mašláňová <mmaslano@redhat.com>
* configure.ac, src/env.c: BSD doesn't define environ in unistd.h.
Also cronie didn't have option for enabling BSD specifics. Based on: naota@gentoo.org Signed-off-by: Marcela Mašláňová <mmaslano@redhat.com>
2014-07-25 Marcela Mašláňová <mmaslano@redhat.com>
* anacron/readtab.c: Add missing brackets into anacron readtab. Signed-off-by: Marcela Mašláňová <mmaslano@redhat.com>
2014-07-25 Marcela Mašláňová <mmaslano@redhat.com>
* src/misc.c: Include missing header for signal handlers. Signed-off-by: Marcela Mašláňová <mmaslano@redhat.com>
2014-07-04 Marcela Mašláňová <mmaslano@redhat.com>
* contrib/cronie.systemd: Missing reload definition in unit file was
added. Signed-off-by: Marcela Mašláňová <mmaslano@redhat.com>
2014-04-30 Marcela Mašláňová <mmaslano@redhat.com>
* : commit b2c8cbcef8c97b5a175d6e71995249b288707b0f Author: Tomas
Mraz <tmraz@fedoraproject.org> Date: Tue Apr 29 14:08:25 2014
+0200
2014-03-31 Martin Poole <mpoole@redhat.com>
* src/misc.c: crond installs a signal hander for SIGINT & SIGTERM
which removes the pid file and exits. This handler is not reset for
individual forked sub-processes which results in the condition that
if the child receives SIGINT or SIGTERM the pid file is erroneously
removed. Signed-off-by: Marcela Mašláňová <mmaslano@redhat.com>
2014-02-14 Marcela Mašláňová <mmaslano@redhat.com>
* anacron/readtab.c: Anacron does not correctly check configuration
parameters for validity and can segfault on certain data types. The return code
from the match_rx calls in readtab.c are not being checked
correctly. Bugfix let to segfaults in downstreams on non intel
architectures. All options in anacrontab should be now working
correctly. Based on patch from: Martin Poole
2014-01-20 Marcela Mašláňová <mmaslano@redhat.com>
* contrib/cronie.systemd: Remove syslog.target according to Fedora
and systemd guidelines. https://fedorahosted.org/fpc/ticket/177#comment:2 Thanks to: Ville Skyttä
2014-01-17 Ville Skyttä <ville.skytta@iki.fi>
* man/anacron.8: [PATCH] Fix anacron.8 UTF-8 encoding. Signed-off-by: Marcela Mašláňová <mmaslano@redhat.com>
2013-12-18 Ville Skyta <ville.skytta@iki.fi>
* anacron/lock.c, anacron/readtab.c, man/crontab.5, src/cron.c,
src/database.c: Spelling fixes. Signed-off-by: Marcela Mašláňová <mmaslano@redhat.com>
2013-12-18 Ville Skytta <ville.skytta@iki.fi>
* anacron/readtab.c, src/do_command.c: strncmp() size fixes. Signed-off-by: Marcela Mašláňová <mmaslano@redhat.com>
2013-12-18 Martin Poole <mpoole@redhat.com>
* anacron/readtab.c: Anacron does not correctly check configuration
parameters for validity and can segfault on certain data types. The
return code from the match_rx calls in readtab.c are not being
checked correctly. Signed-off-by: Marcela Mašláňová <mmaslano@redhat.com>
2013-09-26 Marcela Mašláňová <mmaslano@redhat.com>
* man/cron.8: crond -n must change pam setting.
2013-09-12 Marcela Mašláňová <mmaslano@redhat.com>
* cronie.init: Non-root user can't read configuration. Init file
will fail with proper error message. rhbz#1006869
2013-08-29 Marcela Mašláňová <mmaslano@redhat.com>
* : commit 2ec335f9549e8134102ac37665171a40a5407512 Author: Saul
Wold <sgw@linux.intel.com> Date: Mon Aug 26 11:18:27 2013 +0200
2013-08-16 Tomas Mraz <tmraz@fedoraproject.org>
* src/security.c: Pull PAM environment variables also from session
modules. - also fix memory leak of environment returned by pam_getenvlist()
2013-08-13 Marcela Mašláňová <mmaslano@redhat.com>
* contrib/cronie.systemd: KillMode in systemd unit file will enable
to finish jobs executed by cron. Even if cron dies, jobs should
continue. Based on: https://bugzilla.redhat.com/show_bug.cgi?id=919290
2013-08-09 Tomas Mraz <tmraz@fedoraproject.org>
* src/misc.c: Fcntl locking has different semantics than flock.
Prefer flock.
2013-07-18 Marcela Mašláňová <mmaslano@redhat.com>
* ChangeLog, configure.ac: Release 1.4.11
2013-06-11 Tomas Mraz <tmraz@fedoraproject.org>
* src/user.c: Log failures in load_user().
2013-06-11 Tomas Mraz <tmraz@fedoraproject.org>
* man/crontab.5, src/cron.c, src/entry.c, src/env.c, src/globals.h,
src/structs.h: Add support for RANDOM_DELAY of jobs.
2013-06-11 Tomas Mraz <tmraz@fedoraproject.org>
* src/user.c: Fixed bug introduced by previous commit and simplified
error handling.
2013-06-07 Tomas Mraz <tmraz@fedoraproject.org>
* src/env.c, src/funcs.h, src/user.c: Copy some variables from the
crond process environment. Also cleanup error handling in load_env().
2013-06-06 Tomas Mraz <tmraz@fedoraproject.org>
* src/cron.c: setenv takes 3 arguments
2013-06-06 Tomas Mraz <tmraz@fedoraproject.org>
* src/cron.c: Do not use putenv with string literal.
2013-04-25 Tomas Mraz <tmraz@fedoraproject.org>
* src/do_command.c: Make From field in mails from crond RFC
compliant.
2012-12-30 Sami Kerola <kerolasa@iki.fi>
* src/crontab.c: cron: clarify usage() print out The -n option needs argument, which was missing from the usage(). Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-29 Sami Kerola <kerolasa@iki.fi>
* anacron/global.h, anacron/main.c, anacron/readtab.c: anacron: fix
shadow declarations Change global variables to have more specific name. This will make
warnings about shadowing to go away, and may result to a little more
readable code. log.c:74:35: warning: declaration of 'args' shadows a global
declaration [-Wshadow] global.h:97:15: warning: shadowed declaration
is here [-Wshadow] Reference:
http://web.archiveorange.com/archive/v/N6p0RpcfZsIBsaU8B2sE#72jDywyk8NZ3i9gSigned-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-29 Sami Kerola <kerolasa@iki.fi>
* src/crontab.c, src/entry.c, src/macros.h, src/security.c: smatch
scan: fix various warningss found using smatch entry.c:396 load_entry() info: redundant null check on e->pwd
calling free() entry.c:398 load_entry() info: redundant null check
on e->cmd calling free() /usr/include/bits/fcntl.h:48:10: warning: preprocessor token
O_NOFOLLOW redefined macros.h:136:9: this was the original
definition security.c:98:44: warning: non-ANSI function declaration of function
'cron_restore_default_security_context' crontab.c:439:29: warning:
non-ANSI function declaration of function 'tmp_path' Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-01-02 Marcela Mašláňová <mmaslano@redhat.com>
* man/cron.8: Mention systemctl command in man page of crond. Based
on rhbz#891160.
2012-12-20 Sami Kerola <kerolasa@iki.fi>
* contrib/0anacron: contrib: remove bashisms Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-20 Sami Kerola <kerolasa@iki.fi>
* COPYING.anacron, anacron/global.h, anacron/gregor.c,
anacron/gregor.h, anacron/lock.c, anacron/log.c, anacron/main.c,
anacron/matchrx.c, anacron/matchrx.h, anacron/readtab.c,
anacron/runjob.c: docs: corrections to FSF license files, and postal
address The COPYING and file is replaced by files from GNU web site. http://www.gnu.org/licenses/gpl-2.0.txt Postal addresses to FSF in other files are updated to match with the
address in license files. References:
http://lists.gnu.org/archive/html/freefont-announce/2005-04/msg00001.htmlSigned-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-02 Sami Kerola <kerolasa@iki.fi>
* cronie.init: init script: remove bashisms References: https://sourceforge.net/projects/checkbaskisms/
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-01 Sami Kerola <kerolasa@iki.fi>
* anacron/log.c, anacron/main.c, anacron/readtab.c,
anacron/runjob.c: anacron: make function declarations to be ansi
compliant Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-01 Sami Kerola <kerolasa@iki.fi>
* anacron/main.c, anacron/runjob.c: anacron: remove numeric exit and
file descriptor values Use symbolic values from standard header instead. Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-01 Sami Kerola <kerolasa@iki.fi>
* anacron/main.c: anacron: clean up usage() output Inform in usage which options will need arguments, and add reference
to manual page. Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-01 Sami Kerola <kerolasa@iki.fi>
* anacron/runjob.c: anacron: set end job message string to be
constant runjob.c:308:7: warning: assignment discards 'const' qualifier from
pointer target type [enabled by default] Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-01 Sami Kerola <kerolasa@iki.fi>
* anacron/global.h, anacron/main.c: anacron: add function attributes Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-01 Sami Kerola <kerolasa@iki.fi>
* Makefile.am, cronie_common.h, src/cron.c, src/crontab.c,
src/security.c: compile: add function attributes Some of the argument values are not in use, and few functions does
not return. Informing which will make few warning messages
disapper, and compiler to generate better binary. Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-01 Sami Kerola <kerolasa@iki.fi>
* src/cron.c: compile: fix signed and unsigned warnings cron.c:100:16: warning: comparison between signed and unsigned
integer expressions [-Wsign-compare] cron.c:108:16: warning:
comparison between signed and unsigned integer expressions
[-Wsign-compare] cron.c:125:16: warning: comparison between signed
and unsigned integer expressions [-Wsign-compare] Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-27 Sami Kerola <kerolasa@iki.fi>
* src/cron.c: crond: make usage easier to read Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-27 Sami Kerola <kerolasa@iki.fi>
* src/crontab.c: crontab: make usage easier to read Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-27 Marcela Mašláňová <mmaslano@redhat.com>
* ChangeLog, configure.ac: New release 1.4.10.
2012-11-27 Marcela Mašláňová <mmaslano@redhat.com>
* src/crontab.c, src/do_command.c, src/funcs.h: Condtionalize pam
functions.
2012-11-27 Tomas Mraz <tmraz@fedoraproject.org>
* configure.ac: Drop duplicate -lselinux -laudit.
2012-11-27 Tomas Mraz <tmraz@fedoraproject.org>
* src/funcs.h, src/security.c, src/structs.h: Fix missing includes
for selinux and other types.
2012-11-27 Marcela Mašláňová <mmaslano@redhat.com>
* man/cron.8, src/cron.c: Fix some issues introduced in c58b1d9
Documentation improvements based on Michael Lass suggestions. * give -m an own line in manpage * don't explain -P twice * correct description of -P to what it actually does Signed-off-by: Marcela Mašláňová <mmaslano@redhat.com>
2012-11-26 Tomas Mraz <tmraz@fedoraproject.org>
* src/crontab.c: Fix const usage in crontab.
2012-11-22 Sami Kerola <kerolasa@iki.fi>
* man/anacron.8: docs: anacron fix out dated information about open
file limits For quite a while open files limit has defaulted to 1024, but rather
than informing what might be the number user should inspect value
from own time. Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-22 Sami Kerola <kerolasa@iki.fi>
* man/anacrontab.5: docs: fix reference to other manual There is no crontabs(4). For user it makes most sense to look
crontab(1). Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-22 Sami Kerola <kerolasa@iki.fi>
* man/anacron.8, man/anacrontab.5, man/cron.8, man/crontab.1,
man/crontab.5: docs: fix various groff issues * Add spaces after dots (English spacing). * Remove use of inline emphasis where possible. * Use mail and url macros. * Wrap long and join short lines. * Remove end of line white spaces. Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-24 Sami Kerola <kerolasa@iki.fi>
* configure.ac, src/pathnames.h: build-sys: make ./configure to
seach vi path Using "/usr/ucb/vi" as defaut fallback EDITOR is not going to work
on most of distributions where this package is installed. That said
it might work somewhere, so searching the vi editor at configure
time is the sensible thing to do, if user does not want to define
the default. Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-24 Sami Kerola <kerolasa@iki.fi>
* src/cron.c, src/crontab.c, src/database.c, src/do_command.c,
src/entry.c, src/env.c, src/macros.h, src/security.c, src/user.c:
debuging: make Debug macro look like function This will make indent(1) program not to think it is a clause. Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-24 Sami Kerola <kerolasa@iki.fi>
* src/do_command.c, src/user.c: declarations: fix shadow
declarations user.c:68:7: warning: declaration of 'save_errno' shadows a previous
local [-Wshadow] user.c:64:14: warning: shadowed declaration is here
[-Wshadow] do_command.c:559:9: warning: declaration of 'pid' shadows a previous
local [-Wshadow] do_command.c:91:8: warning: shadowed declaration is
here [-Wshadow] Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-24 Sami Kerola <kerolasa@iki.fi>
* src/Makefile.am, src/cron.c, src/cron.h, src/crontab.c,
src/database.c, src/do_command.c, src/entry.c, src/env.c,
src/externs.h, src/funcs.h, src/globals.h, src/job.c, src/macros.h,
src/misc.c, src/popen.c, src/pw_dup.c, src/security.c,
src/structs.h, src/user.c: includes: make inclusions clean This change makes files to include what they need, instead of having
generic inclusion headers which will include everything to
everywhere. Also the local headers havee ifndef & define
protection, which makes them to be save to include in any file,
without one having to think in which order the inclusions happen at
compile time. Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-26 Tomas Mraz <tmraz@fedoraproject.org>
* src/misc.c: Fix up also the const in comment.
2012-11-24 Sami Kerola <kerolasa@iki.fi>
* src/crontab.c, src/database.c, src/env.c, src/funcs.h, src/misc.c:
variables: use const where ever possible Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-24 Sami Kerola <kerolasa@iki.fi>
* src/crontab.c, src/security.c, src/user.c: build-sys: reduce
selinux and pam compiling scope when possible This will fix following warnings, and makes compiled program to
contain less unnecessary references. crontab.c:60:14: warning: 'selinux_context' defined but not used
[-Wunused-variable] security.c:188:12: warning:
'cron_open_pam_session' defined but not used [-Wunused-function]
security.c:250:12: warning: 'cron_authorize_context' defined but not
used [-Wunused-function] security.c:283:12: warning:
'cron_authorize_range' defined but not used [-Wunused-function] Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-24 Sami Kerola <kerolasa@iki.fi>
* src/crontab.c: compliancy: do not mix declarations and code Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-24 Sami Kerola <kerolasa@iki.fi>
* src/database.c, src/do_command.c: clean up: reduce variable
passing when they are not used Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-24 Sami Kerola <kerolasa@iki.fi>
* src/database.c, src/pw_dup.c, src/security.c: assingments: remove
initialization if value is never used The next operation with these variables will overwrite the values
set at init. Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-24 Sami Kerola <kerolasa@iki.fi>
* src/cron.c, src/entry.c, src/env.c, src/misc.c, src/popen.c:
compliancy: use memset() rather than bzero() Reference:
http://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xsh_chap03.htmlSigned-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-24 Sami Kerola <kerolasa@iki.fi>
* src/Makefile.am: build-sys: make clean needs to remove
cron-paths.h The file is generated at build time. This change is needed to make
distcheck work without an error. [...] ERROR: files left in build directory after distclean:
./src/cron-paths.h Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-24 Sami Kerola <kerolasa@iki.fi>
* autogen.sh: build-sys: add autotools helper script The script will help building when source code is checked out from
git. Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-26 Tomas Mraz <tmraz@fedoraproject.org>
* src/cron.c: Do not log that syslog will be used instead of
sendmail if explicitly requested.
2012-11-26 Tomas Mraz <tmraz@fedoraproject.org>
* configure.ac, src/cron.c, src/database.c: Enable system crontab by
default and use AC_ARG_ENABLE instead of AC_ARG_WITH.
2012-11-22 Marcela Mašláňová <mmaslano@redhat.com>
* ChangeLog, configure.ac: Minor release 1.4.9.
2012-11-13 Marcela Mašláňová <mmaslano@redhat.com>
* man/cron.8, src/cron.c: Documentation improvements based on
Michael Lass suggestions.
2012-11-02 Marcela Mašláňová <mmaslano@redhat.com>
* contrib/cronie.systemd: Add time-sync.target. If synchronization
is used, crond will start after sync by ntpd/chrony. rhbz#872516
2012-10-11 Tom Jones <tom@oxix.org>
* man/cron.8, src/cron.c, src/entry.c, src/globals.h: The sysadmin
may want to arrange for the PATH to be correct in the environment
from which cron is launched. This new option tells cron to not
overwrite this path for itself or for the child cron jobs. Signed-off-by: Marcela Mašláňová <mmaslano@redhat.com>
2012-07-24 Marcela Mašláňová <mmaslano@redhat.com>
* configure.ac: The enable-relro erased previously set LDFLAGS.
2012-07-02 Marcela Mašláňová <mmaslano@redhat.com>
* man/crontab.5: Fix typo in man page. rhbz#836292 Thanks to: Dave Allan
2012-06-22 Marcela Mašláňová <mmaslano@redhat.com>
* anacron/global.h, anacron/lock.c, anacron/main.c,
anacron/readtab.c: Preferred hour of start of the job. If the hour
is missed job will be skipped.
2012-06-21 Marcela Mašláňová <mmaslano@redhat.com>
* anacron/readtab.c: Range of hours for daily jobs must have
lower-higher hour.
2012-06-21 Marcela Mašláňová <mmaslano@redhat.com>
* src/crontab.c: Crontab has wrong permission. Based on rhbz#676081
2012-06-19 Marcela Mašláňová <mmaslano@redhat.com>
* configure.ac, src/cron.c, src/database.c: syscrontab, the system
crontab, is not mandatory anymore. Cronie can be build without it. The patch was based on complaints of
distribution without /etc/crontab file. https://fedorahosted.org/cronie/ticket/10
2012-06-13 Marcela Mašláňová <mmaslano@redhat.com>
* src/cron.c, src/do_command.c: Sendmail doesn't have to be
installed. The info message should make sense. https://fedorahosted.org/cronie/ticket/15
2012-06-06 Tim Landscheidt <tim@tim-landscheidt.de>
* src/cron.c: Previously, crond exited in the signal handler for
SIGINT and SIGTERM. Thus, the Inotify close code in main() was
never reached. This commit introduces a got_sigintterm variable
that is set when SIGINT or SIGTERM are received and leads to a clean
exit of the main loop. * src/cron.c: Rename quit() to sigintterm_handler(). Add
got_sigintterm variable and set it on SIGINT and SIGTERM. Shorten
sleep and exit main loop on got_sigintterm. Signed-off-by: Marcela Mašláňová <mmaslano@redhat.com>
2012-06-06 Tim Landscheidt <tim@tim-landscheidt.de>
* src/entry.c: 9th bit is overwritten. Hour bit fields have 24 bits (0..23, 3 bytes). bit_nclear() however
in this case is called to clear bits 0..24! Thus, it overwrites the
first bit of the following struct member (dom). This is not
problematic for normal use as dom is set after hour as are all other
fields. The last field, dow, uses 8 bits so 9 are cleared. This could be the
MIN_STAR bit of flags, but as flags is an int, there is probably a
padding byte in between; at least I couldn't trigger it to be unset.
So this could probably only cause problems on 8-bit systems. https://fedorahosted.org/cronie/ticket/11 Signed-off-by: Marcela
Mašláňová <mmaslano@redhat.com>
2012-06-06 Tim Landscheidt <tim@tim-landscheidt.de>
* anacron/readtab.c, anacron/runjob.c: Remove unused variables. Signed-off-by: Marcela Mašláňová <mmaslano@redhat.com>
2012-06-06 Tim Landscheidt <tim@tim-landscheidt.de>
* anacron/runjob.c: Fix use of "const char *" in call to putenv(). Signed-off-by: Marcela Mašláňová <mmaslano@redhat.com>
2012-04-12 Marcela Mašláňová <mmaslano@redhat.com>
* src/do_command.c: The mail header for automatic reply will now
contain another field: "Precedence: bulk", which is not compulsory
according to RFC3834. Based on: Harald Reindl request in rhbz#811186
2012-04-12 Sven Vermeulen <swift@gentoo.org>
* src/security.c: setkeycreatecon is not needed. Users should
inherited key context if it was already set for them. Signed-off-by: Marcela Mašláňová <mmaslano@redhat.com>
2012-04-11 Marcela Mašláňová <mmaslano@redhat.com>
* Makefile.am, contrib/cronie.systemd: systemd unit file was added
into contrib This unit file is used in Fedora. The systemd-user-sessions.service
guarantees everything, what is needed for log in of users, is
already running (ypbind, sssd, ldap, ...).
2012-04-11 T.M. Abraham <tabraham@novell.com>
* man/crontab.5: adjust documentation title to reference "crontab"
instead of "anacrontab" Signed-off-by: Marcela Mašláňová <mmaslano@redhat.com>
2011-12-07 Tomas Mraz <tmraz@fedoraproject.org>
* contrib/0anacron, contrib/0hourly, contrib/dailyjobs, man/cron.8,
man/crontab.5: Adjust the documentation to better describe the
current situation with crontab and anacrontab.
2011-11-24 Marcela Mašláňová <mmaslano@redhat.com>
* man/crontab.1: Add name of file, where can be set PAM
configuration.
2011-10-24 Petr Sabata <psabata@redhat.com>
* cronie.init: Service restart needlessly reports failure. Signed-off-by: Marcela Mašláňová <mmaslano@redhat.com>
2011-10-06 Marcela Mašláňová <mmaslano@redhat.com>
* src/security.c: Raw context should be used. Especially when
mcstransd in older releases is running.
2011-09-20 Tomas Mraz <tmraz@fedoraproject.org>
* src/cron.c, src/crontab.c: No need to have full path in the
ProgramName.
2011-06-29 Tomas Mraz <tmraz@fedoraproject.org>
* : commit 01a692b123c885c883e7791f0a1833df5edfe327 Author: Tomas
Mraz <tmraz@fedoraproject.org> Date: Wed Jun 29 12:42:27 2011
+0200
2011-06-29 Tomas Mraz <tmraz@fedoraproject.org>
* src/cron.c: Revert "Cronie disables inotify support when the
/etc/crontab file does not exist at startup." This reverts commit acdf4ae8456888ed78201906ef528f4c28f54582 as it
introduces fd leaks.
2011-06-27 Marcela Mašláňová <mmaslano@redhat.com>
* ChangeLog, configure.ac: Minor release 1.4.8
2011-06-24 Marcela Mašláňová <mmaslano@redhat.com> 2011-06-24 Marcela Mašláňová <mmaslano@redhat.com>
* src/do_command.c: Cron writes job output to syslog incorrectly. * src/do_command.c: Cron writes job output to syslog incorrectly.

22
INSTALL
View File

@ -1,22 +1,14 @@
Basic Installation Basic Installation
================== ==================
In the vixie-cron directory run: Run the usual autotools combination of:
autoreconf ./configure
These commands create from configure.ac executable ./configure
Then you can start installation:
make make
make install make install
The executable files will be installed in /usr/local/* The executable files will be installed in /usr/local/* by default.
Options
=======
In the default package are used configure options:
--with-pam
--with-selinux
--with-audit
Configure Options
=================
Please see the ./configure --help output for available build-time
options.

View File

@ -1,13 +1,21 @@
SUBDIRS = src man SUBDIRS = src man anacron
if ANACRON
SUBDIRS += anacron dist_noinst_HEADERS = \
endif cronie_common.h
EXTRA_DIST = \
cronie.init \
crond.sysconfig \
contrib/anacrontab \
contrib/0anacron \
contrib/0hourly \
contrib/dailyjobs \
contrib/cronie.systemd \
anacron/ChangeLog.anacron
if PAM if PAM
pamdir = $(sysconfdir)/pam.d pamdir = $(sysconfdir)/pam.d
dist_pam_DATA = pam/crond dist_pam_DATA = pam/crond
else
EXTRA_DIST += pam/crond
endif endif
EXTRA_DIST = cronie.init crond.sysconfig contrib/anacrontab \
contrib/0anacron contrib/0hourly \
contrib/dailyjobs

858
Makefile.in Normal file
View File

@ -0,0 +1,858 @@
# Makefile.in generated by automake 1.16.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2018 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
@PAM_FALSE@am__append_1 = pam/crond
subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
$(am__configure_deps) $(am__dist_pam_DATA_DIST) \
$(dist_noinst_HEADERS) $(am__DIST_COMMON)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
configure.lineno config.status.lineno
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
SOURCES =
DIST_SOURCES =
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
ctags-recursive dvi-recursive html-recursive info-recursive \
install-data-recursive install-dvi-recursive \
install-exec-recursive install-html-recursive \
install-info-recursive install-pdf-recursive \
install-ps-recursive install-recursive installcheck-recursive \
installdirs-recursive pdf-recursive ps-recursive \
tags-recursive uninstall-recursive
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__dist_pam_DATA_DIST = pam/crond
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \
test -z "$$files" \
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
$(am__cd) "$$dir" && rm -f $$files; }; \
}
am__installdirs = "$(DESTDIR)$(pamdir)"
DATA = $(dist_pam_DATA)
HEADERS = $(dist_noinst_HEADERS)
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
am__recursive_targets = \
$(RECURSIVE_TARGETS) \
$(RECURSIVE_CLEAN_TARGETS) \
$(am__extra_recursive_targets)
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
cscope distdir distdir-am dist dist-all distcheck
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
$(LISP)config.h.in
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
CSCOPE = cscope
DIST_SUBDIRS = $(SUBDIRS)
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in AUTHORS \
COPYING ChangeLog INSTALL NEWS README compile config.guess \
config.sub depcomp install-sh missing
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
am__remove_distdir = \
if test -d "$(distdir)"; then \
find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
&& rm -rf "$(distdir)" \
|| { sleep 5 && rm -rf "$(distdir)"; }; \
else :; fi
am__post_remove_distdir = $(am__remove_distdir)
am__relativize = \
dir0=`pwd`; \
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
sed_rest='s,^[^/]*/*,,'; \
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
sed_butlast='s,/*[^/]*$$,,'; \
while test -n "$$dir1"; do \
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
if test "$$first" != "."; then \
if test "$$first" = ".."; then \
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
else \
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
if test "$$first2" = "$$first"; then \
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
else \
dir2="../$$dir2"; \
fi; \
dir0="$$dir0"/"$$first"; \
fi; \
fi; \
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
done; \
reldir="$$dir2"
DIST_ARCHIVES = $(distdir).tar.gz
GZIP_ENV = --best
DIST_TARGETS = dist-gzip
distuninstallcheck_listfiles = find . -type f -print
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
distcleancheck_listfiles = find . -type f -print
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
ANACRONTAB = @ANACRONTAB@
ANACRON_SPOOL_DIR = @ANACRON_SPOOL_DIR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DAEMON_GROUPNAME = @DAEMON_GROUPNAME@
DAEMON_USERNAME = @DAEMON_USERNAME@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBAUDIT = @LIBAUDIT@
LIBOBJS = @LIBOBJS@
LIBPAM = @LIBPAM@
LIBS = @LIBS@
LIBSELINUX = @LIBSELINUX@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
SPOOL_DIR = @SPOOL_DIR@
STRIP = @STRIP@
SYSCRONTAB = @SYSCRONTAB@
SYS_CROND_DIR = @SYS_CROND_DIR@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
editor_defined = @editor_defined@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
SUBDIRS = src man anacron
dist_noinst_HEADERS = \
cronie_common.h
EXTRA_DIST = cronie.init crond.sysconfig contrib/anacrontab \
contrib/0anacron contrib/0hourly contrib/dailyjobs \
contrib/cronie.systemd anacron/ChangeLog.anacron \
$(am__append_1)
@PAM_TRUE@pamdir = $(sysconfdir)/pam.d
@PAM_TRUE@dist_pam_DATA = pam/crond
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-recursive
.SUFFIXES:
am--refresh: Makefile
@:
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \
$(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
echo ' $(SHELL) ./config.status'; \
$(SHELL) ./config.status;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(top_srcdir)/configure: $(am__configure_deps)
$(am__cd) $(srcdir) && $(AUTOCONF)
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
$(am__aclocal_m4_deps):
config.h: stamp-h1
@test -f $@ || rm -f stamp-h1
@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
@rm -f stamp-h1
cd $(top_builddir) && $(SHELL) ./config.status config.h
$(srcdir)/config.h.in: $(am__configure_deps)
($(am__cd) $(top_srcdir) && $(AUTOHEADER))
rm -f stamp-h1
touch $@
distclean-hdr:
-rm -f config.h stamp-h1
install-dist_pamDATA: $(dist_pam_DATA)
@$(NORMAL_INSTALL)
@list='$(dist_pam_DATA)'; test -n "$(pamdir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(pamdir)'"; \
$(MKDIR_P) "$(DESTDIR)$(pamdir)" || exit 1; \
fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pamdir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(pamdir)" || exit $$?; \
done
uninstall-dist_pamDATA:
@$(NORMAL_UNINSTALL)
@list='$(dist_pam_DATA)'; test -n "$(pamdir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
dir='$(DESTDIR)$(pamdir)'; $(am__uninstall_files_from_dir)
# This directory's subdirectories are mostly independent; you can cd
# into them and run 'make' without going through this Makefile.
# To change the values of 'make' variables: instead of editing Makefiles,
# (1) if the variable is set in 'config.status', edit 'config.status'
# (which will cause the Makefiles to be regenerated when you run 'make');
# (2) otherwise, pass the desired values on the 'make' command line.
$(am__recursive_targets):
@fail=; \
if $(am__make_keepgoing); then \
failcom='fail=yes'; \
else \
failcom='exit 1'; \
fi; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
case "$@" in \
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
*) list='$(SUBDIRS)' ;; \
esac; \
for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-recursive
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
include_option=--etags-include; \
empty_fix=.; \
else \
include_option=--include; \
empty_fix=; \
fi; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test ! -f $$subdir/TAGS || \
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
fi; \
done; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-recursive
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscope: cscope.files
test ! -s cscope.files \
|| $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
clean-cscope:
-rm -f cscope.files
cscope.files: clean-cscope cscopelist
cscopelist: cscopelist-recursive
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
$(am__remove_distdir)
test -d "$(distdir)" || mkdir "$(distdir)"
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
$(am__make_dryrun) \
|| test -d "$(distdir)/$$subdir" \
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|| exit 1; \
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
$(am__relativize); \
new_distdir=$$reldir; \
dir1=$$subdir; dir2="$(top_distdir)"; \
$(am__relativize); \
new_top_distdir=$$reldir; \
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
($(am__cd) $$subdir && \
$(MAKE) $(AM_MAKEFLAGS) \
top_distdir="$$new_top_distdir" \
distdir="$$new_distdir" \
am__remove_distdir=: \
am__skip_length_check=: \
am__skip_mode_fix=: \
distdir) \
|| exit 1; \
fi; \
done
-test -n "$(am__skip_mode_fix)" \
|| find "$(distdir)" -type d ! -perm -755 \
-exec chmod u+rwx,go+rx {} \; -o \
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|| chmod -R a+r "$(distdir)"
dist-gzip: distdir
tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz
$(am__post_remove_distdir)
dist-bzip2: distdir
tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
$(am__post_remove_distdir)
dist-lzip: distdir
tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
$(am__post_remove_distdir)
dist-xz: distdir
tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
$(am__post_remove_distdir)
dist-tarZ: distdir
@echo WARNING: "Support for distribution archives compressed with" \
"legacy program 'compress' is deprecated." >&2
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
$(am__post_remove_distdir)
dist-shar: distdir
@echo WARNING: "Support for shar distribution archives is" \
"deprecated." >&2
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz
$(am__post_remove_distdir)
dist-zip: distdir
-rm -f $(distdir).zip
zip -rq $(distdir).zip $(distdir)
$(am__post_remove_distdir)
dist dist-all:
$(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
$(am__post_remove_distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
# tarfile.
distcheck: dist
case '$(DIST_ARCHIVES)' in \
*.tar.gz*) \
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\
*.tar.bz2*) \
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
*.tar.lz*) \
lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
*.tar.xz*) \
xz -dc $(distdir).tar.xz | $(am__untar) ;;\
*.tar.Z*) \
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
*.shar.gz*) \
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\
*.zip*) \
unzip $(distdir).zip ;;\
esac
chmod -R a-w $(distdir)
chmod u+w $(distdir)
mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst
chmod a-w $(distdir)
test -d $(distdir)/_build || exit 0; \
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
&& am__cwd=`pwd` \
&& $(am__cd) $(distdir)/_build/sub \
&& ../../configure \
$(AM_DISTCHECK_CONFIGURE_FLAGS) \
$(DISTCHECK_CONFIGURE_FLAGS) \
--srcdir=../.. --prefix="$$dc_install_base" \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
&& $(MAKE) $(AM_MAKEFLAGS) uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
distuninstallcheck \
&& chmod -R a-w "$$dc_install_base" \
&& ({ \
(cd ../.. && umask 077 && mkdir "$$dc_destdir") \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
} || { rm -rf "$$dc_destdir"; exit 1; }) \
&& rm -rf "$$dc_destdir" \
&& $(MAKE) $(AM_MAKEFLAGS) dist \
&& rm -rf $(DIST_ARCHIVES) \
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
&& cd "$$am__cwd" \
|| exit 1
$(am__post_remove_distdir)
@(echo "$(distdir) archives ready for distribution: "; \
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
distuninstallcheck:
@test -n '$(distuninstallcheck_dir)' || { \
echo 'ERROR: trying to run $@ with an empty' \
'$$(distuninstallcheck_dir)' >&2; \
exit 1; \
}; \
$(am__cd) '$(distuninstallcheck_dir)' || { \
echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
exit 1; \
}; \
test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
|| { echo "ERROR: files left after uninstall:" ; \
if test -n "$(DESTDIR)"; then \
echo " (check DESTDIR support)"; \
fi ; \
$(distuninstallcheck_listfiles) ; \
exit 1; } >&2
distcleancheck: distclean
@if test '$(srcdir)' = . ; then \
echo "ERROR: distcleancheck can only run from a VPATH build" ; \
exit 1 ; \
fi
@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
|| { echo "ERROR: files left in build directory after distclean:" ; \
$(distcleancheck_listfiles) ; \
exit 1; } >&2
check-am: all-am
check: check-recursive
all-am: Makefile $(DATA) $(HEADERS) config.h
installdirs: installdirs-recursive
installdirs-am:
for dir in "$(DESTDIR)$(pamdir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-recursive
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-recursive
clean-am: clean-generic mostlyclean-am
distclean: distclean-recursive
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-hdr distclean-tags
dvi: dvi-recursive
dvi-am:
html: html-recursive
html-am:
info: info-recursive
info-am:
install-data-am: install-dist_pamDATA
install-dvi: install-dvi-recursive
install-dvi-am:
install-exec-am:
install-html: install-html-recursive
install-html-am:
install-info: install-info-recursive
install-info-am:
install-man:
install-pdf: install-pdf-recursive
install-pdf-am:
install-ps: install-ps-recursive
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-recursive
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-generic
pdf: pdf-recursive
pdf-am:
ps: ps-recursive
ps-am:
uninstall-am: uninstall-dist_pamDATA
.MAKE: $(am__recursive_targets) all install-am install-strip
.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
am--refresh check check-am clean clean-cscope clean-generic \
cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \
dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \
distcheck distclean distclean-generic distclean-hdr \
distclean-tags distcleancheck distdir distuninstallcheck dvi \
dvi-am html html-am info info-am install install-am \
install-data install-data-am install-dist_pamDATA install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
installdirs-am maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \
tags-am uninstall uninstall-am uninstall-dist_pamDATA
.PRECIOUS: Makefile
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

42
NEWS
View File

@ -0,0 +1,42 @@
cronie NEWS -- history of user-visible changes.
Release 1.5.4
* crond: Fix regression from previous release. Only first job from a crontab
was being run.
Release 1.5.3
* Fix CVE-2019-9704 and CVE-2019-9705 to avoid local DoS of the crond.
* crontab: Make crontab without arguments fail.
* crond: In PAM configuration include system-auth instead of password-auth.
* crond: In the systemd service file restart crond if it fails.
* crond: Use the role from the crond context for system job contexts.
* Multiple small cleanups and fixes.
Release 1.5.2
* cronnext: New useful utility to find out time of the next job run.
* crond: Avoid creating PID files when crond doesn't fork.
* crontab: Do not try to replace the crontab with a directory.
* crond: Log startup even when started in non-forking mode.
* Multiple small cleanups and fixes.
Release 1.5.1
* crontab: Use temporary file name that is ignored by crond.
* crond: Inherit PATH from the crond environment if -P option is used.
* crond: Remove hardcoded "system_u" SELinux user, use the SELinux user
of the running crond.
* anacron: Small cleanups and fixes.
* crond: Fix longstanding race condition on repeated crontab modification.
Release 1.5.0
* First release with NEWS. :)
* crond: Job environment variables are set also when executing sendmail.
* crond: Adding duplicate orphans on reload is now prevented.
* crond: The regular crond shutdown is now logged.
* crontab: PAM is not called in crontab command if the caller's uid is 0.
* crond: PAM is not called from crond for system cron jobs
(/etc/crontab, /etc/cron.d) which are run for uid 0.
* crond: The existence of an user is checked at time when job is run
and not when the crontab is parsed on database reload.

View File

@ -1,142 +0,0 @@
What is Anacron ?
-----------------
Anacron is a periodic command scheduler. It executes commands at
intervals specified in days. Unlike cron, it does not assume that the
system is running continuously. It can therefore be used to control
the execution of daily, weekly and monthly jobs (or anything with a
period of n days), on systems that don't run 24 hours a day. When
installed and configured properly, Anacron will make sure that the
commands are run at the specified intervals as closely as
machine-uptime permits.
Every time Anacron is run, it reads a configuration file that
specifies the jobs Anacron controls, and their periods in days. If a
job wasn't executed in the last n days, where n is the period of that
job, Anacron executes it. Anacron then records the date in a special
timestamp file that it keeps for each job, so it can know when to run
it again. When all the executed commands terminate, Anacron exits.
It is recommended to run Anacron from the system boot-scripts.
This way the jobs "whose time has come" will be run shortly after the
machine boots. A delay can be specified for each job so that the
machine isn't overloaded at boot time.
In addition to running Anacron from the boot-scripts, it is also
recommended to schedule it as a daily cron-job (usually at an early
morning hour), so that if the machine is kept running for a night,
jobs for the next day will still be executed.
Why this may be useful ?
------------------------
Most Unix-like systems have daily, weekly and monthly scripts that
take care of various "housekeeping chores" such as log-rotation,
updating the "locate" and "man" databases, etc. Daily scripts are
usually scheduled as cron-jobs to execute around 1-7 AM. Weekly
scripts are scheduled to run on Sundays. On machines that are turned
off for the night or for the weekend, these scripts rarely get run.
Anacron solves this problem. These jobs can simply be scheduled as
Anacron-jobs with periods of 1, 7 and a special target called @monthly.
What Anacron is not ?
---------------------
Anacron is not an attempt to make cron redundant. It cannot
currently be used to schedule commands at intervals smaller than days.
It also does not guarantee that the commands will be executed at any
specific day or hour.
It isn't a full-time daemon. It has to be executed from boot
scripts, from cron-jobs, or explicitly.
For more details, see the anacron(8) manpage.
Requirements
------------
- A Linux system. (maybe other *NIX systems)
- A functioning syslog daemon.
- A functioning /usr/lib/sendmail command. (all MTAs should have
that).
Compilation and Installation
----------------------------
- Untar the source package.
- Check the Makefile. Edit as required.
- Check the top of "global.h". You may want to change the syslog
facility and priorities, and the path to your MTA's sendmail
compatible command (/usr/lib/sendmail).
- cd to the directory.
- Type "make".
You can safely ignore warnings of the form: "*.d: No such file or
directory"
- Become root. Type "make install".
Setup
-----
1. Locate your system's daily, weekly and monthly cron-jobs.
See your cron documentation for more details.
2. Decide which of these jobs should be controlled by Anacron.
Remember that Anacron does not guarantee execution at any specific
day of the month, day of the week, or time of day. Jobs for which
the timing is critical should probably not be controlled by
Anacron.
3. Comment these jobs out of their crontab files. (You may have to
use the "crontab" command for this. See the cron documentation.)
4. Put them in /etc/anacrontab. Note that the format is not the same
as the crontab entries. See the anacrontab(5) manpage. Here's an
example from a typical Debian system:
-----Cut
# /etc/anacrontab example
SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
# format: period delay job-identifier command
1 5 cron.daily run-parts /etc/cron.daily
7 10 cron.weekly run-parts /etc/cron.weekly
@monthly 15 cron.monthly run-parts /etc/cron.monthly
-----Cut
5. Put the command "anacron -s" somewhere in your boot-scripts.
Make sure that syslogd is started before this command.
6. Schedule the command "anacron -s" as a daily cron-job (preferably
at some early morning hour). This will make sure that jobs are run
when the systems is left running for a night.
That's it.
It is a good idea to check what your daily, weekly and monthly scripts
actually do, and disable any parts that may be irrelevant for your
system.
Credits
-------
Anacron was originally conceived and implemented by Christian Schwarz
<schwarz@monet.m.isar.de>.
The current implementation is a complete rewrite by Itai Tzur
<itzur@actcom.co.il>.
Current code base maintained by Sean 'Shaleh' Perry <shaleh@(debian.org|valinux.com)>.

1135
aclocal.m4 vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,7 @@
# Makefile.am - two binaries crond and crontab # Makefile.am - two binaries crond and crontab
if ANACRON
sbin_PROGRAMS = anacron sbin_PROGRAMS = anacron
endif
anacron_SOURCES = \ anacron_SOURCES = \
gregor.c lock.c log.c main.c matchrx.c readtab.c runjob.c \ gregor.c lock.c log.c main.c matchrx.c readtab.c runjob.c \
@ -9,6 +11,7 @@ common_nodist = anacron-paths.h
nodist_anacron_SOURCES = $(common_nodist) nodist_anacron_SOURCES = $(common_nodist)
BUILT_SOURCES = $(common_nodist) BUILT_SOURCES = $(common_nodist)
AM_CFLAGS = -I$(top_srcdir)
LDADD = $(LIBSELINUX) $(LIBPAM) $(LIBAUDIT) LDADD = $(LIBSELINUX) $(LIBPAM) $(LIBAUDIT)

647
anacron/Makefile.in Normal file
View File

@ -0,0 +1,647 @@
# Makefile.in generated by automake 1.16.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2018 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
@ANACRON_TRUE@sbin_PROGRAMS = anacron$(EXEEXT)
subdir = anacron
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(sbindir)"
PROGRAMS = $(sbin_PROGRAMS)
am__objects_1 =
am_anacron_OBJECTS = gregor.$(OBJEXT) lock.$(OBJEXT) log.$(OBJEXT) \
main.$(OBJEXT) matchrx.$(OBJEXT) readtab.$(OBJEXT) \
runjob.$(OBJEXT) $(am__objects_1)
nodist_anacron_OBJECTS = $(am__objects_1)
anacron_OBJECTS = $(am_anacron_OBJECTS) $(nodist_anacron_OBJECTS)
anacron_LDADD = $(LDADD)
am__DEPENDENCIES_1 =
anacron_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1)
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/gregor.Po ./$(DEPDIR)/lock.Po \
./$(DEPDIR)/log.Po ./$(DEPDIR)/main.Po ./$(DEPDIR)/matchrx.Po \
./$(DEPDIR)/readtab.Po ./$(DEPDIR)/runjob.Po
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo " CC " $@;
am__v_CC_1 =
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(anacron_SOURCES) $(nodist_anacron_SOURCES)
DIST_SOURCES = $(anacron_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
ANACRONTAB = @ANACRONTAB@
ANACRON_SPOOL_DIR = @ANACRON_SPOOL_DIR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DAEMON_GROUPNAME = @DAEMON_GROUPNAME@
DAEMON_USERNAME = @DAEMON_USERNAME@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBAUDIT = @LIBAUDIT@
LIBOBJS = @LIBOBJS@
LIBPAM = @LIBPAM@
LIBS = @LIBS@
LIBSELINUX = @LIBSELINUX@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
SPOOL_DIR = @SPOOL_DIR@
STRIP = @STRIP@
SYSCRONTAB = @SYSCRONTAB@
SYS_CROND_DIR = @SYS_CROND_DIR@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
editor_defined = @editor_defined@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
anacron_SOURCES = \
gregor.c lock.c log.c main.c matchrx.c readtab.c runjob.c \
$(common_src)
common_src = global.h gregor.h matchrx.h
common_nodist = anacron-paths.h
nodist_anacron_SOURCES = $(common_nodist)
BUILT_SOURCES = $(common_nodist)
AM_CFLAGS = -I$(top_srcdir)
LDADD = $(LIBSELINUX) $(LIBPAM) $(LIBAUDIT)
all: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) all-am
.SUFFIXES:
.SUFFIXES: .c .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu anacron/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu anacron/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
install-sbinPROGRAMS: $(sbin_PROGRAMS)
@$(NORMAL_INSTALL)
@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
$(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
fi; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
while read p p1; do if test -f $$p \
; then echo "$$p"; echo "$$p"; else :; fi; \
done | \
sed -e 'p;s,.*/,,;n;h' \
-e 's|.*|.|' \
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
if ($$2 == $$4) files[d] = files[d] " " $$1; \
else { print "f", $$3 "/" $$4, $$1; } } \
END { for (d in files) print "f", d, files[d] }' | \
while read type dir files; do \
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
test -z "$$files" || { \
echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
$(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
} \
; done
uninstall-sbinPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
-e 's/$$/$(EXEEXT)/' \
`; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(sbindir)" && rm -f $$files
clean-sbinPROGRAMS:
-test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS)
anacron$(EXEEXT): $(anacron_OBJECTS) $(anacron_DEPENDENCIES) $(EXTRA_anacron_DEPENDENCIES)
@rm -f anacron$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(anacron_OBJECTS) $(anacron_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gregor.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lock.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/matchrx.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readtab.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/runjob.Po@am__quote@ # am--include-marker
$(am__depfiles_remade):
@$(MKDIR_P) $(@D)
@echo '# dummy' >$@-t && $(am__mv) $@-t $@
am--depfiles: $(am__depfiles_remade)
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-am
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) check-am
all-am: Makefile $(PROGRAMS)
installdirs:
for dir in "$(DESTDIR)$(sbindir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
clean: clean-am
clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am
distclean: distclean-am
-rm -f ./$(DEPDIR)/gregor.Po
-rm -f ./$(DEPDIR)/lock.Po
-rm -f ./$(DEPDIR)/log.Po
-rm -f ./$(DEPDIR)/main.Po
-rm -f ./$(DEPDIR)/matchrx.Po
-rm -f ./$(DEPDIR)/readtab.Po
-rm -f ./$(DEPDIR)/runjob.Po
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am: install-sbinPROGRAMS
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/gregor.Po
-rm -f ./$(DEPDIR)/lock.Po
-rm -f ./$(DEPDIR)/log.Po
-rm -f ./$(DEPDIR)/main.Po
-rm -f ./$(DEPDIR)/matchrx.Po
-rm -f ./$(DEPDIR)/readtab.Po
-rm -f ./$(DEPDIR)/runjob.Po
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-sbinPROGRAMS
.MAKE: all check install install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
clean-generic clean-sbinPROGRAMS cscopelist-am ctags ctags-am \
distclean distclean-compile distclean-generic distclean-tags \
distdir dvi dvi-am html html-am info info-am install \
install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-ps install-ps-am \
install-sbinPROGRAMS install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
uninstall-am uninstall-sbinPROGRAMS
.PRECIOUS: Makefile
# This header contains all the paths.
# If they are configurable, they are declared in configure script.
# Depends on this Makefile, because it uses make variables.
anacron-paths.h: Makefile
@echo 'creating $@'
@sed >$@ 's/ *\\$$//' <<\END #\
/* This file has been automatically generated. Do not edit. */ \
\
#ifndef _ANACRON_PATHS_H_ \
#define _ANACRON_PATHS_H_ \
#define ANACRON_SPOOL_DIR "$(ANACRON_SPOOL_DIR)" \
#define ANACRONTAB "$(ANACRONTAB)" \
#endif /* _ANACRON_PATHS_H_ */ \
END
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@ -14,9 +14,9 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License along
along with this program; if not, write to the Free Software with this program; if not, write to the Free Software Foundation, Inc.,
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
The GNU General Public License can also be found in the file The GNU General Public License can also be found in the file
`COPYING' that comes with the Anacron source distribution. `COPYING' that comes with the Anacron source distribution.
@ -44,6 +44,7 @@
#include <signal.h> #include <signal.h>
#include <time.h> #include <time.h>
#include "anacron-paths.h" #include "anacron-paths.h"
#include "cronie_common.h"
/* Some declarations */ /* Some declarations */
@ -67,7 +68,7 @@ struct job_rec1 {
int timestamp_fd; int timestamp_fd;
int input_fd; int input_fd;
int output_fd; int output_fd;
int mail_header_size; off_t mail_header_size;
pid_t job_pid; pid_t job_pid;
pid_t mailer_pid; pid_t mailer_pid;
int drop_job; int drop_job;
@ -93,8 +94,8 @@ extern int in_background;
extern job_rec *first_job_rec; extern job_rec *first_job_rec;
extern env_rec *first_env_rec; extern env_rec *first_env_rec;
extern char **args; extern char **job_args;
extern int nargs; extern int job_nargs;
extern int njobs; extern int njobs;
extern job_rec **job_array; extern job_rec **job_array;
@ -109,6 +110,9 @@ extern time_t start_sec;
extern int range_start; extern int range_start;
extern int range_stop; extern int range_stop;
/* preferred hour for jobs */
extern int preferred_hour;
/* Function prototypes */ /* Function prototypes */
/* main.c */ /* main.c */
@ -128,8 +132,8 @@ void explain(const char *fmt, ...)PRINTF_FORMAT(1,2);
void explain_e(const char *fmt, ...)PRINTF_FORMAT(1,2); void explain_e(const char *fmt, ...)PRINTF_FORMAT(1,2);
void complain(const char *fmt, ...)PRINTF_FORMAT(1,2); void complain(const char *fmt, ...)PRINTF_FORMAT(1,2);
void complain_e(const char *fmt, ...)PRINTF_FORMAT(1,2); void complain_e(const char *fmt, ...)PRINTF_FORMAT(1,2);
void die(const char *fmt, ...)PRINTF_FORMAT(1,2); void die(const char *fmt, ...)PRINTF_FORMAT(1,2) ATTRIBUTE_NORETURN;
void die_e(const char *fmt, ...)PRINTF_FORMAT(1,2); void die_e(const char *fmt, ...)PRINTF_FORMAT(1,2) ATTRIBUTE_NORETURN;
void xdebug(const char *fmt, ...)PRINTF_FORMAT(1,2); void xdebug(const char *fmt, ...)PRINTF_FORMAT(1,2);
void xdebug_e(const char *fmt, ...)PRINTF_FORMAT(1,2); void xdebug_e(const char *fmt, ...)PRINTF_FORMAT(1,2);
void xcloselog(void); void xcloselog(void);

View File

@ -14,9 +14,9 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License along
along with this program; if not, write to the Free Software with this program; if not, write to the Free Software Foundation, Inc.,
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
The GNU General Public License can also be found in the file The GNU General Public License can also be found in the file
`COPYING' that comes with the Anacron source distribution. `COPYING' that comes with the Anacron source distribution.

View File

@ -14,9 +14,9 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License along
along with this program; if not, write to the Free Software with this program; if not, write to the Free Software Foundation, Inc.,
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
The GNU General Public License can also be found in the file The GNU General Public License can also be found in the file
`COPYING' that comes with the Anacron source distribution. `COPYING' that comes with the Anacron source distribution.

View File

@ -14,9 +14,9 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License along
along with this program; if not, write to the Free Software with this program; if not, write to the Free Software Foundation, Inc.,
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
The GNU General Public License can also be found in the file The GNU General Public License can also be found in the file
`COPYING' that comes with the Anacron source distribution. `COPYING' that comes with the Anacron source distribution.
@ -129,7 +129,7 @@ consider_job(job_rec *jr)
period = days_last_month (); period = days_last_month ();
bypass = days_this_month (); bypass = days_this_month ();
break; break;
case 2: /* yearly, annualy */ case 2: /* yearly, annually */
period = days_last_year (); period = days_last_year ();
bypass = days_this_year (); bypass = days_this_year ();
break; break;
@ -156,6 +156,12 @@ consider_job(job_rec *jr)
jobtime = start_sec + jr->delay * 60; jobtime = start_sec + jr->delay * 60;
t = localtime(&jobtime); t = localtime(&jobtime);
if (!now && preferred_hour != -1 && t->tm_hour != preferred_hour) {
Debug(("The job's %s preferred hour %d was missed, skipping the job.", jr->ident, preferred_hour));
xclose (jr->timestamp_fd);
return 0;
}
if (!now && range_start != -1 && range_stop != -1 && if (!now && range_start != -1 && range_stop != -1 &&
(t->tm_hour < range_start || t->tm_hour >= range_stop)) (t->tm_hour < range_start || t->tm_hour >= range_stop))
{ {

View File

@ -14,9 +14,9 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License along
along with this program; if not, write to the Free Software with this program; if not, write to the Free Software Foundation, Inc.,
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
The GNU General Public License can also be found in the file The GNU General Public License can also be found in the file
`COPYING' that comes with the Anacron source distribution. `COPYING' that comes with the Anacron source distribution.
@ -54,7 +54,7 @@ static int log_open = 0;
int complaints = 0; int complaints = 0;
static void static void
xopenlog() xopenlog(void)
{ {
if (!log_open) if (!log_open)
{ {
@ -64,7 +64,7 @@ xopenlog()
} }
void void
xcloselog() xcloselog(void)
{ {
if (log_open) closelog(); if (log_open) closelog();
log_open = 0; log_open = 0;

View File

@ -14,14 +14,15 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License along
along with this program; if not, write to the Free Software with this program; if not, write to the Free Software Foundation, Inc.,
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
The GNU General Public License can also be found in the file The GNU General Public License can also be found in the file
`COPYING' that comes with the Anacron source distribution. `COPYING' that comes with the Anacron source distribution.
*/ */
#include "config.h"
#include <time.h> #include <time.h>
#include <sys/time.h> #include <sys/time.h>
@ -36,6 +37,7 @@
#include <locale.h> #include <locale.h>
#include "global.h" #include "global.h"
#include "gregor.h" #include "gregor.h"
#include "cronie_common.h"
pid_t primary_pid; pid_t primary_pid;
int day_now; int day_now;
@ -46,11 +48,10 @@ char *anacrontab;
char *spooldir; char *spooldir;
int serialize, force, update_only, now, int serialize, force, update_only, now,
no_daemon, quiet, testing_only; /* command-line options */ no_daemon, quiet, testing_only; /* command-line options */
char **args; /* vector of "job" command-line arguments */ char **job_args; /* vector of "job" command-line arguments */
int nargs; /* number of these */ int job_nargs; /* number of these */
char *defarg = "*"; char *defarg = "*";
int in_background; /* are we in the background? */ int in_background; /* are we in the background? */
int old_umask; /* umask when started */
sigset_t old_sigmask; /* signal mask when started */ sigset_t old_sigmask; /* signal mask when started */
job_rec *first_job_rec; job_rec *first_job_rec;
@ -61,41 +62,39 @@ static volatile int got_sigalrm, got_sigchld, got_sigusr1;
int running_jobs, running_mailers; /* , number of */ int running_jobs, running_mailers; /* , number of */
int range_start = -1; int range_start = -1;
int range_stop = -1; int range_stop = -1;
int preferred_hour = -1;
static void static void
print_version() print_version(void)
{ {
printf("Anacron \n" printf("Anacron from project %s\n"
"Copyright (C) 1998 Itai Tzur <itzur@actcom.co.il>\n" "Copyright (C) 1998 Itai Tzur <itzur@actcom.co.il>\n"
"Copyright (C) 1999 Sean 'Shaleh' Perry <shaleh@debian.org>\n" "Copyright (C) 1999 Sean 'Shaleh' Perry <shaleh@debian.org>\n"
"Copyright (C) 2004 Pascal Hakim <pasc@redellipse.net>\n" "Copyright (C) 2004 Pascal Hakim <pasc@redellipse.net>\n"
"\n" "\n"
"Mail comments, suggestions and bug reports to <pasc@redellipse.net>." "Mail comments, suggestions and bug reports to <pasc@redellipse.net>."
"\n\n"); "\n\n", PACKAGE_STRING);
} }
static void static void
print_usage() print_usage(void)
{ {
printf("Usage: anacron [-s] [-f] [-n] [-d] [-q] [-t anacrontab] [-S spooldir] [job] ...\n" printf("Usage:\n");
" anacron [-S spooldir] -u [job] ...\n" printf(" %s [options] [job] ...\n", program_name);
" anacron [-V|-h]\n" printf(" %s -T [-t anacrontab-file]\n", program_name);
" anacron -T [-t anacrontab]\n" printf("\nOptions:\n");
"\n" printf(" -s Serialize execution of jobs\n");
" -s Serialize execution of jobs\n" printf(" -f Force execution of jobs, even before their time\n");
" -f Force execution of jobs, even before their time\n" printf(" -n Run jobs with no delay, implies -s\n");
" -n Run jobs with no delay, implies -s\n" printf(" -d Don't fork to the background\n");
" -d Don't fork to the background\n" printf(" -q Suppress stderr messages, only applicable with -d\n");
" -q Suppress stderr messages, only applicable with -d\n" printf(" -u Update the timestamps without actually running anything\n");
" -u Update the timestamps without actually running anything\n" printf(" -V Print version information\n");
" -t Use this anacrontab\n" printf(" -h Print this message\n");
" -V Print version information\n" printf(" -t <file> Use alternative anacrontab\n");
" -h Print this message\n" printf(" -T Test an anacrontab\n");
" -T Test an anacrontab\n" printf(" -S <dir> Select a different spool directory\n");
" -S Select a different spool directory\n" printf("\nSee the anacron(8) manpage for more details.\n");
"\n"
"See the manpage for more details.\n"
"\n");
} }
static void static void
@ -139,10 +138,10 @@ parse_opts(int argc, char *argv[])
break; break;
case 'V': case 'V':
print_version(); print_version();
exit(0); exit(EXIT_SUCCESS);
case 'h': case 'h':
print_usage(); print_usage();
exit(0); exit(EXIT_SUCCESS);
case '?': case '?':
fprintf(stderr, "%s: invalid option: %c\n", fprintf(stderr, "%s: invalid option: %c\n",
program_name, optopt); program_name, optopt);
@ -154,18 +153,18 @@ parse_opts(int argc, char *argv[])
if (optind == argc) if (optind == argc)
{ {
/* no arguments. Equivalent to: `*' */ /* no arguments. Equivalent to: `*' */
nargs = 1; job_nargs = 1;
args = &defarg; job_args = &defarg;
} }
else else
{ {
nargs = argc - optind; job_nargs = argc - optind;
args = argv + optind; job_args = argv + optind;
} }
} }
pid_t pid_t
xfork() xfork(void)
/* Like fork(), only never returns on failure */ /* Like fork(), only never returns on failure */
{ {
pid_t pid; pid_t pid;
@ -201,7 +200,7 @@ xclose(int fd)
} }
static void static void
go_background() go_background(void)
/* Become a daemon. The foreground process exits successfully. */ /* Become a daemon. The foreground process exits successfully. */
{ {
pid_t pid; pid_t pid;
@ -218,7 +217,7 @@ go_background()
if (pid != 0) if (pid != 0)
{ {
/* parent */ /* parent */
exit(0); exit(EXIT_SUCCESS);
} }
else else
{ {
@ -229,26 +228,26 @@ go_background()
} }
} }
void static void
handle_sigalrm() handle_sigalrm(int unused ATTRIBUTE_UNUSED)
{ {
got_sigalrm = 1; got_sigalrm = 1;
} }
void static void
handle_sigchld() handle_sigchld(int unused ATTRIBUTE_UNUSED)
{ {
got_sigchld = 1; got_sigchld = 1;
} }
void static void
handle_sigusr1() handle_sigusr1(int unused ATTRIBUTE_UNUSED)
{ {
got_sigusr1 = 1; got_sigusr1 = 1;
} }
static void static void
set_signal_handling() set_signal_handling(void)
/* We only use SIGALRM, SIGCHLD and SIGUSR1, and we unblock them only /* We only use SIGALRM, SIGCHLD and SIGUSR1, and we unblock them only
* in wait_signal(). * in wait_signal().
*/ */
@ -285,7 +284,7 @@ set_signal_handling()
} }
static void static void
wait_signal() wait_signal(void)
/* Return after a signal is caught */ /* Return after a signal is caught */
{ {
sigset_t ss; sigset_t ss;
@ -298,7 +297,7 @@ wait_signal()
} }
static void static void
wait_children() wait_children(void)
/* Wait until we have no more children (of any kind) */ /* Wait until we have no more children (of any kind) */
{ {
while (running_jobs > 0 || running_mailers > 0) while (running_jobs > 0 || running_mailers > 0)
@ -312,14 +311,14 @@ wait_children()
} }
static void static void
orderly_termination() orderly_termination(void)
/* Execution is diverted here, when we get SIGUSR1 */ /* Execution is diverted here, when we get SIGUSR1 */
{ {
explain("Received SIGUSR1"); explain("Received SIGUSR1");
got_sigusr1 = 0; got_sigusr1 = 0;
wait_children(); wait_children();
explain("Exited"); explain("Exited");
exit(0); exit(EXIT_SUCCESS);
} }
static void static void
@ -342,7 +341,7 @@ xsleep(unsigned int n)
} }
static void static void
wait_jobs() wait_jobs(void)
/* Wait until there are no running jobs, /* Wait until there are no running jobs,
* servicing SIGCHLDs and SIGUSR1s in the meantime. * servicing SIGCHLDs and SIGUSR1s in the meantime.
*/ */
@ -357,7 +356,7 @@ wait_jobs()
} }
static void static void
record_start_time() record_start_time(void)
{ {
struct tm *tm_now; struct tm *tm_now;
@ -373,17 +372,17 @@ record_start_time()
year, month, day_of_month); year, month, day_of_month);
} }
static int static unsigned int
time_till(job_rec *jr) time_till(job_rec *jr)
/* Return the number of seconds that we have to wait until it's time /* Return the number of seconds that we have to wait until it's time
* to start job jr. * to start job jr.
*/ */
{ {
unsigned int tj, tn; time_t tj, tn;
if (now) return 0; if (now) return 0;
tn = time(NULL); tn = time(NULL);
tj = start_sec + jr->delay * 60; tj = start_sec + (time_t)jr->delay * 60;
if (tj < tn) return 0; if (tj < tn) return 0;
if (tj - tn > 3600*24) if (tj - tn > 3600*24)
{ {
@ -391,11 +390,11 @@ time_till(job_rec *jr)
jr->ident); jr->ident);
return 0; return 0;
} }
return tj - tn; return (unsigned int)(tj - tn);
} }
static void static void
fake_jobs() fake_jobs(void)
{ {
int j; int j;
@ -410,7 +409,7 @@ fake_jobs()
} }
static void static void
explain_intentions() explain_intentions(void)
{ {
int j; int j;
@ -448,7 +447,7 @@ main(int argc, char *argv[])
if (gettimeofday(&tv, &tz) != 0) if (gettimeofday(&tv, &tz) != 0)
explain("Can't get exact time, failure."); explain("Can't get exact time, failure.");
srandom(getpid()+tv.tv_usec); srandom((unsigned int)(getpid() + tv.tv_usec));
if((program_name = strrchr(argv[0], '/')) == NULL) if((program_name = strrchr(argv[0], '/')) == NULL)
program_name = argv[0]; program_name = argv[0];
@ -471,12 +470,10 @@ main(int argc, char *argv[])
if (chdir(spooldir)) die_e("Can't chdir to %s", spooldir ); if (chdir(spooldir)) die_e("Can't chdir to %s", spooldir );
old_umask = umask(0);
if (sigprocmask(0, NULL, &old_sigmask)) die_e("sigset error"); if (sigprocmask(0, NULL, &old_sigmask)) die_e("sigset error");
if (fclose(stdin)) die_e("Can't close stdin"); if (fclose(stdin)) die_e("Can't close stdin");
xopen(0, "/dev/null", O_RDONLY); xopen(STDIN_FILENO, "/dev/null", O_RDONLY);
if (!no_daemon && !testing_only) if (!no_daemon && !testing_only)
go_background(); go_background();
@ -490,15 +487,15 @@ main(int argc, char *argv[])
if (testing_only) if (testing_only)
{ {
if (complaints) exit (1); if (complaints) exit (EXIT_FAILURE);
exit (0); exit (EXIT_SUCCESS);
} }
if (update_only) if (update_only)
{ {
fake_jobs(); fake_jobs();
exit(0); exit(EXIT_SUCCESS);
} }
explain_intentions(); explain_intentions();
@ -512,5 +509,5 @@ main(int argc, char *argv[])
} }
wait_children(); wait_children();
explain("Normal exit (%d job%s run)", njobs, njobs == 1 ? "" : "s"); explain("Normal exit (%d job%s run)", njobs, njobs == 1 ? "" : "s");
exit(0); exit(EXIT_SUCCESS);
} }

View File

@ -13,9 +13,9 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License along
along with this program; if not, write to the Free Software with this program; if not, write to the Free Software Foundation, Inc.,
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
The GNU General Public License can also be found in the file The GNU General Public License can also be found in the file
`COPYING' that comes with the Anacron source distribution. `COPYING' that comes with the Anacron source distribution.
@ -30,7 +30,7 @@
#include "matchrx.h" #include "matchrx.h"
int int
match_rx(const char *rx, char *string, int n_sub, /* char **substrings */...) match_rx(const char *rx, char *string, unsigned int n_sub, /* char **substrings */...)
/* Return 1 if the regular expression "*rx" matches the string "*string", /* Return 1 if the regular expression "*rx" matches the string "*string",
* 0 if not, -1 on error. * 0 if not, -1 on error.
* "Extended" regular expressions are used. * "Extended" regular expressions are used.

View File

@ -13,9 +13,9 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License along
along with this program; if not, write to the Free Software with this program; if not, write to the Free Software Foundation, Inc.,
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
The GNU General Public License can also be found in the file The GNU General Public License can also be found in the file
`COPYING' that comes with the Anacron source distribution. `COPYING' that comes with the Anacron source distribution.
@ -23,4 +23,4 @@
int match_rx(const char *rx, char *string, int match_rx(const char *rx, char *string,
int n_sub, /* char **substrings */...); unsigned int n_sub, /* char **substrings */...);

View File

@ -14,9 +14,9 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License along
along with this program; if not, write to the Free Software with this program; if not, write to the Free Software Foundation, Inc.,
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
The GNU General Public License can also be found in the file The GNU General Public License can also be found in the file
`COPYING' that comes with the Anacron source distribution. `COPYING' that comes with the Anacron source distribution.
@ -77,11 +77,11 @@ conv2int(const char *s)
l = strtol(s, NULL, 10); l = strtol(s, NULL, 10);
/* we use negative as error, so I am really returning unsigned int */ /* we use negative as error, so I am really returning unsigned int */
if (errno == ERANGE || l < 0 || l > INT_MAX) return - 1; if (errno == ERANGE || l < 0 || l > INT_MAX) return - 1;
return l; return (int)l;
} }
static char * static char *
read_tab_line () read_tab_line (void)
/* Read one line and return a pointer to it. /* Read one line and return a pointer to it.
Return NULL if no more lines. Return NULL if no more lines.
*/ */
@ -94,11 +94,11 @@ Return NULL if no more lines.
c = getc(tab); c = getc(tab);
if ((c == '\n' && prev != '\\') || c == EOF) if ((c == '\n' && prev != '\\') || c == EOF)
{ {
if (0 != prev) obstack_1grow(&input_o, prev); if (0 != prev) obstack_1grow(&input_o, (char)prev);
break; break;
} }
if ('\\' != prev && 0 != prev && '\n' != prev) obstack_1grow(&input_o, prev); if ('\\' != prev && 0 != prev && '\n' != prev) obstack_1grow(&input_o, (char)prev);
else if ('\n' == prev) obstack_1grow(&input_o, ' '); else if ('\n' == prev) obstack_1grow(&input_o, ' ');
prev = c; prev = c;
@ -110,15 +110,15 @@ Return NULL if no more lines.
static int static int
job_arg_num(const char *ident) job_arg_num(const char *ident)
/* Return the command-line-argument number refering to this job-identifier. /* Return the command-line-argument number referring to this job-identifier.
* If it isn't specified, return -1. * If it isn't specified, return -1.
*/ */
{ {
int i, r; int i, r;
for (i = 0; i < nargs; i++) for (i = 0; i < job_nargs; i++)
{ {
r = fnmatch(args[i], ident, 0); r = fnmatch(job_args[i], ident, 0);
if (r == 0) return i; if (r == 0) return i;
if (r != FNM_NOMATCH) die("fnmatch() error"); if (r != FNM_NOMATCH) die("fnmatch() error");
} }
@ -132,10 +132,21 @@ register_env(const char *env_var, const char *value)
env_rec *er; env_rec *er;
int var_len, val_len; int var_len, val_len;
var_len = strlen(env_var); var_len = (int)strlen(env_var);
val_len = strlen(value); val_len = (int)strlen(value);
if (!var_len) {
return;
}
er = obstack_alloc(&tab_o, sizeof(env_rec)); er = obstack_alloc(&tab_o, sizeof(env_rec));
if (er == NULL) {
die_e("Cannot allocate memory.");
}
er->assign = obstack_alloc(&tab_o, var_len + 1 + val_len + 1); er->assign = obstack_alloc(&tab_o, var_len + 1 + val_len + 1);
if (er->assign == NULL) {
die_e("Cannot allocate memory.");
}
strcpy(er->assign, env_var); strcpy(er->assign, env_var);
er->assign[var_len] = '='; er->assign[var_len] = '=';
strcpy(er->assign + var_len + 1, value); strcpy(er->assign + var_len + 1, value);
@ -155,8 +166,8 @@ register_job(const char *periods, const char *delays,
job_rec *jr; job_rec *jr;
int ident_len, command_len; int ident_len, command_len;
ident_len = strlen(ident); ident_len = (int)strlen(ident);
command_len = strlen(command); command_len = (int)strlen(command);
jobs_read++; jobs_read++;
period = conv2int(periods); period = conv2int(periods);
delay = conv2int(delays); delay = conv2int(delays);
@ -167,15 +178,24 @@ register_job(const char *periods, const char *delays,
return; return;
} }
jr = obstack_alloc(&tab_o, sizeof(job_rec)); jr = obstack_alloc(&tab_o, sizeof(job_rec));
if (jr == NULL) {
die_e("Cannot allocate memory.");
}
jr->period = period; jr->period = period;
jr->named_period = 0; jr->named_period = 0;
delay += random_number; delay += random_number;
jr->delay = delay; jr->delay = delay;
jr->tab_line = line_num; jr->tab_line = line_num;
jr->ident = obstack_alloc(&tab_o, ident_len + 1); jr->ident = obstack_alloc(&tab_o, ident_len + 1);
if (jr->ident == NULL) {
die_e("Cannot allocate memory.");
}
strcpy(jr->ident, ident); strcpy(jr->ident, ident);
jr->arg_num = job_arg_num(ident); jr->arg_num = job_arg_num(ident);
jr->command = obstack_alloc(&tab_o, command_len + 1); jr->command = obstack_alloc(&tab_o, command_len + 1);
if (jr->command == NULL) {
die_e("Cannot allocate memory.");
}
strcpy(jr->command, command); strcpy(jr->command, command);
jr->job_pid = jr->mailer_pid = 0; jr->job_pid = jr->mailer_pid = 0;
if (last_job_rec != NULL) last_job_rec->next = jr; if (last_job_rec != NULL) last_job_rec->next = jr;
@ -194,11 +214,10 @@ register_period_job(const char *periods, const char *delays,
{ {
int delay; int delay;
job_rec *jr; job_rec *jr;
int period_len, ident_len, command_len; int ident_len, command_len;
period_len = strlen(periods); ident_len = (int)strlen(ident);
ident_len = strlen(ident); command_len = (int)strlen(command);
command_len = strlen(command);
jobs_read++; jobs_read++;
delay = conv2int(delays); delay = conv2int(delays);
if (delay < 0) if (delay < 0)
@ -209,11 +228,14 @@ register_period_job(const char *periods, const char *delays,
} }
jr = obstack_alloc(&tab_o, sizeof(job_rec)); jr = obstack_alloc(&tab_o, sizeof(job_rec));
if (!strncmp ("@monthly", periods, 7)) { if (jr == NULL) {
die_e("Cannot allocate memory.");
}
if (!strncmp ("@monthly", periods, 8)) {
jr->named_period = 1; jr->named_period = 1;
} else if (!strncmp("@yearly", periods, 7) || !strncmp("@annualy", periods, 8)) { } else if (!strncmp("@yearly", periods, 7) || !strncmp("@annually", periods, 9) || !strncmp(/* backwards compat misspelling */"@annualy", periods, 8)) {
jr->named_period = 2; jr->named_period = 2;
} else if (!strncmp ("@daily", periods, 7)) { } else if (!strncmp ("@daily", periods, 6)) {
jr->named_period = 3; jr->named_period = 3;
} else if (!strncmp ("@weekly", periods, 7)) { } else if (!strncmp ("@weekly", periods, 7)) {
jr->named_period = 4; jr->named_period = 4;
@ -226,9 +248,15 @@ register_period_job(const char *periods, const char *delays,
jr->delay = delay; jr->delay = delay;
jr->tab_line = line_num; jr->tab_line = line_num;
jr->ident = obstack_alloc(&tab_o, ident_len + 1); jr->ident = obstack_alloc(&tab_o, ident_len + 1);
if (jr->ident == NULL) {
die_e("Cannot allocate memory.");
}
strcpy(jr->ident, ident); strcpy(jr->ident, ident);
jr->arg_num = job_arg_num(ident); jr->arg_num = job_arg_num(ident);
jr->command = obstack_alloc(&tab_o, command_len + 1); jr->command = obstack_alloc(&tab_o, command_len + 1);
if (jr->command == NULL) {
die_e("Cannot allocate memory.");
}
strcpy(jr->command, command); strcpy(jr->command, command);
jr->job_pid = jr->mailer_pid = 0; jr->job_pid = jr->mailer_pid = 0;
if (last_job_rec != NULL) last_job_rec->next = jr; if (last_job_rec != NULL) last_job_rec->next = jr;
@ -240,6 +268,21 @@ register_period_job(const char *periods, const char *delays,
jr->named_period, jr->delay, jr->ident, jr->command)); jr->named_period, jr->delay, jr->ident, jr->command));
} }
static long int
unbiased_rand(long int max)
{
long int rn;
long int divisor;
divisor = RAND_MAX / (max + 1);
do {
rn = random() / divisor;
} while (rn > max);
return rn;
}
static void static void
parse_tab_line(char *line) parse_tab_line(char *line)
{ {
@ -252,6 +295,7 @@ parse_tab_line(char *line)
char *command; char *command;
char *from; char *from;
char *to; char *to;
char *pref_hour;
/* an empty line? */ /* an empty line? */
r = match_rx("^[ \t]*($|#)", line, 0); r = match_rx("^[ \t]*($|#)", line, 0);
@ -271,21 +315,35 @@ parse_tab_line(char *line)
if (strncmp(env_var, "START_HOURS_RANGE", 17) == 0) if (strncmp(env_var, "START_HOURS_RANGE", 17) == 0)
{ {
r = match_rx("^([[:digit:]]+)-([[:digit:]]+)$", value, 2, &from, &to); r = match_rx("^([[:digit:]]+)-([[:digit:]]+)$", value, 2, &from, &to);
if ((r == -1) || (from == NULL) || (to == NULL)) goto reg_invalid; if (r == -1) goto reg_err;
if (r == 0) goto reg_invalid;
range_start = atoi(from); range_start = atoi(from);
range_stop = atoi(to); range_stop = atoi(to);
if (range_stop < range_start) {
range_start = 0; range_stop = 0;
goto reg_invalid;
}
Debug(("Jobs will start in the %02d:00-%02d:00 range.", range_start, range_stop)); Debug(("Jobs will start in the %02d:00-%02d:00 range.", range_start, range_stop));
} }
if (strncmp(env_var, "RANDOM_DELAY", 12) == 0) { else if (strncmp(env_var, "RANDOM_DELAY", 12) == 0) {
r = match_rx("^([[:digit:]]+)$", value, 0); r = match_rx("^([[:digit:]]+)$", value, 0);
if (r != -1) { if (r == -1) goto reg_err;
int i = random(); if (r == 0) goto reg_invalid;
double x = 0;
x = (double) i / (double) RAND_MAX * (double) (atoi(value)); random_number = (int)unbiased_rand(atoi(value));
random_number = (int)x;
Debug(("Randomized delay set: %d", random_number)); Debug(("Randomized delay set: %d", random_number));
} }
else goto reg_invalid; else if (strncmp(env_var, "PREFERRED_HOUR", 14) == 0) {
r = match_rx("^([[:digit:]]+)$", value, 1, &pref_hour);
if (r == -1) goto reg_err;
if (r) {
preferred_hour = atoi(pref_hour);
if ((preferred_hour < 0) || (preferred_hour > 24)) {
preferred_hour = -1;
goto reg_invalid;
}
}
} }
register_env(env_var, value); register_env(env_var, value);
return; return;
@ -333,7 +391,7 @@ read_tab(int cwd)
jobs_read = 0; jobs_read = 0;
line_num = 0; line_num = 0;
/* Open the anacrontab file */ /* Open the anacrontab file */
fchdir (cwd); if (fchdir(cwd)) die_e("Can't chdir to original cwd");
tab = fopen(anacrontab, "r"); tab = fopen(anacrontab, "r");
if (chdir(spooldir)) die_e("Can't chdir to %s", spooldir); if (chdir(spooldir)) die_e("Can't chdir to %s", spooldir);
@ -366,7 +424,7 @@ execution_order(const job_rec **job1, const job_rec **job2)
} }
void void
arrange_jobs() arrange_jobs(void)
/* Make an array of pointers to jobs that are going to be executed, /* Make an array of pointers to jobs that are going to be executed,
* and arrange them in the order of execution. * and arrange them in the order of execution.
* Also lock these jobs. * Also lock these jobs.
@ -388,6 +446,6 @@ arrange_jobs()
job_array = obstack_finish(&tab_o); job_array = obstack_finish(&tab_o);
/* sort the jobs */ /* sort the jobs */
qsort(job_array, njobs, sizeof(*job_array), qsort(job_array, (size_t)njobs, sizeof(*job_array),
(int (*)(const void *, const void *))execution_order); (int (*)(const void *, const void *))execution_order);
} }

View File

@ -13,9 +13,9 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License along
along with this program; if not, write to the Free Software with this program; if not, write to the Free Software Foundation, Inc.,
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
The GNU General Public License can also be found in the file The GNU General Public License can also be found in the file
`COPYING' that comes with the Anacron source distribution. `COPYING' that comes with the Anacron source distribution.
@ -33,6 +33,7 @@
#include <signal.h> #include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <limits.h>
#include "global.h" #include "global.h"
#include <langinfo.h> #include <langinfo.h>
@ -41,30 +42,28 @@ static int
temp_file(job_rec *jr) temp_file(job_rec *jr)
/* Open a temporary file and return its file descriptor */ /* Open a temporary file and return its file descriptor */
{ {
const int max_retries = 50; char *dir;
char *name; char template[PATH_MAX+1];
int fdin = -1; int fdin = -1;
int fdout, i; int fdout;
int len;
i = 0; dir = getenv("TMPDIR");
name = NULL; if (dir == NULL || *dir == '\0')
do dir = P_tmpdir;
{
i++;
free(name);
name = tempnam(NULL, NULL);
if (name == NULL) die("Can't find a unique temporary filename");
fdout = open(name, O_WRONLY | O_CREAT | O_EXCL | O_APPEND,
S_IRUSR | S_IWUSR);
if ( fdout != -1 )
fdin = open(name, O_RDONLY, S_IRUSR | S_IWUSR);
/* I'm not sure we actually need to be so persistent here */
} while (fdout == -1 && errno == EEXIST && i < max_retries);
len = snprintf(template, sizeof(template), "%s/$anacronXXXXXX", dir);
if (len >= sizeof(template))
die_e("TMPDIR too long");
fdout = mkstemp(template);
if (fdout == -1) die_e("Can't open temporary file for writing"); if (fdout == -1) die_e("Can't open temporary file for writing");
fdin = open(template, O_RDONLY, S_IRUSR | S_IWUSR);
if (fdin == -1) die_e("Can't open temporary file for reading"); if (fdin == -1) die_e("Can't open temporary file for reading");
if (unlink(name)) die_e("Can't unlink temporary file");
free(name); if (unlink(template)) die_e("Can't unlink temporary file");
fcntl(fdout, F_SETFD, FD_CLOEXEC); /* set close-on-exec flag */ fcntl(fdout, F_SETFD, FD_CLOEXEC); /* set close-on-exec flag */
fcntl(fdin, F_SETFD, FD_CLOEXEC); /* set close-on-exec flag */ fcntl(fdin, F_SETFD, FD_CLOEXEC); /* set close-on-exec flag */
@ -85,19 +84,63 @@ file_size(int fd)
} }
static char * static char *
username() username(void)
{ {
struct passwd *ps; struct passwd *ps;
static char *user;
if (user)
return user;
ps = getpwuid(geteuid()); ps = getpwuid(geteuid());
if (ps == NULL) die_e("getpwuid() error"); if (ps == NULL || ps->pw_name == NULL) die_e("getpwuid() error");
return ps->pw_name;
user = strdup(ps->pw_name);
if (user == NULL) die_e("memory allocation error");
return user;
} }
static void static void
xputenv(const char *s) xputenv(const char *s)
{ {
if (putenv(s)) die_e("Can't set the environment"); char *name = NULL, *val = NULL;
char *eq_ptr;
size_t eq_index;
if (s == NULL) {
die_e("Invalid environment string");
}
eq_ptr = strchr(s, '=');
if (eq_ptr == NULL) {
die_e("Invalid environment string");
}
eq_index = (size_t) (eq_ptr - s);
name = malloc((eq_index + 1) * sizeof(char));
if (name == NULL) {
die_e("Not enough memory to set the environment");
}
val = malloc((strlen(s) - eq_index) * sizeof(char));
if (val == NULL) {
die_e("Not enough memory to set the environment");
}
strncpy(name, s, eq_index);
name[eq_index] = '\0';
strcpy(val, s + eq_index + 1);
if (setenv(name, val, 1)) {
die_e("Can't set the environment");
}
free(name);
free(val);
return;
} }
static void static void
@ -128,7 +171,6 @@ run_job(const job_rec *jr)
in_background = 0; /* now, errors will be mailed to the user */ in_background = 0; /* now, errors will be mailed to the user */
if (chdir("/")) die_e("Can't chdir to '/'"); if (chdir("/")) die_e("Can't chdir to '/'");
umask(old_umask);
if (sigprocmask(SIG_SETMASK, &old_sigmask, NULL)) if (sigprocmask(SIG_SETMASK, &old_sigmask, NULL))
die_e("sigprocmask error"); die_e("sigprocmask error");
xcloselog(); xcloselog();
@ -164,7 +206,12 @@ launch_mailer(job_rec *jr)
{ {
pid_t pid; pid_t pid;
struct stat buf; struct stat buf;
int r;
if (jr->mailto == NULL)
{
explain("Empty MAILTO set, not mailing output");
return;
}
/* Check that we have a way of sending mail. */ /* Check that we have a way of sending mail. */
if(stat(SENDMAIL, &buf)) if(stat(SENDMAIL, &buf))
@ -179,17 +226,16 @@ launch_mailer(job_rec *jr)
/* child */ /* child */
in_background = 1; in_background = 1;
/* set stdin to the job's output */ /* set stdin to the job's output */
xclose(0); xclose(STDIN_FILENO);
if (dup2(jr->input_fd, 0) != 0) die_e("Can't dup2()"); if (dup2(jr->input_fd, STDIN_FILENO) != 0) die_e("Can't dup2()");
if (lseek(0, 0, SEEK_SET) != 0) die_e("Can't lseek()"); if (lseek(STDIN_FILENO, 0, SEEK_SET) != 0) die_e("Can't lseek()");
umask(old_umask);
if (sigprocmask(SIG_SETMASK, &old_sigmask, NULL)) if (sigprocmask(SIG_SETMASK, &old_sigmask, NULL))
die_e("sigprocmask error"); die_e("sigprocmask error");
xcloselog(); xcloselog();
/* Ensure stdout/stderr are sane before exec-ing sendmail */ /* Ensure stdout/stderr are sane before exec-ing sendmail */
xclose(1); xopen(1, "/dev/null", O_WRONLY); xclose(STDOUT_FILENO); xopen(STDOUT_FILENO, "/dev/null", O_WRONLY);
xclose(2); xopen(2, "/dev/null", O_WRONLY); xclose(STDERR_FILENO); xopen(STDERR_FILENO, "/dev/null", O_WRONLY);
xclose(jr->output_fd); xclose(jr->output_fd);
/* Ensure stdin is not appendable ... ? */ /* Ensure stdin is not appendable ... ? */
@ -237,6 +283,7 @@ launch_job(job_rec *jr)
int fd; int fd;
char hostname[512]; char hostname[512];
char *mailto; char *mailto;
char *mailfrom;
/* get hostname */ /* get hostname */
if (gethostname(hostname, 512)) { if (gethostname(hostname, 512)) {
@ -248,25 +295,25 @@ launch_job(job_rec *jr)
/* Get the destination email address if set, or current user otherwise */ /* Get the destination email address if set, or current user otherwise */
mailto = getenv("MAILTO"); mailto = getenv("MAILTO");
if (mailto) if (mailto == NULL)
jr->mailto = mailto; mailto = username();
else
jr->mailto = username (); /* Get the source email address if set, or current user otherwise */
mailfrom = getenv("MAILFROM");
if (mailfrom == NULL)
mailfrom = username();
/* create temporary file for stdout and stderr of the job */ /* create temporary file for stdout and stderr of the job */
temp_file(jr); fd = jr->output_fd; temp_file(jr); fd = jr->output_fd;
/* write mail header */ /* write mail header */
xwrite(fd, "From: "); xwrite(fd, "From: ");
xwrite(fd, "Anacron <"); xwrite(fd, "Anacron <");
xwrite(fd, username()); xwrite(fd, mailfrom);
xwrite(fd, ">\n"); xwrite(fd, ">\n");
xwrite(fd, "To: "); xwrite(fd, "To: ");
if (mailto) {
xwrite(fd, mailto); xwrite(fd, mailto);
} else {
xwrite(fd, username());
}
xwrite(fd, "\n"); xwrite(fd, "\n");
xwrite(fd, "MIME-Version: 1.0\n");
xwrite(fd, "Content-Type: text/plain; charset=\""); xwrite(fd, "Content-Type: text/plain; charset=\"");
xwrite(fd, nl_langinfo(CODESET)); xwrite(fd, nl_langinfo(CODESET));
xwrite(fd, "\"\n"); xwrite(fd, "\"\n");
@ -276,6 +323,12 @@ launch_job(job_rec *jr)
xwrite(fd, hostname); xwrite(fd, hostname);
xwrite(fd, "\n\n"); xwrite(fd, "\n\n");
if (*mailto == '\0')
jr->mailto = NULL;
else
/* ugly but works without strdup() */
jr->mailto = mailto;
jr->mail_header_size = file_size(fd); jr->mail_header_size = file_size(fd);
pid = xfork(); pid = xfork();
@ -297,14 +350,14 @@ tend_job(job_rec *jr, int status)
/* Take care of a finished job */ /* Take care of a finished job */
{ {
int mail_output; int mail_output;
char *m; const char *m;
update_timestamp(jr); update_timestamp(jr);
unlock(jr); unlock(jr);
if (file_size(jr->output_fd) > jr->mail_header_size) mail_output = 1; if (file_size(jr->output_fd) > jr->mail_header_size) mail_output = 1;
else mail_output = 0; else mail_output = 0;
m = mail_output ? " (mailing output)" : ""; m = mail_output ? " (produced output)" : "";
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
explain("Job `%s' terminated%s", jr->ident, m); explain("Job `%s' terminated%s", jr->ident, m);
else if (WIFEXITED(status)) else if (WIFEXITED(status))
@ -324,7 +377,7 @@ tend_job(job_rec *jr, int status)
} }
void void
tend_children() tend_children(void)
/* This is called whenever we get a SIGCHLD. /* This is called whenever we get a SIGCHLD.
* Takes care of zombie children. * Takes care of zombie children.
*/ */

348
compile Executable file
View File

@ -0,0 +1,348 @@
#! /bin/sh
# Wrapper for compilers which do not understand '-c -o'.
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1999-2018 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
nl='
'
# We need space, tab and new line, in precisely that order. Quoting is
# there to prevent tools from complaining about whitespace usage.
IFS=" "" $nl"
file_conv=
# func_file_conv build_file lazy
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts. If the determined conversion
# type is listed in (the comma separated) LAZY, no conversion will
# take place.
func_file_conv ()
{
file=$1
case $file in
/ | /[!/]*) # absolute file, and not a UNC file
if test -z "$file_conv"; then
# lazily determine how to convert abs files
case `uname -s` in
MINGW*)
file_conv=mingw
;;
CYGWIN*)
file_conv=cygwin
;;
*)
file_conv=wine
;;
esac
fi
case $file_conv/,$2, in
*,$file_conv,*)
;;
mingw/*)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin/*)
file=`cygpath -m "$file" || echo "$file"`
;;
wine/*)
file=`winepath -w "$file" || echo "$file"`
;;
esac
;;
esac
}
# func_cl_dashL linkdir
# Make cl look for libraries in LINKDIR
func_cl_dashL ()
{
func_file_conv "$1"
if test -z "$lib_path"; then
lib_path=$file
else
lib_path="$lib_path;$file"
fi
linker_opts="$linker_opts -LIBPATH:$file"
}
# func_cl_dashl library
# Do a library search-path lookup for cl
func_cl_dashl ()
{
lib=$1
found=no
save_IFS=$IFS
IFS=';'
for dir in $lib_path $LIB
do
IFS=$save_IFS
if $shared && test -f "$dir/$lib.dll.lib"; then
found=yes
lib=$dir/$lib.dll.lib
break
fi
if test -f "$dir/$lib.lib"; then
found=yes
lib=$dir/$lib.lib
break
fi
if test -f "$dir/lib$lib.a"; then
found=yes
lib=$dir/lib$lib.a
break
fi
done
IFS=$save_IFS
if test "$found" != yes; then
lib=$lib.lib
fi
}
# func_cl_wrapper cl arg...
# Adjust compile command to suit cl
func_cl_wrapper ()
{
# Assume a capable shell
lib_path=
shared=:
linker_opts=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
eat=1
case $2 in
*.o | *.[oO][bB][jJ])
func_file_conv "$2"
set x "$@" -Fo"$file"
shift
;;
*)
func_file_conv "$2"
set x "$@" -Fe"$file"
shift
;;
esac
;;
-I)
eat=1
func_file_conv "$2" mingw
set x "$@" -I"$file"
shift
;;
-I*)
func_file_conv "${1#-I}" mingw
set x "$@" -I"$file"
shift
;;
-l)
eat=1
func_cl_dashl "$2"
set x "$@" "$lib"
shift
;;
-l*)
func_cl_dashl "${1#-l}"
set x "$@" "$lib"
shift
;;
-L)
eat=1
func_cl_dashL "$2"
;;
-L*)
func_cl_dashL "${1#-L}"
;;
-static)
shared=false
;;
-Wl,*)
arg=${1#-Wl,}
save_ifs="$IFS"; IFS=','
for flag in $arg; do
IFS="$save_ifs"
linker_opts="$linker_opts $flag"
done
IFS="$save_ifs"
;;
-Xlinker)
eat=1
linker_opts="$linker_opts $2"
;;
-*)
set x "$@" "$1"
shift
;;
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
func_file_conv "$1"
set x "$@" -Tp"$file"
shift
;;
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
func_file_conv "$1" mingw
set x "$@" "$file"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -n "$linker_opts"; then
linker_opts="-link$linker_opts"
fi
exec "$@" $linker_opts
exit 1
}
eat=
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: compile [--help] [--version] PROGRAM [ARGS]
Wrapper for compilers which do not understand '-c -o'.
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
arguments, and rename the output as expected.
If you are trying to build a whole package this is not the
right script to run: please start by reading the file 'INSTALL'.
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "compile $scriptversion"
exit $?
;;
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \
icl | *[/\\]icl | icl.exe | *[/\\]icl.exe )
func_cl_wrapper "$@" # Doesn't return...
;;
esac
ofile=
cfile=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
# So we strip '-o arg' only if arg is an object.
eat=1
case $2 in
*.o | *.obj)
ofile=$2
;;
*)
set x "$@" -o "$2"
shift
;;
esac
;;
*.c)
cfile=$1
set x "$@" "$1"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -z "$ofile" || test -z "$cfile"; then
# If no '-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# '.c' file was seen then we are probably linking. That is also
# ok.
exec "$@"
fi
# Name of file we expect compiler to create.
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
# Create the lock directory.
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
while true; do
if mkdir "$lockdir" >/dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir '$lockdir'; exit 1" 1 2 15
# Run the compile.
"$@"
ret=$?
if test -f "$cofile"; then
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
elif test -f "${cofile}bj"; then
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
fi
rmdir "$lockdir"
exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

1476
config.guess vendored Executable file

File diff suppressed because it is too large Load Diff

255
config.h.in Normal file
View File

@ -0,0 +1,255 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* if you have a tm_gmtoff member in struct tm */
#undef CAPITALIZE_FOR_PS
/* Code will be built with debug info. */
#undef DEBUGGING
/* default editor */
#undef EDITOR
/* Define if you want system crontab. */
#undef ENABLE_SYSCRONTAB
/* Define to 1 if you have the <dirent.h> header file. */
#undef HAVE_DIRENT_H
/* Define to 1 if you have the `fchgrp' function. */
#undef HAVE_FCHGRP
/* Define to 1 if you have the `fchown' function. */
#undef HAVE_FCHOWN
/* Define to 1 if you have the `fcntl' function. */
#undef HAVE_FCNTL
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define to 1 if you have the `flock' function. */
#undef HAVE_FLOCK
/* Define to 1 if you have the <getopt.h> header file. */
#undef HAVE_GETOPT_H
/* Define to 1 if you have the `getseuserbyname' function. */
#undef HAVE_GETSEUSERBYNAME
/* Define to 1 if you have the `get_default_context_with_level' function. */
#undef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
/* Define to 1 if you have the <glob.h> header file. */
#undef HAVE_GLOB_H
/* Define to 1 if you have the `inotify_add_watch' function. */
#undef HAVE_INOTIFY_ADD_WATCH
/* Define to 1 if you have the `inotify_init' function. */
#undef HAVE_INOTIFY_INIT
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `pam' library (-lpam). */
#undef HAVE_LIBPAM
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
/* Define to 1 if you have the `lockf' function. */
#undef HAVE_LOCKF
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `pam_getenvlist' function. */
#undef HAVE_PAM_GETENVLIST
/* Define to 1 if you have the <pam/pam_appl.h> header file. */
#undef HAVE_PAM_PAM_APPL_H
/* Define to 1 if you have the `pam_putenv' function. */
#undef HAVE_PAM_PUTENV
/* Define to 1 if you have the <paths.h> header file. */
#undef HAVE_PATHS_H
/* Define to 1 if you have the <pty.h> header file. */
#undef HAVE_PTY_H
/* Define to 1 if you have the <security/pam_appl.h> header file. */
#undef HAVE_SECURITY_PAM_APPL_H
/* Define to 1 if you have the <selinux/selinux.h> header file. */
#undef HAVE_SELINUX_SELINUX_H
/* Define to 1 if you have the <stddef.h> header file. */
#undef HAVE_STDDEF_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if `tm_gmtoff' is a member of `struct tm'. */
#undef HAVE_STRUCT_TM_TM_GMTOFF
/* Define to 1 if you have the <sys/audit.h> header file. */
#undef HAVE_SYS_AUDIT_H
/* Define to 1 if you have the <sys/cdefs.h> header file. */
#undef HAVE_SYS_CDEFS_H
/* Define to 1 if you have the <sys/fcntl.h> header file. */
#undef HAVE_SYS_FCNTL_H
/* Define to 1 if you have the <sys/inotify.h> header file. */
#undef HAVE_SYS_INOTIFY_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/stream.h> header file. */
#undef HAVE_SYS_STREAM_H
/* Define to 1 if you have the <sys/stropts.h> header file. */
#undef HAVE_SYS_STROPTS_H
/* Define to 1 if you have the <sys/timers.h> header file. */
#undef HAVE_SYS_TIMERS_H
/* Define to 1 if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <time.h> header file. */
#undef HAVE_TIME_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the <util.h> header file. */
#undef HAVE_UTIL_H
/* Define to 1 if you have the <utime.h> header file. */
#undef HAVE_UTIME_H
/* There will be path to sendmail. */
#undef MAILARG
/* -i = don't terminate on "." by itself -Fx = Set full-name of sender -odi =
Option Deliverymode Interactive -oem = Option Errors Mailedtosender -oi =
Ignore "." alone on a line -t = Get recipient from headers -f %s = Envelope
sender address -d = undocumented but common flag. */
#undef MAILFMT
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define as the return type of signal handlers (`int' or `void'). */
#undef RETSIGTYPE
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Using syslog for log messages. */
#undef SYSLOG
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
#undef TM_IN_SYS_TIME
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# undef _GNU_SOURCE
#endif
/* Enable threading extensions on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# undef _POSIX_PTHREAD_SEMANTICS
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# undef _TANDEM_SOURCE
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# undef __EXTENSIONS__
#endif
/* Version number of package */
#undef VERSION
/* Define if you want Audit trails. */
#undef WITH_AUDIT
/* Define if you want inotify support. */
#undef WITH_INOTIFY
/* Define if you want to enable PAM support */
#undef WITH_PAM
/* Define if you want SELinux support. */
#undef WITH_SELINUX
/* Define to 1 if on MINIX. */
#undef _MINIX
/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
#undef _POSIX_1_SOURCE
/* Define to 1 if you need to in order for `stat' and other things to work. */
#undef _POSIX_SOURCE
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `int' if <sys/types.h> doesn't define. */
#undef gid_t
/* Define to `int' if <sys/types.h> does not define. */
#undef mode_t
/* Define to `long int' if <sys/types.h> does not define. */
#undef off_t
/* Define to `int' if <sys/types.h> does not define. */
#undef pid_t
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t
/* Define to `int' if <sys/types.h> doesn't define. */
#undef uid_t

1833
config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

6894
configure vendored Executable file

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,12 @@
AC_INIT([cronie],[1.4.8],[mmaslano@redhat.com]) AC_INIT([cronie],[1.5.4],[mmaslano@redhat.com,tmraz@fedoraproject.org])
AC_CONFIG_HEADER([config.h]) AC_CONFIG_HEADER([config.h])
AC_PREREQ(2.60) AC_PREREQ(2.60)
AM_INIT_AUTOMAKE AM_INIT_AUTOMAKE
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])],
[AC_SUBST([AM_DEFAULT_VERBOSITY], [1])])
AC_CANONICAL_HOST AC_CANONICAL_HOST
dnl Checks for programs. dnl Checks for programs.
@ -63,6 +66,15 @@ AC_CHECK_MEMBERS([struct tm.tm_gmtoff],,,[#include <time.h>])
dnl Checking for programs dnl Checking for programs
AC_ARG_WITH([editor],
[AC_HELP_STRING([--with-editor=EDITOR], [path to default editor])],
[editor_defined="$with_editor"],
[editor_defined="no"])
AS_IF([test "x$editor_defined" = "xno"], [
AC_PATH_PROG([editor_defined], [vi], [/usr/bin/vi])
])
AC_DEFINE_UNQUOTED([EDITOR], ["$editor_defined"], [default editor])
AC_MSG_CHECKING(username to run under) AC_MSG_CHECKING(username to run under)
AC_ARG_WITH(daemon_username, AC_ARG_WITH(daemon_username,
[AS_HELP_STRING([--with-daemon_username=DAEMON_USERNAME], [Username to run under (default daemon) ])], [AS_HELP_STRING([--with-daemon_username=DAEMON_USERNAME], [Username to run under (default daemon) ])],
@ -124,9 +136,11 @@ fi
AC_ARG_ENABLE(relro,CRONIE_HELP_STRING(--enable-relro,Build cronie with relro flag)) AC_ARG_ENABLE(relro,CRONIE_HELP_STRING(--enable-relro,Build cronie with relro flag))
if test "x$enable_relro" = xyes; then if test "x$enable_relro" = xyes; then
LDFLAGS="-Wl,-z,relro -Wl,-z,now" LDFLAGS="$LDFLAGS -Wl,-z,relro -Wl,-z,now"
fi fi
AC_ARG_ENABLE(bsd, BSD_STRING(--enable-bsd,Build cronie with BSD specific parts))
# Check whether user wants SELinux support # Check whether user wants SELinux support
SELINUX_MSG="no" SELINUX_MSG="no"
LIBSELINUX="" LIBSELINUX=""
@ -140,7 +154,7 @@ AC_ARG_WITH(selinux,
AC_CHECK_LIB(selinux, setexeccon, [ LIBSELINUX="-lselinux" ], AC_CHECK_LIB(selinux, setexeccon, [ LIBSELINUX="-lselinux" ],
AC_MSG_ERROR(SELinux support requires libselinux library)) AC_MSG_ERROR(SELinux support requires libselinux library))
AC_CHECK_FUNCS(getseuserbyname get_default_context_with_level) AC_CHECK_FUNCS(getseuserbyname get_default_context_with_level)
LIBS="$saved_LIBS $LIBSELINUX" LIBS="$saved_LIBS"
AC_SUBST(LIBSELINUX) AC_SUBST(LIBSELINUX)
fi ] fi ]
) )
@ -207,11 +221,18 @@ AC_ARG_WITH(audit,
AC_CHECK_HEADER([libaudit.h], ,AC_MSG_ERROR(Audit trails requires libaudit.h header)) AC_CHECK_HEADER([libaudit.h], ,AC_MSG_ERROR(Audit trails requires libaudit.h header))
AC_CHECK_LIB(audit, audit_open, [ LIBAUDIT="-laudit" ], AC_CHECK_LIB(audit, audit_open, [ LIBAUDIT="-laudit" ],
AC_MSG_ERROR(Audit support needs audit libraries.)) AC_MSG_ERROR(Audit support needs audit libraries.))
LIBS="$saved_LIBS $LIBAUDIT" LIBS="$saved_LIBS"
AC_SUBST(LIBAUDIT) AC_SUBST(LIBAUDIT)
fi ] fi ]
) )
AC_ARG_ENABLE(syscrontab,
[AS_HELP_STRING([--enable-syscrontab], [Build cronie with system crontab enabled.])],
[ if test "x$enableval" != xno; then
AC_DEFINE(ENABLE_SYSCRONTAB,1,[Define if you want system crontab.])
fi ], [AC_DEFINE(ENABLE_SYSCRONTAB,1,[Define if you want system crontab.])]
)
dnl CRONIE_VAR_DEFAULT (VAR, DESCRIPTION, DEFAULT) dnl CRONIE_VAR_DEFAULT (VAR, DESCRIPTION, DEFAULT)
dnl -------------------------------------------- dnl --------------------------------------------
AC_DEFUN([CRONIE_CONF_VAR], AC_DEFUN([CRONIE_CONF_VAR],

View File

@ -1,18 +1,27 @@
#!/bin/bash #!/bin/sh
#in case file doesn't exist # Check whether 0anacron was run today already
if test -r /var/spool/anacron/cron.daily; then if test -r /var/spool/anacron/cron.daily; then
day=`cat /var/spool/anacron/cron.daily` day=`cat /var/spool/anacron/cron.daily`
fi fi
if [ `date +%Y%m%d` = "$day" ]; then if [ `date +%Y%m%d` = "$day" ]; then
exit 0;
fi
# in case anacron is already running,
# there will be log (daemon won't be running twice).
if test -x /usr/bin/on_ac_power; then
/usr/bin/on_ac_power &> /dev/null
if test $? -eq 1; then
exit 0 exit 0
fi fi
# Do not run jobs when on battery power
online=1
for psupply in AC ADP0 ; do
sysfile="/sys/class/power_supply/$psupply/online"
if [ -f $sysfile ] ; then
if [ `cat $sysfile 2>/dev/null`x = 1x ]; then
online=1
break
else
online=0
fi
fi
done
if [ $online = 0 ]; then
exit 0
fi fi
/usr/sbin/anacron -s /usr/sbin/anacron -s

View File

@ -1,3 +1,4 @@
# Run the hourly jobs
SHELL=/bin/bash SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root MAILTO=root

15
contrib/cronie.systemd Normal file
View File

@ -0,0 +1,15 @@
[Unit]
Description=Command Scheduler
After=auditd.service nss-user-lookup.target systemd-user-sessions.service time-sync.target ypbind.service autofs.service
[Service]
EnvironmentFile=/etc/sysconfig/crond
ExecStart=/usr/sbin/crond -n $CRONDARGS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=30s
[Install]
WantedBy=multi-user.target

View File

@ -1,3 +1,4 @@
# Run the daily, weekly, and monthly jobs if cronie-anacron is not installed
SHELL=/bin/bash SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root MAILTO=root

View File

@ -34,16 +34,16 @@ config=/etc/sysconfig/crond
# Source function library. # Source function library.
. /etc/rc.d/init.d/functions . /etc/rc.d/init.d/functions
[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog [ $UID -eq 0 ] && [ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog
start() { start() {
if [ $UID -ne 0 ] ; then if [ $(id -ru) -ne 0 ] ; then
echo "User has insufficient privilege." echo "User has insufficient privilege."
exit 4 exit 4
fi fi
[ -x $exec ] || exit 5 [ -x $exec ] || exit 5
[ -f $config ] || exit 6 [ -f $config ] || exit 6
echo -n $"Starting $prog: " printf "Starting $prog: "
daemon $prog $CRONDARGS daemon $prog $CRONDARGS
retval=$? retval=$?
echo echo
@ -51,16 +51,16 @@ start() {
} }
stop() { stop() {
if [ $UID -ne 0 ] ; then if [ $(id -ru) -ne 0 ] ; then
echo "User has insufficient privilege." echo "User has insufficient privilege."
exit 4 exit 4
fi fi
echo -n $"Stopping $prog: " printf "Stopping $prog: "
if [ -n "`pidfileofproc $exec`" ]; then if [ -n "`pidfileofproc $exec`" ]; then
killproc $exec killproc $exec
RETVAL=3 RETVAL=3
else else
failure $"Stopping $prog" failure "Stopping $prog"
fi fi
retval=$? retval=$?
echo echo
@ -68,16 +68,16 @@ stop() {
} }
restart() { restart() {
stop rh_status_q && stop
start start
} }
reload() { reload() {
echo -n $"Reloading $prog: " printf "Reloading $prog: "
if [ -n "`pidfileofproc $exec`" ]; then if [ -n "`pidfileofproc $exec`" ]; then
killproc $exec -HUP killproc $exec -HUP
else else
failure $"Reloading $prog" failure "Reloading $prog"
fi fi
retval=$? retval=$?
echo echo
@ -125,7 +125,7 @@ case "$1" in
restart restart
;; ;;
*) *)
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}" echo "Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
exit 2 exit 2
esac esac
exit $? exit $?

View File

@ -1,10 +1,5 @@
/* Copyright 1988,1990,1993,1994 by Paul Vixie
* All rights reserved
*/
/* /*
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") * Copyright (c) 2012 Copyright Red Hat Software
* Copyright (c) 1997,2000 by Internet Software Consortium, Inc.
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -19,33 +14,24 @@
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
/* cron.h - header for vixie's cron /* Collection of definitions, inline functions, etc, that are useful for
* * both cron and anacron. */
* $Id: cron.h,v 1.6 2004/01/23 18:56:42 vixie Exp $
*
* vix 14nov88 [rest of log is in RCS]
* vix 14jan87 [0 or 7 can be sunday; thanks, mwm@berkeley]
* vix 30dec86 [written]
*/
#include "../config.h" #ifndef CRONIE_COMMON_H
#include "externs.h" #define CRONIE_COMMON_H
#ifdef WITH_SELINUX #ifndef __attribute__
#include <selinux/selinux.h> # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
# define __attribute__(x) /* empty */
# endif
#endif #endif
#ifdef WITH_PAM #ifndef ATTRIBUTE_NORETURN
#include <security/pam_appl.h> # define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
#endif #endif
#ifdef WITH_INOTIFY #ifndef ATTRIBUTE_UNUSED
#include <sys/inotify.h> # define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
#endif #endif
#include "pathnames.h" #endif /* CRONIE_COMMON_H */
#include "macros.h"
#include "structs.h"
#include "funcs.h"
#include "globals.h"

791
depcomp Executable file
View File

@ -0,0 +1,791 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1999-2018 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
Run PROGRAMS ARGS to compile a file, generating dependencies
as side-effects.
Environment variables:
depmode Dependency tracking mode.
source Source file read by 'PROGRAMS ARGS'.
object Object file output by 'PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputting dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "depcomp $scriptversion"
exit $?
;;
esac
# Get the directory component of the given path, and save it in the
# global variables '$dir'. Note that this directory component will
# be either empty or ending with a '/' character. This is deliberate.
set_dir_from ()
{
case $1 in
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
*) dir=;;
esac
}
# Get the suffix-stripped basename of the given path, and save it the
# global variable '$base'.
set_base_from ()
{
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
}
# If no dependency file was actually created by the compiler invocation,
# we still have to create a dummy depfile, to avoid errors with the
# Makefile "include basename.Plo" scheme.
make_dummy_depfile ()
{
echo "#dummy" > "$depfile"
}
# Factor out some common post-processing of the generated depfile.
# Requires the auxiliary global variable '$tmpdepfile' to be set.
aix_post_process_depfile ()
{
# If the compiler actually managed to produce a dependency file,
# post-process it.
if test -f "$tmpdepfile"; then
# Each line is of the form 'foo.o: dependency.h'.
# Do two passes, one to just change these to
# $object: dependency.h
# and one to simply output
# dependency.h:
# which is needed to avoid the deleted-header problem.
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
} > "$depfile"
rm -f "$tmpdepfile"
else
make_dummy_depfile
fi
}
# A tabulation character.
tab=' '
# A newline character.
nl='
'
# Character ranges might be problematic outside the C locale.
# These definitions help.
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
lower=abcdefghijklmnopqrstuvwxyz
digits=0123456789
alpha=${upper}${lower}
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
depfile=${depfile-`echo "$object" |
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Avoid interferences from the environment.
gccflag= dashmflag=
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
cygpath_u="cygpath -u -f -"
if test "$depmode" = msvcmsys; then
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvisualcpp
fi
if test "$depmode" = msvc7msys; then
# This is just like msvc7 but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvc7
fi
if test "$depmode" = xlc; then
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
gccflag=-qmakedep=gcc,-MF
depmode=gcc
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
## the command line argument order; so add the flags where they
## appear in depend2.am. Note that the slowdown incurred here
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
for arg
do
case $arg in
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
*) set fnord "$@" "$arg" ;;
esac
shift # fnord
shift # $arg
done
"$@"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
## (see the conditional assignment to $gccflag above).
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say). Also, it might not be
## supported by the other compilers which use the 'gcc' depmode.
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The second -e expression handles DOS-style file names with drive
# letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the "deleted header file" problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
## Some versions of gcc put a space before the ':'. On the theory
## that the space means something, we add a space to the output as
## well. hp depmode also adds that space, but also prefixes the VPATH
## to the object. Take care to not repeat it in the output.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like '#:fec' to the end of the
# dependency line.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
| tr "$nl" ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile"
;;
xlc)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts '$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
tmpdepfile3=$dir.libs/$base.u
"$@" -Wc,-M
else
tmpdepfile1=$dir$base.u
tmpdepfile2=$dir$base.u
tmpdepfile3=$dir$base.u
"$@" -M
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
aix_post_process_depfile
;;
tcc)
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
# FIXME: That version still under development at the moment of writing.
# Make that this statement remains true also for stable, released
# versions.
# It will wrap lines (doesn't matter whether long or short) with a
# trailing '\', as in:
#
# foo.o : \
# foo.c \
# foo.h \
#
# It will put a trailing '\' even on the last line, and will use leading
# spaces rather than leading tabs (at least since its commit 0394caf7
# "Emit spaces for -MD").
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
# We have to change lines of the first kind to '$object: \'.
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
# And for each line of the second kind, we have to emit a 'dep.h:'
# dummy dependency, to avoid the deleted-header problem.
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
rm -f "$tmpdepfile"
;;
## The order of this option in the case statement is important, since the
## shell code in configure will try each of these formats in the order
## listed in this file. A plain '-MD' option would be understood by many
## compilers, so we must ensure this comes after the gcc and icc options.
pgcc)
# Portland's C compiler understands '-MD'.
# Will always output deps to 'file.d' where file is the root name of the
# source file under compilation, even if file resides in a subdirectory.
# The object file name does not affect the name of the '.d' file.
# pgcc 10.2 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using '\' :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
set_dir_from "$object"
# Use the source, not the object, to determine the base name, since
# that's sadly what pgcc will do too.
set_base_from "$source"
tmpdepfile=$base.d
# For projects that build the same source file twice into different object
# files, the pgcc approach of using the *source* file root name can cause
# problems in parallel builds. Use a locking strategy to avoid stomping on
# the same $tmpdepfile.
lockdir=$base.d-lock
trap "
echo '$0: caught signal, cleaning up...' >&2
rmdir '$lockdir'
exit 1
" 1 2 13 15
numtries=100
i=$numtries
while test $i -gt 0; do
# mkdir is a portable test-and-set.
if mkdir "$lockdir" 2>/dev/null; then
# This process acquired the lock.
"$@" -MD
stat=$?
# Release the lock.
rmdir "$lockdir"
break
else
# If the lock is being held by a different process, wait
# until the winning process is done or we timeout.
while test -d "$lockdir" && test $i -gt 0; do
sleep 1
i=`expr $i - 1`
done
fi
i=`expr $i - 1`
done
trap - 1 2 13 15
if test $i -le 0; then
echo "$0: failed to acquire lock after $numtries attempts" >&2
echo "$0: check lockdir '$lockdir'" >&2
exit 1
fi
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp2)
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
# compilers, which have integrated preprocessors. The correct option
# to use with these is +Maked; it writes dependencies to a file named
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
"$@" -Wc,+Maked
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
"$@" +Maked
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
# Add 'dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
s/$/:/
p
}' "$tmpdepfile" >> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in 'foo.d' instead, so we check for that too.
# Subdirectories are respected.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
# Libtool generates 2 separate objects for the 2 libraries. These
# two compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir$base.o.d # libtool 1.5
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
# Same post-processing that is required for AIX mode.
aix_post_process_depfile
;;
msvc7)
if test "$libtool" = yes; then
showIncludes=-Wc,-showIncludes
else
showIncludes=-showIncludes
fi
"$@" $showIncludes > "$tmpdepfile"
stat=$?
grep -v '^Note: including file: ' "$tmpdepfile"
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The first sed program below extracts the file names and escapes
# backslashes for cygpath. The second sed program outputs the file
# name when reading, but also accumulates all include files in the
# hold buffer in order to output them again at the end. This only
# works with sed implementations that can handle large buffers.
sed < "$tmpdepfile" -n '
/^Note: including file: *\(.*\)/ {
s//\1/
s/\\/\\\\/g
p
}' | $cygpath_u | sort -u | sed -n '
s/ /\\ /g
s/\(.*\)/'"$tab"'\1 \\/p
s/.\(.*\) \\/\1:/
H
$ {
s/.*/'"$tab"'/
G
p
}' >> "$depfile"
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
rm -f "$tmpdepfile"
;;
msvc7msys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for ':'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
"$@" $dashmflag |
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this sed invocation
# correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no eat=no
for arg
do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
if test $eat = yes; then
eat=no
continue
fi
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-arch)
eat=yes ;;
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix=`echo "$object" | sed 's/^.*\././'`
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
# makedepend may prepend the VPATH from the source file name to the object.
# No need to regex-escape $object, excess matching of '.' is harmless.
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process the last invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed '1,2d' "$tmpdepfile" \
| tr ' ' "$nl" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E \
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
| sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
IFS=" "
for arg
do
case "$arg" in
-o)
shift
;;
$object)
shift
;;
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E 2>/dev/null |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
echo "$tab" >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvcmsys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

518
install-sh Executable file
View File

@ -0,0 +1,518 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2018-03-11.20; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
tab=' '
nl='
'
IFS=" $tab$nl"
# Set DOITPROG to "echo" to test this script.
doit=${DOITPROG-}
doit_exec=${doit:-exec}
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
posix_mkdir=
# Desired mode of installed file.
mode=0755
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=
src=
dst=
dir_arg=
dst_arg=
copy_on_change=false
is_target_a_directory=possibly
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
--help display this help and exit.
--version display version info and exit.
-c (ignored)
-C install only if different (preserve the last data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
"
while test $# -ne 0; do
case $1 in
-c) ;;
-C) copy_on_change=true;;
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
case $mode in
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift;;
-s) stripcmd=$stripprog;;
-t)
is_target_a_directory=always
dst_arg=$2
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) is_target_a_directory=never;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
# We allow the use of options -d and -T together, by making -d
# take the precedence; this is for compatibility with GNU install.
if test -n "$dir_arg"; then
if test -n "$dst_arg"; then
echo "$0: target directory not allowed when installing a directory." >&2
exit 1
fi
fi
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dst_arg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dst_arg"
shift # fnord
fi
shift # arg
dst_arg=$arg
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
done
fi
if test $# -eq 0; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call 'install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
if test -z "$dir_arg"; then
if test $# -gt 1 || test "$is_target_a_directory" = always; then
if test ! -d "$dst_arg"; then
echo "$0: $dst_arg: Is not a directory." >&2
exit 1
fi
fi
fi
if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
trap "ret=143; $do_exit" 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
case $mode in
# Optimize common cases.
*644) cp_umask=133;;
*755) cp_umask=22;;
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
fi
for src
do
# Protect names problematic for 'test' and other utilities.
case $src in
-* | [=\(\)!]) src=./$src;;
esac
if test -n "$dir_arg"; then
dst=$src
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dst_arg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dst_arg
# If destination is a directory, append the input filename.
if test -d "$dst"; then
if test "$is_target_a_directory" = never; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dstbase=`basename "$src"`
case $dst in
*/) dst=$dst$dstbase;;
*) dst=$dst/$dstbase;;
esac
dstdir_status=0
else
dstdir=`dirname "$dst"`
test -d "$dstdir"
dstdir_status=$?
fi
fi
case $dstdir in
*/) dstdirslash=$dstdir;;
*) dstdirslash=$dstdir/;;
esac
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
# Note that $RANDOM variable is not portable (e.g. dash); Use it
# here however when possible just to lower collision chance.
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
# Because "mkdir -p" follows existing symlinks and we likely work
# directly in world-writeable /tmp, make sure that the '$tmpdir'
# directory is successfully created first before we actually test
# 'mkdir -p' feature.
if (umask $mkdir_umask &&
$mkdirprog $mkdir_mode "$tmpdir" &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
test_tmpdir="$tmpdir/a"
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
fi
trap '' 0;;
esac;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# The umask is ridiculous, or mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix='/';;
[-=\(\)!]*) prefix='./';;
*) prefix='';;
esac
oIFS=$IFS
IFS=/
set -f
set fnord $dstdir
shift
set +f
IFS=$oIFS
prefixes=
for d
do
test X"$d" = X && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
if test -n "$dir_arg"; then
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
else
# Make a couple of temp file names in the proper directory.
dsttmp=${dstdirslash}_inst.$$_
rmtmp=${dstdirslash}_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
rm -f "$dsttmp"
else
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1
trap '' 0
fi
done
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

View File

@ -1,6 +1,6 @@
dist_man_MANS = crontab.1 crontab.5 cron.8 crond.8 dist_man_MANS = crontab.1 crontab.5 cron.8 crond.8 cronnext.1
if ANACRON EXTRA_DIST = anacrontab.5 anacron.8
dist_man_MANS += anacrontab.5 anacron.8
endif
noinst_MANS = bitstring.3
if ANACRON
dist_man_MANS += $(EXTRA_DIST)
endif

593
man/Makefile.in Normal file
View File

@ -0,0 +1,593 @@
# Makefile.in generated by automake 1.16.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2018 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
@ANACRON_TRUE@am__append_1 = $(EXTRA_DIST)
subdir = man
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
SOURCES =
DIST_SOURCES =
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \
test -z "$$files" \
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
$(am__cd) "$$dir" && rm -f $$files; }; \
}
man1dir = $(mandir)/man1
am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" \
"$(DESTDIR)$(man8dir)"
man5dir = $(mandir)/man5
man8dir = $(mandir)/man8
NROFF = nroff
MANS = $(dist_man_MANS)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
am__DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
ANACRONTAB = @ANACRONTAB@
ANACRON_SPOOL_DIR = @ANACRON_SPOOL_DIR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DAEMON_GROUPNAME = @DAEMON_GROUPNAME@
DAEMON_USERNAME = @DAEMON_USERNAME@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBAUDIT = @LIBAUDIT@
LIBOBJS = @LIBOBJS@
LIBPAM = @LIBPAM@
LIBS = @LIBS@
LIBSELINUX = @LIBSELINUX@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
SPOOL_DIR = @SPOOL_DIR@
STRIP = @STRIP@
SYSCRONTAB = @SYSCRONTAB@
SYS_CROND_DIR = @SYS_CROND_DIR@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
editor_defined = @editor_defined@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
dist_man_MANS = crontab.1 crontab.5 cron.8 crond.8 cronnext.1 \
$(am__append_1)
EXTRA_DIST = anacrontab.5 anacron.8
all: all-am
.SUFFIXES:
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu man/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu man/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
install-man1: $(dist_man_MANS)
@$(NORMAL_INSTALL)
@list1=''; \
list2='$(dist_man_MANS)'; \
test -n "$(man1dir)" \
&& test -n "`echo $$list1$$list2`" \
|| exit 0; \
echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \
$(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \
{ for i in $$list1; do echo "$$i"; done; \
if test -n "$$list2"; then \
for i in $$list2; do echo "$$i"; done \
| sed -n '/\.1[a-z]*$$/p'; \
fi; \
} | while read p; do \
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; echo "$$p"; \
done | \
sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
sed 'N;N;s,\n, ,g' | { \
list=; while read file base inst; do \
if test "$$base" = "$$inst"; then list="$$list $$file"; else \
echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
$(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
fi; \
done; \
for i in $$list; do echo "$$i"; done | $(am__base_list) | \
while read files; do \
test -z "$$files" || { \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
done; }
uninstall-man1:
@$(NORMAL_UNINSTALL)
@list=''; test -n "$(man1dir)" || exit 0; \
files=`{ for i in $$list; do echo "$$i"; done; \
l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
sed -n '/\.1[a-z]*$$/p'; \
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir)
install-man5: $(dist_man_MANS)
@$(NORMAL_INSTALL)
@list1=''; \
list2='$(dist_man_MANS)'; \
test -n "$(man5dir)" \
&& test -n "`echo $$list1$$list2`" \
|| exit 0; \
echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \
$(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \
{ for i in $$list1; do echo "$$i"; done; \
if test -n "$$list2"; then \
for i in $$list2; do echo "$$i"; done \
| sed -n '/\.5[a-z]*$$/p'; \
fi; \
} | while read p; do \
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; echo "$$p"; \
done | \
sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
sed 'N;N;s,\n, ,g' | { \
list=; while read file base inst; do \
if test "$$base" = "$$inst"; then list="$$list $$file"; else \
echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \
$(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \
fi; \
done; \
for i in $$list; do echo "$$i"; done | $(am__base_list) | \
while read files; do \
test -z "$$files" || { \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \
done; }
uninstall-man5:
@$(NORMAL_UNINSTALL)
@list=''; test -n "$(man5dir)" || exit 0; \
files=`{ for i in $$list; do echo "$$i"; done; \
l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
sed -n '/\.5[a-z]*$$/p'; \
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir)
install-man8: $(dist_man_MANS)
@$(NORMAL_INSTALL)
@list1=''; \
list2='$(dist_man_MANS)'; \
test -n "$(man8dir)" \
&& test -n "`echo $$list1$$list2`" \
|| exit 0; \
echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
$(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
{ for i in $$list1; do echo "$$i"; done; \
if test -n "$$list2"; then \
for i in $$list2; do echo "$$i"; done \
| sed -n '/\.8[a-z]*$$/p'; \
fi; \
} | while read p; do \
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; echo "$$p"; \
done | \
sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
sed 'N;N;s,\n, ,g' | { \
list=; while read file base inst; do \
if test "$$base" = "$$inst"; then list="$$list $$file"; else \
echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
$(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
fi; \
done; \
for i in $$list; do echo "$$i"; done | $(am__base_list) | \
while read files; do \
test -z "$$files" || { \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
done; }
uninstall-man8:
@$(NORMAL_UNINSTALL)
@list=''; test -n "$(man8dir)" || exit 0; \
files=`{ for i in $$list; do echo "$$i"; done; \
l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
sed -n '/\.8[a-z]*$$/p'; \
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
tags TAGS:
ctags CTAGS:
cscope cscopelist:
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(MANS)
installdirs:
for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic mostlyclean-am
distclean: distclean-am
-rm -f Makefile
distclean-am: clean-am distclean-generic
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am: install-man
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man: install-man1 install-man5 install-man8
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-man
uninstall-man: uninstall-man1 uninstall-man5 uninstall-man8
.MAKE: install-am install-strip
.PHONY: all all-am check check-am clean clean-generic cscopelist-am \
ctags-am distclean distclean-generic distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-man1 install-man5 \
install-man8 install-pdf install-pdf-am install-ps \
install-ps-am install-strip installcheck installcheck-am \
installdirs maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags-am \
uninstall uninstall-am uninstall-man uninstall-man1 \
uninstall-man5 uninstall-man8
.PRECIOUS: Makefile
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@ -1,4 +1,4 @@
.TH ANACRON 8 2009-07-17 "Marcela Mašláňová" "Anacron Users' Manual" .TH ANACRON 8 2012-11-22 "cronie" "System Administration"
.SH NAME .SH NAME
anacron \- runs commands periodically anacron \- runs commands periodically
.SH SYNOPSIS .SH SYNOPSIS
@ -11,90 +11,116 @@ anacron \- runs commands periodically
.br .br
.B anacron -T \fR[\fB-t anacrontab\fR] .B anacron -T \fR[\fB-t anacrontab\fR]
.SH DESCRIPTION .SH DESCRIPTION
Anacron .B Anacron
is used to execute commands periodically, with a is used to execute commands periodically, with a frequency specified in
frequency specified in days. Unlike \fBcron(8)\fR, days. Unlike
it does not assume that the machine is running continuously. Hence, .BR cron(8) ,
it can be used on machines that are not running 24 hours a day it does not assume that the machine is running continuously. Hence, it
to control regular jobs as daily, weekly, and monthly jobs. can be used on machines that are not running 24 hours a day to control
regular jobs as daily, weekly, and monthly jobs.
.PP .PP
Anacron reads a list of jobs from the Anacron reads a list of jobs from the
.I /etc/anacrontab .I /etc/anacrontab
configuration file (see \fBanacrontab(5)\fR). This file configuration file (see
contains the list of jobs that Anacron controls. Each .BR anacrontab (5)).
job entry specifies a period in days, This file contains the list of jobs that Anacron controls. Each job
a delay in minutes, a unique entry specifies a period in days, a delay in minutes, a unique job
job identifier, and a shell command. identifier, and a shell command.
.PP .PP
For each job, Anacron checks whether For each job, Anacron checks whether this job has been executed in the
this job has been executed in the last \fBn\fR days, where \fBn\fR is the time period specified last
for that job. If a job has not been executed in \fBn\fR days or more, Anacron runs the job's shell command, after waiting .B n
for the number of minutes specified as the delay parameter. days, where
.B n
is the time period specified for that job. If a job has not been
executed in
.B n
days or more, Anacron runs the job's shell command, after waiting for the
number of minutes specified as the delay parameter.
.PP .PP
After the command exits, Anacron records the date (excludes the hour) in a special After the command exits, Anacron records the date (excludes the hour) in
timestamp file for that job, so it knows when to execute that job again. a special timestamp file for that job, so it knows when to execute that
job again.
.PP .PP
When there are no more jobs to be run, Anacron exits. When there are no more jobs to be run, Anacron exits.
.PP .PP
Anacron only considers jobs whose identifier, as Anacron only considers jobs whose identifier, as specified in
specified in \fBanacrontab(5)\fR, matches any of .BR anacrontab (5),
the matches any of the
.I job .I job
command-line arguments. The command-line arguments. The
.I job .I job
command-line arguments can be represented by shell wildcard patterns (be sure to protect them from command-line arguments can be represented by shell wildcard patterns (be
your shell with adequate quoting). Specifying no sure to protect them from your shell with adequate quoting). Specifying
no
.I job .I job
command-line arguments is equivalent to specifying "*" (that is, all jobs are command-line arguments is equivalent to specifying "*" (that is, all
considered by Anacron). jobs are considered by Anacron).
.PP .PP
Unless Anacron is run with the \fB-d\fR option (specified below), it forks to the Unless Anacron is run with the
background when it starts, and any parent processes exit immediately. .B \-d
option (specified below), it forks to the background when it starts, and
any parent processes exit immediately.
.PP .PP
Unless Anacron is run with the \fB-s\fR or \fB-n\fR options, it starts jobs Unless Anacron is run with the
immediately when their delay is over. The execution of different jobs is .B \-s
completely independent. or
.B \-n
options, it starts jobs immediately when their delay is over. The
execution of different jobs is completely independent.
.PP .PP
If an executed job generates any output to standard output or to standard error, If an executed job generates any output to standard output or to standard
the output is mailed to the user under whom Anacron is running (usually root), or to error, the output is mailed to the user under whom Anacron is running
the address specified in the \fBMAILTO\fR environment variable in the (usually root), or to the address specified in the
.B MAILTO
environment variable in the
.I /etc/anacrontab .I /etc/anacrontab
file, if such exists. If the \fBLOGNAME\fR environment variable is set, it is used in the From: field of the mail. file, if such exists. If the
.B LOGNAME
environment variable is set, it is used in the From: field of the mail.
.PP .PP
Any informative messages generated by Anacron are sent to \fBsyslogd(8)\fR Any informative messages generated by Anacron are sent to
or \fBrsyslogd(8)\fR under with facility set to \fBcron\fR and priority set to \fBnotice\fR. Any error .BR syslogd (8)
messages are sent with the priority \fBerror\fR. or
.BR rsyslogd (8)
under with facility set to
.B cron
and priority set to
.BR notice .
Any error messages are sent with the priority
.BR error .
.PP .PP
"Active" jobs (i.e. jobs that Anacron already decided "Active" jobs (i.e., jobs that Anacron already decided to run and are now
to run and are now waiting for their delay to pass, and jobs that are currently waiting for their delay to pass, and jobs that are currently being
being executed by executed by Anacron), are "locked", so that other copies of Anacron
Anacron), are "locked", so that other copies of Anacron cannot run them cannot run them at the same time.
at the same time.
.SH OPTIONS .SH OPTIONS
.TP .TP
.B -f .B \-f
Forces execution of all jobs, ignoring any timestamps. Forces execution of all jobs, ignoring any timestamps.
.TP .TP
.B -u .B \-u
Updates the timestamps of all jobs to the current date, but Updates the timestamps of all jobs to the current date, but does not run
does not run any. any.
.TP .TP
.B -s .B \-s
Serializes execution of jobs. Anacron does not start a new job before the Serializes execution of jobs. Anacron does not start a new job before the
previous one finished. previous one finished.
.TP .TP
.B -n .B \-n
Runs jobs immediately and ignores the specified delays in the Runs jobs immediately and ignores the specified delays in the
.I /etc/anacrontab .I /etc/anacrontab
file. This options implies \fB-s\fR. file. This options implies
.BR -s .
.TP .TP
.B -d .B \-d
Does not fork Anacron to the background. In this mode, Anacron will output informational Does not fork Anacron to the background. In this mode, Anacron will
messages to standard error, as well as to syslog. The output of any job output informational messages to standard error, as well as to syslog.
is mailed by Anacron. The output of any job is mailed by Anacron.
.TP .TP
.B -q .B \-q
Suppresses any messages to standard error. Only applicable with \fB-d\fR. Suppresses any messages to standard error. Only applicable with
.BR -d .
.TP .TP
.B -t some_anacrontab .B -t some_anacrontab
Uses the specified anacrontab, rather than the Uses the specified anacrontab, rather than the
@ -104,13 +130,13 @@ default one.
.B -T .B -T
Anacrontab testing. Tests the Anacrontab testing. Tests the
.I /etc/anacrontab .I /etc/anacrontab
configuration file for validity. If configuration file for validity. If there is an error in the file, it is
there is an error in the file, it is shown on the standard output and Anacron shown on the standard output and Anacron returns the value of 1. Valid
returns the value of 1. Valid anacrontabs return the value of 0. anacrontabs return the value of 0.
.TP .TP
.B -S spooldir .B -S spooldir
Uses the specified spooldir to store timestamps in. This option is required for Uses the specified spooldir to store timestamps in. This option is
users who wish to run anacron themselves. required for users who wish to run anacron themselves.
.TP .TP
.B -V .B -V
Prints version information, and exits. Prints version information, and exits.
@ -118,29 +144,36 @@ Prints version information, and exits.
.B -h .B -h
Prints short usage message, and exits. Prints short usage message, and exits.
.SH SIGNALS .SH SIGNALS
After receiving a \fBSIGUSR1\fR signal, Anacron waits for any running After receiving a
jobs to finish and then exits. This can be used to stop .B SIGUSR1
Anacron cleanly. signal, Anacron waits for any running jobs to finish and then exits.
This can be used to stop Anacron cleanly.
.SH NOTES .SH NOTES
Make sure your time-zone is set correctly before Anacron is Make sure your time-zone is set correctly before Anacron is started since
started since the time-zone affects the date. This is usually accomplished the time-zone affects the date. This is usually accomplished by setting
by setting the TZ environment variable, or by installing a the TZ environment variable, or by installing a
.I /usr/lib/zoneinfo/localtime .I /usr/lib/zoneinfo/localtime
file. See file. See
.B tzset(3) .BR tzset (3)
for more information. for more information.
.PP
Timestamp files are created in the spool directory for each job specified in an anacrontab. These files are never removed automatically by Anacron, and should be removed by hand if a job is no longer being scheduled. Timestamp files are created in the spool directory for each job specified
in an anacrontab. These files are never removed automatically by
Anacron, and should be removed by hand if a job is no longer being
scheduled.
.SH FILES .SH FILES
.TP .TP
.I /etc/anacrontab .I /etc/anacrontab
Contains specifications of jobs. See \fBanacrontab(5)\fR for a complete Contains specifications of jobs. See
description. .BR anacrontab (5)
for a complete description.
.TP .TP
.I /var/spool/anacron .I /var/spool/anacron
This directory is used by Anacron for storing timestamp files. This directory is used by Anacron for storing timestamp files.
.SH "SEE ALSO" .SH "SEE ALSO"
.BR anacrontab (5), cron (8), tzset (3) .BR anacrontab (5),
.BR cron (8),
.BR tzset (3)
.PP .PP
The Anacron The Anacron
.I README .I README
@ -148,20 +181,37 @@ file.
.SH BUGS .SH BUGS
Anacron never removes timestamp files. Remove unused files manually. Anacron never removes timestamp files. Remove unused files manually.
.PP .PP
Anacron Anacron uses up to two file descriptors for each active job. It may run
uses up to two file descriptors for each active job. It may run out of out of descriptors if there are lots of active jobs. See
descriptors if there are more than about 125 active jobs (on normal kernels). .B echo $(($(ulimit -n) / 2))
for information how many concurent jobs anacron may run.
.PP .PP
Mail comments, suggestions and bug reports to Sean 'Shaleh' Perry <shaleh@(debian.org|valinux.com)>. Mail comments, suggestions and bug reports to
.MT shaleh@\:(debian.\:org|\:valinux.\:com)
Sean 'Shaleh' Perry
.ME .
.SH AUTHOR .SH AUTHOR
Anacron was originally conceived and implemented by Christian Schwarz Anacron was originally conceived and implemented by
<schwarz@monet.m.isar.de>. .MT schwarz@\:monet.\:m.\:isar.\:de
Christian Schwarz
.ME .
.PP .PP
The current implementation is a complete rewrite by Itai Tzur The current implementation is a complete rewrite by
<itzur@actcom.co.il>. .MT itzur@\:actcom.\:co.\:il
Itai Tzur
.ME .
.PP .PP
The code base was maintained by Sean 'Shaleh' Perry <shaleh@(debian.org|valinux.com)>. The code base was maintained by
.MT shaleh@\:(debian.\:org|\:valinux.\:com)
Sean 'Shaleh' Perry
.ME .
.PP .PP
Since 2004, it is maintained by Pascal Hakim <pasc@(debian.org|redellipse.net)>. Since 2004, it is maintained by
.MT pasc@\:(debian.\:org|\:redellipse.\:net)
Pascal Hakim
.ME .
.PP .PP
For Fedora, Anacron is maintained by Marcela Mašláňová <mmaslano@redhat.com>. For Fedora, Anacron is maintained by
.MT mmaslano@redhat.\:com
Marcela Mašláňová
.ME .

View File

@ -1,11 +1,13 @@
.TH ANACRONTAB 5 2009-08-17 "Marcela Mašláňová" "Anacron Users' Manual" .TH ANACRONTAB 5 2012-11-22 "cronie" "File Formats"
.SH NAME .SH NAME
/etc/anacrontab \- configuration file for Anacron /etc/anacrontab \- configuration file for Anacron
.SH DESCRIPTION .SH DESCRIPTION
The The
.I /etc/anacrontab .I /etc/anacrontab
configuration file describes the jobs controlled by \fBanacron(8)\fR. It can contain three types of lines: configuration file describes the jobs controlled by
job-description lines, environment assignments, or empty lines. .BR anacron (8).
It can contain three types of lines: job-description lines, environment
assignments, or empty lines.
.PP .PP
Job-description lines can have the following format: Job-description lines can have the following format:
.PP .PP
@ -13,11 +15,17 @@ Job-description lines can have the following format:
.PP .PP
The The
.I period in days .I period in days
variable specifies the frequency of execution of a job in days. This variable can be represented by an integer or a macro (@daily, @weekly, @monthly), where @daily denotes the same value as the integer 1, @weekly the same as 7, and @monthly specifies that the job is run once a month, independent on the length of the month. variable specifies the frequency of execution of a job in days. This
variable can be represented by an integer or a macro (@daily, @weekly,
@monthly), where @daily denotes the same value as the integer 1, @weekly
the same as 7, and @monthly specifies that the job is run once a month,
independent on the length of the month.
.PP .PP
The The
.I delay in minutes .I delay in minutes
variable specifies the number of minutes anacron waits, if necessary, before executing a job. This variable is represented by an integer where 0 means no delay. variable specifies the number of minutes anacron waits, if necessary,
before executing a job. This variable is represented by an integer where
0 means no delay.
.PP .PP
The The
.I job-identifier .I job-identifier
@ -25,7 +33,10 @@ variable specifies a unique name of a job which is used in the log files.
.PP .PP
The The
.I command .I command
variable specifies the command to execute. The command can either be a command such as \fBls /proc >> /tmp/proc\fR or a command to execute a custom script. variable specifies the command to execute. The command can either be a
command such as
.B ls /proc >> /tmp/proc
or a command to execute a custom script.
.PP .PP
Environment assignment lines can have the following format: Environment assignment lines can have the following format:
.PP .PP
@ -35,32 +46,36 @@ Any spaces around
.I VAR .I VAR
are removed. No spaces around are removed. No spaces around
.I VALUE .I VALUE
are allowed (unless you want them to be part of the value). The specified assignment are allowed (unless you want them to be part of the value). The
takes effect from the next line until the end of the file, or to the next specified assignment takes effect from the next line until the end of the
assignment of the same variable. file, or to the next assignment of the same variable.
.PP .PP
The The
.I START_HOURS_RANGE .I START_HOURS_RANGE
variable defines an interval (in hours) when scheduled jobs can be run. In case this time interval is missed, for example, due to a power down, then scheduled jobs are not executed that day. variable defines an interval (in hours) when scheduled jobs can be run.
In case this time interval is missed, for example, due to a power down,
then scheduled jobs are not executed that day.
.PP .PP
The The
.I RANDOM_DELAY .I RANDOM_DELAY
variable denotes the maximum number of minutes that will be added to the delay in minutes variable which is specified for each job. A variable denotes the maximum number of minutes that will be added to the
delay in minutes variable which is specified for each job. A
.I RANDOM_DELAY .I RANDOM_DELAY
set to 12 would therefore add, randomly, between 0 and 12 minutes to the delay in minutes for each job in that particular anacrontab. When set to 0, no random delay is added. set to 12 would therefore add, randomly, between 0 and 12 minutes to the
delay in minutes for each job in that particular anacrontab. When set to
0, no random delay is added.
.PP .PP
Empty lines are either blank lines, line containing white spaces only, or Empty lines are either blank lines, line containing white spaces only, or
lines with white spaces followed by a '#' followed by an arbitrary comment. lines with white spaces followed by a '#' followed by an arbitrary
comment.
.PP .PP
You can continue a line onto the next line by adding a '\\' at the end of it. You can continue a line onto the next line by adding a '\\' at the end of it.
.PP .PP
In case you want to disable Anacron, add the In case you want to disable Anacron, add a line with
.I 0anacron .I 0anacron
cron job (which is a part of which is the name of the script running the Anacron into the
.IR crontabs(4) )
into the
.I /etc/cron.hourly/jobs.deny .I /etc/cron.hourly/jobs.deny
directory. file.
.SH EXAMPLE .SH EXAMPLE
This example shows how to set up an Anacron job similar in functionality to This example shows how to set up an Anacron job similar in functionality to
.I /etc/crontab .I /etc/crontab
@ -69,7 +84,10 @@ between 6:00 and 8:00
.I only. .I only.
A A
.I RANDOM_DELAY .I RANDOM_DELAY
which can be 30 minutes at the most is specified. Jobs will run serialized in a queue where each job is started only after the previous one is finished. which can be 30 minutes at the most is specified. Jobs will run
serialized in a queue where each job is started only after the previous
one is finished.
.PP
.nf .nf
# environment variables # environment variables
SHELL=/bin/sh SHELL=/bin/sh
@ -85,14 +103,22 @@ START_HOURS_RANGE=6-8
.fi .fi
.SH "SEE ALSO" .SH "SEE ALSO"
.BR anacron (8), .BR anacron (8),
.BR crontabs (4) .BR crontab (1)
.PP .PP
The Anacron The Anacron
.I README .I README
file. file.
.SH AUTHOR .SH AUTHOR
Itai Tzur <itzur@actcom.co.il> .MT itzur@\:actcom.\:co.\:il
Itai Tzur
.ME
.PP .PP
Currently maintained by Pascal Hakim <pasc@(debian.org|redellipse.net)>. Currently maintained by
.MT pasc@\:(debian.\:org|\:redellipse.\:net)
Pascal Hakim
.ME .
.PP .PP
For Fedora, maintained by Marcela Mašláňová <mmaslano@redhat.com>. For Fedora, maintained by
.MT mmaslano@redhat.com
Marcela Mašláňová
.ME .

View File

@ -22,24 +22,31 @@
.\" .\"
.\" $Id: cron.8,v 1.8 2004/01/23 19:03:32 vixie Exp $ .\" $Id: cron.8,v 1.8 2004/01/23 19:03:32 vixie Exp $
.\" .\"
.TH CRON "8" "July 2010" "Marcela Mašláňová" "Cronie Users' Manual" .TH CRON "8" "2013-09-26" "cronie" "System Administration"
.SH NAME .SH NAME
crond \- daemon to execute scheduled commands crond \- daemon to execute scheduled commands
.SH SYNOPSIS .SH SYNOPSIS
.B crond .B crond
.RB [ -n " | " -p " | " -s " | " -c " | " -m \fP\fI<mail command>\fP ] .RB [ -c " | " -h " | " -i " | " -n " | " -p " | " -P " | " -s " | " -m \fP\fI<mail command>\fP ]
.br
.B crond .B crond
.B -x .B -x
.RB [ext,sch,proc,pars,load,misc,test,bit] .RB [ext,sch,proc,pars,load,misc,test,bit]
.br .br
.B crond
.B -V
.SH DESCRIPTION .SH DESCRIPTION
.I Cron .I Cron
is started from is started from
.I /etc/rc.d/init.d .I /etc/rc.d/init.d
or or
.I /etc/init.d .I /etc/init.d
It returns immediately, thus, there is no need to need to start it with the '&' parameter. when classical sysvinit scripts are used. In case systemd is enabled, then unit file is installed into
.I /lib/systemd/system/crond.service
and daemon is started by
.I systemctl start crond.service
command. It returns immediately, thus, there is no need to need to start it with
the '&' parameter.
.PP .PP
.I Cron .I Cron
searches searches
@ -56,97 +63,120 @@ directory, which have a different format (see
.BR crontab (5)). .BR crontab (5)).
.I Cron .I Cron
examines all stored crontabs and checks each job to see if it needs to be examines all stored crontabs and checks each job to see if it needs to be
run in the current minute. When executing run in the current minute. When executing commands, any output is mailed
commands, any output is mailed to the owner of the crontab (or to the user to the owner of the crontab (or to the user specified in the
specified in the
.I MAILTO .I MAILTO
environment variable in the crontab, if such exists). environment variable in the crontab, if such exists). Any job output can
Any job output can also be sent to syslog by using the also be sent to syslog by using the
.B "\-s" .B "\-s"
option. option.
.PP .PP
There are two ways how changes in crontables are checked. The first There are two ways how changes in crontables are checked. The first
method is checking the modtime of a file. The second method is using the inotify support. method is checking the modtime of a file. The second method is using the
Using of inotify is logged in the inotify support. Using of inotify is logged in the
.I /var/log/cron .I /var/log/cron
log after the daemon is started. The inotify support checks for changes in all crontables and accesses the log after the daemon is started. The inotify support checks for changes
hard disk only when a change is detected. in all crontables and accesses the hard disk only when a change is
detected.
.PP .PP
When using the modtime option, When using the modtime option,
.I Cron .I Cron
checks its crontables' modtimes every minute to check for any changes and reloads checks its crontables' modtimes every minute to check for any changes and
the crontables which have changed. There is no need to restart reloads the crontables which have changed. There is no need to restart
.I Cron .I Cron
after some of the after some of the crontables were modified. The modtime option is also
crontables were modified. The modtime option is also used when inotify can not be initialized. used when inotify can not be initialized.
.PP .PP
.I Cron .I Cron
checks these files and directories: checks these files and directories:
.TP
.IR /etc/crontab
system crontab. Nowadays the file is empty by default. Originally it
was usually used to run daily, weekly, monthly jobs. By default these
jobs are now run through anacron which reads
.IR /etc/anacrontab .IR /etc/anacrontab
system crontab, usually used to run daily, weekly, monthly jobs. See configuration file. See
.BR anacrontab (5) .BR anacrontab (5)
for more details. for more details.
.TP
.IR /etc/cron.d/ .IR /etc/cron.d/
directory that contains system cronjobs stored for different users. directory that contains system cronjobs stored for different users.
.TP
.IR /var/spool/cron .IR /var/spool/cron
directory that contains user crontables created by the directory that contains user crontables created by the
.IR crontab .IR crontab
command. command.
.PP
Note that the Note that the
.BR crontab (1) .BR crontab (1)
command updates the modtime of the spool directory whenever it changes a command updates the modtime of the spool directory whenever it changes a
crontab. crontab.
.PP .PP
.SS Daylight Saving Time and other time changes .SS Daylight Saving Time and other time changes
Local time changes of less than three hours, such as those caused Local time changes of less than three hours, such as those caused by the
by the Daylight Saving Time changes, are handled in a special way. Daylight Saving Time changes, are handled in a special way. This only
This only applies to jobs that run at a specific time and jobs that applies to jobs that run at a specific time and jobs that run with a
run with a granularity greater than one hour. Jobs that run granularity greater than one hour. Jobs that run more frequently are
more frequently are scheduled normally. scheduled normally.
.PP .PP
If time was adjusted one hour forward, those jobs that would have run in the If time was adjusted one hour forward, those jobs that would have run in
interval that has been skipped will be run immediately. the interval that has been skipped will be run immediately. Conversely,
Conversely, if time was adjusted backward, running the same job twice is avoided. if time was adjusted backward, running the same job twice is avoided.
.PP .PP
Time changes of more than 3 hours are considered to be corrections to Time changes of more than 3 hours are considered to be corrections to the
the clock or the timezone, and the new time is used immediately. clock or the timezone, and the new time is used immediately.
.PP .PP
It is possible to use different time zones for crontables. See It is possible to use different time zones for crontables. See
.IR crontab (5) .BR crontab (5)
for more information. for more information.
.SS PAM Access Control .SS PAM Access Control
.IR Cron .IR Cron
supports access control with PAM if the system has PAM installed. For more information, see supports access control with PAM if the system has PAM installed. For
.IR pam (8). more information, see
.BR pam (8).
A PAM configuration file for A PAM configuration file for
.IR crond .IR crond
is installed in is installed in
.IR /etc/pam.d/crond . .IR /etc/pam.d/crond .
The daemon loads the PAM environment from the pam_env module. This The daemon loads the PAM environment from the pam_env module. This can
can be overridden by defining specific settings in the appropriate crontab file. be overridden by defining specific settings in the appropriate crontab
file.
.SH "OPTIONS" .SH "OPTIONS"
.TP .TP
.B "\-h"
Prints a help message and exits.
.TP
.B "\-i"
Disables inotify support.
.TP
.B "\-m" .B "\-m"
This option allows you to specify a shell command to use for sending This option allows you to specify a shell command to use for sending
.I Cron .I Cron
mail output instead of using mail output instead of using
.BR sendmail (8) .BR sendmail (8)
This command must accept a fully formatted mail message (with headers) on standard input and send it This command must accept a fully formatted mail message (with headers) on
as a mail message to the recipients specified in the mail headers. Specifying standard input and send it as a mail message to the recipients specified
the string in the mail headers. Specifying the string
.I "off" .I "off"
(i.e. crond -m off) (i.e., crond -m off)
will disable the sending of mail. will disable the sending of mail.
.TP .TP
.B "\-n" .B "\-n"
Tells the daemon to run in the foreground. This can be useful when starting it out of init. Tells the daemon to run in the foreground. This can be useful when
starting it out of init. With this option is needed to change pam setting.
.I /etc/pam.d/crond
must not enable
.I pam_loginuid.so
module.
.TP .TP
.B "\-p" .B "\-p"
Allows Allows
.I Cron .I Cron
to accept any user set crontables. to accept any user set crontables.
.TP .TP
.B "\-P"
Don't set PATH. PATH is instead inherited from the environment.
.TP
.B "\-c" .B "\-c"
This option enables clustering support, as described below. This option enables clustering support, as described below.
.TP .TP
@ -154,19 +184,24 @@ This option enables clustering support, as described below.
This option will direct This option will direct
.I Cron .I Cron
to send the job output to the system log using to send the job output to the system log using
.IR syslog (3). .BR syslog (3).
This is useful if your system does not have This is useful if your system does not have
.BR sendmail (8), .BR sendmail (8),
installed or if mail is disabled. installed or if mail is disabled.
.TP .TP
.B "\-x" .B "\-x"
This option allows you to set debug flags. This option allows you to set debug flags.
.TP
.B "\-V"
Print version and exit.
.SH SIGNALS .SH SIGNALS
When the \s-2SIGHUP\s+2 is received, the When the
.I SIGHUP
is received, the
.I Cron .I Cron
daemon will close and reopen its daemon will close and reopen its log file. This proves to be useful in
log file. This proves to be useful in scripts which rotate and age log files. scripts which rotate and age log files. Naturally, this is not relevant
Naturally, this is not relevant if if
.I Cron .I Cron
was built to use was built to use
.IR syslog (3). .IR syslog (3).
@ -176,16 +211,19 @@ In this version of
it is possible to use a network-mounted shared it is possible to use a network-mounted shared
.I /var/spool/cron .I /var/spool/cron
across a cluster of hosts and specify that only one of the hosts should across a cluster of hosts and specify that only one of the hosts should
run the crontab jobs in this directory at any one time. This is done by starting run the crontab jobs in this directory at any one time. This is done by
starting
.I Cron .I Cron
with the \fB-c\fP option, and have the with the
.B \-c
option, and have the
.I /var/spool/cron/.cron.hostname .I /var/spool/cron/.cron.hostname
file contain just one line, which represents the hostname of whichever host in the file contain just one line, which represents the hostname of whichever
cluster should run the jobs. If this file does not exist, or the hostname host in the cluster should run the jobs. If this file does not exist, or
in it does not match that returned by the hostname in it does not match that returned by
.BR gethostname (2), .BR gethostname (2),
then all crontab files in this directory are ignored. This has no effect on then all crontab files in this directory are ignored. This has no effect
cron jobs specified in the on cron jobs specified in the
.I /etc/crontab .I /etc/crontab
file or on files in the file or on files in the
.I /etc/cron.d .I /etc/cron.d
@ -193,36 +231,52 @@ directory. These files are always run and considered host-specific.
.PP .PP
Rather than editing Rather than editing
.I /var/spool/cron/.cron.hostname .I /var/spool/cron/.cron.hostname
directly, use the \fB-n\fP option of directly, use the
.B \-n
option of
.BR crontab (1) .BR crontab (1)
to specify the host. to specify the host.
.PP .PP
You should ensure that all hosts in a cluster, and the file server from which You should ensure that all hosts in a cluster, and the file server from
they mount the shared crontab directory, have closely synchronised clocks, which they mount the shared crontab directory, have closely synchronised
e.g. using clocks, e.g., using
.BR ntpd (8) .BR ntpd (8),
, otherwise the results will be very unpredictable. otherwise the results will be very unpredictable.
.PP .PP
Using cluster sharing automatically disables inotify support, because inotify cannot be Using cluster sharing automatically disables inotify support, because
relied on with network-mounted shared file systems. inotify cannot be relied on with network-mounted shared file systems.
.SH CAVEATS .SH CAVEATS
All All
.BR crontab .BR crontab
files have to be regular files or symlinks to regular files, they must not be executable files have to be regular files or symlinks to regular files, they must
or writable for anyone else but the owner. not be executable or writable for anyone else but the owner. This
This requirement can be overridden by using the \fB-p\fP option on the crond command line. requirement can be overridden by using the
If inotify support is in use, changes in the symlinked crontabs are not automatically .B \-p
noticed by the cron daemon. The cron daemon must receive a SIGHUP signal to reload the crontabs. option on the crond command line. If inotify support is in use, changes
This is a limitation of the inotify API. in the symlinked crontabs are not automatically noticed by the cron
daemon. The cron daemon must receive a SIGHUP signal to reload the
crontabs. This is a limitation of the inotify API.
.PP .PP
The syslog output will be used instead of mail, when sendmail is not installed. The syslog output will be used instead of mail, when sendmail is not
installed.
.SH "SEE ALSO" .SH "SEE ALSO"
.BR crontab (1), .BR crontab (1),
.BR crontab (5), .BR crontab (5),
.BR inotify (7), .BR inotify (7),
.BR pam (8) .BR pam (8)
.SH AUTHOR .SH AUTHOR
.nf .MT vixie@isc.org
Paul Vixie <vixie@isc.org> Paul Vixie
Marcela Mašláňová <mmaslano@redhat.com> .ME
Colin Dean <colin@colin-dean.org> .br
.MT mmaslano@redhat.com
Marcela Mašláňová
.ME
.br
.MT colin@colin-dean.org
Colin Dean
.ME
.br
.MT tmraz@fedoraproject.org
Tomáš Mráz
.ME

83
man/cronnext.1 Normal file
View File

@ -0,0 +1,83 @@
.TH CRONNEXT 1 "2017-06-11" "cronie" "User Commands"
.SH NAME
cronnext \- time of next job cron will execute
.SH SYNOPSIS
.TP 9
.B cronnext
[\fB-i \fIusers\fR] [\fB-e \fIusers\fR] [\fB-s\fR]
[\fB-a\fR]
[\fB-t \fItime\fR] [\fB-q \fItime\fR]
[\fB-l\fR] [\fB-c\fR] [\fB-f\fR] [\fB-h\fR] [\fB-V\fR]
[file]...
.SH DESCRIPTION
Determine the time cron will execute the next job. Without arguments, it
prints that time considering all crontabs, in number of seconds since the
Epoch, rounded to the minute. This number can be converted into other formats
using
.BR date (1),
like
.B date --date @43243254
The file arguments are optional. If provided,
.I cronnext
uses them as crontabs instead of the ones installed in the system.
.SH OPTIONS
.TP
.BI "\-i " user,user,user,...
Consider only the crontabs of the specified users. Use
.B *system*
for the system crontab.
.TP
.BI "\-e " user,user,user,...
Do not consider the crontabs of the specified users.
.TP
.B \-s
Do not consider the system crontab, usually the
.I /etc/crontab
file. The system crontab usually contains the hourly, daily, weekly and
montly crontabs, which might be better dealt with
.BR anacron (8).
.TP
.BI \-a
Use the crontabs installed in the system in addition to the ones passed as
file arguments. This is implicit if no file is passed.
.TP
.BI "\-t " time
Determine the next job from this time, instead of now. The time is
expressed in number of seconds since the Epoch, as obtained for example by
.BR "date +%s --date \(dqnow + 2 hours\(dq" ,
and is internally rounded to the minute.
.TP
.BI "\-q " time
Do not check jobs over this time, expressed in the same way as in option
.BR -t .
.TP
.B \-l
Print the whole entries of the jobs that are the next to be executed by cron.
The default is to only print their next time of execution.
.TP
.B \-c
Print every entry in every crontab with the next time it is executed.
.TP
.B \-f
Print all jobs that are executed in the given interval. Requires option
\fB-q\fR.
.TP
.B \-h
Print usage output and exit.
.TP
.B \-V
Print version and exit.
.SH AUTHOR
.MT sgerwk@aol.com
Marco Migliori
.ME
.SH SEE ALSO
.BR cron (8),
.BR cron (1),
.BR crontab (5),
.BR crontab (1),
.BR anacron (8),
.BR anacrontab (5),
.BR atq (1),
.BR date (1)

View File

@ -22,18 +22,20 @@
.\" .\"
.\" $Id: crontab.1,v 1.7 2004/01/23 19:03:32 vixie Exp $ .\" $Id: crontab.1,v 1.7 2004/01/23 19:03:32 vixie Exp $
.\" .\"
.TH CRONTAB 1 "22 September 2010" .TH CRONTAB 1 "2012-11-22" "cronie" "User Commands"
.SH NAME .SH NAME
crontab \- maintains crontab files for individual users crontab \- maintains crontab files for individual users
.SH SYNOPSIS .SH SYNOPSIS
.B crontab .B crontab
.RB [ -u .RB [ -u
.IR user ] " file" .IR user ]
.RI < "file"
.RB | \ - >
.br .br
.B crontab .B crontab
.RB [ -u .RB [ -u
.IR user ] .IR user ]
.RB [ -l " | " -r " | " -e ]\ [ -i ] .RB < -l " | " -r " | " -e >\ [ -i ]
.RB [ -s ] .RB [ -s ]
.br .br
.B crontab .B crontab
@ -42,15 +44,20 @@ crontab \- maintains crontab files for individual users
.br .br
.B crontab .B crontab
.BR -c .BR -c
.br
.B crontab
.BR -V
.SH DESCRIPTION .SH DESCRIPTION
.I Crontab .I Crontab
is the program used to install, remove or list the tables is the program used to install a crontab table
used to serve the .IR file ,
remove or list the existing tables used to serve the
.BR cron (8) .BR cron (8)
daemon. Each user can have their own crontab, and though these are files in daemon. Each user can have their own crontab, and though these are files
in
.IR /var/spool/ , .IR /var/spool/ ,
they are not intended to be edited directly. For SELinux in MLS mode, you can define they are not intended to be edited directly. For SELinux in MLS mode,
more crontabs for each range. For more information, see you can define more crontabs for each range. For more information, see
.BR selinux (8). .BR selinux (8).
.PP .PP
In this version of In this version of
@ -58,55 +65,51 @@ In this version of
it is possible to use a network-mounted shared it is possible to use a network-mounted shared
.I /var/spool/cron .I /var/spool/cron
across a cluster of hosts and specify that only one of the hosts should across a cluster of hosts and specify that only one of the hosts should
run the crontab jobs in the particular directory at any one time. You may also use run the crontab jobs in the particular directory at any one time. You
may also use
.BR crontab (1) .BR crontab (1)
from any of these hosts to edit the same shared set of crontab files, and to from any of these hosts to edit the same shared set of crontab files, and
set and query which host should run the crontab jobs. to set and query which host should run the crontab jobs.
.PP .PP
Running cron jobs can be allowed or disallowed for different users. For this purpose, use the Running cron jobs can be allowed or disallowed for different users. For
this purpose, use the
.I cron.allow .I cron.allow
and and
.I cron.deny .I cron.deny
files. files. If the
If the
.I cron.allow .I cron.allow
file exists, a user must be listed in it to be allowed to use cron file exists, a user must be listed in it to be allowed to use cron If the
If the
.I cron.allow .I cron.allow
file does not exist but the file does not exist but the
.I cron.deny .I cron.deny
file does exist, then a user must \fInot\fR be listed in the file does exist, then a user must
.I not
be listed in the
.I cron.deny .I cron.deny
file in order to use cron. If neither of these files exists, file in order to use cron. If neither of these files exists, only the
only the super user is allowed to use cron. super user is allowed to use cron. Another way to restrict access to
Another way to restrict access to cron is to use PAM authentication to set up users, cron is to use PAM authentication in
which are allowed or disallowed to use .I /etc/security/access.conf
to set up users, which are allowed or disallowed to use
.I crontab .I crontab
or modify system cron jobs in the or modify system cron jobs in the
.IR /etc/cron.d/ .IR /etc/cron.d/
directory. directory.
.PP .PP
The temporary directory can be set in an environment variable. If it is not set The temporary directory can be set in an environment variable. If it is
by the user, the not set by the user, the
.I /tmp .I /tmp
directory is used. directory is used.
.PP .PP
.SH "OPTIONS" .SH "OPTIONS"
.TP .TP
.B "\-u" .B "\-u"
Appends the name of the user whose crontab is to be modified. If this option Specifies the name of the user whose crontab is to be modified. If this
is not used, option is not used,
.I crontab .I crontab
examines "your" crontab, i.e., the crontab of the person executing the examines "your" crontab, i.e., the crontab of the person executing the
command. Note that command. If no crontab exists for a particular user, it is created for
.BR su (8) him the first time the
may confuse
.IR crontab ,
thus, when executing commands under
.BR su (8)
you should always use the
.B -u
option. If no crontab exists for a particular user, it is created for him the first time the
.B crontab -u .B crontab -u
command is used under his username. command is used under his username.
.TP .TP
@ -117,31 +120,35 @@ Displays the current crontab on standard output.
Removes the current crontab. Removes the current crontab.
.TP .TP
.B "\-e" .B "\-e"
Edits the current crontab using the editor specified by Edits the current crontab using the editor specified by the
the \s-1VISUAL\s+1 or \s-1EDITOR\s+1 environment variables. After you exit .I VISUAL
from the editor, the modified crontab will be installed automatically. or
.I EDITOR
environment variables. After you exit from the editor, the modified
crontab will be installed automatically.
.TP .TP
.B "\-i" .B "\-i"
This option modifies the This option modifies the
.B "\-r" .B "\-r"
option to prompt the user for a 'y/Y' response option to prompt the user for a 'y/Y' response before actually removing
before actually removing the crontab. the crontab.
.TP .TP
.B "\-s" .B "\-s"
Appends the current SELinux security context string as an Appends the current SELinux security context string as an MLS_LEVEL
MLS_LEVEL setting to the crontab file before editing / replacement setting to the crontab file before editing / replacement occurs - see the
occurs - see the documentation of MLS_LEVEL in documentation of MLS_LEVEL in
.BR crontab(5)\. .BR crontab (5).
.TP .TP
.B "\-n" .B "\-n"
This option is relevant only if This option is relevant only if
.BR cron (8) .BR cron (8)
was started with the \fB-c\fP option, to enable clustering support. It is was started with the
used to set the host in the cluster which should run the jobs specified in the .B \-c
crontab files in the option, to enable clustering support. It is used to set the host in the
cluster which should run the jobs specified in the crontab files in the
.I /var/spool/cron .I /var/spool/cron
directory. directory. If a hostname is supplied, the host whose hostname returned
If a hostname is supplied, the host whose hostname returned by by
.BR gethostname (2) .BR gethostname (2)
matches the supplied hostname, will be selected to run the selected cron jobs subsequently. If there matches the supplied hostname, will be selected to run the selected cron jobs subsequently. If there
is no host in the cluster matching the supplied hostname, or you explicitly specify is no host in the cluster matching the supplied hostname, or you explicitly specify
@ -154,18 +161,26 @@ file and the files in the
.I /etc/cron.d .I /etc/cron.d
directory, which are always run, and considered host-specific. For more directory, which are always run, and considered host-specific. For more
information on clustering support, see information on clustering support, see
.BR cron (8)\. .BR cron (8).
.TP .TP
.B "\-c" .B "\-c"
This option is only relevant if This option is only relevant if
.BR cron (8) .BR cron (8)
was started with the \fB-c\fP option, to enable clustering support. It is was started with the
used to query which host in the cluster is currently set to run the jobs .B \-c
specified in the crontab files in the directory option, to enable clustering support. It is used to query which host in
the cluster is currently set to run the jobs specified in the crontab
files in the directory
.I /var/spool/cron .I /var/spool/cron
, as set using the \fB-n\fP option. , as set using the
.B \-n
option.
.TP
.B "\-V"
Print version and exit.
.SH "SEE ALSO" .SH "SEE ALSO"
.BR crontab (5), cron (8) .BR crontab (5),
.BR cron (8)
.SH FILES .SH FILES
.nf .nf
/etc/cron.allow /etc/cron.allow
@ -174,13 +189,20 @@ specified in the crontab files in the directory
.SH STANDARDS .SH STANDARDS
The The
.I crontab .I crontab
command conforms to IEEE Std1003.2-1992 (``POSIX''). This new command syntax command conforms to IEEE Std1003.2-1992 (``POSIX'') with one exception:
differs from previous versions of Vixie Cron, as well as from the classic For replacing the current crontab with data from standard input the
SVR3 syntax. .B \-
has to be specified on the command line. This new command
syntax differs from previous versions of Vixie Cron, as well as from the
classic SVR3 syntax.
.SH DIAGNOSTICS .SH DIAGNOSTICS
An informative usage message appears if you run a crontab with a faulty command An informative usage message appears if you run a crontab with a faulty
defined in it. command defined in it.
.SH AUTHOR .SH AUTHOR
.nf .MT vixie@isc.org
Paul Vixie <vixie@isc.org> Paul Vixie
Colin Dean <colin@colin-dean.org> .ME
.br
.MT colin@colin-dean.org
Colin Dean
.ME

View File

@ -19,7 +19,7 @@
.\" .\"
.\" $Id: crontab.5,v 1.6 2004/01/23 19:03:33 vixie Exp $ .\" $Id: crontab.5,v 1.6 2004/01/23 19:03:33 vixie Exp $
.\" .\"
.TH ANACRONTAB 5 "July 2010" "Marcela Mašláňová" "Cronie Users' Manual" .TH CRONTAB 5 2012-11-22 "cronie" "File Formats"
.SH NAME .SH NAME
crontab \- files used to schedule the execution of programs crontab \- files used to schedule the execution of programs
.SH DESCRIPTION .SH DESCRIPTION
@ -27,36 +27,37 @@ A
.I crontab .I crontab
file contains instructions for the file contains instructions for the
.BR cron (8) .BR cron (8)
daemon in the following simplified manner: "run this command at this time on this date". daemon in the following simplified manner: "run this command at this time
Each user can define their own crontab. Commands defined in any given crontab are on this date". Each user can define their own crontab. Commands defined
executed under the user who owns that particular crontab. Uucp and News usually have in any given crontab are executed under the user who owns that particular
their own crontabs, eliminating the need for explicitly running crontab. Uucp and News usually have their own crontabs, eliminating the
need for explicitly running
.BR su (1) .BR su (1)
as part of a cron command. as part of a cron command.
.PP .PP
Blank lines, leading spaces, and tabs are ignored. Lines whose first Blank lines, leading spaces, and tabs are ignored. Lines whose first
non-white space character is a pound-sign (#) are comments, and are note processed. non-white space character is a pound-sign (#) are comments, and are not
Note that comments are not allowed on the same line as cron commands, since processed. Note that comments are not allowed on the same line as cron
they are considered a part of the command. Similarly, comments are not commands, since they are considered a part of the command. Similarly,
allowed on the same line as environment variable settings. comments are not allowed on the same line as environment variable
settings.
.PP .PP
An active line in a crontab is either an environment setting or a cron An active line in a crontab is either an environment setting or a cron
command. An environment setting is of the form: command. An environment setting is of the form:
.PP .PP
name = value name = value
.PP .PP
where the white spaces around the equal-sign (=) are optional, and any subsequent where the white spaces around the equal-sign (=) are optional, and any
non-leading white spaces in subsequent non-leading white spaces in
.I value .I value
is a part of the value assigned to is a part of the value assigned to
.IR name . .IR name .
The The
.I value .I value
string may be placed in quotes (single or double, but matching) to preserve string may be placed in quotes (single or double, but matching) to
leading or trailing white spaces. preserve leading or trailing white spaces.
.PP .PP
Several environment variables are set up Several environment variables are set up automatically by the
automatically by the
.BR cron (8) .BR cron (8)
daemon. daemon.
.I SHELL .I SHELL
@ -84,80 +85,90 @@ and
.BR cron (8) .BR cron (8)
looks at the looks at the
.I MAILTO .I MAILTO
variable if a mail needs to be send as a result of running variable if a mail needs to be send as a result of running any commands
any commands in that particular crontab. If in that particular crontab. If
.I MAILTO .I MAILTO
is defined (and non-empty), mail is is defined (and non-empty), mail is sent to the specified address. If
sent to the specified address. If
.I MAILTO .I MAILTO
is defined but empty (\fIMAILTO=""\fR), no is defined but empty
mail is sent. Otherwise, mail is sent to the owner of the crontab. This .RI ( MAILTO="" ),
option is useful if you decide to use /bin/mail instead of /usr/lib/sendmail as no mail is sent. Otherwise, mail is sent to the owner of the crontab.
your mailer. Note that /bin/mail does not provide aliasing and UUCP This option is useful if you decide to use /bin/mail instead of
usually does not read its mail. If /usr/lib/sendmail as your mailer. Note that /bin/mail does not provide
aliasing and UUCP usually does not read its mail. If
.I MAILFROM .I MAILFROM
is defined (and non-empty), it is defined (and non-empty), it is used as the envelope sender address,
is used as the envelope sender address, otherwise, ``root'' is used. otherwise, ``root'' is used.
.PP .PP
By default, cron sends a mail using the 'Content-Type:' header of 'text/plain' By default, cron sends a mail using the 'Content-Type:' header
with the 'charset=' parameter set to the 'charmap/codeset' of the locale in which of 'text/plain' with the 'charset=' parameter set to the 'charmap/codeset'
of the locale in which
.BR crond (8) .BR crond (8)
is started up - i.e. either the default system locale, if no LC_* environment is started up, i.e., either the default system locale, if no LC_*
variables are set, or the locale specified by the LC_* environment variables environment variables are set, or the locale specified by the LC_*
(see environment variables (see
.BR locale (7)). .BR locale (7)).
Different character encodings can be used for mailing cron job outputs by Different character encodings can be used for mailing cron job outputs by
setting the setting the
.I CONTENT_TYPE .I CONTENT_TYPE
and and
.I CONTENT_TRANSFER_ENCODING .I CONTENT_TRANSFER_ENCODING
variables in a crontab to the correct values of the mail headers of those names. variables in a crontab to the correct values of the mail headers of those
names.
.PP .PP
The The
.I CRON_TZ .I CRON_TZ
variable specifies the time zone specific for the cron table. variable specifies the time zone specific for the cron table. The user
The user should enter a time according to the specified time zone into the table. should enter a time according to the specified time zone into the table.
The time used for writing into a log file is taken from the local time zone, where the The time used for writing into a log file is taken from the local time
daemon is running. zone, where the daemon is running.
.PP .PP
The The
.I MLS_LEVEL .I MLS_LEVEL
environment variable provides support for multiple per-job environment variable provides support for multiple per-job SELinux
SELinux security contexts in the same crontab. security contexts in the same crontab. By default, cron jobs execute
By default, cron jobs execute with the default SELinux security context of the with the default SELinux security context of the user that created the
user that created the crontab file. crontab file. When using multiple security levels and roles, this may
When using multiple security levels and roles, this may not be sufficient, because not be sufficient, because the same user may be running in different
the same user may be running in different roles or in different security levels. roles or in different security levels. For more information about roles
For more information about roles and SELinux MLS/MCS, see and SELinux MLS/MCS, see
.BR selinux (8) .BR selinux (8)
and the crontab example mentioned later on in this text. and the crontab example mentioned later on in this text. You can set the
You can set the
.I MLS_LEVEL .I MLS_LEVEL
variable to the SELinux security context string specifying variable to the SELinux security context string specifying the particular
the particular SELinux security context in which you want jobs to be run. SELinux security context in which you want jobs to be run.
.B crond .B crond
will then set the execution context of those jobs that meet the specifications of the particular security context. will then set the execution context of those jobs that meet the
For more information, see specifications of the particular security context. For more information,
see
.BR crontab (1)\ -s\ option. .BR crontab (1)\ -s\ option.
.PP .PP
The format of a cron command is similar to the V7 standard, with a number of The
upward-compatible extensions. Each line has five time-and-date fields .I RANDOM_DELAY
variable allows delaying job startups by random amount of minutes with
upper limit specified by the variable. The random scaling factor is
determined during the cron daemon startup so it remains constant for
the whole run time of the daemon.
.PP
The format of a cron command is similar to the V7 standard, with a number
of upward-compatible extensions. Each line has five time-and-date fields
followed by a followed by a
.BR user name .BR user name
(if this is the (if this is the
.BR system .BR system
crontab file), and followed by a command. Commands are executed by crontab file), and followed by a command. Commands are executed by
.BR cron (8) .BR cron (8)
when the 'minute', 'hour', and 'month of the year' fields match the current time, when the 'minute', 'hour', and 'month of the year' fields match the
current time,
.I and .I and
at least one of the two 'day' fields ('day of month', or 'day of week') at least one of the two 'day' fields ('day of month', or 'day of week')
match the current time (see "Note" below). match the current time (see "Note" below).
.PP .PP
Note that this means that non-existent times, such as the "missing hours" Note that this means that non-existent times, such as the "missing hours"
during the daylight savings time conversion, will never match, causing jobs during the daylight savings time conversion, will never match, causing
scheduled during the "missing times" not to be run. Similarly, times jobs scheduled during the "missing times" not to be run. Similarly,
that occur more than once (again, during the daylight savings time conversion) times that occur more than once (again, during the daylight savings time
will cause matching jobs to be run twice. conversion) will cause matching jobs to be run twice.
.PP .PP
.BR cron (8) .BR cron (8)
examines cron entries every minute. examines cron entries every minute.
@ -180,48 +191,50 @@ month 1-12 (or names, see below)
day of week 0-7 (0 or 7 is Sunday, or use names) day of week 0-7 (0 or 7 is Sunday, or use names)
.br .br
.PP .PP
A field may contain an asterisk (*), which always stands for "first\-last". A field may contain an asterisk (*), which always stands for
"first\-last".
.PP .PP
Ranges of numbers are allowed. Ranges are two numbers separated Ranges of numbers are allowed. Ranges are two numbers separated with a
with a hyphen. The specified range is inclusive. For example, hyphen. The specified range is inclusive. For example, 8-11 for
8-11 for an 'hours' entry specifies execution at hours 8, 9, 10, an 'hours' entry specifies execution at hours 8, 9, 10, and 11. The first
and 11. number must be less than or equal to the second one.
.PP .PP
Lists are allowed. A list is a set of numbers (or ranges) Lists are allowed. A list is a set of numbers (or ranges) separated by
separated by commas. Examples: "1,2,5,9", "0-4,8-12". commas. Examples: "1,2,5,9", "0-4,8-12".
.PP .PP
Step values can be used in conjunction with ranges. Following Step values can be used in conjunction with ranges. Following a range
a range with "/<number>" specifies skips of the number's value with "/<number>" specifies skips of the number's value through the range.
through the range. For example, "0-23/2" can be used in the 'hours' For example, "0-23/2" can be used in the 'hours' field to specify command
field to specify command execution for every other hour (the alternative execution for every other hour (the alternative in the V7 standard is
in the V7 standard is "0,2,4,6,8,10,12,14,16,18,20,22"). Step values are "0,\:2,\:4,\:6,\:8,\:10,\:12,\:14,\:16,\:18,\:20,\:22"). Step values are
also permitted after an asterisk, so if specifying a job to be run every two also permitted after an asterisk, so if specifying a job to be run every
hours, you can use "*/2". two hours, you can use "*/2".
.PP .PP
Names can also be used for the 'month' and 'day of week' Names can also be used for the 'month' and 'day of week' fields. Use the
fields. Use the first three letters of the particular first three letters of the particular day or month (case does not
day or month (case does not matter). Ranges or matter). Ranges or lists of names are not allowed.
lists of names are not allowed.
.PP .PP
The "sixth" field (the rest of the line) specifies the command to be If the UID of the owner is 0 (root), the first character of a crontab
run. entry can be "-" character. This will prevent cron from writing a syslog
message about the command being executed.
.PP
The "sixth" field (the rest of the line) specifies the command to be run.
The entire command portion of the line, up to a newline or a "%" The entire command portion of the line, up to a newline or a "%"
character, will be executed by /bin/sh or by the shell character, will be executed by /bin/sh or by the shell specified in the
specified in the SHELL variable of the cronfile. SHELL variable of the cronfile. A "%" character in the command, unless
A "%" character in the command, unless escaped with a backslash escaped with a backslash (\\), will be changed into newline characters,
(\\), will be changed into newline characters, and all data and all data after the first % will be sent to the command as standard
after the first % will be sent to the command as standard
input. input.
.PP .PP
Note: The day of a command's execution can be specified in the following two Note: The day of a command's execution can be specified in the following
fields \(em 'day of month', and 'day of week'. If both fields are two fields \(em 'day of month', and 'day of week'. If both fields are
restricted (i.e., do not contain the "*" character), the command will be run when restricted (i.e., do not contain the "*" character), the command will be
run when
.I either .I either
field matches the current time. For example, field matches the current time. For example,
.br .br
"30 4 1,15 * 5" "30 4 1,15 * 5" would cause a command to be run at 4:30 am on the 1st and
would cause a command to be run at 4:30 am on the 1st and 15th of each 15th of each month, plus every Friday.
month, plus every Friday.
.SH EXAMPLE CRON FILE .SH EXAMPLE CRON FILE
.nf .nf
# use /bin/sh to run commands, no matter what /etc/passwd says # use /bin/sh to run commands, no matter what /etc/passwd says
@ -244,9 +257,9 @@ The jobs in
.I cron.d .I cron.d
and and
.I /etc/crontab .I /etc/crontab
are system jobs, which are used usually for more than are system jobs, which are used usually for more than one user, thus,
one user, thus, the username is needed. MAILTO on the first line additionally the username is needed. MAILTO on the first line is
is optional. optional.
.SH EXAMPLE OF A JOB IN /etc/cron.d/job .SH EXAMPLE OF A JOB IN /etc/cron.d/job
.nf .nf
#login as root #login as root
@ -255,13 +268,19 @@ MAILTO=root
* * * * * root touch /tmp/file * * * * * root touch /tmp/file
.fi .fi
.SH SELinux with multi level security (MLS) .SH SELinux with multi level security (MLS)
In a crontab, it is important to specify a security level by \fIcrontab\ -s\fR or specifying In a crontab, it is important to specify a security level by
the required level on the first line of the crontab. Each level is specified .I crontab \-s
in \fI/etc/selinux/targeted/seusers\fR. When using crontab in the MLS mode, it is especially important to: or specifying the required level on the first line of the crontab. Each
level is specified in
.IR /etc/selinux/targeted/seusers .
When using crontab in the MLS mode, it is especially important to:
.br .br
- check/change the actual role, - check/change the actual role,
.br .br
- set correct \fIrole for directory\fR, which is used for input/output. - set correct
.I role for
.IR directory ,
which is used for input/output.
.SH EXAMPLE FOR SELINUX MLS .SH EXAMPLE FOR SELINUX MLS
.nf .nf
# login as root # login as root
@ -274,18 +293,20 @@ MLS_LEVEL=SystemHigh
0-59 * * * * id -Z > /tmp/SystemHigh/crontest 0-59 * * * * id -Z > /tmp/SystemHigh/crontest
.fi .fi
.SH FILES .SH FILES
.I /etc/anacrontab .I /etc/crontab
system crontab file for jobs like cron.daily, weekly, monthly. main system crontab file.
.I /var/spool/cron/ .I /var/spool/cron/
a directory for storing crontabs defined by users. a directory for storing crontabs defined by users.
.I /etc/cron.d/ .I /etc/cron.d/
a directory for storing system crontables. a directory for storing system crontabs.
.SH "SEE ALSO" .SH "SEE ALSO"
.BR cron (8), .BR cron (8),
.BR crontab (1) .BR crontab (1)
.SH EXTENSIONS .SH EXTENSIONS
These special time specification "nicknames" which replace These special time specification "nicknames" which replace the 5 initial
the 5 initial time and date fields, and are prefixed with the '@' character, are supported: time and date fields, and are prefixed with the '@' character, are
supported:
.PP
.nf .nf
@reboot : Run once after reboot. @reboot : Run once after reboot.
@yearly : Run once a year, ie. "0 0 1 1 *". @yearly : Run once a year, ie. "0 0 1 1 *".
@ -297,13 +318,15 @@ the 5 initial time and date fields, and are prefixed with the '@' character, are
.fi .fi
.SH CAVEATS .SH CAVEATS
.BR crontab .BR crontab
files have to be regular files or symlinks to regular files, they must not be executable files have to be regular files or symlinks to regular files, they must
or writable for anyone else but the owner. not be executable or writable for anyone else but the owner. This
This requirement can be overridden by using the \fB-p\fP option on the crond command line. requirement can be overridden by using the
If inotify support is in use, changes in the symlinked crontabs are not automatically .B \-p
noticed by the cron daemon. The cron daemon must receive a SIGHUP signal to reload the crontabs. option on the crond command line. If inotify support is in use, changes
This is a limitation of the inotify API. in the symlinked crontabs are not automatically noticed by the cron
daemon. The cron daemon must receive a SIGHUP signal to reload the
crontabs. This is a limitation of the inotify API.
.SH AUTHOR .SH AUTHOR
.nf .MT vixie@isc.org
Paul Vixie <vixie@isc.org> Paul Vixie
.ME

215
missing Executable file
View File

@ -0,0 +1,215 @@
#! /bin/sh
# Common wrapper for a few potentially missing GNU programs.
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1996-2018 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
echo 1>&2 "Try '$0 --help' for more information"
exit 1
fi
case $1 in
--is-lightweight)
# Used by our autoconf macros to check whether the available missing
# script is modern enough.
exit 0
;;
--run)
# Back-compat with the calling convention used by older automake.
shift
;;
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
to PROGRAM being missing or too old.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
Supported PROGRAM values:
aclocal autoconf autoheader autom4te automake makeinfo
bison yacc flex lex help2man
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
'g' are ignored when checking the name.
Send bug reports to <bug-automake@gnu.org>."
exit $?
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing $scriptversion (GNU Automake)"
exit $?
;;
-*)
echo 1>&2 "$0: unknown '$1' option"
echo 1>&2 "Try '$0 --help' for more information"
exit 1
;;
esac
# Run the given program, remember its exit status.
"$@"; st=$?
# If it succeeded, we are done.
test $st -eq 0 && exit 0
# Also exit now if we it failed (or wasn't found), and '--version' was
# passed; such an option is passed most likely to detect whether the
# program is present and works.
case $2 in --version|--help) exit $st;; esac
# Exit code 63 means version mismatch. This often happens when the user
# tries to use an ancient version of a tool on a file that requires a
# minimum version.
if test $st -eq 63; then
msg="probably too old"
elif test $st -eq 127; then
# Program was missing.
msg="missing on your system"
else
# Program was found and executed, but failed. Give up.
exit $st
fi
perl_URL=https://www.perl.org/
flex_URL=https://github.com/westes/flex
gnu_software_URL=https://www.gnu.org/software
program_details ()
{
case $1 in
aclocal|automake)
echo "The '$1' program is part of the GNU Automake package:"
echo "<$gnu_software_URL/automake>"
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/autoconf>"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
autoconf|autom4te|autoheader)
echo "The '$1' program is part of the GNU Autoconf package:"
echo "<$gnu_software_URL/autoconf/>"
echo "It also requires GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
esac
}
give_advice ()
{
# Normalize program name to check for.
normalized_program=`echo "$1" | sed '
s/^gnu-//; t
s/^gnu//; t
s/^g//; t'`
printf '%s\n' "'$1' is $msg."
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
case $normalized_program in
autoconf*)
echo "You should only need it if you modified 'configure.ac',"
echo "or m4 files included by it."
program_details 'autoconf'
;;
autoheader*)
echo "You should only need it if you modified 'acconfig.h' or"
echo "$configure_deps."
program_details 'autoheader'
;;
automake*)
echo "You should only need it if you modified 'Makefile.am' or"
echo "$configure_deps."
program_details 'automake'
;;
aclocal*)
echo "You should only need it if you modified 'acinclude.m4' or"
echo "$configure_deps."
program_details 'aclocal'
;;
autom4te*)
echo "You might have modified some maintainer files that require"
echo "the 'autom4te' program to be rebuilt."
program_details 'autom4te'
;;
bison*|yacc*)
echo "You should only need it if you modified a '.y' file."
echo "You may want to install the GNU Bison package:"
echo "<$gnu_software_URL/bison/>"
;;
lex*|flex*)
echo "You should only need it if you modified a '.l' file."
echo "You may want to install the Fast Lexical Analyzer package:"
echo "<$flex_URL>"
;;
help2man*)
echo "You should only need it if you modified a dependency" \
"of a man page."
echo "You may want to install the GNU Help2man package:"
echo "<$gnu_software_URL/help2man/>"
;;
makeinfo*)
echo "You should only need it if you modified a '.texi' file, or"
echo "any other file indirectly affecting the aspect of the manual."
echo "You might want to install the Texinfo package:"
echo "<$gnu_software_URL/texinfo/>"
echo "The spurious makeinfo call might also be the consequence of"
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
echo "want to install GNU make:"
echo "<$gnu_software_URL/make/>"
;;
*)
echo "You might have modified some files without having the proper"
echo "tools for further handling them. Check the 'README' file, it"
echo "often tells you about the needed prerequisites for installing"
echo "this package. You may also peek at any GNU archive site, in"
echo "case some other package contains this missing '$1' program."
;;
esac
}
give_advice "$1" | sed -e '1s/^/WARNING: /' \
-e '2,$s/^/ /' >&2
# Propagate the correct exit status (expected to be 127 for a program
# not found, 63 for a program that failed due to version mismatch).
exit $st
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

View File

@ -2,9 +2,10 @@
# The PAM configuration file for the cron daemon # The PAM configuration file for the cron daemon
# #
# #
# No PAM authentication called, auth modules not needed # Although no PAM authentication is called, auth modules
# are used for credential setting
auth include system-auth
account required pam_access.so account required pam_access.so
account include password-auth account include system-auth
session required pam_loginuid.so session required pam_loginuid.so
session include password-auth session include system-auth
auth include password-auth

32
src/.indent.pro vendored
View File

@ -1,32 +0,0 @@
--blank-before-sizeof
--brace-indent0
--braces-on-func-def-line
--braces-on-if-line
--braces-on-struct-decl-line
--break-after-boolean-operator
--case-brace-indentation0
--case-indentation0
--comment-indentation0
--continuation-indentation4
--cuddle-do-while
--declaration-comment-column0
--declaration-indentation0
--dont-break-function-decl-args
--dont-break-procedure-type
--dont-line-up-parentheses
--honour-newlines
--indent-level4
--line-length80
--paren-indentation4
--preprocessor-indentation1
--no-blank-lines-after-commas
--space-after-cast
--space-after-for
--space-after-if
--space-after-while
--space-special-semicolon
--no-space-after-parentheses
--no-space-after-function-call-names
--start-left-side-of-comments
--struct-brace-indentation4
--tab-size4

View File

@ -1,20 +1,25 @@
# Makefile.am - two binaries crond and crontab # Makefile.am - two binaries crond and crontab
sbin_PROGRAMS = crond sbin_PROGRAMS = crond
bin_PROGRAMS = crontab bin_PROGRAMS = crontab cronnext
crond_SOURCES = \ crond_SOURCES = \
cron.c database.c user.c job.c do_command.c popen.c \ cron.c database.c user.c job.c do_command.c popen.c security.c \
$(common_src) $(common_src)
crontab_SOURCES = crontab.c $(common_src) crontab_SOURCES = crontab.c security.c $(common_src)
common_src = entry.c env.c misc.c pw_dup.c security.c cron.h \ cronnext_SOURCES = \
cronnext.c database.c user.c job.c \
$(common_src)
common_src = entry.c env.c misc.c pw_dup.c \
externs.h funcs.h globals.h macros.h pathnames.h structs.h \ externs.h funcs.h globals.h macros.h pathnames.h structs.h \
bitstring.h bitstring.h
common_nodist = cron-paths.h common_nodist = cron-paths.h
nodist_crond_SOURCES = $(common_nodist) nodist_crond_SOURCES = $(common_nodist)
nodist_crontab_SOURCES = $(common_nodist) nodist_crontab_SOURCES = $(common_nodist)
nodist_cronnext_SOURCES = $(common_nodist)
BUILT_SOURCES = $(common_nodist) BUILT_SOURCES = $(common_nodist)
AM_CFLAGS = -I$(top_srcdir)
LDADD = $(LIBSELINUX) $(LIBPAM) $(LIBAUDIT) LDADD = $(LIBSELINUX) $(LIBPAM) $(LIBAUDIT)
@ -26,6 +31,7 @@ LDADD = $(LIBSELINUX) $(LIBPAM) $(LIBAUDIT)
# If they are configurable, they are declared in configure script. # If they are configurable, they are declared in configure script.
# Depends on this Makefile, because it uses make variables. # Depends on this Makefile, because it uses make variables.
# CCD 2010/09/10 added CRON_HOSTNAME for clustered-cron. # CCD 2010/09/10 added CRON_HOSTNAME for clustered-cron.
CLEANFILES = cron-paths.h
cron-paths.h: Makefile cron-paths.h: Makefile
@echo 'creating $@' @echo 'creating $@'
@sed >$@ 's/ *\\$$//' <<\END #\ @sed >$@ 's/ *\\$$//' <<\END #\

788
src/Makefile.in Normal file
View File

@ -0,0 +1,788 @@
# Makefile.in generated by automake 1.16.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2018 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# Makefile.am - two binaries crond and crontab
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
sbin_PROGRAMS = crond$(EXEEXT)
bin_PROGRAMS = crontab$(EXEEXT) cronnext$(EXEEXT)
subdir = src
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)"
PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS)
am__objects_1 = entry.$(OBJEXT) env.$(OBJEXT) misc.$(OBJEXT) \
pw_dup.$(OBJEXT)
am_crond_OBJECTS = cron.$(OBJEXT) database.$(OBJEXT) user.$(OBJEXT) \
job.$(OBJEXT) do_command.$(OBJEXT) popen.$(OBJEXT) \
security.$(OBJEXT) $(am__objects_1)
am__objects_2 =
nodist_crond_OBJECTS = $(am__objects_2)
crond_OBJECTS = $(am_crond_OBJECTS) $(nodist_crond_OBJECTS)
crond_LDADD = $(LDADD)
am__DEPENDENCIES_1 =
crond_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1)
am_cronnext_OBJECTS = cronnext.$(OBJEXT) database.$(OBJEXT) \
user.$(OBJEXT) job.$(OBJEXT) $(am__objects_1)
nodist_cronnext_OBJECTS = $(am__objects_2)
cronnext_OBJECTS = $(am_cronnext_OBJECTS) $(nodist_cronnext_OBJECTS)
cronnext_LDADD = $(LDADD)
cronnext_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1)
am_crontab_OBJECTS = crontab.$(OBJEXT) security.$(OBJEXT) \
$(am__objects_1)
nodist_crontab_OBJECTS = $(am__objects_2)
crontab_OBJECTS = $(am_crontab_OBJECTS) $(nodist_crontab_OBJECTS)
crontab_LDADD = $(LDADD)
crontab_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1)
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/cron.Po ./$(DEPDIR)/cronnext.Po \
./$(DEPDIR)/crontab.Po ./$(DEPDIR)/database.Po \
./$(DEPDIR)/do_command.Po ./$(DEPDIR)/entry.Po \
./$(DEPDIR)/env.Po ./$(DEPDIR)/job.Po ./$(DEPDIR)/misc.Po \
./$(DEPDIR)/popen.Po ./$(DEPDIR)/pw_dup.Po \
./$(DEPDIR)/security.Po ./$(DEPDIR)/user.Po
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo " CC " $@;
am__v_CC_1 =
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(crond_SOURCES) $(nodist_crond_SOURCES) $(cronnext_SOURCES) \
$(nodist_cronnext_SOURCES) $(crontab_SOURCES) \
$(nodist_crontab_SOURCES)
DIST_SOURCES = $(crond_SOURCES) $(cronnext_SOURCES) $(crontab_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
ANACRONTAB = @ANACRONTAB@
ANACRON_SPOOL_DIR = @ANACRON_SPOOL_DIR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DAEMON_GROUPNAME = @DAEMON_GROUPNAME@
DAEMON_USERNAME = @DAEMON_USERNAME@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBAUDIT = @LIBAUDIT@
LIBOBJS = @LIBOBJS@
LIBPAM = @LIBPAM@
LIBS = @LIBS@
LIBSELINUX = @LIBSELINUX@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
SPOOL_DIR = @SPOOL_DIR@
STRIP = @STRIP@
SYSCRONTAB = @SYSCRONTAB@
SYS_CROND_DIR = @SYS_CROND_DIR@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
editor_defined = @editor_defined@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
crond_SOURCES = \
cron.c database.c user.c job.c do_command.c popen.c security.c \
$(common_src)
crontab_SOURCES = crontab.c security.c $(common_src)
cronnext_SOURCES = \
cronnext.c database.c user.c job.c \
$(common_src)
common_src = entry.c env.c misc.c pw_dup.c \
externs.h funcs.h globals.h macros.h pathnames.h structs.h \
bitstring.h
common_nodist = cron-paths.h
nodist_crond_SOURCES = $(common_nodist)
nodist_crontab_SOURCES = $(common_nodist)
nodist_cronnext_SOURCES = $(common_nodist)
BUILT_SOURCES = $(common_nodist)
AM_CFLAGS = -I$(top_srcdir)
LDADD = $(LIBSELINUX) $(LIBPAM) $(LIBAUDIT)
# This header contains all the paths.
# If they are configurable, they are declared in configure script.
# Depends on this Makefile, because it uses make variables.
# CCD 2010/09/10 added CRON_HOSTNAME for clustered-cron.
CLEANFILES = cron-paths.h
all: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) all-am
.SUFFIXES:
.SUFFIXES: .c .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu src/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
$(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
fi; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
while read p p1; do if test -f $$p \
; then echo "$$p"; echo "$$p"; else :; fi; \
done | \
sed -e 'p;s,.*/,,;n;h' \
-e 's|.*|.|' \
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
if ($$2 == $$4) files[d] = files[d] " " $$1; \
else { print "f", $$3 "/" $$4, $$1; } } \
END { for (d in files) print "f", d, files[d] }' | \
while read type dir files; do \
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
test -z "$$files" || { \
echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
$(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
} \
; done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
-e 's/$$/$(EXEEXT)/' \
`; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(bindir)" && rm -f $$files
clean-binPROGRAMS:
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
install-sbinPROGRAMS: $(sbin_PROGRAMS)
@$(NORMAL_INSTALL)
@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
$(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
fi; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
while read p p1; do if test -f $$p \
; then echo "$$p"; echo "$$p"; else :; fi; \
done | \
sed -e 'p;s,.*/,,;n;h' \
-e 's|.*|.|' \
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
if ($$2 == $$4) files[d] = files[d] " " $$1; \
else { print "f", $$3 "/" $$4, $$1; } } \
END { for (d in files) print "f", d, files[d] }' | \
while read type dir files; do \
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
test -z "$$files" || { \
echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
$(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
} \
; done
uninstall-sbinPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
-e 's/$$/$(EXEEXT)/' \
`; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(sbindir)" && rm -f $$files
clean-sbinPROGRAMS:
-test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS)
crond$(EXEEXT): $(crond_OBJECTS) $(crond_DEPENDENCIES) $(EXTRA_crond_DEPENDENCIES)
@rm -f crond$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(crond_OBJECTS) $(crond_LDADD) $(LIBS)
cronnext$(EXEEXT): $(cronnext_OBJECTS) $(cronnext_DEPENDENCIES) $(EXTRA_cronnext_DEPENDENCIES)
@rm -f cronnext$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(cronnext_OBJECTS) $(cronnext_LDADD) $(LIBS)
crontab$(EXEEXT): $(crontab_OBJECTS) $(crontab_DEPENDENCIES) $(EXTRA_crontab_DEPENDENCIES)
@rm -f crontab$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(crontab_OBJECTS) $(crontab_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cron.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cronnext.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crontab.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/database.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/do_command.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entry.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/env.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/job.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/popen.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pw_dup.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/security.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/user.Po@am__quote@ # am--include-marker
$(am__depfiles_remade):
@$(MKDIR_P) $(@D)
@echo '# dummy' >$@-t && $(am__mv) $@-t $@
am--depfiles: $(am__depfiles_remade)
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-am
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) check-am
all-am: Makefile $(PROGRAMS)
installdirs:
for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
clean: clean-am
clean-am: clean-binPROGRAMS clean-generic clean-sbinPROGRAMS \
mostlyclean-am
distclean: distclean-am
-rm -f ./$(DEPDIR)/cron.Po
-rm -f ./$(DEPDIR)/cronnext.Po
-rm -f ./$(DEPDIR)/crontab.Po
-rm -f ./$(DEPDIR)/database.Po
-rm -f ./$(DEPDIR)/do_command.Po
-rm -f ./$(DEPDIR)/entry.Po
-rm -f ./$(DEPDIR)/env.Po
-rm -f ./$(DEPDIR)/job.Po
-rm -f ./$(DEPDIR)/misc.Po
-rm -f ./$(DEPDIR)/popen.Po
-rm -f ./$(DEPDIR)/pw_dup.Po
-rm -f ./$(DEPDIR)/security.Po
-rm -f ./$(DEPDIR)/user.Po
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am: install-binPROGRAMS install-sbinPROGRAMS
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/cron.Po
-rm -f ./$(DEPDIR)/cronnext.Po
-rm -f ./$(DEPDIR)/crontab.Po
-rm -f ./$(DEPDIR)/database.Po
-rm -f ./$(DEPDIR)/do_command.Po
-rm -f ./$(DEPDIR)/entry.Po
-rm -f ./$(DEPDIR)/env.Po
-rm -f ./$(DEPDIR)/job.Po
-rm -f ./$(DEPDIR)/misc.Po
-rm -f ./$(DEPDIR)/popen.Po
-rm -f ./$(DEPDIR)/pw_dup.Po
-rm -f ./$(DEPDIR)/security.Po
-rm -f ./$(DEPDIR)/user.Po
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-binPROGRAMS uninstall-sbinPROGRAMS
.MAKE: all check install install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
clean-binPROGRAMS clean-generic clean-sbinPROGRAMS \
cscopelist-am ctags ctags-am distclean distclean-compile \
distclean-generic distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-binPROGRAMS \
install-data install-data-am install-dvi install-dvi-am \
install-exec install-exec-am install-html install-html-am \
install-info install-info-am install-man install-pdf \
install-pdf-am install-ps install-ps-am install-sbinPROGRAMS \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \
uninstall-sbinPROGRAMS
.PRECIOUS: Makefile
cron-paths.h: Makefile
@echo 'creating $@'
@sed >$@ 's/ *\\$$//' <<\END #\
/* This file has been automatically generated. Do not edit. */ \
\
#ifndef _CRON_PATHS_H_ \
#define _CRON_PATHS_H_ \
\
/* SPOOLDIR is where the crontabs live. \
* This directory will have its modtime updated \
* whenever crontab(1) changes a crontab; this is \
* the signal for cron(8) to look at each individual \
* crontab file and reload those whose modtimes are \
* newer than they were last time around (or which \
* didn't exist last time around...) \
* or it will be checked by inotify \
*/ \
#define SPOOL_DIR "$(SPOOL_DIR)" \
\
/* CRON_HOSTNAME is file in SPOOL_DIR which, if it \
* exists, and does not just contain a line matching \
* the name returned by gethostname(), causes all \
* crontabs in SPOOL_DIR to be ignored. This is \
* intended to be used when clustering hosts sharing \
* one NFS-mounted SPOOL_DIR, and where only one host \
* should use the crontab files here at any one time. \
*/ \
#define CRON_HOSTNAME ".cron.hostname" \
\
/* cron allow/deny file. At least cron.deny must \
* exist for ordinary users to run crontab. \
*/ \
#define CRON_ALLOW "$(sysconfdir)/cron.allow" \
#define CRON_DENY "$(sysconfdir)/cron.deny" \
\
/* 4.3BSD-style crontab f.e. /etc/crontab */ \
#define SYSCRONTAB "$(SYSCRONTAB)" \
\
/* system crontab dir f.e. /etc/cron.d/ */ \
#define SYS_CROND_DIR "$(SYS_CROND_DIR)" \
\
#define SYSCONFDIR "$(sysconfdir)" \
\
#endif /* _CRON_PATHS_H_ */ \
END
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@ -68,11 +68,11 @@ typedef unsigned char bitstr_t;
/* set bit N of bitstring name */ /* set bit N of bitstring name */
#define bit_set(name, bit) \ #define bit_set(name, bit) \
(name)[_bit_byte(bit)] |= _bit_mask(bit) (name)[_bit_byte(bit)] |= (bitstr_t)_bit_mask(bit)
/* clear bit N of bitstring name */ /* clear bit N of bitstring name */
#define bit_clear(name, bit) \ #define bit_clear(name, bit) \
(name)[_bit_byte(bit)] &= ~_bit_mask(bit) (name)[_bit_byte(bit)] &= (bitstr_t)~_bit_mask(bit)
/* clear bits start ... stop in bitstring */ /* clear bits start ... stop in bitstring */
#define bit_nclear(name, start, stop) { \ #define bit_nclear(name, start, stop) { \
@ -81,13 +81,13 @@ typedef unsigned char bitstr_t;
register int _startbyte = _bit_byte(_start); \ register int _startbyte = _bit_byte(_start); \
register int _stopbyte = _bit_byte(_stop); \ register int _stopbyte = _bit_byte(_stop); \
if (_startbyte == _stopbyte) { \ if (_startbyte == _stopbyte) { \
_name[_startbyte] &= ((0xff >> (8 - (_start&0x7))) | \ _name[_startbyte] &= (bitstr_t)((0xff >> (8 - (_start&0x7))) | \
(0xff << ((_stop&0x7) + 1))); \ (0xff << ((_stop&0x7) + 1))); \
} else { \ } else { \
_name[_startbyte] &= 0xff >> (8 - (_start&0x7)); \ _name[_startbyte] &= (bitstr_t)(0xff >> (8 - (_start&0x7))); \
while (++_startbyte < _stopbyte) \ while (++_startbyte < _stopbyte) \
_name[_startbyte] = 0; \ _name[_startbyte] = 0; \
_name[_stopbyte] &= 0xff << ((_stop&0x7) + 1); \ _name[_stopbyte] &= (bitstr_t)(0xff << ((_stop&0x7) + 1)); \
} \ } \
} }
@ -98,13 +98,13 @@ typedef unsigned char bitstr_t;
register int _startbyte = _bit_byte(_start); \ register int _startbyte = _bit_byte(_start); \
register int _stopbyte = _bit_byte(_stop); \ register int _stopbyte = _bit_byte(_stop); \
if (_startbyte == _stopbyte) { \ if (_startbyte == _stopbyte) { \
_name[_startbyte] |= ((0xff << (_start&0x7)) & \ _name[_startbyte] |= (bitstr_t)((0xff << (_start&0x7)) & \
(0xff >> (7 - (_stop&0x7)))); \ (0xff >> (7 - (_stop&0x7)))); \
} else { \ } else { \
_name[_startbyte] |= 0xff << ((_start)&0x7); \ _name[_startbyte] |= (bitstr_t)(0xff << ((_start)&0x7)); \
while (++_startbyte < _stopbyte) \ while (++_startbyte < _stopbyte) \
_name[_startbyte] = 0xff; \ _name[_startbyte] = 0xff; \
_name[_stopbyte] |= 0xff >> (7 - (_stop&0x7)); \ _name[_stopbyte] |= (bitstr_t)(0xff >> (7 - (_stop&0x7))); \
} \ } \
} }

View File

@ -24,9 +24,35 @@
* to add clustering support. * to add clustering support.
*/ */
#include "config.h"
#define MAIN_PROGRAM #define MAIN_PROGRAM
#include <cron.h> #include <errno.h>
#include <langinfo.h>
#include <locale.h>
#include <pwd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/time.h>
#ifdef WITH_INOTIFY
# include <sys/inotify.h>
#endif
#ifdef HAVE_SYS_FCNTL_H
# include <sys/fcntl.h>
#endif
#include "cronie_common.h"
#include "funcs.h"
#include "globals.h"
#include "pathnames.h"
#if defined WITH_INOTIFY #if defined WITH_INOTIFY
int inotify_enabled; int inotify_enabled;
@ -36,16 +62,16 @@ int inotify_enabled;
enum timejump { negative, small, medium, large }; enum timejump { negative, small, medium, large };
static void usage(void), static void usage(void) ATTRIBUTE_NORETURN,
run_reboot_jobs(cron_db *), run_reboot_jobs(cron_db *),
find_jobs(int, cron_db *, int, int, long), find_jobs(int, cron_db *, int, int, long),
set_time(int), set_time(int),
cron_sleep(int, cron_db *), cron_sleep(int, cron_db *),
sigchld_handler(int), sigchld_handler(int),
sighup_handler(int), sighup_handler(int),
sigchld_reaper(void), quit(int), parse_args(int c, char *v[]); sigchld_reaper(void), sigintterm_handler(int), parse_args(int c, char *v[]);
static volatile sig_atomic_t got_sighup, got_sigchld; static volatile sig_atomic_t got_sighup, got_sigchld, got_sigintterm;
static int timeRunning, virtualTime, clockTime; static int timeRunning, virtualTime, clockTime;
static long GMToff; static long GMToff;
static int DisableInotify; static int DisableInotify;
@ -59,16 +85,30 @@ static int DisableInotify;
* clustering enabled. * clustering enabled.
*/ */
# if defined ENABLE_SYSCRONTAB
# define NUM_WATCHES 3 # define NUM_WATCHES 3
int wd[NUM_WATCHES]; int wd[NUM_WATCHES];
const char *watchpaths[NUM_WATCHES] = {SPOOL_DIR, SYS_CROND_DIR, SYSCRONTAB}; const char *watchpaths[NUM_WATCHES] = {SPOOL_DIR, SYS_CROND_DIR, SYSCRONTAB};
# else
# define NUM_WATCHES 2
int wd[NUM_WATCHES];
const char *watchpaths[NUM_WATCHES] = {SPOOL_DIR, SYS_CROND_DIR};
# endif
void set_cron_unwatched(int fd) { static void reset_watches(void) {
int i; size_t i;
for (i = 0; i < sizeof (wd) / sizeof (wd[0]); ++i) { for (i = 0; i < sizeof (wd) / sizeof (wd[0]); ++i) {
if (wd[i] < 0) { wd[i] = -2;
}
}
void set_cron_unwatched(int fd) {
size_t i;
for (i = 0; i < sizeof (wd) / sizeof (wd[0]); ++i) {
if (wd[i] > 0) {
inotify_rm_watch(fd, wd[i]); inotify_rm_watch(fd, wd[i]);
wd[i] = -1; wd[i] = -1;
} }
@ -77,7 +117,7 @@ void set_cron_unwatched(int fd) {
void set_cron_watched(int fd) { void set_cron_watched(int fd) {
pid_t pid = getpid(); pid_t pid = getpid();
int i; size_t i;
if (fd < 0) { if (fd < 0) {
inotify_enabled = 0; inotify_enabled = 0;
@ -87,15 +127,15 @@ void set_cron_watched(int fd) {
for (i = 0; i < sizeof (wd) / sizeof (wd[0]); ++i) { for (i = 0; i < sizeof (wd) / sizeof (wd[0]); ++i) {
int w; int w;
if (open(watchpaths[i], O_RDONLY | O_NONBLOCK, 0) != -1) {
w = inotify_add_watch(fd, watchpaths[i], w = inotify_add_watch(fd, watchpaths[i],
IN_CREATE | IN_CLOSE_WRITE | IN_ATTRIB | IN_MODIFY | IN_MOVED_TO | IN_CREATE | IN_CLOSE_WRITE | IN_ATTRIB | IN_MODIFY | IN_MOVED_TO |
IN_MOVED_FROM | IN_MOVE_SELF | IN_DELETE | IN_DELETE_SELF); IN_MOVED_FROM | IN_MOVE_SELF | IN_DELETE | IN_DELETE_SELF);
if (w < 0) { if (w < 0 && errno != ENOENT) {
if (wd[i] != -1) { if (wd[i] != -1) {
log_it("CRON", pid, "This directory or file can't be watched", log_it("CRON", pid, "This directory or file can't be watched",
watchpaths[i], errno); watchpaths[i], errno);
log_it("CRON", pid, "INFO", "running without inotify support", 0); log_it("CRON", pid, "INFO", "running without inotify support",
0);
} }
inotify_enabled = 0; inotify_enabled = 0;
set_cron_unwatched(fd); set_cron_unwatched(fd);
@ -103,7 +143,6 @@ void set_cron_watched(int fd) {
} }
wd[i] = w; wd[i] = w;
} }
}
if (!inotify_enabled) { if (!inotify_enabled) {
log_it("CRON", pid, "INFO", "running with inotify support", 0); log_it("CRON", pid, "INFO", "running with inotify support", 0);
@ -120,6 +159,7 @@ static void handle_signals(cron_db * database) {
/* watches must be reinstated on reload */ /* watches must be reinstated on reload */
if (inotify_enabled && (EnableClustering != 1)) { if (inotify_enabled && (EnableClustering != 1)) {
set_cron_unwatched(database->ifd); set_cron_unwatched(database->ifd);
reset_watches();
inotify_enabled = 0; inotify_enabled = 0;
} }
#endif #endif
@ -136,18 +176,24 @@ static void handle_signals(cron_db * database) {
static void usage(void) { static void usage(void) {
const char **dflags; const char **dflags;
fprintf(stderr, "usage: %s [-h] print this message \n \ fprintf(stderr, "Usage:\n");
[-i] deamon runs without inotify support \n \ fprintf(stderr, " %s [options]\n", ProgramName);
[-m <mail command>] off or specify prefered client for sending mails \n \ fprintf(stderr, "\n");
[-n] run in foreground \n \ fprintf(stderr, "Options:\n");
[-p] permit any crontab \n \ fprintf(stderr, " -h print this message \n");
[-c] enable clustering support \n \ fprintf(stderr, " -i deamon runs without inotify support\n");
[-s] log into syslog instead of sending mails \n \ fprintf(stderr, " -m <comm> off, or specify preferred client for sending mails\n");
[-x [", fprintf(stderr, " -n run in foreground\n");
ProgramName); fprintf(stderr, " -p permit any crontab\n");
fprintf(stderr, " -P use PATH=\"%s\"\n", _PATH_DEFPATH);
fprintf(stderr, " -c enable clustering support\n");
fprintf(stderr, " -s log into syslog instead of sending mails\n");
fprintf(stderr, " -V print version and exit\n");
fprintf(stderr, " -x <flag> print debug information\n");
fprintf(stderr, "\n");
fprintf(stderr, "Debugging flags are: ");
for (dflags = DebugFlagNames; *dflags; dflags++) for (dflags = DebugFlagNames; *dflags; dflags++)
fprintf(stderr, "%s%s", *dflags, dflags[1] ? "," : "]"); fprintf(stderr, "%s%s", *dflags, dflags[1] ? "," : "\n");
fprintf(stderr, "] print debug information\n");
exit(ERROR_EXIT); exit(ERROR_EXIT);
} }
@ -158,11 +204,17 @@ int main(int argc, char *argv[]) {
char *cs; char *cs;
pid_t pid = getpid(); pid_t pid = getpid();
long oldGMToff; long oldGMToff;
#if defined WITH_INOTIFY struct timeval tv;
int i; struct timezone tz;
#endif char buf[256];
if ((ProgramName=strrchr(argv[0], '/')) == NULL) {
ProgramName = argv[0]; ProgramName = argv[0];
}
else {
++ProgramName;
}
MailCmd[0] = '\0'; MailCmd[0] = '\0';
cron_default_mail_charset[0] = '\0'; cron_default_mail_charset[0] = '\0';
@ -175,9 +227,10 @@ int main(int argc, char *argv[]) {
SyslogOutput = 0; SyslogOutput = 0;
NoFork = 0; NoFork = 0;
ChangePath = 1;
parse_args(argc, argv); parse_args(argc, argv);
bzero((char *) &sact, sizeof sact); memset((char *) &sact, 0, sizeof sact);
sigemptyset(&sact.sa_mask); sigemptyset(&sact.sa_mask);
sact.sa_flags = 0; sact.sa_flags = 0;
#ifdef SA_RESTART #ifdef SA_RESTART
@ -187,7 +240,7 @@ int main(int argc, char *argv[]) {
(void) sigaction(SIGCHLD, &sact, NULL); (void) sigaction(SIGCHLD, &sact, NULL);
sact.sa_handler = sighup_handler; sact.sa_handler = sighup_handler;
(void) sigaction(SIGHUP, &sact, NULL); (void) sigaction(SIGHUP, &sact, NULL);
sact.sa_handler = quit; sact.sa_handler = sigintterm_handler;
(void) sigaction(SIGINT, &sact, NULL); (void) sigaction(SIGINT, &sact, NULL);
(void) sigaction(SIGTERM, &sact, NULL); (void) sigaction(SIGTERM, &sact, NULL);
@ -195,10 +248,13 @@ int main(int argc, char *argv[]) {
set_cron_uid(); set_cron_uid();
check_spool_dir(); check_spool_dir();
if (putenv("PATH=" _PATH_DEFPATH) < 0) { if (ChangePath) {
log_it("CRON", pid, "DEATH", "can't putenv PATH", errno); if (setenv("PATH", _PATH_DEFPATH, 1) < 0) {
log_it("CRON", pid, "DEATH", "can't setenv PATH",
errno);
exit(1); exit(1);
} }
}
/* Get the default locale character set for the mail /* Get the default locale character set for the mail
* "Content-Type: ...; charset=" header * "Content-Type: ...; charset=" header
@ -206,7 +262,7 @@ int main(int argc, char *argv[]) {
setlocale(LC_ALL, ""); /* set locale to system defaults or to setlocale(LC_ALL, ""); /* set locale to system defaults or to
* that specified by any LC_* env vars */ * that specified by any LC_* env vars */
if ((cs = nl_langinfo(CODESET)) != 0L) if ((cs = nl_langinfo(CODESET)) != 0L)
strncpy(cron_default_mail_charset, cs, MAX_ENVSTR); strncpy(cron_default_mail_charset, cs, MAX_ENVSTR-1);
else else
strcpy(cron_default_mail_charset, "US-ASCII"); strcpy(cron_default_mail_charset, "US-ASCII");
@ -233,7 +289,6 @@ int main(int argc, char *argv[]) {
if (fd != STDERR) if (fd != STDERR)
(void) close(fd); (void) close(fd);
} }
log_it("CRON", getpid(), "STARTUP", PACKAGE_VERSION, 0);
break; break;
default: default:
/* parent process should just die */ /* parent process should just die */
@ -241,12 +296,23 @@ int main(int argc, char *argv[]) {
} }
} }
if (access("/usr/sbin/sendmail", X_OK) != 0) { log_it("CRON", getpid(), "STARTUP", PACKAGE_VERSION, 0);
if (!SyslogOutput && MailCmd[0] == '\0' && access("/usr/sbin/sendmail", X_OK) != 0) {
SyslogOutput=1; SyslogOutput=1;
log_it("CRON", pid, "INFO","Syslog will be used instead of sendmail.", errno); log_it("CRON", pid, "INFO","Syslog will be used instead of sendmail.", 0);
} }
pid = getpid(); pid = getpid();
/* obtain a random scaling factor for RANDOM_DELAY */
if (gettimeofday(&tv, &tz) != 0)
tv.tv_usec = 0;
srandom((unsigned int)(pid + tv.tv_usec));
RandomScale = (double)random() / (double)RAND_MAX;
snprintf(buf, sizeof(buf), "RANDOM_DELAY will be scaled with factor %d%% if used.", (int)(RandomScale*100));
log_it("CRON", pid, "INFO", buf, 0);
acquire_daemonlock(0); acquire_daemonlock(0);
database.head = NULL; database.head = NULL;
database.tail = NULL; database.tail = NULL;
@ -261,13 +327,7 @@ int main(int argc, char *argv[]) {
"", 0); "", 0);
} }
else { else {
for (i = 0; i < sizeof (wd) / sizeof (wd[0]); ++i) { reset_watches();
/* initialize to negative number other than -1
* so an eventual error is reported for the first time
*/
wd[i] = -2;
}
database.ifd = fd = inotify_init(); database.ifd = fd = inotify_init();
fcntl(fd, F_SETFD, FD_CLOEXEC); fcntl(fd, F_SETFD, FD_CLOEXEC);
if (fd < 0) if (fd < 0)
@ -291,7 +351,7 @@ int main(int argc, char *argv[]) {
* timeRunning: is the time we last awakened. * timeRunning: is the time we last awakened.
* clockTime: is the time when set_time was last called. * clockTime: is the time when set_time was last called.
*/ */
while (TRUE) { while (!got_sigintterm) {
int timeDiff; int timeDiff;
enum timejump wakeupKind; enum timejump wakeupKind;
@ -299,7 +359,9 @@ int main(int argc, char *argv[]) {
do { do {
cron_sleep(timeRunning + 1, &database); cron_sleep(timeRunning + 1, &database);
set_time(FALSE); set_time(FALSE);
} while (clockTime == timeRunning); } while (!got_sigintterm && clockTime == timeRunning);
if (got_sigintterm)
break;
timeRunning = clockTime; timeRunning = clockTime;
/* /*
@ -345,7 +407,7 @@ int main(int argc, char *argv[]) {
* minute until caught up. * minute until caught up.
*/ */
Debug(DSCH, ("[%ld], normal case %d minutes to go\n", Debug(DSCH, ("[%ld], normal case %d minutes to go\n",
(long) pid, timeDiff)) (long) pid, timeDiff));
do { do {
if (job_runqueue()) if (job_runqueue())
sleep(10); sleep(10);
@ -370,7 +432,7 @@ int main(int argc, char *argv[]) {
* housekeeping. * housekeeping.
*/ */
Debug(DSCH, ("[%ld], DST begins %d minutes to go\n", Debug(DSCH, ("[%ld], DST begins %d minutes to go\n",
(long) pid, timeDiff)) (long) pid, timeDiff));
/* run wildcard jobs for current minute */ /* run wildcard jobs for current minute */
find_jobs(timeRunning, &database, TRUE, FALSE, GMToff); find_jobs(timeRunning, &database, TRUE, FALSE, GMToff);
@ -397,7 +459,7 @@ int main(int argc, char *argv[]) {
* change until we are caught up. * change until we are caught up.
*/ */
Debug(DSCH, ("[%ld], DST ends %d minutes to go\n", Debug(DSCH, ("[%ld], DST ends %d minutes to go\n",
(long) pid, timeDiff)) (long) pid, timeDiff));
find_jobs(timeRunning, &database, TRUE, FALSE, GMToff); find_jobs(timeRunning, &database, TRUE, FALSE, GMToff);
break; break;
default: default:
@ -405,7 +467,7 @@ int main(int argc, char *argv[]) {
* other: time has changed a *lot*, * other: time has changed a *lot*,
* jump virtual time, and run everything * jump virtual time, and run everything
*/ */
Debug(DSCH, ("[%ld], clock jumped\n", (long) pid)) Debug(DSCH, ("[%ld], clock jumped\n", (long) pid));
virtualTime = timeRunning; virtualTime = timeRunning;
oldGMToff = GMToff; oldGMToff = GMToff;
find_jobs(timeRunning, &database, TRUE, TRUE, GMToff); find_jobs(timeRunning, &database, TRUE, TRUE, GMToff);
@ -425,6 +487,12 @@ int main(int argc, char *argv[]) {
if (fd >= 0 && close(fd) < 0) if (fd >= 0 && close(fd) < 0)
log_it("CRON", pid, "INFO", "Inotify close failed", errno); log_it("CRON", pid, "INFO", "Inotify close failed", errno);
#endif #endif
log_it("CRON", pid, "INFO", "Shutting down", 0);
(void) unlink(_PATH_CRON_PID);
return 0;
} }
static void run_reboot_jobs(cron_db * db) { static void run_reboot_jobs(cron_db * db) {
@ -457,13 +525,10 @@ static void run_reboot_jobs(cron_db * db) {
static void find_jobs(int vtime, cron_db * db, int doWild, int doNonWild, long vGMToff) { static void find_jobs(int vtime, cron_db * db, int doWild, int doNonWild, long vGMToff) {
char *orig_tz, *job_tz; char *orig_tz, *job_tz;
time_t virtualSecond = vtime * SECONDS_PER_MINUTE;
time_t virtualGMTSecond = virtualSecond - vGMToff;
struct tm *tm; struct tm *tm;
int minute, hour, dom, month, dow; int minute, hour, dom, month, dow;
user *u; user *u;
entry *e; entry *e;
const char *uname;
/* The support for the job-specific timezones is not perfect. There will /* The support for the job-specific timezones is not perfect. There will
* be jobs missed or run twice during the DST change in the job timezone. * be jobs missed or run twice during the DST change in the job timezone.
@ -491,11 +556,7 @@ static void find_jobs(int vtime, cron_db * db, int doWild, int doNonWild, long v
} while (0) } while (0)
orig_tz = getenv("TZ"); orig_tz = getenv("TZ");
maketime(NULL, orig_tz);
Debug(DSCH, ("[%ld] tick(%d,%d,%d,%d,%d) %s %s\n",
(long) getpid(), minute, hour, dom, month, dow,
doWild ? " " : "No wildcard", doNonWild ? " " : "Wildcard only"))
/* the dom/dow situation is odd. '* * 1,15 * Sun' will run on the /* the dom/dow situation is odd. '* * 1,15 * Sun' will run on the
* first and fifteenth AND every Sunday; '* * * * Sun' will run *only* * first and fifteenth AND every Sunday; '* * * * Sun' will run *only*
* on Sundays; '* * 1,15 * *' will run *only* the 1st and 15th. this * on Sundays; '* * 1,15 * *' will run *only* the 1st and 15th. this
@ -504,14 +565,11 @@ static void find_jobs(int vtime, cron_db * db, int doWild, int doNonWild, long v
*/ */
for (u = db->head; u != NULL; u = u->next) { for (u = db->head; u != NULL; u = u->next) {
for (e = u->crontab; e != NULL; e = e->next) { for (e = u->crontab; e != NULL; e = e->next) {
Debug(DSCH | DEXT, ("user [%s:%ld:%ld:...] cmd=\"%s\"\n", time_t virtualSecond = (time_t)(vtime - e->delay) * (time_t)SECONDS_PER_MINUTE;
e->pwd->pw_name, (long) e->pwd->pw_uid, time_t virtualGMTSecond = virtualSecond - vGMToff;
(long) e->pwd->pw_gid, e->cmd))
uname = e->pwd->pw_name;
/* check if user exists in time of job is being run f.e. ldap */
if (getpwnam(uname) != NULL) {
job_tz = env_get("CRON_TZ", e->envp); job_tz = env_get("CRON_TZ", e->envp);
maketime(job_tz, orig_tz); maketime(job_tz, orig_tz);
/* here we test whether time is NOW */ /* here we test whether time is NOW */
if (bit_test(e->minute, minute) && if (bit_test(e->minute, minute) &&
bit_test(e->hour, hour) && bit_test(e->hour, hour) &&
@ -534,7 +592,6 @@ static void find_jobs(int vtime, cron_db * db, int doWild, int doNonWild, long v
} }
} }
} }
}
if (orig_tz != NULL) if (orig_tz != NULL)
setenv("TZ", orig_tz, 1); setenv("TZ", orig_tz, 1);
else else
@ -557,9 +614,9 @@ static void set_time(int initialize) {
if (initialize || tm.tm_isdst != isdst) { if (initialize || tm.tm_isdst != isdst) {
isdst = tm.tm_isdst; isdst = tm.tm_isdst;
GMToff = get_gmtoff(&StartTime, &tm); GMToff = get_gmtoff(&StartTime, &tm);
Debug(DSCH, ("[%ld] GMToff=%ld\n", (long) getpid(), (long) GMToff)) Debug(DSCH, ("[%ld] GMToff=%ld\n", (long) getpid(), (long) GMToff));
} }
clockTime = (StartTime + GMToff) / (time_t) SECONDS_PER_MINUTE; clockTime = (int)((StartTime + GMToff) / (time_t) SECONDS_PER_MINUTE);
} }
/* /*
@ -573,11 +630,14 @@ static void cron_sleep(int target, cron_db * db) {
seconds_to_wait = (int) (target * SECONDS_PER_MINUTE - t1) + 1; seconds_to_wait = (int) (target * SECONDS_PER_MINUTE - t1) + 1;
Debug(DSCH, ("[%ld] Target time=%ld, sec-to-wait=%d\n", Debug(DSCH, ("[%ld] Target time=%ld, sec-to-wait=%d\n",
(long) getpid(), (long) target * SECONDS_PER_MINUTE, (long) getpid(), (long) target * SECONDS_PER_MINUTE,
seconds_to_wait)) seconds_to_wait));
while (seconds_to_wait > 0 && seconds_to_wait < 65) { while (seconds_to_wait > 0 && seconds_to_wait < 65) {
sleep((unsigned int) seconds_to_wait); sleep((unsigned int) seconds_to_wait);
if (got_sigintterm)
return;
/* /*
* Check to see if we were interrupted by a signal. * Check to see if we were interrupted by a signal.
* If so, service the signal(s) then continue sleeping * If so, service the signal(s) then continue sleeping
@ -599,9 +659,8 @@ static void sigchld_handler(int x) {
got_sigchld = 1; got_sigchld = 1;
} }
static void quit(int x) { static void sigintterm_handler(int x) {
(void) unlink(_PATH_CRON_PID); got_sigintterm = 1;
_exit(0);
} }
static void sigchld_reaper(void) { static void sigchld_reaper(void) {
@ -614,15 +673,15 @@ static void sigchld_reaper(void) {
case -1: case -1:
if (errno == EINTR) if (errno == EINTR)
continue; continue;
Debug(DPROC, ("[%ld] sigchld...no children\n", (long) getpid())) Debug(DPROC, ("[%ld] sigchld...no children\n", (long) getpid()));
break; break;
case 0: case 0:
Debug(DPROC, ("[%ld] sigchld...no dead kids\n", (long) getpid())) Debug(DPROC, ("[%ld] sigchld...no dead kids\n", (long) getpid()));
break; break;
default: default:
Debug(DPROC, Debug(DPROC,
("[%ld] sigchld...pid #%ld died, stat=%d\n", ("[%ld] sigchld...pid #%ld died, stat=%d\n",
(long) getpid(), (long) pid, WEXITSTATUS(waiter))) (long) getpid(), (long) pid, WEXITSTATUS(waiter)));
break; break;
} }
} while (pid > 0); } while (pid > 0);
@ -631,7 +690,7 @@ static void sigchld_reaper(void) {
static void parse_args(int argc, char *argv[]) { static void parse_args(int argc, char *argv[]) {
int argch; int argch;
while (-1 != (argch = getopt(argc, argv, "hnpsix:m:c"))) { while (-1 != (argch = getopt(argc, argv, "hnpsiPx:m:cV"))) {
switch (argch) { switch (argch) {
case 'x': case 'x':
if (!set_debug_flags(optarg)) if (!set_debug_flags(optarg))
@ -649,12 +708,18 @@ static void parse_args(int argc, char *argv[]) {
case 'i': case 'i':
DisableInotify = 1; DisableInotify = 1;
break; break;
case 'P':
ChangePath = 0;
break;
case 'm': case 'm':
strncpy(MailCmd, optarg, MAX_COMMAND); strncpy(MailCmd, optarg, MAX_COMMAND);
break; break;
case 'c': case 'c':
EnableClustering = 1; EnableClustering = 1;
break; break;
case 'V':
puts(PACKAGE_STRING);
exit(EXIT_SUCCESS);
case 'h': case 'h':
default: default:
usage(); usage();

418
src/cronnext.c Normal file
View File

@ -0,0 +1,418 @@
/*
cronnext - calculate the time cron will execute the next job
Copyright (C) 2016 Marco Migliori <sgerwk@aol.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
The GNU General Public License can also be found in the file
`COPYING' that comes with the Anacron source distribution.
*/
#include "config.h"
#define MAIN_PROGRAM
#include <stdlib.h>
#include <string.h>
#include <pwd.h>
#include "globals.h"
#include "funcs.h"
#include "cron-paths.h"
/* flags to crontab search */
#define ENTRIES 0x01 // print entries
#define CRONTABS 0x02 // print crontabs
#define SYSTEM 0x04 // include system crontab
#define ALLJOBS 0x08 // print all jobs in interval
#ifdef WITH_INOTIFY
void set_cron_watched(int fd) {
/* empty stub */
(void)fd;
}
#endif
void do_command(entry *e, user *u) {
/* empty stub */
(void)e;
(void)u;
}
#ifdef WITH_SELINUX
int get_security_context(const char *name, int crontab_fd,
security_context_t *rcontext, const char *tabname) {
/* empty stub */
(void)name;
(void)crontab_fd;
(void)tabname;
*rcontext = NULL;
return 0;
}
void free_security_context(security_context_t *scontext) {
/* empty stub */
(void)scontext;
}
#endif
/*
* print entry flags
*/
const char *flagname[]= {
"MIN_STAR",
"HR_STAR",
"DOM_STAR",
"DOW_STAR",
"WHEN_REBOOT",
"DONT_LOG"
};
void printflags(char *indent, int flags) {
int f;
int first = 1;
printf("%s flagnames:", indent);
for (f = 0; f < sizeof(flagname)/sizeof(char *); f++)
if (flags & (int)1 << f) {
printf("%s%s", first ? " " : "|", flagname[f]);
first = 0;
}
printf("\n");
}
/*
* print a crontab entry
*/
void printentry(char *indent, entry *e, time_t next) {
printf("%s - user: %s\n", indent, e->pwd->pw_name);
printf("%s cmd: \"%s\"\n", indent, e->cmd);
printf("%s flags: 0x%02X\n", indent, e->flags);
printflags(indent, e->flags);
printf("%s delay: %d\n", indent, e->delay);
printf("%s next: %ld\n", indent, (long)next);
printf("%s nextstring: ", indent);
printf("%s", asctime(localtime(&next)));
}
/*
* print a crontab data
*/
void printcrontab(user *u) {
printf(" - user: \"%s\"\n", u->name);
printf(" crontab: %s\n", u->tabname);
printf(" system: %d\n", u->system);
printf(" entries:\n");
}
/*
* basic algorithm: iterate over time from now to 8 year ahead in default steps
* of 1 minute, checking whether time matches a crontab entry at each step (8
* years is the largest interval between two crontab matches)
*
* to save iterations, use larger steps if month or day don't match the entry:
* - if the month doesn't match, skip to 00:00 of the first day of next month
* - for the day, avoid the complication of the different length of months: if
* neither the day nor the next day match, increase time of one day
*/
/*
* check whether time matches day of month and/or day of week; this requires
* checking dom if dow=*, dow if dom=*, either one otherwise; see comment "the
* dom/dow situation is odd..." in cron.c
*/
int matchday(entry *e, time_t time) {
struct tm current;
localtime_r(&time, &current);
if (e->flags & DOW_STAR)
return bit_test(e->dom, current.tm_mday - 1);
if (e->flags & DOM_STAR)
return bit_test(e->dow, current.tm_wday);
return bit_test(e->dom, current.tm_mday - 1) ||
bit_test(e->dow, current.tm_wday);
}
/*
* next time matching a crontab entry
*/
time_t nextmatch(entry *e, time_t start, time_t end) {
time_t time;
struct tm current;
for (time = start; time <= end; ) {
localtime_r(&time, &current);
/* month doesn't match: move to 1st of next month */
if (!bit_test(e->month, current.tm_mon)) {
current.tm_mon++;
if (current.tm_mon >= 12) {
current.tm_year++;
current.tm_mon = 0;
}
current.tm_mday = 1;
current.tm_hour = 0;
current.tm_min = 0;
time = mktime(&current);
continue;
}
/* neither time nor time+1day match day: increase 1 day */
if (!matchday(e, time) && !matchday(e, time + 24 * 60 * 60)) {
time += 24 * 60 * 60;
continue;
}
/* if time matches, return time;
* check for month is redudant, but check for day is
* necessary because we only know that either time
* or time+1day match */
if (bit_test(e->month, current.tm_mon) &&
matchday(e, time) &&
bit_test(e->hour, current.tm_hour) &&
bit_test(e->minute, current.tm_min)
)
return time;
/* skip to next minute */
time += 60;
}
return -1;
}
/*
* match a user against a list
*/
int matchuser(char *user, char *list) {
char *pos;
size_t l = strlen(user);
for (pos = list; (pos = strstr(pos, user)) != NULL; pos += l) {
if ((pos != list) && (*(pos - 1) != ','))
continue;
if ((pos[l] != '\0') && (pos[l] != ','))
continue;
return 1;
}
return 0;
}
/*
* find next sheduled job
*/
time_t cronnext(cron_db database,
time_t start, time_t end,
char *include, char *exclude, int flags) {
time_t closest, next;
user *u;
entry *e;
char *indent = "";
if (flags & CRONTABS) {
printf("crontabs:\n");
indent = " ";
}
else if (flags & ALLJOBS)
printf("jobs:\n");
/* find next sheduled time */
closest = -1;
for (u = database.head; u; u = u->next) {
if (include && !matchuser(u->name, include))
continue;
if (exclude && matchuser(u->name, exclude))
continue;
if (!(flags & SYSTEM) && u->system)
continue;
if (flags & CRONTABS)
printcrontab(u);
for (e = u->crontab; e; e = e->next)
for (next = nextmatch(e, start, end);
next <= end;
next = nextmatch(e, next + 60, end)) {
if (next < 0)
break;
if (closest < 0 || next < closest)
closest = next;
if (flags & ENTRIES)
printentry(indent, e, next);
if (! (flags & ALLJOBS))
break;
}
}
return closest;
}
/*
* load installed crontabs and/or crontab files
*/
cron_db database(int installed, char **additional) {
cron_db db = {NULL, NULL, (time_t) 0};
struct passwd pw;
int fd;
user *u;
if (installed)
load_database(&db);
for ( ; *additional != NULL; additional++) {
fd = open(*additional, O_RDONLY);
if (fd == -1) {
perror(*additional);
continue;
}
memset(&pw, 0, sizeof(pw));
pw.pw_name = *additional;
pw.pw_passwd = "";
pw.pw_dir = ".";
u = load_user(fd, &pw, *additional, *additional, *additional);
if (u == NULL) {
printf("cannot load crontab %s\n", *additional);
continue;
}
link_user(&db, u);
}
return db;
}
void usage() {
fprintf(stderr, "Find the time of the next scheduled cron job.\n");
fprintf(stderr, "Usage:\n");
fprintf(stderr, " cronnext [options] [file ...]\n");
fprintf(stderr, "\n");
fprintf(stderr, "Options:\n");
fprintf(stderr, " -i users include only the crontab of these users\n");
fprintf(stderr, " -e users exclude the crontab of these users\n");
fprintf(stderr, " -s do not include the system crontab\n");
fprintf(stderr, " -a examine installed crontabs even if files are given\n");
fprintf(stderr, " -t time start from this time (seconds since epoch)\n");
fprintf(stderr, " -q time end check at this time (seconds since epoch)\n");
fprintf(stderr, " -l print next jobs to be executed\n");
fprintf(stderr, " -c print next execution of each job\n");
fprintf(stderr, " -f print all jobs executed in the given interval\n");
fprintf(stderr, " -h this help\n");
fprintf(stderr, " -V print version and exit\n");
}
/*
* main
*/
int main(int argn, char *argv[]) {
int opt;
char *include, *exclude;
int flags;
time_t start, next, end = 0;
int endtime, printjobs;
cron_db db;
int installed = 0;
include = NULL;
exclude = NULL;
flags = SYSTEM;
endtime = 0;
printjobs = 0;
start = time(NULL) / 60 * 60;
while (-1 != (opt = getopt(argn, argv, "i:e:ast:q:lcfhV"))) {
switch (opt) {
case 'i':
include = optarg;
break;
case 'e':
exclude = optarg;
break;
case 'a':
installed = 1;
break;
case 's':
flags &= ~SYSTEM;
break;
case 't':
start = atoi(optarg) / 60 * 60;
break;
case 'q':
end = atoi(optarg) / 60 * 60;
endtime = 1;
break;
case 'l':
printjobs = 1;
break;
case 'c':
flags |= ENTRIES | CRONTABS;
break;
case 'f':
flags |= ALLJOBS | ENTRIES;
break;
case 'h':
usage();
return EXIT_SUCCESS;
case 'V':
puts(PACKAGE_STRING);
return EXIT_SUCCESS;
default:
fprintf(stderr, "unrecognized option: %s\n",
argv[optind - 1]);
usage();
exit(EXIT_FAILURE);
}
}
if (flags & ALLJOBS && !endtime) {
fprintf(stderr, "no ending time specified: -f requires -q\n");
usage();
exit(EXIT_FAILURE);
}
/* maximum match interval is 8 years:
* crontab has '* * 29 2 *' and we are on 1 March 2096:
* next matching time will be 29 February 2104 */
if (!endtime)
end = start + 8 * 12 * 31 * 24 * 60 * 60;
/* debug cron */
if (flags & CRONTABS) {
printf("spool: %s\n", SPOOL_DIR);
set_debug_flags("");
}
/* "load,pars" for debugging loading and parsing, "" for nothing
see globals.h for symbolic names and macros.h for meaning */
/* load database */
db = database(installed || argv[optind] == NULL, argv + optind);
/* find time of next scheduled command */
next = cronnext(db, start, end, include, exclude, flags);
/* print time */
if (next == -1)
return EXIT_FAILURE;
else
printf("next: %ld\n", (long) next);
/* print next jobs */
if (printjobs) {
printf("nextjobs:\n");
cronnext(db, next, next, include, exclude, (flags & SYSTEM) | ENTRIES);
}
return EXIT_SUCCESS;
}

View File

@ -29,35 +29,63 @@
* to add clustering support. * to add clustering support.
*/ */
#include "config.h"
#define MAIN_PROGRAM #define MAIN_PROGRAM
#include <cron.h> #include <errno.h>
#include <locale.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <utime.h>
#ifdef WITH_PAM
# include <security/pam_appl.h>
#endif
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
# include <selinux/selinux.h> # include <selinux/selinux.h>
# include <selinux/context.h> # include <selinux/context.h>
# include <selinux/av_permissions.h>
#endif #endif
#include "cronie_common.h"
#include "bitstring.h"
#include "externs.h"
#include "funcs.h"
#include "globals.h"
#include "macros.h"
#include "pathnames.h"
#include "structs.h"
#define NHEADER_LINES 0 #define NHEADER_LINES 0
enum opt_t {opt_unknown, opt_list, opt_delete, opt_edit, opt_replace, opt_hostset, opt_hostget}; enum opt_t {opt_unknown, opt_list, opt_delete, opt_edit, opt_replace, opt_hostset, opt_hostget};
#if DEBUGGING #if DEBUGGING
static char *Options[] = {"???", "list", "delete", "edit", "replace", "hostset", "hostget"}; static const char *Options[] = {"???", "list", "delete", "edit", "replace", "hostset", "hostget"};
# ifdef WITH_SELINUX # ifdef WITH_SELINUX
static char *getoptargs = "u:lerisncx:"; static const char *getoptargs = "u:lerisncx:V";
# else # else
static char *getoptargs = "u:lerincx:"; static const char *getoptargs = "u:lerincx:V";
# endif # endif
#else #else
# ifdef WITH_SELINUX # ifdef WITH_SELINUX
static char *getoptargs = "u:lerisnc"; static const char *getoptargs = "u:lerisncV";
# else # else
static char *getoptargs = "u:lerinc"; static const char *getoptargs = "u:lerincV";
# endif # endif
#endif #endif
#ifdef WITH_SELINUX
static char *selinux_context = 0; static char *selinux_context = 0;
#endif
static PID_T Pid; static PID_T Pid;
static char User[MAX_UNAME], RealUser[MAX_UNAME]; static char User[MAX_UNAME], RealUser[MAX_UNAME];
@ -73,35 +101,49 @@ static void list_cmd(void),
delete_cmd(void), delete_cmd(void),
edit_cmd(void), edit_cmd(void),
poke_daemon(void), poke_daemon(void),
check_error(const char *), parse_args(int c, char *v[]), die(int); check_error(const char *), parse_args(int c, char *v[]), die(int) ATTRIBUTE_NORETURN;
static int replace_cmd(void), hostset_cmd(void), hostget_cmd(void); static int replace_cmd(void), hostset_cmd(void), hostget_cmd(void);
static char *host_specific_filename(char *filename, int prefix); static char *host_specific_filename(const char *prefix, const char *suffix);
static char *tmp_path(void); static const char *tmp_path(void);
static void usage(const char *msg) ATTRIBUTE_NORETURN;
static void usage(const char *msg) { static void usage(const char *msg) {
fprintf(stderr, "%s: usage error: %s\n", ProgramName, msg); fprintf(stderr, "%s: usage error: %s\n", ProgramName, msg);
fprintf(stderr, "usage:\t%s [-u user] file\n", ProgramName); fprintf(stderr, "Usage:\n");
fprintf(stderr, "\t%s [-u user] [ -e | -l | -r ]\n", ProgramName); fprintf(stderr, " %s [options] file\n", ProgramName);
fprintf(stderr, "\t%s -n [ hostname ]\n", ProgramName); fprintf(stderr, " %s [options]\n", ProgramName);
fprintf(stderr, "\t%s -c\n", ProgramName); fprintf(stderr, " %s -n [hostname]\n", ProgramName);
fprintf(stderr, "\t\t(default operation is replace, per 1003.2)\n"); fprintf(stderr, "\n");
fprintf(stderr, "\t-e\t(edit user's crontab)\n"); fprintf(stderr, "Options:\n");
fprintf(stderr, "\t-l\t(list user's crontab)\n"); fprintf(stderr, " -u <user> define user\n");
fprintf(stderr, "\t-r\t(delete user's crontab)\n"); fprintf(stderr, " -e edit user's crontab\n");
fprintf(stderr, "\t-i\t(prompt before deleting user's crontab)\n"); fprintf(stderr, " -l list user's crontab\n");
fprintf(stderr, "\t-n\t(set host in cluster to run users' crontabs)\n"); fprintf(stderr, " -r delete user's crontab\n");
fprintf(stderr, "\t-c\t(get host in cluster to run users' crontabs)\n"); fprintf(stderr, " -i prompt before deleting\n");
fprintf(stderr, " -n <host> set host in cluster to run users' crontabs\n");
fprintf(stderr, " -c get host in cluster to run users' crontabs\n");
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
fprintf(stderr, "\t-s\t(selinux context)\n"); fprintf(stderr, " -s selinux context\n");
#endif #endif
fprintf(stderr, " -V print version and exit\n");
#ifdef DEBUGGING
fprintf(stderr, " -x <mask> enable debugging\n");
#endif
fprintf(stderr, "\nDefault operation is replace, per 1003.2\n");
exit(ERROR_EXIT); exit(ERROR_EXIT);
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
int exitstatus; int exitstatus;
Pid = getpid(); if ((ProgramName=strrchr(argv[0], '/')) == NULL) {
ProgramName = argv[0]; ProgramName = argv[0];
}
else {
++ProgramName;
}
Pid = getpid();
MailCmd[0] = '\0'; MailCmd[0] = '\0';
cron_default_mail_charset[0] = '\0'; cron_default_mail_charset[0] = '\0';
@ -110,11 +152,6 @@ int main(int argc, char *argv[]) {
#if defined(BSD) #if defined(BSD)
setlinebuf(stderr); setlinebuf(stderr);
#endif #endif
char *n = "-"; /*set the n string to - so we have a valid string to use */
/*should we desire to make changes to behavior later. */
if (argv[1] == NULL) { /* change behavior to allow crontab to take stdin with no '-' */
argv[1] = n;
}
parse_args(argc, argv); /* sets many globals, opens a file */ parse_args(argc, argv); /* sets many globals, opens a file */
check_spool_dir(); check_spool_dir();
if (!allowed(RealUser, CRON_ALLOW, CRON_DENY)) { if (!allowed(RealUser, CRON_ALLOW, CRON_DENY)) {
@ -127,7 +164,7 @@ int main(int argc, char *argv[]) {
} }
#if defined(WITH_PAM) #if defined(WITH_PAM)
if (cron_start_pam(pw) != PAM_SUCCESS) { if (getuid() != 0 && cron_start_pam(pw) != PAM_SUCCESS) {
fprintf(stderr, fprintf(stderr,
"You (%s) are not allowed to access to (%s) because of pam configuration.\n", "You (%s) are not allowed to access to (%s) because of pam configuration.\n",
User, ProgramName); User, ProgramName);
@ -164,7 +201,9 @@ int main(int argc, char *argv[]) {
default: default:
abort(); abort();
} }
#ifdef WITH_PAM
cron_close_pam(); cron_close_pam();
#endif
exit(exitstatus); exit(exitstatus);
/*NOTREACHED*/} /*NOTREACHED*/}
@ -200,13 +239,13 @@ static void parse_args(int argc, char *argv[]) {
fprintf(stderr, "must be privileged to use -u\n"); fprintf(stderr, "must be privileged to use -u\n");
exit(ERROR_EXIT); exit(ERROR_EXIT);
} }
#ifdef WITH_SELINUX
if (crontab_security_access() != 0) { if (crontab_security_access() != 0) {
fprintf(stderr, fprintf(stderr,
"Access denied by SELinux, must be privileged to use -u\n"); "Access denied by SELinux, must be privileged to use -u\n");
exit(ERROR_EXIT); exit(ERROR_EXIT);
} }
#endif
if (Option == opt_hostset || Option == opt_hostget) { if (Option == opt_hostset || Option == opt_hostget) {
fprintf(stderr, fprintf(stderr,
"cannot use -u with -n or -c\n"); "cannot use -u with -n or -c\n");
@ -273,6 +312,9 @@ static void parse_args(int argc, char *argv[]) {
} }
Option = opt_hostget; Option = opt_hostget;
break; break;
case 'V':
puts(PACKAGE_STRING);
exit(EXIT_SUCCESS);
default: default:
usage("unrecognized option"); usage("unrecognized option");
} }
@ -300,7 +342,7 @@ static void parse_args(int argc, char *argv[]) {
(void) strcpy(Filename, argv[optind]); (void) strcpy(Filename, argv[optind]);
} }
else else
usage("file name must be specified for replace"); usage("file name or - (for stdin) must be specified for replace");
} }
if (Option == opt_replace) { if (Option == opt_replace) {
@ -314,6 +356,7 @@ static void parse_args(int argc, char *argv[]) {
* Arnt Gulbrandsen <agulbra@pvv.unit.no> for spotting * Arnt Gulbrandsen <agulbra@pvv.unit.no> for spotting
* the race. * the race.
*/ */
struct stat sb;
if (swap_uids() < OK) { if (swap_uids() < OK) {
perror("swapping uids"); perror("swapping uids");
@ -323,6 +366,17 @@ static void parse_args(int argc, char *argv[]) {
perror(Filename); perror(Filename);
exit(ERROR_EXIT); exit(ERROR_EXIT);
} }
if (fstat(fileno(NewCrontab), &sb) < 0) {
perror(Filename);
exit(ERROR_EXIT);
}
if ((sb.st_mode & S_IFMT) == S_IFDIR) {
fprintf(stderr,
"cannot replace crontab with a directory: %s\n",
Filename);
fclose(NewCrontab);
exit(ERROR_EXIT);
}
if (swap_uids_back() < OK) { if (swap_uids_back() < OK) {
perror("swapping uids back"); perror("swapping uids back");
exit(ERROR_EXIT); exit(ERROR_EXIT);
@ -331,7 +385,7 @@ static void parse_args(int argc, char *argv[]) {
} }
Debug(DMISC, ("user=%s, file=%s, option=%s\n", Debug(DMISC, ("user=%s, file=%s, option=%s\n",
User, Filename, Options[(int) Option])) User, Filename, Options[(int) Option]));
} }
static void list_cmd(void) { static void list_cmd(void) {
@ -391,8 +445,8 @@ static void check_error(const char *msg) {
fprintf(stderr, "\"%s\":%d: %s\n", Filename, LineNumber - 1, msg); fprintf(stderr, "\"%s\":%d: %s\n", Filename, LineNumber - 1, msg);
} }
static char *tmp_path() { static const char *tmp_path(void) {
char *tmpdir = NULL; const char *tmpdir = NULL;
if ((getuid() == geteuid()) && (getgid() == getegid())) { if ((getuid() == geteuid()) && (getgid() == getegid())) {
tmpdir = getenv("TMPDIR"); tmpdir = getenv("TMPDIR");
@ -400,26 +454,27 @@ static char *tmp_path() {
return tmpdir ? tmpdir : "/tmp"; return tmpdir ? tmpdir : "/tmp";
} }
static char *host_specific_filename(char *filename, int prefix) static char *host_specific_filename(const char *prefix, const char *suffix)
{ {
/* /*
* For cluster-wide use, where there is otherwise risk of the same * For cluster-wide use, where there is otherwise risk of the same
* name being generated on more than one host at once, prefix with * name being generated on more than one host at once, insert hostname
* "hostname." or suffix with ".hostname" as requested, and return * separated with dots, and return static buffer or NULL on failure.
* static buffer or NULL on failure.
*/ */
static char safename[MAX_FNAME]; static char safename[MAX_FNAME];
char hostname[MAXHOSTNAMELEN]; char hostname[MAX_FNAME];
if (gethostname(hostname, sizeof hostname) != 0) if (gethostname(hostname, sizeof hostname) != 0)
return NULL; return NULL;
if (prefix) { if (prefix) {
if (!glue_strings(safename, sizeof safename, hostname, filename, '.')) if (!glue_strings(safename, sizeof safename, prefix, hostname, '.'))
return NULL; return NULL;
} else { strcpy(hostname, safename);
if (!glue_strings(safename, sizeof safename, filename, hostname, '.')) }
if (suffix) {
if (!glue_strings(safename, sizeof safename, hostname, suffix, '.'))
return NULL; return NULL;
} }
@ -427,7 +482,8 @@ static char *host_specific_filename(char *filename, int prefix)
} }
static void edit_cmd(void) { static void edit_cmd(void) {
char n[MAX_FNAME], q[MAX_TEMPSTR], *editor; char n[MAX_FNAME], q[MAX_TEMPSTR];
const char *editor;
FILE *f; FILE *f;
int ch = '\0', t; int ch = '\0', t;
struct stat statbuf; struct stat statbuf;
@ -697,9 +753,10 @@ static int replace_cmd(void) {
uid_t file_owner; uid_t file_owner;
char **envp; char **envp;
char *safename; char *safename;
int envs = 0, entries = 0;
safename = host_specific_filename("tmp.XXXXXXXXXX", 1); safename = host_specific_filename("#tmp", "XXXXXXXXXX");
if (!safename || !glue_strings(TempFilename, sizeof TempFilename, SPOOL_DIR, if (!safename || !glue_strings(TempFilename, sizeof TempFilename, SPOOL_DIR,
safename, '/')) { safename, '/')) {
TempFilename[0] = '\0'; TempFilename[0] = '\0';
@ -776,6 +833,10 @@ static int replace_cmd(void) {
} }
while (!CheckErrorCount && !eof) { while (!CheckErrorCount && !eof) {
if (!skip_comments(tmp)) {
check_error("too many garbage characters");
break;
}
switch (load_env(envstr, tmp)) { switch (load_env(envstr, tmp)) {
case ERR: case ERR:
/* check for data before the EOF */ /* check for data before the EOF */
@ -787,14 +848,30 @@ static int replace_cmd(void) {
break; break;
case FALSE: case FALSE:
e = load_entry(tmp, check_error, pw, envp); e = load_entry(tmp, check_error, pw, envp);
if (e) if (e) {
++entries;
free_entry(e); free_entry(e);
}
break; break;
case TRUE: case TRUE:
++envs;
break; break;
} }
} }
env_free(envp); env_free(envp);
if (envs > MAX_USER_ENVS) {
fprintf(stderr, "More than %d environment variables in crontab file, can't install.\n", MAX_USER_ENVS);
fclose(tmp);
error = -1;
goto done;
}
if (entries > MAX_USER_ENTRIES) {
fprintf(stderr, "More than %d entries in crontab file, can't install.\n", MAX_USER_ENTRIES);
fclose(tmp);
error = -1;
goto done;
}
if (CheckErrorCount != 0) { if (CheckErrorCount != 0) {
fprintf(stderr, "errors in crontab file, can't install.\n"); fprintf(stderr, "errors in crontab file, can't install.\n");
@ -803,17 +880,17 @@ static int replace_cmd(void) {
goto done; goto done;
} }
file_owner = (getgid() == getegid())? ROOT_UID : pw->pw_uid; file_owner = (getgid() == geteuid() && getgid() == getegid()) ? ROOT_UID : pw->pw_uid;
#ifdef HAVE_FCHOWN #ifdef HAVE_FCHOWN
if (fchown(fileno(tmp), file_owner, -1) < OK) { if (fchown(fileno(tmp), file_owner, (gid_t)-1) < OK) {
perror("fchown"); perror("fchown");
fclose(tmp); fclose(tmp);
error = -2; error = -2;
goto done; goto done;
} }
#else #else
if (chown(TempFilename, file_owner, -1) < OK) { if (chown(TempFilename, file_owner, (gid_t)-1) < OK) {
perror("chown"); perror("chown");
fclose(tmp); fclose(tmp);
error = -2; error = -2;
@ -865,7 +942,7 @@ static int hostset_cmd(void) {
if (!HostSpecified) if (!HostSpecified)
gethostname(Host, sizeof Host); gethostname(Host, sizeof Host);
safename = host_specific_filename("tmp.XXXXXXXXXX", 1); safename = host_specific_filename("#tmp", "XXXXXXXXXX");
if (!safename || !glue_strings(TempFilename, sizeof TempFilename, SPOOL_DIR, if (!safename || !glue_strings(TempFilename, sizeof TempFilename, SPOOL_DIR,
safename, '/')) { safename, '/')) {
TempFilename[0] = '\0'; TempFilename[0] = '\0';

View File

@ -27,9 +27,29 @@
* to add clustering support. * to add clustering support.
*/ */
#include <cron.h> #include "config.h"
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#ifdef WITH_INOTIFY
# include <sys/inotify.h>
#endif
#include "funcs.h"
#include "globals.h"
#include "pathnames.h"
#define TMAX(a,b) ((a)>(b)?(a):(b)) #define TMAX(a,b) ((a)>(b)?(a):(b))
#define TMIN(a,b) ((a)<(b)?(a):(b))
/* size of the event structure, not counting name */ /* size of the event structure, not counting name */
#define EVENT_SIZE (sizeof (struct inotify_event)) #define EVENT_SIZE (sizeof (struct inotify_event))
@ -45,11 +65,11 @@ static void process_crontab(const char *, const char *,
static int not_a_crontab(DIR_T * dp); static int not_a_crontab(DIR_T * dp);
/* return 1 if we should skip this file */ /* return 1 if we should skip this file */
static void max_mtime(char *dir_name, struct stat *max_st); static void max_mtime(const char *dir_name, struct stat *max_st);
/* record max mtime of any file under dir_name in max_st */ /* record max mtime of any file under dir_name in max_st */
static int static int
check_open(const char *tabname, const char *fname, const char *uname, check_open(const char *tabname, const char *uname,
struct passwd *pw, time_t * mtime) { struct passwd *pw, time_t * mtime) {
struct stat statbuf; struct stat statbuf;
int crontab_fd; int crontab_fd;
@ -134,10 +154,41 @@ check_orphans(cron_db *db) {
} }
} }
static int
find_orphan(const char *uname, const char *fname, const char *tabname) {
orphan *o;
for (o = orphans; o != NULL; o = o->next) {
if (uname && o->uname) {
if (strcmp(uname, o->uname) != 0)
continue;
} else if (uname != o->uname)
continue;
if (fname && o->fname) {
if (strcmp(fname, o->fname) != 0)
continue;
} else if (fname != o->fname)
continue;
if (tabname && o->tabname) {
if (strcmp(tabname, o->tabname) != 0)
continue;
} else if (tabname != o->tabname)
continue;
return 1;
}
return 0;
}
static void static void
add_orphan(const char *uname, const char *fname, const char *tabname) { add_orphan(const char *uname, const char *fname, const char *tabname) {
orphan *o; orphan *o;
if (find_orphan(uname, fname, tabname))
return;
o = calloc(1, sizeof(*o)); o = calloc(1, sizeof(*o));
if (o == NULL) if (o == NULL)
return; return;
@ -185,10 +236,12 @@ process_crontab(const char *uname, const char *fname, const char *tabname,
goto next_crontab; goto next_crontab;
} }
if ((crontab_fd = check_open(tabname, fname, uname, pw, &mtime)) == -1) if ((crontab_fd = check_open(tabname, uname, pw, &mtime)) == -1)
goto next_crontab; goto next_crontab;
Debug(DLOAD, ("\t%s:", fname)) mtime = TMIN(new_db->mtime, mtime);
Debug(DLOAD, ("\t%s:", fname));
if (old_db != NULL) if (old_db != NULL)
u = find_user(old_db, fname, crond_crontab ? tabname : NULL); /* find user in old_db */ u = find_user(old_db, fname, crond_crontab ? tabname : NULL); /* find user in old_db */
@ -198,7 +251,7 @@ process_crontab(const char *uname, const char *fname, const char *tabname,
* in, then we can just use our existing entry. * in, then we can just use our existing entry.
*/ */
if (u->mtime == mtime) { if (u->mtime == mtime) {
Debug(DLOAD, (" [no change, using old data]")) Debug(DLOAD, (" [no change, using old data]"));
unlink_user(old_db, u); unlink_user(old_db, u);
link_user(new_db, u); link_user(new_db, u);
goto next_crontab; goto next_crontab;
@ -211,7 +264,7 @@ process_crontab(const char *uname, const char *fname, const char *tabname,
* users will be deleted from the old database when * users will be deleted from the old database when
* we finish with the crontab... * we finish with the crontab...
*/ */
Debug(DLOAD, (" [delete old data]")) Debug(DLOAD, (" [delete old data]"));
unlink_user(old_db, u); unlink_user(old_db, u);
free_user(u); free_user(u);
log_it(fname, getpid(), "RELOAD", tabname, 0); log_it(fname, getpid(), "RELOAD", tabname, 0);
@ -226,7 +279,7 @@ process_crontab(const char *uname, const char *fname, const char *tabname,
next_crontab: next_crontab:
if (crontab_fd != -1) { if (crontab_fd != -1) {
Debug(DLOAD, (" [done]\n")) Debug(DLOAD, (" [done]\n"));
close(crontab_fd); close(crontab_fd);
} }
} }
@ -234,7 +287,7 @@ process_crontab(const char *uname, const char *fname, const char *tabname,
static int static int
cluster_host_is_local(void) cluster_host_is_local(void)
{ {
char filename[MAXNAMLEN+1]; char filename[NAME_MAX+1];
int is_local; int is_local;
FILE *f; FILE *f;
char hostname[MAXHOSTNAMELEN], myhostname[MAXHOSTNAMELEN]; char hostname[MAXHOSTNAMELEN], myhostname[MAXHOSTNAMELEN];
@ -279,18 +332,18 @@ void check_inotify_database(cron_db * old_db) {
cron_db new_db; cron_db new_db;
DIR_T *dp; DIR_T *dp;
DIR *dir; DIR *dir;
struct timeval time; struct timeval tv;
fd_set rfds; fd_set rfds;
int retval = 0; int retval;
char buf[BUF_LEN]; char buf[BUF_LEN];
pid_t pid = getpid(); pid_t pid = getpid();
time.tv_sec = 0; tv.tv_sec = 0;
time.tv_usec = 0; tv.tv_usec = 0;
FD_ZERO(&rfds); FD_ZERO(&rfds);
FD_SET(old_db->ifd, &rfds); FD_SET(old_db->ifd, &rfds);
retval = select(old_db->ifd + 1, &rfds, NULL, NULL, &time); retval = select(old_db->ifd + 1, &rfds, NULL, NULL, &tv);
if (retval == -1) { if (retval == -1) {
if (errno != EINTR) if (errno != EINTR)
log_it("CRON", pid, "INOTIFY", "select failed", errno); log_it("CRON", pid, "INOTIFY", "select failed", errno);
@ -299,7 +352,8 @@ void check_inotify_database(cron_db * old_db) {
else if (FD_ISSET(old_db->ifd, &rfds)) { else if (FD_ISSET(old_db->ifd, &rfds)) {
new_db.head = new_db.tail = NULL; new_db.head = new_db.tail = NULL;
new_db.ifd = old_db->ifd; new_db.ifd = old_db->ifd;
while ((retval = read(old_db->ifd, buf, sizeof (buf))) == -1 && new_db.mtime = time(NULL) - 1;
while ((retval = (int)read(old_db->ifd, buf, sizeof (buf))) == -1 &&
errno == EINTR) ; errno == EINTR) ;
if (retval == 0) { if (retval == 0) {
@ -309,7 +363,7 @@ void check_inotify_database(cron_db * old_db) {
if (retval <= 0) { if (retval <= 0) {
log_it("CRON", pid, "INOTIFY", "read failed", errno); log_it("CRON", pid, "INOTIFY", "read failed", errno);
/* something fatal must have occured we have no other reasonable /* something fatal must have occurred we have no other reasonable
* way how to handle this failure than exit. * way how to handle this failure than exit.
*/ */
(void) exit(ERROR_EXIT); (void) exit(ERROR_EXIT);
@ -321,15 +375,16 @@ void check_inotify_database(cron_db * old_db) {
set_cron_watched(old_db->ifd); set_cron_watched(old_db->ifd);
/* TODO: parse the events and read only affected files */ /* TODO: parse the events and read only affected files */
#if defined ENABLE_SYSCRONTAB
process_crontab("root", NULL, SYSCRONTAB, &new_db, old_db); process_crontab("root", NULL, SYSCRONTAB, &new_db, old_db);
#endif
if (!(dir = opendir(SYS_CROND_DIR))) { if (!(dir = opendir(SYS_CROND_DIR))) {
log_it("CRON", pid, "OPENDIR FAILED", SYS_CROND_DIR, errno); log_it("CRON", pid, "OPENDIR FAILED", SYS_CROND_DIR, errno);
} }
else { else {
while (NULL != (dp = readdir(dir))) { while (NULL != (dp = readdir(dir))) {
char tabname[MAXNAMLEN + 1]; char tabname[NAME_MAX + 1];
if (not_a_crontab(dp)) if (not_a_crontab(dp))
continue; continue;
@ -347,12 +402,12 @@ void check_inotify_database(cron_db * old_db) {
} }
else { else {
while (NULL != (dp = readdir(dir))) { while (NULL != (dp = readdir(dir))) {
char fname[MAXNAMLEN + 1], tabname[MAXNAMLEN + 1]; char fname[NAME_MAX + 1], tabname[NAME_MAX + 1];
if (not_a_crontab(dp)) if (not_a_crontab(dp))
continue; continue;
strncpy(fname, dp->d_name, MAXNAMLEN); strncpy(fname, dp->d_name, NAME_MAX + 1);
if (!glue_strings(tabname, sizeof tabname, SPOOL_DIR, if (!glue_strings(tabname, sizeof tabname, SPOOL_DIR,
dp->d_name, '/')) dp->d_name, '/'))
@ -374,7 +429,7 @@ void check_inotify_database(cron_db * old_db) {
} }
overwrite_database(old_db, &new_db); overwrite_database(old_db, &new_db);
Debug(DLOAD, ("check_inotify_database is done\n")) Debug(DLOAD, ("check_inotify_database is done\n"));
} }
#endif #endif
@ -382,9 +437,9 @@ static void overwrite_database(cron_db * old_db, cron_db * new_db) {
user *u, *nu; user *u, *nu;
/* whatever's left in the old database is now junk. /* whatever's left in the old database is now junk.
*/ */
Debug(DLOAD, ("unlinking old database:\n")) Debug(DLOAD, ("unlinking old database:\n"));
for (u = old_db->head; u != NULL; u = nu) { for (u = old_db->head; u != NULL; u = nu) {
Debug(DLOAD, ("\t%s\n", u->name)) Debug(DLOAD, ("\t%s\n", u->name));
nu = u->next; nu = u->next;
unlink_user(old_db, u); unlink_user(old_db, u);
free_user(u); free_user(u);
@ -402,8 +457,11 @@ int load_database(cron_db * old_db) {
DIR *dir; DIR *dir;
pid_t pid = getpid(); pid_t pid = getpid();
int is_local = 0; int is_local = 0;
time_t now;
Debug(DLOAD, ("[%ld] load_database()\n", (long) pid)) Debug(DLOAD, ("[%ld] load_database()\n", (long) pid));
now = time(NULL);
/* before we start loading any data, do a stat on SPOOL_DIR /* before we start loading any data, do a stat on SPOOL_DIR
* so that if anything changes as of this moment (i.e., before we've * so that if anything changes as of this moment (i.e., before we've
@ -429,10 +487,12 @@ int load_database(cron_db * old_db) {
max_mtime(SYS_CROND_DIR, &crond_stat); max_mtime(SYS_CROND_DIR, &crond_stat);
} }
#if defined ENABLE_SYSCRONTAB
/* track system crontab file /* track system crontab file
*/ */
if (stat(SYSCRONTAB, &syscron_stat) < OK) if (stat(SYSCRONTAB, &syscron_stat) < OK)
syscron_stat.st_mtime = 0; syscron_stat.st_mtime = 0;
#endif
/* if spooldir's mtime has not changed, we don't need to fiddle with /* if spooldir's mtime has not changed, we don't need to fiddle with
* the database. * the database.
@ -440,12 +500,16 @@ int load_database(cron_db * old_db) {
* Note that old_db->mtime is initialized to 0 in main(), and * Note that old_db->mtime is initialized to 0 in main(), and
* so is guaranteed to be different than the stat() mtime the first * so is guaranteed to be different than the stat() mtime the first
* time this function is called. * time this function is called.
*
* We also use now - 1 as the upper bound of timestamp to avoid race,
* when a crontab is updated twice in a single second when we are
* just reading it.
*/ */
if (old_db->mtime == TMAX(crond_stat.st_mtime, if (old_db->mtime == TMIN(now - 1, TMAX(crond_stat.st_mtime,
TMAX(statbuf.st_mtime, syscron_stat.st_mtime)) TMAX(statbuf.st_mtime, syscron_stat.st_mtime)))
) { ) {
Debug(DLOAD, ("[%ld] spool dir mtime unch, no load needed.\n", Debug(DLOAD, ("[%ld] spool dir mtime unch, no load needed.\n",
(long) pid)) (long) pid));
return 0; return 0;
} }
@ -454,22 +518,23 @@ int load_database(cron_db * old_db) {
* actually changed. Whatever is left in the old database when * actually changed. Whatever is left in the old database when
* we're done is chaff -- crontabs that disappeared. * we're done is chaff -- crontabs that disappeared.
*/ */
new_db.mtime = TMAX(crond_stat.st_mtime, new_db.mtime = now - 1;
TMAX(statbuf.st_mtime, syscron_stat.st_mtime));
new_db.head = new_db.tail = NULL; new_db.head = new_db.tail = NULL;
#if defined WITH_INOTIFY #if defined WITH_INOTIFY
new_db.ifd = old_db->ifd; new_db.ifd = old_db->ifd;
#endif #endif
#if defined ENABLE_SYSCRONTAB
if (syscron_stat.st_mtime) if (syscron_stat.st_mtime)
process_crontab("root", NULL, SYSCRONTAB, &new_db, old_db); process_crontab("root", NULL, SYSCRONTAB, &new_db, old_db);
#endif
if (!(dir = opendir(SYS_CROND_DIR))) { if (!(dir = opendir(SYS_CROND_DIR))) {
log_it("CRON", pid, "OPENDIR FAILED", SYS_CROND_DIR, errno); log_it("CRON", pid, "OPENDIR FAILED", SYS_CROND_DIR, errno);
} }
else { else {
while (NULL != (dp = readdir(dir))) { while (NULL != (dp = readdir(dir))) {
char tabname[MAXNAMLEN + 1]; char tabname[NAME_MAX + 1];
if (not_a_crontab(dp)) if (not_a_crontab(dp))
continue; continue;
@ -496,12 +561,12 @@ int load_database(cron_db * old_db) {
is_local = cluster_host_is_local(); is_local = cluster_host_is_local();
while (is_local && NULL != (dp = readdir(dir))) { while (is_local && NULL != (dp = readdir(dir))) {
char fname[MAXNAMLEN + 1], tabname[MAXNAMLEN + 1]; char fname[NAME_MAX + 1], tabname[NAME_MAX + 1];
if (not_a_crontab(dp)) if (not_a_crontab(dp))
continue; continue;
strncpy(fname, dp->d_name, MAXNAMLEN); strncpy(fname, dp->d_name, NAME_MAX + 1);
if (!glue_strings(tabname, sizeof tabname, SPOOL_DIR, fname, '/')) if (!glue_strings(tabname, sizeof tabname, SPOOL_DIR, fname, '/'))
continue; /* XXX log? */ continue; /* XXX log? */
@ -518,7 +583,7 @@ int load_database(cron_db * old_db) {
endpwent(); endpwent();
overwrite_database(old_db, &new_db); overwrite_database(old_db, &new_db);
Debug(DLOAD, ("load_database is done\n")) Debug(DLOAD, ("load_database is done\n"));
return 1; return 1;
} }
@ -558,7 +623,7 @@ user *find_user(cron_db * db, const char *name, const char *tabname) {
} }
static int not_a_crontab(DIR_T * dp) { static int not_a_crontab(DIR_T * dp) {
int len; size_t len;
/* avoid file names beginning with ".". this is good /* avoid file names beginning with ".". this is good
* because we would otherwise waste two guaranteed calls * because we would otherwise waste two guaranteed calls
@ -578,10 +643,10 @@ static int not_a_crontab(DIR_T * dp) {
len = strlen(dp->d_name); len = strlen(dp->d_name);
if (len >= MAXNAMLEN) if (len >= NAME_MAX || len == 0)
return (1); /* XXX log? */ return (1);
if ((len > 0) && (dp->d_name[len - 1] == '~')) if (dp->d_name[len - 1] == '~')
return (1); return (1);
if ((len > 8) && (strncmp(dp->d_name + len - 8, ".rpmsave", 8) == 0)) if ((len > 8) && (strncmp(dp->d_name + len - 8, ".rpmsave", 8) == 0))
@ -594,7 +659,7 @@ static int not_a_crontab(DIR_T * dp) {
return (0); return (0);
} }
static void max_mtime(char *dir_name, struct stat *max_st) { static void max_mtime(const char *dir_name, struct stat *max_st) {
DIR *dir; DIR *dir;
DIR_T *dp; DIR_T *dp;
struct stat st; struct stat st;
@ -605,7 +670,7 @@ static void max_mtime(char *dir_name, struct stat *max_st) {
} }
while (NULL != (dp = readdir(dir))) { while (NULL != (dp = readdir(dir))) {
char tabname[MAXNAMLEN + 1]; char tabname[NAME_MAX + 1];
if ( not_a_crontab ( dp ) && strcmp(dp->d_name, CRON_HOSTNAME) != 0) if ( not_a_crontab ( dp ) && strcmp(dp->d_name, CRON_HOSTNAME) != 0)
continue; continue;

View File

@ -19,9 +19,28 @@
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <cron.h> #include "config.h"
static int child_process(entry *, user *, char **); #include <ctype.h>
#include <errno.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#include "externs.h"
#include "funcs.h"
#include "globals.h"
#include "structs.h"
#ifndef isascii
# define isascii(c) ((unsigned)(c)<=0177)
#endif
static int child_process(entry *, char **);
static int safe_p(const char *, const char *); static int safe_p(const char *, const char *);
void do_command(entry * e, user * u) { void do_command(entry * e, user * u) {
@ -31,7 +50,7 @@ void do_command(entry * e, user * u) {
Debug(DPROC, ("[%ld] do_command(%s, (%s,%ld,%ld))\n", Debug(DPROC, ("[%ld] do_command(%s, (%s,%ld,%ld))\n",
(long) pid, e->cmd, u->name, (long) pid, e->cmd, u->name,
(long) e->pwd->pw_uid, (long) e->pwd->pw_gid)) (long) e->pwd->pw_uid, (long) e->pwd->pw_gid));
/* fork to become asynchronous -- parent process is done immediately, /* fork to become asynchronous -- parent process is done immediately,
* and continues to run the normal cron code, which means return to * and continues to run the normal cron code, which means return to
@ -52,20 +71,22 @@ void do_command(entry * e, user * u) {
if (cron_set_job_security_context(e, u, &jobenv) != 0) { if (cron_set_job_security_context(e, u, &jobenv) != 0) {
_exit(ERROR_EXIT); _exit(ERROR_EXIT);
} }
ev = child_process(e, u, jobenv); ev = child_process(e, jobenv);
#ifdef WITH_PAM
cron_close_pam(); cron_close_pam();
#endif
env_free(jobenv); env_free(jobenv);
Debug(DPROC, ("[%ld] child process done, exiting\n", (long) getpid())) Debug(DPROC, ("[%ld] child process done, exiting\n", (long) getpid()));
_exit(ev); _exit(ev);
break; break;
default: default:
/* parent process */ /* parent process */
break; break;
} }
Debug(DPROC, ("[%ld] main process returning to work\n", (long) pid)) Debug(DPROC, ("[%ld] main process returning to work\n", (long) pid));
} }
static int child_process(entry * e, user * u, char **jobenv) { static int child_process(entry * e, char **jobenv) {
int stdin_pipe[2], stdout_pipe[2]; int stdin_pipe[2], stdout_pipe[2];
char *input_data, *usernm, *mailto, *mailfrom; char *input_data, *usernm, *mailto, *mailfrom;
int children = 0; int children = 0;
@ -87,7 +108,7 @@ static int child_process(entry * e, user * u, char **jobenv) {
sigaction(SIGCHLD, &sa, NULL); sigaction(SIGCHLD, &sa, NULL);
Debug(DPROC, ("[%ld] child_process('%s')\n", (long) getpid(), e->cmd)) Debug(DPROC, ("[%ld] child_process('%s')\n", (long) getpid(), e->cmd));
#ifdef CAPITALIZE_FOR_PS #ifdef CAPITALIZE_FOR_PS
/* mark ourselves as different to PS command watchers by upshifting /* mark ourselves as different to PS command watchers by upshifting
* our program name. This has no effect on some kernels. * our program name. This has no effect on some kernels.
@ -96,7 +117,7 @@ static int child_process(entry * e, user * u, char **jobenv) {
char *pch; char *pch;
for (pch = ProgramName; *pch; pch++) for (pch = ProgramName; *pch; pch++)
*pch = MkUpper(*pch); *pch = (char)MkUpper(*pch);
} }
#endif /* CAPITALIZE_FOR_PS */ #endif /* CAPITALIZE_FOR_PS */
@ -135,10 +156,10 @@ static int child_process(entry * e, user * u, char **jobenv) {
for (input_data = p = e->cmd; for (input_data = p = e->cmd;
(ch = *input_data) != '\0'; input_data++, p++) { (ch = *input_data) != '\0'; input_data++, p++) {
if (p != input_data) if (p != input_data)
*p = ch; *p = (char)ch;
if (escaped) { if (escaped) {
if (ch == '%') if (ch == '%')
*--p = ch; *--p = (char)ch;
escaped = FALSE; escaped = FALSE;
continue; continue;
} }
@ -163,7 +184,7 @@ static int child_process(entry * e, user * u, char **jobenv) {
return ERROR_EXIT; return ERROR_EXIT;
/*NOTREACHED*/ /*NOTREACHED*/
case 0: case 0:
Debug(DPROC, ("[%ld] grandchild process fork()'ed\n", (long) getpid())) Debug(DPROC, ("[%ld] grandchild process fork()'ed\n", (long) getpid()));
/* write a log message. we've waited this long to do it /* write a log message. we've waited this long to do it
* because it was not until now that we knew the PID that * because it was not until now that we knew the PID that
@ -217,6 +238,12 @@ static int child_process(entry * e, user * u, char **jobenv) {
*/ */
{ {
char *shell = env_get("SHELL", jobenv); char *shell = env_get("SHELL", jobenv);
int fd, fdmax = getdtablesize();
/* close all unwanted open file descriptors */
for(fd = STDERR + 1; fd < fdmax; fd++) {
close(fd);
}
#if DEBUGGING #if DEBUGGING
if (DebugFlags & DTEST) { if (DebugFlags & DTEST) {
@ -243,7 +270,7 @@ static int child_process(entry * e, user * u, char **jobenv) {
* the user's command. * the user's command.
*/ */
Debug(DPROC, ("[%ld] child continues, closing pipes\n", (long) getpid())) Debug(DPROC, ("[%ld] child continues, closing pipes\n", (long) getpid()));
/* close the ends of the pipe that will only be referenced in the /* close the ends of the pipe that will only be referenced in the
* grandchild process... * grandchild process...
@ -269,7 +296,7 @@ static int child_process(entry * e, user * u, char **jobenv) {
int ch; int ch;
Debug(DPROC, ("[%ld] child2 sending data to grandchild\n", Debug(DPROC, ("[%ld] child2 sending data to grandchild\n",
(long) getpid())) (long) getpid()));
/* reset the SIGPIPE back to default so the child will terminate /* reset the SIGPIPE back to default so the child will terminate
* if it tries to write to a closed pipe * if it tries to write to a closed pipe
@ -315,7 +342,7 @@ static int child_process(entry * e, user * u, char **jobenv) {
fclose(out); fclose(out);
Debug(DPROC, ("[%ld] child2 done sending to grandchild\n", Debug(DPROC, ("[%ld] child2 done sending to grandchild\n",
(long) getpid())) (long) getpid()));
_exit(0); _exit(0);
} }
@ -334,7 +361,7 @@ static int child_process(entry * e, user * u, char **jobenv) {
*/ */
Debug(DPROC, ("[%ld] child reading output from grandchild\n", Debug(DPROC, ("[%ld] child reading output from grandchild\n",
(long) getpid())) (long) getpid()));
/*local */ { /*local */ {
FILE *in = fdopen(stdout_pipe[READ_PIPE], "r"); FILE *in = fdopen(stdout_pipe[READ_PIPE], "r");
@ -349,13 +376,13 @@ static int child_process(entry * e, user * u, char **jobenv) {
int bufidx = 0; int bufidx = 0;
if (SyslogOutput) { if (SyslogOutput) {
if (ch != '\n') if (ch != '\n')
logbuf[bufidx++] = ch; logbuf[bufidx++] = (char)ch;
} }
#endif #endif
Debug(DPROC | DEXT, Debug(DPROC | DEXT,
("[%ld] got data (%x:%c) from grandchild\n", ("[%ld] got data (%x:%c) from grandchild\n",
(long) getpid(), ch, ch)) (long) getpid(), ch, ch));
/* get name of recipient. this is MAILTO if set to a /* get name of recipient. this is MAILTO if set to a
* valid local username; USER otherwise. * valid local username; USER otherwise.
@ -389,9 +416,9 @@ static int child_process(entry * e, user * u, char **jobenv) {
/* Also skip it if MailCmd is set to "off" */ /* Also skip it if MailCmd is set to "off" */
if (mailto && safe_p(usernm, mailto) if (mailto && safe_p(usernm, mailto)
&& strncmp(MailCmd,"off",4)) { && strncmp(MailCmd,"off",3) && !SyslogOutput) {
char **env; char **env;
char mailcmd[MAX_COMMAND]; char mailcmd[MAX_COMMAND+1]; /* +1 for terminator */
char hostname[MAXHOSTNAMELEN]; char hostname[MAXHOSTNAMELEN];
char *content_type = env_get("CONTENT_TYPE", jobenv), char *content_type = env_get("CONTENT_TYPE", jobenv),
*content_transfer_encoding = *content_transfer_encoding =
@ -407,14 +434,14 @@ static int child_process(entry * e, user * u, char **jobenv) {
} }
} }
else { else {
strncpy(mailcmd, MailCmd, MAX_COMMAND); strncpy(mailcmd, MailCmd, MAX_COMMAND+1);
} }
if (!(mail = cron_popen(mailcmd, "w", e->pwd))) { if (!(mail = cron_popen(mailcmd, "w", e->pwd, jobenv))) {
perror(mailcmd); perror(mailcmd);
(void) _exit(ERROR_EXIT); (void) _exit(ERROR_EXIT);
} }
fprintf(mail, "From: %s (Cron Daemon)\n", mailfrom); fprintf(mail, "From: \"(Cron Daemon)\" <%s>\n", mailfrom);
fprintf(mail, "To: %s\n", mailto); fprintf(mail, "To: %s\n", mailto);
fprintf(mail, "Subject: Cron <%s@%s> %s\n", fprintf(mail, "Subject: Cron <%s@%s> %s\n",
usernm, first_word(hostname, "."), e->cmd); usernm, first_word(hostname, "."), e->cmd);
@ -422,6 +449,7 @@ static int child_process(entry * e, user * u, char **jobenv) {
#ifdef MAIL_DATE #ifdef MAIL_DATE
fprintf(mail, "Date: %s\n", arpadate(&StartTime)); fprintf(mail, "Date: %s\n", arpadate(&StartTime));
#endif /*MAIL_DATE */ #endif /*MAIL_DATE */
fprintf(mail, "MIME-Version: 1.0\n");
if (content_type == 0L) { if (content_type == 0L) {
fprintf(mail, "Content-Type: text/plain; charset=%s\n", fprintf(mail, "Content-Type: text/plain; charset=%s\n",
cron_default_mail_charset); cron_default_mail_charset);
@ -455,6 +483,7 @@ static int child_process(entry * e, user * u, char **jobenv) {
* defined (and suggested by) RFC3834. * defined (and suggested by) RFC3834.
*/ */
fprintf(mail, "Auto-Submitted: auto-generated\n"); fprintf(mail, "Auto-Submitted: auto-generated\n");
fprintf(mail, "Precedence: bulk\n");
for (env = jobenv; *env; env++) for (env = jobenv; *env; env++)
fprintf(mail, "X-Cron-Env: <%s>\n", *env); fprintf(mail, "X-Cron-Env: <%s>\n", *env);
@ -476,7 +505,7 @@ static int child_process(entry * e, user * u, char **jobenv) {
putc(ch, mail); putc(ch, mail);
#if defined(SYSLOG) #if defined(SYSLOG)
if (SyslogOutput) { if (SyslogOutput) {
logbuf[bufidx++] = ch; logbuf[bufidx++] = (char)ch;
if ((ch == '\n') || (bufidx == sizeof(logbuf)-1)) { if ((ch == '\n') || (bufidx == sizeof(logbuf)-1)) {
if (ch == '\n') if (ch == '\n')
logbuf[bufidx-1] = '\0'; logbuf[bufidx-1] = '\0';
@ -493,7 +522,7 @@ static int child_process(entry * e, user * u, char **jobenv) {
*/ */
if (mail) { if (mail) {
Debug(DPROC, ("[%ld] closing pipe to mail\n", (long) getpid())) Debug(DPROC, ("[%ld] closing pipe to mail\n", (long) getpid()));
/* Note: the pclose will probably see /* Note: the pclose will probably see
* the termination of the grandchild * the termination of the grandchild
* in addition to the mail process, since * in addition to the mail process, since
@ -515,7 +544,7 @@ static int child_process(entry * e, user * u, char **jobenv) {
* log the facts so the poor user can figure out * log the facts so the poor user can figure out
* what's going on. * what's going on.
*/ */
if (mail && status) { if (mail && status && !SyslogOutput) {
char buf[MAX_TEMPSTR]; char buf[MAX_TEMPSTR];
sprintf(buf, sprintf(buf,
@ -526,7 +555,7 @@ static int child_process(entry * e, user * u, char **jobenv) {
} /*if data from grandchild */ } /*if data from grandchild */
Debug(DPROC, ("[%ld] got EOF from grandchild\n", (long) getpid())) Debug(DPROC, ("[%ld] got EOF from grandchild\n", (long) getpid()));
fclose(in); /* also closes stdout_pipe[READ_PIPE] */ fclose(in); /* also closes stdout_pipe[READ_PIPE] */
} }
@ -535,22 +564,22 @@ static int child_process(entry * e, user * u, char **jobenv) {
*/ */
for (; children > 0; children--) { for (; children > 0; children--) {
WAIT_T waiter; WAIT_T waiter;
PID_T pid; PID_T child;
Debug(DPROC, ("[%ld] waiting for grandchild #%d to finish\n", Debug(DPROC, ("[%ld] waiting for grandchild #%d to finish\n",
(long) getpid(), children)) (long) getpid(), children));
while ((pid = wait(&waiter)) < OK && errno == EINTR) ; while ((child = wait(&waiter)) < OK && errno == EINTR) ;
if (pid < OK) { if (child < OK) {
Debug(DPROC, Debug(DPROC,
("[%ld] no more grandchildren--mail written?\n", ("[%ld] no more grandchildren--mail written?\n",
(long) getpid())) (long) getpid()));
break; break;
} }
Debug(DPROC, ("[%ld] grandchild #%ld finished, status=%04x", Debug(DPROC, ("[%ld] grandchild #%ld finished, status=%04x",
(long) getpid(), (long) pid, WEXITSTATUS(waiter))) (long) getpid(), (long) child, WEXITSTATUS(waiter)));
if (WIFSIGNALED(waiter) && WCOREDUMP(waiter)) if (WIFSIGNALED(waiter) && WCOREDUMP(waiter))
Debug(DPROC, (", dumped core")) Debug(DPROC, (", dumped core"));
Debug(DPROC, ("\n")) Debug(DPROC, ("\n"));
} }
return OK_EXIT; return OK_EXIT;
} }

View File

@ -26,7 +26,22 @@
* vix 30dec86 [written] * vix 30dec86 [written]
*/ */
#include <cron.h> #include "config.h"
#include <ctype.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include "bitstring.h"
#include "funcs.h"
#include "globals.h"
#include "macros.h"
#include "pathnames.h"
typedef enum ecode { typedef enum ecode {
e_none, e_minute, e_hour, e_dom, e_month, e_dow, e_none, e_minute, e_hour, e_dom, e_month, e_dow,
@ -78,15 +93,16 @@ entry *load_entry(FILE * file, void (*error_func) (), struct passwd *pw,
*/ */
ecode_e ecode = e_none; ecode_e ecode = e_none;
entry *e; entry *e = NULL;
int ch; int ch;
char cmd[MAX_COMMAND]; char cmd[MAX_COMMAND];
char envstr[MAX_ENVSTR]; char envstr[MAX_ENVSTR];
char **tenvp; char **tenvp;
char *p;
struct passwd temppw;
int i;
Debug(DPARS, ("load_entry()...about to eat comments\n")) Debug(DPARS, ("load_entry()...about to eat comments\n"));
skip_comments(file);
ch = get_char(file); ch = get_char(file);
if (ch == EOF) if (ch == EOF)
@ -98,6 +114,10 @@ entry *load_entry(FILE * file, void (*error_func) (), struct passwd *pw,
*/ */
e = (entry *) calloc(sizeof (entry), sizeof (char)); e = (entry *) calloc(sizeof (entry), sizeof (char));
if (e == NULL) {
ecode = e_memory;
goto eof;
}
/* check for '-' as a first character, this option will disable /* check for '-' as a first character, this option will disable
* writing a syslog message about command getting executed * writing a syslog message about command getting executed
@ -114,9 +134,11 @@ entry *load_entry(FILE * file, void (*error_func) (), struct passwd *pw,
goto eof; goto eof;
} }
ch = get_char(file); ch = get_char(file);
if (ch == EOF) if (ch == EOF) {
free(e);
return NULL; return NULL;
} }
}
if (ch == '@') { if (ch == '@') {
/* all of these should be flagged and load-limited; i.e., /* all of these should be flagged and load-limited; i.e.,
@ -188,7 +210,7 @@ entry *load_entry(FILE * file, void (*error_func) (), struct passwd *pw,
} }
} }
else { else {
Debug(DPARS, ("load_entry()...about to parse numerics\n")) Debug(DPARS, ("load_entry()...about to parse numerics\n"));
if (ch == '*') if (ch == '*')
e->flags |= MIN_STAR; e->flags |= MIN_STAR;
@ -259,10 +281,10 @@ entry *load_entry(FILE * file, void (*error_func) (), struct passwd *pw,
if (!pw) { if (!pw) {
char *username = cmd; /* temp buffer */ char *username = cmd; /* temp buffer */
Debug(DPARS, ("load_entry()...about to parse username\n")) Debug(DPARS, ("load_entry()...about to parse username\n"));
ch = get_string(username, MAX_COMMAND, file, " \t\n"); ch = get_string(username, MAX_COMMAND, file, " \t\n");
Debug(DPARS, ("load_entry()...got %s\n", username)) Debug(DPARS, ("load_entry()...got %s\n", username));
if (ch == EOF || ch == '\n' || ch == '*') { if (ch == EOF || ch == '\n' || ch == '*') {
ecode = e_cmd; ecode = e_cmd;
goto eof; goto eof;
@ -270,18 +292,36 @@ entry *load_entry(FILE * file, void (*error_func) (), struct passwd *pw,
pw = getpwnam(username); pw = getpwnam(username);
if (pw == NULL) { if (pw == NULL) {
ecode = e_username; Debug(DPARS, ("load_entry()...unknown user entry\n"));
goto eof; memset(&temppw, 0, sizeof (temppw));
} temppw.pw_name = username;
temppw.pw_passwd = "";
pw = &temppw;
} else {
Debug(DPARS, ("load_entry()...uid %ld, gid %ld\n", Debug(DPARS, ("load_entry()...uid %ld, gid %ld\n",
(long) pw->pw_uid, (long) pw->pw_gid)) (long) pw->pw_uid, (long) pw->pw_gid));
}
} }
if ((e->pwd = pw_dup(pw)) == NULL) { if ((e->pwd = pw_dup(pw)) == NULL) {
ecode = e_memory; ecode = e_memory;
goto eof; goto eof;
} }
bzero(e->pwd->pw_passwd, strlen(e->pwd->pw_passwd)); memset(e->pwd->pw_passwd, 0, strlen(e->pwd->pw_passwd));
p = env_get("RANDOM_DELAY", envp);
if (p) {
char *endptr;
long val;
errno = 0; /* To distinguish success/failure after call */
val = strtol(p, &endptr, 10);
if (errno != 0 || val < 0 || val > 24*60) {
log_it("CRON", getpid(), "ERROR", "bad value of RANDOM_DELAY", 0);
} else {
e->delay = (int)((double)val * RandomScale);
}
}
/* copy and fix up environment. some variables are just defaults and /* copy and fix up environment. some variables are just defaults and
* others are overrides. * others are overrides.
@ -301,21 +341,25 @@ entry *load_entry(FILE * file, void (*error_func) (), struct passwd *pw,
else else
log_it("CRON", getpid(), "ERROR", "can't set SHELL", 0); log_it("CRON", getpid(), "ERROR", "can't set SHELL", 0);
} }
if (!env_get("HOME", e->envp)) { if ((tenvp = env_update_home(e->envp, pw->pw_dir)) == NULL) {
if (glue_strings(envstr, sizeof envstr, "HOME", pw->pw_dir, '=')) {
if ((tenvp = env_set(e->envp, envstr)) == NULL) {
ecode = e_memory; ecode = e_memory;
goto eof; goto eof;
} }
e->envp = tenvp; e->envp = tenvp;
}
else
log_it("CRON", getpid(), "ERROR", "can't set HOME", 0);
}
#ifndef LOGIN_CAP #ifndef LOGIN_CAP
/* If login.conf is in used we will get the default PATH later. */ /* If login.conf is in used we will get the default PATH later. */
if (!env_get("PATH", e->envp)) { if (!env_get("PATH", e->envp)) {
if (glue_strings(envstr, sizeof envstr, "PATH", _PATH_DEFPATH, '=')) { char *defpath;
if (ChangePath)
defpath = _PATH_DEFPATH;
else {
defpath = getenv("PATH");
if (defpath == NULL)
defpath = _PATH_DEFPATH;
}
if (glue_strings(envstr, sizeof envstr, "PATH", defpath, '=')) {
if ((tenvp = env_set(e->envp, envstr)) == NULL) { if ((tenvp = env_set(e->envp, envstr)) == NULL) {
ecode = e_memory; ecode = e_memory;
goto eof; goto eof;
@ -347,7 +391,7 @@ entry *load_entry(FILE * file, void (*error_func) (), struct passwd *pw,
log_it("CRON", getpid(), "ERROR", "can't set USER", 0); log_it("CRON", getpid(), "ERROR", "can't set USER", 0);
#endif #endif
Debug(DPARS, ("load_entry()...about to parse command\n")) Debug(DPARS, ("load_entry()...about to parse command\n"));
/* Everything up to the next \n or EOF is part of the command... /* Everything up to the next \n or EOF is part of the command...
* too bad we don't know in advance how long it will be, since we * too bad we don't know in advance how long it will be, since we
@ -369,21 +413,21 @@ entry *load_entry(FILE * file, void (*error_func) (), struct passwd *pw,
goto eof; goto eof;
} }
Debug(DPARS, ("load_entry()...returning successfully\n")) Debug(DPARS, ("load_entry()...returning successfully\n"));
/* success, fini, return pointer to the entry we just created... /* success, fini, return pointer to the entry we just created...
*/ */
return (e); return (e);
eof: eof:
if (e) {
if (e->envp) if (e->envp)
env_free(e->envp); env_free(e->envp);
if (e->pwd)
free(e->pwd); free(e->pwd);
if (e->cmd)
free(e->cmd); free(e->cmd);
free(e); free(e);
while (ch != '\n' && !feof(file)) }
for (i = 0; i < MAX_COMMAND && ch != '\n' && !feof(file); i++)
ch = get_char(file); ch = get_char(file);
if (ecode != e_none && error_func) if (ecode != e_none && error_func)
(*error_func) (ecodes[(int) ecode]); (*error_func) (ecodes[(int) ecode]);
@ -401,13 +445,13 @@ get_list(bitstr_t * bits, int low, int high, const char *names[],
* assume the same thing. * assume the same thing.
*/ */
Debug(DPARS | DEXT, ("get_list()...entered\n")) Debug(DPARS | DEXT, ("get_list()...entered\n"));
/* list = range {"," range} /* list = range {"," range}
*/ */
/* clear the bit string, since the default is 'off'. /* clear the bit string, since the default is 'off'.
*/ */
bit_nclear(bits, 0, (high - low + 1)); bit_nclear(bits, 0, (high - low));
/* process all ranges /* process all ranges
*/ */
@ -426,7 +470,7 @@ get_list(bitstr_t * bits, int low, int high, const char *names[],
Skip_Nonblanks(ch, file) Skip_Nonblanks(ch, file)
Skip_Blanks(ch, file) Skip_Blanks(ch, file)
Debug(DPARS | DEXT, ("get_list()...exiting w/ %02x\n", ch)) Debug(DPARS | DEXT, ("get_list()...exiting w/ %02x\n", ch));
return (ch); return (ch);
} }
@ -440,7 +484,7 @@ get_range(bitstr_t * bits, int low, int high, const char *names[],
int i, num1, num2, num3; int i, num1, num2, num3;
Debug(DPARS | DEXT, ("get_range()...entering, exit won't show\n")) Debug(DPARS | DEXT, ("get_range()...entering, exit won't show\n"));
if (ch == '*') { if (ch == '*') {
/* '*' means "first-last" but can still be modified by /step /* '*' means "first-last" but can still be modified by /step
@ -531,7 +575,7 @@ get_number(int *numptr, int low, const char *names[], int ch, FILE * file,
while (isdigit((unsigned char) ch)) { while (isdigit((unsigned char) ch)) {
if (++len >= MAX_TEMPSTR) if (++len >= MAX_TEMPSTR)
goto bad; goto bad;
*pc++ = ch; *pc++ = (char)ch;
ch = get_char(file); ch = get_char(file);
} }
*pc = '\0'; *pc = '\0';
@ -548,14 +592,14 @@ get_number(int *numptr, int low, const char *names[], int ch, FILE * file,
while (isalpha((unsigned char) ch)) { while (isalpha((unsigned char) ch)) {
if (++len >= MAX_TEMPSTR) if (++len >= MAX_TEMPSTR)
goto bad; goto bad;
*pc++ = ch; *pc++ = (char)ch;
ch = get_char(file); ch = get_char(file);
} }
*pc = '\0'; *pc = '\0';
if (len != 0 && strchr(terms, ch)) { if (len != 0 && strchr(terms, ch)) {
for (i = 0; names[i] != NULL; i++) { for (i = 0; names[i] != NULL; i++) {
Debug(DPARS | DEXT, Debug(DPARS | DEXT,
("get_num, compare(%s,%s)\n", names[i], temp)) ("get_num, compare(%s,%s)\n", names[i], temp));
if (!strcasecmp(names[i], temp)) { if (!strcasecmp(names[i], temp)) {
*numptr = i + low; *numptr = i + low;
return (ch); return (ch);
@ -570,7 +614,7 @@ get_number(int *numptr, int low, const char *names[], int ch, FILE * file,
} }
static int set_element(bitstr_t * bits, int low, int high, int number) { static int set_element(bitstr_t * bits, int low, int high, int number) {
Debug(DPARS | DEXT, ("set_element(?,%d,%d,%d)\n", low, high, number)) Debug(DPARS | DEXT, ("set_element(?,%d,%d,%d)\n", low, high, number));
if (number < low || number > high) if (number < low || number > high)
return (EOF); return (EOF);

134
src/env.c
View File

@ -19,7 +19,21 @@
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <cron.h> #include "config.h"
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include "globals.h"
#include "funcs.h"
#if defined(BSD)
extern char **environ;
#endif
char **env_init(void) { char **env_init(void) {
char **p = (char **) malloc(sizeof (char *)); char **p = (char **) malloc(sizeof (char *));
@ -38,7 +52,8 @@ void env_free(char **envp) {
} }
char **env_copy(char **envp) { char **env_copy(char **envp) {
int count, i, save_errno; int save_errno;
size_t count, i;
char **p; char **p;
for (count = 0; envp[count] != NULL; count++) ; for (count = 0; envp[count] != NULL; count++) ;
@ -48,7 +63,7 @@ char **env_copy(char **envp) {
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
if ((p[i] = strdup(envp[i])) == NULL) { if ((p[i] = strdup(envp[i])) == NULL) {
save_errno = errno; save_errno = errno;
while (--i >= 0) while (i-- > 0)
free(p[i]); free(p[i]);
free(p); free(p);
errno = save_errno; errno = save_errno;
@ -59,22 +74,22 @@ char **env_copy(char **envp) {
return (p); return (p);
} }
char **env_set(char **envp, char *envstr) { char **env_set(char **envp, const char *envstr) {
int count, found; size_t count, found;
char **p, *envtmp; char **p, *envtmp;
/* /*
* count the number of elements, including the null pointer; * count the number of elements, including the null pointer;
* also set 'found' to -1 or index of entry if already in here. * also set 'found' to -1 or index of entry if already in here.
*/ */
found = -1; found = (size_t)-1;
for (count = 0; envp[count] != NULL; count++) { for (count = 0; envp[count] != NULL; count++) {
if (!strcmp_until(envp[count], envstr, '=')) if (!strcmp_until(envp[count], envstr, '='))
found = count; found = count;
} }
count++; /* for the NULL */ count++; /* for the NULL */
if (found != -1) { if (found != (size_t)-1) {
/* /*
* it exists already, so just free the existing setting, * it exists already, so just free the existing setting,
* save our new one there, and return the existing array. * save our new one there, and return the existing array.
@ -94,7 +109,7 @@ char **env_set(char **envp, char *envstr) {
if ((envtmp = strdup(envstr)) == NULL) if ((envtmp = strdup(envstr)) == NULL)
return (NULL); return (NULL);
p = (char **) realloc((void *) envp, p = (char **) realloc((void *) envp,
(size_t) ((count + 1) * sizeof (char *))); (count + 1) * sizeof (char *));
if (p == NULL) { if (p == NULL) {
free(envtmp); free(envtmp);
return (NULL); return (NULL);
@ -104,6 +119,48 @@ char **env_set(char **envp, char *envstr) {
return (p); return (p);
} }
int env_set_from_environ(char ***envpp) {
static const char *names[] = {
"LANG",
"LC_CTYPE",
"LC_NUMERIC",
"LC_TIME",
"LC_COLLATE",
"LC_MONETARY",
"LC_MESSAGES",
"LC_PAPER",
"LC_NAME",
"LC_ADDRESS",
"LC_TELEPHONE",
"LC_MEASUREMENT",
"LC_IDENTIFICATION",
"LC_ALL",
"LANGUAGE",
"RANDOM_DELAY",
NULL
};
const char **name;
char **procenv;
for (procenv = environ; *procenv != NULL; ++procenv) {
for (name = names; *name != NULL; ++name) {
size_t namelen;
namelen = strlen(*name);
if (strncmp(*name, *procenv, namelen) == 0
&& (*procenv)[namelen] == '=') {
char **tmpenv;
tmpenv = env_set(*envpp, *procenv);
if (tmpenv == NULL)
return FALSE;
*envpp = tmpenv;
}
}
}
return TRUE;
}
/* The following states are used by load_env(), traversed in order: */ /* The following states are used by load_env(), traversed in order: */
enum env_state { enum env_state {
NAMEI, /* First char of NAME, may be quote */ NAMEI, /* First char of NAME, may be quote */
@ -124,20 +181,16 @@ int load_env(char *envstr, FILE * f) {
long filepos; long filepos;
int fileline; int fileline;
enum env_state state; enum env_state state;
char name[MAX_ENVSTR], val[MAX_ENVSTR]; char quotechar, *c, *str, *val;
char quotechar, *c, *str;
filepos = ftell(f); filepos = ftell(f);
fileline = LineNumber; fileline = LineNumber;
skip_comments(f);
if (EOF == get_string(envstr, MAX_ENVSTR, f, "\n")) if (EOF == get_string(envstr, MAX_ENVSTR, f, "\n"))
return (ERR); return (ERR);
Debug(DPARS, ("load_env, read <%s>\n", envstr)) Debug(DPARS, ("load_env, read <%s>\n", envstr));
bzero(name, sizeof name); str = envstr;
bzero(val, sizeof val);
str = name;
state = NAMEI; state = NAMEI;
quotechar = '\0'; quotechar = '\0';
c = envstr; c = envstr;
@ -181,8 +234,9 @@ int load_env(char *envstr, FILE * f) {
case EQ1: case EQ1:
if (*c == '=') { if (*c == '=') {
state++; state++;
str = val;
quotechar = '\0'; quotechar = '\0';
*str++ = *c;
val = str;
} }
else { else {
if (!isspace((unsigned char) *c)) if (!isspace((unsigned char) *c))
@ -203,33 +257,25 @@ int load_env(char *envstr, FILE * f) {
abort(); abort();
} }
} }
if (state != FINI && !(state == VALUE && !quotechar)) { if (state != FINI && state != EQ2 && !(state == VALUE && !quotechar)) {
Debug(DPARS, ("load_env, not an env var, state = %d\n", state)) Debug(DPARS, ("load_env, not an env var, state = %d\n", state));
fseek(f, filepos, 0); if (fseek(f, filepos, 0)) {
return ERR;
}
Set_LineNum(fileline); Set_LineNum(fileline);
return (FALSE); return (FALSE);
} }
*str = '\0';
if (state == VALUE) { if (state == VALUE) {
/* End of unquoted value: trim trailing whitespace */ /* End of unquoted value: trim trailing whitespace */
c = val + strlen(val); while (str > val && isspace((unsigned char)str[-1]))
while (c > val && isspace((unsigned char) c[-1])) *(--str) = '\0';
*(--c) = '\0'; }
return TRUE;
} }
/* 2 fields from parser; looks like an env setting */ char *env_get(const char *name, char **envp) {
size_t len = strlen(name);
/*
* This can't overflow because get_string() limited the size of the
* name and val fields. Still, it doesn't hurt to be careful...
*/
if (!glue_strings(envstr, MAX_ENVSTR, name, val, '='))
return (FALSE);
Debug(DPARS, ("load_env, <%s> <%s> -> <%s>\n", name, val, envstr))
return (TRUE);
}
char *env_get(char *name, char **envp) {
int len = strlen(name);
char *p, *q; char *p, *q;
while ((p = *envp++) != NULL) { while ((p = *envp++) != NULL) {
@ -240,3 +286,19 @@ char *env_get(char *name, char **envp) {
} }
return (NULL); return (NULL);
} }
char **env_update_home(char **envp, const char *dir) {
char envstr[MAX_ENVSTR];
if (dir == NULL || *dir == '\0' || env_get("HOME", envp)) {
return envp;
}
if (glue_strings(envstr, sizeof envstr, "HOME", dir, '=')) {
envp = env_set(envp, envstr);
}
else
log_it("CRON", getpid(), "ERROR", "can't set HOME", 0);
return envp;
}

View File

@ -21,40 +21,8 @@
/* reorder these #include's at your peril */ /* reorder these #include's at your peril */
#include <sys/param.h> #ifndef CRONIE_EXTERNS_H
#include <sys/types.h> #define CRONIE_EXTERNS_H
#include <sys/time.h>
#include <sys/wait.h>
#ifdef HAVE_SYS_FCNTL_H
#include <sys/fcntl.h>
#endif
#include <sys/file.h>
/* stat is used even, when --with-inotify */
#include <sys/stat.h>
#include <bitstring.h>
#include <ctype.h>
#ifndef isascii
#define isascii(c) ((unsigned)(c)<=0177)
#endif
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <locale.h>
#include <pwd.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <utime.h>
#if defined(SYSLOG)
# include <syslog.h>
#endif
#if defined(LOGIN_CAP) #if defined(LOGIN_CAP)
# include <login_cap.h> # include <login_cap.h>
@ -64,12 +32,6 @@
# include <bsd_auth.h> # include <bsd_auth.h>
#endif /*BSD_AUTH*/ #endif /*BSD_AUTH*/
/* include locale stuff for mailer "Content-Type":
*/
#include <locale.h>
#include <nl_types.h>
#include <langinfo.h>
#define DIR_T struct dirent #define DIR_T struct dirent
#define WAIT_T int #define WAIT_T int
#define SIG_T sig_t #define SIG_T sig_t
@ -125,3 +87,5 @@ extern int flock(int, int);
#ifndef WCOREDUMP #ifndef WCOREDUMP
# define WCOREDUMP(st) (((st) & 0200) != 0) # define WCOREDUMP(st) (((st) & 0200) != 0)
#endif #endif
#endif /* CRONIE_EXTERNS_H */

View File

@ -20,10 +20,22 @@
*/ */
/* Notes: /* Notes:
* This file has to be included by cron.h after data structure defs.
* We should reorg this into sections by module. * We should reorg this into sections by module.
*/ */
#ifndef CRONIE_FUNCS_H
#define CRONIE_FUNCS_H
#include <stdio.h>
#include <sys/types.h>
#ifdef WITH_SELINUX
#include <selinux/selinux.h>
#endif
#include "externs.h"
#include "structs.h"
void set_cron_uid(void), void set_cron_uid(void),
check_spool_dir(void), check_spool_dir(void),
open_logfile(void), open_logfile(void),
@ -37,7 +49,6 @@ void set_cron_uid(void),
unget_char(int, FILE *), unget_char(int, FILE *),
free_entry(entry *), free_entry(entry *),
acquire_daemonlock(int), acquire_daemonlock(int),
skip_comments(FILE *),
log_it(const char *, PID_T, const char *, const char *, int), log_it(const char *, PID_T, const char *, const char *, int),
log_close(void), log_close(void),
check_orphans(cron_db *); check_orphans(cron_db *);
@ -51,32 +62,35 @@ int load_database(cron_db *),
job_runqueue(void), job_runqueue(void),
set_debug_flags(const char *), set_debug_flags(const char *),
get_char(FILE *), get_char(FILE *),
get_string(char *, int, FILE *, char *), get_string(char *, int, FILE *, const char *),
swap_uids(void), swap_uids(void),
swap_uids_back(void), swap_uids_back(void),
load_env(char *, FILE *), load_env(char *, FILE *),
env_set_from_environ(char ***envpp),
cron_pclose(FILE *), cron_pclose(FILE *),
glue_strings(char *, size_t, const char *, const char *, char), glue_strings(char *, size_t, const char *, const char *, char),
strcmp_until(const char *, const char *, char), strcmp_until(const char *, const char *, char),
allowed(const char * ,const char * ,const char *), skip_comments(FILE *),
allowed(const char * ,const char * ,const char *);
size_t strlens(const char *, ...),
strdtb(char *); strdtb(char *);
size_t strlens(const char *, ...); char *env_get(const char *, char **),
char *env_get(char *, char **),
*arpadate(time_t *), *arpadate(time_t *),
*mkprints(unsigned char *, unsigned int), *mkprints(unsigned char *, size_t),
*first_word(char *, char *), *first_word(const char *, const char *),
**env_init(void), **env_init(void),
**env_copy(char **), **env_copy(char **),
**env_set(char **, char *); **env_set(char **, const char *),
**env_update_home(char **, const char *);
user *load_user(int, struct passwd *, const char *, const char *, const char *), user *load_user(int, struct passwd *, const char *, const char *, const char *),
*find_user(cron_db *, const char *, const char *); *find_user(cron_db *, const char *, const char *);
entry *load_entry(FILE *, void (*)(), struct passwd *, char **); entry *load_entry(FILE *, void (*)(), struct passwd *, char **);
FILE *cron_popen(char *, const char *, struct passwd *); FILE *cron_popen(char *, const char *, struct passwd *, char **);
struct passwd *pw_dup(const struct passwd *); struct passwd *pw_dup(const struct passwd *);
@ -109,5 +123,9 @@ void free_security_context( security_context_t *scontext );
int crontab_security_access(void); int crontab_security_access(void);
/* PAM */ /* PAM */
#ifdef WITH_PAM
int cron_start_pam(struct passwd *pw); int cron_start_pam(struct passwd *pw);
void cron_close_pam(void); void cron_close_pam(void);
#endif
#endif /* CRONIE_FUNCS_H */

View File

@ -24,6 +24,13 @@
* to add clustering support. * to add clustering support.
*/ */
#ifndef CRONIE_GLOBALS_H
#define CRONIE_GLOBALS_H
#include <time.h>
#include "macros.h"
#ifdef MAIN_PROGRAM #ifdef MAIN_PROGRAM
# define XTRN # define XTRN
# define INIT(x) = x # define INIT(x) = x
@ -70,9 +77,11 @@ XTRN int SyslogOutput;
XTRN time_t StartTime; XTRN time_t StartTime;
XTRN int NoFork; XTRN int NoFork;
XTRN int PermitAnyCrontab; XTRN int PermitAnyCrontab;
XTRN char MailCmd[MAX_COMMAND]; XTRN char MailCmd[MAX_COMMAND+1]; /* +1 for terminator */
XTRN char cron_default_mail_charset[MAX_ENVSTR]; XTRN char cron_default_mail_charset[MAX_ENVSTR];
XTRN int EnableClustering; XTRN int EnableClustering;
XTRN int ChangePath;
XTRN double RandomScale;
#if DEBUGGING #if DEBUGGING
XTRN int DebugFlags INIT(0); XTRN int DebugFlags INIT(0);
@ -87,3 +96,5 @@ XTRN const char *DebugFlagNames[]
#else #else
#define DebugFlags 0 #define DebugFlags 0
#endif /* DEBUGGING */ #endif /* DEBUGGING */
#endif /* CRONIE_GLOBALS_H */

View File

@ -19,7 +19,17 @@
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <cron.h> #include "config.h"
#include <stdlib.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include "funcs.h"
#include "globals.h"
typedef struct _job { typedef struct _job {
struct _job *next; struct _job *next;
@ -31,12 +41,42 @@ static job *jhead = NULL, *jtail = NULL;
void job_add(entry * e, user * u) { void job_add(entry * e, user * u) {
job *j; job *j;
struct passwd *newpwd;
struct passwd *temppwd;
const char *uname;
/* if already on queue, keep going */ /* if already on queue, keep going */
for (j = jhead; j != NULL; j = j->next) for (j = jhead; j != NULL; j = j->next)
if (j->e == e && j->u == u) if (j->e == e && j->u == u)
return; return;
uname = e->pwd->pw_name;
/* check if user exists in time of job is being run f.e. ldap */
if ((temppwd = getpwnam(uname)) != NULL) {
char **tenvp;
Debug(DSCH | DEXT, ("user [%s:%ld:%ld:...] cmd=\"%s\"\n",
e->pwd->pw_name, (long) temppwd->pw_uid,
(long) temppwd->pw_gid, e->cmd));
if ((newpwd = pw_dup(temppwd)) == NULL) {
log_it(uname, getpid(), "ERROR", "memory allocation failed", errno);
return;
}
free(e->pwd);
e->pwd = newpwd;
if ((tenvp = env_update_home(e->envp, e->pwd->pw_dir)) == NULL) {
log_it(uname, getpid(), "ERROR", "memory allocation failed", errno);
return;
}
e->envp = tenvp;
} else {
log_it(uname, getpid(), "ERROR", "getpwnam() failed - user unknown",errno);
Debug(DSCH | DEXT, ("%s:%d pid=%d time=%ld getpwnam(%s) failed errno=%d error=%s\n",
__FILE__,__LINE__,getpid(),time(NULL),uname,errno,strerror(errno)));
return;
}
/* build a job queue element */ /* build a job queue element */
if ((j = (job *) malloc(sizeof (job))) == NULL) if ((j = (job *) malloc(sizeof (job))) == NULL)
return; return;

View File

@ -18,9 +18,14 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#ifndef CRONIE_MACROS_H
#define CRONIE_MACROS_H
#ifdef HAVE_LIMITS_H #ifdef HAVE_LIMITS_H
#include <limits.h> #include <limits.h>
#endif #endif
/* these are really immutable, and are /* these are really immutable, and are
* defined for symbolic convenience only * defined for symbolic convenience only
* TRUE, FALSE, and ERR must be distinct * TRUE, FALSE, and ERR must be distinct
@ -53,6 +58,9 @@
#define MAX_UNAME 256 /* max length of username */ #define MAX_UNAME 256 /* max length of username */
#define ROOT_UID 0 /* don't change this, it really must be root */ #define ROOT_UID 0 /* don't change this, it really must be root */
#define ROOT_USER "root" /* ditto */ #define ROOT_USER "root" /* ditto */
#define MAX_USER_ENVS 1000 /* maximum environment variables in user's crontab */
#define MAX_USER_ENTRIES 1000 /* maximum crontab entries in user's crontab */
#define MAX_GARBAGE 32768 /* max num of chars of comments and whitespaces between entries */
/* NOTE: these correspond to DebugFlagNames, /* NOTE: these correspond to DebugFlagNames,
* defined below. * defined below.
@ -82,10 +90,10 @@
#if DEBUGGING #if DEBUGGING
# define Debug(mask, message) \ # define Debug(mask, message) \
if ((DebugFlags & (mask)) != 0) \ if ((DebugFlags & (mask)) != 0) \
printf message; printf message
#else /* !DEBUGGING */ #else /* !DEBUGGING */
# define Debug(mask, message) \ # define Debug(mask, message) \
; ()
#endif /* DEBUGGING */ #endif /* DEBUGGING */
#define MkUpper(ch) (islower(ch) ? toupper(ch) : ch) #define MkUpper(ch) (islower(ch) ? toupper(ch) : ch)
@ -127,6 +135,9 @@
* we will just have to live without it. In order for this to be an * we will just have to live without it. In order for this to be an
* issue an attacker would have to subvert group CRON_GROUP. * issue an attacker would have to subvert group CRON_GROUP.
*/ */
#include <fcntl.h>
#ifndef O_NOFOLLOW #ifndef O_NOFOLLOW
#define O_NOFOLLOW 0 #define O_NOFOLLOW 0
#endif #endif
#endif /* CRONIE_MACROS_H */

View File

@ -23,7 +23,23 @@
* vix 30dec86 [written] * vix 30dec86 [written]
*/ */
#include <cron.h> #include "config.h"
#include "globals.h"
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#if defined(SYSLOG)
# include <syslog.h>
#endif
#ifdef WITH_AUDIT #ifdef WITH_AUDIT
# include <libaudit.h> # include <libaudit.h>
#endif #endif
@ -37,7 +53,10 @@
#ifdef HAVE_FLOCK /* flock(2) */ #ifdef HAVE_FLOCK /* flock(2) */
# include <sys/file.h> # include <sys/file.h>
#endif #endif
#include <stdio.h>
#include "funcs.h"
#include "macros.h"
#include "pathnames.h"
#if defined(SYSLOG) && defined(LOG_FILE) #if defined(SYSLOG) && defined(LOG_FILE)
# undef LOG_FILE # undef LOG_FILE
@ -57,7 +76,9 @@ static int LogFD = ERR;
static int syslog_open = FALSE; static int syslog_open = FALSE;
#endif #endif
#if defined(HAVE_FCNTL) && defined(F_SETLK) #if defined(HAVE_FLOCK)
# define trylock_file(fd) flock((fd), LOCK_EX|LOCK_NB)
#elif defined(HAVE_FCNTL) && defined(F_SETLK)
static int trylock_file(int fd) { static int trylock_file(int fd) {
struct flock fl; struct flock fl;
@ -71,8 +92,6 @@ static int trylock_file(int fd) {
} }
#elif defined(HAVE_LOCKF) #elif defined(HAVE_LOCKF)
# define trylock_file(fd) lockf((fd), F_TLOCK, 0) # define trylock_file(fd) lockf((fd), F_TLOCK, 0)
#elif defined(HAVE_FLOCK)
# define trylock_file(fd) flock((fd), LOCK_EX|LOCK_NB)
#endif #endif
/* /*
@ -124,7 +143,7 @@ int strcmp_until(const char *left, const char *right, char until) {
/* strdtb(s) - delete trailing blanks in string 's' and return new length /* strdtb(s) - delete trailing blanks in string 's' and return new length
*/ */
int strdtb(char *s) { size_t strdtb(char *s) {
char *x = s; char *x = s;
/* scan forward to the null /* scan forward to the null
@ -147,7 +166,7 @@ int strdtb(char *s) {
/* the difference between the position of the null character and /* the difference between the position of the null character and
* the position of the first character of the string is the length. * the position of the first character of the string is the length.
*/ */
return (x - s); return ((size_t)(x - s));
} }
int set_debug_flags(const char *flags) { int set_debug_flags(const char *flags) {
@ -290,9 +309,15 @@ void acquire_daemonlock(int closeflag) {
close(fd); close(fd);
fd = -1; fd = -1;
} }
/* and restore default sig handlers so we don't remove pid file if killed */
signal(SIGINT,SIG_DFL);
signal(SIGTERM,SIG_DFL);
return; return;
} }
if (NoFork == 1)
return; //move along, nothing to do here...
if (fd == -1) { if (fd == -1) {
pidfile = _PATH_CRON_PID; pidfile = _PATH_CRON_PID;
/* Initial mode is 0600 to prevent flock() race/DoS. */ /* Initial mode is 0600 to prevent flock() race/DoS. */
@ -308,7 +333,7 @@ void acquire_daemonlock(int closeflag) {
if (trylock_file(fd) < OK) { if (trylock_file(fd) < OK) {
int save_errno = errno; int save_errno = errno;
bzero(buf, sizeof (buf)); memset(buf, 0, sizeof (buf));
if ((num = read(fd, buf, sizeof (buf) - 1)) > 0 && if ((num = read(fd, buf, sizeof (buf) - 1)) > 0 &&
(otherpid = strtol(buf, &ep, 10)) > 0 && (otherpid = strtol(buf, &ep, 10)) > 0 &&
ep != buf && *ep == '\n' && otherpid != LONG_MAX) { ep != buf && *ep == '\n' && otherpid != LONG_MAX) {
@ -327,11 +352,18 @@ void acquire_daemonlock(int closeflag) {
(void) fchmod(fd, 0644); (void) fchmod(fd, 0644);
(void) fcntl(fd, F_SETFD, 1); (void) fcntl(fd, F_SETFD, 1);
} }
#if !defined(HAVE_FLOCK)
else {
/* Racy but better than nothing, just hope the parent exits */
sleep(0);
trylock_file(fd);
}
#endif
sprintf(buf, "%ld\n", (long) pid); sprintf(buf, "%ld\n", (long) pid);
(void) lseek(fd, (off_t) 0, SEEK_SET); (void) lseek(fd, (off_t) 0, SEEK_SET);
len = strlen(buf); len = (ssize_t)strlen(buf);
if ((num = write(fd, buf, len)) != len) if ((num = write(fd, buf, (size_t)len)) != len)
log_it("CRON", pid, "ERROR", "write() failed", errno); log_it("CRON", pid, "ERROR", "write() failed", errno);
else { else {
if (ftruncate(fd, num) == -1) if (ftruncate(fd, num) == -1)
@ -368,7 +400,7 @@ void unget_char(int ch, FILE * file) {
* (3) uses get_char() so LineNumber will be accurate * (3) uses get_char() so LineNumber will be accurate
* (4) returns EOF or terminating character, whichever * (4) returns EOF or terminating character, whichever
*/ */
int get_string(char *string, int size, FILE * file, char *terms) { int get_string(char *string, int size, FILE * file, const char *terms) {
int ch; int ch;
while (EOF != (ch = get_char(file)) && !strchr(terms, ch)) { while (EOF != (ch = get_char(file)) && !strchr(terms, ch)) {
@ -386,14 +418,20 @@ int get_string(char *string, int size, FILE * file, char *terms) {
/* skip_comments(file) : read past comment (if any) /* skip_comments(file) : read past comment (if any)
*/ */
void skip_comments(FILE * file) { int skip_comments(FILE * file) {
int ch; int ch;
int n = 0;
while (EOF != (ch = get_char(file))) { while (EOF != (ch = get_char(file))) {
/* ch is now the first character of a line. /* ch is now the first character of a line.
*/ */
while (ch == ' ' || ch == '\t') if (++n > MAX_GARBAGE)
return FALSE;
while (ch == ' ' || ch == '\t') {
ch = get_char(file); ch = get_char(file);
if (++n > MAX_GARBAGE)
return FALSE;
}
if (ch == EOF) if (ch == EOF)
break; break;
@ -408,15 +446,18 @@ void skip_comments(FILE * file) {
* character on a line. * character on a line.
*/ */
while (ch != '\n' && ch != EOF) while (ch != '\n' && ch != EOF) {
ch = get_char(file); ch = get_char(file);
if (++n > MAX_GARBAGE)
return FALSE;
}
/* ch is now the newline of a line which we're going to /* ch is now the newline of a line which we're going to
* ignore. * ignore.
*/ */
} }
if (ch != EOF) if (ch != EOF)
unget_char(ch, file); unget_char(ch, file);
return TRUE;
} }
/* int in_file(const char *string, FILE *file, int error) /* int in_file(const char *string, FILE *file, int error)
@ -582,7 +623,7 @@ void log_close(void) {
#endif /*SYSLOG*/ #endif /*SYSLOG*/
} }
/* char *first_word(char *s, char *t) /* char *first_word(const char *s, const char *t)
* return pointer to first word * return pointer to first word
* parameters: * parameters:
* s - string we want the first word of * s - string we want the first word of
@ -591,7 +632,7 @@ void log_close(void) {
* (1) this routine is fairly slow * (1) this routine is fairly slow
* (2) it returns a pointer to static storage * (2) it returns a pointer to static storage
*/ */
char *first_word(char *s, char *t) { char *first_word(const char *s, const char *t) {
static char retbuf[2][MAX_TEMPSTR + 1]; /* sure wish C had GC */ static char retbuf[2][MAX_TEMPSTR + 1]; /* sure wish C had GC */
static int retsel = 0; static int retsel = 0;
char *rb, *rp; char *rb, *rp;
@ -619,7 +660,7 @@ char *first_word(char *s, char *t) {
/* warning: /* warning:
* heavily ascii-dependent. * heavily ascii-dependent.
*/ */
void mkprint(char *dst, unsigned char *src, int len) { static void mkprint(char *dst, unsigned char *src, size_t len) {
/* /*
* XXX * XXX
* We know this routine can't overflow the dst buffer because mkprints() * We know this routine can't overflow the dst buffer because mkprints()
@ -630,10 +671,10 @@ void mkprint(char *dst, unsigned char *src, int len) {
if (ch < ' ') { /* control character */ if (ch < ' ') { /* control character */
*dst++ = '^'; *dst++ = '^';
*dst++ = ch + '@'; *dst++ = (char)(ch + '@');
} }
else if (ch < 0177) { /* printable */ else if (ch < 0177) { /* printable */
*dst++ = ch; *dst++ = (char)ch;
} }
else if (ch == 0177) { /* delete/rubout */ else if (ch == 0177) { /* delete/rubout */
*dst++ = '^'; *dst++ = '^';
@ -650,7 +691,7 @@ void mkprint(char *dst, unsigned char *src, int len) {
/* warning: /* warning:
* returns a pointer to malloc'd storage, you must call free yourself. * returns a pointer to malloc'd storage, you must call free yourself.
*/ */
char *mkprints(unsigned char *src, unsigned int len) { char *mkprints(unsigned char *src, size_t len) {
char *dst = malloc(len * 4 + 1); char *dst = malloc(len * 4 + 1);
if (dst) if (dst)

View File

@ -45,15 +45,6 @@
#define _PATH_CRON_PID PIDDIR PIDFILE #define _PATH_CRON_PID PIDDIR PIDFILE
#define REBOOT_LOCK PIDDIR "cron.reboot" #define REBOOT_LOCK PIDDIR "cron.reboot"
/* what editor to use if no EDITOR or VISUAL
* environment variable specified.
*/
#if defined(_PATH_VI)
# define EDITOR _PATH_VI
#else
# define EDITOR "/usr/ucb/vi"
#endif
#ifndef _PATH_BSHELL #ifndef _PATH_BSHELL
# define _PATH_BSHELL "/bin/sh" # define _PATH_BSHELL "/bin/sh"
#endif #endif

View File

@ -30,11 +30,24 @@
* *
*/ */
#include "config.h"
#include <errno.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#include "funcs.h"
#include "globals.h"
#include "macros.h"
#ifdef HAVE_SYS_CDEFS_H #ifdef HAVE_SYS_CDEFS_H
# include <sys/cdefs.h> # include <sys/cdefs.h>
#endif #endif
#include <cron.h>
#include <signal.h> #include <signal.h>
/* /*
@ -47,7 +60,7 @@ static int fds;
#define MAX_ARGS 1024 #define MAX_ARGS 1024
FILE *cron_popen(char *program, const char *type, struct passwd *pw) { FILE *cron_popen(char *program, const char *type, struct passwd *pw, char **jobenv) {
char *cp; char *cp;
FILE *iop; FILE *iop;
int argc, pdes[2]; int argc, pdes[2];
@ -56,6 +69,7 @@ FILE *cron_popen(char *program, const char *type, struct passwd *pw) {
ssize_t out; ssize_t out;
char buf[PIPE_BUF]; char buf[PIPE_BUF];
struct sigaction sa; struct sigaction sa;
int fd;
#ifdef __GNUC__ #ifdef __GNUC__
(void) &iop; /* Avoid fork clobbering */ (void) &iop; /* Avoid fork clobbering */
@ -67,9 +81,9 @@ FILE *cron_popen(char *program, const char *type, struct passwd *pw) {
if (!pids) { if (!pids) {
if ((fds = getdtablesize()) <= 0) if ((fds = getdtablesize()) <= 0)
return (NULL); return (NULL);
if (!(pids = (PID_T *) malloc((u_int) (fds * sizeof (PID_T))))) if (!(pids = (PID_T *) malloc((u_int) ((size_t)fds * sizeof (PID_T)))))
return (NULL); return (NULL);
bzero((char *) pids, fds * sizeof (PID_T)); memset((char *) pids, 0, (size_t)fds * sizeof (PID_T));
} }
if (pipe(pdes) < 0) if (pipe(pdes) < 0)
return (NULL); return (NULL);
@ -108,10 +122,15 @@ FILE *cron_popen(char *program, const char *type, struct passwd *pw) {
sa.sa_handler = SIG_DFL; sa.sa_handler = SIG_DFL;
sigaction(SIGPIPE, &sa, NULL); sigaction(SIGPIPE, &sa, NULL);
if (cron_change_user_permanently(pw, pw->pw_dir) != 0) /* close all unwanted open file descriptors */
for (fd = STDERR + 1; fd < fds; fd++) {
close(fd);
}
if (cron_change_user_permanently(pw, env_get("HOME", jobenv)) != 0)
_exit(2); _exit(2);
if (execvp(argv[0], argv) < 0) { if (execvpe(argv[0], argv, jobenv) < 0) {
int save_errno = errno; int save_errno = errno;
log_it("CRON", getpid(), "EXEC FAILED", program, save_errno); log_it("CRON", getpid(), "EXEC FAILED", program, save_errno);

View File

@ -30,7 +30,8 @@
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <config.h> #include "config.h"
#include <sys/param.h> #include <sys/param.h>
#if !defined(OpenBSD) || OpenBSD < 200105 #if !defined(OpenBSD) || OpenBSD < 200105
@ -40,10 +41,13 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "funcs.h"
#include "globals.h"
struct passwd * struct passwd *
pw_dup(const struct passwd *pw) { pw_dup(const struct passwd *pw) {
char *cp; char *cp;
size_t nsize=0, psize=0, gsize=0, dsize=0, ssize=0, total=0; size_t nsize=0, psize=0, gsize=0, dsize=0, ssize=0, total;
struct passwd *newpw; struct passwd *newpw;
/* Allocate in one big chunk for easy freeing */ /* Allocate in one big chunk for easy freeing */

View File

@ -19,13 +19,28 @@
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <cron.h> #include "config.h"
#include <errno.h>
#include <grp.h>
#include <pwd.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "cronie_common.h"
#include "funcs.h"
#include "globals.h"
#include "macros.h"
#ifdef WITH_PAM
# include <security/pam_appl.h>
#endif
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
# include <selinux/selinux.h> # include <selinux/selinux.h>
# include <selinux/context.h> # include <selinux/context.h>
# include <selinux/flask.h>
# include <selinux/av_permissions.h>
# include <selinux/get_context_list.h> # include <selinux/get_context_list.h>
#endif #endif
@ -39,7 +54,8 @@ static int pam_session_opened = 0; //global for open session
static int static int
cron_conv(int num_msg, const struct pam_message **msgm, cron_conv(int num_msg, const struct pam_message **msgm,
struct pam_response **response, void *appdata_ptr) struct pam_response **response ATTRIBUTE_UNUSED,
void *appdata_ptr ATTRIBUTE_UNUSED)
{ {
int i; int i;
@ -70,6 +86,7 @@ static int cron_open_pam_session(struct passwd *pw);
if (pam_session_opened != 0) \ if (pam_session_opened != 0) \
pam_close_session(pamh, PAM_SILENT); \ pam_close_session(pamh, PAM_SILENT); \
pam_end(pamh, retcode); \ pam_end(pamh, retcode); \
pamh = NULL; \
} \ } \
return(retcode); } return(retcode); }
#endif #endif
@ -82,13 +99,18 @@ static int cron_get_job_range(user * u, security_context_t * ucontextp,
char **jobenv); char **jobenv);
#endif #endif
void cron_restore_default_security_context() { void cron_restore_default_security_context(void) {
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
setexeccon(NULL); if (is_selinux_enabled() <= 0)
return;
if (setexeccon(NULL) < 0)
log_it("CRON", getpid(), "ERROR",
"failed to restore SELinux context", 0);
#endif #endif
} }
int cron_set_job_security_context(entry * e, user * u, char ***jobenv) { int cron_set_job_security_context(entry *e, user *u ATTRIBUTE_UNUSED,
char ***jobenv) {
time_t minutely_time = 0; time_t minutely_time = 0;
#ifdef WITH_PAM #ifdef WITH_PAM
int ret; int ret;
@ -99,26 +121,25 @@ int cron_set_job_security_context(entry * e, user * u, char ***jobenv) {
* Ensure that these jobs never run in the same minute: * Ensure that these jobs never run in the same minute:
*/ */
minutely_time = time(0); minutely_time = time(0);
Debug(DSCH, ("Minute-ly job. Recording time %lu\n", minutely_time)) Debug(DSCH, ("Minute-ly job. Recording time %lu\n", minutely_time));
} }
#ifdef WITH_PAM #ifdef WITH_PAM
if ((ret = cron_start_pam(e->pwd)) != 0) { /* PAM is called only for non-root users or non-system crontab */
if ((!u->system || e->pwd->pw_uid != 0) && (ret = cron_start_pam(e->pwd)) != 0) {
log_it(e->pwd->pw_name, getpid(), "FAILED to authorize user with PAM", log_it(e->pwd->pw_name, getpid(), "FAILED to authorize user with PAM",
pam_strerror(pamh, ret), 0); pam_strerror(pamh, ret), 0);
return -1; return -1;
} }
#endif #endif
*jobenv = build_env(e->envp);
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
/* we must get the crontab context BEFORE changing user, else /* we must get the crontab context BEFORE changing user, else
* we'll not be permitted to read the cron spool directory :-) * we'll not be permitted to read the cron spool directory :-)
*/ */
security_context_t ucontext = 0; security_context_t ucontext = 0;
if (cron_get_job_range(u, &ucontext, *jobenv) < OK) { if (cron_get_job_range(u, &ucontext, e->envp) < OK) {
log_it(e->pwd->pw_name, getpid(), "ERROR", log_it(e->pwd->pw_name, getpid(), "ERROR",
"failed to get SELinux context", 0); "failed to get SELinux context", 0);
return -1; return -1;
@ -135,7 +156,7 @@ int cron_set_job_security_context(entry * e, user * u, char ***jobenv) {
freecon(ucontext); freecon(ucontext);
#endif #endif
#ifdef WITH_PAM #ifdef WITH_PAM
if ((ret = cron_open_pam_session(e->pwd)) != 0) { if (pamh != NULL && (ret = cron_open_pam_session(e->pwd)) != 0) {
log_it(e->pwd->pw_name, getpid(), log_it(e->pwd->pw_name, getpid(),
"FAILED to open PAM security session", pam_strerror(pamh, ret), 0); "FAILED to open PAM security session", pam_strerror(pamh, ret), 0);
return -1; return -1;
@ -146,6 +167,8 @@ int cron_set_job_security_context(entry * e, user * u, char ***jobenv) {
return -1; return -1;
} }
*jobenv = build_env(e->envp);
time_t job_run_time = time(0L); time_t job_run_time = time(0L);
if ((minutely_time > 0) && ((job_run_time / 60) != (minutely_time / 60))) { if ((minutely_time > 0) && ((job_run_time / 60) != (minutely_time / 60))) {
@ -168,10 +191,10 @@ int cron_set_job_security_context(entry * e, user * u, char ***jobenv) {
return 0; return 0;
} }
#if defined(WITH_PAM)
int cron_start_pam(struct passwd *pw) { int cron_start_pam(struct passwd *pw) {
int retcode = 0; int retcode = 0;
#if defined(WITH_PAM)
retcode = pam_start("crond", pw->pw_name, &conv, &pamh); retcode = pam_start("crond", pw->pw_name, &conv, &pamh);
PAM_FAIL_CHECK; PAM_FAIL_CHECK;
retcode = pam_set_item(pamh, PAM_TTY, "cron"); retcode = pam_set_item(pamh, PAM_TTY, "cron");
@ -180,23 +203,23 @@ int cron_start_pam(struct passwd *pw) {
PAM_FAIL_CHECK; PAM_FAIL_CHECK;
retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED | PAM_SILENT); retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED | PAM_SILENT);
PAM_FAIL_CHECK; PAM_FAIL_CHECK;
#endif
return retcode; return retcode;
} }
#endif
static int cron_open_pam_session(struct passwd *pw) {
int retcode = 0;
#if defined(WITH_PAM) #if defined(WITH_PAM)
static int cron_open_pam_session(struct passwd *pw) {
int retcode;
retcode = pam_open_session(pamh, PAM_SILENT); retcode = pam_open_session(pamh, PAM_SILENT);
PAM_FAIL_CHECK; PAM_FAIL_CHECK;
if (retcode == PAM_SUCCESS) if (retcode == PAM_SUCCESS)
pam_session_opened = 1; pam_session_opened = 1;
#endif
return retcode; return retcode;
} }
#endif
void cron_close_pam(void) { void cron_close_pam(void) {
#if defined(WITH_PAM) #if defined(WITH_PAM)
@ -204,7 +227,10 @@ void cron_close_pam(void) {
pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT); pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT);
pam_close_session(pamh, PAM_SILENT); pam_close_session(pamh, PAM_SILENT);
} }
if (pamh != NULL) {
pam_end(pamh, PAM_SUCCESS); pam_end(pamh, PAM_SUCCESS);
pamh = NULL;
}
#endif #endif
} }
@ -224,7 +250,9 @@ int cron_change_groups(struct passwd *pw) {
#if defined(WITH_PAM) #if defined(WITH_PAM)
/* credentials may take form of supplementary groups so reinitialize /* credentials may take form of supplementary groups so reinitialize
* them here */ * them here */
if (pamh != NULL) {
pam_setcred(pamh, PAM_REINITIALIZE_CRED | PAM_SILENT); pam_setcred(pamh, PAM_REINITIALIZE_CRED | PAM_SILENT);
}
#endif #endif
return 0; return 0;
@ -247,9 +275,9 @@ int cron_change_user_permanently(struct passwd *pw, char *homedir) {
} }
#ifdef WITH_SELINUX
static int cron_authorize_context(security_context_t scontext, static int cron_authorize_context(security_context_t scontext,
security_context_t file_context) { security_context_t file_context) {
#ifdef WITH_SELINUX
struct av_decision avd; struct av_decision avd;
int retval; int retval;
security_class_t tclass; security_class_t tclass;
@ -276,13 +304,13 @@ static int cron_authorize_context(security_context_t scontext,
tclass, bit, &avd); tclass, bit, &avd);
if (retval || ((bit & avd.allowed) != bit)) if (retval || ((bit & avd.allowed) != bit))
return 0; return 0;
#endif
return 1; return 1;
} }
#endif
#ifdef WITH_SELINUX
static int cron_authorize_range(security_context_t scontext, static int cron_authorize_range(security_context_t scontext,
security_context_t ucontext) { security_context_t ucontext) {
#ifdef WITH_SELINUX
struct av_decision avd; struct av_decision avd;
int retval; int retval;
security_class_t tclass; security_class_t tclass;
@ -309,9 +337,9 @@ static int cron_authorize_range(security_context_t scontext,
if (retval || ((bit & avd.allowed) != bit)) if (retval || ((bit & avd.allowed) != bit))
return 0; return 0;
#endif
return 1; return 1;
} }
#endif
#if WITH_SELINUX #if WITH_SELINUX
/* always uses u->scontext as the default process context, then changes the /* always uses u->scontext as the default process context, then changes the
@ -389,7 +417,7 @@ static int cron_change_selinux_range(user * u, security_context_t ucontext) {
} }
} }
if (strcmp(u->scontext, ucontext)) { if (!ucontext || strcmp(u->scontext, ucontext)) {
if (!cron_authorize_range(u->scontext, ucontext)) { if (!cron_authorize_range(u->scontext, ucontext)) {
if (security_getenforce() > 0) { if (security_getenforce() > 0) {
# ifdef WITH_AUDIT # ifdef WITH_AUDIT
@ -424,7 +452,7 @@ static int cron_change_selinux_range(user * u, security_context_t ucontext) {
} }
} }
if (setexeccon(ucontext) < 0 || setkeycreatecon(ucontext) < 0) { if (setexeccon(ucontext) < 0) {
if (security_getenforce() > 0) { if (security_getenforce() > 0) {
if (asprintf if (asprintf
(&msg, "Could not set exec or keycreate context to %s for user", (&msg, "Could not set exec or keycreate context to %s for user",
@ -437,7 +465,7 @@ static int cron_change_selinux_range(user * u, security_context_t ucontext) {
else { else {
if (asprintf if (asprintf
(&msg, (&msg,
"Could not set exec or keycreate context to %s for user," "Could not set exec context to %s for user,"
" but SELinux in permissive mode, continuing", " but SELinux in permissive mode, continuing",
(char *) ucontext) >= 0) { (char *) ucontext) >= 0) {
log_it(u->name, getpid(), "WARNING", msg, 0); log_it(u->name, getpid(), "WARNING", msg, 0);
@ -450,13 +478,16 @@ static int cron_change_selinux_range(user * u, security_context_t ucontext) {
} }
#endif #endif
#ifdef WITH_SELINUX
int int
get_security_context(const char *name, int crontab_fd, get_security_context(const char *name, int crontab_fd,
security_context_t * rcontext, const char *tabname) { security_context_t * rcontext, const char *tabname) {
#ifdef WITH_SELINUX
security_context_t scontext = NULL; security_context_t scontext = NULL;
security_context_t file_context = NULL; security_context_t file_context = NULL;
int retval = 0; security_context_t rawcontext=NULL;
context_t current_context = NULL;
int retval;
char *current_context_str = NULL;
char *seuser = NULL; char *seuser = NULL;
char *level = NULL; char *level = NULL;
@ -468,12 +499,37 @@ get_security_context(const char *name, int crontab_fd,
if (name != NULL) { if (name != NULL) {
if (getseuserbyname(name, &seuser, &level) < 0) { if (getseuserbyname(name, &seuser, &level) < 0) {
log_it(name, getpid(), "getseuserbyname FAILED", name, 0); log_it(name, getpid(), "getseuserbyname FAILED", name, 0);
return (security_getenforce() > 0); return security_getenforce() > 0 ? -1 : 0;
}
} }
retval = get_default_context_with_level(name == NULL ? "system_u" : seuser, retval = get_default_context_with_level(seuser, level, NULL, &scontext);
level, NULL, &scontext); }
else {
const char *current_user, *current_role;
if (getcon(&current_context_str) < 0) {
log_it(name, getpid(), "getcon FAILED", "", 0);
return (security_getenforce() > 0);
}
current_context = context_new(current_context_str);
if (current_context == NULL) {
log_it(name, getpid(), "context_new FAILED", current_context_str, 0);
freecon(current_context_str);
return (security_getenforce() > 0);
}
current_user = context_user_get(current_context);
current_role = context_role_get(current_context);
retval = get_default_context_with_rolelevel(current_user, current_role, level, NULL, &scontext);
freecon(current_context_str);
context_free(current_context);
}
if (selinux_trans_to_raw_context(scontext, &rawcontext) == 0) {
freecon(scontext);
scontext = rawcontext;
}
free(seuser); free(seuser);
free(level); free(level);
if (retval) { if (retval) {
@ -528,21 +584,21 @@ get_security_context(const char *name, int crontab_fd,
freecon(file_context); freecon(file_context);
*rcontext = scontext; *rcontext = scontext;
#endif
return 0; return 0;
} }
#endif
void free_security_context(security_context_t * scontext) {
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
void free_security_context(security_context_t * scontext) {
if (*scontext != NULL) { if (*scontext != NULL) {
freecon(*scontext); freecon(*scontext);
*scontext = 0L; *scontext = 0L;
} }
#endif
} }
#endif
int crontab_security_access(void) {
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
int crontab_security_access(void) {
int selinux_check_passwd_access = -1; int selinux_check_passwd_access = -1;
if (is_selinux_enabled() > 0) { if (is_selinux_enabled() > 0) {
security_context_t user_context; security_context_t user_context;
@ -582,20 +638,28 @@ int crontab_security_access(void) {
return selinux_check_passwd_access; return selinux_check_passwd_access;
} }
#endif
return 0; return 0;
} }
#endif
/* Build up the job environment from the PAM environment plus the /* Build up the job environment from the PAM environment plus the
* crontab environment * crontab environment
*/ */
static char **build_env(char **cronenv) { static char **build_env(char **cronenv) {
char **jobenv;
#ifdef WITH_PAM #ifdef WITH_PAM
char **jobenv = cronenv;
char **pamenv = pam_getenvlist(pamh);
char *cronvar; char *cronvar;
int count = 0; int count = 0;
jobenv = env_copy(pamenv);
if (pamh == NULL || (jobenv=pam_getenvlist(pamh)) == NULL) {
#endif
jobenv = env_copy(cronenv);
if (jobenv == NULL)
log_it("CRON", getpid(),
"ERROR", "Initialization of cron environment variables failed", 0);
return jobenv;
#ifdef WITH_PAM
}
/* Now add the cron environment variables. Since env_set() /* Now add the cron environment variables. Since env_set()
* overwrites existing variables, this will let cron's * overwrites existing variables, this will let cron's
@ -609,7 +673,5 @@ static char **build_env(char **cronenv) {
} }
} }
return jobenv; return jobenv;
#else
return env_copy(cronenv);
#endif #endif
} }

View File

@ -19,6 +19,17 @@
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#ifndef CRONIE_STRUCTS_H
#define CRONIE_STRUCTS_H
#include <time.h>
#include <sys/types.h>
#ifdef WITH_SELINUX
#include <selinux/selinux.h>
#endif
#include "macros.h"
#include "bitstring.h"
typedef struct _entry { typedef struct _entry {
struct _entry *next; struct _entry *next;
struct passwd *pwd; struct passwd *pwd;
@ -30,6 +41,7 @@ typedef struct _entry {
bitstr_t bit_decl(month, MONTH_COUNT); bitstr_t bit_decl(month, MONTH_COUNT);
bitstr_t bit_decl(dow, DOW_COUNT); bitstr_t bit_decl(dow, DOW_COUNT);
int flags; int flags;
int delay;
#define MIN_STAR 0x01 #define MIN_STAR 0x01
#define HR_STAR 0x02 #define HR_STAR 0x02
#define DOM_STAR 0x04 #define DOM_STAR 0x04
@ -55,6 +67,7 @@ typedef struct _user {
time_t mtime; /* last modtime of crontab */ time_t mtime; /* last modtime of crontab */
entry *crontab; /* this person's crontab */ entry *crontab; /* this person's crontab */
security_context_t scontext; /* SELinux security context */ security_context_t scontext; /* SELinux security context */
int system; /* is it a system crontab */
} user; } user;
typedef struct _orphan { typedef struct _orphan {
@ -75,3 +88,5 @@ typedef struct _cron_db {
* variables for the main program, just * variables for the main program, just
* extern them elsewhere. * extern them elsewhere.
*/ */
#endif /* CRONIE_STRUCTS_H */

View File

@ -22,7 +22,15 @@
/* vix 26jan87 [log is in RCS file] /* vix 26jan87 [log is in RCS file]
*/ */
#include <cron.h> #include "config.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "funcs.h"
#include "globals.h"
static const char *FileName; static const char *FileName;
@ -36,13 +44,19 @@ void
free_user (user * u) { free_user (user * u) {
entry *e, *ne; entry *e, *ne;
if (!u) {
return;
}
free(u->name); free(u->name);
free(u->tabname); free(u->tabname);
for (e = u->crontab; e != NULL; e = ne) { for (e = u->crontab; e != NULL; e = ne) {
ne = e->next; ne = e->next;
free_entry(e); free_entry(e);
} }
#ifdef WITH_SELINUX
free_security_context(&(u->scontext)); free_security_context(&(u->scontext));
#endif
free(u); free(u);
} }
@ -53,59 +67,70 @@ load_user (int crontab_fd, struct passwd *pw, const char *uname,
FILE *file; FILE *file;
user *u; user *u;
entry *e; entry *e;
int status, save_errno = errno; int status = TRUE, save_errno = 0;
char **envp = NULL, **tenvp; char **envp = NULL, **tenvp;
int envs = 0, entries = 0;
if (!(file = fdopen(crontab_fd, "r"))) { if (!(file = fdopen(crontab_fd, "r"))) {
int save_errno = errno; save_errno = errno;
log_it(uname, getpid (), "FAILED", "fdopen on crontab_fd in load_user", log_it(uname, getpid (), "FAILED", "fdopen on crontab_fd in load_user",
save_errno); save_errno);
close(crontab_fd); close(crontab_fd);
return (NULL); return (NULL);
} }
Debug(DPARS, ("load_user()\n")) Debug(DPARS, ("load_user()\n"));
/* file is open. build user entry, then read the crontab file. /* file is open. build user entry, then read the crontab file.
*/ */
if ((u = (user *) malloc (sizeof (user))) == NULL) if ((u = (user *) malloc (sizeof (user))) == NULL) {
save_errno = errno;
goto done; goto done;
}
memset(u, 0, sizeof(*u)); memset(u, 0, sizeof(*u));
if (((u->name = strdup(fname)) == NULL) if (((u->name = strdup(fname)) == NULL)
|| ((u->tabname = strdup(tabname)) == NULL)) { || ((u->tabname = strdup(tabname)) == NULL)) {
save_errno = errno; save_errno = errno;
free_user(u);
u = NULL;
goto done; goto done;
} }
u->system = pw == NULL;
/* init environment. this will be copied/augmented for each entry. /* init environment. this will be copied/augmented for each entry.
*/ */
if ((envp = env_init()) == NULL) { if ((envp = env_init()) == NULL) {
save_errno = errno; save_errno = errno;
free_user(u);
u = NULL;
goto done; goto done;
} }
if (env_set_from_environ(&envp) == FALSE) {
save_errno = errno;
goto done;
}
#ifdef WITH_SELINUX
if (get_security_context(pw == NULL ? NULL : uname, if (get_security_context(pw == NULL ? NULL : uname,
crontab_fd, &u->scontext, tabname) != 0) { crontab_fd, &u->scontext, tabname) != 0) {
free_user (u);
u = NULL;
goto done; goto done;
} }
#endif
/* load the crontab /* load the crontab
*/ */
while ((status = load_env (envstr, file)) >= OK) { while (status >= OK) {
if (!skip_comments(file) && !u->system) {
log_error("too many garbage characters");
status = TRUE;
break;
}
status = load_env (envstr, file);
switch (status) { switch (status) {
case ERR:
save_errno = errno;
free_user(u);
u = NULL;
goto done;
case FALSE: case FALSE:
++entries;
if (!u->system && entries > MAX_USER_ENTRIES) {
log_error("too many entries");
status = TRUE;
goto done;
}
FileName = tabname; FileName = tabname;
e = load_entry(file, log_error, pw, envp); e = load_entry(file, log_error, pw, envp);
if (e) { if (e) {
@ -114,10 +139,13 @@ load_user (int crontab_fd, struct passwd *pw, const char *uname,
} }
break; break;
case TRUE: case TRUE:
++envs;
if (!u->system && envs > MAX_USER_ENVS) {
log_error("too many environment variables");
goto done;
}
if ((tenvp = env_set (envp, envstr)) == NULL) { if ((tenvp = env_set (envp, envstr)) == NULL) {
save_errno = errno; save_errno = errno;
free_user(u);
u = NULL;
goto done; goto done;
} }
envp = tenvp; envp = tenvp;
@ -126,10 +154,16 @@ load_user (int crontab_fd, struct passwd *pw, const char *uname,
} }
done: done:
if (status == TRUE) {
log_it(uname, getpid(), "FAILED", "loading cron table",
save_errno);
free_user(u);
u = NULL;
}
if (envp) if (envp)
env_free(envp); env_free(envp);
fclose(file); fclose(file);
Debug(DPARS, ("...load_user() done\n")) Debug(DPARS, ("...load_user() done\n"));
errno = save_errno; errno = save_errno;
return (u); return (u);
} }