home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / fsrc1241.zip / rexxexec.c < prev    next >
C/C++ Source or Header  |  1999-02-14  |  73KB  |  2,216 lines

  1. /*---------------------------------------------------------------------------+
  2.  | Titel: REXXEXEC.C                                                         |
  3.  +-----------------------------------------+---------------------------------+
  4.  | Erstellt von: Michael Hohner            | Am: 10.08.1994                  |
  5.  +-----------------------------------------+---------------------------------+
  6.  | System: OS/2 2.x PM                                                       |
  7.  +---------------------------------------------------------------------------+
  8.  | Beschreibung:                                                             |
  9.  |                                                                           |
  10.  |   Rexx-Ausfuehrung                                                        |
  11.  |                                                                           |
  12.  |                                                                           |
  13.  +---------------------------------------------------------------------------+
  14.  | Bemerkungen:                                                              |
  15.  +---------------------------------------------------------------------------*/
  16.  
  17. /*----------------------------- Header-Dateien ------------------------------*/
  18. #pragma strings(readonly)
  19.  
  20. #define INCL_BASE
  21. #define INCL_PM
  22. #include <os2.h>
  23. #define INCL_REXXSAA
  24. #include <rexxsaa.h>
  25. #include <stdlib.h>
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include "main.h"
  29. #include "resids.h"
  30. #include "messages.h"
  31. #include "structs.h"
  32. #include "msgheader.h"
  33. #include "areaman\areaman.h"
  34. #include "dialogids.h"
  35. #include "rexxexec.h"
  36. #include "mainwindow.h"
  37. #include "savemsg.h"
  38. #include "utility.h"
  39. #include "fltv7\fltv7.h"
  40. #include "lookups.h"
  41. #include "ccmanage.h"
  42. #include "controls\editwin.h"
  43. #include "handlemsg\handlemsg.h"
  44. #include "handlemsg\kludgeapi.h"
  45. #include "util\addrcnv.h"
  46. #include "dump\expt.h"
  47.  
  48. /*--------------------------------- Defines ---------------------------------*/
  49.  
  50. #define ERRORMSGFILE    "rex.msg"
  51. #define ERROREXPLFILE   "rexh.msg"
  52. #define REXXENVNAME     "FLEETSTREET"
  53.  
  54. #define STDIN   0
  55. #define STDOUT  1
  56. #define STDERR  2
  57.  
  58. /*---------------------------------- Typen ----------------------------------*/
  59.  
  60. typedef struct _STRINGLIST {
  61.             struct _STRINGLIST *next;
  62.             PCHAR pchLine;
  63.          } STRINGLIST, *PSTRINGLIST;
  64.  
  65. typedef struct {
  66.             HMTX        hmtxQueueAccess;
  67.             HEV         hevQueueAdd;
  68.             PSTRINGLIST pLines;
  69.          } IOQUEUE, *PIOQUEUE;
  70.  
  71. typedef struct {
  72.             ULONG   ulStatus;
  73.             BOOL    bNotify;
  74.          } MONITORDATA, *PMONITORDATA;
  75.  
  76. #define REXXSTATUS_WAITFORSTART   0
  77. #define REXXSTATUS_RUNNING        1
  78. #define REXXSTATUS_ENDED          2
  79.  
  80. typedef struct {
  81.             USHORT cb;
  82.             PCHAR pchErrorText;
  83.             PCHAR pchErrorTitle;
  84.          } REXXERRORPAR, *PREXXERRORPAR;
  85.  
  86. typedef struct {
  87.             PCHAR               pchFuncName;
  88.             RexxFunctionHandler *pFuncAddr;
  89.          } FUNCTIONTABLE;
  90.  
  91. /*---------------------------- Globale Variablen ----------------------------*/
  92.  
  93. extern SCRIPTLIST scriptlist;
  94. extern HWND client, hwndhelp;
  95. extern HMODULE hmodLang;
  96. extern HAB anchor;
  97.  
  98. extern HWND hwndMonitor;
  99. extern PRXSCRIPT pExecScript;
  100. extern int tidRexxExec;
  101.  
  102. static HFILE   stdin_r;
  103. static HFILE   stdin_w;
  104. static HFILE   stdout_r;
  105. static HFILE   stdout_w;
  106. static HFILE   stderr_w;
  107. static IOQUEUE stdinqueue;
  108.  
  109. /*----------------------- interne Funktionsprototypen -----------------------*/
  110.  
  111. static MRESULT EXPENTRY ScriptMonitorProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
  112. static void _Optlink stdinpipe(PVOID pData);
  113. static void _Optlink stdoutpipe(PVOID pData);
  114. static void makepipe(PHFILE read, HFILE rspot, PHFILE write, HFILE wspot, ULONG psize);
  115. static void setinherit(HFILE handle, BOOL inh);
  116. static MRESULT EXPENTRY RexxErrorProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
  117. INT _System RexxInitExit(LONG lExitNumber, LONG lSubfunction, PEXIT pParams);
  118. INT _System RexxTermExit(LONG lExitNumber, LONG lSubfunction, PEXIT pParams);
  119. void _Optlink CallRexx(PVOID pParam);
  120. static char *FormatRexxError(char *pchText);
  121. static char *FormatRexxTitle(char *pchText);
  122. static void RexxVarUserNames(void);
  123. static void RexxVarUserAddresses(void);
  124. static void RexxVarCC(PCCLIST pList);
  125. static void SetRexxVar(const char *pchName, const char *pchValue);
  126. static int QueryRexxVar(const char *pchName, char *pchBuffer, ULONG ulBufLen);
  127. static void RexxVarMessageHeader(MSGHEADER *pHeader);
  128. static void RexxVarMessageText(FTNMESSAGE *pMessage, ULONG ulCursor);
  129. static void RexxVarSeenbys(FTNMESSAGE *pMessage);
  130. static void RexxVarKludges(FTNMESSAGE *pMessage);
  131. static void RegisterFunctions(void);
  132. static void DeregisterFunctions(void);
  133.  
  134. static ULONG _System FSSetText(PUCHAR pchFuncName, ULONG argc, PRXSTRING argv, PSZ pchQueueName, PRXSTRING pRetStr);
  135. static ULONG _System FSLookupAddress(PUCHAR pchFuncName, ULONG argc, PRXSTRING argv, PSZ pchQueueName, PRXSTRING pRetStr);
  136. static ULONG _System FSLookupName(PUCHAR pchFuncName, ULONG argc, PRXSTRING argv, PSZ pchQueueName, PRXSTRING pRetStr);
  137. static ULONG _System FSSetEntryField(PUCHAR pchFuncName, ULONG argc, PRXSTRING argv, PSZ pchQueueName, PRXSTRING pRetStr);
  138. static ULONG _System FSCls(PUCHAR pchFuncName, ULONG argc, PRXSTRING argv, PSZ pchQueueName, PRXSTRING pRetStr);
  139. static ULONG _System FSSetHeader(PUCHAR pchFuncName, ULONG argc, PRXSTRING argv, PSZ pchQueueName, PRXSTRING pRetStr);
  140. static ULONG _System FSEncodeLine(PUCHAR pchFuncName, ULONG argc, PRXSTRING argv, PSZ pchQueueName, PRXSTRING pRetStr);
  141. static ULONG _System FSDecodeLine(PUCHAR pchFuncName, ULONG argc, PRXSTRING argv, PSZ pchQueueName, PRXSTRING pRetStr);
  142.  
  143. static const FUNCTIONTABLE FunctionTable[] =
  144. {
  145.  {"FSSetText",       &FSSetText},
  146.  {"FSLookupAddress", &FSLookupAddress},
  147.  {"FSLookupName",    &FSLookupName},
  148.  {"FSSetEntryField", &FSSetEntryField},
  149.  {"FSCls",           &FSCls},
  150.  {"FSSetHeader",     &FSSetHeader},
  151.  {"FSDecodeLine",    &FSDecodeLine},
  152.  {"FSEncodeLine",    &FSEncodeLine},
  153.  {NULL, NULL}
  154. };
  155.  
  156. /*---------------------------------------------------------------------------*/
  157. /* Funktionsname: StartRexxScript                                            */
  158. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  159. /* Beschreibung: Startet mit der Ausfuehrung des Scripts                     */
  160. /*                                                                           */
  161. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  162. /* Parameter: ulScriptID: Script-ID                                          */
  163. /*            phwndMonitor: Empfangspuffer f. Monitor-Window-Handle          */
  164. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  165. /* Rückgabewerte: 0 Script gestartet                                         */
  166. /*                1 Fehler, Script nicht gestartet                           */
  167. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  168. /* Sonstiges:-                                                               */
  169. /*                                                                           */
  170. /*---------------------------------------------------------------------------*/
  171.  
  172. int StartRexxScript(ULONG ulScriptID, PHWND phwndMonitor)
  173. {
  174.    PRXSCRIPT pScript=scriptlist.pScripts;
  175.    HWND hwndNewMonitor = NULLHANDLE;
  176.  
  177.    if (tidRexxExec)
  178.    {
  179.       return 1;
  180.    }
  181.  
  182.    while (pScript && pScript->ulScriptID != ulScriptID)
  183.       pScript = pScript->next;
  184.  
  185.    if (!pScript)
  186.    {
  187.       return 1;   /* unbekannte ID */
  188.    }
  189.  
  190.    if (!pScript->pchPathName[0])
  191.    {
  192.       return 1;   /* kein Pfadname */
  193.    }
  194.  
  195.    pExecScript = pScript;
  196.  
  197.    if (!(pScript->ulFlags & REXXFLAG_NOMONITOR))
  198.    {
  199. #if 1
  200.       /* Monitor-Fenster erzeugen */
  201.       hwndNewMonitor = WinLoadDlg(HWND_DESKTOP, client, ScriptMonitorProc,
  202.                                   hmodLang, IDD_RXMONITOR, NULL);
  203.  
  204.       if (!hwndNewMonitor)
  205.       {
  206.          return 1;
  207.       }
  208. #endif
  209.  
  210.       if (phwndMonitor)
  211.          *phwndMonitor = hwndNewMonitor;
  212.  
  213.    }
  214.  
  215.    hwndMonitor = hwndNewMonitor;
  216.  
  217.    SendMsg(client, WORKM_DISABLEVIEWS, NULL, NULL);
  218.    tidRexxExec = _beginthread(CallRexx, NULL, 100000, pScript);
  219.  
  220.    return 0;
  221. }
  222.  
  223. /*---------------------------------------------------------------------------*/
  224. /* Funktionsname: RegisterFunctions                                          */
  225. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  226. /* Beschreibung: Registriert alle Funktionen der Funktionstabelle            */
  227. /*                                                                           */
  228. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  229. /* Parameter: -                                                              */
  230. /*                                                                           */
  231. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  232. /* Rückgabewerte: -                                                          */
  233. /*                                                                           */
  234. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  235. /* Sonstiges:-                                                               */
  236. /*                                                                           */
  237. /*---------------------------------------------------------------------------*/
  238.  
  239. static void RegisterFunctions(void)
  240. {
  241.    int i=0;
  242.  
  243.    while (FunctionTable[i].pchFuncName)
  244.    {
  245.       RexxRegisterFunctionExe(FunctionTable[i].pchFuncName,
  246.                               (PFN)FunctionTable[i].pFuncAddr);
  247.       i++;
  248.    }
  249.    return;
  250. }
  251.  
  252. /*---------------------------------------------------------------------------*/
  253. /* Funktionsname: DeregisterFunctions                                        */
  254. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  255. /* Beschreibung: De-Registriert alle Funktionen der Funktionstabelle         */
  256. /*                                                                           */
  257. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  258. /* Parameter: -                                                              */
  259. /*                                                                           */
  260. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  261. /* Rückgabewerte: -                                                          */
  262. /*                                                                           */
  263. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  264. /* Sonstiges:-                                                               */
  265. /*                                                                           */
  266. /*---------------------------------------------------------------------------*/
  267.  
  268. static void DeregisterFunctions(void)
  269. {
  270.    int i=0;
  271.  
  272.    while (FunctionTable[i].pchFuncName)
  273.    {
  274.       RexxDeregisterFunction(FunctionTable[i].pchFuncName);
  275.       i++;
  276.    }
  277.    return;
  278. }
  279.  
  280. /*---------------------------------------------------------------------------*/
  281. /* Funktionsname: ScriptMonitorProc                                          */
  282. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  283. /* Beschreibung: Window-Procedure des Script-Monitors                        */
  284. /*                                                                           */
  285. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  286. /* Parameter: WinProc                                                        */
  287. /*                                                                           */
  288. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  289. /* Rückgabewerte: MRESULT                                                    */
  290. /*                                                                           */
  291. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  292. /* Sonstiges:-                                                               */
  293. /*                                                                           */
  294. /*---------------------------------------------------------------------------*/
  295.  
  296. static MRESULT EXPENTRY ScriptMonitorProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  297. {
  298.    PMONITORDATA pMonitorData = (PMONITORDATA) WinQueryWindowULong(hwnd, QWL_USER);
  299.    extern WINDOWCOLORS windowcolors;
  300.    extern WINDOWFONTS windowfonts;
  301.  
  302.    switch(msg)
  303.    {
  304.       case WM_INITDLG:
  305.          /* Instanzdaten */
  306.          pMonitorData = calloc(1, sizeof(MONITORDATA));
  307.          WinSetWindowULong(hwnd, QWL_USER, (ULONG) pMonitorData);
  308.  
  309.          /* Eingabelaenge */
  310.          WinSendDlgItemMsg(hwnd, IDD_RXMONITOR+2, EM_SETTEXTLIMIT,
  311.                            MPFROMSHORT(500), NULL);
  312.  
  313.          WinSubclassWindow(WinWindowFromID(hwnd, IDD_RXMONITOR+2), FileEntryProc);
  314.  
  315.          SetBackground(WinWindowFromID(hwnd, IDD_RXMONITOR+1), &windowcolors.monitorback);
  316.          SetForeground(WinWindowFromID(hwnd, IDD_RXMONITOR+1), &windowcolors.monitorfore);
  317.          SetFont(WinWindowFromID(hwnd, IDD_RXMONITOR+1), windowfonts.monitorfont);
  318.  
  319.          RestoreWinPos(hwnd, &pExecScript->MonitorPos, FALSE, TRUE);
  320.          pMonitorData->bNotify = TRUE;
  321.          break;
  322.  
  323.       case WM_CLOSE:
  324.          if (pMonitorData->ulStatus != REXXSTATUS_ENDED)
  325.             return (MRESULT) FALSE;
  326.          else
  327.          {
  328.             WinPostMsg(client, REXXM_CLOSE, (MPARAM) hwnd, NULL);
  329.             break;
  330.          }
  331.  
  332.       case WM_DESTROY:
  333.          if (!WinRequestMutexSem(stdinqueue.hmtxQueueAccess, SEM_INDEFINITE_WAIT))
  334.          {
  335.             if (stdinqueue.pLines)
  336.             {
  337.                /* Queue aufraeumen */
  338.  
  339.                PSTRINGLIST pString = stdinqueue.pLines;
  340.                PSTRINGLIST pNextString;
  341.  
  342.                while(pString)
  343.                {
  344.                   pNextString = pString->next;
  345.                   free(pString->pchLine);
  346.                   free(pString);
  347.                   pString = pNextString;
  348.                }
  349.             }
  350.  
  351.             DosReleaseMutexSem(stdinqueue.hmtxQueueAccess);
  352.          }
  353.          QueryBackground(WinWindowFromID(hwnd, IDD_RXMONITOR+1), &windowcolors.monitorback);
  354.          QueryForeground(WinWindowFromID(hwnd, IDD_RXMONITOR+1), &windowcolors.monitorfore);
  355.          QueryFont(WinWindowFromID(hwnd, IDD_RXMONITOR+1), windowfonts.monitorfont);
  356.          free(pMonitorData);
  357.          break;
  358.  
  359.       case WM_WINDOWPOSCHANGED:
  360.          if (pMonitorData && pMonitorData->bNotify)
  361.          {
  362.             if (SaveWinPos(hwnd, (PSWP) mp1, &pExecScript->MonitorPos, &pExecScript->bDirty))
  363.                scriptlist.bDirty=TRUE;
  364.          }
  365.          break;
  366.  
  367.       case REXXM_STARTSCRIPT:
  368.          pMonitorData->ulStatus = REXXSTATUS_RUNNING;
  369.          WinEnableControl(hwnd, IDD_RXMONITOR+2, TRUE);
  370.          WinEnableControl(hwnd, IDD_RXMONITOR+4, TRUE);
  371.          SetFocusControl(hwnd, IDD_RXMONITOR+2);
  372.          return (MRESULT) NULL;
  373.  
  374.       case REXXM_STOPSCRIPT:
  375.          pMonitorData->ulStatus = REXXSTATUS_ENDED;
  376.          WinEnableControl(hwnd, IDD_RXMONITOR+2, FALSE);
  377.          WinEnableControl(hwnd, IDD_RXMONITOR+4, FALSE);
  378.          WinEnableControl(hwnd, IDD_RXMONITOR+3, TRUE);
  379.          if (pExecScript->ulFlags & REXXFLAG_AUTOCLOSE)
  380.             WinPostMsg(hwnd, WM_CLOSE, NULL, NULL);
  381.          return (MRESULT) NULL;
  382.  
  383.       case REXXM_CLS:
  384.          WinSendDlgItemMsg(hwnd, IDD_RXMONITOR+1, LM_DELETEALL, NULL, NULL);
  385.          return (MRESULT) NULL;
  386.  
  387.       case REXXM_ERROR:
  388.          DisplayRexxError(hwnd, (PCHAR) mp1, (PCHAR) mp2);
  389.          pMonitorData->ulStatus = REXXSTATUS_ENDED;
  390.          WinEnableControl(hwnd, IDD_RXMONITOR+2, FALSE);
  391.          WinEnableControl(hwnd, IDD_RXMONITOR+4, FALSE);
  392.          WinEnableControl(hwnd, IDD_RXMONITOR+3, TRUE);
  393.          return (MRESULT) NULL;
  394.  
  395.       case REXXM_OUTLINE:  /* mp1 ist PSTRINGLIST */
  396.          if (mp1)
  397.          {
  398.             SHORT sTop;
  399.             ULONG ulNumLines=0;
  400.             PSTRINGLIST pHelp=(PSTRINGLIST) mp1, pHelp2;
  401.  
  402.             while(pHelp)
  403.             {
  404.                while (WinSendDlgItemMsg(hwnd, IDD_RXMONITOR+1, LM_INSERTITEM,
  405.                                         MPFROMSHORT(LIT_END), pHelp->pchLine) == (MRESULT) LIT_MEMERROR)
  406.                {
  407.                   /* zu wenig Speicher, erstes wieder loeschen */
  408.                   WinSendDlgItemMsg(hwnd, IDD_RXMONITOR+1, LM_DELETEITEM,
  409.                                     NULL, NULL);
  410.                }
  411.                ulNumLines++;
  412.                free(pHelp->pchLine);
  413.  
  414.                pHelp2 = pHelp;
  415.                pHelp = pHelp->next;
  416.                free(pHelp2);
  417.             }
  418.  
  419.             if (ulNumLines)
  420.             {
  421.                /* ulNumLines nach unten scrollen */
  422.                sTop = (SHORT) WinSendDlgItemMsg(hwnd, IDD_RXMONITOR+1, LM_QUERYTOPINDEX,
  423.                                                 NULL, NULL);
  424.                WinSendDlgItemMsg(hwnd, IDD_RXMONITOR+1, LM_SETTOPINDEX,
  425.                                  MPFROMSHORT(sTop+ulNumLines), NULL);
  426.             }
  427.          }
  428.          return (MRESULT) NULL;
  429.  
  430.       case WM_COMMAND:
  431.          switch(SHORT1FROMMP(mp1))
  432.          {
  433.             PID pid;
  434.             TID tid;
  435.  
  436.             case DID_OK:
  437.                WinAlarm(HWND_DESKTOP, WA_NOTE);
  438.                return (MRESULT) FALSE;
  439.  
  440.             case DID_CANCEL:
  441.                return (MRESULT) FALSE;
  442.  
  443.             case IDD_RXMONITOR+3:  /* Close-Button */
  444.                WinPostMsg(client, REXXM_CLOSE, (MPARAM) hwnd, NULL);
  445.                break;
  446.  
  447.             case IDD_RXMONITOR+4:  /* Stop-Button */
  448.                WinQueryWindowProcess(hwnd, &pid, &tid);
  449.                RexxSetHalt(pid, tidRexxExec);
  450.                WinEnableControl(hwnd, IDD_RXMONITOR+4, FALSE);
  451.                return (MRESULT) FALSE;
  452.  
  453.             default:
  454.                return (MRESULT) FALSE;
  455.          }
  456.          break;
  457.  
  458.       case WM_CHAR:
  459.          if (!(SHORT1FROMMP(mp1) & KC_KEYUP) &&
  460.              (SHORT1FROMMP(mp1) & KC_VIRTUALKEY) &&
  461.              (SHORT2FROMMP(mp2) == VK_NEWLINE ||
  462.               SHORT2FROMMP(mp2) == VK_ENTER) &&
  463.              WinQueryFocus(HWND_DESKTOP) == WinWindowFromID(hwnd, IDD_RXMONITOR+2) &&
  464.              pMonitorData->ulStatus == REXXSTATUS_RUNNING)
  465.          {
  466.             /* Text aus Zeile holen */
  467.             PCHAR pchText=NULL;
  468.             LONG lLen;
  469.             PSTRINGLIST pListItem;
  470.  
  471.             lLen= WinQueryDlgItemTextLength(hwnd, IDD_RXMONITOR+2)+1;
  472.             pchText=malloc(lLen);
  473.             *pchText=0;
  474.             WinQueryDlgItemText(hwnd, IDD_RXMONITOR+2, lLen, pchText);
  475.             WinSetDlgItemText(hwnd, IDD_RXMONITOR+2, "");
  476.  
  477.             /* Neues Item erzeugen */
  478.             pListItem = malloc(sizeof(STRINGLIST));
  479.             pListItem->next = NULL;
  480.             pListItem->pchLine = pchText;
  481.  
  482.             /* Item in Queue einhaengen */
  483.             if (!WinRequestMutexSem(stdinqueue.hmtxQueueAccess, SEM_INDEFINITE_WAIT))
  484.             {
  485.                if (!stdinqueue.pLines)
  486.                {
  487.                   stdinqueue.pLines = pListItem;
  488.                }
  489.                else
  490.                {
  491.                   PSTRINGLIST pHelp=stdinqueue.pLines;
  492.  
  493.                   while(pHelp->next)
  494.                      pHelp = pHelp->next;
  495.  
  496.                   pHelp->next = pListItem;
  497.                }
  498.  
  499.                DosPostEventSem(stdinqueue.hevQueueAdd);
  500.                DosReleaseMutexSem(stdinqueue.hmtxQueueAccess);
  501.             }
  502.             return (MRESULT) TRUE;
  503.          }
  504.          else
  505.             break;
  506.  
  507.       case WM_ACTIVATE:
  508.          if (mp1)
  509.             WinAssociateHelpInstance(hwndhelp, hwnd);
  510.          else
  511.             WinAssociateHelpInstance(hwndhelp, NULLHANDLE);
  512.          break;
  513.  
  514.       default:
  515.          break;
  516.    }
  517.    return WinDefDlgProc(hwnd, msg, mp1, mp2);
  518. }
  519.  
  520. void DisplayRexxError(HWND hwndOwner, char *pchText, char *pchTitle)
  521. {
  522.    if (pchText)
  523.    {
  524.       REXXERRORPAR ErrorPar;
  525.  
  526.       ErrorPar.cb = sizeof(ErrorPar);
  527.       ErrorPar.pchErrorText = pchText;
  528.       ErrorPar.pchErrorTitle = pchTitle;
  529.  
  530.       WinDlgBox(HWND_DESKTOP, hwndOwner, RexxErrorProc, hmodLang,
  531.                 IDD_REXXERROR, &ErrorPar);
  532.    }
  533.  
  534.    if (pchText)
  535.       free(pchText);
  536.    if (pchTitle)
  537.       free(pchTitle);
  538.  
  539.    return;
  540. }
  541.  
  542. int CreatePipes(void)
  543. {
  544.    LONG         rc;                   /* return code                         */
  545.  
  546.    DosClose(STDIN);                   /* close stdin, stdout, stderr         */
  547.    DosClose(STDOUT);
  548.    DosClose(STDERR);
  549.  
  550.    DosCreateMutexSem(NULL, &stdinqueue.hmtxQueueAccess, 0, FALSE);
  551.    DosCreateEventSem(NULL, &stdinqueue.hevQueueAdd, 0, FALSE);
  552.  
  553.    /* Since we closed all open file handles, we are free to use any *
  554.     * handles we want.                                                        */
  555.    /* First, standard input                                                   */
  556.  
  557.    makepipe(&stdin_r, STDIN, &stdin_w, 4, 16384);
  558.    setinherit(stdin_r, TRUE);
  559.    setinherit(stdin_w, FALSE);
  560.  
  561.    /* Next, standard output                                                   */
  562.  
  563.    makepipe(&stdout_r, 5, &stdout_w, STDOUT, 16384);
  564.    setinherit(stdout_w, TRUE);
  565.    setinherit(stdout_r, FALSE);
  566.  
  567.    /* And, finally, standard error                                            */
  568.    /* Just dup the standard output and handle it once.                        */
  569.    stderr_w = STDERR;
  570.  
  571.    if (rc = DosDupHandle(stdout_w, &stderr_w))
  572.    {
  573.       return  rc;
  574.    }
  575.  
  576.    /* Pipe-Threads starten */
  577.  
  578.    _beginthread(stdoutpipe, NULL, 16384, NULL);
  579.    _beginthread(stdinpipe, NULL, 16384, NULL);
  580.  
  581.    return rc;
  582. }
  583.  
  584. static void _Optlink stdinpipe(PVOID pData)
  585. {
  586.    ULONG written;
  587.    ULONG ulCount;
  588.    PSTRINGLIST pLine;
  589.  
  590.    INSTALLEXPT("stdin");
  591.  
  592.    pData = pData;
  593.  
  594.    while (TRUE)
  595.    {
  596.       /* Auf Eingabe in Queue warten */
  597.       DosResetEventSem(stdinqueue.hevQueueAdd, &ulCount);
  598.       if (DosWaitEventSem(stdinqueue.hevQueueAdd, SEM_INDEFINITE_WAIT))
  599.          break;
  600.  
  601.       /* Queue belegen */
  602.       if (!DosRequestMutexSem(stdinqueue.hmtxQueueAccess, SEM_INDEFINITE_WAIT))
  603.       {
  604.          while (stdinqueue.pLines)
  605.          {
  606.             pLine = stdinqueue.pLines;
  607.             DosWrite(stdin_w, pLine->pchLine, strlen(pLine->pchLine), &written);
  608.             DosWrite(stdin_w, "\r\n", 2, &written);
  609.             free(pLine->pchLine);
  610.             stdinqueue.pLines = pLine->next;
  611.             free(pLine);
  612.          }
  613.  
  614.          DosReleaseMutexSem(stdinqueue.hmtxQueueAccess);
  615.       }
  616.       else
  617.          break;
  618.    }
  619.  
  620.    DEINSTALLEXPT;
  621.  
  622.    return;
  623. }
  624.  
  625. static void _Optlink stdoutpipe(PVOID pData)
  626. {
  627.    UCHAR pchLineBuffer[200]="";
  628.    UCHAR pchReadBuffer[200]="";
  629.    int LinePos=0;
  630.    PSTRINGLIST pNewList=NULL;
  631.    PSTRINGLIST pLastList=NULL;
  632.    ULONG nread;
  633.    int i;
  634.  
  635.    INSTALLEXPT("stdout");
  636.  
  637.    pData = pData;
  638.  
  639.    while (TRUE)
  640.    {
  641.       if (pNewList) /* Liste noch posten */
  642.          if (hwndMonitor)
  643.             while(!WinPostMsg(hwndMonitor, REXXM_OUTLINE, pNewList, NULL))
  644.                DosSleep(1L);
  645.          else
  646.          {
  647.             /* Liste wieder freigeben */
  648.             while (pNewList)
  649.             {
  650.                free(pNewList->pchLine);
  651.                pLastList = pNewList->next;
  652.                free(pNewList);
  653.                pNewList = pLastList;
  654.             }
  655.          }
  656.       pNewList=NULL;
  657.       nread=0;
  658.       while (nread==0) /* lesen */
  659.          DosRead(stdout_r, pchReadBuffer, sizeof(pchReadBuffer), &nread);
  660.  
  661.       for (i=0; i<nread; i++) /* gelesenes abklappern */
  662.       {
  663.          switch(pchReadBuffer[i])
  664.          {
  665.             case '\n':     /* Zeilenende, neuen Listeneintrag */
  666.                pchLineBuffer[LinePos]=0;
  667.                LinePos=0;
  668.                if (pNewList)
  669.                {
  670.                   pLastList->next = malloc(sizeof(STRINGLIST));
  671.                   pLastList = pLastList->next;
  672.                }
  673.                else
  674.                {
  675.                   pNewList = malloc(sizeof(STRINGLIST));
  676.                   pLastList = pNewList;
  677.                }
  678.                pLastList->next=NULL;
  679.                pLastList->pchLine = strdup(pchLineBuffer);
  680.                break;
  681.  
  682.             case '\r': /* ignorieren */
  683.                break;
  684.  
  685.             default:  /* kopieren */
  686.                pchLineBuffer[LinePos++]=pchReadBuffer[i];
  687.                if (LinePos == 199)
  688.                {
  689.                   /* Pufferueberlauf */
  690.                   pchLineBuffer[199]=0;
  691.                   LinePos=0;
  692.  
  693.                   if (pNewList)
  694.                   {
  695.                      pLastList->next = malloc(sizeof(STRINGLIST));
  696.                      pLastList = pLastList->next;
  697.                   }
  698.                   else
  699.                   {
  700.                      pNewList = malloc(sizeof(STRINGLIST));
  701.                      pLastList = pNewList;
  702.                   }
  703.                   pLastList->next=NULL;
  704.                   pLastList->pchLine = strdup(pchLineBuffer);
  705.                }
  706.                break;
  707.          }
  708.       }
  709.    }
  710.  
  711.    DEINSTALLEXPT;
  712. }
  713.  
  714. static void makepipe(PHFILE read, HFILE rspot, PHFILE write, HFILE wspot, ULONG psize)
  715. {
  716.    HFILE rh,wh;                         /* read and write handles for pipe     */
  717.    HFILE newh = 0xFFFF;                 /* we want to get a new handle         */
  718.  
  719.    /* Create the pipe                                                          */
  720.    DosCreatePipe(&rh, &wh, psize);
  721.  
  722.    if (rh != rspot)
  723.    {
  724.  
  725.       if (wh == rspot)
  726.       {
  727.          if (rh != wspot)
  728.             newh = wspot;
  729.  
  730.          DosDupHandle(wh, &newh);
  731.          wh = newh;
  732.       }
  733.  
  734.       /* Dup requested read handle to the read handle we got                   */
  735.       DosDupHandle(rh, &rspot);
  736.  
  737.       /* Close the original read handle we received                            */
  738.       DosClose(rh);
  739.       rh = rspot;
  740.    }
  741.  
  742.    if (wh != wspot)
  743.    {
  744.       DosDupHandle(wh, &wspot);
  745.  
  746.       /* Close original write handle we received                               */
  747.       DosClose(wh);
  748.       wh = wspot;
  749.    }
  750.  
  751.    *read = rh;
  752.    *write = wh;
  753.  
  754.    return;
  755. }
  756.  
  757. static void setinherit(HFILE handle, BOOL inh)
  758. {
  759.    ULONG  state;                        /* Variable to change current state of */
  760.                                         /* the file handle                     */
  761.  
  762.    DosQueryFHState(handle, &state);
  763.  
  764.    if (inh)
  765.       state &= ~OPEN_FLAGS_NOINHERIT;
  766.    else
  767.       state |= OPEN_FLAGS_NOINHERIT;
  768.  
  769.    DosSetFHState(handle, state);
  770.  
  771.    return;
  772. }
  773.  
  774.  
  775. static void FlushPipes(void)
  776. {
  777.    DosResetBuffer(stdin_r);
  778.    DosResetBuffer(stdin_w);
  779.    DosResetBuffer(stdout_r);
  780.    DosResetBuffer(stdout_w);
  781.    DosResetBuffer(stderr_w);
  782.  
  783.    return;
  784. }
  785.  
  786. /*---------------------------------------------------------------------------*/
  787. /* Funktionsname: RexxErrorProc                                              */
  788. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  789. /* Beschreibung: Window-Prozedur f. Rexx-Fehlermeldungen                     */
  790. /*                                                                           */
  791. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  792. /* Parameter: WinProc                                                        */
  793. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  794. /* Rückgabewerte: MRESULT                                                    */
  795. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  796. /* Sonstiges: -                                                              */
  797. /*                                                                           */
  798. /*---------------------------------------------------------------------------*/
  799.  
  800. static MRESULT EXPENTRY RexxErrorProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  801. {
  802.    switch(msg)
  803.    {
  804.       case WM_INITDLG:
  805.          if (mp2)
  806.          {
  807.             PREXXERRORPAR pErrorPar = (PREXXERRORPAR) mp2;
  808.             WinSetDlgItemText(hwnd, IDD_REXXERROR+3, pErrorPar->pchErrorText);
  809.             if (pErrorPar->pchErrorTitle)
  810.                WinSetWindowText(hwnd, pErrorPar->pchErrorTitle);
  811.          }
  812.          WinAlarm(HWND_DESKTOP, WA_ERROR);
  813.          break;
  814.  
  815.       case WM_ACTIVATE:
  816.          if (mp1)
  817.             WinAssociateHelpInstance(hwndhelp, hwnd);
  818.          else
  819.             WinAssociateHelpInstance(hwndhelp, NULLHANDLE);
  820.          break;
  821.  
  822.       default:
  823.          break;
  824.    }
  825.    return WinDefDlgProc(hwnd, msg, mp1, mp2);
  826. }
  827.  
  828. /*---------------------------------------------------------------------------*/
  829. /* Funktionsname: GetRexxErrorMsg                                            */
  830. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  831. /* Beschreibung: Holt die Fehlermeldung   aus dem Message-File               */
  832. /*                                                                           */
  833. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  834. /* Parameter: pMsg: Zeiger auf den Meldungspuffer                            */
  835. /*            ulMsgNr: Message-Nummer                                        */
  836. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  837. /* Rückgabewerte: 0  OK                                                      */
  838. /*                1  Fehler                                                  */
  839. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  840. /* Sonstiges:                                                                */
  841. /*                                                                           */
  842. /*---------------------------------------------------------------------------*/
  843.  
  844. int GetRexxErrorMsg(PCHAR pMsg, PCHAR pchTitle, ULONG ulMsgNr)
  845. {
  846.    ULONG retlen=0;
  847.  
  848.    memset(pMsg, 0, 1000);
  849.    memset(pchTitle, 0, 100);
  850.  
  851.    switch (DosGetMessage(NULL, 0, pMsg, 1000, ulMsgNr,
  852.            ERROREXPLFILE, &retlen))
  853.    {
  854.       case NO_ERROR:
  855.          FormatRexxError(pMsg);
  856.          break;
  857.  
  858.       case ERROR_FILE_NOT_FOUND:
  859.       case ERROR_FILENAME_EXCED_RANGE:
  860.       case ERROR_MR_UN_ACC_MSGF:
  861.       case ERROR_MR_INV_MSGF_FORMAT:
  862.       case ERROR_MR_INV_IVCOUNT:
  863.       case ERROR_MR_UN_PERFORM:
  864.          break;
  865.  
  866.       case ERROR_MR_MID_NOT_FOUND:
  867.          sprintf(pMsg, "Error #%d", ulMsgNr);
  868.          break;
  869.  
  870.       default:
  871.          break;
  872.    }
  873.  
  874.    switch (DosGetMessage(NULL, 0, pchTitle, 100, ulMsgNr,
  875.            ERRORMSGFILE, &retlen))
  876.    {
  877.       case NO_ERROR:
  878.          FormatRexxTitle(pchTitle);
  879.          break;
  880.  
  881.       case ERROR_FILE_NOT_FOUND:
  882.       case ERROR_FILENAME_EXCED_RANGE:
  883.       case ERROR_MR_UN_ACC_MSGF:
  884.       case ERROR_MR_INV_MSGF_FORMAT:
  885.       case ERROR_MR_INV_IVCOUNT:
  886.       case ERROR_MR_UN_PERFORM:
  887.          break;
  888.  
  889.       case ERROR_MR_MID_NOT_FOUND:
  890.          break;
  891.  
  892.       default:
  893.          break;
  894.    }
  895.  
  896.    return 0;
  897. }
  898.  
  899. /*---------------------------------------------------------------------------*/
  900. /* Funktionsname: FormatRexxError                                            */
  901. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  902. /* Beschreibung: Formatiert die Fehlermeldung um                             */
  903. /*                                                                           */
  904. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  905. /* Parameter: pMsg: Zeiger auf den Meldungspuffer                            */
  906. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  907. /* Rückgabewerte: Zeiger auf Meldung                                         */
  908. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  909. /* Sonstiges:                                                                */
  910. /*                                                                           */
  911. /*---------------------------------------------------------------------------*/
  912.  
  913. static char *FormatRexxError(char *pchText)
  914. {
  915.    char *pchSrc = pchText;
  916.    char *pchDest = pchText;
  917.  
  918.    while (*pchSrc)
  919.    {
  920.       switch(*pchSrc)
  921.       {
  922.          case '\r':
  923.             pchSrc++;
  924.             break;
  925.  
  926.          case '\n':
  927.             pchSrc++;
  928.             if (*pchSrc != ' ')
  929.             {
  930.                *pchDest++ = '\n';
  931.                *pchDest++ = *pchSrc;
  932.                if (*pchSrc)
  933.                   pchSrc++;
  934.             }
  935.             else
  936.             {
  937.                *pchDest++ = ' ';
  938.                while (*pchSrc == ' ')
  939.                   pchSrc++;
  940.             }
  941.             break;
  942.  
  943.          default:
  944.             *pchDest++ = *pchSrc++;
  945.             break;
  946.       }
  947.    }
  948.    *pchDest=0;
  949.    return pchText;
  950. }
  951.  
  952. static char *FormatRexxTitle(char *pchText)
  953. {
  954.    char *pchSrc = pchText;
  955.    char *pchDest = pchText;
  956.  
  957. #if 0
  958.    while (*pchSrc && *pchSrc != '%')
  959.       pchSrc++;
  960.  
  961.    if (*pchSrc)
  962.    {
  963.       pchSrc++;
  964.       if (*pchSrc)
  965.       {
  966.          pchSrc++;
  967.          while(*pchSrc && *pchSrc != '%')
  968.             *pchDest++ = *pchSrc++;
  969.          *pchDest = 0;
  970.       }
  971.    }
  972. #else
  973.    while(*pchSrc)
  974.    {
  975.       if (*pchSrc == '%')
  976.       {
  977.          pchSrc++;
  978.          pchSrc++;
  979.       }
  980.       else
  981.          *pchDest++ = *pchSrc++;
  982.    }
  983.    *pchDest = 0;
  984. #endif
  985.    return pchText;
  986. }
  987.  
  988. #if 0
  989. /*---------------------------------------------------------------------------*/
  990. /* Funktionsname: PszToRxstring                                              */
  991. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  992. /* Beschreibung: Wandelt einen C-String in einen Rexx-String um              */
  993. /*                                                                           */
  994. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  995. /* Parameter: pRxString: Zeiger auf den Rexx-String                          */
  996. /*            pchString: Zeiger auf den C-String                             */
  997. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  998. /* Rückgabewerte: Zeiger auf den erzeugten Rexx-String                       */
  999. /*                NULL bei Fehler                                            */
  1000. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  1001. /* Sonstiges: Speicher fuer den Rexx-String wird mit DosAllocMem belegt      */
  1002. /*            falls notwendig                                                */
  1003. /*---------------------------------------------------------------------------*/
  1004.  
  1005. PRXSTRING PszToRxstring(PRXSTRING pRxString, PCHAR pchString)
  1006. {
  1007.    int len;
  1008.  
  1009.    if (!pchString)
  1010.       return NULL;
  1011.  
  1012.    len=strlen(pchString);
  1013.  
  1014.    if ((!pRxString->strptr) || (pRxString->strlength < len))
  1015.    {
  1016.       if (pRxString->strptr)
  1017.          DosFreeMem(pRxString->strptr);
  1018.  
  1019.       if (DosAllocMem((PVOID)&pRxString->strptr, len,
  1020.                    PAG_COMMIT | PAG_READ | PAG_WRITE))
  1021.          return NULL;
  1022.    }
  1023.    pRxString->strlength=len;
  1024.    strncpy(pRxString->strptr, pchString, len);
  1025.  
  1026.    return pRxString;
  1027. }
  1028.  
  1029. /*---------------------------------------------------------------------------*/
  1030. /* Funktionsname: RxstringToPsz                                              */
  1031. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  1032. /* Beschreibung: Wandelt einen Rexx-String in einen 0-terminierten           */
  1033. /*               C-String um                                                 */
  1034. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  1035. /* Parameter: pRxString: Zeiger auf den Rexx-String                          */
  1036. /*            ppchString: Zeiger auf den erzeugten String                    */
  1037. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  1038. /* Rückgabewerte: Zeiger auf den erzeugten String                            */
  1039. /*                NULL bei Fehler                                            */
  1040. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  1041. /* Sonstiges: Speicher fuer den erzeugten String wird mit malloc belegt      */
  1042. /*                                                                           */
  1043. /*---------------------------------------------------------------------------*/
  1044.  
  1045. PCHAR RxstringToPsz(PRXSTRING pRxString, PCHAR *ppchString)
  1046. {
  1047.    if (!pRxString->strptr)
  1048.       return NULL;
  1049.    if (!(*ppchString=malloc(pRxString->strlength+1)))
  1050.       return NULL;
  1051.  
  1052.    strncpy(*ppchString, pRxString->strptr, pRxString->strlength);
  1053.    *ppchString[pRxString->strlength]='\0';
  1054.  
  1055.    return *ppchString;
  1056. }
  1057. #endif
  1058.  
  1059. /*---------------------------------------------------------------------------*/
  1060. /* Funktionsname: RexxInitExit                                               */
  1061. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  1062. /* Beschreibung: Exit-Handler fuer INIT                                      */
  1063. /*                                                                           */
  1064. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  1065. /* Parameter: lExitNumber: Exit-Nummer                                       */
  1066. /*            lSubfunction: Sub-Funktion                                     */
  1067. /*            pParams:      Exit-Parameter                                   */
  1068. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  1069. /* Rückgabewerte: RXEXIT_HANDLED: Exit behandelt                             */
  1070. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  1071. /* Sonstiges: -                                                              */
  1072. /*                                                                           */
  1073. /*---------------------------------------------------------------------------*/
  1074.  
  1075. INT _System RexxInitExit(LONG lExitNumber, LONG lSubfunction, PEXIT pParams)
  1076. {
  1077.    extern ECHOTOSSOPT echotossoptions;
  1078.    extern PATHNAMES pathnames;
  1079.    extern char CurrentAddress[LEN_5DADDRESS+1];
  1080.    extern char CurrentName[LEN_USERNAME+1];
  1081.    extern char NewArea[LEN_AREATAG+1];
  1082.    extern char CurrentArea[LEN_AREATAG+1];
  1083.    extern int  CurrentStatus;
  1084.    extern MSGHEADER CurrentHeader;
  1085.    extern FTNMESSAGE CurrentMessage;
  1086.    extern AREALIST arealiste;
  1087.    FTNMESSAGE Message;
  1088.    MSGHEADER Header;
  1089.    AREADEFLIST *pAreaDef;
  1090.    char *pchTemp;
  1091.  
  1092.    pParams = pParams;
  1093.    if (lExitNumber == RXINI &&
  1094.        lSubfunction == RXINIEXT)
  1095.    {
  1096.       RegisterFunctions();
  1097.       RexxVarUserNames();
  1098.       RexxVarUserAddresses();
  1099.       SetRexxVar("FleetSetup.Echotoss", echotossoptions.pchEchoToss);
  1100.       SetRexxVar("FleetSetup.Tosser", pathnames.squishcfg);
  1101.       SetRexxVar("FleetStatus.Area.Tag", CurrentArea);
  1102.       if (CurrentStatus == PROGSTATUS_EDITING)
  1103.          SetRexxVar("FleetStatus.DestArea", NewArea);
  1104.       pAreaDef = AM_FindArea(&arealiste, CurrentArea);
  1105.       if (pAreaDef)
  1106.       {
  1107.          SetRexxVar("FleetStatus.Area.Desc", pAreaDef->areadata.areadesc);
  1108.          SetRexxVar("FleetStatus.Area.File", pAreaDef->areadata.pathfile);
  1109.          switch(pAreaDef->areadata.areaformat)
  1110.          {
  1111.             case AREAFORMAT_FTS:
  1112.                pchTemp = "*.MSG";
  1113.                break;
  1114.             case AREAFORMAT_SQUISH:
  1115.                pchTemp = "Squish";
  1116.                break;
  1117.             case AREAFORMAT_JAM:
  1118.                pchTemp = "JAM";
  1119.                break;
  1120.             default:
  1121.                pchTemp = "Unknown";
  1122.                break;
  1123.          }
  1124.          SetRexxVar("FleetStatus.Area.Format", pchTemp);
  1125.  
  1126.          switch(pAreaDef->areadata.areatype)
  1127.          {
  1128.             case AREATYPE_ECHO:
  1129.                pchTemp = "Echo";
  1130.                break;
  1131.  
  1132.             case AREATYPE_NET:
  1133.                pchTemp = "Net";
  1134.                break;
  1135.  
  1136.             case AREATYPE_LOCAL:
  1137.                if (pAreaDef->areadata.ulAreaOpt & AREAOPT_FROMCFG)
  1138.                   pchTemp = "Local";
  1139.                else
  1140.                   pchTemp = "Private";
  1141.                break;
  1142.          }
  1143.          SetRexxVar("FleetStatus.Area.Type", pchTemp);
  1144.       }
  1145.       SetRexxVar("FleetStatus.Name", CurrentName);
  1146.       SetRexxVar("FleetStatus.Address", CurrentAddress);
  1147.       switch(CurrentStatus)
  1148.       {
  1149.          char pchTemp[50];
  1150.          extern char *pchXPostList;
  1151.          extern ULONG ulCCSelected;
  1152.          extern PCCLIST pQuickCCList;
  1153.          IPT iptCursor;
  1154.  
  1155.          case PROGSTATUS_NOSETUP:
  1156.             SetRexxVar("FleetStatus.Mode", "No Setup");
  1157.             RexxVarMessageHeader(&CurrentHeader);
  1158.             RexxVarMessageText(&CurrentMessage, 0);
  1159.             break;
  1160.  
  1161.          case PROGSTATUS_EDITING:
  1162.             strcpy(pchTemp, "Edit ");
  1163.             if (pchXPostList)
  1164.                strcat(pchTemp, "XPost");
  1165.             else
  1166.                if (ulCCSelected || pQuickCCList)
  1167.                {
  1168.                   strcat(pchTemp, "CCopy");
  1169.  
  1170.                   if (ulCCSelected)
  1171.                   {
  1172.                      PCCLIST pList;
  1173.                      extern CCANCHOR ccanchor;
  1174.  
  1175.                      pList = QueryCCList(&ccanchor, ulCCSelected);
  1176.                      if (pList)
  1177.                         RexxVarCC(pList);
  1178.                   }
  1179.                   else
  1180.                      RexxVarCC(pQuickCCList);
  1181.                }
  1182.                else
  1183.                   strcat(pchTemp, "Single");
  1184.             SetRexxVar("FleetStatus.Mode", pchTemp);
  1185.             memset(&Message, 0, sizeof(Message));
  1186.             memcpy(&Header, &CurrentHeader, sizeof(Header));
  1187.  
  1188.             GetMsgContents(client, &Message, &Header,
  1189.                            AM_FindArea(&arealiste, NewArea)->areadata.areatype != AREATYPE_NET);
  1190.             RexxVarMessageHeader(&Header);
  1191.             iptCursor=(IPT)WinSendDlgItemMsg(client, IDML_MAINEDIT, MLM_QUERYSEL,
  1192.                                              MPFROMSHORT(MLFQS_CURSORSEL), NULL);
  1193.             RexxVarMessageText(&Message, iptCursor);
  1194.             MSG_ClearMessage(&Header, &Message);
  1195.             break;
  1196.  
  1197.          case PROGSTATUS_READING:
  1198.             SetRexxVar("FleetStatus.Mode", "Read");
  1199.             RexxVarMessageHeader(&CurrentHeader);
  1200.             RexxVarMessageText(&CurrentMessage, 0);
  1201.             RexxVarKludges(&CurrentMessage);
  1202.             RexxVarSeenbys(&CurrentMessage);
  1203.             break;
  1204.  
  1205.          case PROGSTATUS_CLEANUP:
  1206.             SetRexxVar("FleetStatus.Mode", "Cleanup");
  1207.             RexxVarMessageHeader(&CurrentHeader);
  1208.             RexxVarMessageText(&CurrentMessage, 0);
  1209.             break;
  1210.  
  1211.          default:
  1212.             SetRexxVar("FleetStatus.Mode", "Unknown");
  1213.             break;
  1214.       }
  1215.  
  1216.       if (CurrentStatus == PROGSTATUS_CLEANUP)
  1217.       {
  1218.          extern BOOL MailEntered[3];
  1219.          char pchTemp[20]="";
  1220.  
  1221.          if (MailEntered[AREATYPE_NET])
  1222.             strcpy(pchTemp, "Net");
  1223.          if (MailEntered[AREATYPE_ECHO])
  1224.             if (pchTemp[0])
  1225.                strcat(pchTemp, " Echo");
  1226.             else
  1227.                strcat(pchTemp, "Echo");
  1228.          if (MailEntered[AREATYPE_LOCAL])
  1229.             if (pchTemp[0])
  1230.                strcat(pchTemp, " Local");
  1231.             else
  1232.                strcat(pchTemp, "Local");
  1233.  
  1234.          SetRexxVar("NewMail", pchTemp);
  1235.       }
  1236.  
  1237.       if (hwndMonitor)
  1238.          SetRexxVar("FleetStatus.Monitor", "1");
  1239.       else
  1240.          SetRexxVar("FleetStatus.Monitor", "0");
  1241.  
  1242.       SendMsg(client, REXXM_STARTSCRIPT, NULL, NULL);
  1243.    }
  1244.  
  1245.    return RXEXIT_HANDLED;
  1246. }
  1247.  
  1248. /*---------------------------------------------------------------------------*/
  1249. /* Funktionsname: RexxTermExit                                               */
  1250. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  1251. /* Beschreibung: Exit-Handler fuer TERM                                      */
  1252. /*                                                                           */
  1253. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  1254. /* Parameter: lExitNumber: Exit-Nummer                                       */
  1255. /*            lSubfunction: Sub-Funktion                                     */
  1256. /*            pParams:      Exit-Parameter                                   */
  1257. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  1258. /* Rückgabewerte: RXEXIT_HANDLED: Exit behandelt                             */
  1259. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  1260. /* Sonstiges: -                                                              */
  1261. /*                                                                           */
  1262. /*---------------------------------------------------------------------------*/
  1263.  
  1264. INT _System RexxTermExit(LONG lExitNumber, LONG lSubfunction, PEXIT pParams)
  1265. {
  1266.    pParams = pParams;
  1267.    if (lExitNumber == RXTER &&
  1268.        lSubfunction == RXTEREXT)
  1269.    {
  1270.       DeregisterFunctions();
  1271.    }
  1272.    return RXEXIT_HANDLED;
  1273. }
  1274.  
  1275. static void RexxVarCC(PCCLIST pList)
  1276. {
  1277.    PCCENTRY pEntry=pList->pEntries;
  1278.    char pchTemp[30];
  1279.    ULONG ulCount=0;
  1280.  
  1281.    while (pEntry)
  1282.    {
  1283.       ulCount++;
  1284.       sprintf(pchTemp, "FleetCCopy.%d.Name", ulCount);
  1285.       SetRexxVar(pchTemp, pEntry->pchName);
  1286.       sprintf(pchTemp, "FleetCCopy.%d.Address", ulCount);
  1287.       SetRexxVar(pchTemp, pEntry->pchAddress);
  1288.  
  1289.       pEntry=pEntry->next;
  1290.    }
  1291.  
  1292.    /* Anzahl */
  1293.    sprintf(pchTemp, "%d", ulCount);
  1294.    SetRexxVar("FleetCCopy.0", pchTemp);
  1295.  
  1296.    return;
  1297. }
  1298.  
  1299. static void RexxVarUserNames(void)
  1300. {
  1301.    extern USERDATAOPT userdaten;
  1302.  
  1303.    int i;
  1304.    PSHVBLOCK pVarBlock;
  1305.    PSHVBLOCK pHelp;
  1306.    char pchTemp[50];
  1307.  
  1308.    pVarBlock=calloc(MAX_USERNAMES+1, sizeof(SHVBLOCK));
  1309.  
  1310.    /* User-Namen */
  1311.    i=0;
  1312.    while (i < MAX_USERNAMES && userdaten.username[i][0])
  1313.    {
  1314.       pVarBlock[i].shvnext = &(pVarBlock[i+1]);
  1315.       sprintf(pchTemp, "FleetSetup.Names.%d", i+1);
  1316.       pVarBlock[i].shvname.strptr=strdup(pchTemp);
  1317.       pVarBlock[i].shvname.strlength=strlen(pchTemp);
  1318.       pVarBlock[i].shvnamelen = pVarBlock[i].shvname.strlength;
  1319.  
  1320.       pVarBlock[i].shvvalue.strptr = userdaten.username[i];
  1321.       pVarBlock[i].shvvalue.strlength = strlen(userdaten.username[i]);
  1322.       pVarBlock[i].shvvaluelen = pVarBlock[i].shvvalue.strlength;
  1323.  
  1324.       pVarBlock[i].shvcode = RXSHV_SYSET;
  1325.  
  1326.       i++;
  1327.    }
  1328.    /* 0-Record */
  1329.    pVarBlock[i].shvnext = NULL;
  1330.    sprintf(pchTemp, "FleetSetup.Names.%d", 0);
  1331.    pVarBlock[i].shvname.strptr=strdup(pchTemp);
  1332.    pVarBlock[i].shvname.strlength=strlen(pchTemp);
  1333.    pVarBlock[i].shvnamelen = pVarBlock[i].shvname.strlength;
  1334.  
  1335.    sprintf(pchTemp, "%d", i);
  1336.    pVarBlock[i].shvvalue.strptr = pchTemp;
  1337.    pVarBlock[i].shvvalue.strlength = strlen(pchTemp);
  1338.    pVarBlock[i].shvvaluelen = pVarBlock[i].shvvalue.strlength;
  1339.  
  1340.    pVarBlock[i].shvcode = RXSHV_SYSET;
  1341.  
  1342.    /* Variablen setzen */
  1343.    RexxVariablePool(pVarBlock);
  1344.  
  1345.    /* aufräumen */
  1346.    pHelp = pVarBlock;
  1347.    while (pHelp)
  1348.    {
  1349.       free(pHelp->shvname.strptr);
  1350.       pHelp = pHelp->shvnext;
  1351.    }
  1352.    free(pVarBlock);
  1353.  
  1354.    return;
  1355. }
  1356.  
  1357. static void RexxVarUserAddresses(void)
  1358. {
  1359.    extern USERDATAOPT userdaten;
  1360.  
  1361.    int i;
  1362.    PSHVBLOCK pVarBlock;
  1363.    PSHVBLOCK pHelp;
  1364.    char pchTemp[50];
  1365.  
  1366.    pVarBlock=calloc(MAX_ADDRESSES+1, sizeof(SHVBLOCK));
  1367.  
  1368.    /* User-Adressen */
  1369.    i=0;
  1370.    while (i < MAX_ADDRESSES && userdaten.address[i][0])
  1371.    {
  1372.       pVarBlock[i].shvnext = &(pVarBlock[i+1]);
  1373.       sprintf(pchTemp, "FleetSetup.Addresses.%d", i+1);
  1374.       pVarBlock[i].shvname.strptr=strdup(pchTemp);
  1375.       pVarBlock[i].shvname.strlength=strlen(pchTemp);
  1376.       pVarBlock[i].shvnamelen = pVarBlock[i].shvname.strlength;
  1377.  
  1378.       pVarBlock[i].shvvalue.strptr = userdaten.address[i];
  1379.       pVarBlock[i].shvvalue.strlength = strlen(userdaten.address[i]);
  1380.       pVarBlock[i].shvvaluelen = pVarBlock[i].shvvalue.strlength;
  1381.  
  1382.       pVarBlock[i].shvcode = RXSHV_SYSET;
  1383.  
  1384.       i++;
  1385.    }
  1386.    /* 0-Record */
  1387.    pVarBlock[i].shvnext = NULL;
  1388.    sprintf(pchTemp, "FleetSetup.Addresses.%d", 0);
  1389.    pVarBlock[i].shvname.strptr=strdup(pchTemp);
  1390.    pVarBlock[i].shvname.strlength=strlen(pchTemp);
  1391.    pVarBlock[i].shvnamelen = pVarBlock[i].shvname.strlength;
  1392.  
  1393.    sprintf(pchTemp, "%d", i);
  1394.    pVarBlock[i].shvvalue.strptr = pchTemp;
  1395.    pVarBlock[i].shvvalue.strlength = strlen(pchTemp);
  1396.    pVarBlock[i].shvvaluelen = pVarBlock[i].shvvalue.strlength;
  1397.  
  1398.    pVarBlock[i].shvcode = RXSHV_SYSET;
  1399.  
  1400.    /* Variablen setzen */
  1401.    RexxVariablePool(pVarBlock);
  1402.  
  1403.    /* aufräumen */
  1404.    pHelp = pVarBlock;
  1405.    while (pHelp)
  1406.    {
  1407.       free(pHelp->shvname.strptr);
  1408.       pHelp = pHelp->shvnext;
  1409.    }
  1410.    free(pVarBlock);
  1411.  
  1412.    return;
  1413. }
  1414.  
  1415. static void RexxVarKludges(FTNMESSAGE *pMessage)
  1416. {
  1417.    char pchName[50];
  1418.    char *pchCont=NULL;
  1419.    int i=0;
  1420.    PKLUDGE pKludge=NULL;
  1421.  
  1422.    while (pKludge = MSG_FindKludge(pMessage, KLUDGE_ANY, pKludge))
  1423.    {
  1424.       if (pKludge->ulKludgeType == KLUDGE_OTHER)
  1425.          pchCont = strdup(pKludge->pchKludgeText);
  1426.       else
  1427.       {
  1428.          size_t len=0;
  1429.  
  1430.          len=strlen(MSG_QueryKludgeName(pKludge->ulKludgeType));
  1431.          len+= 1 + strlen(pKludge->pchKludgeText);
  1432.  
  1433.          pchCont = malloc(len+1);
  1434.  
  1435.          strcpy(pchCont, MSG_QueryKludgeName(pKludge->ulKludgeType));
  1436.          strcat(pchCont, " ");
  1437.          strcat(pchCont, pKludge->pchKludgeText);
  1438.       }
  1439.  
  1440.       i++;
  1441.       sprintf(pchName, "FleetMsg.Kludges.%d", i);
  1442.       SetRexxVar(pchName, pchCont);
  1443.       free(pchCont);
  1444.    }
  1445.  
  1446.    /* Anzahl */
  1447.    _itoa(i, pchName, 10);
  1448.    SetRexxVar("FleetMsg.Kludges.0", pchName);
  1449.  
  1450.    return;
  1451. }
  1452.  
  1453. static void RexxVarSeenbys(FTNMESSAGE *pMessage)
  1454. {
  1455.    char pchName[50];
  1456.    char *pchDup, *pchTemp;
  1457.    int i=0;
  1458.  
  1459.    if (pMessage->pchSeenPath)
  1460.    {
  1461.       pchDup = strdup(pMessage->pchSeenPath);
  1462.  
  1463.       /* SOH umwandeln (v. PATH) */
  1464.       pchTemp = pchDup;
  1465.       while (*pchTemp)
  1466.       {
  1467.          if (*pchTemp == 1)
  1468.             *pchTemp = '@';
  1469.          pchTemp++;
  1470.       }
  1471.  
  1472.       pchTemp = strtok(pchDup, "\r\n");
  1473.       while (pchTemp)
  1474.       {
  1475.          i++;
  1476.          sprintf(pchName, "FleetMsg.Seenbys.%d", i);
  1477.          SetRexxVar(pchName, pchTemp);
  1478.  
  1479.          pchTemp = strtok(NULL, "\r\n");
  1480.       }
  1481.  
  1482.       free(pchDup);
  1483.    }
  1484.  
  1485.    /* Anzahl */
  1486.    _itoa(i, pchName, 10);
  1487.    SetRexxVar("FleetMsg.Seenbys.0", pchName);
  1488.  
  1489.    return;
  1490. }
  1491.  
  1492. static void SetRexxVar(const char *pchName, const char *pchValue)
  1493. {
  1494.    SHVBLOCK VarBlock;
  1495.  
  1496.    VarBlock.shvnext=NULL;
  1497.  
  1498.    MAKERXSTRING(VarBlock.shvname, pchName, strlen(pchName));
  1499.    VarBlock.shvnamelen = VarBlock.shvname.strlength;
  1500.    MAKERXSTRING(VarBlock.shvvalue, pchValue, strlen(pchValue));
  1501.    VarBlock.shvvaluelen = VarBlock.shvvalue.strlength;
  1502.  
  1503. #if 1
  1504.    VarBlock.shvcode = RXSHV_SYSET;
  1505. #else
  1506.    VarBlock.shvcode = RXSHV_SET;
  1507. #endif
  1508.  
  1509.    RexxVariablePool(&VarBlock);
  1510.  
  1511.    return;
  1512. }
  1513.  
  1514. static int QueryRexxVar(const char *pchName, char *pchBuffer, ULONG ulBufLen)
  1515. {
  1516.    SHVBLOCK VarBlock;
  1517.  
  1518.    if (ulBufLen < 1 || !pchBuffer || !pchName)
  1519.       return -1;
  1520.  
  1521.    VarBlock.shvnext=NULL;
  1522.  
  1523.    MAKERXSTRING(VarBlock.shvname, pchName, strlen(pchName));
  1524.    VarBlock.shvnamelen = VarBlock.shvname.strlength;
  1525.    VarBlock.shvvalue.strptr=NULL;
  1526.    VarBlock.shvvaluelen = 0;
  1527.  
  1528.    VarBlock.shvcode = RXSHV_SYFET;
  1529.  
  1530.    if (RexxVariablePool(&VarBlock))
  1531.       return -1;
  1532.  
  1533.    pchBuffer[ulBufLen-1]=0;
  1534.    if (ulBufLen-1 <= VarBlock.shvvalue.strlength)
  1535.       memcpy(pchBuffer, VarBlock.shvvalue.strptr, ulBufLen-1);
  1536.    else
  1537.    {
  1538.       memcpy(pchBuffer, VarBlock.shvvalue.strptr, VarBlock.shvvalue.strlength);
  1539.       pchBuffer[VarBlock.shvvalue.strlength]=0;
  1540.    }
  1541.  
  1542.    DosFreeMem(VarBlock.shvvalue.strptr);
  1543.  
  1544.    return 0;
  1545. }
  1546.  
  1547. static void RexxVarMessageHeader(MSGHEADER *pHeader)
  1548. {
  1549.    static char flagsbuf[200];
  1550.  
  1551.    MSG_AttribToText(pHeader->ulAttrib, flagsbuf);
  1552.    SetRexxVar("FleetMsg.Header.Attrib", flagsbuf);
  1553.  
  1554.    SetRexxVar("FleetMsg.Header.From", pHeader->pchFromName);
  1555.    SetRexxVar("FleetMsg.Header.To",   pHeader->pchToName);
  1556.    SetRexxVar("FleetMsg.Header.Subj", pHeader->pchSubject);
  1557.    SetRexxVar("FleetMsg.Header.FromAddress", NetAddrToString(flagsbuf, &pHeader->FromAddress));
  1558.    SetRexxVar("FleetMsg.Header.ToAddress", NetAddrToString(flagsbuf, &pHeader->ToAddress));
  1559.    SetRexxVar("FleetMsg.Header.DateWritten", StampToString(flagsbuf, &pHeader->StampWritten));
  1560.    SetRexxVar("FleetMsg.Header.DateReceived", StampToString(flagsbuf, &pHeader->StampArrived));
  1561.  
  1562.    return;
  1563. }
  1564.  
  1565. static void RexxVarMessageText(FTNMESSAGE *pMessage, ULONG ulCursor)
  1566. {
  1567.    char pchNameTemp[50];
  1568.    char *pchTextDup;
  1569.    char *pchHelp;
  1570.    char *pchHelp2;
  1571.    int i=0;
  1572.  
  1573.    ULONG ulHelp=0;
  1574.    ULONG ulPara=1;
  1575.    ULONG ulOffs=1;
  1576.  
  1577.    /* Cursorposition ermitteln */
  1578.    while (ulHelp < ulCursor && pMessage->pchMessageText[ulHelp])
  1579.    {
  1580.       if (pMessage->pchMessageText[ulHelp] == '\n')
  1581.       {
  1582.          ulPara++;
  1583.          ulOffs=1;
  1584.       }
  1585.       else
  1586.          ulOffs++;
  1587.       ulHelp++;
  1588.    }
  1589.  
  1590.    sprintf(pchNameTemp, "%d %d", ulPara, ulOffs);
  1591.    SetRexxVar("FleetStatus.Cursor", pchNameTemp);
  1592.  
  1593.    if (!pMessage->pchMessageText)
  1594.    {
  1595.       SetRexxVar("FleetMsg.Text.0", "0");
  1596.       return;
  1597.    }
  1598.    else
  1599.    {
  1600.       pchTextDup = strdup(pMessage->pchMessageText);
  1601.       pchHelp = pchTextDup;
  1602.  
  1603.       do
  1604.       {
  1605.          pchHelp2 = pchHelp;
  1606.          while (*pchHelp && *pchHelp != '\n')
  1607.             pchHelp++;
  1608.          if (*pchHelp)
  1609.             *pchHelp++ = 0;
  1610.  
  1611.          i++;
  1612.          sprintf(pchNameTemp, "FleetMsg.Text.%d", i);
  1613.          SetRexxVar(pchNameTemp, pchHelp2);
  1614.       } while(*pchHelp);
  1615.       sprintf(pchNameTemp, "%d", i);
  1616.       SetRexxVar("FleetMsg.Text.0", pchNameTemp);
  1617.       free(pchTextDup);
  1618.       return;
  1619.    }
  1620. }
  1621.  
  1622. /*---------------------------------------------------------------------------*/
  1623. /* Funktionsname: CallRexx                                                   */
  1624. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  1625. /* Beschreibung: Threadfunktion zur Ausfuehrung des Rexx-Scripts             */
  1626. /*                                                                           */
  1627. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  1628. /* Parameter: pParam: Zeiger auf Script                                      */
  1629. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  1630. /* Rückgabewerte: -                                                          */
  1631. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  1632. /* Sonstiges: -                                                              */
  1633. /*                                                                           */
  1634. /*---------------------------------------------------------------------------*/
  1635.  
  1636. void _Optlink CallRexx(PVOID pParam)
  1637. {
  1638.    PRXSCRIPT pScript = (PRXSCRIPT) pParam;
  1639.    RXSYSEXIT Exits[] = {
  1640.                         {"ScriptInit", RXINI},
  1641.                         {"ScriptTerm", RXTER},
  1642.                         {NULL,         RXENDLST}
  1643.                        };
  1644.    LONG rc;
  1645.    SHORT ReturnCode;
  1646.    RXSTRING ReturnString= {0, NULL};
  1647.    HMQ hmq;
  1648.    HAB hab;
  1649.  
  1650.    INSTALLEXPT("CallRexx");
  1651.  
  1652.    hab=WinInitialize(0);
  1653.    hmq=WinCreateMsgQueue(hab, 100);
  1654.    WinCancelShutdown(hmq, TRUE);
  1655.  
  1656.    FlushPipes();
  1657.  
  1658.    RexxRegisterExitExe("ScriptInit", RexxInitExit, NULL);
  1659.    RexxRegisterExitExe("ScriptTerm", RexxTermExit, NULL);
  1660.  
  1661.    rc = RexxStart(0,                    /* Arg count */
  1662.                   NULL,                 /* Arg list */
  1663.                   pScript->pchPathName, /* Name */
  1664.                   NULL,                 /* Instore */
  1665.                   REXXENVNAME,          /* environment name */
  1666.                   RXSUBROUTINE,         /* call type */
  1667.                   Exits,                /* Exits */
  1668.                   &ReturnCode,
  1669.                   &ReturnString);
  1670.  
  1671.    if (ReturnString.strptr)
  1672.       DosFreeMem(ReturnString.strptr);
  1673.  
  1674.    RexxDeregisterExit("ScriptInit", NULL);
  1675.    RexxDeregisterExit("ScriptTerm", NULL);
  1676.  
  1677.    if (rc)
  1678.    {
  1679.       if (rc < 0)
  1680.       {
  1681.          char *pchErrorDesc=malloc(1000);
  1682.          char *pchErrorTitle=malloc(100);
  1683.          *pchErrorDesc=0;
  1684.          *pchErrorTitle=0;
  1685.  
  1686.          GetRexxErrorMsg(pchErrorDesc, pchErrorTitle, -rc);
  1687.  
  1688.          SendMsg(client, REXXM_ERROR, pchErrorDesc, pchErrorTitle);
  1689.       }
  1690.       else
  1691.       {
  1692.          char *pchErrorText=malloc(50);
  1693.  
  1694.          sprintf(pchErrorText, "System error %d", rc);
  1695.          SendMsg(client, REXXM_ERROR, pchErrorText, NULL);
  1696.       }
  1697.    }
  1698.    else
  1699.       SendMsg(client, REXXM_STOPSCRIPT, NULL, NULL);
  1700.  
  1701.    WinDestroyMsgQueue(hmq);
  1702.    WinTerminate(hab);
  1703.  
  1704.    DEINSTALLEXPT;
  1705.  
  1706.    return;
  1707. }
  1708.  
  1709. static ULONG _System FSSetText(PUCHAR pchFuncName, ULONG argc, PRXSTRING argv, PSZ pchQueueName, PRXSTRING pRetStr)
  1710. {
  1711.    extern FTNMESSAGE CurrentMessage;
  1712.    extern BOOL bTemplateProcessed;
  1713.  
  1714.    char *pchTempName;
  1715.    SHVBLOCK VarBlock;
  1716.    ULONG ulNum=0;
  1717.    PCHAR pchRest=NULL;
  1718.    ULONG i;
  1719.    PCHAR pchNewText=NULL, pchHelp;
  1720.    ULONG ulReqSpace=0;
  1721.    PSTRINGLIST pStringList=NULL, pLast=NULL;
  1722.  
  1723.    pchFuncName = pchFuncName;
  1724.    pchQueueName = pchQueueName;
  1725.  
  1726.    if (argc != 1)
  1727.       return 40;
  1728.  
  1729.    /* Stem.0 abfragen */
  1730.    pchTempName=calloc(1, strlen(argv[0].strptr)+20);
  1731.    sprintf(pchTempName, "%s.0", argv[0].strptr);
  1732.  
  1733.    memset(&VarBlock, 0, sizeof(VarBlock));
  1734.    VarBlock.shvnext=NULL;
  1735.    VarBlock.shvname.strptr= pchTempName;
  1736.    VarBlock.shvname.strlength = strlen(pchTempName);
  1737.    VarBlock.shvnamelen=VarBlock.shvname.strlength;
  1738.    VarBlock.shvcode = RXSHV_SYFET;
  1739.  
  1740.    if (RexxVariablePool(&VarBlock))
  1741.    {
  1742.       free(pchTempName);
  1743.       return 40;
  1744.    }
  1745.    free(pchTempName);
  1746.  
  1747.    pchTempName = calloc(1, VarBlock.shvvalue.strlength+1);
  1748.    strncpy(pchTempName,VarBlock.shvvalue.strptr, VarBlock.shvvalue.strlength);
  1749.    DosFreeMem(VarBlock.shvvalue.strptr);
  1750.  
  1751.    /* numerischen Wert auslesen */
  1752.    ulNum=strtoul(pchTempName, &pchRest, 10);
  1753.    if (*pchRest)
  1754.    {
  1755.       free(pchTempName);
  1756.       return 40;
  1757.    }
  1758.    free(pchTempName);
  1759.  
  1760.    if (ulNum > 0)
  1761.    {
  1762.       /* Alle Variablen abfragen */
  1763.       pchTempName=malloc(strlen(argv[0].strptr)+20);
  1764.  
  1765.       for (i=0; i<ulNum; i++)
  1766.       {
  1767.          memset(&VarBlock, 0, sizeof(VarBlock));
  1768.  
  1769.          VarBlock.shvname.strptr = pchTempName;
  1770.          sprintf(pchTempName, "%s.%d", argv[0].strptr, i+1);
  1771.          VarBlock.shvname.strlength = strlen(pchTempName);
  1772.          VarBlock.shvnamelen = VarBlock.shvname.strlength;
  1773.          VarBlock.shvcode = RXSHV_SYFET;
  1774.  
  1775.          if (!RexxVariablePool(&VarBlock))
  1776.          {
  1777.             /* Wert kopieren */
  1778.             if (pStringList)
  1779.             {
  1780.                pLast->next = malloc(sizeof(STRINGLIST));
  1781.                pLast= pLast->next;
  1782.             }
  1783.             else
  1784.                pStringList = pLast = malloc(sizeof(STRINGLIST));
  1785.             pLast->next=NULL;
  1786.             pLast->pchLine = calloc(1, VarBlock.shvvalue.strlength+1);
  1787.             memcpy(pLast->pchLine, VarBlock.shvvalue.strptr, VarBlock.shvvalue.strlength);
  1788.             DosFreeMem(VarBlock.shvvalue.strptr);
  1789.             ulReqSpace += VarBlock.shvvalue.strlength+2;
  1790.          }
  1791.          else
  1792.          {
  1793.             /* Fehler */
  1794.             /* bisherige Liste freigeben */
  1795.             while (pStringList)
  1796.             {
  1797.                pLast = pStringList->next;
  1798.                free(pStringList->pchLine);
  1799.                free(pStringList);
  1800.                pStringList = pLast;
  1801.             }
  1802.             free(pchTempName);
  1803.             return 40;
  1804.          }
  1805.       }
  1806.       free(pchTempName);
  1807.  
  1808.       /* String f. neuen Text bereitstellen */
  1809.       pchNewText = malloc(ulReqSpace);
  1810.       *pchNewText=0;
  1811.       pchHelp = pchNewText;
  1812.  
  1813.       /* Liste zusammenkopieren */
  1814.       while (pStringList)
  1815.       {
  1816.          strcpy(pchHelp, pStringList->pchLine);
  1817.          pchHelp = strchr(pchHelp, 0);
  1818.          *pchHelp++ = '\n';
  1819.          pLast = pStringList->next;
  1820.          free(pStringList->pchLine);
  1821.          free(pStringList);
  1822.          pStringList = pLast;
  1823.       }
  1824.       *pchHelp = 0;
  1825.  
  1826.    }
  1827.    else
  1828.       pchNewText=calloc(1, 1);
  1829.  
  1830.    /* in pchNewText steht nun der neue Text */
  1831.    if (CurrentMessage.pchMessageText)
  1832.       free(CurrentMessage.pchMessageText);
  1833.  
  1834.    CurrentMessage.pchMessageText = pchNewText;
  1835.    CurrentMessage.pchSeenPath=NULL;
  1836.    WinSetDlgItemText(client, IDML_MAINEDIT, "");
  1837.    DisplayMsgText(client, &CurrentMessage);
  1838.  
  1839.    /* Text wurde geaendert, weitere Template-Verarbeitung macht keinen
  1840.       Sinn mehr, deshalb abschalten. */
  1841.    bTemplateProcessed = TRUE;
  1842.  
  1843.    strcpy(pRetStr->strptr, "OK");
  1844.    pRetStr->strlength = 2;
  1845.  
  1846.    return 0;
  1847. }
  1848.  
  1849. static ULONG _System FSLookupName(PUCHAR pchFuncName, ULONG argc, PRXSTRING argv, PSZ pchQueueName, PRXSTRING pRetStr)
  1850. {
  1851.    PNODEDATA pNodeData=NULL;
  1852.    extern PDOMAINS domains;
  1853.    char pchErrDomain[LEN_DOMAIN+1];
  1854.    char *pchVarName;
  1855.    char pchTemp[40];
  1856.    char *pchLookupName;
  1857.    int iRet, i;
  1858.  
  1859.    pchFuncName = pchFuncName;
  1860.    pchQueueName = pchQueueName;
  1861.  
  1862.    if (argc != 2)
  1863.       return 40;
  1864.  
  1865.    pchLookupName = calloc(1, LEN_USERNAME+1);
  1866.    strncpy(pchLookupName, argv[0].strptr, LEN_USERNAME);
  1867.  
  1868.    iRet = LookupNodelists(pchLookupName, domains, &pNodeData, pchErrDomain);
  1869.  
  1870.    if (iRet == 0)
  1871.    {
  1872.       strcpy(pRetStr->strptr, "NotFound");
  1873.       pRetStr->strlength = strlen(pRetStr->strptr);
  1874.    }
  1875.    else
  1876.       if (iRet < 0)
  1877.       {
  1878.          strcpy(pRetStr->strptr, "Error");
  1879.          pRetStr->strlength = strlen(pRetStr->strptr);
  1880.       }
  1881.       else
  1882.       {
  1883.          pchVarName = malloc(argv[1].strlength + 20);
  1884.          sprintf(pchVarName, "%s.0", argv[1].strptr);
  1885.          _itoa(iRet, pchTemp, 10);
  1886.          SetRexxVar(pchVarName, pchTemp);
  1887.  
  1888.          for (i=0; i < iRet; i++)
  1889.          {
  1890.             sprintf(pchVarName, "%s.%d.Address", argv[1].strptr, i+1);
  1891.             NetAddrToString(pchTemp, (PFTNADDRESS) &pNodeData[i].Address);
  1892.             SetRexxVar(pchVarName, pchTemp);
  1893.  
  1894.             sprintf(pchVarName, "%s.%d.Name", argv[1].strptr, i+1);
  1895.             SetRexxVar(pchVarName, pNodeData[i].SysopName);
  1896.  
  1897.             sprintf(pchVarName, "%s.%d.System", argv[1].strptr, i+1);
  1898.             SetRexxVar(pchVarName, pNodeData[i].SystemName);
  1899.  
  1900.             sprintf(pchVarName, "%s.%d.Phone", argv[1].strptr, i+1);
  1901.             SetRexxVar(pchVarName, pNodeData[i].PhoneNr);
  1902.  
  1903.             sprintf(pchVarName, "%s.%d.Location", argv[1].strptr, i+1);
  1904.             SetRexxVar(pchVarName, pNodeData[i].Location);
  1905.  
  1906.             sprintf(pchVarName, "%s.%d.Password", argv[1].strptr, i+1);
  1907.             SetRexxVar(pchVarName, pNodeData[i].Password);
  1908.  
  1909.             sprintf(pchVarName, "%s.%d.Modem", argv[1].strptr, i+1);
  1910.             _itoa(pNodeData[i].ModemType, pchTemp, 10);
  1911.             SetRexxVar(pchVarName, pchTemp);
  1912.  
  1913.             sprintf(pchVarName, "%s.%d.Baud", argv[1].strptr, i+1);
  1914.             _itoa(pNodeData[i].BaudRate, pchTemp, 10);
  1915.             SetRexxVar(pchVarName, pchTemp);
  1916.  
  1917.             sprintf(pchVarName, "%s.%d.UserCost", argv[1].strptr, i+1);
  1918.             _itoa(pNodeData[i].UserCost, pchTemp, 10);
  1919.             SetRexxVar(pchVarName, pchTemp);
  1920.  
  1921.             sprintf(pchVarName, "%s.%d.CallCost", argv[1].strptr, i+1);
  1922.             _itoa(pNodeData[i].CallCost, pchTemp, 10);
  1923.             SetRexxVar(pchVarName, pchTemp);
  1924.  
  1925.             sprintf(pchVarName, "%s.%d.Flags", argv[1].strptr, i+1);
  1926.             SetRexxVar(pchVarName, NLFlagsToString(&pNodeData[i], pchTemp));
  1927.          }
  1928.          free(pNodeData);
  1929.          free(pchVarName);
  1930.  
  1931.          strcpy(pRetStr->strptr, "OK");
  1932.          pRetStr->strlength= 2;
  1933.       }
  1934.  
  1935.    free(pchLookupName);
  1936.  
  1937.    return 0;
  1938. }
  1939.  
  1940. static ULONG _System FSLookupAddress(PUCHAR pchFuncName, ULONG argc, PRXSTRING argv, PSZ pchQueueName, PRXSTRING pRetStr)
  1941. {
  1942.    PNODEDATA pNodeData=NULL;
  1943.    extern PDOMAINS domains;
  1944.    char pchErrDomain[LEN_DOMAIN+1];
  1945.    char *pchVarName;
  1946.    char pchTemp[40];
  1947.    char *pchLookupAddress;
  1948.  
  1949.    pchFuncName = pchFuncName;
  1950.    pchQueueName = pchQueueName;
  1951.  
  1952.    if (argc != 2)
  1953.       return 40;
  1954.  
  1955.    pchLookupAddress = calloc(1, LEN_5DADDRESS+1);
  1956.    strncpy(pchLookupAddress, argv[0].strptr, LEN_5DADDRESS);
  1957.  
  1958.    switch(LookupAddress(pchLookupAddress, domains, &pNodeData, pchErrDomain))
  1959.    {
  1960.       case 0:
  1961.          strcpy(pRetStr->strptr, "NotFound");
  1962.          pRetStr->strlength = strlen(pRetStr->strptr);
  1963.          break;
  1964.  
  1965.       case 1:
  1966.          pchVarName = malloc(argv[1].strlength + 15);
  1967.          strcpy(pchVarName, argv[1].strptr);
  1968.          strcat(pchVarName, ".Address");
  1969.          SetRexxVar(pchVarName, pchLookupAddress);
  1970.          strcpy(pchVarName, argv[1].strptr);
  1971.          strcat(pchVarName, ".Name");
  1972.          SetRexxVar(pchVarName, pNodeData->SysopName);
  1973.          strcpy(pchVarName, argv[1].strptr);
  1974.          strcat(pchVarName, ".System");
  1975.          SetRexxVar(pchVarName, pNodeData->SystemName);
  1976.          strcpy(pchVarName, argv[1].strptr);
  1977.          strcat(pchVarName, ".Phone");
  1978.          SetRexxVar(pchVarName, pNodeData->PhoneNr);
  1979.          strcpy(pchVarName, argv[1].strptr);
  1980.          strcat(pchVarName, ".Location");
  1981.          SetRexxVar(pchVarName, pNodeData->Location);
  1982.          strcpy(pchVarName, argv[1].strptr);
  1983.          strcat(pchVarName, ".Password");
  1984.          SetRexxVar(pchVarName, pNodeData->Password);
  1985.          strcpy(pchVarName, argv[1].strptr);
  1986.          strcat(pchVarName, ".Modem");
  1987.          _itoa(pNodeData->ModemType, pchTemp, 10);
  1988.          SetRexxVar(pchVarName, pchTemp);
  1989.          strcpy(pchVarName, argv[1].strptr);
  1990.          strcat(pchVarName, ".Baud");
  1991.          _itoa(pNodeData->BaudRate, pchTemp, 10);
  1992.          SetRexxVar(pchVarName, pchTemp);
  1993.          strcpy(pchVarName, argv[1].strptr);
  1994.          strcat(pchVarName, ".UserCost");
  1995.          _itoa(pNodeData->UserCost, pchTemp, 10);
  1996.          SetRexxVar(pchVarName, pchTemp);
  1997.          strcpy(pchVarName, argv[1].strptr);
  1998.          strcat(pchVarName, ".CallCost");
  1999.          _itoa(pNodeData->CallCost, pchTemp, 10);
  2000.          SetRexxVar(pchVarName, pchTemp);
  2001.          strcpy(pchVarName, argv[1].strptr);
  2002.          strcat(pchVarName, ".Flags");
  2003.          SetRexxVar(pchVarName, NLFlagsToString(pNodeData, pchTemp));
  2004.          free(pNodeData);
  2005.          free(pchVarName);
  2006.  
  2007.          strcpy(pRetStr->strptr, "OK");
  2008.          pRetStr->strlength= 2;
  2009.          break;
  2010.  
  2011.       default:
  2012.          strcpy(pRetStr->strptr, "Error");
  2013.          pRetStr->strlength = strlen(pRetStr->strptr);
  2014.          break;
  2015.    }
  2016.  
  2017.    free(pchLookupAddress);
  2018.  
  2019.    return 0;
  2020. }
  2021.  
  2022. static ULONG _System FSSetEntryField(PUCHAR pchFuncName, ULONG argc, PRXSTRING argv, PSZ pchQueueName, PRXSTRING pRetStr)
  2023. {
  2024.    pchFuncName = pchFuncName;
  2025.    pchQueueName = pchQueueName;
  2026.  
  2027.    if (argc != 1)
  2028.       return 40;
  2029.  
  2030.    if (hwndMonitor)
  2031.    {
  2032.       WinSetDlgItemText(hwndMonitor, IDD_RXMONITOR+2, argv[0].strptr);
  2033.       strcpy(pRetStr->strptr, "OK");
  2034.    }
  2035.    else
  2036.    {
  2037.       strcpy(pRetStr->strptr, "NoMonitor");
  2038.    }
  2039.    pRetStr->strlength = strlen(pRetStr->strptr);
  2040.  
  2041.    return 0;
  2042. }
  2043.  
  2044. static ULONG _System FSCls(PUCHAR pchFuncName, ULONG argc, PRXSTRING argv, PSZ pchQueueName, PRXSTRING pRetStr)
  2045. {
  2046.    pchFuncName = pchFuncName;
  2047.    pchQueueName = pchQueueName;
  2048.    argv=argv;
  2049.  
  2050.    if (argc != 0)
  2051.       return 40;
  2052.  
  2053.    if (hwndMonitor)
  2054.    {
  2055.       WinPostMsg(hwndMonitor, REXXM_CLS, NULL, NULL);
  2056.       strcpy(pRetStr->strptr, "OK");
  2057.    }
  2058.    else
  2059.    {
  2060.       strcpy(pRetStr->strptr, "NoMonitor");
  2061.    }
  2062.    pRetStr->strlength = strlen(pRetStr->strptr);
  2063.  
  2064.    return 0;
  2065. }
  2066.  
  2067. static ULONG _System FSSetHeader(PUCHAR pchFuncName, ULONG argc, PRXSTRING argv, PSZ pchQueueName, PRXSTRING pRetStr)
  2068. {
  2069.    char pchFromName[LEN_USERNAME+1];
  2070.    char pchToName[LEN_USERNAME+1];
  2071.    char pchSubject[LEN_SUBJECT+1];
  2072.    char pchFromAddr[LEN_5DADDRESS+1];
  2073.    char pchToAddr[LEN_5DADDRESS+1];
  2074.    char *pchVarName;
  2075.    ULONG ret=0;
  2076.  
  2077.    pchFuncName = pchFuncName;
  2078.    pchQueueName = pchQueueName;
  2079.  
  2080.    if (argc != 1)
  2081.       return 40;
  2082.  
  2083.    pchVarName=malloc(argv[0].strlength + 30);
  2084.  
  2085.    sprintf(pchVarName, "%s.%s", argv[0].strptr, "From");
  2086.    if (!QueryRexxVar(pchVarName, pchFromName, LEN_USERNAME+1))
  2087.    {
  2088.       sprintf(pchVarName, "%s.%s", argv[0].strptr, "To");
  2089.       if (!QueryRexxVar(pchVarName, pchToName, LEN_USERNAME+1))
  2090.       {
  2091.          sprintf(pchVarName, "%s.%s", argv[0].strptr, "FromAddress");
  2092.          if (!QueryRexxVar(pchVarName, pchFromAddr, LEN_5DADDRESS+1))
  2093.          {
  2094.             sprintf(pchVarName, "%s.%s", argv[0].strptr, "ToAddress");
  2095.             if (!QueryRexxVar(pchVarName, pchToAddr, LEN_5DADDRESS+1))
  2096.             {
  2097.                sprintf(pchVarName, "%s.%s", argv[0].strptr, "Subj");
  2098.                if (!QueryRexxVar(pchVarName, pchSubject, LEN_SUBJECT+1))
  2099.                {
  2100.                   extern MSGHEADER CurrentHeader;
  2101.  
  2102.                   /* Alles da, Header updaten */
  2103.                   strcpy(CurrentHeader.pchFromName, pchFromName);
  2104.                   strcpy(CurrentHeader.pchToName,   pchToName);
  2105.                   strcpy(CurrentHeader.pchSubject,  pchSubject);
  2106.                   StringToNetAddr(pchFromAddr, &CurrentHeader.FromAddress, NULL);
  2107.                   StringToNetAddr(pchToAddr,   &CurrentHeader.ToAddress, NULL);
  2108.  
  2109.                   WinSetDlgItemText(client, IDML_MAINEDIT, "");
  2110.                   DisplayMessage(TRUE);
  2111.                   /*UpdateDisplay(FALSE, TRUE);*/
  2112.                }
  2113.                else
  2114.                   ret=40;
  2115.             }
  2116.             else
  2117.                ret=40;
  2118.          }
  2119.          else
  2120.             ret=40;
  2121.       }
  2122.       else
  2123.          ret=40;
  2124.    }
  2125.    else
  2126.       ret=40;
  2127.  
  2128.    free(pchVarName);
  2129.  
  2130.    if (ret)
  2131.       strcpy(pRetStr->strptr, "Error");
  2132.    else
  2133.       strcpy(pRetStr->strptr, "OK");
  2134.  
  2135.    pRetStr->strlength = strlen(pRetStr->strptr);
  2136.  
  2137.    return ret;
  2138. }
  2139.  
  2140.  
  2141. #define ENC(c) (c?(((c) & 077) + ' '):'`')
  2142. #define DEC(c) ((c=='`')?0:((c) - ' '))
  2143.  
  2144. static ULONG _System FSEncodeLine(PUCHAR pchFuncName, ULONG argc, PRXSTRING argv, PSZ pchQueueName, PRXSTRING pRetStr)
  2145. {
  2146.    ULONG ret=0;
  2147.  
  2148.    pchFuncName = pchFuncName;
  2149.    pchQueueName = pchQueueName;
  2150.  
  2151.    if (argc == 1)
  2152.    {
  2153.       if (argv[0].strlength)
  2154.       {
  2155.          int i=0, j=1;
  2156.  
  2157.          pRetStr->strptr[0] = ENC(argv[0].strlength);
  2158.  
  2159.          while (i < argv[0].strlength)
  2160.          {
  2161.             pRetStr->strptr[j]=ENC( argv[0].strptr[i] >> 2);
  2162.             pRetStr->strptr[j+1]=ENC( (argv[0].strptr[i] << 4) & 060 | (argv[0].strptr[i+1] >> 4) & 017);
  2163.             pRetStr->strptr[j+2]=ENC( (argv[0].strptr[i+1] << 2) & 074 | (argv[0].strptr[i+2] >> 6) & 03);
  2164.             pRetStr->strptr[j+3]=ENC( argv[0].strptr[i+2] & 077);
  2165.  
  2166.             i+=3;
  2167.             j+=4;
  2168.          }
  2169.          pRetStr->strlength=j;
  2170.       }
  2171.    }
  2172.    else
  2173.       ret=40;
  2174.  
  2175.    return ret;
  2176. }
  2177.  
  2178. static ULONG _System FSDecodeLine(PUCHAR pchFuncName, ULONG argc, PRXSTRING argv, PSZ pchQueueName, PRXSTRING pRetStr)
  2179. {
  2180.    ULONG ret=0;
  2181.  
  2182.    pchFuncName = pchFuncName;
  2183.    pchQueueName = pchQueueName;
  2184.  
  2185.    if (argc == 1)
  2186.    {
  2187.       if (argv[0].strlength)
  2188.       {
  2189.         int i=0, j=1;
  2190.         int numbytes=0;
  2191.  
  2192.         numbytes = DEC(argv[0].strptr[0]);
  2193.  
  2194.         while (j < argv[0].strlength &&
  2195.                i < numbytes)
  2196.         {
  2197.            pRetStr->strptr[i]  = (DEC(argv[0].strptr[j]) << 2) | (DEC(argv[0].strptr[j+1]) >> 4);
  2198.            pRetStr->strptr[i+1]= (DEC(argv[0].strptr[j+1]) << 4) | (DEC(argv[0].strptr[j+2]) >> 2);
  2199.            pRetStr->strptr[i+2]= (DEC(argv[0].strptr[j+2]) << 6) | DEC(argv[0].strptr[j+3]);
  2200.  
  2201.            i+=3;
  2202.            j+=4;
  2203.         }
  2204.         pRetStr->strlength=numbytes;
  2205.       }
  2206.    }
  2207.    else
  2208.       ret=40;
  2209.  
  2210.    return ret;
  2211. }
  2212.  
  2213. /*-------------------------------- Modulende --------------------------------*/
  2214.  
  2215.  
  2216.