1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 #include <stdio.h> 34 #include <stdarg.h> 35 #include <stdlib.h> 36 #include <unistd.h> 37 #include <strings.h> 38 #include <sys/systeminfo.h> 39 #include <sys/types.h> 40 #include <sys/stat.h> 41 #include "prtconf.h" 42 43 struct prt_opts opts; 44 struct prt_dbg dbg; 45 static char new_path[MAXPATHLEN]; 46 47 #define INDENT_LENGTH 4 48 49 #ifdef __x86 50 static const char *usage = "%s [ -V | -x | -abcvpPD ] [ <device_path > ]\n"; 51 #else 52 static const char *usage = "%s [ -F | -V | -x | -abcvpPD ][ <device_path > ]\n"; 53 #endif /* __x86 */ 54 55 static void 56 setprogname(const char *name) 57 { 58 char *p; 59 60 if (name == NULL) 61 opts.o_progname = "prtconf"; 62 else if (p = strrchr(name, '/')) 63 opts.o_progname = (const char *) p + 1; 64 else 65 opts.o_progname = name; 66 } 67 68 /*PRINTFLIKE1*/ 69 void 70 dprintf(const char *fmt, ...) 71 { 72 if (dbg.d_debug) { 73 va_list ap; 74 va_start(ap, fmt); 75 (void) vfprintf(stderr, fmt, ap); 76 va_end(ap); 77 } 78 } 79 80 void 81 indent_to_level(int ilev) 82 { 83 (void) printf("%*s", INDENT_LENGTH * ilev, ""); 84 } 85 86 static void 87 cleanup_path(const char *input_path, char *path) 88 { 89 char *ptr, *ptr2; 90 size_t len; 91 92 if ((input_path == NULL) || (path == NULL)) 93 return; 94 95 (void) strcpy(path, input_path); 96 97 /*LINTED*/ 98 while (1) { 99 len = strlen(path); 100 if (len == 0) 101 break; 102 103 /* change substring "//" into "/" */ 104 if (ptr = strstr(path, "//")) { 105 len = strlen(ptr + 1); 106 (void) memmove(ptr, ptr + 1, len + 1); 107 continue; 108 } 109 /* change substring "/./" into "/" */ 110 if (ptr = strstr(path, "/./")) { 111 len = strlen(ptr + 2); 112 (void) memmove(ptr, ptr + 2, len + 1); 113 continue; 114 } 115 116 /* change substring "/<foo>/../" into "/" */ 117 if (ptr = strstr(path, "/../")) { 118 len = strlen(ptr + 3); 119 *ptr = '\0'; 120 ptr2 = strrchr(path, (int)'/'); 121 if (ptr2 == NULL) { 122 /* path had a leading "/../" */ 123 ptr2 = path; 124 } 125 (void) memmove(ptr2, ptr + 3, len + 1); 126 continue; 127 } 128 129 /* change trailing "/<foo>/.." into "/" */ 130 if ((len >= 3) && 131 (path[len - 3] == '/') && 132 (path[len - 2] == '.') && 133 (path[len - 1] == '.')) { 134 path[len - 3] = '\0'; 135 ptr2 = strrchr(path, (int)'/'); 136 if (ptr2 != NULL) { 137 ptr2[1] = '\0'; 138 } else { 139 /* path was "/.." */ 140 path[0] = '/'; 141 path[1] = '\0'; 142 } 143 continue; 144 } 145 146 /* change trailing "/." into "/" */ 147 if ((len >= 2) && 148 (path[len - 2] == '/') && 149 (path[len - 1] == '.')) { 150 path[len - 1] = '\0'; 151 continue; 152 } 153 154 /* remove trailing "/" unless it's the root */ 155 if ((len > 1) && (path[len - 1] == '/')) { 156 path[len - 1] = '\0'; 157 continue; 158 } 159 160 break; 161 } 162 } 163 164 165 /* 166 * debug version has two more flags: 167 * -L force load driver 168 * -M: print per driver list 169 */ 170 171 #ifdef DEBUG 172 static const char *optstring = "abcDvVxpPFf:M:dLuC"; 173 #else 174 static const char *optstring = "abcDvVxpPFf:uC"; 175 #endif /* DEBUG */ 176 177 int 178 main(int argc, char *argv[]) 179 { 180 long pagesize, npages; 181 int c, ret; 182 char hw_provider[SYS_NMLN]; 183 184 setprogname(argv[0]); 185 opts.o_promdev = "/dev/openprom"; 186 187 while ((c = getopt(argc, argv, optstring)) != -1) { 188 switch (c) { 189 case 'a': 190 ++opts.o_ancestors; 191 break; 192 case 'b': 193 ++opts.o_productinfo; 194 break; 195 case 'c': 196 ++opts.o_children; 197 break; 198 case 'D': 199 ++opts.o_drv_name; 200 break; 201 case 'v': 202 ++opts.o_verbose; 203 break; 204 case 'p': 205 ++opts.o_prominfo; 206 break; 207 case 'f': 208 opts.o_promdev = optarg; 209 break; 210 case 'V': 211 ++opts.o_promversion; 212 break; 213 case 'x': 214 ++opts.o_prom_ready64; 215 break; 216 case 'F': 217 ++opts.o_fbname; 218 ++opts.o_noheader; 219 break; 220 case 'P': 221 ++opts.o_pseudodevs; 222 break; 223 case 'C': 224 ++opts.o_forcecache; 225 break; 226 #ifdef DEBUG 227 case 'M': 228 dbg.d_drivername = optarg; 229 ++dbg.d_bydriver; 230 break; 231 case 'L': 232 ++dbg.d_forceload; 233 break; 234 #endif /* DEBUG */ 235 236 default: 237 (void) fprintf(stderr, usage, opts.o_progname); 238 return (1); 239 } 240 } 241 242 (void) uname(&opts.o_uts); 243 244 if (opts.o_fbname) 245 return (do_fbname()); 246 247 if (opts.o_promversion) 248 return (do_promversion()); 249 250 if (opts.o_prom_ready64) 251 return (do_prom_version64()); 252 253 if (opts.o_productinfo) 254 return (do_productinfo()); 255 256 opts.o_devices_path = NULL; 257 opts.o_devt = DDI_DEV_T_NONE; 258 opts.o_target = 0; 259 if (optind < argc) { 260 struct stat sinfo; 261 char *path = argv[optind]; 262 int error; 263 264 if (strlen(path) >= MAXPATHLEN) { 265 (void) fprintf(stderr, "%s: " 266 "path specified is too long\n", opts.o_progname); 267 return (1); 268 } 269 270 if (error = stat(path, &sinfo)) { 271 272 /* an invalid path was specified */ 273 (void) fprintf(stderr, "%s: invalid path specified\n", 274 opts.o_progname); 275 return (1); 276 277 } else if (((sinfo.st_mode & S_IFMT) == S_IFCHR) || 278 ((sinfo.st_mode & S_IFMT) == S_IFBLK)) { 279 280 opts.o_devt = sinfo.st_rdev; 281 error = 0; 282 283 } else if ((sinfo.st_mode & S_IFMT) == S_IFDIR) { 284 size_t len, plen; 285 286 /* clean up the path */ 287 cleanup_path(path, new_path); 288 289 len = strlen(new_path); 290 plen = strlen("/devices"); 291 if (len < plen) { 292 /* This is not a valid /devices path */ 293 error = 1; 294 } else if ((len == plen) && 295 (strcmp(new_path, "/devices") == 0)) { 296 /* /devices is the root nexus */ 297 opts.o_devices_path = "/"; 298 error = 0; 299 } else if (strncmp(new_path, "/devices/", plen + 1)) { 300 /* This is not a valid /devices path */ 301 error = 1; 302 } else { 303 /* a /devices/ path was specified */ 304 opts.o_devices_path = new_path + plen; 305 error = 0; 306 } 307 308 } else { 309 /* an invalid device path was specified */ 310 error = 1; 311 } 312 313 if (error) { 314 (void) fprintf(stderr, "%s: " 315 "invalid device path specified\n", 316 opts.o_progname); 317 return (1); 318 } 319 320 opts.o_target = 1; 321 } 322 323 if ((opts.o_ancestors || opts.o_children) && (!opts.o_target)) { 324 (void) fprintf(stderr, "%s: options require a device path\n", 325 opts.o_progname); 326 return (1); 327 } 328 329 if (opts.o_target) { 330 prtconf_devinfo(); 331 return (0); 332 } 333 334 ret = sysinfo(SI_HW_PROVIDER, hw_provider, sizeof (hw_provider)); 335 /* 336 * If 0 bytes are returned (the system returns '1', for the \0), 337 * we're probably on x86, and there has been no si-hw-provider 338 * set in /etc/bootrc, so just default to Sun. 339 */ 340 if (ret <= 1) { 341 (void) strncpy(hw_provider, "Sun Microsystems", 342 sizeof (hw_provider)); 343 } else { 344 /* 345 * Provide backward compatibility by stripping out the _. 346 */ 347 if (strcmp(hw_provider, "Sun_Microsystems") == 0) 348 hw_provider[3] = ' '; 349 } 350 (void) printf("System Configuration: %s %s\n", hw_provider, 351 opts.o_uts.machine); 352 353 pagesize = sysconf(_SC_PAGESIZE); 354 npages = sysconf(_SC_PHYS_PAGES); 355 (void) printf("Memory size: "); 356 if (pagesize == -1 || npages == -1) 357 (void) printf("unable to determine\n"); 358 else { 359 const int64_t kbyte = 1024; 360 const int64_t mbyte = 1024 * 1024; 361 int64_t ii = (int64_t)pagesize * npages; 362 363 if (ii >= mbyte) 364 (void) printf("%ld Megabytes\n", 365 (long)((ii+mbyte-1) / mbyte)); 366 else 367 (void) printf("%ld Kilobytes\n", 368 (long)((ii+kbyte-1) / kbyte)); 369 } 370 371 if (opts.o_prominfo) { 372 (void) printf("System Peripherals (PROM Nodes):\n\n"); 373 if (do_prominfo() == 0) 374 return (0); 375 (void) fprintf(stderr, "%s: Defaulting to non-PROM mode...\n", 376 opts.o_progname); 377 } 378 379 (void) printf("System Peripherals (Software Nodes):\n\n"); 380 381 (void) prtconf_devinfo(); 382 383 return (0); 384 } 385