Home
Developer Resources
QNX RTOS v4
QNX RTOS v4 Knowledge Base

QNX RTOS v4 Knowledge Base

Foundry27
Foundry27
QNX RTOS v4 project
Resources

QNX RTOS v4 Knowledge Base

Title Controlling Terminals
Ref. No. QNX.000009241
Category(ies) Development, Character I/O
Issue How do we set the controlling terminal for a process?  We tried:

ioctl(0,TIOCSCTTY,(char *)0)

which returns a good status, but doesn't seem to have really done the job.  We noticed that ioctl was not documented in the Library Reference manuals, it seems that maybe we need to use qnx_ioctl instead?  qnx_ioctl seems to work differently and is not well documented (the only documentation on available functions is the header file).
Let me clarify this with an example.  The following program works if TEST is not defined, but fails if it is with the "No such file or directory"

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

main()
{
  pid_t pid;
  int master, slave;
  char buffer[1024];
  int rc;

  pid = fork();
  if (pid) {
    fprintf (stderr, "In parentn");
    master = open ("/dev/ptype", O_RDWR, 0);

    while ((rc = read (master, buffer, sizeof(buffer))) > 0)
      write (0, buffer, rc);
  }
  else {
#ifdef TEST
    setsid();
#endif

    close(0);
    close(1);
    close(2);

    slave = open ("/dev/ttype", O_RDWR, 0);
    dup2 (slave, 1);
    dup2 (slave, 2);

#ifdef TEST
    tcsetct (0, getpid());
#endif
    execl ("/usr/bin/X11/xterm", "xterm", NULL);
  }
}



Solution Take a look at tcsetct().

ioctl() is not part of POSIX. ioctl() in UNIX systems is the general purpose function which does everything the OS writers forgot to put into their systems when they developed it. Every major UNIX flavor has its own set of IOCTLs which were created over the years. The POSIX committee looked at ioctl() and created a bunch of well-defined functions to do the most common and most important of those functions (eg: the "tc*" functions for terminal control).

We provide an ioctl() function in our UNIX porting library which allows most PD UNIX programs which use ioctl() to compile and run in a POSIX environment (it maps the common/known IOCTLS into POSIX functions).

One area of complexity is the whole issue of "job control" which is optional in POSIX (many UNIXes did job control differently, if at all).  QNX doesn't support full job control, although QNX does support most of the common job-control related functions suggested by POSIX.  QNX does has full support for process groups, and does have support for POSIX sessions. What QNX doesn't do is the optional foreground/background semantics for terminal control (hardly necessary when you have full screen virtual consoles anyways) and QNX starts up processes in new sessions in a QNX specific manner (perfectly OK with the POSIX committee, just different than some of the mainstream UNIX implementations).

In QNX, new sessions are started by specifying the appropriate options in the qnx_spawn() function (_SPAWN_SETSID/NEWPGRP/TCSETPGRP). The QNX facilities for launching new programs (shells and sinit/tinit) all use these facilities. Since QNX is an inherently network distributed environment, the QNX process creation choices are much richer than those found in a traditional monolithic UNIX kernel, so there are many other process creation option available as well (like the ability to spawn on remote computers, and run in terminal sessions on other computers). Many UNIX implementations created new terminal sessions by telling the UNIX kernel that they were about to do so (the 'CTTY' ioctl) and then forking and execing into a new program. The first device actually opened by that new process (if any) became the controlling terminal for that new session. Although rather obscure, this works OK in monolithic kernels running on a single processor, but is not very appropriate in a distributed environment like QNX (hence the spawn options).