[comp.unix.questions] determine the current directory of a son-process

valder@gmdzi.UUCP (Wilhelm Valder) (06/21/88)

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).
The command listener in turn should provide a set of facilities to ease
command formulation. Two of these facilities are: expansion of regular
expressions into a string of file names and file name completion.
Whenever the user requests the command listener to complete a partial
file name, this name is replaced by its completed file name (if such a
completion exists). For this purpose the command listener must know
the current working directory of the son process. Up to now I have
found no solution to this problem. The only thing I have found is an
entry in the user-structure of a process that holds some information
about the current directory of this process (namely the entry
'u_cdir'). Unfortunately, this entry is actually a pointer to a
structure of type 'vnode' and I see no way to get the name of the
coresponding directory or to even read the contents of this directory.

I would be very grateful if anybody could give me a hint how to solve this
problem or to state the problem is unsolvable. 

BTW, we are implementing on a SUN3/75 running SUN-OS 3.4.

	
	Thanks in advance for any assistance.

---------------------------------------------------------------------------------
Willi Valder
GMD / F2.G2
Schloss Birlinghoven
D-5205 Sankt Augustin 1, FRG

phone:	(+49 2241) 14-2590
email:	valder%gmdzi&mcvax

mesard@bbn.com (Wayne Mesard) (06/22/88)

[ N.B. followups to wizards.]

From article <579@gmdzi.UUCP>, by valder@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@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!!)