determine the current directory of a son-process (longish)
Wayne Mesard
mesard at bbn.com
Thu Jun 23 01:46:05 AEST 1988
[ N.B. followups to wizards.]
>From article <579 at gmdzi.UUCP>, by valder at gmdzi.UUCP (Wilhelm Valder):
> Does anyone know how to determine the current working directory (CWD) of
> a son-process in UNIX. Any hints, comments, solutions are appreciated.
>
> The problem: In our current implementation of a command listener, we
> have one process that builds up a command line and sends it to a son
> process (normally /bin/sh or /bin/sh) that has been forked and exec'd
> during startup. The two processes communicate via pseudo ttys (pty's).
Geez, why don't you hack the shell source? Well, none of my business I
suppose.
Anyway, I was in the same situation when I was writing a UNIX [BSD]
tutorial last summer on CMU's Andrew system. I had the tutorial running
in one window, and a shell in another. The tutorial had to listen to what
the user typed and provid helpful information. The communication
worked almost like yours except I had a third program involved.
What I did was this:
o At startup, the tutorial opens a pipe stream to a "voyeur" program
which acts as an intermediary between the shell and the tutorial,
and between the user and the shell. Before making the call,
the tutorial ensures that its stderr goes to the same place as
its stdout (see below) (via dup(2)).
o The voyeur then sets up a pty and forks a shell which it could talk
and listen to via the pty.
------------ ------------ ------------
| | pipe | | pty | |
| Tutorial |<======= | Voyeur | <========> | Shell |
| | (V's | | (Shell's | |
------------ stdout) ------------ stdout,in ------------
^ | & err)
stdin | | stderr
| V
So, in voyeur's main loop:
o It does a select to wait for input from the keyboard (the user) or
from the pty (the shell).
o On shell output, voyeur first sends a copy to its stderr (which is the
screen) so that the user can see it (no flames, please). Remember,
that the shell is only talking to the pty and voyeur's stdout goes
to the tutorial.
Next it sends a copy to the tutorial (via it's stdout) along with
some control messages to advise the tutorial of where the incoming
data came from.
o On stdin (keyboard) input it sends a copy down the stdout to both
the shell and the tutorial.
Now to get to your question:
On keyboard input, it checks to see if the typed string is a request for
change of directory and if it is, voyeur (1) asks the shell for the new
directory name (2) warns the tutorial that important data is on the way
and to wait for it:
if (!strncmp(buf, "cd", 2) || !strncmp(buf, "chdir", 5) ||
!strncmp(buf, "pushdir", 7) || !strncmp(buf, "popdir", 6)) {
(void) write(ptyfd, "echo \007\007$cwd\001\n", 13);
(void) write(1, "\001\001WAIT\n", 7);
}
Meanwhile, there is a check in voyeur's shell output handler to watch
for messages with double Ctrl-G's. It knows that this is the answer to
its question, finds the useful information and sends it as a
control message to the tutorial.
if (sel & (1 << ptyfd)) { /* output from shell */
int n = read (ptyfd, buf, BUFSIZ);
[...]
if ((newdir = index(buf, '\007')) && *(newdir+1) == '\007') {
(void) write(1, "\001\001CWD:",6);
(void) write(1, newdir+2, (int)(index(buf, '\001') - newdir - 2));
(void) write(1, "\n", 1);
(void) write(2, buf, (int)(newdir - buf));
/* If we didn't get the prompt after $cwd, get it next time. */
okay_to_write = n - (int)(index(newdir,'\n')-buf) - 1;
*newdir = '\0';
}
else if (okay_to_write)
(void) write(2, buf, n);
else
okay_to_write = 1;
}
}
I wasn't sure whether or not to include the "okay_to_write" nonsense in
this article, but since I have, I might as well, explain it: The user
should have no idea that we're sneaking that echo command to his/her
shell. So of course we don't echo the output. But we also have to make
sure that the prompt which gets printed after the "echo" command is also
suppressed. Since this stuff comes down the pty asynchronously, it
might get read in one packet ("^G^G/usr/newdir^A\nprompt>") which is no
problem, or in two packets ("^G^G/usr/newdir^A\n", "prompt>") in which
case we have to wait for and suppress the second one.
Now, I realize that this routine can be easily defeated, and lose big in
some cases, but the general algorithm is a sound and efficient way to
preprocess input to and output from a command processor.
--
unsigned *Wayne_Mesard(); MESARD at BBN.COM BBN Labs, Cambridge, MA
Is it because of the people you hang around with that you say you do not
need dan rather?
M-x psychoanalyze-pinhead
(Gee, whataneditor!!)
More information about the Comp.unix.questions
mailing list