From 03be66c857eb673617312cbd65a5c5766cb6b4a2 Mon Sep 17 00:00:00 2001 From: Drazen Kacar Date: Sun, 9 May 1999 20:27:43 +0000 Subject: [PATCH] Initial Solaris 2.5 port. It's far from being complete and hasn't been * glibtop_machine.h, procdata.c, proclist.c, procmap.c, procmem.c, procsignal.c, procstate.c, procuid.c, open.c, mem.c: Initial Solaris 2.5 port. It's far from being complete and hasn't been tested properly. We'll need setuid root daemon, which is currently not implemented. #ifdef symbols to check are HAVE_PROCFS_H and KSTAT_DATA_UINT32. These will be defined on Solaris 2.6 and later, but not on earlier releases. --- sysdeps/solaris/ChangeLog | 10 +++ sysdeps/solaris/glibtop_machine.h | 5 ++ sysdeps/solaris/mem.c | 4 + sysdeps/solaris/open.c | 11 +++ sysdeps/solaris/procdata.c | 124 +++++++++++++++++++++++++++++- sysdeps/solaris/proclist.c | 20 +++-- sysdeps/solaris/procmap.c | 42 ++++++++-- sysdeps/solaris/procmem.c | 19 +++-- sysdeps/solaris/procsignal.c | 8 ++ sysdeps/solaris/procstate.c | 25 ++++-- sysdeps/solaris/procuid.c | 24 +++++- 11 files changed, 263 insertions(+), 29 deletions(-) diff --git a/sysdeps/solaris/ChangeLog b/sysdeps/solaris/ChangeLog index 94e6f8aa..a775ebe1 100644 --- a/sysdeps/solaris/ChangeLog +++ b/sysdeps/solaris/ChangeLog @@ -1,3 +1,13 @@ +1999-05-09 Drazen Kacar + + * glibtop_machine.h, procdata.c, proclist.c, procmap.c, procmem.c, + procsignal.c, procstate.c, procuid.c, open.c, mem.c: Initial + Solaris 2.5 port. It's far from being complete and hasn't been + tested properly. We'll need setuid root daemon, which is + currently not implemented. #ifdef symbols to check are + HAVE_PROCFS_H and KSTAT_DATA_UINT32. These will be defined on + Solaris 2.6 and later, but not on earlier releases. + 1999-05-08 Drazen Kacar * safeio.c, safeio.h: Added s_open(), s_close() etc. with EINTR diff --git a/sysdeps/solaris/glibtop_machine.h b/sysdeps/solaris/glibtop_machine.h index c38f3c41..f4bff6cb 100644 --- a/sysdeps/solaris/glibtop_machine.h +++ b/sysdeps/solaris/glibtop_machine.h @@ -25,7 +25,11 @@ #define __GLIBTOP_MACHINE_H__ #include +#ifdef HAVE_PROCFS_H #include +#else +#include +#endif #include #include @@ -58,6 +62,7 @@ struct _glibtop_machine int pagesize; /* in bits to shift, ie. 2^pagesize gives Kb */ int ticks; /* clock ticks, as returned by sysconf() */ unsigned long long boot; /* boot time, it's ui32 in kstat */ + long argvenvp; /* max length or argv + env */ }; END_LIBGTOP_DECLS diff --git a/sysdeps/solaris/mem.c b/sysdeps/solaris/mem.c index 7c7edc18..ffd4cd96 100644 --- a/sysdeps/solaris/mem.c +++ b/sysdeps/solaris/mem.c @@ -57,6 +57,10 @@ glibtop_get_mem_s (glibtop *server, glibtop_mem *buf) kstat_named_t *kn; int pagesize = server->machine.pagesize; +#ifndef KSTAT_DATA_UINT32 +#define ui32 ul +#endif + memset (buf, 0, sizeof (glibtop_mem)); buf->total = (u_int64_t)sysconf(_SC_PHYS_PAGES) << pagesize; diff --git a/sysdeps/solaris/open.c b/sysdeps/solaris/open.c index 03f2c430..61d1f048 100644 --- a/sysdeps/solaris/open.c +++ b/sysdeps/solaris/open.c @@ -179,6 +179,7 @@ glibtop_open_s (glibtop *server, const char *program_name, if(kn) switch(kn->data_type) { +#ifdef KSTAT_DATA_INT32 case KSTAT_DATA_INT32: server->machine.boot = kn->value.i32; break; case KSTAT_DATA_UINT32: server->machine.boot = kn->value.ui32; @@ -187,6 +188,16 @@ glibtop_open_s (glibtop *server, const char *program_name, break; case KSTAT_DATA_UINT64: server->machine.boot = kn->value.ui64; break; +#else + case KSTAT_DATA_LONG: server->machine.boot = kn->value.l; + break; + case KSTAT_DATA_ULONG: server->machine.boot = kn->value.ul; + break; + case KSTAT_DATA_LONGLONG: server->machine.boot = kn->value.ll; + break; + case KSTAT_DATA_ULONGLONG: server->machine.boot = kn->value.ull; + break; } +#endif } } diff --git a/sysdeps/solaris/procdata.c b/sysdeps/solaris/procdata.c index 11c1e07d..b21be2b2 100644 --- a/sysdeps/solaris/procdata.c +++ b/sysdeps/solaris/procdata.c @@ -29,6 +29,21 @@ #include "safeio.h" +/* + * The differences between old and new procfs API are: + * - old has /proc/ file and ioctl() is used to obtain the data. + * - new has /proc//* files and read() & friends are used to + * obtain the data. + * - names of structures and members are different. It's mostly the + * prefix. Old uses `pr' and new uses `ps'. + * + * Since almost every line would be in #ifdef, I think it would + * be more readable to just copy everything twice. This is not a big + * file, after all. + */ + +#ifdef HAVE_PROCFS_H + /* Read /proc//psinfo. */ int @@ -135,10 +150,117 @@ glibtop_get_proc_status_s(glibtop *server, struct pstatus *pstatus, pid_t pid) if(s_pread(fd, pstatus, sizeof(struct pstatus), 0) != sizeof(struct pstatus)) { - close(fd); + s_close(fd); glibtop_warn_io_r(server, "pread (%s)", buffer); return -1; } s_close(fd); return 0; } + +#else /* old API */ + +int +glibtop_get_proc_data_psinfo_s (glibtop *server, + struct prpsinfo *psinfo, + pid_t pid) +{ + int fd; + char buffer [BUFSIZ]; + + sprintf (buffer, "/proc/%d", (int) pid); + fd = s_open (buffer, O_RDONLY); + if (fd < 0) { + if(errno != EPERM && errno != EACCES) + glibtop_warn_io_r (server, "open (%s)", buffer); + return -1; + } + + if(ioctl(fd, PIOCPSINFO, psinfo) < 0) + { + s_close (fd); + glibtop_warn_io_r (server, "ioctl(%s, PIOCPSINFO)", buffer); + return -1; + } + + s_close (fd); + return 0; +} + +int +glibtop_get_proc_data_usage_s (glibtop *server, + struct prusage *prusage, + pid_t pid) +{ + int fd; + char buffer [BUFSIZ]; + + sprintf (buffer, "/proc/%d", (int) pid); + fd = s_open (buffer, O_RDONLY); + if (fd < 0) { + if(errno != EPERM && errno != EACCES) + glibtop_warn_io_r (server, "open (%s)", buffer); + return -1; + } + + if(ioctl(fd, PIOCUSAGE, prusage) < 0) + { + s_close (fd); + glibtop_warn_io_r (server, "ioctl(%s, PIOCUSAGE)", buffer); + return -1; + } + + s_close (fd); + return 0; +} + +int +glibtop_get_proc_credentials_s(glibtop *server, + struct prcred *prcred, + gid_t *groups, + pid_t pid) +{ + int fd; + size_t toread; + char buffer[BUFSIZ]; + + sprintf(buffer, "/proc/%d", (int)pid); + if((fd = s_open(buffer, O_RDONLY)) < 0) + { + if(errno != EPERM && errno != EACCES) + glibtop_warn_io_r(server, "open (%s)", buffer); + return -1; + } + if(ioctl(fd, PIOCCRED, prcred) < 0) + { + s_close(fd); + glibtop_warn_io_r(server, "ioctl(%s, PIOCCRED)", buffer); + return -1; + } + s_close(fd); + return 0; +} + +int +glibtop_get_proc_status_s(glibtop *server, struct prstatus *pstatus, pid_t pid) +{ + int fd; + char buffer[BUFSIZ]; + + sprintf(buffer, "/proc/%d", (int)pid); + if((fd = s_open(buffer, O_RDONLY)) < 0) + { + if(errno != EPERM && errno != EACCES) + glibtop_warn_io_r(server, "open (%s)", buffer); + return -1; + } + if(ioctl(fd, PIOCSTATUS, pstatus) < 0) + { + s_close(fd); + glibtop_warn_io_r(server, "ioctl(%s, PIOCSTATUS)", buffer); + return -1; + } + s_close(fd); + return 0; +} +#endif diff --git a/sysdeps/solaris/proclist.c b/sysdeps/solaris/proclist.c index 33c6172b..11c1176a 100644 --- a/sysdeps/solaris/proclist.c +++ b/sysdeps/solaris/proclist.c @@ -79,23 +79,31 @@ glibtop_get_proclist_s (glibtop *server, glibtop_proclist *buf, ok = 1; len = strlen (entry->d_name); /* does it consist entirely of digits? */ - +#if 0 + /* It does, except for "." and "..". Let's speed up */ + for (i = 0; i < len; i++) if (!isdigit (entry->d_name [i])) ok = 0; if (!ok) continue; +#else + if(entry->d_name[0] == '.') + continue; +#endif /* convert it in a number */ - +#if 0 if (sscanf (entry->d_name, "%u", &pid) != 1) continue; - +#else + pid = (unsigned)atol(entry->d_name); +#endif + sprintf (buffer, "/proc/%d", pid); +#ifdef HAVE_PROCFS_H /* is it really a directory? */ - sprintf (buffer, "/proc/%d", pid); - if (s_stat (buffer, &statb)) continue; if (!S_ISDIR (statb.st_mode)) continue; - +#endif /* Fine. Now we first try to store it in pids. If this buffer is * full, we copy it to the pids_chain. */ diff --git a/sysdeps/solaris/procmap.c b/sysdeps/solaris/procmap.c index 1973f7f3..d35057c3 100644 --- a/sysdeps/solaris/procmap.c +++ b/sysdeps/solaris/procmap.c @@ -55,25 +55,39 @@ glibtop_get_proc_map_s (glibtop *server, glibtop_proc_map *buf, pid_t pid) { int fd, i, nmaps; prmap_t *maps; + + /* A few defines, to make it shorter down there */ + +#ifdef HAVE_PROCFS_H +# define OFFSET pr_offset +#else +# define OFFSET pr_off +#endif + glibtop_map_entry *entry; struct stat inode; char buffer[BUFSIZ]; memset (buf, 0, sizeof (glibtop_proc_map)); +#ifdef HAVE_PROCFS_H sprintf(buffer, "/proc/%d/map", (int)pid); +#else + sprintf(buffer, "/proc/%d", (int)pid); +#endif if((fd = s_open(buffer, O_RDONLY)) < 0) { if(errno != EPERM && errno != EACCES) glibtop_warn_io_r(server, "open (%s)", buffer); return NULL; } +#ifdef HAVE_PROCFS_H if(fstat(fd, &inode) < 0) { if(errno != EOVERFLOW) glibtop_warn_io_r(server, "fstat (%s)", buffer); /* else call daemon for 64-bit support */ - close(fd); + s_close(fd); return NULL; } maps = alloca(inode.st_size); @@ -81,13 +95,28 @@ glibtop_get_proc_map_s (glibtop *server, glibtop_proc_map *buf, pid_t pid) if(s_pread(fd, maps, inode.st_size, 0) != inode.st_size) { glibtop_warn_io_r(server, "pread (%s)", buffer); - close(fd); + s_close(fd); return NULL; } - close(fd); - if(!(entry = glibtop_malloc_r(server, nmaps * sizeof(glibtop_map_entry)))) +#else + if(ioctl(fd, PIOCNMAP, &nmaps) < 0) + { + glibtop_warn_io_r(server, "ioctl(%s, PIOCNMAP)", buffer); + s_close(fd); + return NULL; + } + maps = alloca((nmaps + 1) * sizeof(prmap_t)); + if(ioctl(fd, PIOCMAP, maps) < 0) + { + glibtop_warn_io_r(server, "ioctl(%s, PIOCMAP)", buffer); + s_close(fd); + return NULL; + } +#endif + s_close(fd); + if(!(entry = glibtop_malloc_r(server, + nmaps * sizeof(glibtop_map_entry)))) return NULL; - buf->number = nmaps; buf->size = sizeof(glibtop_map_entry); buf->total = nmaps * sizeof(glibtop_map_entry); @@ -97,7 +126,7 @@ glibtop_get_proc_map_s (glibtop *server, glibtop_proc_map *buf, pid_t pid) { entry[i].start = maps[i].pr_vaddr; entry[i].end = maps[i].pr_vaddr + maps[i].pr_size; - entry[i].offset = maps[i].pr_offset; + entry[i].offset = maps[i].OFFSET; if(maps[i].pr_mflags & MA_READ) entry[i].perm |= GLIBTOP_MAP_PERM_READ; if(maps[i].pr_mflags & MA_WRITE) @@ -110,7 +139,6 @@ glibtop_get_proc_map_s (glibtop *server, glibtop_proc_map *buf, pid_t pid) entry[i].perm |= GLIBTOP_MAP_PERM_PRIVATE; entry[i].flags = _glibtop_sysdeps_map_entry; } - buf->flags = _glibtop_sysdeps_proc_map; return entry; } diff --git a/sysdeps/solaris/procmem.c b/sysdeps/solaris/procmem.c index a21647ee..6452f0f7 100644 --- a/sysdeps/solaris/procmem.c +++ b/sysdeps/solaris/procmem.c @@ -39,19 +39,26 @@ glibtop_init_proc_mem_s (glibtop *server) /* Provides detailed information about a process. */ void -glibtop_get_proc_mem_s (glibtop *server, glibtop_proc_mem *buf, - pid_t pid) +glibtop_get_proc_mem_s (glibtop *server, glibtop_proc_mem *buf, pid_t pid) { - int pagesize = server->machine.pagesize; +#ifdef HAVE_PROCFS_H struct psinfo psinfo; +#else + struct prpsinfo psinfo; + int pagesize = server->machine.pagesize; +#endif memset (buf, 0, sizeof (glibtop_proc_mem)); if(glibtop_get_proc_data_psinfo_s(server, &psinfo, pid)) return; - buf->size = buf->vsize = psinfo.pr_size; - buf->resident = buf->rss = psinfo.pr_rssize; - +#ifdef HAVE_PROCFS_H + buf->size = buf->vsize = psinfo.pr_size << 10; + buf->resident = buf->rss = psinfo.pr_rssize << 10; +#else + buf->size = buf->vsize = psinfo.pr_size << pagesize << 10; + buf->resident = buf->rss = psinfo.pr_rssize << pagesize << 10; +#endif buf->flags = _glibtop_sysdeps_proc_mem; } diff --git a/sysdeps/solaris/procsignal.c b/sysdeps/solaris/procsignal.c index aa51ee25..5b4d06a7 100644 --- a/sysdeps/solaris/procsignal.c +++ b/sysdeps/solaris/procsignal.c @@ -43,7 +43,11 @@ void glibtop_get_proc_signal_s (glibtop *server, glibtop_proc_signal *buf, pid_t pid) { +#ifdef HAVE_PROCFS_H struct pstatus pstatus; +#else + struct prstatus pstatus; +#endif int size; memset (buf, 0, sizeof (glibtop_proc_signal)); @@ -57,7 +61,11 @@ glibtop_get_proc_signal_s (glibtop *server, glibtop_proc_signal *buf, size = sizeof(sigset_t); memcpy(buf->signal, &pstatus.pr_sigpend, size); +#ifdef HAVE_PROCFS_H memcpy(buf->blocked, &pstatus.pr_lwp.pr_lwphold, size); +#else + memcpy(buf->blocked, &pstatus.pr_lwppend, size); +#endif /* Technically, most of this is meaningless on a process level, but this should be a good enough approximation. */ diff --git a/sysdeps/solaris/procstate.c b/sysdeps/solaris/procstate.c index 8e415879..b2aba4b7 100644 --- a/sysdeps/solaris/procstate.c +++ b/sysdeps/solaris/procstate.c @@ -27,11 +27,13 @@ #include static const unsigned long _glibtop_sysdeps_proc_state = +#ifdef HAVE_PROCFS_H +(1L << GLIBTOP_PROC_STATE_HAS_CPU) + (1L << GLIBTOP_PROC_STATE_PROCESSOR) + +(1L << GLIBTOP_PROC_STATE_LAST_PROCESSOR) + +#endif (1L << GLIBTOP_PROC_STATE_CMD) + (1L << GLIBTOP_PROC_STATE_STATE) + (1L << GLIBTOP_PROC_STATE_UID) + (1L << GLIBTOP_PROC_STATE_GID) + -(1L << GLIBTOP_PROC_STATE_RUID) + (1L << GLIBTOP_PROC_STATE_RGID) + -(1L << GLIBTOP_PROC_STATE_HAS_CPU) + (1L << GLIBTOP_PROC_STATE_PROCESSOR) + -(1L << GLIBTOP_PROC_STATE_LAST_PROCESSOR); +(1L << GLIBTOP_PROC_STATE_RUID) + (1L << GLIBTOP_PROC_STATE_RGID); /* Init function. */ @@ -46,7 +48,11 @@ glibtop_init_proc_state_s (glibtop *server) void glibtop_get_proc_state_s (glibtop *server, glibtop_proc_state *buf, pid_t pid) { +#ifdef HAVE_PROCFS_H struct psinfo psinfo; +#else + struct prpsinfo psinfo; +#endif memset (buf, 0, sizeof (glibtop_proc_state)); @@ -57,10 +63,17 @@ glibtop_get_proc_state_s (glibtop *server, glibtop_proc_state *buf, pid_t pid) buf->gid = psinfo.pr_egid; buf->ruid = psinfo.pr_uid; buf->rgid = psinfo.pr_gid; +#ifdef HAVE_PROCFS_H switch(psinfo.pr_lwp.pr_state) +#else + switch(psinfo.pr_state) +#endif { - case SONPROC: buf->has_cpu = 1; + case SONPROC: +#ifdef HAVE_PROCFS_H + buf->has_cpu = 1; buf->processor = psinfo.pr_lwp.pr_onpro; +#endif case SRUN: buf->state = GLIBTOP_PROCESS_RUNNING; break; case SZOMB: buf->state = GLIBTOP_PROCESS_ZOMBIE; @@ -70,9 +83,9 @@ glibtop_get_proc_state_s (glibtop *server, glibtop_proc_state *buf, pid_t pid) break; case SIDL: buf->state = GLIBTOP_PROCESS_UNINTERRUPTIBLE; } +#ifdef HAVE_PROCFS_H buf->last_processor = psinfo.pr_lwp.pr_onpro; - - +#endif strncpy (buf->cmd, psinfo.pr_fname, 39); buf->flags = _glibtop_sysdeps_proc_state; diff --git a/sysdeps/solaris/procuid.c b/sysdeps/solaris/procuid.c index edeb03cb..9238e88b 100644 --- a/sysdeps/solaris/procuid.c +++ b/sysdeps/solaris/procuid.c @@ -34,9 +34,11 @@ static const unsigned long _glibtop_sysdeps_proc_uid_psinfo = (1L << GLIBTOP_PROC_UID_TTY) + (1L << GLIBTOP_PROC_UID_PRIORITY) + (1L << GLIBTOP_PROC_UID_NICE); static const unsigned long _glibtop_sysdeps_proc_uid_prcred = +#ifdef HAVE_PROCFS_H +(1L << GLIBTOP_PROC_UID_GROUPS) + +#endif (1L << GLIBTOP_PROC_UID_SUID) + (1L << GLIBTOP_PROC_UID_SGID) + -(1L << GLIBTOP_PROC_UID_NGROUPS) + (1L << GLIBTOP_PROC_UID_GROUPS); - +(1L << GLIBTOP_PROC_UID_NGROUPS); /* Init function. */ void @@ -51,9 +53,14 @@ glibtop_init_proc_uid_s (glibtop *server) void glibtop_get_proc_uid_s (glibtop *server, glibtop_proc_uid *buf, pid_t pid) { - struct psinfo psinfo; struct prcred prcred; +#ifdef HAVE_PROCFS_H + struct psinfo psinfo; gid_t groups[GLIBTOP_MAX_GROUPS]; +#else + struct prpsinfo psinfo; + gid_t groups[1]; /* dummy for consistent function prototype */ +#endif memset (buf, 0, sizeof (glibtop_proc_uid)); @@ -67,13 +74,22 @@ glibtop_get_proc_uid_s (glibtop *server, glibtop_proc_uid *buf, pid_t pid) buf->pid = psinfo.pr_pid; buf->ppid = psinfo.pr_ppid; +#ifdef HAVE_PROCFS_H buf->pgrp = psinfo.pr_pgid; +#else + buf->pgrp = psinfo.pr_pgrp; +#endif buf->session = psinfo.pr_sid; buf->tty = psinfo.pr_ttydev; +#ifdef HAVE_PROCFS_H buf->priority = psinfo.pr_lwp.pr_pri; buf->nice = psinfo.pr_lwp.pr_nice - NZERO; +#else + buf->priority = psinfo.pr_pri; + buf->nice = psinfo.pr_nice - NZERO; +#endif buf->flags = _glibtop_sysdeps_proc_uid_psinfo; @@ -85,6 +101,7 @@ glibtop_get_proc_uid_s (glibtop *server, glibtop_proc_uid *buf, pid_t pid) buf->ngroups = (prcred.pr_ngroups <= GLIBTOP_MAX_GROUPS) ? prcred.pr_ngroups : GLIBTOP_MAX_GROUPS; +#ifdef HAVE_PROCFS_H if(sizeof(int) == sizeof(gid_t)) memcpy(buf->groups, &groups, buf->ngroups * sizeof(gid_t)); else @@ -94,5 +111,6 @@ glibtop_get_proc_uid_s (glibtop *server, glibtop_proc_uid *buf, pid_t pid) for(i = 0; i < buf->ngroups; ++i) buf->groups[i] = groups[i]; } +#endif buf->flags += _glibtop_sysdeps_proc_uid_prcred; }