components/net-snmp-57/sun/agent/modules/healthMonitor/dsr.c
changeset 5867 445e2cf1c845
parent 252 ee0fb1eabcbf
equal deleted inserted replaced
5866:683c5c035a79 5867:445e2cf1c845
       
     1 /*
       
     2 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
       
     3 *
       
     4 * U.S. Government Rights - Commercial software. Government users are subject
       
     5 * to the Sun Microsystems, Inc. standard license agreement and applicable
       
     6 * provisions of the FAR and its supplements.
       
     7 *
       
     8 *
       
     9 * This distribution may include materials developed by third parties. Sun,
       
    10 * Sun Microsystems, the Sun logo and Solaris are trademarks or registered
       
    11 * trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
       
    12 *
       
    13 */
       
    14 
       
    15 
       
    16 #include <stdio.h>
       
    17 #include <stdlib.h>
       
    18 #include <unistd.h>
       
    19 #include <dirent.h>
       
    20 #include <sys/types.h>
       
    21 #include <sys/stat.h>
       
    22 #include <limits.h>
       
    23 #include <string.h>
       
    24 #include <ctype.h>
       
    25 #include <fcntl.h>
       
    26 #include <sys/mnttab.h>
       
    27 #include <sys/systeminfo.h>
       
    28 #include <sys/dklabel.h>
       
    29 #include <sys/dkio.h>
       
    30 
       
    31 typedef struct nms {
       
    32 	char	*dsk;
       
    33 	int	dnum;
       
    34 	char	*dty;
       
    35 	char	*real;
       
    36 	int	devtype;
       
    37 	struct nms *next;
       
    38 } nms_t;
       
    39 
       
    40 typedef struct list_of_disks {
       
    41 	char	*dtype;
       
    42 	int	dnum;
       
    43 	char	*dsk;
       
    44 	char	*dpart[NDKMAP];
       
    45 	struct list_of_disks *next;
       
    46 } disk_list_t;
       
    47 
       
    48 static nms_t *rummage_dev_dsk(void);
       
    49 static void	do_snm(char *, char *);
       
    50 static int	look_up_name(const char *, nms_t *);
       
    51 static void	make_an_entry(char *, const char *, nms_t **, int);
       
    52 static char	*trim(char *);
       
    53 static void	rummage_path_to_inst(nms_t *);
       
    54 static nms_t	*find_str(const char *, nms_t *);
       
    55 static int	pline(char *, nms_t *);
       
    56 static void	insert_dlist_ent(const char *, const int, const char *,
       
    57 			int, disk_list_t **);
       
    58 static void	mk_list_of_disks(nms_t *, disk_list_t **);
       
    59 static int	str_is_digit(char *);
       
    60 
       
    61 extern void	*build_disk_list(void *);
       
    62 extern char	*lookup_ks_name(char *, void *);
       
    63 
       
    64 #define	DISK		0
       
    65 #define	TAPE		1
       
    66 
       
    67 #define	MAX_TYPES	2
       
    68 
       
    69 
       
    70 /*
       
    71  * Build a list of disks attached to the system. if a previous list is passed
       
    72  * in, delete that list before building the new list.
       
    73  */
       
    74 
       
    75 void *
       
    76 build_disk_list(void *v)
       
    77 {
       
    78 	nms_t	*list;
       
    79 	nms_t	*t;
       
    80 	disk_list_t *rv=NULL;
       
    81 	disk_list_t *p;
       
    82 	int	i;
       
    83 
       
    84 	p = (disk_list_t *)v;
       
    85 	if (p != (disk_list_t *)NULL) {
       
    86 		disk_list_t *t;
       
    87 		while (p) {
       
    88 			(void) free(p->dtype);
       
    89 			(void) free(p->dsk);
       
    90 			for (i = 0; i < NDKMAP; i++)
       
    91 				(void) free(p->dpart[i]);
       
    92 			t = p;
       
    93 			p = p->next;
       
    94 			(void) free(t);
       
    95 		}
       
    96 	}
       
    97 	/*
       
    98 	 * Build the list of devices connected to the system.
       
    99 	 */
       
   100 	list = rummage_dev_dsk();
       
   101 	rummage_path_to_inst(list);
       
   102 	mk_list_of_disks(list, &rv);
       
   103 	t = list;
       
   104 	while (t) {
       
   105 		nms_t	*f;
       
   106 		(void) free(t->real);
       
   107 		f = t;
       
   108 		t = t->next;
       
   109 		if (t != list) {
       
   110 			(void) free(f);
       
   111 		}
       
   112 	}
       
   113 	return (rv);
       
   114 }
       
   115 
       
   116 
       
   117 /*
       
   118  * Currently it isn't necessary to look below the cntndn level....
       
   119  */
       
   120 
       
   121 static nms_t *
       
   122 rummage_dev_dsk(void)
       
   123 {
       
   124 	nms_t	*list = (nms_t *)0;
       
   125 	DIR		*dskp;
       
   126 	int	i;
       
   127 
       
   128 	for (i = 0; i < MAX_TYPES; i++) {
       
   129 		switch (i) {
       
   130 
       
   131 			case DISK:
       
   132 				dskp = opendir("/dev/dsk");
       
   133 				break;
       
   134 			case TAPE:
       
   135 				dskp = opendir("/dev/rmt");
       
   136 				break;
       
   137 			default:
       
   138 				dskp = NULL;
       
   139 				break;
       
   140 		}
       
   141 
       
   142 		if (dskp != NULL) {
       
   143 			struct dirent  *bpt;
       
   144 			while ((bpt = readdir(dskp)) != NULL) {
       
   145 				struct stat	sbuf;
       
   146 				char	dnmbuf[1025];
       
   147 				char	snm[256];
       
   148 				char	lnm[256];
       
   149 				char	*npt;
       
   150 				char	nmbuf[1025];
       
   151 
       
   152 				if (bpt->d_name[0] == '.')
       
   153 					continue;
       
   154 
       
   155 				if (i == DISK) {
       
   156 					(void) strcpy(lnm, bpt->d_name);
       
   157 					do_snm(bpt->d_name, snm);
       
   158 				} else {
       
   159 					/*
       
   160 					 * don't want all rewind/etc
       
   161 					 * devices for a tape
       
   162 					 */
       
   163 					if (!str_is_digit(bpt->d_name))
       
   164 						continue;
       
   165 					(void) sprintf(snm, "rmt/%s",
       
   166 						bpt->d_name);
       
   167 					(void) sprintf(lnm, "rmt/%s",
       
   168 						bpt->d_name);
       
   169 				}
       
   170 				if (look_up_name(snm, list) != 0)
       
   171 					continue;
       
   172 
       
   173 				if (i == DISK) {
       
   174 					(void) sprintf(dnmbuf,
       
   175 						"/dev/dsk/%s", bpt->d_name);
       
   176 				} else {
       
   177 					(void) sprintf(dnmbuf,
       
   178 						"/dev/rmt/%s", bpt->d_name);
       
   179 				}
       
   180 				if (lstat(dnmbuf, &sbuf) != -1) {
       
   181 					int cnt;
       
   182 					if ((sbuf.st_mode & S_IFMT)
       
   183 								== S_IFLNK) {
       
   184 
       
   185 						nmbuf[0] = '\0';
       
   186 						if ((cnt = readlink(dnmbuf, nmbuf, sizeof (nmbuf))) != 1) {
       
   187 							nmbuf[cnt] = '\0';
       
   188 							npt = nmbuf;
       
   189 						} else
       
   190 							npt = (char *)0;
       
   191 					} else
       
   192 						npt = lnm;
       
   193 					if (npt)
       
   194 						make_an_entry(npt, snm,
       
   195 								&list, i);
       
   196 				}
       
   197 			}
       
   198 			(void) closedir(dskp);
       
   199 		}
       
   200 	}
       
   201 	return (list);
       
   202 }
       
   203 
       
   204 
       
   205 static int
       
   206 look_up_name(const char *nm, nms_t *list)
       
   207 {
       
   208 	int	rv = 0;
       
   209 
       
   210 	while (list != (nms_t *)NULL) {
       
   211 		if (strcmp(list->dsk, nm) != 0)
       
   212 			list = list->next;
       
   213 		else {
       
   214 			rv++;
       
   215 			break;
       
   216 		}
       
   217 	}
       
   218 	return (rv);
       
   219 }
       
   220 
       
   221 
       
   222 static void
       
   223 do_snm(char *orig, char *shortnm)
       
   224 {
       
   225 	while (*orig != 's' && *orig != 'p')
       
   226 		*shortnm++ = *orig++;
       
   227 	*shortnm = '\0';
       
   228 }
       
   229 
       
   230 
       
   231 static void
       
   232 make_an_entry(char *lname, const char *shortnm, nms_t **list, int devtype)
       
   233 {
       
   234 	nms_t	*entry;
       
   235 
       
   236 	entry = (nms_t *)malloc(sizeof (nms_t));
       
   237 	if (entry != (nms_t *)NULL) {
       
   238 		int	len;
       
   239 		char	*nlnm;
       
   240 
       
   241 		nlnm = trim(lname);
       
   242 		len = strlen(nlnm);
       
   243 		len++;
       
   244 		entry->real = (char *)malloc(len);
       
   245 		if (entry->real) {
       
   246 			(void) strcpy(entry->real, nlnm);
       
   247 			len = strlen(shortnm);
       
   248 			len++;
       
   249 			entry->dsk = (char *)malloc(len);
       
   250 			if (entry->dsk) {
       
   251 				(void) strcpy(entry->dsk, shortnm);
       
   252 				entry->dnum = -1;
       
   253 				entry->dty = (char *)NULL;
       
   254 				entry->next = (nms_t *)NULL;
       
   255 				entry->devtype = devtype;
       
   256 				if (*list != (nms_t *)NULL) {
       
   257 					entry->next = *list;
       
   258 					*list = entry;
       
   259 				} else
       
   260 					*list = entry;
       
   261 			} else {
       
   262 				(void) free(entry->real);
       
   263 				(void) free(entry);
       
   264 			}
       
   265 		} else
       
   266 			(void) free(entry);
       
   267 	}
       
   268 }
       
   269 
       
   270 
       
   271 static char    *
       
   272 trim(char *fnm)
       
   273 {
       
   274 	char	*ptr;
       
   275 	char	*lname = "../../devices";
       
   276 
       
   277 	while (*lname == *fnm) {
       
   278 		lname++;
       
   279 		fnm++;
       
   280 	}
       
   281 	if ((ptr = strrchr(fnm, (int)':')) != (char *)NULL)
       
   282 		*ptr = '\0';
       
   283 	return (fnm);
       
   284 }
       
   285 
       
   286 
       
   287 static void
       
   288 rummage_path_to_inst(nms_t *list)
       
   289 {
       
   290 	FILE	*inpt;
       
   291 
       
   292 	inpt = fopen("/etc/path_to_inst", "r");
       
   293 	if (inpt) {
       
   294 		char	ibuf[1024];
       
   295 
       
   296 		while (fgets(ibuf, sizeof (ibuf), inpt) != (char *)NULL) {
       
   297 			if (ibuf[0] != '#') {
       
   298 				(void) pline(ibuf, list);
       
   299 			}
       
   300 		}
       
   301 		(void) fclose(inpt);
       
   302 	}
       
   303 }
       
   304 
       
   305 
       
   306 /*
       
   307  * Process an /etc/path_to_inst line. The line is of the format:
       
   308  * "/pathname/device@unit,instance" devicenumber We want to extract the
       
   309  * devicenumber and the device from this string if it is one of the ones in
       
   310  * /dev/dsk.
       
   311  */
       
   312 
       
   313 
       
   314 static int
       
   315 pline(char *ib, nms_t *list)
       
   316 {
       
   317 	char	*rpt;
       
   318 	char	*bpt;
       
   319 	nms_t	*entry;
       
   320 	int	rv = 0;
       
   321 	int	done;
       
   322 	int	len;
       
   323 	char	*v;
       
   324 	/*
       
   325 	 * Skip over any stuff at the beginning of the line before a leading
       
   326 	 * '/' If we don't find a '/', the line is malformed and we just skip
       
   327 	 * it.
       
   328 	 */
       
   329 	while (*ib) {
       
   330 		if (*ib != '/')
       
   331 			ib++;
       
   332 		else
       
   333 			break;
       
   334 	}
       
   335 	if (!(*ib))
       
   336 		goto done;
       
   337 
       
   338 	/*
       
   339 	 * Find the trailing '"' in the line. If not found, we just
       
   340 	 * skip the line.
       
   341 	 */
       
   342 
       
   343 	rpt = strchr(ib, (int)'""');
       
   344 	if (rpt != NULL)
       
   345 		rpt = strchr(rpt, (int)'""');
       
   346 
       
   347 	/*
       
   348 	 * Find a matching entry in the list of names from /dev/dsk.
       
   349 	 * If no match, we're not interested.
       
   350 	 */
       
   351 	if (!rpt)
       
   352 		goto done;
       
   353 
       
   354 	*rpt = '\0';
       
   355 
       
   356 
       
   357 	if ((entry = find_str(ib, list)) == (nms_t *)NULL)
       
   358 		goto done;
       
   359 
       
   360 	bpt = rpt;
       
   361 	/*
       
   362 	 * Extract the device number at the end of
       
   363 	 * the line. We expect whitespace followed by
       
   364 	 * the beginning of the currently numeric
       
   365 	 * device id string;
       
   366 	 */
       
   367 	rpt++;
       
   368 	done = 0;
       
   369 	while (!done) {
       
   370 		if (*rpt) {
       
   371 			if (*rpt != '\n') {
       
   372 				if (isspace((int)*rpt))
       
   373 					rpt++;
       
   374 				else
       
   375 					done++;
       
   376 			} else
       
   377 				done++;
       
   378 		} else
       
   379 			done++;
       
   380 	}
       
   381 	/*
       
   382 	 * Should now be at the beginning of the
       
   383 	 * device number. Point entry->dn at the
       
   384 	 * string.
       
   385 	 */
       
   386 	if (*rpt) {
       
   387 		v = rpt;
       
   388 		len = 0;
       
   389 		while (v) {
       
   390 			if (*v != '\n') {
       
   391 				v++;
       
   392 				len++;
       
   393 			} else {
       
   394 				*v = '\0';
       
   395 				v = (char *)NULL;
       
   396 			}
       
   397 		}
       
   398 		if (len) {
       
   399 			entry->dnum = atoi(rpt);
       
   400 			while (bpt > ib) {
       
   401 				if (*bpt != '@')
       
   402 					bpt--;
       
   403 				else
       
   404 					break;
       
   405 			}
       
   406 			if (bpt > ib) {
       
   407 				*bpt-- = '\0';
       
   408 				len = 0;
       
   409 				while (bpt > ib) {
       
   410 					if (*bpt != '/') {
       
   411 						bpt--;
       
   412 						len++;
       
   413 					} else
       
   414 						break;
       
   415 				}
       
   416 				if (bpt > ib) {
       
   417 					bpt++;
       
   418 					len++;
       
   419 					entry->dty = (char *)malloc(len);
       
   420 					if (entry->dty) {
       
   421 						(void) strcpy(entry->dty, bpt);
       
   422 						rv++;
       
   423 					}
       
   424 				}
       
   425 			}
       
   426 		}
       
   427 	}
       
   428 done:
       
   429 	return (rv);
       
   430 }
       
   431 
       
   432 
       
   433 
       
   434 static nms_t *
       
   435 find_str(const char *inbuf, nms_t *list)
       
   436 {
       
   437 	while (list) {
       
   438 		if (strcmp(inbuf, list->real) != 0)
       
   439 			list = list->next;
       
   440 		else
       
   441 			break;
       
   442 	}
       
   443 	return (list);
       
   444 }
       
   445 
       
   446 
       
   447 
       
   448 static void
       
   449 mk_list_of_disks(nms_t *list, disk_list_t **hd)
       
   450 {
       
   451 	while (list) {
       
   452 		insert_dlist_ent(list->dsk, list->dnum, list->dty,
       
   453 					list->devtype, hd);
       
   454 		list = list->next;
       
   455 	}
       
   456 }
       
   457 
       
   458 
       
   459 
       
   460 /*
       
   461  * Determine if a name is already in the list of disks. If not, insert the
       
   462  * name in the list.
       
   463  */
       
   464 
       
   465 
       
   466 static void
       
   467 insert_dlist_ent(const char *nm, const int dn, const char *dty,
       
   468 			int devtype, disk_list_t ** hd)
       
   469 {
       
   470 	disk_list_t *stuff;
       
   471 	int	i, len;
       
   472 
       
   473 	if (dty == NULL)
       
   474 		return;
       
   475 
       
   476 	stuff = *hd;
       
   477 	while (stuff) {
       
   478 		if (strcmp(nm, stuff->dsk) != 0)
       
   479 			stuff = stuff->next;
       
   480 		else
       
   481 			break;
       
   482 	}
       
   483 	if (!stuff) {
       
   484 		disk_list_t	*entry;
       
   485 		int	mv;
       
   486 
       
   487 		entry = (disk_list_t *)malloc(
       
   488 				sizeof (disk_list_t));
       
   489 		if (entry) {
       
   490 			entry->dnum = dn;
       
   491 			entry->dsk = (char *)nm;
       
   492 			entry->dtype = (char *)dty;
       
   493 
       
   494 			len = strlen(nm) + 4;
       
   495 			for (i = 0; i < NDKMAP; i++) {
       
   496 				if (devtype == DISK) {
       
   497 					entry->dpart[i] = (char *)malloc(len);
       
   498 					if (entry->dpart[i]) {
       
   499 						(void) sprintf(entry->dpart[i],
       
   500 							"%ss%d\0", nm, i);
       
   501 					}
       
   502 				} else
       
   503 					entry->dpart[i] = NULL;
       
   504 			}
       
   505 			/*
       
   506 			 * Figure out where to insert the name. The list is
       
   507 			 * ostensibly in sorted order.
       
   508 			 */
       
   509 			if (*hd != (disk_list_t *)NULL) {
       
   510 				disk_list_t *follw;
       
   511 				stuff = *hd;
       
   512 
       
   513 				/*
       
   514 				 * Look through the list. While the strcmp
       
   515 				 * value is less than the current value,
       
   516 				 */
       
   517 				while (stuff) {
       
   518 					if ((mv = strcmp(entry->dtype,
       
   519 						stuff->dtype)) < 0) {
       
   520 							follw = stuff;
       
   521 							stuff = stuff->next;
       
   522 					} else
       
   523 						break;
       
   524 				}
       
   525 				if (mv == 0) {
       
   526 					while (stuff) {
       
   527 						if (strcmp(entry->dtype,
       
   528 							stuff->dtype) != 0)
       
   529 								break;
       
   530 						if (dn > stuff->dnum) {
       
   531 							follw = stuff;
       
   532 							stuff = stuff->next;
       
   533 						} else
       
   534 							break;
       
   535 					}
       
   536 				}
       
   537 				/*
       
   538 				 * We should now be ready to insert an
       
   539 				 * entry...
       
   540 				 */
       
   541 				if (mv >= 0) {
       
   542 					if (stuff == *hd) {
       
   543 						entry->next = stuff;
       
   544 						*hd = entry;
       
   545 					} else {
       
   546 						entry->next = follw->next;
       
   547 						follw->next = entry;
       
   548 					}
       
   549 				} else {
       
   550 					/*
       
   551 					 * insert at the end of the
       
   552 					 * list
       
   553 					 */
       
   554 					follw->next = entry;
       
   555 					entry->next = (disk_list_t *)NULL;
       
   556 				}
       
   557 			} else {
       
   558 				*hd = entry;
       
   559 				entry->next = (disk_list_t *)NULL;
       
   560 			}
       
   561 		}
       
   562 	}
       
   563 }
       
   564 
       
   565 
       
   566 
       
   567 char *
       
   568 lookup_ks_name(char *dev_nm, void *val)
       
   569 {
       
   570 	char	*rv = (char *)0;
       
   571 	int	dv;
       
   572 	char	*device;
       
   573 	int	len;
       
   574 	char	cmpbuf[1024];
       
   575 	struct	list_of_disks *list;
       
   576 	char	nmbuf[1024];
       
   577 	char	*tmpnm;
       
   578 	char	*nm;
       
   579 	int	partition;
       
   580 
       
   581 	tmpnm = nm = nmbuf;
       
   582 	while ((*dev_nm) && (*dev_nm != ',')) {
       
   583 		*tmpnm++ = *dev_nm++;
       
   584 	}
       
   585 	*tmpnm = '\0';
       
   586 
       
   587 	if (*dev_nm == ',') {
       
   588 		dev_nm++;
       
   589 		partition = (int)(*dev_nm - 'a');
       
   590 		if ((partition < 0) || (partition > NDKMAP))
       
   591 			partition = -1;
       
   592 	} else
       
   593 		partition = -1;
       
   594 
       
   595 	list = (disk_list_t *)val;
       
   596 	device = nm;
       
   597 	len = 0;
       
   598 	while (*nm) {
       
   599 		if (isalpha((int)*nm)) {
       
   600 			nm++;
       
   601 			len++;
       
   602 		} else
       
   603 			break;
       
   604 	}
       
   605 	(void) strncpy(cmpbuf, device, len);
       
   606 	cmpbuf[len] = '\0';
       
   607 
       
   608 	if (*nm) {
       
   609 		int mv;
       
   610 
       
   611 		dv = atoi(nm);
       
   612 		while (list) {
       
   613 			if ((mv = strcmp(cmpbuf, list->dtype)) < 0)
       
   614 				list = list->next;
       
   615 			else
       
   616 				break;
       
   617 		}
       
   618 		if (mv == 0) {
       
   619 			while (list) {
       
   620 				if (list->dnum < dv)
       
   621 					list = list->next;
       
   622 				else
       
   623 					break;
       
   624 			}
       
   625 			if(list) {
       
   626 				if (list->dnum == dv) {
       
   627 					if ((partition != -1) &&
       
   628 						(list->dpart[partition] != NULL))
       
   629 							rv = list->dpart[partition];
       
   630 					else
       
   631 						rv = list->dsk;
       
   632 				}
       
   633 			}
       
   634 		}
       
   635 	}
       
   636 	return (rv);
       
   637 }
       
   638 
       
   639 
       
   640 
       
   641 static int
       
   642 str_is_digit(char *str)
       
   643 {
       
   644 	int i;
       
   645 	int j = 0;
       
   646 
       
   647 	for (i = 0; i < (int)strlen(str); i++) {
       
   648 		if (isdigit(str[i])) j++;
       
   649 	}
       
   650 
       
   651 	if (j == strlen(str))
       
   652 		return (1);
       
   653 	else
       
   654 		return (0);
       
   655 }
       
   656