A PtTerminal widget attached to a device
PtWidget → PtBasic → PtContainer → PtTerminal → PtTty
For more information, see the diagram of the widget hierarchy.
<photon/PtTty.h>
A PtTty widget is a PtTerminal attached to a device. The device output is passed to the terminal, but also can be caught with the Pt_CB_TTY_OUTPUT callback.
If the widget has the Pt_GETS_FOCUS flag set in its Pt_ARG_FLAGS resource, keyboard input to the widget (as well as mouse events) are redirected to the device. You can also use the Pt_ARG_TTY_INPUT resource to simulate keyboard input.
The main difference between PtTerminal and PtTty is that PtTerminal doesn't do any I/O for you. The only way to display characters in a PtTerminal is by giving them to one of the PtTerminalPut*() functions. Similarly, the only thing PtTerminal does with Photon input is translate function keys into text-mode compatible escape sequences and give the result to your Pt_CB_TERM_INPUT callback.
PtTty adds device I/O to that. The code that opens a pty, reads characters from it, and gives those characters to PtTerminalPut() is part of PtTty. Similarly, PtTty attaches a Pt_CB_TERM_INPUT callback that writes Photon keyboard input (translated by PtTerminal to text-mode compatible format) to the pty.
Another responsibility of PtTty is spawning a command for you and invoking the Pt_CB_TTY_TERMINATED callbacks when the command terminates.
Some of the resources for PtTty aren't just data stored in the widget, they're “action resources” that define an action to be performed when you set the resource. This includes all the resources flagged as write-only.
Some of those actions are order-dependent. For example, you can't spawn a program on a device (by setting Pt_ARG_TTY_CMD or Pt_ARG_TTY_ARGV) before defining which device it's to be spawned on (by setting Pt_ARG_TTY_SFD, Pt_ARG_TTY_PATH, or Pt_ARG_TTY_PSEUDO).
The widget opens its pty and starts its command as soon as you set Pt_ARG_TTY_CMD or Pt_ARG_TTY_ARGV, even if the widget hasn't yet been realized. By default, the command continues to run if you unrealize the widget. |
Additionally, the following resources are order-dependent even though they're not action resources:
Since the widget looks at the current value of these resources when spawning the command, changing their values after a command has been spawned doesn't affect the command that's already running. Make sure that those resources have correct values before you set Pt_ARG_TTY_CMD or Pt_ARG_TTY_ARGV.
Here's an example:
/* Open a pseudo tty -- NULL is a shortcut for "/dev"; * the widget will add something like "ttyp3" to it */ PtSetArg( &arg, Pt_ARG_TTY_PSEUDO, NULL, 0 ); PtSetResources( ABW_tty, 1, &arg ); /* Have we succeeded? */ PtSetArg( &arg, Pt_ARG_TTY_SFD, 0, 0 ); PtGetResources( ABW_tty, 1, &arg ); if ( arg.value == -1 ) PtTerminalPuts( ABW_tty, "Unable to find a pty\r\n" ); else { /* Run a program on the pseudo tty. * NULL is more or less a shortcut for * "char *argv[] = { "/bin/sh", NULL };", * except it runs *your* shell rather than always /bin/sh. */ PtSetArg( &arg, Pt_ARG_TTY_ARGV, NULL, 0 ); PtSetResources( ABW_tty, 1, &arg ); /* Have we succeeded? */ PtSetArg( &arg, Pt_ARG_TTY_PID, NULL, 0 ); PtGetResources( ABW_tty, 1, &arg ); if ( arg.value == 0 ) PtTerminalPuts( ABW_tty, "Unable to spawn the shell\r\n" ); }
PhAB doesn't know that these resources are order-dependent. Set the resources in the correct order. If you suspect that the order isn't correct, set all the order-dependent resources to their default values, and then set them again in the correct order. |
PtTty uses three file descriptors, but they don't have to be different. The following resources are involved:
Pt_ARG_TTY_SFD overrides the entries in the iov array of the Pt_ARG_TTY_SPAWN_OPTIONS resource that correspond to the set bits in Pt_ARG_TTY_FDSET. |
When you set Pt_ARG_TTY_RFD or Pt_ARG_TTY_WFD to a file descriptor, the widget sets the O_NONBLOCK flag on that fd if it isn't already set.
When the widget is later destroyed, or its resources are changed in such a way that neither Pt_ARG_TTY_RFD nor Pt_ARG_TTY_WFD references that fd any more, the widget unsets the O_NONBLOCK flag. If the Pt_ARG_TTY_SFD resource doesn't reference that fd either, the fd is then closed.
In short, if you give an fd to a PtTty widget, it's the widget's responsibility to close it when it's no longer used. If you want to keep the fd, make a copy using dup() (see the QNX Neutrino Library Reference) and give that copy to the widget. Either way, don't use either the copy or the original fd for any I/O while the widget is using it.
If you select some text and hold down the Ctrl key, you can drag the selected text to a PtText, PtMultiText, PtTerminal, or PtTty widget.
Resource | C type | Pt type | Default |
---|---|---|---|
Pt_ARG_TTY_ARGV | char ** | Pointer | (write-only) |
Pt_ARG_TTY_BUFFER | char, unsigned short | Array | allocated |
Pt_ARG_TTY_BUFLEN | unsigned short | Scalar | 1024 |
Pt_ARG_TTY_CMD | char * | String | (write-only) |
Pt_ARG_TTY_DEVSIZE | PtTerminalRowCol_t | Struct | 0, 0 |
Pt_ARG_TTY_EXIT_STATUS | int | Scalar | 0 (read-only) |
Pt_ARG_TTY_FDS | int | Scalar | -1 |
Pt_ARG_TTY_FDSET | unsigned short | Scalar | 7 |
Pt_ARG_TTY_FLAGS | unsigned short | Flag | See below |
Pt_ARG_TTY_INPUT | char, unsigned short | Array | (write-only) |
Pt_ARG_TTY_INPUT_WRITTEN | unsigned short | Scalar | 0 (read-only) |
Pt_ARG_TTY_PATH | char * | String | NULL |
Pt_ARG_TTY_PID | pid_t | Scalar | 0 |
Pt_ARG_TTY_PRI | int | Scalar | -1 |
Pt_ARG_TTY_PSEUDO | char * | String | NULL |
Pt_ARG_TTY_RFD | int | Scalar | -1 |
Pt_ARG_TTY_SFD | int | Scalar | -1 |
Pt_ARG_TTY_SPAWN_OPTIONS | PtSpawnOptions_t const * | Pointer | NULL |
Pt_ARG_TTY_WFD | int | Scalar | -1 |
Pt_CB_TTY_DEVSIZE | PtCallback_t * | Link | NULL |
Pt_CB_TTY_OUTPUT | PtCallback_t * | Link | NULL |
Pt_CB_TTY_TERMINATED | PtCallback_t * | Link | NULL |
C type | Pt type | Default |
---|---|---|
char ** | Pointer |
When you set this resource, the widget spawns a process on the device. The resource value must be the pointer to a NULL-terminated array of pointers to strings. These strings are used for the program name and arguments.
The first string in the array specifies the program to execute. If it doesn't contain a slash character, the PATH environment variable is used to search for the program.
If the Pt_TTY_ARGV0 flag is set (which is the default), the first string is also used as the first argument to the new process (argv[0]). If the flag is clear, the argument list is assumed to start from the second item of the array passed as the resource value. This lets you run a program whose argv[0] entry is different from the actual name of the program.
If the list is NULL or contains too few non-NULL elements (the minimum is one when the Pt_TTY_ARGV0 flag is set and two when it's clear), the user's shell is spawned. If the Pt_TTY_ARGV0 flag is clear and the list is NULL or empty, this is a login shell.
All the flags and resources described under Pt_ARG_TTY_CMD, except the Pt_TTY_ARGV0 flag, have the same effect when this resource is set.
C type | Pt type | Default |
---|---|---|
char, unsigned short | Array | allocated |
The buffer that's used by the widget for reading data from the device and passing them to the PtTerminalPut() function. If you set this resource, you must give both the address and the length of a buffer for the widget to use. Several widgets may share a common buffer, provided that none of them attaches a callback that could cause a recursive invocation of PtTerminalPut().
C type | Pt type | Default |
---|---|---|
unsigned short | Scalar | 1024 |
The length of the buffer used by the widget for reading data from the device. If you set this resource, the widget allocates a buffer.
C type | Pt type | Default |
---|---|---|
char * | String |
When you set this resource, the widget spawns a process on the device.
If the resource value is a NULL or points to an empty string, the user's shell is spawned. If the resource is a nonempty string, the widget spawns the user's shell with two arguments: -c and the resource string. In either case, if the Pt_TTY_ARGV0 flag is clear, the shell is started as a login shell.
If another process has been spawned previously and is still running, and the Pt_ARG_TTY_PID resource hasn't been set to zero, a SIGTERM signal is sent to the process group of that process before starting the new program.
If the Pt_TTY_SETENV flag is set (which is the default), the TERM environment variable of the new process is set to a value corresponding to the current terminal protocol (using the PtTerminalName() function). The environment variables LINES and COLUMNS are also removed if they exist.
C type | Pt type | Default |
---|---|---|
PtTerminalRowCol_t | Struct | 0, 0 |
The current device size. It can differ from the terminal widget's size, depending on the Pt_ARG_TTY_FLAGS resource. The PtTerminalRowCol_t structure contains the following members:
C type | Pt type | Default |
---|---|---|
int | Scalar | 0 |
The exit status of the process spawned on the device. You can examine the value using the POSIX macros described for waitpid() in the QNX Neutrino Library Reference. The value is valid only after the child process has terminated.
C type | Pt type | Default |
---|---|---|
int | Scalar | -1 |
A shortcut for setting Pt_ARG_TTY_RFD, Pt_ARG_TTY_WFD, and Pt_ARG_TTY_SFD to the same value. Setting Pt_ARG_TTY_FDS to -1 closes any previously open file descriptors and sets the Pt_ARG_TTY_PATH to NULL.
For more details, see “File descriptors,” above.
C type | Pt type | Default |
---|---|---|
unsigned short | Scalar | 7 |
This number defines (as a bitmask) the set of file descriptors that the widget sets for a new process started when the Pt_ARG_TTY_CMD or Pt_ARG_TTY_ARGV resource is set. The default value of 7 means that the PtTty widget's device is available as descriptors 0, 1 and 2. Only the ten low-order bits are used because the redirection is done using the iov[] member of the PtSpawnOptions_t structure, which has ten elements.
C type | Pt type | Default |
---|---|---|
unsigned short | Flag | See below |
Flags that affect the widget's behavior. Any combination of:
By default, all bits are set except Pt_TTY_DEVFORCE.
If both Pt_TTY_TERMRESIZE and Pt_TTY_DEVRESIZE flags are set, changes of sizes are propagated in both directions. However, if the sizes differ at the moment when the flags are set or when the device is being opened, the device size is adjusted.
If the Pt_TTY_DEVFORCE flag is set, the Pt_TTY_DEVLIMIT flag is ignored.
C type | Pt type | Default |
---|---|---|
char, unsigned short | Array | NULL |
Characters to be written to the device.
Since the device is opened with the O_NONBLOCK flag, the number of bytes that are actually written may be less than the specified length. You can use the Pt_ARG_TTY_INPUT_WRITTEN resource to find out how many bytes the widget managed to write.
C type | Pt type | Default |
---|---|---|
unsigned short | Scalar | 0 |
The number of characters successfully written by the Pt_ARG_TTY_INPUT resource.
C type | Pt type | Default |
---|---|---|
char * | String | NULL |
When you set this resource, the widget closes all its file descriptors, then attempts to open the given pathname and stores the new fd (or -1 on error) in Pt_ARG_TTY_RFD, Pt_ARG_TTY_WFD, and Pt_ARG_TTY_SFD.
The descriptor is guaranteed to be greater than 2 and have the FD_CLOEXEC flag set.
C type | Pt type | Default |
---|---|---|
pid_t | Scalar | 0 |
Zero or the process ID of the process that has been spawned on the device. The only value to which you can explicitly set this resource is zero, meaning “Forget about that process.” If this resource is nonzero when the device is closed (e.g. when the widget is being destroyed), a SIGHUP signal is sent to the process group of the child process.
C type | Pt type | Default |
---|---|---|
int | Scalar | -1 |
The priority of Photon pulses attached to the device — see PtAppAddFdPri() in the Photon Library Reference.
C type | Pt type | Default |
---|---|---|
char * | String | NULL |
When you set this resource, the widget closes all its file descriptors, then attempts to find and open a pseudo-tty.
The “master” fd is stored in both Pt_ARG_TTY_RFD and Pt_ARG_TTY_WFD, and the “slave” fd in Pt_ARG_TTY_SFD.
Also, the pathname of the slave device is stored in Pt_ARG_TTY_PATH.
You should set this resource to NULL or to the name of a directory that contains some ptys.
After opening the pseudo tty, the stty entry of the “slave” device is set to default modes. The editing keys are set according to the current value of the Pt_ARG_TERM_ANSI_PROTOCOL resource (see PtTerminal). If the protocol is changed with the same call to PtSetResources() that opens the pseudo tty, the order of the argument list is significant.
Both descriptors opened in this mode are guaranteed to be greater than 2 and have the FD_CLOEXEC flag set.
C type | Pt type | Default |
---|---|---|
int | Scalar | -1 |
The file descriptor that the widget uses for reading. Any input from this FD is displayed in the widget.
For more details, see “File descriptors,” above.
C type | Pt type | Default |
---|---|---|
int | Scalar | -1 |
The file descriptor to which the widget maps stdin, stdout, and stderr when you set Pt_ARG_TTY_CMD or Pt_ARG_TTY_ARGV.
For more details, see “File descriptors,” above.
Pt_ARG_TTY_SFD overrides the entries in the iov array of the Pt_ARG_TTY_SPAWN_OPTIONS resource that correspond to the set bits in Pt_ARG_TTY_FDSET. |
C type | Pt type | Default |
---|---|---|
PtSpawnOptions_t const * | Pointer | NULL |
A pointer to a PtSpawnOptions_t structure that's used for spawning the child process.
If you leave this resource set to NULL, the widget uses the default values in:
extern const PtSpawnOptions_t PtTtyDefaultSpawnOptions
For more information about this structure, see PtSpawn() in the Photon Library Reference.
Pt_ARG_TTY_SFD overrides the entries in the iov array of the Pt_ARG_TTY_SPAWN_OPTIONS resource that correspond to the set bits in Pt_ARG_TTY_FDSET. |
C type | Pt type | Default |
---|---|---|
int | Scalar | -1 |
The file descriptor to which the widget writes keyboard input.
When you set this resource, the widget attaches itself to the given file descriptor. The descriptor must be open in a mode that allows writing. To force the widget to detach from any file descriptor it's attached to, set this resource to -1.
For more details, see “File descriptors,” above.
C type | Pt type | Default |
---|---|---|
PtCallback_t * | Link | NULL |
A list of PtCallback_t structures that define the callbacks invoked when a resize event is received from the device (and before the terminal widget is resized according to the new size).
Each callback is passed a PtCallbackInfo_t structure that contains at least the following members:
The PtTerminalRowCol_t structure contains the following members:
These callbacks should return Pt_CONTINUE.
C type | Pt type | Default |
---|---|---|
PtCallback_t * | Link | NULL |
A list of PtCallback_t structures that define the callbacks invoked when any output from the device is received (and before the output is passed to the terminal widget)
Each callback is passed a PtCallbackInfo_t structure that contains at least the following members:
These callbacks should return Pt_CONTINUE.
C type | Pt type | Default |
---|---|---|
PtCallback_t * | Link | NULL |
A list of PtCallback_t structures that define the callbacks invoked after the child process has terminated. Each callback is passed a PtCallbackInfo_t structure that contains at least the following members:
These callbacks should return Pt_CONTINUE.
If the widget modifies an inherited resource, the “Default override” column indicates the new value. This modification affects any subclasses of the widget.
The PtTty widget defines the following convenience function: