# "Hijack" other programs stdin & stdout



## c_geier (Oct 13, 2012)

Hi,
I'm working on an address book program in python (pycarddav) for use with mail/mutt, which has the ability to add email address directly from mutt. I use devel/py-urwid, an ncurses like console UI kit which needs to write to stdout. On Linux we use the /proc fs to walk up the program's parents until we find one that is connected to a TTY and than use its stdin, stdout and stderr.

I would also like to do this on FreeBSD. How could we:

 find the parent process which is connected to a TTY? (Is there anything better than parsing ps's output?)
 use this process's stdin etc?

For reference purposes I'm attaching the relevant Linux centric code.

Thanks for your input!



```
def capture_tty():                                                                 
    """Walk the parent processes until a TTY is found.                             
                                                                                   
    See http://stackoverflow.com/questions/1728330/how-to-get-processs-grandparent-id
    """                                                                            
    pid = 'self'                                                                   
    input_file = sys.stdin                                                         
    while not input_file.isatty():                                                 
        with open('/proc/%s/status' % pid) as f:                                   
            for line in f:                                                         
                if line.startswith('PPid:'):                                       
                    _, _, pid = line.rpartition("\t")                              
                    pid = pid.rstrip()                                             
                    input_file = open('/proc/%s/fd/0' % pid)                       
                    break                                                          
            else:                                                                  
                raise RuntimeError('cannot find parent of %s' % pid)               
                                                                                   
    if pid != 'self':                                                              
        sys.stdin = input_file                                                     
        sys.stdout = open('/proc/%s/fd/1' % pid, 'wb')                             
        sys.stderr = open('/proc/%s/fd/2' % pid, 'wb')                             
                                                                                   
        os.dup2(sys.stdin.fileno(), 0)                                             
        os.dup2(sys.stdout.fileno(), 1)                                            
        os.dup2(sys.stderr.fileno(), 2)                                            
        print sys.stdout.fileno()                                                  
                                                                                   
                                                                                   
                                                                                   
def release_tty():                                                                 
    sys.stdin.close()                                                              
    sys.stdout.close()                                                             
    sys.stderr.close()
```


----------



## Crest (Oct 14, 2012)

Their is procstat(1).


----------



## oops (Oct 17, 2012)

Try sysutils/py-psutil.

```
$ sleep 99999 &
[1] 14884

$ python2
>>> import psutil
>>> psutil.Process(pid=14884).ppid
1159
>>> psutil.Process(pid=14884).terminal
'/dev/pts/5'
>>> psutil.Process(pid=14884).get_open_files()
[openfile(path='/bin/sleep', fd=-5)]
```


----------



## c_geier (Oct 17, 2012)

oops said:
			
		

> Try sysutils/py-psutil.
> 
> ```
> $ sleep 99999 &
> ...


This looks awesome, looks like we only need one implementation after all.

Thanks! I'll let you guys know how it works out.


----------



## c_geier (Oct 25, 2012)

Thanks, psutils does the trick perfectly and platform independent (only tested FreeBSD & Linux).


----------



## jilles@ (Nov 1, 2012)

Am I misunderstanding something or can you just open /dev/tty instead of doing complicated process tree walks?


----------



## c_geier (Nov 2, 2012)

jilles@ said:
			
		

> Am I misunderstanding something or can you just open /dev/tty instead of doing complicated process tree walks?



But how do I know which /dev/ttyX is the right one?


----------



## jilles@ (Nov 3, 2012)

I mean literally /dev/tty. This refers to the controlling terminal of the process that opens it.


----------



## c_geier (Nov 5, 2012)

jilles@ said:
			
		

> I mean literally /dev/tty. This refers to the controlling terminal of the process that opens it.



Thx, I didn't know that before.


----------

