summaryrefslogtreecommitdiff
path: root/sysdeps/sun4/open.c
blob: 94cc5a449f512fca26e93d3877e924d2f4111724 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/* $Id$ */

/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
   This file is part of the Gnome Top Library.
   Contributed by Martin Baulig <martin@home-of-linux.org>, April 1998.

   The Gnome Top Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   The Gnome Top Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with the GNU C Library; see the file COPYING.LIB.  If not,
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */

#include <glibtop.h>
#include <glibtop/open.h>

struct nlist _glibtop_nlist[] = {
#ifdef i386
    { "avenrun" },		/* 0 */
    { "ccpu" },			/* 1 */
    { "mpid" },			/* 2 */
    { "nproc" },		/* 3 */
    { "proc" },			/* 4 */
    { "total" },		/* 5 */
    { "cp_time" },		/* 6 */
    { "pages" },		/* 7 */
    { "epages" },		/* 8 */
#else
    { "_avenrun" },		/* 0 */
    { "_ccpu" },		/* 1 */
    { "_mpid" },		/* 2 */
    { "_nproc" },		/* 3 */
    { "_proc" },		/* 4 */
    { "_total" },		/* 5 */
    { "_cp_time" },		/* 6 */
    { "_pages" },		/* 7 */
    { "_epages" },		/* 8 */
#ifdef MULTIPROCESSOR
    { "_ncpu" },
    { "_mp_time" },
#endif
#endif
    { 0 }
};

/* Opens pipe to gtop server. Returns 0 on success and -1 on error. */

/* !!! THIS FUNCTION RUNS SUID ROOT - CHANGE WITH CAUTION !!! */

void
glibtop_open (glibtop *server, const char *program_name)
{
	/* !!! WE ARE ROOT HERE - CHANGE WITH CAUTION !!! */

	memset (server, 0, sizeof (glibtop));
	server->name = program_name;

	server->machine.uid = getuid ();
	server->machine.euid = geteuid ();
	server->machine.gid = getgid ();
	server->machine.egid = getegid ();

	/* initialize the kernel interface */

	server->machine.kd = kvm_open (NULL, NULL, NULL, O_RDONLY, "libgtop");
	
	if (server->machine.kd == NULL)
		glibtop_error__r (server, "kvm_open: %s", strerror (errno));
	
	/* get the list of symbols we want to access in the kernel */
	
	server->machine.nlist_count = kvm_nlist (server->machine.kd, _glibtop_nlist);
	
	if (server->machine.nlist_count < 0)
		glibtop_error__r (server, "nlist: %s", strerror (errno));

#ifdef MULTIPROCESSOR
	/* were ncpu and xp_time not found in the nlist? */
	
	if ((server->machine.nlist_count > 0) && (_glibtop_nlist[X_NCPU].n_type == 0) &&
	    (_glibtop_nlist[X_MP_TIME].n_type == 0)) {
		/* we were compiled on an MP system but we are not running on one */
		/* so we will pretend this didn't happen and set ncpu = 1 */
		server->machine.nlist_count -= 2;
		server->machine.ncpu = 1;
	}
#endif

#ifdef solbourne
	{
		unsigned int status, type;
		
		/* Get the number of CPUs on this system.  */
		syscall(SYS_getcpustatus, &status, &server->machine.ncpu, &type);
	}
#endif

	/* Make sure all of the symbols were found. */

	if ((server->machine.nlist_count > 0) &&
	    (_glibtop_check_nlist (server, _glibtop_nlist) > 0))
		_exit (1);
	
	/* Drop priviledges. */	
	
	if (setreuid (server->machine.euid, server->machine.uid))
		_exit (1);
	
	if (setregid (server->machine.egid, server->machine.gid))
		_exit (1);
	
	/* !!! END OF SUID ROOT PART !!! */
		
	/* Our effective uid is now those of the user invoking the server,
	   so we do no longer have any priviledges.
	 */

	/* NOTE: On SunOS, we do not need to be suid root, we just need to be sgid kmem.
	 *       The server will only use setegid() to get back it's priviledges, so it
	 *       will fail if it is suid root and not sgid kmem.
	 */
}

/* Used internally. Returns number of symbols that cannot be found in the nlist. */

int
_glibtop_check_nlist (void *server, register struct nlist *nlst)
{
	register int not_found;
	
	/* check to see if we got ALL the symbols we requested */
	/* this will write one line to stderr for every symbol not found */
	
	not_found = 0;
	
	while (nlst->n_name != NULL) {

#ifdef i386
		if (nlst->n_value == 0) {
			glibtop_error__r (server, "kernel: no symbol named `%s'", nlst->n_name);
			not_found++;
		}
#else
		if (nlst->n_type == 0) {
			glibtop_error__r (server, "kernel: no symbol named `%s'", nlst->n_name);
			not_found++;
		}
#endif

		nlst++;
	}
	
	return not_found;
}

/* Used internally. Fetches value from kernel. */

int
_glibtop_getkval (void *void_server, unsigned long offset, int *ptr, int size, char *refstr)
{
	glibtop	*server = (glibtop *) void_server;

	if (kvm_read (server->machine.kd, offset, ptr, size) != size)
		{
			if (*refstr == '!') return 0;

			glibtop_error__r (server, "kvm_read(%s): %s",
					  refstr, strerror (errno));
		}

	return 1;
}