These two examples illustrate programs that implement a generic terminal and a simple interpreter.
This program starts and runs a generic terminal.
This program 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; }
This 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); }
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.
Create the terminal program:
CRTBNDC PGM(QGPL/TERMINAL) SRCFILE(QGPL/QCSRC) SRCMBR(TERMINAL) SYSIFCOPT(*IFSIO) TEXT('Example Terminal program')
Create the interpreter program:
CRTBNDC PGM(QGPL/INTERPRET) SRCFILE(QGPL/QCSRC) SRCMBR(INTERPRET) SYSIFCOPT(*IFSIO) TEXT('Example Interpreter program')