Entwickeln unter/für FreeBSD?

odenter

Well-Known Member
Hi,

da FreeBSD 7, ich benutze PCBSD, jetzt so ist wie ich es mir immer vorgestellt habe wollte ich mal anfangen ein bischen unter FreeBSD zu programmieren.

Unter Windows habe ich 10 Jahre Erfahrung mit WinAPI (c/c++) und .net (vb.net und c#) sammeln können. Alle Webseiten oder Bücher die ich habe oder kenne beziehen sich entsprechend auf Windows.
Das einzige Buch das ich für FreeBSD habe ist "Designing BSD rootkits", ich weiss also im Grunde wie so Kernel-Module aufgebaut sind, welche im Grunde wie *.dll's unter Windows aufgebaut sind.

Aber wo finde ich solche Grundlagen? Von Linux weiss ich es gibt so *.so Dateien, die am ehesten *.dll's unter Windows entsprechen.

Auch was GUI's angeht weiss ich das es QT und GTK gibt.

Ich suche also HowTo's oder Bücher erstmal für die Grundlagen und eben um Grob zu gucken und einmal erstmal drauf los zu probieren und ein paar Erfahrungen zu sammeln.
Hat da jemand von euch nützliche Links oder Buch Empfehlungen?
 
Was GUIs angeht. GTK+ mit GtkBuilder bringt schnell erste Erfolge, vor allem wenn man es erst mal über eine Skriptsprache verwendet, die einem die Speicherverwaltung abnimmt.

Und da man die GUI in XML verfasst hat kann man das Programm dahinter dann gemütlich zu C migrieren.
 
Ich weiß jetzt ja nicht wie sinnvoll das ist, aber für ein "shared object" unter Linux/*BSD kann ich dir hier schnell ein Beispiel zeigen. Das sollte für dich ja keine Probleme machen, da du ja C beherrschst. Vllt gibt es dir ein paar Anhaltspunkte wonach du suchen kannst.

Als erstes legen wir unser Bilbiothek an mit der tollen Funktion "echo_hm". ^^

lib.c
Code:
#include <stdio.h>

void echo_hm() {
	printf("Hakuna Matata\n");
}

Dann kommt ein Progrämmchen, was unser "shared object" verarbeitet und unsere Funktion darin aufruft.

main.c
Code:
#include <stdio.h>
#include <dlfcn.h> //Gibt dir dlopen, dlsym...

//wie die Lib heißen soll
#define LIBRARY "lib.so" 

int main() {
	void *handler; //Der Lib Handler
	void  (*func)(); // Pointer auf die Funktion aus unserer Lib
	const char *error;

	handler = dlopen(LIBRARY, RTLD_LAZY);
	if (!handler) {
		fprintf(stderr, "Error: %s\n", dlerror()); //gibt einen Fehler aus wenn was schief gelaufen ist, zb die Datei nicht gefunden wurde.
		exit(1);
	}

	func = dlsym(handler, "echo_hm"); //Sucht die Funktion in unserer Lib
	error = dlerror(); //Fehler, zb Funktion nicht vorhanden
	if (error) {
		fprintf(stderr, "Error: %s\n", error);
		exit(1);
	}
    
	(*func)(); //Ruft unsere Funktion auf
        
	dlclose(handler);

	return 0;
}
Jetzt den Kram bauen:
Code:
$ gcc -c -fpic lib.c
$ gcc -shared -o lib.so lib.o
$ gcc -o test main.c
Denk dran deine LD_LIBRARY_PATH richtig zu setzen, wo deine dynamische Bibliothek liegt. ;)

Das ist jetzt nicht so elegant, aber man sollte es denke (hoffe) ich einigermaßen verstehen können, was dort geschiet. Damit kannst du vllt selber weitersuchen, oder dir zb mal die "dlfcn.h" angucken.

Eine Literaturliste kann ich dir auch erstellen, allerdings nicht mehr heute Abend. Muss morgen früh aufstehen. -.-
Aber ich glaube erstmal sollte dir das Web genug offenbaren. So hab ich das auch am Anfang überwiegend gemacht. Die $Suchmaschine gequält. ;)

Ich hoffe das bringt dich auf die richtige Spur.
 
Danke erstmal, eine Literaturliste wäre super.

Mit dem Beispiel komme ich aber auch erstmal weiter, das ist im Grunde genau das Beispiel das ich zu shared libraries gesucht habe. :) Damit habe ich erstmal ein paar Suchbegriffe.
 
Code:
	func = dlsym(handler, "echo_hm"); //Sucht die Funktion in unserer Lib
	error = dlerror(); //Fehler, zb Funktion nicht vorhanden
	if (error) {
Die Verwendung von dlerror() ist hier konzeptionell falsch. dlerror() gibt nur einen Fehler zurück, der sich auf das vorige dlsym() bezieht, falls dieses einen Nullzeiger zurückgegeben hat.
Zudem sollte dlfunc() statt dlsym() verwendet werden, da es sich bei dem nachgefragten Objekt um eine Funktion handelt.

Code:
(*func)(); //Ruft unsere Funktion auf
Die Klammern und der Stern sind redundaterweise redundant und machen den Quelltext nur schlechter lesbar. Funktionszeiger können, wie normale Funktionsdesignatoren auch, einfach durch func() aufgerufen werden. Tatsächlich ruft man /immer/ nur Funktionszeiger auf, da Funktionsdesignatoren sofort zu Funktionszeigern degenerieren. Zum selbst ausprobieren:
Code:
printf("hello world\n");
(*printf)("hello world\n");
(**********printf)("hello world\n");
Analog kann man dasselbe auch mit dem Funktionszeiger tun. Also was tut (*func)()? Es wandelt per * den Funktionszeiger in einen Funktionsdesignator um, dieser degeneriert sofort wieder zu einem Funktionszeiger und dann wird ein Aufruf mit diesem Funktionszeiger durchgeführt.

Am Rande sei noch erwähnt, dass es sich bei
Code:
void  (*func)();
um einen Funktionszeiger ohne Prototypen, also mit unspezifizierter Parameterliste, und nicht um einen Funkzionszeiger ohne Parameter handelt. Es ist anzuraten explizit "void" in die Parameterliste zu schreiben, wenn keine Parameter erwünscht sind, um Fehlbenutzung vorzubeugen, denn mit bloßen leeren Klammern ist folgendes erlaubt:
Code:
func();
func(23);
func("Hello world\n");
 
Danke, das war sehr aufschlussreich. Das man void statt einer leeren Parameterliste verwenden sollte, wusste ich nicht.
 
Was für eine IDE verwendet man denn am besten?
KDevelop sieht ja ganz nett aus, bringt aber natürlich keine Projekt-Templates für FreeBSD mit. Gibts da irgendwelche Vorlagen die ich dort einfügen kann?
 
Es gibt auch Leute, die wissen es immer besser. :P

Code:
	func = dlsym(handler, "echo_hm"); //Sucht die Funktion in unserer Lib
	error = dlerror(); //Fehler, zb Funktion nicht vorhanden
	if (error) {
Die Verwendung von dlerror() ist hier konzeptionell falsch. dlerror() gibt nur einen Fehler zurück, der sich auf das vorige dlsym() bezieht, falls dieses einen Nullzeiger zurückgegeben hat.
Mh das ist doch genau das was ich möchte, oder habe ich da einen Denkfehler drin?

Zudem sollte dlfunc() statt dlsym() verwendet werden, da es sich bei dem nachgefragten Objekt um eine Funktion handelt.
Da hast du recht...

Code:
(*func)(); //Ruft unsere Funktion auf
Die Klammern und der Stern sind redundaterweise redundant und machen den Quelltext nur schlechter lesbar.

Ja das weiß ich, aber zum grundlegenden Verständnis finde ich das so besser, auch wenn er das intern so handhabt, mit oder ohne *(...)

Am Rande sei noch erwähnt, dass es sich bei
Code:
void  (*func)();
um einen Funktionszeiger ohne Prototypen, also mit unspezifizierter Parameterliste, und nicht um einen Funkzionszeiger ohne Parameter handelt. Es ist anzuraten explizit "void" in die Parameterliste zu schreiben, wenn keine Parameter erwünscht sind, um Fehlbenutzung vorzubeugen, denn mit bloßen leeren Klammern ist folgendes erlaubt:
Code:
func();
func(23);
func("Hello world\n");
Da hast du leider wieder recht. Hab ich vergessen... -.-

Wie gesagt war das etwas, zugegebenermaßen schlecht in der Nacht zusammengeschriebenes, Beispiel. Aber Danke für deine Korrekturen. ^^

Was für eine IDE verwendet man denn am besten?
KDevelop sieht ja ganz nett aus, bringt aber natürlich keine Projekt-Templates für FreeBSD mit. Gibts da irgendwelche Vorlagen die ich dort einfügen kann?
IDE? Wer braucht denn das? vim + ctags ist meine IDE. ;)

Bei der Literaturliste bin ich jetzt sehr bequem und rate dir mal das hier zu lesen:
http://www.freebsd.org/doc/en_US.ISO8859-1/books/developers-handbook/index.html
Das hier ist das Developer Handbuch, dort gibt es auch einen Abschnitt über shared libraries unter FreeBSD und am Ende glaube ich ist auch eine Literaturliste. Ich denke wirklich mal mit einer Suchmaschine deiner Wahl und wenn du dir einige rl Beispiele anguckst, wirst du das sehr schnell lernen können.
 
Was für eine IDE verwendet man denn am besten?
KDevelop sieht ja ganz nett aus, bringt aber natürlich keine Projekt-Templates für FreeBSD mit. Gibts da irgendwelche Vorlagen die ich dort einfügen kann?

Ich verwende immer Eclipse und vim. Für so gut wie jede Sprache gibt es ein Eclipse-Plugin und vim hat auch Syntax-highlighting für fast alles.

Meistens fange ich damit an in Eclipse das Projekt anzulegen, die Struktur festzulegen (Klassen erstellen, Ordnerstruktur usw.). Dann arbeite ich oft mit vim weiter.
 
odenter: FreeBSD hat sehr gut manpages.
Schau dir z.B. mal
Code:
man dlsym
an.

Oder halt die anderen Funktionen, die du benutzen möchtest.
 
Warum überhaupt der ganze dlXXX() Kram? Einfach das Programm gegen die Bibliothek linken und das Auflösen der Symbole wird vom Runtime-Linker automatisch erledigt. In den allermeisten Fällen wird das genügen.

Als kleine Bemerkung: In C ist "int foo();" nicht das selbe wie "int foo(void);". In C++ wird allerdings "int foo();" implizit zu "int foo(void);", d.h. eine Funktion ohne Parameter-Angaben hat in C++ implizit keine Parameter.

Für den OP: Warum versteifst Du Dich auf dynamische Bibliotheken? Willst Du wissen wie das funktioniert oder willst Du unter FreeBSD entwickeln? Falls ersteres zutrifft, so kann ich Dir die Lektüre der ELF ABI empfehlen, da steht drin wie sowas funktioniert. Im letzteren Fall solltest Du vielleicht erst nach einem Build-System Ausschau halten, d.h. lies Dich erstmal in Make oder Ant o.ä. ein. Auch das Manual vom Compiler (vermutlich GCC) solltest Du lesen. Dann schau nach einem Framework in dem Du Anwendungen entwickeln willst. Qt ist z.Zt. glaub ich bei vielen Recht hoch im Kurs. Wenn Du kein Framework verwenden willst, dann bist Du auf POSIX beschränkt. Die Manpages für die implementierten Funktionen findest Du auf Deinem System. Ein Buch würde ich mir nicht kaufen, die meisten Informationen findet man auch im Netz.
 
odenter: FreeBSD hat sehr gut manpages.
Schau dir z.B. mal
Code:
man dlsym
an.
Oder halt die anderen Funktionen, die du benutzen möchtest.
Ja würde ich ja gerne, mein Problem ist das ich gar nicht weiss wie die Funktionen heissen.


Warum überhaupt der ganze dlXXX() Kram? Einfach das Programm gegen die Bibliothek linken und das Auflösen der Symbole wird vom Runtime-Linker automatisch erledigt. In den allermeisten Fällen wird das genügen.
Hängt halt davon ab was man machen will.

Für den OP: Warum versteifst Du Dich auf dynamische Bibliotheken? Willst Du wissen wie das funktioniert oder willst Du unter FreeBSD entwickeln? Falls ersteres zutrifft, so kann ich Dir die Lektüre der ELF ABI empfehlen, da steht drin wie sowas funktioniert.
Ich versteife mich überhaupt nicht darauf, ich wollte wissen wie die Funktionen zum laden/etc. von shared libraries heissen, wenn man nicht weiss wonach man suchen muss, dann bringen die man-pages auch nichts.
Ich will ne Übersicht bzw. einen Index zu Funktionen die z.B. für Prozesshandling sind oder eben für shared libraries, die MSDN hat sowas sehr gut.

Im letzteren Fall solltest Du vielleicht erst nach einem Build-System Ausschau halten, d.h. lies Dich erstmal in Make oder Ant o.ä. ein. Auch das Manual vom Compiler (vermutlich GCC) solltest Du lesen.
Mit Make habe ich schon rumgespielt, als ich den Code aus meinem Buch ausprobiert habe, und mit Ant habe ich mich auch kurz beschäftigt.
Beides ist aber genau das was ich mir nicht vorgestellt habe, wenn ich mit dem Studio von MS arbeite, da brauche ich mich auch nicht um irgendwelche Make-Files kümmern, die werden automatisch erzeugt. Wer das alles von Hand machen will kann das ja gerne machen, ich hab da keine Lust zu und beschäftige mich dann lieber mit anderen Dingen.

Dann schau nach einem Framework in dem Du Anwendungen entwickeln willst. Qt ist z.Zt. glaub ich bei vielen Recht hoch im Kurs. Wenn Du kein Framework verwenden willst, dann bist Du auf POSIX beschränkt. Die Manpages für die implementierten Funktionen findest Du auf Deinem System. Ein Buch würde ich mir nicht kaufen, die meisten Informationen findet man auch im Netz.
QT dekct soweit ich weiss ja schon mehrere Bereiche ab.
Ich brauche eine Übersicht in der ich sehe welches Framework worauf aufbaut.

Unter Windows gibts die WinAPI, darauf setzt die MFC auf (was ja dann QT entsprechen würde). Wie schreibe ich für ein FreeBSD ein Programm das ein Fenster anzeigt ohne QT oder GTK?
Unter Windows macht man das mit der API Funktion CreateWindowEx etc. Wie geht das unter nem FreeBSD?
 
Zuletzt bearbeitet:
Unter FreeBSD müsstest du dann direkt mit dem X-Server kommunizieren. Ich vermute mal (bin nie auf die Idee gekommen so etwas ohne Framework zu probieren) man macht einfach eine TCP-Verbindung zum X-Server auf und schickt dann in seinem Protokoll (Spezifikationen gibt's wahrscheinlich unter http://x.org) was der so zeichnen soll.
 
Unter FreeBSD müsstest du dann direkt mit dem X-Server kommunizieren. Ich vermute mal (bin nie auf die Idee gekommen so etwas ohne Framework zu probieren) man macht einfach eine TCP-Verbindung zum X-Server auf und schickt dann in seinem Protokoll (Spezifikationen gibt's wahrscheinlich unter http://x.org) was der so zeichnen soll.

Nein, man verwendet die XLib. Oder das X Toolkit. Das ist so in etwa das Äquivalent zur GUI-Programmierung ohne MFC sondern direkt per Win32 API.
 
Nein, man verwendet die XLib. Oder das X Toolkit. Das ist so in etwa das Äquivalent zur GUI-Programmierung ohne MFC sondern direkt per Win32 API.

Echt? XLib oder X Toolkit implementiert eigene Widgets? :apaul: Gut zu wissen, habe immer gedacht, die bringen nur die Zeichenwerkzeuge mit, aber Widgets muß man selber implementieren.

Win32-API bzw. ein Teil davon, war für mich eher immer mit GTK+ vergleichbar.
 
Ich versteife mich überhaupt nicht darauf, ich wollte wissen wie die Funktionen zum laden/etc. von shared libraries heissen, wenn man nicht weiss wonach man suchen muss, dann bringen die man-pages auch nichts.
Ich will ne Übersicht bzw. einen Index zu Funktionen die z.B. für Prozesshandling sind oder eben für shared libraries, die MSDN hat sowas sehr gut.

Vielleicht hilft Dir die Single Unix Specification. Oder der Klassiker: Avdanced Programming in the Unix Environment.

Ich glaube aber, dass Du ein generelles Verständnisproblem hast. Versteh das nicht negativ, Windows ist nun mal nicht mit Unix-artigen Systemen zu vergleichen. Im Gegensatz zu Windows stellt in FreeBSD (wie in Linux und anderen vergleichbaren Systemen) der Kernel bzw. "das System" selbst nur relativ wenige Schnittstellen zur Verfügung. Die Schnittstellen sind im wesentlichen auf Prozess-Handling und I/O begrenzt. Alles was darüber hinaus geht, z.B. GUI Programmierung, ist nicht Teil von FreeBSD sondern wird von anderen Programmen erledigt. Die grafische Ein-/Ausgabe wird vom X Server übernommen, d.h. um grafische Programme zu schreiben, musst Du Dich damit beschäftigen.

Ähnliches gilt für die Programmierumgebung. In Windows-Land gibt's ja zu Visual Studio keine echten Alternativen. In FreeBSD gibt's keine Standard-IDE, vielmehr gibt es Programme, die sich um Abhängigkeiten zw. Quelltexten u. Objektdateien kümmern, z.B. Make. Andere Programme kümmern sich um das Übersetzen selbst, z.B. GCC. Ein weiterer Satz von Programmen linkt Objektdateien zu ausführbaren Dateien oder Bibliotheken, z.B. die GNU Binutils.

Eben weil das Entwickeln so viele Schnittstellen und Programme benutzt, wirst Du schwer eine zum MSDN vergleichbare Auflistung aller Programme und Funktionen finden.

Mit Make habe ich schon rumgespielt, als ich den Code aus meinem Buch ausprobiert habe, und mit Ant habe ich mich auch kurz beschäftigt.
Beides ist aber genau das was ich mir nicht vorgestellt habe, wenn ich mit dem Studio von MS arbeite, da brauche ich mich auch nicht um irgendwelche Make-Files kümmern, die werden automatisch erzeugt. Wer das alles von Hand machen will kann das ja gerne machen, ich hab da keine Lust zu und beschäftige mich dann lieber mit anderen Dingen.

Wie schon von anderen erwähnt, Eclipse mit dem CDT Plugin macht Dir das automatisch.
 
J
Unter Windows gibts die WinAPI, darauf setzt die MFC auf (was ja dann QT entsprechen würde). Wie schreibe ich für ein FreeBSD ein Programm das ein Fenster anzeigt ohne QT oder GTK?
Unter Windows macht man das mit der API Funktion CreateWindowEx etc. Wie geht das unter nem FreeBSD?
Bin zwar kein Unix-Experte, aber hier mal mein Senf: FreeBSD und Konsorten kennen keine Grafik. Du mußt die mit Grafik bestücken, z.B. Xorg. Dann mußt du dir einen Window-Manager aussuchen, und dann optimalerweise einen Desktop. Und da sind die APIs alle unterschiedlich. Dann haste ein System vergleichbar mir Windows.

Wenn du dich mit C++ auskennst, kannst du locker mit der C++-Standard-Library, Boost und einem Toolkit a la FLTK programmieren, ohne dich auf eine Platform festzulegen. Gerade bei FreeBSD, Linux und Co ist es nicht immer sinnvoll platformspezifisch zu entwickeln, außer man will einen ganz bestimmten Kundenkreis bedienen oder super spezielle Features nutzen. Aber das ist bei Desktop-Anwendungen nicht immer der Fall.

Bei Win32 ist es anders, da erreicht man praktisch alle PC-Besitzer, da kann man dann speziell MFC benutzen, ohne das einem ein Haufen Kunden durch die Lappen gehen. (außer den Unix-Kunden, aber bei Desktop-Systemen kein Weltuntergang für einen Desktop-Entwickler)

Ich kann dir deshalb diese Seiten empfehlen, speziell bzgl. GUI:
http://kharchi.eu/wiki/doku.php?id=cpp:gui:basics
http://kharchi.eu/wiki/doku.php?id=cpp:gui:libs
 
Ich hab unter Windows auch schon mit wxWidgets gearbeitet, das würde ich hier unter FreeBSD dann auch machen, aber ich will das erst machen wenn ich weiss was auch am Ende ganz unten passiert.

Am Beispiel vom X-Server, wxWidgets/QT/Gtk/etc. muss ja auch irgendwie die Fenster zeichnen und Events oder sonst was senden und empfangen mit/nach welcher Technik auch immer.

@Vincent Vega
Vermutlich ist das so ja, mein Problem sind zum einen sicher die Grundlagen, zum anderen auch das das was ich kenne nicht 1:1 zu übertragen ist. Nur ist es eben schwer da nützliche Links oder Literatur zu finden, deshalb frag ich ja. :)
Die Bücher werd ich mir mal anschauen, auch einige andere Stichworte XLib sind ja gefallen, damit komme ich in jedem Fall schonmal etwas weiter.

@Amin
Naja es gibt den X-Server und WindowManager, das gehört zwar nicht zum OS, ist aber ja quasi ein Standard. Und die WindowManager rendern ja nicht sondern rufen irgendwelche Funktionen zum rendern. Also Grafikausgabe und das Handling damit muss irgendwo da vergraben sein, so stell ich mir das jedenfalls vor. Und ich will wissen wie das läuft bevor ich mit Signalen in QT oder Events in wxWidgets arbeite.
 
Warum willst du das wissen? Einfach nur aus Neugierde, oder weil du der Meinung bist, das man es wissen muß? Weil letzteres halte ich für falsch. Irgendwo ist immer eine Abstraktion, mit der man sich nicht mehr beschäftigen muß. (wollen ist ein anderes Thema) Denn dann kann man genauso gut fragen, ob du auf Windows tiefer als Win32-API gestiegen bist? Wahrscheinlich nicht? Warum nicht? :D Denn die Win32-API ist noch lange nicht das tiefste, was es gibt. Denn auch Win32-API ist eine Abstarktionsschicht und verbirgt noch Sachen, die man sich nicht beschäftigen muß aber könnte. ;)

Aber wenn es nur Neugierde ist, dann ist das i.O. :)
 
Ja im Grunde aus neugierde, unter Windows war ich mal mit der MFC an einem Punkt an dem es von Vorteil war zu wissen das intern die Events eigentlich "nur" Nachrichten sind. Ich will nicht alles bis ins letzte Detail kennen, aber halt wissen was da intern abläuft sei es auch nur grob.

Von dem was unter FreeBSD so läuft habe ich wenig bis keine Ahnung, deshalb möchte ich es wissen. :)
 
So ich hab Eclipse jetzt am Laufen, hab mich nun aber doch für KDevelop entschieden, da das CodeCompletion funktioniert (hatte das sonst nie hinbekommen) und Eclipse mir mein Projekt nicht übersetzt, obwohl ich mich an die Anleitung gehalten habe und ein makefile genau wie beschrieben erzeugt habe etc.

Das Problem war um Eclipse nicht lief mit Java war, vermutlich, das ich Diablo für FreeBSD 6.x heruntergeladen und installiert habe, nachdem ich dann das für die 7.x Version genommen habe funktionierte es dann auch.
 
Wenn du in Eclipse CDT die automatisch generierten Makefiles verwenden willst, musst du in deinem Projekt gmake als Make-Tool eintragen.
 
von Vorteil war zu wissen das intern die Events eigentlich "nur" Nachrichten sind.

So steht es übrigens auch im Wörterbuch (neben "Ereignis") :)

Unter MS-Windows (als ich noch jung war), habe ich auch immer mit IDEs entwickelt. Heute entwickle ich primär unter FreeBSD, da die Sachen, die hier entstehen so weit portabel sind, dass sie oft automatisch unter MS-Windows laufen (kümmert mich aber eher nicht, da ich kein MS-Windows beim Entwickeln einschalte). Und Programmieren nehme ich sofort gvim und das normale BSD-make. Natürlich sind oft diverse Libraries in Gebrauch (auch selbstgeschriebene).

DLLs (SOs) programmatisch zu laden, wie es vorher aufgezeigt wurde, mache ich selten. Das kann man eher für so etwas wie Plugins verwenden, wo viele verschiedene Plugins die gleiche API exponieren aber verschieden arbeiten. Die normalen SOs "lade ich" per -R beim Linken. In den meisten Fällen kümmere ich mich aber nicht darum und linke mit -l. Vieles wird sowieso nur als Stub gebunden.

Als Widget-Kit nehme ich GTK+. Dialoge und Fenster kann man auch ohne IDEs entwickeln (mache ich übrigens auch unter Java so, mit gvim und ant). Zur Entwicklung gehört auch Versionierung und Code-Management. Hier fiel meine Wahl vor kurzem auf git (vorher: CVS).
 
Zur Versionsverwaltung setzt ich schon seit Jahren CVS ein, sowohl beruflich als auch privat, hat gute Dienste geleistet. :)
 
Zurück
Oben