Initial commit.

This commit is contained in:
依瑪貓 2021-02-06 08:59:23 +08:00
commit 3d641859e1
32 changed files with 4544 additions and 0 deletions

1
AUTHORS Normal file
View File

@ -0,0 +1 @@
imacat <imacat@mail.imacat.idv.tw>

1
AUTHORS.zh-cn Normal file
View File

@ -0,0 +1 @@
依玛猫 <imacat@mail.imacat.idv.tw>

1
AUTHORS.zh-tw Normal file
View File

@ -0,0 +1 @@
依瑪貓 <imacat@mail.imacat.idv.tw>

674
COPYING Normal file
View File

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. 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
them 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 prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. 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.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey 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;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If 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 convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU 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 that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
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.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
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.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
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
state 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 3 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, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program 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, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU 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. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

133
ChangeLog Normal file
View File

@ -0,0 +1,133 @@
vsntp change log
2013-11-13
Does not work on x86_64 yet. Don't know whether it still works on i386.
I don't have i386 anymore.
1. vsntp.c: Removed the weird method to calculate the next time line
for synchronization. It was my bad taste to synchronize at the
the time of multiples of interval. When many clients are
synchronized to a same server, synchronizing them at a same time
will overload the server and create DDoS. Thanks to the reminder of
Steven Shen <fbishen@gmail.com>.
2. AUTHORS.zh-tw, INSTALL.zh-tw, NEWS.zh-tw, README.zh-tw, THANKS.zh-tw,
init.d/README.zh-tw: Converted from Big5 to UTF-8. I'm not woking
on Windows anymore. Big5 cause problem with gedit.
3. AUTHORS.zh-cn, INSTALL.zh-cn, NEWS.zh-cn, README.zh-cn, THANKS.zh-cn,
init.d/README.zh-cn: Converted from GB2312 to UTF-8. I'm not woking
on Windows anymore. GB2312 cause problem with gedit.
4. configure: Updated with GNU Autoconf 2.69.
2007-11-28
1. ChangeLog.zh-tw, ChangeLog.zh-cn: Removed.
2. COPYING.zh-tw, COPYING.zh-cn: Removed.
3. License updated to GPLv3.
4. Removed Traditional Chinese comments.
2004-03-29 version 2.0.0
1. vsntp.c: The syhchronization scheduler has been rewritten to
allow alternative schedulers, in order to work with the problem
reported by Jean-Alain Le Borgne <jalb@pobox.com> 2007-03-26,
that sleep() may not return after MS Virtual PC 2007 was suspended
for a while.
2. vsntp.c: An alternative schedular using alarm() was added in
addition to sleep(), based on the contribution by Jean-Alain.
3. vsntp.c: New subroutine setsigalrm() was added to set the SIGALRM
signal handler.
4. vsntp.c: New subroutine alarm_wakeup() was added as the alarm()
schedular.
5. vsntp.c: Two new constants SCHEDULER_SLEEP and SCHEDULER_ALARM were
added as the scheduler choices of the user.
6. vsntp.c: Two new switches -a/--alarm and -s/--sleep were added for
the user to choose the scheduler. The default is currently -s.
7. vsntp.c: New variable "scheduler" added to as the scheduler choice
of the user.
8. vsntp.c: Variable "next" was made global so that the alarm()
scheduler can access it, too.
9. vsntp.c: Check the return value of synctime() so that skip logging
when time was not adjusted (time correct or network error).
10. vsntp.c: Logging of time synchronization after the first time
was added, in log level LOG_DEBUG.
11. vsntp.c: errstart is now calculated and maintained in synctime()
instead of neterror(), in order to log the time sequence of the
network errors.
12. vsntp.c: Re-formatting error messages and warnings according to
the GNU Coding Standards, as:
source-file-name:lineno: message
Refer to: http://www.gnu.org/prep/standards/html_node/Errors.html
13. vsntp.c: Added logging before connect(), send() and recv() at
log level LOG_DEBUG in order to know the current progress when
debugging network problems.
14. vsntp.c: Added logging of value t1, t2, t3, t4 and toff in log
level LOG_DEBUG in order to debug time calculation problems.
15. vsntp.c: New subroutine xsigemptyset() was added to run
sigemptyset() and handle its error. setsigalrm() was updated
to use xsigemptyset() instead of sigemptyset().
16. vsntp.c: New subroutine xsigaction() was added to run sigaction()
and handle its error. setsigalrm() was updated to use xsigaction()
instead of sigaction().
17. vsntp.c: English comment fix. "... and handle errors" was updated
as "... and handle its error."
18. configure.ac: Added AC_TYPE_SSIZE_T, and added "alarm()" in
AC_CHECK_FUNCS, acccording to the suggestion by automake 1.9.6.
19. configure.in and aclocal.m4: Regenrated using automake 1.9.6.
20. configure: Regenrated using autoconf 2.61.
21. vsntp.c: Added conditional #ifdef, so that if alarm() is not
supported on the target platform the alarm() scheduler will not
be compiled.
22. vsntp.c: A new constant DEFAULT_SCHEDULER was added as the
default scheduler.
23. Added init.d directory, with a Debian SysV init script, a Red Hat
SysV init script, a configuration file used by the init scripts,
and README in 3 languages.
24. Added doc directory, and moved vsntp.texi, vsntp.8 and rfc1769.txt
inside.
25. vsntp.c: Fixed the basic profile in the beginning comment, from
synctime.c to vsntp.c. That was the first name of vsntp. It was
renamed for years.
26. vsntp.8: Fixed the BUGS chapter, replacing the originall text with
the SourceForge users' mailing list information.
27. README, vsntp.8 and vsntp.texi: Added notes about the scheduler
issue.
28. README, vsntp.8 and vsntp.texi: Added notes about how to debug.
29. README, vsntp.8 and vsntp.texi: Added notes about portability.
30. README, vsntp.8 and vsntp.texi: Added requests to users to let me
know that someone is using vsntp. :p
2004-01-14 version 1.1.1
Documentation fix.
1. ChangeLog and NEWS year typo fixed. (2003 -> 2004)
2. Home site at SourceForge done.
3. Documentation revised on official website, other reference
information.
4. Documentation revised on wordings and typos.
2004-01-13
1. HTML page at Tavern IMACAT's done.
2. texinfo document revised.
2004-01-12 version 1.1.0
First public release.
1. Added texinfo documentation.
2. Added -i and -p switch.
3. Default synchronization interval changed to 900 seconds, do avoid
making troubles with foreign NTP servers.
2004-01-11
1. Added automake and autoconf.
2. Added documentation: README, INSTALL, COPYING, ChangeLog, NEWS,
AUTHORS, THANKS, and manpage.
2004-01-10
1. The SourceForge project space approved.
2004-01-09
1. Applying a SourceForge project space.
2003-12-24 version 1.0.0
Finalized.
1. Program name changed from "synctime" to "vsntp".
2. Protocol changed from RFC 868 Time to RFC 1769 SNTP.
3. Synchronization interval shortened to 5 seconds.
2003-12-23
Start writing, with a name as "synctime".

84
INSTALL Normal file
View File

@ -0,0 +1,84 @@
vsntp Installation and Running Procedure
1. Compilation and Installation Procedure
vsntp uses standard GNU autoconf to compile and install:
1. Download, unzip and untar the vsntp package:
% tar xzf vsntp-x.x.x.tar.gz
2. Go into its directory:
% cd vsntp-x.x.x
3. Configure with ./configure:
% ./configure
4. Compile with make:
% make
The resulted executable will be named "vsntp".
5. You need to be root in order to install vsntp:
% su
Password:
#
6. You can simply copy vsntp to the appropriate directory:
# cp vsntp /usr/local/sbin
Or, you can run automatic install:
# make install
You can reduce the size of the installed executable by
stripping off debug symbols inside:
# make install-strip
By default vsntp will be installed in /usr/local/sbin .
2. Compilation and Installation Options
GNU autoconf configure provides the following options:
--prefix=PREFIX install architecture-independent files in PREFIX
[/usr/local]
--exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
[PREFIX]
--bindir=DIR user executables [EPREFIX/bin]
--sbindir=DIR system admin executables [EPREFIX/sbin]
--libexecdir=DIR program executables [EPREFIX/libexec]
--datadir=DIR read-only architecture-independent data [PREFIX/share]
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
--infodir=DIR info documentation [PREFIX/info]
--mandir=DIR man documentation [PREFIX/man]
Type `./configure --help' for a detailed list of compilation options.
3. Run
You need to be root to run vsntp. vsntp uses settimeofday() to
set the system time. settimeofday() requires root privilege.
To start vsntp, just specify your NTP server:
# vsntp my.ntp.server.com
vsntp writes its PID in /var/run/vsntp.pid. To stop vsntp,
kill it by its PID:
# kill `cat /var/run/vsntp.pid`
The PID file location can be changed with the `-p' switch.

81
INSTALL.zh-cn Normal file
View File

@ -0,0 +1,81 @@
vsntp 安装执行说明
一、编译安装程序
vsntp 使用标准的 GNU autoconf 来安装编译:
1. 下载 vsntp 并解压缩:
% tar xzf vsntp-x.x.x.tar.gz
2. 进入 vsntp 的子目录:
% cd vsntp-x.x.x
3. 执行 ./configure 设定:
% ./configure
4. 以 make 编译:
% make
编译出来的档案为 vsntp 。
5. 要安装程式,你可能要先 su 到 root ,用 root 的权限安装:
% su
Password:
#
6. 将 vsntp 档复制到适当的目录即可:
# cp vsntp /usr/local/sbin
或者,你也可以用自动安装:
# make install
或用 install-strip 清除档案里的除错符号,安装起来档案比较小:
# make install-strip
用上述方式安装时, vsntp 预设安装目录在 /usr/local/sbin 。
二、编译安装选项
GNU autoconf 的 configure 提供下列的编译安装选项:
--prefix=PREFIX 作业平台无关的档案装在 PREFIX 下 [/usr/local]
--exec-prefix=EPREFIX 作业平台专用的档案装在 EPREFIX 下 [PREFIX]
--bindir=DIR 一般使用者用的执行档 [EPREFIX/bin]
--sbindir=DIR 系统管理者用的执行档 [EPREFIX/sbin]
--libexecdir=DIR 程式内部引用的执行档 [EPREFIX/libexec]
--datadir=DIR 与作业平台无关的唯读资料 [PREFIX/share]
--sysconfdir=DIR 本系统专用的唯读资料 [PREFIX/etc]
--sharedstatedir=DIR 与作业平台无关的异动资料 [PREFIX/com]
--localstatedir=DIR 本系统专用的异动资料 [PREFIX/var]
--libdir=DIR 目的码程式库 [EPREFIX/lib]
--includedir=DIR C 语言标头档 [PREFIX/include]
--oldincludedir=DIR 非 gcc 用的 C 语言标头档 [/usr/include]
--infodir=DIR info 说明文件 [PREFIX/info]
--mandir=DIR man 说明文件 [PREFIX/man]
完整的编译安装选项,请参阅 ./configure --help 的说明。
三、执行
要有 root 权限才能执行 vsntp 。 vsntp 用 settimeofday() 对时,没
有 root 权限不能执行 settimeofday() 。
要启动 vsntp ,加上对时用的 ntp server 即可:
# vsntp my.ntp.server.com
vsntp 会把 PID 存在 /var/run/vsntp.pid 。要结束程式,只要 kill 它
的 PID 即可:
# kill `cat /var/run/vsntp.pid`
你可以用 -p 选项,更改 PID 档的位置。

81
INSTALL.zh-tw Normal file
View File

@ -0,0 +1,81 @@
vsntp 安裝執行說明
一、編譯安裝程序
vsntp 使用標準的 GNU autoconf 法編譯安裝:
1. 下載 vsntp 並解壓縮:
% tar xzf vsntp-x.x.x.tar.gz
2. 進入 vsntp 的子目錄:
% cd vsntp-x.x.x
3. 執行 ./configure 設定:
% ./configure
4. 以 make 編譯:
% make
編譯出來的檔案為 vsntp 。
5. 要安裝程式,妳可能要先 su 到 root ,用 root 的權限安裝:
% su
Password:
#
6. 將 vsntp 檔複製到適當的目錄即可:
# cp vsntp /usr/local/sbin
或者,妳也可以用自動安裝:
# make install
妳也可以邊裝邊清掉檔案裏的除錯符號,安裝起來檔案比較小:
# make install-strip
用上述方式安裝時, vsntp 預設安裝目錄在 /usr/local/sbin 。
二、編譯安裝選項
GNU autoconf 的 configure 提供下列的編譯安裝選項:
--prefix=PREFIX 作業平台無關的檔案裝在 PREFIX 下 [/usr/local]
--exec-prefix=EPREFIX 作業平台專用的檔案裝在 EPREFIX 下 [PREFIX]
--bindir=DIR 一般使用者用的執行檔 [EPREFIX/bin]
--sbindir=DIR 系統管理者用的執行檔 [EPREFIX/sbin]
--libexecdir=DIR 程式內部引用的執行檔 [EPREFIX/libexec]
--datadir=DIR 與作業平台無關的唯讀資料 [PREFIX/share]
--sysconfdir=DIR 本系統專用的唯讀資料 [PREFIX/etc]
--sharedstatedir=DIR 與作業平台無關的異動資料 [PREFIX/com]
--localstatedir=DIR 本系統專用的異動資料 [PREFIX/var]
--libdir=DIR 目的碼程式庫 [EPREFIX/lib]
--includedir=DIR C 語言標頭檔 [PREFIX/include]
--oldincludedir=DIR 非 gcc 用的 C 語言標頭檔 [/usr/include]
--infodir=DIR info 說明文件 [PREFIX/info]
--mandir=DIR man 說明文件 [PREFIX/man]
完整的編譯安裝選項,請參閱 ./configure --help 的說明。
三、執行
要有 root 權限才能執行 vsntp 。 vsntp 用 settimeofday() 對時,沒
有 root 權限不能執行 settimeofday() 。
要啟動 vsntp ,加上對時用的 NTP server 即可:
# vsntp my.ntp.server.com
vsntp 會把 PID 存在 /var/run/vsntp.pid 。要結束程式,只要 kill 它
的 PID 即可:
# kill `cat /var/run/vsntp.pid`
妳可以用 -p 選項,更改 PID 檔的位置。

25
Makefile.am Normal file
View File

@ -0,0 +1,25 @@
## Makefile.in template file for vsntp
## Process this file with automake to produce Makefile.in
##
## Copyright (c) 2003-2007 imacat
##
## 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 3 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, see <http://www.gnu.org/licenses/>.
AUTOMAKE_OPTIONS = gnits
sbin_PROGRAMS = vsntp
vsntp_SOURCES = vsntp.c
EXTRA_DIST = README.* INSTALL.* NEWS.* AUTHORS.* THANKS.*
SUBDIRS = doc init.d

31
NEWS Normal file
View File

@ -0,0 +1,31 @@
vsntp NEWS
2007-03-29 version 2.0.0
1. Added alarm() in addition to sleep() as an alternative
synchronization scheduler, in order to fix a problem that vsntp
sleep() may stop working after MS Virtual PC 2007 was suspended
for a while, as reported and suggested by Jean-Alain Le Borgne
<jalb@pobox.com> 2007-03-26. The codes are based on
Jean-Alain's contribution. Thank you. Two new switches "-a" and
"-s" were added for for setting the schedular. Currently the
default is -s (sleep()). If you find vsntp stops synchronization
after running for some time, that the sleep() is not functioning
normally on your system, you may try to switch to alarm() using
the "-a" switch.
2. More debugging information were logged, in the syslog log level
LOG_DEBUG with log facility LOG_DAEMON.
3. Two SysV-styled init scripts are provided for convenience in the
init.d subdirectory. Check the README file in that directory for
more information.
2004-01-14 version 1.1.1
Documentation fix.
1. Reference information revised.
2004-01-12 version 1.1.0
First public release.
1. Added -i and -p switch.
2. Documentation added.
2003-12-24 version 1.0.0
First version.

25
NEWS.zh-cn Normal file
View File

@ -0,0 +1,25 @@
vsntp 新版功能:
2007-03-29 2.0.0 版
1. 加上 alarm() ,作为 sleep() 之外的另一种计时器,以解决
Jean-Alain Le Borgne <jalb@pobox.com> 於 2007-03-26 所回报与建议
的, MS Virtual PC 2007 在暂停一段时间后复原, sleep() 定时会醒不
来的问题。程式由 Jean-Alain 贡献的修正码改写而成,在此致谢。新增两
个选项 -a 与 -s ,以设定要用的计时器。目前预设为 -s ,使用 sleep()
呼叫定时。若你 vsntp 校时一段时间后就不动了,系统的 sleep() 呼叫有
问题时,可以加上 -a 选项,改用 alarm() 定时。
2. 加上更多侦错的 syslog 记录讯息,大多记录於 LOG_DEBUG 层级。
3. 在 init.d 目录下,提供两个 SysV 的启动程式,以便大家使用。请查阅
init.d 目录下 README 档案的说明。
2004-01-14 1.1.1 版
修订说明文件。
1. 修订参考资料。
2004-01-12 1.1.0 版
正式公开发行。
1. 加上 -i 与 -p 选项。
2. 加上说明文件。
2003-12-24 1.0.0 版
第一版。

25
NEWS.zh-tw Normal file
View File

@ -0,0 +1,25 @@
vsntp 新版功能:
2007-03-29 2.0.0 版
1. 加上 alarm() ,作為 sleep() 之外的另一種計時器,以解決
Jean-Alain Le Borgne <jalb@pobox.com> 於 2007-03-26 所回報與建議
的, MS Virtual PC 2007 在暫停一段時間後復原, sleep() 定時會醒不
來的問題。程式由 Jean-Alain 貢獻的修正碼改寫而成,在此致謝。新增兩
個選項 -a 與 -s ,以設定要用的計時器。目前預設為 -s ,使用 sleep()
呼叫定時。若妳 vsntp 校時一段時間後就不動了,系統的 sleep() 呼叫有
問題時,可以加上 -a 選項,改用 alarm() 定時。
2. 加上更多偵錯的 syslog 記錄訊息,大多記錄於 LOG_DEBUG 層級。
3. 在 init.d 目錄下,提供兩個 SysV 的啟動程式,以便大家使用。詳情請查
閱 init.d 目錄下 README 檔案的說明。
2004-01-14 1.1.1 版
修訂說明文件。
1. 修訂參考資料。
2004-01-12 1.1.0 版
正式公開發行。
1. 加上 -i 與 -p 選項。
2. 加上說明文件。
2003-12-24 1.0.0 版
第一版。

102
README Normal file
View File

@ -0,0 +1,102 @@
vsntp README
See INSTALL for details on how to install and run vsntp.
Obtaining the Newest Information
vsntp's official website is at...
SourceForge's home site: http://vsntp.sourceforge.net/
SourceForge's project page: https://sourceforge.net/projects/vsntp/
Tavern IMACAT's page: http://www.imacat.idv.tw/tech/vsntp.html
You can always download the newest version of vsntp from...
SourceForge: https://sourceforge.net/project/showfiles.php?group_id=99098
Tavern IMACAT's FTP: ftp://ftp.imacat.idv.tw/pub/vsntp/
imacat's PGP public key is at...
SourceForge: http://vsntp.sourceforge.net/pgpkey.asc
Tavern IMACAT's: http://www.imacat.idv.tw/me/pgpkey.asc
Introduction:
vsntp is an SNTP client daemon for machines without a sane system
time. The word "vsntp" stands for "SNTP for Virtual PC". It was
originally designed for my GNU/Linux server running on Connectix
Virtual PC. It runs according to RFC 1769 SNTP, connecting the NTP
server on UDP port 123.
Without Virtual PC Additions, the system time on Virtual PC is
completely insane. It's RTC (Real Time Clock, or CMOS time, or
hardware clock) is software emulated, which does not seems to be
running. The GNU/Linux kernel hardly maintains a system time itself.
With smooth run it goes 4 seconds ahead per minute, which is nearly
1.5 hours per day. That is insane. You can even tell it with your
eyes.
David L. Mills' ntp does not work here. It uses a method that
learns the clock frequency drift first, and adjust the kerenl clock
with adjtimex() so that time adjustment goes smoothly, from the point
of view of system and applications. This assumes an existing fix-
speed system clock. But this is not the case of Virtual PC. The
system clock on Virtual PC is software emulated. It can be faster
or slower now and then, depending on the load of the hosting machine.
There is no fixed clock speed. The frequency drift does not exist,
then. It dooms to fail to measure it.
There is an sntp client that comes with David L. Mills' ntp
package. It is suggested to be run from crontab. But crontab runs
by minutes, and Virtual PC goes 4 seconds ahead per minute. Rolling
back 4 seconds every minute is insane for most applications. It also
increases system load heavily to run one instance per minute.
vsntp is a workaround on this. It runs as a daemon to eliminates
the additional system load on every synchronization. It uses
settimeofday() to synchronize the time. It synchronizes the time
with an arbitrary interval, so that time can be accurate within a
second.
There are some defects. Synchronizing the time too often
introduces heavy network load. It introduces heavy load on the
target NTP server, too. You should have a working NTP server nearby
that is owned by you. Also, since settimeofday() is called so often,
high-accurate time operations like timer, etc., may not run
correctly.
vsntp uses sleep() as the synchronization scheduler. Reports show
that on some systems sleep() may not function normally. If you find
vsntp stops synchronization after running for some time, that the
sleep() is not functioning normally on your system, you may want to
switch to the alarm() scheduler with the "-a" switch.
If you ever encounter any problem, you may check your syslog.
vsntp logs detailed debugging information to syslog in log level
LOG_DEBUG with facility LOG_DAEMON. You may turn it on in your
/etc/syslog.conf with the following line:
daemon.debug /var/log/debug
and check the /var/log/debug file for the debugging message. Remember
to remove this afterwards, for the amount of the debugging messages
may be huge and may use up your harddisk in a very short time. To the
least it may slow down your system for frequent harddisk I/O.
vsntp was originally written for GNU/Linux. It uses POSIX
compatible system calls. It should work on any POSIX compatible
system. But I have yet only tested it on Cygwin. Cygwin is known to
work. I don't have others to test and run on. Please let me know
(and submit the patch if needed) if you can port it to other systems.
I know it does not work on MSWin32, for the way it handles the PID
file path.
Please tell me if you have successfully running vsntp on other
virtual machines, like VMWare.
Generally, please tell me if you are using vsntp. I would like
to know that I am really doing some good for the world, *^_^* but not
having fun myself. :p
This is my first daemon, my first socket program and my first
public-released C program. Any comment or suggestion is welcome. ^_*'

82
README.zh-cn Normal file
View File

@ -0,0 +1,82 @@
vsntp 读我说明
请参阅 INSTALL 档案,以取得安装执行的相关说明。
想知道 vsntp 的最新消息,下载最新版本,请参阅:
http://vsntp.sourceforge.net/
http://sourceforge.net/projects/vsntp
http://www.imacat.idv.tw/tech/vsntp.html
ftp://ftp.imacat.idv.tw/pub/vsntp/
作者的 PGP Public Key 可在下列网址下载:
http://www.imacat.idv.tw/me/pgpkey.txt
简介:
vsntp 是 SNTP 客户端服务程式,专为时间不正常的系统设计。 vsntp
的意思是 SNTP for Virtual PC ,原先是我为了在 Connectix Virtual PC
上跑 GNU/Linux 系统而写。 vsntp 依 RFC 1769 SNTP 标准,连线到 SNTP 伺
服器上的 UDP 埠 123 以校时。
若没有装 Virtual PC Additions Virtual PC 的时间很乱。 Virtual
PC 的 RTC Real Time Clock, 或称 CMOS 时钟、硬体时钟)是用软体模拟
出来的,往往根本没有在跑。 GNU/Linux 核心勉强维持一个大概的时间。正常
情况下,平均一分钟会快四秒,一天快一个半小时。这实在是太夸张了,用眼
睛都分辨得出时钟速度有问题。
David L. Mills 的 ntp 校时伺服器在此完全失灵。 ntp 先测出系统时间
速度偏移,用 adjtimex() 来调整系统时钟速度,用这个方法渐近式调整,系
统本身和相关应用程式比较不会出问题。这个方法有一个前提:时间速度本身
恒定不变。可是 Virtual PC 不讲这一套。 Virtual PC 的时间纯粹是软体模
拟出来的,受主电脑负荷与其它因素影响,时快时慢。没有固定的时间速度,
也就没有时间速度偏移值。怎么测都是枉然。
David L. Mills 的 ntp 程式里,附了一 sntp 客户端程式,可以放在
crontab 里定期对时,对时完结束程式。问题是, crontab 最小单位为分,
顶多一分钟跑一次,可是 Virtual PC 的时间一分钟慢四秒。一分钟退回四秒
,大多数应用程式都受不了。一分钟跑一次,对系统的负荷也很大。
vsntp 是为此而写的。它以 daemon 来执行,以免每次对时都对系统造成
严重负荷。它用 settimeofday() 来调整时间,校时频率可任意设定,尽可能
把系统时钟误差,维持在一秒以内。
vsntp 的做法有下列缺陷:频繁校时时,网路流量很大,频宽的负荷不小
,对对方 NTP 伺服器也会造成很大的负担。你最好自己在区网内,架一台自
己的 NTP 伺服器。同时因 settimeofday() 强制时间设定太频繁了,系统的
高精度计时功能会出问题。
  vsntp 用 sleep() 呼叫来定时校时。在某些系统上 sleep() 可能不大正
常。若 vsntp 校时一段时间后就不动了,系统上的 sleep() 呼叫不正常时,
可以改用 -a 选项换成 alarm() 计时器试看看。
  若碰到任何问题,请参阅你系统的上的 syslog 记录。 vsntp 把详细侦错
讯息,都以 LOG_DEBUG 层次, LOG_DAEMON 类别记录到 syslog 中。你可以在
/etc/syslog.conf 中加上这一行,写入侦错讯息:
daemon.debug /var/log/debug
并查阅 /var/log/debug 中的侦错讯息。记得在侦错结束后关闭。侦错讯息流
量很大,很快就会塞爆硬碟。就算没塞爆,大量资料写入硬碟,对系统效能的
影响也很大。
   vsntp 原是为 GNU/Linux 系统上执行而写。 vsntp 用的都是 POSIX 相
容的系统呼叫,在 POSIX 相容系统上应该都可以执行。不过目前为止我只有
Cygwin ,只在 Cygwin 上测试过。 Cygwin 上可以执行。若你可以成功在其它
系统上执行,请来信告知。若需要任何原始程式的修正,亦请一并附给我。我
知道因为 PID 档路径处理方式,所以无法在 MSWin32 上执行。
  vsntp 只在 GNU/Linux 系统上测试执行过。 vsntp 用的都是 POSIX 相容
的系统呼叫,在 POSIX 相容系统上应该都可以执行。不过我没有其它系统,无
从测试起。若你可以成功在其它系统上执行,请来信告知。若需要任何原始程式
的修正,亦请一并附给我。我知道因为 PID 档路径处理方式,所以无法在
MSWin32 上执行。但在 Cygwin 上说不定可以执行。
  若你可以在其它虚拟机器上执行 vsntp ,例如 VMWare ,请来信告知。
  基本上,若你在用 vsntp ,请一定要来信告诉我。我很想知道 vsntp 是
不是真的有人在用,对世界和平有帮助 *^_^* 或只是自己写好玩的而已。 :p
vsntp 是我写的第一个 daemon ,我写的第一个 socket 程式,也是我第
一个公开发行的 C 程式。请多多指教~ ^_*'

82
README.zh-tw Normal file
View File

@ -0,0 +1,82 @@
vsntp 讀我說明
請參閱 INSTALL 檔案,以取得安裝執行的相關說明。
想知道 vsntp 的最新消息,下載最新版本,請參閱:
http://vsntp.sourceforge.net/
http://sourceforge.net/projects/vsntp
http://www.imacat.idv.tw/tech/vsntp.html
ftp://ftp.imacat.idv.tw/pub/vsntp/
作者的 PGP Public Key 可在下列網址下載:
http://www.imacat.idv.tw/me/pgpkey.txt
簡介:
vsntp 是 SNTP 客戶端服務程式,專為時間不正常的系統設計。 vsntp
的意思是 SNTP for Virtual PC ,原先是我為了在 Connectix Virtual PC
上跑 GNU/Linux 系統而寫。 vsntp 依 RFC 1769 SNTP 標準,連線到 SNTP 伺
服器上的 UDP 埠 123 以校時。
若沒有裝 Virtual PC Additions Virtual PC 的時間很亂。 Virtual
PC 的 RTC Real Time Clock, 或稱 CMOS 時鐘、硬體時鐘)是用軟體模擬
出來的,往往根本沒有在跑。 GNU/Linux 核心勉強維持一個大概的時間。正常
情況下,平均一分鐘會快四秒,一天快一個半小時。這實在是太誇張了,用眼
睛都分辨得出時鐘速度有問題。
David L. Mills 的 ntp 校時伺服器在此完全失靈。 ntp 先測出系統時間
速度偏移,用 adjtimex() 來調整系統時鐘速度,用這個方法漸近式調整,系
統本身和相關應用程式比較不會出問題。這個方法有一個前提:時間速度本身
恆定不變。可是 Virtual PC 不講這一套。 Virtual PC 的時間純粹是軟體模
擬出來的,受主電腦負荷與其它因素影響,時快時慢。沒有固定的時間速度,
也就沒有時間速度偏移值。怎麼測都是枉然。
David L. Mills 的 ntp 程式裏,附了一 sntp 客戶端程式,可以放在
crontab 裏定期對時,對時完結束程式。問題是, crontab 最小單位為分,
頂多一分鐘跑一次,可是 Virtual PC 的時間一分鐘慢四秒。一分鐘退回四秒
,大多數應用程式都受不了。一分鐘跑一次,對系統的負荷也很大。
vsntp 是為此而寫的。它以 daemon 來執行,以免每次對時都對系統造成
嚴重負荷。它用 settimeofday() 來調整時間,校時頻率可任意設定,儘可能
把系統時鐘誤差,維持在一秒以內。
vsntp 的做法有下列缺陷:頻繁校時時,網路流量很大,頻寬的負荷不小
,對對方 NTP 伺服器也會造成很大的負擔。妳最好自己在區網內,架一台自
己的 NTP 伺服器。同時因 settimeofday() 強制時間設定太頻繁了,系統的
高精度計時功能會出問題。
  vsntp 用 sleep() 呼叫來定時校時。在某些系統上 sleep() 可能不大正
常。若 vsntp 校時一段時間後就不動了,系統上的 sleep() 呼叫不正常時,
可以改用 -a 選項換成 alarm() 計時器試看看。
  若碰到任何問題,請參閱妳系統的上的 syslog 記錄。 vsntp 把詳細偵錯
訊息,都以 LOG_DEBUG 層次, LOG_DAEMON 類別記錄到 syslog 中。妳可以在
/etc/syslog.conf 中加上這一行,寫入偵錯訊息:
daemon.debug /var/log/debug
並查閱 /var/log/debug 中的偵錯訊息。記得在偵錯結束後關閉。偵錯訊息流
量很大,很快就會塞爆硬碟。就算沒塞爆,大量資料寫入硬碟,對系統效能的
影響也很大。
   vsntp 原是為 GNU/Linux 系統上執行而寫。 vsntp 用的都是 POSIX 相
容的系統呼叫,在 POSIX 相容系統上應該都可以執行。不過目前為止我只有
Cygwin ,只在 Cygwin 上測試過。 Cygwin 上可以執行。若妳可以成功在其它
系統上執行,請來信告知。若需要任何原始程式的修正,亦請一併附給我。我
知道因為 PID 檔路徑處理方式,所以無法在 MSWin32 上執行。
  vsntp 只在 GNU/Linux 系統上測試執行過。 vsntp 用的都是 POSIX 相容
的系統呼叫,在 POSIX 相容系統上應該都可以執行。不過我沒有其它系統,無
從測試起。若妳可以成功在其它系統上執行,請來信告知。若需要任何原始程式
的修正,亦請一併附給我。我知道因為 PID 檔路徑處理方式,所以無法在
MSWin32 上執行。但在 Cygwin 上說不定可以執行。
  若妳可以在其它虛擬機器上執行 vsntp ,例如 VMWare ,請來信告知。
  基本上,若妳在用 vsntp ,請一定要來信告訴我。我很想知道 vsntp 是
不是真的有人在用,對世界和平有幫助 *^_^* 或只是自己寫好玩的而已。 :p
vsntp 是我寫的第一個 daemon ,我寫的第一個 socket 程式,也是我第
一個公開發行的 C 程式。請多多指教~ ^_*'

7
THANKS Normal file
View File

@ -0,0 +1,7 @@
Thanks to SourceForge's people to kindly provide hosting of the
vsntp project.
Thanks to Jean-Alain Le Borgne <jalb@pobox.com> to debug and find out
the sleep() scheduler problem when MS Virtual PC 2007 suspended for a while,
file a bug report and provide a fix with an alternative scheduler alarm()
on 2007-03-26.

5
THANKS.zh-cn Normal file
View File

@ -0,0 +1,5 @@
感谢 SourceForge 热心提供架设 vsntp 。
感谢 Jean-Alain Le Borgne <jalb@pobox.com> 於 2007-03-26 侦错并找出
以 sleep() 定时,在 MS Virtual PC 2007 暂停一段时间后恢复,会醒不来的问题,
回报该问题,并提供 alarm() 作为替代的定时器的修正程式。

5
THANKS.zh-tw Normal file
View File

@ -0,0 +1,5 @@
感謝 SourceForge 熱心提供架設 vsntp 。
感謝 Jean-Alain Le Borgne <jalb@pobox.com> 於 2007-03-26 偵錯並找出
以 sleep() 定時,在 MS Virtual PC 2007 暫停一段時間後恢復,會醒不來的問題,
回報該問題,並提供 alarm() 作為替代的定時器的修正程式。

122
config.h.in Normal file
View File

@ -0,0 +1,122 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the `alarm' function. */
#undef HAVE_ALARM
/* Define to 1 if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H
/* Define to 1 if you have the `fork' function. */
#undef HAVE_FORK
/* Define to 1 if you have the `gethostbyname' function. */
#undef HAVE_GETHOSTBYNAME
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#undef HAVE_MALLOC
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the <netdb.h> header file. */
#undef HAVE_NETDB_H
/* Define to 1 if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H
/* Define to 1 if you have the `socket' function. */
#undef HAVE_SOCKET
/* 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 `strerror' function. */
#undef HAVE_STRERROR
/* 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 you have the <syslog.h> header file. */
#undef HAVE_SYSLOG_H
/* Define to 1 if you have the <sys/socket.h> header file. */
#undef HAVE_SYS_SOCKET_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/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 <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `vfork' function. */
#undef HAVE_VFORK
/* Define to 1 if you have the <vfork.h> header file. */
#undef HAVE_VFORK_H
/* Define to 1 if `fork' works. */
#undef HAVE_WORKING_FORK
/* Define to 1 if `vfork' works. */
#undef HAVE_WORKING_VFORK
/* 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 to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Version number of package */
#undef VERSION
/* Define to rpl_malloc if the replacement function should be used. */
#undef malloc
/* 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> does not define. */
#undef ssize_t
/* Define as `fork' if `vfork' does not work. */
#undef vfork

32
configure.ac Normal file
View File

@ -0,0 +1,32 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT([vsntp], [2.1.0], [imacat@mail.imacat.idv.tw])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([vsntp.c])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
# Checks for header files.
AC_CHECK_HEADERS([arpa/inet.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h syslog.h unistd.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_TYPE_SSIZE_T
# Checks for library functions.
AC_FUNC_ERROR_AT_LINE
AC_FUNC_FORK
AC_FUNC_MALLOC
AC_CHECK_FUNCS([alarm gethostbyname gettimeofday socket strerror])
AC_CONFIG_FILES([Makefile
doc/Makefile
init.d/Makefile])
AC_OUTPUT

25
doc/Makefile.am Normal file
View File

@ -0,0 +1,25 @@
## Makefile.in template file for vsntp documentation
## Process this file with automake to produce Makefile.in
##
## Copyright (c) 2007 imacat
##
## 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 3 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, see <http://www.gnu.org/licenses/>.
AUTOMAKE_OPTIONS = gnits
info_TEXINFOS = vsntp.texi
man8_MANS = vsntp.8
dist_man8_MANS = $(man8_MANS)
EXTRA_DIST = rfc1769.txt

787
doc/rfc1769.txt Normal file
View File

@ -0,0 +1,787 @@
Network Working Group D. Mills
Request for Comments: 1769 University of Delaware
Obsoletes: 1361 March 1995
Category: Informational
Simple Network Time Protocol (SNTP)
Status of this Memo
This memo provides information for the Internet community. This memo
does not specify an Internet standard of any kind. Distribution of
this memo is unlimited.
Abstract
This memorandum describes the Simple Network Time Protocol (SNTP),
which is an adaptation of the Network Time Protocol (NTP) used to
synchronize computer clocks in the Internet. SNTP can be used when
the ultimate performance of the full NTP implementation described in
RFC-1305 is not needed or justified. It can operate in both unicast
modes (point to point) and broadcast modes (point to multipoint). It
can also operate in IP multicast mode where this service is
available. SNTP involves no change to the current or previous NTP
specification versions or known implementations, but rather a
clarification of certain design features of NTP which allow operation
in a simple, stateless remote-procedure call (RPC) mode with accuracy
and reliability expectations similar to the UDP/TIME protocol
described in RFC-868.
This memorandum obsoletes RFC-1361 of the same title. Its purpose is
to explain the protocol model for operation in broadcast mode, to
provide additional clarification in some places and to correct a few
typographical errors. A working knowledge of the NTP Version 3
specification RFC-1305 is not required for an implementation of SNTP.
Distribution of this memorandum is unlimited.
1. Introduction
The Network Time Protocol (NTP) specified in RFC-1305 [MIL92] is used
to synchronize computer clocks in the global Internet. It provides
comprehensive mechanisms to access national time and frequency
dissemination services, organize the time-synchronization subnet and
adjust the local clock in each participating subnet peer. In most
places of the Internet of today, NTP provides accuracies of 1-50 ms,
depending on the characteristics of the synchronization source and
network paths.
Mills [Page 1]
RFC 1769 SNTP March 1995
RFC-1305 specifies the NTP protocol machine in terms of events,
states, transition functions and actions and, in addition, optional
algorithms to improve the timekeeping quality and mitigate among
several, possibly faulty, synchronization sources. To achieve
accuracies in the low milliseconds over paths spanning major portions
of the Internet of today, these intricate algorithms, or their
functional equivalents, are necessary. However, in many cases
accuracies of this order are not required and something less, perhaps
in the order of large fractions of the second, is sufficient. In such
cases simpler protocols such as the Time Protocol [POS83], have been
used for this purpose. These protocols usually involve an RPC
exchange where the client requests the time of day and the server
returns it in seconds past some known reference epoch.
NTP is designed for use by clients and servers with a wide range of
capabilities and over a wide range of network delays and jitter
characteristics. Most users of the Internet NTP synchronization
subnet of today use a software package including the full suite of
NTP options and algorithms, which are relatively complex, real-time
applications. While the software has been ported to a wide variety of
hardware platforms ranging from supercomputers to personal computers,
its sheer size and complexity is not appropriate for many
applications. Accordingly, it is useful to explore alternative access
strategies using far simpler software appropriate for less stringent
accuracy expectations.
This memorandum describes the Simple Network Time Protocol (SNTP),
which is a simplified access strategy for servers and clients using
NTP as now specified and deployed in the Internet. There are no
changes to the protocol or implementations now running or likely to
be implemented in the near future. The access paradigm is identical
to the UDP/TIME Protocol and, in fact, it should be easily possible
to adapt a UDP/TIME client implementation, say for a personal
computer, to operate using SNTP. Moreover, SNTP is also designed to
operate in a dedicated server configuration including an integrated
radio clock. With careful design and control of the various latencies
in the system, which is practical in a dedicated design, it is
possible to deliver time accurate to the order of microseconds.
It is strongly recommended that SNTP be used only at the extremities
of the synchronization subnet. SNTP clients should operate only at
the leaves (highest stratum) of the subnet and in configurations
where no NTP or SNTP client is dependent on another SNTP client for
synchronization. SNTP servers should operate only at the root
(stratum 1) of the subnet and then only in configurations where no
other source of synchronization other than a reliable radio clock is
available. The full degree of reliability ordinarily expected of
primary servers is possible only using the redundant sources, diverse
Mills [Page 2]
RFC 1769 SNTP March 1995
subnet paths and crafted algorithms of a full NTP implementation.
This extends to the primary source of synchronization itself in the
form of multiple radio clocks and backup paths to other primary
servers should the radio clock fail or deliver incorrect time.
Therefore, the use of SNTP rather than NTP in primary servers should
be carefully considered.
2. Operating Modes and Addressing
Like NTP, SNTP can operate in either unicast (point to point) or
broadcast (point to multipoint) modes. A unicast client sends a
request to a server and expects a reply from which it can determine
the time and, optionally, the roundtrip delay and local clock offset
relative to the server. A broadcast server periodically sends a
message to a designated IP broadcast address or IP multicast group
address and ordinarily expects no requests from clients, while a
broadcast client listens on this address and ordinarily sends no
requests to servers. Some broadcast servers may elect to respond to
client requests as well as send unsolicited broadcast messages, while
some broadcast clients may elect to send requests only in order to
determine the network propagation delay between the server and
client.
In unicast mode the client and server IP addresses are assigned
following the usual conventions. In broadcast mode the server uses a
designated IP broadcast address or IP multicast group address,
together with a designated media-access broadcast address, and the
client listens on these addresses. For this purpose, an IP broadcast
address has scope limited to a single IP subnet, since routers do not
propagate IP broadcast datagrams. In the case of Ethernets, for
example, the Ethernet media-access broadcast address (all ones) is
used with an IP address consisting of the IP subnet number in the net
field and all ones in the host field.
On the other hand, an IP multicast group address has scope extending
to potentially the entire Internet. The actual scope, group
membership and routing are determined by the Internet Group
Management Protocol (IGMP) [DEE89] and various routing protocols,
which are beyond the scope of this document. In the case of
Ethernets, for example, the Ethernet media-access broadcast address
(all ones) is used with the assigned IP multicast group address of
224.0.1.1. Other than the IP addressing conventions and IGMP, there
is no difference in server operations with either the IP broadcast
address or IP multicast group address.
Broadcast clients listen on the designated media-access broadcast
address, such as all ones in the case of Ethernets. In the case of IP
broadcast addresses, no further provisions are necessary. In the case
Mills [Page 3]
RFC 1769 SNTP March 1995
of IP multicast group addresses, the host may need to implement IGMP
in order that the local router intercepts messages to the 224.0.1.1
multicast group. These considerations are beyond the scope of this
document.
In the case of SNTP as specified herein, there is a very real
vulnerability that SNTP multicast clients can be disrupted by
misbehaving or hostile SNTP or NTP multicast servers elsewhere in the
Internet, since at present all such servers use the same IP multicast
group address 224.0.1.1. Where necessary, access control based on the
server source address can be used to select only those servers known
to and trusted by the client. Alternatively, by convention and
informal agreement, all NTP multicast servers now include an MD5-
encrypted message digest in every message, so that clients can
determine if the message is authentic and not modified in transit. It
is in principle possible that SNTP clients could implement the
necessary encryption and key-distribution schemes, but this is
considered not likely in the simple systems for which SNTP is
intended.
While not integral to the SNTP specification, it is intended that IP
broadcast addresses will be used primarily in IP subnets and LAN
segments including a fully functional NTP server with a number of
SNTP clients in the same subnet, while IP multicast group addresses
will be used only in special cases engineered for the purpose. In
particular, IP multicast group addresses should be used in SNTP
servers only if the server implements the NTP authentication scheme
described in RFC-1305, including support for the MD5 message-digest
algorithm.
3. NTP Timestamp Format
SNTP uses the standard NTP timestamp format described in RFC-1305 and
previous versions of that document. In conformance with standard
Internet practice, NTP data are specified as integer or fixed-point
quantities, with bits numbered in big-endian fashion from 0 starting
at the left, or high-order, position. Unless specified otherwise, all
quantities are unsigned and may occupy the full field width with an
implied 0 preceding bit 0.
Since NTP timestamps are cherished data and, in fact, represent the
main product of the protocol, a special timestamp format has been
established. NTP timestamps are represented as a 64-bit unsigned
fixed-point number, in seconds relative to 0h on 1 January 1900. The
integer part is in the first 32 bits and the fraction part in the
last 32 bits. In the fraction part, the non-significant low-order
bits should be set to 0. This format allows convenient multiple-
precision arithmetic and conversion to UDP/TIME representation
Mills [Page 4]
RFC 1769 SNTP March 1995
(seconds), but does complicate the conversion to ICMP Timestamp
message representation (milliseconds). The precision of this
representation is about 200 picoseconds, which should be adequate for
even the most exotic requirements.
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Seconds |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Seconds Fraction (0-padded) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Note that, since some time in 1968 the most significant bit (bit 0 of
the integer part) has been set and that the 64-bit field will
overflow some time in 2036. Should NTP or SNTP be in use in 2036,
some external means will be necessary to qualify time relative to
1900 and time relative to 2036 (and other multiples of 136 years).
Timestamped data requiring such qualification will be so precious
that appropriate means should be readily available. There will exist
a 200-picosecond interval, henceforth ignored, every 136 years when
the 64-bit field will be 0, which by convention is interpreted as an
invalid or unavailable timestamp.
4. NTP Message Format
Both NTP and SNTP are clients of the User Datagram Protocol (UDP)
[POS80], which itself is a client of the Internet Protocol (IP)
[DAR81]. The structure of the IP and UDP headers is described in the
cited specification documents and will not be described further here.
The UDP port number assigned to NTP is 123, which should be used in
both the Source Port and Destination Port fields in the UDP header.
The remaining UDP header fields should be set as described in the
specification.
Mills [Page 5]
RFC 1769 SNTP March 1995
Following is a description of the SNTP message format, which follows
the IP and UDP headers. The SNTP message format is identical to the
NTP format described in RFC-1305, with the exception that some of the
data fields are "canned," that is, initialized to pre-specified
values. The format of the NTP message is shown below.
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|LI | VN |Mode | Stratum | Poll | Precision |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Root Delay |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Root Dispersion |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reference Identifier |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Reference Timestamp (64) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Originate Timestamp (64) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Receive Timestamp (64) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Transmit Timestamp (64) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| |
| Authenticator (optional) (96) |
| |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
As described in the next section, in SNTP most of these fields are
initialized with pre-specified data. For completeness, the function
of each field is briefly summarized below.
Mills [Page 6]
RFC 1769 SNTP March 1995
Leap Indicator (LI): This is a two-bit code warning of an impending
leap second to be inserted/deleted in the last minute of the current
day, with bit 0 and bit 1, respectively, coded as follows:
LI Value Meaning
-------------------------------------------------------
00 0 no warning
01 1 last minute has 61 seconds
10 2 last minute has 59 seconds)
11 3 alarm condition (clock not synchronized)
Version Number (VN): This is a three-bit integer indicating the NTP
version number, currently 3.
Mode: This is a three-bit integer indicating the mode, with values
defined as follows:
Mode Meaning
------------------------------------
0 reserved
1 symmetric active
2 symmetric passive
3 client
4 server
5 broadcast
6 reserved for NTP control message
7 reserved for private use
In unicast mode the client sets this field to 3 (client) in the
request and the server sets it to 4 (server) in the reply. In
broadcast mode the server sets this field to 5 (broadcast).
Stratum: This is a eight-bit unsigned integer indicating the stratum
level of the local clock, with values defined as follows:
Stratum Meaning
----------------------------------------------
0 unspecified or unavailable
1 primary reference (e.g., radio clock)
2-15 secondary reference (via NTP or SNTP)
16-255 reserved
Poll Interval: This is an eight-bit signed integer indicating the
maximum interval between successive messages, in seconds to the
nearest power of two. The values that can appear in this field
presently range from 4 (16 s) to 14 (16284 s); however, most
applications use only the sub-range 6 (64 s) to 10 (1024 s).
Mills [Page 7]
RFC 1769 SNTP March 1995
Precision: This is an eight-bit signed integer indicating the
precision of the local clock, in seconds to the nearest power of two.
The values that normally appear in this field range from -6 for
mains-frequency clocks to -20 for microsecond clocks found in some
workstations.
Root Delay: This is a 32-bit signed fixed-point number indicating the
total roundtrip delay to the primary reference source, in seconds
with fraction point between bits 15 and 16. Note that this variable
can take on both positive and negative values, depending on the
relative time and frequency offsets. The values that normally appear
in this field range from negative values of a few milliseconds to
positive values of several hundred milliseconds.
Root Dispersion: This is a 32-bit unsigned fixed-point number
indicating the nominal error relative to the primary reference
source, in seconds with fraction point between bits 15 and 16. The
values that normally appear in this field range from 0 to several
hundred milliseconds.
Reference Clock Identifier: This is a 32-bit code identifying the
particular reference source. In the case of stratum 0 (unspecified)
or stratum 1 (primary reference), this is a four-octet, left-
justified, 0-padded ASCII string. While not enumerated as part of the
NTP specification, the following are representative ASCII
identifiers:
Stratum Code Meaning
----------------------------------------------------------------
1 pps precision calibrated source, such as ATOM (atomic
clock), PPS (precision pulse-per-second source),
etc.
1 service generic time service other than NTP, such as ACTS
(Automated Computer Time Service), TIME (UDP/Time
Protocol), TSP (Unix Time Service Protocol), DTSS
(Digital Time Synchronization Service), etc.
1 radio Generic radio service, with callsigns such as CHU,
DCF77, MSF, TDF, WWV, WWVB, WWVH, etc.
1 nav radionavigation system, such as OMEG (OMEGA), LORC
(LORAN-C), etc.
1 satellite generic satellite service, such as GOES
(Geostationary Orbit Environment Satellite, GPS
(Global Positioning Service), etc.
2 address secondary reference (four-octet Internet address of
the NTP server)
Mills [Page 8]
RFC 1769 SNTP March 1995
Reference Timestamp: This is the time at which the local clock was
last set or corrected, in 64-bit timestamp format.
Originate Timestamp: This is the time at which the request departed
the client for the server, in 64-bit timestamp format.
Receive Timestamp: This is the time at which the request arrived at
the server, in 64-bit timestamp format.
Transmit Timestamp: This is the time at which the reply departed the
server for the client, in 64-bit timestamp format.
Authenticator (optional): When the NTP authentication mechanism is
implemented, this contains the authenticator information defined in
Appendix C of RFC-1305. In SNTP this field is ignored for incoming
messages and is not generated for outgoing messages.
5. SNTP Client Operations
The model for n SNTP client operating with either a NTP or SNTP
server is a RPC client with no persistent state. In unicast mode, the
client sends a client request (mode 3) to the server and expects a
server reply (mode 4). In broadcast mode, the client sends no request
and waits for a broadcast message (mode 5) from one or more servers,
depending on configuration. Unicast client and broadcast server
messages are normally sent at periods from 64 s to 1024 s, depending
on the client and server configurations.
A unicast client initializes the SNTP message header, sends the
message to the server and strips the time of day from the reply. For
this purpose all of the message-header fields shown above are set to
0, except the first octet. In this octet the LI field is set to 0 (no
warning) and the Mode field is set to 3 (client). The VN field must
agree with the software version of the NTP or SNTP server; however,
NTP Version 3 (RFC-1305) servers will also accept Version 2 (RFC-
1119) and Version 1 (RFC-1059) messages, while NTP Version 2 servers
will also accept NTP Version 1 messages. Version 0 (RFC-959) messages
are no longer supported. Since there are NTP servers of all three
versions interoperating in the Internet of today, it is recommended
that the VN field be set to 1.
In both unicast and broadcast modes, the unicast server reply or
broadcast message includes all the fields described above; however,
in SNTP only the Transmit Timestamp has explicit meaning and then
only if nonzero. The integer part of this field contains the server
time of day in the same format as the UDP/TIME Protocol [POS83].
While the fraction part of this field will usually be valid, the
accuracy achieved with SNTP may justify its use only to a significant
Mills [Page 9]
RFC 1769 SNTP March 1995
fraction of a second. If the Transmit Timestamp field is 0, the
message should be disregarded.
In broadcast mode, a client has no additional information to
calculate the propagation delay between the server and client, as the
Transmit Timestamp and Receive Timestamp fields have no meaning in
this mode. Even in unicast mode, most clients will probably elect to
ignore the Originate Timestamp and Receive Timestamp fields anyway.
However, in unicast mode a simple calculation can be used to provide
the roundtrip delay d and local clock offset t relative to the
server, generally to within a few tens of milliseconds. To do this,
the client sets the Originate Timestamp in the request to the time of
day according to its local clock converted to NTP timestamp format.
When the reply is received, the client determines a Destination
Timestamp as the time of arrival according to its local clock
converted to NTP timestamp format. The following table summarizes the
four timestamps.
Timestamp Name ID When Generated
------------------------------------------------------------
Originate Timestamp T1 time request sent by client
Receive Timestamp T2 time request received at server
Transmit Timestamp T3 time reply sent by server
Destination Timestamp T4 time reply received at client
The roundtrip delay d and local clock offset t are defined as
d = (T4 - T1) - (T2 - T3)
t = ((T2 - T1) + (T3 - T4)) / 2.
The following table is a summary of the SNTP client operations. There
are two recommended error checks shown in the table. In all NTP
versions, if the LI field is 3, or the Stratum field is not in the
range 1-15, or the Transmit Timestamp is 0, the server has never
synchronized or not synchronized to a valid timing source within the
last 24 hours. At the client discretion, the values of the remaining
fields can be checked as well. Whether to believe the transmit
timestamp or not in case one or more of these fields appears invalid
is at the discretion of the implementation.
Mills [Page 10]
RFC 1769 SNTP March 1995
Field Name Request Reply
-------------------------------------------------------------
LI 0 leap indicator; if 3
(unsynchronized), disregard
message
VN 1 (see text) ignore
Mode 3 (client) ignore
Stratum 0 ignore
Poll 0 ignore
Precision 0 ignore
Root Delay 0 ignore
Root Dispersion 0 ignore
Reference Identifier 0 ignore
Reference Timestamp 0 ignore
Originate Timestamp 0 (see text) ignore (see text)
Receive Timestamp 0 ignore (see text)
Transmit Timestamp 0 time of day; if 0
(unsynchronized), disregard
message
Authenticator (not used) ignore
6. SNTP Server Operations
The model for a SNTP server operating with either a NTP or SNTP
client is an RPC server with no persistent state. Since a SNTP server
ordinarily does not implement the full set of NTP algorithms intended
to support redundant peers and diverse network paths, it is
recommended that a SNTP server be operated only in conjunction with a
source of external synchronization, such as a reliable radio clock.
In this case the server always operates at stratum 1.
A server can operate in unicast mode, broadcast mode or both at the
same time. In unicast mode the server receives a request message,
modifies certain fields in the NTP or SNTP header, and returns the
message to the sender, possibly using the same message buffer as the
request. The server may or may not respond if not synchronized to a
correctly operating radio clock, but the preferred option is to
respond, since this allows reachability to be determined regardless
of synchronization state. In unicast mode, the VN and Poll fields of
the request are copied intact to the reply. If the Mode field of the
request is 3 (client), it is set to 4 (server) in the reply;
otherwise, this field is set to 2 (symmetric passive) in order to
conform to the NTP specification.
In broadcast mode, the server sends messages only if synchronized to
a correctly operating reference clock. In this mode, the VN field is
set to 3 (for the current SNTP version), and the Mode field to 5
(broadcast). The Poll field is set to the server poll interval, in
Mills [Page 11]
RFC 1769 SNTP March 1995
seconds to the nearest power of two. It is highly desirable that, if
a server supports broadcast mode, it also supports unicast mode. This
is necessary so a potential broadcast client can calculate the
propagation delay using client/server messages prior to regular
operation using only broadcast messages.
The remaining fields are set in the same way in both unicast and
broadcast modes. Assuming the server is synchronized to a radio clock
or other primary reference source and operating correctly, the
Stratum field is set to 1 (primary server) and the LI field is set to
0; if not, the Stratum field is set to 0 and the LI field is set to
3. The Precision field is set to reflect the maximum reading error of
the local clock. For all practical cases it is computed as the
negative of the number of significant bits to the right of the
decimal point in the NTP timestamp format. The Root Delay and Root
Dispersion fields are set to 0 for a primary server; optionally, the
Root Dispersion field can be set to a value corresponding to the
maximum expected error of the radio clock itself. The Reference
Identifier is set to designate the primary reference source, as
indicated in the table above.
The timestamp fields are set as follows. If the server is
unsynchronized or first coming up, all timestamp fields are set to
zero. If synchronized, the Reference Timestamp is set to the time the
last update was received from the radio clock or, if unavailable, to
the time of day when the message is sent. The Receive Timestamp and
Transmit Timestamp fields are set to the time of day when the message
is sent. In unicast mode, the Originate Timestamp field is copied
unchanged from the Transmit Timestamp field of the request. It is
important that this field be copied intact, as a NTP client uses it
to check for replays. In broadcast mode, this field is set to the
time of day when the message is sent. The following table summarizes
these actions.
Mills [Page 12]
RFC 1769 SNTP March 1995
Field Name Request Reply
----------------------------------------------------------
LI ignore 0 (normal), 3
(unsynchronized)
VN 1, 2 or 3 3 or copied from request
Mode 3 (see text) 2, 4 or 5 (see text)
Stratum ignore 1 server stratum
Poll ignore copied from request
Precision ignore server precision
Root Delay ignore 0
Root Dispersion ignore 0 (see text)
Reference Identifier ignore source identifier
Reference Timestamp ignore 0 or time of day
Originate Timestamp ignore 0 or time of day or copied
from Transmit Timestamp of
request
Receive Timestamp ignore 0 or time of day
Transmit Timestamp (see text) 0 or time of day
Authenticator ignore (not used)
There is some latitude on the part of most clients to forgive invalid
timestamps, such as might occur when first coming up or during
periods when the primary reference source is inoperative. The most
important indicator of an unhealthy server is the LI field, in which
a value of 3 indicates an unsynchronized condition. When this value
is displayed, clients should discard the server message, regardless
of the contents of other fields.
7. References
[DAR81] Postel, J., "Internet Protocol - DARPA Internet Program
Protocol Specification", STD 5, RFC 791, DARPA, September 1981.
[DEE89] Deering, S., "Host Extensions for IP Multicasting. STD 5,
RFC 1112, Stanford University, August 1989.
[MIL92] Mills, D., "Network Time Protocol (Version 3) Specification,
Implementation and Analysis. RFC 1305, University of Delaware,
March 1992.
[POS80] Postel, J., "User Datagram Protocol", STD 6, RFC 768,
USC/Information Sciences Institute, August 1980.
[POS83] Postel, J., and K. Harrenstien, "Time Protocol", STD 26,
RFC 868, USC/Information Sciences Institute, SRI, May 1983.
Mills [Page 13]
RFC 1769 SNTP March 1995
Security Considerations
Security issues are not discussed in this memo.
Author's Address
David L. Mills
Electrical Engineering Department
University of Delaware
Newark, DE 19716
Phone: (302) 831-8247
EMail: mills@udel.edu
Mills [Page 14]

219
doc/vsntp.8 Normal file
View File

@ -0,0 +1,219 @@
.\" Process this file with
.\" groff -man -Tascii vsntp.8
.\"
.TH VSNTP 8 "MARCH 2007" VSNTP "System Administration Tools"
.SH NAME
vsntp \- SNTP client for Virtual PC
.SH SYNOPSIS
.BI "vsntp [-i " n "] [-p " file "] [-a|-s] " server
.SH DESCRIPTION
.B vsntp
is an
.SM SNTP
client daemon for machines without a sane system time. The word
.B vsntp
stands for
.BR "SNTP for Virtual PC" .
It was originally designed for my
.I GNU/Linux
server running on Connectix Virtual PC. It runs according to
.SM RFC
1769
.SM SNTP
, connecting the
.SM NTP
server on
.SM UDP
port 123. It has only been compiled and run on
.I GNU/Linux
before.
Without "Virtual
.SM PC
Additions", the system time on Virtual
.SM PC
is completely insane. It's
.SM RTC
(Real Time Clock, or
.SM CMOS
time, or hardware clock) is software emulated, which does not seems
to be running. The
.I GNU/Linux
kernel hardly maintains a system time itself. With smooth run it
goes 4 seconds ahead per minute, which is nearly 1.5 hours per day.
That is insane. You can even tell it with your eyes.
David L. Mills'
.B ntp
does not work here. It uses a method that learns the clock frequency
drift first, and adjust the kerenl clock with
.B adjtimex()
so that time adjustment goes smoothly, from the point of view of
system and applications. This assumes an existing fix-speed system
clock. But this is not the case here. The system clock on Virtual
.SM PC
is software emulated. It goes faster or slower now and then,
depending on the load of the hosting machine. There is no fixed
clock speed. The frequency drift does not exist, then. It dooms to
fail to measure it.
There is an
.B sntp
client that comes with David L. Mills'
.B ntp
package.
It is suggested to be run from crontab. But crontab runs by minutes,
and Virtual
.SM PC
goes 4 seconds ahead per minute. Rolling back 4 seconds every minute
is insane for most applications. It also increases system load
heavily to run one instance per minute.
.B vsntp
is a workaround on this. It runs as a daemon to to eliminates the
additional system load on every synchronization. It uses
.B settimeofday()
to synchronize the time. It synchronizes the
time with an arbitrary interval, so that time can be accurate within
a second.
There are some defects. Synchronizing the time too often introduces
heavy network load. It introduces heavy load on the target
.SM NTP
server, too. You should have a working
.SM NTP
server nearby that is owned by you. Also, since
.B settimeofday()
is called so often, highly-accurate time operations like timer, etc.,
may not run correctly.
.B vsntp
uses
.BI sleep()
as the synchronization scheduler. Reports show that on some systems
.BI sleep()
may not function normally. If you find
.BI vsntp
stops synchronization after running for some time, that the
.BI sleep()
is not functioning normally on your system, you may want to switch
to the
.BI alarm()
scheduler with the
.B -a
switch.
.B vsntp
was originally written for
.I GNU/Linux .
It uses
.SM POSIX
compatible system calls. It should work on any
.SM POSIX
compatible system. But I have yet only tested it on Cygwin. Cygwin
is known to work. I don't have others to test and run on. Please let
me know (and submit the patch if needed) if you can port it to other
systems. I know it does not work on MSWin32, for the way it handles
the
.SM PID
file path.
Please tell me if you have successfully running vsntp on other virtual
machines, like
.BR "VMWare" .
Generally, please tell me if you are using
.B "vsntp" .
I would like to know that I am really doing some good for the world,
*^_^* but not having fun myself. :p
This is my first daemon, my first socket program and my first
public-released C program. Any comment or suggestion is welcome. ^_*'
.SH OPTIONS
.IP "-i,--interval n"
Set the synchronization interval to
.I n
seconds. Default is 900 seconds (15 minutes).
.IP "-p,--pidfile file"
The
.SM PID
file location. Default to
.IR /var/run/vsntp.pid .
.IP -s,--sleep
Use
.BI sleep()
as the scheduler. This is currently the default.
.IP -a,--alarm
Use
.BI alarm()
as the scheduler.
.IP -h,--help
Display the help message.
.IP -v,--version
Display version information.
.SH FILES
.I /var/run/vsntp.pid
.RS
The
.SM PID
of the running daemon.
.SH DIAGNOSTICS
If you ever encounter any problem, you may check your syslog.
.B vsntp
logs detailed debugging information to syslog in log level
.B LOG_DEBUG
with facility
.B LOG_DAEMON .
You may turn it on in your
.I /etc/syslog.conf
with the following line:
daemon.debug /var/log/debug
and check the
.I /var/log/debug
file for the debugging message. Remember to remove this afterwards,
for the amount of the debugging messages may be huge and may use up
your harddisk in a very short time. To the least it may slow down
your system for frequent harddisk
.SM "I/O" .
.SH BUGS
.B vsntp
is hosted on SourceForge and Tavern IMACAT's. For the latest
infomation, see:
http://vsntp.sourceforge.net/
https://sourceforge.net/projects/vsntp/
http://www.imacat.idv.tw/tech/vsntp.html
.B vsntp has a mailing list hosted at SourceForge:
vsntp-users@lists.sourceforge.net . Please submit your questions,
suggestions or bug reports there. It is a Mailman mailing list.
For more information, see:
https://lists.sourceforge.net/lists/listinfo/vsntp-users
Alternatively, you can send a mail to:
vsntp-users-request@lists.sourceforge.net with the subject
.B help
for a list of available e-mail commands.
.SH AUTHOR
imacat <imacat@mail.imacat.idv.tw>.
.SH "SEE ALSO"
.BR settimeofday (2),
.BR adjtimex (2),
.BR sleep (3),
.BR alarm (2).
.BR ntp :
http://www.ntp.org/ .
.SM RFC
1769
.SM SNTP
: http://www.faqs.org/rfcs/rfc1769.html .
.SM RFC
1305
.SM NTP
: http://www.faqs.org/rfcs/rfc1305.html .

410
doc/vsntp.texi Normal file
View File

@ -0,0 +1,410 @@
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename vsntp.info
@include version.texi
@settitle vsntp v@value{VERSION}
@syncodeindex vr cp
@syncodeindex pg cp
@c %**end of header
@copying
This manual is for vsntp
(version @value{VERSION}, @value{UPDATED}),
a SNTP daemon for Virtual @acronym{PC}@.
Copyright @copyright{} 2003-2007 imacat@.
@quotation
Permission is granted to copy, distribute and/or modify this document
under the terms of the @acronym{GNU} Free Documentation License, Version 1.2
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts@.
A copy of the license is included in the section entitled ``@acronym{GNU}
Free Documentation License''@.
@end quotation
@end copying
@titlepage
@title vsntp v@value{VERSION}
@c The following two commands start the copyright page.
@page
@vskip 0pt plus 1filll
@insertcopying
Published by imacat@*
@email{imacat@@mail.imacat.idv.tw}@*
@uref{http://www.imacat.idv.tw/}@*
@end titlepage
@c Output the table of contents at the beginning.
@contents
@ifnottex
@node Top
@top Short Sample
@insertcopying
@end ifnottex
@menu
* Introduction::
* Download the Newest Version: Download.
* Compilation and Installation: Install.
* Running and Stopping: Run.
* Command Line Options: Options.
* Supports and Bugs Report: Support.
* References::
* Copyright::
* Index::
@end menu
@node Introduction
@chapter Introduction
@pindex Virtual PC
@pindex Connectix Virtual PC
@cindex RFC 1769 SNTP
@cindex UDP
@dfn{vsntp} is an @acronym{SNTP} client daemon for machines without a
sane system time@. The word ``@dfn{vsntp}'' stands for
``@dfn{@acronym{SNTP} for Virtual PC}''@. It was originally designed
for my @acronym{GNU}/Linux server running on Connectix Virtual @acronym{PC}@.
It runs according to @acronym{RFC} 1769 @acronym{SNTP}, connecting
the @acronym{NTP} server on @acronym{UDP} port 123@. It was originally
written for @acronym{GNU}/Linux@.
Without Virtual @acronym{PC} Additions, the system time on Virtual @acronym{PC} is
completely insane@. It's @acronym{RTC} (Real Time Clock, or
@acronym{CMOS} time, or hardware clock) is software emulated, which
does not seems to be running@. The @acronym{GNU}/Linux kernel hardly
maintains a system time itself@. With smooth run it goes 4 seconds
ahead per minute, which is nearly 1.5 hours per day@. That is
insane@. You can even tell it with your eyes@.
@pindex David L. Mills
@pindex ntp
@findex adjtimex()
@uref{http://www.ntp.org/,David L. Mills' @command{ntp}} does not
work here@. It uses a method that learns the clock frequency drift
first, and adjust the kerenl clock with @code{adjtimex()} so that
time adjustment goes smoothly, from the point of view of system and
applications@. This assumes an existing fix-speed system clock@.
But this is not the case of Virtual @acronym{PC}@. The system clock
on Virtual @acronym{PC} is software emulated@. It can be faster or
slower now and then, depending on the load of the hosting machine@.
There is no fixed clock speed@. The frequency drift does not exist,
then@. It dooms to fail to measure it@.
@pindex sntp
There is an @command{sntp} client that comes with David L. Mills'
@command{ntp} package@. It is suggested to be run from
@command{crontab}@. But @command{crontab} runs by minutes, and
Virtual @acronym{PC} goes 4 seconds ahead per minute@. Rolling back
4 seconds every minute is insane for most applications@. It also
increases system load heavily to run one instance per minute@.
@findex settimeofday()
@command{vsntp} is a workaround on this@. It runs as a daemon to
eliminates the additional system load on every synchronization@. It
uses @code{settimeofday()} to synchronize the time@. It synchronizes
the time with an arbitrary interval, so that time can be accurate
within a second@.
There are some defects@. Synchronizing the time too often introduces
heavy network load@. It introduces heavy load on the target
@acronym{NTP} server, too@. You should have a working
@acronym{NTP} server nearby that is owned by you@. Also, since
@code{settimeofday()} is called so often, high-accurate time
operations like timer, @acronym{etc.}, may not run correctly@.
@findex sleep()
@findex alarm()
@command{vsntp} uses @code{sleep()} as the synchronization scheduler.
Reports show that on some systems @code{sleep()} may not function
normally@. If you find @command{vsntp} stops synchronization after
running for some time, that the @code{sleep()} is not functioning
normally on your system, you may want to switch to the @code{alarm()}
scheduler with the @option{-a} switch@.
If you ever encounter any problem, you may check your syslog@.
@command{vsntp} logs detailed debugging information to syslog in log
level @code{LOG_DEBUG} with facility @code{LOG_DAEMON}@. You may turn
it on in your @file{/etc/syslog.conf} with the following line:
@example
daemon.debug /var/log/debug
@end example
and check the @file{/var/log/debug} file for the debugging message@.
Remember to remove this afterwards, for the amount of the debugging
messages may be huge and may use up your harddisk in a very short
time@. To the least it may slow down your system for frequent
harddisk @acronym{I/O}@.
@command{vsntp} was originally written for @acronym{GNU}/Linux@. It
uses @acronym{POSIX} compatible system calls@. It should work on
any @acronym{POSIX} compatible system@. But I have yet only tested
it on @uref{http://www.cygwin.com/, Cygwin}@. Cygwin is known to
work. I don't have others to test and run on. Please
let me know (and submit the patch if needed) if you can port it to
other systems@. I know it does not work on MSWin32, for the way it
handles the @acronym{PID} file path@.
Please tell me if you have successfully running @command{vsntp} on
other virtual machines, like @uref{http://www.vmware.com/, VMWare}@.
Generally, please tell me if you are using @command{vsntp}@. I
would like to know that I am really doing some good for the world,
*^_^* but not having fun myself@. :p
@node Download
@chapter Download the Newest Version
@cindex website
@cindex official website
@cindex download
@cindex SourceForge
@cindex Tavern IMACAT's
@command{vsntp}'s official website is at@dots{}
@itemize
@item
@uref{https://sourceforge.net/,SourceForge}'s home site:
@uref{http://vsntp.sourceforge.net/}
@item
@uref{https://sourceforge.net/,SourceForge}'s project page:
@uref{https://sourceforge.net/projects/vsntp/}
@item
@uref{http://www.imacat.idv.tw/,Tavern IMACAT's} page:
@uref{http://www.imacat.idv.tw/tech/vsntp.html}
@end itemize
You can always download the newest version of @command{vsntp}
from@dots{}
@itemize
@item
SourceForge:
@uref{https://sourceforge.net/project/showfiles.php?group_id=99098}
@item
Tavern IMACAT's @acronym{FTP}:
@uref{ftp://ftp.imacat.idv.tw/pub/vsntp/}
@end itemize
imacat's @acronym{PGP} public key is at@dots{}
@itemize
@item
SourceForge:
@uref{http://vsntp.sourceforge.net/pgpkey.asc}
@item
Tavern IMACAT's:
@uref{http://www.imacat.idv.tw/me/pgpkey.asc}
@end itemize
@node Install
@chapter Compilation and Installation
@command{vsntp} uses standard @acronym{GNU} @command{autoconf} to
compile and install:
@enumerate
@item
Download, unzip and untar the @command{vsntp} package:
@example
% tar xzf vsntp-@value{VERSION}.tar.gz
@end example
@item
Go into its directory:
@example
% cd vsntp-@value{VERSION}
@end example
@pindex configure
@item
Configure with @command{./configure}:
@example
% ./configure
@end example
@item
Compile with @command{make}:
@example
% make
@end example
The resulted executable will be named @file{vsntp}@.
@item
You need to be @code{root} in order to install @command{vsntp}:
@example
% su
Password:
#
@end example
@item
You can simply copy @command{vsntp} to the appropriate directory:
@example
# cp vsntp /usr/local/sbin
@end example
Or, you can run automatic install:
@example
# make install
@end example
You can reduce the size of the installed executable by stripping off
debug symbols inside:
@example
# make install-strip
@end example
By default @command{vsntp} will be installed in
@file{/usr/local/sbin}@.
@end enumerate
@node Run
@chapter Running and Stopping
You need to be @code{root} to run @command{vsntp}@. @command{vsntp}
uses @code{settimeofday()} to set the system time@.
@code{settimeofday()} requires @code{root} privilege@.
To start @command{vsntp}, just specify your @acronym{NTP} server:
@example
# vsntp my.ntp.server.com
@end example
@command{vsntp} writes its @acronym{PID} in
@file{/var/run/vsntp.pid}@. To stop @command{vsntp}, @command{kill}
it by its @acronym{PID}:
@example
# kill `cat /var/run/vsntp.pid`
@end example
The @acronym{PID} file location can be changed with the @option{-p}
switch.
@node Options
@chapter Command Line Options
@defopt{-i,--interval} @var{n}
Set the synchronization interval to @var{n} seconds@. Default is
900@dmn{sec} (15@dmn{min})@.
@end defopt
@defopt{-p,--pidfile} @var{file}
The @acronym{PID} file location@. Default to @file{/var/run/vsntp.pid}@.
@end defopt
@defopt{-s,--sleep}
Use @code{sleep()} to schedule synchronization@. (default)
@end defopt
@defopt{-a,--alarm}
Use @code{alarm()} to schedule synchronization@.
@end defopt
@defopt{-h,--help}
Display the help message@.
@end defopt
@defopt{-v,--version}
Display version information@.
@end defopt
@node Support
@chapter Supports and Bugs Report
@cindex SourceForge
@cindex Tavern IMACAT's
@command{vsntp} is hosted on
@uref{https://sourceforge.net/,SourceForge} and
@uref{http://www.imacat.idv.tw/,Tavern IMACAT's}@. For the latest
infomation, see:
@itemize
@item
@uref{http://vsntp.sourceforge.net/}
@item
@uref{https://sourceforge.net/projects/vsntp/}
@item
@uref{http://www.imacat.idv.tw/tech/vsntp.html}
@end itemize
@cindex mailing list
@cindex Mailman
@command{vsntp} has a mailing list hosted at
@uref{https://sourceforge.net/,SourceForge}:
@email{vsntp-users@@lists.sourceforge.net}@. Please submit your
questions, suggestions or bug reports there@. It is a
@uref{http://www.list.org/,Mailman} mailing list@. For more
information, see:
@uref{https://lists.sourceforge.net/lists/listinfo/vsntp-users}@.
Alternatively, you can send a mail to:
@email{vsntp-users-request@@lists.sourceforge.net}
with the subject @code{help} for a list of available e-mail
commands@.
@node References
@unnumbered References
@findex settimeofday()
@findex adjtimex()
@pindex ntp
@cindex RFC 1769 SNTP
@cindex RFC 1305 NTP
@itemize
@item
@inforef{High-Resolution Calendar, ,libc}, for settimeofday() and adjtimex().
@inforef{Setting an Alarm, ,libc}, for alarm().
@inforef{Sleeping, ,libc}, for sleep().
@item
@uref{http://www.ntp.org/,ntp}
@item
@uref{http://www.faqs.org/rfcs/rfc1769.html,@acronym{RFC} 1769 @acronym{SNTP}}.
@item
@uref{http://www.faqs.org/rfcs/rfc1305.html,@acronym{RFC} 1305 @acronym{NTP}}.
@end itemize
@node Copyright
@unnumbered Copyright
@quotation
Copyright @copyright{} 2003-2007 imacat@.
This program is free software: you can redistribute it and/or modify
it under the terms of the @cite{@acronym{GNU} General Public License}
as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version@.
This program is distributed in the hope that it will be useful,
but @emph{WITHOUT ANY WARRANTY}; without even the implied warranty of
@emph{MERCHANTABILITY} or @emph{FITNESS FOR A PARTICULAR PURPOSE}@.
See the @cite{@acronym{GNU} General Public License} for more details@.
You should have received a copy of the @cite{@acronym{GNU} General
Public License} along with this program@. If not, see
<@uref{http://www.gnu.org/licenses/}>@.
@end quotation
@node Index
@unnumbered Index
@printindex cp
@bye
@bye

21
init.d/Makefile.am Normal file
View File

@ -0,0 +1,21 @@
## Makefile.in template file for vsntp init.d directory
## Process this file with automake to produce Makefile.in
##
## Copyright (c) 2007 imacat
##
## 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 3 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, see <http://www.gnu.org/licenses/>.
AUTOMAKE_OPTIONS = gnits
EXTRA_DIST = README* vsntp vsntp.debian vsntp.redhat

62
init.d/README Normal file
View File

@ -0,0 +1,62 @@
vsntp SysV init.d start-up scripts README
TABLE OF CONTENTS
* Preface
* Debian Based Systems
* Red Hat Based Systems
PREFACE
Two SysV-styled init.d scripts are supplied with vsntp from 2.0.0,
together with one configuration file. One of them is for Debian based
systems (Knoppix, Ubuntu... etc.) The other is for Red Hat based systems
(Fedora, Mandriva... etc.) They are not installed by default. You may
install them so that vsntp will start as a daemon after each reboot.
Installion is easy. You have to be root.
DEBIAN BASED SYSTEMS
Copy the files to their appropriate directory:
# cp vsntp.debian /etc/init.d/vsntp
# cp vsntp /etc/default/vsntp
Edit /etc/default/vsntp to accommodate your environment. Remember
to uncomment the line with "SERVER=" and change it to your local NTP
server. Once finished, run:
# /etc/init.d/vsntp start
And watch the syslog. vsntp shall start working.
To run it every time the system boots, use updat-rc.d:
# update-rc.d vsntp defaults 23
23 is taken from the start/stop order of the Debian ntp package.
You may set it to your preferred order.
RED HAT BASED SYSTEMS
Copy the files to their appropriate directory:
# cp vsntp.redhat /etc/init.d/vsntp
# cp vsntp /etc/sysconfig/vsntp
Edit /etc/sysconfig/vsntp to accommodate your environment. Remember
to uncomment the line with "SERVER=" and change it to your local NTP
server. Once finished, run:
# /etc/init.d/vsntp start
And watch the syslog. vsntp shall start working.
To run it every time the system boots, use chkconfig:
# chkconfig --add vsntp
imacat
imacat@mail.imacat.idv.tw
2007-03-30

59
init.d/README.zh-cn Normal file
View File

@ -0,0 +1,59 @@
vsntp SysV init.d 启动程式读我说明
目录
* 前言
* Debian 类系统
* Red Hat 类系统
前言
  自 2.0.0 版起, vsntp 新增了两个 SysV 式的启动程式,及一个启动设定档。
一个程式是 Debian 类的系统(如 Knoppix 、 Ubuntu 等)专用,另一个则是
Red Hat 类系统专用(如 Fedora 、 Mandriva 等)。安装 vsntp 时,不会自动安
装这些档案。若你希望每次系统启动都会自动启动 vsntp ,你可以安装这些档案。
  安装不难。你要先切为 root 的权限。
Debian 类系统
  将档案复制到相关目录:
# cp vsntp.debian /etc/init.d/vsntp
# cp vsntp /etc/default/vsntp
  编辑 /etc/default/vsntp ,依你的环境需求修改其中的设定。记得一定要将
SERVER= 那一行前的 # 符号去掉,改为你自己架的时间伺服器。改好后,执行:
# /etc/init.d/vsntp start
  查阅 syslog 记录档,应该就会开始校时了。
  若要在每次系统启动时自动执行,可以跑 updat-rc.d
# update-rc.d vsntp defaults 23
  23 是 Debian NTP 套件的启动顺序。你也可以自设适当的启动顺序。
Red Hat 类系统
  将档案复制到相关目录:
# cp vsntp.redhat /etc/init.d/vsntp
# cp vsntp /etc/sysconfig/vsntp
  编辑 /etc/sysconfig/vsntp ,依你的环境需求修改其中的设定。记得一定
要将 SERVER= 那一行前的 # 符号去掉,改为你自己架的时间伺服器。改好后,
执行:
# /etc/init.d/vsntp start
  查阅 syslog 记录档,应该就会开始校时了。
  若要在每次系统启动时自动执行,可以跑 chkconfig
# chkconfig --add vsntp
依玛猫
imacat@mail.imacat.idv.tw
2007-03-30

59
init.d/README.zh-tw Normal file
View File

@ -0,0 +1,59 @@
vsntp SysV init.d 啟動程式讀我說明
目錄
* 前言
* Debian 類系統
* Red Hat 類系統
前言
  自 2.0.0 版起, vsntp 新增了兩個 SysV 式的啟動程式,及一個啟動設定檔。
一個程式是 Debian 類的系統(如 Knoppix 、 Ubuntu 等)專用,另一個則是
Red Hat 類系統專用(如 Fedora 、 Mandriva 等)。安裝 vsntp 時,不會自動安
裝這些檔案。若妳希望每次系統啟動都會自動啟動 vsntp ,妳可以安裝這些檔案。
  安裝不難。妳要先切為 root 的權限。
Debian 類系統
  將檔案複製到相關目錄:
# cp vsntp.debian /etc/init.d/vsntp
# cp vsntp /etc/default/vsntp
  編輯 /etc/default/vsntp ,依妳的環境需求修改其中的設定。記得一定要將
SERVER= 那一行前的 # 符號去掉,改為妳自己架的時間伺服器。改好後,執行:
# /etc/init.d/vsntp start
  查閱 syslog 記錄檔,應該就會開始校時了。
  若要在每次系統啟動時自動執行,可以跑 updat-rc.d
# update-rc.d vsntp defaults 23
  23 是 Debian NTP 套件的啟動順序。妳也可以自設適當的啟動順序。
Red Hat 類系統
  將檔案複製到相關目錄:
# cp vsntp.redhat /etc/init.d/vsntp
# cp vsntp /etc/sysconfig/vsntp
  編輯 /etc/sysconfig/vsntp ,依妳的環境需求修改其中的設定。記得一定
要將 SERVER= 那一行前的 # 符號去掉,改為妳自己架的時間伺服器。改好後,
執行:
# /etc/init.d/vsntp start
  查閱 syslog 記錄檔,應該就會開始校時了。
  若要在每次系統啟動時自動執行,可以跑 chkconfig
# chkconfig --add vsntp
依瑪貓
imacat@mail.imacat.idv.tw
2007-03-30

13
init.d/vsntp Normal file
View File

@ -0,0 +1,13 @@
# SNTP client for Virtual PC configuration file
# by imacat <imacat@mail.imacat.idv.tw> 2007-03-29
# SERVER: The server. Uncomment this line and replace it with YOUR LOCAL NTP SERVER.
# This must be set and cannot be commented out.
#SERVER=my.ntp.server.com
# SCHEDULER: Choose the scheduler. Currently either "sleep" or "alarm"
# Values that are not "alarm" are treated as "sleep".
SCHEDULER=sleep
# SYNC_INTERVAL: The synchronization interval, in seconds. The default is 900.
SYNC_INTERVAL=900

182
init.d/vsntp.debian Executable file
View File

@ -0,0 +1,182 @@
#!/bin/sh
# start and stop the SNTP client for Virtual PC
# LSB-convension comments
# See: http://refspecs.freestandards.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/initscrcomconv.html
### BEGIN INIT INFO
# Provides: vsntp
# Required-Start: $network $time
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: start and stop the SNTP client for Virtual PC
# Description: vsntp is a SNTP client for Virtual PC that synchronize
# time periodically for systems without hardward RTC.
### END INIT INFO
export PATH=/sbin:/bin:/usr/sbin:/usr/bin
THISFILE=${0##*/}
VERSION=1.1.0
AUTHORNAME=imacat
AUTHORMAIL=imacat@mail.imacat.idv.tw
DESC="SNTP client for Virtual PC"
THISCONF=/etc/default/vsntp
# source the configuration
test -e $THISCONF && . $THISCONF
case "$SCHEDULER" in
alarm|a|-a|--alarm)
SCHEDULER=-a ;;
*)
SCHEDULER=-s ;;
esac
BINPATH=/usr/sbin/vsntp
BINNAME=${BINPATH##*/}
PIDFILE=/var/run/$BINNAME.pid
RUNUSER=root
# default values -- do not change anything here
_DEFSYNC_INTERVAL=900
_DEFSCHEDULER=-s
# startup options
OPTS=""
test -n "$SCHEDULER" -a "$SCHEDULER" != "$_DEFSCHEDULER" && OPTS="$OPTS $SCHEDULER"
test -n "$SYNC_INTERVAL" -a "$SYNC_INTERVAL" != "$_DEFSYNC_INTERVAL" && OPTS="$OPTS -i $SYNC_INTERVAL"
OPTS="$OPTS $SERVER"
# sanity checks
if test ! -n "$SERVER"; then
echo "$THISFILE: You must set the SERVER in $THISCONF" >&2
exit 1
fi
if test ! -x $BINPATH; then
echo "$THISFILE: Missing valid daemon program at $BINPATH" >&2
exit 1
fi
if test -n "$USER" -a ! "$USER" = "root"; then
echo "$THISFILE: You need to be root to run this script." >&2
exit 1
fi
start () {
echo -n "Starting $DESC:"
RETVAL=0
echo -n " $BINNAME"
start-stop-daemon --start --startas $BINPATH --quiet \
--pidfile $PIDFILE --name $BINNAME --user $RUNUSER --exec $BINPATH -- $OPTS
RETVALS=$?
test $RETVALS = 0 || { echo -n ":failed"; RETVAL=$RETVALS; }
echo "."
return $RETVAL
}
stop () {
echo -n "Stopping $DESC:"
RETVAL=0
echo -n " $BINNAME"
start-stop-daemon --stop --quiet \
--pidfile $PIDFILE --name $BINNAME --user $RUNUSER --exec $BINPATH
RETVALS=$?
test $RETVALS = 0 || { echo -n ":failed"; RETVAL=$RETVALS; }
rm -f $PIDFILE
echo "."
return $RETVAL
}
restart () {
stop
sleep 1
start
RETVAL=$?
return $RETVAL
}
status () {
RETVAL=0
start-stop-daemon --stop --signal 0 --quiet \
--pidfile $PIDFILE --name $BINNAME --user $RUNUSER --exec $BINPATH
RETVALS=$?
if test $RETVALS = 0; then
echo "$DESC $BINNAME is up and running ($(<$PIDFILE))."
else
echo "$DESC $BINNAME is not running (or some problem may exists)."
RETVAL=$RETVALS
fi
return $RETVAL
}
# parse the arguments
while test $# != 0; do
case "$1" in
start|stop|restart|force-reload|status)
action="$1"
;;
-h|--help)
cat << EOF
Start and/or stop the $DESC
Usage: $THISFILE {start|stop|restart|force-reload|status}
start Start the daemon.
stop Stop the daemon.
restart Stop and restart the daemon.
force-reload Enforce a reload to the configuration file.
status Display the daemon status.
-h,--help Display this help.
-v,--version Display the version infomation.
Report bugs to $AUTHORNAME <$AUTHORMAIL>
EOF
exit 0
;;
-v|--version)
cat << EOF
$THISFILE version $VERSION by $AUTHORNAME <$AUTHORMAIL>
EOF
exit 0
;;
*)
echo "$THISFILE: unrecognized argument: $1" >&2
echo "Try \`$THISFILE --help' for more infomation" >&2
exit 1
;;
esac
shift
done
# no action specified
if test -z "$action"; then
echo "$THISFILE: what do you want to do now?" >&2
echo "Try \`$THISFILE --help' for more infomation" >&2
exit 1
fi
# act now!
case "$action" in
start)
start
RETVAL=$?
;;
stop)
stop
RETVAL=$?
;;
restart|force-reload)
restart
RETVAL=$?
;;
status)
status
RETVAL=$?
;;
esac
exit $RETVAL

148
init.d/vsntp.redhat Executable file
View File

@ -0,0 +1,148 @@
#!/bin/sh
# start and stop the SNTP client for Virtual PC
# Red Hat styled comments for chkconfig
# chkconfig: 2345 58 74
# description: SNTP client for Virtual PC
# processname: vsntp
# config: /etc/sysconfig/vsntp
# LSB-convension comments
# See: http://refspecs.freestandards.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/initscrcomconv.html
### BEGIN INIT INFO
# Provides: vsntp
# Required-Start: $network $time
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: start and stop the SNTP client for Virtual PC
# Description: vsntp is a SNTP client for Virtual PC that synchronize
# time periodically for systems without hardward RTC.
### END INIT INFO
export PATH=/sbin:/bin:/usr/sbin:/usr/bin
# initialize the environment
THISFILE="${0##*/}"
VERSION="1.0.0"
AUTHORNAME=imacat
AUTHORMAIL=imacat@mail.imacat.idv.tw
lock=/var/lock/subsys/vsntp
# Source function library.
. /etc/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 0
if [ -f /etc/sysconfig/vsntp ];then
. /etc/sysconfig/vsntp
fi
case "$SCHEDULER" in
alarm|a|-a|--alarm)
SCHEDULER=-a ;;
*)
SCHEDULER=-s ;;
esac
# default values -- do not change anything here
_DEFSYNC_INTERVAL=900
_DEFSCHEDULER=-s
RETVAL="0"
OPTIONS=""
test -n "$SCHEDULER" -a "$SCHEDULER" != "$_DEFSCHEDULER" && OPTIONS="$OPTIONS $SCHEDULER"
test -n "$SYNC_INTERVAL" -a "$SYNC_INTERVAL" != "$_DEFSYNC_INTERVAL" && OPTIONS="$OPTIONS -i $SYNC_INTERVAL"
OPTIONS="$OPTIONS $SERVER"
# See how we were called.
start() {
echo -n "Starting SNTP client for Virtual PC: "
daemon vsntp $OPTIONS
RETVAL="$?"
echo
[ "$RETVAL" -eq "0" ] && touch $lock
return "$RETVAL"
}
stop() {
echo -n "Stopping SNTP client for Virtual PC: "
killproc vsntp
RETVAL="$?"
echo
[ "$RETVAL" -eq "0" ] && rm -f $lock
return "$RETVAL"
}
rhstatus() {
status vsntp
}
restart() {
stop
start
}
# parse the arguments
while [ "$#" != "0" ]; do
case "$1" in
start|stop|restart|status)
action="$1"
;;
-h|--help)
cat << EOF
Start and/or stop the SNTP client for Virtual PC
Usage: $THISFILE {start|stop|restart|status}
start Start the daemon.
stop Stop the daemon.
restart Stop and restart the daemon.
status Display the daemon status
-h,--help Display this help.
-v,--version Display the version infomation.
Report bugs to $AUTHORNAME <$AUTHORMAIL>
EOF
exit 0
;;
-v|--version)
cat << EOF
$THISFILE v$VERSION by $AUTHORNAME <$AUTHORMAIL>
EOF
exit 0
;;
*)
echo "$THISFILE: unrecognized argument: $1"
echo "Try \`$THISFILE --help' for more infomation"
exit 1
;;
esac
shift
done
# check the arguments
if [ -z "$action" ]; then
cat << EOF
Usage: $THISFILE {start|stop|restart|status}
EOF
exit 0
fi
# process now
case "$action" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
status)
rhstatus
;;
esac
exit $?

960
vsntp.c Normal file
View File

@ -0,0 +1,960 @@
/* SNTP for Virtual PC */
/*
Copyright (C) 2003-2007 imacat.
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 3 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, see <http://www.gnu.org/licenses/>.
*/
/* Filename: vsntp.c
Description: SNTP for Virtual PC
Author: imacat <imacat@mail.imacat.idv.tw>
Date: 2003-12-22
Copyright: (c) 2003-2007 imacat */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* Headers */
#include <arpa/inet.h>
#include <errno.h>
#include <getopt.h>
#include <netdb.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <syslog.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
extern int h_errno;
/* Configuration */
#define AUTHOR "imacat"
#define AUTHORMAIL "imacat@mail.imacat.idv.tw"
#define EXEC_USER "root"
#define PIDDIR "/var/run"
#define DEFAULT_INTERVAL 900
#define MAX_NETWORK_ERROR 1200
#define SNTP_PORT 123
#define SCHEDULER_SLEEP 1
#define SCHEDULER_ALARM 2
#define DEFAULT_SCHEDULER SCHEDULER_SLEEP
#define VERSTR "\
%s v%s, Copyright (C) 2003-2007 %s\n\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
\n"
#define LONGHELP "\
Usage: %s [-i n] [-p file] [-a|-s] server\n\
Synchronize the system time against a time server periodically. It\n\
uses RFC 1361 SNTP service UDP port 123 to synchronize the time. You\n\
may need to be root to synchronize the system time.\n\
\n\
-i,--interval n Set the synchronization interval to n seconds. (%d)\n\
-p,--pidfile file The PID file location. (%s)\n\
-s,--sleep Use sleep() to schedule synchronization. (default)\n\
-a,--alarm Use alarm() to schedule synchronization.\n\
-h,--help Display this help.\n\
-v,--version Display version information.\n\
server Time server to synchronize against.\n\
\n"
#define EXIT_OK 0
#define EXIT_ARGERR 1
#define EXIT_NETERR 2
#define EXIT_SYSERR 127
#define EPOCH_DIFF ((unsigned long) 86400 * (365 * 70 + 17))
/* Prototypes */
void set_this_file (char *argv0);
void parse_args (int argc, char *argv[]);
void check_priv (void);
void xexit (int status)
__attribute__((noreturn));
void verror (int status, char *message, va_list ap)
__attribute__((noreturn));
void error (int status, char *message, ...)
__attribute__((noreturn, format(printf, 2, 3)));
void vwarn (char *message, va_list ap);
void warn (char *message, ...)
__attribute__((format(printf, 1, 2)));
void neterror (int firstsync, time_t errstart, char *message, ...)
__attribute__((format(printf, 3, 4)));
void sigterm_exit (int signum)
__attribute__((noreturn));
void daemonize (void);
void makepid (void);
void setsigterm (void);
#ifdef HAVE_ALARM
void setsigalrm (void);
void alarm_wakeup (int signum);
#endif
double synctime (void);
void fork2background (void);
void closeall (void);
unsigned long fromnetnum (const char *oct);
const char *tonetnum (unsigned long num);
unsigned long usec2frac (long usec);
long frac2usec (unsigned long frac);
void *xmalloc (size_t size);
char *xstrcpy (const char *src);
char *xstrcat (int n, ...);
time_t xtime (time_t *t);
void xgettimeofday (struct timeval *tv, struct timezone *tz);
void xsettimeofday (const struct timeval *tv , const struct timezone *tz);
void xchdir (const char *path);
pid_t xfork (void);
pid_t xsetsid (void);
long xsysconf (int name, const char *confname);
FILE *xfopen (const char *path, const char *mode);
void xfclose (FILE *stream);
int xfprintf (FILE *stream, const char *format, ...)
__attribute__((format(printf, 2, 3)));
void xsigemptyset (sigset_t *set);
void xsigaction (int signum, const struct sigaction *act, struct sigaction *oldact);
/* Variables */
char *server_name = NULL, *this_file = NULL, *pidfile = NULL;
int interval = -1, daemonized = 0, scheduler = -1;
struct sockaddr_in server;
time_t next;
/* Main program */
int
main (int argc, char *argv[])
{
double toff;
/* Find this file's name */
set_this_file (argv[0]);
parse_args (argc, argv);
/* Synchronize for the first time, to ensure no obvious network errors */
toff = synctime ();
/* Record the first synchronization */
if (toff != 0)
syslog (LOG_INFO, "Time adjusted %.6f seconds.", toff);
/* Daemonize */
daemonize ();
/* Make the PID file */
makepid ();
/* Set the way we exit */
setsigterm ();
switch (scheduler)
{
/* Use sleep() to schedule synchronization */
case SCHEDULER_SLEEP:
syslog (LOG_INFO, "Using sleep() to schedule synchronization");
/* Enter an endless loop of synchronization */
while (1) {
/* Synchronize the time */
toff = synctime ();
/* Record the synchronization */
if (toff != 0)
syslog (LOG_DEBUG, "Time adjusted %.6f seconds.", toff);
/* Wait until the next time */
sleep (interval);
}
break;
#ifdef HAVE_ALARM
/* Use alarm() to schedule synchronization */
case SCHEDULER_ALARM:
/* Set the the synchronization scheduler alerm */
setsigalrm ();
/* syslog() must follow setaction(), or it crash after the first alarm.
To be investigated. */
syslog (LOG_INFO, "Using alarm() to schedule synchronization");
/* Schedule the next alarm */
alarm (interval);
/* Enter an endless loop of synchronization
pause() is interrupted by every SIGALRM signal.
Endless loop of pause() make SIGALRM signals endlessly. */
while (1)
pause ();
break;
#endif
}
return 0;
}
/* set_this_file: Get the name of this file
return: none. */
void
set_this_file (char *argv0)
{
char *p;
p = rindex (argv0, '/');
if (p == NULL)
this_file = xstrcpy (argv0);
else
this_file = xstrcpy (++p);
return;
}
/* parse_args: Parse the arguments.
return: none. */
void
parse_args (int argc, char *argv[])
{
static struct option longopts[] = {
{"interval", 1, NULL, 'i'},
{"pidfile", 1, NULL, 'p'},
{"sleep", 0, NULL, 's'},
{"alarm", 0, NULL, 'a'},
{"help", 0, NULL, 'h'},
{"version", 0, NULL, 'v'},
{0, 0, 0, 0}
};
int i, r, c, c0, longindex = 0;
struct in_addr server_addr;
struct hostent *server_hostent;
void *p;
size_t len;
/* Set the default value */
interval = DEFAULT_INTERVAL;
scheduler = DEFAULT_SCHEDULER;
pidfile = xstrcat (4, PIDDIR, "/", this_file, ".pid");
while (1)
{
c = getopt_long (argc, argv, "i:p:sahv", longopts, &longindex);
if (c == -1)
break;
switch (c)
{
case 'i':
r = sscanf (optarg, "%5d%c", &interval, &c0);
if (r != 1 || interval <= 0)
error (EXIT_ARGERR, "invalid interval: %s.", optarg);
break;
case 'p':
if (pidfile != NULL)
free (pidfile);
pidfile = xstrcpy (optarg);
break;
case 's':
scheduler = SCHEDULER_SLEEP;
break;
case 'a':
scheduler = SCHEDULER_ALARM;
break;
case 'h':
printf (LONGHELP, this_file, interval, pidfile);
exit (EXIT_OK);
case 'v':
printf (VERSTR, this_file, VERSION, AUTHOR);
exit (EXIT_OK);
default:
exit (EXIT_ARGERR);
}
}
/* Process each argument */
for (i = optind; i < argc; i++)
switch (i - optind)
{
case 0:
server_name = xstrcpy (argv[i]);
break;
default:
error (EXIT_ARGERR, "Too many argument: %s.", argv[i]);
}
/* Process the interval */
if (interval == -1)
interval = DEFAULT_INTERVAL;
#ifndef HAVE_ALARM
if (scheduler == SCHEDULER_ALARM)
error (EXIT_ARGERR, "alarm() is not supported on this platform.");
#endif
/* Process the PID file */
/* Compose the default PID file path */
if (pidfile == NULL)
pidfile = xstrcat (4, PIDDIR, "/", this_file, ".pid");
/* Process the time server */
if (server_name == NULL)
error (EXIT_ARGERR, "Please specify the time server.");
r = inet_aton (server_name, &server_addr);
if (r == 0)
{
/* Try DNS look up */
server_hostent = gethostbyname (server_name);
if (server_hostent == NULL)
error (EXIT_ARGERR, "%s: %s.", server_name, hstrerror (h_errno));
/* Obtain the IP number, reverse the byte order */
server_addr.s_addr =
((server_hostent->h_addr_list[0][3] << 24) & 0xFF000000) |
((server_hostent->h_addr_list[0][2] << 16) & 0x00FF0000) |
((server_hostent->h_addr_list[0][1] << 8) & 0x0000FF00) |
(server_hostent->h_addr_list[0][0] & 0x000000FF);
/* Modify the server name for logging */
len = strlen (server_name) + 20;
p = (void *) server_name;
server_name = (char *) xmalloc (len);
snprintf (server_name, len, "%s (%hhu.%hhu.%hhu.%hhu)", (char *) p,
server_hostent->h_addr_list[0][0],
server_hostent->h_addr_list[0][1],
server_hostent->h_addr_list[0][2],
server_hostent->h_addr_list[0][3]);
free (p);
}
/* Save the server infomation */
server.sin_family = AF_INET;
server.sin_addr = server_addr;
server.sin_port = htons (SNTP_PORT);
return;
}
/* xexit: Properly handle the exit.
return: none. */
void
xexit (int status)
{
int r;
/* Proper exit in daemon mode */
if (daemonized)
{
/* Remove the PID file */
r = unlink (pidfile);
if (r == -1)
syslog (LOG_ERR, "%s:%d: unlink %s: %s",
__FILE__, __LINE__, pidfile, strerror (errno));
/* Close the syslog */
closelog ();
}
exit (status);
}
/* verror: Issue an error with variable argument list */
void
verror (int status, char *message, va_list ap)
{
/* Issue the error message */
if (daemonized)
{
vsyslog (LOG_ERR, message, ap);
syslog (LOG_ERR, "Exited upon unrecoverable network error.");
}
else
{
vfprintf (stderr, message, ap);
fprintf (stderr, "\n");
}
xexit (status);
}
/* error: Issue an error */
void
error (int status, char *message, ...)
{
va_list ap;
/* Handle the error with verror */
va_start (ap, message);
verror (status, message, ap);
va_end (ap);
/* No return */
}
/* vwarn: Issue a warning with variable argument list */
void
vwarn (char *message, va_list ap)
{
/* Issue the warning message */
if (daemonized)
vsyslog (LOG_WARNING, message, ap);
else
vfprintf (stderr, message, ap);
return;
}
/* warn: Issue a warning */
void
warn (char *message, ...)
{
va_list ap;
/* Handle warnings with vwarn */
va_start (ap, message);
vwarn (message, ap);
va_end (ap);
return;
}
/* neterror: Issue a network error */
void
neterror (int firstsync, time_t errstart, char *message, ...)
{
va_list ap;
time_t now;
va_start (ap, message);
/* Don't pass it if we can't even synchronize the first time */
if (firstsync)
verror (EXIT_NETERR, message, ap);
/* Warn it */
vwarn (message, ap);
/* Errors lasted for too long */
now = xtime (NULL);
if (now - errstart > MAX_NETWORK_ERROR)
error (EXIT_NETERR, "Exited upon network error exceeding %d seconds.", MAX_NETWORK_ERROR);
return;
}
/* sigterm: End the program */
void
sigterm_exit (int signum)
{
/* Log the exit */
syslog (LOG_INFO, "Exited upon TERM signal.");
/* Exit normally */
xexit (EXIT_OK);
}
/* daemonize: Daemonize the process */
/* http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16 */
void
daemonize (void)
{
/* Fork to be a new process group leader */
fork2background ();
/* Become a new session group leader, to get rid of the
controlling terminal */
xsetsid ();
/* Fork again to get rid of this new session */
fork2background ();
/* chdir to "/", to avoid staying on any mounted file system */
xchdir ("/");
/* Avoid inheriting umasks */
umask (0);
/* Close all opened file descriptors */
closeall ();
/* Set the flag */
daemonized = 1;
/* Start the syslog */
openlog (this_file, LOG_PID, LOG_DAEMON);
/* Log the start */
syslog (LOG_INFO, "Start synchronization with %s.", server_name);
return;
}
/* makepid: Make the PID file */
void
makepid (void)
{
pid_t pid;
FILE *fp;
/* Record the PID */
pid = getpid ();
/* Save to the file */
fp = xfopen (pidfile, "w");
xfprintf (fp, "%d\n", pid);
xfclose (fp);
return;
}
/* setsigterm: Configure the way we exit */
void
setsigterm (void)
{
struct sigaction action;
/* Set the TERM signal handler */
action.sa_handler = sigterm_exit;
/* Block further signals */
xsigemptyset (&action.sa_mask);
/* Set the TERM signal handler */
xsigaction (SIGTERM, &action, NULL);
return;
}
#ifdef HAVE_ALARM
/* setsigalrm: Configure the synchronization scheduler alerm */
void
setsigalrm (void)
{
struct sigaction action;
/* Set the ALRM signal handler */
action.sa_handler = alarm_wakeup;
/* Block further signals */
xsigemptyset (&action.sa_mask);
/* Set the TERM signal handler */
xsigaction (SIGALRM, &action, NULL);
return;
}
/* alarm_wakeup: Wake up on alarm and synchronize the time */
void
alarm_wakeup (int signum)
{
double toff;
/* Synchronize the time */
toff = synctime ();
/* Record the synchronization */
if (toff != 0)
syslog (LOG_DEBUG, "Time adjusted %.6f seconds.", toff);
/* Schedule the next alarm */
alarm (interval);
return;
}
#endif
/* synctime: Synchronize the time. See RFC 1361.
return: Time offset that is synchronized */
double
synctime (void)
{
int i, r, udp;
static int firstsync = 1;
char buf[61];
ssize_t len;
static time_t errstart = 0;
static struct timeval tv1, tv2, tv3, tv4, tvnew;
struct timezone tz;
double t1, t2, t3, t4, toff, tnew;
time_t now;
/* Create the UDP socket */
syslog (LOG_DEBUG, "%s:%d: Connecting UDP to %s",
__FILE__, __LINE__, server_name);
udp = socket (PF_INET, SOCK_DGRAM, 0);
/* Initialize the connection */
r = connect (udp, (struct sockaddr*) &server, sizeof (server));
if (r == -1)
{
now = xtime (NULL);
/* First error */
if (errstart == 0)
errstart = now;
neterror (firstsync, errstart, "%s:%d: connect %s (%d): %s",
__FILE__, __LINE__, server_name, now - errstart, strerror (errno));
/* Close the opened socket */
r = close (udp);
if (r != 0)
warn ("%s:%d: close udp: %s",
__FILE__, __LINE__, strerror (errno));
return 0;
}
/* Send to the server */
/* Pad zeroes */
for (i = 0; i < 61; i++)
buf[i] = 0;
/* 00 001 011 - leap, ntp ver, client. See RFC 1361. */
buf[0] = (0 << 6) | (1 << 3) | 3;
/* Get the local sent time - Originate Timestamp */
xgettimeofday (&tv1, &tz);
t1 = (double) tv1.tv_sec + (double) tv1.tv_usec / 1000000;
/* Send to the server */
memcpy (&buf[40], tonetnum ((unsigned long) tv1.tv_sec + EPOCH_DIFF), 4);
memcpy (&buf[44], tonetnum (usec2frac (tv1.tv_usec)), 4);
syslog (LOG_DEBUG, "%s:%d: Sending UDP buf to %s",
__FILE__, __LINE__, server_name);
len = send (udp, buf, 48, 0);
if (len == -1)
{
now = xtime (NULL);
/* First error */
if (errstart == 0)
errstart = now;
neterror (firstsync, errstart, "%s:%d: send %s (%d): %s",
__FILE__, __LINE__, server_name, now - errstart, strerror (errno));
/* Close the opened socket */
r = close (udp);
if (r != 0)
warn ("%s:%d: close udp: %s",
__FILE__, __LINE__, strerror (errno));
return 0;
}
/* Read from the server */
syslog (LOG_DEBUG, "%s:%d: Reading UDP buf from %s",
__FILE__, __LINE__, server_name);
len = recv (udp, &buf, 60, 0);
if (len == -1)
{
now = xtime (NULL);
/* First error */
if (errstart == 0)
errstart = now;
neterror (firstsync, errstart, "%s:%d: recv %s (%d): %s",
__FILE__, __LINE__, server_name, now - errstart, strerror (errno));
/* Close the opened socket */
r = close (udp);
if (r != 0)
warn ("%s:%d: close udp: %s",
__FILE__, __LINE__, strerror (errno));
return 0;
}
/* Close the socket */
r = close (udp);
if (r != 0)
warn ("%s:%d: close udp: %s",
__FILE__, __LINE__, strerror (errno));
/* Get the local received time */
xgettimeofday (&tv4, &tz);
t4 = (double) tv4.tv_sec + (double) tv4.tv_usec / 1000000;
/* Calculate the local time offset */
/* Get the remote Receive Timestamp */
tv2.tv_sec = fromnetnum (&buf[32]) - EPOCH_DIFF;
tv2.tv_usec = frac2usec (fromnetnum (&buf[36]));
t2 = (double) tv2.tv_sec + (double) tv2.tv_usec / 1000000;
/* Get the remote Transmit Timestamp */
tv3.tv_sec = fromnetnum (&buf[40]) - EPOCH_DIFF;
tv3.tv_usec = frac2usec (fromnetnum (&buf[44]));
t3 = (double) tv3.tv_sec + (double) tv3.tv_usec / 1000000;
/* The time offset */
toff = (t2 + t3 - t1 - t4) / 2;
syslog (LOG_DEBUG, "%s:%d: Local time offset: t1: %.6f, t2: %.6f, t3: %.6f, t4: %.6f, toff: %.6f",
__FILE__, __LINE__, t1, t2, t3, t4, toff);
/* Calculate the new time */
tnew = t4 + toff;
tvnew.tv_usec = (long long) (tnew * 1000000) % 1000000;
tvnew.tv_sec = ((long long) (tnew * 1000000) - tvnew.tv_usec) / 1000000;
/* Set the time */
xsettimeofday (&tvnew, &tz);
/* Re-initialize the error timer */
errstart = 0;
/* Remove the first time flag */
firstsync = 0;
return toff;
}
/* fork2background: Fork to the background.
return: none. */
void
fork2background (void)
{
pid_t pid;
/* Fork */
pid = xfork ();
/* Exit the parent process */
if (pid != 0)
exit (0);
return;
}
/* closeall: Close all the opened file descriptors,
especially: stdin, stdout and stderr.
return: none. */
void
closeall (void)
{
int i;
long openmax;
openmax = xsysconf (_SC_OPEN_MAX, "_SC_OPEN_MAX");
for (i = 0; i < openmax; i++)
close (i);
return;
}
/* fromnetnum: Convert from a network number to a C number.
return: the number in unsigned long. */
unsigned long
fromnetnum (const char *oct)
{
return ((unsigned char) oct[0] << 24 | (unsigned char) oct[1] << 16 | (unsigned char) oct[2] << 8 | (unsigned char) oct[3]);
}
/* tonetnum: Convert from a C number to a network number.
return: the number in network octet. */
const char *tonetnum (unsigned long num)
{
static char oct[5] = "0000";
oct[0] = (num >> 24) & 255;
oct[1] = (num >> 16) & 255;
oct[2] = (num >> 8) & 255;
oct[3] = num & 255;
return oct;
}
/* usec2frac: Convert from microsecond to fraction of a second.
return: Fraction of a second. */
unsigned long
usec2frac (long usec)
{
return (unsigned long) (((long long) usec << 32) / 1000000);
}
/* usec2frac: Convert from fraction of a second to microsecond
return: microsecond. */
long
frac2usec (unsigned long frac)
{
return (long) (((long long) frac * 1000000) >> 32);
}
/* xstrcpy: allocate enough memory, make a copy of the string, and handle its error.
return: pointer to the destination string. */
char *
xstrcpy (const char *src)
{
char *dest;
dest = (char *) xmalloc (strlen (src) + 1);
strcpy (dest, src);
return dest;
}
/* xstrcat: allocate enough memory, concatenate the strings, and handle its error.
return: pointer to the destination string. */
char *
xstrcat (int n, ...)
{
int i;
size_t len;
va_list ap;
char *s;
/* Calculate the result size */
va_start (ap, n);
for (i = 0, len = 0; i < n; i++)
len += strlen (va_arg (ap, char *));
va_end (ap);
/* Allocate the memory */
s = (char *) xmalloc (len + 1);
/* Concatenate the strings */
va_start (ap, n);
strcpy (s, va_arg (ap, char *));
for (i = 1; i < n; i++)
strcat (s, va_arg (ap, char *));
va_end (ap);
return s;
}
/* xmalloc: malloc() and handle its error.
return: pointer to the allocated memory block. */
void *
xmalloc (size_t size)
{
void *ptr;
ptr = malloc (size);
if (ptr == NULL)
error (EXIT_SYSERR, "%s:%d: malloc: %s",
__FILE__, __LINE__, strerror (errno));
return ptr;
}
/* xtime: time() and handle its error.
return: current time. */
time_t
xtime (time_t *t)
{
time_t r;
r = time (t);
if (r == -1)
error (EXIT_SYSERR, "%s:%d: time: %s",
__FILE__, __LINE__, strerror (errno));
return r;
}
/* xgettimeofday: gettimeofday() and handle its error.
return: none. */
void
xgettimeofday (struct timeval *tv, struct timezone *tz)
{
int r;
r = gettimeofday (tv, tz);
if (r == -1)
error (EXIT_SYSERR, "%s:%d: gettimeofday: %s",
__FILE__, __LINE__, strerror (errno));
return;
}
/* xsettimeofday: settimeofday() and handle its error.
return: none. */
void
xsettimeofday (const struct timeval *tv , const struct timezone *tz)
{
int r;
r = settimeofday (tv, tz);
if (r == -1)
error (EXIT_SYSERR, "%s:%d: settimeofday: %s",
__FILE__, __LINE__, strerror (errno));
return;
}
/* xchdir: chdir() and handle its error.
return: none. */
void
xchdir (const char *path)
{
int r;
r = chdir (path);
if (r == -1)
error (EXIT_SYSERR, "%s:%d: chdir %s: %s",
__FILE__, __LINE__, path, strerror (errno));
return;
}
/* xfork: fork() and handle its error.
return: none. */
pid_t
xfork (void)
{
pid_t pid;
pid = fork ();
if (pid == -1)
error (EXIT_SYSERR, "%s:%d: fork: %s",
__FILE__, __LINE__, strerror (errno));
return pid;
}
/* xsetsid: setsid() and handle its error.
return: none. */
pid_t
xsetsid (void)
{
pid_t pid;
pid = setsid ();
if (pid == -1)
error (EXIT_SYSERR, "%s:%d: setsid: %s",
__FILE__, __LINE__, strerror (errno));
return pid;
}
/* xsysconf: sysconf() and handle its error.
return: none. */
long
xsysconf (int name, const char *confname)
{
long r;
r = sysconf (name);
if (r == -1)
error (EXIT_SYSERR, "%s:%d: sysconf %s: %s",
__FILE__, __LINE__, confname, strerror (errno));
return r;
}
/* xfopen: fopen() and handle its error.
return: file handler pointer. */
FILE *
xfopen (const char *path, const char *mode)
{
FILE *fp;
fp = fopen (path, mode);
if (fp == NULL)
error (EXIT_SYSERR, "%s:%d: fopen %s: %s",
__FILE__, __LINE__, path, strerror (errno));
return fp;
}
/* xfclose: fclose() and handle its error.
return: none. */
void
xfclose (FILE *stream)
{
int r;
r = fclose (stream);
if (r == EOF)
error (EXIT_SYSERR, "%s:%d: fclose: %s",
__FILE__, __LINE__, strerror (errno));
return;
}
/* xfprintf: fprintf() and handle its error.
return: length print so far. */
int
xfprintf (FILE *stream, const char *format, ...)
{
int len;
va_list ap;
va_start (ap, format);
len = vfprintf (stream, format, ap);
va_end (ap);
if (len < 0)
error (EXIT_SYSERR, "%s:%d: vfprintf: %s",
__FILE__, __LINE__, strerror (errno));
return len;
}
/* xsigemptyset: sigemptyset() and handle its error.
return: none. */
void
xsigemptyset (sigset_t *set)
{
int r;
r = sigemptyset (set);
if (r == -1)
error (EXIT_SYSERR, "%s:%d: sigemptyset: %s",
__FILE__, __LINE__, strerror (errno));
return;
}
/* xsigaction: sigaction() and handle its error.
return: none. */
void
xsigaction (int signum, const struct sigaction *act, struct sigaction *oldact)
{
int r;
r = sigaction (signum, act, oldact);
if (r == -1)
error (EXIT_SYSERR, "%s:%d: sigaction: %s",
__FILE__, __LINE__, strerror (errno));
return;
}