Blame sysdeps/sun4/open.c

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