From a239876d99bd2db4a3edb15ca911e1977493d112 Mon Sep 17 00:00:00 2001 From: Thomas Hurst Date: Wed, 21 May 2008 11:39:30 +0100 Subject: [PATCH] Move cwd detection code about a bit, add FreeBSD support code that'll currently only do anything on 7-STABLE as of last month. --- terminator | 22 ++++++----- terminatorlib/freebsd.py | 83 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 10 deletions(-) create mode 100644 terminatorlib/freebsd.py diff --git a/terminator b/terminator index 89815c45..21a7dcd4 100755 --- a/terminator +++ b/terminator @@ -42,6 +42,17 @@ from terminatorlib.config import dbg #import encoding list from terminatorlib.encoding import TerminatorEncoding +# Sort out cwd detection code, if available +pid_get_cwd = lambda pid: None +if platform.system() == 'FreeBSD': + try: + from terminatorlib import freebsd + pid_get_cwd = lambda pid: freebsd.get_process_cwd(pid) + except: + pass +elif platform.system == 'Linux': + pid_get_cwd = lambda pid: os.path.realpath ('/proc/%s/cwd' % pid) + # import gtk libs # check just in case anyone runs it on a non-gnome system. try: @@ -224,16 +235,7 @@ class TerminatorTerm (gtk.VBox): """ Return the current working directory of the subprocess. This function requires OS specific behaviours """ - cwd = None - system = platform.system () - - if system == 'Linux': - try: - cwd = os.path.realpath ('/proc/%s/cwd' % self._pid) - except: - pass - - return (cwd) + return (pid_get_cwd(self._pid)) def reconfigure_vte (self): # Set our emulation diff --git a/terminatorlib/freebsd.py b/terminatorlib/freebsd.py new file mode 100644 index 00000000..221d5146 --- /dev/null +++ b/terminatorlib/freebsd.py @@ -0,0 +1,83 @@ +#!/usr/local/bin/python +# +# Use sysctl() to retrieve the cwd of an arbitrary process on FreeBSD. +# Tested on FreeBSD 7-STABLE/amd64 from April 11 2008. +# +# Be prepared for excitement if the structs are changed. +# +# Blame: Thomas Hurst +# + +from ctypes import * + +# This is padded awkwardly, see /usr/include/sys/socket.h +class sockaddr_storage(Structure): + _fields_ = [ + ('ss_len', c_char), + ('ss_family', c_char), # /usr/include/sys/_types.h; _uint8_t + ('__ss_pad1', c_char * 6), # (sizeof(int64) - sizeof(char) - sizeof(ss_family_t)) + ('__ss_align', c_longlong), + ('__ss_pad2', c_char * 112), # (128(maxsize) - sizeof(char) - sizeof(ss_family_t) - + # sizeof(ss_pad1) - sizeof(int64)) + ] + +# struct kinfo_file, defined in /usr/include/sys/user.h +class kinfo_file(Structure): + _fields_ = [ + ('kf_structsize', c_int), + ('kf_type', c_int), + ('kf_fd', c_int), + ('kf_ref_count', c_int), + ('kf_flags', c_int), + ('kf_offset', c_long), # this is a off_t, a pointer + ('kf_vnode_type', c_int), + ('kf_sock_domain', c_int), + ('kf_sock_type', c_int), + ('kf_sock_protocol', c_int), + ('kf_path', c_char * 1024), # PATH_MAX + ('kf_sa_local', sockaddr_storage), + ('kf_sa_peer', sockaddr_storage), + ] + + +def get_process_cwd(pid): + libc = CDLL('libc.so') + + len = c_uint(sizeof(c_uint)) + ver = c_uint(0) + + if (libc.sysctlbyname('kern.osreldate', byref(ver), byref(len), None, 0) < 0): + return None + + # kern.proc.filedesc added for procstat(1) after these __FreeBSD_versions + if ver.value < 700104 and ver.value < 800019: + return None + + # /usr/include/sys/sysctl.h + # CTL_KERN, KERN_PROC, KERN_PROC_FILEDESC + oid = (c_uint * 4)(1, 14, 14, pid) + + if libc.sysctl(oid, 4, None, byref(len), None, 0) < 0: + return None + + buf = c_char_p(" " * len.value) + if libc.sysctl(oid, 4, buf, byref(len), None, 0) < 0: + return None + + kifs = cast(buf, POINTER(kinfo_file)) + for i in range(0, len.value / sizeof(kinfo_file)): + kif = kifs[i] + if kif.kf_fd == -1: # KF_FD_TYPE_CWD + return kif.kf_path + +if __name__ == '__main__': + import os, sys + print " => %d cwd = %s" % (os.getpid(), get_process_cwd(os.getpid())) + for pid in sys.argv: + try: + pid = int(pid) + except: + pass + else: + print " => %d cwd = %s" % (pid, get_process_cwd(pid)) +