Blame sysdeps/sun4/open.c

Packit d37888
/* Copyright (C) 1998-99 Martin Baulig
Packit d37888
   This file is part of LibGTop 1.0.
Packit d37888
Packit d37888
   Contributed by Martin Baulig <martin@home-of-linux.org>, April 1998.
Packit d37888
Packit d37888
   LibGTop is free software; you can redistribute it and/or modify it
Packit d37888
   under the terms of the GNU General Public License as published by
Packit d37888
   the Free Software Foundation; either version 2 of the License,
Packit d37888
   or (at your option) any later version.
Packit d37888
Packit d37888
   LibGTop is distributed in the hope that it will be useful, but WITHOUT
Packit d37888
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
Packit d37888
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
Packit d37888
   for more details.
Packit d37888
Packit d37888
   You should have received a copy of the GNU General Public License
Packit d37888
   along with LibGTop; see the file COPYING. If not, write to the
Packit d37888
   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Packit d37888
   Boston, MA 02110-1301, USA.
Packit d37888
*/
Packit d37888
Packit d37888
#include <config.h>
Packit d37888
#include <glib.h>
Packit d37888
#include <errno.h>
Packit d37888
Packit d37888
#include <glibtop.h>
Packit d37888
#include <glibtop/open.h>
Packit d37888
Packit d37888
struct nlist _glibtop_nlist[] = {
Packit d37888
#ifdef i386
Packit d37888
    { "avenrun" },		/* 0 */
Packit d37888
    { "ccpu" },			/* 1 */
Packit d37888
    { "mpid" },			/* 2 */
Packit d37888
    { "nproc" },		/* 3 */
Packit d37888
    { "proc" },			/* 4 */
Packit d37888
    { "total" },		/* 5 */
Packit d37888
    { "cp_time" },		/* 6 */
Packit d37888
    { "pages" },		/* 7 */
Packit d37888
    { "epages" },		/* 8 */
Packit d37888
    { "shminfo" },		/* 9 */
Packit d37888
    { "msginfo" },		/* 10 */
Packit d37888
    { "seminfo" },		/* 11 */
Packit d37888
#else
Packit d37888
    { "_avenrun" },		/* 0 */
Packit d37888
    { "_ccpu" },		/* 1 */
Packit d37888
    { "_mpid" },		/* 2 */
Packit d37888
    { "_nproc" },		/* 3 */
Packit d37888
    { "_proc" },		/* 4 */
Packit d37888
    { "_total" },		/* 5 */
Packit d37888
    { "_cp_time" },		/* 6 */
Packit d37888
    { "_pages" },		/* 7 */
Packit d37888
    { "_epages" },		/* 8 */
Packit d37888
    { "_shminfo" },		/* 9 */
Packit d37888
    { "_msginfo" },		/* 10 */
Packit d37888
    { "_seminfo" },		/* 11 */
Packit d37888
#ifdef MULTIPROCESSOR
Packit d37888
    { "_ncpu" },
Packit d37888
    { "_mp_time" },
Packit d37888
#endif
Packit d37888
#endif
Packit d37888
    { 0 }
Packit d37888
};
Packit d37888
Packit d37888
/* Opens pipe to gtop server. Returns 0 on success and -1 on error. */
Packit d37888
Packit d37888
/* !!! THIS FUNCTION RUNS SUID ROOT - CHANGE WITH CAUTION !!! */
Packit d37888
Packit d37888
void
Packit d37888
glibtop_init_p (glibtop *server, const unsigned long features,
Packit d37888
		const unsigned flags)
Packit d37888
{
Packit d37888
	if (server == NULL)
Packit d37888
		glibtop_error_r (NULL, "glibtop_init_p (server == NULL)");
Packit d37888
Packit d37888
	glibtop_open_p (server, "glibtop", features, flags);
Packit d37888
}
Packit d37888
Packit d37888
void
Packit d37888
glibtop_open_p (glibtop *server, const char *program_name,
Packit d37888
		const unsigned long features, const unsigned flags)
Packit d37888
{
Packit d37888
	register int pagesize;
Packit d37888
Packit d37888
	/* !!! WE ARE ROOT HERE - CHANGE WITH CAUTION !!! */
Packit d37888
Packit d37888
	server->name = program_name;
Packit d37888
Packit d37888
	server->machine->uid = getuid ();
Packit d37888
	server->machine->euid = geteuid ();
Packit d37888
	server->machine->gid = getgid ();
Packit d37888
	server->machine->egid = getegid ();
Packit d37888
Packit d37888
	/* initialize the kernel interface */
Packit d37888
Packit d37888
	server->machine->kd = kvm_open (NULL, NULL, NULL, O_RDONLY, "libgtop");
Packit d37888
Packit d37888
	if (server->machine->kd == NULL)
Packit d37888
		glibtop_error_io_r (server, "kvm_open");
Packit d37888
Packit d37888
	/* get the list of symbols we want to access in the kernel */
Packit d37888
Packit d37888
	server->machine->nlist_count = kvm_nlist
Packit d37888
		(server->machine->kd, _glibtop_nlist);
Packit d37888
Packit d37888
	if (server->machine->nlist_count < 0)
Packit d37888
		glibtop_error_io_r (server, "nlist");
Packit d37888
Packit d37888
#ifdef MULTIPROCESSOR
Packit d37888
	/* were ncpu and xp_time not found in the nlist? */
Packit d37888
Packit d37888
	if ((server->machine->nlist_count > 0) &&
Packit d37888
	    (_glibtop_nlist[X_NCPU].n_type == 0) &&
Packit d37888
	    (_glibtop_nlist[X_MP_TIME].n_type == 0)) {
Packit d37888
		/* we were compiled on an MP system but we are not running
Packit d37888
		 * on one, so we will pretend this didn't happen and set
Packit d37888
		 * ncpu = 1 */
Packit d37888
		server->machine->nlist_count -= 2;
Packit d37888
		server->machine->ncpu = 1;
Packit d37888
	}
Packit d37888
#endif
Packit d37888
Packit d37888
#ifdef solbourne
Packit d37888
	{
Packit d37888
		unsigned int status, type;
Packit d37888
Packit d37888
		/* Get the number of CPUs on this system.  */
Packit d37888
		syscall(SYS_getcpustatus, &status,
Packit d37888
			&server->machine->ncpu, &type);
Packit d37888
	}
Packit d37888
#endif
Packit d37888
Packit d37888
	/* Make sure all of the symbols were found. */
Packit d37888
Packit d37888
	if ((server->machine->nlist_count > 0) &&
Packit d37888
	    (_glibtop_check_nlist (server, _glibtop_nlist) > 0))
Packit d37888
		_exit (1);
Packit d37888
Packit d37888
	/* Get process array stuff. */
Packit d37888
Packit d37888
	(void) _glibtop_getkval (server, _glibtop_nlist[X_NPROC].n_value,
Packit d37888
				 (int *)(&server->machine->nproc),
Packit d37888
				 sizeof (server->machine->nproc),
Packit d37888
				 _glibtop_nlist[X_NPROC].n_name);
Packit d37888
Packit d37888
	(void) _glibtop_getkval (server, _glibtop_nlist[X_PROC].n_value,
Packit d37888
				 (int *)(&server->machine->ptable_offset),
Packit d37888
				 sizeof (server->machine->ptable_offset),
Packit d37888
				 _glibtop_nlist[X_PROC].n_name);
Packit d37888
Packit d37888
	server->machine->ptable_size = (unsigned long) server->machine->nproc *
Packit d37888
		(unsigned long) sizeof (struct proc);
Packit d37888
Packit d37888
	server->machine->proc_table = g_malloc
Packit d37888
		(server, server->machine->ptable_size);
Packit d37888
Packit d37888
	/* This are for the memory statistics. */
Packit d37888
Packit d37888
	(void) _glibtop_getkval (server, _glibtop_nlist[X_PAGES].n_value,
Packit d37888
				 (int *)(&server->machine->pages),
Packit d37888
				 sizeof (server->machine->pages),
Packit d37888
				 _glibtop_nlist[X_PAGES].n_name);
Packit d37888
Packit d37888
	(void) _glibtop_getkval (server, _glibtop_nlist[X_EPAGES].n_value,
Packit d37888
				 (int *)(&server->machine->epages),
Packit d37888
				 sizeof (server->machine->epages),
Packit d37888
				 _glibtop_nlist[X_EPAGES].n_name);
Packit d37888
Packit d37888
	server->machine->bytesize = server->machine->epages -
Packit d37888
		server->machine->pages;
Packit d37888
	server->machine->count = server->machine->bytesize /
Packit d37888
		sizeof (struct page);
Packit d37888
Packit d37888
	server->machine->physpage = (struct page *)
Packit d37888
		g_malloc (server->machine->bytesize);
Packit d37888
Packit d37888
	/* get the page size with "getpagesize" and
Packit d37888
	 * calculate pageshift from it */
Packit d37888
Packit d37888
	pagesize = getpagesize();
Packit d37888
Packit d37888
	server->machine->pageshift = 0;
Packit d37888
Packit d37888
	while (pagesize > 1) {
Packit d37888
		server->machine->pageshift++;
Packit d37888
		pagesize >>= 1;
Packit d37888
	}
Packit d37888
Packit d37888
	/* we only need the amount of log(2)1024 for our conversion */
Packit d37888
Packit d37888
	server->machine->pageshift -= LOG1024;
Packit d37888
Packit d37888
	/* Drop priviledges. */
Packit d37888
Packit d37888
	if (setreuid (server->machine->euid, server->machine->uid))
Packit d37888
		_exit (1);
Packit d37888
Packit d37888
	if (setregid (server->machine->egid, server->machine->gid))
Packit d37888
		_exit (1);
Packit d37888
Packit d37888
	/* !!! END OF SUID ROOT PART !!! */
Packit d37888
Packit d37888
	/* Our effective uid is now those of the user invoking the server,
Packit d37888
	 * so we do no longer have any priviledges. */
Packit d37888
Packit d37888
	/* NOTE: On SunOS, we do not need to be suid root, we just need to
Packit d37888
	 * be sgid kmem.
Packit d37888
	 *
Packit d37888
	 * The server will only use setegid() to get back it's priviledges,
Packit d37888
	 * so it will fail if it is suid root and not sgid kmem. */
Packit d37888
}
Packit d37888
Packit d37888
/* Used internally. Returns number of symbols that cannot be found in
Packit d37888
 * the nlist. */
Packit d37888
Packit d37888
int
Packit d37888
_glibtop_check_nlist (void *server, register struct nlist *nlst)
Packit d37888
{
Packit d37888
	register int not_found;
Packit d37888
Packit d37888
	/* check to see if we got ALL the symbols we requested */
Packit d37888
	/* this will write one line to stderr for every symbol not found */
Packit d37888
Packit d37888
	not_found = 0;
Packit d37888
Packit d37888
	while (nlst->n_name != NULL) {
Packit d37888
Packit d37888
#ifdef i386
Packit d37888
		if (nlst->n_value == 0) {
Packit d37888
			glibtop_error_r (server,
Packit d37888
					 "kernel: no symbol named `%s'",
Packit d37888
					 nlst->n_name);
Packit d37888
			not_found++;
Packit d37888
		}
Packit d37888
#else
Packit d37888
		if (nlst->n_type == 0) {
Packit d37888
			glibtop_error_r (server,
Packit d37888
					 "kernel: no symbol named `%s'",
Packit d37888
					 nlst->n_name);
Packit d37888
			not_found++;
Packit d37888
		}
Packit d37888
#endif
Packit d37888
Packit d37888
		nlst++;
Packit d37888
	}
Packit d37888
Packit d37888
	return not_found;
Packit d37888
}
Packit d37888
Packit d37888
/* Used internally. Fetches value from kernel. */
Packit d37888
Packit d37888
int
Packit d37888
_glibtop_getkval (void *void_server, unsigned long offset, int *ptr,
Packit d37888
		  int size, char *refstr)
Packit d37888
{
Packit d37888
	glibtop	*server = (glibtop *) void_server;
Packit d37888
Packit d37888
	if (kvm_read (server->machine->kd, offset, ptr, size) != size)
Packit d37888
		{
Packit d37888
			if (*refstr == '!') return 0;
Packit d37888
Packit d37888
			glibtop_error_r (server, "kvm_read(%s): %s",
Packit d37888
					 refstr, g_strerror (errno));
Packit d37888
		}
Packit d37888
Packit d37888
	return 1;
Packit d37888
}
Packit d37888
Packit d37888
/* Used internally. Reads process table from kernel. */
Packit d37888
Packit d37888
void
Packit d37888
_glibtop_read_proc_table (void *void_server)
Packit d37888
{
Packit d37888
	glibtop *server = (glibtop *) void_server;
Packit d37888
Packit d37888
	/* !!! THE FOLLOWING CODE RUNS SGID KMEM - CHANGE WITH CAUTION !!! */
Packit d37888
Packit d37888
	setregid (server->machine->gid, server->machine->egid);
Packit d37888
Packit d37888
	/* Read process table from kernel. */
Packit d37888
Packit d37888
	(void) _glibtop_getkval (server, server->machine->ptable_offset,
Packit d37888
				 (int *) server->machine->proc_table,
Packit d37888
				 (size_t) server->machine->ptable_size,
Packit d37888
				 _glibtop_nlist[X_PROC].n_name);
Packit d37888
Packit d37888
	if (setregid (server->machine->egid, server->machine->gid))
Packit d37888
		_exit (1);
Packit d37888
Packit d37888
	/* !!! END OF SGID KMEM PART !!! */
Packit d37888
}
Packit d37888
Packit d37888
/* Used internally. Finds pid in process table. */
Packit d37888
Packit d37888
struct proc *
Packit d37888
_glibtop_find_pid (void *void_server, pid_t pid)
Packit d37888
{
Packit d37888
	register struct proc *pp;
Packit d37888
	register int i;
Packit d37888
Packit d37888
	glibtop *server = (glibtop *) void_server;
Packit d37888
Packit d37888
	for (pp = server->machine->proc_table, i = 0;
Packit d37888
	     i < server->machine->nproc; pp++, i++) {
Packit d37888
		if ((pp->p_stat != 0) && (pp->p_pid == pid))
Packit d37888
			return pp;
Packit d37888
	}
Packit d37888
Packit d37888
	return NULL;
Packit d37888
}