xref: /onnv-gate/usr/src/cmd/prtconf/prtconf.c (revision 13093:48f2dbca79a2)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
58638SVikram.Hegde@Sun.COM  * Common Development and Distribution License (the "License").
68638SVikram.Hegde@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*13093SRoger.Faulkner@Oracle.COM 
220Sstevel@tonic-gate /*
2313038Sanil.udupa@sun.com  * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
270Sstevel@tonic-gate /*	  All Rights Reserved	*/
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #include <stdio.h>
300Sstevel@tonic-gate #include <stdarg.h>
310Sstevel@tonic-gate #include <stdlib.h>
320Sstevel@tonic-gate #include <unistd.h>
330Sstevel@tonic-gate #include <strings.h>
340Sstevel@tonic-gate #include <sys/systeminfo.h>
350Sstevel@tonic-gate #include <sys/types.h>
360Sstevel@tonic-gate #include <sys/stat.h>
370Sstevel@tonic-gate #include "prtconf.h"
380Sstevel@tonic-gate 
390Sstevel@tonic-gate struct prt_opts	opts;
400Sstevel@tonic-gate struct prt_dbg	dbg;
410Sstevel@tonic-gate static char	new_path[MAXPATHLEN];
420Sstevel@tonic-gate 
430Sstevel@tonic-gate #define	INDENT_LENGTH	4
440Sstevel@tonic-gate 
450Sstevel@tonic-gate #ifdef	__x86
469074SJudy.Chen@Sun.COM static const char *usage = "%s [ -V | -x | -abcdvpPD ] [ <device_path > ]\n";
470Sstevel@tonic-gate #else
489074SJudy.Chen@Sun.COM static const char *usage =
499074SJudy.Chen@Sun.COM 	"%s [ -F | -V | -x | -abcdvpPD ][ <device_path > ]\n";
500Sstevel@tonic-gate #endif	/* __x86 */
510Sstevel@tonic-gate 
520Sstevel@tonic-gate static void
setpname(const char * name)53*13093SRoger.Faulkner@Oracle.COM setpname(const char *name)
540Sstevel@tonic-gate {
550Sstevel@tonic-gate 	char *p;
560Sstevel@tonic-gate 
570Sstevel@tonic-gate 	if (name == NULL)
580Sstevel@tonic-gate 		opts.o_progname = "prtconf";
590Sstevel@tonic-gate 	else if (p = strrchr(name, '/'))
600Sstevel@tonic-gate 		opts.o_progname = (const char *) p + 1;
610Sstevel@tonic-gate 	else
620Sstevel@tonic-gate 		opts.o_progname = name;
630Sstevel@tonic-gate }
640Sstevel@tonic-gate 
650Sstevel@tonic-gate /*PRINTFLIKE1*/
660Sstevel@tonic-gate void
dprintf(const char * fmt,...)670Sstevel@tonic-gate dprintf(const char *fmt, ...)
680Sstevel@tonic-gate {
690Sstevel@tonic-gate 	if (dbg.d_debug) {
700Sstevel@tonic-gate 		va_list ap;
710Sstevel@tonic-gate 		va_start(ap, fmt);
720Sstevel@tonic-gate 		(void) vfprintf(stderr, fmt, ap);
730Sstevel@tonic-gate 		va_end(ap);
740Sstevel@tonic-gate 	}
750Sstevel@tonic-gate }
760Sstevel@tonic-gate 
770Sstevel@tonic-gate void
indent_to_level(int ilev)780Sstevel@tonic-gate indent_to_level(int ilev)
790Sstevel@tonic-gate {
800Sstevel@tonic-gate 	(void) printf("%*s", INDENT_LENGTH * ilev, "");
810Sstevel@tonic-gate }
820Sstevel@tonic-gate 
830Sstevel@tonic-gate static void
cleanup_path(const char * input_path,char * path)840Sstevel@tonic-gate cleanup_path(const char *input_path, char *path)
850Sstevel@tonic-gate {
860Sstevel@tonic-gate 	char	*ptr, *ptr2;
870Sstevel@tonic-gate 	size_t	len;
880Sstevel@tonic-gate 
890Sstevel@tonic-gate 	if ((input_path == NULL) || (path == NULL))
900Sstevel@tonic-gate 		return;
910Sstevel@tonic-gate 
920Sstevel@tonic-gate 	(void) strcpy(path, input_path);
930Sstevel@tonic-gate 
940Sstevel@tonic-gate 	/*LINTED*/
950Sstevel@tonic-gate 	while (1) {
960Sstevel@tonic-gate 		len = strlen(path);
970Sstevel@tonic-gate 		if (len == 0)
980Sstevel@tonic-gate 			break;
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 		/* change substring "//" into "/" */
1010Sstevel@tonic-gate 		if (ptr = strstr(path, "//")) {
1020Sstevel@tonic-gate 			len = strlen(ptr + 1);
1030Sstevel@tonic-gate 			(void) memmove(ptr, ptr + 1, len + 1);
1040Sstevel@tonic-gate 			continue;
1050Sstevel@tonic-gate 		}
1060Sstevel@tonic-gate 		/* change substring "/./" into "/" */
1070Sstevel@tonic-gate 		if (ptr = strstr(path, "/./")) {
1080Sstevel@tonic-gate 			len = strlen(ptr + 2);
1090Sstevel@tonic-gate 			(void) memmove(ptr, ptr + 2, len + 1);
1100Sstevel@tonic-gate 			continue;
1110Sstevel@tonic-gate 		}
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 		/* change substring "/<foo>/../" into "/" */
1140Sstevel@tonic-gate 		if (ptr = strstr(path, "/../")) {
1150Sstevel@tonic-gate 			len = strlen(ptr + 3);
1160Sstevel@tonic-gate 			*ptr = '\0';
1170Sstevel@tonic-gate 			ptr2 = strrchr(path, (int)'/');
1180Sstevel@tonic-gate 			if (ptr2 == NULL) {
1190Sstevel@tonic-gate 				/* path had a leading "/../" */
1200Sstevel@tonic-gate 				ptr2 = path;
1210Sstevel@tonic-gate 			}
1220Sstevel@tonic-gate 			(void) memmove(ptr2, ptr + 3, len + 1);
1230Sstevel@tonic-gate 			continue;
1240Sstevel@tonic-gate 		}
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate 		/* change trailing "/<foo>/.." into "/" */
1270Sstevel@tonic-gate 		if ((len >= 3) &&
1280Sstevel@tonic-gate 		    (path[len - 3] == '/') &&
1290Sstevel@tonic-gate 		    (path[len - 2] == '.') &&
1300Sstevel@tonic-gate 		    (path[len - 1] == '.')) {
1310Sstevel@tonic-gate 			path[len - 3] = '\0';
1320Sstevel@tonic-gate 			ptr2 = strrchr(path, (int)'/');
1330Sstevel@tonic-gate 			if (ptr2 != NULL) {
1340Sstevel@tonic-gate 				ptr2[1] = '\0';
1350Sstevel@tonic-gate 			} else {
1360Sstevel@tonic-gate 				/* path was "/.." */
1370Sstevel@tonic-gate 				path[0] = '/';
1380Sstevel@tonic-gate 				path[1] = '\0';
1390Sstevel@tonic-gate 			}
1400Sstevel@tonic-gate 			continue;
1410Sstevel@tonic-gate 		}
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate 		/* change trailing "/." into "/" */
1440Sstevel@tonic-gate 		if ((len >= 2) &&
1450Sstevel@tonic-gate 		    (path[len - 2] == '/') &&
1460Sstevel@tonic-gate 		    (path[len - 1] == '.')) {
1470Sstevel@tonic-gate 			path[len - 1] = '\0';
1480Sstevel@tonic-gate 			continue;
1490Sstevel@tonic-gate 		}
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate 		/* remove trailing "/" unless it's the root */
1520Sstevel@tonic-gate 		if ((len > 1) && (path[len - 1] == '/')) {
1530Sstevel@tonic-gate 			path[len - 1] = '\0';
1540Sstevel@tonic-gate 			continue;
1550Sstevel@tonic-gate 		}
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 		break;
1580Sstevel@tonic-gate 	}
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate /*
1630Sstevel@tonic-gate  * debug version has two more flags:
1640Sstevel@tonic-gate  *	-L force load driver
1650Sstevel@tonic-gate  *	-M: print per driver list
1660Sstevel@tonic-gate  */
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate #ifdef	DEBUG
1699074SJudy.Chen@Sun.COM static const char *optstring = "abcdDvVxpPFf:M:dLuC";
1700Sstevel@tonic-gate #else
1719074SJudy.Chen@Sun.COM static const char *optstring = "abcdDvVxpPFf:uC";
1720Sstevel@tonic-gate #endif	/* DEBUG */
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate int
main(int argc,char * argv[])1750Sstevel@tonic-gate main(int argc, char *argv[])
1760Sstevel@tonic-gate {
1770Sstevel@tonic-gate 	long pagesize, npages;
1780Sstevel@tonic-gate 	int c, ret;
1790Sstevel@tonic-gate 	char hw_provider[SYS_NMLN];
1800Sstevel@tonic-gate 
181*13093SRoger.Faulkner@Oracle.COM 	setpname(argv[0]);
1820Sstevel@tonic-gate 	opts.o_promdev = "/dev/openprom";
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 	while ((c = getopt(argc, argv, optstring)) != -1)  {
1850Sstevel@tonic-gate 		switch (c)  {
1860Sstevel@tonic-gate 		case 'a':
1870Sstevel@tonic-gate 			++opts.o_ancestors;
1880Sstevel@tonic-gate 			break;
1890Sstevel@tonic-gate 		case 'b':
1900Sstevel@tonic-gate 			++opts.o_productinfo;
1910Sstevel@tonic-gate 			break;
1920Sstevel@tonic-gate 		case 'c':
1930Sstevel@tonic-gate 			++opts.o_children;
1940Sstevel@tonic-gate 			break;
1959074SJudy.Chen@Sun.COM 		case 'd':
1969074SJudy.Chen@Sun.COM 			++opts.o_pciid;
1979074SJudy.Chen@Sun.COM 			break;
1980Sstevel@tonic-gate 		case 'D':
1990Sstevel@tonic-gate 			++opts.o_drv_name;
2000Sstevel@tonic-gate 			break;
2010Sstevel@tonic-gate 		case 'v':
2020Sstevel@tonic-gate 			++opts.o_verbose;
2030Sstevel@tonic-gate 			break;
2040Sstevel@tonic-gate 		case 'p':
2050Sstevel@tonic-gate 			++opts.o_prominfo;
2060Sstevel@tonic-gate 			break;
2070Sstevel@tonic-gate 		case 'f':
2080Sstevel@tonic-gate 			opts.o_promdev = optarg;
2090Sstevel@tonic-gate 			break;
2100Sstevel@tonic-gate 		case 'V':
2110Sstevel@tonic-gate 			++opts.o_promversion;
2120Sstevel@tonic-gate 			break;
2130Sstevel@tonic-gate 		case 'x':
2140Sstevel@tonic-gate 			++opts.o_prom_ready64;
2150Sstevel@tonic-gate 			break;
2160Sstevel@tonic-gate 		case 'F':
2170Sstevel@tonic-gate 			++opts.o_fbname;
2180Sstevel@tonic-gate 			++opts.o_noheader;
2190Sstevel@tonic-gate 			break;
2200Sstevel@tonic-gate 		case 'P':
2210Sstevel@tonic-gate 			++opts.o_pseudodevs;
2220Sstevel@tonic-gate 			break;
2230Sstevel@tonic-gate 		case 'C':
2240Sstevel@tonic-gate 			++opts.o_forcecache;
2250Sstevel@tonic-gate 			break;
2260Sstevel@tonic-gate #ifdef	DEBUG
2270Sstevel@tonic-gate 		case 'M':
2280Sstevel@tonic-gate 			dbg.d_drivername = optarg;
2290Sstevel@tonic-gate 			++dbg.d_bydriver;
2300Sstevel@tonic-gate 			break;
2310Sstevel@tonic-gate 		case 'L':
2320Sstevel@tonic-gate 			++dbg.d_forceload;
2330Sstevel@tonic-gate 			break;
2340Sstevel@tonic-gate #endif	/* DEBUG */
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate 		default:
2370Sstevel@tonic-gate 			(void) fprintf(stderr, usage, opts.o_progname);
2380Sstevel@tonic-gate 			return (1);
2390Sstevel@tonic-gate 		}
2400Sstevel@tonic-gate 	}
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 	(void) uname(&opts.o_uts);
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 	if (opts.o_fbname)
2450Sstevel@tonic-gate 		return (do_fbname());
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 	if (opts.o_promversion)
2480Sstevel@tonic-gate 		return (do_promversion());
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 	if (opts.o_prom_ready64)
2510Sstevel@tonic-gate 		return (do_prom_version64());
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 	if (opts.o_productinfo)
2540Sstevel@tonic-gate 		return (do_productinfo());
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate 	opts.o_devices_path = NULL;
2570Sstevel@tonic-gate 	opts.o_devt = DDI_DEV_T_NONE;
2580Sstevel@tonic-gate 	opts.o_target = 0;
2590Sstevel@tonic-gate 	if (optind < argc) {
2600Sstevel@tonic-gate 		struct stat	sinfo;
2610Sstevel@tonic-gate 		char		*path = argv[optind];
2620Sstevel@tonic-gate 		int		error;
2630Sstevel@tonic-gate 
2648638SVikram.Hegde@Sun.COM 		if (opts.o_prominfo) {
2658638SVikram.Hegde@Sun.COM 			/* PROM tree cannot be used with path */
2668638SVikram.Hegde@Sun.COM 			(void) fprintf(stderr, "%s: path and -p option are "
2678638SVikram.Hegde@Sun.COM 			    "mutually exclusive\n", opts.o_progname);
2688638SVikram.Hegde@Sun.COM 			return (1);
2698638SVikram.Hegde@Sun.COM 		}
2708638SVikram.Hegde@Sun.COM 
2710Sstevel@tonic-gate 		if (strlen(path) >= MAXPATHLEN) {
2720Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: "
2730Sstevel@tonic-gate 			    "path specified is too long\n", opts.o_progname);
2740Sstevel@tonic-gate 			return (1);
2750Sstevel@tonic-gate 		}
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate 		if (error = stat(path, &sinfo)) {
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate 			/* an invalid path was specified */
2800Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: invalid path specified\n",
2818638SVikram.Hegde@Sun.COM 			    opts.o_progname);
2820Sstevel@tonic-gate 			return (1);
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate 		} else if (((sinfo.st_mode & S_IFMT) == S_IFCHR) ||
2858638SVikram.Hegde@Sun.COM 		    ((sinfo.st_mode & S_IFMT) == S_IFBLK)) {
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 			opts.o_devt = sinfo.st_rdev;
2880Sstevel@tonic-gate 			error = 0;
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 		} else if ((sinfo.st_mode & S_IFMT) == S_IFDIR) {
2910Sstevel@tonic-gate 			size_t	len, plen;
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate 			/* clean up the path */
2940Sstevel@tonic-gate 			cleanup_path(path, new_path);
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate 			len = strlen(new_path);
2970Sstevel@tonic-gate 			plen = strlen("/devices");
2980Sstevel@tonic-gate 			if (len < plen) {
2990Sstevel@tonic-gate 				/* This is not a valid /devices path */
3000Sstevel@tonic-gate 				error = 1;
3010Sstevel@tonic-gate 			} else if ((len == plen) &&
3020Sstevel@tonic-gate 			    (strcmp(new_path, "/devices") == 0)) {
3030Sstevel@tonic-gate 				/* /devices is the root nexus */
3040Sstevel@tonic-gate 				opts.o_devices_path = "/";
3050Sstevel@tonic-gate 				error = 0;
3060Sstevel@tonic-gate 			} else if (strncmp(new_path, "/devices/", plen + 1)) {
3070Sstevel@tonic-gate 				/* This is not a valid /devices path */
3080Sstevel@tonic-gate 				error = 1;
3090Sstevel@tonic-gate 			} else {
3100Sstevel@tonic-gate 				/* a /devices/ path was specified */
3110Sstevel@tonic-gate 				opts.o_devices_path = new_path + plen;
3120Sstevel@tonic-gate 				error = 0;
3130Sstevel@tonic-gate 			}
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 		} else {
3160Sstevel@tonic-gate 			/* an invalid device path was specified */
3170Sstevel@tonic-gate 			error = 1;
3180Sstevel@tonic-gate 		}
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate 		if (error) {
3210Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: "
3220Sstevel@tonic-gate 			    "invalid device path specified\n",
3230Sstevel@tonic-gate 			    opts.o_progname);
3240Sstevel@tonic-gate 			return (1);
3250Sstevel@tonic-gate 		}
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate 		opts.o_target = 1;
3280Sstevel@tonic-gate 	}
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 	if ((opts.o_ancestors || opts.o_children) && (!opts.o_target)) {
3310Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: options require a device path\n",
3320Sstevel@tonic-gate 		    opts.o_progname);
3330Sstevel@tonic-gate 		return (1);
3340Sstevel@tonic-gate 	}
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate 	if (opts.o_target) {
3370Sstevel@tonic-gate 		prtconf_devinfo();
3380Sstevel@tonic-gate 		return (0);
3390Sstevel@tonic-gate 	}
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 	ret = sysinfo(SI_HW_PROVIDER, hw_provider, sizeof (hw_provider));
3420Sstevel@tonic-gate 	/*
3430Sstevel@tonic-gate 	 * If 0 bytes are returned (the system returns '1', for the \0),
3440Sstevel@tonic-gate 	 * we're probably on x86, and there has been no si-hw-provider
34513038Sanil.udupa@sun.com 	 * set in /etc/bootrc, default to Oracle.
3460Sstevel@tonic-gate 	 */
3470Sstevel@tonic-gate 	if (ret <= 1) {
34813038Sanil.udupa@sun.com 		(void) strncpy(hw_provider, "Oracle Corporation",
3490Sstevel@tonic-gate 		    sizeof (hw_provider));
3500Sstevel@tonic-gate 	}
3510Sstevel@tonic-gate 	(void) printf("System Configuration:  %s  %s\n", hw_provider,
3520Sstevel@tonic-gate 	    opts.o_uts.machine);
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate 	pagesize = sysconf(_SC_PAGESIZE);
3550Sstevel@tonic-gate 	npages = sysconf(_SC_PHYS_PAGES);
3560Sstevel@tonic-gate 	(void) printf("Memory size: ");
3570Sstevel@tonic-gate 	if (pagesize == -1 || npages == -1)
3580Sstevel@tonic-gate 		(void) printf("unable to determine\n");
3590Sstevel@tonic-gate 	else {
3600Sstevel@tonic-gate 		const int64_t kbyte = 1024;
3610Sstevel@tonic-gate 		const int64_t mbyte = 1024 * 1024;
3620Sstevel@tonic-gate 		int64_t ii = (int64_t)pagesize * npages;
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate 		if (ii >= mbyte)
3650Sstevel@tonic-gate 			(void) printf("%ld Megabytes\n",
3668638SVikram.Hegde@Sun.COM 			    (long)((ii+mbyte-1) / mbyte));
3670Sstevel@tonic-gate 		else
3680Sstevel@tonic-gate 			(void) printf("%ld Kilobytes\n",
3698638SVikram.Hegde@Sun.COM 			    (long)((ii+kbyte-1) / kbyte));
3700Sstevel@tonic-gate 	}
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate 	if (opts.o_prominfo) {
3730Sstevel@tonic-gate 		(void) printf("System Peripherals (PROM Nodes):\n\n");
3740Sstevel@tonic-gate 		if (do_prominfo() == 0)
3750Sstevel@tonic-gate 			return (0);
3760Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: Defaulting to non-PROM mode...\n",
3770Sstevel@tonic-gate 		    opts.o_progname);
3780Sstevel@tonic-gate 	}
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate 	(void) printf("System Peripherals (Software Nodes):\n\n");
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate 	(void) prtconf_devinfo();
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate 	return (0);
3850Sstevel@tonic-gate }
386