Matthias Andreas Benkard | b382b10 | 2021-01-02 15:32:21 +0100 | [diff] [blame] | 1 | #!/usr/bin/perl |
| 2 | |
| 3 | use DBI; |
| 4 | use LockFile::Simple qw(lock trylock unlock); |
| 5 | use Proc::ProcessTable; |
| 6 | use Data::Dumper qw(Dumper); |
| 7 | use IPC::Run 'run'; |
| 8 | use File::Temp; |
| 9 | use Try::Tiny; |
| 10 | use sigtrap 'handler' => \&sig_handler, qw(INT TERM KILL QUIT); |
| 11 | |
| 12 | sub trim { my $s = shift; $s =~ s/^\s+|\s+$//g; return $s }; |
| 13 | my $t = Proc::ProcessTable->new; |
| 14 | my $imapsync_running = grep { $_->{cmndline} =~ /imapsync\s/i } @{$t->table}; |
| 15 | if ($imapsync_running ge 1) |
| 16 | { |
| 17 | print "imapsync is active, exiting..."; |
| 18 | exit; |
| 19 | } |
| 20 | |
| 21 | sub qqw($) { |
| 22 | my @params = (); |
| 23 | my @values = split(/(?=--)/, $_[0]); |
| 24 | foreach my $val (@values) { |
| 25 | my @tmpparam = split(/ /, $val, 2); |
| 26 | foreach my $tmpval (@tmpparam) { |
| 27 | if ($tmpval ne '') { |
| 28 | push @params, $tmpval; |
| 29 | } |
| 30 | } |
| 31 | } |
| 32 | foreach my $val (@params) { |
| 33 | $val=trim($val); |
| 34 | } |
| 35 | return @params; |
| 36 | } |
| 37 | |
| 38 | $run_dir="/tmp"; |
Matthias Andreas Benkard | 7b2a3a1 | 2021-08-16 10:57:25 +0200 | [diff] [blame] | 39 | $dsn = 'DBI:mysql:database=' . $ENV{'DBNAME'} . ';mysql_socket=/var/run/mysqld/mysqld.sock'; |
Matthias Andreas Benkard | b382b10 | 2021-01-02 15:32:21 +0100 | [diff] [blame] | 40 | $lock_file = $run_dir . "/imapsync_busy"; |
| 41 | $lockmgr = LockFile::Simple->make(-autoclean => 1, -max => 1); |
| 42 | $lockmgr->lock($lock_file) || die "can't lock ${lock_file}"; |
Matthias Andreas Benkard | 7b2a3a1 | 2021-08-16 10:57:25 +0200 | [diff] [blame] | 43 | $dbh = DBI->connect($dsn, $ENV{'DBUSER'}, $ENV{'DBPASS'}, { |
Matthias Andreas Benkard | b382b10 | 2021-01-02 15:32:21 +0100 | [diff] [blame] | 44 | mysql_auto_reconnect => 1, |
| 45 | mysql_enable_utf8mb4 => 1 |
| 46 | }); |
| 47 | $dbh->do("UPDATE imapsync SET is_running = 0"); |
| 48 | |
| 49 | sub sig_handler { |
| 50 | # Send die to force exception in "run" |
| 51 | die "sig_handler received signal, preparing to exit...\n"; |
| 52 | }; |
| 53 | |
| 54 | open my $file, '<', "/etc/sogo/sieve.creds"; |
| 55 | my $creds = <$file>; |
| 56 | close $file; |
| 57 | my ($master_user, $master_pass) = split /:/, $creds; |
| 58 | my $sth = $dbh->prepare("SELECT id, |
| 59 | user1, |
| 60 | user2, |
| 61 | host1, |
| 62 | authmech1, |
| 63 | password1, |
| 64 | exclude, |
| 65 | port1, |
| 66 | enc1, |
| 67 | delete2duplicates, |
| 68 | maxage, |
| 69 | subfolder2, |
| 70 | delete1, |
| 71 | delete2, |
| 72 | automap, |
| 73 | skipcrossduplicates, |
| 74 | maxbytespersecond, |
| 75 | custom_params, |
| 76 | subscribeall, |
| 77 | timeout1, |
| 78 | timeout2 |
| 79 | FROM imapsync |
| 80 | WHERE active = 1 |
| 81 | AND is_running = 0 |
| 82 | AND ( |
| 83 | UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(last_run) > mins_interval * 60 |
| 84 | OR |
| 85 | last_run IS NULL) |
| 86 | ORDER BY last_run"); |
| 87 | |
| 88 | $sth->execute(); |
| 89 | my $row; |
| 90 | |
| 91 | while ($row = $sth->fetchrow_arrayref()) { |
| 92 | |
| 93 | $id = @$row[0]; |
| 94 | $user1 = @$row[1]; |
| 95 | $user2 = @$row[2]; |
| 96 | $host1 = @$row[3]; |
| 97 | $authmech1 = @$row[4]; |
| 98 | $password1 = @$row[5]; |
| 99 | $exclude = @$row[6]; |
| 100 | $port1 = @$row[7]; |
| 101 | $enc1 = @$row[8]; |
| 102 | $delete2duplicates = @$row[9]; |
| 103 | $maxage = @$row[10]; |
| 104 | $subfolder2 = @$row[11]; |
| 105 | $delete1 = @$row[12]; |
| 106 | $delete2 = @$row[13]; |
| 107 | $automap = @$row[14]; |
| 108 | $skipcrossduplicates = @$row[15]; |
| 109 | $maxbytespersecond = @$row[16]; |
| 110 | $custom_params = @$row[17]; |
| 111 | $subscribeall = @$row[18]; |
| 112 | $timeout1 = @$row[19]; |
| 113 | $timeout2 = @$row[20]; |
| 114 | |
| 115 | if ($enc1 eq "TLS") { $enc1 = "--tls1"; } elsif ($enc1 eq "SSL") { $enc1 = "--ssl1"; } else { undef $enc1; } |
| 116 | |
| 117 | my $template = $run_dir . '/imapsync.XXXXXXX'; |
| 118 | my $passfile1 = File::Temp->new(TEMPLATE => $template); |
| 119 | my $passfile2 = File::Temp->new(TEMPLATE => $template); |
| 120 | |
| 121 | print $passfile1 "$password1\n"; |
| 122 | print $passfile2 trim($master_pass) . "\n"; |
| 123 | |
| 124 | my @custom_params_a = qqw($custom_params); |
| 125 | my $custom_params_ref = \@custom_params_a; |
| 126 | |
| 127 | my $generated_cmds = [ "/usr/local/bin/imapsync", |
| 128 | "--tmpdir", "/tmp", |
| 129 | "--nofoldersizes", |
Matthias Andreas Benkard | 7b2a3a1 | 2021-08-16 10:57:25 +0200 | [diff] [blame] | 130 | "--addheader", |
Matthias Andreas Benkard | b382b10 | 2021-01-02 15:32:21 +0100 | [diff] [blame] | 131 | ($timeout1 gt "0" ? () : ('--timeout1', $timeout1)), |
| 132 | ($timeout2 gt "0" ? () : ('--timeout2', $timeout2)), |
| 133 | ($exclude eq "" ? () : ("--exclude", $exclude)), |
| 134 | ($subfolder2 eq "" ? () : ('--subfolder2', $subfolder2)), |
| 135 | ($maxage eq "0" ? () : ('--maxage', $maxage)), |
| 136 | ($maxbytespersecond eq "0" ? () : ('--maxbytespersecond', $maxbytespersecond)), |
| 137 | ($delete2duplicates ne "1" ? () : ('--delete2duplicates')), |
| 138 | ($subscribeall ne "1" ? () : ('--subscribeall')), |
| 139 | ($delete1 ne "1" ? () : ('--delete')), |
| 140 | ($delete2 ne "1" ? () : ('--delete2')), |
| 141 | ($automap ne "1" ? () : ('--automap')), |
| 142 | ($skipcrossduplicates ne "1" ? () : ('--skipcrossduplicates')), |
| 143 | (!defined($enc1) ? () : ($enc1)), |
| 144 | "--host1", $host1, |
| 145 | "--user1", $user1, |
| 146 | "--passfile1", $passfile1->filename, |
| 147 | "--port1", $port1, |
| 148 | "--host2", "localhost", |
| 149 | "--user2", $user2 . '*' . trim($master_user), |
| 150 | "--passfile2", $passfile2->filename, |
| 151 | '--no-modulesversion', |
| 152 | '--noreleasecheck']; |
| 153 | |
| 154 | try { |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 155 | $is_running = $dbh->prepare("UPDATE imapsync SET is_running = 1, success = NULL, exit_status = NULL WHERE id = ?"); |
Matthias Andreas Benkard | b382b10 | 2021-01-02 15:32:21 +0100 | [diff] [blame] | 156 | $is_running->bind_param( 1, ${id} ); |
| 157 | $is_running->execute(); |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 158 | |
Matthias Andreas Benkard | b382b10 | 2021-01-02 15:32:21 +0100 | [diff] [blame] | 159 | run [@$generated_cmds, @$custom_params_ref], '&>', \my $stdout; |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 160 | |
| 161 | # check exit code and status |
| 162 | ($exit_code, $exit_status) = ($stdout =~ m/Exiting\swith\sreturn\svalue\s(\d+)\s\(([^:)]+)/); |
| 163 | |
| 164 | $success = 0; |
| 165 | if (defined $exit_code && $exit_code == 0) { |
| 166 | $success = 1; |
| 167 | } |
| 168 | |
| 169 | $update = $dbh->prepare("UPDATE imapsync SET returned_text = ?, success = ?, exit_status = ? WHERE id = ?"); |
Matthias Andreas Benkard | b382b10 | 2021-01-02 15:32:21 +0100 | [diff] [blame] | 170 | $update->bind_param( 1, ${stdout} ); |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 171 | $update->bind_param( 2, ${success} ); |
| 172 | $update->bind_param( 3, ${exit_status} ); |
| 173 | $update->bind_param( 4, ${id} ); |
Matthias Andreas Benkard | b382b10 | 2021-01-02 15:32:21 +0100 | [diff] [blame] | 174 | $update->execute(); |
| 175 | } catch { |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 176 | $update = $dbh->prepare("UPDATE imapsync SET returned_text = 'Could not start or finish imapsync', success = 0 WHERE id = ?"); |
Matthias Andreas Benkard | b382b10 | 2021-01-02 15:32:21 +0100 | [diff] [blame] | 177 | $update->bind_param( 1, ${id} ); |
| 178 | $update->execute(); |
| 179 | } finally { |
| 180 | $update = $dbh->prepare("UPDATE imapsync SET last_run = NOW(), is_running = 0 WHERE id = ?"); |
| 181 | $update->bind_param( 1, ${id} ); |
| 182 | $update->execute(); |
| 183 | }; |
| 184 | |
| 185 | |
| 186 | } |
| 187 | |
| 188 | $sth->finish(); |
| 189 | $dbh->disconnect(); |
| 190 | |
| 191 | $lockmgr->unlock($lock_file); |