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.
Output from a terminal device.
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. The Pt_ARG_TTY_INPUT resource can also be used 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 have to open a device (by setting Pt_ARG_TTY_FD, Pt_ARG_TTY_PATH, or Pt_ARG_TTY_PSEUDO) before you can spawn a program on the device (by setting Pt_ARG_TTY_CMD or Pt_ARG_TTY_ARGV).
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 resouces are order-dependent even though they're not action resources:
Since the widget looks at the current value of those 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 "//0/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_FD, 0, 0 ); PtGetResources( ABW_tty, 1, &arg ); if ( arg.value == -1 ) PtTerminalPuts( "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( "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. |
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_FD | 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 | NULL |
Pt_ARG_TTY_INPUT_WRITTEN | unsigned short | Scalar | 0 (read-only) |
Pt_ARG_TTY_MFD | int | Scalar | -1 (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_SPAWN_OPTIONS | PtSpawnOptions_t const * | Pointer | NULL |
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 this resource is being set, 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 allows to 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 this resource is set, both the address and the length of a buffer must be given. The widget then uses the given buffer. Several widgets may share a common buffer, provided that none of them attaches a callback that could cause a recursive invocation of the PtTerminalPut() function.
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 this resource is set, the widget allocates a buffer.
C type | Pt type | Default |
---|---|---|
char * | String |
When this resource is being set, 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. The value can be examined using the POSIX macros described in the C Library Reference, under waitpid(). The value is valid only after the child process has terminated.
C type | Pt type | Default |
---|---|---|
int | Scalar | -1 |
When this resource is set, the widget attaches itself to the given file descriptor. The descriptor must be a character device open in a mode that allows reading. Using a value of -1 forces the widget to detach from any device it's attached to.
When this resource is read, the current file descriptor is returned. If the widget isn't attached to any device, -1 is returned.
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 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 |
The possible flags are as follows:
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. The Pt_ARG_TTY_INPUT_WRITTEN resource can be used to find out how many bytes the widget managed to read.
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 |
---|---|---|
int | Scalar | -1 |
The current "master" file descriptor. It's equal to the Pt_ARG_TTY_FD resource unless the device has been opened using the Pt_ARG_TTY_PSEUDO resource, in which case this is the descriptor of the "master" size of the pty.
C type | Pt type | Default |
---|---|---|
char * | String | NULL |
When this resource is set, the widget opens the given pathname for reading and writing and attaches itself to the open device. The pathname must be a character device.
The descriptor is greater than 2 and has the CLOEXEC flag set.
When this resource is read, the pathname of the current device is returned. If the widget isn't attached to any device or was attached using the Pt_ARG_TTY_FD resource, NULL is returned.
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 this resource can be explicitly set 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 |
Priority of Photon pulses attached to the device - see PtAppAddFdPri() in the Photon Library Reference.
C type | Pt type | Default |
---|---|---|
char * | String | NULL |
When this resource is set, the widget attempts to find an unused pseudo-tty device and attach to it. The resource value is used as a prefix to which a string similar to /ttyp0 is appended. If a NULL is given, //0/dev is used instead. If an empty string "" is given, /dev is assumed and thus the default network root rather than the local node is used. The application can also choose an explicit prefix or scan a configuration-dependent prefix list.
If a pseudo tty has been opened in this way, the widget uses the "master" end of the tty, but when reading the Pt_ARG_TTY_FD or Pt_ARG_TTY_PATH resources, information about the "slave" end is returned. The Pt_ARG_TTY_PSEUDO resource can be read to obtain the "master" device pathname.
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_PROTOCOL resource. 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 greater than 2 and have the CLOEXEC flag set.
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 this resource is left as NULL, default values in
extern const PtSpawnOptions_t PtTtyDefaultSpawnOptions
are used. For more information about this structure, see PtSpawn() in the Photon Library Reference.
C type | Pt type | Default |
---|---|---|
PtCallback_t * | Link | NULL |
A list of 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 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 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 functions: