Simulating forkpty/exec with spawn?

My app needs to control a small child process which opens /dev/tty to
get its console. forkpty() followed by exec() works fine in a test
program, but I don’t have enough memory to fork my app. So I’m trying
without much success to roll my own forkpty/exec using openpty and spawn.

First of all, is there an easy way to tell spawn() to attach the child
process to a new controlling terminal?

Assuming the answer is no, then I believe I’ll need to temporarily
associate the parent process with the slave pty, spawn off the child,
and reassociate the parent with its old tty. I have the following
code to do just that:

struct inheritance inh;
int pty_master_fd, pty_slave_fd, tty_fd;
char *args[]; (passed in as a parameter)

if (openpty(&pty_master_fd, &pty_slave_fd, NULL, NULL, NULL)) {
perror(“openpty”);
return -1;
}

memset(&inh, 0, sizeof(inh));
inh.flags = SPAWN_CHECK_SCRIPT | SPAWN_SEARCH_PATH | SPAWN_SETGROUP;
inh.pgroup = SPAWN_NEWPGROUP;

/* Detach from current controlling tty, if any */
tty_fd = open("/dev/tty", O_RDWR);
if (tty_fd >= 0) {
if (ioctl(tty_fd, TIOCNOTTY, 0) < 0) {
perror(“Can’t detach from old tty”);
return -1;
}
}

/* Attach to pty */
if (ioctl(pty_slave_fd, TIOCSCTTY, 0) < 0) {
perror(“Can’t attach to pseudo-tty”);
return -1;
}

pid = spawn(args[0], 3, fds, &inh, args, environ);
if (pid < 0) {
perror(“spawn”);
return -1;
}

/* Reattach to our old tty, if any */
if (tty_fd >= 0) {
if (ioctl(tty_fd, TIOCSCTTY, 0) < 0) {
perror(“Can’t reattach to old controlling terminal”);
}

close(tty_fd);
}
else {
if (ioctl(pty_slave_fd, TIOCNOTTY, 0) < 0) {
perror(“Can’t detach from pseudo-tty”);
}
}

close(pty_slave_fd);

The TIOCNOTTY call fails with an ENOTTY error. Kind of an odd error to
get on a file descriptor that I just opened using /dev/tty! If I comment
that call out, the TIOCSCTTY call fails with an EPERM error. I’m running
as root. My app is already a process group leader so I can’t call setsid().

What should I be doing instead of the above mess?

This is on QNX 6.0, I should add (I don’t have the ability to upgrade
the platform I’m writing this for, much as I’d prefer to be running 6.1).
But since forkpty works I assume there must be some way to do it.

“Steven Grimm” <koreth-qnx@midwinter.com> wrote in message
news:1103_1008784416@inn.qnx.com

My app needs to control a small child process which opens /dev/tty to
get its console. forkpty() followed by exec() works fine in a test
program, but I don’t have enough memory to fork my app. So I’m trying
without much success to roll my own forkpty/exec using openpty and spawn.

Take a look at vfork(), it’s a little cheaper (not much). The problem with
using spawn is that the spawn’ed process inherits its session membership
from it’s parent, which means you’re not the session leader, and can’t have
a controlling terminal…

Another idea I have is that, if you can’t fork you app (due to memory),
spawn a little “helper” program that is small and just fork()'s/exec’s what
you need to. It’s a little less effiencent but gets around having to fork()
your main application.

-Adam