Import Upstream version 3.0038+nmu1

This commit is contained in:
openKylinBot 2022-05-14 03:13:01 +08:00
commit 3a0feb4ad0
16 changed files with 4484 additions and 0 deletions

340
COPYING Normal file
View File

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

211
ChangeLog Normal file
View File

@ -0,0 +1,211 @@
2008-02-21 Manoj Srivastava <srivasta@debian.org>
* ucfq (process):
srivasta@debian.org--lenny/ucf--devel--3.0--patch-2 Niko
Tyni says ucfq /path/to/file never gives any output. It
looks like the problem is that ^/ is matched twice with
the global option (m//g) on the filename in
ucf::process(), so the second one fails looking for the
next match. I don't see the need for global match here,
and removing the /g fixesthis for me.
(report): srivasta@debian.org--lenny/ucf--devel--3.0--patch-2
Major changes to ensure that the modified column
actually contains a valid value. This whole script needs
a rewrite.
2007-11-30 Manoj Srivastava <srivasta@debian.org>
* ucf (newsum):
srivasta@debian.org--lenny/ucf--devel--3.0--patch-1 For
"keep current" and "threeway merge", ucf expects answers
from debconf which differ from what is specified in the
template master. Frans Pop suggested using the Choices-C
feature of debconf, which is relatively new, but defines
a fixed alias for each option which Debconf will then
use in db_get and db_set operations -- so no more
matching the template in the code.
2007-09-19 Manoj Srivastava <srivasta@debian.org>
* ucf (choice_keep_current):
srivasta@debian.org--lenny/ucf--devel--3.0--base-0
Change the name to fit the changed template
2007-05-05 Manoj Srivastava <srivasta@debian.org>
* ucf (show_diff):
srivasta@debian.org--lenny/ucf--devel--2.0--patch-1
Users using a Graphical frontend are surprised when the
display apparently just blocks when they ask to see a
diff (or 3-way diff) of the configuration file being
handled, when actually the diff is displayed on the
terminal window ucf was run on. Until the debconf-escape
utility and the escape CAPB support, db_subst ran into
newline and line length issues. Patch from Michael Vogt.
2007-04-17 Manoj Srivastava <srivasta@debian.org>
* ucf.1: srivasta@debian.org--lenny/ucf--devel--2.0--base-0
Document that ucf now tries to preserve owner/permission
bits for the file.
* ucf: srivasta@debian.org--lenny/ucf--devel--2.0--base-0 As far
as possible, preserve file attributes like ownership and
permission by using cp -pf instead of just cp -f.
2007-02-25 Manoj Srivastava <srivasta@debian.org>
* ucfr (safe_conf_file):
srivasta@debian.org--etch/ucf--devel--2.0--versionfix-4
Reincorporate the fix from the NMU. Add a space before
the echo.
2007-02-24 Manoj Srivastava <srivasta@debian.org>
* ucf.1: srivasta@debian.org--etch/ucf--devel--2.0--versionfix-3
Add documentation clarifying the primary use for ucf.
* ucfr (safe_conf_file):
srivasta@debian.org--etch/ucf--devel--2.0--versionfix-2
Add $progname: prefix to all error messages.
2007-01-18 Manoj Srivastava <srivasta@debian.org>
* ucfr.1: srivasta@debian.org--etch/ucf--devel--2.0--versionfix-1
Emphasize that the full path to the configuration file
is expected.
* ucfq.1: srivasta@debian.org--etch/ucf--devel--2.0--versionfix-1
Ditto.
* ucfr (safe_conf_file):
srivasta@debian.org--etch/ucf--devel--2.0--versionfix-1
Issue a diagnostic, and exit gracefully if the
registration request has not provided a full path to the
configuration file. For lenny, the graceful exit shall
be changed into die with a error message.
* ucfq (process):
srivasta@debian.org--etch/ucf--devel--2.0--versionfix-1
Issue a diagnostic, and exit gracefully if the query has
not provided a full path to the configuration file. For
lenny, the graceful exit shall be changed into die with
a error message.
* ucf: srivasta@debian.org--etch/ucf--devel--2.0--patch-20 Typo
fix.
* ucf.1: srivasta@debian.org--etch/ucf--devel--2.0--patch-20 Typo
fix.
2006-11-16 Manoj Srivastava <srivasta@debian.org>
* ucfr.1: srivasta@debian.org--etch/ucf--devel--2.0--patch-18 Typo
fixes: cofiguration -> configuration, asociating ->
associating, mutiple -> multiple
* ucfq.1: srivasta@debian.org--etch/ucf--devel--2.0--patch-18 Typo
Fix: modfied -> modified
* ucf.1: srivasta@debian.org--etch/ucf--devel--2.0--patch-18 Typo
fix: "witht he" -> "with the"
2006-10-23 Manoj Srivastava <srivasta@debian.org>
* ucf (TEMP): srivasta@debian.org--etch/ucf--devel--2.0--patch-17
Use readlink to canonicalize the path names presented to
ucf. This ensures that we keep track of information
about the correct file in ucf, even if it is referred to
differently (like, multiple ///s, or a/../a/)
* ucfq: srivasta@debian.org--etch/ucf--devel--2.0--patch-16 The
package name is ucf, not Ucf. Fixes the usage help
output.
2006-09-11 Manoj Srivastava <srivasta@debian.org>
* ucf.1 (needed):
srivasta@debian.org--etch/ucf--devel--2.0--patch-15 Typo fix.
2006-08-20 Manoj Srivastava <srivasta@debian.org>
* ucf.1: srivasta@debian.org--etch/ucf--devel--2.0--patch-14
Document various extensions optionally used by ucf to
store copies of versions of configuration files ucf is
working with.
2006-06-16 Manoj Srivastava <srivasta@debian.org>
* ucf (safe_dest_file):
srivasta@debian.org--etch/ucf--devel--2.0--patch-12
Improve the handling of finding a sensible pager. This
now handles a messed up /etc/alternatives/paper
setting. Also included sensible pager as an
alternative, and fall back to /bin/more if
needed. Also, allow for readlink failures.
2006-04-11 Manoj Srivastava <srivasta@debian.org>
* ucf.1: srivasta@debian.org--etch/ucf--devel--2.0--patch-8 Added
documentation for the --state-dir option.
* ucfr.1: Documentation for the new command ucfr
* ucfr: New file. Associates, and disassociates, a package name
with configuration files.
* Makefile (check):
srivasta@debian.org--etch/ucf--devel--2.0--patch-8 Added
a check for ucfr
(install):
srivasta@debian.org--etch/ucf--devel--2.0--patch-8
Install ucfr and manual page as well
* ucf (NEW_SUFFIX):
srivasta@debian.org--etch/ucf--devel--2.0--patch-7 Added
new variables to hold the suffix we use todenote the
{maintainers, old, new} versions of a file. Used to be
dpkg-{dist,old,new}, now it is ucf-{dist,old,new}.
2005-09-20 Manoj Srivastava <srivasta@debian.org>
* ucf (newsum): srivasta@debian.org--etch/ucf--devel--2.0--patch-4
Added support for side-by-side diffs, This is very
similar to doing a standard diff, apart from calling
sdiff instead (and change the option switches around as
needed.
2005-09-01 Manoj Srivastava <srivasta@debian.org>
* examples/postrm:
srivasta@debian.org--etch/ucf--devel--2.0--patch-2 only
use ucf if it is available
2005-08-08 Manoj Srivastava <srivasta@debian.org>
* ucf: srivasta@debian.org--etch/ucf--devel--2.0--patch-1 Add code
to determine the value of UCF_FORCE_CONFFMISS, looking
at the command line, env variable, config file, or
default (the default being unset). No command line
option is currently available, but the underpinning are
there. Replace the destination file, if missing, and iff
the variable is set.
* ucf.1: srivasta@debian.org--etch/ucf--devel--2.0--patch-1
Document UCF_FORCE_CONFFMISS. This environment variable
is only applicable when the installed destination file
does not exist (perhaps due to user removal),and forces
ucf to recreate the missing file (the default behaviour
is to honor the users wishes and not recreate the
locally deleted file).
2005-06-25 Manoj Srivastava <srivasta@debian.org>
* ucf (safe_dest_file):
srivasta@debian.org--etch/ucf--devel--0.1--base-0 Well,
setting VERBOSE to 0 is the same as being quiet,
according to the man page. Unfortunately, the code
actually looked to see if VERBOSE was set (even if set
to 0). Now, we unset VERBOSE if the user had set it to
0, making everyone happy.

72
Makefile Normal file
View File

@ -0,0 +1,72 @@
############################ -*- Mode: Makefile -*- ###########################
## Makefile<ucf> ---
## Author : Manoj Srivastava ( srivasta@glaurung.green-gryphon.com )
## Created On : Tue Nov 18 22:00:27 2003
## Created On Node : glaurung.green-gryphon.com
## Last Modified By : Manoj Srivastava
## Last Modified On : Sun Apr 16 16:32:23 2006
## Last Machine Used: glaurung.internal.golden-gryphon.com
## Update Count : 6
## Status : Unknown, Use with caution!
## HISTORY :
## Description :
##
###############################################################################
prefix = $(DESTDIR)
package = ucf
ETCDIR = $(prefix)/etc
BINDIR = $(prefix)/usr/bin
DEBLIBDIR = $(prefix)/var/lib/$(package)
DEBDOCDIR = $(prefix)/usr/share/doc/$(package)
MANDIR = $(prefix)/usr/share/man/
MAN1DIR = $(MANDIR)/man1
MAN5DIR = $(MANDIR)/man5
# install commands
install_file := /usr/bin/install -p -o root -g root -m 644
install_program := /usr/bin/install -p -o root -g root -m 755
make_directory := /usr/bin/install -p -d -o root -g root -m 755
all build: check
check:
bash -n ucf
bash -n ucfr
perl -wc ucfq
bash -n debian/ucf.preinst
bash -n debian/ucf.postinst
bash -n debian/ucf.postrm
install:
$(make_directory) $(BINDIR)
$(make_directory) $(ETCDIR)
$(make_directory) $(MAN1DIR)
$(make_directory) $(MAN5DIR)
$(make_directory) $(DEBLIBDIR)
$(make_directory) $(DEBDOCDIR)/examples
$(install_program) ucf $(BINDIR)
$(install_file) ucf.1 $(MAN1DIR)
gzip -9fq $(MAN1DIR)/ucf.1
$(install_program) ucfr $(BINDIR)
$(install_file) ucfr.1 $(MAN1DIR)
gzip -9fq $(MAN1DIR)/ucfr.1
$(install_program) ucfq $(BINDIR)
$(install_file) ucfq.1 $(MAN1DIR)
gzip -9fq $(MAN1DIR)/ucfq.1
$(install_program) lcf $(BINDIR)
$(install_file) lcf.1 $(MAN1DIR)
gzip -9fq $(MAN1DIR)/lcf.1
$(install_file) ucf.conf.5 $(MAN5DIR)
gzip -9fq $(MAN5DIR)/ucf.conf.5
$(install_file) ucf.conf $(ETCDIR)
$(install_file) debian/changelog $(DEBDOCDIR)/changelog
gzip -9frq $(DEBDOCDIR)
# make sure the copyright file is not compressed
$(install_file) debian/copyright $(DEBDOCDIR)/copyright
$(install_file) examples/postinst $(DEBDOCDIR)/examples/
$(install_file) examples/postrm $(DEBDOCDIR)/examples/
clean distclean:
@echo nothing to do for clean

6
examples/ChangeLog Normal file
View File

@ -0,0 +1,6 @@
2007-04-17 Manoj Srivastava <srivasta@debian.org>
* postrm: srivasta@debian.org--lenny/ucf--devel--2.0--base-0 Now
ucf creates .ucf-new, .ucf-old, and .ucf-dist suffixes,
so the example is updated to clean the new names.

153
examples/postinst Normal file
View File

@ -0,0 +1,153 @@
#! /bin/sh
# postinst.skeleton
# Skeleton maintainer script showing all the possible cases.
# Written by Charles Briscoe-Smith, March-June 1998. Public Domain.
# Abort if any command returns an error value
set -e
# This script is called as the last step of the installation of the
# package. All the package's files are in place, dpkg has already done
# its automatic conffile handling, and all the packages we depend of
# are already fully installed and configured.
# The following idempotent stuff doesn't generally need protecting
# against being run in the abort-* cases.
# Install info files into the dir file
: install-info --quiet --section "section pattern" "Section Title" \
: --description="Name of the document" /usr/info/foo.info
# Create stub directories under /usr/local
: if test ! -d /usr/local/lib/foo; then
: if test ! -d /usr/local/lib; then
: if mkdir /usr/local/lib; then
: chown root.staff /usr/local/lib || true
: chmod 2775 /usr/local/lib || true
: fi
: fi
: if mkdir /usr/local/lib/foo; then
: chown root.staff /usr/local/lib/foo || true
: chmod 2775 /usr/local/lib/foo || true
: fi
: fi
# Ensure the menu system is updated
: [ ! -x /usr/bin/update-menus ] || /usr/bin/update-menus
# Arrange for a daemon to be started at system boot time
: update-rc.d foo default >/dev/null
case "$1" in
configure)
# Configure this package. If the package must prompt the user for
# information, do it here.
:
# Activate menu-methods script
: chmod a+x /etc/menu-methods/foo
# Update ld.so cache
: ldconfig
# Make our version of a program available
: update-alternatives \
: --install /usr/bin/program program /usr/bin/alternative 50 \
: --slave /usr/share/man/man1/program.1.gz program.1.gz \
: /usr/share/man/man1/alternative.1.gz
# Tell ucf that the file in /usr/share/foo is the latest
# maintainer version, and let it handle how to manage the real
# confuguration file in /etc. This is how a static configuration
# file can be handled:
ucf /usr/share/foo/configuration /etc/foo.conf
ucfr foo /etc/foo.conf
### We could also do this on the fly. The following is from Tore
### Anderson:
#. /usr/share/debconf/confmodule
### find out what the user answered.
# db_get foo/run_on_boot
# run_on_boot=$RET
# db_stop
### safely create a temporary file to generate our suggested
### configuration file.
# tempfile=`tempfile`
# cat << _eof > $tempfile
### Configuration file for Foo.
### this was answered by you, the user in a debconf dialogue
# RUNONBOOT=$run_on_boot
### this was not, as it has a sane default value.
# COLOUROFSKY=blue
#_eof
### Note that some versions of debconf do not release stdin, so
### the following invocation of ucf may not work, since the stdin
### is never connected to ucfr.
### now, invoke ucf, which will take care of the rest, and ask
### the user if he wants to update his file, if it is modified.
#ucf $tempfile /etc/foo.conf
### done! now we'll just clear up our cruft.
#rm -f $tempfile
# There are three sub-cases:
if test "${2+set}" != set; then
# We're being installed by an ancient dpkg which doesn't remember
# which version was most recently configured, or even whether
# there is a most recently configured version.
:
elif test -z "$2" -o "$2" = "<unknown>"; then
# The package has not ever been configured on this system, or was
# purged since it was last configured.
:
else
# Version $2 is the most recently configured version of this
# package.
:
fi ;;
abort-upgrade)
# Back out of an attempt to upgrade this package FROM THIS VERSION
# to version $2. Undo the effects of "prerm upgrade $2".
:
;;
abort-remove)
if test "$2" != in-favour; then
echo "$0: undocumented call to \`postinst $*'" 1>&2
exit 0
fi
# Back out of an attempt to remove this package, which was due to
# a conflict with package $3 (version $4). Undo the effects of
# "prerm remove in-favour $3 $4".
:
;;
abort-deconfigure)
if test "$2" != in-favour -o "$5" != removing; then
echo "$0: undocumented call to \`postinst $*'" 1>&2
exit 0
fi
# Back out of an attempt to deconfigure this package, which was
# due to package $6 (version $7) which we depend on being removed
# to make way for package $3 (version $4). Undo the effects of
# "prerm deconfigure in-favour $3 $4 removing $6 $7".
:
;;
*) echo "$0: didn't understand being called with \`$1'" 1>&2
exit 0;;
esac
exit 0

115
examples/postrm Normal file
View File

@ -0,0 +1,115 @@
#! /bin/sh
# postrm.skeleton
# Skeleton maintainer script showing all the possible cases.
# Written by Charles Briscoe-Smith, March-June 1998. Public Domain.
# Abort if any command returns an error value
set -e
# This script is called twice during the removal of the package; once
# after the removal of the package's files from the system, and as
# the final step in the removal of this package, after the package's
# conffiles have been removed.
# Ensure the menu system is updated
: [ ! -x /usr/bin/update-menus ] || /usr/bin/update-menus
case "$1" in
remove)
# This package is being removed, but its configuration has not yet
# been purged.
:
# Remove diversion
: dpkg-divert --package foo --remove --rename \
: --divert /usr/bin/other.real /usr/bin/other
# ldconfig is NOT needed during removal of a library, only during
# installation
;;
purge)
# This package has previously been removed and is now having
# its configuration purged from the system.
:
# we mimic dpkg as closely as possible, so we remove configuration
# files with dpkg backup extensions too:
### Some of the following is from Tore Anderson:
for ext in '~' '%' .bak .ucf-new .ucf-old .ucf-dist; do
rm -f /etc/foo.conf$ext
done
# remove the configuration file itself
rm -f /etc/foo.conf
# and finally clear it out from the ucf database
if which ucf >/dev/null; then
ucf --purge /etc/foo.conf
fi
if which ucfr >/dev/null; then
ucfr --purge foo /etc/foo.conf
fi
# Remove symlinks from /etc/rc?.d
: update-rc.d foo remove >/dev/null
;;
disappear)
if test "$2" != overwriter; then
echo "$0: undocumented call to \`postrm $*'" 1>&2
exit 0
fi
# This package has been completely overwritten by package $3
# (version $4). All our files are already gone from the system.
# This is a special case: neither "prerm remove" nor "postrm remove"
# have been called, because dpkg didn't know that this package would
# disappear until this stage.
:
;;
upgrade)
# About to upgrade FROM THIS VERSION to version $2 of this package.
# "prerm upgrade" has been called for this version, and "preinst
# upgrade" has been called for the new version. Last chance to
# clean up.
:
;;
failed-upgrade)
# About to upgrade from version $2 of this package TO THIS VERSION.
# "prerm upgrade" has been called for the old version, and "preinst
# upgrade" has been called for this version. This is only used if
# the previous version's "postrm upgrade" couldn't handle it and
# returned non-zero. (Fix old postrm bugs here.)
:
;;
abort-install)
# Back out of an attempt to install this package. Undo the effects of
# "preinst install...". There are two sub-cases.
:
if test "${2+set}" = set; then
# When the install was attempted, version $2's configuration
# files were still on the system. Undo the effects of "preinst
# install $2".
:
else
# We were being installed from scratch. Undo the effects of
# "preinst install".
:
fi ;;
abort-upgrade)
# Back out of an attempt to upgrade this package from version $2
# TO THIS VERSION. Undo the effects of "preinst upgrade $2".
:
;;
*) echo "$0: didn't understand being called with \`$1'" 1>&2
exit 0;;
esac
exit 0

260
lcf Executable file
View File

@ -0,0 +1,260 @@
#!/bin/bash
# -*- Mode: Sh -*-
# lcf ---
# Author : Manoj Srivastava ( srivasta@glaurung.green-gryphon.com )
# Created On : Mon Feb 25 12:04:52 2002
# Created On Node : glaurung.green-gryphon.com
# Last Modified By : Manoj Srivastava
# Last Modified On : Mon Feb 25 12:06:54 2002
# Last Machine Used: glaurung.green-gryphon.com
# Update Count : 2
# Status : Unknown, Use with caution!
# HISTORY :
# Description :
#
#
# make sure we exit on error
set -e
# set the version and revision
progname="$(basename $0)"
pversion='Revision: 3.00'
######################################################################
######## #########
######## Utility functions #########
######## #########
######################################################################
setq() {
# Variable Value Doc_string
if [ "x$2" = "x" ]; then
echo >&2 "$progname: Unable to determine $3"
exit 1;
else
if [ "x$VERBOSE" != "x" ]; then
echo "$progname: $3 is $2";
fi
eval "$1=\"\$2\"";
fi
}
withecho () {
echo "$@" >&2
"$@"
}
usageversion () {
cat >&2 <<END
Debian GNU/Linux $progname $pversion.
Copyright (C) 2002 Manoj Srivastava.
This is free software; see the GNU General Public Licence for copying
conditions. There is NO warranty.
Usage: $progname [options] dest_file src_dir
Options:
-h, --help print this message
-s foo, --src-dir foo Set the src dir (historical md5sums live here)
-d [n], --debug [n] Set the Debug level to N
-n, --no-action Dry run. No action is actually taken.
-v, --verbose Make the script verbose
By default, the directory the new_file lives in is assumed to be the src-dir,
which is where we look for any historical md5sums.
END
}
######################################################################
######## #########
######## Command line args #########
######## #########
######################################################################
#
# Long term variables#
#
docmd='YES'
action='withecho'
DEBUG=0
VERBOSE=''
statedir='/var/lib/ucf';
# Note that we use `"$@"' to let each command-line parameter expand to a
# separate word. The quotes around `$@' are essential!
# We need TEMP as the `eval set --' would nuke the return value of getopt.
TEMP=$(getopt -o hs:d:D::nv -n "$progname" \
--long help,src-dir:,dest-dir:DEBUG::,no-action,verbose \
-- "$@")
if [ $? != 0 ] ; then
echo "Error handling options.Terminating..." >&2 ;
exit 1 ;
fi
# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"
while true ; do
case "$1" in
-h|--help) usageversion; exit 0 ;;
-n|--no-action) action='echo'; docmd='NO'; shift ;;
-v|--verbose) VERBOSE=1; shift ;;
-s|--src-dir)
opt_source_dir="$2"; shift 2 ;;
-d|--debug)
# d has an optional argument. As we are in quoted mode,
# an empty parameter will be generated if its optional
# argument is not found.
case "$2" in
"") setq DEBUG 1 "The Debug value"; shift 2 ;;
*) setq DEBUG "$2" "The Debug value"; shift 2 ;;
esac ;;
--) shift ; break ;;
*) echo "Internal error!" ; exit 1 ;;
esac
done
if [ $# != 2 ]; then
echo >&2 "*** ERROR: Need exactly two arguments, got $#";
echo >&2 ""
usageversion;
exit 0 ;
fi
setq dest_file "$1" "The Destination file";
setq source_dir "$2" "The source directory";
# Load site defaults and over rides.
if [ -f /etc/ucf.conf ]; then
. /etc/ucf.conf
fi
# Command line, env variable, config file, or default
if [ "X$source_dir" = "X" ]; then
if [ ! "x$opt_source_dir" = "x" ]; then
setq source_dir "$opt_source_dir" "The Source directory"
elif [ ! "x$UCF_SOURCE_DIR" = "x" ]; then
setq source_dir "$UCF_SOURCE_DIR" "The Source directory"
elif [ ! "x$conf_source_dir" = "x" ]; then
setq source_dir "$conf_source_dir" "The Source directory"
fi
fi
if [ ! -d "$source_dir" ]; then
echo >&2 "The source dir does not exist. Stopping now."
exit 2;
fi
if [ "X$dest_file" = "X" ]; then
echo >&2 "Uknown file to search for. Stopping now."
exit 2;
fi
old_mdsum_dir="$source_dir/$(basename ${new_file}).md5sum.d";
old_mdsum_file="$source_dir/$(basename ${new_file}).md5sum";
if [ -e "$statedir/hashfile" -a ! -r "$statedir/hashfile" ]; then
echo >&2 "$progname: do not have read privilege to the state data"
if [ "X$docmd" = "XYES" ]; then
exit 1;
fi
fi
# test and see if this file exists in the database
if [ -e "$statedir/hashfile" ]; then
if [ "X$VERBOSE" != "X" ]; then
echo >&2 "The hash file exists";
echo grep "[[:space:]]${dest_file}$" "$statedir/hashfile";
grep "[[:space:]]${dest_file}$" "$statedir/hashfile" ;
fi
lastsum=$(grep "[[:space:]]${dest_file}$" "$statedir/hashfile" | \
awk '{print $1;}' );
fi
if [ "X$lastsum" = "X" ]; then
echo >&2 "$progname: No record of file in databse. Stopping now."
exit 2;
fi
if [ $DEBUG -gt 0 ]; then
cat <<EOF
The new start file is \`$new_file\'
The destination is \`$dest_file\'
The history is kept under \'$source_dir\'
EOF
if [ -s "$dest_file" ]; then
echo "The destination file exists, and has md5sum:"
$action md5sum "$dest_file"
else
echo "The destination file does not exist."
fi
if [ "X$lastsum" != "X" ]; then
echo "The old md5sum exists, and is:"
echo "$lastsum"
else
echo "The old md5sum does not exist."
fi
if [ -e "$new_file" ]; then
echo "The new file exists, and has md5sum:"
$action md5sum "$new_file"
else
echo "The new file does not exist."
fi
if [ -d "$old_mdsum_dir" ]; then
echo "The historical md5sum dir $old_mdsum_dir exists"
elif [ -f "$old_mdsum_file" ]; then
echo "The histotical md5sum file $old_mdsum_file exists"
else
echo "Historical md5sums are not available"
fi
fi
if [ -d "$old_mdsum_dir" -o -f "$old_mdsum_file" ]; then
if [ -d "$old_mdsum_dir" ]; then
for file in ${old_mdsum_dir}/*; do
oldsum="$(awk '{print $1}' $file)";
if [ "$oldsum" = "$destsum" ]; then
# Bingo!
echo "$(awk '{print $2}' $file)";
exit 0;
fi
done
elif [ -f "$old_mdsum_file" ]; then
oldsum=$(grep "^${destsum}" "$old_mdsum_file")
if [ "X$oldsum" != "X" ]; then
# Bingo
echo $(grep "^${destsum}" "$old_mdsum_file" | awk '{print $2}')
exit 0;
fi
fi
# Well, nothing matched. We now check to see if the
# maintainer has an opinion on how to set the ``md5sum of the
# previously installed version'', since we have no way of
# determining that automatically. Please note that unless
# there are limited number of previously released packages
# (like just one), the maintainer is also making a guess at
# this point by supplying a historical md5sum default file.
if [ "X$VERBOSE" != "X" ]; then
echo >&2 "Histotical md5sums did not match."
fi
if [ -d "$old_mdsum_dir" ]; then
if [ -e "${old_mdsum_dir}/default" ]; then
echo default;
exit 0;
fi
elif [ -f "$old_mdsum_file" ]; then
oldsum=$(grep "[[:space:]]default$" "$old_mdsum_file" | \
awk '{print $1;}')
if [ "X$oldsum" != "X" ]; then
# Bingo
echo default;
exit 0;
fi
fi
fi
exit 0;

85
lcf.1 Normal file
View File

@ -0,0 +1,85 @@
.\" -*- Mode: Nroff -*-
.\" lcf.1 ---
.\" Author : Manoj Srivastava ( srivasta@green-gryphon.com )
.\" Created On : Fri Feb 1 11:17:32 2002
.\" Created On Node : glaurung.green-gryphon.com
.\" Last Modified By : Manoj Srivastava
.\" Last Modified On : Mon May 2 01:09:42 2005
.\" Last Machine Used: glaurung.internal.golden-gryphon.com
.\" Update Count : 28
.\" Status : Unknown, Use with caution!
.\" HISTORY :
.\" Description :
.\"
.\" Copyright (c) 2002 Manoj Srivastava <srivasta@debian.org>
.\"
.\" This is free documentation; you can redistribute it and/or
.\" modify it under the terms of the GNU General Public License as
.\" published by the Free Software Foundation; either version 2 of
.\" the License, or (at your option) any later version.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
.\" 02111-1307, USA.
.\"
.\" $Id: lcf.1,v 1.1 2002/02/26 20:12:06 srivasta Exp $
.TH LCF 1 "Feb 1 2002" "Debian" "Debian GNU/Linux manual"
.SH NAME
lcf \- Determine which of the historical versions of a config is installed
.SH SYNOPSIS
.B lcf
.I [options]
.I <Destination File Name>
.I <Historical MD5SUM source directory>
.SH DESCRIPTION
This script, given a destination file name, and a directory containing
md5sums of historical versions of the file, attempts to determine if
the installed version corresponds to a historical version. lcf uses
the same algorithm that ucf uses, and should exhibit the same
behaviour.
.PP
The source directory is the place where historical md5sums are
expected to live. Specifically, the historical md5sums are looked for
in either the file
.I ${filename}.md5sum,
or the subdirectory
.I ${filename}.md5sum.d/
.SH OPTIONS
.TP
.B "-h, --help"
Print a short usage message
.TP
.B "-n, --no-action"
Dry run. Print the actions that would be taken if the script is
invoked, but take no action.
.TP
.B "-d [n], --debug [n]"
Set the debug level to the (optional) level
.I n
(n defaults to 1). This turns on copious debugging information.
.TP
.B "-v, --verbose"
Make the script be very verbose about setting internal variables.
.SH FILES
.PP
.I /var/lib/ucf/hashfile,
.I /etc/ucf.conf
.SH "SEE ALSO"
ucf(1)
ucf.conf(5).
.SH BUGS
There are no bugs. Any resemblance thereof is delirium. Really.
.SH AUTHOR
This manual page was written Manoj Srivastava <srivasta@debian.org>,
for the Debian GNU/Linux system.

1117
ucf Executable file

File diff suppressed because it is too large Load Diff

369
ucf.1 Normal file
View File

@ -0,0 +1,369 @@
.\" -*- Mode: Nroff -*-
.\" updateConfFile.1 ---
.\" Author : Manoj Srivastava ( srivasta@green-gryphon.com )
.\" Created On : Fri Feb 1 11:17:32 2002
.\" Created On Node : glaurung.green-gryphon.com
.\" Last Modified By : Manoj Srivastava
.\" Last Modified On : Tue Apr 11 14:46:06 2006
.\" Last Machine Used: glaurung.internal.golden-gryphon.com
.\" Update Count : 53
.\" Status : Unknown, Use with caution!
.\" HISTORY :
.\" Description :
.\"
.\" Copyright (c) 2002 Manoj Srivastava <srivasta@debian.org>
.\"
.\" This is free documentation; you can redistribute it and/or
.\" modify it under the terms of the GNU General Public License as
.\" published by the Free Software Foundation; either version 2 of
.\" the License, or (at your option) any later version.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
.\" 02111-1307, USA.
.\"
.\" $Id: ucf.1,v 1.10 2003/09/28 23:29:21 srivasta Exp $
.TH UCF 1 "May 30 2008" "Debian" "Debian GNU/Linux manual"
.SH NAME
ucf \- Update Configuration File: preserve user changes in configuration files
.SH SYNOPSIS
.B ucf
.RI [ options "] "
.I <New File>
.I <Destination>
.PP
.B ucf
.RI [ options "] "
.I \-\-purge
.I <Destination>
.SH DESCRIPTION
This utility provides a means of asking the user whether or not to
accept new versions of configuration files provided by the package
maintainer, with various heuristics designed to minimize
interaction time. It uses debconf to interact with the user, as per Debian
policy. In the SYNOPSIS above,
.I New file
is the configuration file as provided by the package (either shipped
with the package, or generated by the maintainer scripts on the fly),
and
.I Destination
is the location (usually under /etc) where the real configuration file
lives, and is potentially modified by the end user. Since the files
edited would be real files, and not symbolic links,
.B ucf
follows and resolves symbolic links before acting. As far as
possible, ucf attempts to preserve the ownership and permission of
the
.I New file
as it is copied to the new location.
.PP
This script attempts to provide conffile like handling for files
installed under
.I /etc
not
shipped in a
.B Debian
package, but handled by the postinst instead.
.B Debian
policy states that files under
.I /etc
which are configuration files
.B must
preserve user changes, and this applies to files handled by maintainer
scripts as well. Using
.B ucf,
one may ship a bunch of default configuration files somewhere in
.I /usr
(
.I /usr/share/<pkg>
is a good location), and maintain files in
.I /etc,
preserving user changes and in general offering the same facilities
while upgrading that
.B dpkg
normally provides for
.I \*(lqconffiles\*(rq
.PP
Additionally, this script provides facilities for transitioning a file
that had not been provided
.I conffile
like protection to come under this
schema, and attempts to minimize questions asked at install
time. Indeed, the transitioning facility is better than the one
offered by
.B dpkg
while transitioning a file from a
.I non\-conffile
to
.I conffile
status. The second form in the SYNOPSIS above is for purging
information about the configuration file when the package is purged;
and is critical for allowing smooth reinstallations.
.PP
During the course of operations, when working with configuration files,
.B ucf
optionally creates copies of versions of the configuration file in
question. For example, a file with the suffix
.I "ucf-old"
holds the old version of a configuration file replaced by
.B ucf.
Also, copies of the configuration file with the suffixes
.I "ucf-new"
and
.I "ucf-dist"
may be created; and the maintainer scripts should consider purging
copies of the configuration file with these extensions during purge.
.SH OPTIONS
.TP
.B "\-h, \-\-help"
Print a short usage message
.TP
.B "\-n, \-\-no\-action"
Dry run. Print the actions that would be taken if the script is
invoked, but take no action.
.TP
.B "\-d[n], \-\-debug=[n]"
Set the debug level to the (optional) level
.I n
(n defaults to 1). Please note there must be no spaces before the
optional digit n. This turns on copious debugging information.
.TP
.B "\-p, \-\-purge"
Removes all vestiges of the file from the state hashfile. This is
required to allow a package to be reinstalled after it is purged;
since otherwise, the real configuration file is removed, but it
remains in the hash file; and on reinstall no action is taken, since
the md5sum of the new file matches that in the hashfile. In short,
remember to use this option in the postrm for every configuration file
managed by ucf when the package is being purged (assuming ucf itself
exists).
.I Note:
ucf does not actually touch the file on disk in this operation, so any
file removals are still the responsibility of the calling package.
.TP
.B "\-v, \-\-verbose"
Make the script be very verbose about setting internal variables.
.TP
.B "\-s foo, \-\-src\-dir foo"
Set the source directory (historical md5sums are expected to live in
files and sub directories of this directory) to foo. By default, the
directory the new_file lives in is assumed to be the source
directory. Setting this option overrides settings in the environment
variable
.B UCF_SOURCE_DIR,
and in the configuration file variable
.B conf_source_dir.
.TP
.B "\-\-sum\-file foo"
Force the historical md5sums to be read from this file, rather than
defaulting to living in the source directory. Setting this option
overrides settings in the environment variable
.B UCF_OLD_MDSUM_FILE,
and in the configuration file variable
.B conf_old_mdsum_file.
.TP
.B "\-\-three\-way"
This turns on the option, during installation, for the user to be
offered a chance to see a merge of the changes between old maintainer
version and the new maintainer version into the local copy of the
configuration file. If the user likes what they see, they can ask to
have these changes merged in. This allows one to get new upstream
changes merged in even while retaining local modifications to the
configuration file. This is accomplished by taking the configuration
file and stashing it in a cache area during registration, and using
diff3 during the install (the stashed file name is a munged version of
the full path of the configuration file to avoid name space clashes).
.TP
.B "\-\-debconf\-ok"
Indicate that it is ok for
.I ucf
to use an already running debconf instance for prompting (it has
always been ok to use ucf when debconf is not running -- it shall
invoke debconf as needed).
.TP
.B "\-\-debconf\-template foo"
Instruct ucf to use the named multiselect debconf template instead of
the normal ucf-provided debconf template. The caller is responsible for
ensuring that the named template exists and has a list of choices
matching those for the default ucf template, and should set
Choices\-C: ${CHOICES} to ensure the returned values match those from
the default template. Note that the choices must be different according
to whether the
.B \-\-three\-way
option is also set.
.TP
.B "\-\-state\-dir /path/to/dir"
Set the state directory to /path/to/dir instead of the default
.I /var/lib/ucf.
Used mostly for testing.
.SH USAGE
The most common case usage is pretty simple: a single line invocation
in the postinst on configure, and another single line in the postrm to
tell
.B ucf
to forget about the configuration file on purge
(using the \-\-purge option) is all that is needed (assuming ucf is
still on the system).
.PP
It is recommended that you also register any file being managed by
.B ucf
with the ucf registry; this associates the configuration file with the
package it belongs to. This is done with a simple call to
.B ucfr.
Users may then query the association between a configuration file and
the package using the tool
.B ucfq.
Please see the appropriate manual pages for details.
.PP
If a file maintained by maintainer scripts is being transitioned from an
unprotected status to the protection afforded by the script, the
maintainer can help ease the transition by reducing the questions that
may be asked at installation time. Specifically, questions should not
be asked if the file in question is an unmodified version that was one
shipped in a previous version of this package; and the maintainer can
help by telling the script about the historical md5sums that published
versions of this file contained.
.PP
The way to do this is to either create a file called
.B <New file>.md5sum,
with one md5sum on each line, (the file names you use are ignored, except
for the entry named default), or create a directory, called
.B <New file>.md5sum.d,
which should contain any number of files, each containing a single
line, namely, the md5sum of a previous version of
.B <New file>.
The names of these files are not important, with one exception: The
file called default is treated specially. For example, the author
personally uses either package version numbers or release code names,
like
.I 7.6.3,
or
.I potato.
If none of the historical md5sums match, we are almost certain that
either the historical record of md5sums is not complete, or the user
has changed the configuration file.
.SS "The default historical md5sum"
The exception to the rule about names mentioned earlier is that if no
md5sums match, and if the file
.B <New file>.md5sum.d/default
exists, or if there is a line corresponding to a
.I default
file in
.B <New file>.md5sum,
it shall be used as the default md5sum of the
.I previous
version of the package assumed to have been installed on this machine.
As you can see, unless there are limited number of previously released
packages (like just one), the maintainer is also making an informed
guess, but the option is provided to the maintainer.
.PP
If the file
.B <New file>.md5sum,
or the directory
.B <New file>.md5sum.d
does not exist, or none of the md5sums match, we test the installed
.I <Destination>
file to see whether it is the same as the
.I <New file>.
If not, we ask the user whether they want us to replace the file.
.PP
An additional facility is also offered: optionally, ucf can store one
old version of the maintainers copy of the configuration file, and,
on upgrade, calculate the changes made in the maintainers version of
the configuration file, and apply that patch to the local version of
the file (on user request, of course). There is also a preview
facility where the user can inspect the results of such a merge,
before asking the action to be taken.
.SH "ENVIRONMENT VARIABLES"
The variable
.B UCF_FORCE_CONFFNEW,
if set, forces the new file to always overwrite the installed
destination file, while the variable
.B UCF_FORCE_CONFFOLD,
if set silently retains the installed file.
.B UCF_FORCE_CONFFMISS
is only applicable when the installed destination file does not exist
(perhaps due to user removal),and forces ucf to recreate the missing
file (the default behaviour is to honor the users wishes and not
recreate the locally deleted file).
.SH FILES
This script creates the file
.I new_file.md5sum,
and it may copy the file (presumably shipped with the package)
.I <New file>
to its destination,
.I <Destination>.
.PP
.I /var/lib/ucf/hashfile,
and
.I /var/lib/ucf/hashfile.X,
where
.I X
is a small integer, where previous versions of the hashfile are
stored.
.PP
.I /etc/ucf.conf
.SH EXAMPLES
If the package
.I foo
wants to use ucf to handle user interaction for configuration file
.I foo.conf,
a version of which is provided in the package as
.I /usr/share/foo/configuration,
a simple invocation of ucf in the post inst file is all that is
needed:
.PP
.B ucf
.I /usr/share/foo/configuration
.I /etc/foo.conf
.PP
On purge, one should tell ucf to forget about the file (see detailed
examples in /usr/share/doc/ucf/examples):
.PP
.B ucf
.I \-\-purge
.I /etc/foo.conf
Please note that purge can also be used to make ucf forget the
previous state of the files, and when the package is next installed or
updated, ucf will ask the user to replace the current cofiguration
file. Do this if you want to change your decision to not update to a
maintainer provided version of the configuration file.
.PP
The motivation for this script was to provide conffile like handling
for start files for emacs lisp packages (for example,
.I /etc/emacs21/site\-start.d/50psgml\-init.el
) These start files are not
shipped with the package, instead, they are installed during the
post installation configuration phase by the script
.I /usr/lib/emacsen\-common/emacs\-package\-install $package_name.
.PP
This script is meant to be invoked by the packages install script at
.I /usr/lib/emacsen\-common/packages/install/$package_name
for each
flavour of installed emacsen by calling it with the proper values of
new file (
.I /usr/share/emacs/site\-lisp/<pkg>/<pkg\-init.el
), and dest file
(
.I /etc/emacs21/site\-start.d/50<pkg\-init.el
), and it should do the rest.
.SH "SEE ALSO"
ucf.conf(5), ucfr(1), ucfq(1), and diff3(1).
The
.B Debian
Emacs policy, shipped with the package
.I emacsen\-common.
.SH AUTHOR
This manual page was written Manoj Srivastava <srivasta@debian.org>,
for the Debian GNU/Linux system.

39
ucf.conf Normal file
View File

@ -0,0 +1,39 @@
#
# This file is a bourne shell snippet, and is sourced by the
# ucf script for configuration.
#
# Debugging information: The default value is 0 (no debugging
# information is printed). To change the default behavior, uncomment
# the following line and set the value to 1.
#
# DEBUG=0
# Verbosity: The default value is 0 (quiet). To change the default
# behavior, uncomment the following line and set the value to 1.
#
# VERBOSE=0
# The src directory. This is the directory where the historical
# md5sums for a file are looked for. Specifically, the historical
# md5sums are looked for in the subdirectory ${filename}.md5sum.d/
#
# conf_source_dir=/some/path/
# Force the installed file to be retained. The default is have this
# variable unset, which makes the script ask in case of doubt. To
# change the default behavior, uncomment the following line and set
# the value to YES
#
# conf_force_conffold=YES
# Force the installed file to be overridden. The default is have this
# variable unset, which makes the script ask in case of doubt. To
# change the default behavior, uncomment the following line and set
# the value to YES
#
# conf_force_conffnew=YES
# Please note that only one of conf_force_conffold and
# conf_force_conffnew should be set.

120
ucf.conf.5 Normal file
View File

@ -0,0 +1,120 @@
.\" -*- Mode: Nroff -*-
.\" updateConfFile.1 ---
.\" Author : Manoj Srivastava ( srivasta@green-gryphon.com )
.\" Created On : Fri Feb 1 11:17:32 2002
.\" Created On Node : glaurung.green-gryphon.com
.\" Last Modified By : Manoj Srivastava
.\" Last Modified On : Mon Apr 19 12:16:51 2004
.\" Last Machine Used: glaurung.internal.golden-gryphon.com
.\" Update Count : 28
.\" Status : Unknown, Use with caution!
.\" HISTORY :
.\" Description :
.\" Copyright (c) 2002 Manoj Srivastava <srivasta@debian.org>
.\"
.\" This is free documentation; you can redistribute it and/or
.\" modify it under the terms of the GNU General Public License as
.\" published by the Free Software Foundation; either version 2 of
.\" the License, or (at your option) any later version.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
.\" 02111-1307, USA.
.\"
.\" $Id: ucf.conf.5,v 1.2 2002/02/25 18:07:21 srivasta Exp $
.\"
.TH UCF.CONF 5 "Feb 12 2002" "Debian" "Debian GNU/Linux manual"
.SH NAME
ucf.conf \- site\-wide configuration file for
.B ucf
.SH SYNOPSIS
.I /etc/ucf.conf
.SH "DESCRIPTION"
The file
.I /etc/ucf.conf
is actually a
.BR "Bourne Shell"
snippet included during the package build process, and hence you may
put any shell directive in that file (just make very sure you know
what you are doing).
.PP
All the variables have reasonable default values, and some may be
overridden on a per run or a per individual basis by using
environment variables, and all configurable variables can be
overridden by options to the scripts themselves.
.PP
The value of a variable can be set so:
.TP 3
a)
Defaults exist in the rules file. These are the values used if no
customization is done.
.IP b)
Some variables can be set in the config file
.I /etc/ucf.conf.
These values override the defaults.
.IP c)
Some variables can also be set by setting a corresponding environment
variable. These values override the config file and the defaults.
.IP d)
Using script command line
options. All configurable variables may be set by this method, and
will override the other methods above.
.SH "Configuration File options"
At the moment, the user modifiable variables supported are:
.TP 18
.B DEBUG
Debugging information: The default value is 0 (no debugging
information is printed). To enable debugging output, set the value to
1.
.TP
.B VERBOSE
Verbosity: The default value is 0 (quiet). To change the default
behavior, set the value to 1.
.TP
.B conf_force_conffold
Force the installed file to be retained. The default is to have this
variable unset, which makes the script ask in case of doubt. This can
be overridden by the environment variable
.B UCF_FORCE_CONFFOLD
.TP
.B conf_force_conffnew
Force the installed file to be overridden. The default is to have this
variable unset, which makes the script ask in case of doubt. This can
be overridden by the environment variable
.B UCF_FORCE_CONFFNEW
.TP
.B conf_source_dir
This is the directory where the historical md5sums for a file are
looked for. Specifically, the historical md5sums are looked for in
either the file
.I ${filename}.md5sum,
or the subdirectory
.I ${filename}.md5sum.d/
.TP
.B conf_old_mdsum_file
Force the historical md5sums to be read from this file, rather than
defaulting to living in the source directory. Setting this option
overrides settings in the environment variable
.B UCF_OLD_MDSUM_FILE
.SH Files
System\-wide defaults are placed in
.I /etc/ucf.conf,
.SH "SEE ALSO"
.BR ucf (1),
.SH BUGS
There are no bugs. Any resemblance thereof is delirium. Really.
.SH AUTHOR
This manual page was written by Manoj Srivastava <srivasta@debian.org>,
for the Debian GNU/Linux system.

851
ucfq Executable file
View File

@ -0,0 +1,851 @@
#!/usr/bin/perl
# -*- Mode: Cperl -*-
# ucfq ---
# Author : Manoj Srivastava ( srivasta@glaurung.internal.golden-gryphon.com )
# Created On : Wed Apr 12 14:51:16 2006
# Created On Node : glaurung.internal.golden-gryphon.com
# Last Modified By : Manoj Srivastava
# Last Modified On : Fri Apr 14 19:30:45 2006
# Last Machine Used: glaurung.internal.golden-gryphon.com
# Update Count : 81
# Status : Unknown, Use with caution!
# HISTORY :
# Description :
#
# arch-tag: 1390e09f-ee31-4d7f-a968-bd539ea061a0
#
=head1 NAME
ucfq - query ucf registry and hashfile about configuration file details.
=cut
use strict;
package ucf;
use strict;
use Getopt::Long;
# set the version and revision
($main::MYNAME = $main::0) =~ s|.*/||;
$main::Author = "Manoj Srivastava";
$main::AuthorMail = "srivasta\@debian.org";
=head1 SYNOPSIS
usage: ucfq [options] (file|package)[file|package ...]
=cut
{ # scope for ultra-private meta-object for class attributes
my %Ucf =
(
Optdesc =>
{
'help|h' => sub {print ucf->Usage(); exit 0;},
'with-colons|w!' => sub {$::ConfOpts{"Colons"}= "$_[1]";},
'state-dir=s' => sub {$::ConfOpts{"StateDir"}= "$_[1]";},
'debug|d' => sub {$::ConfOpts{"DEBUG"}+= "$_[1]";},
'verbose|v' => sub {$::ConfOpts{"VERBOSE"}+= "$_[1]";}
},
Usage => qq(Usage: $main::MYNAME [options]
Author: $main::Author <$main::AuthorMail>
where options are:
--help This message.
--debug Turn on debugging mode.
--verbose Make the script more verbose.
--with-colons A compact, machine readable version of the output.
--state-dir </path/> Set the state directory to /path/ instead of the
default /var/lib/ucf.
),
Defaults =>
{
"Colons" => 0,
"DEBUG" => 0,
"VERBOSE" => 0,
"StateDir" => '/var/lib/ucf'
}
);
# tri-natured: function, class method, or object method
sub _classobj {
my $obclass = shift || __PACKAGE__;
my $class = ref($obclass) || $obclass;
no strict "refs"; # to convert sym ref to real one
return \%$class;
}
for my $datum (keys %Ucf ) {
no strict "refs";
*$datum = sub {
use strict "refs";
my ($self, $newvalue) = @_;
$Ucf{$datum} = $newvalue if @_ > 1;
return $Ucf{$datum};
}
}
}
=head1 OPTIONS
=over 3
=item B<--help> B<h> Print out a usage message.
=item B<--debug> B<-d> Turn on debugging mode.
=item B<--verbose> B<-v> Make the script more verbose..
=item B<--with-colons> B<-w>
=over 2
Normally, the script presents the information in a human readable
tabular format, but that may be harder for a machine to parse. With
this option, the output is a compact, colon separated line, with no
dividers, headers, or footer.
=back
=item B<--state-dr> dir
=over 2
Set the state directory to C</path/to/dir> instead of the default
C</var/lib/ucf>. Used mostly for testing.
=back
=back
=cut
=head1 DESCRIPTION
This script takes a set of arguments, each of which is a package or a
path to a configuration file, and outputs the associated package, if
any, if the file exists on disk, and whether it has been modfied by te
user. The output is either a human readable tabular form, or a
compact colon-separated machine friendly format.
This script can potentially be used in package C<postinst> scripts
during purge to query the system for configuration files that may
still exist on the system, and whether these files have been locally
modified by the user -- assuming that the package registered all the
configuration files with B<ucf> using C<ucfr>.
=cut
=head1 INTERNALS
=head2 Class Methods
All class methods mediate access to class variables. All class
methods can be invoked with zero or one parameters. When invoked with
the optional parameter, the class method sets the value of the
underlying class data. In either case, the value of the underlying
variable is returned.
=cut
=head1 Class ucf
This is a combination view and controller class that mediates between
the user and the internal model classes.
=head2 new
This is the constructor for the class. It takes a number of optional
parameters. If the parameter B<Colons> is present, then the output
will be compact. The parameters B<DEBUG> and B<VERBOSE> turn on
additional diagnostics from the script.
=cut
sub new {
my $this = shift;
my %params = @_;
my $class = ref($this) || $this;
my $self = {};
bless $self => $class;
# validate and sanitize the settings
$self->validate(%params);
return $self;
}
=head2 validate
This routine is responsible for ensuring that the parameters passed in
(presumably from the command line) are given preference.
=cut
sub validate{
my $this = shift;
my %params = @_;
my $defaults = $this->Defaults();
# Make sure runtime options override what we get from the config file
for my $option (keys %params) {
$this->{Con_Ref}->{"$option"} = $params{"$option"};
}
# Ensure that if default parameters have not been set on the comman
# line on in the configuration file, if any, we use the built in
# defaults.
for my $default (keys %$defaults) {
if (! defined $this->{Con_Ref}->{"$default"}) {
$this->{Con_Ref}->{"$default"} = $defaults->{"$default"};
}
}
}
=head2 get_config_ref
This routine returns a reference to the configuration hash
=cut
sub get_config_ref {
my $this = shift;
return $this->{Con_Ref};
}
=head2 dump_config
This routine returns a C<Data::Dumper> for debugging purposes
=cut
sub dump_config {
my $this = shift;
for (keys %{$this->{Con_Ref}}) {
print "$_ = [${$this->{Con_Ref}}{$_}]\n"
}
}
=head2 process
This routine is the work horse routine -- it parses the command line
arguments, and queries the on disk databases, determines of the files
exist, and have been modified.
=cut
sub process {
my $this = shift;
# Step 1: Process all arguments in sequence.
# Step 2: determine if the arument given is a package name (no / in
# arg)
%{$this->{packages}} = map { +"$_" => 1} grep {! m,/,} @ARGV;
%{$this->{configs}} = map { +"$_" => 1} grep { m,/,} @ARGV;
$this->{pkg_list} = object_list->new;
$this->{file_list} = object_list->new;
$this->{registry_proxy} =
registry->new("StateDir" => $this->{Con_Ref}->{StateDir});
$this->{hashfile_proxy} =
hashfile->new("StateDir" => $this->{Con_Ref}->{StateDir});
for (keys %{$this->{packages}} ) {
my $package = pkg->new('Name' => "$_");
$this->{pkg_list}->element($_, $package);
}
for (keys %{$this->{configs}}) {
warn "Need a fully qualified path name for config file \"$_\"\n"
unless m,^/,;
# Don't die for etch
exit 0 unless m,^/,;
my $file = conffile->new('Name' => "$_");
$this->{file_list}->element($_, $file);
}
# Step 3: If so, gather all files associated with the package
for my $package ($this->{pkg_list}->list) {
my $pkg_files = $this->{registry_proxy}->list_files($package);
for my $file (@$pkg_files) {
if (! defined $this->{file_list}->element($file)) {
my $ret = conffile->new('Name' => "$file");
$this->{file_list}->element($file, $ret);
}
$this->{file_list}->element($file)->conffile_package($package);
}
}
# Step 4: for all configuration files, determine package (unless
# already determined), if any
# Step 5: For each configuration file, check if it exists
# Step 6: For each existing file, see if it has been changed
for my $file ($this->{file_list}->list) {
$this->{file_list}->element($file)->conffile_hash($file, $this->{hashfile_proxy}->hash($file));
if (! defined $this->{file_list}->element($file)->conffile_package) {
$this->{file_list}->element($file)->conffile_package($this->{registry_proxy}->find_pkg($file));
}
}
}
=head2 report
This routine generates a nicely formatted report based on the
information gathered during the processing. There are two kinds of
reports, the first being a user friendly tabular form, the second
(turned on by the C<-w> option) a easily parseable colon separated
report.
=cut
our ($out_pkg, $out_file, $there, $mod);
format STDOUT_TOP =
Configuration file Package Exists Changed
.
format STDOUT =
@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<< @||| @|||
$out_file, $out_pkg, $there,$mod
.
sub report {
my $this = shift;
for my $file (sort $this->{file_list}->list) {
($out_pkg, $out_file, $there, $mod) =
$this->{file_list}->element($file)->conffile_report;
if ($this->{Con_Ref}->{Colons}) {
print "$out_file:$out_pkg:$there:$mod\n";
}
else {
write;
}
}
}
=head1 Class registry
This moel class encapsulates the package-configuration file
associations registry. It parses the data in the registry, and
provides methods to query the registry based either on package name,
or the full path of the configuration file.
=cut
package registry;
use strict;
=head2 new
This is the constructor for the class. It takes a required parameter
B<StateDir>, and based on that, proceeds toparse the registry and
populate internal data structures.
=cut
sub new {
my $this = shift;
my %params = @_;
my $class = ref($this) || $this;
my $self = {};
die "Missing required parameter StateDir"
unless $params{StateDir};
if (-e "$params{StateDir}/registry") {
if (! -r "$params{StateDir}/registry") {
die "Can't read registry file $params{StateDir}/registry:$!";
}
open (REG, "$params{StateDir}/registry") ||
die "Can't read registry file $params{StateDir}/registry:$!";
while (<REG>) {
chomp;
my ($pkg, $file) = m/^(\S+)\s+(\S+)$/;
$self->{Packages}->{$file} = $pkg;
if (exists $self->{List}->{$pkg}) {
push @{$self->{List}->{$pkg}}, $file;
}
else {
$self->{List}->{$pkg} = [ $file ];
}
}
}
bless $self => $class;
return $self;
}
=head2 list_files
This routine queries the registry and lists all configuration files
associated with the given package. Takes the package name as a
required parameter.
=cut
sub list_files {
my $this = shift;
my $pkg = shift;
if (exists $this->{List}->{$pkg}) {
return [ @{$this->{List}->{$pkg}} ];
}
else {
return [];
}
}
=head2 find_pkg
This routine queries the registry for the package associated with the
given file. Takes the path of the configuration file as a required
parameter.
=cut
sub find_pkg {
my $this = shift;
my $file = shift;
if (exists $this->{Packages}->{$file}) {
return $this->{Packages}->{$file};
}
else {
return undef;
}
}
=head1 Class hashfile
This moel class encapsulates the configuration file hash database. It
parses the data in the database, and provides methods to query the
hash of the configuration file.
=cut
package hashfile;
use strict;
sub new {
my $this = shift;
my %params = @_;
my $class = ref($this) || $this;
my $self = {};
die "Missing required parameter StateDir"
unless $params{StateDir};
if (-e "$params{StateDir}/hashfile") {
if (! -r "$params{StateDir}/hashfile") {
die "Can't read registry file $params{StateDir}/hashfile:$!";
}
open (HASH, "$params{StateDir}/hashfile") ||
die "Can't read registry file $params{StateDir}/hashfile:$!";
while (<HASH>) {
chomp;
my ($hash, $file) = m/^(\S+)\s+(\S+)$/;
$self->{$file} = $hash
}
}
bless $self => $class;
return $self;
}
=head2 hash
This routine queries the database for the hash associated with the
developers version of the given file. Takes the path of the
configuration file as a required parameter.
=cut
sub hash {
my $this = shift;
my $file = shift;
my $value = shift;
if ($value) {
$this->{$file} = $value;
}
return $this->{$file};
}
=head1 class conffile
This is the encapsulation of a configuration file metadata.
=cut
package conffile;
use strict;
use Cwd qw{abs_path};
=head2 new
This is the constructor for the class. It takes a number of optional
parameters. If the parameter B<Colons> is present, then the output
will be compact. The parameters B<DEBUG> and B<VERBOSE> turn on
additional diagnostics from the script.
=cut
sub new {
my $this = shift;
my %params = @_;
my $class = ref($this) || $this;
my $self = {};
die "Missing required parameter Name"
unless $params{Name};
$self->{Name} = $params{Name};
$self->{Package} = $params{Package}
if $params{Package};
$self->{Exists} = 'Yes' if -e $self->{Name};
if ($self->{Exists}) {
$self->{Name} = abs_path( $self->{Name});
}
bless $self => $class;
return $self;
}
=head2 conffile_package
This routine is the accessor method of the internal attribute that
holds package name associated with the file. If an optional C<value>
is present, updates the value of the attribute.
=cut
sub conffile_package {
my $this = shift;
my $value = shift;
if ($value ) {
$this->{Package} = $value;
}
if (exists $this->{Package}) {
return $this->{Package};
}
else {
return undef;
}
}
=head2 conffile_exists
This routine is the accessor method of the internal attribute that
holds the information whether the file exists on disk or not.
=cut
sub conffile_exists {
my $this = shift;
my $name = shift;
my $value = shift;
die "Missing required parameter Name"
unless $name;
if (exists $this->{Exists}) {
return $this->{Exists};
}
else {
return undef;
}
}
=head2 conffile_modified
This routine is the accessor method of the internal attribute that
holds the information whether the file exists on disk or not. If an
optional C<value> is present, updates the value of the attribute.
=cut
sub conffile_modified {
my $this = shift;
my $name = shift;
my $value = shift;
die "Missing required parameter Name"
unless $name;
if ($value ) {
$this->{Modified} = $value;
}
if (exists $this->{Modified}) {
return $this->{Modified};
}
else {
return undef;
}
}
=head2 conffile_hash
This routine is the accessor method of the internal attribute that
holds the hash for the developers version of the file. If an optional
C<value> is present, updates the value of the attribute. It also
notes whether or not the file is modified from the developers version.
=cut
sub conffile_hash {
my $this = shift;
my $name = shift;
my $value = shift;
die "Missing required parameter Name"
unless $name;
if ($value ) {
$this->{Hash} = $value;
if (-e "$name") {
if (-x "/usr/bin/md5sum") {
open (NEWHASH, "/usr/bin/md5sum $name |") ||
die "Could not run md5sum: $!";
while (<NEWHASH>) {
chomp;
my ($hash, $dummy) = m/^(\S+)\s+(\S+)$/;
if ("$hash" ne "$value") {
$this->{Modified} = 'Yes';
}
else {
$this->{Modified} = 'No';
}
}
close NEWHASH;
}
else {
die "Could not find /usr/bin/md5sum .\n";
}
}
}
if (exists $this->{Hash}) {
return $this->{Hash};
}
else {
return undef;
}
}
sub conffile_report {
my $this = shift;
return $this->{Package} ? $this->{Package} : "",
$this->{Name}, $this->{Exists} ? $this->{Exists} : "",
$this->{Modified}? $this->{Modified} : "";
}
=head1 CLASS PKG
This is an encapsulation of package metadata. Packages may be
associated with configuration files.
=cut
package pkg;
use strict;
=head2 new
This is the constructor for the class. It takes a number of optional
parameters. If the parameter B<Colons> is present, then the output
will be compact. The parameters B<DEBUG> and B<VERBOSE> turn on
additional diagnostics from the script.
=cut
sub new {
my $this = shift;
my %params = @_;
my $class = ref($this) || $this;
my $self = {};
die "Missing required parameter Name"
unless $params{Name};
$self->{Name} = $params{Name};
bless $self => $class;
return $self;
}
sub list_files {
my $this = shift;
return [];
}
=head1 CLASS object_list
This is a clas which holds lists of object names, either packages or
configuration file object names. It provides methods to add, access,
and remove objects, as well as an option to list all elements in the
list.
=cut
package object_list;
use strict;
=head2 new
This is the constructor for the class. It takes no arguments.
=cut
sub new {
my $this = shift;
my %params = @_;
my $class = ref($this) || $this;
my $self = {};
$self->{"List"} = ();
bless $self => $class;
return $self;
}
=head2 element
This is an accessor method for elements of the list. If an optional
value argument exists, it creates or updates the element associtated
with the vaslue. Takes in a required name, which is used as a kay, and
an optional value argument. The value is returned.
=cut
sub element {
my $this = shift;
my $name = shift;
my $value = shift;
die "Missing required parameter Name"
unless $name;
if ($value) {
$this->{"List"}->{$name} = $value;
}
if (exists $this->{"List"}->{$name}) {
return $this->{"List"}->{$name};
}
else {
return undef;
}
}
=head2 remove
Removes elements from the list. Take in an required name, which is
used as the key for the element to delete.
=cut
sub remove {
my $this = shift;
my $name = shift;
die "Missing required parameter Name"
unless $name;
delete $this->{"List"}->{$name}
if (exists $this->{"List"}->{$name} );
}
=head2 list
This routine lists all the elements in the list. It does not take any
options.
=cut
sub list {
my $this = shift;
return keys %{$this->{"List"}};
}
package main;
use Getopt::Long;
sub main {
my $optdesc = ucf->Optdesc();
my $parser = new Getopt::Long::Parser;
$parser->configure("bundling");
$parser->getoptions (%$optdesc);
my $query = ucf->new(%::ConfOpts);
$query->process;
$query->report;
}
&main;
exit 0;
=head1 CAVEATS
This is very inchoate, at the moment, and needs testing.
=cut
=head1 BUGS
None Known so far.
=cut
=head1 AUTHOR
Manoj Srivastava <srivasta\@debian.org>
=head1 COPYRIGHT AND LICENSE
This script is a part of the Ucf package, and is
Copyright (c) 2006 Manoj Srivastava <srivasta\@debian.org>
This program is free software; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
=cut
1;
__END__

235
ucfq.1 Normal file
View File

@ -0,0 +1,235 @@
.\" -*- Mode: Nroff -*-
.\" ucfq.1 ---
.\" Author : Manoj Srivastava ( srivasta@glaurung.internal.golden-gryphon.com )
.\" Created On : Sun Apr 16 16:29:21 2006
.\" Created On Node : glaurung.internal.golden-gryphon.com
.\" Last Modified By : Manoj Srivastava
.\" Last Modified On : Sun Apr 16 16:31:08 2006
.\" Last Machine Used: glaurung.internal.golden-gryphon.com
.\" Update Count : 2
.\" Status : Unknown, Use with caution!
.\" HISTORY :
.\" Description :
.\"
.\" arch-tag: daf13e00-a69c-45f0-80a1-b6f3b8bdb14b
.\"
.\" Copyright (c) 2006 Manoj Srivastava <srivasta@debian.org>
.\"
.\" This is free documentation; you can redistribute it and/or
.\" modify it under the terms of the GNU General Public License as
.\" published by the Free Software Foundation; either version 2 of
.\" the License, or (at your option) any later version.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
.\" 02111-1307, USA.
.\"
.\" ========================================================================
.de Sh \" Subsection heading
.br
.if t .Sp
.ne 5
.PP
\fB\\$1\fR
.PP
..
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings. \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote. \*(C+ will
.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
.\" nothing in troff, for use with C<>.
.tr \(*W-
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
. ds -- \(*W-
. ds PI pi
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
. ds L" ""
. ds R" ""
. ds C` ""
. ds C' ""
'br\}
.el\{\
. ds -- \|\(em\|
. ds PI \(*p
. ds L" ``
. ds R" ''
'br\}
.\"
.\" If the F register is turned on, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
.\" entries marked with X<> in POD. Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.if \nF \{\
. de IX
. tm Index:\\$1\t\\n%\t"\\$2"
..
. nr % 0
. rr F
.\}
.\"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.hy 0
.if n .na
.\"
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
.\" Fear. Run. Save yourself. No user-serviceable parts.
. \" fudge factors for nroff and troff
.if n \{\
. ds #H 0
. ds #V .8m
. ds #F .3m
. ds #[ \f1
. ds #] \fP
.\}
.if t \{\
. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
. ds #V .6m
. ds #F 0
. ds #[ \&
. ds #] \&
.\}
. \" simple accents for nroff and troff
.if n \{\
. ds ' \&
. ds ` \&
. ds ^ \&
. ds , \&
. ds ~ ~
. ds /
.\}
.if t \{\
. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
.\}
. \" troff and (daisy-wheel) nroff accents
.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
.ds ae a\h'-(\w'a'u*4/10)'e
.ds Ae A\h'-(\w'A'u*4/10)'E
. \" corrections for vroff
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
. \" for low resolution devices (crt and lpr)
.if \n(.H>23 .if \n(.V>19 \
\{\
. ds : e
. ds 8 ss
. ds o a
. ds d- d\h'-1'\(ga
. ds D- D\h'-1'\(hy
. ds th \o'bp'
. ds Th \o'LP'
. ds ae ae
. ds Ae AE
.\}
.rm #[ #] #H #V #F C
.\" ========================================================================
.\"
.TH UCFQ 1 "2006-04-16" "perl v5.8.8" "User Contributed Perl Documentation"
.SH NAME
ucfq \- query the ucf database
.SH "SYNOPSIS"
.Vb 1
\& usage: ucfq [options] (/path/to/file|package)[/path/to/file|package ...]
.Ve
.SH "OPTIONS"
.IP "\fB\-\-help\fR \fBh\fR Print out a usage message." 3
.PD 0
.IP "\fB\-\-debug\fR \fB\-d\fR Turn on debugging mode." 3
.IP "\fB\-\-verbose\fR \fB\-v\fR Make the script more verbose.." 3
.IP "\fB\-\-with\-colons\fR \fB\-w\fR" 3
.RS 3
.PD
.RS 2
Normally, the script presents the information in a human readable
tabular format, but that may be harder for a machine to parse. With
this option, the output is a compact, colon separated line, with no
dividers, headers, or footer.
.RE
.RE
.RS 3
.RE
.IP "\fB\-\-state\-dr\fR dir" 3
.RS 3
.RS 2
Set the state directory to \f(CW\*(C`/path/to/dir\*(C'\fR instead of the default
\&\f(CW\*(C`/var/lib/ucf\*(C'\fR. Used mostly for testing.
.RE
.RE
.RS 3
.RE
.SH "DESCRIPTION"
This script takes a set of arguments, each of which is a package name
(and thus does not contain a /) or a full path to a configuration
file, and outputs the associated package, if any, if the file exists
on disk, and whether it has been modified by the user. The output is
either a human readable tabular form, or a compact colon-separated
machine friendly format.
.PP
This script can potentially be used in package \f(CW\*(C`postrm\*(C'\fR scripts
during purge to query the system for configuration files that may
still exist on the system, and whether these files have been locally
modified by the user \*(-- assuming that the package registered all the
configuration files with \fBucf\fR using \f(CW\*(C`ucfr\*(C'\fR.
.SH "CAVEATS"
This is very inchoate, at the moment, and needs testing.
.SH "BUGS"
None Known so far.
.SH "AUTHOR"
Manoj Srivastava <srivasta\e@debian.org>
.SH "COPYRIGHT AND LICENSE"
This script is a part of the Ucf package, and is
.PP
Copyright (c) 2006 Manoj Srivastava <srivasta\e@debian.org>
.PP
This program is free software; you can redistribute it and / or modify
it under the terms of the \s-1GNU\s0 General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
.PP
This program is distributed in the hope that it will be useful,
but \s-1WITHOUT\s0 \s-1ANY\s0 \s-1WARRANTY\s0; without even the implied warranty of
\&\s-1MERCHANTABILITY\s0 or \s-1FITNESS\s0 \s-1FOR\s0 A \s-1PARTICULAR\s0 \s-1PURPOSE\s0. See the
\&\s-1GNU\s0 General Public License for more details.
.PP
You should have received a copy of the \s-1GNU\s0 General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, \s-1MA\s0 02111\-1307 \s-1USA\s0

336
ucfr Executable file
View File

@ -0,0 +1,336 @@
#! /bin/bash
# -*- Mode: Sh -*-
# ucfr ---
# Author : Manoj Srivastava ( srivasta@glaurung.internal.golden-gryphon.com )
# Created On : Tue Apr 11 11:09:15 2006
# Created On Node : glaurung.internal.golden-gryphon.com
# Last Modified By : Manoj Srivastava
# Last Modified On : Tue Apr 11 13:50:58 2006
# Last Machine Used: glaurung.internal.golden-gryphon.com
# Update Count : 43
# Status : Unknown, Use with caution!
# HISTORY :
# Description :
#
# Register a configuration file as belonging to a package
#
# arch-tag: 6e1d33fe-a930-41ce-8d0f-c87f87b19918
#
# make sure we exit on error
set -e
# set the version and revision
progname=$(basename "$0")
pversion='Revision 3.00'
######################################################################
######## #########
######## Utility functions #########
######## #########
######################################################################
setq() {
# Variable Value Doc_string
if [ "x$2" = "x" ]; then
echo >&2 "$progname: Unable to determine $3"
exit 1;
else
if [ "x$VERBOSE" != "x" ]; then
echo >&2 "$progname: $3 is $2";
fi
eval "$1=\"\$2\"";
fi
}
withecho () {
echo "$@" >&2
"$@"
}
purge_from_registry () {
if [ ! -e "$statedir/registry" ]; then
echo >&2 "$progname: Internal error: $statedir/registry does not exist";
exit 6;
fi
if [ "$count" -eq 0 ]; then
if [ "X$VERBOSE" != "X" ]; then
echo >&2 "$progname: Association already purged. No changes.";
fi
exit 0;
fi
old_pkg=$(egrep "[[:space:]]${real_conf_file_re}$" "$statedir/registry" | \
awk '{print $1;}' );
if [ "$pkg" != "$old_pkg" ]; then
echo >&2 "ucfr: Association belongs to $old_pkg, not $pkg";
if [ "X$FORCE" = "X" ]; then
echo >&2 "ucfr: Aborting";
exit 5;
fi
fi
# OK, so we have something to purge.
for i in $(/usr/bin/seq 6 -1 0); do
if [ -e "${statedir}/registry.${i}" ]; then
if [ "X$docmd" = "XYES" ]; then
cp -f "${statedir}/registry.${i}" "${statedir}/registry.$(($i + 1))"
else
echo cp -f "${statedir}/registry.${i}" "${statedir}/registry.$(($i + 1))"
fi
fi
done
if [ "X$docmd" = "XYES" ]; then
cp -f "$statedir/registry" "$statedir/registry.0"
else
echo cp -f "$statedir/registry" "$statedir/registry.0"
fi
if [ "X$docmd" = "XYES" ]; then
set +e
if [ "X$VERBOSE" != "X" ]; then
echo "egrep -v [[:space:]]${real_conf_file_re}$ $statedir/registry >\\"
echo " $statedir/registry.tmp || true";
fi
#echo "egrep -v [[:space:]]${real_conf_file_re}$ $statedir/registry"
egrep -v "[[:space:]]${real_conf_file_re}$" "$statedir/registry" > \
"$statedir/registry.tmp" || true;
if [ "X$docmd" = "XYES" ]; then
mv -f "$statedir/registry.tmp" "$statedir/registry"
else
echo mv -f "$statedir/registry.tmp" "$statedir/registry"
fi
set -e
fi
}
replace_in_registry () {
if [ ! -e "$statedir/registry" ]; then
echo >&2 "$progname: Internal error: $statedir/registry does not exist";
exit 6;
fi
if [ "$count" -eq 1 ]; then
old_pkg=$(egrep "[[:space:]]${real_conf_file_re}$" "$statedir/registry" | \
awk '{print $1;}' );
if [ "$pkg" != "$old_pkg" ]; then
if [ "X$FORCE" = "X" ]; then
echo >&2 "$progname: Attempt from package $pkg to take ${real_conf_file} away from package $old_pkg";
echo >&2 "ucfr: Aborting.";
exit 4;
fi
else
if [ "X$VERBOSE" != "X" ]; then
echo >&2 "$progname: Association already recorded. No changes.";
fi
exit 0;
fi
fi
for i in $(/usr/bin/seq 6 -1 0); do
if [ -e "${statedir}/registry.${i}" ]; then
if [ "X$docmd" = "XYES" ]; then
cp -f "${statedir}/registry.${i}" \
"${statedir}/registry.$(($i + 1))"
else
echo cp -f "${statedir}/registry.${i}" \
"${statedir}/registry.$(($i + 1))"
fi
fi
done
if [ "X$docmd" = "XYES" ]; then
cp -f "$statedir/registry" "$statedir/registry.0"
else
echo cp -f "$statedir/registry" "$statedir/registry.0"
fi
if [ "X$docmd" = "XYES" ]; then
set +e
if [ "X$VERBOSE" != "X" ]; then
echo "egrep -v \"[[:space:]]${real_conf_file_re}$\" \"$statedir/registry\" \\"
echo " $statedir/registry.tmp || true"
echo "echo \"$pkg $real_conf_file\" >> \"$statedir/registry.tmp\""
echo "mv -f $statedir/registry.tmp $statedir/registry"
fi
egrep -v "[[:space:]]${real_conf_file_re}$" "$statedir/registry" > \
"$statedir/registry.tmp" || true;
echo "$pkg $real_conf_file" >> "$statedir/registry.tmp";
mv -f "$statedir/registry.tmp" "$statedir/registry"
set -e
else
echo "egrep -v \"[[:space:]]${real_conf_file_re}$\" \"$statedir/registry\" \\"
echo " $statedir/registry.tmp || true"
echo "echo \"$pkg $real_conf_file\" >> \"$statedir/registry.tmp\""
echo "mv -f $statedir/registry.tmp $statedir/registry"
fi
}
usageversion () {
cat >&2 <<END
Debian GNU/Linux $progname $pversion.
Copyright (C) 2002-2006 Manoj Srivastava.
This is free software; see the GNU General Public Licence for copying
conditions. There is NO warranty.
Usage: $progname [options] package_name path_for_configuration_file
Options:
-h, --help print this message
-f --force Force the association, even if another package
used to own the configuration file.
-d [n], --debug [n] Set the Debug level to N
-n, --no-action Dry run. No action is actually taken.
-v, --verbose Make the script verbose
-p, --purge Remove any reference to the package/file association
from the records
--state-dir bar Set the state directory to bar instead of the
default '/var/lib/ucf'. Used mostly for testing.
END
}
######################################################################
######## #########
######## Command line args #########
######## #########
######################################################################
#
# Long term variables#
#
docmd='YES'
action='withecho'
action=
DEBUG=0
VERBOSE=''
statedir='/var/lib/ucf';
THREEWAY=
# Note that we use `"$@"' to let each command-line parameter expand to a
# separate word. The quotes around `$@' are essential!
# We need TEMP as the `eval set --' would nuke the return value of getopt.
TEMP=$(getopt -a -o hd::D::fnvp -n "$progname" \
--long help,debug::,DEBUG::,force,no-action,purge,verbose,state-dir: \
-- "$@")
if [ $? != 0 ] ; then
echo "Error handling options.Terminating..." >&2 ;
exit 1 ;
fi
# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"
while true ; do
case "$1" in
-h|--help) usageversion; exit 0 ;;
-n|--no-action) action='echo'; docmd='NO'; shift ;;
-v|--verbose) VERBOSE=1; shift ;;
-f|--force) FORCE=1; shift ;;
--state-dir) opt_state_dir="$2"; shift 2 ;;
-D|-d|--debug|--DEBUG)
# d has an optional argument. As we are in quoted mode,
# an empty parameter will be generated if its optional
# argument is not found.
case "$2" in
"") setq DEBUG 1 "The Debug value"; shift 2 ;;
*) setq DEBUG "$2" "The Debug value"; shift 2 ;;
esac ;;
-p|--purge) PURGE=YES; shift ;;
--) shift ; break ;;
*) echo >&2 "$progname: Internal error!" ; exit 1 ;;
esac
done
# Need to run as root, or else the
if test "$(id -u)" != 0; then
if [ "$docmd" = "YES" ]; then
echo "$progname: Need to be run as root." >&2
echo "$progname: Setting up no action mode." >&2
action='echo';
docmd='NO';
fi
fi
if [ $# != 2 ]; then
echo >&2 "$progname: *** ERROR: Need exactly two arguments, got $#";
echo >&2 ""
usageversion;
exit 3 ;
fi
# We have here a configuration file, which can be a symlink, and may
# contain characters that are unsafe in regular expressions
setq pkg "$1" "The Package name";
setq conf_file "$2" "The Configuration file";
setq real_conf_file "$(readlink -q -m $conf_file)" "The (real) Configuration file";
pkg_re="$(echo $pkg | sed -e 's,+,\\+,')"
conf_file_re="$(echo $conf_file | sed -e 's,+,\\+,')"
real_conf_file_re="$(echo $real_conf_file | sed -e 's,+,\\+,')"
case $conf_file_re in
/*)
: echo fine
;;
*)
echo >&2 "$progname: Need a fully qualified path for the file \"$conf_file\""
# Don't exit with an error for etch'
exit 0;
esac
# Load site defaults and over rides.
if [ -f /etc/ucf.conf ]; then
. /etc/ucf.conf
fi
# Command line, env variable, config file, or default
if [ ! "x$opt_state_dir" = "x" ]; then
setq statedir "$opt_state_dir" "The State directory"
elif [ ! "x$UCF_STATE_DIR" = "x" ]; then
setq statedir "$UCF_STATE_DIR" "The State directory"
elif [ ! "x$conf_state_dir" = "x" ]; then
setq statedir "$conf_state_dir" "The State directory"
else
setq statedir '/var/lib/ucf' "The State directory"
fi
# VERBOSE of 0 is supposed to be the same as not setting VERBOSE
if [ "X$VERBOSE" = "X0" ]; then
VERBOSE=''
fi
#
if [ -e "$statedir/registry" -a ! -w "$statedir/registry" ]; then
echo >&2 "$progname: do not have write privilege to the registry data"
if [ "X$docmd" = "XYES" ]; then
exit 1;
fi
fi
# test and see if this file exists in the database
if [ ! -d "$statedir" ]; then
$action mkdir -p "$statedir"
fi
if [ ! -f "$statedir/registry" ]; then
$action touch "$statedir/registry"
fi
if [ "X$VERBOSE" != "X" ]; then
echo >&2 "$progname: The registry exists"
fi
# sanity check
count=$(egrep --count "[[:space:]]${real_conf_file_re}$" "$statedir/registry") || true
if [ "$count" -ge 2 ]; then
echo >&2 "$progname: Corrupt registry: Duplicate entries for ${conf_file}";
egrep "[[:space:]]${real_conf_file_re}$" "$statedir/registry";
exit "$count";
fi
if [ "X$PURGE" != "X" ]; then
$action purge_from_registry
else
$action replace_in_registry
fi
exit 0;

175
ucfr.1 Normal file
View File

@ -0,0 +1,175 @@
.\" -*- Mode: Nroff -*-
.\" ucfr.1 ---
.\" Author : Manoj Srivastava ( srivasta@glaurung.internal.golden-gryphon.com )
.\" Created On : Tue Apr 11 13:58:23 2006
.\" Created On Node : glaurung.internal.golden-gryphon.com
.\" Last Modified By : Manoj Srivastava
.\" Last Modified On : Tue Apr 11 14:43:23 2006
.\" Last Machine Used: glaurung.internal.golden-gryphon.com
.\" Update Count : 14
.\" Status : Unknown, Use with caution!
.\" HISTORY :
.\" Description :
.\"
.\" arch-tag: f2f569c2-5b54-4e5d-83f0-d2a39e103ecb
.\"
.\" Copyright (c) 2006 Manoj Srivastava <srivasta@debian.org>
.\"
.\" This is free documentation; you can redistribute it and/or
.\" modify it under the terms of the GNU General Public License as
.\" published by the Free Software Foundation; either version 2 of
.\" the License, or (at your option) any later version.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
.\" 02111-1307, USA.
.\"
.TH UCFR 1 "Feb 16 2018" "Debian" "Debian GNU/Linux manual"
.SH NAME
ucfr \- Update Configuration File Registry: associate packages with configuration files
.SH SYNOPSIS
.B ucfr
.RI [ options "] "
.I <Package>
.I <Path to configuration file>
.SH DESCRIPTION
Where
.I Package
is the package associated with the configuration file (and, in some
sense, its owner), and
.I Path to configuration file
is the full path to the location (usually under /etc) where the
configuration file lives, and is potentially modified by the end
user. Please note that usually this means that we register actual
files, and not symbolic links to files.
.B ucfr
will follow symbolic links and register the real file, and not the
symbolic link.
.PP
This script maintains an association between configuration files and
packages, and is meant to help provide facilities that
.I dpkg
provides conffiles for configuration files and not shipped in a
.B Debian
package, but handled by the postinst by
.I ucf
instead. This script is idempotent, associating a package to a file
multiple times is not an error. It is normally an error to try to
associate a file which is already associated with another package, but
this can be overridden by using the
.I \-\-force
option.
.SH OPTIONS
.TP
.B "\-h, \-\-help"
Print a short usage message
.TP
.B "\-n, \-\-no\-action"
Dry run. Print the actions that would be taken if the script is
invoked, but take no action.
.TP
.B "\-d [n], \-\-debug [n]"
Set the debug level to the (optional) level
.I n
(n defaults to 1). This turns on copious debugging information.
.TP
.B "\-p, \-\-purge"
Removes all vestiges of the association between the named package and
the configuration file from the registry. The association must already
exist; if the configuration file is associated with some other
package, an error happens, unless the option
.I \-\-force
is also given. In that case, the any associations for the
configuration file are removed from the registry, whether or not the
package name matches. This action is idempotent, asking for an
association to be purged multiple times does not result in an error,
since attempting to remove an non-existent association is silently
ignored unless the
.I \-\-verbose
option is used (in which case it just issues a diagnostic).
.TP
.B "\-v, \-\-verbose"
Make the script be very verbose about setting internal variables.
.TP
.B "\-f, \-\-force"
This option forces operations requested even if the configuration file
in consideration is owned by another package. This allows a package to
.I "hijack"
a configuration file from another package, or to purge the
association between the file and some other package in the registry.
.TP
.B "\-\-state\-dir /path/to/dir"
Set the state directory to /path/to/dir instead of the default
.I /var/lib/ucf.
Used mostly for testing.
.SH USAGE
The most common case usage is pretty simple: a single line invocation
in the postinst on configure, and another single line in the postrm to
tell
.B ucfr
to forget about the association with the configuration file on purge
(using the \-\-purge option) is all that is needed (assuming ucfr is
still on the system).
.SH FILES
.I /var/lib/ucf/registry,
and
.I /var/lib/ucf/registry.X,
where
.I X
is a small integer, where previous versions of the registry are
stored.
.PP
.I /etc/ucf.conf
.SH EXAMPLES
If the package
.I foo
wants to use ucfr to associate itself with a configuration file
.I foo.conf,
a simple invocation of ucfr in the postinst file is all that is
needed:
.PP
.B ucfr
.I foo
.I /etc/foo.conf
.PP
On purge, one should tell ucf to forget about the file (see detailed
examples in /usr/share/doc/ucf/examples):
.PP
.B ucfr
.I \-\-purge
.I foo
.I /etc/foo.conf
.PP
If you want to remove all the conf files for a given package
.I foo,
the simplest way is to use
.B ucfq.
For example
.PP
.B ucfq
.I \-w
.I foo |
.B cut
.I \-d : \-f 1 |
.B while read
.I cfile ;
.B do
.B ucfr
.I \-v $cfile ;
.B done
.SH "SEE ALSO"
ucf(1), ucf.conf(5).
.SH AUTHOR
This manual page was written Manoj Srivastava <srivasta@debian.org>,
for the Debian GNU/Linux system.