Path: utzoo!mnetor!uunet!husc6!hao!ames!umd5!mimsy!chris From: chris@mimsy.UUCP (Chris Torek) Newsgroups: comp.unix.questions Subject: Re: Another attempt at getting help with process communications Message-ID: <9801@mimsy.UUCP> Date: 15 Dec 87 18:53:56 GMT References: <8214@steinmetz.steinmetz.UUCP> Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 91 In article <8214@steinmetz.steinmetz.UUCP> lanzo@mercutio.steinmetz (Mark Lanzo) writes: [using ptys,] >The thing which confuses me most is that I don't know how to handle the >bidirectional communications with a pseudoterminal, especially with the >master end of the pseudoterminal, which can only be opened once .... Things written on the master end of a pty pair appear on the slave end and can be read there. Things written on the slave end of a pair appear on the master end, and can be read there. Things written on the master end cannot be read back from the master end (unless, of course, the process on the slave side echoes them). >... especially if the child process exited so that the slave end of >the pty wasn't really connected to anything. When this happens, read(masterfd) should return EOF. >...I definitely need 2 (or 3) descriptors in the subprocess, since >these are supposed to be stdin, stdout, and stderr. /* assume masterfd is set */ slavefd = open(slave, 2); if (slavefd < 0) ... /* something went wrong */ pid = fork(); if (pid < 0) ... /* something went wrong */ if (pid == 0) { /* child */ if (dup2(slavefd, 0) < 0 || dup2(0, 1) < 0 || dup2(0, 2) < 0) ... /* discard irrelevent descriptors */ for (i = getdtablesize(); --i > 2;) (void) close(i); exec... /* get here iff exec fails, so send message to master */ perror("exec(...)"); _exit(1); } (void) close(slavefd); /* do not want this anymore */ /* go on with master stuff */ > How do I locate an unused pty/tty pair; There should be a nice way to do this, but all existing programs loop trying to open ptyp0, then ptyp1, then ptyp2, ... ptypf, ptyq0, .... >and how do I ensure that nothing else tries to access the pty while >my job is using it? As long as you have the master end open, no one else can touch it. Of course, anyone with the proper permissions can open the slave end. >What if there is NO currently unused pty? Then you are out of luck. `Good' programs currently use stat() to tell whether there is a block of ptys: (void) strcpy(name, "/dev/ptyXX"); for (c = 'p'; c <= 'z'; c++) { name[sizeof("/dev/pty") - 1] = c; if (stat(name, &st)) break; /* no ptys */ for (i = 0; i < 16; i++) { name[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i]; if ((masterfd = open(name, 2)) >= 0) goto havemaster; } } /* no ptys */ ... havemaster: /* have the master end */ Note that some wayward programs sometimes leave slave pty protections such that even after someone opens the master, that user cannot open the slave. (Root need not worry about this, of course.) Hence it is a safer to do something like this: if ((masterfd = open(name, 2)) < 0) continue; name[sizeof("/dev/p") - 1] = 't'; if ((slavefd = open(name, 2)) >= 0) goto havepty; /* someone left a pty unusable; just move on */ (void) close(masterfd); -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris