home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / progtool / c / xacclib / xacc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-22  |  13.6 KB  |  470 lines

  1. /* XACC.C - Routinen zur Behandlung des XACC-Protokolls
  2.             nach der Spezifikation vom 28. November 1992,
  3.             erweitert um Mag!X 2.0
  4.     (c) 1993 Harald Sommerfeldt @ KI
  5.     E-Mail:  Harald_Sommerfeldt@ki.maus.de
  6. */
  7.  
  8. /* Geschichte:
  9.     22.03.93: erste Version
  10.     03.08.93: läuft auch unter Speicherschutz (MiNT)
  11.     05.09.93: überarbeitet und als seperater Quelltext XACC.C
  12.     06.09.93: fängt weitesgehend Blindgänger (z.B. Watchdog 1.4) ab
  13.     09.09.93: - neue Funktion xacc_malloc()
  14.               - die Variable 'xacc' wird nun beachtet
  15.               - Mag!X-Versionsabfrage, um Endlosschleife bei Mag!X 1.x zu verhindern
  16.     04.10.93: - Anpassung an GNU-C (16-Bit int) von Christian Felsch @ HH
  17.     31.10.93: - Anpassung an GNU-C (32-Bit int), klappt aber noch nicht!
  18.               - xacc_send() überarbeitet, neue Routine xacc_decode()
  19.               - getcookie() (MyLibs-kompatibel) statt xacc_cookie()
  20. */
  21.  
  22. /* Hinweise:
  23.     - dieser Quelltext ist Freeware und darf daher nur umsonst und nur
  24.       komplett (XACC.C, XACC.H, XACC_EXT.H, XACC_EXT.C, XACCTEST.C, XACCTEST.PRJ,
  25.       XACCTEST.PRG, MAKEFILE, XACC2.TXT) weitergegeben werden!
  26.     - dieser Quelltext kann ohne Hinweis auf mein Copyright in eigene Programme
  27.       nach belieben eingebunden werden, die Entfernung meines Copyrightes in
  28.       diesen Quelltexten ist jedoch nicht erlaubt!
  29.     - dieser Quelltext wurde mit Tabweite 3 entwickelt
  30. */
  31.  
  32.  
  33. #define XACC_ACC
  34. /* Dieses Routinen funktionieren auch, wenn das Programm als ACC läuft.
  35.     Ist dies bei eigenen Programmen nicht der Fall, so können die dafür
  36.     zuständigen Routinen durch Löschung dieser Zeile ausmaskiert werden,
  37.     um redundanten Quellcode zu vermeiden. */
  38.  
  39. #define XACC_PRG
  40. /* Dieses Routinen funktionieren auch, wenn das Programm als PRG läuft. */
  41.  
  42. /* #define XACC_SMALL */
  43. /* Diese Routinen können nur als ACC per XACC empfangen, nicht selber senden.
  44.     Dies ist z.B. sinnvoll, wenn man als ACC das XACC nicht aktiv benutzt,
  45.     d.h. selbst keine Applikationen anmorsen will, man kann aber korrekt
  46.     durch XACC angesprochen werden.
  47.    Das XACC-Protokoll ist hierbei vollständig implementiert!!! */
  48.  
  49.  
  50. #if !defined( XACC_ACC ) && !defined( XACC_PRG )
  51. #error Warum binden Sie diesen Quelltext überhaupt ein?
  52. #endif
  53. #if defined( XACC_SMALL ) && defined( XACC_PRG )
  54. #error XACC_SMALL ist nur bei ACCs möglich
  55. #endif
  56.  
  57. #if defined(__TURBOC__) || defined(__PUREC__)
  58. #define __MSHORT__
  59. #endif
  60.  
  61. #ifdef __PUREC__
  62. #include <aes.h>
  63. #include <tos.h>
  64. #include <stddef.h>
  65. #endif
  66. #ifdef __GNUC__
  67. #include <gemfast.h>
  68. #include <aesbind.h>
  69. #include <osbind.h>
  70. #include <stdlib.h>
  71. #include <stdio.h>
  72. #include "gemext.h"
  73. #endif
  74.  
  75. #include <string.h>
  76. #include "xacc_ext.h"
  77. #include "xacc.h"
  78.  
  79. /* benötigte AES-Definitionen */
  80. #ifdef __PUREC__
  81. #define ap_version    _GemParBlk.global[0]    /* AES-Versionsnummer (z.B. 0x140 = 1.40) */
  82. #define ap_count        _GemParBlk.global[1]    /* Anzahl der max. laufenden Applikationen */
  83. #define ap_id            _GemParBlk.global[2]    /* eigene ID */
  84. #endif
  85. #ifdef __GNUC__
  86. #define ap_version    gl_ap_version
  87. #define ap_count        _global[1]
  88. #define ap_id            gl_apid
  89. #endif
  90.  
  91. /* benötigte allgemeine Definitionen */
  92. #define NIL        -1
  93. typedef enum { FALSE, TRUE } bool;
  94.  
  95.  
  96. /* globale Variablen */
  97. static bool xacc;                        /* XACC-Protokoll aktiviert */
  98. static bool xacc_singletask;        /* alte Spezifikation vom 12.3.89 verwenden? */
  99. static char *xacc_name;                /* Platz für den eigenen XACC-Namen */
  100. static unsigned xacc_groups;        /* eigenes XACC-Group-Wort */
  101. static int xacc_menuid;                /* die ID des Menüeintrages bzw. -1 */
  102.  
  103. #ifndef XACC_SMALL
  104. struct xaccs xaccs[MAX_XACC];        /* Strukturen, um sich die XACC-Partner zu merken */
  105. #endif
  106.  
  107.  
  108. /* XACC-Protokoll initialisieren,
  109.     diese Routine MUSS beim Programmstart irgendwann nach appl_init() aufgerufen werden */
  110.  
  111. int    xacc_init( int menu_id, const char *name, int sizeofname, unsigned groups )
  112. {
  113.     long    value;
  114.     int    i;
  115.  
  116.     xacc = TRUE;
  117.  
  118.     /* den XACC-Namen in einem global zugänglichen Block (Speicherschutz!) unterbringen */
  119.     xacc_name = xacc_malloc( sizeofname );
  120.     if ( xacc_name == NULL ) return xacc = FALSE;
  121.     memcpy( xacc_name, name, sizeofname );
  122.  
  123.     /* die Menü-ID und das Group-Wort merken */
  124.     xacc_menuid = menu_id;
  125.     xacc_groups = groups;
  126.  
  127. #ifndef XACC_SMALL
  128.     /* erstmal alle Einträge löschen */
  129.     for ( i = 0; i < MAX_XACC; i++ ) xaccs[i].id = -1;
  130. #endif
  131.  
  132.     /* unter einem Multi-AES-TOS gilt die neue Spezifikation... */
  133.     if ( ap_count != 1 ) {
  134.         xacc_singletask = FALSE;
  135.         /* AES 4.0 (z.B. MTOS) oder MagX 2.x ? */
  136.         if ( ap_version >= 0x400 ||
  137.              (getcookie( 0x4D616758L /*'MagX' */, &value ) && ((short **)value)[2][24] >= 0x200) ) {
  138.             int    type, id;
  139.             char    name[10];
  140.  
  141.             /* ...wir senden also an alle Applikationen unseren Willkommensgruß */
  142.             for ( i = appl_search( 0, name, &type, &id ); i; i = appl_search( 1, name, &type, &id ) ) {
  143.                 if ( (type & 6) != 0 ) xacc_id( id, ACC_ID );
  144.             }
  145.         }
  146.         else xacc = FALSE;        /* sorry, wird wohl nichts draus... */
  147.     }
  148.  
  149.     /* ansonsten handelt es sich um ein altes, trostloses Singletasking-AES,
  150.        wo wir das angestaubte XACC-Protokoll vom 12.3.89 verwenden */
  151.     else xacc_singletask = TRUE;
  152.  
  153.     return xacc;
  154. }
  155.  
  156.  
  157. /*    XACC-Protokoll deinitialisieren,
  158.     diese Routine MUSS irgendwann beim Programmende vor appl_exit() aufgerufen werden */
  159.  
  160. #ifndef XACC_SMALL
  161. void    xacc_exit( void )
  162. {
  163.     int    i;
  164.  
  165.     /* Im Multitasking-Fall ... */
  166.     if ( !xacc_singletask ) {
  167.  
  168.         /* ... verabschieden wir und brav und höflich (mittels ACC_EXIT) */
  169.         for ( i = 0; i < MAX_XACC; i++ ) {
  170.             if ( xaccs[i].id >= 0 ) xacc_id( xaccs[i].id, ACC_EXIT );
  171.         }
  172.     }
  173.     if ( xacc_name != NULL ) Mfree( xacc_name );
  174. }
  175. #endif
  176.  
  177.  
  178. /* einen globalen (und damit für XACC geeigneten) Speicherblock allozieren */
  179.  
  180. void    *xacc_malloc( long amount )
  181. {
  182.     void    *result;
  183.  
  184.     if ( ap_version >= 0x0400 && getcookie( 0x4D694E54L /*'MiNT' */, NULL ) )
  185.         result = (void *)Mxalloc( amount, 0x0022 );
  186.     else
  187.         result = (void *)Malloc( amount );
  188.     return result;
  189. }
  190.  
  191.  
  192. /*    die Nachricht in msgbuf verarbeiten, falls es sich um eine
  193.     Nachricht des Types AC_CLOSE, ACC_ID, ACC_ACC oder ACC_EXIT handelt;
  194.     es wird TRUE zurückgegeben, falls die Nachricht komplett verarbeitet wurde */
  195.  
  196. int    xacc_message( const int *msgbuf )
  197. {
  198.     int    i;
  199.  
  200.     if ( !xacc ) return FALSE;
  201.  
  202. #ifdef XACC_ACC
  203.     if ( msgbuf[0] == AC_CLOSE ) {
  204.  
  205.         /*    wenn wir dem Singletasking-Protokoll hörig sind,
  206.             ist dies der Moment, wo der Elefant das Wasser läßt:
  207.             das XACC-Protokoll wird angekurbelt */
  208.         if ( xacc_singletask ) {
  209.  
  210. #ifndef XACC_SMALL
  211.             /* erstmal alle Einträge löschen... */
  212.             for ( i = 0; i < MAX_XACC; i++ ) xaccs[i].id = -1;
  213. #endif
  214.  
  215.             /*    ...dann die Lawine in Gang setzen: ACC_ID ans Haupt-
  216.                 programm verschicken; die Bedingung ap_id != 0 sollte
  217.                 hierbei eigentlich immer erfüllt sein, aber man weiß
  218.                 ja nie, wer einem so alles eine AC_CLOSE-Nachricht
  219.                 andrehen will (z.B. Schlemi) */
  220.             if ( ap_id != 0 ) xacc_id( 0, ACC_ID );
  221.         }
  222.         return FALSE;
  223.     }
  224. #endif
  225.  
  226.     if ( msgbuf[0] == ACC_ID ) {
  227.  
  228.         /* wenn wir dem Single-Tasking-Protokoll hörig sind,
  229.             ist dies der Moment, wo der Elefant das Wasser gelassen hat:
  230.             das XACC-Protokoll wurde angekurbelt */
  231.         if ( xacc_singletask ) {
  232. #ifdef XACC_PRG
  233.             if ( ap_id == 0 ) {    /* nur wenn wir ein PRG sind... */
  234.                 int    mymsgbuf[8];
  235.  
  236.                 /* ...verschicken wir fleißig Grußkarten (ACC_ACC) */
  237.                 mymsgbuf[0] = ACC_ACC;
  238.                 mymsgbuf[1] = ap_id;
  239.                 mymsgbuf[2] = 0;
  240.                 mymsgbuf[3] = msgbuf[3];
  241.                 mymsgbuf[4] = msgbuf[4];
  242.                 mymsgbuf[5] = msgbuf[5];
  243.                 mymsgbuf[6] = msgbuf[6];
  244.                 mymsgbuf[7] = msgbuf[1];
  245.                 for ( i = 0; i < MAX_XACC; i++ ) {
  246.                     if ( xaccs[i].id >= 0 ) appl_write( xaccs[i].id, 16, mymsgbuf );
  247.                 }
  248.                 /* dem Auslöser dieser Lawine einen Heiratsantrag schicken */
  249.                 xacc_id( msgbuf[1], ACC_ID );
  250.             }
  251. #else
  252.             ;
  253. #endif
  254.         }
  255.  
  256.         /* im Falle des Multitasking-Protokolls tut sich hier nicht
  257.             ganz so viel: Wir erwiedern das Moin (ACC_ID) mit Moin-Moin (ACC_ACC) */
  258.         else xacc_id( msgbuf[1], ACC_ACC );
  259.  
  260. #ifndef XACC_SMALL
  261.         /* auf jeden Fall lassen wir ein ACC_ID nicht ungestraft
  262.             durchgehen, der Absender wird in der Fahndungsliste vermerkt! */
  263.         xacc_remid( msgbuf[1], msgbuf );
  264. #endif
  265.  
  266.         return TRUE;
  267.     }
  268.  
  269.     if ( msgbuf[0] == ACC_ACC ) {
  270.  
  271.         /* ACC_ACC ist vergleichsweise harmlos: Im Singletasking-Fall
  272.             erhalten wir so als ACC von anderen ACCs Kenntnis (und
  273.             vermitteln diesen die Kenntnis über uns), im Multitasking-Fall
  274.             ist dies einfach das Moin-Moin auf das Moin (ACC_ID)
  275.             ACHTUNG: Im ersten Fall steht die interessante Id bei
  276.                      msgbuf[7], im zweiteren bei msgbuf[1]! */
  277.         if ( xacc_singletask ) {
  278. #ifdef XACC_ACC
  279.             if ( ap_id != 0 ) {    /* sollte eigentlich immer der Fall sein,
  280.                                     im Falle Watchdog 1.4 leider nicht :-((( */
  281.                 xacc_id( msgbuf[7], ACC_ID );
  282. #ifndef XACC_SMALL
  283.                 xacc_remid( msgbuf[7], msgbuf );
  284. #endif
  285.             }
  286. #else
  287.             ;
  288. #endif
  289.         }
  290. #ifndef XACC_SMALL
  291.         else xacc_remid( msgbuf[1], msgbuf );
  292. #endif
  293.         return TRUE;
  294.     }
  295.  
  296.     if ( msgbuf[0] == ACC_EXIT ) {
  297.  
  298.         /* Der Untergang der Titanic, hier allerdings nicht ohne
  299.             Vorankündigung: Die Id wird mangels grünen Punkt nicht
  300.             wiederverwertet, sondern wandert auf den Müll */
  301.         xacc_killid( msgbuf[1] );        /* wech mit den Altlasten */
  302.         return TRUE;
  303.     }
  304.  
  305.     return FALSE;
  306. }
  307.  
  308.  
  309. /* ein Teil des Ganzen als XACC-Nachricht versenden
  310.     dest_id : die ap_id des glücklichen Empfängers
  311.     message : Nachrichtentyp (ACC_KEY, ACC_TEXT, ACC_IMG oder ACC_META)
  312.     last    : Letzter Speicherblock? (FALSE/TRUE) bzw. Tastaturcode
  313.     addr    : Adresse des Speicherblockes
  314.     length  : Länge des Speicherblockes
  315. */
  316.  
  317. int    xacc_send( int dest_id, int message, int last_or_keycode, void *addr, long length )
  318. {
  319.     int    msgbuf[8];
  320.  
  321.     msgbuf[0] = message;
  322.     msgbuf[1] = ap_id;
  323.     msgbuf[2] = 0;
  324.     msgbuf[3] = last_or_keycode;
  325.  
  326. #ifdef __MSHORT__
  327.     *(const char **)(msgbuf+4) = addr;
  328.     *(long *)(msgbuf+6) = length;
  329. #else
  330.     msgbuf[4] = (long)addr >> 16;
  331.     msgbuf[5] = (long)addr & 0xFFFF;
  332.     msgbuf[6] = length >> 16;
  333.     msgbuf[7] = length & 0xFFFF;
  334. #endif
  335.     return appl_write( dest_id, 16, msgbuf );
  336. }
  337.  
  338.  
  339. /* XACC-Nachricht entschlüsseln
  340.     msgbuf  : die empfangene Message-Buffer
  341.    Rückgabewerte:
  342.     plast   : Letzter Speicherblock? (FALSE/TRUE) bzw. Tastaturcode
  343.     paddr   : Adresse des empfangenden Speicherblockes
  344.     plength : Länge des empfangenden Speicherblockes
  345. */
  346.  
  347. int    xacc_decode( const int *msgbuf, int *plast_or_keycode, void **paddr, long *plength )
  348. {
  349.     if ( plast_or_keycode != NULL )
  350.         *plast_or_keycode = msgbuf[3];
  351. #ifdef __MSHORT__
  352.     if ( paddr != NULL )
  353.         *paddr = *(void **)(msgbuf+4);
  354.     if ( plength != NULL )
  355.         *plength = *(long *)(msgbuf+6);
  356. #else
  357.     if ( paddr != NULL )
  358.         *paddr = (void *)((msgbuf[4] << 16) | (msgbuf[5] & 0xFFFF));
  359.     if ( plength != NULL )
  360.         *plength = (msgbuf[6] << 16) | (msgbuf[7] & 0xFFFF);
  361. #endif
  362.     return msgbuf[0];
  363. }
  364.  
  365.  
  366. /* ACC_ACK als Antwort auf ACC_TEXT, ACC_KEY, ACC_META oder ACC_IMG versenden
  367.     dest_id : die ap_id des (un-)glücklichen Empfängers
  368.     ok      : TRUE oder FALSE */
  369.  
  370. int    xacc_ack( int dest_id, int ok )
  371. {
  372.     int    msgbuf[8];
  373.  
  374.     msgbuf[0] = ACC_ACK;
  375.     msgbuf[1] = ap_id;
  376.     msgbuf[2] = 0;
  377.     msgbuf[3] = ok;
  378.     msgbuf[4] = msgbuf[5] = msgbuf[6] = msgbuf[7] = 0;
  379.     return appl_write( dest_id, 16, msgbuf );
  380. }
  381.  
  382.  
  383. /* die eigene XACC-ID versenden
  384.     dest_id : die ap_id des glücklichen Empfängers
  385.     message : ACC_ID oder ACC_ACC, je nach Lust & Laune */
  386.  
  387. int    xacc_id( int dest_id, int message )
  388. {
  389.     int    msgbuf[8];
  390.  
  391.     /* da in xacc_init() die eigene ap_id nicht herausgefiltert wird,
  392.        wird hier verhindert, daß wir uns selber eine Nachricht schicken */
  393.     if ( dest_id != ap_id ) {
  394.         msgbuf[0] = message;            /* Nachrichtentyp */
  395.         msgbuf[1] = ap_id;            /* unsere ap_id */
  396.         msgbuf[2] = 0;                    /* Länge der Nachricht - 16 */
  397.         msgbuf[3] = xacc_groups;    /* die von uns unterstützten XACC-Gruppen */
  398. #ifdef __MSHORT__
  399.         *(const char **)(msgbuf+4) = xacc_name;    /* unser XACC-Name */
  400. #else
  401.         msgbuf[4] = (long)xacc_name >> 16;
  402.         msgbuf[5] = (long)xacc_name & 0xFFFF;
  403. #endif
  404.         msgbuf[6] = xacc_menuid;    /* unsere Menükennung (falls ACC), sonst -1 */
  405.         msgbuf[7] = NIL;                /* reserviert */
  406.         return appl_write( dest_id, 16, msgbuf );
  407.     }
  408.     return 0;
  409. }
  410.  
  411.  
  412. /* XACC-Eintrag vermerken (bei ACC_ID & ACC_ACC)
  413.     id     : die ap_id des Absenders,
  414.     msgbuf : der empfangene Nachrichtenpuffer */
  415.  
  416. #ifndef XACC_SMALL
  417. int    xacc_remid( int id, const int *msgbuf )
  418. {
  419.     int    i;
  420.  
  421.     /* eventuell alten Eintrag mit der gleichen Id vorher löschen.
  422.        es gibt verschiedene Fälle, wo dies notwendig ist:
  423.        - ein Eintrag ist veraltet, da das Programm abgestürzt ist
  424.          und daher kein ACC_EXIT versandt hat
  425.        - beim Singletasking-Protokoll kann ein ACC mehrere ACC_ACC
  426.          vom gleichen ACC erhalten
  427.        - beim Multitasking-Protokolls erhält ein ACC _IMMER_ von einem
  428.          anderen ACC beim Neustart des Rechners sowohl ein ACC_ID als
  429.          auch ein ACC_ACC
  430.     */
  431.     xacc_killid( id );
  432.  
  433.     /* nun gehts aber los! */
  434.     for ( i = 0; i < MAX_XACC; i++ ) {    /* XACC-Liste abklappern */
  435.         if ( xaccs[i].id < 0 ) {                /* freier Eintrag gefunden */
  436.             xaccs[i].id = id;                    /* Eintrag vermerken */
  437.             xaccs[i].groups = msgbuf[3];
  438. #ifdef __MSHORT__
  439.             xaccs[i].name = *(const char **)(msgbuf+4);
  440. #else
  441.             xaccs[i].name = (const char *)((msgbuf[4] << 16) | (msgbuf[5] & 0xFFFF));
  442. #endif
  443.             return TRUE;
  444.         }
  445.     }
  446.  
  447.     return FALSE;
  448. }
  449. #endif
  450.  
  451.  
  452. /* XACC-Eintrag löschen (z.B. bei ACC_EXIT)
  453.     id : die nicht mehr gültige ap_id */
  454.  
  455. #ifndef XACC_SMALL
  456. int    xacc_killid( int id )
  457. {
  458.     int    i;
  459.  
  460.     for ( i = 0; i < MAX_XACC; i++ ) {    /* XACC-Liste abklappern */
  461.         if ( xaccs[i].id == id ) {            /* Id gefunden ! */
  462.             xaccs[i].id = NIL;                /* Eintrag in der Liste freigeben */
  463.             return TRUE;
  464.         }
  465.     }
  466.  
  467.     return FALSE;
  468. }
  469. #endif
  470.