#!/usr/bin/perl -w # Aenderungen bitte an mich weitergeben! # Autor : Tjabo Kloppenburg # Datum : 26. Oktober 1999 # System: Suse Linux 6.2 auf x86 # Idee : Man kann sich per Mail, oder in der Console, auf Termine, # Feiertage und Geburtstage hinweisen lassen. #1.1f: # - Ueblen Fehler in Berechnung der Wochentlichen Termine beseitigt! #1.1e: # - Ausgabeformat (Einruecken) nun mit Variablen anpassbar # - Wochentage werden angezeigt! # - Monatsnamen bei xx.-Terminen. # - Neue Vorgehensweise beim Ausrichten der Zeilen: # LFill("Im Oktober",16," "); # 1999c Monatsnamen werden bei xx.-Datums angegeben # 1999b Bug beseitigt: Bei Termine: xx.11.1999 # SCHNELLSTART: # 1. Das Script ausfhrbar machen: # chmod 700 termine # # 2. Die Install-Hilfe anzeigen: # ./termine -i # ENDE DER DOKU. # --------------------------------------------------------------------- # Hier faengt das Script an: use strict; my $version = "1.1f"; # ---------------------------------------------------------------------- # Moegliche Probleme -- und wie man sie beseitigt: # # 1. Probleme mit dem Auslesen des Systemdatums: # Dieses Script verwendet das Systemtool "date", um das Datum zu # ermitteln. Wenn das auf dem Zielsystem nicht hinhaut, kann man # im folgenden Block das "chomp($date =ate "+%d:%m:%Y");" ersetzen # durch etwas besseres, dass in "$date" das Datum in der Form # "TT:MM:JJJJ" hinterl„sst. # # 2. Homeverzeichnis: # M÷glicherweise existiert auf dem Zielsystem keine Environment- # Variable "HOME". Diese wird ausgelesen, um das Basis-Verzeichnis # ($basedir) festzulegen (folgender Block). # # 3. Zieladresse fuer EMails: # Diese wird mit der Systemfunktion "whoami" ermittelt. Man kann der # Variablen "$empfaenger" natuerlich auch einen festen Wert zuweisen: # my $empfaenger = "schnorg@morg.org"; # # Anmerkung: das "chomp" dient dazu, das Zeilenende-Zeichen der Ausgabe # von "whoami" zu entfernen. # # 4. Erzeugen von Mails: # Erfolgt durch einen Aufruf von "mail", suche einfach nach # "SUCHPUNKT MAILGEN", und du bist an der richtigen Stelle! :-) # # ---------------------------------------------------------------------- # Anpassungen durch den Benutzer sollten nur in diesem Bereich geschehen: my $basedir = $ENV{HOME}; my $termindaten = "$basedir/.termine"; my $mailtxt = "$basedir/.termine_mailtxt"; chomp(my $empfaenger = `whoami`); # EMail-Adresse des Empfaengers per Systemkommando ermitteln # Lockfile zusammenbauen: .termine_ttmmjjjj my $lockprefix = "$basedir/.termine_"; # Tagesdatum ermitteln: # Falls dies auf dem Zielsystem nicht funktioniert, kann es durch etwas ersetzt # werden, dass das aktuelle Datum in der Form TT:MM:JJJJ liefert: my $date = ""; chomp($date =`date "+%d:%m:%Y"`); # ---------------------------------------------------------------------- my ($d_now,$m_now,$y_now) = split(/:/, $date); my $lockfile = "$lockprefix$y_now$m_now$d_now"; my $ja = 1; my $nein = 0; # Anpassbare Werte fuer die ausgerichtete Ausgabe: # Folgende Zeile ist gut zum testen: # my $einruecken = "...."; my $einruecken = " "; my $normlaenge = 17; # Kommandozeilen-Parameter durchchecken: # coole Version: mehrere Optionen gleichzeitig moeglich! :-) # my $optstring = ""; foreach my $opt (@ARGV) { $optstring .= $opt; } my $opt_help = 1 == 1; $opt_help = index($optstring,"h") > -1; my $opt_mail = index($optstring,"m") > -1; my $opt_show = index($optstring,"s") > -1; my $opt_cfg = index($optstring,"c") > -1; my $opt_debug = index($optstring,"d") > -1; my $opt_force = index($optstring,"f") > -1; my $opt_install = index($optstring,"i") > -1; my $opt_version = index($optstring,"v") > -1; if ((!$opt_mail) && (!$opt_show)) { $opt_show = !$opt_show; } if (($opt_help) || ($#ARGV == -1)) { help(); exit; } if ($opt_cfg) { show_example(); exit; } if ($opt_install) { show_install(); exit; } if ($opt_version) { show_version(); exit; } if ($opt_debug) { print "Wichtige Variablenwerte:\n"; print " Basisverzeichnis = $basedir\n"; print " Lockfile = $lockfile\n"; print " Termindaten = $termindaten\n"; print " Tempdatei fuer Mailtext= $mailtxt\n"; print " Mail-Empfaenger = $empfaenger\n"; } # Lockfile pruefen usw: if ($opt_force) { if ($opt_debug) { print "Ich ignoriere das Lockfile \"$lockfile\".\n"; } } else { if (-f "$lockfile") { if ($opt_debug) { print "Das Lockfile $lockfile existiert!\nIch wurde also heute schonmal aufgerufen.\n\n"; } exit; } else { if ($opt_debug) { print "Datei $lockfile existiert nicht.\nDies ist also mein erster Aufruf heute...\n\n"; } system("rm -f $lockprefix" . "*"); system("touch $lockfile"); } } # In diese Arrays werden die in die Mail zu setzenden Texte geschrieben: my @terminarray = (); my @wochenarray = (); my @monatsarray = (); my @feiertagsarray = (); my @geburtstagsarray = (); # Variablen zur Steuerung des Verhaltens: my $keinmodus = 0; my $termine = 1; my $woechentlich = 2; my $monatlich = 3; my $feiertage = 4; my $geburtstage = 5; my $modus = $keinmodus; # Weitere Variablen: my $zeile = ""; my @warnliste = (); # Hashfeld zur Berechnung der Wochentags-Abstaende: my %revdow = ("Mo" => "1", "Di" => "2", "Mi" => "3", "Do" => "4", "Fr" => "5", "Sa" => "6", "So" => "7"); my @Monatsname = ("????", "Januar", "Februar", "Maerz", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember" ); my @Wochentag = ("??", "Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"); # exit ; my $jdnow = MyJulianDate($d_now, $m_now, $y_now); my $downow = day_of_week($jdnow); # 1..7 ?? if ($opt_debug) { print "Heute = $d_now.$m_now.$y_now ($downow) JD = $jdnow\n"; } # Einlesen und Verarbeiten der Termindaten: open(INPUT, "<$termindaten") || die "Konnte Termindatei $termindaten nicht ÷ffnen! :-("; while() { chomp($zeile = $_); # Nur Zeilen verarbeiten, die l„nger als 0 sind, und nicht mit "#" anfangen: if (!( ($zeile =~ /^\#/) || (length($zeile) == 0) )) { if ($zeile =~ /^Termine:/) { $modus = $termine; WarndatenExtrahieren(); } elsif ($zeile =~ /^Woechentlich:/) { $modus = $woechentlich; WarndatenExtrahieren(); } elsif ($zeile =~ /^W.chentlich:/) { $modus = $woechentlich; WarndatenExtrahieren(); } elsif ($zeile =~ /^Monatlich:/) { $modus = $monatlich; WarndatenExtrahieren(); } elsif ($zeile =~ /^Feiertage:/) { $modus = $feiertage; WarndatenExtrahieren(); } elsif ($zeile =~ /^Geburtstage:/) { $modus = $geburtstage; WarndatenExtrahieren(); } else { # Termin auslesen und gem„˜ Warndaten Meldung generieren: my $tag = substr($zeile,0,2); my $mon = substr($zeile,3,2); my $jar = substr($zeile,6,4); my $txt = substr($zeile,11); if ($modus == $termine) { if ($opt_debug) { print "in Termin-Bearbeitung: $tag.$mon.$jar\n"; } if (($tag eq "xx") || ($tag eq "XX") || ($tag eq "??")) { # Termine der Form xx.12.1999 immer ausgeben, wenn Monat und Jahr ok sind : if ($opt_debug) { print "ist ein Termin xx.MM.JJJJ!\n"; } if (($mon == $m_now) && ($jar == $y_now)) { my $tmp = LFill("Im $Monatsname[$mon]",$normlaenge," "); push (@terminarray, "$tmp: $txt"); } } else { # Normalfall: tt.mm.jjjj my $jdthen = MyJulianDate($tag,$mon,$jar); if ($opt_debug) { print "JulianDate = $jdthen\n"; } my $diff = $jdnow - $jdthen; if (DiffIstWarnDiff($diff)) { my $tmp = LFill(MakeDiffZeitString($diff ) . " (" . WochenTag($jdthen) . ")",$normlaenge," ") . ": $txt"; push (@terminarray, "$tmp"); } } } elsif ($modus == $woechentlich) { my $dowthen = $revdow{$tag}; if ($dowthen < $downow) { my $danach = $downow - $dowthen; my $davor = -$dowthen - 7 + $downow; if ($opt_debug) { print "($downow/$dowthen) danach = $danach, davor = $davor\n"; } if (DiffIstWarnDiff($danach)) { my $tmp = LFill(MakeDiffZeitString($danach). " ($tag)",$normlaenge," ") .": $txt"; push (@wochenarray, "$tmp"); } if (DiffIstWarnDiff($davor)) { my $tmp = LFill(MakeDiffZeitString($davor). " ($tag)",$normlaenge," ") .": $txt"; push (@wochenarray, "$tmp"); } } elsif ($downow == $dowthen) { if (DiffIstWarnDiff(0)) { my $tmp = LFill(MakeDiffZeitString(0). " ($tag)",$normlaenge," ") .": $txt"; push (@wochenarray, "$tmp"); } } else { my $danach = $downow + 7 - $dowthen; my $davor = $downow - $dowthen; if ($opt_debug) { # print "($downow/$dowthen) danach = $danach, davor = $davor\n"; } if (DiffIstWarnDiff($danach)) { my $tmp = LFill(MakeDiffZeitString($danach). " ($tag)",$normlaenge," ") .": $txt"; push (@wochenarray, "$tmp"); } if (DiffIstWarnDiff($davor)) { my $tmp = LFill(MakeDiffZeitString($davor). " ($tag)",$normlaenge," ") .": $txt"; push (@wochenarray, "$tmp"); } } # War Falsch! Wegen: Heute: Freitag, Montag Termin: # 5 - 1 = 4, tatsächliche Differenz ist 3 (sa,so,mo) # if (DiffIstWarnDiff($diff)) { # my $tmp = LFill(MakeDiffZeitString($diff). " ($tag)",$normlaenge," ") .": $txt"; # push (@wochenarray, "$tmp"); # } } elsif ($modus == $monatlich) { my $jdthen = MyJulianDate($tag,$m_now,$y_now); # spezielle Basteltag my $diff = $jdnow - $jdthen; if (DiffIstWarnDiff($diff)) { # print "MONATLICH : $zeile\n"; my $tmp = LFill(MakeDiffZeitString($diff). " (" . WochenTag($jdthen). ")",$normlaenge," ") . ": $txt"; push (@monatsarray, "$tmp"); } } elsif ($modus == $feiertage) { my $jdthen = MyJulianDate($tag,$mon,$jar); my $diff = $jdnow - $jdthen; if (DiffIstWarnDiff($diff)) { # print "FEIERTAG : $zeile\n"; my $tmp = LFill(MakeDiffZeitString($diff). " (" . WochenTag($jdthen). ")",$normlaenge," ") . ": $txt"; push (@feiertagsarray, "$tmp"); } } elsif ($modus == $geburtstage) { my $jdthen = MyJulianDate($tag,$mon,$y_now); my $diff = $jdnow - $jdthen; if (DiffIstWarnDiff($diff)) { # print "GEBURTSTAG : $zeile\n"; my $tmp = LFill(MakeDiffZeitString($diff). " (" . WochenTag($jdthen). ")",$normlaenge," ") . ": $txt"; # Alter des Geburtstagskindes berechnen: my $alter = $y_now - $jar; push (@geburtstagsarray, "$tmp ($alter)"); } } } } # if no comment } # while close(INPUT); # print "\n\nMailtext:\n\n"; if (($#terminarray > -1) || ($#wochenarray > -1) || ($#monatsarray > -1) || ($#feiertagsarray > -1) || ($#geburtstagsarray > -1)) { open(MAILTXT, ">$mailtxt") || die "Fehler beim Erzeugen von $mailtxt!"; if ($#terminarray > -1) { print MAILTXT "\nTermine:\n"; foreach my $line (@terminarray) { print MAILTXT "$einruecken$line\n"; } } if ($#wochenarray > -1) { print MAILTXT "\nWoechentliche Termine:\n"; foreach my $line (@wochenarray) { print MAILTXT "$einruecken$line\n"; } } if ($#monatsarray > -1) { print MAILTXT "\nMonatliche Termine:\n"; foreach my $line (@monatsarray) { print MAILTXT "$einruecken$line\n"; } } if ($#feiertagsarray > -1) { print MAILTXT "\nFeiertage:\n"; foreach my $line (@feiertagsarray) { print MAILTXT "$einruecken$line\n"; } } if ($#geburtstagsarray > -1) { print MAILTXT "\nGeburtstage:\n"; foreach my $line (@geburtstagsarray) {print MAILTXT "$einruecken$line\n"; } } close(MAILTXT); # SUCHPUNKT MAILGEN if ($opt_mail) { system("mail \"$empfaenger\" -s \"[Termine] $d_now.$m_now.$y_now\" < $mailtxt"); } if ($opt_show) { # printf("Heute ist der %2d.%2d.%2d (%s).\n",$d_now,$m_now,$y_now,WochenTag($jdnow)); system("cat \"$mailtxt\""); print "\n"; } } if ($opt_debug) { print "Fertig\n"; } exit; # -------------------------------------------------------- sub LFill { my ($str, $len, $womit) = @_; while (length($str) < $len) { $str = "$womit$str"; } return $str; } # -------------------------------------------------------- sub WarndatenExtrahieren { my $pos = 0; my $part = ""; @warnliste = (); my ($liste) = ( $zeile =~ /.*\[(.*)\]/ ); $liste = Trim($liste); # print "Liste: _$liste" . "_\n"; while (length($liste) > 0) { $pos = index($liste," "); if ($pos != -1) { $part = Trim(substr($liste,0,$pos)); $liste = Trim(substr($liste,$pos+1)); } else { $part = $liste; $liste = ""; } # print "part = $part\n"; $warnliste[++$#warnliste] = int($part); } # wend } # --------------------------------------------- sub Trim { my ($line) = @_; if (!defined($line)) { $line = ""; } while ( (length($line) > 0) && (substr($line,0,1) eq " ") ) { $line = substr($line,1); } while ( (length($line) > 0) && (substr($line,length($line)-1,1) eq " ") ) { $line = substr($line,0,length($line)-2); } return $line; } # ---------------------------------------------- sub DiffIstWarnDiff { my ($mydiff) = @_; my $found = 0; my $i = 0; # print "Laenge der warnliste = " . $#warnliste + 1 . "\n"; while (($i <= $#warnliste) && ($found == 0)) { if ($warnliste[$i] == $mydiff) { $found = 1; } $i++; } return $found == 1; } # ---------------------------------------------- sub MakeDiffZeitString { my ($mydiff) = @_; if ($mydiff == -2) { return "Uebermorgen"; } elsif ($mydiff == -1) { return "M o r g e n"; } elsif ($mydiff == 0) { return "H e u t e"; } elsif ($mydiff == 1) { return "Gestern"; } elsif ($mydiff < 0) { return sprintf("In %d Tagen" , -$mydiff); } elsif ($mydiff > 0) { return sprintf("Vor %d Tagen", $mydiff); } } # ---------------------------------------------- sub MyJulianDate { my ($tt,$mm,$jj) = @_; my $JD = 0; my $J = 0; my $M = 0; my $G = 0; my $a = 0; if ($mm < 3) { $J = $jj - 1; $M = $mm + 12; } else { $J = $jj; $M = $mm; } $a = int($J / 100); $G = 2 - $a + int($a/4); $JD = int(365.25 * $J) + int(30.6001*($M + 1)) + $tt + 1720995 + $G; return $JD; } # -------------------------------------------------- sub day_of_week { my ($JD) = @_; $JD = $JD - 7 * int($JD/7); $JD++; return $JD; } # -------------------------------------------------------- sub WochenTag { my ($JD) = @_; return $Wochentag[day_of_week($JD)]; } # -------------------------------------------------- sub help { print "\n -+-- TERMIN-ERINNERER $version (Perl-Version) --+-\n\n"; print " Autor: Tjabo Kloppenburg \n"; print " Datum: Oktober 1999\n"; print " Usage: termine [-optionen]\n"; print " -m = mail Terminmeldungen per Mail senden.\n"; print " -s = show Terminmeldungen im Terminal anzeigen.\n"; print " -f = force Lockdatei nicht beachten.\n"; print " -d = debug Anzeige wichtiger Variableninhalte.\n"; print " -c = cfg Beispiel-Termindatei (~/.termine) ausgeben.\n"; print " -i = info Installationshinweise, nach less pipen!).\n"; print " -v = version Infos zur aktuellen Version (Aenderungen).\n"; print " -h, = Diese Hilfe anzeigen.\n\n"; } # ------------------------------------------------------------------------- sub show_example { print "# Termindatei fuer das Termine-Script ($version) von Tjabo Kloppenburg"; print <~/.termine 3. Anpassungen vornehmen: joe ~/.termine - Nach "Termine: [-3 -2 -1 0]" folgen Termine, deren Datum genau mit Tag, Monat und Jahr festgelegt sind. Die Zahlen in den eckigen Klammern geben an, an welchen Tagen vor dem Termin ein Hinweis erstellt werden soll: -3 bedeutet, es wird drei Tage vor dem Termin ein Hinweis generiert. Termine mit einem Datum "xx.10.1999" werden immer angezeigt. Terminhinweise werden in der Reihenfolge der Termine in ~/.termine ausgegeben. - "W÷chentlich: [...]" Dies sind Termine wie "Montags schwimmen gehen". Als Datum wird eines der Krzel "Mo, Di, Mi, Do, Fr, Sa, So" angegeben: Mo Schwimmen gehen ^^^^^^^^^ Dieser Abstand ist wichtig! - "Monatlich: [...]" Du musst am 15. Deine Miete berweisen? Generiere einen Eintrag wie folgt: 15. Miete berweisen - "Feiertage: [...]" Hier kann man eine Liste bundeseinheitlicher und lokaler Feiertage anlegen. Die kann man zB einem Kalender entnehmen. Die Berechnung von Ostern usw. folgt eventl. in einer zuknftigen Version. Alle Tage sind mit Tag, Monat und Jahr anzugeben. - "Geburtstage: [...]" Der Clou hierbei: Es wird automagisch das Alter der Person berechnet, und in Klammern hinter dem Namen ausgegeben! :-) Beispiel fr einen Geburtstags-Eintrag: 13.05.1962 Hans Schauinsall 4. Testlauf: ./termine -fsd Optionen: f = force = Sperrdatei nicht beachten s = show = Keine Mail generieren, Ausgabe als Text. d = debug = Variableninhalte zur Kontrolle ausgeben. 5. Wenn alles einwandfrei lief, kann man "termine" z.B. nach ~/bin/ kopieren. Fuer einen Aufruf, der eine Mail erzeugen soll, erstellt man entweder einen CRON-Job, der mindestens einmal pro Tag gestartet wird, oder einen Eintrag in der ~/.bashrc (Start bei Login): a) CRON-Job einrichten: L„uft der Rechner nicht st„ndig, kann man den Job z.B. alle Stunde einmal starten. Es wird trotzdem nur eine Termin-EMail erzeugt: crontab -e Dann eintragen: 5 * * * * /home/user/bin/termine -m Und abspeichern. Dann wird 5 Minuten nach jeder vollen Stunde das Script aktiviert. b) Eintrag in ~/.bashrc mit Generierung einer EMail. Das ist sinnvoll fuer Systeme, die jeden Tag neu hochgefahren werden. Mit dem Lieblingseditor die ~/.bashrc ÷ffnen: joe ~/.bashrc Dann am Ende den Eintrag vornehmen: /home/user/bin/termine -m So wird bei jedem Login "termine" gestartet, und einmal pro Tag ein Terminhinweis per EMail versendet. Wer die Termine gerne sieht, wann immer er/sie eine Shell ÷ffnet, macht am Ende von ~/.bashrc einen Eintrag der Form: /home/user/bin/termine -fs Das f sorgt dafuer, dass die Sperrdatei nicht beachtet wird. Diese verhindert ohne f, dass die Terminhinweise mehr als einmal pro Tag ausgegeben werden. 6. Wenn Probleme auftreten, sollte man einen Blick in die ersten 20 Zeilen des perl-Scriptes werfen. Dort finden sich Hinweise zur Loesung von moeglichen Problemen wie - Probleme mit der Erzeugung von Mails, - Anpassen der EMail-Adresse, - Auslesen des Systemdatums. 7. Viel Spass wuenscht Tjabo Kloppenburg. Feedback ist willkommen! EOF } # ---------------------------------------------------- sub show_version { print "Version: $version\n"; print <