Example: Using generic terminal APIs

These example programs implement a generic terminal and a simple interpreter.

Note: By using the code examples, you agree to the terms of the Code license and disclaimer information.

Terminal program

This example program starts and runs a generic terminal.

It demonstrates the use of the generic terminal functions Qp0zStartTerminal(), Qp0zRunTerminal(), Qp0zEndTerminal(), and Qp0zGetTerminalPid().

Use the Create Bound C Program (CRTBNDC) command to create this program (see Creating the terminal and interpreter programs).

Call this program with no parameters (see Calling the terminal program).


/* Includes */
#include <qp0ztrml.h>
#include <qp0z1170.h>
#include <stdlib.h>
#include <stdio.h>

/* Constants */
#define NUM_PREDEFINED_ENVS 2

/* Global Variables */
extern char **environ;

int main (int argc, char *argv[])
{
  char *args[2];             /* Argument array */
  int envCount;              /* Count of currently defined env vars */
  int index;                 /* Loop index */
  char **envp;               /* For walking environ array */
  char **envs;               /* Environment variable array */
  Qp0z_Terminal_T handle;    /* Terminal handle */
  Qp0z_Terminal_Attr_T ta;   /* Terminal attributes */
  pid_t pid;                 /* Process ID of interpreter */
  int rc;                    /* Return code */

  /********************************************************************/
  /* Build the argument array.  */
  /********************************************************************/

  args[0] = "/QSYS.LIB/QGPL.LIB/ECHOINT.PGM";
  args[1] = NULL;

  /********************************************************************/
  /* Build the environment variable array. */
  /********************************************************************/

  /* Make sure environ is set in this activation group. */
  Qp0zInitEnv();

  /* Count the number of environment variables currently defined in this
     process.  Qp0zStartTerminal() will make sure the interpreter
     process does not have too many environment variables. */
  for (envCount = 0, envp = environ; *envp != NULL; ++envp, ++envCount);

  /* Allocate storage for the environment variable array. */
  envs = (char **)malloc(sizeof(char *) *
                           (envCount + NUM_PREDEFINED_ENVS));
  if (envs == NULL) {
    perror("malloc() failed");
    exit(1);
  }

  /* Copy the current environment variables to the array. */
  for (index = 0; environ[index] != NULL; ++index) {
    envs[index] = environ[index];
  }

  /* Set QIBM_USE_DESCRIPTOR_STDIO variable for using descriptors.  This
     will override the current value of the variable. */
  envs[index++] = "QIBM_USE_DESCRIPTOR_STDIO=Y";

  /* Null terminate array of environment variables. */
  envs[index] = NULL;

  /********************************************************************/
  /* Set the terminal attributes.  */
  /********************************************************************/

  memset(&ta, '\0', sizeof(Qp0z_Terminal_Attr_T));
  ta.Buffer_Size = 8196;
  ta.Inherit.pgroup = SPAWN_NEWPGROUP;
  ta.Title = "Echo Interpreter";
  ta.Cmd_Key_Line1 = "F3=Exit F9=Retrieve";
  ta.Cmd_Key_Line2 = "F17=Top F18=Bottom";

  /********************************************************************/
  /* Start and run the terminal.  */
  /********************************************************************/

  /* Start the terminal. */
  if (Qp0zStartTerminal(
handle, args, envs, ta) != 0) {
    perror("Qp0zStartTerminal() failed");
    exit(1);
  }

  /* Get the PID of the interpreter process. */
  if (Qp0zGetTerminalPid(handle, &pid) != 0) {
    perror("Qp0zGetTerminalPid() failed");
    exit(1);
  }

  /* Run the terminal. */
  rc = Qp0zRunTerminal(handle);
  switch (rc) {
    case QP0Z_TERMINAL_F12:
    case QP0Z_TERMINAL_F3:
    case QP0Z_TERMINAL_ENDED:
      /* Do nothing */
      break;

    default:
      perror("Qp0zRunTerminal() failed");
      exit(1);
      break;
  }

  /* End the terminal. */
  Qp0zEndTerminal(handle);

  return 0;
}

Interpreter program

This example program is a simple echo interpreter that is used by the terminal program (see Terminal program).

Use the Create Bound C Program (CRTBNDC) command to create this program (see Creating the terminal and interpreter programs).


/* Echo interpreter */
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>

static void SignalHandler(int);

int main (int argc, char *argv[])
{
  char buffer[8192];         /* Buffer for reading input */
  struct sigaction sigact;   /* Signal action */

  /* Set up a signal handler for SIGHUP.  The terminal
     sends this signal when the user presses F3 to exit. */
  sigemptyset(&sigact.sa_mask);
  sigact.sa_flags = 0;
  sigact.sa_handler = SignalHandler;
  if (sigaction(SIGHUP, &sigact, NULL) != 0) {
    perror("sigaction(SIGHUP) failed.");
    exit(2);
  }

  /* Set up a signal handler for SIGINT.  The terminal sends
     this signal when the user presses SysReq 2. */
  sigemptyset(&sigact.sa_mask);
  sigact.sa_flags = 0;
  sigact.sa_handler = SignalHandler;
  if (sigaction(SIGINT, &sigact, NULL) != 0) {
    perror("sigaction(SIGINT) failed.");
    exit(2);
  }

  /* Switch stdout to use line-mode buffering. */
  setvbuf(stdout, NULL, _IOLBF, 128);
  printf("Echo interpreter starting ...\n");
  printf("Enter text:\n");

  /* Do forever. */
  while (1) {
    /* Read a line from stdin. */
    gets(buffer);

    /* End and clean up any allocated
       resources when stdin is closed. */
    if (feof(stdin)) {
      printf("Echo interpreter ending ...\n");
      exit(0);
    }

    /* Echo the line to stdout. */
    printf("%s\n", buffer);
  } /* End of while */

  return 0;
}

void
SignalHandler(int signo)
{
  printf("Ending for signal %d\n", signo);
  exit(1);
}

Creating the terminal and interpreter programs

The following examples show how to create the example programs (Terminal program and Interpreter program). These examples assume that the source for the terminal program is member TERMINAL in the file QGPL/QCSRC and that the source for the interpreter program is member INTERPRET in the file QGPL/QCSRC.

Creating the terminal program:


CRTBNDC PGM(QGPL/TERMINAL)
        SRCFILE(QGPL/QCSRC)
        SRCMBR(TERMINAL)
        SYSIFCOPT(*IFSIO)
        TEXT('Example Terminal program')

Creating the interpreter program:


CRTBNDC PGM(QGPL/INTERPRET)
        SRCFILE(QGPL/QCSRC)
        SRCMBR(INTERPRET)
        SYSIFCOPT(*IFSIO)
        TEXT('Example Interpreter program')

Calling the terminal program

The following example shows how to start the example program:


CALL PGM(QGPL/TERMINAL)