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

# User Rev Content
1 tdb 1.23 /*
2 tdb 1.5 * i-scream central monitoring system
3 tdb 1.6 * http://www.i-scream.org
4 tdb 1.23 * Copyright (C) 2000-2004 i-scream
5 tdb 1.5 *
6 tdb 1.23 * 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 tdb 1.5 *
11 tdb 1.23 * This library is distributed in the hope that it will be useful,
12 tdb 1.5 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 tdb 1.23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14     * Lesser General Public License for more details.
15 tdb 1.5 *
16 tdb 1.23 * 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 tdb 1.24 *
21 tdb 1.34 * $Id: tools.c,v 1.33 2004/03/20 21:28:10 tdb Exp $
22 tdb 1.5 */
23    
24     #ifdef HAVE_CONFIG_H
25     #include "config.h"
26     #endif
27    
28 pajs 1.1 #include <stdio.h>
29     #include <string.h>
30 pajs 1.3 #include <stdlib.h>
31 ats 1.18 #include <unistd.h>
32 pajs 1.3 #include <sys/types.h>
33     #include <regex.h>
34 ats 1.9 #ifdef ALLBSD
35 ats 1.8 #include <fcntl.h>
36 tdb 1.29 #endif
37 tdb 1.34 #if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
38 ats 1.8 #include <kvm.h>
39     #endif
40 ats 1.28 #if defined(NETBSD) || defined(OPENBSD)
41 ats 1.9 #include <uvm/uvm_extern.h>
42 ats 1.28 #include <sys/param.h>
43     #include <sys/sysctl.h>
44 ats 1.9 #endif
45 pajs 1.1
46 ats 1.7 #include "tools.h"
47    
48 pajs 1.14 #ifdef SOLARIS
49 pajs 1.27 #ifdef HAVE_LIBDEVINFO_H
50 pajs 1.14 #include <libdevinfo.h>
51 pajs 1.27 #endif
52 pajs 1.14 #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 pajs 1.26 #if defined(SOLARIS) && defined(HAVE_LIBDEVINFO_H)
64 pajs 1.14 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 pajs 1.26 #endif
74 pajs 1.14
75 pajs 1.26 #ifdef SOLARIS
76 pajs 1.14 char *get_svr_from_bsd(char *bsd){
77 pajs 1.26 #ifdef HAVE_LIBDEVINFO_H
78 pajs 1.14 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 pajs 1.26 #endif
82 pajs 1.14 return bsd;
83     }
84 pajs 1.26 #endif
85 pajs 1.14
86 pajs 1.26 #if defined(SOLARIS) && defined(HAVE_LIBDEVINFO_H)
87 pajs 1.14 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 tdb 1.15 struct dirent *dp;
125     struct stat stbuf;
126 pajs 1.14 char *svr_name;
127 tdb 1.15 char current_dir[MAXPATHLEN];
128     char file_name[MAXPATHLEN];
129     char temp_name[MAXPATHLEN];
130     char dir_dname[MAXPATHLEN];
131 pajs 1.14 char *dsk_dir;
132     int x;
133    
134     dsk_dir = "/dev/osa/dev/dsk";
135 tdb 1.15 strncpy(current_dir, dsk_dir, sizeof current_dir);
136     if ((dirp = opendir(current_dir)) == NULL){
137 pajs 1.14 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 tdb 1.15 while ((dp = readdir(dirp)) != NULL){
145 pajs 1.14 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 tdb 1.16 closedir(dirp);
160 pajs 1.14 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 pajs 1.17 return 1;
177 pajs 1.14 }
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 pajs 1.17 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 pajs 1.14 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 tdb 1.15 }
200 pajs 1.14 di_fini(root_node);
201 pajs 1.17 return 0;
202 pajs 1.14 }
203    
204 pajs 1.22
205     #define BIG_ENOUGH 512
206 pajs 1.17 int build_mapping(){
207 pajs 1.22 char device_name[BIG_ENOUGH];
208 pajs 1.14 int x;
209 tdb 1.15 kstat_ctl_t *kc;
210     kstat_t *ksp;
211     kstat_io_t kios;
212 pajs 1.14
213 pajs 1.22 char driver_list[BIG_ENOUGH][BIG_ENOUGH];
214     int list_entries = 0;
215     int found;
216    
217 pajs 1.14 if ((kc = kstat_open()) == NULL) {
218 tdb 1.16 return;
219 tdb 1.15 }
220 pajs 1.14
221 tdb 1.15 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 pajs 1.14 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 pajs 1.22
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 pajs 1.17 }
255 tdb 1.15 }
256 pajs 1.14 }
257 tdb 1.15
258 pajs 1.17 return 0;
259 pajs 1.14 }
260    
261     #endif
262    
263    
264    
265 pajs 1.1 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 pajs 1.2 while((fgets(line, sizeof(line), f))!=NULL){
270 pajs 1.1 if(strncmp(string, line, strlen(string))==0){
271     return line;
272     }
273     }
274    
275     return NULL;
276 pajs 1.3 }
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 ats 1.7
288 pajs 1.14
289    
290 ats 1.13 #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 pajs 1.19 #ifndef HAVE_STRLCPY
311 ats 1.21 /* $OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $ */
312 pajs 1.19
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 pajs 1.3 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 ats 1.8 }
422    
423 tdb 1.34 #if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
424 ats 1.8 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 pajs 1.1 }
434 tdb 1.34
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 pajs 1.4 #endif
447 ats 1.9
448 ats 1.28 #if defined(NETBSD) || defined(OPENBSD)
449 ats 1.9 struct uvmexp *get_uvmexp() {
450 ats 1.28 int mib[2];
451     size_t size;
452     static struct uvmexp *uvm = NULL;
453 ats 1.9
454 ats 1.28 mib[0] = CTL_VM;
455     mib[1] = VM_UVMEXP;
456    
457     if (sysctl(mib, 2, NULL, &size, NULL, 0) < 0) {
458 ats 1.9 return NULL;
459     }
460    
461 ats 1.28 uvm = realloc(uvm, size);
462     if (uvm == NULL) {
463     return NULL;
464 ats 1.9 }
465    
466 ats 1.28 if (sysctl(mib, 2, uvm, &size, NULL, 0) < 0) {
467 ats 1.9 return NULL;
468     }
469 ats 1.28
470     return uvm;
471 ats 1.9 }
472     #endif
473    
474 pajs 1.10 int statgrab_init(){
475 tdb 1.33 #if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
476 pajs 1.11 {
477     kvm_t *kvmd = get_kvm();
478 tdb 1.15 if (kvmd == NULL) return 1;
479 tdb 1.34 }
480     {
481     kvm_t *kvmd2 = get_kvm2();
482     if (kvmd2 == NULL) return 1;
483 ats 1.32 }
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 pajs 1.11 }
494 pajs 1.14 #endif
495     #ifdef SOLARIS
496 pajs 1.20 /* 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 pajs 1.26 #ifdef HAVE_LIBDEVINFO_H
501 pajs 1.20 build_mapping();
502 pajs 1.25 #endif
503 pajs 1.10 #endif
504     return 0;
505     }
506 ats 1.18
507     int statgrab_drop_privileges() {
508     if (setegid(getgid()) != 0) return -1;
509     if (seteuid(getuid()) != 0) return -1;
510     return 0;
511     }
512