diff --git a/psutil/_pssunos.py b/psutil/_pssunos.py index b1ba6b452..6a0e007d3 100644 --- a/psutil/_pssunos.py +++ b/psutil/_pssunos.py @@ -370,11 +370,13 @@ def __init__(self, pid): def oneshot_enter(self): self._proc_name_and_args.cache_activate() + self._proc_environ.cache_activate() self._proc_basic_info.cache_activate() self._proc_cred.cache_activate() def oneshot_exit(self): self._proc_name_and_args.cache_deactivate() + self._proc_environ.cache_deactivate() self._proc_basic_info.cache_deactivate() self._proc_cred.cache_deactivate() @@ -382,6 +384,12 @@ def oneshot_exit(self): def _proc_name_and_args(self): return cext.proc_name_and_args(self.pid, self._procfs_path) + @memoize_when_activated + def _proc_environ(self): + args = cext.proc_environ(self.pid, self._procfs_path) + if args: + return dict(args) + @memoize_when_activated def _proc_basic_info(self): ret = cext.proc_basic_info(self.pid, self._procfs_path) @@ -414,6 +422,10 @@ def exe(self): def cmdline(self): return self._proc_name_and_args()[1].split(' ') + @wrap_exceptions + def environ(self): + return self._proc_environ() + @wrap_exceptions def create_time(self): return self._proc_basic_info()[proc_info_map['create_time']] diff --git a/psutil/_psutil_sunos.c b/psutil/_psutil_sunos.c index 785805d4d..3d887c8c0 100644 --- a/psutil/_psutil_sunos.c +++ b/psutil/_psutil_sunos.c @@ -114,6 +114,106 @@ psutil_proc_basic_info(PyObject *self, PyObject *args) { ); } +static int +read_offt(int fd, off_t offt, char *buf, size_t buf_size) { + off_t ret = lseek(fd, offt, SEEK_SET); + if (ret == (off_t)-1) { + return -errno; + } + + size_t to_read = buf_size; + size_t offset = 0; + + while (to_read) { + int r = read(fd, buf + offset, to_read); + if (r < 0) { + return -errno; + } + to_read -= r; + offset += r; + } + + return offset; +} + +#define STRING_SEARCH_BUF_SIZE 512 + +static char * +read_cstring_offt(int fd, off_t offset) { + if (lseek(fd, offset, SEEK_SET) == (off_t)-1) { + return NULL; + } + + // Search end of string + off_t end = offset; + for (;; end += STRING_SEARCH_BUF_SIZE) { + char buf[STRING_SEARCH_BUF_SIZE] = {}; + int r = read(fd, buf, sizeof(buf)); + + if (r == -1) { + if (end == offset) + return NULL; + else { + end -= 1; + break; + } + } else if (r == 0) { + break; + } else { + int i; + int found = 0; + for (i=0; i 8) { + return -1; + } + + int res = 0; + static const char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + for (;; res ++) { + char buf[8] = {}; + int r = read(fd, buf, ptr_size); + if (r != ptr_size) + return -1; + if (!memcmp(buf, zeros, ptr_size)) + return res; + } + + return res; +} /* * Return process name and args as a Python tuple. @@ -121,15 +221,17 @@ psutil_proc_basic_info(PyObject *self, PyObject *args) { static PyObject * psutil_proc_name_and_args(PyObject *self, PyObject *args) { int pid; + int fd = -1; int i; char path[1000]; psinfo_t info; const char *procfs_path; PyObject *py_name; - PyObject *py_args; PyObject *py_retlist; + PyObject *py_args = NULL; if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) return NULL; + sprintf(path, "%s/%i/psinfo", procfs_path, pid); if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) return NULL; @@ -137,23 +239,217 @@ psutil_proc_name_and_args(PyObject *self, PyObject *args) { py_name = PyUnicode_DecodeFSDefault(info.pr_fname); if (!py_name) goto error; - py_args = PyUnicode_DecodeFSDefault(info.pr_psargs); - if (!py_args) - goto error; + + if (info.pr_argc && strlen(info.pr_psargs) == PRARGSZ-1 +#if !defined(_LP64) + && (info.pr_dmodel == PR_MODEL_ILP32) +#endif + ) { + sprintf(path, "%s/%i/as", procfs_path, pid); + fd = open(path, O_RDONLY); + if (fd != -1) { + char **args = (char**) calloc(info.pr_argc, sizeof(char *)); + if (info.pr_dmodel == PR_MODEL_ILP32) { + size_t argv_size = sizeof(uint32_t) * info.pr_argc; + uint32_t *argv = (uint32_t *) malloc(argv_size); + if (!argv || read_offt(fd, info.pr_argv, (char *)argv, argv_size) != argv_size) { + close(fd); + free(args); free(argv); + goto error; + } + for (i=0; itcp6ConnCreationProcess; #else - processed_pid = 0; + processed_pid = 0; #endif if (pid != -1 && processed_pid != pid) continue; @@ -1163,7 +1459,7 @@ psutil_net_connections(PyObject *self, PyObject *args) { else if (mibhdr->level == MIB2_UDP || mibhdr->level == MIB2_UDP_ENTRY) { ude = (mib2_udpEntry_t *)databuf.buf; num_ent = mibhdr->len / sizeof(mib2_udpEntry_t); - assert(num_ent * sizeof(mib2_udpEntry_t) == mibhdr->len); + assert(num_ent * sizeof(mib2_udpEntry_t) == mibhdr->len); for (i = 0; i < num_ent; i++, ude++) { #ifdef NEW_MIB_COMPLIANT processed_pid = ude->udpCreationProcess; @@ -1475,6 +1771,8 @@ PsutilMethods[] = { "Return process ppid, rss, vms, ctime, nice, nthreads, status and tty"}, {"proc_name_and_args", psutil_proc_name_and_args, METH_VARARGS, "Return process name and args."}, + {"proc_environ", psutil_proc_environ, METH_VARARGS, + "Return process environment."}, {"proc_cpu_times", psutil_proc_cpu_times, METH_VARARGS, "Return process user and system CPU times."}, {"proc_cred", psutil_proc_cred, METH_VARARGS,