#!/usr/local/bin/perl # Copyright (C) 1995, 1996 Ikuo Nakagawa. # Copyright (C) 1999 Masatoshi Tsuchiya. # Author: Ikuo Nakagawa # Tsuchiya Masatoshi # Version: $Id: rotate.perl,v 1.2 2002/08/03 00:15:37 tsuchiya Exp $ # rotate.perl is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # rotate.perl 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 GNU Emacs; see the file COPYING. If not, write to # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. require 5.000; use strict; use vars qw/ $CYCLE $DEBUG $VERBOSE $OWNER $GROUP $MODE $GZIP $COMPRESS $ZCMD @TARGET /; # Customize variables $CYCLE = 6; $DEBUG = 0; $VERBOSE = 0; $OWNER = -1; $GROUP = -1; $MODE = 0644; $GZIP = '/bin/gzip'; $COMPRESS = '/usr/bin/compress'; # Analyze options while( $_ = shift @ARGV ){ if( /^-(v|-verbose)$/ ){ $VERBOSE = 1; } elsif( /^-(n|-debug)$/ ){ $DEBUG = 1; $VERBOSE = 1; } elsif( /^-(c|-cycle)$/ ){ $CYCLE = shift @ARGV; die "Illegal level is spcified: $CYCLE\n" if $CYCLE =~ /\D/; } elsif( /^-(m|-mode)$/ ){ my $m = shift @ARGV; die "Illegal mode is spcified: $m\n" if $m =~ /\D/; $m =~ s/^([^0])/0$1/; $MODE = eval $m; } elsif( /^-(z|-gzip)$/ ){ $ZCMD = $GZIP; } elsif( /^-(Z|-compress)$/ ){ $ZCMD = $COMPRESS; } elsif( /^-(o|-owner|u|-uid)$/ ){ $OWNER = &getuid( shift @ARGV ); } elsif( /^-(g|-group|-gid)$/ ){ $GROUP = &getgid( shift @ARGV ); } elsif( /^-(V|-version)$/ ){ &version; } elsif( /^-(\?|h|-help)$/ ){ &usage; } elsif( /^-/ ){ die "Illegal option: $_\n"; } else { s/\\-/-/g; push( @TARGET, $_ ); } } &usage unless @TARGET; if(( $OWNER < 0 )||( $GROUP < 0 )){ my( $name,$paswd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell ) = getpwnam( $ENV{'USER'} ); $OWNER = $uid if $OWNER < 0; $GROUP = $gid if $GROUP < 0; } grep( &rotate($_), @TARGET ); exit 0; sub rotate { my( $target ) = @_; my( $i, $j ); &debug( "rotate($target)" ); &unlink( "$target.$CYCLE" ); &unlink( "$target.$CYCLE.gz" ); &unlink( "$target.$CYCLE.Z" ); for( $i=$CYCLE-1; $i>=0; $i-- ){ $j = $i+1; &compress( "$target.$i" ); &rename( "$target.$i", "$target.$j" ); &rename( "$target.$i.gz", "$target.$j.gz" ); &rename( "$target.$i.Z", "$target.$j.Z" ); } &rename( $target, "$target.0" ); &touch( $target ); &chown( $OWNER, $GROUP, $target ); &chmod( $MODE, $target ); } sub touch { my( $file ) = @_; &debug( "touch($file)" ); unless( $DEBUG ){ open( FILE, ">> $file" ) or die "Can't touch file: file=$file, reason=$!\n"; close FILE or die "Can't close file: file=$file, reason=$!\n"; } } sub chown { my( $uid, $gid, $file ) = @_; &debug( "chown($uid,$gid,$file)" ); unless( $DEBUG ){ chown $uid, $gid, $file or die "Can't change owner: uid=$uid, gid=$gid, file=$file, reason=$!\n"; } } sub chmod { my( $mode, $file ) = @_; &debug( "chmod($mode,$file)" ); unless( $DEBUG ){ chmod $mode, $file or die "Can't change mode: mode=$mode, file=$file, reason=$!\n"; } } sub unlink { my( $file ) = @_; if( -e $file ){ &debug( "unlink($file)" ); unless( $DEBUG ){ unlink( $file ) or die "Can't unlink file: file=$file, reason=$!\n"; } } } sub rename { my( $old, $new ) = @_; if( -e $old ){ &debug( "rename($old,$new)" ); unless( $DEBUG ){ rename( $old, $new ) or die "Can't change file name: old=$old, new=$new, reason=$!\n"; } } } sub compress { my( $file ) = @_; if( -x $ZCMD && -e $file && ! -z $file ){ &debug( "compress($file)" ); unless( $DEBUG ){ system $ZCMD, $file; warn "Process returns non-zero value: command=$ZCMD, file=$file, value=$?, reason=$!\n" if $?; } } } sub getuid { my( $user ) = @_; &debug( "getuid($user)" ); if( $user =~ /\D/ ){ my( $name,$paswd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell ) = getpwnam( $user ); die "Can't get UID of \"$user\"\n" if $name ne $user; $user = $uid; } $user; } sub getgid { my( $group ) = @_; &debug( "getgid($group)" ); if( $group =~ /\D+/ ){ my( $name,$passwd,$gid,$members ) = getgrnam( $group ); die "Can't get GID of \"$group\"\n" if $name ne $group; $group = $gid; } $group; } sub debug { print map( "$_\n", @_ ) if $VERBOSE; } sub version { printf( "%s %d.%02d\n", ( $0 =~ m!/([^/]+)$! ), ( q$Revision: 1.2 $ =~ /(\d+)\.(\d+)/ ) ); exit 0; } sub usage { my( $program ) = ( $0 =~ m!/([^/]+)$! ); print STDERR <<"__USAGE__"; Usage: $program [OPTION]... [FILE]... Options: -m, --mode MODE chmod log files to MODE -o, --owner, -u, --uid USER chown log files to USER -g, --group, --gid GROUP chgrp log files to GROUP -c, --cycle CYCLE Save cycle versions of the logfile. (default: 6) -z, --gzip Compress log files with gzip -Z, --compress Compress log files with compress -v, --verbose Verbosely print commands. -n, --debug Don't actually run any commands; just print them. -V, --version Display version number __USAGE__ exit 1; }