|
1 #! /usr/bin/perl |
|
2 # $Id$ |
|
3 # $URL$ |
|
4 my $USAGE = <<'#'; |
|
5 $ME [options] |
|
6 --[no]db insert into log database [$opt_db] |
|
7 --[no]mail send mails to @config::mailto [$opt_mail] |
|
8 --message=s message |
|
9 # |
|
10 |
|
11 use strict; |
|
12 use warnings; |
|
13 use File::Basename; |
|
14 use File::Temp qw(tempfile); |
|
15 use File::stat; |
|
16 use Getopt::Long; |
|
17 use Mail::Mailer; |
|
18 use DBI; |
|
19 |
|
20 use lib "/etc/logbuch"; |
|
21 use config; |
|
22 |
|
23 # print @config::mailto, "\n"; |
|
24 |
|
25 #+-------+---------------+------+-----+---------+----------------+ |
|
26 #| Field | Type | Null | Key | Default | Extra | |
|
27 #+-------+---------------+------+-----+---------+----------------+ |
|
28 #| id | int(11) | | MUL | NULL | auto_increment | |
|
29 #| host | varchar(255) | YES | | NULL | | |
|
30 #| date | datetime | YES | | NULL | | |
|
31 #| user | varchar(255) | YES | | NULL | | |
|
32 #| mailto| varchar(255) | YES | | NULL | | |
|
33 #| text | text | YES | MUL | NULL | | |
|
34 #| stamp | timestamp(14) | YES | | NULL | | |
|
35 #+-------+---------------+------+-----+---------+----------------+ |
|
36 |
|
37 my $ME = basename $0; |
|
38 |
|
39 my $DSN = "DBI:mysql:logbuch:pu.schlittermann.de"; |
|
40 my $USER = "logbuch"; |
|
41 my $PW = "HIDDEN"; |
|
42 |
|
43 my $LOG = "$ENV{HOME}/LOG"; |
|
44 my $EDITOR = $ENV{VISUAL} || $ENV{EDITOR} || "vim"; |
|
45 my $MAGIC = "#--- all changes below are ignored ---#\n"; |
|
46 |
|
47 my $opt_db = 1; |
|
48 my $opt_mail = 1; |
|
49 my $opt_message = ""; |
|
50 |
|
51 |
|
52 |
|
53 my $Dbh; |
|
54 |
|
55 sub identity(); |
|
56 sub hostname(); |
|
57 sub mailto(); |
|
58 |
|
59 MAIN: { |
|
60 |
|
61 GetOptions("db!" => \$opt_db, |
|
62 "mail!" => \$opt_mail, |
|
63 "message=s" => \$opt_message) |
|
64 or die eval "\"$USAGE\""; |
|
65 |
|
66 if ($opt_message =~ /^\.?\// and -f $opt_message) { |
|
67 @ARGV = ($opt_message); |
|
68 $opt_message = join "", <>; |
|
69 } elsif ($opt_message eq "-") { |
|
70 $opt_message = join "", <STDIN>; |
|
71 } |
|
72 |
|
73 if ($opt_message =~ /\n/) { |
|
74 $opt_message =~ s/\n/\n /g; |
|
75 } |
|
76 |
|
77 if ($opt_db) { |
|
78 $Dbh = DBI->connect($DSN, $USER, $PW, {RaiseError => 1}) |
|
79 or die $DBI::errstr; |
|
80 END { $Dbh->disconnect() if $Dbh; } |
|
81 } |
|
82 |
|
83 # Temporärfile öffnen |
|
84 my ($fh, $file); |
|
85 END { unlink $file if $file; } |
|
86 ($fh, $file) = tempfile(DIR => "/tmp"); |
|
87 |
|
88 # Kopftext eintragen |
|
89 print $fh |
|
90 "Date: ", scalar(localtime()), "\n", |
|
91 "User: ", identity(), "\n", |
|
92 "MailTo: ", mailto(), "\n", |
|
93 "\n", |
|
94 " * $opt_message", |
|
95 "\n", |
|
96 "\n", $MAGIC, "\n"; |
|
97 |
|
98 if (!-e $LOG) { |
|
99 open(X, $_ = ">>$LOG") or die "Can't open $_: $!\n"; |
|
100 close X; |
|
101 }; |
|
102 |
|
103 open(IN, $_ = $LOG) or die "Can't open $_: $!\n"; |
|
104 print $fh <IN>; |
|
105 close IN; |
|
106 |
|
107 if (!$opt_message) { |
|
108 my $stamp = stat($file)->mtime(); |
|
109 system($EDITOR, "+5", $file); |
|
110 |
|
111 if ($stamp == stat($file)->mtime()) { |
|
112 print STDERR "Nothing changed. Discarding the note.\n"; |
|
113 unlink $file; |
|
114 exit 0; |
|
115 } |
|
116 } |
|
117 |
|
118 # Jetzt wie versprochen den (eventuell geänderten Rest) aus der |
|
119 # Temp-Datei wegschneiden |
|
120 { |
|
121 my ($date, $user, $head, $text, $mailto); |
|
122 my $pos; |
|
123 |
|
124 seek $fh, 0, 0; |
|
125 for($pos = tell $fh; defined($_ = <$fh>); $pos = tell $fh) { |
|
126 |
|
127 $head .= "$_" if not $text and /^\S+:/; |
|
128 |
|
129 /^Date:\s+(.*)/ and $date = $1, next; |
|
130 /^User:\s+(.*)/ and $user = $1, next; |
|
131 /^MailTo:\s(.*)/ and $mailto = $1, next; |
|
132 last if $_ eq $MAGIC; |
|
133 |
|
134 $text .= $_ if /\S/ || $text; # somit werden die ersten Leerzeilen übersprungen |
|
135 } |
|
136 |
|
137 $text =~ s/\s*$//s; # Leerzeichen am Ende weg |
|
138 |
|
139 truncate $fh, $pos; |
|
140 seek $fh, 0, 2; |
|
141 |
|
142 if ($opt_db) { |
|
143 my $sth = $Dbh->prepare(" |
|
144 INSERT INTO log (host, date, user, mailto, text) |
|
145 VALUES(?, now(), ?, ?, ?)"); |
|
146 $sth->execute(hostname(), $user, $mailto, $text); |
|
147 print STDERR "Database entry inserted\n"; |
|
148 } |
|
149 |
|
150 if ($opt_mail and $mailto) { |
|
151 my $mailer = new Mail::Mailer "sendmail" |
|
152 or die "Can't create Mailer: $!\n"; |
|
153 |
|
154 my $subject = (split /\n/, $text)[0]; |
|
155 $subject =~ s/^\s*\S\s//; |
|
156 $subject = "Service [". hostname(). "]: $subject"; |
|
157 |
|
158 $mailer->open({ |
|
159 "To" => $mailto, |
|
160 "Subject" => $subject}); |
|
161 print $mailer $head, "\n", $text; |
|
162 close $mailer; |
|
163 print STDERR "Mail sent (to $mailto).\n"; |
|
164 } |
|
165 } |
|
166 |
|
167 # Und jetzt das aus der alten Datei dort anhängen |
|
168 open(IN, $_ = $LOG) or die "Can't open $_: $!\n"; |
|
169 print $fh <IN>; |
|
170 close $fh; |
|
171 close IN; |
|
172 |
|
173 rename $file, $LOG; |
|
174 |
|
175 } |
|
176 |
|
177 sub identity() |
|
178 { |
|
179 my $user = `who am i`; |
|
180 chomp $user; |
|
181 $user .= " [" . ($ENV{REMOTE_USER} || "-") . "]"; |
|
182 return $user; |
|
183 } |
|
184 |
|
185 sub hostname() |
|
186 { |
|
187 my $r = `hostname -f`; |
|
188 chomp($r); |
|
189 return $r; |
|
190 } |
|
191 |
|
192 sub mailto() |
|
193 { |
|
194 return join(", ", @config::mailto); |
|
195 } |
|
196 |
|
197 # vim:sts=4 sw=4 aw ai sm: |
|
198 |