ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/tools.c
Revision: 1.34
Committed: Sun Apr 4 22:09:32 2004 UTC (20 years, 1 month ago) by tdb
Content type: text/plain
Branch: MAIN
Changes since 1.33: +19 -3 lines
Log Message:
Add an get_kvm2 function to open kvm with slightly different args. This
set of args doesn't seem to need elevated privileges, but in my last test
wouldn't perform the functions required in swap_stats.

File Contents

# Content
1 /*
2 * i-scream central monitoring system
3 * http://www.i-scream.org
4 * Copyright (C) 2000-2004 i-scream
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 * 02111-1307 USA
20 *
21 * $Id: tools.c,v 1.33 2004/03/20 21:28:10 tdb Exp $
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <sys/types.h>
33 #include <regex.h>
34 #ifdef ALLBSD
35 #include <fcntl.h>
36 #endif
37 #if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
38 #include <kvm.h>
39 #endif
40 #if defined(NETBSD) || defined(OPENBSD)
41 #include <uvm/uvm_extern.h>
42 #include <sys/param.h>
43 #include <sys/sysctl.h>
44 #endif
45
46 #include "tools.h"
47
48 #ifdef SOLARIS
49 #ifdef HAVE_LIBDEVINFO_H
50 #include <libdevinfo.h>
51 #endif
52 #include <kstat.h>
53 #include <unistd.h>
54 #include <ctype.h>
55 #include <sys/types.h>
56 #include <sys/dkio.h>
57 #include <sys/stat.h>
58 #include <fcntl.h>
59 #include <sys/fcntl.h>
60 #include <dirent.h>
61 #endif
62
63 #if defined(SOLARIS) && defined(HAVE_LIBDEVINFO_H)
64 struct map{
65 char *bsd;
66 char *svr;
67
68 struct map *next;
69 };
70 typedef struct map mapping_t;
71
72 static mapping_t *mapping = NULL;
73 #endif
74
75 #ifdef SOLARIS
76 char *get_svr_from_bsd(char *bsd){
77 #ifdef HAVE_LIBDEVINFO_H
78 mapping_t *map_ptr;
79 for(map_ptr = mapping; map_ptr != NULL; map_ptr = map_ptr->next)
80 if(!strcmp(map_ptr->bsd, bsd)) return map_ptr->svr;
81 #endif
82 return bsd;
83 }
84 #endif
85
86 #if defined(SOLARIS) && defined(HAVE_LIBDEVINFO_H)
87 void add_mapping(char *bsd, char *svr){
88 mapping_t *map_ptr;
89 mapping_t *map_end_ptr;
90
91 bsd = strdup(bsd);
92 svr = strdup(svr);
93
94 if (mapping == NULL){
95 mapping = malloc(sizeof(mapping_t));
96 if (mapping == NULL) return;
97 map_ptr = mapping;
98 }else{
99 /* See if its already been added */
100 for(map_ptr = mapping; map_ptr != NULL; map_ptr = map_ptr->next){
101 if( (!strcmp(map_ptr->bsd, bsd)) || (!strcmp(map_ptr->svr, svr)) ){
102 return;
103 }
104 map_end_ptr = map_ptr;
105 }
106
107 /* We've reached end of list and not found the entry.. So we need to malloc
108 * new mapping_t
109 */
110 map_end_ptr->next = malloc(sizeof(mapping_t));
111 if (map_end_ptr->next == NULL) return;
112 map_ptr = map_end_ptr->next;
113 }
114
115 map_ptr->next = NULL;
116 map_ptr->bsd = bsd;
117 map_ptr->svr = svr;
118
119 return;
120 }
121
122 char *read_dir(char *disk_path){
123 DIR *dirp;
124 struct dirent *dp;
125 struct stat stbuf;
126 char *svr_name;
127 char current_dir[MAXPATHLEN];
128 char file_name[MAXPATHLEN];
129 char temp_name[MAXPATHLEN];
130 char dir_dname[MAXPATHLEN];
131 char *dsk_dir;
132 int x;
133
134 dsk_dir = "/dev/osa/dev/dsk";
135 strncpy(current_dir, dsk_dir, sizeof current_dir);
136 if ((dirp = opendir(current_dir)) == NULL){
137 dsk_dir = "/dev/dsk";
138 snprintf(current_dir, sizeof current_dir, "%s", dsk_dir);
139 if ((dirp = opendir(current_dir)) == NULL){
140 return NULL;
141 }
142 }
143
144 while ((dp = readdir(dirp)) != NULL){
145 snprintf(temp_name, sizeof temp_name, "../..%s", disk_path);
146 snprintf(dir_dname, sizeof dir_dname, "%s/%s", dsk_dir, dp->d_name);
147 stat(dir_dname,&stbuf);
148
149 if (S_ISBLK(stbuf.st_mode)){
150 x = readlink(dir_dname, file_name, sizeof(file_name));
151 file_name[x] = '\0';
152 if (strcmp(file_name, temp_name) == 0) {
153 svr_name = strdup(dp->d_name);
154 closedir(dirp);
155 return svr_name;
156 }
157 }
158 }
159 closedir(dirp);
160 return NULL;
161 }
162
163
164
165 int get_alias(char *alias){
166 char file[MAXPATHLEN];
167 di_node_t root_node;
168 di_node_t node;
169 di_minor_t minor = DI_MINOR_NIL;
170 char tmpnode[MAXPATHLEN];
171 char *phys_path;
172 char *minor_name;
173 char *value;
174 int instance;
175 if ((root_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
176 return 1;
177 }
178 node = di_drv_first_node(alias, root_node);
179 while (node != DI_NODE_NIL) {
180 if ((minor = di_minor_next(node, DI_MINOR_NIL)) != DI_MINOR_NIL) {
181 instance = di_instance(node);
182 phys_path = di_devfs_path(node);
183 minor_name = di_minor_name(minor);
184 strcpy(tmpnode, alias);
185 sprintf(tmpnode, "%s%d", tmpnode, instance);
186 strlcpy(file, "/devices", sizeof file);
187 strlcat(file, phys_path, sizeof file);
188 strlcat(file, ":", sizeof file);
189 strlcat(file, minor_name, sizeof file);
190 value = read_dir(file);
191 if (value != NULL){
192 add_mapping(tmpnode, value);
193 }
194 di_devfs_path_free(phys_path);
195 node = di_drv_next_node(node);
196 }else{
197 node = di_drv_next_node(node);
198 }
199 }
200 di_fini(root_node);
201 return 0;
202 }
203
204
205 #define BIG_ENOUGH 512
206 int build_mapping(){
207 char device_name[BIG_ENOUGH];
208 int x;
209 kstat_ctl_t *kc;
210 kstat_t *ksp;
211 kstat_io_t kios;
212
213 char driver_list[BIG_ENOUGH][BIG_ENOUGH];
214 int list_entries = 0;
215 int found;
216
217 if ((kc = kstat_open()) == NULL) {
218 return;
219 }
220
221 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
222 if (!strcmp(ksp->ks_class, "disk")) {
223 if(ksp->ks_type != KSTAT_TYPE_IO) continue;
224 /* We dont want metadevices appearing as num_diskio */
225 if(strcmp(ksp->ks_module, "md")==0) continue;
226 if((kstat_read(kc, ksp, &kios))==-1) continue;
227 strncpy(device_name, ksp->ks_name, sizeof device_name);
228 for(x=0;x<(sizeof device_name);x++){
229 if( isdigit((int)device_name[x]) ) break;
230 }
231 if(x == sizeof device_name) x--;
232 device_name[x] = '\0';
233
234 /* Check if we've not already looked it up */
235 found = 0;
236 for(x=0;x<list_entries;x++){
237 if (x>=BIG_ENOUGH){
238 /* We've got bigger than we thought was massive */
239 /* If we hit this.. Make big enough bigger */
240 return 1;
241 }
242 if( !strncmp(driver_list[x], device_name, BIG_ENOUGH)){
243 found = 1;
244 break;
245 }
246 }
247
248 if(!found){
249 if((get_alias(device_name)) != 0){
250 return 1;
251 }
252 strncpy(driver_list[x], device_name, BIG_ENOUGH);
253 list_entries++;
254 }
255 }
256 }
257
258 return 0;
259 }
260
261 #endif
262
263
264
265 char *f_read_line(FILE *f, const char *string){
266 /* Max line length. 8k should be more than enough */
267 static char line[8192];
268
269 while((fgets(line, sizeof(line), f))!=NULL){
270 if(strncmp(string, line, strlen(string))==0){
271 return line;
272 }
273 }
274
275 return NULL;
276 }
277
278 char *get_string_match(char *line, regmatch_t *match){
279 int len=match->rm_eo - match->rm_so;
280 char *match_string=malloc(len+1);
281
282 match_string=strncpy(match_string, line+match->rm_so, len);
283 match_string[len]='\0';
284
285 return match_string;
286 }
287
288
289
290 #ifndef HAVE_ATOLL
291 static long long atoll(const char *s) {
292 long long value = 0;
293 int isneg = 0;
294
295 while (*s == ' ' || *s == '\t') {
296 s++;
297 }
298 if (*s == '-') {
299 isneg = 1;
300 s++;
301 }
302 while (*s >= '0' && *s <= '9') {
303 value = (10 * value) + (*s - '0');
304 s++;
305 }
306 return (isneg ? -value : value);
307 }
308 #endif
309
310 #ifndef HAVE_STRLCPY
311 /* $OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $ */
312
313 /*
314 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
315 *
316 * Permission to use, copy, modify, and distribute this software for any
317 * purpose with or without fee is hereby granted, provided that the above
318 * copyright notice and this permission notice appear in all copies.
319 *
320 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
321 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
322 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
323 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
324 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
325 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
326 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
327 */
328
329 /*
330 * Copy src to string dst of size siz. At most siz-1 characters
331 * will be copied. Always NUL terminates (unless siz == 0).
332 * Returns strlen(src); if retval >= siz, truncation occurred.
333 */
334 size_t strlcpy(char *dst, const char *src, size_t siz){
335 register char *d = dst;
336 register const char *s = src;
337 register size_t n = siz;
338
339 /* Copy as many bytes as will fit */
340 if (n != 0 && --n != 0) {
341 do {
342 if ((*d++ = *s++) == 0)
343 break;
344 } while (--n != 0);
345 }
346
347 /* Not enough room in dst, add NUL and traverse rest of src */
348 if (n == 0) {
349 if (siz != 0)
350 *d = '\0'; /* NUL-terminate dst */
351 while (*s++)
352 ;
353 }
354
355 return(s - src - 1); /* count does not include NUL */
356 }
357 #endif
358
359 #ifndef HAVE_STRLCAT
360 /* $OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $ */
361
362 /*
363 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
364 *
365 * Permission to use, copy, modify, and distribute this software for any
366 * purpose with or without fee is hereby granted, provided that the above
367 * copyright notice and this permission notice appear in all copies.
368 *
369 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
370 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
371 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
372 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
373 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
374 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
375 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
376 */
377
378 /*
379 * Appends src to string dst of size siz (unlike strncat, siz is the
380 * full size of dst, not space left). At most siz-1 characters
381 * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
382 * Returns strlen(src) + MIN(siz, strlen(initial dst)).
383 * If retval >= siz, truncation occurred.
384 */
385 size_t strlcat(char *dst, const char *src, size_t siz){
386 register char *d = dst;
387 register const char *s = src;
388 register size_t n = siz;
389 size_t dlen;
390
391 /* Find the end of dst and adjust bytes left but don't go past end */
392 while (n-- != 0 && *d != '\0')
393 d++;
394 dlen = d - dst;
395 n = siz - dlen;
396
397 if (n == 0)
398 return(dlen + strlen(s));
399 while (*s != '\0') {
400 if (n != 1) {
401 *d++ = *s;
402 n--;
403 }
404 s++;
405 }
406 *d = '\0';
407
408 return(dlen + (s - src)); /* count does not include NUL */
409 }
410
411 #endif
412
413 long long get_ll_match(char *line, regmatch_t *match){
414 char *ptr;
415 long long num;
416
417 ptr=line+match->rm_so;
418 num=atoll(ptr);
419
420 return num;
421 }
422
423 #if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
424 kvm_t *get_kvm() {
425 static kvm_t *kvmd = NULL;
426
427 if (kvmd != NULL) {
428 return kvmd;
429 }
430
431 kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, NULL);
432 return kvmd;
433 }
434
435 /* Can't think of a better name for this function */
436 kvm_t *get_kvm2() {
437 static kvm_t *kvmd2 = NULL;
438
439 if (kvmd2 != NULL) {
440 return kvmd2;
441 }
442
443 kvmd2 = kvm_openfiles(_PATH_DEVNULL, _PATH_DEVNULL, NULL, O_RDONLY, NULL);
444 return kvmd2;
445 }
446 #endif
447
448 #if defined(NETBSD) || defined(OPENBSD)
449 struct uvmexp *get_uvmexp() {
450 int mib[2];
451 size_t size;
452 static struct uvmexp *uvm = NULL;
453
454 mib[0] = CTL_VM;
455 mib[1] = VM_UVMEXP;
456
457 if (sysctl(mib, 2, NULL, &size, NULL, 0) < 0) {
458 return NULL;
459 }
460
461 uvm = realloc(uvm, size);
462 if (uvm == NULL) {
463 return NULL;
464 }
465
466 if (sysctl(mib, 2, uvm, &size, NULL, 0) < 0) {
467 return NULL;
468 }
469
470 return uvm;
471 }
472 #endif
473
474 int statgrab_init(){
475 #if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
476 {
477 kvm_t *kvmd = get_kvm();
478 if (kvmd == NULL) return 1;
479 }
480 {
481 kvm_t *kvmd2 = get_kvm2();
482 if (kvmd2 == NULL) return 1;
483 }
484 #endif
485 #if defined(NETBSD) || defined(OPENBSD)
486 {
487 /* This should always succeed, but it seems that on some
488 * versions of NetBSD the first call to get_uvmexp will return
489 * a non-filled-in structure; this is a workaround for that.
490 */
491 struct uvmexp *uvm = get_uvmexp();
492 if (uvm == NULL) return 1;
493 }
494 #endif
495 #ifdef SOLARIS
496 /* On solaris 7, this will fail if you are not root. But, everything
497 * will still work, just no disk mappings. So we will ignore the exit
498 * status of this, and carry on merrily.
499 */
500 #ifdef HAVE_LIBDEVINFO_H
501 build_mapping();
502 #endif
503 #endif
504 return 0;
505 }
506
507 int statgrab_drop_privileges() {
508 if (setegid(getgid()) != 0) return -1;
509 if (seteuid(getuid()) != 0) return -1;
510 return 0;
511 }
512