From dbb7399cf634ebc433853bf4870789e424debf98 Mon Sep 17 00:00:00 2001 From: Damir Dzeko Date: Tue, 29 Mar 2005 17:37:13 +0000 Subject: [PATCH] r29: Almost ready for new release (cp-update) --- carnet-tools.8 | 167 +++++++++++++++++++++++ cp-update | 16 ++- cp-update.new | 410 -------------------------------------------------------- debian/install | 2 + functions.sh | 4 +- test/Makefile | 2 +- 6 files changed, 185 insertions(+), 416 deletions(-) create mode 100644 carnet-tools.8 delete mode 100755 cp-update.new diff --git a/carnet-tools.8 b/carnet-tools.8 new file mode 100644 index 0000000..8e2322b --- /dev/null +++ b/carnet-tools.8 @@ -0,0 +1,167 @@ +.\" Copied from from Pod::Man template +.\" Wed, 23 Mar 2005 11:51:08 +0100 +.\" +.\" Standard preamble: +.\" ====================================================================== +.de Sh \" Subsection heading +.br +.if t .Sp +.ne 5 +.PP +\fB\\$1\fR +.PP +.. +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Ip \" List item +.br +.ie \\n(.$>=3 .ne \\$3 +.el .ne 3 +.IP "\\$1" \\$2 +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R + +.fi +.. +.\" +.\" For nroff, turn off justification. Always turn off hyphenation; it +.\" makes way too many mistakes in technical documents. +.hy 0 +.if n .na +.\" +.IX Title "carnet-tools 8" +.TH carnet-tools 8 "March 2005" CARNet "CARNet Packaging Tools" +.SH NAME +carnet-tools \- pomocni alati za laksi zivot package maintainera +.\" +.SH PREGLED +.B . /usr/share/carnet-tools/functions.sh +.\" +.SH OPIS +Paket carnet-tools-cn sadrzi skripte i shell funkcije koje se cesto +koriste u CARNetovim paketima. To sluzi tome da se postinst skripte +pisu lakse, brze i pouzdanije temeljene na vec isprobanom kodu. Tu +su i primjeri provjerenih rjesenja za shell-skriptiranje da se nadju +pri ruci kad zatreba. +.\" +.SH FUNKCIJE +.TP +\fBcp_get_ifaddr\fR \fIinterface\fR +Funkcija vraca IP adresu mreznog sucelja. U slucaju da nije +naveden kao argument, vraca IP adresu od loopback sucelja (lo). +.TP +\fBcp_get_ifmask\fR \fIinterface\fR +Funkcija vraca IP netmask mreznog sucelja. U slucaju da nije +naveden kao argument, vraca IP netmask od loopback sucelja (lo). +.TP +\fBcp_get_ifdefault\fR [\fBdev\fR|\fBaddr\fR] +Funkcija vraca naziv uredjaj ili adresu podrazumne rute (default +route). +.TP +\fBcp_get_netaddr\fR \fIinterface\fR +Funkcija vraca podmrezu mreznog sucelja u CIDR obliku. U slucaju +da nije naveden \fIinterface\fR argument, vraca CIDR sucelja preko +kojeg ide default route, a ako isti nije definiran, vraca CIDR +loopback sucelja (lo). +.TP +\fBcp_backup_conffile\fR \fIfile\fR +Funkcija backupira datoteku u /var/backups/ direktorij. Po +potrebi rotira, ako postoje neke razlike. +.TP +\fBcp_check_and_sed\fR \fIregexp\fR \fIsed\fR \fIfile\fR [\fIfile\fR ...] +Funkcija trazi (egrep) regularni izraz \fIregexp\fR u datotekama, te ako +postoji, izvrsi sed program \fIsed\fR nad tim datotekama. Najcesce se +koristi za zamjenu stare vrijednosti postavke novom. +.TP +\fBcp_echo\fR [\fB-mailonly\fR|\fB-m\fR] \fIstring\fR +.TP +\fBcp_mail\fR [\fB-q\fR] \fIpackage\fR \fIversion\fR +U kombinaciji, ove funkcije sluze za slanje poruka na stdout \fUi\fR na +mail rootu. Koristiti za informacije koje svakako treba dostaviti +sistemcu (passwordi, nekompatibilne izmjene u konfiguraciji +kriticnih servisa), cak i ako ne cita dokumentaciju niti prati +poruke kod upgradea. :\-> +.PP +cp_echo se koristi umjesto echo. Uz \fB-m\fR salje poruku samo na mail. +cp_mail se poziva na kraju (postinsta), kad posalje mail. Bez +\fB-q\fR opcije \fBcp_mail\fR ce ispisati obavijest o slanju tog maila. +.PP +Ove dvije funkcije koriste globalnu varijablu \fBCP_NOTICE\fR u koju se +spremaju poruke za mail. +.TP +\fBcp_mv\fR \fInew-file\fR \fItarget-file\fR +Funkcija cija je namjena da novu datoteku \fInew-file\fR instalira kao +zadanu \fItarget-file\fR datoteku, koja moze i/ili ne postojati. Ako ta +datoteka postoji onda se novoj dodjeljuje njeno vlasnistvo i modovi +pristupa. Operacija je atomicna. +.PP +Funkcija \fBcp_safe_file_replace\fR je prikladna za koristenje kod raznih +sed-like izmjena neke postojece datoteke iako se za samo sed-anje +preporuca koristiti funkciju \fBcp_check_and_sed\fR. +.TP +\fBcp_yes_no\fR [\fIprompt\fR] +Funkcija za jednostavni \fUy\fRes/\fUn\fRo dijalog. Odgovor '\fBy\fR' | '\fBn\fR' +vraca u RET. Valja napomenuti da je kao i sve ostalo sto koristi stdin/stdout +nekompatibilan s debconfom (doticnog treba ugasiti prvo). +.TP +\fBcp_db_get_wrap\fR \fIpackage\fR\fB/\fR\fIvariable\fR +Wrapper za debconfovu funkciju db_get koji umjesto neke neocekivane +greske vrati prazni \fBRET\fR. Kome treba greska neka ga ne koristi. +.PP +Funkcije cije ime pocinje sa \fBcp_get_\fR pohranjuju rezultat u varijabli \fB$RET\fR, +a one s prefiksom cp_check_ kao rezultat vracaju exit status. U pozivnoj +skripti se mogu definirati sljedece varijable koje utjecu na rad svih +pomocnih funkcija: + +.SH PRIMJER +Poziv \fBcp_get_\fRxxx funkcije i preuzimanje rezultata: +.Sp +.Vb 4 +\& . /usr/share/carnet-tools/functions.sh +\& +\& cp_get_ifaddr ppp0 +\& addr="$RET" +.Ve +Poziv \fBcp_check_\fRxxx funkcije i nastavak toka programa: +.Sp +.Vb 6 +\& . /usr/share/carnet-tools/functions.sh +\& +\& if ! cp_check_and_sed watter 's/watter/ice/' \\ +\& /dev/fridge; then +\& cp_echo "Clean the /dev/fridge!" +\& fi +.Ve +.\" +.SH ENVIRONMENT +\fBCP_ECHO_RETURN\fR - kontrola nacina povrata vrijednosti +.br +.PP +\fBCP_SCRIPT_DEBUG\fR - potpomaze debugiranje (set -vx) +.br +.PP +\fBCP_NOTICE\fR - tijelo poruke koja se salje na mail +.br +.PP +\fBRET\fR - povrat vrijednosti iz \fBcp_get_\fRxxx funkcija +.\" +.SH DATOTEKE +Ne koriste se nikakve posebne datoteke. +.\" +.SH BUGOVI +Nema poznatih. +.\" +.SH AUTORI +Ivan 'ico' Rako, Zoran Dzelajlija, Damir Dzeko. SRCE . +.\" +.SH "VEZANO" +.BR cp-update(1) +.\" End diff --git a/cp-update b/cp-update index 6491c78..2207c40 100755 --- a/cp-update +++ b/cp-update @@ -311,6 +311,8 @@ sub del() { my ($mytrailer, $mybegin, $myend) = ($Trailer, $MarkBegin, $MarkEnd); + my ($bm_found, $em_found); # begin/end mark found indicator + # Make the strings regexp-friendly by quoting non-word chars. $mybegin =~ s/\W/\\$&/g; $myend =~ s/\W/\\$&/g; @@ -320,9 +322,19 @@ sub del() { foreach (@Lines) { push (@filtered, $_) unless (/^$mybegin(?:$mytrailer)?$/o .. /^$myend(?:$mytrailer)?$/o); + + # for safety check: + $bm_found = 1 if (/^$mybegin(?:$mytrailer)?$/o); + $em_found = 1 if (/^$myend(?:$mytrailer)?$/o); + } + if ($bm_found and $em_found) { + DEBUG and print STDERR "Deleted ". (@Lines - @filtered) ." out of ".scalar(@Lines)." lines\n"; + @Lines = @filtered; + } + elsif ($bm_found and ! $em_found) { + # safety exit + die "$ProgramName: no end-mark after begin-mark!\n"; } - DEBUG and print STDERR "Deleted ". (@Lines - @filtered) ." out of ".scalar(@Lines)." lines\n"; - @Lines = @filtered; return scalar(@Lines); # whatever } diff --git a/cp-update.new b/cp-update.new deleted file mode 100755 index 56517a0..0000000 --- a/cp-update.new +++ /dev/null @@ -1,410 +0,0 @@ -#! /usr/bin/perl -w - -## Copyright (C) 1998 Hrvoje Niksic -## Modification by Zeljko Boros (block entries, removing old entries) -## More options and use strict by Zoran Dzelajlija on 2004-02-24 -## -## 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., 675 Mass Ave, Cambridge, MA 02139, USA. - -## altered by ddzeko, 2005-03-18 -## -> reformated code, introduced coding conventions -## -> increased reliability through atomic actualization -## -> everything is done in the memory - more mem, less i/o -## -> removed append mode - in-place editing considered harmfull -## -> added in-place mode as option - -use strict; -use Fcntl qw(:DEFAULT :flock :seek); - -sub DEBUG () { 0 }; - -# coding convention: CamelCase vars are global here -# -my ($ProgramName, $UsageLong, $UsageShort); - -# Looks nicer without the slashes and dots -($ProgramName = $0) =~ s!.*/!!; # strip dir -$ProgramName =~ s!\.[^.]+$!!; # strip last ext - -# 34567890 34567890 34567890 34567890 34567890 34567890 34567890 345678 - -$UsageLong = " - $ProgramName -- versatile line-based file updating tool - usually used by package configuration scripts - - Usage: $ProgramName [options] PACKAGE FILE < stdin-content - - - - General options: - - -r | --remove Remove entry PACKAGE from FILE. - Default is to add lines from stdin. - - -m | --allow-multiple Allow multiple blocks of the same type. - By default, old blocks are replaced with - the new one. - - -h | --help Print this message. - - - Placement control: - - -t | --insert-on-top Insert stdin-content block on top. - The default is to add it at the bottom. - - -i | --insert-after x Insert after this/matching line. - -f | --insert-before x Insert before this/matching line. - -R | --regexp-match Use regexp mode for line matching. - - - Manipulating block marks: - - -c | --comment x Use alternative comment char/string. - The default is shell-style \#-sign. - - --comment-end x Use this marker for comment ending. - The default is none. Ie. '-->', '*/'. - - -b | --begin-mark x Block starting mark (ie. 'service ftp') - -e | --end-mark x Block ending mark (ie. '}') - - These will delete to the end of the file if no end mark - is found. The deletion is otherwise not greedy and stops - at the first end mark found. You can use \%P to insert - the PACKAGE argument, and \%\% to insert a literal \% sign - into the mark. - - - File handling options: - - -p | --in-place Try to preserve original inode. - -n | --no-close Do not close and reopen file when - editing it in place. - - Options marked with 'x' take single argument. Others do not. - -\n"; - -$UsageShort = "$ProgramName -- versatile line-based file updating tool\n"; -$UsageShort .= " Options: [-r] [-m] [-i AFTER|-f BEFORE|-t] [-b START -e STOP] [-c CHAR] PACKAGE FILE\n"; -$UsageShort .= " or type $ProgramName --help to be choked with help.\n"; - -my ($MarkBegin, $MarkEnd, $Trailer, $ParamBegin, $ParamEnd, $Placement, - $Package, $File, $Block, $Multi, $InsertRemove, $Comment, $CommentEnd, - $MatchLine, $RegexpMatch, $StdinContent, $NewContent, $InPlace, - $NoClose, $FileHandle, @Lines); - -# Placement modes -use constant APPEND_AT_END => 0; -use constant INSERT_BEFORE => 1; -use constant INSERT_AFTER => 2; -use constant INSERT_ON_TOP => 3; - -# InsertRemove modes -use constant DO_REMOVE => 0; -use constant DO_INSERT => 1; - -# Operation defaults -$InsertRemove = DO_INSERT; -$Placement = APPEND_AT_END; -$Comment = '#'; -$CommentEnd = ''; -$MatchLine = ''; -$InPlace = 0; -$NoClose = 0; - -while (@ARGV) { - $_ = shift; - if (/^-c$/ || /^--comment$/) { - defined ($Comment = shift) - || die "$ProgramName: `-c|--comment' must be followed by an argument\n"; - } - elsif (/^--comment-end$/) { - defined ($CommentEnd = shift) - || die "$ProgramName: `--comment-end' must be followed by an argument\n"; - } - elsif (/^-r$/ || /^--remove$/) { - $InsertRemove = DO_REMOVE; - } - elsif (/^-m$/ || /^--allow-multi(?:ple)?$/) { - $Multi = 1; - } - elsif (/^-b$/ || /^--begin(?:-mark)?$/) { - defined ($ParamBegin = shift) - || die "$ProgramName: '-b|--begin-mark' must be followed by an argument\n"; - $Block = 1; - } - elsif (/^-e$/ || /^--end(?:-mark)?$/) { - defined ($ParamEnd = shift) - || die "$ProgramName: '-e|--end-mark' must be followed by an argument\n"; - $Block = 1; - } - elsif (/^-i$/ || /^--insert-after$/) { - defined($MatchLine = shift) - || die "$ProgramName: '-i|--insert-after' must be followed by an argument\n"; - $Placement = INSERT_AFTER; - } - elsif (/^-f$/ || /^--insert-before$/) { - defined($MatchLine = shift) - || die "$ProgramName: '-f|--insert-before' must be followed by an argument\n"; - $Placement = INSERT_BEFORE; - } - elsif (/^-t$/ || /^--insert-on-top$/) { - $Placement = INSERT_ON_TOP; - } - elsif (/^-R$/ || /^--regexp(?:-match|-mode)?$/) { - $RegexpMatch = 1; - } - elsif (/^-h$/ || /^--help$/) { - die $UsageLong; - } - elsif (/^-p$/ || /^--in-place$/) { - $InPlace = 1; - } - elsif (/^-n$/ || /^--no-close$/) { - $NoClose = 1; - } - elsif (/^-/) { - die "$ProgramName: Unrecognized option \`$_'\n"; - } - else { - unshift(@ARGV, $_); - last; - } -} - -$Package = shift or die $UsageShort; -$File = shift or die $UsageShort; - -# prepare block begin and end marks -# -(! $Block || ($ParamBegin && $ParamEnd)) - or die ("$ProgramName: must provide both begin and end marks.\n"); -# -if ($Block) { - $ParamBegin =~ s, %P , $Package ,gx; - $ParamBegin =~ s, %% , % ,gx; - $ParamEnd =~ s, %P , $Package ,gx; - $ParamEnd =~ s, %% , % ,gx; - $MarkBegin = $ParamBegin; - $MarkEnd = $ParamEnd; - $Trailer = ''; -} else { - $MarkBegin = "$Comment Begin update by CARNet package $Package"; - $MarkEnd = "$Comment End update by CARNet package $Package"; - $Trailer = " -- DO NOT DELETE THIS LINE!".$CommentEnd; -} - -DEBUG and print STDERR "MarkBegin='$MarkBegin'\nMarkEnd='$MarkEnd'\nTrailer='$Trailer'\n"; - -# compile regexp if provided -# -if ($RegexpMatch) { - # compile user's regexp - eval { $MatchLine = qr<$MatchLine> }; -} -else { - # we'll do regexp matching anyway :) - # just not with user's specials interfering - eval { $MatchLine = qr<^\Q$MatchLine\E>o; }; -} -if ($@) { - die "$ProgramName: regexp compilation failed: $@ ($!)\n"; -} - -do_it() and exit(0); - - -# main procedure -# -------------- - -sub do_it { - slurp(); - if (DO_INSERT == $InsertRemove) { - $StdinContent = &stdin_content; - del() unless $Multi; - add(); - } - else { - del(); - } - actualize(); -} - - -# subroutines -# ----------- - -sub slurp() { - sysopen($FileHandle, $File, O_RDWR) or die "$ProgramName: Cannot open $File: $!\n"; - @Lines = <$FileHandle>; # slurp the whole file as lines - close($FileHandle) unless ($InPlace && $NoClose); - - # If FILE does not have a trailing newline, be sure to add it - # before appending anything else. - - if (@Lines and $Lines[$#Lines] !~ m/\n$/s) { - $Lines[$#Lines] .= "\n"; - } -} - -sub add() { - if (APPEND_AT_END == $Placement) { - # append stuff at the end of the file - push(@Lines, $StdinContent); - } - elsif (INSERT_ON_TOP == $Placement) { - # throw the stuff on top of the file - unshift(@Lines, $StdinContent); - } - else { - # insert stuff where needed - my ($line, $lineNo, $added); - $lineNo = 0; - $added = 0; - foreach $line (@Lines) { - DEBUG and print STDERR "at: $line"; - if ($line =~ m/$MatchLine/) { - DEBUG and print STDERR " - MATCH\n"; - if (INSERT_AFTER == $Placement) { - DEBUG and print STDERR " - INSERT_AFTER\n"; - splice(@Lines, $lineNo + 1, 0, $StdinContent); - } - elsif (INSERT_BEFORE == $Placement) { - DEBUG and print STDERR " - INSERT_BEFORE\n"; - splice(@Lines, $lineNo, 0, $StdinContent); - } - # once added and we're done - $added = 1; - last; - } - ++ $lineNo; - } - if (! $added) { - warn "$ProgramName: Inserting lines at the end implicitly!\n"; - push(@Lines, $StdinContent); - } - } - return scalar(@Lines); # whatever -} - -sub del() { - my ($mytrailer, $mybegin, $myend) = - ($Trailer, $MarkBegin, $MarkEnd); - - # Make the strings regexp-friendly by quoting non-word chars. - $mybegin =~ s/\W/\\$&/g; - $myend =~ s/\W/\\$&/g; - $mytrailer =~ s/\W/\\$&/g; - - my (@filtered); - foreach (@Lines) { - push (@filtered, $_) - unless (/^$mybegin(?:$mytrailer)?$/o .. /^$myend(?:$mytrailer)?$/o); - } - DEBUG and print STDERR "Deleted ". (@Lines - @filtered) ." out of ".scalar(@Lines)." lines\n"; - @Lines = @filtered; - return scalar(@Lines); # whatever -} - -# written by ddzeko@srce.hr, 2005-03-18 -# to improve reliabilitah :) -# -sub actualize() { - # put it all thogether - my $newContent = join('', @Lines); - - unless (length($newContent)) { - # safety exit in last second :) - die "$ProgramName: New content empty -- aborting file alteration!\n"; - } - - if ($InPlace) { - # Provdided as means of changing the file content - # and keeping it's inode number still. - # ------------------------------------------------------- - # this is dangerous since it can leave file in bad state - # do not use this for highly critical files (ie. inittab) - # ------------------------------------------------------- - # (REVISIT: add File::Copy call to back-up the file so - # we can at least try undoing the file content change) - # backup_copy(); - unless (fileno($FileHandle)) { - sysopen($FileHandle, $File, O_WRONLY|O_TRUNC) - or die "$ProgramName: Failed to open file '$File' for writing ($!)\n"; - } - else { - sysseek(*$FileHandle, 0, SEEK_SET) - or die "$ProgramName: Failed to seek to the begining of file ($!)\n"; - } - my $wb = syswrite($FileHandle, $newContent); - if (! $wb or length($newContent) != $wb) { - # FIXME: try restoring backup copy - die "$ProgramName: Failed to write the content to '$File' ($!)\n"; - } - if ($NoClose) { - # this could be handy for files that had stuff appended - # at the end of the file - truncate($FileHandle, length($newContent)) - or die "$ProgramName: Failed to truncate the file ($!)\n"; - } - close($FileHandle); - } - else { - my ($file_new, $file_old) = ($File, $File); - $file_new .= '.cp-update.new'; # our .new file - $file_old .= '.cp-update.old'; # our .old file - # write content in new file in single write op - sysopen ($FileHandle, $file_new, O_CREAT|O_TRUNC|O_WRONLY) - or die "$ProgramName: Failed to open file '$File' for writing ($!)\n"; - my $wb = syswrite($FileHandle, $newContent); - if (! $wb or length($newContent) != $wb) { - unlink($file_new); - die "$ProgramName: Failed to write the content to '$File' ($!)\n"; - } - close($FileHandle); - # do the moving (should be atomic) - rename($File, $file_old) - or die "$ProgramName: Failed to rename file '$File' to '$file_old' ($!)\n"; - rename($file_new, $File) - or die "$ProgramName: Failed to rename file '$file_new' to '$File' ($!)\n"; - unlink($file_old) - or warn "$ProgramName: Failed to remove file '$file_old' ($!)\n"; - } -} - -# return content from standard input -sub stdin_content() { - my ($stdin_content) = join('', ); - unless (length($stdin_content)) { - die "$ProgramName: No stdin-content provided!\n"; - } - if ($stdin_content !~ m/\n$/s) { - # add trailing newline - $stdin_content .= "\n"; - } - - my ($mytrailer, $mybegin, $myend) = - ($Trailer, $MarkBegin, $MarkEnd); - - $mytrailer .= "\n"; - $mybegin .= $mytrailer; - $myend .= $mytrailer; - - $stdin_content = ($mybegin . $stdin_content . $myend); - return $stdin_content; -} - -# create backup copy of altered file -sub backup_copy() { - die "$ProgramName: backup_copy() not implemented"; -} diff --git a/debian/install b/debian/install index 1cc8436..4adcb40 100644 --- a/debian/install +++ b/debian/install @@ -1,2 +1,4 @@ functions.sh usr/share/carnet-tools cp-update usr/sbin +cp-update.1 usr/share/man/man1 +carnet-tools.8 usr/share/man/man8 diff --git a/functions.sh b/functions.sh index f3124da..3141959 100644 --- a/functions.sh +++ b/functions.sh @@ -179,9 +179,7 @@ cp_check_and_sed() { for i in "$@" do [ -e "$i" ] || continue - if egrep -q "$s" "$i"; then - continue - fi + egrep -q "$s" "$i" || continue [ -h "$i" ] && i=$(readlink -f "$i") sed "$sedcmd" "$i" > "$i.dpkg-tmp" if ! cmp -s "$i" "$i.dpkg-tmp" 2>&1 >/dev/null; then diff --git a/test/Makefile b/test/Makefile index a873b7e..5c19de1 100644 --- a/test/Makefile +++ b/test/Makefile @@ -4,7 +4,7 @@ # Created by: ddzeko@srce.hr, 2005-03-20 # path to cp-update script -CPUPDATE=../cp-update.new +CPUPDATE=../cp-update tests: test0 test1 test2 test3 test4 test5 test6 @echo "All tests completed successfully" -- 1.7.10.4