Perl 1

Perl 2

Perl 3

Perl 4

Perl 5

Perl 6

Zurück

Einführung in Perl - Teil VI

Kommunikation mit anderen Programmen

von Achim Schmidt


Im heutigen Teil der Perl Serie geht es darum, zu zeigen wie sich die Kommunikation von Perl Skripten zu anderen Programmen hin gestaltet. Unter anderem verdankt Perl seine Beliebtheit als Sprache für CGI Skripte, neben seiner Zeichenverwaltung, auch diesem Feature.

Perl bietet eine recht triviale Art mit anderen Programmen zu kommunizieren, welche ähnlich der Dateibehandlung ist, welche wir uns im letzten Teil dieser Serie angesehen haben. Programme werden einfach als Handle geöffenet und entsprechende Daten können diesem mitgeteilt bzw. ausgelesen werden.

Anders als bei Dateien wird als Operationskennzeichen hier jedoch das Pipesymbol (|) eingesetzt. Steht dieses Symbol vor dem Programmnamen, so werden Informationen über STDOUT in dieses Programm "hereingepipet". Steht es hinter dem Programmausruf, können die Programmausgaben im Perlprogramm eingelesen werden.

Deutlicher düfte dies jedoch an einem kleinen Beispiel werden. Hierzu betrachten wir ein WWW-Mailformular, mit welchem der Besucher einer Website eine Nachricht an den Webmaster senden kann.

Beispiel 1: HTML Dokument zum Darstellen des Mailformulares

<HTML>
<HEAD>
<TITLE>MAILFORMULAR</TITLE>
</HEAD>
<BODY>
<CENTER>
<H1>Nachricht hinterlassen</H1>
</CENTER>
<HR>
<FORM ACTION="mailform.cgi" METHOD="POST">
<CENTER>
<TABLE>
	<TD>Ihr Name:</TD>
	<TD><INPUT TYPE="TEXT" NAME="NAME" SIZE="40"</TD><TR>
	<TD>Ihr Emailadresse:</TD>
	<TD><INPUT TYPE="TEXT" NAME="EMAIL" SIZE="40"</TD><TR>
	<TD>Ihr Kommentar:</TD>
	<TD><TEXTAREA NAME="KOMMENTAR" COLS="40" ROWS="10">
	    </TEXTAREA></TD>
</TABLE>
<INPUT TYPE="SUBMIT" VALUE="absenden">
</CENTER>
</FORM>
<HR>
</BODY>
</HTML>

Beispiel 2: CGI Skript zum Auswerten der Informationen aus Beispiel 1 und Erzeugen einer entsprechenden Mail

#!/usr/bin/perl

require "cgi-lib.pl";

&ReadParse(*formdata);

open (EMAIL, "| /usr/sbin/sendmail -t");
	print EMAIL <<EOMAIL;
From: $formdata{'EMAIL'} ($formdata{'NAME'})
To: as\@Saar.de
Subject: Web - Kommentar
X-Mailer: Own Perl-WebMail

$formdata{'NAME'} <$formdata{'EMAIL'}>
hat heute folgenden Kommentar hinterlassen:

$formdata{'KOMMENTAR'}
EOMAIL

close (EMAIL);

print &PrintHeader;
print &HtmlTop ("Mail gesendet");
print <<EOTEXT;
<HR>
Ihre Nachricht wurde soeben mit folgenden Absenderdaten versandt:<P>
<CENTER><TABLE BORDER=3>
	<TD>Name:</TD>
	<TD>$formdata{'NAME'}</TD><TR>
	<TD>Email:</TD>
	<TD>$formdata{'EMAIL'}<BR></TD><TL>
</TABLE></CENTER>
<HR>
EOTEXT
print &HtmlBot;

Das erste Beispiel ist die HTML Datei, welche ein Kommentarformular generiert. Bei Betätigung des Submitbuttons werden die Feldinhalte nun dem Programm demo6-2.cgi üebergeben, welches in Beispiel 2 dargestellt ist.

Beispiel 2 ist ein kleines CGI Skript, welches in Perl programmiert wurde. Um die Übernahme und Konvertierung der Feldinhalte zu realisieren und mir auch ansonsten ein wenig Arbeit und Tipperei zu sparen, verwende ich eine frei verfügbare Perlbibliothek, nämlich die cgi-lib.pl von Steven E. Brenner (S.E.Brenner@bioc.cam.ac.uk), welche über das Internet unter http://www.bio.cam.ac.uk/cgi-lib/ zu beziehen ist. Diese Library nimmt dem Perl Programmierer einige nervtötende Arbeit im Umgang mit CGI Skripten ab. Wesentlichste und wohl auch meistbenutze Bestandteile sind die folgenden Funktionen:

&ReadParse():		 Nimmt Feldeingaben entgegen, konvertiert diese und speichert die 
			 Ergebnisse in einem assoziativen Array ab
&PrintHeader:	 	 Gibt den HTML Header für die Rückgabe aus
&HtmlTop(<Überschrift>): Gibt den Anfang einer HTML Datei aus und gibt dabei den 
			 definierten Text als Überschrift aus
&HtmlBot:		 Gibt das Ende einer HTML Datei aus

Weiterer wesentlcher Bestandteil des CGI Skriptes ist natürlich der Teil, welcher die Mail versendet. Hier wird das Programm sendmail mit der Option -t aufgerufen, welche sendmail veranlaßt die nachfolgenden Information quasi als fertige Mail zu betrachten. Dabei ist zu beachten, daß der Mailheader ebenfalls von Perl Programm generiert werden muß. Dies ist der erste Teil der Printanweisung. Trennzeichen zwischen Mailheader und -body bildet eine Leerzeile. Nach dieser kann also der zu mailende Text eingegeben werden.

Um mir hier die Arbeit ein wenig zu erleichtern, habe ich eine weitere Eigenheit von Perl ausgenutzt um mehrer Zeilen Text auszugeben, ohne jedesmal eine lästige print - Anweisung voransetzen zu müßen. Die Anweisung

	print MAIL << EOMAIL;
bewirkt, daß der Text bis zur Zeile
	EOMAIL
in das geöffnete Handle MAIL ausgegeben wird. Neben der Ausgabe des reinen Textes findet in diesem Abschnitt auch eine Variablenersetzung statt, so daß hier auch alle im Programm definierten Variablen benutzt werden können und beim Ablauf durch deren entsprechende Inhalte ersetzt werden. Die gleiche Technik benutze ich später noch einmal, um die HTML Seite zu erzeugen, welche nach der Mailbertragung ausgegeben wird. So kann man mit mit sehr einfachen Mitteln ein komfortables Kommentarsystem erstellen.

Auch der engegengesetzte Weg ist durchaus sinvoll. Hier wird die Ausgabe eines Programmes oder eines Prozesses abgefangen und kann innerhalb des Perl Programmes weiterverarbeitet werden. Dazu wird das PIPE - Symbol innerhalb der open() Anweisung hinter den Programmaufruf gesetzt, was Perl dazu veranlasst die Ausgabe des entsprechenden Prozesses mittels des (ebenfalls innerhalb der open() Anweisung) Filehandles entgegenzunehmen und dem Programm somit zur weiteren Verarbeitung verfügbar zu machen.

Sehen wir und nun auch dies einmal an einem kleinen und einfachen Beispielprogramm an:

Beispiel 3: Aufruf des finger Kommandos

#!/usr/bin/perl

open (FINGERPROC, "finger |");
while (<FINGERPROC>) {
	print $_ ;
}

Dieses kleine Programm öffnet das finger Programm als Prozess. Seine Ausgabe wird mittels des Filehandles FINGERPROC verarbeitet. Die Weiterverarbeitung funktioniert hier analog zum Einlesen von Datensätzen aus einer Datei. Die Ausgabe wird zeilenweise eingelesen bis die while - Schleife false liefert, sprich alle Ausgabezeilen des Prozeses eingelesen wurden.

Zugriff auf Systeminformationen

Ein weiters nicht zu unterschätzendes Thema, ist der Zugriff aus einem Programm heraus auf Systeminformationen. Auch dies ist natürlich in Perl kein großes Problem. Zum Abschluß dieser Serie möchte ich Ihnen hier einmal die wichtigsten Funktionen vorstellen.

Oft benötigt sind beispielsweise Informationen über eine Loginkennung. Diese Informationen werden nun meist innerhalb der Datei /etc/passwd vorgehalten. Perl bietet mit der Funktion:

	getpwnam ()
die Informationen zu einem konkreten Login aus der /etc/passwd. Der Rückgabewert dieser Funktion isr ein Array, mit folgendem Aufbau:
Feld			Inhalt
0			Login
1			Passwort (codiert)
2			User - ID
3			Gruppen - ID
4			Quota
5			Kommentar
6			GCOS
7			Homeverzeichnis
8			Shell
An folgendem kleinen Beispielprogramm sollte diese Funktion klar werden:

Beispiel 4

#!/usr/bin/perl

print "\nUser-ID: ";
chop ($login = <STDIN>);

(@pw_info) = (getpwnam("$login"));
print "\nUserinformationen fuer login: $login\n\n";
print "Login: $pw_info[0]\n";
print "Pw (encoded): $pw_info[1]\n";
print "UserID: $pw_info[2]\n";
print "GroupID: $pw_info[3]\n";
print "Kommentar: $pw_info[6]\n";
print "HomeDir: $pw_info[7]\n";
print "Shell: $pw_info[8]\n";
print "\n\n";

Das Programm läßt zunächst eine Userid eingeben, deren Informationen es anschließend über einen Aufruf der Funktion getpwnam () ausließt. Nach der Zuweisung der Rückgabeinformationen in das Array @pw_info werden die einzelnen Feldinformationen ausgegeben, welche ja nun in dem Feld zur Verfügung stehen.

Analog zur zur Funktion getpwnam () gibt es auch di Funktion getpwuid (), welche die Informationen nicht nach dem Login, sondern nach der User ID heraussucht. Das Beispielprgramm 5 ist nun insofern geändert, daß nicht mehr nach dem Loginnamen, sondern eben nach der User-ID herausgesucht wird.

Beispiel 5

#!/usr/bin/perl

print "\nUser-ID: ";
chop ($login = <STDIN>);

(@pw_info) = (getpwuid("$login"));
print "\nUserinformationen fuer login: $login\n\n";
print "Login: $pw_info[0]\n";
print "Pw (encoded): $pw_info[1]\n";
print "UserID: $pw_info[2]\n";
print "GroupID: $pw_info[3]\n";
print "Kommentar: $pw_info[6]\n";
print "HomeDir: $pw_info[7]\n";
print "Shell: $pw_info[8]\n";
print "\n\n";

Weitere oft benutzte Information sind Informationen zum Netzwerk. Um Angaben zu einem bestimmten Rechner zu bekommen, dessen Name bekannt ist, kann man sich der Funktion gethostbyname () bedienen. Diese Funktion liefert ebenfalls ein Feld zurück, welches folgenden Aufbau hat:

Feldnr.			Inhalt
0			Name
1			Aliases
2			Addresstype
3			Länge
4			Adresse 
Von Bedeutung sind normalerweise die Felder 0, 1 und 4. Wie diese Informationen abgefragt werden, zeigt Beispiel 6.

Beispiel 6

#!/usr/bin/perl

print "Rechnername: ";
chop ($rechner = <STDIN>);
($name,$aliases,$atype,$len,$addrs) = gethostbyname($rechner);

print "Name: $name\n";
print "Aliases: $aliases\n";
print "Adresse: ".join (".",unpack("C4", $addrs)), "\n";

Das Programm sollte bis auf die letzte Zeile selbsterklärend sein. Hier werden aus diesen vier Zeichen mittels der unpack Funktion die vier Ziffern der IP Adresse gebildet, wobei der Punkt als Trennzeichen hergenommen wird.

Der Autor

Achim Schmidt ist staatlich geprüfter Assistent für Automatisierungs- und Computertechnik (HBFS) und beschäftigt sich bereits seit 6 Jahren intensiv mit dem Internet und seinen Diensten. Mit Linux wurde er erstmalig 1992 beim Aufbau eines Mailboxsystemes direkt konfrontiert. Seit 1995 ist er als Netzwerk- und Systemmanager tätig und beschäftigt sich dabei auch mir der Entwicklung und Realisierung WWW- basierter Onlinesysteme und Internetkopplungen. Zu erreichen ist er unter as@Saar.DE.

Copyright © 1997 Linux-Magazin Verlag