unix/hostemu.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 2009-2017 Rexx Language Association. All rights reserved. */
4 /* */
5 /* This program and the accompanying materials are made available under */
6 /* the terms of the Common Public License v1.0 which accompanies this */
7 /* distribution. A copy is also available at the following address: */
8 /* https://www.oorexx.org/license.html */
9 /* */
10 /* Redistribution and use in source and binary forms, with or */
11 /* without modification, are permitted provided that the following */
12 /* conditions are met: */
13 /* */
14 /* Redistributions of source code must retain the above copyright */
15 /* notice, this list of conditions and the following disclaimer. */
16 /* Redistributions in binary form must reproduce the above copyright */
17 /* notice, this list of conditions and the following disclaimer in */
18 /* the documentation and/or other materials provided with the distribution. */
19 /* */
20 /* Neither the name of Rexx Language Association nor the names */
21 /* of its contributors may be used to endorse or promote products */
22 /* derived from this software without specific prior written permission. */
23 /* */
24 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
25 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
26 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
27 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
28 /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
29 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
30 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
31 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
32 /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
33 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
34 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
35 /* */
36 /* Authors; */
37 /* W. David Ashley <dashley@us.ibm.com> */
38 /* */
39 /*----------------------------------------------------------------------------*/
40 
41 
42 #include <stdlib.h>
43 #include <string.h>
44 #include <stdio.h>
45 #include <sys/types.h>
46 #include <unistd.h>
47 #include <pthread.h>
48 #include <rexx.h>
49 #include <oorexxapi.h>
50 #include "PlatformDefinitions.h" // first need: DEFRXSTRING
51 
52 #include "../../hostemu.h"
53 
54 
55 /*--------------------------------------------------------------------*/
56 /* */
57 /* Global variables */
58 /* */
59 /*--------------------------------------------------------------------*/
60 
61 // #define HOSTEMU_DEBUG
62 
65 long lCmdPtr;
66 unsigned long ulNumSym;
68 char szInline[100000];
69 long lStmtType;
70 
71 
72 /*--------------------------------------------------------------------*/
73 /* */
74 /* Local definitions */
75 /* */
76 /*--------------------------------------------------------------------*/
77 
78 typedef struct _LL
79  {
80  struct _LL * prev;
81  struct _LL * next;
82  char FileName [1024];
83  FILE * pFile;
84  } LL;
85 typedef LL * PLL;
86 
87 
88 /*--------------------------------------------------------------------*/
89 /* */
90 /* Local variables */
91 /* */
92 /*--------------------------------------------------------------------*/
93 
94 static pthread_mutex_t hmtxExecIO = PTHREAD_MUTEX_INITIALIZER;
95 static PLL pHead = NULL;
96 static PLL pTail = NULL;
97 
98 
99 /*--------------------------------------------------------------------*/
100 /* */
101 /* Local function prototypes */
102 /* */
103 /*--------------------------------------------------------------------*/
104 
105 static unsigned long ExecIO_Write_From_Stem(
106  PLL pll); /* Pointer to file linked list item */
107 static unsigned long ExecIO_Write_From_Queue(
108  PLL pll); /* Pointer to file linked list item */
109 static unsigned long ExecIO_Read_To_Stem(
110  PLL pll); /* Pointer to file linked list item */
111 static unsigned long ExecIO_Read_To_Queue(
112  PLL pll); /* Pointer to file linked list item */
113 static PLL Search_LL(
114  char * SFilename); /* Source file name */
115 static void Insert_LL(
116  PLL pll); /* Pointer to the new item */
117 static void Delete_LL(
118  PLL pll); /* Pointer to the item to be deleted */
119 static long queued(
120  void); /* No arguments */
121 static void push(
122  char * pushstr, /* String to be pushed onto queue */
123  long lOp); /* 0 = FIFO, 1 = LIFO */
124 static char * pull(
125  void); /* No arguments */
126 
127 /*--------------------------------------------------------------------*/
128 /* */
129 /* Function: FetchRexxVar() */
130 /* */
131 /* Description: Fetch contents of a REXX variable from the current */
132 /* variable pool. The caller is responsible for freeing */
133 /* the buffer pointed to by the return value via */
134 /* DosFreeMem(). */
135 /* */
136 /* Input: PSZ - name of the REXX variable to be fetched */
137 /* PRXSTRING - pointer to the return RXSTRING structure */
138 /* */
139 /* Returns: ULONG - return code from RexxVariablePool() */
140 /* */
141 /* Notes: None. */
142 /* */
143 /*--------------------------------------------------------------------*/
144 
145 unsigned long FetchRexxVar (
146  char * pszVar, /* Variable name */
147  PRXSTRING prxVar) /* REXX variable contents */
148  {
149 
150  /* local function variables */
151  SHVBLOCK RxVarBlock;
152  unsigned long ulRetc;
153  char * pszTemp;
154 
155  /* initialize the shared variable block */
156  RxVarBlock.shvnext = NULL;
157  RxVarBlock.shvname.strptr = pszVar;
158  RxVarBlock.shvname.strlength = strlen(pszVar);
159  RxVarBlock.shvnamelen = RxVarBlock.shvname.strlength;
160  RxVarBlock.shvvalue.strptr = NULL;
161  RxVarBlock.shvvalue.strlength = 0;
162  RxVarBlock.shvvaluelen = 0;
163  RxVarBlock.shvcode = RXSHV_SYFET;
164  RxVarBlock.shvret = RXSHV_OK;
165 
166  /* fetch variable from pool */
167  ulRetc = RexxVariablePool(&RxVarBlock);
168 
169  /* test return code */
170  if (ulRetc != RXSHV_OK && ulRetc != RXSHV_NEWV) {
171  prxVar -> strptr = NULL;
172  prxVar -> strlength = 0;
173  }
174  else {
175  /* allocate a new buffer for the Rexx variable pool value */
176  pszTemp = (char *) RexxAllocateMemory(RxVarBlock.shvvalue.strlength + 1);
177  if (pszTemp == NULL) {
178  /* no buffer available so return a NULL Rexx value */
179  prxVar -> strptr = NULL;
180  prxVar -> strlength = 0;
181  ulRetc = RXSHV_MEMFL;
182  }
183  else {
184  /* copy to new buffer and zero-terminate */
185  memmove(pszTemp, RxVarBlock.shvvalue.strptr,
186  RxVarBlock.shvvalue.strlength);
187  *(pszTemp + RxVarBlock.shvvalue.strlength) = '\0';
188  prxVar -> strptr = pszTemp;
189  prxVar -> strlength = RxVarBlock.shvvalue.strlength;
190  }
191  // free memory returned from RexxVariablePool API
192  RexxFreeMemory(RxVarBlock.shvvalue.strptr);
193  }
194 
195  return ulRetc;
196  }
197 
198 
199 /*--------------------------------------------------------------------*/
200 /* */
201 /* Function: SetRexxVar() */
202 /* */
203 /* Description: Sets the contents of a variable in the REXX variable */
204 /* pool. */
205 /* */
206 /* Input: PSZ - name of the REXX variable to be set */
207 /* PVOID - pointer to new contents for variable */
208 /* ULONG - buffer size of new contents */
209 /* */
210 /* Returns: ULONG - return code from RexxVariablePool() */
211 /* */
212 /* Notes: None. */
213 /* */
214 /*--------------------------------------------------------------------*/
215 
216 unsigned long SetRexxVar (
217  char * pszVar, /* Variable name to be set */
218  char * pValue, /* Ptr to new value */
219  size_t ulLen) /* Value length */
220  {
221 
222  /* local function data */
223  SHVBLOCK RxVarBlock;
224  unsigned long ulRetc;
225 
226  /* initialize RxVarBlock */
227  RxVarBlock.shvnext = NULL;
228  RxVarBlock.shvname.strptr = pszVar;
229  RxVarBlock.shvname.strlength = strlen(pszVar);
230  RxVarBlock.shvnamelen = RxVarBlock.shvname.strlength;
231  RxVarBlock.shvvalue.strptr = pValue;
232  RxVarBlock.shvvalue.strlength = ulLen;
233  RxVarBlock.shvvaluelen = ulLen;
234  RxVarBlock.shvcode = RXSHV_SYSET;
235  RxVarBlock.shvret = RXSHV_OK;
236 
237  /* set variable in pool */
238  ulRetc = RexxVariablePool(&RxVarBlock);
239 
240  /* test return code */
241  if (ulRetc == RXSHV_NEWV) {
242  ulRetc = RXSHV_OK;
243  }
244 
245  return ulRetc;
246  }
247 
248 
249 /*--------------------------------------------------------------------*/
250 /* */
251 /* Function: GrxHost() */
252 /* */
253 /* Description: Emulates the IBM host environment commands. */
254 /* */
255 /* Input: Command string */
256 /* Pointer to return flags */
257 /* Pointer to return string */
258 /* */
259 /* Returns: Return indicating success or failure */
260 /* */
261 /* References: None. */
262 /* */
263 /* Notes: */
264 /* */
265 /*--------------------------------------------------------------------*/
266 
268  unsigned short int *flags,
269  PRXSTRING retc)
270  {
271 
272  /* Local function variables */
273  unsigned long i, rc = 0;
274  PLL pll;
275 
276  #ifdef HOSTEMU_DEBUG
277  printf("HOSTEMU: Subcom called.\n");
278  #endif
279 
280  /* request the semaphore so we can get exclusive access to */
281  /* our variables */
282  pthread_mutex_lock(&hmtxExecIO);
283 
284  /* initialize the global variables */
285  memset(&ExecIO_Options, '\0', sizeof(EXECIO_OPTIONS));
287  ExecIO_Options.fFinis = false;
289 
290  prxCmd = command;
291  lCmdPtr = 0;
292  ulNumSym = 0;
293  *flags = RXSUBCOM_OK;
294 
295  /* parse the command */
296  if (!yyparse ()) {
297  #ifdef HOSTEMU_DEBUG
298  printf("HOSTEMU: Parse complete, lStartRcd=%d, lRcdCnt=%d, lDirection=%d, fRW=%d, fFinis=%d\n",
301  #endif
302  if (lStmtType == HI_STMT) {
303  RexxSetHalt(getpid(), pthread_self());
304  }
305  else if (lStmtType == TE_STMT) {
306  RexxResetTrace(getpid(), pthread_self());
307  }
308  else if (lStmtType == TS_STMT) {
309  RexxSetTrace(getpid(), pthread_self());
310  }
311  else if (lStmtType == EXECIO_STMT) {
312  #ifdef HOSTEMU_DEBUG
313  printf("HOSTEMU: Executing execio statement.\n");
314  #endif
315  /* check to see if the file is already open */
317  if (pll == NULL) {
318  /* it is a new file, so open it and add to the list */
319  pll = (PLL)malloc(sizeof (LL));
320  if (pll == NULL) {
322  *flags = RXSUBCOM_FAILURE;
323  goto return_point;
324  }
325  memset(pll, '\0', sizeof (LL));
326  strcpy(pll -> FileName, ExecIO_Options.aFilename);
327  if (ExecIO_Options.fRW) {
328  /* DISKW */
329  pll -> pFile = fopen(pll -> FileName, "w+");
330  }
331  else {
332  /* DISKR */
333  pll -> pFile = fopen(pll -> FileName, "r+");
334  }
335  if (pll -> pFile == NULL) {
336  /* file could be opened so return an error */
337  free(pll);
338  rc = ERR_EXECIO_BAD_PLIST; // Bad PLIST
339  *flags = RXSUBCOM_FAILURE;
340  goto return_point;
341  }
342  Insert_LL(pll);
343  }
344  /* is this a read or write operation? */
345  if (ExecIO_Options.fRW) {
346  /* DISKW */
347  /* is this a stem or queue operation? */
348  if (strlen (ExecIO_Options.aStem)) {
349  rc = ExecIO_Write_From_Stem(pll);
350  }
351  else {
352  rc = ExecIO_Write_From_Queue(pll);
353  }
354  }
355  else {
356  /* DISKR */
357  /* is this a stem or queue operation? */
358  // also send any STEM. name SKIP request to Read_To_Queue()
359  // as Read_To_Stem() won't handle SKIP
360  if (strlen(ExecIO_Options.aStem) && (ExecIO_Options.lDirection != 2)) {
361  rc = ExecIO_Read_To_Stem(pll);
362  }
363  else {
364  rc = ExecIO_Read_To_Queue(pll);
365  }
366  }
367  /* process the FINIS option */
368  if (ExecIO_Options.fFinis) {
369  fclose(pll -> pFile);
370  Delete_LL(pll);
371  }
372  /* if the return code is 20 then set the failure flag */
373  if (rc == ERR_EXECIO_BAD_PLIST) {
374  *flags = RXSUBCOM_FAILURE;
375  }
376  }
377  else { /* bad statement type */
378  // should never happen, as parsing is restricted to the four known commands
379  *flags = RXSUBCOM_FAILURE;
380  rc = ERR_EXECIO_BAD_PLIST; // Bad PLIST
381  }
382  }
383  else { /* parse failed */
384  // we don't know whether parse failed due to an invalid command (which would be a failure)
385  // or due to e. g. a misformed EXECIO command (which would be an error)
386  *flags = RXSUBCOM_ERROR;
387  rc = ERR_EXECIO_BAD_PLIST; // Bad PLIST
388  }
389 
390  return_point:
391 
392  /* release our symbol table memory */
393  if (ulNumSym != 0) {
394  for (i = 0; i < ulNumSym; i++) {
395  free(pszSymbol[i]);
396  }
397  }
398 
399  pthread_mutex_unlock(&hmtxExecIO);
400 
401  snprintf(retc->strptr, DEFRXSTRING, "%ld", rc);
402  retc->strlength = strlen(retc->strptr);
403  #ifdef HOSTEMU_DEBUG
404  printf("HOSTEMU: Subcom return code = %u.\n", rc);
405  #endif
406  return rc;
407  }
408 
409 
410 /*--------------------------------------------------------------------*/
411 /* */
412 /* Function: ExecIO_Write_From_Stem */
413 /* */
414 /* Description: ExecIO write from a stem to a file. */
415 /* */
416 /* Input: Pointer to file linked list item */
417 /* */
418 /* Returns: Return indicating success or failure */
419 /* */
420 /* References: None. */
421 /* */
422 /* Notes: */
423 /* */
424 /* */
425 /*--------------------------------------------------------------------*/
426 
427 static unsigned long ExecIO_Write_From_Stem (
428  PLL pll) /* Pointer to file linked list item */
429  {
430 
431  /* Local function variables */
432  char * Stem; /* Stem variable name */
433  char * Index; /* Stem index value (string) */
434  RXSTRING rxVal; /* Rexx stem variable value */
435  int elements;
436 
437  /* process request */
438  if (ExecIO_Options.lRcdCnt == 0)
439  return 0;
440  size_t StemSize = strlen(ExecIO_Options.aStem) + 33;
441  Stem = (char *)malloc(StemSize);
442  if (Stem == NULL) {
443  return ERR_EXECIO_NO_STORAGE; // Insufficient free storage to load EXECIO
444  }
445  strcpy(Stem, ExecIO_Options.aStem);
446  size_t StemLen = strlen(Stem);
447  Index = Stem + StemLen;
448  if (ExecIO_Options.lRcdCnt == -1) {
449  /* process an "*" record count */
450  // get the number of elements
451  snprintf(Index, StemSize - StemLen, "%u", 0);
452  if (FetchRexxVar(Stem, &rxVal))
453  {
454  return ERR_EXECIO_VAR_INVALID; // Variable name supplied on STEM or VAR option was not valid
455  }
456  elements = atoi(rxVal.strptr);
457  RexxFreeMemory(rxVal.strptr);
458  while (ExecIO_Options.lStartRcd <= elements) {
459  snprintf(Index, StemSize - StemLen, "%ld", ExecIO_Options.lStartRcd);
460  if (FetchRexxVar(Stem, &rxVal))
461  {
462  return ERR_EXECIO_VAR_INVALID; // Variable name supplied on STEM or VAR option was not valid
463  }
464  fputs(rxVal.strptr, pll -> pFile);
465  fputs("\n", pll -> pFile);
466  RexxFreeMemory(rxVal.strptr);
468  }
469  }
470  else {
471  /* process a specific record count */
473  snprintf(Index, StemSize - StemLen, "%ld", ExecIO_Options.lStartRcd);
474  if (FetchRexxVar(Stem, &rxVal))
475  {
476  return ERR_EXECIO_VAR_INVALID; // Variable name supplied on STEM or VAR option was not valid
477  }
478  fputs(rxVal.strptr, pll -> pFile);
479  fputs("\n", pll -> pFile);
480  RexxFreeMemory(rxVal.strptr);
482  }
483  }
484  fflush (pll -> pFile);
485 
486  /* return with successful return code */
487  return 0;
488  }
489 
490 
491 /*--------------------------------------------------------------------*/
492 /* */
493 /* Function: ExecIO_Write_From_Queue */
494 /* */
495 /* Description: ExecIO write from the queue to a file. */
496 /* */
497 /* Input: Pointer to file linked list item */
498 /* */
499 /* Returns: Return indicating success or failure */
500 /* */
501 /* References: None. */
502 /* */
503 /* Notes: */
504 /* */
505 /*--------------------------------------------------------------------*/
506 
507 static unsigned long ExecIO_Write_From_Queue (
508  PLL pll) /* Pointer to file linked list item */
509  {
510 
511  /* Local function variables */
512  char * Item; /* Item pulled from the queue */
513  long items;
514 
515  /* process request */
516  if (ExecIO_Options.lRcdCnt == 0) {
517  return 0;
518  }
519  /* start at the proper place in the queue */
520  while (ExecIO_Options.lStartRcd > 1 && queued() > 0) {
521  Item = pull();
522  if (Item != NULL) {
523  RexxFreeMemory(Item);
524  }
526  }
527  if (ExecIO_Options.lRcdCnt == -1) {
528  /* process an "*" record count */
529  items = queued();
530  while (items > 0) {
531  Item = pull();
532  if (Item != NULL) {
533  fputs(Item, pll -> pFile);
534  fputs("\n", pll -> pFile);
535  RexxFreeMemory(Item);
536  }
537  else {
538  goto return_point;
539  }
540  items--;
541  }
542  }
543  else {
544  /* process a specific record count */
545  while (ExecIO_Options.lRcdCnt > 0) {
546  if (queued() == 0)
547  break;
548  Item = pull();
549  if (Item != NULL) {
550  fputs(Item, pll -> pFile);
551  fputs("\n", pll -> pFile);
552  RexxFreeMemory(Item);
553  }
554  else {
555  goto return_point;
556  }
558  }
559  }
560 
561  return_point:
562  fflush (pll -> pFile);
563 
564  /* return with successful return code */
565  return 0;
566  }
567 
568 
569 /*--------------------------------------------------------------------*/
570 /* */
571 /* Function: ExecIO_Read_To_Stem */
572 /* */
573 /* Description: ExecIO read from a file to a stem. */
574 /* */
575 /* Input: Pointer to file linked list item */
576 /* */
577 /* Returns: Return indicating success or failure */
578 /* */
579 /* References: None. */
580 /* */
581 /* Notes: */
582 /* */
583 /* */
584 /*--------------------------------------------------------------------*/
585 
586 static unsigned long ExecIO_Read_To_Stem (
587  PLL pll) /* Pointer to file linked list item */
588  {
589 
590  /* Local function variables */
591  char * Stem; /* Stem variable name */
592  char * Index; /* Stem index value (string) */
593  unsigned long ulRc = 0; /* Return code */
594  int i;
595 
596  /* process request */
597  size_t StemSize = strlen(ExecIO_Options.aStem) + 33;
598  Stem = (char *)malloc(StemSize);
599  if (Stem == NULL) {
600  return ERR_EXECIO_NO_STORAGE; // Insufficient free storage to load EXECIO
601  }
602 
603  // skip until we reach line number 'StartRcd'
604  for (i = 1; i < ExecIO_Options.lStartRcd; i++)
605  {
606  char* ignore; // avoid warning: ignoring return value of 'char* fgets(char*, int, FILE*)'
607  ignore = fgets(szInline, sizeof(szInline), pll -> pFile);
608  }
609 
610  strcpy(Stem, ExecIO_Options.aStem);
611  size_t StemLen = strlen(Stem);
612  Index = Stem + StemLen;
613  i = 0;
614 
615  if (ExecIO_Options.lRcdCnt == -1) {
616  /* process an "*" record count */
617  while (fgets(szInline, sizeof (szInline), pll -> pFile)) {
618  if (*(szInline + strlen(szInline) - 1) == '\n')
619  *(szInline + strlen(szInline) - 1) = '\0';
620  i++;
621  snprintf(Index, StemSize - StemLen, "%d", i);
622  if (SetRexxVar(Stem, szInline, strlen(szInline)))
623  {
624  return ERR_EXECIO_VAR_INVALID; // Variable name supplied on STEM or VAR option was not valid
625  }
626  }
627  }
628  else {
629  /* process a specific record count */
630  while (ExecIO_Options.lRcdCnt > 0) {
631  if (fgets(szInline, sizeof(szInline), pll -> pFile)) {
632  if (*(szInline + strlen(szInline) - 1) == '\n') {
633  *(szInline + strlen(szInline) - 1) = '\0';
634  }
635  i++;
636  snprintf(Index, StemSize - StemLen, "%d", i);
637  if (SetRexxVar(Stem, szInline, strlen(szInline)))
638  {
639  return ERR_EXECIO_VAR_INVALID; // Variable name supplied on STEM or VAR option was not valid
640  }
641  }
642  else {
643  ulRc = ERR_EXECIO_EOF; // EOF before specified number of lines were read
644  break;
645  }
647  }
648  }
649  snprintf(szInline, sizeof szInline, "%d", i);
650  snprintf(Index, StemSize - StemLen, "%d", 0);
651  if (SetRexxVar(Stem, szInline, strlen(szInline)))
652  {
653  return ERR_EXECIO_VAR_INVALID; // Variable name supplied on STEM or VAR option was not valid
654  }
655  free(Stem);
656 
657  /* return with successful return code */
658  return ulRc;
659  }
660 
661 
662 /*--------------------------------------------------------------------*/
663 /* */
664 /* Function: ExecIO_Read_To_Queue */
665 /* */
666 /* Description: ExecIO read file to the current queue. */
667 /* */
668 /* Input: Pointer to file linked list item */
669 /* */
670 /* Returns: Return indicating success or failure */
671 /* */
672 /* References: None. */
673 /* */
674 /* Notes: */
675 /* */
676 /*--------------------------------------------------------------------*/
677 
678 static unsigned long ExecIO_Read_To_Queue (
679  PLL pll) /* Pointer to file linked list item */
680  {
681 
682  /* Local function variables */
683  int i;
684 
685  /* process request */
686 
687  // skip until we reach line number 'StartRcd'
688  for (i = 1; i < ExecIO_Options.lStartRcd; i++)
689  {
690  char* ignore; // avoid warning: ignoring return value of 'char* fgets(char*, int, FILE*)'
691  ignore = fgets(szInline, sizeof(szInline), pll -> pFile);
692  }
693 
694  if (ExecIO_Options.lRcdCnt == -1) {
695  /* process an "*" record count */
696  while (fgets (szInline, sizeof (szInline), pll -> pFile)) {
697  if (*(szInline + strlen (szInline) - 1) == '\n') {
698  *(szInline + strlen (szInline) - 1) = '\0';
699  }
700  if (ExecIO_Options.lDirection != 2) {
702  }
703  }
704  }
705  else {
706  /* process a specific record count */
707  while (ExecIO_Options.lRcdCnt > 0) {
708  if (fgets (szInline, sizeof (szInline), pll -> pFile)) {
709  if (*(szInline + strlen (szInline) - 1) == '\n') {
710  *(szInline + strlen (szInline) - 1) = '\0';
711  }
712  if (ExecIO_Options.lDirection != 2) {
714  }
715  }
716  else {
717  return ERR_EXECIO_EOF; // EOF before specified number of lines were read
718  }
720  }
721  }
722 
723  /* return with successful return code */
724  return 0;
725  }
726 
727 
728 /*--------------------------------------------------------------------*/
729 /* */
730 /* Function: Search_LL */
731 /* */
732 /* Description: Search the linked list of files for a match. */
733 /* */
734 /* Input: Filename */
735 /* */
736 /* Returns: Pointer to found struct or NULL if not found */
737 /* */
738 /* References: None. */
739 /* */
740 /* Notes: */
741 /* */
742 /*--------------------------------------------------------------------*/
743 
744 static PLL Search_LL (
745  char * SFilename) /* Source file name */
746  {
747 
748  /* Local function variables */
749  PLL pll = pHead;
750 
751  while (pll != NULL) {
752  if (!strcmp (SFilename, pll -> FileName)) {
753  return pll;
754  }
755  pll = pll -> next;
756  }
757  return pll;
758  }
759 
760 
761 /*--------------------------------------------------------------------*/
762 /* */
763 /* Function: Insert_LL */
764 /* */
765 /* Description: Insert a new item at the end of the list. */
766 /* */
767 /* Input: Pointer to new item struct. */
768 /* */
769 /* Returns: None. */
770 /* */
771 /* References: None. */
772 /* */
773 /* Notes: */
774 /* */
775 /*--------------------------------------------------------------------*/
776 
777 static void Insert_LL (
778  PLL pll) /* Pointer to the new item */
779  {
780 
781  if (pHead == NULL) {
782  pHead = pll;
783  }
784  else {
785  pTail -> next = pll;
786  }
787  pll -> prev = pTail;
788  pll -> next = NULL;
789  pTail = pll;
790  return;
791  }
792 
793 
794 /*--------------------------------------------------------------------*/
795 /* */
796 /* Function: Delete_LL */
797 /* */
798 /* Description: Delete an item from the list. */
799 /* */
800 /* Input: Pointer to item to be deleted. */
801 /* */
802 /* Returns: None. */
803 /* */
804 /* References: None. */
805 /* */
806 /* Notes: */
807 /* */
808 /*--------------------------------------------------------------------*/
809 
810 static void Delete_LL (
811  PLL pll) /* Pointer to the item to be deleted */
812  {
813 
814  if (pHead == pll) {
815  pHead = pll -> next;
816  }
817  if (pTail == pll) {
818  pTail = pll -> prev;
819  }
820  if (pll -> next != NULL) {
821  pll -> next -> prev = pll -> prev;
822  }
823  if (pll -> prev != NULL) {
824  pll -> prev -> next = pll -> next;
825  }
826  free(pll);
827  return;
828  }
829 
830 
831 /*--------------------------------------------------------------------*/
832 /* */
833 /* Function: queued */
834 /* */
835 /* Description: Returns the number of items in the current Rexx queue */
836 /* */
837 /* Input: None. */
838 /* */
839 /* Returns: Number of queued items */
840 /* */
841 /* References: None. */
842 /* */
843 /* Notes: */
844 /* */
845 /*--------------------------------------------------------------------*/
846 
847 static long queued (
848  void) /* No arguments */
849  {
850 
851  /* local function variables */
852  size_t elements;
853 
854  RexxQueryQueue("SESSION", &elements);
855  return (long)elements;
856  }
857 
858 
859 /*--------------------------------------------------------------------*/
860 /* */
861 /* Function: push */
862 /* */
863 /* Description: Push an item onto the current Rexx queue. */
864 /* */
865 /* Input: Pointer to the string to be pushed */
866 /* */
867 /* Returns: Number of queued items */
868 /* */
869 /* References: None. */
870 /* */
871 /* Notes: */
872 /* */
873 /*--------------------------------------------------------------------*/
874 
875 static void push (
876  char * pushstr, /* String to be pushed onto queue */
877  long lOp) /* 0 = FIFO, 1 = LIFO */
878  {
879 
880  CONSTRXSTRING rxstr;
881 
882  rxstr.strptr = pushstr;
883  rxstr.strlength = strlen(pushstr);
884  RexxAddQueue("SESSION", &rxstr, (size_t)lOp);
885  return;
886  }
887 
888 
889 /*--------------------------------------------------------------------*/
890 /* */
891 /* Function: pull */
892 /* */
893 /* Description: Pull an item off the current Rexx queue. */
894 /* */
895 /* Input: None */
896 /* */
897 /* Returns: Pointer to the pulled string */
898 /* */
899 /* References: None. */
900 /* */
901 /* Notes: */
902 /* */
903 /*--------------------------------------------------------------------*/
904 
905 static char * pull (
906  void) /* No arguments */
907  {
908 
909  /* local function variables */
910  RXSTRING result = {0, NULL};
911  RexxReturnCode rc;
912 
913  rc = RexxPullFromQueue("SESSION", &result, NULL, RXQUEUE_WAIT);
914  return result.strptr;
915  }
916 
917 
918 static void hostemu_loader(RexxThreadContext *context) {
919  RexxReturnCode rc;
920 
921  rc = RexxRegisterSubcomExe("HostEmu", (void *)GrxHost, NULL);
922  #ifdef HOSTEMU_DEBUG
923  printf("HOSTEMU: Library loaded.\n");
924  printf("HOSTEMU: RexxRegisterSubcomExe retc = %d.\n", rc);
925  #endif
926  }
927 
928 
929 static void hostemu_unloader(RexxThreadContext *context) {
930  PLL pll;
931 
932  /* close all our open files */
933  pll = pHead;
934  while (pll != NULL) {
935  fclose (pll -> pFile);
936  pll = pll -> next;
937  }
938  }
939 
940 
943  REXX_INTERPRETER_4_0_0, // anything after 4.0.0 will work
944  "hostemu", // name of the package
945  "1.0.1", // package information
946  hostemu_loader, // load function
947  hostemu_unloader, // unload function
948  NULL, // the exported routines
949  NULL // the exported methods
950  };
951 
952 // package loading stub.
954 
RexxReturnCode RexxEntry RexxVariablePool(PSHVBLOCK pshvblock)
RexxReturnCode REXXENTRY RexxResetTrace(process_id_t procid, thread_id_t threadid)
RexxReturnCode REXXENTRY RexxSetTrace(process_id_t procid, thread_id_t threadid)
RexxReturnCode REXXENTRY RexxSetHalt(process_id_t procid, thread_id_t threadid)
#define HI_STMT
Definition: hostemu.h:93
#define ERR_EXECIO_VAR_INVALID
Definition: hostemu.h:89
#define TS_STMT
Definition: hostemu.h:95
int yyparse(void)
Definition: cmdparse.cpp:1203
#define ERR_EXECIO_NO_STORAGE
Definition: hostemu.h:88
#define EXECIO_STMT
Definition: hostemu.h:92
#define SYMTABLESIZE
Definition: hostemu.h:91
#define TE_STMT
Definition: hostemu.h:94
#define ERR_EXECIO_EOF
Definition: hostemu.h:86
#define ERR_EXECIO_BAD_PLIST
Definition: hostemu.h:87
#define REXX_INTERPRETER_4_0_0
Definition: oorexxapi.h:216
#define STANDARD_PACKAGE_HEADER
Definition: oorexxapi.h:230
RexxReturnCode REXXENTRY RexxRegisterSubcomExe(CONSTANT_STRING, REXXPFN, CONSTANT_STRING)
RexxReturnCode REXXENTRY RexxPullFromQueue(CONSTANT_STRING, PRXSTRING, RexxQueueTime *, size_t)
RexxReturnCode REXXENTRY RexxFreeMemory(void *)
RexxReturnCode REXXENTRY RexxAddQueue(CONSTANT_STRING, PCONSTRXSTRING, size_t)
CONSTANT_RXSTRING * PCONSTRXSTRING
Definition: rexx.h:186
RexxReturnCode REXXENTRY RexxQueryQueue(CONSTANT_STRING, size_t *)
void *REXXENTRY RexxAllocateMemory(size_t)
int RexxReturnCode
Definition: rexx.h:73
#define RexxEntry
Definition: rexx.h:235
#define RXSHV_NEWV
Definition: rexxapidefs.h:113
#define RXQUEUE_WAIT
Definition: rexxapidefs.h:243
#define RXSHV_SYFET
Definition: rexxapidefs.h:101
#define RXSUBCOM_OK
Definition: rexxapidefs.h:85
#define RXSUBCOM_ERROR
Definition: rexxapidefs.h:79
#define RXSHV_OK
Definition: rexxapidefs.h:112
#define RXSHV_SYSET
Definition: rexxapidefs.h:100
#define RXSUBCOM_FAILURE
Definition: rexxapidefs.h:80
#define RXSHV_MEMFL
Definition: rexxapidefs.h:117
const char * strptr
Definition: rexx.h:163
size_t strlength
Definition: rexx.h:162
long lStartRcd
Definition: hostemu.h:103
char aFilename[1024]
Definition: hostemu.h:100
long lRcdCnt
Definition: hostemu.h:98
char aStem[251]
Definition: hostemu.h:101
long lDirection
Definition: hostemu.h:104
struct _LL * prev
FILE * pFile
struct _LL * next
char FileName[1024]
size_t strlength
Definition: rexx.h:157
char * strptr
Definition: rexx.h:158
Definition: oorexxapi.h:242
size_t shvvaluelen
Definition: rexx.h:209
CONSTANT_RXSTRING shvname
Definition: rexx.h:206
unsigned char shvret
Definition: rexx.h:211
unsigned char shvcode
Definition: rexx.h:210
RXSTRING shvvalue
Definition: rexx.h:207
size_t shvnamelen
Definition: rexx.h:208
struct _SHVBLOCK * shvnext
Definition: rexx.h:205
#define DEFRXSTRING
RexxReturnCode RexxEntry GrxHost(PCONSTRXSTRING command, unsigned short int *flags, PRXSTRING retc)
OOREXX_GET_PACKAGE(hostemu)
static unsigned long ExecIO_Write_From_Stem(PLL pll)
static void hostemu_unloader(RexxThreadContext *context)
static unsigned long ExecIO_Read_To_Queue(PLL pll)
static void push(char *pushstr, long lOp)
unsigned long SetRexxVar(char *pszVar, char *pValue, size_t ulLen)
long lStmtType
struct _LL LL
char * pszSymbol[SYMTABLESIZE]
LL * PLL
static void Delete_LL(PLL pll)
long lCmdPtr
static PLL pTail
unsigned long FetchRexxVar(char *pszVar, PRXSTRING prxVar)
static char * pull(void)
RexxPackageEntry hostemu_package_entry
static PLL pHead
static PLL Search_LL(char *SFilename)
static unsigned long ExecIO_Read_To_Stem(PLL pll)
static void hostemu_loader(RexxThreadContext *context)
static void Insert_LL(PLL pll)
unsigned long ulNumSym
static long queued(void)
static unsigned long ExecIO_Write_From_Queue(PLL pll)
char szInline[100000]
EXECIO_OPTIONS ExecIO_Options
static pthread_mutex_t hmtxExecIO
PCONSTRXSTRING prxCmd