@node Hintergrundinfos
@chapter Hintergrundinfos
@cindex Hintergrundinfos

@menu
* Zusammenarbeit mit anderen Programmen::
* Systemlisten und Schutzprotokolle::
@end menu


@c ----------------------------------------
@node Zusammenarbeit mit anderen Programmen
@section Zusammenarbeit mit anderen Programmen
@cindex Zusammenarbeit mit anderen Programmen

   @file{@sc{RSys}} wurde unter Berücksichtigung aller mir bekannten
Richtlinien der Programmierung unter AmigaOS 2.0 geschrieben.  Alle
kritischen Routinen wurden bis zu dreimal abgesichert.  Das bläht zwar
etwas den Code, gewährleistet aber die Lauffähigkeit auch unter
Betriebssystemen >= 2.04.

   Besonderer Wert wurde auf die Vermeidung von Speicherfehlern und
@file{Enforcer}-Hits gelegt.  Bei einem auftretenden Speicherfehler wird
in den meisten Fällen das Programm unter Angabe von Quelldatei- und
Funktionsname, sowie der Zeilennummer im Quelltext abgebrochen und
beendet.

@file{@sc{RSys}} ist darauf ausgelegt, mit allen Programmen so gut wie
möglich zusammenzuarbeiten.  Das schließt jedoch die Programme aus, die
von Haus aus Hacks sind, die sich nicht an die Programmierrichtlinien
unter AmigaOS halten.  Weiterhin hat @file{@sc{RSys}} keinerlei Problem
mit systemkonformen Patches, wie z.B.  @file{MagicMenu} von Martin
Korndörfer, oder @file{MFR} von Stefan Stuntz.

   Viele Leute haben mich per EMAIL angeschrieben, daß ich doch bitte
OS 3.0-Features verwenden soll. @file{@sc{RSys}} soll eigentlich unter
allen Systemen >2.0 laufen, weswegen ich spezielle Features von 3.0
absichtlich vermieden habe. Ausnahmen bilden jedoch einige verwendete
Tags, wie z.B. die @code{GTM_NewLookMenus}, das die
Standard-3.0-Menüfarben einstellt. Diese werden von OS 2.x-System
ignoriert, womit also dem Einbau nichts im Wege stand.

   Ein weiteres Feature von OS 3.0 ist die Routine
@code{GT_GetGadgetAttrsA} der @file{gadtools.library}. Damit wird eine
vollständige Steuerung der ListView-Gadgets über Pfeiltasten ermöglicht.
Diese ist jedoch unter 2.x noch nicht implementiert, sodaß auch dieses
Feature in @file{@sc{RSys}} aus Gründen der Kompatibilität nichts zu
suchen hat.


@c ----------------------------------------
@node Systemlisten und Schutzprotokolle
@section Systemlisten und Schutzprotokolle
@cindex Systemlisten und Schutzprotokolle

   Intuition-Objekte werden beim Auslesen der Daten mit dem Protokoll
@dfn{LockIBase() / UnlockIBase()} geschützt.  Damit werden die jeweiligen Listen
vor der Veränderung durch Intuition-Routinen während des Auslesens
ausreichend geschützt.  Bei der Veränderung der Objekte durch @file{@sc{RSys}}
ist selten ein Schutzprotokoll erforderlich, da die Routinen von Intuition
dieses meistens selbst erledigen.

   Alle  Exec-Objekte,  wie  Tasks, Ports, Libraries, etc., werden während
des Auslesens durch ein @dfn{Forbid()/Permit()}, im Falle von Tasks, sogar durch
ein @dfn{Disable()/Enable()} vor Veränderung durch Systemroutinen geschützt.  Im
Falle  der  Tasks ist zum Auslesen der Taskzeiger das Protokoll @dfn{Disable()/Enable()}
zu  verwenden,  zum  Auslesen der Taskstruktur reicht jedoch ein
@dfn{Forbid()/Permit()}.

   @dfn{Disable()/Enable()} sollte deswegen verwendet werden, da die Systemliste
in  der  ExecBase durch den interruptgesteuerten Task-Scheduler laufend in
ihrer  Anordnung  geändert  wird  (man  denke nur an die Aktivierung eines
Tasks,  also  die  Umsetzung  des entsprechenden Taskknotenzeigers aus der
Wait-Liste   in   die   Ready-Liste   und   dann  in  den  Running-Zustand
[ExecBase->ThisTask-Eintrag]).

   Die  Task-Struktur  selber  kann jedoch nur von einem Task oder Prozeß
aus  verändert  werden.   Daher  reicht  zum Auslesen der Taskstruktur das
Protokoll  @dfn{Forbid()/Permit()}  aus.   Daraus  ergibt  sich  also  folgendes
Schema:

@display
   Reservieren der eigenen Struktur-Speicherbereiche

   @dfn{Forbid()};

      @dfn{Disable()};
      Auslesen und Merken der Tasknodes
      @dfn{Enable()};

      Auslesen der Taskstrukturen in eigene Strukturen (@emph{ohne}
      Verwendung von DOS-Routinen, also KEIN FGets(), Open() etc.)

   @dfn{Permit()};

   Auswerten der eigenen Strukturen
   Freigeben der eigenen Struktur-Speicherbereiche
@end display

   Für die Implementation dieser Routinen könnt Ihr den dokumentierten
Quelltext einsehen.

   Unter diesen Vorsichtsmaßnahmen sollte es keine Probleme im
Zusammenspiel mit anderen Programmen geben, bis auf eine Einschränkung:
@file{@sc{RSys}} kann nicht mit Programmen zusammenarbeiten, die
nicht systemkonform programmiert wurden.  Beispiele dafür sind Programme,
die beispielsweise den Namen eines öffentlichen Ports nicht korrekt
initialisieren.  So kommt es beispielsweise vor, daß ein Programm zwar
einen Zeiger auf einen Portnamen ungleich Null hat, diesen Zeiger aber
uninitialisiert läßt und dieser dann folglich irgendwohin zeigt.  Die
Folge ist im harmlosesten Fall ein @file{Enforcer}-Hit des Typs
@code{READ-BYTE} (beim Auslesen des vermeintlichen Strings), im extremsten
Fall ein Guru!

   Ich habe das Problem jetzt so gelöst, daß ich bei den auszulesenen
Node-Namen das Typen-Flag untersuche.  Steht dort der Eintrag @code{NT_UNKNOWN}
oder nicht das erwartete Flag, lese ich den String einfach nicht aus,
sondern trage in das ListView

@example
   <wrong type:0>
@end example

ein. Hierbei steht die @code{0} für den ermittelten Knotentypen. Die
möglichen Knotentypen sind:

@example
 Wert       Typ
------------------------------------------------------
   0        Unbekannter Node-Typ
   1        Task
   2        Interrupt
   3        Device
   4        Message Port
   5        Message
   6        @code{freie} Message
   7        Message wurde beantwortet
   8        Resource
   9        Library
  10        Memory-Node
  11        Softinterrupt
  12        Font
  13        Prozeß
  14        Semaphor
  15        Signalsemaphor
  16        Boo-Node
  17        Kick-Memory-Node
  18        Graphics-Node (Monitor-Node z.B.)
  19        Death Message (eine @code{tote} Nachricht)
 254        Benutzerdefinierter Node
 255        Erweiterung (auch benutzerdefiniert)
@end example

   Manche Systemutilities (z.B.  ARTM) achten darauf nicht und produzieren
@file{Enforcer}-Hits  en mas.  Diese Fehler lassen sich auch nicht vermeiden.  Der Aufwand
dafür  wäre  einfach  zu  groß,  da  man  ja praktisch Teile des Programms
@file{Enforcer}  in  das eigene Programm implementieren müßte.  Solange man nicht
davon  ausgehen  kann, daß @emph{JEDER} Programmierer systemkonform programmiert,
wird es diese Lücke auch weiterhin geben.

@findex strcpy()
   Ein weiterer typischer Fehler ist die Verwendung der Compiler-Funktion
@dfn{strcpy()} auf Quellstrings vorher unbekannter Länge.  Viele
Programmierer verwenden diese Routine, um schneller Strings zu kopieren.
Dabei wird nicht beachtet, daß man eventuell  gar nicht soviel Speicherplatz
reserviert hat, um den Quellstring aufzunehmen.  Ein signifikantes
Beispiel dafür ist das o.g.  Port-Namen-Problem.  Ist der String
uninitialisiert und nicht mit @code{ASCII 0} terminiert, kopiert
@dfn{strcpy()} einen solchen Portnamen bis in alle Ewigkeit, bis zum Ende
des Speichers, bis zur nächsten Einsprungadresse eines anderen Tasks oder
bis zur nächsten Reise von Indian tours @code{:-)}
Manche  Programmierer sagen sich dann, überprüfen wir doch einfach mit
@dfn{strlen()}  den Quellstring.  Nun, da @dfn{strlen()} auch solange zählt, bis @code{ASCII
0} erkannt wurde, ist diese Methode auch für eine Auslandsreise nach Indien
durchaus geeignet.
@findex strlen()
@findex strncpy()

   Das einfachste und probateste Mittel in diesem Fall, ist die
Compiler-Funktion @dfn{strncpy()}.  Damit kann man einfach festlegen,
wieviel Zeichen denn nun kopiert werden sollen.  Das einzige, was jetzt
noch stört, ist der @code{READ-BYTE}-Hit den man bekommt, wenn man
@emph{merkwürdige} Adressen an @dfn{strncpy()} übergibt.

   Ein  weitere  Fehlerquelle  ist  die  Verwendung  von @dfn{printf()} in allen
seinen Erscheinungsformen (@dfn{sprintf()}, @dfn{vsprintf()} etc.) im Zusammenhang mit
Systemlisten.   Da  die @dfn{printf()}-Routinen auch auf DOS-Routinen zugreifen,
sind  sie  zum  zügigen  Kopieren von mehreren Systemeinträgen ungeeignet.
Die Routine @dfn{RawDoFmt()} der Exec-Library ist jedoch @emph{sicher}. Mit ihr kann
man sich selbst ein @dfn{sprintf()} zusammenbauen, was ich auch getan habe.
Normalerweise befindet sich aber diese Routine in der @file{amiga.lib}.
@findex RawDoFmt()
@findex sprintf()

   Sicher  ist weiterhin die Verwendung der @dfn{str...()}-Routinen
zwischen Schutzprotokollen, da
diese  nur  Speicherbereiche  kopieren  oder  verschieben.   Möchte man es
trotzdem  noch  schneller  haben,  gibt es  noch die Funktionen @dfn{CopyMem()} und
@dfn{CopyMemQuick(}).    Bei   letzterer   ist   zu   beachten,  daß  die  Daten
auf longwords ausgerichtet   sein   müssen.    Beide   Routinen   gehören   zur
@file{exec.library}, können also bei Systemlistenuntersuchungen verwendet werden.
@findex CopyMem()
@findex CopyMemQuick()

