initial commit of file from CVS for e-smith-lib on Wed 12 Jul 08:58:46 BST 2023
This commit is contained in:
		
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
*.rpm
 | 
			
		||||
*.log
 | 
			
		||||
*spec-20*
 | 
			
		||||
*.tar.xz
 | 
			
		||||
							
								
								
									
										21
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
# Makefile for source rpm: e-smith-lib
 | 
			
		||||
# $Id: Makefile,v 1.1 2016/02/05 22:44:50 stephdl Exp $
 | 
			
		||||
NAME := e-smith-lib
 | 
			
		||||
SPECFILE = $(firstword $(wildcard *.spec))
 | 
			
		||||
 | 
			
		||||
define find-makefile-common
 | 
			
		||||
for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done
 | 
			
		||||
endef
 | 
			
		||||
 | 
			
		||||
MAKEFILE_COMMON := $(shell $(find-makefile-common))
 | 
			
		||||
 | 
			
		||||
ifeq ($(MAKEFILE_COMMON),)
 | 
			
		||||
# attept a checkout
 | 
			
		||||
define checkout-makefile-common
 | 
			
		||||
test -f CVS/Root && { cvs -Q -d $$(cat CVS/Root) checkout common && echo "common/Makefile.common" ; } || { echo "ERROR: I can't figure out how to checkout the 'common' module." ; exit -1 ; } >&2
 | 
			
		||||
endef
 | 
			
		||||
 | 
			
		||||
MAKEFILE_COMMON := $(shell $(checkout-makefile-common))
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include $(MAKEFILE_COMMON)
 | 
			
		||||
							
								
								
									
										18
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								README.md
									
									
									
									
									
								
							@@ -1,3 +1,17 @@
 | 
			
		||||
# e-smith-lib
 | 
			
		||||
# <img src="https://www.koozali.org/images/koozali/Logo/Png/Koozali_logo_2016.png" width="25%" vertical="auto" style="vertical-align:bottom"> e-smith-lib
 | 
			
		||||
 | 
			
		||||
SMEServer Koozali developed git repo for e-smith-lib smeserver
 | 
			
		||||
SMEServer Koozali developed git repo for e-smith-lib smeserver
 | 
			
		||||
 | 
			
		||||
## Wiki
 | 
			
		||||
<br />https://wiki.koozali.org/
 | 
			
		||||
 | 
			
		||||
## Bugzilla
 | 
			
		||||
Show list of outstanding bugs: [here](https://bugs.koozali.org/buglist.cgi?component=e-smith-lib&product=SME%20Server%2010.X&query_format=advanced&limit=0&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=CONFIRMED)
 | 
			
		||||
 | 
			
		||||
## Description
 | 
			
		||||
 | 
			
		||||
<br />*This description has been generated by an LLM AI system and cannot be relied on to be fully correct.*
 | 
			
		||||
*Once it has been checked, then this comment will be deleted*
 | 
			
		||||
<br />
 | 
			
		||||
 | 
			
		||||
E-smith-lib is an open source software that enables users to quickly and easily create, edit, and share digital content. The platform offers a variety of tools and features that make it easy for users to create and edit a variety of digital documents, such as text documents, audio files, video files, and photographs. It also allows users to collaborate with other users, share digital content, and manage digital workflow. E-smith-lib also features a powerful search engine that can help users locate digital content quickly. Additionally, it offers a variety of templates for quickly creating digital documents, and provides support for multiple languages and different operating systems. The software is easy to use and offers a convenient way for users to manage their digital content.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										131
									
								
								additional/Artistic
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								additional/Artistic
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,131 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
			 The "Artistic License"
 | 
			
		||||
 | 
			
		||||
				Preamble
 | 
			
		||||
 | 
			
		||||
The intent of this document is to state the conditions under which a
 | 
			
		||||
Package may be copied, such that the Copyright Holder maintains some
 | 
			
		||||
semblance of artistic control over the development of the package,
 | 
			
		||||
while giving the users of the package the right to use and distribute
 | 
			
		||||
the Package in a more-or-less customary fashion, plus the right to make
 | 
			
		||||
reasonable modifications.
 | 
			
		||||
 | 
			
		||||
Definitions:
 | 
			
		||||
 | 
			
		||||
	"Package" refers to the collection of files distributed by the
 | 
			
		||||
	Copyright Holder, and derivatives of that collection of files
 | 
			
		||||
	created through textual modification.
 | 
			
		||||
 | 
			
		||||
	"Standard Version" refers to such a Package if it has not been
 | 
			
		||||
	modified, or has been modified in accordance with the wishes
 | 
			
		||||
	of the Copyright Holder as specified below.
 | 
			
		||||
 | 
			
		||||
	"Copyright Holder" is whoever is named in the copyright or
 | 
			
		||||
	copyrights for the package.
 | 
			
		||||
 | 
			
		||||
	"You" is you, if you're thinking about copying or distributing
 | 
			
		||||
	this Package.
 | 
			
		||||
 | 
			
		||||
	"Reasonable copying fee" is whatever you can justify on the
 | 
			
		||||
	basis of media cost, duplication charges, time of people involved,
 | 
			
		||||
	and so on.  (You will not be required to justify it to the
 | 
			
		||||
	Copyright Holder, but only to the computing community at large
 | 
			
		||||
	as a market that must bear the fee.)
 | 
			
		||||
 | 
			
		||||
	"Freely Available" means that no fee is charged for the item
 | 
			
		||||
	itself, though there may be fees involved in handling the item.
 | 
			
		||||
	It also means that recipients of the item may redistribute it
 | 
			
		||||
	under the same conditions they received it.
 | 
			
		||||
 | 
			
		||||
1. You may make and give away verbatim copies of the source form of the
 | 
			
		||||
Standard Version of this Package without restriction, provided that you
 | 
			
		||||
duplicate all of the original copyright notices and associated disclaimers.
 | 
			
		||||
 | 
			
		||||
2. You may apply bug fixes, portability fixes and other modifications
 | 
			
		||||
derived from the Public Domain or from the Copyright Holder.  A Package
 | 
			
		||||
modified in such a way shall still be considered the Standard Version.
 | 
			
		||||
 | 
			
		||||
3. You may otherwise modify your copy of this Package in any way, provided
 | 
			
		||||
that you insert a prominent notice in each changed file stating how and
 | 
			
		||||
when you changed that file, and provided that you do at least ONE of the
 | 
			
		||||
following:
 | 
			
		||||
 | 
			
		||||
    a) place your modifications in the Public Domain or otherwise make them
 | 
			
		||||
    Freely Available, such as by posting said modifications to Usenet or
 | 
			
		||||
    an equivalent medium, or placing the modifications on a major archive
 | 
			
		||||
    site such as uunet.uu.net, or by allowing the Copyright Holder to include
 | 
			
		||||
    your modifications in the Standard Version of the Package.
 | 
			
		||||
 | 
			
		||||
    b) use the modified Package only within your corporation or organization.
 | 
			
		||||
 | 
			
		||||
    c) rename any non-standard executables so the names do not conflict
 | 
			
		||||
    with standard executables, which must also be provided, and provide
 | 
			
		||||
    a separate manual page for each non-standard executable that clearly
 | 
			
		||||
    documents how it differs from the Standard Version.
 | 
			
		||||
 | 
			
		||||
    d) make other distribution arrangements with the Copyright Holder.
 | 
			
		||||
 | 
			
		||||
4. You may distribute the programs of this Package in object code or
 | 
			
		||||
executable form, provided that you do at least ONE of the following:
 | 
			
		||||
 | 
			
		||||
    a) distribute a Standard Version of the executables and library files,
 | 
			
		||||
    together with instructions (in the manual page or equivalent) on where
 | 
			
		||||
    to get the Standard Version.
 | 
			
		||||
 | 
			
		||||
    b) accompany the distribution with the machine-readable source of
 | 
			
		||||
    the Package with your modifications.
 | 
			
		||||
 | 
			
		||||
    c) give non-standard executables non-standard names, and clearly
 | 
			
		||||
    document the differences in manual pages (or equivalent), together
 | 
			
		||||
    with instructions on where to get the Standard Version.
 | 
			
		||||
 | 
			
		||||
    d) make other distribution arrangements with the Copyright Holder.
 | 
			
		||||
 | 
			
		||||
5. You may charge a reasonable copying fee for any distribution of this
 | 
			
		||||
Package.  You may charge any fee you choose for support of this
 | 
			
		||||
Package.  You may not charge a fee for this Package itself.  However,
 | 
			
		||||
you may distribute this Package in aggregate with other (possibly
 | 
			
		||||
commercial) programs as part of a larger (possibly commercial) software
 | 
			
		||||
distribution provided that you do not advertise this Package as a
 | 
			
		||||
product of your own.  You may embed this Package's interpreter within
 | 
			
		||||
an executable of yours (by linking); this shall be construed as a mere
 | 
			
		||||
form of aggregation, provided that the complete Standard Version of the
 | 
			
		||||
interpreter is so embedded.
 | 
			
		||||
 | 
			
		||||
6. The scripts and library files supplied as input to or produced as
 | 
			
		||||
output from the programs of this Package do not automatically fall
 | 
			
		||||
under the copyright of this Package, but belong to whoever generated
 | 
			
		||||
them, and may be sold commercially, and may be aggregated with this
 | 
			
		||||
Package.  If such scripts or library files are aggregated with this
 | 
			
		||||
Package via the so-called "undump" or "unexec" methods of producing a
 | 
			
		||||
binary executable image, then distribution of such an image shall
 | 
			
		||||
neither be construed as a distribution of this Package nor shall it
 | 
			
		||||
fall under the restrictions of Paragraphs 3 and 4, provided that you do
 | 
			
		||||
not represent such an executable image as a Standard Version of this
 | 
			
		||||
Package.
 | 
			
		||||
 | 
			
		||||
7. C subroutines (or comparably compiled subroutines in other
 | 
			
		||||
languages) supplied by you and linked into this Package in order to
 | 
			
		||||
emulate subroutines and variables of the language defined by this
 | 
			
		||||
Package shall not be considered part of this Package, but are the
 | 
			
		||||
equivalent of input as in Paragraph 6, provided these subroutines do
 | 
			
		||||
not change the language in any way that would cause it to fail the
 | 
			
		||||
regression tests for the language.
 | 
			
		||||
 | 
			
		||||
8. Aggregation of this Package with a commercial distribution is always
 | 
			
		||||
permitted provided that the use of this Package is embedded; that is,
 | 
			
		||||
when no overt attempt is made to make this Package's interfaces visible
 | 
			
		||||
to the end user of the commercial distribution.  Such use shall not be
 | 
			
		||||
construed as a distribution of this Package.
 | 
			
		||||
 | 
			
		||||
9. The name of the Copyright Holder may not be used to endorse or promote
 | 
			
		||||
products derived from this software without specific prior written permission.
 | 
			
		||||
 | 
			
		||||
10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
 | 
			
		||||
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 | 
			
		||||
WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 | 
			
		||||
				The End
 | 
			
		||||
							
								
								
									
										340
									
								
								additional/Copying
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										340
									
								
								additional/Copying
									
									
									
									
									
										Normal 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
 | 
			
		||||
 | 
			
		||||
	    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.
 | 
			
		||||
							
								
								
									
										33
									
								
								additional/LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								additional/LICENSE
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                           Perl Kit, Version 5.0
 | 
			
		||||
 | 
			
		||||
                       Copyright 1989-2001, Larry Wall
 | 
			
		||||
                            All rights reserved.
 | 
			
		||||
 | 
			
		||||
    This program is free software; you can redistribute it and/or modify
 | 
			
		||||
    it under the terms of either:
 | 
			
		||||
 | 
			
		||||
        a) the GNU General Public License as published by the Free
 | 
			
		||||
        Software Foundation; either version 1, or (at your option) any
 | 
			
		||||
        later version, or
 | 
			
		||||
 | 
			
		||||
        b) the "Artistic License" which comes with this Kit.
 | 
			
		||||
 | 
			
		||||
    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 either
 | 
			
		||||
    the GNU General Public License or the Artistic License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the Artistic License with this
 | 
			
		||||
    Kit, in the file named "Artistic".  If not, I'll be glad to provide one.
 | 
			
		||||
 | 
			
		||||
    You should also have received a copy of the GNU General Public License
 | 
			
		||||
    along with this program in the file named "Copying". If not, write to the
 | 
			
		||||
    Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 | 
			
		||||
    02111-1307, USA or visit their web page on the internet at
 | 
			
		||||
    http://www.gnu.org/copyleft/gpl.html.
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										790
									
								
								additional/e-smith-lib.spec
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										790
									
								
								additional/e-smith-lib.spec
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,790 @@
 | 
			
		||||
# $Id: e-smith-lib.spec,v 1.24 2010/10/11 22:27:51 slords Exp $
 | 
			
		||||
 | 
			
		||||
Summary: e-smith server and gateway - library module
 | 
			
		||||
%define name e-smith-lib
 | 
			
		||||
Name: %{name}
 | 
			
		||||
%define version 2.4.0
 | 
			
		||||
%define release 1
 | 
			
		||||
Version: %{version}
 | 
			
		||||
Release: %{release}%{?dist}
 | 
			
		||||
License: Artistic
 | 
			
		||||
Group: Networking/Daemons
 | 
			
		||||
Source: %{name}-%{version}.tar.xz
 | 
			
		||||
BuildRoot: /var/tmp/%{name}-%{version}-%{release}-buildroot
 | 
			
		||||
BuildArchitectures: noarch
 | 
			
		||||
BuildRequires: e-smith-devtools >= 1.6.3-01
 | 
			
		||||
Obsoletes: %{name}-Tai64n
 | 
			
		||||
Obsoletes: whiptail
 | 
			
		||||
Requires: dialog
 | 
			
		||||
Requires: perl, perl(Text::Template)
 | 
			
		||||
Requires: perl(Time::HiRes), perl(MIME::Base64)
 | 
			
		||||
Requires: perl(Authen::PAM), perl(I18N::AcceptLanguage)
 | 
			
		||||
Requires: perl(I18N::LangTags) >= 0.27
 | 
			
		||||
Requires: perl(Net::IPv4Addr) >= 0.10
 | 
			
		||||
 | 
			
		||||
%description
 | 
			
		||||
e-smith server and gateway software - library module.
 | 
			
		||||
 | 
			
		||||
%changelog
 | 
			
		||||
* Fri Jan 25 2013 Shad L. Lords <slords@mail.com> 2.4.0-1.sme
 | 
			
		||||
- Bump version in prep for SME9
 | 
			
		||||
 | 
			
		||||
* Mon Oct 11 2010 Shad L. Lords <slords@mail.com> 2.2.0-7.sme
 | 
			
		||||
- Serialize configure_peers to prevent errors [SME: 5831]
 | 
			
		||||
 | 
			
		||||
* Fri Feb 5 2010 Stephen Noble <support@dungog.net> 2.2.0-6.sme
 | 
			
		||||
- adds the hwaddr parameter to probeAdapters() [SME: 4528]
 | 
			
		||||
 | 
			
		||||
* Thu Feb 4 2010 Shad L. Lords <slords@mail.com> 2.2.0-5.sme
 | 
			
		||||
- Update path for 64-bit compatibility [SME: 5756]
 | 
			
		||||
 | 
			
		||||
* Tue Dec 22 2009 Filippo Carletti <filippo.carletti@gmail.com> 2.2.0-4.sme
 | 
			
		||||
- Really apply previous patch in the spec file. [SME: 5659]
 | 
			
		||||
 | 
			
		||||
* Wed Dec  9 2009 Charlie Brady <charlieb@budge.apana.org.au> 2.2.0-3.sme
 | 
			
		||||
- Add patch (Federico Simoncelli) to prevent re-use of uids. [SME: 5659]
 | 
			
		||||
 | 
			
		||||
* Mon Oct 13 2008 Shad L. Lords <slords@mail.com> 2.2.0-2.sme
 | 
			
		||||
- Add patch to support multiple samba roles [SME: 4172]
 | 
			
		||||
 | 
			
		||||
* Tue Oct 7 2008 Shad L. Lords <slords@mail.com> 2.2.0-1.sme
 | 
			
		||||
- Roll new stream to separate sme7/sme8 trees [SME: 4633]
 | 
			
		||||
 | 
			
		||||
* Wed Aug 20 2008 Shad L. Lords <slords@mail.com> 1.19.0-1
 | 
			
		||||
- Roll new dev stream.
 | 
			
		||||
 | 
			
		||||
* Sat Aug 9 2008 Shad L. Lords <slords@mail.com> 1.18.0-28
 | 
			
		||||
- Read /dev/urandmon instead of /dev/random [SME: 4492]
 | 
			
		||||
 | 
			
		||||
* Sat Aug 9 2008 Shad L. Lords <slords@mail.com> 1.18.0-27
 | 
			
		||||
- Make dialog not use STDERR for return values [SME: 3663]
 | 
			
		||||
- Remove requires for whiptail.  No longer needed [SME: 4491]
 | 
			
		||||
 | 
			
		||||
* Thu Jul 31 2008 Shad L. Lords <slords@mail.com> 1.18.0-26
 | 
			
		||||
- Make binmode properties of db class [SME: 4317]
 | 
			
		||||
- Add new navigation db & utf8 classes [SME: 4317]
 | 
			
		||||
 | 
			
		||||
* Wed Apr 2 2008 Shad L. Lords <slords@mail.com> 1.18.0-25
 | 
			
		||||
- Add .utf8 to locale unless server-console [SME: 4162]
 | 
			
		||||
- Add new languages to langtag2locale [SME: 4163]
 | 
			
		||||
 | 
			
		||||
* Sun Mar 30 2008 Shad L. Lords <slords@mail.com> 1.18.0-24
 | 
			
		||||
- Gracefully handle encoding errors in navigation dbs [SME: 4147]
 | 
			
		||||
 | 
			
		||||
* Wed Mar 26 2008 Shad L. Lords <slords@mail.com> 1.18.0-23
 | 
			
		||||
- Make PAM conv routine not look for english strings [SME: 4117]
 | 
			
		||||
 | 
			
		||||
* Tue Mar 25 2008 Shad L. Lords <slords@mail.com> 1.18.0-22
 | 
			
		||||
- Fix wide output to syslog and allow navigations db to be utf8 [SME: 4101]
 | 
			
		||||
 | 
			
		||||
* Mon Mar 10 2008 Shad L. Lords <slords@mail.com> 1.18.0-21
 | 
			
		||||
- Output navigation in UTF-8 [SME: 3858]
 | 
			
		||||
 | 
			
		||||
* Sun Jan 20 2008 Gavin Weight <gweight@gmail.com> 1.18.0-20
 | 
			
		||||
- Call smbpasswd -e - to reset user correctly. [SME: 3755]
 | 
			
		||||
 | 
			
		||||
* Tue Jan 08 2008 Stephen Noble <support@dungog.net> 1.18.0-19
 | 
			
		||||
- modify validate password strong match for console [SME: 2173]
 | 
			
		||||
 | 
			
		||||
* Thu Nov 01 2007 Gavin Weight <gweight@gmail.com> 1.18.0-18
 | 
			
		||||
- Fix I18N.pm file descriptor leak. [SME: 3509]
 | 
			
		||||
 | 
			
		||||
* Wed Oct 31 2007 Charlie Brady <charlie_brady@mitel.com> 1.18.0-17
 | 
			
		||||
- Remove undocumented and unused template metadata handling from
 | 
			
		||||
  generic_template_expand action (Take II). [SME: 2798]
 | 
			
		||||
 | 
			
		||||
* Fri Jun 1 2007 Shad L. Lords <slords@mail.com> 1.18.0-16
 | 
			
		||||
- pam_unix requires passwords >= 6 [SME: 3039]
 | 
			
		||||
 | 
			
		||||
* Mon May 21 2007 Shad L. Lords <slords@mail.com> 1.18.0-15
 | 
			
		||||
- Fix ip addr shift to work on 64-bit
 | 
			
		||||
 | 
			
		||||
* Sun Apr 29 2007 Shad L. Lords <slords@mail.com>
 | 
			
		||||
- Clean up spec so package can be built by koji/plague
 | 
			
		||||
 | 
			
		||||
* Thu Apr 05 2007 Shad L. Lords <slords@mail.com> 1.18.0-14
 | 
			
		||||
- Reverse changes for 1.18.0-12 as it is being used. [SME: 2838]
 | 
			
		||||
 | 
			
		||||
* Wed Apr 04 2007 Charlie Brady <charlie_brady@mitel.com> 1.18.0-13
 | 
			
		||||
- Allow gauge console widget to be used without following message_page.
 | 
			
		||||
  [SME: 2832].
 | 
			
		||||
 | 
			
		||||
* Mon Mar 26 2007 Charlie Brady <charlie_brady@mitel.com> 1.18.0-12
 | 
			
		||||
- Remove undocumented and unused template metadata handling from
 | 
			
		||||
  generic_template_expand action. [SME: 2798]
 | 
			
		||||
 | 
			
		||||
* Mon Mar 26 2007 Charlie Brady <charlie_brady@mitel.com> 1.18.0-11
 | 
			
		||||
- Split logfile rotation code out of generic_template_expand.
 | 
			
		||||
  Code moved to a new action in e-smith-base. [SME: 2795]
 | 
			
		||||
 | 
			
		||||
* Mon Mar 19 2007 Charlie Brady <charlie_brady@mitel.com> 1.18.0-10
 | 
			
		||||
  Don't try to read template.metadata from subdirectories (affects 
 | 
			
		||||
  initialize_database_defaults). [SME: 2690]
 | 
			
		||||
 | 
			
		||||
* Fri Mar 16 2007 Charlie Brady <charlie_brady@mitel.com> 1.18.0-9
 | 
			
		||||
- Allow template.metadata to be provided via a directory of
 | 
			
		||||
  small files. [SME: 2690]
 | 
			
		||||
- Add support for a DELETE boolean template.metadata item. [SME: 2691]
 | 
			
		||||
 | 
			
		||||
* Wed Feb 28 2007 Charlie Brady <charlie_brady@mitel.com> 1.18.0-8
 | 
			
		||||
- Add gauge widget to esmith::console. [SME: 2579]
 | 
			
		||||
 | 
			
		||||
* Sun Feb 25 2007 Charlie Brady <charlie_brady@mitel.com> 1.18.0-7
 | 
			
		||||
- Default infobox height to 8 rows, and allow override via params.
 | 
			
		||||
  [SME: 2560]
 | 
			
		||||
 | 
			
		||||
* Fri Feb 23 2007 Shad L. Lords <slords@mail.com> 1.18.0-6
 | 
			
		||||
- Really fix clear parameter for inputbox dialog screen [SME: 2533]
 | 
			
		||||
 | 
			
		||||
* Fri Feb 23 2007 Shad L. Lords <slords@mail.com> 1.18.0-5
 | 
			
		||||
- Fix clear parameter for dialog screens [SME: 2533]
 | 
			
		||||
 | 
			
		||||
* Thu Feb 22 2007 Charlie Brady <charlie_brady@mitel.com> 1.18.0-4
 | 
			
		||||
- switch esmith::console::password_page() to use dialog rather than
 | 
			
		||||
  whiptail. [SME: 2534]
 | 
			
		||||
 | 
			
		||||
* Thu Feb 22 2007 Charlie Brady <charlie_brady@mitel.com> 1.18.0-3
 | 
			
		||||
- Add infobox widget. [SME: 2533]
 | 
			
		||||
 | 
			
		||||
* Sun Jan 28 2007 Shad L. Lords <slords@mail.com> 1.18.0-2
 | 
			
		||||
- Fix backtitle spacing for new dialog menus [SME: 2328]
 | 
			
		||||
 | 
			
		||||
* Fri Jan 26 2007 Shad L. Lords <slords@mail.com> 1.18.0-1
 | 
			
		||||
- Roll stable stream. [SME: 2328]
 | 
			
		||||
 | 
			
		||||
* Tue Dec 15 2006 Federico Simoncelli <federico.simoncelli@gmail.com> 1.17.0-8
 | 
			
		||||
- Added the validatePassword function to esmith::util. [SME: 2100]
 | 
			
		||||
 | 
			
		||||
* Thu Dec 07 2006 Shad L. Lords <slords@mail.com>
 | 
			
		||||
- Update to new release naming.  No functional changes.
 | 
			
		||||
- Make Packager generic
 | 
			
		||||
 | 
			
		||||
* Fri Nov 24 2006 Gordon Rowell <gordonr@gormand.com.au> 1.17.0-06
 | 
			
		||||
- Allow optional path to peeers directory in 
 | 
			
		||||
  esmith::tcpsvd::configure_peers() [SME: 2086]
 | 
			
		||||
 | 
			
		||||
* Tue Nov 14 2006 Charlie Brady <charlie_brady@mitel.com> 1.17.0-05
 | 
			
		||||
- Allow defaulno option to esmith::console::yesno.
 | 
			
		||||
- Fix I/O redirection in esmith::console::new.
 | 
			
		||||
 | 
			
		||||
* Tue Nov 07 2006 Charlie Brady <charlie_brady@mitel.com> 1.17.0-04
 | 
			
		||||
- Allow display of "0" in iesmith::cgi::genSmallCell. [SME: 2038]
 | 
			
		||||
 | 
			
		||||
* Mon Oct 23 2006 Charlie Brady <charlie_brady@mitel.com> 1.17.0-03
 | 
			
		||||
- Make dialog the default console app, with whiptail used only when
 | 
			
		||||
  required.
 | 
			
		||||
 | 
			
		||||
* Wed Oct 11 2006 Charlie Brady <charlie_brady@mitel.com> 1.17.0-02
 | 
			
		||||
- Allow 'dialog' to be called from esmith::console. [SME: 1958]
 | 
			
		||||
 | 
			
		||||
* Wed Oct 11 2006 Charlie Brady <charlie_brady@mitel.com> 1.17.0-01
 | 
			
		||||
- Roll development branch.
 | 
			
		||||
 | 
			
		||||
* Mon Sep 25 2006 Charlie Brady <charlie_brady@mitel.com> 1.16.0-06
 | 
			
		||||
- Fix problem with greedy RE in template.metadata parsing. [SME: 1906]
 | 
			
		||||
 | 
			
		||||
* Fri Sep 08 2006 Charlie Brady <charlie_brady@mitel.com> 1.16.0-05
 | 
			
		||||
- Fix taint problem in template.metadata handling. [SME: 1906]
 | 
			
		||||
 | 
			
		||||
* Thu Apr 13 2006 Charlie Brady <charlie_brady@mitel.com> 1.16.0-04
 | 
			
		||||
- Use "kudzu --probe --class network" for NIC detection. [SME: 727]
 | 
			
		||||
 | 
			
		||||
* Fri Apr 7 2006 Gordon Rowell <gordonr@gormand.com.au> 1.16.0-03
 | 
			
		||||
- Don't call smbpasswd -e - setting the password is sufficient [SME: 1193]
 | 
			
		||||
 | 
			
		||||
* Tue Mar 28 2006 Gordon Rowell <gordonr@gormand.com.au> 1.16.0-02
 | 
			
		||||
- Log previous contents of db entry in DELETE log [SME: 1066]
 | 
			
		||||
 | 
			
		||||
* Tue Mar 14 2006 Charlie Brady <charlie_brady@mitel.com> 1.16.0-01
 | 
			
		||||
- Roll to stable stream version number. [SME: 1016]
 | 
			
		||||
 | 
			
		||||
* Fri Mar 10 2006 Charlie Brady <charlie_brady@mitel.com> 1.15.4-02
 | 
			
		||||
- Suppress warning from genSmallCell if text is undefined. [SME: 986]
 | 
			
		||||
 | 
			
		||||
* Fri Feb 17 2006 Gordon Rowell <gordonr@gormand.com.au> 1.15.4-01
 | 
			
		||||
- Roll patches up to 1.15.3-42
 | 
			
		||||
- Trim changelog prior to 1.15.0-01 [SME: 828]
 | 
			
		||||
 | 
			
		||||
* Thu Feb 16 2006 Gordon Rowell <gordonr@gormand.com.au> 1.15.3-42
 | 
			
		||||
- Adjust console title bar to 'SME Server' [SME: 726]
 | 
			
		||||
 | 
			
		||||
* Tue Feb 14 2006 Gordon Rowell <gordonr@gormand.com.au> 1.15.3-41
 | 
			
		||||
- Reworded text for template-begin and change URL to /development/
 | 
			
		||||
  rather than /custom/ [SME: 773]
 | 
			
		||||
 | 
			
		||||
* Mon Feb 13 2006 Charlie Brady <charlie_brady@mitel.com> 1.15.3-40
 | 
			
		||||
- Update URL in default template-begin fragment. [SME: 773]
 | 
			
		||||
 | 
			
		||||
* Sat Feb 11 2006 Charlie Brady <charlieb@e-smith.com> 1.15.3-39
 | 
			
		||||
- Remove obsolete e-smith-lib-Tai64n package. [SME: 689]
 | 
			
		||||
 | 
			
		||||
* Sat Feb 11 2006 Charlie Brady <charlieb@e-smith.com> 1.15.3-38
 | 
			
		||||
- [Null changelog for missing version - we accidentally skipped
 | 
			
		||||
   this version.]
 | 
			
		||||
 | 
			
		||||
* Sat Feb 11 2006 Charlie Brady <charlieb@e-smith.com> 1.15.3-37
 | 
			
		||||
- Fix get_all_by_prop in scalar context. [SME: 669,721]
 | 
			
		||||
 | 
			
		||||
* Mon Feb  6 2006 Shad L. Lords <slords@mail.com> 1.15.3-37
 | 
			
		||||
- Add ability to pass many props to get_all_by_prop [SME: 669]
 | 
			
		||||
 | 
			
		||||
* Mon Jan 23 2006 Charlie Brady <charlieb@e-smith.com> 1.15.3-36
 | 
			
		||||
- Fix warning during pseudonym deletion. [SME: 491]
 | 
			
		||||
 | 
			
		||||
* Fri Jan 20 2006 Charlie Brady <charlieb@e-smith.com> 1.15.3-35
 | 
			
		||||
- Fix up use of Sys::Syslog::syslog. [SME: 526]
 | 
			
		||||
 | 
			
		||||
* Thu Jan 19 2006 Charlie Brady <charlieb@e-smith.com> 1.15.3-34
 | 
			
		||||
- Remove running of kudzu during NIC probing. TODO: Find a solution
 | 
			
		||||
  to system reconfiguration when new hardware is added. [SME: 192]
 | 
			
		||||
 | 
			
		||||
* Tue Jan 10 2006 Charlie Brady <charlieb@e-smith.com> 1.15.3-33
 | 
			
		||||
- Fold a.b.c.d/255.255.255.255 to a.b.c.d in local_access_spec() to
 | 
			
		||||
  work around bugs in applications which don't accept such specs.
 | 
			
		||||
  [SME: 430]
 | 
			
		||||
 | 
			
		||||
* Mon Jan 9 2006 Gordon Rowell <gordonr@gormand.com.au> 1.15.3-32
 | 
			
		||||
- Check whether an accounts db record exists before trying to create
 | 
			
		||||
  the dot and underscore pseudonyms (new_record will fail silently)
 | 
			
		||||
  and check that the records are pseudonyms before deleting them [SME: 24]
 | 
			
		||||
 | 
			
		||||
* Mon Jan 9 2006 Gordon Rowell <gordonr@gormand.com.au> 1.15.3-31
 | 
			
		||||
- And update POD for last change [SME: 24]
 | 
			
		||||
 | 
			
		||||
* Mon Jan 9 2006 Gordon Rowell <gordonr@gormand.com.au> 1.15.3-30
 | 
			
		||||
- Allow dot and underscore in account names [SME: 24]
 | 
			
		||||
 | 
			
		||||
* Tue Dec 27 2005 Gordon Rowell <gordonr@gormand.com.au> 1.15.3-29
 | 
			
		||||
- Remove newlines from cluck() string and just note that the old
 | 
			
		||||
  path was used [SME: 365]
 | 
			
		||||
 | 
			
		||||
* Sat Dec 25 2005 Gordon Rowell <gordonr@gormand.com.au> 1.15.3-28
 | 
			
		||||
- If db exists in both the old and new locations in 
 | 
			
		||||
  initialize_default_databases, rename the one in the new 
 | 
			
		||||
  location to db.time(), avoiding the conflict and saving the 
 | 
			
		||||
  evidence in case it is needed later [SME: 229]
 | 
			
		||||
 | 
			
		||||
* Mon Dec 05 2005 Mark Knox <mark_knox@mitel.com>
 | 
			
		||||
- [1.15.3-27]
 | 
			
		||||
- Moved queueing logic to separate daemon, replaced with FIFO IPC [BZ252
 | 
			
		||||
 | 
			
		||||
* Thu Dec 01 2005 Mark Knox <mark_knox@mitel.com>
 | 
			
		||||
- [1.15.3-26]
 | 
			
		||||
- Added event queueing (open source portion) for clustered systems [BZ250]
 | 
			
		||||
 | 
			
		||||
* Wed Nov 30 2005 Gordon Rowell <gordonr@gormand.com.au> 1.15.3-25
 | 
			
		||||
- Bump release number only
 | 
			
		||||
 | 
			
		||||
* Thu Nov 24 2005 Gordon Rowell <gordonr@e-smith.com>
 | 
			
		||||
- [1.15.3-24]
 | 
			
		||||
- Add missing 'use Locale::gettext' to esmith::console.pm [MN00108804]
 | 
			
		||||
 | 
			
		||||
* Sun Nov 20 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-23]
 | 
			
		||||
- Clarify logic for stopped services in adjust-services. [SF: 1357629]
 | 
			
		||||
 | 
			
		||||
* Sun Nov 20 2005 Gordon Rowell <gordonr@e-smith.com>
 | 
			
		||||
- [1.15.3-22]
 | 
			
		||||
- Correct adjust-services logic for stopped services [SF: 1357629]
 | 
			
		||||
 | 
			
		||||
* Wed Nov 16 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-21]
 | 
			
		||||
- Allow services2adjust directories to contain files rather than just dangling
 | 
			
		||||
  symlinks. Files can contain more than one actions to perform. [SF: 1270644]
 | 
			
		||||
 | 
			
		||||
* Wed Nov 16 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-20]
 | 
			
		||||
- Also don't start services if we just want to "once" them. [SF: 1357629]
 | 
			
		||||
 | 
			
		||||
* Wed Nov 16 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-19]
 | 
			
		||||
- Fix restart of enabled supervised services which we are attempting to stop.
 | 
			
		||||
  [SF: 1357629]
 | 
			
		||||
 | 
			
		||||
* Tue Nov 15 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-18]
 | 
			
		||||
- Set default for $type in esmith::cgi::genSmallCell, to prevent some log
 | 
			
		||||
  noise. [SF: 1357830]
 | 
			
		||||
 | 
			
		||||
* Tue Nov 15 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-17]
 | 
			
		||||
- Pass $EVENT to template expansions in generic_template_expand.
 | 
			
		||||
  [SF: MN00106104]
 | 
			
		||||
 | 
			
		||||
* Tue Nov 15 2005 Gordon Rowell <gordonr@e-smith.com>
 | 
			
		||||
- [1.15.3-16]
 | 
			
		||||
- Redirect esmith::config calls on old db paths to the new
 | 
			
		||||
  location [SF: 1335865]
 | 
			
		||||
 | 
			
		||||
* Thu Oct 27 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-15]
 | 
			
		||||
- Fix a few minor spec file portability issues. [SF: 1339729]
 | 
			
		||||
 | 
			
		||||
* Wed Oct 26 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-14]
 | 
			
		||||
- Add it and de to the langtag2locale fixups. [SF: 1338236]
 | 
			
		||||
 | 
			
		||||
* Tue Oct 11 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-13]
 | 
			
		||||
- Build driver list from .ko files as well as .o files. Untaint driver
 | 
			
		||||
  names while building list. [SF: 1323270]
 | 
			
		||||
 | 
			
		||||
* Mon Sep 26 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-12]
 | 
			
		||||
- Fix "defaults" handling so that values which evaluate to false are
 | 
			
		||||
  not overridden by default. [SF: 1303885]
 | 
			
		||||
 | 
			
		||||
* Fri Sep 23 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-11]
 | 
			
		||||
- Untaint db names before attempting to move them. [MN00098405]
 | 
			
		||||
 | 
			
		||||
* Thu Sep 22 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-10]
 | 
			
		||||
- Provide networks method in esmith::NetworksDB. [SF: 1296099]
 | 
			
		||||
- Support a "localhost" configuration in esmith::tcpsvd:configure_peers
 | 
			
		||||
  [SF: 1294719]
 | 
			
		||||
 | 
			
		||||
* Tue Sep 20 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-09]
 | 
			
		||||
- Remove deprecated functions from esmith::utils. [SF: 1295851]
 | 
			
		||||
- Include only "network" records in local_access_spec. [SF: 1296099]
 | 
			
		||||
 | 
			
		||||
* Mon Sep 12 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-08]
 | 
			
		||||
- Remove warning about explicit path in esmith::db::_db_path.
 | 
			
		||||
  [SF: 1286294]
 | 
			
		||||
 | 
			
		||||
* Fri Sep  9 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-07]
 | 
			
		||||
- Tolerate, but warn about, symlinks in /home/e-smith. [SF: 1216546]
 | 
			
		||||
 | 
			
		||||
* Fri Sep  9 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-06]
 | 
			
		||||
- Reduce the noise from _file_path() in esmith::DB::db. [SF: 1286294]
 | 
			
		||||
 | 
			
		||||
* Wed Sep  7 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-05]
 | 
			
		||||
- Fix operation of expandTemplate when taint check is enabled.
 | 
			
		||||
  [SF: 1284301]
 | 
			
		||||
 | 
			
		||||
* Wed Aug 17 2005 Mark Knox <markk@e-smith.com>
 | 
			
		||||
- [1.15.3-04]
 | 
			
		||||
- Added open_local and open_ro_local methods for clustering [markk MN00094831]
 | 
			
		||||
 | 
			
		||||
* Tue Aug 16 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-03]
 | 
			
		||||
- Fix POD error in util.pm.
 | 
			
		||||
 | 
			
		||||
* Wed Jul 27 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-02]
 | 
			
		||||
- Move databases default location from /home/e-smith to /home/e-smith/db.
 | 
			
		||||
  During esmith::utils::initialize_default_databases, move from old to new
 | 
			
		||||
  location before doing db migrate actions. [SF: 1216546]
 | 
			
		||||
 | 
			
		||||
* Wed Jul 27 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-01]
 | 
			
		||||
- Roll a new development stream - 1.15.3
 | 
			
		||||
 | 
			
		||||
* Wed Jul 27 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.2-04]
 | 
			
		||||
- Remove broken MergeDB stuff. [SF: 1246315]
 | 
			
		||||
 | 
			
		||||
* Wed Jul 27 2005 Mark Knox <markk@e-smith.com>
 | 
			
		||||
- [1.15.2-03]
 | 
			
		||||
- Fixed misleading comment in util.pm
 | 
			
		||||
- Added 'use' statements in Record classes for SOAP compatibility
 | 
			
		||||
- Fixed undefined max_len warning
 | 
			
		||||
- Added explicit writeconf calls in db::Record.pm, needed for setting props
 | 
			
		||||
  via SOAP
 | 
			
		||||
 | 
			
		||||
* Tue Jul 19 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.2-02]
 | 
			
		||||
- Allow db open API to use default path if a simple filename
 | 
			
		||||
  is provided as arg. This is preparation for move of dbs to
 | 
			
		||||
  /home/e-smith/db. Patch by Shad Lords.
 | 
			
		||||
 | 
			
		||||
* Mon Jul 18 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.2-01]
 | 
			
		||||
- Roll new development stream - 1.15.2
 | 
			
		||||
 | 
			
		||||
* Fri Jul 15 2005 Mark Knox <markk@e-smith.com>
 | 
			
		||||
- [1.15.1-44]
 | 
			
		||||
- Tweak to allow calling _writeconf from SOAP [markk MN00090738]
 | 
			
		||||
 | 
			
		||||
* Tue Jun 21 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-43]
 | 
			
		||||
- Ensure that esmith::util::LdapPassword returns bare string without
 | 
			
		||||
  newline terminator.
 | 
			
		||||
 | 
			
		||||
* Sun Jun 12 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-42]
 | 
			
		||||
- Remove .rpmsave and .rpmnew symlinks (as well as files). [SF: 1217969]
 | 
			
		||||
- Handle missing description in pcitables entries.
 | 
			
		||||
 | 
			
		||||
* Sun Jun 12 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-41]
 | 
			
		||||
- Provide feedback (via log messages) from services2adjust. [SF: 1218920]
 | 
			
		||||
 | 
			
		||||
* Mon May 30 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-40]
 | 
			
		||||
- Add preinstall scripting to create required accounts/groups if they
 | 
			
		||||
  don't already exist. [SF: 1210723]
 | 
			
		||||
 | 
			
		||||
* Thu May  5 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-39]
 | 
			
		||||
- Show Text::Template error text rather than inappropriate $! if template
 | 
			
		||||
  expansion fails.
 | 
			
		||||
- Change error to warning if a config item is set with an empty "type"
 | 
			
		||||
  property.
 | 
			
		||||
 | 
			
		||||
* Thu May  5 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-38]
 | 
			
		||||
- Fix esmith::DB::get_prop_and_delete fail if prop is "false" [From Gordon].
 | 
			
		||||
 | 
			
		||||
* Tue May  3 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-37]
 | 
			
		||||
- Update directory list so that ethernet drivers from kernel-unsupported are
 | 
			
		||||
  added to "choose by driver" list.
 | 
			
		||||
 | 
			
		||||
* Sat Mar 19 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-36]
 | 
			
		||||
- Rework esmith::tcpsvd::configure_peers so that it doesn't chdir.
 | 
			
		||||
- Fix generic_template_expand so that templates.metadata doesn't
 | 
			
		||||
  need to set OUTPUT_FILENAME is TEMPLATE_PATH is changed. This
 | 
			
		||||
  matches what expand-template already does.
 | 
			
		||||
 | 
			
		||||
* Fri Mar 18 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-35]
 | 
			
		||||
- Change numerous calls to "croak" in esmith::template
 | 
			
		||||
  to "carp ...; return", so that problem with any single
 | 
			
		||||
  template expansion doesn't terminate calling program.
 | 
			
		||||
  [MN00075009]
 | 
			
		||||
 | 
			
		||||
* Wed Mar 16 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-34]
 | 
			
		||||
- Add missing "use esmith::util" in esmith::tcpsvd.
 | 
			
		||||
 | 
			
		||||
* Wed Mar 16 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-33]
 | 
			
		||||
- Add esmith::tcpsvd library for managing tcpsvd "peers"
 | 
			
		||||
  directories.
 | 
			
		||||
 | 
			
		||||
* Mon Mar 14 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-32]
 | 
			
		||||
- Make template expansion message more succinct.
 | 
			
		||||
 | 
			
		||||
* Thu Mar 10 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-31]
 | 
			
		||||
- Remove pseudonyms of pseudonyms when removing user
 | 
			
		||||
  accounts. Adapted from patch submitted by Shad. [MN00039941]
 | 
			
		||||
 | 
			
		||||
* Wed Feb 23 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-30]
 | 
			
		||||
- Fix incompatibility with CentOS's CGI.pm. 
 | 
			
		||||
 | 
			
		||||
* Tue Feb 22 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-29]
 | 
			
		||||
- Fix bug in output to empty file when FILTER is used
 | 
			
		||||
  during template expansion. [charlieb MN00050075]
 | 
			
		||||
 | 
			
		||||
* Tue Feb 22 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-28]
 | 
			
		||||
- Refresh contents of /etc/sysconfig/hwconf before listing
 | 
			
		||||
  network adaptors [MN00069993]
 | 
			
		||||
- Fix typo in documentation of esmith::DB::db - reported from Tanna -
 | 
			
		||||
  http://www.livejournal.com/users/gcrumb/61169.html (thanks Dan!)
 | 
			
		||||
 | 
			
		||||
* Wed Feb 16 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-27]
 | 
			
		||||
- Fix typo. [MN00066059]
 | 
			
		||||
 | 
			
		||||
* Wed Feb 16 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-26]
 | 
			
		||||
- Use /sbin/e-smith/whiptail if it is available. [MN00066059]
 | 
			
		||||
 | 
			
		||||
* Mon Feb  7 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-25]
 | 
			
		||||
- Update perms and ownership when expanding templates, regardless of
 | 
			
		||||
  whether file content has changed or not. [MN00068043]
 | 
			
		||||
 | 
			
		||||
* Wed Feb  2 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-24]
 | 
			
		||||
- Fix the insertion of implicit actions into sorted action list in
 | 
			
		||||
  event.pm. Problem was perl syntax ambiguity.  [MN00066406]
 | 
			
		||||
 | 
			
		||||
* Fri Jan 28 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-23]
 | 
			
		||||
- Really move /home/e-smith/* to e-smith-base. [MN00066635]
 | 
			
		||||
 | 
			
		||||
* Fri Jan 28 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-22]
 | 
			
		||||
- Move /home/e-smith/* to e-smith-base. [MN00066635]
 | 
			
		||||
- Move generic-template expand to S05 position in sort, and
 | 
			
		||||
  adjust-service to S90. Fix run-time error. [MN00066406]
 | 
			
		||||
- Don't attempt to execute non-executable action scripts.
 | 
			
		||||
 | 
			
		||||
* Thu Jan 27 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-21]
 | 
			
		||||
- Implicitly include template expand and services adjust actions
 | 
			
		||||
  in each event if the respective metadata directory exists.
 | 
			
		||||
  [MN00066406]
 | 
			
		||||
 | 
			
		||||
* Tue Jan 25 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-20]
 | 
			
		||||
- Add "adjust" to list of verbs which serviceControl groks,
 | 
			
		||||
  to allow for "masq adjust". [MN00065576]
 | 
			
		||||
 | 
			
		||||
* Tue Jan 25 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-19]
 | 
			
		||||
- Add adjust-services generic action script [MN00065576]
 | 
			
		||||
 | 
			
		||||
* Tue Jan 18 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-18]
 | 
			
		||||
- Fix typo. [MN00064412]
 | 
			
		||||
- Improve die() message in esmith::config::STORE. [MN00064394]
 | 
			
		||||
 | 
			
		||||
* Mon Jan 17 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-17]
 | 
			
		||||
- Fix broken logging (and reduce logging) in initialize_default_databases.
 | 
			
		||||
  [MN00064412]
 | 
			
		||||
- Fix inappropriate use of global $_ in initialize_default_databases.
 | 
			
		||||
  [MN00064415]
 | 
			
		||||
 | 
			
		||||
* Thu Dec 23 2004 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-16]
 | 
			
		||||
- Read templated file metadata (if any) from file tree under 
 | 
			
		||||
  /etc/e-smith/templates.metadata. Update expand-template to
 | 
			
		||||
  use current API. [MN00061830]
 | 
			
		||||
 | 
			
		||||
* Tue Dec 14 2004 Mark Knox <markk@e-smith.com>
 | 
			
		||||
- [1.15.1-15]
 | 
			
		||||
- Change copyright date to 2004 [markk MN00060958]
 | 
			
		||||
 | 
			
		||||
* Fri Nov  5 2004 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-14]
 | 
			
		||||
- Fix Authen::PAM dependency header [charlieb MN00040240]
 | 
			
		||||
- Use kudzu's generated /etc/sysconfig/hwconf file for NIC detection
 | 
			
		||||
  [charlieb MN00056220]
 | 
			
		||||
 | 
			
		||||
* Thu Oct 14 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.1-13]
 | 
			
		||||
- Updated esmith::ethernet's search code to remove File::Find, as it doesn't
 | 
			
		||||
  get along with taint checking. [msoulier MN00052510]
 | 
			
		||||
 | 
			
		||||
* Wed Oct 13 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.1-12]
 | 
			
		||||
- Updated esmith::ethernet's search code such that is it more adaptable, and
 | 
			
		||||
  recurses the directories given. [msoulier MN00052510]
 | 
			
		||||
 | 
			
		||||
* Wed Oct 13 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.1-11]
 | 
			
		||||
- Updated esmith::ethernet's search paths for network drivers.
 | 
			
		||||
  [msoulier MN00052510]
 | 
			
		||||
 | 
			
		||||
* Mon Oct  4 2004 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-10]
 | 
			
		||||
- Remove dependency on perl(Filter::Handle) [charlieb MN00050075]
 | 
			
		||||
 | 
			
		||||
* Fri Sep 24 2004 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-09]
 | 
			
		||||
- Updated requires with new perl dependencies. [msoulier MN00040240]
 | 
			
		||||
- Remove "AutoReqProv: no" so that "Provides" headers are auto-generated.
 | 
			
		||||
  [charlieb MN00040240]
 | 
			
		||||
- Remove anachronistic "require v5.6.0" directives. [charlieb MN00050370]
 | 
			
		||||
- Avoid use of Filter::Handle in esmith::template. [charlieb MN00050075]
 | 
			
		||||
 | 
			
		||||
* Fri Aug 27 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.1-08]
 | 
			
		||||
- Added esmith::util::network::isValidEmail function. [msoulier MN00023814]
 | 
			
		||||
 | 
			
		||||
* Thu Aug 26 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.1-07]
 | 
			
		||||
- Added svdisable to permissible actions in serviceControl.
 | 
			
		||||
  [msoulier MN00043056]
 | 
			
		||||
 | 
			
		||||
* Tue Aug 10 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.1-06]
 | 
			
		||||
- Fixed new methods. Bad else case. [msoulier MN00044891]
 | 
			
		||||
 | 
			
		||||
* Fri Aug  6 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.1-05]
 | 
			
		||||
- Added a keys() method. [msoulier MN00041968]
 | 
			
		||||
 | 
			
		||||
* Fri Aug  6 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.1-04]
 | 
			
		||||
- Added set_prop and set_value methods in esmith::DB. [msoulier MN00044891]
 | 
			
		||||
 | 
			
		||||
* Tue Jul 20 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.1-03]
 | 
			
		||||
- Undeprecated esmith::util::serviceControl. [msoulier MN00043056]
 | 
			
		||||
 | 
			
		||||
* Fri Jun 25 2004 Tony Clayton <apc@e-smith.com>
 | 
			
		||||
- [1.15.1-02]
 | 
			
		||||
- Merge language_tag2locale() function from perl-I18N-LangTags [tonyc
 | 
			
		||||
  MN00040170]
 | 
			
		||||
 | 
			
		||||
* Fri May 28 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.1-01]
 | 
			
		||||
- Rolling to collect patches.
 | 
			
		||||
 | 
			
		||||
* Fri May 28 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-23]
 | 
			
		||||
- Reordered the create code slightly to catch more errors.
 | 
			
		||||
  [msoulier MN00035059]
 | 
			
		||||
 | 
			
		||||
* Fri May 28 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-22]
 | 
			
		||||
- Added yet more error handling and reporting. [msoulier MN00035059]
 | 
			
		||||
 | 
			
		||||
* Fri May 28 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-21]
 | 
			
		||||
- Fixed one $Error reference that I missed in the last rev.
 | 
			
		||||
  [msoulier MN00035059]
 | 
			
		||||
 | 
			
		||||
* Fri May 28 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-20]
 | 
			
		||||
- Moved error handling from esmith::DB::db to esmith::DB, since it should not
 | 
			
		||||
  be database implementation specific. [msoulier MN00035059]
 | 
			
		||||
 | 
			
		||||
* Fri May 28 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-19]
 | 
			
		||||
- Propagated migration failures up to calling code for reporting to syslog.
 | 
			
		||||
- Propagated creation failures up to calling code. 
 | 
			
		||||
- Moved lexicon $Error in esmith::DB::db to a class property so it can be used
 | 
			
		||||
  by subclasses. [msoulier MN00035059]
 | 
			
		||||
 | 
			
		||||
* Thu May 27 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-18]
 | 
			
		||||
- Changed print statements to calls to the logger. [msoulier MN00035059]
 | 
			
		||||
 | 
			
		||||
* Thu May 27 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-17]
 | 
			
		||||
- Added print statements to initialize-default-databases for post-install
 | 
			
		||||
  debugging. [msoulier MN00035059]
 | 
			
		||||
 | 
			
		||||
* Fri May  7 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-16]
 | 
			
		||||
- Fixed migrate to report the caught error message. [msoulier MN00032503]
 | 
			
		||||
 | 
			
		||||
* Thu May  6 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-15]
 | 
			
		||||
- Added isValidHostname function to esmith::util::network.
 | 
			
		||||
  [msoulier MN00024212]
 | 
			
		||||
 | 
			
		||||
* Fri Feb 13 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-14]
 | 
			
		||||
- Greatly simplified the _mysystem function by ripping out open3.
 | 
			
		||||
  [msoulier dpar-20385]
 | 
			
		||||
 | 
			
		||||
* Fri Feb 13 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-13]
 | 
			
		||||
- Backed-out change in esmith::util, as it's non-trivial there with the exec.
 | 
			
		||||
  Completed update of esmith::event, and separated the esmith::Logger class.
 | 
			
		||||
  [msoulier dpar-20385]
 | 
			
		||||
 | 
			
		||||
* Fri Feb 13 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-12]
 | 
			
		||||
- Removed use of the logger entirely, replacing it with an abstracted
 | 
			
		||||
  interface to the Sys::Syslog module. [msoulier dpar-20385]
 | 
			
		||||
 | 
			
		||||
* Thu Jan  8 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-11]
 | 
			
		||||
- Fixed esmith::util::network::isValidIP() so valid IP substrings no longer
 | 
			
		||||
  return true values. [msoulier 9308]
 | 
			
		||||
 | 
			
		||||
* Thu Jan  8 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-10]
 | 
			
		||||
- Added a check in STORE in esmith::config for invalid attempts to set a value
 | 
			
		||||
  without a type. Also escalated previous warnings for undef key and value to
 | 
			
		||||
  fatal exceptions. [msoulier 7386]
 | 
			
		||||
 | 
			
		||||
* Thu Jan  8 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-09]
 | 
			
		||||
- Now trimming whitespace around keys and values during esmith::config STORE
 | 
			
		||||
  events, to prevent invalid keys and values from being saved. [msoulier 7021]
 | 
			
		||||
 | 
			
		||||
* Mon Jan  5 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-08]
 | 
			
		||||
- Fixed POD around merge_props. [msoulier 9482]
 | 
			
		||||
 | 
			
		||||
* Fri Nov  7 2003 Tony Clayton <apc@e-smith.com>
 | 
			
		||||
- [1.15.0-07]
 | 
			
		||||
- And again [tonyc 10569]
 | 
			
		||||
 | 
			
		||||
* Fri Nov  7 2003 Tony Clayton <apc@e-smith.com>
 | 
			
		||||
- [1.15.0-06]
 | 
			
		||||
- Change Merge API a bit, fix pod [tonyc 10569]
 | 
			
		||||
 | 
			
		||||
* Fri Nov  7 2003 Tony Clayton <apc@e-smith.com>
 | 
			
		||||
- [1.15.0-05]
 | 
			
		||||
- Add esmith::DB::Merge library [tonyc 10569]
 | 
			
		||||
 | 
			
		||||
* Fri Oct 10 2003 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-04]
 | 
			
		||||
- Fixed AccountsDB.pm to handle group names with hyphens and periods, to match
 | 
			
		||||
  the error message in the groups panel, and the rest of the group/user
 | 
			
		||||
  behaviour. [msoulier 10236]
 | 
			
		||||
 | 
			
		||||
* Sun Sep 21 2003 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.0-03]
 | 
			
		||||
- Skip any directries when iterating over action scripts in esmith::event.
 | 
			
		||||
  Add logfile timestamp symlinking to generic_template_expand action.
 | 
			
		||||
  Use templates2expand and logfiles2timestamp subdirectories of the event
 | 
			
		||||
  directory. Fix shebang line. [charlieb 10035]
 | 
			
		||||
 | 
			
		||||
* Thu Sep 18 2003 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.0-02]
 | 
			
		||||
- Add generic_template_expand action. [charlieb 10035]
 | 
			
		||||
 | 
			
		||||
* Thu Sep 18 2003 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.0-01]
 | 
			
		||||
- Changing version to development stream number - 1.15.0
 | 
			
		||||
 | 
			
		||||
%prep
 | 
			
		||||
%setup
 | 
			
		||||
 | 
			
		||||
%pre
 | 
			
		||||
#--------------------------------------------------
 | 
			
		||||
# add admin, public and www user accounts
 | 
			
		||||
#--------------------------------------------------
 | 
			
		||||
/usr/sbin/groupadd \
 | 
			
		||||
  -g 500 shared 2>/dev/null || :
 | 
			
		||||
/usr/sbin/useradd \
 | 
			
		||||
  -u 102 -c 'e-smith web server' -d /home/e-smith \
 | 
			
		||||
  -G shared -M -s /bin/false www 2>/dev/null || :
 | 
			
		||||
/usr/sbin/useradd \
 | 
			
		||||
  -u 101 -c 'e-smith administrator' -d /home/e-smith \
 | 
			
		||||
  -G shared,root,www -M -s /sbin/e-smith/console admin 2>/dev/null || :
 | 
			
		||||
/usr/sbin/useradd \
 | 
			
		||||
  -u 103 -c 'e-smith guest' -d /home/e-smith \
 | 
			
		||||
  -G shared -M -s /bin/false public 2>/dev/null || :
 | 
			
		||||
/usr/sbin/useradd \
 | 
			
		||||
  -u 1002 -c 'sme log user' -d /var/log/smelog \
 | 
			
		||||
  -M -s /bin/false smelog 2>/dev/null || :
 | 
			
		||||
 | 
			
		||||
exit 0
 | 
			
		||||
 | 
			
		||||
%post
 | 
			
		||||
 | 
			
		||||
%build
 | 
			
		||||
for event in post-install post-upgrade bootstrap-console-save console-save
 | 
			
		||||
do
 | 
			
		||||
    mkdir -p root/etc/e-smith/events/$event
 | 
			
		||||
done
 | 
			
		||||
perl createlinks
 | 
			
		||||
 | 
			
		||||
%install
 | 
			
		||||
rm -rf $RPM_BUILD_ROOT
 | 
			
		||||
(cd root   ; find . -depth -print | cpio -dump $RPM_BUILD_ROOT)
 | 
			
		||||
rm -f %{name}-%{version}-%{release}-filelist
 | 
			
		||||
/sbin/e-smith/genfilelist $RPM_BUILD_ROOT \
 | 
			
		||||
    >%{name}-%{version}-%{release}-filelist
 | 
			
		||||
echo "%doc Copying" >> %{name}-%{version}-%{release}-filelist
 | 
			
		||||
echo "%doc Artistic" >> %{name}-%{version}-%{release}-filelist
 | 
			
		||||
echo "%doc LICENSE" >> %{name}-%{version}-%{release}-filelist
 | 
			
		||||
 | 
			
		||||
%clean
 | 
			
		||||
rm -rf $RPM_BUILD_ROOT
 | 
			
		||||
 | 
			
		||||
%files -f %{name}-%{version}-%{release}-filelist
 | 
			
		||||
%defattr(-,root,root)
 | 
			
		||||
							
								
								
									
										1
									
								
								contriborbase
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								contriborbase
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
sme10
 | 
			
		||||
							
								
								
									
										38
									
								
								createlinks
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								createlinks
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
#!/usr/bin/perl -w
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright (c) 2001 Mitel Networks Corporation 
 | 
			
		||||
# 
 | 
			
		||||
# Technical support for this program is available from Mitel Networks
 | 
			
		||||
# Corporation.  Please visit our web site www.e-smith.com for details.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
sub panel_link
 | 
			
		||||
{
 | 
			
		||||
    my ($function, $panel) = @_;
 | 
			
		||||
 | 
			
		||||
	unlink "root/etc/e-smith/web/panels/$panel/cgi-bin/$function";
 | 
			
		||||
	symlink("../../../functions/$function",
 | 
			
		||||
		"root/etc/e-smith/web/panels/$panel/cgi-bin/$function")
 | 
			
		||||
	or die "Can't symlink to root/etc/e-smith/web/panels/$panel".
 | 
			
		||||
		"/cgi-bin/$function: $!";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub event_link
 | 
			
		||||
{
 | 
			
		||||
    my ($action, $event, $level) = @_;
 | 
			
		||||
 | 
			
		||||
    unlink "root/etc/e-smith/events/${event}/S${level}${action}";
 | 
			
		||||
    symlink("../actions/${action}",
 | 
			
		||||
	"root/etc/e-smith/events/${event}/S${level}${action}")
 | 
			
		||||
    or die "Can't symlink to " .
 | 
			
		||||
	"root/etc/e-smith/events/${event}/S${level}${action}: $!";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#--------------------------------------------------
 | 
			
		||||
# actions for events
 | 
			
		||||
#--------------------------------------------------
 | 
			
		||||
 | 
			
		||||
foreach my $event (qw(post-install post-upgrade bootstrap-console-save console-save))
 | 
			
		||||
{
 | 
			
		||||
    event_link("initialize-default-databases", $event, "00");
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										902
									
								
								e-smith-lib.spec
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										902
									
								
								e-smith-lib.spec
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,902 @@
 | 
			
		||||
# $Id: e-smith-lib.spec,v 1.20 2023/07/11 02:49:10 trevorb Exp $
 | 
			
		||||
 | 
			
		||||
%define copykooz 2013-2021
 | 
			
		||||
 | 
			
		||||
Summary: e-smith server and gateway - library module
 | 
			
		||||
%define name e-smith-lib
 | 
			
		||||
Name: %{name}
 | 
			
		||||
%define version 2.6.0
 | 
			
		||||
%define release 17
 | 
			
		||||
Version: %{version}
 | 
			
		||||
Release: %{release}%{?dist}
 | 
			
		||||
License: Artistic
 | 
			
		||||
Group: Networking/Daemons
 | 
			
		||||
Source: %{name}-%{version}.tar.xz
 | 
			
		||||
 | 
			
		||||
BuildRoot: /var/tmp/%{name}-%{version}-%{release}-buildroot
 | 
			
		||||
BuildArchitectures: noarch
 | 
			
		||||
BuildRequires: e-smith-devtools >= 1.6.3-01
 | 
			
		||||
Obsoletes: %{name}-Tai64n
 | 
			
		||||
Obsoletes: whiptail
 | 
			
		||||
Requires(pre): e-smith
 | 
			
		||||
Requires: dialog
 | 
			
		||||
Requires: perl, perl(Text::Template)
 | 
			
		||||
Requires: perl(Time::HiRes), perl(MIME::Base64)
 | 
			
		||||
Requires: perl(Authen::PAM), perl(I18N::AcceptLanguage)
 | 
			
		||||
Requires: perl(I18N::LangTags) >= 0.27
 | 
			
		||||
Requires: perl(Net::IPv4Addr) >= 0.10
 | 
			
		||||
Requires: perl(Taint::Util)
 | 
			
		||||
Requires: pciutils
 | 
			
		||||
 | 
			
		||||
%description
 | 
			
		||||
e-smith server and gateway software - library module.
 | 
			
		||||
 | 
			
		||||
%changelog
 | 
			
		||||
* Wed Jul 12 2023 cvs2git.sh aka Brian Read <brianr@koozali.org> 2.6.0-17.sme
 | 
			
		||||
- Roll up patches and move to git repo [SME: 12338]
 | 
			
		||||
- Remove create e-smith-lib-update event [SME: 12338]
 | 
			
		||||
 | 
			
		||||
* Wed Jul 12 2023 BogusDateBot
 | 
			
		||||
- Eliminated rpmbuild "bogus date" warnings due to inconsistent weekday,
 | 
			
		||||
  by assuming the date is correct and changing the weekday.
 | 
			
		||||
 | 
			
		||||
* Wed Nov 23 2022 Jean-Philippe Pialasse <tests@pialasse.com> 2.6.0-16.sme
 | 
			
		||||
- allow call to systemctl aliases in etc [SME: 12194]
 | 
			
		||||
  fix network=>networking service is not restarted.
 | 
			
		||||
 | 
			
		||||
* Thu Oct 28 2021 Jean-Philippe Pialasse <tests@pialasse.com> 2.6.0-15.sme
 | 
			
		||||
- add support for service with instances [SME: 11723]
 | 
			
		||||
 | 
			
		||||
* Mon Apr 19 2021 Jean-Philippe Pialasse <tests@pialasse.com> 2.6.0-14.sme
 | 
			
		||||
- update copyright dates, and make it easier to change from spec file [SME: 11570]
 | 
			
		||||
 | 
			
		||||
* Sat Jan 02 2021 Jean-Philipe Pialasse <tests@pialasse.com> 2.6.0-13.sme
 | 
			
		||||
- partial revert of signals [SME: 11177]
 | 
			
		||||
  signal s not passed to runit services (dnscache*, qmail, qpsmtpd...)
 | 
			
		||||
  services handled by systemd crash if they do not have Restart=always defined
 | 
			
		||||
 | 
			
		||||
* Fri Jan 01 2021 Jean-Philipe Pialasse <tests@pialasse.com> 2.6.0-12.sme
 | 
			
		||||
- add support for signals SIG* with systemd [SME: 11177]
 | 
			
		||||
  fix typo for reload-or-try-restart
 | 
			
		||||
  unsupervised services: really stop when disabled and start stopped enabled ones 
 | 
			
		||||
 | 
			
		||||
* Thu Nov 26 2020 Jean-Philipe Pialasse <tests@pialasse.com> 2.6.0-11.sme
 | 
			
		||||
- remove error when sending sighup event [SME: 11177]
 | 
			
		||||
 | 
			
		||||
* Tue Nov 17 2020 Jean-Philipe Pialasse <tests@pialasse.com> 2.6.0-10.sme
 | 
			
		||||
- allow more systemctl controls [SME: 11177]
 | 
			
		||||
  convert unrecognized signals from service2adjust in events for systemd
 | 
			
		||||
  handle unsupervised services the same way supervised were in adjust-services
 | 
			
		||||
- create e-smith-lib-event [SME: 11141]
 | 
			
		||||
  
 | 
			
		||||
* Thu Dec 12 2019 Jean-Philipe Pialasse <tests@pialasse.com> 2.6.0-9.sme
 | 
			
		||||
- add support for systemctl reload-or-restart, try-restart, enable -now  [SME: 10848]
 | 
			
		||||
 | 
			
		||||
* Wed Oct 25 2017 Daniel Berteaud <daniel@firewall-services.com> 2.6.0-8.sme
 | 
			
		||||
- Revert prev change regarding tap_soft, as it's not needed [SME: 10445]
 | 
			
		||||
 | 
			
		||||
* Mon Oct 23 2017 Daniel Berteaud <daniel@firewall-services.com> 2.6.0-7.sme
 | 
			
		||||
- Skip tap_soft interfaces (eg SoftEther, code from Hsing-Foo Wang)
 | 
			
		||||
  [SME: 10445]
 | 
			
		||||
 | 
			
		||||
* Wed Apr 12 2017 Jean-Philipe Pialasse <tests@pialasse.com> 2.6.0-6.sme
 | 
			
		||||
- remove reference to smtpd in configuration.conf [SME: 9478]
 | 
			
		||||
 | 
			
		||||
* Thu Aug 04 2016 Jean-Philipe Pialasse <tests@pialasse.com> 2.6.0-5.sme
 | 
			
		||||
- fix console startup display [SME: 9352]
 | 
			
		||||
 | 
			
		||||
* Sat Jul 23 2016 Jean-Philipe Pialasse <tests@pialasse.com> 2.6.0-4.sme
 | 
			
		||||
- fix service name  syslog to rsyslog [SME: 9691]
 | 
			
		||||
 | 
			
		||||
* Mon Jul 18 2016 Jean-Philipe Pialasse <tests@pialasse.com> 2.6.0-3.sme
 | 
			
		||||
- fix mysqld to mariadb [SME: 9438]
 | 
			
		||||
- Eliminated rpmbuild "bogus date" warnings due to inconsistent weekday,
 | 
			
		||||
  by assuming the date is correct and changing the weekday.
 | 
			
		||||
  Sat Dec 25 2005 --> Sat Dec 24 2005 or Sun Dec 25 2005 or Sat Dec 31 2005 or ....
 | 
			
		||||
  Tue Dec 15 2006 --> Tue Dec 12 2006 or Fri Dec 15 2006 or Tue Dec 19 2006 or ....
 | 
			
		||||
 | 
			
		||||
* Thu Jul 14 2016 stephane de Labrusse <stephdl@de-labrusse.fr> 2.6.0-2.sme
 | 
			
		||||
- fix esmith::util::serviceControl to manage systemd service [SME: 9660]
 | 
			
		||||
- Added e-smith-lib-2.6.0.bz9660.serviceControlSystemd.patch
 | 
			
		||||
 | 
			
		||||
* Fri Feb 05 2016 stephane de Labrusse <stephdl@de-labrusse.fr> 2.6.0-1.sme
 | 
			
		||||
- Initial release to sme10
 | 
			
		||||
 | 
			
		||||
* Tue Jan 12 2016 Daniel Berteaud <daniel@firewall-services.com> 2.4.0-16.sme
 | 
			
		||||
- Adjust regex so adjust-service accepts sigusr1 and sigusr2 from files
 | 
			
		||||
  [SME: 9184]
 | 
			
		||||
 | 
			
		||||
* Thu Jun 18 2015 stephane de Labrusse <stephdl@de-labrusse.fr> 2.4.0-15.sme
 | 
			
		||||
- Added a password creation (set_secret) [SME: 8943]
 | 
			
		||||
- code from Charlie Brady <charlieb-contribs-bugzilla@budge.apana.org.au>
 | 
			
		||||
 | 
			
		||||
* Sat Apr 5 2014 Ian Wells <esmith@wellsi.com> 2.4.0-14.sme
 | 
			
		||||
- Untaint the license filename [SME: 8305]
 | 
			
		||||
- Non-functional perl::Critic changes.
 | 
			
		||||
 | 
			
		||||
* Sun Mar 16 2014 Ian Wells <esmith@wellsi.com> 2.4.0-13.sme
 | 
			
		||||
- Add textbox() to console.pm, getLicenseFile to util.pm [SME: 8264]
 | 
			
		||||
 | 
			
		||||
* Sun Feb 2 2014 Ian Wells <esmith@wellsi.com> 2.4.0-12.sme
 | 
			
		||||
- Update frame header and footer [SME: 8183]
 | 
			
		||||
 | 
			
		||||
* Sat Nov 30 2013 Daniel Berteaud <daniel@firewall-services.com> 2.4.0-11.sme
 | 
			
		||||
- Remove the "swap interface" feature [SME: 7993]
 | 
			
		||||
 | 
			
		||||
* Sat Nov 30 2013 Daniel Berteaud <daniel@firewall-services.com> 2.4.0-10.sme
 | 
			
		||||
- Return nic names in probeAdapters so we can drop HWAddress [SME: 7991]
 | 
			
		||||
 | 
			
		||||
* Sat May 25 2013 Ian Wells <esmith@wellsi.com> 2.4.0-9.sme
 | 
			
		||||
- Correctly display accented letters in the console [SME: 7591]
 | 
			
		||||
  by Filippo Carletti 
 | 
			
		||||
 | 
			
		||||
* Sun May 05 2013 Ian Wells <esmith@wellsi.com> 2.4.0-8.sme
 | 
			
		||||
- Add e-smith as a Requires(pre) and remove adding users in %pre
 | 
			
		||||
- Fix uid and gid to be the same in create-system-user [SME: 7547]
 | 
			
		||||
 | 
			
		||||
* Sat Mar 9 2013 Shad L. Lords <slords@mail.com> 2.4.0-7.sme
 | 
			
		||||
- Ensure group www exists before user [SME: 7319]
 | 
			
		||||
 | 
			
		||||
* Wed Mar 6 2013 Shad L. Lords <slords@mail.com> 2.4.0-6.sme
 | 
			
		||||
- Fix pre script to make www and apache the same [SME: 7319]
 | 
			
		||||
 | 
			
		||||
* Tue Mar 5 2013 Daniel Berteaud <daniel@firewall-services.com> 2.4.0-5.sme
 | 
			
		||||
- Untaint variable in probeAdapters() [SME: 7416]
 | 
			
		||||
 | 
			
		||||
* Thu Feb 28 2013 Ian Wells <esmith@wellsi.com> 2.4.0-4.sme
 | 
			
		||||
- Improve error checking in isValidIP [SME: 7410]
 | 
			
		||||
 | 
			
		||||
* Sun Feb 24 2013 Daniel Berteaud <daniel@firewall-services.com> 2.4.0-3.sme
 | 
			
		||||
- Fix MAC detection for bond slaves [SME: 3596]
 | 
			
		||||
 | 
			
		||||
* Thu Jan 31 2013 Daniel Berteaud <daniel@firewall-services.com> 2.4.0-2.sme
 | 
			
		||||
- Stop using kudzu for NIC detection [SME: 3596]
 | 
			
		||||
 | 
			
		||||
* Fri Jan 25 2013 Shad L. Lords <slords@mail.com> 2.4.0-1.sme
 | 
			
		||||
- Bump version in prep for SME9
 | 
			
		||||
- Perl module rpms moved to /usr/share/perl5/vendor_perl [SME: 7223]
 | 
			
		||||
 | 
			
		||||
* Mon Oct 11 2010 Shad L. Lords <slords@mail.com> 2.2.0-7.sme
 | 
			
		||||
- Serialize configure_peers to prevent errors [SME: 5831]
 | 
			
		||||
 | 
			
		||||
* Fri Feb 5 2010 Stephen Noble <support@dungog.net> 2.2.0-6.sme
 | 
			
		||||
- adds the hwaddr parameter to probeAdapters() [SME: 4528]
 | 
			
		||||
 | 
			
		||||
* Thu Feb 4 2010 Shad L. Lords <slords@mail.com> 2.2.0-5.sme
 | 
			
		||||
- Update path for 64-bit compatibility [SME: 5756]
 | 
			
		||||
 | 
			
		||||
* Tue Dec 22 2009 Filippo Carletti <filippo.carletti@gmail.com> 2.2.0-4.sme
 | 
			
		||||
- Really apply previous patch in the spec file. [SME: 5659]
 | 
			
		||||
 | 
			
		||||
* Wed Dec  9 2009 Charlie Brady <charlieb@budge.apana.org.au> 2.2.0-3.sme
 | 
			
		||||
- Add patch (Federico Simoncelli) to prevent re-use of uids. [SME: 5659]
 | 
			
		||||
 | 
			
		||||
* Mon Oct 13 2008 Shad L. Lords <slords@mail.com> 2.2.0-2.sme
 | 
			
		||||
- Add patch to support multiple samba roles [SME: 4172]
 | 
			
		||||
 | 
			
		||||
* Tue Oct 7 2008 Shad L. Lords <slords@mail.com> 2.2.0-1.sme
 | 
			
		||||
- Roll new stream to separate sme7/sme8 trees [SME: 4633]
 | 
			
		||||
 | 
			
		||||
* Wed Aug 20 2008 Shad L. Lords <slords@mail.com> 1.19.0-1
 | 
			
		||||
- Roll new dev stream.
 | 
			
		||||
 | 
			
		||||
* Sat Aug 9 2008 Shad L. Lords <slords@mail.com> 1.18.0-28
 | 
			
		||||
- Read /dev/urandmon instead of /dev/random [SME: 4492]
 | 
			
		||||
 | 
			
		||||
* Sat Aug 9 2008 Shad L. Lords <slords@mail.com> 1.18.0-27
 | 
			
		||||
- Make dialog not use STDERR for return values [SME: 3663]
 | 
			
		||||
- Remove requires for whiptail.  No longer needed [SME: 4491]
 | 
			
		||||
 | 
			
		||||
* Thu Jul 31 2008 Shad L. Lords <slords@mail.com> 1.18.0-26
 | 
			
		||||
- Make binmode properties of db class [SME: 4317]
 | 
			
		||||
- Add new navigation db & utf8 classes [SME: 4317]
 | 
			
		||||
 | 
			
		||||
* Wed Apr 2 2008 Shad L. Lords <slords@mail.com> 1.18.0-25
 | 
			
		||||
- Add .utf8 to locale unless server-console [SME: 4162]
 | 
			
		||||
- Add new languages to langtag2locale [SME: 4163]
 | 
			
		||||
 | 
			
		||||
* Sun Mar 30 2008 Shad L. Lords <slords@mail.com> 1.18.0-24
 | 
			
		||||
- Gracefully handle encoding errors in navigation dbs [SME: 4147]
 | 
			
		||||
 | 
			
		||||
* Wed Mar 26 2008 Shad L. Lords <slords@mail.com> 1.18.0-23
 | 
			
		||||
- Make PAM conv routine not look for english strings [SME: 4117]
 | 
			
		||||
 | 
			
		||||
* Tue Mar 25 2008 Shad L. Lords <slords@mail.com> 1.18.0-22
 | 
			
		||||
- Fix wide output to syslog and allow navigations db to be utf8 [SME: 4101]
 | 
			
		||||
 | 
			
		||||
* Mon Mar 10 2008 Shad L. Lords <slords@mail.com> 1.18.0-21
 | 
			
		||||
- Output navigation in UTF-8 [SME: 3858]
 | 
			
		||||
 | 
			
		||||
* Sun Jan 20 2008 Gavin Weight <gweight@gmail.com> 1.18.0-20
 | 
			
		||||
- Call smbpasswd -e - to reset user correctly. [SME: 3755]
 | 
			
		||||
 | 
			
		||||
* Tue Jan 08 2008 Stephen Noble <support@dungog.net> 1.18.0-19
 | 
			
		||||
- modify validate password strong match for console [SME: 2173]
 | 
			
		||||
 | 
			
		||||
* Thu Nov 01 2007 Gavin Weight <gweight@gmail.com> 1.18.0-18
 | 
			
		||||
- Fix I18N.pm file descriptor leak. [SME: 3509]
 | 
			
		||||
 | 
			
		||||
* Wed Oct 31 2007 Charlie Brady <charlie_brady@mitel.com> 1.18.0-17
 | 
			
		||||
- Remove undocumented and unused template metadata handling from
 | 
			
		||||
  generic_template_expand action (Take II). [SME: 2798]
 | 
			
		||||
 | 
			
		||||
* Fri Jun 1 2007 Shad L. Lords <slords@mail.com> 1.18.0-16
 | 
			
		||||
- pam_unix requires passwords >= 6 [SME: 3039]
 | 
			
		||||
 | 
			
		||||
* Mon May 21 2007 Shad L. Lords <slords@mail.com> 1.18.0-15
 | 
			
		||||
- Fix ip addr shift to work on 64-bit
 | 
			
		||||
 | 
			
		||||
* Sun Apr 29 2007 Shad L. Lords <slords@mail.com>
 | 
			
		||||
- Clean up spec so package can be built by koji/plague
 | 
			
		||||
 | 
			
		||||
* Thu Apr 05 2007 Shad L. Lords <slords@mail.com> 1.18.0-14
 | 
			
		||||
- Reverse changes for 1.18.0-12 as it is being used. [SME: 2838]
 | 
			
		||||
 | 
			
		||||
* Wed Apr 04 2007 Charlie Brady <charlie_brady@mitel.com> 1.18.0-13
 | 
			
		||||
- Allow gauge console widget to be used without following message_page.
 | 
			
		||||
  [SME: 2832].
 | 
			
		||||
 | 
			
		||||
* Mon Mar 26 2007 Charlie Brady <charlie_brady@mitel.com> 1.18.0-12
 | 
			
		||||
- Remove undocumented and unused template metadata handling from
 | 
			
		||||
  generic_template_expand action. [SME: 2798]
 | 
			
		||||
 | 
			
		||||
* Mon Mar 26 2007 Charlie Brady <charlie_brady@mitel.com> 1.18.0-11
 | 
			
		||||
- Split logfile rotation code out of generic_template_expand.
 | 
			
		||||
  Code moved to a new action in e-smith-base. [SME: 2795]
 | 
			
		||||
 | 
			
		||||
* Mon Mar 19 2007 Charlie Brady <charlie_brady@mitel.com> 1.18.0-10
 | 
			
		||||
  Don't try to read template.metadata from subdirectories (affects 
 | 
			
		||||
  initialize_database_defaults). [SME: 2690]
 | 
			
		||||
 | 
			
		||||
* Fri Mar 16 2007 Charlie Brady <charlie_brady@mitel.com> 1.18.0-9
 | 
			
		||||
- Allow template.metadata to be provided via a directory of
 | 
			
		||||
  small files. [SME: 2690]
 | 
			
		||||
- Add support for a DELETE boolean template.metadata item. [SME: 2691]
 | 
			
		||||
 | 
			
		||||
* Wed Feb 28 2007 Charlie Brady <charlie_brady@mitel.com> 1.18.0-8
 | 
			
		||||
- Add gauge widget to esmith::console. [SME: 2579]
 | 
			
		||||
 | 
			
		||||
* Sun Feb 25 2007 Charlie Brady <charlie_brady@mitel.com> 1.18.0-7
 | 
			
		||||
- Default infobox height to 8 rows, and allow override via params.
 | 
			
		||||
  [SME: 2560]
 | 
			
		||||
 | 
			
		||||
* Fri Feb 23 2007 Shad L. Lords <slords@mail.com> 1.18.0-6
 | 
			
		||||
- Really fix clear parameter for inputbox dialog screen [SME: 2533]
 | 
			
		||||
 | 
			
		||||
* Fri Feb 23 2007 Shad L. Lords <slords@mail.com> 1.18.0-5
 | 
			
		||||
- Fix clear parameter for dialog screens [SME: 2533]
 | 
			
		||||
 | 
			
		||||
* Thu Feb 22 2007 Charlie Brady <charlie_brady@mitel.com> 1.18.0-4
 | 
			
		||||
- switch esmith::console::password_page() to use dialog rather than
 | 
			
		||||
  whiptail. [SME: 2534]
 | 
			
		||||
 | 
			
		||||
* Thu Feb 22 2007 Charlie Brady <charlie_brady@mitel.com> 1.18.0-3
 | 
			
		||||
- Add infobox widget. [SME: 2533]
 | 
			
		||||
 | 
			
		||||
* Sun Jan 28 2007 Shad L. Lords <slords@mail.com> 1.18.0-2
 | 
			
		||||
- Fix backtitle spacing for new dialog menus [SME: 2328]
 | 
			
		||||
 | 
			
		||||
* Fri Jan 26 2007 Shad L. Lords <slords@mail.com> 1.18.0-1
 | 
			
		||||
- Roll stable stream. [SME: 2328]
 | 
			
		||||
 | 
			
		||||
* Fri Dec 15 2006 Federico Simoncelli <federico.simoncelli@gmail.com> 1.17.0-8
 | 
			
		||||
  Tue Dec 15 2006 --> Tue Dec 12 2006 or Fri Dec 15 2006 or Tue Dec 19 2006 or ....
 | 
			
		||||
- Added the validatePassword function to esmith::util. [SME: 2100]
 | 
			
		||||
 | 
			
		||||
* Thu Dec 07 2006 Shad L. Lords <slords@mail.com>
 | 
			
		||||
- Update to new release naming.  No functional changes.
 | 
			
		||||
- Make Packager generic
 | 
			
		||||
 | 
			
		||||
* Fri Nov 24 2006 Gordon Rowell <gordonr@gormand.com.au> 1.17.0-06
 | 
			
		||||
- Allow optional path to peeers directory in 
 | 
			
		||||
  esmith::tcpsvd::configure_peers() [SME: 2086]
 | 
			
		||||
 | 
			
		||||
* Tue Nov 14 2006 Charlie Brady <charlie_brady@mitel.com> 1.17.0-05
 | 
			
		||||
- Allow defaulno option to esmith::console::yesno.
 | 
			
		||||
- Fix I/O redirection in esmith::console::new.
 | 
			
		||||
 | 
			
		||||
* Tue Nov 07 2006 Charlie Brady <charlie_brady@mitel.com> 1.17.0-04
 | 
			
		||||
- Allow display of "0" in iesmith::cgi::genSmallCell. [SME: 2038]
 | 
			
		||||
 | 
			
		||||
* Mon Oct 23 2006 Charlie Brady <charlie_brady@mitel.com> 1.17.0-03
 | 
			
		||||
- Make dialog the default console app, with whiptail used only when
 | 
			
		||||
  required.
 | 
			
		||||
 | 
			
		||||
* Wed Oct 11 2006 Charlie Brady <charlie_brady@mitel.com> 1.17.0-02
 | 
			
		||||
- Allow 'dialog' to be called from esmith::console. [SME: 1958]
 | 
			
		||||
 | 
			
		||||
* Wed Oct 11 2006 Charlie Brady <charlie_brady@mitel.com> 1.17.0-01
 | 
			
		||||
- Roll development branch.
 | 
			
		||||
 | 
			
		||||
* Mon Sep 25 2006 Charlie Brady <charlie_brady@mitel.com> 1.16.0-06
 | 
			
		||||
- Fix problem with greedy RE in template.metadata parsing. [SME: 1906]
 | 
			
		||||
 | 
			
		||||
* Fri Sep 08 2006 Charlie Brady <charlie_brady@mitel.com> 1.16.0-05
 | 
			
		||||
- Fix taint problem in template.metadata handling. [SME: 1906]
 | 
			
		||||
 | 
			
		||||
* Thu Apr 13 2006 Charlie Brady <charlie_brady@mitel.com> 1.16.0-04
 | 
			
		||||
- Use "kudzu --probe --class network" for NIC detection. [SME: 727]
 | 
			
		||||
 | 
			
		||||
* Fri Apr 7 2006 Gordon Rowell <gordonr@gormand.com.au> 1.16.0-03
 | 
			
		||||
- Don't call smbpasswd -e - setting the password is sufficient [SME: 1193]
 | 
			
		||||
 | 
			
		||||
* Tue Mar 28 2006 Gordon Rowell <gordonr@gormand.com.au> 1.16.0-02
 | 
			
		||||
- Log previous contents of db entry in DELETE log [SME: 1066]
 | 
			
		||||
 | 
			
		||||
* Tue Mar 14 2006 Charlie Brady <charlie_brady@mitel.com> 1.16.0-01
 | 
			
		||||
- Roll to stable stream version number. [SME: 1016]
 | 
			
		||||
 | 
			
		||||
* Fri Mar 10 2006 Charlie Brady <charlie_brady@mitel.com> 1.15.4-02
 | 
			
		||||
- Suppress warning from genSmallCell if text is undefined. [SME: 986]
 | 
			
		||||
 | 
			
		||||
* Fri Feb 17 2006 Gordon Rowell <gordonr@gormand.com.au> 1.15.4-01
 | 
			
		||||
- Roll patches up to 1.15.3-42
 | 
			
		||||
- Trim changelog prior to 1.15.0-01 [SME: 828]
 | 
			
		||||
 | 
			
		||||
* Thu Feb 16 2006 Gordon Rowell <gordonr@gormand.com.au> 1.15.3-42
 | 
			
		||||
- Adjust console title bar to 'SME Server' [SME: 726]
 | 
			
		||||
 | 
			
		||||
* Tue Feb 14 2006 Gordon Rowell <gordonr@gormand.com.au> 1.15.3-41
 | 
			
		||||
- Reworded text for template-begin and change URL to /development/
 | 
			
		||||
  rather than /custom/ [SME: 773]
 | 
			
		||||
 | 
			
		||||
* Mon Feb 13 2006 Charlie Brady <charlie_brady@mitel.com> 1.15.3-40
 | 
			
		||||
- Update URL in default template-begin fragment. [SME: 773]
 | 
			
		||||
 | 
			
		||||
* Sat Feb 11 2006 Charlie Brady <charlieb@e-smith.com> 1.15.3-39
 | 
			
		||||
- Remove obsolete e-smith-lib-Tai64n package. [SME: 689]
 | 
			
		||||
 | 
			
		||||
* Sat Feb 11 2006 Charlie Brady <charlieb@e-smith.com> 1.15.3-38
 | 
			
		||||
- [Null changelog for missing version - we accidentally skipped
 | 
			
		||||
   this version.]
 | 
			
		||||
 | 
			
		||||
* Sat Feb 11 2006 Charlie Brady <charlieb@e-smith.com> 1.15.3-37
 | 
			
		||||
- Fix get_all_by_prop in scalar context. [SME: 669,721]
 | 
			
		||||
 | 
			
		||||
* Mon Feb  6 2006 Shad L. Lords <slords@mail.com> 1.15.3-37
 | 
			
		||||
- Add ability to pass many props to get_all_by_prop [SME: 669]
 | 
			
		||||
 | 
			
		||||
* Mon Jan 23 2006 Charlie Brady <charlieb@e-smith.com> 1.15.3-36
 | 
			
		||||
- Fix warning during pseudonym deletion. [SME: 491]
 | 
			
		||||
 | 
			
		||||
* Fri Jan 20 2006 Charlie Brady <charlieb@e-smith.com> 1.15.3-35
 | 
			
		||||
- Fix up use of Sys::Syslog::syslog. [SME: 526]
 | 
			
		||||
 | 
			
		||||
* Thu Jan 19 2006 Charlie Brady <charlieb@e-smith.com> 1.15.3-34
 | 
			
		||||
- Remove running of kudzu during NIC probing. TODO: Find a solution
 | 
			
		||||
  to system reconfiguration when new hardware is added. [SME: 192]
 | 
			
		||||
 | 
			
		||||
* Tue Jan 10 2006 Charlie Brady <charlieb@e-smith.com> 1.15.3-33
 | 
			
		||||
- Fold a.b.c.d/255.255.255.255 to a.b.c.d in local_access_spec() to
 | 
			
		||||
  work around bugs in applications which don't accept such specs.
 | 
			
		||||
  [SME: 430]
 | 
			
		||||
 | 
			
		||||
* Mon Jan 9 2006 Gordon Rowell <gordonr@gormand.com.au> 1.15.3-32
 | 
			
		||||
- Check whether an accounts db record exists before trying to create
 | 
			
		||||
  the dot and underscore pseudonyms (new_record will fail silently)
 | 
			
		||||
  and check that the records are pseudonyms before deleting them [SME: 24]
 | 
			
		||||
 | 
			
		||||
* Mon Jan 9 2006 Gordon Rowell <gordonr@gormand.com.au> 1.15.3-31
 | 
			
		||||
- And update POD for last change [SME: 24]
 | 
			
		||||
 | 
			
		||||
* Mon Jan 9 2006 Gordon Rowell <gordonr@gormand.com.au> 1.15.3-30
 | 
			
		||||
- Allow dot and underscore in account names [SME: 24]
 | 
			
		||||
 | 
			
		||||
* Tue Dec 27 2005 Gordon Rowell <gordonr@gormand.com.au> 1.15.3-29
 | 
			
		||||
- Remove newlines from cluck() string and just note that the old
 | 
			
		||||
  path was used [SME: 365]
 | 
			
		||||
 | 
			
		||||
* Sun Dec 25 2005 Gordon Rowell <gordonr@gormand.com.au> 1.15.3-28
 | 
			
		||||
  Sat Dec 25 2005 --> Sat Dec 24 2005 or Sun Dec 25 2005 or Sat Dec 31 2005 or ....
 | 
			
		||||
- If db exists in both the old and new locations in 
 | 
			
		||||
  initialize_default_databases, rename the one in the new 
 | 
			
		||||
  location to db.time(), avoiding the conflict and saving the 
 | 
			
		||||
  evidence in case it is needed later [SME: 229]
 | 
			
		||||
 | 
			
		||||
* Mon Dec 05 2005 Mark Knox <mark_knox@mitel.com>
 | 
			
		||||
- [1.15.3-27]
 | 
			
		||||
- Moved queueing logic to separate daemon, replaced with FIFO IPC [BZ252
 | 
			
		||||
 | 
			
		||||
* Thu Dec 01 2005 Mark Knox <mark_knox@mitel.com>
 | 
			
		||||
- [1.15.3-26]
 | 
			
		||||
- Added event queueing (open source portion) for clustered systems [BZ250]
 | 
			
		||||
 | 
			
		||||
* Wed Nov 30 2005 Gordon Rowell <gordonr@gormand.com.au> 1.15.3-25
 | 
			
		||||
- Bump release number only
 | 
			
		||||
 | 
			
		||||
* Thu Nov 24 2005 Gordon Rowell <gordonr@e-smith.com>
 | 
			
		||||
- [1.15.3-24]
 | 
			
		||||
- Add missing 'use Locale::gettext' to esmith::console.pm [MN00108804]
 | 
			
		||||
 | 
			
		||||
* Sun Nov 20 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-23]
 | 
			
		||||
- Clarify logic for stopped services in adjust-services. [SF: 1357629]
 | 
			
		||||
 | 
			
		||||
* Sun Nov 20 2005 Gordon Rowell <gordonr@e-smith.com>
 | 
			
		||||
- [1.15.3-22]
 | 
			
		||||
- Correct adjust-services logic for stopped services [SF: 1357629]
 | 
			
		||||
 | 
			
		||||
* Wed Nov 16 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-21]
 | 
			
		||||
- Allow services2adjust directories to contain files rather than just dangling
 | 
			
		||||
  symlinks. Files can contain more than one actions to perform. [SF: 1270644]
 | 
			
		||||
 | 
			
		||||
* Wed Nov 16 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-20]
 | 
			
		||||
- Also don't start services if we just want to "once" them. [SF: 1357629]
 | 
			
		||||
 | 
			
		||||
* Wed Nov 16 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-19]
 | 
			
		||||
- Fix restart of enabled supervised services which we are attempting to stop.
 | 
			
		||||
  [SF: 1357629]
 | 
			
		||||
 | 
			
		||||
* Tue Nov 15 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-18]
 | 
			
		||||
- Set default for $type in esmith::cgi::genSmallCell, to prevent some log
 | 
			
		||||
  noise. [SF: 1357830]
 | 
			
		||||
 | 
			
		||||
* Tue Nov 15 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-17]
 | 
			
		||||
- Pass $EVENT to template expansions in generic_template_expand.
 | 
			
		||||
  [SF: MN00106104]
 | 
			
		||||
 | 
			
		||||
* Tue Nov 15 2005 Gordon Rowell <gordonr@e-smith.com>
 | 
			
		||||
- [1.15.3-16]
 | 
			
		||||
- Redirect esmith::config calls on old db paths to the new
 | 
			
		||||
  location [SF: 1335865]
 | 
			
		||||
 | 
			
		||||
* Thu Oct 27 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-15]
 | 
			
		||||
- Fix a few minor spec file portability issues. [SF: 1339729]
 | 
			
		||||
 | 
			
		||||
* Wed Oct 26 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-14]
 | 
			
		||||
- Add it and de to the langtag2locale fixups. [SF: 1338236]
 | 
			
		||||
 | 
			
		||||
* Tue Oct 11 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-13]
 | 
			
		||||
- Build driver list from .ko files as well as .o files. Untaint driver
 | 
			
		||||
  names while building list. [SF: 1323270]
 | 
			
		||||
 | 
			
		||||
* Mon Sep 26 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-12]
 | 
			
		||||
- Fix "defaults" handling so that values which evaluate to false are
 | 
			
		||||
  not overridden by default. [SF: 1303885]
 | 
			
		||||
 | 
			
		||||
* Fri Sep 23 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-11]
 | 
			
		||||
- Untaint db names before attempting to move them. [MN00098405]
 | 
			
		||||
 | 
			
		||||
* Thu Sep 22 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-10]
 | 
			
		||||
- Provide networks method in esmith::NetworksDB. [SF: 1296099]
 | 
			
		||||
- Support a "localhost" configuration in esmith::tcpsvd:configure_peers
 | 
			
		||||
  [SF: 1294719]
 | 
			
		||||
 | 
			
		||||
* Tue Sep 20 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-09]
 | 
			
		||||
- Remove deprecated functions from esmith::utils. [SF: 1295851]
 | 
			
		||||
- Include only "network" records in local_access_spec. [SF: 1296099]
 | 
			
		||||
 | 
			
		||||
* Mon Sep 12 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-08]
 | 
			
		||||
- Remove warning about explicit path in esmith::db::_db_path.
 | 
			
		||||
  [SF: 1286294]
 | 
			
		||||
 | 
			
		||||
* Fri Sep  9 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-07]
 | 
			
		||||
- Tolerate, but warn about, symlinks in /home/e-smith. [SF: 1216546]
 | 
			
		||||
 | 
			
		||||
* Fri Sep  9 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-06]
 | 
			
		||||
- Reduce the noise from _file_path() in esmith::DB::db. [SF: 1286294]
 | 
			
		||||
 | 
			
		||||
* Wed Sep  7 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-05]
 | 
			
		||||
- Fix operation of expandTemplate when taint check is enabled.
 | 
			
		||||
  [SF: 1284301]
 | 
			
		||||
 | 
			
		||||
* Wed Aug 17 2005 Mark Knox <markk@e-smith.com>
 | 
			
		||||
- [1.15.3-04]
 | 
			
		||||
- Added open_local and open_ro_local methods for clustering [markk MN00094831]
 | 
			
		||||
 | 
			
		||||
* Tue Aug 16 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-03]
 | 
			
		||||
- Fix POD error in util.pm.
 | 
			
		||||
 | 
			
		||||
* Wed Jul 27 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-02]
 | 
			
		||||
- Move databases default location from /home/e-smith to /home/e-smith/db.
 | 
			
		||||
  During esmith::utils::initialize_default_databases, move from old to new
 | 
			
		||||
  location before doing db migrate actions. [SF: 1216546]
 | 
			
		||||
 | 
			
		||||
* Wed Jul 27 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.3-01]
 | 
			
		||||
- Roll a new development stream - 1.15.3
 | 
			
		||||
 | 
			
		||||
* Wed Jul 27 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.2-04]
 | 
			
		||||
- Remove broken MergeDB stuff. [SF: 1246315]
 | 
			
		||||
 | 
			
		||||
* Wed Jul 27 2005 Mark Knox <markk@e-smith.com>
 | 
			
		||||
- [1.15.2-03]
 | 
			
		||||
- Fixed misleading comment in util.pm
 | 
			
		||||
- Added 'use' statements in Record classes for SOAP compatibility
 | 
			
		||||
- Fixed undefined max_len warning
 | 
			
		||||
- Added explicit writeconf calls in db::Record.pm, needed for setting props
 | 
			
		||||
  via SOAP
 | 
			
		||||
 | 
			
		||||
* Tue Jul 19 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.2-02]
 | 
			
		||||
- Allow db open API to use default path if a simple filename
 | 
			
		||||
  is provided as arg. This is preparation for move of dbs to
 | 
			
		||||
  /home/e-smith/db. Patch by Shad Lords.
 | 
			
		||||
 | 
			
		||||
* Mon Jul 18 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.2-01]
 | 
			
		||||
- Roll new development stream - 1.15.2
 | 
			
		||||
 | 
			
		||||
* Fri Jul 15 2005 Mark Knox <markk@e-smith.com>
 | 
			
		||||
- [1.15.1-44]
 | 
			
		||||
- Tweak to allow calling _writeconf from SOAP [markk MN00090738]
 | 
			
		||||
 | 
			
		||||
* Tue Jun 21 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-43]
 | 
			
		||||
- Ensure that esmith::util::LdapPassword returns bare string without
 | 
			
		||||
  newline terminator.
 | 
			
		||||
 | 
			
		||||
* Sun Jun 12 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-42]
 | 
			
		||||
- Remove .rpmsave and .rpmnew symlinks (as well as files). [SF: 1217969]
 | 
			
		||||
- Handle missing description in pcitables entries.
 | 
			
		||||
 | 
			
		||||
* Sun Jun 12 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-41]
 | 
			
		||||
- Provide feedback (via log messages) from services2adjust. [SF: 1218920]
 | 
			
		||||
 | 
			
		||||
* Mon May 30 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-40]
 | 
			
		||||
- Add preinstall scripting to create required accounts/groups if they
 | 
			
		||||
  don't already exist. [SF: 1210723]
 | 
			
		||||
 | 
			
		||||
* Thu May  5 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-39]
 | 
			
		||||
- Show Text::Template error text rather than inappropriate $! if template
 | 
			
		||||
  expansion fails.
 | 
			
		||||
- Change error to warning if a config item is set with an empty "type"
 | 
			
		||||
  property.
 | 
			
		||||
 | 
			
		||||
* Thu May  5 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-38]
 | 
			
		||||
- Fix esmith::DB::get_prop_and_delete fail if prop is "false" [From Gordon].
 | 
			
		||||
 | 
			
		||||
* Tue May  3 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-37]
 | 
			
		||||
- Update directory list so that ethernet drivers from kernel-unsupported are
 | 
			
		||||
  added to "choose by driver" list.
 | 
			
		||||
 | 
			
		||||
* Sat Mar 19 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-36]
 | 
			
		||||
- Rework esmith::tcpsvd::configure_peers so that it doesn't chdir.
 | 
			
		||||
- Fix generic_template_expand so that templates.metadata doesn't
 | 
			
		||||
  need to set OUTPUT_FILENAME is TEMPLATE_PATH is changed. This
 | 
			
		||||
  matches what expand-template already does.
 | 
			
		||||
 | 
			
		||||
* Fri Mar 18 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-35]
 | 
			
		||||
- Change numerous calls to "croak" in esmith::template
 | 
			
		||||
  to "carp ...; return", so that problem with any single
 | 
			
		||||
  template expansion doesn't terminate calling program.
 | 
			
		||||
  [MN00075009]
 | 
			
		||||
 | 
			
		||||
* Wed Mar 16 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-34]
 | 
			
		||||
- Add missing "use esmith::util" in esmith::tcpsvd.
 | 
			
		||||
 | 
			
		||||
* Wed Mar 16 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-33]
 | 
			
		||||
- Add esmith::tcpsvd library for managing tcpsvd "peers"
 | 
			
		||||
  directories.
 | 
			
		||||
 | 
			
		||||
* Mon Mar 14 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-32]
 | 
			
		||||
- Make template expansion message more succinct.
 | 
			
		||||
 | 
			
		||||
* Thu Mar 10 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-31]
 | 
			
		||||
- Remove pseudonyms of pseudonyms when removing user
 | 
			
		||||
  accounts. Adapted from patch submitted by Shad. [MN00039941]
 | 
			
		||||
 | 
			
		||||
* Wed Feb 23 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-30]
 | 
			
		||||
- Fix incompatibility with CentOS's CGI.pm. 
 | 
			
		||||
 | 
			
		||||
* Tue Feb 22 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-29]
 | 
			
		||||
- Fix bug in output to empty file when FILTER is used
 | 
			
		||||
  during template expansion. [charlieb MN00050075]
 | 
			
		||||
 | 
			
		||||
* Tue Feb 22 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-28]
 | 
			
		||||
- Refresh contents of /etc/sysconfig/hwconf before listing
 | 
			
		||||
  network adaptors [MN00069993]
 | 
			
		||||
- Fix typo in documentation of esmith::DB::db - reported from Tanna -
 | 
			
		||||
  http://www.livejournal.com/users/gcrumb/61169.html (thanks Dan!)
 | 
			
		||||
 | 
			
		||||
* Wed Feb 16 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-27]
 | 
			
		||||
- Fix typo. [MN00066059]
 | 
			
		||||
 | 
			
		||||
* Wed Feb 16 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-26]
 | 
			
		||||
- Use /sbin/e-smith/whiptail if it is available. [MN00066059]
 | 
			
		||||
 | 
			
		||||
* Mon Feb  7 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-25]
 | 
			
		||||
- Update perms and ownership when expanding templates, regardless of
 | 
			
		||||
  whether file content has changed or not. [MN00068043]
 | 
			
		||||
 | 
			
		||||
* Wed Feb  2 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-24]
 | 
			
		||||
- Fix the insertion of implicit actions into sorted action list in
 | 
			
		||||
  event.pm. Problem was perl syntax ambiguity.  [MN00066406]
 | 
			
		||||
 | 
			
		||||
* Fri Jan 28 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-23]
 | 
			
		||||
- Really move /home/e-smith/* to e-smith-base. [MN00066635]
 | 
			
		||||
 | 
			
		||||
* Fri Jan 28 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-22]
 | 
			
		||||
- Move /home/e-smith/* to e-smith-base. [MN00066635]
 | 
			
		||||
- Move generic-template expand to S05 position in sort, and
 | 
			
		||||
  adjust-service to S90. Fix run-time error. [MN00066406]
 | 
			
		||||
- Don't attempt to execute non-executable action scripts.
 | 
			
		||||
 | 
			
		||||
* Thu Jan 27 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-21]
 | 
			
		||||
- Implicitly include template expand and services adjust actions
 | 
			
		||||
  in each event if the respective metadata directory exists.
 | 
			
		||||
  [MN00066406]
 | 
			
		||||
 | 
			
		||||
* Tue Jan 25 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-20]
 | 
			
		||||
- Add "adjust" to list of verbs which serviceControl groks,
 | 
			
		||||
  to allow for "masq adjust". [MN00065576]
 | 
			
		||||
 | 
			
		||||
* Tue Jan 25 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-19]
 | 
			
		||||
- Add adjust-services generic action script [MN00065576]
 | 
			
		||||
 | 
			
		||||
* Tue Jan 18 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-18]
 | 
			
		||||
- Fix typo. [MN00064412]
 | 
			
		||||
- Improve die() message in esmith::config::STORE. [MN00064394]
 | 
			
		||||
 | 
			
		||||
* Mon Jan 17 2005 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-17]
 | 
			
		||||
- Fix broken logging (and reduce logging) in initialize_default_databases.
 | 
			
		||||
  [MN00064412]
 | 
			
		||||
- Fix inappropriate use of global $_ in initialize_default_databases.
 | 
			
		||||
  [MN00064415]
 | 
			
		||||
 | 
			
		||||
* Thu Dec 23 2004 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-16]
 | 
			
		||||
- Read templated file metadata (if any) from file tree under 
 | 
			
		||||
  /etc/e-smith/templates.metadata. Update expand-template to
 | 
			
		||||
  use current API. [MN00061830]
 | 
			
		||||
 | 
			
		||||
* Tue Dec 14 2004 Mark Knox <markk@e-smith.com>
 | 
			
		||||
- [1.15.1-15]
 | 
			
		||||
- Change copyright date to 2004 [markk MN00060958]
 | 
			
		||||
 | 
			
		||||
* Fri Nov  5 2004 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-14]
 | 
			
		||||
- Fix Authen::PAM dependency header [charlieb MN00040240]
 | 
			
		||||
- Use kudzu's generated /etc/sysconfig/hwconf file for NIC detection
 | 
			
		||||
  [charlieb MN00056220]
 | 
			
		||||
 | 
			
		||||
* Thu Oct 14 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.1-13]
 | 
			
		||||
- Updated esmith::ethernet's search code to remove File::Find, as it doesn't
 | 
			
		||||
  get along with taint checking. [msoulier MN00052510]
 | 
			
		||||
 | 
			
		||||
* Wed Oct 13 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.1-12]
 | 
			
		||||
- Updated esmith::ethernet's search code such that is it more adaptable, and
 | 
			
		||||
  recurses the directories given. [msoulier MN00052510]
 | 
			
		||||
 | 
			
		||||
* Wed Oct 13 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.1-11]
 | 
			
		||||
- Updated esmith::ethernet's search paths for network drivers.
 | 
			
		||||
  [msoulier MN00052510]
 | 
			
		||||
 | 
			
		||||
* Mon Oct  4 2004 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-10]
 | 
			
		||||
- Remove dependency on perl(Filter::Handle) [charlieb MN00050075]
 | 
			
		||||
 | 
			
		||||
* Fri Sep 24 2004 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.1-09]
 | 
			
		||||
- Updated requires with new perl dependencies. [msoulier MN00040240]
 | 
			
		||||
- Remove "AutoReqProv: no" so that "Provides" headers are auto-generated.
 | 
			
		||||
  [charlieb MN00040240]
 | 
			
		||||
- Remove anachronistic "require v5.6.0" directives. [charlieb MN00050370]
 | 
			
		||||
- Avoid use of Filter::Handle in esmith::template. [charlieb MN00050075]
 | 
			
		||||
 | 
			
		||||
* Fri Aug 27 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.1-08]
 | 
			
		||||
- Added esmith::util::network::isValidEmail function. [msoulier MN00023814]
 | 
			
		||||
 | 
			
		||||
* Thu Aug 26 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.1-07]
 | 
			
		||||
- Added svdisable to permissible actions in serviceControl.
 | 
			
		||||
  [msoulier MN00043056]
 | 
			
		||||
 | 
			
		||||
* Tue Aug 10 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.1-06]
 | 
			
		||||
- Fixed new methods. Bad else case. [msoulier MN00044891]
 | 
			
		||||
 | 
			
		||||
* Fri Aug  6 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.1-05]
 | 
			
		||||
- Added a keys() method. [msoulier MN00041968]
 | 
			
		||||
 | 
			
		||||
* Fri Aug  6 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.1-04]
 | 
			
		||||
- Added set_prop and set_value methods in esmith::DB. [msoulier MN00044891]
 | 
			
		||||
 | 
			
		||||
* Tue Jul 20 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.1-03]
 | 
			
		||||
- Undeprecated esmith::util::serviceControl. [msoulier MN00043056]
 | 
			
		||||
 | 
			
		||||
* Fri Jun 25 2004 Tony Clayton <apc@e-smith.com>
 | 
			
		||||
- [1.15.1-02]
 | 
			
		||||
- Merge language_tag2locale() function from perl-I18N-LangTags [tonyc
 | 
			
		||||
  MN00040170]
 | 
			
		||||
 | 
			
		||||
* Fri May 28 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.1-01]
 | 
			
		||||
- Rolling to collect patches.
 | 
			
		||||
 | 
			
		||||
* Fri May 28 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-23]
 | 
			
		||||
- Reordered the create code slightly to catch more errors.
 | 
			
		||||
  [msoulier MN00035059]
 | 
			
		||||
 | 
			
		||||
* Fri May 28 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-22]
 | 
			
		||||
- Added yet more error handling and reporting. [msoulier MN00035059]
 | 
			
		||||
 | 
			
		||||
* Fri May 28 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-21]
 | 
			
		||||
- Fixed one $Error reference that I missed in the last rev.
 | 
			
		||||
  [msoulier MN00035059]
 | 
			
		||||
 | 
			
		||||
* Fri May 28 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-20]
 | 
			
		||||
- Moved error handling from esmith::DB::db to esmith::DB, since it should not
 | 
			
		||||
  be database implementation specific. [msoulier MN00035059]
 | 
			
		||||
 | 
			
		||||
* Fri May 28 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-19]
 | 
			
		||||
- Propagated migration failures up to calling code for reporting to syslog.
 | 
			
		||||
- Propagated creation failures up to calling code. 
 | 
			
		||||
- Moved lexicon $Error in esmith::DB::db to a class property so it can be used
 | 
			
		||||
  by subclasses. [msoulier MN00035059]
 | 
			
		||||
 | 
			
		||||
* Thu May 27 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-18]
 | 
			
		||||
- Changed print statements to calls to the logger. [msoulier MN00035059]
 | 
			
		||||
 | 
			
		||||
* Thu May 27 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-17]
 | 
			
		||||
- Added print statements to initialize-default-databases for post-install
 | 
			
		||||
  debugging. [msoulier MN00035059]
 | 
			
		||||
 | 
			
		||||
* Fri May  7 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-16]
 | 
			
		||||
- Fixed migrate to report the caught error message. [msoulier MN00032503]
 | 
			
		||||
 | 
			
		||||
* Thu May  6 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-15]
 | 
			
		||||
- Added isValidHostname function to esmith::util::network.
 | 
			
		||||
  [msoulier MN00024212]
 | 
			
		||||
 | 
			
		||||
* Fri Feb 13 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-14]
 | 
			
		||||
- Greatly simplified the _mysystem function by ripping out open3.
 | 
			
		||||
  [msoulier dpar-20385]
 | 
			
		||||
 | 
			
		||||
* Fri Feb 13 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-13]
 | 
			
		||||
- Backed-out change in esmith::util, as it's non-trivial there with the exec.
 | 
			
		||||
  Completed update of esmith::event, and separated the esmith::Logger class.
 | 
			
		||||
  [msoulier dpar-20385]
 | 
			
		||||
 | 
			
		||||
* Fri Feb 13 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-12]
 | 
			
		||||
- Removed use of the logger entirely, replacing it with an abstracted
 | 
			
		||||
  interface to the Sys::Syslog module. [msoulier dpar-20385]
 | 
			
		||||
 | 
			
		||||
* Thu Jan  8 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-11]
 | 
			
		||||
- Fixed esmith::util::network::isValidIP() so valid IP substrings no longer
 | 
			
		||||
  return true values. [msoulier 9308]
 | 
			
		||||
 | 
			
		||||
* Thu Jan  8 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-10]
 | 
			
		||||
- Added a check in STORE in esmith::config for invalid attempts to set a value
 | 
			
		||||
  without a type. Also escalated previous warnings for undef key and value to
 | 
			
		||||
  fatal exceptions. [msoulier 7386]
 | 
			
		||||
 | 
			
		||||
* Thu Jan  8 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-09]
 | 
			
		||||
- Now trimming whitespace around keys and values during esmith::config STORE
 | 
			
		||||
  events, to prevent invalid keys and values from being saved. [msoulier 7021]
 | 
			
		||||
 | 
			
		||||
* Mon Jan  5 2004 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-08]
 | 
			
		||||
- Fixed POD around merge_props. [msoulier 9482]
 | 
			
		||||
 | 
			
		||||
* Fri Nov  7 2003 Tony Clayton <apc@e-smith.com>
 | 
			
		||||
- [1.15.0-07]
 | 
			
		||||
- And again [tonyc 10569]
 | 
			
		||||
 | 
			
		||||
* Fri Nov  7 2003 Tony Clayton <apc@e-smith.com>
 | 
			
		||||
- [1.15.0-06]
 | 
			
		||||
- Change Merge API a bit, fix pod [tonyc 10569]
 | 
			
		||||
 | 
			
		||||
* Fri Nov  7 2003 Tony Clayton <apc@e-smith.com>
 | 
			
		||||
- [1.15.0-05]
 | 
			
		||||
- Add esmith::DB::Merge library [tonyc 10569]
 | 
			
		||||
 | 
			
		||||
* Fri Oct 10 2003 Michael Soulier <msoulier@e-smith.com>
 | 
			
		||||
- [1.15.0-04]
 | 
			
		||||
- Fixed AccountsDB.pm to handle group names with hyphens and periods, to match
 | 
			
		||||
  the error message in the groups panel, and the rest of the group/user
 | 
			
		||||
  behaviour. [msoulier 10236]
 | 
			
		||||
 | 
			
		||||
* Sun Sep 21 2003 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.0-03]
 | 
			
		||||
- Skip any directries when iterating over action scripts in esmith::event.
 | 
			
		||||
  Add logfile timestamp symlinking to generic_template_expand action.
 | 
			
		||||
  Use templates2expand and logfiles2timestamp subdirectories of the event
 | 
			
		||||
  directory. Fix shebang line. [charlieb 10035]
 | 
			
		||||
 | 
			
		||||
* Thu Sep 18 2003 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.0-02]
 | 
			
		||||
- Add generic_template_expand action. [charlieb 10035]
 | 
			
		||||
 | 
			
		||||
* Thu Sep 18 2003 Charlie Brady <charlieb@e-smith.com>
 | 
			
		||||
- [1.15.0-01]
 | 
			
		||||
- Changing version to development stream number - 1.15.0
 | 
			
		||||
 | 
			
		||||
%prep
 | 
			
		||||
%setup
 | 
			
		||||
 | 
			
		||||
%pre
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
%post
 | 
			
		||||
 | 
			
		||||
%build
 | 
			
		||||
for event in post-install post-upgrade bootstrap-console-save console-save
 | 
			
		||||
do
 | 
			
		||||
    mkdir -p root/etc/e-smith/events/$event
 | 
			
		||||
done
 | 
			
		||||
perl createlinks
 | 
			
		||||
find root/ -type f | xargs grep -l ____COPYYEARS____ | xargs sed -i -e 's/____COPYYEARS____/%{copykooz}/g'
 | 
			
		||||
 | 
			
		||||
%install
 | 
			
		||||
rm -rf $RPM_BUILD_ROOT
 | 
			
		||||
(cd root   ; find . -depth -print | cpio -dump $RPM_BUILD_ROOT)
 | 
			
		||||
rm -f %{name}-%{version}-%{release}-filelist
 | 
			
		||||
/sbin/e-smith/genfilelist $RPM_BUILD_ROOT \
 | 
			
		||||
    >%{name}-%{version}-%{release}-filelist
 | 
			
		||||
echo "%doc Copying" >> %{name}-%{version}-%{release}-filelist
 | 
			
		||||
echo "%doc Artistic" >> %{name}-%{version}-%{release}-filelist
 | 
			
		||||
echo "%doc LICENSE" >> %{name}-%{version}-%{release}-filelist
 | 
			
		||||
 | 
			
		||||
%clean
 | 
			
		||||
rm -rf $RPM_BUILD_ROOT
 | 
			
		||||
 | 
			
		||||
%files -f %{name}-%{version}-%{release}-filelist
 | 
			
		||||
%defattr(-,root,root)
 | 
			
		||||
							
								
								
									
										3
									
								
								root/etc/e-smith/db/configuration/migrate/00openRW
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								root/etc/e-smith/db/configuration/migrate/00openRW
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
{
 | 
			
		||||
    $DB = esmith::ConfigDB->open(${DB_FILENAME});
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										146
									
								
								root/etc/e-smith/events/actions/adjust-services
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										146
									
								
								root/etc/e-smith/events/actions/adjust-services
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,146 @@
 | 
			
		||||
#!/usr/bin/perl -w
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# copyright (C) 2005 Mitel Networks Corporation
 | 
			
		||||
# 
 | 
			
		||||
# 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
 | 
			
		||||
# 
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
package esmith;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use Errno;
 | 
			
		||||
use DirHandle;
 | 
			
		||||
 | 
			
		||||
my $event = shift || die "must give event name parameter";
 | 
			
		||||
chdir "/etc/e-smith/events/$event" or die "Couldn't chdir to event directory /etc/e-smith/events/$event: $!";
 | 
			
		||||
my $dh = DirHandle->new("services2adjust");
 | 
			
		||||
 | 
			
		||||
exit(0) unless $dh; # Nothing to do
 | 
			
		||||
 | 
			
		||||
use esmith::ConfigDB;
 | 
			
		||||
use esmith::util;
 | 
			
		||||
 | 
			
		||||
my %param2char = (
 | 
			
		||||
	down => 'd',
 | 
			
		||||
	stop => 'd',
 | 
			
		||||
	up => 'u',
 | 
			
		||||
	start => 'u',
 | 
			
		||||
	restart => 't',
 | 
			
		||||
	sigterm => 't',
 | 
			
		||||
	adjust => 'h',
 | 
			
		||||
	reload => 'h',
 | 
			
		||||
	sighup => 'h',
 | 
			
		||||
	sigusr1 => '1',
 | 
			
		||||
	sigusr2 => '2',
 | 
			
		||||
	once => 'o',
 | 
			
		||||
	pause => 'p',
 | 
			
		||||
	alarm => 'a',
 | 
			
		||||
	interrupt => 'i',
 | 
			
		||||
	quit => 'q',
 | 
			
		||||
	kill => 'k',
 | 
			
		||||
	exit => 'x',
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
sub adjust_supervised_service
 | 
			
		||||
{
 | 
			
		||||
    my ($s, @actions) = @_;
 | 
			
		||||
    my $m = "control fifo for service $s: ";
 | 
			
		||||
    unless (open(C, ">/service/$s/supervise/control"))
 | 
			
		||||
    {
 | 
			
		||||
	warn "Couldn't open $m$!";
 | 
			
		||||
	return;
 | 
			
		||||
    }
 | 
			
		||||
    foreach my $p (@actions)
 | 
			
		||||
    {
 | 
			
		||||
	my $c = $param2char{$p};
 | 
			
		||||
	unless ($c)
 | 
			
		||||
	{
 | 
			
		||||
	    warn "Unrecognised param $p for service $s\n";
 | 
			
		||||
	    next;
 | 
			
		||||
	}
 | 
			
		||||
	warn "adjusting supervised $s ($p)\n";
 | 
			
		||||
	unless (print C $c)
 | 
			
		||||
	{
 | 
			
		||||
	    warn "Couldn't write to $m$!";
 | 
			
		||||
	    return;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
    warn  "Couldn't close $m$!" unless close(C);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
my $conf = esmith::ConfigDB->open_ro || die "Couldn't open config db";
 | 
			
		||||
 | 
			
		||||
foreach my $service (grep { !/^\./ } $dh->read())
 | 
			
		||||
{
 | 
			
		||||
    my $s = $conf->get($service);
 | 
			
		||||
    unless ($s)
 | 
			
		||||
    {
 | 
			
		||||
	warn "No conf db entry for service $service\n";
 | 
			
		||||
	next;
 | 
			
		||||
    }
 | 
			
		||||
    my $f =  "services2adjust/$service";
 | 
			
		||||
    
 | 
			
		||||
    my @actions;
 | 
			
		||||
    if (-l "$f")
 | 
			
		||||
    {
 | 
			
		||||
	@actions = ( readlink "$f" );
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
	if (open(F, $f))
 | 
			
		||||
	{
 | 
			
		||||
	    # Read list of actions from the file, and untaint
 | 
			
		||||
	    @actions = map { chomp; /([a-z]+[12]?)/ ; $1 } <F>;
 | 
			
		||||
	    close(F);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
	    warn "Could not open $f: $!";
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # if service is supervised and not handled by systemd
 | 
			
		||||
    if (-d "/service/$service" && glob("/etc/rc7.d/S??$service"))
 | 
			
		||||
    {
 | 
			
		||||
	my $enabled = ($s->prop('status') || 'disabled') eq 'enabled';
 | 
			
		||||
	adjust_supervised_service($service,
 | 
			
		||||
		# stop the service if it is now disabled
 | 
			
		||||
		$enabled ? () : 'down',
 | 
			
		||||
		# Send the specified signal(s) to the running daemon
 | 
			
		||||
		@actions,
 | 
			
		||||
		# bring the service up if it is enabled (and we're not
 | 
			
		||||
		# stopping it or running it once)
 | 
			
		||||
		($enabled && !grep { /^(down|stop|d|once|o)$/ } @actions) ? 'up' : (),
 | 
			
		||||
	    );
 | 
			
		||||
    }
 | 
			
		||||
    # for service handled by former sysvinit or directly with systemd
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        my $enabled = ($s->prop('status') || 'disabled') eq 'enabled';
 | 
			
		||||
        # bring the service up if it is enabled (and we're not stopping it or running it once, or using signal able to start it)
 | 
			
		||||
        unshift(@actions,'start') if ($enabled && !grep { /^(down|stop|d|once|o|start|restart|reload-or-restart)$/ } @actions) ;
 | 
			
		||||
	# stop the service if it is disabled
 | 
			
		||||
	@actions = ('stop') unless  $enabled;
 | 
			
		||||
	foreach (@actions)
 | 
			
		||||
	{
 | 
			
		||||
	    warn "adjusting non-supervised $service ($_)\n";
 | 
			
		||||
	    esmith::util::serviceControl(
 | 
			
		||||
		    NAME => $service,
 | 
			
		||||
		    ACTION => $_,
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										61
									
								
								root/etc/e-smith/events/actions/generic_template_expand
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								root/etc/e-smith/events/actions/generic_template_expand
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
#! /usr/bin/perl -w
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# copyright (C) 2003-2007 Mitel Networks Corporation
 | 
			
		||||
# 
 | 
			
		||||
# 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
 | 
			
		||||
# 
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use File::Find;
 | 
			
		||||
use File::Copy;
 | 
			
		||||
use esmith::templates;
 | 
			
		||||
 | 
			
		||||
sub expand;
 | 
			
		||||
 | 
			
		||||
my $event = shift or die "Event name is required\n";
 | 
			
		||||
 | 
			
		||||
my $filename;
 | 
			
		||||
my %args;
 | 
			
		||||
my ($param, $value);
 | 
			
		||||
my $templates_dir = "/etc/e-smith/events/$event/templates2expand";
 | 
			
		||||
exit 0 unless -d $templates_dir;
 | 
			
		||||
 | 
			
		||||
chdir $templates_dir or die "Could not chdir to $templates_dir: $!\n";;
 | 
			
		||||
# Walk the tree and expand all templates referenced thereunder.
 | 
			
		||||
find({ 
 | 
			
		||||
	no_chdir => 1,
 | 
			
		||||
	follow => 0,
 | 
			
		||||
	wanted => \&expand,
 | 
			
		||||
    },
 | 
			
		||||
    '.'
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
exit 0;
 | 
			
		||||
 | 
			
		||||
sub expand
 | 
			
		||||
{
 | 
			
		||||
    return unless -f $_;
 | 
			
		||||
    # For each file found, read the file to find
 | 
			
		||||
    # processTemplate args, then expand the template
 | 
			
		||||
    s/^\.//;
 | 
			
		||||
    $filename = $_;
 | 
			
		||||
    warn "expanding $filename\n";
 | 
			
		||||
    esmith::templates::processTemplate({
 | 
			
		||||
		MORE_DATA => { EVENT => $event },
 | 
			
		||||
		TEMPLATE_PATH => $filename,
 | 
			
		||||
		OUTPUT_FILENAME => $filename,
 | 
			
		||||
	    });
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								root/etc/e-smith/events/actions/initialize-default-databases
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								root/etc/e-smith/events/actions/initialize-default-databases
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
#!/usr/bin/perl -w
 | 
			
		||||
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# copyright (C) 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# 
 | 
			
		||||
# 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
 | 
			
		||||
# 
 | 
			
		||||
# Technical support for this program is available from Mitel Networks 
 | 
			
		||||
# Please visit our web site www.mitel.com/sme/ for details.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
package esmith;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use esmith::util;
 | 
			
		||||
 | 
			
		||||
if (esmith::util::initialize_default_databases())
 | 
			
		||||
{
 | 
			
		||||
    exit 0;
 | 
			
		||||
}
 | 
			
		||||
else
 | 
			
		||||
{
 | 
			
		||||
    exit 1;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										0
									
								
								root/etc/e-smith/events/e-smith-lib-update/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								root/etc/e-smith/events/e-smith-lib-update/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
								
								
									
										10
									
								
								root/etc/e-smith/templates-default/template-begin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								root/etc/e-smith/templates-default/template-begin
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
#------------------------------------------------------------
 | 
			
		||||
#	       !!DO NOT MODIFY THIS FILE!!
 | 
			
		||||
# 
 | 
			
		||||
# Manual changes will be lost when this file is regenerated.
 | 
			
		||||
#
 | 
			
		||||
# Please read the developer's guide, which is available
 | 
			
		||||
# at http://www.contribs.org/development/
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 1999-2006 Mitel Networks Corporation
 | 
			
		||||
#------------------------------------------------------------
 | 
			
		||||
							
								
								
									
										13
									
								
								root/etc/e-smith/templates-default/template-begin-html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								root/etc/e-smith/templates-default/template-begin-html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
{
 | 
			
		||||
    $OUT = <<HERE;
 | 
			
		||||
<!--
 | 
			
		||||
HERE
 | 
			
		||||
 | 
			
		||||
    $OUT .= 
 | 
			
		||||
    Text::Template::_load_text("/etc/e-smith/templates-default/template-begin");
 | 
			
		||||
 | 
			
		||||
    $OUT .= <<HERE;
 | 
			
		||||
-->
 | 
			
		||||
HERE
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								root/etc/e-smith/templates-default/template-begin-pam
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								root/etc/e-smith/templates-default/template-begin-pam
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
    $OUT = <<HERE;
 | 
			
		||||
#%PAM-1.0
 | 
			
		||||
HERE
 | 
			
		||||
 | 
			
		||||
    $OUT .= 
 | 
			
		||||
    Text::Template::_load_text("/etc/e-smith/templates-default/template-begin");
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								root/etc/e-smith/templates-default/template-begin-perl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								root/etc/e-smith/templates-default/template-begin-perl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
    $OUT = <<HERE;
 | 
			
		||||
#!/usr/bin/perl -w
 | 
			
		||||
HERE
 | 
			
		||||
 | 
			
		||||
    $OUT .= 
 | 
			
		||||
    Text::Template::_load_text("/etc/e-smith/templates-default/template-begin");
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								root/etc/e-smith/templates-default/template-begin-php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								root/etc/e-smith/templates-default/template-begin-php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
{
 | 
			
		||||
    $OUT = <<HERE;
 | 
			
		||||
<?php
 | 
			
		||||
/*
 | 
			
		||||
HERE
 | 
			
		||||
 | 
			
		||||
    $OUT .= 
 | 
			
		||||
    Text::Template::_load_text("/etc/e-smith/templates-default/template-begin");
 | 
			
		||||
 | 
			
		||||
    $OUT .= <<HERE;
 | 
			
		||||
*/
 | 
			
		||||
HERE
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								root/etc/e-smith/templates-default/template-begin-shell
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								root/etc/e-smith/templates-default/template-begin-shell
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
    $OUT = <<HERE;
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
HERE
 | 
			
		||||
 | 
			
		||||
    $OUT .= 
 | 
			
		||||
    Text::Template::_load_text("/etc/e-smith/templates-default/template-begin");
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								root/etc/e-smith/templates-default/template-end-php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								root/etc/e-smith/templates-default/template-end-php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
?>
 | 
			
		||||
							
								
								
									
										81
									
								
								root/etc/e-smith/tests/10e-smith-lib/accounts.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								root/etc/e-smith/tests/10e-smith-lib/accounts.conf
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
			
		||||
# DO NOT MODIFY THIS FILE.
 | 
			
		||||
# This file is automatically maintained by the Mitel Networks SME Server
 | 
			
		||||
# configuration software.  Manually editing this file may put your 
 | 
			
		||||
# system in an unknown state.
 | 
			
		||||
#
 | 
			
		||||
# updated: Thu Mar 28 15:29:31 2002
 | 
			
		||||
Bart.Simpson=pseudonym|Account|bart
 | 
			
		||||
Bart_Simpson=pseudonym|Account|bart
 | 
			
		||||
Global=system
 | 
			
		||||
Primary=system
 | 
			
		||||
adm=system|Gid|4|Uid|3
 | 
			
		||||
admin=system|Gid|101|Uid|101
 | 
			
		||||
alias=system|Gid|400|Uid|400
 | 
			
		||||
apache=existing|Gid|48|Uid|48
 | 
			
		||||
bart=user|FirstName|Bart|LastName|Simpson
 | 
			
		||||
bin=system|Gid|1|Uid|1
 | 
			
		||||
cdrom=system
 | 
			
		||||
cgi-bin=url
 | 
			
		||||
console=system
 | 
			
		||||
daemon=system|Gid|2|Uid|2
 | 
			
		||||
dip=system|Gid|40
 | 
			
		||||
disk=system|Gid|6
 | 
			
		||||
dns=existing|Gid|53|Uid|53
 | 
			
		||||
e-smith-manager=url
 | 
			
		||||
e-smith-password=url
 | 
			
		||||
everyone=pseudonym|Account|shared|Visible|internal
 | 
			
		||||
floppy=system|Gid|19
 | 
			
		||||
ftp=system|Gid|50|Uid|14
 | 
			
		||||
games=system|Gid|20|Uid|12
 | 
			
		||||
global=system
 | 
			
		||||
gopher=system|Gid|30|Uid|13
 | 
			
		||||
halt=system
 | 
			
		||||
homes=system
 | 
			
		||||
kmem=system|Gid|9
 | 
			
		||||
ldap=existing|Gid|55|Uid|55
 | 
			
		||||
lp=system|Gid|7|Uid|4
 | 
			
		||||
mail=system|Gid|12|Uid|8
 | 
			
		||||
mailer-daemon=pseudonym|Account|admin
 | 
			
		||||
man=system|Gid|15
 | 
			
		||||
mem=system|Gid|8
 | 
			
		||||
mysql=existing|Gid|27|Uid|27
 | 
			
		||||
named=existing|Gid|25|Uid|25
 | 
			
		||||
netlogon=netlogon|Comment|placeholder for netlogon share
 | 
			
		||||
news=system|Gid|13|Uid|9
 | 
			
		||||
nofiles=system|Gid|400
 | 
			
		||||
operator=system|Gid|0|Uid|11
 | 
			
		||||
postgres=system
 | 
			
		||||
postmaster=pseudonym|Account|admin
 | 
			
		||||
primary=system
 | 
			
		||||
printers=system
 | 
			
		||||
public=system|Gid|103|Uid|102
 | 
			
		||||
qmail=system|Gid|401
 | 
			
		||||
qmaild=system|Gid|400|Uid|401
 | 
			
		||||
qmaill=system|Gid|400|Uid|402
 | 
			
		||||
qmailp=system|Gid|400|Uid|403
 | 
			
		||||
qmailq=system|Gid|401|Uid|404
 | 
			
		||||
qmailr=system|Gid|401|Uid|405
 | 
			
		||||
qmails=system|Gid|401|Uid|406
 | 
			
		||||
qmailscan=existing|Gid|407|Uid|407
 | 
			
		||||
root=system|Gid|0|Uid|0
 | 
			
		||||
schwern=user|Uid|500|Gid|501|FirstName|Michael|LastName|Schwern
 | 
			
		||||
server-manager=url
 | 
			
		||||
server-manual=url
 | 
			
		||||
shared=system|Gid|500|Visible|internal
 | 
			
		||||
shutdown=system
 | 
			
		||||
simpsons=group|Description|bar|Gid|5005|Members|bart,lisa,homer,maggie|Uid|5005
 | 
			
		||||
slocate=system
 | 
			
		||||
somegroup=group|Gid|42|Members|admin
 | 
			
		||||
squid=system|Gid|23|Uid|23
 | 
			
		||||
sync=system
 | 
			
		||||
sys=system|Gid|3
 | 
			
		||||
trend=existing|Gid|408|Uid|408
 | 
			
		||||
tty=system|Gid|5
 | 
			
		||||
user-password=url
 | 
			
		||||
users=system|Gid|100
 | 
			
		||||
utmp=system|Gid|22
 | 
			
		||||
uucp=system|Gid|14|Uid|10
 | 
			
		||||
webmail=url
 | 
			
		||||
wheel=system|Gid|10
 | 
			
		||||
www=system|Gid|102|Uid|100
 | 
			
		||||
wwwpublic=system
 | 
			
		||||
							
								
								
									
										95
									
								
								root/etc/e-smith/tests/10e-smith-lib/config.t
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								root/etc/e-smith/tests/10e-smith-lib/config.t
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,95 @@
 | 
			
		||||
#!/usr/bin/perl -w
 | 
			
		||||
 | 
			
		||||
# Overall tests for esmith::config
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use File::Copy;
 | 
			
		||||
 | 
			
		||||
use Test::More 'no_plan';
 | 
			
		||||
use_ok('esmith::config');
 | 
			
		||||
 | 
			
		||||
my %Expect = ( foo              => 'bar',
 | 
			
		||||
               'this key'       => 'has whitespace',
 | 
			
		||||
               'that key '      => 'has trailing whitespace',
 | 
			
		||||
               ' another key'   => 'has leading whitespace',
 | 
			
		||||
               'this value'     => ' has leading whitespace',
 | 
			
		||||
               'that value'     => 'has trailing whitespace ',
 | 
			
		||||
               'tricky value'   => 'with=equals.',
 | 
			
		||||
             );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# so we don't bork the original.
 | 
			
		||||
my $Scratch = '10e-smith-lib/mydummy.conf';
 | 
			
		||||
copy('10e-smith-lib/dummy.conf', $Scratch);
 | 
			
		||||
END { unlink $Scratch }
 | 
			
		||||
 | 
			
		||||
my %config;
 | 
			
		||||
tie %config, 'esmith::config', $Scratch;
 | 
			
		||||
ok( tied %config,                'tie worked' );
 | 
			
		||||
is_deeply( \%config, \%Expect,   'read in the config properly' );
 | 
			
		||||
 | 
			
		||||
# Test the tied interface.
 | 
			
		||||
is_deeply( [sort keys   %config], [sort keys   %Expect], 'keys' );
 | 
			
		||||
is_deeply( [sort values %config], [sort values %Expect], 'values' );
 | 
			
		||||
 | 
			
		||||
is_deeply( [@config{'foo', 'this key'}], [@Expect{'foo', 'this key'}],
 | 
			
		||||
                                                           'hash slice');
 | 
			
		||||
 | 
			
		||||
$config{foo} = 'baz';
 | 
			
		||||
is( $config{foo}, 'baz',        'STORE' );
 | 
			
		||||
 | 
			
		||||
my %config_copy;
 | 
			
		||||
tie %config_copy, 'esmith::config', $Scratch;
 | 
			
		||||
is( $config_copy{foo}, 'baz',   '  STORE saved' );
 | 
			
		||||
 | 
			
		||||
SKIP: {
 | 
			
		||||
   skip "Locking is broken in perl 5.6.0", 2 if $] eq 5.006;
 | 
			
		||||
 | 
			
		||||
tied(%config_copy)->_lock_write;
 | 
			
		||||
my $start_time = time;
 | 
			
		||||
{
 | 
			
		||||
    local $ENV{PERL5LIB} = join ':', @INC;
 | 
			
		||||
    system(qq{$^X -Mesmith::config -e 'alarm 4;  tie %config, "esmith::config", q{$Scratch}'});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cmp_ok( time - 2, '<=', $start_time,     'write locks dont prevent read' );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
tied(%config_copy)->_lock_write;
 | 
			
		||||
$start_time = time;
 | 
			
		||||
{
 | 
			
		||||
    local $ENV{PERL5LIB} = join ':', @INC;
 | 
			
		||||
    system(qq{$^X -Mesmith::config -e 'alarm 4;  tie %config, "esmith::config", q{$Scratch};  \$config{foo} = 42'});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cmp_ok( time - 1, '>=', $start_time,     'write locks prevent writes' );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
my $new_conf = 'I_dont_exist';
 | 
			
		||||
unlink $new_conf;
 | 
			
		||||
ok( !-e $new_conf,  'config file doesnt exist' );
 | 
			
		||||
END { unlink $new_conf }
 | 
			
		||||
 | 
			
		||||
tie %config, 'esmith::config', $new_conf;
 | 
			
		||||
is( keys %config, 0, 'new() from nonexistent config' );
 | 
			
		||||
$config{wibble} = 'wobble';
 | 
			
		||||
 | 
			
		||||
tie %config_copy, 'esmith::config', $new_conf;
 | 
			
		||||
is( $config_copy{wibble}, 'wobble',   '  new config file written' );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
SKIP: {
 | 
			
		||||
   skip "Locking is broken in perl 5.6.0", 1 if $] eq 5.006;
 | 
			
		||||
 | 
			
		||||
# There was a bug where if you set something to its existing value
 | 
			
		||||
# it wouldn't unlock properly.
 | 
			
		||||
my $Alarm;
 | 
			
		||||
eval {
 | 
			
		||||
    local $SIG{ALRM} = sub { $Alarm = 1;  die "ALARM!\n"; };
 | 
			
		||||
    alarm 1;
 | 
			
		||||
    $config_copy{wibble} = $config_copy{wibble};
 | 
			
		||||
    $config{wibble} = 42;
 | 
			
		||||
    alarm 0;
 | 
			
		||||
};
 | 
			
		||||
ok( !$Alarm, 'Unlocking works for setting the same value' );
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										13
									
								
								root/etc/e-smith/tests/10e-smith-lib/config_taint.t
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								root/etc/e-smith/tests/10e-smith-lib/config_taint.t
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
#!/usr/bin/perl -Tw
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use esmith::config;
 | 
			
		||||
use Test::More tests => 2;
 | 
			
		||||
 | 
			
		||||
my %config;
 | 
			
		||||
tie %config, 'esmith::config', '10e-smith-lib/dummy.conf';
 | 
			
		||||
my $value = $config{foo};
 | 
			
		||||
 | 
			
		||||
# Config values *should* be tained, but code depends on them not being.
 | 
			
		||||
is( $value, 'bar',      'tied to the dummy database' );
 | 
			
		||||
ok( eval { () = join('', $value), kill 0; 1; }, 'config values not tainted' );
 | 
			
		||||
							
								
								
									
										103
									
								
								root/etc/e-smith/tests/10e-smith-lib/configuration.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								root/etc/e-smith/tests/10e-smith-lib/configuration.conf
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
			
		||||
# DO NOT MODIFY THIS FILE.
 | 
			
		||||
# This file is automatically maintained by the Mitel Networks SME Server
 | 
			
		||||
# configuration software.  Manually editing this file may put your 
 | 
			
		||||
# system in an unknown state.
 | 
			
		||||
#
 | 
			
		||||
# updated: Fri Feb 28 16:41:34 2003
 | 
			
		||||
AccessType=dedicated
 | 
			
		||||
ActiveAccounts=0
 | 
			
		||||
AdminEmail=
 | 
			
		||||
ConsoleMode=login
 | 
			
		||||
ContactEmail=
 | 
			
		||||
ContactName=
 | 
			
		||||
ContactOrg=
 | 
			
		||||
DialupConnOffice=long
 | 
			
		||||
DialupConnOutside=long
 | 
			
		||||
DialupConnWeekend=long
 | 
			
		||||
DialupFreqOffice=every15min
 | 
			
		||||
DialupFreqOutside=everyhour
 | 
			
		||||
DialupFreqWeekend=everyhour
 | 
			
		||||
DialupModemDevice=/dev/ttyS1
 | 
			
		||||
DialupPhoneNumber=
 | 
			
		||||
DialupUserAccount=useraccount
 | 
			
		||||
DialupUserPassword=userpassword
 | 
			
		||||
DomainName=e-smith.com
 | 
			
		||||
DynDnsAccount=dnsaccount
 | 
			
		||||
DynDnsPassword=dnspassword
 | 
			
		||||
DynDnsService=off
 | 
			
		||||
EmailUnknownUser=return
 | 
			
		||||
EthernetDriver1=pcnet32
 | 
			
		||||
EthernetDriver2=unknown
 | 
			
		||||
ExternalDHCP=off
 | 
			
		||||
ExternalNetmask=255.255.255.0
 | 
			
		||||
GatewayIP=192.168.16.1
 | 
			
		||||
LocalIP=192.168.16.228
 | 
			
		||||
LocalNetmask=255.255.255.0
 | 
			
		||||
MinUid=5000
 | 
			
		||||
PasswordSet=yes
 | 
			
		||||
PreviousConfiguration=/home/e-smith/db/configuration.previous
 | 
			
		||||
SMTPSmartHost=
 | 
			
		||||
SambaDomainMaster=no
 | 
			
		||||
SambaServerName=pretz
 | 
			
		||||
SambaWorkgroup=mitel-networks
 | 
			
		||||
ServiceAccountId=
 | 
			
		||||
ServiceDomainName=
 | 
			
		||||
ServiceTargetIP=
 | 
			
		||||
SquidParent=
 | 
			
		||||
SquidParentPort=
 | 
			
		||||
StatusReports=off
 | 
			
		||||
SystemMode=serveronly
 | 
			
		||||
SystemName=pretz
 | 
			
		||||
TimeZone=US/Eastern
 | 
			
		||||
UnsavedChanges=yes
 | 
			
		||||
atalk=service|InitscriptOrder|91|status|enabled
 | 
			
		||||
auth=service|access|public|status|enabled
 | 
			
		||||
bazbar=service|status|enabled
 | 
			
		||||
blades=service|Host|service.e-smith.com|status|enabled
 | 
			
		||||
bootstrap-console=service|InitscriptOrder|35|Run|no|status|enabled
 | 
			
		||||
branding=service|modified|000000000000|status|enabled
 | 
			
		||||
crond=service|InitscriptOrder|40|status|enabled
 | 
			
		||||
ctrlaltdel=service|status|enabled
 | 
			
		||||
dhcpd=service|InitscriptOrder|65|end|192.168.16.250|start|192.168.16.65|status|disabled
 | 
			
		||||
diald=service|InitscriptOrder|57|status|disabled
 | 
			
		||||
fetchmail=service|FreqOffice|every5min|FreqOutside|every30min|FreqWeekend|never|Method|standard|SecondaryMailAccount|popaccount|SecondaryMailPassword|poppassword|SecondaryMailServer|mail.myisp.xxx|status|disabled
 | 
			
		||||
flexbackup=backupservice|erase_rewind_only|true
 | 
			
		||||
ftp=service|access|private|accessLimits|off|status|enabled
 | 
			
		||||
hdparm=service|InitscriptOrder|40|status|disabled
 | 
			
		||||
horde=service|status|disabled
 | 
			
		||||
httpd-admin=service|InitscriptOrder|86|status|enabled
 | 
			
		||||
httpd-e-smith=service|InitscriptOrder|85|access|private|status|enabled
 | 
			
		||||
imap=service|access|private|status|enabled
 | 
			
		||||
imp=service|status|disabled
 | 
			
		||||
ippp=service|InitscriptOrder|55|status|enabled
 | 
			
		||||
ipsec=service|InitscriptOrder|90|PubKey|0sAQOoIKaOMuDqSdCZJXgv9QI86DAuAwbbvn8uoKn2lRQ9ZVPTn9Ow5znhuw/GopsYD2eujhtvkQo7fszAhWbEpn+lW2LzLCbZYaDov7j8Q9CpeJSVgeuzaBcw3OenSL3ltTwWWtG0pvyaYsfepNqVYvo64YVmrxo0O7dCECySMVBZkQ==|status|disabled
 | 
			
		||||
isdn=service|Protocol|2|UseSyncPPP|yes|status|disabled
 | 
			
		||||
keytable=service|InitscriptOrder|25|status|enabled
 | 
			
		||||
ldap=service|InitscriptOrder|80|access|private|defaultCity|Ottawa|defaultCompany|XYZ Corporation|defaultDepartment|Main|defaultPhoneNumber|555-5555|defaultStreet|123 Main Street|status|enabled
 | 
			
		||||
lilo=service|AddressMode|linear
 | 
			
		||||
local=service|InitscriptOrder|99|status|enabled
 | 
			
		||||
lpd=service|InitscriptOrder|60|status|enabled
 | 
			
		||||
mariadb=service|InitscriptOrder|90|status|enabled
 | 
			
		||||
masq=service|InitscriptOrder|06|Logging|none|Stealth|no|status|disabled
 | 
			
		||||
modSSL=service|status|enabled
 | 
			
		||||
mysql.init=service|InitscriptOrder|99|status|enabled
 | 
			
		||||
named=service|chroot|yes|status|enabled|Forwarder1|1.2.3.4
 | 
			
		||||
network=service|InitscriptOrder|10|status|enabled
 | 
			
		||||
ntpd=service|InitscriptOrder|55|status|disabled
 | 
			
		||||
php=service|status|enabled
 | 
			
		||||
popd=service|access|private|status|enabled
 | 
			
		||||
pppoe=service|DemandIdleTime|no|InitscriptOrder|57|SynchronousPPP|no|status|disabled
 | 
			
		||||
pptpd=service|sessions|10|status|disabled
 | 
			
		||||
qmail=service|InitscriptOrder|80|status|enabled
 | 
			
		||||
random=service|InitscriptOrder|20|status|enabled
 | 
			
		||||
rsyslog=service|InitscriptOrder|05|status|enabled
 | 
			
		||||
scanner=service|ScannerFns|iscan|UpdateTime|1:14|scanMail|yes|status|enabled
 | 
			
		||||
smb=service|InitscriptOrder|91|RoamingProfiles|no|status|enabled
 | 
			
		||||
smtpd=service|access|public|status|enabled
 | 
			
		||||
smtpfwdd=service|InitscriptOrder|81|status|enabled
 | 
			
		||||
squid=service|InitscriptOrder|90|status|enabled
 | 
			
		||||
sshd=service|InitscriptOrder|85|PasswordAuthentication|yes|PermitRootLogin|yes|access|private|status|enabled
 | 
			
		||||
sync=service|Host|service.e-smith.com|LastId|0|SuccessId|0|SyncFrequency|1|SyncMinute|57|status|disabled
 | 
			
		||||
telnet=service|access|private|status|disabled
 | 
			
		||||
wibble=42
 | 
			
		||||
xinetd=service|InitscriptOrder|50|status|enabled
 | 
			
		||||
							
								
								
									
										215
									
								
								root/etc/e-smith/tests/10e-smith-lib/db.t
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								root/etc/e-smith/tests/10e-smith-lib/db.t
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,215 @@
 | 
			
		||||
#!/usr/bin/perl -w
 | 
			
		||||
 | 
			
		||||
# Overall test for esmith::db
 | 
			
		||||
 | 
			
		||||
use File::Copy;
 | 
			
		||||
use esmith::TestUtils;
 | 
			
		||||
use Test::More 'no_plan';
 | 
			
		||||
use_ok('esmith::db');
 | 
			
		||||
 | 
			
		||||
my %Expect = (
 | 
			
		||||
              Foo       =>  ['Bar', {}],
 | 
			
		||||
              Night     =>  ['Day', {}],
 | 
			
		||||
              Squid     =>  ['cephalopod', {
 | 
			
		||||
                                            arms => 10, 
 | 
			
		||||
                                            species => 'Loligo',
 | 
			
		||||
                                           }
 | 
			
		||||
                            ],
 | 
			
		||||
 | 
			
		||||
              # Ensure that empty values are read in properly.
 | 
			
		||||
              Octopus   =>  ['cephalopod', {
 | 
			
		||||
                                            arms => 8,
 | 
			
		||||
                                            species => '',
 | 
			
		||||
                                           }
 | 
			
		||||
                            ],
 | 
			
		||||
 | 
			
		||||
              # Ensure that escaped pipes are read in properly.
 | 
			
		||||
              Pipe      =>  ['art',  { pipe => 'this is not a \| got that?'}],
 | 
			
		||||
 | 
			
		||||
              # Ensure that escaped newlines are handled properly.
 | 
			
		||||
              Haiku     =>  ['poem', { words => 
 | 
			
		||||
                                       "Damian Conway\n".
 | 
			
		||||
                                       "God damn! Damian Conway\n".
 | 
			
		||||
                                       "Damian Conway"
 | 
			
		||||
                                     }
 | 
			
		||||
                            ]
 | 
			
		||||
             );
 | 
			
		||||
 | 
			
		||||
my $Scratch_Conf = '10e-smith-lib/db_scratch.conf';
 | 
			
		||||
copy '10e-smith-lib/db_dummy.conf', $Scratch_Conf;
 | 
			
		||||
END { unlink $Scratch_Conf }
 | 
			
		||||
 | 
			
		||||
my %config;
 | 
			
		||||
tie %config, 'esmith::config', $Scratch_Conf;
 | 
			
		||||
ok( tied %config, 'tied to the dummy config file' );
 | 
			
		||||
isnt( keys %config, 0, '  and theres something in there' );
 | 
			
		||||
 | 
			
		||||
is( db_get_type(\%config, 'Foo'), 'Bar', 'simple db_get_type' );
 | 
			
		||||
 | 
			
		||||
my @keys = db_get(\%config);
 | 
			
		||||
is_deeply( [sort @keys], [sort keys %Expect], 
 | 
			
		||||
                                          'db_get() all keys' );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
foreach my $key (@keys) {
 | 
			
		||||
    my($type, %properties) = db_get(\%config, $key);
 | 
			
		||||
    my($exp_type, $exp_properties) = @{$Expect{$key}};
 | 
			
		||||
 | 
			
		||||
    is( $type, $exp_type,                       "db_get - type - $key" );
 | 
			
		||||
    is( db_get_type(\%config, $key), $exp_type, "db_get_type" );
 | 
			
		||||
    is_deeply( \%properties, $exp_properties,   "db_get - prop" );
 | 
			
		||||
    is_deeply( {db_get_prop(\%config, $key)}, $exp_properties,
 | 
			
		||||
                                             "db_get_prop - all properties");
 | 
			
		||||
    while( my($prop, $val) = each %properties ) {
 | 
			
		||||
        is( db_get_prop(\%config, $key, $prop), $val,
 | 
			
		||||
                                   "db_get_prop - single prop - $prop");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
is( db_get_type(\%config, 'I_dont_exist'), undef,
 | 
			
		||||
                                        'db_get_type on non-existent key' );
 | 
			
		||||
is( db_get_prop(\%config, 'I_dont_exist'), undef,
 | 
			
		||||
                                        '  db_get_prop' );
 | 
			
		||||
is( db_get_prop(\%config, 'Squid', 'feet'), undef,
 | 
			
		||||
                                        'db_get_prop on non-existent prop' );
 | 
			
		||||
is( db_delete_prop(\%config, 'I_dont_exist', 'feet'), undef,
 | 
			
		||||
                                      'db_delete_prop on non-existent key' );
 | 
			
		||||
 | 
			
		||||
is( db_get(\%config, 'Squid'), 'cephalopod|arms|10|species|Loligo',
 | 
			
		||||
                                        'db_get a raw value');
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
    package TieOut;
 | 
			
		||||
 | 
			
		||||
    sub TIEHANDLE {
 | 
			
		||||
	bless( \(my $scalar), $_[0]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sub PRINT {
 | 
			
		||||
	my $self = shift;
 | 
			
		||||
	$$self .= join('', @_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sub read {
 | 
			
		||||
	my $self = shift;
 | 
			
		||||
	return substr($$self, 0, length($$self), '');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
my $out = tie *STDOUT, 'TieOut';
 | 
			
		||||
db_show(\%config);
 | 
			
		||||
is( $out->read, <<SHOW, 'db_show() all' );
 | 
			
		||||
Foo=Bar
 | 
			
		||||
Haiku=poem
 | 
			
		||||
    words=Damian Conway\nGod damn! Damian Conway\nDamian Conway
 | 
			
		||||
Night=Day
 | 
			
		||||
Octopus=cephalopod
 | 
			
		||||
    arms=8
 | 
			
		||||
    species=
 | 
			
		||||
Pipe=art
 | 
			
		||||
    pipe=this is not a \\| got that?
 | 
			
		||||
Squid=cephalopod
 | 
			
		||||
    arms=10
 | 
			
		||||
    species=Loligo
 | 
			
		||||
SHOW
 | 
			
		||||
 | 
			
		||||
db_show(\%config, 'Squid');
 | 
			
		||||
is( $out->read, <<SHOW,       'db_show() one key' );
 | 
			
		||||
Squid=cephalopod
 | 
			
		||||
    arms=10
 | 
			
		||||
    species=Loligo
 | 
			
		||||
SHOW
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
db_print(\%config);
 | 
			
		||||
is( $out->read, <<PRINT, 'db_print all' );
 | 
			
		||||
Foo=Bar
 | 
			
		||||
Haiku=poem|words|Damian Conway\nGod damn! Damian Conway\nDamian Conway
 | 
			
		||||
Night=Day
 | 
			
		||||
Octopus=cephalopod|arms|8|species|
 | 
			
		||||
Pipe=art|pipe|this is not a \\| got that?
 | 
			
		||||
Squid=cephalopod|arms|10|species|Loligo
 | 
			
		||||
PRINT
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
db_print(\%config, 'Squid');
 | 
			
		||||
is( $out->read, <<PRINT, 'db_print one key' );
 | 
			
		||||
Squid=cephalopod|arms|10|species|Loligo
 | 
			
		||||
PRINT
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
db_print_type(\%config);
 | 
			
		||||
is( $out->read, <<PRINT_TYPE, 'db_print_type all keys' );
 | 
			
		||||
Foo=Bar
 | 
			
		||||
Haiku=poem
 | 
			
		||||
Night=Day
 | 
			
		||||
Octopus=cephalopod
 | 
			
		||||
Pipe=art
 | 
			
		||||
Squid=cephalopod
 | 
			
		||||
PRINT_TYPE
 | 
			
		||||
 | 
			
		||||
db_print_type(\%config, 'Squid');
 | 
			
		||||
is( $out->read, <<PRINT_TYPE, 'db_print_type one key' );
 | 
			
		||||
Squid=cephalopod
 | 
			
		||||
PRINT_TYPE
 | 
			
		||||
 | 
			
		||||
db_print_prop(\%config, 'Squid');
 | 
			
		||||
is( $out->read, <<PRINT_PROP, 'db_print_prop all props' );
 | 
			
		||||
arms=10
 | 
			
		||||
species=Loligo
 | 
			
		||||
PRINT_PROP
 | 
			
		||||
 | 
			
		||||
db_print_prop(\%config, 'Squid', 'arms');
 | 
			
		||||
is( $out->read, <<PRINT_PROP, 'db_print_prop one prop' );
 | 
			
		||||
arms=10
 | 
			
		||||
PRINT_PROP
 | 
			
		||||
 | 
			
		||||
undef $out;
 | 
			
		||||
untie *STDOUT;
 | 
			
		||||
 | 
			
		||||
db_set(\%config, 'Wibble', 'dribble|hip|hop');
 | 
			
		||||
my($type, %props) = db_get(\%config, 'Wibble');
 | 
			
		||||
is( $type, 'dribble',   'db_set with raw value' );
 | 
			
		||||
is_deeply( \%props, { hip => 'hop' }, '  again' );
 | 
			
		||||
 | 
			
		||||
db_set(\%config, 'Wibble', 'word', { thingy => 'yep' });
 | 
			
		||||
($type, %props) = db_get(\%config, 'Wibble');
 | 
			
		||||
is( $type, 'word',      'db_set');
 | 
			
		||||
is_deeply( \%props, { thingy => 'yep' } );
 | 
			
		||||
 | 
			
		||||
db_set_type(\%config, 'Wibble', 'yibble');
 | 
			
		||||
is( db_get_type(\%config, 'Wibble'), 'yibble', 'db_set_type' );
 | 
			
		||||
 | 
			
		||||
db_set_prop(\%config, 'Wibble', har => 'far');
 | 
			
		||||
is( db_get_prop(\%config, 'Wibble', 'har'), 'far', 'db_set_prop' );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Test read-only open()
 | 
			
		||||
my $scratch = scratch_copy('10e-smith-lib/configuration.conf');
 | 
			
		||||
ok( chmod 0444, $scratch );
 | 
			
		||||
my $ro_db = esmith::DB::db->open_ro($scratch);
 | 
			
		||||
 | 
			
		||||
eval { $ro_db->new_record('wibble', { type => 'something' }) };
 | 
			
		||||
like( $@, qr/read-only/ );
 | 
			
		||||
 | 
			
		||||
my $sshd = $ro_db->get('sshd');
 | 
			
		||||
eval { $sshd->set_prop('foo', 'bar') };
 | 
			
		||||
like( $@, qr/read-only/ );
 | 
			
		||||
is( $sshd->prop('foo'), undef );
 | 
			
		||||
 | 
			
		||||
eval { $sshd->delete_prop('status') };
 | 
			
		||||
like( $@, qr/read-only/ );
 | 
			
		||||
isnt( $sshd->prop('status'), undef );
 | 
			
		||||
 | 
			
		||||
eval { $sshd->merge_props(foo => 'bar') };
 | 
			
		||||
like( $@, qr/read-only/ );
 | 
			
		||||
is( $sshd->prop('foo'), undef );
 | 
			
		||||
 | 
			
		||||
eval { $sshd->reset_props(foo => 'bar') };
 | 
			
		||||
like( $@, qr/read-only/ );
 | 
			
		||||
is( $sshd->prop('foo'), undef );
 | 
			
		||||
 | 
			
		||||
eval { $sshd->delete };
 | 
			
		||||
like( $@, qr/read-only/ );
 | 
			
		||||
ok( $ro_db->get('sshd') );
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
invalid
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
enabled
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
service
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
enabled
 | 
			
		||||
@@ -0,0 +1,4 @@
 | 
			
		||||
{
 | 
			
		||||
    $DB = esmith::ConfigDB->open("${DB_FILENAME}");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -0,0 +1,3 @@
 | 
			
		||||
{
 | 
			
		||||
    $DB->new_record("quux", {type=>'service', status=>'enabled'});
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								root/etc/e-smith/tests/10e-smith-lib/db_dummy.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								root/etc/e-smith/tests/10e-smith-lib/db_dummy.conf
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
# Dummy configuration file for testing esmith::db
 | 
			
		||||
Foo=Bar
 | 
			
		||||
Night=Day
 | 
			
		||||
Squid=cephalopod|arms|10|species|Loligo
 | 
			
		||||
Pipe=art|pipe|this is not a \| got that?
 | 
			
		||||
Haiku=poem|words|Damian Conway\nGod damn! Damian Conway\nDamian Conway
 | 
			
		||||
Octopus=cephalopod|arms|8|species|
 | 
			
		||||
							
								
								
									
										141
									
								
								root/etc/e-smith/tests/10e-smith-lib/default_migrate_force.t
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								root/etc/e-smith/tests/10e-smith-lib/default_migrate_force.t
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,141 @@
 | 
			
		||||
#!/usr/bin/perl -w
 | 
			
		||||
# vim: ft=perl:
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use esmith::util;
 | 
			
		||||
use esmith::ConfigDB;
 | 
			
		||||
use Test::More 'no_plan';
 | 
			
		||||
use File::Copy qw(copy);
 | 
			
		||||
use POSIX qw(tmpnam);
 | 
			
		||||
 | 
			
		||||
# What we want to do is run initialize-default-databases on a scratch
 | 
			
		||||
# db and check the results.
 | 
			
		||||
my $dbhome = '/tmp/dbhome';
 | 
			
		||||
my $dbroot = '/etc/e-smith/db';
 | 
			
		||||
system('rm', '-rf', $dbhome);
 | 
			
		||||
system('mkdir', '-p', $dbhome) == 0
 | 
			
		||||
    or die "Can't create $dbhome: $!\n";
 | 
			
		||||
 | 
			
		||||
ok( esmith::util::initialize_default_databases(dbhome => $dbhome),
 | 
			
		||||
    "initialize_default_databases created successfully" );
 | 
			
		||||
 | 
			
		||||
# Confirm the default settings.
 | 
			
		||||
walk_dbtree($dbroot, 'defaults');
 | 
			
		||||
# Test that forced options were forced.
 | 
			
		||||
walk_dbtree($dbroot, 'force');
 | 
			
		||||
 | 
			
		||||
# We should now have default configuration files. We can go through each
 | 
			
		||||
# setting specified by the defaults and confirm that it is correct.
 | 
			
		||||
 | 
			
		||||
# To test migration, we should take a typical 5.6 set of databases and migrate
 | 
			
		||||
# those. The existing .conf databases in the 10e-smith-lib directory are
 | 
			
		||||
# styled after 5.6, and suitable for this.
 | 
			
		||||
foreach my $dummyconf (qw(accounts.conf domains.conf networks.conf 
 | 
			
		||||
                          configuration.conf hosts.conf))
 | 
			
		||||
{
 | 
			
		||||
    # Copy them over the ones in our test directory, and then migrate them.
 | 
			
		||||
    my $dest;
 | 
			
		||||
    ($dest = $dummyconf) =~ s/\.conf$//;
 | 
			
		||||
    $dest = "$dbhome/$dest";
 | 
			
		||||
    copy($dummyconf, $dest) or die "Can't copy $dummyconf to $dest: $!\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Migrate the directory.
 | 
			
		||||
ok( esmith::util::initialize_default_databases(dbhome => $dbhome),
 | 
			
		||||
    "initialize_default_databases migrated successfully" );
 | 
			
		||||
 | 
			
		||||
#run_migrate_tests($dbhome, $dbroot);
 | 
			
		||||
system('rm', '-rf', $dbhome);
 | 
			
		||||
 | 
			
		||||
exit 0;
 | 
			
		||||
 | 
			
		||||
sub walk_dbtree
 | 
			
		||||
{
 | 
			
		||||
    my $dbroot = shift;
 | 
			
		||||
    my $mode = shift;
 | 
			
		||||
    die unless $mode =~ /^(defaults|force)$/;
 | 
			
		||||
 | 
			
		||||
    opendir(DBROOT, $dbroot) or die "Can't open $dbroot: $!\n";
 | 
			
		||||
    my @dbfiles = grep { -d "$dbroot/$_" }
 | 
			
		||||
		grep { !/^\./ } readdir DBROOT;
 | 
			
		||||
    closedir(DBROOT);
 | 
			
		||||
    foreach my $dbfile (@dbfiles)
 | 
			
		||||
    {
 | 
			
		||||
	# Handle the defaults in this case.
 | 
			
		||||
	my $defaultdir = "$dbroot/$dbfile/defaults";
 | 
			
		||||
	next if not -e $defaultdir;
 | 
			
		||||
	opendir(DEFAULTDIR, $defaultdir) or die "Can't open $defaultdir: $!\n";
 | 
			
		||||
	my @keys = grep { -d "$defaultdir/$_" }
 | 
			
		||||
		grep { !/^\./ } readdir DEFAULTDIR;
 | 
			
		||||
	closedir(DEFAULTDIR);
 | 
			
		||||
	# There should now be a db file output at the dbhome.
 | 
			
		||||
	ok( -e "$dbhome/$dbfile", "$dbfile db exists" );
 | 
			
		||||
 | 
			
		||||
	my $db = esmith::ConfigDB->open_ro("$dbhome/$dbfile");
 | 
			
		||||
	ok( defined $db, "$dbhome/$dbfile loads properly" );
 | 
			
		||||
	# Loop on all the keys.
 | 
			
		||||
	foreach my $keydir (@keys)
 | 
			
		||||
	{
 | 
			
		||||
	    my $key_fullpath = "$defaultdir/$keydir";
 | 
			
		||||
	    opendir(KEYDIR, $key_fullpath)
 | 
			
		||||
		or die "Can't open $key_fullpath: $!\n";
 | 
			
		||||
	    my @propfiles = grep { -f "$key_fullpath/$_" }
 | 
			
		||||
			    grep { !/^\./ } readdir KEYDIR;
 | 
			
		||||
	    closedir(KEYDIR);
 | 
			
		||||
 | 
			
		||||
	    foreach my $propfile (@propfiles)
 | 
			
		||||
	    {
 | 
			
		||||
		my $propfile_fullpath = "$key_fullpath/$propfile";
 | 
			
		||||
		# Open each and check what the default should be.
 | 
			
		||||
		open(PROPFILE, "<$propfile_fullpath")
 | 
			
		||||
		    or die "Can't open $propfile_fullpath: $!\n";
 | 
			
		||||
		chomp( my $propval = <PROPFILE> );
 | 
			
		||||
		close(PROPFILE);
 | 
			
		||||
		if ($keydir eq 'ActiveAccounts')
 | 
			
		||||
		{
 | 
			
		||||
		    print "get_prop on $keydir, $propfile returns ";
 | 
			
		||||
		    print $db->get_prop($keydir, $propfile) . "\n";
 | 
			
		||||
		    print "propval is $propval\n";
 | 
			
		||||
		}
 | 
			
		||||
		ok( $db->get_prop($keydir, $propfile) eq $propval,
 | 
			
		||||
		    "property $propfile of record $keydir has correct $mode value of $propval" );
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# FIXME: This works, but the numbers of the tests are thrown off. We probably
 | 
			
		||||
# want to eval the test block of code instead.
 | 
			
		||||
sub run_migrate_tests
 | 
			
		||||
{
 | 
			
		||||
    my $dbhome = shift;
 | 
			
		||||
    my $dbroot = shift;
 | 
			
		||||
 | 
			
		||||
    opendir(DBROOT, $dbroot) or die "Can't open $dbroot: $!\n";
 | 
			
		||||
    my @dbfiles = grep { -d "$dbroot/$_" }
 | 
			
		||||
		grep { !/^\./ } readdir DBROOT;
 | 
			
		||||
    closedir(DBROOT);
 | 
			
		||||
    foreach my $dbfile (@dbfiles)
 | 
			
		||||
    {
 | 
			
		||||
	# Handle the defaults in this case.
 | 
			
		||||
	my $migratedir = "$dbroot/$dbfile/migrate";
 | 
			
		||||
	next if not -e $migratedir;
 | 
			
		||||
 | 
			
		||||
	opendir(MIGRATEDIR, $migratedir) or die "Can't open $migratedir: $!\n";
 | 
			
		||||
	my @migrate_fragments = grep { !/^\./ } readdir MIGRATEDIR;
 | 
			
		||||
	closedir(MIGRATEDIR);
 | 
			
		||||
 | 
			
		||||
	foreach my $migrate_fragment (sort @migrate_fragments)
 | 
			
		||||
	{
 | 
			
		||||
	    my $tempname = tmpnam() or die "Can't obtain tempfile: $!\n";
 | 
			
		||||
	    my $pod2test = '/usr/bin/pod2test';
 | 
			
		||||
	    system($pod2test, "$migratedir/$migrate_fragment", $tempname);
 | 
			
		||||
	    if (! -e $tempname)
 | 
			
		||||
	    {
 | 
			
		||||
		warn "The fragment $migrate_fragment apparently has no embedded tests\n";
 | 
			
		||||
		next;
 | 
			
		||||
	    }
 | 
			
		||||
	    system('/usr/bin/perl', $tempname);
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								root/etc/e-smith/tests/10e-smith-lib/domains.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								root/etc/e-smith/tests/10e-smith-lib/domains.conf
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
test=domain|foo|bar
 | 
			
		||||
foo=domain|baz|quux
 | 
			
		||||
wombat=notadomain
 | 
			
		||||
							
								
								
									
										11
									
								
								root/etc/e-smith/tests/10e-smith-lib/dummy.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								root/etc/e-smith/tests/10e-smith-lib/dummy.conf
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
foo=bar
 | 
			
		||||
this key=has whitespace
 | 
			
		||||
that key =has trailing whitespace
 | 
			
		||||
 another key=has leading whitespace
 | 
			
		||||
this value= has leading whitespace
 | 
			
		||||
that value=has trailing whitespace 
 | 
			
		||||
 | 
			
		||||
# this is a comment.  ignore it.
 | 
			
		||||
    # this is a comment = too
 | 
			
		||||
 | 
			
		||||
tricky value=with=equals.
 | 
			
		||||
							
								
								
									
										13
									
								
								root/etc/e-smith/tests/10e-smith-lib/hosts.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								root/etc/e-smith/tests/10e-smith-lib/hosts.conf
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
# DO NOT MODIFY THIS FILE.
 | 
			
		||||
# This file is automatically maintained by the Mitel Networks SME Server
 | 
			
		||||
# configuration software.  Manually editing this file may put your 
 | 
			
		||||
# system in an unknown state.
 | 
			
		||||
#
 | 
			
		||||
# updated: Fri Mar 11 18:21:42 2002
 | 
			
		||||
ftp.mydomain.xxx=host|ExternalIP||HostType|Self|InternalIP||MACAddress||Visibility|Local
 | 
			
		||||
mail.mydomain.xxx=host|ExternalIP||HostType|Self|InternalIP||MACAddress||Visibility|Local
 | 
			
		||||
myserver.mydomain.xxx=host|ExternalIP||HostType|Local|InternalIP||MACAddress||Visibility|Local
 | 
			
		||||
otherhost.mydomain.xxx=host|ExternalIP||HostType|Local|InternalIP|192.168.1.3|MACAddress||Visibility|Local
 | 
			
		||||
www.mydomain.xxx=host|ExternalIP||HostType|Self|InternalIP||MACAddress||Visibility|Local
 | 
			
		||||
www.otherdomain.xxx=host|ExternalIP||HostType|Self|InternalIP||MACAddress||Visibility|Local
 | 
			
		||||
foo.otherdomain.xxx=host|ExternalIP||HostType|Self|InternalIP||MACAddress||Visibility|Local
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
I am an English license.
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
Je suis une license francais. Or something like that.
 | 
			
		||||
							
								
								
									
										1
									
								
								root/etc/e-smith/tests/10e-smith-lib/networks.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								root/etc/e-smith/tests/10e-smith-lib/networks.conf
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
10.0.0.0=network|Mask|255.255.255.0|Router|default
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
sysconfig=configuration|KeyboardType|pc|Keytable|us|Language|en_US|ReleaseVersion|6.0alpha2
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
sysconfig=configuration|KeyboardType|pc|Keytable|us|Language|fr_CA|ReleaseVersion|6.0alpha2
 | 
			
		||||
							
								
								
									
										111
									
								
								root/etc/e-smith/tests/10e-smith-lib/templates.t
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								root/etc/e-smith/tests/10e-smith-lib/templates.t
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,111 @@
 | 
			
		||||
#!/usr/bin/perl -w
 | 
			
		||||
 | 
			
		||||
use esmith::TestUtils qw(scratch_copy);
 | 
			
		||||
use File::Path;
 | 
			
		||||
 | 
			
		||||
use Test::More 'no_plan';
 | 
			
		||||
 | 
			
		||||
use_ok('esmith::templates', qw(:DEFAULT removeBlankLines));
 | 
			
		||||
 | 
			
		||||
use esmith::config;
 | 
			
		||||
my %config;
 | 
			
		||||
tie %config, 'esmith::config', '10e-smith-lib/scratch.conf';
 | 
			
		||||
$ENV{ESMITH_CONFIG_DB} = '10e-smith-lib/scratch.conf';
 | 
			
		||||
END { unlink '10e-smith-lib/scratch.conf' }
 | 
			
		||||
 | 
			
		||||
my $Scratch_Temp_Dir = 'template_scratch_dir';
 | 
			
		||||
my $Scratch_Temp = "$Scratch_Temp_Dir/dummy";
 | 
			
		||||
mkpath "$Scratch_Temp_Dir/10e-smith-lib";
 | 
			
		||||
END { rmtree $Scratch_Temp_Dir }
 | 
			
		||||
 | 
			
		||||
# processTemplate() is going to be Loud and Helpful about skipping
 | 
			
		||||
# things like CVS directories.
 | 
			
		||||
$SIG{__WARN__} = sub { return if $_[0] =~ /^Skipping directory/ };
 | 
			
		||||
 | 
			
		||||
$config{Koala_Say} = "This is not the bear you're looking for.";
 | 
			
		||||
processTemplate({ CONFREF => \%config, 
 | 
			
		||||
                  OUTPUT_PREFIX   => $Scratch_Temp_Dir,
 | 
			
		||||
                  OUTPUT_FILENAME => 'dummy',
 | 
			
		||||
                  TEMPLATE_PATH => 'templates',
 | 
			
		||||
                  TEMPLATE_EXPAND_QUEUE => [
 | 
			
		||||
                      '10e-smith-lib'
 | 
			
		||||
                  ],
 | 
			
		||||
                  FILTER => \&removeBlankLines,
 | 
			
		||||
                  UID => $<,
 | 
			
		||||
                  GID => (split / /, $()[0]
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
ok( -f $Scratch_Temp,   'file generated' );
 | 
			
		||||
ok( -s $Scratch_Temp,   '  its not empty' );
 | 
			
		||||
 | 
			
		||||
open(SCRATCH, $Scratch_Temp) || die $!;
 | 
			
		||||
my $out;
 | 
			
		||||
{ local $/; $out = <SCRATCH>; }
 | 
			
		||||
close SCRATCH;
 | 
			
		||||
 | 
			
		||||
my $koala_output = <<'THIS';
 | 
			
		||||
# This is the beginning of the beginning
 | 
			
		||||
# confref ok
 | 
			
		||||
  ----------------------------------------
 | 
			
		||||
< This is not the bear you're looking for. >
 | 
			
		||||
  ----------------------------------------
 | 
			
		||||
  \
 | 
			
		||||
   \          .
 | 
			
		||||
       ___   //
 | 
			
		||||
     {~._.~}// 
 | 
			
		||||
      ( Y )K/  
 | 
			
		||||
     ()~*~()   
 | 
			
		||||
     (_)-(_)   
 | 
			
		||||
     Luke    
 | 
			
		||||
     Skywalker
 | 
			
		||||
     koala   
 | 
			
		||||
# This is the end, My only friend, the end of our elaborate templates, the end
 | 
			
		||||
THIS
 | 
			
		||||
 | 
			
		||||
is( $out, $koala_output,   'file generated properly' );
 | 
			
		||||
 | 
			
		||||
$out = processTemplate({ 
 | 
			
		||||
                  CONFREF => \%config, 
 | 
			
		||||
                  TEMPLATE_PATH => 'templates',
 | 
			
		||||
                  TEMPLATE_EXPAND_QUEUE => [
 | 
			
		||||
                      '10e-smith-lib'
 | 
			
		||||
                  ],
 | 
			
		||||
                  FILTER => sub { $_[0] =~ /^\s*$/ ? '' : $_[0] },
 | 
			
		||||
                  UID => $<,
 | 
			
		||||
                  GID => (split / /, $()[0],
 | 
			
		||||
                  OUTPUT_TYPE => 'string'
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
is( $out, $koala_output,   'string generated properly' );
 | 
			
		||||
 | 
			
		||||
my $h_scratch = scratch_copy('10e-smith-lib/hosts.conf');
 | 
			
		||||
my $a_scratch = scratch_copy('10e-smith-lib/accounts.conf');
 | 
			
		||||
use esmith::AccountsDB;
 | 
			
		||||
use esmith::HostsDB;
 | 
			
		||||
my $acct = esmith::AccountsDB->open($a_scratch);
 | 
			
		||||
my $host = esmith::HostsDB->open($h_scratch);
 | 
			
		||||
$out = processTemplate({
 | 
			
		||||
                  MORE_DATA => { Author => 'Douglas Adams' },
 | 
			
		||||
                  TEMPLATE_PATH => 'templates_DB',
 | 
			
		||||
                  TEMPLATE_EXPAND_QUEUE => [
 | 
			
		||||
                      '10e-smith-lib'
 | 
			
		||||
                  ],
 | 
			
		||||
                  OUTPUT_TYPE => 'string'
 | 
			
		||||
                });
 | 
			
		||||
is( $out, <<'THIS', 'DB & MORE_DATA' );
 | 
			
		||||
                        Chapter 1
 | 
			
		||||
 | 
			
		||||
The story so far:
 | 
			
		||||
 | 
			
		||||
        In the beginning the Universe was created.  This has made a lot
 | 
			
		||||
of people very angry and been widely regarded as a bad move.
 | 
			
		||||
                -- Douglas Adams
 | 
			
		||||
 | 
			
		||||
$DB ok
 | 
			
		||||
default vars ok
 | 
			
		||||
 | 
			
		||||
confref not defined
 | 
			
		||||
 | 
			
		||||
The end of labor is to gain leisure.
 | 
			
		||||
THIS
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										20
									
								
								root/etc/e-smith/tests/10e-smith-lib/templates/10moof
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								root/etc/e-smith/tests/10e-smith-lib/templates/10moof
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
{
 | 
			
		||||
    my $ksez = $Koala_Say;
 | 
			
		||||
    my $line = '-' x length $ksez;
 | 
			
		||||
 | 
			
		||||
    $OUT = <<KOALA_SEZ;
 | 
			
		||||
  $line
 | 
			
		||||
< $ksez >
 | 
			
		||||
  $line
 | 
			
		||||
KOALA_SEZ
 | 
			
		||||
}
 | 
			
		||||
  \
 | 
			
		||||
   \          .
 | 
			
		||||
       ___   //
 | 
			
		||||
     \{~._.~\}// 
 | 
			
		||||
      ( Y )K/  
 | 
			
		||||
     ()~*~()   
 | 
			
		||||
     (_)-(_)   
 | 
			
		||||
     Luke    
 | 
			
		||||
     Skywalker
 | 
			
		||||
     koala   
 | 
			
		||||
@@ -0,0 +1,3 @@
 | 
			
		||||
# This is the beginning of the beginning
 | 
			
		||||
# { keys %$confref == 1 && exists $confref->{Koala_Say}
 | 
			
		||||
         ? "confref ok" : "confref not ok" }
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
# This is the end, My only friend, the end of our elaborate templates, the end
 | 
			
		||||
							
								
								
									
										20
									
								
								root/etc/e-smith/tests/10e-smith-lib/templates2/10moof
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								root/etc/e-smith/tests/10e-smith-lib/templates2/10moof
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
{
 | 
			
		||||
    my $ksez = $Koala_Say;
 | 
			
		||||
    my $line = '-' x length $ksez;
 | 
			
		||||
 | 
			
		||||
    $OUT = <<KOALA_SEZ;
 | 
			
		||||
  $line
 | 
			
		||||
< $ksez >
 | 
			
		||||
  $line
 | 
			
		||||
KOALA_SEZ
 | 
			
		||||
}
 | 
			
		||||
  \
 | 
			
		||||
   \          .
 | 
			
		||||
       ___   //
 | 
			
		||||
     \{~._.~\}// 
 | 
			
		||||
      ( Y )K/  
 | 
			
		||||
     ()~*~()   
 | 
			
		||||
     (_)-(_)   
 | 
			
		||||
     Luke    
 | 
			
		||||
     Skywalker
 | 
			
		||||
     koala   
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
# This is the end, My only friend, the end of our elaborate templates, the end
 | 
			
		||||
							
								
								
									
										9
									
								
								root/etc/e-smith/tests/10e-smith-lib/templates_DB/10DB
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								root/etc/e-smith/tests/10e-smith-lib/templates_DB/10DB
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
{ '$DB ok' if defined $DB && $DB->isa('esmith::ConfigDB') }
 | 
			
		||||
{ my $ok = 1;
 | 
			
		||||
  foreach my $rec ($DB->get_all) {
 | 
			
		||||
    my $key = $rec->key;
 | 
			
		||||
    my $type = $rec->props <= 1 ? "SCALAR" : "HASH";
 | 
			
		||||
    $ok = 0 unless *{$key}{$type};
 | 
			
		||||
  }
 | 
			
		||||
  'default vars ok' if $ok;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,7 @@
 | 
			
		||||
 | 
			
		||||
{ if( *{confref}{SCALAR} ) {
 | 
			
		||||
    "confref not defined";
 | 
			
		||||
  } else {
 | 
			
		||||
    "confref defined" 
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,10 @@
 | 
			
		||||
                        Chapter 1
 | 
			
		||||
 | 
			
		||||
The story so far:
 | 
			
		||||
 | 
			
		||||
        In the beginning the Universe was created.  This has made a lot
 | 
			
		||||
of people very angry and been widely regarded as a bad move.
 | 
			
		||||
                -- { # Testing MORE_DATA
 | 
			
		||||
                     $Author 
 | 
			
		||||
                   }
 | 
			
		||||
 | 
			
		||||
@@ -0,0 +1,2 @@
 | 
			
		||||
 | 
			
		||||
The end of labor is to gain leisure.
 | 
			
		||||
							
								
								
									
										112
									
								
								root/etc/e-smith/tests/10e-smith-lib/uidgid.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								root/etc/e-smith/tests/10e-smith-lib/uidgid.conf
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,112 @@
 | 
			
		||||
# This file stores uid/gid information from the CreatingSystemUsers topic of 
 | 
			
		||||
# the Engineering Wiki. It is read by the uidgid.t test script. Please keep it
 | 
			
		||||
# up to date.
 | 
			
		||||
[passwd]
 | 
			
		||||
0  root  0
 | 
			
		||||
1 bin 1
 | 
			
		||||
2 daemon 2
 | 
			
		||||
3 adm 4
 | 
			
		||||
4 lp 7
 | 
			
		||||
8 mail 12
 | 
			
		||||
9 news 13
 | 
			
		||||
10 uucp 14
 | 
			
		||||
11 operator 0
 | 
			
		||||
12 games 100
 | 
			
		||||
13 gopher 30
 | 
			
		||||
14 ftp 50
 | 
			
		||||
23 squid 23
 | 
			
		||||
27 mysql 27
 | 
			
		||||
32 rpc 32
 | 
			
		||||
37 rpm 37
 | 
			
		||||
38 ntp 38
 | 
			
		||||
48 apache 48
 | 
			
		||||
53 dns 53
 | 
			
		||||
55 ldap 55
 | 
			
		||||
69 vcsa 69
 | 
			
		||||
74 sshd 74
 | 
			
		||||
77 pcap 77
 | 
			
		||||
99 nobody 99
 | 
			
		||||
100 www 101
 | 
			
		||||
101 admin 101
 | 
			
		||||
102 public 103
 | 
			
		||||
400 alias 400
 | 
			
		||||
401 qmaild 400
 | 
			
		||||
402 qmaill 400
 | 
			
		||||
403 qmailp 400
 | 
			
		||||
404 qmailq 401
 | 
			
		||||
405 qmailr 401
 | 
			
		||||
406 qmails 401
 | 
			
		||||
407 qmailscan 407
 | 
			
		||||
408 jabber 408
 | 
			
		||||
410 dnscache 410
 | 
			
		||||
411 dnslog 411
 | 
			
		||||
420 nutups 420
 | 
			
		||||
421 trend 421
 | 
			
		||||
422 fax 422
 | 
			
		||||
451 stunnel 451
 | 
			
		||||
452 memtestlog 452
 | 
			
		||||
1001 imaplog 1001
 | 
			
		||||
1002 smelog 1002
 | 
			
		||||
1003 cvmlog 1003
 | 
			
		||||
1004 mn_dvr 1004
 | 
			
		||||
1005 spamd 1005
 | 
			
		||||
2999 smelastsys 2999
 | 
			
		||||
 | 
			
		||||
[group]
 | 
			
		||||
0  root
 | 
			
		||||
1 bin
 | 
			
		||||
2 daemon
 | 
			
		||||
3 sys
 | 
			
		||||
4 adm
 | 
			
		||||
5 tty
 | 
			
		||||
6 disk
 | 
			
		||||
7 lp
 | 
			
		||||
8 mem
 | 
			
		||||
9 kmem
 | 
			
		||||
10 wheel
 | 
			
		||||
12 mail
 | 
			
		||||
13 news
 | 
			
		||||
14 uucp
 | 
			
		||||
15 man
 | 
			
		||||
19 floppy
 | 
			
		||||
20 games
 | 
			
		||||
21 slocate
 | 
			
		||||
22 utmp
 | 
			
		||||
23 squid
 | 
			
		||||
27 mysql
 | 
			
		||||
30 gopher
 | 
			
		||||
32 rpc
 | 
			
		||||
37 rpm
 | 
			
		||||
38 ntp
 | 
			
		||||
40 dip
 | 
			
		||||
48 apache
 | 
			
		||||
50 ftp
 | 
			
		||||
53 dns
 | 
			
		||||
54 lock
 | 
			
		||||
55 ldap
 | 
			
		||||
69 vcsa
 | 
			
		||||
74 sshd
 | 
			
		||||
77 pcap
 | 
			
		||||
99 nobody
 | 
			
		||||
100 users
 | 
			
		||||
101 admin
 | 
			
		||||
102 www
 | 
			
		||||
103 public
 | 
			
		||||
400 nofiles
 | 
			
		||||
401 qmail
 | 
			
		||||
407 qmailscan
 | 
			
		||||
408 jabber
 | 
			
		||||
410 dnscache
 | 
			
		||||
411 dnslog
 | 
			
		||||
420 nutups
 | 
			
		||||
421 trend
 | 
			
		||||
422 fax
 | 
			
		||||
451 stunnel
 | 
			
		||||
452 memtestlog
 | 
			
		||||
500 shared
 | 
			
		||||
1001 imaplog
 | 
			
		||||
1002 smelog
 | 
			
		||||
1003 cvmlog
 | 
			
		||||
1004 mn_dvr
 | 
			
		||||
1005 spamd
 | 
			
		||||
2999 smelastsys
 | 
			
		||||
							
								
								
									
										78
									
								
								root/etc/e-smith/tests/10e-smith-lib/uidgid.t
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								root/etc/e-smith/tests/10e-smith-lib/uidgid.t
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
#!/usr/bin/perl -w
 | 
			
		||||
# vim: ft=perl:
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use Test::More 'no_plan';
 | 
			
		||||
use Unix::PasswdFile;
 | 
			
		||||
use Unix::GroupFile;
 | 
			
		||||
 | 
			
		||||
use constant TRUE  => 1;
 | 
			
		||||
use constant FALSE => 0;
 | 
			
		||||
 | 
			
		||||
my $conffile = 'uidgid.conf';
 | 
			
		||||
 | 
			
		||||
exit 1 if not -e $conffile;
 | 
			
		||||
 | 
			
		||||
my %passwdlist = ();
 | 
			
		||||
my %grouplist  = ();
 | 
			
		||||
my $passwd = FALSE;
 | 
			
		||||
my $group = FALSE;
 | 
			
		||||
 | 
			
		||||
open(CONF, "<$conffile") or die "Can't open $conffile: $!\n";
 | 
			
		||||
 | 
			
		||||
while(<CONF>)
 | 
			
		||||
{
 | 
			
		||||
    next if /^(#|\s)/;
 | 
			
		||||
    if (/\[passwd]/)
 | 
			
		||||
    {
 | 
			
		||||
	$passwd = TRUE;
 | 
			
		||||
	next;
 | 
			
		||||
    }
 | 
			
		||||
    elsif (/\[group]/)
 | 
			
		||||
    {
 | 
			
		||||
	$group = TRUE;
 | 
			
		||||
	$passwd = FALSE;
 | 
			
		||||
	next;
 | 
			
		||||
    }
 | 
			
		||||
    next if not $passwd and not $group;
 | 
			
		||||
 | 
			
		||||
    if ($passwd)
 | 
			
		||||
    {
 | 
			
		||||
	my ($uid, $name, $gid) = split;
 | 
			
		||||
	$passwdlist{$name}{uid} = $uid;
 | 
			
		||||
	$passwdlist{$name}{gid} = $gid;
 | 
			
		||||
    }
 | 
			
		||||
    elsif ($group)
 | 
			
		||||
    {
 | 
			
		||||
	my ($gid, $name) = split;
 | 
			
		||||
	$grouplist{$name} = $gid;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
close(CONF);
 | 
			
		||||
 | 
			
		||||
# We can now confirm the uid and gid of every user, and the gid of every
 | 
			
		||||
# group, on the system.
 | 
			
		||||
# I don't know of a good way to query every user on the system, so for now
 | 
			
		||||
# lets just read them from the passwd file.
 | 
			
		||||
my $pw = Unix::PasswdFile->new('/etc/passwd', mode => 'r')
 | 
			
		||||
	or die "Can't open /etc/passwd: $!\n";
 | 
			
		||||
 | 
			
		||||
foreach my $user ($pw->users)
 | 
			
		||||
{
 | 
			
		||||
    my ($name,$passwd,$uid,$gid,undef) = getpwnam($user);
 | 
			
		||||
    ok( exists $passwdlist{$name}, "user $name is on our list" );
 | 
			
		||||
    ok( $uid == $passwdlist{$name}{uid}, "user $name has uid of $uid" );
 | 
			
		||||
    ok( $gid == $passwdlist{$name}{gid}, "user $name has gid of $gid" );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
my $gr = Unix::GroupFile->new('/etc/group', mode => 'r')
 | 
			
		||||
	or die "Can't open /etc/group: $!\n";
 | 
			
		||||
 | 
			
		||||
foreach my $group ($gr->groups)
 | 
			
		||||
{
 | 
			
		||||
    my ($name,$passwd,$gid,$members) = getgrnam($group);
 | 
			
		||||
    ok( exists $grouplist{$name}, "group $name is on our list" );
 | 
			
		||||
    ok( $gid == $grouplist{$name}, "group $group has gid of $gid" );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exit 0;
 | 
			
		||||
							
								
								
									
										10
									
								
								root/sbin/e-smith/config
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										10
									
								
								root/sbin/e-smith/config
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
#!/usr/bin/perl -w
 | 
			
		||||
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
exec "/sbin/e-smith/db", "configuration", @ARGV;
 | 
			
		||||
die "Could not exec /sbin/e-smith/db";
 | 
			
		||||
							
								
								
									
										84
									
								
								root/sbin/e-smith/create-system-user
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								root/sbin/e-smith/create-system-user
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
			
		||||
#! /usr/bin/perl -w
 | 
			
		||||
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
 | 
			
		||||
sub usage
 | 
			
		||||
{
 | 
			
		||||
    my $msg = shift;
 | 
			
		||||
    warn("$msg\n") if $msg;
 | 
			
		||||
    die("Usage: $0: user userid descr home_dir shell\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
my $user = shift || usage("Must give username param");
 | 
			
		||||
my $uid = shift || usage("Must give userid param");
 | 
			
		||||
my $user_desc = shift || usage("Must give user desc param");
 | 
			
		||||
my $home = shift || usage("Must give home param");
 | 
			
		||||
my $shell = shift || usage("Must give shell param");
 | 
			
		||||
 | 
			
		||||
use User::pwent;
 | 
			
		||||
use User::grent;
 | 
			
		||||
 | 
			
		||||
if (my $pw = getpwnam($user))
 | 
			
		||||
{
 | 
			
		||||
    my $euid = $pw->uid;
 | 
			
		||||
    exit 0 if $euid == $uid; # Do not create user if it already exists with correct uid
 | 
			
		||||
    warn ("Users $user exists but has uid of $euid - should be $uid\n");
 | 
			
		||||
    exit 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if (my $pw = getpwuid($uid))       
 | 
			
		||||
{
 | 
			
		||||
    my $name = $pw->name;
 | 
			
		||||
    warn "User id of $uid is already taken by user $name\n";
 | 
			
		||||
    warn "Falling back to a system chosen uid\n";
 | 
			
		||||
    # We can now go ahead and create the user and group leaving the system to choose uid/gid
 | 
			
		||||
    die ("Failed to create user $user\n") if
 | 
			
		||||
          system("/usr/sbin/useradd",
 | 
			
		||||
		     "-r",
 | 
			
		||||
		     "-d", $home,
 | 
			
		||||
		     "-M",
 | 
			
		||||
		     "-s", $shell,
 | 
			
		||||
		     "-c", $user_desc,
 | 
			
		||||
		     $user);
 | 
			
		||||
    exit (0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if (my $pw = getgrgid($uid))       
 | 
			
		||||
{
 | 
			
		||||
    my $name = $pw->name;
 | 
			
		||||
    warn "Group id of $uid is already taken by user $name\n";
 | 
			
		||||
    # We can now go ahead and create the user but the gid will be chosen by the system
 | 
			
		||||
    die ("Failed to create user $user\n") if
 | 
			
		||||
          system("/usr/sbin/useradd",
 | 
			
		||||
		     "-u", $uid,
 | 
			
		||||
		     "-d", $home,
 | 
			
		||||
		     "-M",
 | 
			
		||||
		     "-s", $shell,
 | 
			
		||||
		     "-c", $user_desc,
 | 
			
		||||
		     $user);
 | 
			
		||||
}
 | 
			
		||||
else
 | 
			
		||||
{
 | 
			
		||||
# We can now go ahead and create the user and group
 | 
			
		||||
    die ("Failed to create group $uid\n") if
 | 
			
		||||
          system("/usr/sbin/groupadd",
 | 
			
		||||
	     	"-g", $uid,
 | 
			
		||||
	     	$user);
 | 
			
		||||
 | 
			
		||||
    die ("Failed to create user $user\n") if
 | 
			
		||||
          system("/usr/sbin/useradd",
 | 
			
		||||
	     	"-u", $uid,
 | 
			
		||||
              "-g", $uid,
 | 
			
		||||
	     	"-d", $home,
 | 
			
		||||
	     	"-M",
 | 
			
		||||
	     	"-s", $shell,
 | 
			
		||||
	     	"-c", $user_desc,
 | 
			
		||||
	     	$user);
 | 
			
		||||
}
 | 
			
		||||
exit 0;
 | 
			
		||||
							
								
								
									
										344
									
								
								root/sbin/e-smith/db
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										344
									
								
								root/sbin/e-smith/db
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,344 @@
 | 
			
		||||
#!/usr/bin/perl -w
 | 
			
		||||
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use esmith::config;
 | 
			
		||||
use esmith::db;
 | 
			
		||||
 | 
			
		||||
#--------------------------------------------------------------------------
 | 
			
		||||
# Set up the command list and usage strings
 | 
			
		||||
 | 
			
		||||
my %commands = (
 | 
			
		||||
	'keys'
 | 
			
		||||
	    =>	{
 | 
			
		||||
		    'function'	=>	\&DB_keys,
 | 
			
		||||
		    'usage'	=>	"$0 dbfile keys",
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
	'print'
 | 
			
		||||
	    =>	{
 | 
			
		||||
		    'function'	=>	\&DB_print,
 | 
			
		||||
		    'usage'	=>	"$0 dbfile print [key]",
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
	'show'
 | 
			
		||||
	    =>	{
 | 
			
		||||
		    'function'	=>	\&DB_show,
 | 
			
		||||
		    'usage'	=>	"$0 dbfile show [key]",
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
	'get'
 | 
			
		||||
	    =>	{
 | 
			
		||||
		    'function'	=>	\&DB_get,
 | 
			
		||||
		    'usage'	=>	"$0 dbfile get key",
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
	'set'
 | 
			
		||||
	    =>	{
 | 
			
		||||
		    'function'	=>	\&DB_set,
 | 
			
		||||
		    'usage'	=>	"$0 dbfile set key type "
 | 
			
		||||
		    			. "[prop1 val1] [prop2 val2] ...",
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
	'setdefault'
 | 
			
		||||
	    =>	{
 | 
			
		||||
		    'function'	=>	\&DB_set_default,
 | 
			
		||||
		    'usage'	=>	"$0 dbfile setdefault key type "
 | 
			
		||||
		    			. "[prop1 val1] [prop2 val2] ...",
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
	'delete'
 | 
			
		||||
	    =>	{
 | 
			
		||||
		    'function'	=>	\&DB_delete,
 | 
			
		||||
		    'usage'	=>	"$0 dbfile delete key",
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
	'printtype'
 | 
			
		||||
	    =>	{
 | 
			
		||||
		    'function'	=>	\&DB_printtype,
 | 
			
		||||
		    'usage'	=>	"$0 dbfile printtype [key]",
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
	'gettype'
 | 
			
		||||
	    =>	{
 | 
			
		||||
		    'function'	=>	\&DB_gettype,
 | 
			
		||||
		    'usage'	=>	"$0 dbfile gettype key",
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
	'settype'
 | 
			
		||||
	    =>	{
 | 
			
		||||
		    'function'	=>	\&DB_settype,
 | 
			
		||||
		    'usage'	=>	"$0 dbfile settype key type",
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
	'printprop'
 | 
			
		||||
	    =>	{
 | 
			
		||||
		    'function'	=>	\&DB_printprop,
 | 
			
		||||
		    'usage'	=>	"$0 dbfile printprop key [prop1] "
 | 
			
		||||
					. "[prop2] [prop3] ...",
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
	'getprop'
 | 
			
		||||
	    =>	{
 | 
			
		||||
		    'function'	=>	\&DB_getprop,
 | 
			
		||||
		    'usage'	=>	"$0 dbfile getprop key prop",
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
	'setprop'
 | 
			
		||||
	    =>	{
 | 
			
		||||
		    'function'	=>	\&DB_setprop,
 | 
			
		||||
		    'usage'	=>	"$0 dbfile setprop key "
 | 
			
		||||
					. "prop1 val1 [prop2 val2] "
 | 
			
		||||
					. "[prop3 val3] ...",
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
	'delprop'
 | 
			
		||||
	    =>	{
 | 
			
		||||
		    'function'	=>	\&DB_delprop,
 | 
			
		||||
		    'usage'	=>	"$0 dbfile delprop key prop1 "
 | 
			
		||||
					. "[prop2] [prop3] ...",
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
#--------------------------------------------------------------------------
 | 
			
		||||
# Set up general usage message.
 | 
			
		||||
 | 
			
		||||
my $usage = "usage:
 | 
			
		||||
    $commands{'keys'}{'usage'}
 | 
			
		||||
    $commands{'print'}{'usage'}
 | 
			
		||||
    $commands{'show'}{'usage'}
 | 
			
		||||
    $commands{'get'}{'usage'}
 | 
			
		||||
    $commands{'set'}{'usage'}
 | 
			
		||||
    $commands{'setdefault'}{'usage'}
 | 
			
		||||
    $commands{'delete'}{'usage'}
 | 
			
		||||
    $commands{'printtype'}{'usage'}
 | 
			
		||||
    $commands{'gettype'}{'usage'}
 | 
			
		||||
    $commands{'settype'}{'usage'}
 | 
			
		||||
    $commands{'printprop'}{'usage'}
 | 
			
		||||
    $commands{'getprop'}{'usage'}
 | 
			
		||||
    $commands{'setprop'}{'usage'}
 | 
			
		||||
    $commands{'delprop'}{'usage'}
 | 
			
		||||
";
 | 
			
		||||
 | 
			
		||||
#--------------------------------------------------------------------------
 | 
			
		||||
# Prepend $ENV{'DBPATH'} to dbfile if defined otherwise let the library
 | 
			
		||||
# deal with it.
 | 
			
		||||
 | 
			
		||||
my $dbfile = shift;
 | 
			
		||||
die $usage unless $dbfile;
 | 
			
		||||
 | 
			
		||||
my $dbpath = $ENV{'DBPATH'};
 | 
			
		||||
$dbfile = "$dbpath/$dbfile" if defined $dbpath;
 | 
			
		||||
 | 
			
		||||
#--------------------------------------------------------------------------
 | 
			
		||||
# Tie the databasefile to a hash
 | 
			
		||||
 | 
			
		||||
my $db = esmith::db->open($dbfile);
 | 
			
		||||
 | 
			
		||||
#--------------------------------------------------------------------------
 | 
			
		||||
# Run the appropriate command
 | 
			
		||||
 | 
			
		||||
my $command = shift;
 | 
			
		||||
die $usage unless $command;
 | 
			
		||||
die $usage unless exists $commands{$command};
 | 
			
		||||
$commands{$command}{'function'}->(@ARGV);
 | 
			
		||||
 | 
			
		||||
exit 0;
 | 
			
		||||
 | 
			
		||||
#--------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
sub DB_print
 | 
			
		||||
{
 | 
			
		||||
    my $key = shift;
 | 
			
		||||
 | 
			
		||||
    if (defined $key)
 | 
			
		||||
    {
 | 
			
		||||
	$db->print($key) ? exit 0 : exit 1;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
	$db->print() ? exit 0 : exit 1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub DB_keys
 | 
			
		||||
{
 | 
			
		||||
    my @keys = $db->get();
 | 
			
		||||
 | 
			
		||||
    exit 1 unless (scalar @keys);
 | 
			
		||||
    print join("\n", @keys), "\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub DB_show
 | 
			
		||||
{
 | 
			
		||||
    my $key = shift;
 | 
			
		||||
 | 
			
		||||
    if (defined $key)
 | 
			
		||||
    {
 | 
			
		||||
	$db->show($key) ? exit 0 : exit 1;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
	$db->show() ? exit 0 : exit 1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub DB_get
 | 
			
		||||
{
 | 
			
		||||
    my $key = shift;
 | 
			
		||||
    die "$commands{'get'}{'usage'}\n" unless $key;
 | 
			
		||||
 | 
			
		||||
    my $value = $db->get($key);
 | 
			
		||||
    exit 1 unless defined $value;
 | 
			
		||||
    print "$value\n" if defined $value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub DB_set
 | 
			
		||||
{
 | 
			
		||||
    my $key = shift;
 | 
			
		||||
    die "$commands{'set'}{'usage'}\n" unless $key;
 | 
			
		||||
    die "$commands{'set'}{'usage'}\n" unless scalar @_;
 | 
			
		||||
 | 
			
		||||
    my $type = shift;
 | 
			
		||||
    die "$commands{'set'}{'usage'}\n" unless defined $type;
 | 
			
		||||
    die "$commands{'set'}{'usage'}\n" if scalar @_ % 2;
 | 
			
		||||
 | 
			
		||||
    $db->set($key, $type) or exit 1;
 | 
			
		||||
 | 
			
		||||
    &DB_setprop($key, @_) if scalar @_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub DB_set_default
 | 
			
		||||
{
 | 
			
		||||
    my $key = shift;
 | 
			
		||||
    die "$commands{'setdefault'}{'usage'}\n" unless $key;
 | 
			
		||||
    die "$commands{'setdefault'}{'usage'}\n" unless scalar @_;
 | 
			
		||||
 | 
			
		||||
    my $type = shift;
 | 
			
		||||
    die "$commands{'setdefault'}{'usage'}\n" unless $type;
 | 
			
		||||
    die "$commands{'setdefault'}{'usage'}\n" if scalar @_ % 2;
 | 
			
		||||
 | 
			
		||||
    # Only set values if the key does not exist
 | 
			
		||||
 | 
			
		||||
    exit 0 if defined $db->get($key);
 | 
			
		||||
 | 
			
		||||
    &DB_set($key, $type, @_);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub DB_delete
 | 
			
		||||
{
 | 
			
		||||
    my $key = shift;
 | 
			
		||||
    die "$commands{'delete'}{'usage'}\n" unless $key;
 | 
			
		||||
 | 
			
		||||
    $db->delete($key) ? exit 0 : exit 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub DB_printtype
 | 
			
		||||
{
 | 
			
		||||
    my $key = shift;
 | 
			
		||||
 | 
			
		||||
    if (defined $key)
 | 
			
		||||
    {
 | 
			
		||||
	$db->print_type($key) ? exit 0 : exit 1;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
	$db->print_type() ? exit 0 : exit 1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub DB_gettype
 | 
			
		||||
{
 | 
			
		||||
    my $key = shift;
 | 
			
		||||
    die "$commands{'get'}{'usage'}\n" unless $key;
 | 
			
		||||
 | 
			
		||||
    my $value = $db->get_type($key);
 | 
			
		||||
    exit 1 unless defined $value;
 | 
			
		||||
    print "$value\n" if defined $value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub DB_settype
 | 
			
		||||
{
 | 
			
		||||
    my $key = shift;
 | 
			
		||||
    die "$commands{'settype'}{'usage'}\n" unless $key;
 | 
			
		||||
    my $type = shift;
 | 
			
		||||
    die "$commands{'settype'}{'usage'}\n" unless $type;
 | 
			
		||||
 | 
			
		||||
    $db->set_type($key, $type) ? exit 0 : exit 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub DB_printprop
 | 
			
		||||
{
 | 
			
		||||
    my $key = shift;
 | 
			
		||||
    die "$commands{'printprop'}{'usage'}\n" unless $key;
 | 
			
		||||
 | 
			
		||||
    my @props = @_;
 | 
			
		||||
 | 
			
		||||
    if (scalar @props)
 | 
			
		||||
    {
 | 
			
		||||
	foreach (@props)
 | 
			
		||||
	{
 | 
			
		||||
	    $db->print_prop($key, $_)
 | 
			
		||||
		if defined $db->get_prop($key, $_);
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
	$db->print_prop($key)  ? exit 0 : exit 1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub DB_getprop
 | 
			
		||||
{
 | 
			
		||||
    my $key = shift;
 | 
			
		||||
    die "$commands{'getprop'}{'usage'}\n" unless $key;
 | 
			
		||||
 | 
			
		||||
    my $prop = shift;
 | 
			
		||||
    die "$commands{'getprop'}{'usage'}\n" unless scalar $prop;
 | 
			
		||||
 | 
			
		||||
    my $val = $db->get_prop($key, $prop);
 | 
			
		||||
 | 
			
		||||
    if (defined $val)
 | 
			
		||||
    {
 | 
			
		||||
	print "$val\n";
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
	exit 1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub DB_setprop
 | 
			
		||||
{
 | 
			
		||||
    my $key = shift;
 | 
			
		||||
    die "$commands{'setprop'}{'usage'}\n" unless $key;
 | 
			
		||||
    die "$commands{'setprop'}{'usage'}\n" unless scalar @_;
 | 
			
		||||
    die "$commands{'setprop'}{'usage'}\n" if scalar @_ % 2;
 | 
			
		||||
 | 
			
		||||
    my %properties = @_;
 | 
			
		||||
 | 
			
		||||
    foreach (sort keys %properties)
 | 
			
		||||
    {
 | 
			
		||||
	$db->set_prop($key, $_, $properties{$_});
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub DB_delprop
 | 
			
		||||
{
 | 
			
		||||
    my $key = shift;
 | 
			
		||||
    die "$commands{'delprop'}{'usage'}\n" unless $key;
 | 
			
		||||
    die "$commands{'delprop'}{'usage'}\n" unless scalar @_;
 | 
			
		||||
 | 
			
		||||
    foreach (@_)
 | 
			
		||||
    {
 | 
			
		||||
	$db->delete_prop($key, $_);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								root/sbin/e-smith/expand-template
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								root/sbin/e-smith/expand-template
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
#!/usr/bin/perl -w
 | 
			
		||||
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2004 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use Errno;
 | 
			
		||||
use Getopt::Long;
 | 
			
		||||
use esmith::templates;
 | 
			
		||||
 | 
			
		||||
my %options = ();
 | 
			
		||||
 | 
			
		||||
GetOptions(\%options, 'output_filename=s', 'expand_queue=s');
 | 
			
		||||
 | 
			
		||||
$options{'template_path'} = $ARGV[0] || die "Usage: $0 /path/to/file/to/expand\n";
 | 
			
		||||
 | 
			
		||||
$options{'output_filename'} = $options{'template_path'}
 | 
			
		||||
    unless ( exists $options{'output_filename'} );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
my %args = ( 
 | 
			
		||||
		TEMPLATE_PATH   => $options{'template_path'},
 | 
			
		||||
		OUTPUT_FILENAME => $options{'output_filename'},
 | 
			
		||||
	    );
 | 
			
		||||
 | 
			
		||||
$args{TEMPLATE_EXPAND_QUEUE} = [$options{'expand_queue'}] 
 | 
			
		||||
  if exists $options{expand_queue};
 | 
			
		||||
 | 
			
		||||
if ( -f $options{'output_filename'} )
 | 
			
		||||
{
 | 
			
		||||
    # If the target file exists, preserve its ownership and mode
 | 
			
		||||
    use File::stat;
 | 
			
		||||
 | 
			
		||||
    my $f = stat($options{'output_filename'} );
 | 
			
		||||
    $args{UID}   = $f->uid;
 | 
			
		||||
    $args{GID}   = $f->gid;
 | 
			
		||||
    $args{PERMS} = $f->mode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
esmith::templates::processTemplate(\%args);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										24
									
								
								root/sbin/e-smith/signal-event
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								root/sbin/e-smith/signal-event
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
#!/usr/bin/perl -w
 | 
			
		||||
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use Getopt::Long;
 | 
			
		||||
use esmith::event;
 | 
			
		||||
 | 
			
		||||
my $usage = "usage:
 | 
			
		||||
    $0 eventname [arg1 [arg2...]]
 | 
			
		||||
";
 | 
			
		||||
 | 
			
		||||
my ($event, @args) = @ARGV;
 | 
			
		||||
die $usage unless $event;
 | 
			
		||||
 | 
			
		||||
my $exitcode = event_signal($event, @args);
 | 
			
		||||
 | 
			
		||||
# reverse exitcode for command-line usage
 | 
			
		||||
exit ($exitcode ? 0 : 1);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										540
									
								
								root/usr/share/perl5/vendor_perl/esmith/AccountsDB.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										540
									
								
								root/usr/share/perl5/vendor_perl/esmith/AccountsDB.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,540 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::AccountsDB;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use warnings;
 | 
			
		||||
use esmith::db;
 | 
			
		||||
 | 
			
		||||
use vars qw( $AUTOLOAD @ISA );
 | 
			
		||||
 | 
			
		||||
use esmith::DB::db;
 | 
			
		||||
@ISA = qw(esmith::DB::db);
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::AccountsDB - interface to esmith configuration database
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
    use esmith::AccountsDB;
 | 
			
		||||
    my $a = esmith::AccountsDB->open;
 | 
			
		||||
 | 
			
		||||
    my @users    = $a->users();
 | 
			
		||||
    my @groups   = $a->groups();
 | 
			
		||||
    my @ibays    = $a->ibays(); 
 | 
			
		||||
    my @printers = $a->printers();
 | 
			
		||||
    my @pseudonyms = $a->pseudonyms();
 | 
			
		||||
 | 
			
		||||
    $a->is_user_in_group($user, $group);
 | 
			
		||||
    my @groups = $a->user_group_list($user);
 | 
			
		||||
    $a->add_user_to_groups($user, @groups);
 | 
			
		||||
    $a->remove_user_from_groups($user, @groups);
 | 
			
		||||
 | 
			
		||||
    $a->create_user_auto_pseudonyms($user);
 | 
			
		||||
    $a->remove_user_auto_pseudonyms($user);
 | 
			
		||||
    $a->remove_all_user_pseudonyms($user);
 | 
			
		||||
    my $dp = $a->dot_pseudonym($user);
 | 
			
		||||
    my $up = $a->underbar_pseudonym($user);
 | 
			
		||||
    my $uid = $a->get_next_uid();
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
This module provides an abstracted interface to the esmith accounts
 | 
			
		||||
database.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
our $VERSION = sprintf '%d.%03d', q$Revision: 1.18 $ =~ /: (\d+).(\d+)/;
 | 
			
		||||
 | 
			
		||||
=head2 open()
 | 
			
		||||
 | 
			
		||||
Loads an existing account database and returns an esmith::AccountsDB
 | 
			
		||||
object representing it.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
use esmith::TestUtils qw(scratch_copy);
 | 
			
		||||
 | 
			
		||||
use_ok("esmith::AccountsDB");
 | 
			
		||||
use esmith::db;
 | 
			
		||||
use vars qw($a);
 | 
			
		||||
 | 
			
		||||
my $conf = scratch_copy('10e-smith-lib/accounts.conf');
 | 
			
		||||
$a = esmith::AccountsDB->open($conf);
 | 
			
		||||
isa_ok($a, 'esmith::AccountsDB');
 | 
			
		||||
is( $a->get("global")->prop('type'), "system", "We can get stuff from the db");
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub open {
 | 
			
		||||
    my($class, $file) = @_;
 | 
			
		||||
    $file = $file || $ENV{ESMITH_ACCOUNT_DB} || "accounts";
 | 
			
		||||
    return $class->SUPER::open($file);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 open_ro()
 | 
			
		||||
 | 
			
		||||
Like esmith::DB->open_ro, but if given no $file it will try to open the
 | 
			
		||||
file in the ESMITH_ACCOUNT_DB environment variable or accounts.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub open_ro {
 | 
			
		||||
    my($class, $file) = @_;
 | 
			
		||||
    $file = $file || $ENV{ESMITH_ACCOUNT_DB} || "accounts";
 | 
			
		||||
    return $class->SUPER::open_ro($file);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 users(), groups(), ibays(), printers(), pseudonyms()
 | 
			
		||||
 | 
			
		||||
Returns a list of records (esmith::DB::db::Record objects) of the 
 | 
			
		||||
given type.
 | 
			
		||||
 | 
			
		||||
=for testing
 | 
			
		||||
foreach my $t (qw(users groups pseudonyms)) {
 | 
			
		||||
    my @list = $a->$t();
 | 
			
		||||
    ok(@list, "Got a list of $t");
 | 
			
		||||
    isa_ok($list[0], 'esmith::DB::db::Record');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub AUTOLOAD {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my ($called_sub_name) = ($AUTOLOAD =~ m/([^:]*)$/);
 | 
			
		||||
    my @types = qw( users groups ibays printers pseudonyms);
 | 
			
		||||
    if (grep /^$called_sub_name$/, @types) {
 | 
			
		||||
        $called_sub_name =~ s/s$//g;    # de-pluralize
 | 
			
		||||
        return $self->get_all_by_prop(type => $called_sub_name);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head1 GROUP MANAGEMENT
 | 
			
		||||
 | 
			
		||||
=head2 $a->is_user_in_group($user, $group)
 | 
			
		||||
 | 
			
		||||
Returns true if the user is a member of the group, false otherwise.  The
 | 
			
		||||
arguments are a user name and a group name.
 | 
			
		||||
 | 
			
		||||
This routine will return undef if there is no such group, false (but
 | 
			
		||||
defined) if the user is not in the group, and true if the user is in the
 | 
			
		||||
group.
 | 
			
		||||
 | 
			
		||||
=for testing
 | 
			
		||||
ok($a->is_user_in_group('bart', 'simpsons'), "Bart is in group Simpsons");
 | 
			
		||||
ok(not($a->is_user_in_group('moe', 'simpsons')), "Moe is not in group Simpsons");
 | 
			
		||||
ok(not(defined $a->is_user_in_group('moe', 'flanders')), "No such group as Flanders");
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub is_user_in_group {
 | 
			
		||||
    my ($self, $user, $group) = @_;
 | 
			
		||||
    $group = $self->get($group) || return undef;
 | 
			
		||||
    my $members = $group->prop('Members');
 | 
			
		||||
 | 
			
		||||
    return grep(/^$user$/, split /,/, $members) ? 1 : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 $a->user_group_list($user)
 | 
			
		||||
 | 
			
		||||
Get a list of groups (by name) of which a user is a member.  The $user argument 
 | 
			
		||||
is simply the username.
 | 
			
		||||
 | 
			
		||||
=for testing
 | 
			
		||||
my @groups = $a->user_group_list('bart');
 | 
			
		||||
is_deeply(\@groups, ['simpsons'], "Bart's group list is 'simpsons'");
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub user_group_list {
 | 
			
		||||
    my ($self, $user) = @_;
 | 
			
		||||
    my @groups = $self->groups();
 | 
			
		||||
    my @user_groups;
 | 
			
		||||
    foreach my $g (@groups) {
 | 
			
		||||
        push(@user_groups, $g->key()) 
 | 
			
		||||
            if $self->is_user_in_group($user, $g->key());
 | 
			
		||||
    }
 | 
			
		||||
    return @user_groups;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 $a->add_user_to_groups($user, @groups)
 | 
			
		||||
 | 
			
		||||
Given a list of groups (by name), adds the user to all of them.
 | 
			
		||||
 | 
			
		||||
Doesn't signal the group-modify event, just does the DB work.
 | 
			
		||||
 | 
			
		||||
Note: the method used here is a bit kludgy.  It could result in a user 
 | 
			
		||||
being in the same group twice.
 | 
			
		||||
 | 
			
		||||
=for testing
 | 
			
		||||
my @groups = $a->groups();
 | 
			
		||||
$a->remove_user_from_groups('maggie', map { $_->key() } @groups);
 | 
			
		||||
my @mg = $a->user_group_list('maggie');
 | 
			
		||||
is(scalar @mg, 0, "Maggie has been removed from all groups");
 | 
			
		||||
$a->add_user_to_groups('maggie', 'simpsons');
 | 
			
		||||
@mg = $a->user_group_list('maggie');
 | 
			
		||||
is_deeply(\@mg, ['simpsons'], "Maggie has been added to group 'simpsons'");
 | 
			
		||||
$a->remove_user_from_groups('maggie', 'simpsons');
 | 
			
		||||
@mg = $a->user_group_list('maggie');
 | 
			
		||||
is_deeply(\@mg, [], "Maggie's been removed from all groups again");
 | 
			
		||||
$a->set_user_groups('maggie', 'simpsons');
 | 
			
		||||
@mg = $a->user_group_list('maggie');
 | 
			
		||||
is_deeply(\@mg, ['simpsons'], "Maggie's groups have been set to: 'simpsons'");
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub add_user_to_groups {
 | 
			
		||||
    my ($self, $user, @groups) = @_;
 | 
			
		||||
    GROUP: foreach my $group (@groups) {
 | 
			
		||||
	unless (($group) = ($group =~ /(^[\w.-]+$)/))
 | 
			
		||||
	{
 | 
			
		||||
            warn "Group name doesn't look like a group!\n";
 | 
			
		||||
            next GROUP;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        my $group_rec = $self->get($group) || next GROUP;
 | 
			
		||||
        my @members = split(/,/, $group_rec->prop('Members'));
 | 
			
		||||
        push @members, $user;
 | 
			
		||||
        # Remove duplicates
 | 
			
		||||
        my %members = map { $_ => 1 } @members;
 | 
			
		||||
        $group_rec->set_prop('Members', join(',', sort keys %members));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 $a->remove_user_from_groups($user, @groups)
 | 
			
		||||
 | 
			
		||||
Given a list of groups, removes a user from all of them.
 | 
			
		||||
Doesn't signal the group-modify event, just does the DB work.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub remove_user_from_groups {
 | 
			
		||||
    my ($self, $user, @groups) = @_;
 | 
			
		||||
 | 
			
		||||
    GROUP: foreach my $g (@groups) {
 | 
			
		||||
        my $group_rec = $self->get($g) || next GROUP;
 | 
			
		||||
        my $members = $group_rec->prop('Members');
 | 
			
		||||
        my @members = split (/,/, $members);
 | 
			
		||||
        @members = grep (!/^$user$/, @members);
 | 
			
		||||
        @members = qw(admin) unless @members; # admin *must* be in every group
 | 
			
		||||
        $group_rec->set_prop('Members', join(',', @members));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 $a->set_user_groups($user, @groups)
 | 
			
		||||
 | 
			
		||||
Sets the user's groups in one fell swoop.  Under the hood, it's removing
 | 
			
		||||
the user from every group they're in then adding them to the set you give.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub set_user_groups
 | 
			
		||||
{
 | 
			
		||||
    my ($self, $user, @groups) = @_;
 | 
			
		||||
    my @old_groups = $self->user_groups_list($user);
 | 
			
		||||
    $self->remove_user_from_groups($user, @old_groups);
 | 
			
		||||
    $self->add_user_to_groups($user, @groups);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head1 PSEUDONYM MANAGEMENT
 | 
			
		||||
 | 
			
		||||
=head2 $a->create_user_auto_pseudonyms($user)
 | 
			
		||||
 | 
			
		||||
Given a user name, creates standard pseudonyms ("dot" and "underbar" style)
 | 
			
		||||
for that user.
 | 
			
		||||
 | 
			
		||||
=for testing
 | 
			
		||||
my $user = 'bart';
 | 
			
		||||
ok($a->pseudonyms(), "There are pseudonyms in the accounts db");
 | 
			
		||||
$a->remove_user_auto_pseudonyms($user);
 | 
			
		||||
ok(! $a->get('bart.simpson'), "Removed dot-pseudonym");
 | 
			
		||||
ok(! $a->get('bart_simpson'), "Removed underbar-pseudonym");
 | 
			
		||||
$a->create_user_auto_pseudonyms($user);
 | 
			
		||||
ok($a->get('bart.simpson'), "Created dot-pseudonym");
 | 
			
		||||
ok($a->get('bart_simpson'), "Created underbar-pseudonym");
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub create_user_auto_pseudonyms {
 | 
			
		||||
    my ($self, $user) = @_;
 | 
			
		||||
    my $user_rec = $self->get($user);
 | 
			
		||||
    my $firstName = $user_rec->prop("FirstName");
 | 
			
		||||
    my $lastName  = $user_rec->prop("LastName");
 | 
			
		||||
 | 
			
		||||
    my $dot_pseudonym = dot_pseudonym($self, $user);
 | 
			
		||||
    my $underbar_pseudonym = underbar_pseudonym($self, $user);
 | 
			
		||||
 | 
			
		||||
    my $dot_acct = $self->get($dot_pseudonym) ||
 | 
			
		||||
    $self->new_record($dot_pseudonym,      { type => 'pseudonym', 
 | 
			
		||||
                                             Account => $user} );
 | 
			
		||||
 | 
			
		||||
    my $underbar_acct = $self->get($underbar_pseudonym) ||
 | 
			
		||||
    $self->new_record($underbar_pseudonym, { type => 'pseudonym', 
 | 
			
		||||
                                             Account => $user} );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=head2 $a->remove_all_user_pseudonyms($user)
 | 
			
		||||
 | 
			
		||||
Given a username, remove any pseudonyms related to that user from the
 | 
			
		||||
accounts database. Also removes any pseudonyms related to a pseudonym
 | 
			
		||||
being removed. Returns the number of pseudonym records deleted.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub remove_all_user_pseudonyms {
 | 
			
		||||
    my ($self, $user) = @_;
 | 
			
		||||
    my $count = 0;
 | 
			
		||||
    foreach my $p_rec (grep { $_->prop("Account") eq $user } $self->pseudonyms())
 | 
			
		||||
    {
 | 
			
		||||
	foreach my $p_p_rec (grep { $_->prop("Account") eq $p_rec->key } $self->pseudonyms())
 | 
			
		||||
	{
 | 
			
		||||
	    $p_p_rec->delete;
 | 
			
		||||
	    $count++;
 | 
			
		||||
	}
 | 
			
		||||
	$p_rec->delete;
 | 
			
		||||
	$count++;
 | 
			
		||||
    }
 | 
			
		||||
    return $count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 $a->remove_user_auto_pseudonyms($user)
 | 
			
		||||
 | 
			
		||||
Given a username, remove the dot_pseudonym and underbar_pseudonym
 | 
			
		||||
related to that user from the accounts database.  Returns the number
 | 
			
		||||
of pseudonym records deleted.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub remove_user_auto_pseudonyms {
 | 
			
		||||
    my ($self, $user) = @_;
 | 
			
		||||
    my $dot_pseudonym = dot_pseudonym($self, $user);
 | 
			
		||||
    my $underbar_pseudonym = underbar_pseudonym($self, $user);
 | 
			
		||||
    my $count = 0;
 | 
			
		||||
    foreach my $p_rec ($self->get($dot_pseudonym),
 | 
			
		||||
			           $self->get($underbar_pseudonym))
 | 
			
		||||
    {
 | 
			
		||||
        if (defined $p_rec && $p_rec->prop("type") eq "pseudonym" &&
 | 
			
		||||
			      $p_rec->prop("Account") eq $user)
 | 
			
		||||
        {
 | 
			
		||||
            $p_rec->delete;
 | 
			
		||||
            $count++;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return $count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 $a->dot_pseudonym($user)
 | 
			
		||||
 | 
			
		||||
Returns the "dot"-style pseudonym for a user as a string.  For instance, 
 | 
			
		||||
dot_pseudonym("bart") might return "bart.simpson".
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub dot_pseudonym {
 | 
			
		||||
    my ($self, $user) = @_;
 | 
			
		||||
    my $user_rec = $self->get($user);
 | 
			
		||||
    my $firstName = $user_rec->prop("FirstName");
 | 
			
		||||
    my $lastName  = $user_rec->prop("LastName");
 | 
			
		||||
 | 
			
		||||
    my $dot_pseudonym = lc("$firstName $lastName");
 | 
			
		||||
 | 
			
		||||
    $dot_pseudonym =~ s/^\s+//;         # Strip leading whitespace
 | 
			
		||||
    $dot_pseudonym =~ s/\s+$//;         # Strip trailing whitespace
 | 
			
		||||
    $dot_pseudonym =~ s/\s+/ /g;        # Multiple spaces become single spaces
 | 
			
		||||
    $dot_pseudonym =~ s/\s/./g;         # Change all spaces to dots
 | 
			
		||||
    return $dot_pseudonym;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 $a->underbar_pseudonym($user)
 | 
			
		||||
 | 
			
		||||
Returns the "underbar"-style pseudonym for a user as a string.  For instance, 
 | 
			
		||||
underbar_pseudonym("bart") might return "bart_simpson".
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
my @users     = $a->users();
 | 
			
		||||
my $user      = 'bart';
 | 
			
		||||
my $rec       = $a->get($user);
 | 
			
		||||
my $firstName = $rec->prop("FirstName");
 | 
			
		||||
my $lastName  = $rec->prop("LastName");
 | 
			
		||||
my $up        = $a->underbar_pseudonym($user);
 | 
			
		||||
is($up, "bart_simpson", "Underbar pseudonym created correctly");
 | 
			
		||||
my $dp        = $a->dot_pseudonym($user);
 | 
			
		||||
is($dp, "bart.simpson", "Underbar pseudonym created correctly");
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub underbar_pseudonym {
 | 
			
		||||
    my ($self, $user) = @_;
 | 
			
		||||
    my $user_rec = $self->get($user);
 | 
			
		||||
    my $firstName = $user_rec->prop("FirstName");
 | 
			
		||||
    my $lastName  = $user_rec->prop("LastName");
 | 
			
		||||
 | 
			
		||||
    my $underbar_pseudonym = lc("$firstName $lastName");
 | 
			
		||||
 | 
			
		||||
    $underbar_pseudonym =~ s/^\s+//;         # Strip leading whitespace
 | 
			
		||||
    $underbar_pseudonym =~ s/\s+$//;         # Strip trailing whitespace
 | 
			
		||||
    $underbar_pseudonym =~ s/\s+/ /g;        # Multiple spaces become single spaces
 | 
			
		||||
    $underbar_pseudonym =~ s/\s/_/g;         # Change all spaces to underbars
 | 
			
		||||
    return $underbar_pseudonym;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 $a->activeUsers()
 | 
			
		||||
 | 
			
		||||
Returns the number of active users, ie, accounts which have passwords set and
 | 
			
		||||
are of type 'user'.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
my $numActiveUsers = scalar $a->activeUsers();
 | 
			
		||||
like($numActiveUsers, qr/[0-9]+/, "active users returns a number");
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub activeUsers()
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my @users = $self->users();
 | 
			
		||||
 | 
			
		||||
    return unless @users;
 | 
			
		||||
    return grep { $_->prop("PasswordSet") eq 'yes' } @users;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 get_next_uid
 | 
			
		||||
 | 
			
		||||
Returns the next available UID from /etc/passwd. All UIDs are above the range
 | 
			
		||||
reserved for 'system' accounts (currently 5000). 
 | 
			
		||||
 | 
			
		||||
=for testing
 | 
			
		||||
SKIP: {
 | 
			
		||||
    skip "Must be root to run get_next_uid" if $<;
 | 
			
		||||
    my $u = $a->get_next_uid();
 | 
			
		||||
    ok($u > 5000, "UID should be greater than 5000");
 | 
			
		||||
    ok(! getpwuid($u), "UID should not yet exist");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub get_next_uid {
 | 
			
		||||
    use esmith::ConfigDB;
 | 
			
		||||
 | 
			
		||||
    my $id;
 | 
			
		||||
    my $db = esmith::ConfigDB->open || die "Couldn't open config db";
 | 
			
		||||
 | 
			
		||||
    if ($id = $db->get('MinUid'))
 | 
			
		||||
    {
 | 
			
		||||
        $id = $id->value();
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        $db->new_record('MinUid');
 | 
			
		||||
        $id = 5000;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    my $maxid = 1 << 31;
 | 
			
		||||
    setpwent();
 | 
			
		||||
    setgrent();
 | 
			
		||||
    while (getpwuid $id || getgrgid $id)
 | 
			
		||||
    {
 | 
			
		||||
        die "All userids in use" if ($id == $maxid);
 | 
			
		||||
        $id++;
 | 
			
		||||
    }
 | 
			
		||||
    endpwent();
 | 
			
		||||
    endgrent();
 | 
			
		||||
 | 
			
		||||
    $db->set_value('MinUid', $id + 1);
 | 
			
		||||
 | 
			
		||||
    return $id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 new_record ($key, \%props)
 | 
			
		||||
 | 
			
		||||
This method is overridden from esmith::DB::db. We do an additional check
 | 
			
		||||
for implicit accounts here - accounts that exist in /etc/passwd but not
 | 
			
		||||
in the db. Otherwise it behaves just like the superclass method.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
isnt($a->new_record("root", {type=>'system'}), "OK", 
 | 
			
		||||
    "can't create existing account");
 | 
			
		||||
is($a->get("nobody"), undef, "nobody doesn't exist in db");
 | 
			
		||||
isnt($a->new_record("nobody", {type=>'system'}), "OK",
 | 
			
		||||
    "can't create account in /etc/passwd");
 | 
			
		||||
isnt($a->new_record("screwy", {type=>'user'}), undef, 
 | 
			
		||||
    "created a regular user");
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub new_record
 | 
			
		||||
{
 | 
			
		||||
    my ($self, $key, $props) = @_;
 | 
			
		||||
 | 
			
		||||
    if(getpwnam($key) || getgrnam($key))
 | 
			
		||||
    {
 | 
			
		||||
        warn "Attempt to create account '$key' which already exists ",
 | 
			
		||||
            "in passwd";
 | 
			
		||||
        return undef;
 | 
			
		||||
    }
 | 
			
		||||
    return $self->SUPER::new_record($key, $props);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 validate_account_name ($name)
 | 
			
		||||
 | 
			
		||||
Check $name to see if it is a valid account name. Valid account names
 | 
			
		||||
start with a letter or number and contain only letters, numbers, 
 | 
			
		||||
underscores, dots and dashes.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
is($a->validate_account_name("root"), "OK", "root is a valid name");
 | 
			
		||||
is($a->validate_account_name("fred.frog"), "OK", "fred.frog is a valid name");
 | 
			
		||||
is($a->validate_account_name("jane_doe"), "OK", "jane_doe is a valid name");
 | 
			
		||||
isnt($a->validate_account_name("^root"), "OK", "^root is not a valid name");
 | 
			
		||||
is(esmith::AccountsDB::validate_account_name("root"), "OK", "called as a function");
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub validate_account_name
 | 
			
		||||
{
 | 
			
		||||
    my $self;
 | 
			
		||||
    # Were we called as a method or a function?
 | 
			
		||||
    if($#_ > 0)
 | 
			
		||||
    {    
 | 
			
		||||
        $self = shift;
 | 
			
		||||
    }
 | 
			
		||||
    my $name = shift;
 | 
			
		||||
    return ($name =~ /[^0-9a-z\-_\.]/ or $name !~ /^[a-z]/) ? undef : 'OK';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head1 AUTHOR
 | 
			
		||||
 | 
			
		||||
SME Server Developers <bugs@e-smith.com>
 | 
			
		||||
 | 
			
		||||
See http://www.e-smith.org/ for more information
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										398
									
								
								root/usr/share/perl5/vendor_perl/esmith/ConfigDB.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										398
									
								
								root/usr/share/perl5/vendor_perl/esmith/ConfigDB.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,398 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::ConfigDB;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use warnings;
 | 
			
		||||
 | 
			
		||||
use vars qw( $AUTOLOAD @ISA );
 | 
			
		||||
 | 
			
		||||
use esmith::DB::db;
 | 
			
		||||
@ISA = qw( esmith::DB::db );
 | 
			
		||||
 | 
			
		||||
use esmith::ConfigDB::Record;
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::ConfigDB - interface to esmith configuration database
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
    use esmith::ConfigDB;
 | 
			
		||||
    my $db = esmith::ConfigDB->open;
 | 
			
		||||
    my $db = esmith::ConfigDB->open_ro;
 | 
			
		||||
 | 
			
		||||
    my @services = $db->services();
 | 
			
		||||
 | 
			
		||||
    # Singleton Records
 | 
			
		||||
    my $record = $db->get($key);
 | 
			
		||||
    my $value = $record->value;
 | 
			
		||||
    $record->set_value($value);
 | 
			
		||||
 | 
			
		||||
    # BAD!
 | 
			
		||||
    my $value = $db->get($key)->value() # Throws a runtime error if $key
 | 
			
		||||
                                        # doesn't exist
 | 
			
		||||
    $value = $db->get($key)->prop($p)   # Throws a runtime error if $key
 | 
			
		||||
                                        # doesn't exist
 | 
			
		||||
 | 
			
		||||
    # GOOD
 | 
			
		||||
    my $record = $db->get($key);
 | 
			
		||||
    my $value;
 | 
			
		||||
    if ($record)
 | 
			
		||||
    {
 | 
			
		||||
        $value = $record->prop($prop);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # Typed Records (eventually they all will be)
 | 
			
		||||
    my $prop = $record->prop($p);
 | 
			
		||||
    $record->set_prop($prop, $propvalue);
 | 
			
		||||
    my $value = $db->get_value($key)    # Returns undef if record doesn't exist
 | 
			
		||||
    $value = $db->get_prop($key, $p)    # Returns undef if record doesn't exist
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
This module provides an abstracted interface to the esmith master
 | 
			
		||||
configuration database.
 | 
			
		||||
 | 
			
		||||
Unless otherwise noted, esmith::ConfigDB acts like esmith::DB::db.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
our $VERSION = sprintf '%d.%03d', q$Revision: 1.29 $ =~ /: (\d+).(\d+)/;
 | 
			
		||||
 | 
			
		||||
=head2 open()
 | 
			
		||||
 | 
			
		||||
Like esmith::DB->open, but if given no $file it will try to open the
 | 
			
		||||
file in the ESMITH_CONFIG_DB environment variable or configuration.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
use esmith::TestUtils qw(scratch_copy);
 | 
			
		||||
use_ok("esmith::ConfigDB");
 | 
			
		||||
 | 
			
		||||
my $scratch_copy_of_conf = scratch_copy('10e-smith-lib/configuration.conf');
 | 
			
		||||
$C = esmith::ConfigDB->open($scratch_copy_of_conf);
 | 
			
		||||
isa_ok($C, 'esmith::ConfigDB');
 | 
			
		||||
is( $C->get("AccessType")->prop('type'), "dedicated", 
 | 
			
		||||
                                    "We can get stuff from the db");
 | 
			
		||||
 | 
			
		||||
is( $C->get_prop("AccessType",'type'), "dedicated", 
 | 
			
		||||
                                    "We can get_prop stuff from the db");
 | 
			
		||||
 | 
			
		||||
is( $C->get_value("AccessType"), "dedicated", 
 | 
			
		||||
                                    "We can get_value stuff from the db");
 | 
			
		||||
 | 
			
		||||
is( $C->get_value("NoSuchKey"), undef, 
 | 
			
		||||
                                    "We can get_value non-existant keys");
 | 
			
		||||
 | 
			
		||||
is( $C->get_prop("diald","status"), "disabled", 
 | 
			
		||||
                                    "We can get_prop stuff from the db");
 | 
			
		||||
 | 
			
		||||
is( $C->get_prop("NoSuchKey","NoSuchProp"), undef, 
 | 
			
		||||
                                    "We can get_prop non-existant keys");
 | 
			
		||||
 | 
			
		||||
is( $C->get_prop("diald","NoSuchProp"), undef, 
 | 
			
		||||
                                    "We can get_prop non-existant props");
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub open
 | 
			
		||||
{
 | 
			
		||||
    my ( $class, $file ) = @_;
 | 
			
		||||
    $file = $file || $ENV{ESMITH_CONFIG_DB} || "configuration";
 | 
			
		||||
    return $class->SUPER::open($file);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 open_ro()
 | 
			
		||||
 | 
			
		||||
Like esmith::DB->open_ro, but if given no $file it will try to open the
 | 
			
		||||
file in the ESMITH_CONFIG_DB environment variable or configuration.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub open_ro
 | 
			
		||||
{
 | 
			
		||||
    my ( $class, $file ) = @_;
 | 
			
		||||
    $file = $file || $ENV{ESMITH_CONFIG_DB} || "configuration";
 | 
			
		||||
    return $class->SUPER::open_ro($file);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 new_record()
 | 
			
		||||
 | 
			
		||||
This method creates a new record in the configuration database. As arguments,
 | 
			
		||||
it expects the key to the record, followed by a hash references with its
 | 
			
		||||
properties, including the type.
 | 
			
		||||
 | 
			
		||||
my $db = esmith::ConfigDB->open;
 | 
			
		||||
my $record = $db->new_record('zope', { type => 'service',
 | 
			
		||||
                                       status => 'disabled' });
 | 
			
		||||
 | 
			
		||||
my %defaults = qw(
 | 
			
		||||
    type => 'service',
 | 
			
		||||
    status => 'disabled',
 | 
			
		||||
    maintainer => 'admin@domain.com'
 | 
			
		||||
    );
 | 
			
		||||
my $record = $db->get('zope');
 | 
			
		||||
unless ($record)
 | 
			
		||||
{
 | 
			
		||||
    $record = $db->new_record('zope', \%defaults);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 get()
 | 
			
		||||
 | 
			
		||||
Like their esmith::DB counterparts except they return
 | 
			
		||||
esmith::ConfigDB::Record objects which have a few extra methods.
 | 
			
		||||
 | 
			
		||||
my $record = $db->get('zope');
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
my $rec = eval { $C->get("I_dont_exist"); };
 | 
			
		||||
ok( !$rec, 'get() on a non-existent key' );
 | 
			
		||||
is( $@, '', '  doesnt blow up' );
 | 
			
		||||
 | 
			
		||||
isa_ok( $C->get("AccessType"), 'esmith::ConfigDB::Record', 
 | 
			
		||||
                                "get()ened records are ConfigDB::Records" );
 | 
			
		||||
 | 
			
		||||
$rec = $C->new_record("I_dont_exist", { type => "foo" });
 | 
			
		||||
isa_ok( $rec, 'esmith::ConfigDB::Record', 
 | 
			
		||||
                                "new_record()s are ConfigDB::Records" );
 | 
			
		||||
$rec->delete("I_dont_exist");
 | 
			
		||||
ok( !$C->get("I_dont_exist"), 'delete()' );
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub get
 | 
			
		||||
{
 | 
			
		||||
    my ($self) = shift;
 | 
			
		||||
 | 
			
		||||
    my $rec = $self->SUPER::get(@_);
 | 
			
		||||
    return $rec ? bless $rec, 'esmith::ConfigDB::Record' : undef;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub new_record
 | 
			
		||||
{
 | 
			
		||||
    my ($self) = shift;
 | 
			
		||||
 | 
			
		||||
    my $rec = $self->SUPER::new_record(@_);
 | 
			
		||||
    return $rec ? bless $rec, 'esmith::ConfigDB::Record' : undef;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 
 | 
			
		||||
=head2 getLocale()
 | 
			
		||||
 
 | 
			
		||||
Retrieves the locale and keyboard settings from the configuration database.
 | 
			
		||||
Returns ($lang, $kbdtype, $keytable) on success. Returns undef if the record
 | 
			
		||||
doesn't exist.
 | 
			
		||||
 
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub getLocale
 | 
			
		||||
{
 | 
			
		||||
    my $self     = shift;
 | 
			
		||||
    my $rec      = $self->get('sysconfig') or return undef;
 | 
			
		||||
    my $lang     = $rec->prop('Language') || 'en_US';
 | 
			
		||||
    my $kbdtype  = $rec->prop('KeyboardType') || 'pc';
 | 
			
		||||
    my $keytable = $rec->prop('Keytable') || 'us';
 | 
			
		||||
    return ( $lang, $kbdtype, $keytable );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 hosts_allow_spec ($service [,$daemon])
 | 
			
		||||
 | 
			
		||||
Given a service, return the string suitable for /etc/hosts.allow,
 | 
			
		||||
checking to see if the service is defined, whether it is enabled and
 | 
			
		||||
whether access is set to public, private, or localhost.
 | 
			
		||||
 | 
			
		||||
An optional argument provides the tag which appears in hosts.allow. If not
 | 
			
		||||
given, the service name is used.
 | 
			
		||||
 | 
			
		||||
For example, one of the following:
 | 
			
		||||
 | 
			
		||||
# 'oidentd' is not defined in the configuration database
 | 
			
		||||
# 'oidentd' is disabled in the configuration database
 | 
			
		||||
in.identd: 127.0.0.1
 | 
			
		||||
in.identd: 127.0.0.1 192.168.1.1/255.255.255.0
 | 
			
		||||
in.identd: ALL
 | 
			
		||||
 | 
			
		||||
And here's the hosts.allow fragment:
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
    $OUT = $DB->hosts_allow_spec('oidentd', 'in.identd');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub hosts_allow_spec
 | 
			
		||||
{
 | 
			
		||||
    my $self         = shift;
 | 
			
		||||
    my $service_name = shift;
 | 
			
		||||
    my $daemon       = shift || $service_name;
 | 
			
		||||
 | 
			
		||||
    my $service = $self->get($service_name)
 | 
			
		||||
      or return
 | 
			
		||||
      "# '$service_name' is not defined in the configuration database";
 | 
			
		||||
 | 
			
		||||
    my $status = $service->prop('status') || "disabled";
 | 
			
		||||
    return "# '$service_name' is disabled in the configuration database"
 | 
			
		||||
      unless ( $status eq "enabled" );
 | 
			
		||||
 | 
			
		||||
    my $access = $service->prop('access') || "private";
 | 
			
		||||
 | 
			
		||||
    use esmith::NetworksDB;
 | 
			
		||||
    my $ndb = esmith::NetworksDB->open_ro;
 | 
			
		||||
 | 
			
		||||
    my @spec = ( "$daemon:", $ndb->local_access_spec($access) );
 | 
			
		||||
    return "@spec";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 wins_server
 | 
			
		||||
 | 
			
		||||
Return the value of the WINS server from the config db
 | 
			
		||||
or undef if we don't have a WINS server set and we are
 | 
			
		||||
not the domain master
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub wins_server
 | 
			
		||||
{
 | 
			
		||||
    my ($self) = @_;
 | 
			
		||||
 | 
			
		||||
    my $wins_server = $self->get_prop( 'smb', 'WINSServer' );
 | 
			
		||||
 | 
			
		||||
    return $wins_server if $wins_server;
 | 
			
		||||
 | 
			
		||||
    my $server_role = $self->get_prop( 'smb', 'ServerRole' ) || 'WS';
 | 
			
		||||
 | 
			
		||||
    return $self->get_prop( 'InternalInterface', 'IPAddress' )
 | 
			
		||||
      if $server_role =~ m{^(PDC|ADS)$};
 | 
			
		||||
 | 
			
		||||
    return undef;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 services()
 | 
			
		||||
 | 
			
		||||
Returns a list of services in the configuration database
 | 
			
		||||
 | 
			
		||||
=for testing
 | 
			
		||||
foreach my $t (qw(services)) {
 | 
			
		||||
    my @list = $C->$t();
 | 
			
		||||
    ok(@list, "Got a list of $t");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub AUTOLOAD
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my ($called_sub_name) = ( $AUTOLOAD =~ m/([^:]*)$/ );
 | 
			
		||||
    my @types = qw( services );
 | 
			
		||||
    if ( grep /^$called_sub_name$/, @types )
 | 
			
		||||
    {
 | 
			
		||||
        $called_sub_name =~ s/s$//g;    # de-pluralize
 | 
			
		||||
        return $self->list_by_type($called_sub_name);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 _loadDefaults ($forceReset)
 | 
			
		||||
 | 
			
		||||
Behaves just like the esmith::DB method of the same name. This is a private
 | 
			
		||||
method used internally.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
$scratch_copy_of_conf = scratch_copy('10e-smith-lib/configuration.conf', 'configuration.conf.scratch');
 | 
			
		||||
is ($scratch_copy_of_conf, 'configuration.conf.scratch', 'scratch copy name');
 | 
			
		||||
$ENV{'ESMITH_CONFIG_DB'} = $scratch_copy_of_conf;
 | 
			
		||||
$C = esmith::ConfigDB->open();
 | 
			
		||||
is ($C->{file}, $scratch_copy_of_conf, 'file name');
 | 
			
		||||
my $accesstype = $C->get("AccessType")->value;
 | 
			
		||||
ok($C->new_record('foobar', {type=>'service', status=>'disabled'}),
 | 
			
		||||
    "Set up foobar record");
 | 
			
		||||
is($C->get('foobar')->prop('status'), "disabled", "foobar is disabled");
 | 
			
		||||
$ENV{'ESMITH_DB_DEFAULTSDIR'} = "10e-smith-lib/db";
 | 
			
		||||
ok($C->_loadDefaults(), "Loaded defaults");
 | 
			
		||||
is($C->get('foobar')->prop('status'), 'enabled', "We forced status enabled");
 | 
			
		||||
is($C->get('bazbar')->prop('status'), 'enabled', "We included a new default");
 | 
			
		||||
is($C->get('AccessType')->value, $accesstype, "AccessType has not changed");
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=head2 record_has_defaults ($name)
 | 
			
		||||
 | 
			
		||||
Behaves just like the esmith::DB method of the same name.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
$ENV{'ESMITH_DB_DEFAULTSDIR'} = "10e-smith-lib/db";
 | 
			
		||||
is($C->record_has_defaults('foobar'), 1, "foobar has some defaults");
 | 
			
		||||
is($C->record_has_defaults('notthisone'), undef, "notthisone does not");
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
# There would normally be a method here, but we inherit _loadDefaults
 | 
			
		||||
# from esmith::DB. The tests need to go here because the superclass is
 | 
			
		||||
# all virtual and testing requires concrete open/get/set methods.
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 migrate
 | 
			
		||||
 | 
			
		||||
Just like the esmith::DB method of the same name.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
$scratch_copy_of_conf = scratch_copy('10e-smith-lib/configuration.conf', 'configuration.conf.scratch');
 | 
			
		||||
is ($scratch_copy_of_conf, 'configuration.conf.scratch', 'scratch copy name');
 | 
			
		||||
$ENV{'ESMITH_CONFIG_DB'} = $scratch_copy_of_conf;
 | 
			
		||||
$C = esmith::ConfigDB->open();
 | 
			
		||||
is($C->get('quux'), undef, "No quux here");
 | 
			
		||||
$ENV{'ESMITH_DB_DEFAULTSDIR'} = "10e-smith-lib/db";
 | 
			
		||||
ok($C->migrate(), "We can migrate");
 | 
			
		||||
my $quux = $C->get('quux');
 | 
			
		||||
ok($quux, "We got quux");
 | 
			
		||||
is($quux->prop('status'), 'enabled', "We migrated to quux");
 | 
			
		||||
$quux->delete;
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
# There would normally be a method here, but we inherit migrate
 | 
			
		||||
# from esmith::DB. The tests need to go here because the superclass is
 | 
			
		||||
# all virtual and testing requires concrete open/get/set methods.
 | 
			
		||||
 | 
			
		||||
=head1 AUTHOR
 | 
			
		||||
 | 
			
		||||
SME Server Developers <bugs@e-smith.com>
 | 
			
		||||
 | 
			
		||||
=head1 SEE ALSO
 | 
			
		||||
 | 
			
		||||
L<esmith::DB>, L<esmith::DB::db>, L<esmith::AccountsDB>, L<esmith::DomainsDB>,
 | 
			
		||||
L<esmith::HostsDB>, L<esmith::NetworksDB>, L<esmith::ConfigDB::Record>
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
							
								
								
									
										108
									
								
								root/usr/share/perl5/vendor_perl/esmith/ConfigDB/Record.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								root/usr/share/perl5/vendor_perl/esmith/ConfigDB/Record.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,108 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::ConfigDB::Record;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use warnings;
 | 
			
		||||
 | 
			
		||||
use esmith::ConfigDB;
 | 
			
		||||
require esmith::DB::db::Record;
 | 
			
		||||
our @ISA = qw(esmith::DB::db::Record);
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::ConfigDB::Record - record in an esmith::ConfigDB database.
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
    Just like esmith::DB::db::Record except...
 | 
			
		||||
 | 
			
		||||
    my $value = $record->value;
 | 
			
		||||
                $record->set_value($value);
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
This provides some extra functionality needed by the esmith::ConfigDB
 | 
			
		||||
databases.
 | 
			
		||||
 | 
			
		||||
Unless noted, it works just like esmith::DB::db::Record.
 | 
			
		||||
 | 
			
		||||
=head2 New Methods
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=over 4
 | 
			
		||||
 | 
			
		||||
=item B<value>
 | 
			
		||||
 | 
			
		||||
=item B<set_value>
 | 
			
		||||
 | 
			
		||||
  my $value = $record->value;
 | 
			
		||||
              $record->set_value($value);
 | 
			
		||||
 | 
			
		||||
Gets/sets the value of the $record.  Some ConfigDB entries don't have
 | 
			
		||||
a set of properties, but rather a single value.
 | 
			
		||||
 | 
			
		||||
It will warn if you use these on $records with properties.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
use esmith::ConfigDB;
 | 
			
		||||
$Scratch_Conf = '10e-smith-lib/scratch.conf';
 | 
			
		||||
unlink $Scratch_Conf;
 | 
			
		||||
$c = esmith::ConfigDB->create($Scratch_Conf);
 | 
			
		||||
END { unlink $Scratch_Conf }
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
    my $warning = '';
 | 
			
		||||
    local $SIG{__WARN__} = sub { $warning = join '', @_ };
 | 
			
		||||
 | 
			
		||||
    my $wib = $c->new_record('wibble', { type => 'yar' });
 | 
			
		||||
    $wib->set_value('foo');
 | 
			
		||||
    is( $wib->value, 'foo',  'value/set_value' );
 | 
			
		||||
    is( $warning, '',        '  no warning' );
 | 
			
		||||
 | 
			
		||||
    $wib->set_prop(bar => 42);
 | 
			
		||||
    is( $wib->value, 'foo' );
 | 
			
		||||
    like( $warning, qr/value\(\) should not be used on records with properties, use prop\(\)/, 'value() warns if the record has props');
 | 
			
		||||
 | 
			
		||||
    $wib->set_value(92);
 | 
			
		||||
    like( $warning, qr/set_value\(\) should not be used on records with properties, use set_prop\(\)/, 'value() warns if the record has props');
 | 
			
		||||
    is( $wib->value, 92 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub value {
 | 
			
		||||
    my($self) = shift;
 | 
			
		||||
 | 
			
		||||
    my %props = $self->props;
 | 
			
		||||
    warn "value() should not be used on records with properties, use prop()" if
 | 
			
		||||
      keys %props > 1;
 | 
			
		||||
    return $self->prop('type');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub set_value {
 | 
			
		||||
    my($self, $value) = @_;
 | 
			
		||||
 | 
			
		||||
    my %props = $self->props;
 | 
			
		||||
    warn "set_value() should not be used on records with properties, ".
 | 
			
		||||
         "use set_prop()" if keys %props > 1;
 | 
			
		||||
    return $self->set_prop('type', $value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=back
 | 
			
		||||
 | 
			
		||||
=head1 SEE ALSO
 | 
			
		||||
 | 
			
		||||
L<esmith::ConfigDB>, L<esmith::DB::db::Record>
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
							
								
								
									
										22
									
								
								root/usr/share/perl5/vendor_perl/esmith/ConfigDB/UTF8.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								root/usr/share/perl5/vendor_perl/esmith/ConfigDB/UTF8.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2008 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::ConfigDB::UTF8;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use warnings;
 | 
			
		||||
 | 
			
		||||
use esmith::DB::db;
 | 
			
		||||
use esmith::config::utf8;
 | 
			
		||||
our @ISA = qw( esmith::DB::db );
 | 
			
		||||
 | 
			
		||||
sub tie_class
 | 
			
		||||
{
 | 
			
		||||
    return 'esmith::config::utf8';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										705
									
								
								root/usr/share/perl5/vendor_perl/esmith/DB.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										705
									
								
								root/usr/share/perl5/vendor_perl/esmith/DB.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,705 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::DB;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use warnings;
 | 
			
		||||
use Carp;
 | 
			
		||||
use File::Basename;
 | 
			
		||||
use esmith::templates;
 | 
			
		||||
 | 
			
		||||
use constant TRUE  => 1;
 | 
			
		||||
use constant FALSE => 0;
 | 
			
		||||
 | 
			
		||||
our $VERSION = sprintf '%d.%03d', q$Revision: 1.40 $ =~ /: (\d+).(\d+)/;
 | 
			
		||||
our $Error = undef;
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::DB - virtual interface to E-Smith databases
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
    # Note: Do not instantiate this class directly. Use a subclass.
 | 
			
		||||
    # Examples in this documentation where you see it being used directly 
 | 
			
		||||
    # are merely for consistency. Substitute a subclass in our examples.
 | 
			
		||||
    use esmith::DB;
 | 
			
		||||
    my $db = esmith::DB->create($filename) or 
 | 
			
		||||
                 die esmith::DB->error;
 | 
			
		||||
    my $db = esmith::DB->open($filename)   or 
 | 
			
		||||
                 die esmith::DB->error;
 | 
			
		||||
    my $db = esmith::DB->open_ro($filename) or
 | 
			
		||||
       	     	 die esmith::DB->error;
 | 
			
		||||
 | 
			
		||||
    my %DB = esmith::DB->as_hash($filename) or
 | 
			
		||||
                 die esmith::DB->error;
 | 
			
		||||
 | 
			
		||||
    $db->reload;
 | 
			
		||||
 | 
			
		||||
    my $file = $db->file;
 | 
			
		||||
 | 
			
		||||
    my $record = $db->new_record($key, \%properties);
 | 
			
		||||
 | 
			
		||||
    my $record              = $db->get($key);
 | 
			
		||||
    my @all_records         = $db->get_all;
 | 
			
		||||
    my @all_records_by_prop = $db->get_all_by_prop($prop => $val);
 | 
			
		||||
 | 
			
		||||
    $db->set_prop($key, $prop, $value);
 | 
			
		||||
    $db->set_value($key, $value);
 | 
			
		||||
 | 
			
		||||
    $db->set_prop($key, $prop, $value, type => $type);
 | 
			
		||||
    $db->set_value($key, $value, create => 0);
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
This module is a general interface to E-Smith's databases of various
 | 
			
		||||
types and formats.  It is not intended to be used directly, but that
 | 
			
		||||
subclasses will implement the interface presented here to provide a
 | 
			
		||||
single interface no matter what the underlying format.
 | 
			
		||||
 | 
			
		||||
For example, there is esmith::DB::db to interface with esmith::db
 | 
			
		||||
flatfile databases.  There could also be esmith::DB::Berkeley to use
 | 
			
		||||
Berkeley database files, or even esmith::DB::DBI.
 | 
			
		||||
 | 
			
		||||
Most of the methods herein are "virtual".  They don't exist.  The
 | 
			
		||||
subclass is responsible for impelmenting them.  There are a handful of
 | 
			
		||||
concrete methods that have been implemented for you that should work
 | 
			
		||||
with any subclass.
 | 
			
		||||
 | 
			
		||||
=head2 Virtual Methods
 | 
			
		||||
 | 
			
		||||
This is the esmith::DB interface.  Subclassers are expected to
 | 
			
		||||
implement these methods.
 | 
			
		||||
 | 
			
		||||
=over 4
 | 
			
		||||
 | 
			
		||||
=item I<create>
 | 
			
		||||
 | 
			
		||||
    my $db = esmith::DB->create($new_config_file) || 
 | 
			
		||||
        die esmith::DB->error;
 | 
			
		||||
 | 
			
		||||
Creates a brand new, empty configuration database and returns a
 | 
			
		||||
subclass of the esmith::DB object representing it.
 | 
			
		||||
 | 
			
		||||
Should the $new_config_file already exist or for some reason you can't
 | 
			
		||||
write to it, esmith::DB->error will return the reason and
 | 
			
		||||
create() will return false.
 | 
			
		||||
 | 
			
		||||
=item I<open>
 | 
			
		||||
 | 
			
		||||
    my $db = esmith::DB->open($config_file) || 
 | 
			
		||||
        die esmith::DB->error
 | 
			
		||||
 | 
			
		||||
Loads an existing configuration database and returns a
 | 
			
		||||
subclass of the esmith::DB::db object representing it.
 | 
			
		||||
 | 
			
		||||
Should the $config_file not exist or not be openable it will return
 | 
			
		||||
false and esmith::DB->error will contain the reason.
 | 
			
		||||
 | 
			
		||||
=item I<open_ro>
 | 
			
		||||
 | 
			
		||||
    my $db = esmith::DB->open_ro($config_file) ||
 | 
			
		||||
        die esmith::DB->error;
 | 
			
		||||
 | 
			
		||||
Like open(), but the database is read-only.  new_record() and all methods
 | 
			
		||||
which could change a record (set_prop(), merge_props(), delete(), etc...)
 | 
			
		||||
will both throw exceptions if used.
 | 
			
		||||
 | 
			
		||||
=item I<error>
 | 
			
		||||
 | 
			
		||||
    my $error = esmith::DB->error;
 | 
			
		||||
 | 
			
		||||
Returns a string describing the error from the last failing method.
 | 
			
		||||
 | 
			
		||||
=item I<reload>
 | 
			
		||||
 | 
			
		||||
    $db->reload;
 | 
			
		||||
 | 
			
		||||
Flushes out the $db's cache (if there is one) and reloads all
 | 
			
		||||
configuration data from disk.
 | 
			
		||||
 | 
			
		||||
=item I<file>
 | 
			
		||||
 | 
			
		||||
    my $file = $db->file;
 | 
			
		||||
 | 
			
		||||
File which this $db represents.
 | 
			
		||||
 | 
			
		||||
=item I<new_record>
 | 
			
		||||
 | 
			
		||||
    my $record = $db->new_record($key, \%properties);
 | 
			
		||||
 | 
			
		||||
Adds a new record at $key in the $db setting it to the given
 | 
			
		||||
%properties.  Returns a subclass of the esmith::DB::Record object.
 | 
			
		||||
 | 
			
		||||
If a record already exists for the $key it will return false.
 | 
			
		||||
 | 
			
		||||
=item I<get>
 | 
			
		||||
 | 
			
		||||
    my $record = $db->get($key);
 | 
			
		||||
 | 
			
		||||
Gets an existing record from the $db with the given $key.  Returns an
 | 
			
		||||
esmith::DB::Record object representing the data in $key.
 | 
			
		||||
 | 
			
		||||
If there's no record for the $key it will return false.
 | 
			
		||||
 | 
			
		||||
=item I<get_all>
 | 
			
		||||
 | 
			
		||||
    my @records = $db->get_all;
 | 
			
		||||
 | 
			
		||||
Gets all the records out of the given $db as a list of
 | 
			
		||||
esmith::DB::Record objects.
 | 
			
		||||
 | 
			
		||||
=back
 | 
			
		||||
 | 
			
		||||
=head2 Concrete methods
 | 
			
		||||
 | 
			
		||||
These are all implemented in terms of the esmith::DB interface and
 | 
			
		||||
its not necessary for a subclass to implement them.
 | 
			
		||||
 | 
			
		||||
=over 4
 | 
			
		||||
 | 
			
		||||
=item I<as_hash>
 | 
			
		||||
 | 
			
		||||
    my %db = $db->as_hash;
 | 
			
		||||
    my %db = esmith::DB->as_hash($file);
 | 
			
		||||
 | 
			
		||||
Returns the entire database as a hash of hashes.  Each key is a key in
 | 
			
		||||
the database, and the value is a hash of it's properties.
 | 
			
		||||
 | 
			
		||||
    my $value = $db{some_key}{some_prop};
 | 
			
		||||
 | 
			
		||||
When used as an object method it will use the already opened database.
 | 
			
		||||
When used as a class method it will open the given $file.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub as_hash
 | 
			
		||||
{
 | 
			
		||||
    my ( $proto, $file ) = @_;
 | 
			
		||||
    my $class = ref $proto || $proto;
 | 
			
		||||
 | 
			
		||||
    my $self;
 | 
			
		||||
    if ( ref $proto )
 | 
			
		||||
    {    # object method
 | 
			
		||||
        $self = $proto;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {    # class method
 | 
			
		||||
        $self = $class->open($file) or return;
 | 
			
		||||
    }
 | 
			
		||||
    my %hash = ();
 | 
			
		||||
    foreach my $rec ( $self->get_all )
 | 
			
		||||
    {
 | 
			
		||||
        my $key   = $rec->key;
 | 
			
		||||
        my %props = $rec->props;
 | 
			
		||||
 | 
			
		||||
        # Setup the hash
 | 
			
		||||
        $hash{$key} = \%props;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return %hash;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item I<get_all_by_prop>
 | 
			
		||||
 | 
			
		||||
    my @records_by_prop = $db->get_all_by_prop($property => $value);
 | 
			
		||||
 | 
			
		||||
Like get_all() except it gets only those records whose $property has
 | 
			
		||||
the given $value.  For properties with multiple comma-delimited values 
 | 
			
		||||
(ie: name|val1,val2,val3), only one of the properties needs to match.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub get_all_by_prop
 | 
			
		||||
{
 | 
			
		||||
    my ( $self, $prop, @rest ) = @_;
 | 
			
		||||
    my %props;
 | 
			
		||||
 | 
			
		||||
    if ( ref($prop) eq 'HASH' )
 | 
			
		||||
    {
 | 
			
		||||
	carp "get_all_by_prop called with anonymous hash argument";
 | 
			
		||||
	%props = ( %{$prop} );
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
	%props = ($prop, @rest);
 | 
			
		||||
    }
 | 
			
		||||
    my @things = sort { $a->key cmp $b->key } grep
 | 
			
		||||
	{
 | 
			
		||||
	    my $found = 1;
 | 
			
		||||
	    while ( my ($p, $v) = each (%props) )
 | 
			
		||||
	    {
 | 
			
		||||
		$found &= ( defined $_->prop($p) and $_->prop($p) =~ /(?:^|,)$v(?:,|$)/ );
 | 
			
		||||
	    }
 | 
			
		||||
	    $found;
 | 
			
		||||
	} $self->get_all;
 | 
			
		||||
    @things;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item I<get_value>
 | 
			
		||||
 | 
			
		||||
    my $value = $db->get_value( $key );
 | 
			
		||||
 | 
			
		||||
Shortcut method to get the value from the record defined by the given
 | 
			
		||||
key. Returns undef if the record does not exist. 
 | 
			
		||||
 | 
			
		||||
The following code is unsafe if the key doesn't exist:
 | 
			
		||||
 | 
			
		||||
    my $value = $db->get("foo")->value || 'default';
 | 
			
		||||
 | 
			
		||||
and should be:
 | 
			
		||||
 | 
			
		||||
    my $value = 'default';
 | 
			
		||||
 | 
			
		||||
    if (my $r = $db->get("foo"))
 | 
			
		||||
    {
 | 
			
		||||
        $value = $r->value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
With this method, you can use:
 | 
			
		||||
 | 
			
		||||
    my $value = $db->get_value("foo") || 'default';
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub get_value
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my $item = $self->get(shift);
 | 
			
		||||
    return undef unless $item;
 | 
			
		||||
    return $item->value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item I<get_prop>
 | 
			
		||||
 | 
			
		||||
    my $prop = $db->get_prop( $key, $prop );
 | 
			
		||||
 | 
			
		||||
Shortcut method to get a property from the record defined by the given key.
 | 
			
		||||
 | 
			
		||||
Returns undef if the record for that key doesn't exist, or the property does
 | 
			
		||||
not exist.
 | 
			
		||||
 | 
			
		||||
The following code is unsafe if either the key or property doesn't exist:
 | 
			
		||||
 | 
			
		||||
    my $status = $db->get("foo")->prop('status') || 'disabled';
 | 
			
		||||
 | 
			
		||||
and should be written as:
 | 
			
		||||
 | 
			
		||||
my $status;
 | 
			
		||||
 | 
			
		||||
if (my $s = $db->get("foo"))
 | 
			
		||||
{
 | 
			
		||||
    $status = $s->prop('status');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
$status ||= "default";
 | 
			
		||||
 | 
			
		||||
With this method, you can use:
 | 
			
		||||
 | 
			
		||||
    my $value = $db->get_prop("foo", "status") || 'default';
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub get_prop
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my $item = $self->get(shift);
 | 
			
		||||
    return undef unless $item;
 | 
			
		||||
    return $item->prop(shift);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item I<set_value>
 | 
			
		||||
 | 
			
		||||
    $db->set_value($key, $value)[, create => 1]);
 | 
			
		||||
 | 
			
		||||
Shortcut method to set a value to a key in the database without extracting the
 | 
			
		||||
record first.
 | 
			
		||||
 | 
			
		||||
If the record is not pre-existing, it will be created, unless the 'create'
 | 
			
		||||
option is passed with a value of 0.
 | 
			
		||||
 | 
			
		||||
Returns 0 for any errors, 1 for success.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub set_value
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my ($key, $value, %options) = @_;
 | 
			
		||||
 | 
			
		||||
    my %defaults = (create => 1);
 | 
			
		||||
    %options = (%defaults, %options);
 | 
			
		||||
 | 
			
		||||
    my $record = $self->get($key);
 | 
			
		||||
    unless ($record)
 | 
			
		||||
    {
 | 
			
		||||
        if ($options{create})
 | 
			
		||||
        {
 | 
			
		||||
            $record = $self->new_record($key, {type => $value})
 | 
			
		||||
                or return 0;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    $record->set_value($value)
 | 
			
		||||
        or return 0;
 | 
			
		||||
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item I<set_prop>
 | 
			
		||||
 | 
			
		||||
    $db->set_prop($key, $prop, $value[, type => $type]);
 | 
			
		||||
 | 
			
		||||
Shortcut method to set a property on a record without having to extract the
 | 
			
		||||
record first.
 | 
			
		||||
 | 
			
		||||
If the optional type option is passed, it will be used to create the record if
 | 
			
		||||
it does not already exist. Otherwise, a non-existent record will cause this
 | 
			
		||||
method to return an error.
 | 
			
		||||
 | 
			
		||||
Returns 0 for any errors, 1 for success.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub set_prop
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my ($key, $prop, $value, %options) = @_;
 | 
			
		||||
    my %defaults = (type => '');
 | 
			
		||||
    %options = (%defaults, %options);
 | 
			
		||||
 | 
			
		||||
    my $record = $self->get($key);
 | 
			
		||||
    unless ($record)
 | 
			
		||||
    {
 | 
			
		||||
        if ($options{type})
 | 
			
		||||
        {
 | 
			
		||||
            $record = $self->new_record($key, {type => $options{type}})
 | 
			
		||||
                or return 0;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    $record->set_prop($prop, $value)
 | 
			
		||||
        or return 0;
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item I<keys>
 | 
			
		||||
 | 
			
		||||
    foreach my $key ($db->keys)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
A simple convenience function to prevent having to access the config hash
 | 
			
		||||
inside the db object (technically private), or calling map across a get_all
 | 
			
		||||
call, which is what this is going to do. :)
 | 
			
		||||
 | 
			
		||||
This method returns a list of keys to the records in the db. It does not sort.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub keys
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    return map { $_->{key} } $self->get_all;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 migrate
 | 
			
		||||
 | 
			
		||||
Process the fragments in the migration queue for this database, using
 | 
			
		||||
processTemplate.
 | 
			
		||||
 | 
			
		||||
The defaults are loaded from /etc/e-smith/db/<dbname>/migrate by default, but
 | 
			
		||||
the environment variable ESMITH_DB_DEFAULTSDIR can be set to use a different
 | 
			
		||||
hierarchy if required.
 | 
			
		||||
 | 
			
		||||
The entries in "migrate" are perl fragments which will be evaluated and
 | 
			
		||||
so can munge anything they choose to. But, please be gentle :-)
 | 
			
		||||
 | 
			
		||||
So you could have
 | 
			
		||||
 | 
			
		||||
    /etc/e-smith/db/configuration/migrate/sshd/access
 | 
			
		||||
 | 
			
		||||
which is a perl fragment which does something funky to migrate the access
 | 
			
		||||
property from some old value to some new value.
 | 
			
		||||
 | 
			
		||||
After running all the migration scripts, and reloading the DB's data into
 | 
			
		||||
its local cache, the private method _loadDefaults is called to set any
 | 
			
		||||
missing default values and any forced settings.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub migrate
 | 
			
		||||
{
 | 
			
		||||
    my ($self) = @_;
 | 
			
		||||
 | 
			
		||||
    my $dbfile = basename( $self->{file} );
 | 
			
		||||
    unless ($dbfile)
 | 
			
		||||
    {
 | 
			
		||||
        carp "migrate can't determine filename";
 | 
			
		||||
        return undef;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    my $defaults_dir = $ENV{ESMITH_DB_DEFAULTSDIR} || "/etc/e-smith/db";
 | 
			
		||||
    my $dir          = "$defaults_dir/$dbfile/migrate";
 | 
			
		||||
 | 
			
		||||
    eval {
 | 
			
		||||
        if ( -d $dir )
 | 
			
		||||
        {
 | 
			
		||||
            processTemplate(
 | 
			
		||||
                {
 | 
			
		||||
                    MORE_DATA             => { 'DB_FILENAME' => $dbfile },
 | 
			
		||||
                    TEMPLATE_PATH         => '',
 | 
			
		||||
                    OUTPUT_TYPE           => 'string',
 | 
			
		||||
                    TEMPLATE_EXPAND_QUEUE =>
 | 
			
		||||
                      [ $dir, "/etc/e-smith/templates-default" ]
 | 
			
		||||
                }
 | 
			
		||||
            );
 | 
			
		||||
            $self->reload;
 | 
			
		||||
        }
 | 
			
		||||
        $self->_loadDefaults();
 | 
			
		||||
    };
 | 
			
		||||
    if ($@)
 | 
			
		||||
    {
 | 
			
		||||
        warn "Warning: Migration of $dbfile failed fatally: $@\n";
 | 
			
		||||
        $self->set_error($@);
 | 
			
		||||
        return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 resetToDefaults
 | 
			
		||||
 | 
			
		||||
Reset all entries to their default values, if defaults exist. This calls
 | 
			
		||||
the internal method _loadDefaults with the forceReset flag set. It should
 | 
			
		||||
not be used lightly!!
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub resetToDefaults
 | 
			
		||||
{
 | 
			
		||||
    my ($self) = @_;
 | 
			
		||||
 | 
			
		||||
    $self->_loadDefaults(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 record_has_defaults
 | 
			
		||||
 | 
			
		||||
Returns true if there are defaults or force directories for the
 | 
			
		||||
given record name
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub record_has_defaults
 | 
			
		||||
{
 | 
			
		||||
    my ( $self, $name ) = @_;
 | 
			
		||||
 | 
			
		||||
    my $dbfile = basename( $self->{file} );
 | 
			
		||||
 | 
			
		||||
    unless ($dbfile)
 | 
			
		||||
    {
 | 
			
		||||
        carp "record_has_defaults can't determine filename";
 | 
			
		||||
        return undef;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    unless ($name)
 | 
			
		||||
    {
 | 
			
		||||
        carp "record_has_defaults can't determine record name";
 | 
			
		||||
        return undef;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    my $defaults_dir = $ENV{ESMITH_DB_DEFAULTSDIR} || "/etc/e-smith/db";
 | 
			
		||||
    my $dir          = "$defaults_dir/$dbfile";
 | 
			
		||||
 | 
			
		||||
    return ( -d "$dir/defaults/$name" ) || ( -d "$dir/force/$name" );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 _loadDefaults ($forceReset)
 | 
			
		||||
 | 
			
		||||
B<This is a private method.>
 | 
			
		||||
 | 
			
		||||
Load the default properties for a given database.
 | 
			
		||||
Caller can provide a flag to force resetting properties that already exist.
 | 
			
		||||
 | 
			
		||||
Any forced properties will be evaluated after setting the default properties.
 | 
			
		||||
 | 
			
		||||
The defaults are loaded from the following directories in order (the 
 | 
			
		||||
environment variable ESMITH_DB_DEFAULTSDIR can be set to use a different 
 | 
			
		||||
hierarchy if required):
 | 
			
		||||
 | 
			
		||||
    /etc/e-smith/db/<dbname>/defaults
 | 
			
		||||
    /etc/e-smith/db/<dbname>/force
 | 
			
		||||
 | 
			
		||||
Each of these directories is arranged as a set of subdirectories, with the
 | 
			
		||||
directory name equal to the key for the given database. With these
 | 
			
		||||
subdirectories are files, which are named by the properties of these
 | 
			
		||||
database keys.
 | 
			
		||||
 | 
			
		||||
The entries in "defaults" will be skipped if the existing key/property
 | 
			
		||||
already exists (unless the $forceReset argument is provided). These are
 | 
			
		||||
simple files, whose contents are the value to be used for that property.
 | 
			
		||||
 | 
			
		||||
The entries in "force" are always loaded into the given key/property.
 | 
			
		||||
These are again simple files, like "defaults".
 | 
			
		||||
 | 
			
		||||
To make this concrete, you might have:
 | 
			
		||||
 | 
			
		||||
    /etc/e-smith/db/configuration/defaults/sshd/access
 | 
			
		||||
 | 
			
		||||
containing the single word "private", which would be the default. This
 | 
			
		||||
value would only be used if no "access" property existed, or the 
 | 
			
		||||
$forceReset option is passed.
 | 
			
		||||
 | 
			
		||||
You can override both "defaults" and "migrate" with
 | 
			
		||||
 | 
			
		||||
    /etc/e-smith/db/configuration/force/sshd/access
 | 
			
		||||
 | 
			
		||||
containing the single word "public" to force the value of that property.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub _loadDefaults
 | 
			
		||||
{
 | 
			
		||||
    my ( $self, $force ) = @_;
 | 
			
		||||
 | 
			
		||||
    my $dbfile = basename( $self->{file} );
 | 
			
		||||
    unless ($dbfile)
 | 
			
		||||
    {
 | 
			
		||||
        carp "_loadDefaults can't determine filename";
 | 
			
		||||
        return undef;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    my $defaults_dir = $ENV{ESMITH_DB_DEFAULTSDIR} || "/etc/e-smith/db";
 | 
			
		||||
 | 
			
		||||
    my @propQueue =
 | 
			
		||||
      ( "$defaults_dir/$dbfile/defaults", "$defaults_dir/$dbfile/force", );
 | 
			
		||||
 | 
			
		||||
    foreach my $dir (@propQueue)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        # Always process the force dir
 | 
			
		||||
        $force = 1 if ( $dir =~ /\/force$/ );
 | 
			
		||||
 | 
			
		||||
        next unless opendir DH, $dir;
 | 
			
		||||
        foreach my $key ( grep !/^\./, readdir DH )
 | 
			
		||||
        {
 | 
			
		||||
            if ( -d "$dir/$key" )
 | 
			
		||||
            {
 | 
			
		||||
                my %props = ();
 | 
			
		||||
 | 
			
		||||
                my $rec = $self->get($key);
 | 
			
		||||
 | 
			
		||||
                opendir DH2, "$dir/$key";
 | 
			
		||||
                foreach my $prop ( grep !/^\./, readdir DH2 )
 | 
			
		||||
                {
 | 
			
		||||
                    unless ($force)
 | 
			
		||||
                    {
 | 
			
		||||
                        next if ( $rec && defined $rec->prop($prop) );
 | 
			
		||||
                    }
 | 
			
		||||
                    open FH, "$dir/$key/$prop";
 | 
			
		||||
                    my $val = join "", (<FH>);
 | 
			
		||||
                    chomp $val;
 | 
			
		||||
 | 
			
		||||
                    $props{$prop} = $val;
 | 
			
		||||
                    close FH;
 | 
			
		||||
                }
 | 
			
		||||
                closedir DH2;
 | 
			
		||||
                if ($rec)
 | 
			
		||||
                {
 | 
			
		||||
                    $rec->merge_props(%props);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    $rec = $self->new_record( $key, \%props );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                warn "Found non-directory $key in $dir\n";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        close DH;
 | 
			
		||||
    }
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 get_value_and_delete ($key)
 | 
			
		||||
 | 
			
		||||
Retrieve the value of the named key, return it, and delete the record.
 | 
			
		||||
If the key does not exist, it returns undef. This is normally called from
 | 
			
		||||
migration code.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub get_value_and_delete
 | 
			
		||||
{
 | 
			
		||||
    my ( $self, $key ) = @_;
 | 
			
		||||
    my $ret;
 | 
			
		||||
    my $rec = $self->get($key);
 | 
			
		||||
    if ($rec)
 | 
			
		||||
    {
 | 
			
		||||
        $ret = $rec->value;
 | 
			
		||||
        $rec->delete;
 | 
			
		||||
    }
 | 
			
		||||
    return $ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 get_prop_and_delete ($key, $prop)
 | 
			
		||||
 | 
			
		||||
Retrieve the named property of the named key, return the value, and delete the
 | 
			
		||||
property from the record. Returns undef if the property or key does not exist.
 | 
			
		||||
This is normally called from migration code.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub get_prop_and_delete
 | 
			
		||||
{
 | 
			
		||||
    my ( $self, $key, $prop ) = @_;
 | 
			
		||||
    my $ret;
 | 
			
		||||
    my $rec = $self->get($key);
 | 
			
		||||
    if ($rec)
 | 
			
		||||
    {
 | 
			
		||||
        $ret = $rec->prop($prop);
 | 
			
		||||
        $rec->delete_prop($prop);
 | 
			
		||||
    }
 | 
			
		||||
    return $ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub set_error
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    $Error = shift;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub error
 | 
			
		||||
{
 | 
			
		||||
    return $Error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=back
 | 
			
		||||
 | 
			
		||||
=head1 AUTHOR
 | 
			
		||||
 | 
			
		||||
SME Server Developers <bugs@e-smith.com>
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
							
								
								
									
										157
									
								
								root/usr/share/perl5/vendor_perl/esmith/DB/Record.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								root/usr/share/perl5/vendor_perl/esmith/DB/Record.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,157 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::DB::Record;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use warnings;
 | 
			
		||||
use esmith::DB;
 | 
			
		||||
 | 
			
		||||
our $VERSION = sprintf '%d.%03d', q$Revision: 1.6 $ =~ /: (\d+).(\d+)/;
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::DB::Record - an individual record in an E-Smith database
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
B<DO NOT USE THIS CLASS DIRECTLY!>  use via esmith::DB.
 | 
			
		||||
 | 
			
		||||
    my $key  = $record->key;
 | 
			
		||||
 | 
			
		||||
    my %properties = $record->props;
 | 
			
		||||
 | 
			
		||||
    my $value = $record->prop($prop_key);
 | 
			
		||||
                $record->set_prop($prop_key, $prop_val);
 | 
			
		||||
 | 
			
		||||
    my $value = $record->delete_prop($prop_key);
 | 
			
		||||
 | 
			
		||||
    $record->merge_props(%more_properties);
 | 
			
		||||
    $record->reset_props(%new_properties);
 | 
			
		||||
 | 
			
		||||
    $record->delete;
 | 
			
		||||
 | 
			
		||||
    print $record->show;
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
This class is a general interface to individual records in esmith::DB
 | 
			
		||||
databases.  It should not be used directly, but rather esmith::DBs
 | 
			
		||||
should hand you esmith::DB::Record objects.
 | 
			
		||||
 | 
			
		||||
Each subclass of esmith::DB will also have to subclass and implement
 | 
			
		||||
an esmith::DB::Record subclass.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=head2 Virtual Methods
 | 
			
		||||
 | 
			
		||||
=over 4
 | 
			
		||||
 | 
			
		||||
=item B<key>
 | 
			
		||||
 | 
			
		||||
  my $key = $record->key;
 | 
			
		||||
 | 
			
		||||
Returns the $key for this $record;
 | 
			
		||||
 | 
			
		||||
=item B<props>
 | 
			
		||||
 | 
			
		||||
  my %properties = $record->props;
 | 
			
		||||
  my $num_props  = $record->props;
 | 
			
		||||
 | 
			
		||||
Returns a hash of all the properties for this $record.  In scalar
 | 
			
		||||
context it will return the number of properties this $record has.
 | 
			
		||||
 | 
			
		||||
=item B<prop>
 | 
			
		||||
 | 
			
		||||
=item B<set_prop>
 | 
			
		||||
 | 
			
		||||
  my $value = $record->prop($property);
 | 
			
		||||
              $record->set_prop($property, $value);
 | 
			
		||||
 | 
			
		||||
Gets/sets the $value of the $property in this $record.
 | 
			
		||||
 | 
			
		||||
set_prop() will die if the database is read-only.
 | 
			
		||||
 | 
			
		||||
=item B<delete_prop>
 | 
			
		||||
 | 
			
		||||
  my $value = $record->delete_prop($property);
 | 
			
		||||
 | 
			
		||||
Deletes a $property from the $record, returning the old $value.
 | 
			
		||||
 | 
			
		||||
delete_prop() will die if the database is read-only.
 | 
			
		||||
 | 
			
		||||
=item B<merge_props>
 | 
			
		||||
 | 
			
		||||
  $record->merge_props(%properties);
 | 
			
		||||
 | 
			
		||||
Adds the %properties to the $records existing properties.  Any new
 | 
			
		||||
keys will be added, any existing keys will be overwritten.
 | 
			
		||||
 | 
			
		||||
merge_props() will die if the database is read-only.
 | 
			
		||||
 | 
			
		||||
=item B<reset_props>
 | 
			
		||||
 | 
			
		||||
  $record->reset_props(%properties);
 | 
			
		||||
 | 
			
		||||
Replaces the $record's properties with the contents of %properties.
 | 
			
		||||
Any old properties will be deleted.
 | 
			
		||||
 | 
			
		||||
reset_props() will die if the database is read-only.
 | 
			
		||||
 | 
			
		||||
=item B<delete>
 | 
			
		||||
 | 
			
		||||
  $record->delete;
 | 
			
		||||
 | 
			
		||||
Deletes the $record from its database.
 | 
			
		||||
 | 
			
		||||
delete() will die if the database is read-only.
 | 
			
		||||
 | 
			
		||||
=back
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=head2 Concrete methods
 | 
			
		||||
 | 
			
		||||
=over 4
 | 
			
		||||
 | 
			
		||||
=item B<show>
 | 
			
		||||
 | 
			
		||||
  my $formatted = $record->show;
 | 
			
		||||
 | 
			
		||||
Returns the $record's key and properties in a nice, human readable
 | 
			
		||||
format suitable for printing.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub show {
 | 
			
		||||
     my($self) = shift;
 | 
			
		||||
 | 
			
		||||
     my $out = $self->key."\n";
 | 
			
		||||
 | 
			
		||||
     my %props = $self->props;
 | 
			
		||||
 | 
			
		||||
     # Determine our longest key so we know how to format.
 | 
			
		||||
     my $max_len = 0;
 | 
			
		||||
     foreach (keys %props) { $max_len = length if length > $max_len }
 | 
			
		||||
 | 
			
		||||
     # But don't go too far.
 | 
			
		||||
     $max_len = 40 if $max_len > 40;
 | 
			
		||||
 | 
			
		||||
     foreach my $prop (sort { $a cmp $b } keys %props) {
 | 
			
		||||
         $out .= sprintf "  %${max_len}s = %s\n", $prop, $props{$prop};
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
     return $out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=back
 | 
			
		||||
 | 
			
		||||
=head1 SEE ALSO
 | 
			
		||||
 | 
			
		||||
L<esmith::DB>
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
							
								
								
									
										660
									
								
								root/usr/share/perl5/vendor_perl/esmith/DB/db.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										660
									
								
								root/usr/share/perl5/vendor_perl/esmith/DB/db.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,660 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::DB::db;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use warnings;
 | 
			
		||||
use Carp;
 | 
			
		||||
 | 
			
		||||
our $VERSION = sprintf '%d.%03d', q$Revision: 1.29 $ =~ /: (\d+).(\d+)/;
 | 
			
		||||
 | 
			
		||||
use esmith::db;
 | 
			
		||||
use esmith::config;
 | 
			
		||||
use esmith::DB::db::Record;
 | 
			
		||||
use esmith::DB;
 | 
			
		||||
our @ISA = qw(esmith::DB);
 | 
			
		||||
 | 
			
		||||
=for testing
 | 
			
		||||
use_ok('esmith::DB::db');
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::DB::db - interface to esmith::db databases 
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
I<Works just like an esmith::DB class except where noted>
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
This module provides an abstracted interface to esmith::db flat-file
 | 
			
		||||
databases.  It will read from and write to esmith::db files and can be
 | 
			
		||||
safely used right along side esmith::db.  This follows the esmith::DB
 | 
			
		||||
interface and will work as documented there unless otherwise stated.
 | 
			
		||||
 | 
			
		||||
You should use this instead of esmith::db, and replace any existing
 | 
			
		||||
esmith::db code with this.
 | 
			
		||||
 | 
			
		||||
I<Note for esmith::db users> the old concept of a 'type' is now simply
 | 
			
		||||
another property.
 | 
			
		||||
 | 
			
		||||
    my $type = $record->prop('type');
 | 
			
		||||
 | 
			
		||||
replaces db_get_type().
 | 
			
		||||
 | 
			
		||||
The $record returned by esmith::DB::db subclass is an esmith::DB::db::Record
 | 
			
		||||
subclass object. See the esmith::DB::db manpage for details on how it is used.
 | 
			
		||||
 | 
			
		||||
=head2 Methods
 | 
			
		||||
 | 
			
		||||
=over 4
 | 
			
		||||
 | 
			
		||||
=item B<create>
 | 
			
		||||
 | 
			
		||||
Puts its error on esmith::DB::db->error
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
$Scratch_Conf = '10e-smith-lib/scratch.conf';
 | 
			
		||||
unlink $Scratch_Conf;
 | 
			
		||||
$db = esmith::DB::db->create($Scratch_Conf);
 | 
			
		||||
END { unlink $Scratch_Conf }
 | 
			
		||||
 | 
			
		||||
isa_ok( $db, 'esmith::DB::db', 'create()' );
 | 
			
		||||
ok( -e $Scratch_Conf, 'created a new config file' ); 
 | 
			
		||||
ok(! esmith::DB::db->create($Scratch_Conf), 
 | 
			
		||||
                              'create() wont walk over an existing config' );
 | 
			
		||||
like( esmith::DB::db->error, qr/^File exists/,    '  right error message' );
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub create
 | 
			
		||||
{
 | 
			
		||||
    my ( $class, $file ) = @_;
 | 
			
		||||
    $file = $class->_file_path($file);
 | 
			
		||||
    my $self;
 | 
			
		||||
 | 
			
		||||
    eval {
 | 
			
		||||
        $self = $class->_init($file);
 | 
			
		||||
        croak "File exists" if -e $file;
 | 
			
		||||
 | 
			
		||||
        $self->{config} = $self->_get_config($file)
 | 
			
		||||
          || croak "Can't get the esmith::config object";
 | 
			
		||||
 | 
			
		||||
        # touch the config file so it gets created immediately
 | 
			
		||||
        open( FILE, ">>$file" )
 | 
			
		||||
            or die "Failed to open $file for appending: $!\n";
 | 
			
		||||
        close FILE;
 | 
			
		||||
 | 
			
		||||
        # Migrate, and check for errors, propagating them if they happen.
 | 
			
		||||
        unless ( $self->migrate() )
 | 
			
		||||
        {
 | 
			
		||||
            chomp $@;
 | 
			
		||||
            $self->set_error($@);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    if ($@)
 | 
			
		||||
    {
 | 
			
		||||
        chomp $@;
 | 
			
		||||
        $self->set_error($@);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    return $self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item B<open>
 | 
			
		||||
 | 
			
		||||
=for notes
 | 
			
		||||
There's currently no way to get the reason why from esmith::config.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
unlink $Scratch_Conf;
 | 
			
		||||
ok( !esmith::DB::db->open($Scratch_Conf),  'open() on a non-existent db' );
 | 
			
		||||
is( esmith::DB::db->error, "File doesn't exist", '  right error' );
 | 
			
		||||
 | 
			
		||||
esmith::DB::db->create($Scratch_Conf);
 | 
			
		||||
$DB = esmith::DB::db->open($Scratch_Conf);
 | 
			
		||||
isa_ok( $DB, 'esmith::DB::db' );
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub open
 | 
			
		||||
{
 | 
			
		||||
    my ( $class, $file ) = @_;
 | 
			
		||||
    $file = $class->_file_path($file);
 | 
			
		||||
    my $self = $class->_init($file);
 | 
			
		||||
 | 
			
		||||
    if ( -e $file && !-w $file )
 | 
			
		||||
    {
 | 
			
		||||
        $self->{ro} = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return $self->_open($file) ? $self : undef;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item B<open_local>
 | 
			
		||||
 | 
			
		||||
=for notes
 | 
			
		||||
There's currently no way to get the reason why from esmith::config.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
unlink $Scratch_Conf;
 | 
			
		||||
ok( !esmith::DB::db->open_local($Scratch_Conf), 'open() on a non-existent db' );
 | 
			
		||||
is( esmith::DB::db->error, "File doesn't exist", '  right error' );
 | 
			
		||||
 | 
			
		||||
esmith::DB::db->create($Scratch_Conf);
 | 
			
		||||
$DB = esmith::DB::db->open_local($Scratch_Conf);
 | 
			
		||||
isa_ok( $DB, 'esmith::DB::db' );
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub open_local
 | 
			
		||||
{
 | 
			
		||||
    my ( $class, $file ) = @_;
 | 
			
		||||
    $file = $class->_file_path($file);
 | 
			
		||||
    my $self = $class->_init($file);
 | 
			
		||||
 | 
			
		||||
    if ( -e $file && !-w $file )
 | 
			
		||||
    {
 | 
			
		||||
        $self->{ro} = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return $self->_open($file) ? $self : undef;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
ok( my $db = esmith::DB::db->open_ro($Scratch_Conf), 
 | 
			
		||||
    'open_ro on a non-existent db');
 | 
			
		||||
eval { $db->new_record('foo', { type => 'bar' }) };
 | 
			
		||||
like( $@, qr/^This DB is opened read-only/ );
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub open_ro
 | 
			
		||||
{
 | 
			
		||||
    my ( $class, $file ) = @_;
 | 
			
		||||
    $file = $class->_file_path($file);
 | 
			
		||||
    my $self = $class->_init($file);
 | 
			
		||||
 | 
			
		||||
    $self->{ro} = 1;
 | 
			
		||||
 | 
			
		||||
    return $self->_open($file) ? $self : undef;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
ok( my $db = esmith::DB::db->open_ro_local($Scratch_Conf), 
 | 
			
		||||
    'open_ro on a non-existent db');
 | 
			
		||||
eval { $db->new_record('foo', { type => 'bar' }) };
 | 
			
		||||
like( $@, qr/^This DB is opened read-only/ );
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub open_ro_local
 | 
			
		||||
{
 | 
			
		||||
    my ( $class, $file ) = @_;
 | 
			
		||||
    $file = $class->_file_path($file);
 | 
			
		||||
    my $self = $class->_init($file);
 | 
			
		||||
 | 
			
		||||
    $self->{ro} = 1;
 | 
			
		||||
 | 
			
		||||
    return $self->_open($file) ? $self : undef;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
sub is_ro
 | 
			
		||||
{
 | 
			
		||||
    return $_[0]->{ro} ? 1 : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub _open
 | 
			
		||||
{
 | 
			
		||||
    my ( $self, $file ) = @_;
 | 
			
		||||
 | 
			
		||||
    eval {
 | 
			
		||||
 | 
			
		||||
        # This is unfortunately not atomic, but I don't think
 | 
			
		||||
        # that's a big deal.
 | 
			
		||||
        die "File doesn't exist\n"  unless -e $file;
 | 
			
		||||
        die "File isn't readable\n" unless -r $file;
 | 
			
		||||
 | 
			
		||||
        $self->{config} = $self->_get_config($file)
 | 
			
		||||
          || die "Can't get the esmith::config object";
 | 
			
		||||
    };
 | 
			
		||||
    if ($@)
 | 
			
		||||
    {
 | 
			
		||||
        chomp $@;
 | 
			
		||||
        $self->set_error($@);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub _get_config
 | 
			
		||||
{
 | 
			
		||||
    my ( $self, $file ) = @_;
 | 
			
		||||
 | 
			
		||||
    my %config;
 | 
			
		||||
    tie %config, $self->tie_class, $file;
 | 
			
		||||
 | 
			
		||||
    return \%config;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub _init
 | 
			
		||||
{
 | 
			
		||||
    my ( $class, $file ) = @_;
 | 
			
		||||
 | 
			
		||||
    my $self = bless { file => $file }, $class;
 | 
			
		||||
 | 
			
		||||
    return $self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub _file_path
 | 
			
		||||
{
 | 
			
		||||
    my ( $class, $file ) = @_;
 | 
			
		||||
 | 
			
		||||
    if ($file =~ m:/:)
 | 
			
		||||
    {
 | 
			
		||||
	use File::Basename;
 | 
			
		||||
	warn "Deprecated pathname $file passed to _file_path()\n"
 | 
			
		||||
	    if dirname($file) eq "/home/e-smith";
 | 
			
		||||
	return $file;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (-e "/home/e-smith/db/$file")
 | 
			
		||||
    {
 | 
			
		||||
	return "/home/e-smith/db/$file";
 | 
			
		||||
    } elsif (-e "/home/e-smith/$file") {
 | 
			
		||||
	warn "Database found in old location /home/e-smith/$file";
 | 
			
		||||
	return "/home/e-smith/$file";
 | 
			
		||||
    } else {
 | 
			
		||||
	return "/home/e-smith/db/$file";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item B<as_hash>
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
use esmith::TestUtils qw(scratch_copy);
 | 
			
		||||
my $scratch = scratch_copy('10e-smith-lib/db_dummy.conf');
 | 
			
		||||
my %db = esmith::DB::db->as_hash($scratch);
 | 
			
		||||
 | 
			
		||||
my %expect = (     Foo      => { type => 'Bar' },
 | 
			
		||||
                   Night    => { type => 'Day' },
 | 
			
		||||
                   Squid    => { type    => 'cephalopod',
 | 
			
		||||
                                 arms    => 10,
 | 
			
		||||
                                 species => 'Loligo' },
 | 
			
		||||
                   Pipe     => { type    => 'art',
 | 
			
		||||
                                 pipe    => 'this is not a | got that?',},
 | 
			
		||||
                   Haiku    => { type    => 'poem',
 | 
			
		||||
                                 words   => 
 | 
			
		||||
"Damian Conway\nGod damn! Damian Conway\nDamian Conway",
 | 
			
		||||
                               },
 | 
			
		||||
                   Octopus  => { type    => 'cephalopod',
 | 
			
		||||
                                 arms    => 8,
 | 
			
		||||
                                 species => '',
 | 
			
		||||
                               }
 | 
			
		||||
             );
 | 
			
		||||
 | 
			
		||||
is_deeply( \%db, \%expect );
 | 
			
		||||
 | 
			
		||||
%db = esmith::DB::db->open($scratch)->as_hash;
 | 
			
		||||
is_deeply( \%db, \%expect );
 | 
			
		||||
                   
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=item B<reload>
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
my $db2 = esmith::DB::db->open($Scratch_Conf);
 | 
			
		||||
my $something = $DB->new_record('something', { type => "wibble" });
 | 
			
		||||
isa_ok( $something, 'esmith::DB::db::Record', 'new record in 1st DB' );
 | 
			
		||||
 | 
			
		||||
ok( !$db2->get('something'),    '  2nd DB still cant see new record' );
 | 
			
		||||
ok( $db2->reload,               '  reload' );
 | 
			
		||||
ok( $db2->get('something'),     '  2nd DB can see new record' );
 | 
			
		||||
 | 
			
		||||
$something->delete;
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub reload
 | 
			
		||||
{
 | 
			
		||||
    my ($self) = shift;
 | 
			
		||||
 | 
			
		||||
    $self->_open( $self->file );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item B<file>
 | 
			
		||||
 | 
			
		||||
=for testing
 | 
			
		||||
is( $db->file, $Scratch_Conf, 'file()' );
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub file
 | 
			
		||||
{
 | 
			
		||||
    my ($self) = shift;
 | 
			
		||||
    return $self->{file};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item B<new_record>
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
my $record = $DB->new_record('Big Brother', { year => 1984,
 | 
			
		||||
                                              day => 'night',
 | 
			
		||||
                                              type => 'Govt',
 | 
			
		||||
                             });
 | 
			
		||||
isa_ok( $record, 'esmith::DB::db::Record', 'new_record' );
 | 
			
		||||
is( $record->key,  'Big Brother',  'key' );
 | 
			
		||||
is( $record->prop('type'), 'Govt',         'type' );
 | 
			
		||||
is_deeply( {$record->props}, {year => 1984, day => 'night', type => 'Govt'}, 
 | 
			
		||||
                                                           'props' );
 | 
			
		||||
is( $record->prop('year'), 1984,        'prop() get' );
 | 
			
		||||
is( $record->prop('day'),  'night',     'prop() get again' );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
$record = $DB->new_record('No props');
 | 
			
		||||
isa_ok( $record, 'esmith::DB::db::Record', 'new_record() w/o props' );
 | 
			
		||||
is( $record->key,  'No props', '  key' );
 | 
			
		||||
 | 
			
		||||
my $db2 = esmith::DB::db->open($DB->file);
 | 
			
		||||
ok( $db2->get('No props'), '  can be gotten' );
 | 
			
		||||
 | 
			
		||||
$record->delete;
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub new_record
 | 
			
		||||
{
 | 
			
		||||
    my ( $self, $key, $props ) = @_;
 | 
			
		||||
 | 
			
		||||
    croak "This DB is opened read-only" if $self->is_ro;
 | 
			
		||||
 | 
			
		||||
    if ( defined db_get( $self->{config}, $key ) )
 | 
			
		||||
    {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    my $type = exists $props->{type} ? delete $props->{type} : '';
 | 
			
		||||
    db_set( $self->{config}, $key, $type, $props );
 | 
			
		||||
    $self->tie_class->_writeconf($self->{file}, $self->{config});
 | 
			
		||||
 | 
			
		||||
    return esmith::DB::db::Record->_construct( $self, $key, $self->{config} );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item B<get>
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
my $rec = $DB->get('Big Brother');
 | 
			
		||||
isa_ok( $rec, 'esmith::DB::db::Record', 'get' );
 | 
			
		||||
is( $rec->key, 'Big Brother',  '  right key' );
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub get
 | 
			
		||||
{
 | 
			
		||||
    my ( $self, $key ) = @_;
 | 
			
		||||
 | 
			
		||||
    unless ( defined db_get( $self->{config}, $key ) )
 | 
			
		||||
    {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return esmith::DB::db::Record->_construct( $self, $key, $self->{config} );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item B<get_all>
 | 
			
		||||
 | 
			
		||||
=begin testing 
 | 
			
		||||
 | 
			
		||||
$DB->new_record('Borg', { type => 'Govt', resistance => 'futile' });
 | 
			
		||||
my @records = $DB->get_all;
 | 
			
		||||
is( @records, 2, 'get_all' );
 | 
			
		||||
ok( !(grep { !$_->isa('esmith::DB::db::Record') } @records),
 | 
			
		||||
                                          '  theyre all records' );
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub get_all
 | 
			
		||||
{
 | 
			
		||||
    my ($self) = shift;
 | 
			
		||||
 | 
			
		||||
    return
 | 
			
		||||
      map { esmith::DB::db::Record->_construct( $self, $_, $self->{config} ) }
 | 
			
		||||
      db_get( $self->{config} );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item B<get_all_by_prop>
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
$DB->new_record('Pretz', { type => 'snack', flavor => 'old fashion' });
 | 
			
		||||
my @records = $DB->get_all_by_prop(type => 'Govt');
 | 
			
		||||
is( @records, 2, 'get_all_by_prop() type' );
 | 
			
		||||
ok( !(grep { $_->prop('type') ne 'Govt' } @records), 
 | 
			
		||||
                                   '  theyre the right type' );
 | 
			
		||||
 | 
			
		||||
$DB->new_record('Pork lips', { type => 'snack', flavor => 'old fashion' });
 | 
			
		||||
@records = $DB->get_all_by_prop(flavor => 'old fashion');
 | 
			
		||||
is( @records, 2, 'get_all_by_prop()' );
 | 
			
		||||
ok( !(grep { $_->prop('flavor') ne 'old fashion' } @records),
 | 
			
		||||
                                   '  they have the right properties' );
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub tie_class
 | 
			
		||||
{
 | 
			
		||||
    return 'esmith::config';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub close
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=begin deprecated
 | 
			
		||||
 | 
			
		||||
=item B<list_by_type>
 | 
			
		||||
 | 
			
		||||
Given a type of item to look for in the database (eg "service", "ibay"), 
 | 
			
		||||
returns a list of items which are that type.  This is the underlying 
 | 
			
		||||
routine behind esmith::AccountsDB::ibays() and similar methods.
 | 
			
		||||
 | 
			
		||||
=end deprecated
 | 
			
		||||
 | 
			
		||||
=for testing
 | 
			
		||||
ok($DB->list_by_type("Govt"), "list_by_type *deprecated*");
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub list_by_type
 | 
			
		||||
{
 | 
			
		||||
    my ( $self, $type ) = @_;
 | 
			
		||||
 | 
			
		||||
    return map $_->key, $self->get_all_by_prop( type => $type );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=back
 | 
			
		||||
 | 
			
		||||
=head1 EXAMPLE
 | 
			
		||||
 | 
			
		||||
The full docs can be found in esmith::DB and esmith::DB::Record, but
 | 
			
		||||
here's a cheat sheet for esmith::config and esmith::db users.
 | 
			
		||||
 | 
			
		||||
=over 4
 | 
			
		||||
 | 
			
		||||
=item opening the default config
 | 
			
		||||
 | 
			
		||||
    use esmith::config
 | 
			
		||||
    my %config;
 | 
			
		||||
    tie %config, 'esmith::config;
 | 
			
		||||
 | 
			
		||||
Now:
 | 
			
		||||
 | 
			
		||||
    use esmith::ConfigDB;
 | 
			
		||||
    my $config = esmith::ConfigDB->open;
 | 
			
		||||
 | 
			
		||||
=item opening a specific config database
 | 
			
		||||
 | 
			
		||||
    my %config;
 | 
			
		||||
    tie %config, 'esmith::config', $config_file;
 | 
			
		||||
 | 
			
		||||
Now:
 | 
			
		||||
 | 
			
		||||
    my $config = esmith::ConfigDB->open($config_file);
 | 
			
		||||
 | 
			
		||||
=item creating a new config database
 | 
			
		||||
 | 
			
		||||
This one's important.  Before you could just tie esmith::config to any file
 | 
			
		||||
and it would create it for you.  Now you have to explicitly create it.
 | 
			
		||||
 | 
			
		||||
    my %config;
 | 
			
		||||
    tie %config, 'esmith::config', $new_config_file;
 | 
			
		||||
 | 
			
		||||
Now:
 | 
			
		||||
 | 
			
		||||
    my $config = esmith::ConfigDB->create($new_config_file);
 | 
			
		||||
 | 
			
		||||
=item checking if a record exists
 | 
			
		||||
 | 
			
		||||
    print "Yep" if exists $config{foo};
 | 
			
		||||
 | 
			
		||||
now:
 | 
			
		||||
 | 
			
		||||
    print "Yep" if $config->get('foo'); # unless of course, 'foo' is zero
 | 
			
		||||
 | 
			
		||||
=item creating a new record
 | 
			
		||||
 | 
			
		||||
Previously you could just create records on the fly:
 | 
			
		||||
 | 
			
		||||
    # single value
 | 
			
		||||
    $config{foo} = 'whatever';
 | 
			
		||||
 | 
			
		||||
    # with properties
 | 
			
		||||
    db_set(\%config, 'whatever', 'sometype', { with => 'properties' });
 | 
			
		||||
 | 
			
		||||
Now you have to explicitly create them:
 | 
			
		||||
 | 
			
		||||
    # single value
 | 
			
		||||
    my $foo = $config->new_record('foo');
 | 
			
		||||
    $foo->set_value('foo');
 | 
			
		||||
 | 
			
		||||
    # with properties
 | 
			
		||||
    my %defaults = ( 'type'    => 'sometype',
 | 
			
		||||
                     'linux'   => 'stable',
 | 
			
		||||
                     'windows' => 'stable?' );
 | 
			
		||||
    my $foo = $config->new_record('foo', \%defaults);
 | 
			
		||||
 | 
			
		||||
Note that 'type' is now just another property.
 | 
			
		||||
 | 
			
		||||
Here's a handy "create this if it doesn't already exist" idiom.
 | 
			
		||||
 | 
			
		||||
    my $rec = $config->get($key) ||
 | 
			
		||||
              $config->new_record($key);
 | 
			
		||||
 | 
			
		||||
=item getting a value
 | 
			
		||||
 | 
			
		||||
Entries in a database should no longer be thought of as values, but as
 | 
			
		||||
records.
 | 
			
		||||
 | 
			
		||||
    my $val = $config{foo};
 | 
			
		||||
 | 
			
		||||
Now this only works with entries with single value. Things with
 | 
			
		||||
multiple properties are dealt with differently.
 | 
			
		||||
 | 
			
		||||
    my $record = $config->get('foo');
 | 
			
		||||
    my $val = $record->value;
 | 
			
		||||
 | 
			
		||||
=item setting a value
 | 
			
		||||
 | 
			
		||||
    $config{foo} = 'something';
 | 
			
		||||
 | 
			
		||||
now
 | 
			
		||||
 | 
			
		||||
    my $record = $config->get('foo');
 | 
			
		||||
    $record->set_value('something');
 | 
			
		||||
 | 
			
		||||
=item getting a property
 | 
			
		||||
 | 
			
		||||
    my $this = db_get_prop(\%config, 'foo', 'this');
 | 
			
		||||
 | 
			
		||||
now:
 | 
			
		||||
 | 
			
		||||
    my $foo = $config->get('foo');
 | 
			
		||||
    my $this = $foo->prop('this');
 | 
			
		||||
 | 
			
		||||
=item getting & setting properties
 | 
			
		||||
 | 
			
		||||
    my $val = db_get_prop(\%config, 'foo', 'some prop');
 | 
			
		||||
    db_set_prop(\%config, 'foo', 'some prop' => $new_val);
 | 
			
		||||
 | 
			
		||||
now:
 | 
			
		||||
 | 
			
		||||
    my $val = $record->prop('some prop');
 | 
			
		||||
    $record->set_prop('some prop' => $new_val);
 | 
			
		||||
 | 
			
		||||
=item get/setting the type
 | 
			
		||||
 | 
			
		||||
    my $type = db_get_type(\%config, 'foo');
 | 
			
		||||
    db_set_type(\%config, 'foo', $new_type);
 | 
			
		||||
 | 
			
		||||
type is now just a property
 | 
			
		||||
 | 
			
		||||
    my $record = $db->get('foo');
 | 
			
		||||
    my $type = $record->prop('type');
 | 
			
		||||
    $record->set_prop('type', $new_type);
 | 
			
		||||
 | 
			
		||||
=item getting all the properties
 | 
			
		||||
 | 
			
		||||
    my %props = db_get_prop(\%config, 'foo');
 | 
			
		||||
 | 
			
		||||
now
 | 
			
		||||
 | 
			
		||||
    my %props = $record->props;
 | 
			
		||||
 | 
			
		||||
=back
 | 
			
		||||
 | 
			
		||||
=head1 AUTHOR
 | 
			
		||||
 | 
			
		||||
SME Server Developers <bugs@e-smith.com>
 | 
			
		||||
 | 
			
		||||
=head1 SEE ALSO
 | 
			
		||||
 | 
			
		||||
L<esmith::AccountsDB>, L<esmith::ConfigDB>, L<esmith::DB::db::Record>
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
							
								
								
									
										353
									
								
								root/usr/share/perl5/vendor_perl/esmith/DB/db/Record.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										353
									
								
								root/usr/share/perl5/vendor_perl/esmith/DB/db/Record.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,353 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::DB::db::Record;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use warnings;
 | 
			
		||||
use Carp;
 | 
			
		||||
 | 
			
		||||
use esmith::db;
 | 
			
		||||
use esmith::DB::db;
 | 
			
		||||
 | 
			
		||||
require esmith::DB::Record;
 | 
			
		||||
our @ISA = qw(esmith::DB::Record);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
use_ok('esmith::DB::db::Record');
 | 
			
		||||
use_ok('esmith::DB::db');
 | 
			
		||||
 | 
			
		||||
use File::Copy;
 | 
			
		||||
$Scratch_Conf = '10e-smith-lib/scratch.conf';
 | 
			
		||||
copy('10e-smith-lib/db_dummy.conf', $Scratch_Conf);
 | 
			
		||||
END { unlink $Scratch_Conf }
 | 
			
		||||
 | 
			
		||||
$DB = esmith::DB::db->open($Scratch_Conf);
 | 
			
		||||
$Squid = $DB->get('Squid');
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::DB::db::Record - Individual records in an esmith::db database
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
Unless otherwise noted, works just like esmith::DB::Record.
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
This class represents entries in esmith::db flat-file database.  A
 | 
			
		||||
single object is a single line.
 | 
			
		||||
 | 
			
		||||
This class is not useful by itself but rather they are handed out
 | 
			
		||||
via esmith::DB::db objects.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=begin protected
 | 
			
		||||
 | 
			
		||||
=head2 Protected Methods
 | 
			
		||||
 | 
			
		||||
These methods are only allowed to be called by esmith::DB::db classes.
 | 
			
		||||
 | 
			
		||||
=item B<_construct>
 | 
			
		||||
 | 
			
		||||
  my $record = esmith::DB::db::Record->_construct($db, $key, $config);
 | 
			
		||||
 | 
			
		||||
Generates a new esmith::DB::db::Record representing data inside the
 | 
			
		||||
$db (an esmith::DB::db object).
 | 
			
		||||
 | 
			
		||||
This does *not* write anything into $db.  This is here so a $db can
 | 
			
		||||
initialize a new Record from existing data.
 | 
			
		||||
 | 
			
		||||
=end protected
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub _construct {
 | 
			
		||||
    my($class, $db, $key, $config) = @_;
 | 
			
		||||
 | 
			
		||||
    die "_construct may only be called by esmith::DB::db"
 | 
			
		||||
      unless caller->isa('esmith::DB::db');
 | 
			
		||||
    
 | 
			
		||||
    my $self = {
 | 
			
		||||
                db      => $db,
 | 
			
		||||
                config  => $config,
 | 
			
		||||
                key     => $key
 | 
			
		||||
               };
 | 
			
		||||
 | 
			
		||||
    return bless $self, $class;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 Methods
 | 
			
		||||
 | 
			
		||||
=over 4
 | 
			
		||||
 | 
			
		||||
=item B<key>
 | 
			
		||||
 | 
			
		||||
=for testing
 | 
			
		||||
is( $Squid->key, 'Squid', 'key()' );
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub key {
 | 
			
		||||
    my($self) = shift;
 | 
			
		||||
    return $self->{key};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item B<props>
 | 
			
		||||
 | 
			
		||||
=for testing
 | 
			
		||||
is_deeply( {$Squid->props}, {arms => 10, species => 'Loligo', 
 | 
			
		||||
                             type => 'cephalopod'},          'props()' );
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub props {
 | 
			
		||||
    my($self) = shift;
 | 
			
		||||
 | 
			
		||||
    my %props = db_get_prop($self->{config}, $self->{key});
 | 
			
		||||
    $props{type} = db_get_type($self->{config}, $self->{key});
 | 
			
		||||
    foreach my $prop (keys %props) {
 | 
			
		||||
        $props{$prop} =~ s{\\\|}{\|}g if $props{$prop};
 | 
			
		||||
    }
 | 
			
		||||
    return wantarray ? %props : keys %props;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item B<prop>
 | 
			
		||||
 | 
			
		||||
=item B<set_prop>
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
is( $Squid->prop('arms'), 10,     'prop()' );
 | 
			
		||||
$Squid->set_prop('arms', 1000);
 | 
			
		||||
is( $Squid->prop('arms'), 1000,   'set_prop()' );
 | 
			
		||||
 | 
			
		||||
is( $Squid->prop('type'), 'cephalopod',         'prop() type get' );
 | 
			
		||||
$Squid->set_prop('type', 'tree dweller');
 | 
			
		||||
is( $Squid->prop('type'), 'tree dweller',       'set_prop() type set' );
 | 
			
		||||
 | 
			
		||||
$Squid->set_prop('bar', 'foo | bar');
 | 
			
		||||
is( $Squid->prop('bar'), 'foo  bar',           'prop/set_prop with pipes - pipe stripped' );
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
    my $warning = '';
 | 
			
		||||
    local $SIG{__WARN__} = sub { $warning = join '', @_ };
 | 
			
		||||
    $Squid->prop('bar', 'foo');
 | 
			
		||||
    like( $warning, qr/^prop\(\) got extra arguments 'foo'. Maybe you ment set_prop\(\)\?/,  'prop()/set_prop() mixup warns' );
 | 
			
		||||
 | 
			
		||||
    $warning = '';
 | 
			
		||||
    is( $Squid->prop('I_dont_exist'), undef,  'prop() on non-existent prop' );
 | 
			
		||||
    is( $warning, '', '  no warning' );
 | 
			
		||||
 | 
			
		||||
    $warning = '';
 | 
			
		||||
    $Squid->set_prop('I_dont_exist', undef);
 | 
			
		||||
    is( $Squid->prop('I_dont_exist'), '', 'set_prop() with undef value' );
 | 
			
		||||
    is( $warning, '', '  no warning' );
 | 
			
		||||
    $Squid->delete_prop('I_dont_exist');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub prop {
 | 
			
		||||
    my($self, $property) = splice @_, 0, 2;
 | 
			
		||||
 | 
			
		||||
    warn sprintf "prop() got extra arguments '%s'. Maybe you ment set_prop()?",
 | 
			
		||||
      "@_" if @_;
 | 
			
		||||
 | 
			
		||||
    my $value;
 | 
			
		||||
    if( $property eq 'type' ) {
 | 
			
		||||
        $value = db_get_type($self->{config}, $self->{key});
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        $value = db_get_prop($self->{config}, $self->{key}, $property);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # Unescape escaped pipes.  esmith::db can't do this for us.
 | 
			
		||||
    $value =~ s{\\\|}{\|}g if defined $value;
 | 
			
		||||
 | 
			
		||||
    return $value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub set_prop {
 | 
			
		||||
    my($self, $property, $value) = @_;
 | 
			
		||||
 | 
			
		||||
    croak "The DB is open read-only" if $self->{db}->is_ro;
 | 
			
		||||
 | 
			
		||||
    # Strip pipes - we can't safely escape them while some code
 | 
			
		||||
    # still expects to split on pipe
 | 
			
		||||
    $value =~ s{\|}{}g if defined $value;
 | 
			
		||||
 | 
			
		||||
    my $ret;
 | 
			
		||||
    if( $property eq 'type' ) {
 | 
			
		||||
        $ret = db_set_type($self->{config}, $self->{key}, $value);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        $ret = db_set_prop($self->{config}, $self->{key}, 
 | 
			
		||||
                           $property => $value);
 | 
			
		||||
    }
 | 
			
		||||
    return $ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=item B<delete_prop>
 | 
			
		||||
 | 
			
		||||
A special case for esmith::DB::db::Record, you're not allowed to
 | 
			
		||||
delete the 'type' property.
 | 
			
		||||
 | 
			
		||||
=for testing
 | 
			
		||||
is( $Squid->delete_prop('species'), 'Loligo', 
 | 
			
		||||
                                  'delete_prop() returns the old value' );
 | 
			
		||||
is_deeply( {$Squid->props}, {arms => 1000, bar => 'foo  bar',
 | 
			
		||||
                             type => 'tree dweller' },
 | 
			
		||||
                                  '  and deletes' );
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub delete_prop {
 | 
			
		||||
    my($self, $property) = @_;
 | 
			
		||||
 | 
			
		||||
    croak "The DB is open read-only" if $self->{db}->is_ro;
 | 
			
		||||
 | 
			
		||||
    croak "You're not allowed to delete a type from an esmith::DB::db::Record" 
 | 
			
		||||
      if $property eq 'type';
 | 
			
		||||
 | 
			
		||||
    my $val = $self->prop($property);
 | 
			
		||||
    db_delete_prop($self->{config}, $self->{key}, $property);
 | 
			
		||||
    
 | 
			
		||||
    return $val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item B<merge_props>
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
my $octopus = $DB->get('Octopus');
 | 
			
		||||
$octopus->merge_props( arms => '8 + 2i', name => 'Fluffy', pipe => 'not |');
 | 
			
		||||
is_deeply( {$octopus->props}, { arms => '8 + 2i', type => 'cephalopod',
 | 
			
		||||
                                species => '', name => 'Fluffy',
 | 
			
		||||
                                pipe => 'not ' },   'merge_props()' );
 | 
			
		||||
$octopus->merge_props( type => 'foo' );
 | 
			
		||||
is_deeply( {$octopus->props}, { arms => '8 + 2i', type => 'foo',
 | 
			
		||||
                                species => '', name => 'Fluffy',
 | 
			
		||||
                                pipe => 'not ' },   '  with type' );
 | 
			
		||||
 | 
			
		||||
$octopus->merge_props( { type => 'foo' } );
 | 
			
		||||
like( $_STDERR_, qr/^merge_props\(\) was accidentally passed a hash ref/m,
 | 
			
		||||
                                       '  anti-hash ref protection');
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub merge_props {
 | 
			
		||||
    my($self, %new_props) = @_;
 | 
			
		||||
 | 
			
		||||
    croak "The DB is open read-only" if $self->{db}->is_ro;
 | 
			
		||||
 | 
			
		||||
    if( ref $_[1] ) {
 | 
			
		||||
        carp("merge_props() was accidentally passed a hash ref");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    my %props = $self->props;
 | 
			
		||||
    my %merged_props = (%props, %new_props);
 | 
			
		||||
 | 
			
		||||
    # Strip out pipes.
 | 
			
		||||
    foreach my $prop (keys %merged_props) {
 | 
			
		||||
        $merged_props{$prop} =~ s{\|}{}g 
 | 
			
		||||
          if defined $merged_props{$prop};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    my $type = delete $merged_props{type};
 | 
			
		||||
    db_set($self->{config}, $self->{key}, $type, \%merged_props);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item B<reset_props>
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
my $octopus = $DB->get('Octopus');
 | 
			
		||||
 | 
			
		||||
eval { $octopus->reset_props( { type => 'foo' } ); };
 | 
			
		||||
like( $_STDERR_, qr/^reset_props\(\) was accidentally passed a hash ref/m,
 | 
			
		||||
                                       '  anti-hash ref protection');
 | 
			
		||||
 | 
			
		||||
$octopus->reset_props( arms => 8, name => 'Rupert', type => 'foo' );
 | 
			
		||||
is_deeply( {$octopus->props}, { arms => '8', name => 'Rupert',
 | 
			
		||||
                                type => 'foo' },   'reset_props' );
 | 
			
		||||
 | 
			
		||||
eval { $octopus->reset_props( arms => '8 + 2i', name => 'Fluffy', 
 | 
			
		||||
                              pipe => 'not ') };
 | 
			
		||||
like( $@, qr/^You must have a type property/,  '  you must have a type');
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub reset_props {
 | 
			
		||||
    my($self, %new_props) = @_;
 | 
			
		||||
 | 
			
		||||
    croak "The DB is open read-only" if $self->{db}->is_ro;
 | 
			
		||||
 | 
			
		||||
    if( ref $_[1] ) {
 | 
			
		||||
        carp("reset_props() was accidentally passed a hash ref");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    die "You must have a type property" unless $new_props{type};
 | 
			
		||||
 | 
			
		||||
    # Strip out pipes
 | 
			
		||||
    foreach my $prop (keys %new_props) {
 | 
			
		||||
        $new_props{$prop} =~ s{\|}{}g
 | 
			
		||||
          if defined $new_props{$prop};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    my $type = delete $new_props{type} || $self->prop('type');
 | 
			
		||||
    db_set($self->{config}, $self->{key}, $type, \%new_props);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=item B<delete>
 | 
			
		||||
 | 
			
		||||
=for testing
 | 
			
		||||
my $foo = $DB->get('Foo');
 | 
			
		||||
$foo->delete;
 | 
			
		||||
ok( !$DB->get('Foo'), 'delete()' );
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub delete {
 | 
			
		||||
    my($self) = shift;
 | 
			
		||||
 | 
			
		||||
    croak "The DB is open read-only" if $self->{db}->is_ro;
 | 
			
		||||
    db_delete($self->{config}, $self->{key});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item B<show>
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
is( $Squid->show, <<SQUID, 'show' );
 | 
			
		||||
Squid
 | 
			
		||||
  arms = 1000
 | 
			
		||||
   bar = foo  bar
 | 
			
		||||
  type = tree dweller
 | 
			
		||||
SQUID
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=back
 | 
			
		||||
 | 
			
		||||
=head1 SEE ALSO
 | 
			
		||||
 | 
			
		||||
L<esmith::DB::db>
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
							
								
								
									
										99
									
								
								root/usr/share/perl5/vendor_perl/esmith/DomainsDB.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								root/usr/share/perl5/vendor_perl/esmith/DomainsDB.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::DomainsDB;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use warnings;
 | 
			
		||||
 | 
			
		||||
use esmith::DB::db;
 | 
			
		||||
our @ISA = qw( esmith::DB::db );
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::DomainsDB - interface to esmith domains database
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
    use esmith::DomainsDB;
 | 
			
		||||
    my $c = esmith::DomainsDB->open;
 | 
			
		||||
 | 
			
		||||
    # everything else works just like esmith::DB::db
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
This module provides an abstracted interface to the esmith domain
 | 
			
		||||
database.
 | 
			
		||||
 | 
			
		||||
Unless otherwise noted, esmith::DomainsDB acts like esmith::DB::db.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
=head2 open()
 | 
			
		||||
 | 
			
		||||
Like esmith::DB->open, but if given no $file it will try to open the
 | 
			
		||||
file in the ESMITH_DOMAINS_DB environment variable or domains.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
use_ok("esmith::DomainsDB");
 | 
			
		||||
 | 
			
		||||
$C = esmith::DomainsDB->open('10e-smith-lib/domains.conf');
 | 
			
		||||
isa_ok($C, 'esmith::DomainsDB');
 | 
			
		||||
is( $C->get("test")->prop('foo'), "bar", 
 | 
			
		||||
                                    "We can get stuff from the db");
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub open {
 | 
			
		||||
    my ($self, $file) = @_;
 | 
			
		||||
    $file = $file || $ENV{ESMITH_DOMAINS_DB} || "domains";
 | 
			
		||||
    return $self->SUPER::open($file);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 open_ro()
 | 
			
		||||
 | 
			
		||||
Like esmith::DB->open_ro, but if given no $file it will try to open the
 | 
			
		||||
file in the ESMITH_DOMAINS_DB environment variable or domains.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub open_ro {
 | 
			
		||||
    my($class, $file) = @_;
 | 
			
		||||
    $file = $file || $ENV{ESMITH_DOMAINS_DB} || "domains";
 | 
			
		||||
    return $class->SUPER::open_ro($file);
 | 
			
		||||
}
 | 
			
		||||
=for testing
 | 
			
		||||
$C = esmith::DomainsDB->open('10e-smith-lib/domains.conf');
 | 
			
		||||
isa_ok($C, 'esmith::DomainsDB');
 | 
			
		||||
can_ok($C, 'domains');
 | 
			
		||||
can_ok($C, 'get_all_by_prop');
 | 
			
		||||
is(scalar($C->domains()), 2, "Found 2 domains with domains()");
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub domains {
 | 
			
		||||
    my ($self) = @_;
 | 
			
		||||
    return $self->get_all_by_prop(type => 'domain');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head1 AUTHOR
 | 
			
		||||
 | 
			
		||||
SME Server Developers <bugs@e-smith.com>
 | 
			
		||||
 | 
			
		||||
=head1 SEE ALSO
 | 
			
		||||
 | 
			
		||||
L<esmith::ConfigDB>
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
							
								
								
									
										230
									
								
								root/usr/share/perl5/vendor_perl/esmith/HostsDB.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										230
									
								
								root/usr/share/perl5/vendor_perl/esmith/HostsDB.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,230 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::HostsDB;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use warnings;
 | 
			
		||||
 | 
			
		||||
use esmith::DB::db;
 | 
			
		||||
our @ISA = qw( esmith::DB::db );
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::HostsDB - interface to esmith hostnames/addresses database
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
    use esmith::HostsDB;
 | 
			
		||||
    my $hosts = esmith::HostsDB->open;
 | 
			
		||||
 | 
			
		||||
    # everything else works just like esmith::DB::db
 | 
			
		||||
 | 
			
		||||
    # these methods are added
 | 
			
		||||
    my @hosts     = $hosts->hosts;
 | 
			
		||||
    my @new_hosts = $hosts->propogate_hosts;
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
This module provides an abstracted interface to the esmith hosts
 | 
			
		||||
database.
 | 
			
		||||
 | 
			
		||||
Unless otherwise noted, esmith::HostsDB acts like esmith::DB::db.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
=head2 Overridden methods
 | 
			
		||||
 | 
			
		||||
=over 4
 | 
			
		||||
 | 
			
		||||
=item I<open>
 | 
			
		||||
 | 
			
		||||
Like esmith::DB->open, but if given no $file it will try to open the
 | 
			
		||||
file in the ESMITH_HOSTS_DB environment variable or hosts.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
use_ok("esmith::HostsDB");
 | 
			
		||||
 | 
			
		||||
$H = esmith::HostsDB->open('10e-smith-lib/hosts.conf');
 | 
			
		||||
isa_ok($H, 'esmith::HostsDB');
 | 
			
		||||
is( $H->get("otherhost.mydomain.xxx")->prop('InternalIP'), "192.168.1.3", 
 | 
			
		||||
                                    "We can get stuff from the db");
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub open {
 | 
			
		||||
    my($class, $file) = @_;
 | 
			
		||||
    $file = $file || $ENV{ESMITH_HOSTS_DB} || "hosts";
 | 
			
		||||
    return $class->SUPER::open($file);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 open_ro()
 | 
			
		||||
 | 
			
		||||
Like esmith::DB->open_ro, but if given no $file it will try to open the
 | 
			
		||||
file in the ESMITH_HOSTS_DB environment variable or hosts.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub open_ro {
 | 
			
		||||
    my($class, $file) = @_;
 | 
			
		||||
    $file = $file || $ENV{ESMITH_HOSTS_DB} || "hosts";
 | 
			
		||||
    return $class->SUPER::open_ro($file);
 | 
			
		||||
}
 | 
			
		||||
=back
 | 
			
		||||
 | 
			
		||||
=head2 Additional Methods
 | 
			
		||||
 | 
			
		||||
These methods are added be esmith::HostsDB
 | 
			
		||||
 | 
			
		||||
=over 4
 | 
			
		||||
 | 
			
		||||
=item I<hosts>
 | 
			
		||||
 | 
			
		||||
    my @hosts = $hosts->hosts;
 | 
			
		||||
 | 
			
		||||
Returns a list of all host records in the database.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
$db = esmith::HostsDB->open('10e-smith-lib/hosts.conf');
 | 
			
		||||
isa_ok($db, 'esmith::HostsDB');
 | 
			
		||||
can_ok($db, 'hosts');
 | 
			
		||||
my @hosts = $db->hosts();
 | 
			
		||||
isnt( @hosts, 0 );
 | 
			
		||||
is_deeply(\@hosts, [$db->get_all_by_prop('type' => 'host')]);
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub hosts {
 | 
			
		||||
    my ($self) = @_;
 | 
			
		||||
    return $self->get_all_by_prop('type' => 'host');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item I<propogate_hosts>
 | 
			
		||||
 | 
			
		||||
    my @new_hosts = $hosts->propogate_hosts($old_name, $new_name);
 | 
			
		||||
 | 
			
		||||
When the name of your e-smith machine changes, this will change the
 | 
			
		||||
name of any hosts which also started with $old_name to use the
 | 
			
		||||
$new_name.
 | 
			
		||||
 | 
			
		||||
Returns a list of the newly tranlsated host records.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
use esmith::ConfigDB;
 | 
			
		||||
 | 
			
		||||
my $hosts_file = '10e-smith-lib/propogate_hosts.conf';
 | 
			
		||||
END { unlink $hosts_file }
 | 
			
		||||
 | 
			
		||||
my $db     = esmith::HostsDB->create($hosts_file);
 | 
			
		||||
 | 
			
		||||
use esmith::TestUtils qw(scratch_copy);
 | 
			
		||||
my $c_scratch = scratch_copy('10e-smith-lib/configuration.conf');
 | 
			
		||||
my $config = esmith::ConfigDB->open($c_scratch);
 | 
			
		||||
isa_ok($config, 'esmith::ConfigDB');
 | 
			
		||||
 | 
			
		||||
my $name   = $config->get('SystemName')->value;
 | 
			
		||||
 | 
			
		||||
# setup some dummy hosts to propogate.
 | 
			
		||||
foreach my $host ( "$name.tofu-dog.com", "$name.wibble.org",
 | 
			
		||||
                     "wibble.$name.org", "yarrow.hack" )
 | 
			
		||||
{
 | 
			
		||||
    $db->new_record($host, { type => 'host',  HostType => 'Self',
 | 
			
		||||
                             ExternalIP => '', InternalIP => ''
 | 
			
		||||
                           });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
$db->reload;
 | 
			
		||||
my @new_hosts = $db->propogate_hosts($name, "armondo");
 | 
			
		||||
my @hosts = $db->hosts;
 | 
			
		||||
is( @hosts, 4 );
 | 
			
		||||
is_deeply( [sort map { $_->key } @hosts], 
 | 
			
		||||
           [sort +('armondo.tofu-dog.com',
 | 
			
		||||
                   'armondo.wibble.org',
 | 
			
		||||
                   "wibble.$name.org",
 | 
			
		||||
                   'yarrow.hack',
 | 
			
		||||
                  )] 
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
is( @new_hosts, 2 );
 | 
			
		||||
is_deeply( [sort map { $_->key } @new_hosts],
 | 
			
		||||
           [sort qw(armondo.tofu-dog.com armondo.wibble.org)] 
 | 
			
		||||
         );
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub propogate_hosts 
 | 
			
		||||
{
 | 
			
		||||
    my($self, $old_name, $new_name) = @_;
 | 
			
		||||
 | 
			
		||||
    my @new_hosts = ();
 | 
			
		||||
    foreach my $host ($self->hosts)
 | 
			
		||||
    {
 | 
			
		||||
        my $new_host = $host->key;
 | 
			
		||||
        if( $new_host =~ s/^\Q$old_name.\E/$new_name./ ) 
 | 
			
		||||
        {
 | 
			
		||||
            push @new_hosts, $self->new_record($new_host, 
 | 
			
		||||
                                               { $host->props }
 | 
			
		||||
                                              );
 | 
			
		||||
            $host->delete;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return @new_hosts;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=head2 $db->get_hosts_by_domain
 | 
			
		||||
 | 
			
		||||
Given a domain name (as a string), finds any hosts which match it and
 | 
			
		||||
return them as a list of record objects.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
my $h = esmith::HostsDB->open('10e-smith-lib/hosts.conf');
 | 
			
		||||
my @hosts = $h->get_hosts_by_domain('otherdomain.xxx');
 | 
			
		||||
is(scalar(@hosts), 2, "Found two hosts in otherdomain.xxx");
 | 
			
		||||
isa_ok($hosts[0], 'esmith::DB::Record');
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub get_hosts_by_domain {
 | 
			
		||||
    my ($self, $domain) = @_;
 | 
			
		||||
    my @all = $self->get_all();
 | 
			
		||||
    my @return;
 | 
			
		||||
    foreach my $h (@all) {
 | 
			
		||||
        push @return, $h if $h->key() =~ /^[^\.]+\.$domain$/;
 | 
			
		||||
    }
 | 
			
		||||
    return @return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=back
 | 
			
		||||
 | 
			
		||||
=head1 AUTHOR
 | 
			
		||||
 | 
			
		||||
SME Server Developers <bugs@e-smith.com>
 | 
			
		||||
 | 
			
		||||
=head1 SEE ALSO
 | 
			
		||||
 | 
			
		||||
L<esmith::ConfigDB>
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
							
								
								
									
										331
									
								
								root/usr/share/perl5/vendor_perl/esmith/I18N.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										331
									
								
								root/usr/share/perl5/vendor_perl/esmith/I18N.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,331 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::I18N;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
 | 
			
		||||
use esmith::ConfigDB;
 | 
			
		||||
use POSIX qw(setlocale LC_ALL LC_CTYPE);
 | 
			
		||||
use Locale::gettext;
 | 
			
		||||
use I18N::AcceptLanguage;
 | 
			
		||||
use I18N::LangTags qw(is_language_tag locale2language_tag);
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::I18N - Internationalization utilities Mitel Network SME Server
 | 
			
		||||
 | 
			
		||||
=head1 VERSION
 | 
			
		||||
 | 
			
		||||
This file documents C<esmith::I18N> version B<1.4.0>
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
    use esmith::I18N;
 | 
			
		||||
 | 
			
		||||
    my $i18n = new esmith::I18N;
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
This module provides general internationalization and localisation
 | 
			
		||||
utilities for developers of the Mitel Networks SME Server.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
use I18N::LangTags qw(is_language_tag locale2language_tag language_tag2locale);
 | 
			
		||||
use_ok('esmith::I18N');
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=head1 GENERAL UTILITIES
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub new
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my $class = ref($self) || $self;
 | 
			
		||||
 | 
			
		||||
    my %args = @_;
 | 
			
		||||
 | 
			
		||||
    return $self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 availableLocales()
 | 
			
		||||
 | 
			
		||||
Returns an array containing the available locales supported by the
 | 
			
		||||
server.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
$ENV{ESMITH_CONFIG_DB}="10e-smith-lib/sysconfig-en_US.conf";
 | 
			
		||||
$ENV{ESMITH_I18N_USRSHARELOCALE}="10e-smith-lib/usr/share/locale";
 | 
			
		||||
 | 
			
		||||
my $i18n = new esmith::I18N;
 | 
			
		||||
my @locales = grep !/CVS/, sort $i18n->availableLocales;
 | 
			
		||||
 | 
			
		||||
# NOTE: de is not a valid locale for the test - no server-console file
 | 
			
		||||
is_deeply(\@locales, [('en_US', 'fr_CA', 'wx_YZ')], "Locales match" );
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub availableLocales()
 | 
			
		||||
{
 | 
			
		||||
    my ($self) = shift;
 | 
			
		||||
 | 
			
		||||
    my $localedir = $ENV{ESMITH_I18N_USRSHARELOCALE} || '/usr/share/locale';
 | 
			
		||||
 | 
			
		||||
    return () unless opendir LOCALE, $localedir;
 | 
			
		||||
 | 
			
		||||
    my @locales;
 | 
			
		||||
 | 
			
		||||
    foreach my $locale ( grep(!/\./, readdir LOCALE) )
 | 
			
		||||
    {
 | 
			
		||||
        push @locales, $locale if 
 | 
			
		||||
		(-f "$localedir/$locale/LC_MESSAGES/server-console.mo" or
 | 
			
		||||
		 -f "$localedir/$locale/LC_MESSAGES/server-console.po");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    closedir LOCALE;
 | 
			
		||||
    return @locales;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 fallbackLocale()
 | 
			
		||||
 | 
			
		||||
Return system fallback locale
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub fallbackLocale()
 | 
			
		||||
{
 | 
			
		||||
    return "en_US.utf8";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 preferredLocale()
 | 
			
		||||
 | 
			
		||||
Retrieves the preferred locale for this server.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
$ENV{ESMITH_CONFIG_DB}="10e-smith-lib/sysconfig-en_US.conf";
 | 
			
		||||
 | 
			
		||||
my $i18n = new esmith::I18N;
 | 
			
		||||
is($i18n->preferredLocale, 'en_US', "en_US.conf: Preferred locale is en_US");
 | 
			
		||||
 | 
			
		||||
$ENV{ESMITH_CONFIG_DB}="10e-smith-lib/sysconfig-fr_CA.conf";
 | 
			
		||||
 | 
			
		||||
$i18n = new esmith::I18N;
 | 
			
		||||
is($i18n->preferredLocale, 'fr_CA', "fr_CA.conf: Preferred locale is fr_CA");
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub preferredLocale()
 | 
			
		||||
{
 | 
			
		||||
    my ($self) = shift;
 | 
			
		||||
 | 
			
		||||
    my $db = esmith::ConfigDB->open_ro || return $self->fallbackLocale;
 | 
			
		||||
 | 
			
		||||
    my ($locale, @rest) = $db->getLocale();
 | 
			
		||||
 | 
			
		||||
    return $locale || $self->fallbackLocale;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 setLocale()
 | 
			
		||||
 | 
			
		||||
Configure the locale for gettext() for the supplied text domain.
 | 
			
		||||
 | 
			
		||||
The method takes two arguments, the text domain, and an optional argument
 | 
			
		||||
which can be either a language tag or a locale.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub setLocale()
 | 
			
		||||
{
 | 
			
		||||
    my ($self, $text_domain, $opt) = @_;
 | 
			
		||||
    my $locale;
 | 
			
		||||
 | 
			
		||||
    $locale = $self->langtag2locale($opt) if ($opt);
 | 
			
		||||
    $locale ||= $self->preferredLocale;
 | 
			
		||||
    $locale =~ s{(?:\..*)?$}{.utf8};
 | 
			
		||||
 | 
			
		||||
    $ENV{'LANGUAGE'} = $locale;
 | 
			
		||||
    $ENV{'LANG'}     = $ENV{'LANGUAGE'};
 | 
			
		||||
 | 
			
		||||
    setlocale(LC_MESSAGES, $locale);
 | 
			
		||||
    setlocale(LC_MESSAGES, $locale);
 | 
			
		||||
    setlocale(LC_ALL, $locale);
 | 
			
		||||
    setlocale(LC_ALL, $locale);
 | 
			
		||||
 | 
			
		||||
    bindtextdomain ($text_domain, "/usr/share/locale");
 | 
			
		||||
    textdomain ($text_domain);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=head2 langtag2locale
 | 
			
		||||
 | 
			
		||||
Even though the directories appear in /usr/share/locale, they also need
 | 
			
		||||
to appear in /usr/lib/locale to actually be treated as locales. Read the
 | 
			
		||||
Perl locale docs for details of how horrid this is. For now, we're just
 | 
			
		||||
going to force things for supported languages.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
my $i18n = new esmith::I18N;
 | 
			
		||||
 | 
			
		||||
is($i18n->langtag2locale("en"), "en_US", "en langtag is en_US locale");
 | 
			
		||||
is($i18n->langtag2locale("en-us"), "en_US", "en-us langtag is en_US locale");
 | 
			
		||||
is($i18n->langtag2locale("en-au"), "en_AU", "en-au langtag is en_AU locale");
 | 
			
		||||
 | 
			
		||||
is($i18n->langtag2locale("es"), "es_ES", "es langtag is es_ES locale");
 | 
			
		||||
is($i18n->langtag2locale("es-es"), "es_ES", "es-es langtag is es_ES locale");
 | 
			
		||||
is($i18n->langtag2locale("es-ar"), "es_AR", "es-ar langtag is es_AR locale");
 | 
			
		||||
 | 
			
		||||
is($i18n->langtag2locale("fr"), "fr_CA", "fr langtag is fr_CA locale");
 | 
			
		||||
is($i18n->langtag2locale("fr-ca"), "fr_CA", "fr-ca langtag is fr_CA locale");
 | 
			
		||||
is($i18n->langtag2locale("fr-fr"), "fr_FR", "fr-fr langtag is fr_FR locale");
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub langtag2locale
 | 
			
		||||
{
 | 
			
		||||
    my ($self, $opt) = @_;
 | 
			
		||||
 | 
			
		||||
    my $locale;
 | 
			
		||||
 | 
			
		||||
    if (is_language_tag($opt))
 | 
			
		||||
    {
 | 
			
		||||
	$locale = _language_tag2locale($opt) || $self->fallbackLocale;
 | 
			
		||||
 | 
			
		||||
	unless (-d "/usr/lib/locale/$locale")
 | 
			
		||||
	{
 | 
			
		||||
	    $locale = "da_DK" if ($opt =~ /^da(-.*)?/);
 | 
			
		||||
	    $locale = "de_DE" if ($opt =~ /^de(-.*)?/);
 | 
			
		||||
	    $locale = "el_GR" if ($opt =~ /^el(-.*)?/);
 | 
			
		||||
	    $locale = "en_US" if ($opt =~ /^en(-.*)?/);
 | 
			
		||||
	    $locale = "es_ES" if ($opt =~ /^es(-.*)?/);
 | 
			
		||||
	    $locale = "fr_CA" if ($opt =~ /^fr(-.*)?/);
 | 
			
		||||
	    $locale = "hu_HU" if ($opt =~ /^hu(-.*)?/);
 | 
			
		||||
	    $locale = "id_ID" if ($opt =~ /^id(-.*)?/);
 | 
			
		||||
	    $locale = "it_IT" if ($opt =~ /^it(-.*)?/);
 | 
			
		||||
	    $locale = "nl_NL" if ($opt =~ /^nl(-.*)?/);
 | 
			
		||||
	    $locale = "pt_BR" if ($opt =~ /^pt(-.*)?/);
 | 
			
		||||
	    $locale = "sl_SL" if ($opt =~ /^sl(-.*)?/);
 | 
			
		||||
	    $locale = "sv_SE" if ($opt =~ /^sv(-.*)?/);
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
    else 
 | 
			
		||||
    {
 | 
			
		||||
	$locale = $opt;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return $locale;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub _language_tag2locale
 | 
			
		||||
{
 | 
			
		||||
    my $langtags = $_[0];
 | 
			
		||||
    my @locales;
 | 
			
		||||
    foreach my $maybe (split /[\n\r\t ,]+/, $langtags) 
 | 
			
		||||
    {
 | 
			
		||||
        push @locales,
 | 
			
		||||
        lc($1) . ( $2 ? ('_' . uc($2)) : '' )
 | 
			
		||||
            if $maybe =~ m/^([a-zA-Z]{2})(?:-([a-zA-Z]{2}))?$/s;
 | 
			
		||||
    }
 | 
			
		||||
    return $locales[0] unless wantarray; # might be undef!
 | 
			
		||||
        return @locales;  # might be empty!
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 availableLanguages()
 | 
			
		||||
 | 
			
		||||
Returns an array containing the available languages supported by the
 | 
			
		||||
server.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
$ENV{ESMITH_CONFIG_DB}="10e-smith-lib/sysconfig-en_US.conf";
 | 
			
		||||
$ENV{ESMITH_I18N_ESMITHLOCALEDIR}="10e-smith-lib/etc/e-smith/locale";
 | 
			
		||||
 | 
			
		||||
my $i18n = new esmith::I18N;
 | 
			
		||||
my @locales =  grep !/CVS/, sort $i18n->availableLanguages;
 | 
			
		||||
 | 
			
		||||
is_deeply(\@locales, [('en-us', 'es', 'fr-ca', 'jk', 'wx-yz')], "Locales match" );
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub availableLanguages
 | 
			
		||||
{
 | 
			
		||||
    my ($self) = shift;
 | 
			
		||||
 | 
			
		||||
    my $localedir = $ENV{ESMITH_I18N_ESMITHLOCALEDIR} || '/etc/e-smith/locale';
 | 
			
		||||
 | 
			
		||||
    return () unless opendir LOCALE, $localedir;
 | 
			
		||||
 | 
			
		||||
    my @locales = grep(!/\./, readdir LOCALE);
 | 
			
		||||
    closedir LOCALE;
 | 
			
		||||
    return @locales;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 fallbackLanguage()
 | 
			
		||||
 | 
			
		||||
Return system fallback language
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub fallbackLanguage()
 | 
			
		||||
{
 | 
			
		||||
    return "en-us";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 preferredLanguage()
 | 
			
		||||
 | 
			
		||||
Returns the preferred language, determined by the HTTP_ACCEPT_LANGUAGE
 | 
			
		||||
setting from the browser and the available languages on the server.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
my $i18n = new esmith::I18N;
 | 
			
		||||
delete $ENV{HTTP_ACCEPT_LANGUAGE};
 | 
			
		||||
 | 
			
		||||
is( $i18n->preferredLanguage(), "en-us", "Preferred language is en-us");
 | 
			
		||||
is( $i18n->preferredLanguage("en-us"), "en-us", "Preferred language is en-us");
 | 
			
		||||
is( $i18n->preferredLanguage("en-us, fr-ca"), "en-us", "Preferred language is en-us");
 | 
			
		||||
is( $i18n->preferredLanguage("fr-ca, en-us"), "fr-ca", "Preferred language is fr-ca");
 | 
			
		||||
 | 
			
		||||
$ENV{HTTP_ACCEPT_LANGUAGE} = "de, es";
 | 
			
		||||
is( $i18n->preferredLanguage(), "es", "Preferred language is es");
 | 
			
		||||
 | 
			
		||||
$ENV{HTTP_ACCEPT_LANGUAGE} = "de, fr-ca, es, en-us";
 | 
			
		||||
is( $i18n->preferredLanguage(), "fr-ca", "Preferred language is fr-ca");
 | 
			
		||||
 | 
			
		||||
$ENV{HTTP_ACCEPT_LANGUAGE} = "de, es, fr-ca, en-us";
 | 
			
		||||
is( $i18n->preferredLanguage(), "es", "Preferred language is es");
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub preferredLanguage
 | 
			
		||||
{
 | 
			
		||||
    my ($self, $browser_languages) = @_;
 | 
			
		||||
 | 
			
		||||
    $browser_languages ||= $ENV{HTTP_ACCEPT_LANGUAGE}
 | 
			
		||||
    		       ||= $self->fallbackLanguage;
 | 
			
		||||
 | 
			
		||||
    my @availableLanguages = $self->availableLanguages;
 | 
			
		||||
 | 
			
		||||
    my $acceptor = I18N::AcceptLanguage->new();
 | 
			
		||||
    my $language = $acceptor->accepts($browser_languages, \@availableLanguages)
 | 
			
		||||
		   || $self->fallbackLanguage;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
							
								
								
									
										77
									
								
								root/usr/share/perl5/vendor_perl/esmith/Logger.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								root/usr/share/perl5/vendor_perl/esmith/Logger.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::Logger;
 | 
			
		||||
 | 
			
		||||
use Sys::Syslog qw(:DEFAULT setlogsock);
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::Logger - A filehandle abstraction around Syslog.
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
    use esmith::Logger;
 | 
			
		||||
 | 
			
		||||
    tie *FH, 'esmith::Logger';
 | 
			
		||||
    print FH "log message";
 | 
			
		||||
    close FH;
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
our $VERSION = sprintf '%d.%03d', q$Revision: 1.100 $ =~ /: (\d+).(\d+)/;
 | 
			
		||||
 | 
			
		||||
sub TIEHANDLE
 | 
			
		||||
{
 | 
			
		||||
    my $class = ref($_[0]) || $_[0]; shift;
 | 
			
		||||
    my $self;
 | 
			
		||||
    my $title = shift || 'e-smith';
 | 
			
		||||
    setlogsock 'unix';
 | 
			
		||||
    openlog($title, 'pid', 'local1');
 | 
			
		||||
    return bless \$self, $class;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub PRINT
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    syslog('info', "%s", "@_");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub PRINTF
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my $fmt = shift;
 | 
			
		||||
    syslog('info', $fmt, @_);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub WRITE
 | 
			
		||||
{
 | 
			
		||||
    die "Sorry, WRITE unimplemented.\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub READ
 | 
			
		||||
{
 | 
			
		||||
    die "Can't read from logger.\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub READLINE
 | 
			
		||||
{
 | 
			
		||||
    die "Can't read from logger.\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub GETC
 | 
			
		||||
{
 | 
			
		||||
    die "Can't read from logger.\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub CLOSE
 | 
			
		||||
{
 | 
			
		||||
    closelog();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
							
								
								
									
										16
									
								
								root/usr/share/perl5/vendor_perl/esmith/NavigationDB.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								root/usr/share/perl5/vendor_perl/esmith/NavigationDB.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2008 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::NavigationDB;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use warnings;
 | 
			
		||||
 | 
			
		||||
use esmith::ConfigDB::UTF8;
 | 
			
		||||
our @ISA = qw( esmith::ConfigDB::UTF8 );
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										157
									
								
								root/usr/share/perl5/vendor_perl/esmith/NetworksDB.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								root/usr/share/perl5/vendor_perl/esmith/NetworksDB.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,157 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::NetworksDB;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use warnings;
 | 
			
		||||
 | 
			
		||||
use esmith::DB::db;
 | 
			
		||||
our @ISA = qw( esmith::DB::db );
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::NetworksDB - interface to esmith networks database
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
    use esmith::NetworksDB;
 | 
			
		||||
    my $c = esmith::NetworksDB->open;
 | 
			
		||||
 | 
			
		||||
    # everything else works just like esmith::DB::db
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
This module provides an abstracted interface to the esmith master
 | 
			
		||||
configuration database.
 | 
			
		||||
 | 
			
		||||
Unless otherwise noted, esmith::NetworksDB acts like esmith::DB::db.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
=head2 open()
 | 
			
		||||
 | 
			
		||||
Like esmith::DB->open, but if given no $file it will try to open the
 | 
			
		||||
file in the ESMITH_NETWORKS_DB environment variable or networks.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
use_ok("esmith::NetworksDB");
 | 
			
		||||
 | 
			
		||||
$C = esmith::NetworksDB->open('10e-smith-lib/networks.conf');
 | 
			
		||||
isa_ok($C, 'esmith::NetworksDB');
 | 
			
		||||
is( $C->get("10.0.0.0")->prop('Mask'), "255.255.255.0", 
 | 
			
		||||
                                    "We can get stuff from the db");
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub open
 | 
			
		||||
{
 | 
			
		||||
    my ( $class, $file ) = @_;
 | 
			
		||||
    $file = $file || $ENV{ESMITH_NETWORKS_DB} || "networks";
 | 
			
		||||
    return $class->SUPER::open($file);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 open_ro()
 | 
			
		||||
 | 
			
		||||
Like esmith::DB->open_ro, but if given no $file it will try to open the
 | 
			
		||||
file in the ESMITH_NETWORKS_DB environment variable or networks.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub open_ro
 | 
			
		||||
{
 | 
			
		||||
    my ( $class, $file ) = @_;
 | 
			
		||||
    $file = $file || $ENV{ESMITH_NETWORKS_DB} || "networks";
 | 
			
		||||
    return $class->SUPER::open_ro($file);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 networks
 | 
			
		||||
 | 
			
		||||
Return a list of all objects of type "network".
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub networks {
 | 
			
		||||
    my ($self) = @_;
 | 
			
		||||
    return $self->get_all_by_prop(type => 'network');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 local_access_spec ([$access])
 | 
			
		||||
 | 
			
		||||
Compute the network/netmask entries which are to treated as local access.
 | 
			
		||||
 | 
			
		||||
There is also an optional access parameter which can further restrict 
 | 
			
		||||
the values returned. If C<access> is C<localhost>, this routine will only
 | 
			
		||||
return a single value, equating to access from localhost only.
 | 
			
		||||
 | 
			
		||||
If called in scalar context, the returned string is suitable for 
 | 
			
		||||
use in /etc/hosts.allow, smb.conf and httpd.conf, for example:
 | 
			
		||||
 | 
			
		||||
127.0.0.1 192.168.1.1/255.255.255.0
 | 
			
		||||
 | 
			
		||||
Note: The elements are space separated, which is suitable for use in
 | 
			
		||||
hosts.allow, smb.conf and httpd.conf. httpd.conf does not permit 
 | 
			
		||||
comma separated lists in C<allow from> directives. Each element is either
 | 
			
		||||
an IP address, or a network/netmask string.
 | 
			
		||||
 | 
			
		||||
If called in list context, returns the array of addresses and network/netmask
 | 
			
		||||
strings. It's trivial, of course, to convert an array to a comma separated
 | 
			
		||||
list :-)
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub local_access_spec
 | 
			
		||||
{
 | 
			
		||||
    my $self   = shift;
 | 
			
		||||
    my $access = shift || "private";
 | 
			
		||||
 | 
			
		||||
    my @localAccess = ("127.0.0.1");
 | 
			
		||||
 | 
			
		||||
    if ( $access eq "localhost" )
 | 
			
		||||
    {
 | 
			
		||||
        # Nothing more to do
 | 
			
		||||
    }
 | 
			
		||||
    elsif ( $access eq "private" )
 | 
			
		||||
    {
 | 
			
		||||
        foreach my $network ( $self->networks )
 | 
			
		||||
        {
 | 
			
		||||
	    my $element = $network->key;
 | 
			
		||||
            my $mask = $network->prop('Mask');
 | 
			
		||||
	    $element .= "/$mask" unless ($mask eq "255.255.255.255");
 | 
			
		||||
            push @localAccess, $element;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    elsif ( $access eq "public" )
 | 
			
		||||
    {
 | 
			
		||||
        @localAccess = ("ALL");
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        warn "local_access_spec: unknown access value $access\n";
 | 
			
		||||
    }
 | 
			
		||||
    return wantarray ? @localAccess : "@localAccess";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head1 AUTHOR
 | 
			
		||||
 | 
			
		||||
SME Server Developers <bugs@e-smith.com>
 | 
			
		||||
 | 
			
		||||
=head1 SEE ALSO
 | 
			
		||||
 | 
			
		||||
L<esmith::DB::db>
 | 
			
		||||
 | 
			
		||||
L<esmith::DB::Record>
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
							
								
								
									
										480
									
								
								root/usr/share/perl5/vendor_perl/esmith/cgi.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										480
									
								
								root/usr/share/perl5/vendor_perl/esmith/cgi.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,480 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::cgi;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use esmith::config;
 | 
			
		||||
use esmith::db;
 | 
			
		||||
use esmith::util;
 | 
			
		||||
 | 
			
		||||
BEGIN
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::cgi - Useful CGI routines for e-smith server and gateway
 | 
			
		||||
 | 
			
		||||
=head1 VERSION
 | 
			
		||||
 | 
			
		||||
This file documents C<esmith::cgi> version B<1.4.0>
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
    use esmith::cgi;
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
This module contains a collection of useful routines for working with
 | 
			
		||||
the e-smith manager's CGI interface.
 | 
			
		||||
=head1 WEB PAGE HEADER GENERATION ROUTINES
 | 
			
		||||
 | 
			
		||||
=head2 genHeaderNonCacheable($q, $confref, $title)
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub genHeaderNonCacheable
 | 
			
		||||
{
 | 
			
		||||
    my ($q, $confref, $title) = @_;
 | 
			
		||||
    genHeader ($q, $confref, $title, '-20y', 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 genHeaderCacheableNoPasswordCheck($q, $confref, $title)
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub genHeaderCacheableNoPasswordCheck
 | 
			
		||||
{
 | 
			
		||||
    my ($q, $confref, $title) = @_;
 | 
			
		||||
    genHeader ($q, $confref, $title, '+1d', 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 genHeaderCacheableNoPasswordCheck($q, $confref, $title)
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub genHeaderNonCacheableNoPasswordCheck
 | 
			
		||||
{
 | 
			
		||||
    my ($q, $confref, $title) = @_;
 | 
			
		||||
    genHeader ($q, $confref, $title, '-20y', 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 genHeader($q, $confref, $title, $expiry, $checkpassword)
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub genHeader
 | 
			
		||||
{
 | 
			
		||||
    my ($q, $confref, $title, $expiry, $checkpassword) = @_;
 | 
			
		||||
 | 
			
		||||
    print $q->header (-EXPIRES => $expiry, charset => 'UTF-8');
 | 
			
		||||
 | 
			
		||||
    genHeaderStartHTML ($q, "panel_main");
 | 
			
		||||
 | 
			
		||||
    print $q->h1 ($title);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 genNavigationHeader($q)
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub genNavigationHeader
 | 
			
		||||
{
 | 
			
		||||
    my ($q, $num) = @_;
 | 
			
		||||
 | 
			
		||||
    print $q->header (-EXPIRES => '-20y', charset => 'UTF-8');
 | 
			
		||||
 | 
			
		||||
    genHeaderStartHTML ($q, "panel_nav", $num);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 genNoframesHeader($q)
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub genNoframesHeader
 | 
			
		||||
{
 | 
			
		||||
    my ($q) = @_;
 | 
			
		||||
 | 
			
		||||
    print $q->header (-EXPIRES => '-20y', charset => 'UTF-8');
 | 
			
		||||
    genHeaderStartHTML ($q, "panel_main");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 genHeaderStartHTML($q)
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub genHeaderStartHTML 
 | 
			
		||||
{
 | 
			
		||||
    my ($q, $page_type, $num) = @_;
 | 
			
		||||
    my ($cssFile);
 | 
			
		||||
    my ($bodyStyle);
 | 
			
		||||
    my ($script) = "//This swaps the class of the selected item.\n"
 | 
			
		||||
    ."function swapClass(){\n"
 | 
			
		||||
    ."var i,x,tB,j=0,tA=new Array(),arg=swapClass.arguments;\n"
 | 
			
		||||
    ."if(document.getElementsByTagName){for(i=4;i<arg.length;i++){tB=document.getElementsByTagName(arg[i]);\n"
 | 
			
		||||
    ."for(x=0;x<tB.length;x++){tA[j]=tB[x];j++;}}for(i=0;i<tA.length;i++){\n"
 | 
			
		||||
    ."if(tA[i].className){if(tA[i].id==arg[1]){if(arg[0]==1){\n"
 | 
			
		||||
    ."tA[i].className=(tA[i].className==arg[3])?arg[2]:arg[3];}else{tA[i].className=arg[2];}\n"
 | 
			
		||||
    ."}else if(arg[0]==1 && arg[1]=='none'){if(tA[i].className==arg[2] || tA[i].className==arg[3]){\n"
 | 
			
		||||
    ."tA[i].className=(tA[i].className==arg[3])?arg[2]:arg[3];}\n"
 | 
			
		||||
    ."}else if(tA[i].className==arg[2]){tA[i].className=arg[3];}}}}}\n";
 | 
			
		||||
 | 
			
		||||
    if    ($page_type eq "panel_nav")  { 
 | 
			
		||||
        $cssFile = "sme_menu.css";
 | 
			
		||||
        $bodyStyle = "menu"
 | 
			
		||||
    }
 | 
			
		||||
    elsif ($page_type eq "panel_main") { 
 | 
			
		||||
        $cssFile = "sme_main.css"; 
 | 
			
		||||
        $bodyStyle = "main"
 | 
			
		||||
    }
 | 
			
		||||
    # the -CLASS thing gets sent as a body class, not in the header
 | 
			
		||||
    print $q->start_html (-TITLE        => 'SME Server server manager',
 | 
			
		||||
              -META         => {'copyright' => 'Copyright 1999-2006 Mitel Networks Corporation, Copyright (C) ____COPYYEARS____ Koozali Foundation, Inc.'},
 | 
			
		||||
			  -SCRIPT       => "$script",
 | 
			
		||||
                          -CLASS        => "$bodyStyle",
 | 
			
		||||
                          -STYLE        => {
 | 
			
		||||
				-code => '@import url("/server-common/css/'.$cssFile.'");',
 | 
			
		||||
				-src => '/server-common/css/sme_core.css'
 | 
			
		||||
				});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head1 WEB PAGE FOOTER GENERATION ROUTINES
 | 
			
		||||
 | 
			
		||||
=head2 genFooter($q)
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub genFooter
 | 
			
		||||
{
 | 
			
		||||
    my ($q) = @_;
 | 
			
		||||
 | 
			
		||||
    if ($q->isa('CGI::FormMagick'))
 | 
			
		||||
    {
 | 
			
		||||
        print $q->parse_template("/etc/e-smith/web/common/foot.tmpl");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
   
 | 
			
		||||
    my $release = esmith::util::determineRelease();
 | 
			
		||||
 | 
			
		||||
    print $q->p 
 | 
			
		||||
        ($q->hr ({-CLASS => "sme-copyrightbar"}), 
 | 
			
		||||
        $q->div ({-CLASS => "sme-copyright"},
 | 
			
		||||
        "SME Server server ${release}<BR>" .
 | 
			
		||||
        "Copyright 1999-2006 Mitel Networks Corporation, Copyright (C) ____COPYYEARS____ Koozali Foundation, Inc..<BR>" .
 | 
			
		||||
	"All rights reserved.")
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
    print '</DIV>';
 | 
			
		||||
    print $q->end_html;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 genFooterNoCopyright($q)
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub genFooterNoCopyright
 | 
			
		||||
{
 | 
			
		||||
    my ($q) = @_;
 | 
			
		||||
    print $q->p ($q->hr);
 | 
			
		||||
    print $q->end_html;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 genNavigationFooter($q)
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub genNavigationFooter
 | 
			
		||||
{
 | 
			
		||||
    my ($q) = @_;
 | 
			
		||||
    print $q->end_html;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 genNoframesFooter($q)
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub genNoframesFooter
 | 
			
		||||
{
 | 
			
		||||
    my ($q) = @_;
 | 
			
		||||
    print $q->end_html;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head1 FONT ROUTINES
 | 
			
		||||
 | 
			
		||||
=head2 curFont()
 | 
			
		||||
 | 
			
		||||
Returns the preferred font faces eg. "Verdana, Arial, Helvetica, sans-serif".
 | 
			
		||||
This should be done by CSS now, so if you're calling this, you shouldn't be.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub curFont
 | 
			
		||||
{
 | 
			
		||||
    return "Verdana, Arial, Helvetica, sans-serif";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head1 TABLE GENERATION ROUTINES
 | 
			
		||||
 | 
			
		||||
=head2 genCell($q, $text)
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub genCell 
 | 
			
		||||
{
 | 
			
		||||
    my ($q, $text, $class) = @_;
 | 
			
		||||
 | 
			
		||||
    if ($text =~ /^\s*$/){$text = " "}
 | 
			
		||||
    if ($class) { return $q->td({-class => "$class"}, $text),"\n";}
 | 
			
		||||
    else { return $q->td ($text),"\n";}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 genDoubleCell($q, $text);
 | 
			
		||||
 | 
			
		||||
Generates a cell which spans two columns, containing the text specified.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub genDoubleCell
 | 
			
		||||
{
 | 
			
		||||
    my ($q, $text) = @_;
 | 
			
		||||
    if ($text =~ /^\s*$/){ $text = " " }
 | 
			
		||||
    return $q->td ({colspan => 2}, $text),"\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 genSmallCell($q, $text, $type, $colspan)
 | 
			
		||||
 | 
			
		||||
Generates a cell with "small" text (font size is 80%).
 | 
			
		||||
"$type" can be one of: 
 | 
			
		||||
"normal" : creates <td class="sme-border"> cell
 | 
			
		||||
"header" : creates <th class="sme-border"> cell
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub genSmallCell
 | 
			
		||||
{
 | 
			
		||||
    my ($q, $text, $type, $colspan) = @_;
 | 
			
		||||
    $text = '' unless defined $text;
 | 
			
		||||
    $type ||= 'normal';
 | 
			
		||||
    $colspan ||= 1;
 | 
			
		||||
    if ($text =~ /^\s*$/){ $text = " " }
 | 
			
		||||
    if ("$type" eq "header") {
 | 
			
		||||
        return $q->th ({class=>"sme-border", colspan=>$colspan}, $text)."\n";
 | 
			
		||||
    } else {
 | 
			
		||||
        return $q->td ({class=>"sme-border", colspan=>$colspan}, $text)."\n";
 | 
			
		||||
    }        
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 genSmallCellCentered($q, $text)
 | 
			
		||||
 | 
			
		||||
Generates a cell with "small" text (font size is 80%), centered.
 | 
			
		||||
creates <td class="sme-border-center"> cell
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub genSmallCellCentered
 | 
			
		||||
{
 | 
			
		||||
    my ($q, $text) = @_;
 | 
			
		||||
    if ($text =~ /^\s*$/){ $text = " " }
 | 
			
		||||
    return $q->td ({class => "sme-border-center"}, $text)."\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 genSmallCellRightJustified($q, $text)
 | 
			
		||||
 | 
			
		||||
=head2 genSmallCellCentered($q, $text)
 | 
			
		||||
 | 
			
		||||
Generates a cell with "small" text (font size is 80%), right justified.
 | 
			
		||||
creates <td class="sme-border-right"> cell
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub genSmallCellRightJustified
 | 
			
		||||
{
 | 
			
		||||
    my ($q, $text) = @_;
 | 
			
		||||
    if ($text =~ /^\s*$/){ $text = " " }
 | 
			
		||||
    return $q->td ({class => "sme-border-right"}, $text)."\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 genSmallRedCell($q, $text)
 | 
			
		||||
 | 
			
		||||
Generates a cell with "small" text (font size is 80%), left justified.
 | 
			
		||||
creates <td class="sme-border-warning"> cell
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub genSmallRedCell
 | 
			
		||||
{
 | 
			
		||||
    my ($q, $text) = @_;
 | 
			
		||||
    if ($text =~ /^\s*$/){ $text = " " }
 | 
			
		||||
    return $q->td ({class => "sme-border-warning"}, $text)."\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 genTextRow($q, $text)
 | 
			
		||||
 | 
			
		||||
Returns a table row containing a two-column cell containing $text.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub genTextRow
 | 
			
		||||
{
 | 
			
		||||
    my ($q, $text) = @_;
 | 
			
		||||
    if ($text =~ /^\s*$/){ $text = " " }
 | 
			
		||||
    return "\n",$q->Tr ($q->td ({colspan => 2}, $text)),"\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 genButtonRow($q, $button)
 | 
			
		||||
 | 
			
		||||
Returns a table row containing an empty first cell and a second cell
 | 
			
		||||
containing a button with the value $button.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub genButtonRow
 | 
			
		||||
{
 | 
			
		||||
    my ($q, $button) = @_;
 | 
			
		||||
 | 
			
		||||
#    return $q->Tr ($q->td ({-class => "sme-submitbutton", -colspan => "2"},$q->b ($button))),"\n";
 | 
			
		||||
#    return $q->Tr ($q->td (' '),
 | 
			
		||||
#		   $q->td ({-class => "sme-submitbutton"},$q->b ($button))),"\n";
 | 
			
		||||
    return $q->Tr ({-class => "sme-layout"}, $q->th ({-class => "sme-layout", colspan => "2"},$q->b ($button))),"\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 genNameValueRow($q, $fieldlabel, $fieldname, $fieldvalue)
 | 
			
		||||
 | 
			
		||||
Returns a table row with two cells.  The first has the text
 | 
			
		||||
"$fieldlabel:" in it, and the second has a text field with the default
 | 
			
		||||
value $fieldvalue and the name $fieldname.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub genNameValueRow
 | 
			
		||||
{
 | 
			
		||||
    my ($q, $fieldlabel, $fieldname, $fieldvalue) = @_;
 | 
			
		||||
 | 
			
		||||
    return $q->Tr (
 | 
			
		||||
        $q->td ({-class => "sme-noborders-label"}, 
 | 
			
		||||
            "$fieldlabel:"),"\n",
 | 
			
		||||
	$q->td ({-class => "sme-noborders-content"},
 | 
			
		||||
            $q->textfield (
 | 
			
		||||
                -name     => $fieldname,
 | 
			
		||||
                -override => 1,
 | 
			
		||||
                -default  => $fieldvalue,
 | 
			
		||||
		-size     => 32))),"\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
sub genWidgetRow($q, $fieldlabel, $popup)
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
# used only by backup panel as far as I can see
 | 
			
		||||
sub genWidgetRow
 | 
			
		||||
{
 | 
			
		||||
    my ($q, $fieldlabel, $popup) = @_;
 | 
			
		||||
 | 
			
		||||
    return $q->Tr ($q->td ("$fieldlabel:"),
 | 
			
		||||
		   $q->td ($popup));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod 
 | 
			
		||||
 | 
			
		||||
=head1 STATUS AND ERROR REPORT GENERATION ROUTINES
 | 
			
		||||
 | 
			
		||||
=head2 genResult($q, $msg)
 | 
			
		||||
 | 
			
		||||
Generates a "status report" page, including the footer
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub genResult
 | 
			
		||||
{
 | 
			
		||||
    my ($q, $msg) = @_;
 | 
			
		||||
 | 
			
		||||
    print $q->p ($msg);
 | 
			
		||||
    genFooter ($q);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 genStateError($q, $confref)
 | 
			
		||||
 | 
			
		||||
Subroutine to generate "unknown state" error message.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub genStateError
 | 
			
		||||
{
 | 
			
		||||
    my ($q, $confref) = @_;
 | 
			
		||||
 | 
			
		||||
    genHeaderNonCacheable ($q, $confref, "Internal error");
 | 
			
		||||
    genResult ($q, "Internal error! Unknown state: " . $q->param ("state") . ".");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
END
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#------------------------------------------------------------
 | 
			
		||||
# return "1" to make the import process return success
 | 
			
		||||
#------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head1 AUTHOR
 | 
			
		||||
 | 
			
		||||
Mitel Networks Corporation
 | 
			
		||||
 | 
			
		||||
For more information, see http://e-smith.org/
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										640
									
								
								root/usr/share/perl5/vendor_perl/esmith/config.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										640
									
								
								root/usr/share/perl5/vendor_perl/esmith/config.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,640 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::config;
 | 
			
		||||
use strict;
 | 
			
		||||
use vars qw($VERSION);
 | 
			
		||||
$VERSION = 1.45;
 | 
			
		||||
 | 
			
		||||
use Sys::Syslog qw(:DEFAULT setlogsock);
 | 
			
		||||
use Fcntl qw(:DEFAULT :flock);
 | 
			
		||||
use Carp qw(cluck);
 | 
			
		||||
 | 
			
		||||
my $Default_Config = '/home/e-smith/db/configuration';
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::config - Access e-smith config files via hashes
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
use esmith::config;
 | 
			
		||||
 | 
			
		||||
my %config;
 | 
			
		||||
my $config_obj = tie %config, 'esmith::config', $config_file;
 | 
			
		||||
 | 
			
		||||
# Read in the value of Wibble from the $config_file.
 | 
			
		||||
print $config{Wibble};
 | 
			
		||||
 | 
			
		||||
# Write out the value of Wibble to the $config_file.
 | 
			
		||||
$config{Wibble} = 42;
 | 
			
		||||
 | 
			
		||||
my $filename = $config_obj->filename;
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
The esmith::config package enables Perl programs to read and write
 | 
			
		||||
entries from the e-smith configuration file using a simple hash
 | 
			
		||||
interface.
 | 
			
		||||
 | 
			
		||||
The configuration file has a simple ASCII representation,
 | 
			
		||||
with one "key=value" entry per line.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
use_ok('esmith::config');
 | 
			
		||||
chdir '10e-smith-lib';
 | 
			
		||||
 | 
			
		||||
%Expect = ( foo              => 'bar',
 | 
			
		||||
'this key'       => 'has whitespace',
 | 
			
		||||
'that key '      => 'has trailing whitespace',
 | 
			
		||||
' another key'   => 'has leading whitespace',
 | 
			
		||||
'this value'     => ' has leading whitespace',
 | 
			
		||||
'that value'     => 'has trailing whitespace ',
 | 
			
		||||
'tricky value'   => 'with=equals.',
 | 
			
		||||
          );
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=head2 Tying
 | 
			
		||||
 | 
			
		||||
tie %config, 'esmith::config', $config_file;
 | 
			
		||||
 | 
			
		||||
Reads in the configuration from the given $config_file, returning a
 | 
			
		||||
tied hash (%config) populated with the keys & values from the
 | 
			
		||||
$config_file which you can then use like a normal hash.  Any writes or
 | 
			
		||||
deletes are immediately written back to the $config_file.
 | 
			
		||||
 | 
			
		||||
If no $config_file is supplied it falls back to the environment variable 
 | 
			
		||||
ESMITH_CONFIG_DB, and finally defaults to F</home/e-smith/db/configuration>
 | 
			
		||||
 | 
			
		||||
If the $config_file doesn't exist it will create one for you.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
my %config;
 | 
			
		||||
tie %config, 'esmith::config', 'dummy.conf';
 | 
			
		||||
ok( tied %config,                'tie worked' );
 | 
			
		||||
is( $config{foo}, 'bar',         '  theres stuff in it' );
 | 
			
		||||
ok( !exists $config{FILENAME},   '  it only contains config info');
 | 
			
		||||
is( tied(%config)->{FILENAME},     'dummy.conf',
 | 
			
		||||
'  and the real object is inside');
 | 
			
		||||
 | 
			
		||||
tie %config, 'esmith::config', 'I_dont_exist';
 | 
			
		||||
ok( tied %config,        'tying a non-existant file' );
 | 
			
		||||
is( keys %config, 0,    '  and its empty' );
 | 
			
		||||
$config{foo} = 42;
 | 
			
		||||
isnt( -s 'I_dont_exist', 0 );
 | 
			
		||||
untie %config;
 | 
			
		||||
ok( unlink 'I_dont_exist' );
 | 
			
		||||
 | 
			
		||||
$ENV{ESMITH_CONFIG_DB} = "dummy.conf";
 | 
			
		||||
tie %config, 'esmith::config';
 | 
			
		||||
ok( tied %config,                'tie to ESMITH_CONFIG_DB worked' );
 | 
			
		||||
is_deeply(\%config, \%Expect, "  picked up data");
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=head2 Methods
 | 
			
		||||
 | 
			
		||||
You can get at the underlying esmith::config object by using tied().
 | 
			
		||||
 | 
			
		||||
my $config_obj = tied %config;
 | 
			
		||||
 | 
			
		||||
it has a few useful methods.
 | 
			
		||||
 | 
			
		||||
=over 4
 | 
			
		||||
 | 
			
		||||
=item filename
 | 
			
		||||
 | 
			
		||||
my $file = $config_obj->filename;
 | 
			
		||||
 | 
			
		||||
Gets the config filename this object is tied to.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
my %config;
 | 
			
		||||
my $obj = tie %config, 'esmith::config', 'dummy.conf';
 | 
			
		||||
is( $obj->filename, 'dummy.conf', 'filename()' );
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub filename {
 | 
			
		||||
    my($self) = shift;
 | 
			
		||||
    return $self->{FILENAME};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=back
 | 
			
		||||
 | 
			
		||||
=begin _private
 | 
			
		||||
 | 
			
		||||
=head2 Private methods
 | 
			
		||||
 | 
			
		||||
=over 4
 | 
			
		||||
 | 
			
		||||
=item _readconf
 | 
			
		||||
 | 
			
		||||
my $config = _readconf($config_file);
 | 
			
		||||
 | 
			
		||||
Returns a hash ref of config key/value pairs read out of the given
 | 
			
		||||
$config_file.  If $config_file doesn't exist an empty hash ref will be
 | 
			
		||||
returned.
 | 
			
		||||
 | 
			
		||||
_readconf() understands the config file to be formatted as individual
 | 
			
		||||
lines of simply:
 | 
			
		||||
 | 
			
		||||
key=value
 | 
			
		||||
 | 
			
		||||
any further complexity of parsing the value is handled elsewhere.
 | 
			
		||||
 | 
			
		||||
=end _private
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
my $config = esmith::config::_readconf('dummy.conf');
 | 
			
		||||
isnt( keys %$config, 0,  '_readconf() got something' );
 | 
			
		||||
is_deeply( $config, \%Expect, '  read in the right values' );
 | 
			
		||||
 | 
			
		||||
$config = esmith::config::_readconf('I_dont_exist');
 | 
			
		||||
isa_ok( $config, 'HASH', '_readconf from a non-existent file' );
 | 
			
		||||
is( keys %$config, 0,    '  and its empty' );
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub _readconf
 | 
			
		||||
{
 | 
			
		||||
    my ($self, $filename) = @_;
 | 
			
		||||
 | 
			
		||||
    my %config = ();
 | 
			
		||||
 | 
			
		||||
    unless (open (FH, $filename)) 
 | 
			
		||||
    {
 | 
			
		||||
        if (-f $filename)
 | 
			
		||||
        {
 | 
			
		||||
            &log("Config: ERROR: \"$filename\" exists but is not readable");
 | 
			
		||||
        }
 | 
			
		||||
        return \%config;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    my $binmode = $self->_read_binmode;
 | 
			
		||||
    binmode(FH, $binmode) if $binmode;
 | 
			
		||||
    while (my $line = <FH>)
 | 
			
		||||
    {
 | 
			
		||||
        chomp $line;
 | 
			
		||||
 | 
			
		||||
        # BLIND UNTAINT!  Much code wrongly depends on this and
 | 
			
		||||
        # they should be moved away from it.
 | 
			
		||||
        $line =~ /(.*)/;
 | 
			
		||||
        $line = $1;
 | 
			
		||||
 | 
			
		||||
        # ignore comments and blank lines
 | 
			
		||||
        next if $line =~ /^\s*$/ || $line =~ /^\s*#/;
 | 
			
		||||
 | 
			
		||||
        my($key, $value) = split /=/, $line, 2;
 | 
			
		||||
        $config{$key} = $value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    close(FH);
 | 
			
		||||
 | 
			
		||||
    return \%config;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=begin _private
 | 
			
		||||
 | 
			
		||||
=item _writeconf
 | 
			
		||||
 | 
			
		||||
my $success = _writeconf($config_file, \%config);
 | 
			
		||||
 | 
			
		||||
The given $config_file is overwritten using the entries in %config.
 | 
			
		||||
 | 
			
		||||
Returns whether or not the write succeded.
 | 
			
		||||
 | 
			
		||||
=end _private
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
my $scratch = 'scratch.conf';
 | 
			
		||||
ok( esmith::config::_writeconf($scratch, \%Expect),  
 | 
			
		||||
'_writeconf() says it worked' );
 | 
			
		||||
is_deeply( esmith::config::_readconf($scratch), \%Expect,   
 | 
			
		||||
'   wrote the right things' );
 | 
			
		||||
unlink $scratch;
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub _writeconf
 | 
			
		||||
{
 | 
			
		||||
    my ($self, $filename, $config) = @_;
 | 
			
		||||
 | 
			
		||||
    eval {
 | 
			
		||||
        if (-f $filename && ! -r $filename)
 | 
			
		||||
        {
 | 
			
		||||
            die "'$filename' exists but is not readable\n";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        sysopen (FH, "$filename.$$", O_RDWR | O_CREAT, 0660)
 | 
			
		||||
            or die "Cannot open $filename.$$: $!\n";
 | 
			
		||||
        my $binmode = $self->_write_binmode;
 | 
			
		||||
        binmode(FH, $binmode) if $binmode;
 | 
			
		||||
 | 
			
		||||
        die "Error writing to $filename.$$: $!" unless
 | 
			
		||||
        printf FH <<EOF, scalar localtime;
 | 
			
		||||
# DO NOT MODIFY THIS FILE.
 | 
			
		||||
# This file is automatically maintained by the Mitel Networks SME Server
 | 
			
		||||
# configuration software.  Manually editing this file may put your 
 | 
			
		||||
# system in an unknown state.
 | 
			
		||||
#
 | 
			
		||||
# updated: %s
 | 
			
		||||
EOF
 | 
			
		||||
 | 
			
		||||
        foreach my $key (sort keys %$config)
 | 
			
		||||
        {
 | 
			
		||||
            print FH "$key=$config->{$key}\n"
 | 
			
		||||
                or die "Error writing to $filename.$$: $!";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        close (FH) or die "Error closing $filename.$$: $!";
 | 
			
		||||
 | 
			
		||||
        rename("$filename.$$", $filename)
 | 
			
		||||
            or die "Couldn't rename $filename.$$ to $filename: $!";
 | 
			
		||||
 | 
			
		||||
        my $gid = getgrnam ('admin') || 0;
 | 
			
		||||
        chown (0, $gid, $filename);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if($@) {
 | 
			
		||||
        chomp $@;
 | 
			
		||||
        &log($@);
 | 
			
		||||
        &log("'$filename' will not be updated");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=begin _private
 | 
			
		||||
 | 
			
		||||
=item B<_lock_write>
 | 
			
		||||
 | 
			
		||||
=item B<_lock_read>
 | 
			
		||||
 | 
			
		||||
$self->_lock_write;
 | 
			
		||||
$self->_lock_read;
 | 
			
		||||
 | 
			
		||||
Sets up read (shared) or write (exclusive) locks on the config file.
 | 
			
		||||
This is actually locking a semaphore file.
 | 
			
		||||
 | 
			
		||||
Returns if the lock succeeded or failed.
 | 
			
		||||
 | 
			
		||||
=item B<_unlock>
 | 
			
		||||
 | 
			
		||||
$self->_unlock
 | 
			
		||||
 | 
			
		||||
Unlocks the config file.
 | 
			
		||||
 | 
			
		||||
=end _private
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub _lock_write { $_[0]->_lock(LOCK_EX) }
 | 
			
		||||
sub _lock_read  { $_[0]->_lock(LOCK_SH) }
 | 
			
		||||
 | 
			
		||||
sub _lock {
 | 
			
		||||
    return if $] eq 5.006; # Locking is broken in perl 5.6.0
 | 
			
		||||
    my($self, $lock) = @_;
 | 
			
		||||
 | 
			
		||||
    my $semaphore = $self->{SEMAPHORE_FILE} = $self->{FILENAME}.'.lock';
 | 
			
		||||
 | 
			
		||||
    eval {
 | 
			
		||||
        open(my $fh, ">>$semaphore") or
 | 
			
		||||
        die "Can't open '$semaphore' semaphore: $!";
 | 
			
		||||
        $self->{SEMAPHORE} = $fh;
 | 
			
		||||
 | 
			
		||||
        flock($fh, $lock) or
 | 
			
		||||
        die "Can't lock '$semaphore' semaphore: $!";
 | 
			
		||||
    };
 | 
			
		||||
    if( $@ ) {
 | 
			
		||||
        warn $@;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
sub _unlock {
 | 
			
		||||
    return if $] eq 5.006; # Locking is broken in perl 5.6.0
 | 
			
		||||
    my($self) = @_;
 | 
			
		||||
 | 
			
		||||
    eval {
 | 
			
		||||
        flock($self->{SEMAPHORE}, LOCK_UN) or
 | 
			
		||||
        die "Can't unlock $self->{SEMAPHORE_FILE}: $!";
 | 
			
		||||
 | 
			
		||||
        unlink $self->{SEMAPHORE_FILE};
 | 
			
		||||
        delete $self->{SEMAPHORE_FILE};
 | 
			
		||||
        delete $self->{SEMAPHORE};
 | 
			
		||||
    };
 | 
			
		||||
    if( $@ ) {
 | 
			
		||||
        warn $@;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=end _private
 | 
			
		||||
 | 
			
		||||
=back
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
#------------------------------------------------------------
 | 
			
		||||
# Constructor for the tied hash. If filename not specified,
 | 
			
		||||
# defaults to '/home/e-smith/db/configuration'.
 | 
			
		||||
#------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
sub TIEHASH
 | 
			
		||||
{
 | 
			
		||||
    my $class    = shift;
 | 
			
		||||
    my $filename = shift || $ENV{ESMITH_CONFIG_DB} || $Default_Config;
 | 
			
		||||
 | 
			
		||||
    if ($filename =~ m:^/home/e-smith/\w+$: )
 | 
			
		||||
    {
 | 
			
		||||
        cluck "*WARNING* esmith::config($filename) called with old " .
 | 
			
		||||
              "database path. The following package needs to be updated: ";
 | 
			
		||||
 | 
			
		||||
        $filename =~ s:e-smith:e-smith/db:;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    my $self =
 | 
			
		||||
        {
 | 
			
		||||
            FILENAME => $filename,
 | 
			
		||||
            CONFIG   => {},
 | 
			
		||||
        };
 | 
			
		||||
    bless $self, $class;
 | 
			
		||||
 | 
			
		||||
    $self->{CONFIG} = $self->_readconf($filename);
 | 
			
		||||
 | 
			
		||||
    return $self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#------------------------------------------------------------
 | 
			
		||||
# Look up a configuration parameter.
 | 
			
		||||
#------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
sub FETCH
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my $key  = shift;
 | 
			
		||||
 | 
			
		||||
    # Trim leading and trailing whitespace from the key.
 | 
			
		||||
    $key =~ s/^\s+|\s+$//g;
 | 
			
		||||
 | 
			
		||||
    return $self->{CONFIG}{$key};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#------------------------------------------------------------
 | 
			
		||||
# Store a configuration parameter.
 | 
			
		||||
#------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
sub STORE
 | 
			
		||||
{
 | 
			
		||||
    my $self  = shift;
 | 
			
		||||
    my $key   = shift;
 | 
			
		||||
    my $value = shift;
 | 
			
		||||
 | 
			
		||||
    die "key not defined" unless defined $key;
 | 
			
		||||
    die "value not defined for key $key" unless defined $value;
 | 
			
		||||
 | 
			
		||||
    if( $value =~ /\n/ or $key =~ /\n/ ) {
 | 
			
		||||
        &log("$self->{FILENAME}: esmith::config doesn't support newlines in ".
 | 
			
		||||
        "keys or values.  Truncating.");
 | 
			
		||||
        $key   =~ s/\n.*//s;
 | 
			
		||||
        $value =~ s/\n.*//s;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # Trim leading and trailing whitespace from the key and value.
 | 
			
		||||
    $key =~ s/^\s+|\s+$//g;
 | 
			
		||||
    $value =~ s/^\s+|\s+$//g;
 | 
			
		||||
 | 
			
		||||
    # Make sure that the value has a type. Given the format, it should be
 | 
			
		||||
    # sufficient to ensure that it does not begin with a pipe char.
 | 
			
		||||
    if ($value =~ /^\|/)
 | 
			
		||||
    {
 | 
			
		||||
        warn "ERROR: You should not set a config record without a type (key was $key).\n";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # read in config again, just in case it changed
 | 
			
		||||
    $self->_lock_write;
 | 
			
		||||
    $self->{CONFIG} = $self->_readconf($self->{FILENAME});
 | 
			
		||||
 | 
			
		||||
    if (exists $self->{CONFIG}{$key} and
 | 
			
		||||
    $self->{CONFIG}{$key} eq $value)
 | 
			
		||||
    {
 | 
			
		||||
        $self->_unlock;
 | 
			
		||||
        return undef;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    my $msg = "$self->{FILENAME}: OLD $key=";
 | 
			
		||||
 | 
			
		||||
    if (exists $self->{CONFIG}{$key})
 | 
			
		||||
    {
 | 
			
		||||
        $msg .= "$self->{CONFIG}{$key}";
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        $msg .= "(undefined)";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &log($msg);
 | 
			
		||||
 | 
			
		||||
    $self->{CONFIG} {$key} = $value;
 | 
			
		||||
    &log("$self->{FILENAME}: NEW $key=$self->{CONFIG}{$key}");
 | 
			
		||||
 | 
			
		||||
    $self->_writeconf ($self->{FILENAME}, $self->{CONFIG});
 | 
			
		||||
    $self->_unlock;
 | 
			
		||||
 | 
			
		||||
    return undef;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#------------------------------------------------------------
 | 
			
		||||
# Delete a configuration parameter.
 | 
			
		||||
#------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
sub DELETE
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my $key = shift;
 | 
			
		||||
 | 
			
		||||
    # Trim leading and trailing whitespace from the key.
 | 
			
		||||
    $key =~ s/^\s+|\s+$//g;
 | 
			
		||||
 | 
			
		||||
    # read in config again, just in case it changed
 | 
			
		||||
    $self->_lock_write;
 | 
			
		||||
    $self->{CONFIG} = $self->_readconf($self->{FILENAME});
 | 
			
		||||
 | 
			
		||||
    my $previous = delete $self->{CONFIG} {$key};
 | 
			
		||||
    $self->_writeconf ($self->{FILENAME}, $self->{CONFIG});
 | 
			
		||||
    $self->_unlock;
 | 
			
		||||
 | 
			
		||||
    &log("$self->{FILENAME}: DELETE $key=$previous");
 | 
			
		||||
 | 
			
		||||
    return $previous;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=begin _private
 | 
			
		||||
 | 
			
		||||
=item CLEAR
 | 
			
		||||
 | 
			
		||||
tie method: Clear the configuration file
 | 
			
		||||
 | 
			
		||||
=end _private
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
my $scratch = 'scratch.conf';
 | 
			
		||||
tie %config, 'esmith::config', $scratch;
 | 
			
		||||
ok( tied %config,        'tying a non-existant file' );
 | 
			
		||||
is( keys %config, 0,    '  and its empty' );
 | 
			
		||||
$config{fibble} = 'blah';
 | 
			
		||||
isnt( keys %config, 0,  '  and its not empty now' );
 | 
			
		||||
%config = ();
 | 
			
		||||
is( keys %config, 0,    '  and CLEAR made it empty again' );
 | 
			
		||||
unlink $scratch;
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub CLEAR
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
 | 
			
		||||
    $self->{CONFIG} = ();
 | 
			
		||||
    $self->_writeconf ($self->{FILENAME}, $self->{CONFIG});
 | 
			
		||||
 | 
			
		||||
    &log("$self->{FILENAME}: CLEAR");
 | 
			
		||||
 | 
			
		||||
    return undef;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#------------------------------------------------------------
 | 
			
		||||
# Check whether a particular key exists in the configuration file.
 | 
			
		||||
#------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
sub EXISTS
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my $key = shift;
 | 
			
		||||
 | 
			
		||||
    # Trim leading and trailing whitespace from the key.
 | 
			
		||||
    $key =~ s/^\s+|\s+$//g;
 | 
			
		||||
 | 
			
		||||
    return exists $self->{CONFIG} {$key};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#------------------------------------------------------------
 | 
			
		||||
# FIRSTKEY is called whenever we start iterating over the
 | 
			
		||||
# configuration table. We cache the configuration table at
 | 
			
		||||
# this point to ensure reasonable results if the
 | 
			
		||||
# configuration file is changed by another program during
 | 
			
		||||
# the iteration.
 | 
			
		||||
#------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
sub FIRSTKEY
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
 | 
			
		||||
    my $discard = keys %{$self->{CONFIG}};    # reset each() iterator
 | 
			
		||||
 | 
			
		||||
    return each %{$self->{CONFIG}};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#------------------------------------------------------------
 | 
			
		||||
# NEXTKEY is called for all iterations after the first.  We
 | 
			
		||||
# just keep returning results from the cached configuration
 | 
			
		||||
# table.  A null array is returned at the end. If the caller
 | 
			
		||||
# starts a new iteration, the FIRSTKEY subroutine is called
 | 
			
		||||
# again, causing the cache to be reloaded.
 | 
			
		||||
#------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
sub NEXTKEY
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    return each %{$self->{CONFIG}};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#------------------------------------------------------------
 | 
			
		||||
# Log messages to syslog
 | 
			
		||||
#------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
sub log
 | 
			
		||||
{
 | 
			
		||||
    # There is a bug in Perl 5.00504 and above. If you are using the unix
 | 
			
		||||
    # domain socket, do NOT use ndelay as part of the second argument
 | 
			
		||||
    # to openlog().
 | 
			
		||||
 | 
			
		||||
    my $msg = shift;
 | 
			
		||||
    $msg =~ s/[^[:ascii:]]/_/g;
 | 
			
		||||
    my $program = $0;
 | 
			
		||||
 | 
			
		||||
    setlogsock 'unix';
 | 
			
		||||
    openlog($program, 'pid', 'local1');
 | 
			
		||||
    syslog('info', "%s", $msg);
 | 
			
		||||
    closelog();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item _read_binmode
 | 
			
		||||
 | 
			
		||||
return undef, indicating that by default binmode() need not be called after
 | 
			
		||||
file open.
 | 
			
		||||
 | 
			
		||||
=end _private
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub _read_binmode
 | 
			
		||||
{
 | 
			
		||||
    return undef;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub _write_binmode
 | 
			
		||||
{
 | 
			
		||||
    return undef;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head1 BUGS and CAVEATS
 | 
			
		||||
 | 
			
		||||
You can't have newlines in keys or values.
 | 
			
		||||
 | 
			
		||||
While the config values happen to be untainted B<do not depend on this
 | 
			
		||||
behavior> as it will change in the future.
 | 
			
		||||
 | 
			
		||||
=head1 AUTHOR
 | 
			
		||||
 | 
			
		||||
SME Server Developers <bugs@e-smith.com>
 | 
			
		||||
 | 
			
		||||
For more information, see http://www.e-smith.org/
 | 
			
		||||
 | 
			
		||||
=head1 SEE ALSO
 | 
			
		||||
 | 
			
		||||
esmith::db
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
							
								
								
									
										25
									
								
								root/usr/share/perl5/vendor_perl/esmith/config/utf8.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								root/usr/share/perl5/vendor_perl/esmith/config/utf8.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2008 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::config::utf8;
 | 
			
		||||
use warnings;
 | 
			
		||||
use strict;
 | 
			
		||||
 | 
			
		||||
use vars qw(@ISA);
 | 
			
		||||
@ISA = qw(esmith::config);
 | 
			
		||||
 | 
			
		||||
sub _read_binmode
 | 
			
		||||
{
 | 
			
		||||
    return ":encoding(UTF-8)";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub _write_binmode
 | 
			
		||||
{
 | 
			
		||||
    return ":utf8";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										603
									
								
								root/usr/share/perl5/vendor_perl/esmith/console.pm
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										603
									
								
								root/usr/share/perl5/vendor_perl/esmith/console.pm
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,603 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2006 Mitel Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::console - A class to provide a backend library to the server console.
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
    use esmith::console;
 | 
			
		||||
 | 
			
		||||
    my $console = esmith::console->new();
 | 
			
		||||
 | 
			
		||||
    ($rc, $choice) = $console->message_page
 | 
			
		||||
        (
 | 
			
		||||
         title   => gettext("Administrator password not set"),
 | 
			
		||||
         text    => gettext("Sorry, you must set the administrator password."),
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
This class provides a backend library of methods for the frontend console on
 | 
			
		||||
the server. The intent is that all of the whiptail code is hidden in this
 | 
			
		||||
library, and the frontend can just concern itself with the logical progression
 | 
			
		||||
through any and all applicable screens.
 | 
			
		||||
 | 
			
		||||
=head1 Methods
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
package esmith::console;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use vars qw($VERSION @ISA @EXPORT_OK);
 | 
			
		||||
use esmith::util;
 | 
			
		||||
use Locale::gettext;
 | 
			
		||||
use esmith::ConfigDB;
 | 
			
		||||
use esmith::I18N;
 | 
			
		||||
 | 
			
		||||
@ISA = qw(Exporter);
 | 
			
		||||
 | 
			
		||||
use constant SCREEN_ROWS => 22;
 | 
			
		||||
use constant SCREEN_COLUMNS => 76;
 | 
			
		||||
use constant CONSOLE_SCREENS => "/sbin/e-smith/console-screens";
 | 
			
		||||
 | 
			
		||||
BEGIN
 | 
			
		||||
{
 | 
			
		||||
    # disable CTRL-C
 | 
			
		||||
    $SIG{INT} = 'IGNORE';
 | 
			
		||||
 | 
			
		||||
    # Set PATH explicitly and clear related environment variables so that calls
 | 
			
		||||
    # to external programs do not cause results to be tainted. See
 | 
			
		||||
    # "perlsec" manual page for details.
 | 
			
		||||
 | 
			
		||||
    $ENV {'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin';
 | 
			
		||||
    $ENV {'SHELL'} = '/bin/bash';
 | 
			
		||||
    delete $ENV {'ENV'};
 | 
			
		||||
    delete $ENV {'BASH_ENV'};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 new
 | 
			
		||||
 | 
			
		||||
This is the class constructor.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub new
 | 
			
		||||
{
 | 
			
		||||
    my $class = ref($_[0]) || $_[0];
 | 
			
		||||
    my $self = {};
 | 
			
		||||
    esmith::util::setRealToEffective ();
 | 
			
		||||
 | 
			
		||||
    my $i18n = new esmith::I18N;
 | 
			
		||||
    $i18n->setLocale("server-console");
 | 
			
		||||
 | 
			
		||||
    #------------------------------------------------------------
 | 
			
		||||
    # Set stdin, stdout and stderr to console
 | 
			
		||||
    #------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
    if (defined $ARGV [0])
 | 
			
		||||
    {
 | 
			
		||||
	$ARGV[0] =~ /(console|tty\d*)/ && -c "/dev/$1"
 | 
			
		||||
	    or die gettext("Bad ttyname:"), " ", $ARGV[0], "\n";
 | 
			
		||||
	my $tty = $1;
 | 
			
		||||
 | 
			
		||||
	open (STDIN,  "</dev/$tty") or die gettext("Can't redirect stdin"),  ": $!\n";
 | 
			
		||||
	open (STDOUT, ">/dev/$tty") or die gettext("Can't redirect stdout"), ": $!\n";
 | 
			
		||||
 | 
			
		||||
	my $pid = open(STDERR, "|-");
 | 
			
		||||
	die gettext("Can't fork"), ": $!\n" unless defined $pid;
 | 
			
		||||
 | 
			
		||||
	unless ($pid)
 | 
			
		||||
	{
 | 
			
		||||
	    exec qw(/usr/bin/logger -p local1.info -t console);
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $self = bless $self, $class;
 | 
			
		||||
    return $self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 screen and dialog
 | 
			
		||||
 | 
			
		||||
These method are wrappers around whiptail and dialog, and permit the creation
 | 
			
		||||
of custom screens depending on the arguments passed. They are typically not
 | 
			
		||||
called directly, but are used by all of the other page methods that
 | 
			
		||||
follow. You should only call these method directly if none of the other
 | 
			
		||||
methods apply.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub screen
 | 
			
		||||
{
 | 
			
		||||
    _screen(shift, "/usr/bin/dialog", @_);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub dialog
 | 
			
		||||
{
 | 
			
		||||
    _screen(shift, "/usr/bin/dialog", @_);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub whiptail
 | 
			
		||||
{
 | 
			
		||||
    _screen(shift, "/usr/bin/whiptail", @_);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub _screen
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my $whiptail = shift;
 | 
			
		||||
    my @whiptailArgs = @_;
 | 
			
		||||
 | 
			
		||||
    # now would be a good time to flush output buffers, so the partial
 | 
			
		||||
    # buffers don't get copied:
 | 
			
		||||
 | 
			
		||||
    $| = 1;
 | 
			
		||||
    print "";
 | 
			
		||||
 | 
			
		||||
    pipe (READER, WRITER)
 | 
			
		||||
        or die gettext("Couldn't create pipe") . ": $!\n";
 | 
			
		||||
 | 
			
		||||
    my $pid = fork;
 | 
			
		||||
 | 
			
		||||
    if (! defined $pid)
 | 
			
		||||
    {
 | 
			
		||||
        die gettext("Couldn't fork") . ": $!\n";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    elsif ($pid == 0)
 | 
			
		||||
    {
 | 
			
		||||
        #----------------------------------------
 | 
			
		||||
        # Child
 | 
			
		||||
        #----------------------------------------
 | 
			
		||||
 | 
			
		||||
        # Attach child's STDIN to the reading end of the pipe
 | 
			
		||||
        close READER
 | 
			
		||||
            or die gettext("Couldn't close reading end of pipe") , ": $!\n";
 | 
			
		||||
 | 
			
		||||
        if ($whiptail =~ m{\bwhiptail$} ) {
 | 
			
		||||
            # whiptail sends its output via STDERR.  We temporarily
 | 
			
		||||
            # shut off warnings so they don't interfere with that.
 | 
			
		||||
            local $^W = 0;
 | 
			
		||||
 | 
			
		||||
            open  STDERR, ">& WRITER"
 | 
			
		||||
                or die gettext("Couldn't connect STDERR to pipe"), ": $!\n";
 | 
			
		||||
 | 
			
		||||
            close WRITER
 | 
			
		||||
                or die gettext("Couldn't close writing end of pipe"), ": $!\n";
 | 
			
		||||
 | 
			
		||||
            unshift @whiptailArgs, $whiptail,
 | 
			
		||||
                '--backtitle', $self->backtitle;
 | 
			
		||||
        } else {
 | 
			
		||||
            use Fcntl qw/F_SETFD/;
 | 
			
		||||
 | 
			
		||||
            # Clear close-on-exec on WRITER so that it stays open for dialog to use
 | 
			
		||||
            fcntl(WRITER, F_SETFD, 0);
 | 
			
		||||
 | 
			
		||||
            unshift @whiptailArgs, $whiptail,
 | 
			
		||||
                '--backtitle', $self->backtitle, "--output-fd", fileno(WRITER);
 | 
			
		||||
        }
 | 
			
		||||
        exec @whiptailArgs;
 | 
			
		||||
        die gettext("Couldn't exec:"), ": $!\n";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #----------------------------------------
 | 
			
		||||
    # Parent
 | 
			
		||||
    #----------------------------------------
 | 
			
		||||
 | 
			
		||||
    close WRITER;
 | 
			
		||||
 | 
			
		||||
    my $choice = <READER>;
 | 
			
		||||
    close READER;
 | 
			
		||||
 | 
			
		||||
    waitpid ($pid, 0);
 | 
			
		||||
    my $rc = $?;
 | 
			
		||||
 | 
			
		||||
    return ($rc, $choice);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 backtitle
 | 
			
		||||
 | 
			
		||||
Console header line for each page
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub backtitle
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
 | 
			
		||||
    my $db = esmith::ConfigDB->open_ro or die "Couldn't open ConfigDB\n";
 | 
			
		||||
 | 
			
		||||
    sprintf("%-33s%45s",
 | 
			
		||||
    ($db->get_prop('sysconfig', 'ProductName') || "SME Server") . " " .
 | 
			
		||||
    ($db->get_prop('sysconfig', 'ReleaseVersion') || "UNKNOWN"),
 | 
			
		||||
    "Copyright (C) 1999-2006 Mitel Corporation, Copyright (C) ____COPYYEARS____ Koozali Foundation, Inc."
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 message_page
 | 
			
		||||
 | 
			
		||||
This method should be used whenever a screen that displays a simple message
 | 
			
		||||
is required.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub message_page
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my %params = @_;
 | 
			
		||||
 | 
			
		||||
    my $title       = $params{title};
 | 
			
		||||
    my $message_box = $params{text};
 | 
			
		||||
 | 
			
		||||
    my $left  = defined $params{left} ? $params{left} : gettext("Back");
 | 
			
		||||
    my $right = defined $params{right} ? $params{right} : gettext("Next");
 | 
			
		||||
 | 
			
		||||
    $self->screen ("--title",  $title,
 | 
			
		||||
                   "--cancel-label",   $left,
 | 
			
		||||
                   "--ok-label",  $right,
 | 
			
		||||
                   "--clear",
 | 
			
		||||
                   "--msgbox", $message_box,
 | 
			
		||||
                   SCREEN_ROWS,
 | 
			
		||||
                   SCREEN_COLUMNS,
 | 
			
		||||
                  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 tryagain_page
 | 
			
		||||
 | 
			
		||||
This method displays a simple "try again" screen.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub tryagain_page
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my %params = @_;
 | 
			
		||||
 | 
			
		||||
    my $title  = $params{title};
 | 
			
		||||
    my $choice = $params{choice};
 | 
			
		||||
 | 
			
		||||
    my $try_again = "; " . gettext("please try again");
 | 
			
		||||
 | 
			
		||||
    my $message_box = $title . ":'${choice}'" . $try_again;
 | 
			
		||||
 | 
			
		||||
    $self->screen ("--title",  $title,
 | 
			
		||||
                   "--cancel-label",  gettext("Back"),
 | 
			
		||||
                   "--ok-label", gettext("Next"),
 | 
			
		||||
                   "--clear",
 | 
			
		||||
                   "--msgbox", $message_box,
 | 
			
		||||
                   SCREEN_ROWS,
 | 
			
		||||
                   SCREEN_COLUMNS,
 | 
			
		||||
                  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 password_page
 | 
			
		||||
 | 
			
		||||
This method displays a screen suitable for entering a password.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub password_page
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my %params = @_;
 | 
			
		||||
 | 
			
		||||
    my $title       = $params{title};
 | 
			
		||||
    my $message_box = $params{text};
 | 
			
		||||
 | 
			
		||||
    my $left  = defined $params{left} ? $params{left} : gettext("Back");
 | 
			
		||||
    my $right = defined $params{right} ? $params{right} : gettext("Next");
 | 
			
		||||
 | 
			
		||||
    $self->dialog ("--title",  $title,
 | 
			
		||||
                   "--insecure",
 | 
			
		||||
                   "--cancel-label",  $left,
 | 
			
		||||
                   "--ok-label", $right,
 | 
			
		||||
                   "--clear",
 | 
			
		||||
                   "--passwordbox", "\n" . $message_box,
 | 
			
		||||
                   SCREEN_ROWS,
 | 
			
		||||
                   SCREEN_COLUMNS,
 | 
			
		||||
                  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 yesno_page
 | 
			
		||||
 | 
			
		||||
This method displays a simple yes/no screen, so the user can make a
 | 
			
		||||
simple binary selection.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub yesno_page
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my %params = @_;
 | 
			
		||||
 | 
			
		||||
    my $title = $params{title};
 | 
			
		||||
    my $text  = $params{text};
 | 
			
		||||
 | 
			
		||||
    my $left  = defined $params{left} ? $params{left} : gettext("Yes");
 | 
			
		||||
    my $right = defined $params{right} ? $params{right} : gettext("No");
 | 
			
		||||
    my @args = (
 | 
			
		||||
	    "--title" =>  $title,
 | 
			
		||||
	    "--yes-label" =>   $left,
 | 
			
		||||
	    "--no-label" =>  $right,
 | 
			
		||||
	);
 | 
			
		||||
    push @args, "--defaultno" if defined $params{defaultno};
 | 
			
		||||
    push @args, "--clear";
 | 
			
		||||
 | 
			
		||||
    $self->screen (@args,
 | 
			
		||||
                   "--yesno",  $text,
 | 
			
		||||
                   SCREEN_ROWS,
 | 
			
		||||
                   SCREEN_COLUMNS,
 | 
			
		||||
                  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 input_page
 | 
			
		||||
 | 
			
		||||
This method displays a simple input screen with an input box.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub input_page
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my %params = @_;
 | 
			
		||||
 | 
			
		||||
    my $title  = $params{title};
 | 
			
		||||
    my $text   = $params{text};
 | 
			
		||||
    my $value  = $params{value};
 | 
			
		||||
 | 
			
		||||
    my $left  = defined $params{left} ? $params{left} : gettext("Back");
 | 
			
		||||
    my $right = defined $params{right} ? $params{right} : gettext("Next");
 | 
			
		||||
 | 
			
		||||
    $self->screen("--title", $title,
 | 
			
		||||
                  "--cancel-label",  $left,
 | 
			
		||||
                  "--ok-label", $right,
 | 
			
		||||
                  "--clear",
 | 
			
		||||
                  "--inputbox", $text,
 | 
			
		||||
                  SCREEN_ROWS,
 | 
			
		||||
                  SCREEN_COLUMNS,
 | 
			
		||||
                  $value
 | 
			
		||||
                 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 infobox
 | 
			
		||||
 | 
			
		||||
This method is similar to a messagebox, but exits immediately, without clearing the screen.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub infobox
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my %params = @_;
 | 
			
		||||
    my $title  = $params{title};
 | 
			
		||||
    my $text   = $params{text};
 | 
			
		||||
    my $height = $params{height} || "8";
 | 
			
		||||
    my $width  = $params{width} || SCREEN_COLUMNS;
 | 
			
		||||
    $self->screen("--title", $title,
 | 
			
		||||
                  "--infobox", $text,
 | 
			
		||||
                  $height,
 | 
			
		||||
                  $width,
 | 
			
		||||
                 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=head2 textbox
 | 
			
		||||
 | 
			
		||||
A text box lets you display the contents of a text file in a dialog box.
 | 
			
		||||
It is like a simple text file viewer.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub textbox
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my %params = @_;
 | 
			
		||||
    my $title  = $params{title};
 | 
			
		||||
    my $file   = $params{file};
 | 
			
		||||
    my $height = $params{height} || '20';
 | 
			
		||||
    my $width  = $params{width} || SCREEN_COLUMNS;
 | 
			
		||||
    $self->screen("--title", $title,
 | 
			
		||||
                  "--textbox", $file,
 | 
			
		||||
                  $height,
 | 
			
		||||
                  $width,
 | 
			
		||||
                 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 menu_page
 | 
			
		||||
 | 
			
		||||
This method displays a screen with a menu.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub menu_page
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my %params = @_;
 | 
			
		||||
 | 
			
		||||
    my $title = $params{title};
 | 
			
		||||
    my $text  = $params{text};
 | 
			
		||||
    my @args = ("--clear", "--title", $title);
 | 
			
		||||
    if ($params{default})
 | 
			
		||||
    {
 | 
			
		||||
        push @args, "--default-item", $params{default};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    my $value     = $params{value};
 | 
			
		||||
    my $argsref   = $params{argsref};
 | 
			
		||||
 | 
			
		||||
    my $menu_rows = scalar @$argsref / 2;
 | 
			
		||||
 | 
			
		||||
    $menu_rows = 10 if ($menu_rows > 10);
 | 
			
		||||
 | 
			
		||||
    my $left  = defined $params{left} ? $params{left} : gettext("Back");
 | 
			
		||||
    my $right = defined $params{right} ? $params{right} : gettext("Next");
 | 
			
		||||
 | 
			
		||||
    $self->dialog(@args,
 | 
			
		||||
                  "--cancel-label",  $left,
 | 
			
		||||
                  "--ok-label", $right,
 | 
			
		||||
                  "--menu", $text,
 | 
			
		||||
                  SCREEN_ROWS,
 | 
			
		||||
                  SCREEN_COLUMNS,
 | 
			
		||||
                  $menu_rows,
 | 
			
		||||
                  @$argsref,
 | 
			
		||||
                 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 keep_option
 | 
			
		||||
 | 
			
		||||
??
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub keep_option
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my ($value) = @_;
 | 
			
		||||
 | 
			
		||||
    my $keep_phrase = gettext("Keep the current setting");
 | 
			
		||||
 | 
			
		||||
    return ( gettext("keep"), "${keep_phrase}: $value" );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 gauge
 | 
			
		||||
 | 
			
		||||
This method displays a progress bar. It takes a coderef as parameter, and uses
 | 
			
		||||
the coderef to drive the --gauge widget of the dialog program, as well as to
 | 
			
		||||
perform whatever actions are being reported by the progress bar. The coderef
 | 
			
		||||
should take one parameter, which is the file handle to write the controlling
 | 
			
		||||
text to. If the return value of the coderef is defined, it is displayed by a
 | 
			
		||||
message_page after the progress bar terminates.
 | 
			
		||||
 | 
			
		||||
All text used to update the progress bar should either be numbers between 0
 | 
			
		||||
and 100, or arbitrary text sandwiched between leading and training lines
 | 
			
		||||
of 'XXX' followed by newline. The numbers will update the percentage complete
 | 
			
		||||
of the display, and the text will update the displayed text. Updating the
 | 
			
		||||
displayed text will reset the precentage complete to 0, so text should always
 | 
			
		||||
be followed by number.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub gauge
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my $sub = shift;
 | 
			
		||||
    my %params = @_;
 | 
			
		||||
    my $title              = $params{title} || 'Progress';
 | 
			
		||||
    my $feedback_title     = $params{feedback_title} || 'Status';
 | 
			
		||||
    my $init_text          = $params{text} || 'Progress';
 | 
			
		||||
    my @args = (
 | 
			
		||||
		'--backtitle', $self->backtitle,
 | 
			
		||||
		'--title', gettext($title),
 | 
			
		||||
	);
 | 
			
		||||
    push @args, "--clear" if $params{clear};
 | 
			
		||||
    push @args, "--colors" if $params{colors};
 | 
			
		||||
    push @args, "--no-collapse" if $params{no_collapse};
 | 
			
		||||
 | 
			
		||||
    use FileHandle;
 | 
			
		||||
 | 
			
		||||
    unless (open(WR, '|-'))
 | 
			
		||||
    {
 | 
			
		||||
	exec('/usr/bin/dialog',
 | 
			
		||||
		@args,
 | 
			
		||||
		'--gauge',
 | 
			
		||||
		gettext($init_text),
 | 
			
		||||
                SCREEN_ROWS,
 | 
			
		||||
                SCREEN_COLUMNS,
 | 
			
		||||
		);
 | 
			
		||||
    }
 | 
			
		||||
    WR->autoflush(1);
 | 
			
		||||
    my $text = &$sub(*WR);
 | 
			
		||||
    close(WR);
 | 
			
		||||
    $self->message_page('title' => $feedback_title, 'text' => $text)
 | 
			
		||||
	if defined $text;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 run_screens
 | 
			
		||||
 | 
			
		||||
This method takes a directory of screens to run, and runs them in order.
 | 
			
		||||
To support navigation between screens, this method respects an integer
 | 
			
		||||
return value from the screens.
 | 
			
		||||
 | 
			
		||||
    0 = all is well, continue to the next screen
 | 
			
		||||
    1 = all is not well, go back to the previous screen
 | 
			
		||||
    2 = catastrophic failure - return from run_screen
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub run_screens
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my ($subdir) = @_;
 | 
			
		||||
 | 
			
		||||
    my $dir = CONSOLE_SCREENS . "/$subdir";
 | 
			
		||||
 | 
			
		||||
    # This is fine. Noop if the directory isn't there.
 | 
			
		||||
    unless (-d $dir)
 | 
			
		||||
    {
 | 
			
		||||
	return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # This is not fine. If it's there, we should be able to open it.
 | 
			
		||||
    unless ( opendir(SCREENS, $dir) )
 | 
			
		||||
    {
 | 
			
		||||
	warn "Failed to open directory $dir: $!\n";
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    my @screens = sort grep (!/^(\.\.?)$/, readdir (SCREENS));
 | 
			
		||||
 | 
			
		||||
    my @previous_screens = ();
 | 
			
		||||
    while (@screens)
 | 
			
		||||
    {
 | 
			
		||||
        my $screen = shift @screens;
 | 
			
		||||
        unless ( $screen =~ /(S\d\d[\d\w]+)/ )
 | 
			
		||||
        {
 | 
			
		||||
            warn "Unknown screen type $dir/$screen\n";
 | 
			
		||||
            next;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $screen = $1;
 | 
			
		||||
        my $rv = system( "$dir/$screen" );
 | 
			
		||||
        $rv >>= 8;
 | 
			
		||||
        if ($rv == 0)
 | 
			
		||||
        {
 | 
			
		||||
            # Success, move to next screen.
 | 
			
		||||
            push @previous_screens, $screen;
 | 
			
		||||
        }
 | 
			
		||||
        elsif ($rv == 1)
 | 
			
		||||
        {
 | 
			
		||||
            # Failure, go back one screen.
 | 
			
		||||
            unshift @screens, $screen;
 | 
			
		||||
            if (@previous_screens)
 | 
			
		||||
            {
 | 
			
		||||
                unshift @screens, pop @previous_screens;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                # We're at the beginning of the stack. Just return.
 | 
			
		||||
                return 0;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            # Catastrophic failure, return. While 2 is the agreed-upon
 | 
			
		||||
            # return code for this, consider it a catastrophic failure
 | 
			
		||||
            # if we don't get a valid return code.
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head1 AUTHOR
 | 
			
		||||
 | 
			
		||||
SME Server Developers <smebugs@mitel.com>
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
							
								
								
									
										743
									
								
								root/usr/share/perl5/vendor_perl/esmith/db.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										743
									
								
								root/usr/share/perl5/vendor_perl/esmith/db.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,743 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::db;
 | 
			
		||||
 | 
			
		||||
use esmith::config;
 | 
			
		||||
use strict;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::db - Routines for handling the e-smith configuration database
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
B<THIS MODULE HAS BEEN DEPRECATED>
 | 
			
		||||
 | 
			
		||||
    use esmith::db;
 | 
			
		||||
    use esmith::config;
 | 
			
		||||
 | 
			
		||||
    my %config;
 | 
			
		||||
    tie %config, 'esmith::config', $config_file;
 | 
			
		||||
 | 
			
		||||
    db_set(\%config, $key, $type, \%properties);
 | 
			
		||||
    db_set_type(\%config, $key, $type);
 | 
			
		||||
    db_set_prop(\%config, $key, $property => $new_value);
 | 
			
		||||
 | 
			
		||||
    my($type, %properties) = db_get(\%config, $key);
 | 
			
		||||
    my $type       = db_get_type(\%config, $key);
 | 
			
		||||
    my %properties = db_get_prop(\%config, $key);
 | 
			
		||||
    my $value      = db_get_prop(\%config, $key, $property);
 | 
			
		||||
 | 
			
		||||
    db_delete(\%config, $key);
 | 
			
		||||
    db_delete_prop(\%config, $key, $property);
 | 
			
		||||
 | 
			
		||||
    db_print(\%config, $key);
 | 
			
		||||
    db_show(\%config, $key);
 | 
			
		||||
    db_print_type(\%config, $key);
 | 
			
		||||
    db_print_prop(\%config, $key, $prop);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
B<THIS MODULE HAS BEEN DEPRECATED>.  Please use a subclass of
 | 
			
		||||
esmith::DB::db instead, such as esmith::AccountsDB or esmith::ConfigDB.
 | 
			
		||||
 | 
			
		||||
I<Do not try to change this module>.  Much code depends on subtle
 | 
			
		||||
nuances and bugs and you will break things if you try to fix it.
 | 
			
		||||
Instead, move any existing code away from esmith::db and towards
 | 
			
		||||
esmith::DB::db.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
This module provides utility routines for manipulating e-smith 
 | 
			
		||||
configuration data. OO and non-OO versions of the routines are provided.
 | 
			
		||||
For example, db_set() is the non-OO while set() can be called with an 
 | 
			
		||||
object reference.
 | 
			
		||||
 | 
			
		||||
E-Smith DB entries have three parts.  A key, a type and a hash of
 | 
			
		||||
properties.
 | 
			
		||||
 | 
			
		||||
  key           squid
 | 
			
		||||
  type          cephalopod
 | 
			
		||||
  properties    arms    => 10
 | 
			
		||||
                species => Loligo
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
use vars qw($VERSION @ISA @EXPORT);
 | 
			
		||||
$VERSION     = sprintf "%d.%03d", q$Revision: 1.16 $ =~ /(\d+)\.(\d+)/;
 | 
			
		||||
 | 
			
		||||
use Exporter;
 | 
			
		||||
@ISA         = qw(Exporter);
 | 
			
		||||
@EXPORT      = qw(
 | 
			
		||||
                  db_set
 | 
			
		||||
                  db_get
 | 
			
		||||
                  db_delete
 | 
			
		||||
 | 
			
		||||
                  db_set_type
 | 
			
		||||
                  db_get_type
 | 
			
		||||
 | 
			
		||||
                  db_get_prop
 | 
			
		||||
                  db_set_prop
 | 
			
		||||
                  db_delete_prop
 | 
			
		||||
 | 
			
		||||
                  db_print
 | 
			
		||||
                  db_show
 | 
			
		||||
 | 
			
		||||
                  db_print_type
 | 
			
		||||
                  db_print_prop
 | 
			
		||||
                 );
 | 
			
		||||
 | 
			
		||||
=head2 Functions
 | 
			
		||||
 | 
			
		||||
=over 4
 | 
			
		||||
 | 
			
		||||
=item B<db_set>
 | 
			
		||||
 | 
			
		||||
  my $success = db_set(\%config, $key, $raw_value);
 | 
			
		||||
  my $success = db_set(\%config, $key, $type);
 | 
			
		||||
  my $success = db_set(\%config, $key, $type, \%properties);
 | 
			
		||||
 | 
			
		||||
Enters a new $key into the %config or replaces an existing $key.  It
 | 
			
		||||
sets the $type and optionally %properties.
 | 
			
		||||
 | 
			
		||||
As a "bug which has become a feature" you can feed db_set() the
 | 
			
		||||
$raw_value for a $key (ie. 'type|prop1|val1|prop2|val2') and it will
 | 
			
		||||
setup the types and properties properly.  I<Do not depend on this> but
 | 
			
		||||
don't change it either.  There's code that depends on this behavior.
 | 
			
		||||
 | 
			
		||||
It returns true on success, false on failure.
 | 
			
		||||
 | 
			
		||||
If the $key contains a newline it will fail.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub db_set
 | 
			
		||||
{
 | 
			
		||||
    my ($hash, $key, $new_value, $hashref) = @_;
 | 
			
		||||
 | 
			
		||||
    return undef if ($key =~ /\n/);
 | 
			
		||||
    if (defined $hashref)
 | 
			
		||||
    {
 | 
			
		||||
        my $properties = _db_hash_to_string($hashref);
 | 
			
		||||
        if (defined $properties && $properties ne '')
 | 
			
		||||
        {
 | 
			
		||||
            $new_value .= "|$properties";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    $new_value and $new_value =~ s/\n/\\n/g;
 | 
			
		||||
    $$hash{$key} = $new_value;
 | 
			
		||||
    return undef unless defined db_get($hash, $key);
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head2 B<db_get>
 | 
			
		||||
 | 
			
		||||
    my($type, %properties) = db_get(\%config, $key);
 | 
			
		||||
    my $raw_value  = db_get(\%config, $key);
 | 
			
		||||
    my @keys       = db_get(\%config);
 | 
			
		||||
 | 
			
		||||
Reads the $type and %properties for the given $key in %config.
 | 
			
		||||
 | 
			
		||||
In scalar context it returns the raw value of $config{$key} B<NOT> the
 | 
			
		||||
type!  But it unescapes newlines.  I<Use db_get_type() instead>.
 | 
			
		||||
 | 
			
		||||
If a $key is not given it returns all the @keys in the %config.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub db_get
 | 
			
		||||
{
 | 
			
		||||
    my ($hash, $key) = @_;
 | 
			
		||||
 | 
			
		||||
    return sort keys %$hash unless defined $key;
 | 
			
		||||
    return undef unless exists $$hash{$key};
 | 
			
		||||
 | 
			
		||||
    my $value = $$hash{$key};
 | 
			
		||||
    $value and $value =~ s/\\n/\n/g;
 | 
			
		||||
    return wantarray() ? _db_string_to_type_and_hash($value) : $value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item B<db_delete>
 | 
			
		||||
 | 
			
		||||
  db_delete(\%config, $key)
 | 
			
		||||
 | 
			
		||||
Deletes the $key from %config.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub db_delete
 | 
			
		||||
{
 | 
			
		||||
    my ($hash, $key) = @_;
 | 
			
		||||
 | 
			
		||||
    return undef unless defined db_get($hash, $key);
 | 
			
		||||
 | 
			
		||||
    delete $$hash{$key};
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=item B<db_set_type>
 | 
			
		||||
 | 
			
		||||
  my $success = db_set_type(\%config, $key, $type)
 | 
			
		||||
 | 
			
		||||
Sets the $type for $config{$key}.
 | 
			
		||||
 | 
			
		||||
Returns true if the set succeeded, false otherwise.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub db_set_type
 | 
			
		||||
{
 | 
			
		||||
    my ($hash, $key, $type) = @_;
 | 
			
		||||
 | 
			
		||||
    return undef unless defined db_get($hash, $key);
 | 
			
		||||
 | 
			
		||||
    my %properties = db_get_prop($hash, $key);
 | 
			
		||||
 | 
			
		||||
    return db_set($hash, $key, $type, \%properties);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=item B<db_get_type>
 | 
			
		||||
 | 
			
		||||
    my $type = db_get_type(\%config, $key);
 | 
			
		||||
 | 
			
		||||
Returns the $type associated with the $key in the %config database.
 | 
			
		||||
 | 
			
		||||
Will return undef if the $key doesn't exist.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub db_get_type
 | 
			
		||||
{
 | 
			
		||||
    my ($hash, $key) = @_;
 | 
			
		||||
 | 
			
		||||
    return undef unless defined db_get($hash, $key);
 | 
			
		||||
 | 
			
		||||
    my ($type) =
 | 
			
		||||
        _db_string_to_type_and_hash(db_get($hash, $key));
 | 
			
		||||
    return $type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=item B<db_set_prop>
 | 
			
		||||
 | 
			
		||||
  my $success = db_set_prop(\%config, $key, $property => $new_value)
 | 
			
		||||
 | 
			
		||||
Sets the given $property of the $key in the %config database to the
 | 
			
		||||
$new_value.  If the $property didn't exist, it will be added.
 | 
			
		||||
 | 
			
		||||
Returns true/value if it succeeded/failed.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub db_set_prop
 | 
			
		||||
{
 | 
			
		||||
    my ($hash, $key, $prop, $new_value) = @_;
 | 
			
		||||
 | 
			
		||||
    return undef unless defined db_get($hash, $key);
 | 
			
		||||
 | 
			
		||||
    my $type = db_get_type($hash, $key);
 | 
			
		||||
    my %properties = db_get_prop($hash, $key);
 | 
			
		||||
    $properties{$prop} = $new_value;
 | 
			
		||||
    return db_set($hash, $key, $type, \%properties);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=item B<db_get_prop>
 | 
			
		||||
 | 
			
		||||
  my %properties = db_get_prop(\%config, $key);    
 | 
			
		||||
  my $value      = db_get_prop(\%config, $key, $property);
 | 
			
		||||
 | 
			
		||||
Returns the %properties for a $key in the %config database.  If you
 | 
			
		||||
ask for a specific $property you'll get the $value for that $property.
 | 
			
		||||
 | 
			
		||||
Returns undef if the $key or $property doesn't exist.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub db_get_prop
 | 
			
		||||
{
 | 
			
		||||
    my ($hash, $key, $prop) = @_;
 | 
			
		||||
 | 
			
		||||
    my $val = db_get($hash, $key);
 | 
			
		||||
    return (defined $prop ? undef : ()) unless defined $val;
 | 
			
		||||
 | 
			
		||||
    my($type, %properties) = _db_string_to_type_and_hash($val);
 | 
			
		||||
 | 
			
		||||
    return %properties unless defined $prop;
 | 
			
		||||
    return undef unless exists $properties{$prop};
 | 
			
		||||
    return $properties{$prop};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=item B<db_delete_prop>
 | 
			
		||||
 | 
			
		||||
  db_delete_prop(\%config, $key, $property)
 | 
			
		||||
 | 
			
		||||
Deletes a $property from the $key in the %config.
 | 
			
		||||
 | 
			
		||||
Returns undef if the $key doesn't exist.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub db_delete_prop
 | 
			
		||||
{
 | 
			
		||||
    my ($hash, $key, $prop) = @_;
 | 
			
		||||
 | 
			
		||||
    return undef unless defined db_get($hash, $key);
 | 
			
		||||
 | 
			
		||||
    my $type = db_get_type($hash, $key);
 | 
			
		||||
    my %properties = db_get_prop($hash, $key);
 | 
			
		||||
    delete $properties{$prop};
 | 
			
		||||
    return db_set($hash, $key, $type, \%properties);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=back
 | 
			
		||||
 | 
			
		||||
=head2 Debugging Functions
 | 
			
		||||
 | 
			
		||||
These functions are useful for debugging.
 | 
			
		||||
 | 
			
		||||
=over 4
 | 
			
		||||
 | 
			
		||||
=item B<db_print>
 | 
			
		||||
 | 
			
		||||
  db_print(\%config);
 | 
			
		||||
  db_print(\%config, $key);
 | 
			
		||||
 | 
			
		||||
Prints out keys and raw values in the %config database.  If $key is
 | 
			
		||||
given it prints the $key and its raw value.  If no $key is given it
 | 
			
		||||
prints out all the keys and their raw values.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub db_print
 | 
			
		||||
{
 | 
			
		||||
    my ($hash, $key) = @_;
 | 
			
		||||
 | 
			
		||||
    my @list;
 | 
			
		||||
 | 
			
		||||
    if (defined $key)
 | 
			
		||||
    {
 | 
			
		||||
        return undef unless defined db_get($hash, $key);
 | 
			
		||||
        @list = ($key);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        @list = db_get($hash);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return undef unless scalar @list;
 | 
			
		||||
 | 
			
		||||
    foreach (@list)
 | 
			
		||||
    {
 | 
			
		||||
        print "$_=", scalar db_get($hash, $_),"\n";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=item B<db_show>
 | 
			
		||||
 | 
			
		||||
  db_show(\%config);
 | 
			
		||||
  db_show(\%config, $key);
 | 
			
		||||
 | 
			
		||||
Prints out keys and their values in a human readable format.
 | 
			
		||||
 | 
			
		||||
If $key is given it prints out the $key, type and properties of that
 | 
			
		||||
$key.  Otherwise it prints out the key, type and properties for all
 | 
			
		||||
keys.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub db_show
 | 
			
		||||
{
 | 
			
		||||
    my ($hash, $key) = @_;
 | 
			
		||||
 | 
			
		||||
    my @list;
 | 
			
		||||
 | 
			
		||||
    if (defined $key)
 | 
			
		||||
    {
 | 
			
		||||
        return undef unless defined db_get($hash, $key);
 | 
			
		||||
        @list = ($key);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        @list = db_get($hash) unless defined $key;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return undef unless scalar @list;
 | 
			
		||||
 | 
			
		||||
    foreach (@list)
 | 
			
		||||
    {
 | 
			
		||||
        print "$_=";
 | 
			
		||||
 | 
			
		||||
        my $type = db_get_type($hash, $_);
 | 
			
		||||
 | 
			
		||||
        if (defined $type)
 | 
			
		||||
        {
 | 
			
		||||
            print "$type\n";
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            print "\n";
 | 
			
		||||
            next;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        my %properties = db_get_prop($hash, $_);
 | 
			
		||||
        next unless scalar keys %properties;
 | 
			
		||||
 | 
			
		||||
        foreach my $property (sort keys %properties)
 | 
			
		||||
        {
 | 
			
		||||
            print "    $property=$properties{$property}\n";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=item B<db_print_type>
 | 
			
		||||
 | 
			
		||||
  db_print_type(\%config);
 | 
			
		||||
  db_print_type(\%config, $key);
 | 
			
		||||
 | 
			
		||||
Prints out keys and their types in the %config database.
 | 
			
		||||
 | 
			
		||||
If $key is given, it prints out just that $key and its type.
 | 
			
		||||
Otherwise it prints out all the keys and their types.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub db_print_type
 | 
			
		||||
{
 | 
			
		||||
    my ($hash, $key) = @_;
 | 
			
		||||
 | 
			
		||||
    my @list;
 | 
			
		||||
 | 
			
		||||
    if (defined $key)
 | 
			
		||||
    {
 | 
			
		||||
        return undef unless defined db_get($hash, $key);
 | 
			
		||||
        @list = $key;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        @list = db_get($hash);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return undef unless scalar @list;
 | 
			
		||||
 | 
			
		||||
    foreach (@list)
 | 
			
		||||
    {
 | 
			
		||||
        print "$_=";
 | 
			
		||||
 | 
			
		||||
        my $type = db_get_type($hash, $_);
 | 
			
		||||
 | 
			
		||||
        print db_get_type($hash, $_),"\n" if defined $type;
 | 
			
		||||
        print "\n" unless defined $type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=item B<db_print_prop>
 | 
			
		||||
 | 
			
		||||
  db_print_prop(\%config, $key);
 | 
			
		||||
  db_print_prop(\%config, $key, $property);
 | 
			
		||||
 | 
			
		||||
Prints out the properties (or a single $property) of the given $key in
 | 
			
		||||
the %config.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub db_print_prop
 | 
			
		||||
{
 | 
			
		||||
    my ($hash, $key, $prop) = @_;
 | 
			
		||||
 | 
			
		||||
    my @list;
 | 
			
		||||
    my %list;
 | 
			
		||||
 | 
			
		||||
    return undef unless defined db_get($hash, $key);
 | 
			
		||||
 | 
			
		||||
    if (defined $prop)
 | 
			
		||||
    {
 | 
			
		||||
        my $value = db_get_prop($hash, $key, $prop);
 | 
			
		||||
        return undef unless defined $value;
 | 
			
		||||
 | 
			
		||||
        %list = ($prop => $value);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        %list = db_get_prop($hash, $key);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return undef unless scalar keys %list;
 | 
			
		||||
 | 
			
		||||
    foreach (sort keys %list)
 | 
			
		||||
    {
 | 
			
		||||
        print "$_=$list{$_}\n";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=head2 OO Interface
 | 
			
		||||
 | 
			
		||||
To add to the confusion, esmith::db has a vestigal object-oriented
 | 
			
		||||
interface.  Use esmith::DB::db instead.
 | 
			
		||||
 | 
			
		||||
=over 4
 | 
			
		||||
 | 
			
		||||
=item B<new>
 | 
			
		||||
 | 
			
		||||
  my $db = esmith::db->new($db_file)
 | 
			
		||||
 | 
			
		||||
Generates a new esmith::db object from the given $db_file
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub new
 | 
			
		||||
{
 | 
			
		||||
    my($class,$dbname) = @_;
 | 
			
		||||
 | 
			
		||||
    return $class->open($dbname);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=item B<open>
 | 
			
		||||
 | 
			
		||||
  my $db = esmith::db->open($db_name);
 | 
			
		||||
  my $db = esmith::db->open($db_file);
 | 
			
		||||
 | 
			
		||||
Takes a database name (or pathname) and opens the named database. 
 | 
			
		||||
The database name form is preferred over the explicit pathname.
 | 
			
		||||
 | 
			
		||||
For example
 | 
			
		||||
 | 
			
		||||
  $db->open( 'configuration' );
 | 
			
		||||
              or
 | 
			
		||||
  $db->open( '/path/to/configuration' );
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub open
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my $dbName = shift;
 | 
			
		||||
    my $class = ref($self) || $self;
 | 
			
		||||
 | 
			
		||||
    my $dataFile = _db_path($dbName);
 | 
			
		||||
 | 
			
		||||
    unless ( $esmith::db::REFCOUNT{$dataFile} )
 | 
			
		||||
    {
 | 
			
		||||
        warn "Reading $dataFile into cache\n" if ($esmith::db::DEBUG);
 | 
			
		||||
 | 
			
		||||
        my %db;
 | 
			
		||||
        tie %db, 'esmith::config', $dataFile;
 | 
			
		||||
 | 
			
		||||
        $esmith::db::CACHE{$dataFile} = \%db;   
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $self = bless { 
 | 
			
		||||
        DBNAME => $dataFile, 
 | 
			
		||||
        CACHE => $esmith::db::CACHE{$dataFile} 
 | 
			
		||||
    }, $class;
 | 
			
		||||
 | 
			
		||||
    $esmith::db::REFCOUNT{$dataFile}++;
 | 
			
		||||
 | 
			
		||||
    return $self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub DESTROY
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    return $self->close();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=item B<close>
 | 
			
		||||
 | 
			
		||||
  $db->close;
 | 
			
		||||
 | 
			
		||||
Closes this database.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub close
 | 
			
		||||
{
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
 | 
			
		||||
    my $dataFile = $self->{'DBNAME'};
 | 
			
		||||
 | 
			
		||||
    $esmith::db::REFCOUNT{$dataFile}--;
 | 
			
		||||
 | 
			
		||||
    if ( $esmith::db::REFCOUNT{$dataFile} == 0 )
 | 
			
		||||
    {
 | 
			
		||||
        delete $esmith::db::CACHE{$dataFile};
 | 
			
		||||
        warn "esmith::db::close Closing $dataFile\n" if ($esmith::db::DEBUG);
 | 
			
		||||
    }
 | 
			
		||||
    elsif ( $esmith::db::REFCOUNT{$dataFile} > 0 )
 | 
			
		||||
    {
 | 
			
		||||
        warn "esmith::db::close Not closing $dataFile, references ",
 | 
			
		||||
        $esmith::db::REFCOUNT{$dataFile}, "\n" if ($esmith::db::DEBUG);
 | 
			
		||||
    }
 | 
			
		||||
    else 
 | 
			
		||||
    {
 | 
			
		||||
        $esmith::db::REFCOUNT{$dataFile} = 0;
 | 
			
		||||
        warn "esmith::db::close Not closing $dataFile, zero references\n" 
 | 
			
		||||
        if ($esmith::db::DEBUG);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=item B<set>
 | 
			
		||||
 | 
			
		||||
=item B<set_type>
 | 
			
		||||
 | 
			
		||||
=item B<set_prop>
 | 
			
		||||
 | 
			
		||||
=item B<get>
 | 
			
		||||
 | 
			
		||||
=item B<get_type>
 | 
			
		||||
 | 
			
		||||
=item B<get_prop>
 | 
			
		||||
 | 
			
		||||
=item B<delete>
 | 
			
		||||
 | 
			
		||||
=item B<delete_prop>
 | 
			
		||||
 | 
			
		||||
These all work like their functional versions (ie. set() == db_set())
 | 
			
		||||
except it is not necessary to input the %config database.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub AUTOLOAD
 | 
			
		||||
{
 | 
			
		||||
    no strict 'refs';
 | 
			
		||||
 | 
			
		||||
    # fully qualified sub-name stored in $AUTOLOAD package variable
 | 
			
		||||
    $esmith::db::AUTOLOAD =~ /^(.*::)(.*)$/;
 | 
			
		||||
    my ($pkg, $sub) = ($1, $2);
 | 
			
		||||
 | 
			
		||||
    # use *foo{THING} syntax to check if sub is defined (see perlref)
 | 
			
		||||
    if (defined *{"${pkg}db_${sub}"}{CODE})
 | 
			
		||||
    {
 | 
			
		||||
        my $self = shift;
 | 
			
		||||
        my $cache = $esmith::db::CACHE{$self->{DBNAME}};
 | 
			
		||||
        wantarray ? return (my @p = &{"${pkg}db_${sub}"}($cache, @_))
 | 
			
		||||
            : return (my $p = &{"${pkg}db_${sub}"}($cache, @_));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=begin private
 | 
			
		||||
 | 
			
		||||
=head2 Private functions
 | 
			
		||||
 | 
			
		||||
=over4
 | 
			
		||||
 | 
			
		||||
=item B<_db_hash_to_string>
 | 
			
		||||
 | 
			
		||||
  my $raw_value = _db_hash_to_string($hashref);
 | 
			
		||||
 | 
			
		||||
Takes a reference to a hash and returns a string of pipe "|" delimited
 | 
			
		||||
pairs suitable for being stored.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub _db_hash_to_string
 | 
			
		||||
{
 | 
			
		||||
    my ($hash) = @_;
 | 
			
		||||
    my $string = '';
 | 
			
		||||
 | 
			
		||||
    foreach (sort keys %$hash)
 | 
			
		||||
    {
 | 
			
		||||
        $string .= '|' if length($string);
 | 
			
		||||
        $string .= "$_|";
 | 
			
		||||
        $string .= $$hash{$_} if defined $$hash{$_};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return $string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=item B<_db_string_to_type_and_hash>
 | 
			
		||||
 | 
			
		||||
  my($type, %properties) = _db_string_to_type_and_hash($raw_value);
 | 
			
		||||
 | 
			
		||||
Takes the $raw_value, which is a | delimited string, and spits it up
 | 
			
		||||
into the $type (the first field) and its %properties (the rest).
 | 
			
		||||
 | 
			
		||||
Escaped pipes (\|) are properly ignored as a delimiter.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub _db_string_to_type_and_hash ($)
 | 
			
		||||
{
 | 
			
		||||
    my ($arg) = @_;
 | 
			
		||||
    return ('', ()) unless defined $arg;
 | 
			
		||||
 | 
			
		||||
    # The funky regex is to avoid escaped pipes.
 | 
			
		||||
    # If you specify a negative limit empty trailing fields are omitted.
 | 
			
		||||
    return split(/(?<!\\)\|/, $arg, -1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item B<_db_path>
 | 
			
		||||
 | 
			
		||||
  my $dfile = _db_path($database_name);
 | 
			
		||||
 | 
			
		||||
Takes a $database_name and returns the $file where it lives.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub _db_path($)
 | 
			
		||||
{
 | 
			
		||||
    my ($file) = @_;
 | 
			
		||||
 | 
			
		||||
    if ($file =~ m:^/:)
 | 
			
		||||
    {
 | 
			
		||||
	return $file;
 | 
			
		||||
    }
 | 
			
		||||
    return "/home/e-smith/db/$file" if (-e "/home/e-smith/db/$file");
 | 
			
		||||
 | 
			
		||||
    if (-e "/home/e-smith/$file")
 | 
			
		||||
    {
 | 
			
		||||
	warn "Database found in old location /home/e-smith/$file";
 | 
			
		||||
	return "/home/e-smith/$file";
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
	return "/home/e-smith/db/$file";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=back
 | 
			
		||||
 | 
			
		||||
=end private
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=head1 BUGS and CAVEATS
 | 
			
		||||
 | 
			
		||||
keys cannot contain newlines or pipes.  
 | 
			
		||||
 | 
			
		||||
types and properties cannot contain pipes.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=head1 AUTHOR
 | 
			
		||||
 | 
			
		||||
Mitel Networks Corporation
 | 
			
		||||
 | 
			
		||||
For more information, see http://www.e-smith.org/
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
							
								
								
									
										133
									
								
								root/usr/share/perl5/vendor_perl/esmith/ethernet.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								root/usr/share/perl5/vendor_perl/esmith/ethernet.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,133 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2005 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::ethernet;
 | 
			
		||||
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use File::Basename;
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::ethernet - Ethernet-related utility routines for e-smith
 | 
			
		||||
 | 
			
		||||
=head1 VERSION
 | 
			
		||||
 | 
			
		||||
This file documents C<esmith::ethernet> version B<1.4.0>
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
    use esmith::ethernet;
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
This module contains routines for 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head2 probeAdapters()
 | 
			
		||||
 | 
			
		||||
Probe for any recognised adapters
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub probeAdapters ()
 | 
			
		||||
{
 | 
			
		||||
    opendir(my $dh, "/sys/class/net") or die "Couldn't open /sys/class/net: $!";
 | 
			
		||||
    my @nics = grep { $_ !~ m/^\./ } readdir($dh);
 | 
			
		||||
    closedir($dh);
 | 
			
		||||
    my $adapters = '';
 | 
			
		||||
    my $index = 1;
 | 
			
		||||
    foreach my $nic (@nics){
 | 
			
		||||
        # Untaint $nic and makes sure the name looks OK
 | 
			
		||||
        next unless ($nic =~ m/^(\w+[\.:]?\d+)$/);
 | 
			
		||||
        $nic = $1;
 | 
			
		||||
        next if (
 | 
			
		||||
            # skip loopback
 | 
			
		||||
            $nic eq 'lo' ||
 | 
			
		||||
            # skip non links
 | 
			
		||||
            !-l "/sys/class/net/$nic" ||
 | 
			
		||||
            # skip wireless nics
 | 
			
		||||
            -d "/sys/class/net/$nic/wireless" ||
 | 
			
		||||
            -l "/sys/class/net/$nic/phy80211" ||
 | 
			
		||||
            # skip bridges
 | 
			
		||||
            -d "/sys/class/net/$nic/bridge" ||
 | 
			
		||||
            # skip vlans
 | 
			
		||||
            -f "/proc/net/vlan/$nic" ||
 | 
			
		||||
            # skip bonds
 | 
			
		||||
            -d "/sys/class/net/$nic/bonding" ||
 | 
			
		||||
            # skip tun/tap
 | 
			
		||||
            -f "/sys/class/net/$nic/tun_flags" ||
 | 
			
		||||
            # skip dummy
 | 
			
		||||
            -d "/sys/devices/virtual/net/$nic"
 | 
			
		||||
        );
 | 
			
		||||
        # Now we should be left only wth ethernet adapters
 | 
			
		||||
        open HW, "/sys/class/net/$nic/address";
 | 
			
		||||
        my $mac = join("", <HW>);
 | 
			
		||||
        close HW;
 | 
			
		||||
        # Check MAC Addr and untaint it
 | 
			
		||||
        next unless ($mac =~ m/^(([\da-f]{2}:){5}[\da-f]{2})$/i);
 | 
			
		||||
        $mac = $1;
 | 
			
		||||
        # If the device is a slave of a bridge, it's real MAC
 | 
			
		||||
        # address can be found in /proc/net/bonding/bondX
 | 
			
		||||
        if (-l "/sys/class/net/$nic/master"){
 | 
			
		||||
            my $bond = basename (readlink "/sys/class/net/$nic/master");
 | 
			
		||||
            local $/ = '';
 | 
			
		||||
            open SLAVES, "/proc/net/bonding/$bond";
 | 
			
		||||
            my @slaves = <SLAVES>;
 | 
			
		||||
            close SLAVES;
 | 
			
		||||
            my @slaveInfo = grep { /^Slave\ Interface:\ $nic/m } @slaves;
 | 
			
		||||
            foreach (split /\n+/, (join "", @slaveInfo)){
 | 
			
		||||
                $mac = $1 if (/^Permanent\ HW\ addr:\ (.*)$/);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        chomp($mac);
 | 
			
		||||
        my $driver = basename (readlink "/sys/class/net/$nic/device/driver");
 | 
			
		||||
        # Untaint driver name
 | 
			
		||||
        next unless ($driver =~ m/^([\w\-]+)$/);
 | 
			
		||||
        $driver = $1;
 | 
			
		||||
        my $bus = basename (readlink "/sys/class/net/$nic/device/subsystem");
 | 
			
		||||
        my $desc = $nic;
 | 
			
		||||
        if ($bus eq 'pci'){
 | 
			
		||||
            my $dev = basename (readlink "/sys/class/net/$nic/device");
 | 
			
		||||
            # Untaint $dev
 | 
			
		||||
            if ($dev =~ m/^(\d+:\d+:\d+\.\d+)$/){
 | 
			
		||||
                $dev = $1;
 | 
			
		||||
                $desc = `/sbin/lspci -s $dev`;
 | 
			
		||||
                # Extract only description 
 | 
			
		||||
                $desc =~ m/^.*:.*:\s+(.*)\s*/;
 | 
			
		||||
                $desc = $1;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        elsif ($bus eq 'virtio'){
 | 
			
		||||
            $desc = 'Virtio Network Device';
 | 
			
		||||
        }
 | 
			
		||||
        # TODO: we should also try to get the description of USB devices
 | 
			
		||||
        $adapters .= "EthernetDriver" . $index++ . "\t" . $driver . "\t" .
 | 
			
		||||
                     $mac . "\t" . "\"$desc\"" . "\t" . $nic ."\n";
 | 
			
		||||
    }
 | 
			
		||||
    return $adapters;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Return one to make the import process return success.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=AUTHOR
 | 
			
		||||
 | 
			
		||||
SME Server Developers <bugs@e-smith.com>
 | 
			
		||||
 | 
			
		||||
For more information see http://www.e-smith.org/
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										220
									
								
								root/usr/share/perl5/vendor_perl/esmith/event.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										220
									
								
								root/usr/share/perl5/vendor_perl/esmith/event.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,220 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2005 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::event;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use Exporter;
 | 
			
		||||
use Time::HiRes qw( usleep ualarm gettimeofday tv_interval );
 | 
			
		||||
use esmith::Logger;
 | 
			
		||||
use File::Basename;
 | 
			
		||||
use File::Temp qw/ :mktemp /;
 | 
			
		||||
use esmith::ConfigDB;
 | 
			
		||||
use POSIX;
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::event - Routines for handling e-smith events
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
    use esmith::event;
 | 
			
		||||
 | 
			
		||||
    my $exitcode = event_signal($event, @args);
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
our $VERSION = sprintf '%d.%03d', q$Revision: 1.16 $ =~ /: (\d+).(\d+)/;
 | 
			
		||||
our @ISA         = qw(Exporter);
 | 
			
		||||
our @EXPORT      = qw(event_signal);
 | 
			
		||||
 | 
			
		||||
our @EXPORT_OK   = ();
 | 
			
		||||
our %EXPORT_TAGS = ();
 | 
			
		||||
our $return_value = undef;
 | 
			
		||||
 | 
			
		||||
tie *LOG, 'esmith::Logger', 'esmith::event';
 | 
			
		||||
 | 
			
		||||
sub event_signal
 | 
			
		||||
{
 | 
			
		||||
    my ($event, @args) = @_;
 | 
			
		||||
    if ($event eq "actions")
 | 
			
		||||
    {
 | 
			
		||||
        warn("'actions' is not a valid event name.\n");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    my $events = "/etc/e-smith/events";
 | 
			
		||||
    my $handlerDir = "$events/$event";
 | 
			
		||||
 | 
			
		||||
    #------------------------------------------------------------
 | 
			
		||||
    # get event handler filenames
 | 
			
		||||
    #------------------------------------------------------------
 | 
			
		||||
    opendir (DIR, $handlerDir)
 | 
			
		||||
        || die "Can't open directory $handlerDir\n";
 | 
			
		||||
 | 
			
		||||
    # Create a hash of handlers (ignore directories),
 | 
			
		||||
    # with value of basename(handler)
 | 
			
		||||
    my %handlers = ();
 | 
			
		||||
    foreach (grep {! -d "$handlerDir/$_"} readdir (DIR))
 | 
			
		||||
    {
 | 
			
		||||
	$handlers{"$handlerDir/$_"} = $_;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    closedir (DIR);
 | 
			
		||||
 | 
			
		||||
    # Add generic handlers to list, if their metadata directories
 | 
			
		||||
    # exist
 | 
			
		||||
    $handlers{"$events/actions/generic_template_expand"} = "S05generic_template_expand"
 | 
			
		||||
	if ( -d "$handlerDir/templates2expand");
 | 
			
		||||
    $handlers{"$events/actions/adjust-services"} = "S90adjust-services"
 | 
			
		||||
	if ( -d "$handlerDir/services2adjust");
 | 
			
		||||
 | 
			
		||||
    #------------------------------------------------------------
 | 
			
		||||
    # Execute all handlers, sending any output to the system log.
 | 
			
		||||
    #
 | 
			
		||||
    # Event handlers are not supposed to generate error messages
 | 
			
		||||
    # under normal conditions, so we do not provide a mechanism
 | 
			
		||||
    # for event handlers to signal errors to the user. Errors can
 | 
			
		||||
    # only be written to the log file.
 | 
			
		||||
    #------------------------------------------------------------
 | 
			
		||||
    print LOG "Processing event: $event @args";
 | 
			
		||||
 | 
			
		||||
    #------------------------------------------------------------
 | 
			
		||||
    # Run handlers, logging all output.
 | 
			
		||||
    #------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
    # assume success
 | 
			
		||||
    my $exitcode = 1;
 | 
			
		||||
 | 
			
		||||
    foreach my $filename
 | 
			
		||||
	(sort { $handlers{$a} cmp $handlers{$b} } keys %handlers)
 | 
			
		||||
    {
 | 
			
		||||
        my $handler = basename $filename;
 | 
			
		||||
        my $startTime = [gettimeofday];
 | 
			
		||||
 | 
			
		||||
        my $status = -1;
 | 
			
		||||
        if (-x $filename)
 | 
			
		||||
        {
 | 
			
		||||
            print LOG "Running event handler: $filename";
 | 
			
		||||
 | 
			
		||||
            unless (($status = _mysystem(\*LOG, $filename, $event, @args)) == 0)
 | 
			
		||||
            {
 | 
			
		||||
                # if any handler fails, the entire event fails
 | 
			
		||||
                $exitcode = 0;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            print LOG "Skipping non-executable event handler: $filename";
 | 
			
		||||
	    next;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        my $endTime = [gettimeofday];
 | 
			
		||||
        my $elapsedTime = tv_interval($startTime, $endTime);
 | 
			
		||||
        my $log = "$handler=action|Event|$event|Action|$handler";
 | 
			
		||||
        $log .= "|Start|@$startTime|End|@$endTime|Elapsed|$elapsedTime";
 | 
			
		||||
        $log .= "|Status|$status" if $status;
 | 
			
		||||
        print LOG $log;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # Implement event queuing for clustered systems. 
 | 
			
		||||
    my $qfifo = "/var/spool/eventq";
 | 
			
		||||
    return $exitcode unless (-e $qfifo);
 | 
			
		||||
 | 
			
		||||
    # Ensure we aren't called by a cascaded event. We only need to
 | 
			
		||||
    # queue the top-level of such a beast.
 | 
			
		||||
    my $ppid = getppid();
 | 
			
		||||
    open F, "/proc/$ppid/cmdline";
 | 
			
		||||
    my $cmd = <F>;
 | 
			
		||||
    close F;
 | 
			
		||||
 | 
			
		||||
    unless($cmd =~ "/etc/e-smith/event")
 | 
			
		||||
    {
 | 
			
		||||
        my $fd = POSIX::open($qfifo, &POSIX::O_WRONLY) or return $exitcode;
 | 
			
		||||
        my $argstr = join(" ",$event,@args);
 | 
			
		||||
        $argstr .= "\n";
 | 
			
		||||
        POSIX::write($fd, $argstr, length($argstr));
 | 
			
		||||
        POSIX::close($fd);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return $exitcode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub _mysystem
 | 
			
		||||
{
 | 
			
		||||
    my ($logger, $filename, $event, @args) = @_;
 | 
			
		||||
 | 
			
		||||
    my $pid = open(PIPE, "-|");
 | 
			
		||||
    die "Failed to fork: $!\n" unless defined $pid;
 | 
			
		||||
 | 
			
		||||
    if ($pid)
 | 
			
		||||
    {
 | 
			
		||||
        # Parent
 | 
			
		||||
        while (my $line = <PIPE>)
 | 
			
		||||
        {
 | 
			
		||||
            print $logger $line;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        # Child
 | 
			
		||||
        open(STDERR, ">&STDOUT");
 | 
			
		||||
        exec($filename, $event, @args);
 | 
			
		||||
    }
 | 
			
		||||
    close(PIPE);
 | 
			
		||||
    return $?;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#------------------------------------------------------------
 | 
			
		||||
# Attempt to eval perl handlers for efficiency - not currently used
 | 
			
		||||
# return 1 on success; 0 on error
 | 
			
		||||
#------------------------------------------------------------
 | 
			
		||||
sub _runHandler($)
 | 
			
		||||
{
 | 
			
		||||
    my ($filename) = @_;
 | 
			
		||||
 | 
			
		||||
    open(FILE, $filename) || die "Couldn't open $filename: $!";
 | 
			
		||||
    my @lines = <FILE>;
 | 
			
		||||
    close FILE;
 | 
			
		||||
 | 
			
		||||
    my $string = "";
 | 
			
		||||
 | 
			
		||||
    unless ( $lines[0] =~ /^#!.*perl/ )
 | 
			
		||||
    {
 | 
			
		||||
        # STDOUT and STDERR are both redirected going to LOG
 | 
			
		||||
        return (system($filename, @ARGV) == 0) ? 1 : 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    map { $string .= $_ } @lines;
 | 
			
		||||
 | 
			
		||||
    print "Eval of $filename...";
 | 
			
		||||
 | 
			
		||||
    # Override 'exit' in symbol table for handlers
 | 
			
		||||
    sub exit { die "$_[0]\n" };
 | 
			
		||||
    *CORE::GLOBAL::exit = \&esmith::event::exit;
 | 
			
		||||
 | 
			
		||||
    my $status = eval $string;
 | 
			
		||||
    chomp $@;
 | 
			
		||||
 | 
			
		||||
    # if $@ is defined, then die or exit was called - use that status
 | 
			
		||||
    $status = $@ if defined $@;
 | 
			
		||||
    
 | 
			
		||||
    # for all exit values except 0, assume failure
 | 
			
		||||
    if ($@)
 | 
			
		||||
    {
 | 
			
		||||
        print "Eval of $filename failed:  $status\n";
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    print "$status\n";
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
							
								
								
									
										61
									
								
								root/usr/share/perl5/vendor_perl/esmith/lockfile.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								root/usr/share/perl5/vendor_perl/esmith/lockfile.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::lockfile;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use vars qw($VERSION @ISA @EXPORT_OK);
 | 
			
		||||
use Exporter;
 | 
			
		||||
use Fcntl ":flock";
 | 
			
		||||
use FileHandle;
 | 
			
		||||
 | 
			
		||||
@ISA = qw(Exporter);
 | 
			
		||||
@EXPORT_OK = qw( 
 | 
			
		||||
    LockFileOrReturn LockFileOrWait UnlockFile 
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
sub LockFileOrReturn ($)
 | 
			
		||||
{
 | 
			
		||||
    # Attempt to lock a file. If the lock fails, return immediately.
 | 
			
		||||
 | 
			
		||||
    my $lock_file = shift;
 | 
			
		||||
 | 
			
		||||
    my $FH = new FileHandle;
 | 
			
		||||
 | 
			
		||||
    $FH->open(">> $lock_file")
 | 
			
		||||
        or die "Cannot open lock file $lock_file for writing: $!.\n";
 | 
			
		||||
 | 
			
		||||
    flock($FH, LOCK_EX | LOCK_NB) or return 0;
 | 
			
		||||
 | 
			
		||||
    return $FH;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub LockFileOrWait ($)
 | 
			
		||||
{
 | 
			
		||||
    # Attempt to lock a file. Wait until the file is available.
 | 
			
		||||
 | 
			
		||||
    my $lock_file = shift;
 | 
			
		||||
 | 
			
		||||
    my $FH = new FileHandle;
 | 
			
		||||
 | 
			
		||||
    $FH->open(">> $lock_file")
 | 
			
		||||
        or die "Cannot open lock file $lock_file for writing: $!.\n";
 | 
			
		||||
 | 
			
		||||
    flock($FH, LOCK_EX) or return 0;
 | 
			
		||||
 | 
			
		||||
    return $FH;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub UnlockFile ($)
 | 
			
		||||
{
 | 
			
		||||
    my $FH = shift;
 | 
			
		||||
 | 
			
		||||
    flock($FH, LOCK_UN);
 | 
			
		||||
    $FH->close;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
							
								
								
									
										76
									
								
								root/usr/share/perl5/vendor_perl/esmith/logrotate.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								root/usr/share/perl5/vendor_perl/esmith/logrotate.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::event;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::logrotate - Routines for handling rotation of log files
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
    use esmith::logrotate;
 | 
			
		||||
 | 
			
		||||
    NewLogFileSymlink($file);
 | 
			
		||||
    MakeFilenameFromSymlink($file);
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
BEGIN
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub NewLogFileSymlink
 | 
			
		||||
{
 | 
			
		||||
    my $file = shift;
 | 
			
		||||
    unless (defined $file)
 | 
			
		||||
    {
 | 
			
		||||
	warn("newlogfilesymlink called with no argument");
 | 
			
		||||
	return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    my $time = time();
 | 
			
		||||
 | 
			
		||||
    if (-f "/var/log/${file}")
 | 
			
		||||
    {
 | 
			
		||||
	my ($sec,$min,$hour,$mday,$mon,$year) = localtime($time - 1);
 | 
			
		||||
	my $target = sprintf("%s%04d%02d%02d%02d%02d%02d",
 | 
			
		||||
	    $file, $year+1900, $mon, $mday, $hour, $min, $sec);
 | 
			
		||||
	move("/var/log/${file}", "/var/log/${target}") or
 | 
			
		||||
	    die "Could not move /var/log/${file} to /var/log/${target}";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    my ($sec,$min,$hour,$mday,$mon,$year) = localtime($time);
 | 
			
		||||
    my $target = sprintf("%s%04d%02d%02d%02d%02d%02d",
 | 
			
		||||
	$file, $year+1900, $mon, $mday, $hour, $min, $sec);
 | 
			
		||||
    unlink("/var/log/${file}") or
 | 
			
		||||
	warn "Could not unlink /var/log/${file}";
 | 
			
		||||
    symlink("/var/log/${target}", "/var/log/${file}") or
 | 
			
		||||
	warn "Could not symlink /var/log/${target} to /var/log/${file}";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub MakeFilenameFromSymlink
 | 
			
		||||
{
 | 
			
		||||
    use File::Basename;
 | 
			
		||||
    my $filename = shift;
 | 
			
		||||
 | 
			
		||||
    return $filename unless (-l $filename);
 | 
			
		||||
    my $link = readlink $filename;
 | 
			
		||||
    my $directory = dirname($filename);
 | 
			
		||||
    return "${directory}/${link}";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
END
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
							
								
								
									
										140
									
								
								root/usr/share/perl5/vendor_perl/esmith/tcpsvd.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								root/usr/share/perl5/vendor_perl/esmith/tcpsvd.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,140 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 2005-2006 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::tcpsvd;
 | 
			
		||||
use strict;
 | 
			
		||||
 | 
			
		||||
=pod
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::tcpsvd - Manage tcpsvd "peers" directory
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
use esmith::tcpsvd;
 | 
			
		||||
 | 
			
		||||
esmith::tcpsvd::configure_peers($service)
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
This module provides utility functions for use with tcpsvd from Gerrit
 | 
			
		||||
Pape's ipsvd package - see http://smarden.org/ipsvd/.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
use esmith::NetworksDB;
 | 
			
		||||
use esmith::ConfigDB;
 | 
			
		||||
use esmith::util;
 | 
			
		||||
use esmith::lockfile;
 | 
			
		||||
use Carp;
 | 
			
		||||
 | 
			
		||||
=head2 configure_peers($service [, $peers_directory] )
 | 
			
		||||
 | 
			
		||||
configure_peers() configures the "peers" direectory used by tcpsvd for
 | 
			
		||||
access control and environment maipulation.  $service identifies the name
 | 
			
		||||
of the service managed by supervise or runit. The peers directory (as
 | 
			
		||||
specified by the optional $peers_directory argument, defaulting to 
 | 
			
		||||
"/var/service/$service/peers") is expected to contain files "0" defining
 | 
			
		||||
access conditions for public (default) accesss, and "local", defining
 | 
			
		||||
access conditions for local access. configure_peers() creates a set of
 | 
			
		||||
symlinks so that tcpsvd uses "local" for all local network access to
 | 
			
		||||
the service.
 | 
			
		||||
 | 
			
		||||
See http://smarden.org/ipsvd/ipsvd-instruct.5.html for all details of
 | 
			
		||||
the contents of the peers directory.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub configure_peers
 | 
			
		||||
{
 | 
			
		||||
    my $service = shift;
 | 
			
		||||
    my $peers = shift || "/var/service/$service/peers";
 | 
			
		||||
 | 
			
		||||
    unless (opendir(PEERS, $peers))
 | 
			
		||||
    {
 | 
			
		||||
	carp "Cannot read peers directory: $!";
 | 
			
		||||
	return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    my $config = esmith::ConfigDB->open;
 | 
			
		||||
    unless ($config)
 | 
			
		||||
    {
 | 
			
		||||
	carp "Could not open config db.";
 | 
			
		||||
	return;
 | 
			
		||||
    }
 | 
			
		||||
    $service = $config->get($service);
 | 
			
		||||
    unless ($service)
 | 
			
		||||
    {
 | 
			
		||||
	carp "No service record for $service";
 | 
			
		||||
	return;
 | 
			
		||||
    }
 | 
			
		||||
    my $access = $service->prop('access') || "localhost";
 | 
			
		||||
    my $nets = esmith::NetworksDB->open;
 | 
			
		||||
    unless ($nets)
 | 
			
		||||
    {
 | 
			
		||||
	carp "Could not open networks db.";
 | 
			
		||||
	return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    my $gw = $config->get('GatewayIP');
 | 
			
		||||
 | 
			
		||||
    # Make a list of local networks, in prefix format
 | 
			
		||||
    my %nets = ($access eq "localhost") ? () :
 | 
			
		||||
	    map
 | 
			
		||||
	    {
 | 
			
		||||
		$_ => 1,
 | 
			
		||||
	    }
 | 
			
		||||
		map
 | 
			
		||||
		{
 | 
			
		||||
		    esmith::util::computeAllLocalNetworkPrefixes($_->key, $_->prop('Mask'));
 | 
			
		||||
		}
 | 
			
		||||
		    ($nets->get_all_by_prop('type', 'network'));
 | 
			
		||||
 | 
			
		||||
    $nets{'127.0.0.1'} = 1;
 | 
			
		||||
 | 
			
		||||
    # Setup lock on peers directory while we manipulate it
 | 
			
		||||
    my $lock = esmith::lockfile::LockFileOrWait("$peers/local");
 | 
			
		||||
 | 
			
		||||
    # Now manage a set of symlinks to the "local" instructions file
 | 
			
		||||
    foreach my $insfile (readdir (PEERS))
 | 
			
		||||
    {
 | 
			
		||||
	next unless -l "$peers/$insfile";
 | 
			
		||||
	if (exists $nets{$insfile})
 | 
			
		||||
	{
 | 
			
		||||
	    # Cross this one off the list so that we don't bother creating it
 | 
			
		||||
	    delete $nets{$insfile};
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
	    # We no longer need this entry
 | 
			
		||||
	    unlink "$peers/$insfile" or
 | 
			
		||||
		warn "Could not delete access control file $peers/$insfile: $!\n";
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
    closedir(PEERS);
 | 
			
		||||
 | 
			
		||||
    foreach my $insfile (keys %nets)
 | 
			
		||||
    {
 | 
			
		||||
	symlink "local", "$peers/$insfile" or
 | 
			
		||||
	    warn "Cannot add instructions file for $peers/$insfile: $!\n";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (defined $gw)
 | 
			
		||||
    {
 | 
			
		||||
	# We have a defined gateway address - make sure that the router doesn't have
 | 
			
		||||
	# relay privileges
 | 
			
		||||
	my $gw_ip = $gw->value;
 | 
			
		||||
	unlink "$peers/$gw_ip";
 | 
			
		||||
	symlink "0", "$peers/$gw_ip" or
 | 
			
		||||
	      warn "Cannot add instructions file for $peers/$gw_ip: $!\n";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # Unlock peers directory
 | 
			
		||||
    $lock && esmith::lockfile::UnlockFile($lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
							
								
								
									
										1091
									
								
								root/usr/share/perl5/vendor_perl/esmith/templates.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1091
									
								
								root/usr/share/perl5/vendor_perl/esmith/templates.pm
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1413
									
								
								root/usr/share/perl5/vendor_perl/esmith/util.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1413
									
								
								root/usr/share/perl5/vendor_perl/esmith/util.pm
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										201
									
								
								root/usr/share/perl5/vendor_perl/esmith/util/link.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								root/usr/share/perl5/vendor_perl/esmith/util/link.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,201 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::util::link;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use esmith::ConfigDB;
 | 
			
		||||
require Exporter;
 | 
			
		||||
 | 
			
		||||
our @ISA = qw(Exporter);
 | 
			
		||||
our @EXPORT_OK = qw(getExternalLink);
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::util::link - utilities for manipulating network links
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
  use esmith::util::link qw(getExternalLink);
 | 
			
		||||
 | 
			
		||||
  # wait at most 60 seconds for the link to come up
 | 
			
		||||
  my $timeout = 60; 
 | 
			
		||||
 | 
			
		||||
  # now just get the link
 | 
			
		||||
  if (getExternalLink($timeout))
 | 
			
		||||
  {
 | 
			
		||||
    # the link is up
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    # the link didn't come up
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
This is a collection of generally useful functions for manipulating network 
 | 
			
		||||
links.
 | 
			
		||||
 | 
			
		||||
Functions are exported only on request.
 | 
			
		||||
 | 
			
		||||
=head2 Functions
 | 
			
		||||
 | 
			
		||||
=over 4
 | 
			
		||||
 | 
			
		||||
=item I<getExternalLink($timeout)>
 | 
			
		||||
 | 
			
		||||
Bring up the external link if it is not already up, waiting at most $timeout
 | 
			
		||||
seconds.  If a $timeout is not specified, it defaults to 300 (5 minutes) for
 | 
			
		||||
dialup connections.  This function can be used for both dialup and dedicated
 | 
			
		||||
connections, but dedicated connections will always return 1 (true).
 | 
			
		||||
 | 
			
		||||
Returns 1 if the external link is already up, or if it comes up within the
 | 
			
		||||
specfied $timeout period.
 | 
			
		||||
 | 
			
		||||
Returns 0 if the external link does not come up within the specified $timeout
 | 
			
		||||
period.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub getExternalLink
 | 
			
		||||
{
 | 
			
		||||
   my $timeout = shift;
 | 
			
		||||
 | 
			
		||||
   my $configdb = esmith::ConfigDB->open;
 | 
			
		||||
   my $rec = $configdb->get("AccessType");
 | 
			
		||||
   my $accessType = $rec->value;
 | 
			
		||||
   if ($accessType eq "dialup")
 | 
			
		||||
   {
 | 
			
		||||
      return _getDialupLink($timeout);  
 | 
			
		||||
   }
 | 
			
		||||
   elsif ($accessType eq "dedicated")
 | 
			
		||||
   {
 | 
			
		||||
      # assume we are up
 | 
			
		||||
      return 1;
 | 
			
		||||
   }
 | 
			
		||||
   else
 | 
			
		||||
   {
 | 
			
		||||
      # unknown access type
 | 
			
		||||
      return 0;
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=begin _private
 | 
			
		||||
 | 
			
		||||
=item I<getDialupLink($timeout)>
 | 
			
		||||
 | 
			
		||||
Bring up the ppp0 link, waiting at most $timeout seconds.  
 | 
			
		||||
 | 
			
		||||
Returns 1 if the link comes up within the timeout period.
 | 
			
		||||
 | 
			
		||||
Returns 0 if the link does not come up within the timeout period.
 | 
			
		||||
 | 
			
		||||
The default timeout is 300 seconds.
 | 
			
		||||
 | 
			
		||||
=end _private
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub _getDialupLink
 | 
			
		||||
{
 | 
			
		||||
    local $|=1;
 | 
			
		||||
    my $timeout = shift(@_) || 300;
 | 
			
		||||
 
 | 
			
		||||
    # check for existing ppp link
 | 
			
		||||
    if (-f "/var/run/ppp0.pid") 
 | 
			
		||||
    {
 | 
			
		||||
       # already up - return 1
 | 
			
		||||
       return 1;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
    # create a diald monitor channel
 | 
			
		||||
    my $ctlFile = "/etc/diald/diald.ctl";
 | 
			
		||||
    my $monFile = "/tmp/diald.monitor.$$";
 | 
			
		||||
    system('/bin/mknod', $monFile, 'p') == 0 
 | 
			
		||||
	or die "Can't mknod $monFile: $!\n";
 | 
			
		||||
 
 | 
			
		||||
    # open control channel to diald
 | 
			
		||||
    open (CTL, ">$ctlFile") or die "Can't open $ctlFile: $!\n";
 | 
			
		||||
 
 | 
			
		||||
    # set up a child process to monitor the channel
 | 
			
		||||
 | 
			
		||||
    my $pid = fork;
 | 
			
		||||
    die "Can't fork: $!" unless defined $pid;
 | 
			
		||||
    if ($pid) 
 | 
			
		||||
    {
 | 
			
		||||
        # parent
 | 
			
		||||
 | 
			
		||||
	# if the pipe reader isn't up first, diald will bail, so we open
 | 
			
		||||
	# another pipe writer just to wait for the pipe reader
 | 
			
		||||
	open (MON_W, ">$monFile") or die "can't open $monFile: $!\n";
 | 
			
		||||
 | 
			
		||||
        # begin monitoring diald status via monitor fifo
 | 
			
		||||
        print CTL "monitor $monFile\n";
 | 
			
		||||
        close CTL;
 | 
			
		||||
 | 
			
		||||
	# ok, everything is up and ready - send USR1 to diald
 | 
			
		||||
	open (PID, "</var/run/diald.pid") 
 | 
			
		||||
	    or die "can't open diald pidfile: $!\n";
 | 
			
		||||
        my $dialdPid = <PID>;
 | 
			
		||||
	close PID;
 | 
			
		||||
	kill 'USR1', $dialdPid;
 | 
			
		||||
 | 
			
		||||
        # Wait for the child to exit, then check for link again
 | 
			
		||||
        waitpid($pid, 0);
 | 
			
		||||
	close MON_W;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        # child
 | 
			
		||||
 | 
			
		||||
        open (MON, "<$monFile") or die "Can't open $monFile: $!\n";
 | 
			
		||||
 | 
			
		||||
        # Parse the diald monitor stream for state information
 | 
			
		||||
        my $state = "";
 | 
			
		||||
        my $elapsed = 0;
 | 
			
		||||
        while (<MON>)
 | 
			
		||||
        {
 | 
			
		||||
	    # lucky us; diald sends a STATUS msg every second
 | 
			
		||||
	    if (/^STATUS/) 
 | 
			
		||||
            { 
 | 
			
		||||
		$elapsed++; 
 | 
			
		||||
		if ($elapsed >= $timeout) 
 | 
			
		||||
		{ 
 | 
			
		||||
		    # time is up - exit with failure code
 | 
			
		||||
		    exit 1; 
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
	    elsif (/^STATE/) 
 | 
			
		||||
            { 
 | 
			
		||||
		$state = $_; 
 | 
			
		||||
	    }
 | 
			
		||||
            elsif ($state eq 'UP') 
 | 
			
		||||
            { 
 | 
			
		||||
		# the link is up - exit with success code
 | 
			
		||||
		exit 0; 
 | 
			
		||||
	    }
 | 
			
		||||
            next;
 | 
			
		||||
        }
 | 
			
		||||
        close MON;
 | 
			
		||||
	# end child
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # parent (cont)
 | 
			
		||||
 | 
			
		||||
    unlink $monFile;
 | 
			
		||||
 | 
			
		||||
    if ($? == 0 || -f "/var/run/ppp0.pid") 
 | 
			
		||||
    {
 | 
			
		||||
       # ok we're up - return 1 (true)
 | 
			
		||||
       return 1;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
       # out of time - return 0 (false)
 | 
			
		||||
       return 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
							
								
								
									
										312
									
								
								root/usr/share/perl5/vendor_perl/esmith/util/network.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										312
									
								
								root/usr/share/perl5/vendor_perl/esmith/util/network.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,312 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::util::network;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
 | 
			
		||||
require Exporter;
 | 
			
		||||
our @ISA = qw(Exporter);
 | 
			
		||||
our @EXPORT_OK = qw(isValidIP cleanIP isValidPort cmpIP);
 | 
			
		||||
our %EXPORT_TAGS = (
 | 
			
		||||
    all => [qw(isValidIP cleanIP isValidPort cmpIP)]
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
use Net::IPv4Addr qw(:all);
 | 
			
		||||
use Mail::RFC822::Address;
 | 
			
		||||
use esmith::AccountsDB;
 | 
			
		||||
 | 
			
		||||
use constant TRUE  => 1;
 | 
			
		||||
use constant FALSE => 0;
 | 
			
		||||
 | 
			
		||||
=for testing
 | 
			
		||||
use_ok('esmith::util::network');
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::util::network - miscellaneous network utilities
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
use esmith::util::network qw(the functions you want);
 | 
			
		||||
 | 
			
		||||
my $ip       = cleanIP($orig_ip);
 | 
			
		||||
my $is_valid = isValidIP($ip);
 | 
			
		||||
my $is_valid = isValidPort($port);
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
This is a collection of generally useful functions for working with IP
 | 
			
		||||
addresses.
 | 
			
		||||
 | 
			
		||||
Functions are exported only on request.
 | 
			
		||||
 | 
			
		||||
=head2 Functions
 | 
			
		||||
 | 
			
		||||
=over 4
 | 
			
		||||
 | 
			
		||||
=item I<cleanIP>
 | 
			
		||||
 | 
			
		||||
my $ip = cleanIP($orig_ip);
 | 
			
		||||
 | 
			
		||||
If the $orig_ip is valid it will be cleaned up into a cannonical form,
 | 
			
		||||
stripping any padding zeros and such.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
use esmith::util::network qw(cleanIP);
 | 
			
		||||
 | 
			
		||||
my %ips = (
 | 
			
		||||
    '000.000.000.000'      => '0.0.0.0',
 | 
			
		||||
    '0.0.0.0'              => '0.0.0.0',
 | 
			
		||||
    '001.2.003.4'          => '1.2.3.4',
 | 
			
		||||
    '100.2.3.4'            => '100.2.3.4',
 | 
			
		||||
    '10.13.14.015'         => '10.13.14.15',
 | 
			
		||||
    '10.33.15.109'         => '10.33.15.109',
 | 
			
		||||
    '1.2.3.4.5'            => ''
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
while( my($ip, $cleanip) = each %ips ) {
 | 
			
		||||
    is( cleanIP($ip), $cleanip,  "cleanIP($ip)" );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub cleanIP {
 | 
			
		||||
    my $ip = shift;
 | 
			
		||||
 | 
			
		||||
    return '' unless isValidIP($ip);
 | 
			
		||||
    $ip =~ s/\b0+(\d+)/$1/g;
 | 
			
		||||
 | 
			
		||||
    return isValidIP($ip) ? $ip : '';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item I<isValidIP>
 | 
			
		||||
 | 
			
		||||
my $is_valid = isValidIP($ip);
 | 
			
		||||
 | 
			
		||||
Returns the IP given if $ip is a properly formatted IP address, undef otherwise.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
use esmith::util::network qw(isValidIP);
 | 
			
		||||
 | 
			
		||||
my @goodIPs = qw(1.2.3.4
 | 
			
		||||
0.0.0.0
 | 
			
		||||
255.255.255.255
 | 
			
		||||
001.002.003.004
 | 
			
		||||
1.32.123.213
 | 
			
		||||
192.168.0.3
 | 
			
		||||
02.19.090.19
 | 
			
		||||
                );
 | 
			
		||||
                foreach my $ip (@goodIPs) {
 | 
			
		||||
                    ok( isValidIP($ip), "valid $ip");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                my @badIPs = qw(256.3.2.4
 | 
			
		||||
                -1.39.9.23
 | 
			
		||||
                0
 | 
			
		||||
                1
 | 
			
		||||
                255.255.255.255.0
 | 
			
		||||
                239..19.23.12
 | 
			
		||||
                1.2.3.4.
 | 
			
		||||
                foo.bar.com
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            foreach my $ip (@badIPs) {
 | 
			
		||||
                ok( !isValidIP($ip), "invalid $ip");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub isValidIP($)
 | 
			
		||||
{
 | 
			
		||||
    my ($string) = @_;
 | 
			
		||||
    return unless defined ipv4_chkip($string);
 | 
			
		||||
    return $string eq ipv4_chkip($string);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item I<isValidPort>
 | 
			
		||||
 | 
			
		||||
my $is_valid = isValidPort($port);
 | 
			
		||||
 | 
			
		||||
Returns true if $port is a properly formatted port, false otherwise.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
@badports = (98765434, -183, 0, 'bad port', 'a');
 | 
			
		||||
@goodports = (67, 23, 1, 54736);
 | 
			
		||||
 | 
			
		||||
foreach $port (@badports) {
 | 
			
		||||
    isnt(esmith::util::network::isValidPort($port), 1);
 | 
			
		||||
}
 | 
			
		||||
foreach $port (@goodports) {
 | 
			
		||||
    is(esmith::util::network::isValidPort($port), 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub isValidPort($)
 | 
			
		||||
{
 | 
			
		||||
    my $port = shift;
 | 
			
		||||
 | 
			
		||||
    return FALSE unless defined $port;
 | 
			
		||||
 | 
			
		||||
    if (($port =~ /^\d+$/) &&
 | 
			
		||||
        ($port > 0) &&
 | 
			
		||||
        ($port < 65536))
 | 
			
		||||
    {
 | 
			
		||||
        return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item I<cmpIP>
 | 
			
		||||
 | 
			
		||||
Performs a cmp operation on two IP addresses. 
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
$ip1 = '24.123.212.87';
 | 
			
		||||
$ip2 = '240.34.216.12';
 | 
			
		||||
 | 
			
		||||
is(esmith::util::network::cmpIP($ip1, $ip2), -1);
 | 
			
		||||
is(esmith::util::network::cmpIP($ip2, $ip1), 1);
 | 
			
		||||
is(esmith::util::network::cmpIP($ip1, $ip1), 0);
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub cmpIP($$)
 | 
			
		||||
{
 | 
			
		||||
    my $ip1 = ipv4_chkip(shift);
 | 
			
		||||
    my $ip2 = ipv4_chkip(shift);
 | 
			
		||||
 | 
			
		||||
    die "The first argument is not a valid IP address.\n" if not $ip1;
 | 
			
		||||
    die "The second argument is not a valid IP address.\n" if not $ip2;
 | 
			
		||||
 | 
			
		||||
    my @ip1cmps = split /\./, $ip1;
 | 
			
		||||
    my @ip2cmps = split /\./, $ip2;
 | 
			
		||||
 | 
			
		||||
    while (@ip1cmps)
 | 
			
		||||
    {
 | 
			
		||||
        my $cmp1 = shift @ip1cmps;
 | 
			
		||||
        my $cmp2 = shift @ip2cmps;
 | 
			
		||||
 | 
			
		||||
        my $cmp = $cmp1 <=> $cmp2;
 | 
			
		||||
        return $cmp if $cmp;
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item I<isValidHostname>
 | 
			
		||||
 | 
			
		||||
This function returns true if it is passed a valid RFC 921 hostname,
 | 
			
		||||
false otherwise.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub isValidHostname
 | 
			
		||||
{
 | 
			
		||||
    my $host_or_ip = shift;
 | 
			
		||||
 | 
			
		||||
    unless (isValidIP($host_or_ip))
 | 
			
		||||
    {
 | 
			
		||||
        # It's not an IP address. Does it look like a hostname?
 | 
			
		||||
        # FIXME: We could do a DNS lookup to be sure.
 | 
			
		||||
        # (See RFC 921, "Domain  Name System  Implementation  Schedule,"
 | 
			
		||||
        # FIXME: Put this in a library.
 | 
			
		||||
        unless ($host_or_ip =~ m{
 | 
			
		||||
            # Must begin with an alphabetical character...
 | 
			
		||||
            ^[a-z]
 | 
			
		||||
            # optionally followed by zero or more alphabetic characters,
 | 
			
		||||
            # hyphens, periods and numbers...
 | 
			
		||||
            [-a-z.0-9]*
 | 
			
		||||
            (
 | 
			
		||||
                # followed by one period...
 | 
			
		||||
                \.
 | 
			
		||||
                # and a repeat of the first pattern
 | 
			
		||||
                [a-z]
 | 
			
		||||
                [-a-z.0-9]*
 | 
			
		||||
            )+
 | 
			
		||||
            # which we can repeat one or more times, to the end of the
 | 
			
		||||
            # string.
 | 
			
		||||
            $
 | 
			
		||||
            # Case insensitive.
 | 
			
		||||
            }ix)
 | 
			
		||||
        {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item I<isValidEmail>
 | 
			
		||||
 | 
			
		||||
This validation function validates an email address, using the
 | 
			
		||||
Mail::RFC822::Address module. Additionally, by default, it permits a local
 | 
			
		||||
address instead of a fully-qualified remote address, even checking the
 | 
			
		||||
existence of said user in the accounts db.
 | 
			
		||||
 | 
			
		||||
If you don't wish to permit local addresses, pass the permitlocal option as
 | 
			
		||||
false.
 | 
			
		||||
 | 
			
		||||
ie. esmith::util::isValidEmail($address, { permitlocal => 0 })
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub isValidEmail
 | 
			
		||||
{
 | 
			
		||||
    my $address = shift;
 | 
			
		||||
    my $hashref = shift || {};
 | 
			
		||||
    my %defaults = ( permitlocal => 1 );
 | 
			
		||||
    my %options = (%defaults, %$hashref);
 | 
			
		||||
 | 
			
		||||
    if (Mail::RFC822::Address::valid($address))
 | 
			
		||||
    {
 | 
			
		||||
        return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
    # Permit a local address.
 | 
			
		||||
    if ($address =~ /^[a-zA-Z][a-zA-Z0-9\._\-]*$/)
 | 
			
		||||
    {
 | 
			
		||||
        # Exception for 'admin' user. FIXME - I'd rather not hardcode this,
 | 
			
		||||
        # but we can't permit email to all system users.
 | 
			
		||||
        return TRUE if $address eq 'admin';
 | 
			
		||||
        # Make sure the user exists.
 | 
			
		||||
        my $accountsdb = esmith::AccountsDB->open_ro;
 | 
			
		||||
        my $user = $accountsdb->get($address) || '';
 | 
			
		||||
        unless (($user) && ($user->prop('type') eq 'user'))
 | 
			
		||||
        {
 | 
			
		||||
            return FALSE;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return TRUE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=back
 | 
			
		||||
 | 
			
		||||
=head1 AUTHOR
 | 
			
		||||
 | 
			
		||||
Mitel Networks Corp.
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
							
								
								
									
										215
									
								
								root/usr/share/perl5/vendor_perl/esmith/util/system.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								root/usr/share/perl5/vendor_perl/esmith/util/system.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,215 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
# Copyright 1999-2003 Mitel Networks Corporation
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the same terms as Perl itself.
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
package esmith::util::system;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
require Exporter;
 | 
			
		||||
our @ISA = qw(Exporter);
 | 
			
		||||
 | 
			
		||||
our @EXPORT_OK = qw(killall rsync rsync_ssh);
 | 
			
		||||
 | 
			
		||||
=for testing
 | 
			
		||||
use_ok('esmith::util::system', 'killall', 'rsync', 'rsync_ssh');
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
esmith::util::system - replacements/wrappers for system() commands
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
  use esmith::util::system qw(killall rsync rsync_ssh);
 | 
			
		||||
 | 
			
		||||
  killall($signal, @commands);
 | 
			
		||||
  rsync($src, $dest, @options);
 | 
			
		||||
  rsync_ssh($src, $dest, $user, $ident, \@rsync_opts, \@ssh_opts);
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
This is for common functions that would normally require a system(...) 
 | 
			
		||||
command.  Makes things easier to document, test and upgrade.
 | 
			
		||||
 | 
			
		||||
If you find yourself writing a system() command, consider putting it
 | 
			
		||||
in here.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=head2 Functions
 | 
			
		||||
 | 
			
		||||
These may be pure Perl functions or they may well just be wrappers
 | 
			
		||||
around system() commands.
 | 
			
		||||
 | 
			
		||||
Each can be imported on request.
 | 
			
		||||
 | 
			
		||||
=over 4
 | 
			
		||||
 | 
			
		||||
=item B<killall>
 | 
			
		||||
 | 
			
		||||
  my $killed_something = killall($signal, @commands);
 | 
			
		||||
 | 
			
		||||
Sends a $signal to all of the named @commands.  $signal can be
 | 
			
		||||
specified by name or number (so 1 or HUP for example, names are
 | 
			
		||||
prefered).
 | 
			
		||||
 | 
			
		||||
Returns true if something was killed, false otherwise.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
open(SCRATCH, ">scratch.exe") || die $!;
 | 
			
		||||
 | 
			
		||||
# XXX Irritating perl bug ends POD processing if it sees /^#!.*perl/
 | 
			
		||||
print SCRATCH sprintf <<'ENDING', '/usr/bin/perl';
 | 
			
		||||
#!%s -w
 | 
			
		||||
 | 
			
		||||
sleep 99;
 | 
			
		||||
ENDING
 | 
			
		||||
 | 
			
		||||
close SCRATCH;
 | 
			
		||||
 | 
			
		||||
END { unlink 'scratch.exe', 'scratch.out' }
 | 
			
		||||
 | 
			
		||||
chmod 0755, 'scratch.exe' || die $!;
 | 
			
		||||
my $pid = open(SCRATCH, "./scratch.exe |");
 | 
			
		||||
ok( $pid, 'scratch program started ok' );
 | 
			
		||||
 | 
			
		||||
ok( killall('USR1', 'scratch.exe'),     'killall returned properly' );
 | 
			
		||||
close SCRATCH;  # so scratch.exe responds to the signal and exits
 | 
			
		||||
 | 
			
		||||
is( kill(9, $pid), 0,    'killall worked' );
 | 
			
		||||
 | 
			
		||||
# I can't actually think of a way to explicitly check this but it
 | 
			
		||||
# will make noise if it doesn't work.
 | 
			
		||||
ok( !killall('USR1', 'I_dont_exist_nope'), 
 | 
			
		||||
    'returned properly for killing nothing' );
 | 
			
		||||
ok( 1, 'killall is quiet when nothing is killed' );
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
sub killall {
 | 
			
		||||
    my($signal, @commands) = @_;
 | 
			
		||||
 | 
			
		||||
    warn "You don't need a - on the signal" if $signal =~ /^-/;
 | 
			
		||||
 | 
			
		||||
    my $killed_something = 
 | 
			
		||||
          system('/usr/bin/killall', '-q', "-$signal", @commands);
 | 
			
		||||
 | 
			
		||||
    return !$killed_something;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=back
 | 
			
		||||
 | 
			
		||||
=item B<rsync>
 | 
			
		||||
 | 
			
		||||
    my $success = rsync($source, $destination, @options);
 | 
			
		||||
 | 
			
		||||
rsyncs the $source file or directory to the $destination.  Any
 | 
			
		||||
@options are direct options to the rsync command.
 | 
			
		||||
 | 
			
		||||
rsync will be run --quiet by default.
 | 
			
		||||
 | 
			
		||||
Returns true if the rsync succeeds, false otherwise.
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
use File::Compare;
 | 
			
		||||
my $src  = '10e-smith-lib/db.t';
 | 
			
		||||
my $dest = '10e-smith-lib/db.t.copy';
 | 
			
		||||
rsync($src, $dest);
 | 
			
		||||
END { unlink $dest }
 | 
			
		||||
 | 
			
		||||
ok( -e $dest );
 | 
			
		||||
ok( compare($src, $dest) == 0, 'basic rsync copy' );
 | 
			
		||||
 | 
			
		||||
open(DEST, ">$dest" ) || die $!;
 | 
			
		||||
print DEST "Fooble\n";
 | 
			
		||||
close DEST;
 | 
			
		||||
 | 
			
		||||
# rsync in update-only mode.  $dest is newer than $src and shouldn't
 | 
			
		||||
# be updated.
 | 
			
		||||
rsync($src, $dest, qw(--update));
 | 
			
		||||
 | 
			
		||||
ok( compare($src, $dest) == 1,  'rsync, update only' );
 | 
			
		||||
 | 
			
		||||
open(DEST, "$dest") || die $!;
 | 
			
		||||
my $data = join '', <DEST>;
 | 
			
		||||
close DEST;
 | 
			
		||||
 | 
			
		||||
is( $data, "Fooble\n" );
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
our $RSYNC_CMD = '/usr/bin/rsync';
 | 
			
		||||
sub rsync {
 | 
			
		||||
    my($src, $dest, @options) = @_;
 | 
			
		||||
 | 
			
		||||
    push @options, '--quiet';
 | 
			
		||||
    return !system($RSYNC_CMD, @options, $src, $dest);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=item B<rsync_ssh>
 | 
			
		||||
 | 
			
		||||
    my $success = rsync_ssh($src, $dest, $user, $ident, \@rsync_opts, 
 | 
			
		||||
                                                        \@ssh_opts);
 | 
			
		||||
 | 
			
		||||
Like rsync() except it uses ssh.  A typical call might be:
 | 
			
		||||
 | 
			
		||||
    rsync_ssh('some.host:', 'some/file', 'someuser', 'some/.ssh/identity',
 | 
			
		||||
              [qw(--archive --delete)]);
 | 
			
		||||
 | 
			
		||||
=begin testing
 | 
			
		||||
 | 
			
		||||
use File::Compare;
 | 
			
		||||
my $src  = '10e-smith-lib/db.t';
 | 
			
		||||
my $dest = '10e-smith-lib/db.t.copy';
 | 
			
		||||
 | 
			
		||||
unlink $dest;
 | 
			
		||||
END { unlink $dest }
 | 
			
		||||
 | 
			
		||||
no warnings 'once';
 | 
			
		||||
my @args;
 | 
			
		||||
my $real_rsync = \&esmith::util::system::rsync;
 | 
			
		||||
local *esmith::util::system::rsync = sub {
 | 
			
		||||
    @args = @_;
 | 
			
		||||
 | 
			
		||||
    pop @_;
 | 
			
		||||
    $real_rsync->(@_);
 | 
			
		||||
};
 | 
			
		||||
        
 | 
			
		||||
rsync_ssh($src, $dest, 'someone', 'some/ident', [qw(--update)], [qw(-C)]);
 | 
			
		||||
ok( -e $dest );
 | 
			
		||||
ok( compare($src, $dest) == 0 );
 | 
			
		||||
 | 
			
		||||
is($args[0], $src );
 | 
			
		||||
is($args[1], $dest );
 | 
			
		||||
is($args[2], '--update' );
 | 
			
		||||
is($args[3], "-e $esmith::util::system::SSH_CMD -l someone -i some/ident -C");
 | 
			
		||||
 | 
			
		||||
=end testing
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
our $SSH_CMD = '/usr/bin/ssh';                
 | 
			
		||||
sub rsync_ssh {
 | 
			
		||||
    my($src, $dest, $user, $ident, $rsync_opts, $ssh_opts) = @_;
 | 
			
		||||
 | 
			
		||||
    $ssh_opts ||= [];
 | 
			
		||||
    my $ssh_opt = join ' ', ('-e', $SSH_CMD, '-l', $user, '-i', $ident, 
 | 
			
		||||
                             @$ssh_opts);
 | 
			
		||||
 | 
			
		||||
    return rsync($src, $dest, @$rsync_opts, $ssh_opt);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
=head1 AUTHOR
 | 
			
		||||
 | 
			
		||||
Mitel Networks Corporation
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
		Reference in New Issue
	
	Block a user