xref: /titanic_44/usr/src/lib/libcmd/common/uname.c (revision 986fd29a0dc13f7608ef7f508f6e700bd7bc2720)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *           Copyright (c) 1992-2007 AT&T Knowledge Ventures            *
5 *                      and is licensed under the                       *
6 *                  Common Public License, Version 1.0                  *
7 *                      by AT&T Knowledge Ventures                      *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *            http://www.opensource.org/licenses/cpl1.0.txt             *
11 *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12 *                                                                      *
13 *              Information and Software Systems Research               *
14 *                            AT&T Research                             *
15 *                           Florham Park NJ                            *
16 *                                                                      *
17 *                 Glenn Fowler <gsf@research.att.com>                  *
18 *                  David Korn <dgk@research.att.com>                   *
19 *                                                                      *
20 ***********************************************************************/
21 #pragma prototyped
22 /*
23  * David Korn
24  * Glenn Fowler
25  * AT&T Research
26  *
27  * uname
28  */
29 
30 static const char usage[] =
31 "[-?\n@(#)$Id: uname (AT&T Research) 2007-01-22 $\n]"
32 USAGE_LICENSE
33 "[+NAME?uname - identify the current system ]"
34 "[+DESCRIPTION?By default \buname\b writes the operating system name to"
35 "	standard output. When options are specified, one or more"
36 "	system characteristics are written to standard output, space"
37 "	separated, on a single line. When more than one option is specifed"
38 "	the output is in the order specfied by the \b-A\b option below."
39 "	Unsupported option values are listed as \a[option]]\a. If any unknown"
40 "	options are specified then the local \b/usr/bin/uname\b is called.]"
41 "[+?If any \aname\a operands are specified then the \bsysinfo\b(2) values"
42 "	for each \aname\a are listed, separated by space, on one line."
43 "	\bgetconf\b(1), a pre-existing \astandard\a interface, provides"
44 "	access to the same information; vendors should spend more time"
45 "	using standards than inventing them.]"
46 "[+?Selected information is printed in the same order as the options below.]"
47 "[a:all?Equivalent to \b-snrvmpio\b.]"
48 "[s:system|sysname|kernel-name?The detailed kernel name. This is the default.]"
49 "[n:nodename?The hostname or nodename.]"
50 "[r:release|kernel-release?The kernel release level.]"
51 "[v:version|kernel-version?The kernel version level.]"
52 "[m:machine?The name of the hardware type the system is running on.]"
53 "[p:processor?The name of the processor instruction set architecture.]"
54 "[i:implementation|platform|hardware-platform?The hardware implementation;"
55 "	this is \b--host-id\b on some systems.]"
56 "[o:operating-system?The generic operating system name.]"
57 "[h:host-id|id?The host id in hex.]"
58 "[d:domain?The domain name returned by \agetdomainname\a(2).]"
59 "[R:extended-release?The extended release name.]"
60 "[A:everything?Equivalent to \b-snrvmpiohdR\b.]"
61 "[f:list?List all \bsysinfo\b(2) names and values, one per line.]"
62 "[S:sethost?Set the hostname or nodename to \aname\a. No output is"
63 "	written to standard output.]:[name]"
64 
65 "[+SEE ALSO?\bhostname\b(1), \bgetconf\b(1), \buname\b(2),"
66 "	\bsysconf\b(2), \bsysinfo\b(2)]"
67 ;
68 
69 #if defined(__STDPP__directive) && defined(__STDPP__hide)
70 __STDPP__directive pragma pp:hide getdomainname gethostid gethostname sethostname
71 #else
72 #define getdomainname	______getdomainname
73 #define gethostid	______gethostid
74 #define gethostname	______gethostname
75 #define sethostname	______sethostname
76 #endif
77 
78 #include <cmd.h>
79 #include <ctype.h>
80 #include <proc.h>
81 
82 #include "FEATURE/utsname"
83 
84 #define MAXHOSTNAME	64
85 
86 #if _lib_uname && _sys_utsname
87 
88 #include <sys/utsname.h>
89 
90 #endif
91 
92 #if defined(__STDPP__directive) && defined(__STDPP__hide)
93 __STDPP__directive pragma pp:nohide getdomainname gethostid gethostname sethostname
94 #else
95 #undef	getdomainname
96 #undef	gethostid
97 #undef	gethostname
98 #undef	sethostname
99 #endif
100 
101 #if _lib_getdomainname
102 extern int	getdomainname(char*, size_t);
103 #endif
104 #if _lib_gethostid
105 extern int	gethostid(void);
106 #endif
107 #if _lib_gethostname
108 extern int	gethostname(char*, size_t);
109 #endif
110 #if _lib_sethostname
111 extern int	sethostname(const char*, size_t);
112 #endif
113 
114 #ifndef HOSTTYPE
115 #define HOSTTYPE	"unknown"
116 #endif
117 
118 static const char	hosttype[] = HOSTTYPE;
119 
120 #if !_lib_uname || !_sys_utsname
121 
122 #if defined(__STDPP__)
123 #define SYSNAME		#(getprd machine)
124 #define RELEASE		#(getprd release)
125 #define VERSION		#(getprd version)
126 #define MACHINE		#(getprd architecture)
127 #else
128 #define SYSNAME		""
129 #define RELEASE		""
130 #define VERSION		""
131 #define MACHINE		""
132 #endif
133 
134 struct utsname
135 {
136 	char*	sysname;
137 	char	nodename[MAXHOSTNAME];
138 	char*	release;
139 	char*	version;
140 	char*	machine;
141 };
142 
143 int
144 uname(register struct utsname* ut)
145 {
146 #ifdef HOSTTYPE
147 	char*		sys = 0;
148 	char*		arch = 0;
149 
150 	if (*hosttype)
151 	{
152 		static char	buf[sizeof(hosttype)];
153 
154 		strcpy(buf, hosttype);
155 		sys = buf;
156 		if (arch = strchr(sys, '.'))
157 		{
158 			*arch++ = 0;
159 			if (!*arch)
160 				arch = 0;
161 		}
162 		if (!*sys)
163 			sys = 0;
164 	}
165 #endif
166 #ifdef _lib_gethostname
167 	if (gethostname(ut->nodename, sizeof(ut->nodename) - 1))
168 		return -1;
169 #else
170 	strncpy(ut->nodename, "local", sizeof(ut->nodename) - 1);
171 #endif
172 #ifdef HOSTTYPE
173 	if (!(ut->sysname = sys))
174 #endif
175 	if (!*(ut->sysname = SYSNAME))
176 		ut->sysname = ut->nodename;
177 #ifdef HOSTTYPE
178 	if (!(ut->machine = arch))
179 #endif
180 	ut->machine = MACHINE;
181 	ut->release = RELEASE;
182 	ut->version = VERSION;
183 	return 0;
184 }
185 
186 #endif
187 
188 #define OPT_system		(1<<0)
189 #define OPT_nodename		(1<<1)
190 #define OPT_release		(1<<2)
191 #define OPT_version		(1<<3)
192 #define OPT_machine		(1<<4)
193 #define OPT_processor		(1<<5)
194 
195 #define OPT_STANDARD		6
196 
197 #define OPT_implementation	(1<<6)
198 #define OPT_operating_system	(1<<7)
199 
200 #define OPT_ALL			8
201 
202 #define OPT_hostid		(1<<8)
203 #define OPT_vendor		(1<<9)
204 #define OPT_domain		(1<<10)
205 #define OPT_machine_type	(1<<11)
206 #define OPT_base		(1<<12)
207 #define OPT_extended_release	(1<<13)
208 #define OPT_extra		(1<<14)
209 
210 #define OPT_TOTAL		15
211 
212 #define OPT_all			(1L<<29)
213 #define OPT_total		(1L<<30)
214 #define OPT_standard		((1<<OPT_STANDARD)-1)
215 
216 #ifndef MACHINE
217 #if defined(__STDPP__)
218 #define MACHINE			#(getprd architecture)
219 #else
220 #define MACHINE			""
221 #endif
222 #endif
223 
224 #ifndef HOSTTYPE
225 #define HOSTTYPE		"unknown"
226 #endif
227 
228 #define extra(m)        do \
229 			{ \
230 				if ((char*)&ut.m[sizeof(ut.m)] > last) \
231 					last = (char*)&ut.m[sizeof(ut.m)]; \
232 			} while(0)
233 
234 #define output(f,v,u)	do \
235 			{ \
236 				if ((flags&(f))&&(*(v)||(flags&(OPT_all|OPT_total))==OPT_all&&((f)&OPT_standard)||!(flags&(OPT_all|OPT_total)))) \
237 				{ \
238 					if (sep) \
239 						sfputc(sfstdout, ' '); \
240 					else \
241 						sep = 1; \
242 					if (*(v)) \
243 						sfputr(sfstdout, v, -1); \
244 					else \
245 						sfprintf(sfstdout, "[%s]", u); \
246 				} \
247 			} while (0)
248 
249 int
250 b_uname(int argc, char** argv, void* context)
251 {
252 	register long	flags = 0;
253 	register int	sep = 0;
254 	register int	n;
255 	register char*	s;
256 	char*		t;
257 	char*		e;
258 	char*		sethost = 0;
259 	int		list = 0;
260 	struct utsname	ut;
261 	char		buf[257];
262 
263 	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
264 	for (;;)
265 	{
266 		switch (optget(argv, usage))
267 		{
268 		case 'a':
269 			flags |= OPT_all|((1L<<OPT_ALL)-1);
270 			continue;
271 		case 'b':
272 			flags |= OPT_base;
273 			continue;
274 		case 'c':
275 			flags |= OPT_vendor;
276 			continue;
277 		case 'd':
278 			flags |= OPT_domain;
279 			continue;
280 		case 'f':
281 			list = 1;
282 			continue;
283 		case 'h':
284 			flags |= OPT_hostid;
285 			continue;
286 		case 'i':
287 			flags |= OPT_implementation;
288 			continue;
289 		case 'm':
290 			flags |= OPT_machine;
291 			continue;
292 		case 'n':
293 			flags |= OPT_nodename;
294 			continue;
295 		case 'o':
296 			flags |= OPT_operating_system;
297 			continue;
298 		case 'p':
299 			flags |= OPT_processor;
300 			continue;
301 		case 'r':
302 			flags |= OPT_release;
303 			continue;
304 		case 's':
305 			flags |= OPT_system;
306 			continue;
307 		case 't':
308 			flags |= OPT_machine_type;
309 			continue;
310 		case 'v':
311 			flags |= OPT_version;
312 			continue;
313 		case 'x':
314 			flags |= OPT_extra;
315 			continue;
316 		case 'A':
317 			flags |= OPT_total|((1L<<OPT_TOTAL)-1);
318 			continue;
319 		case 'R':
320 			flags |= OPT_extended_release;
321 			continue;
322 		case 'S':
323 			sethost = opt_info.arg;
324 			continue;
325 		case ':':
326 			s = "/usr/bin/uname";
327 			if (!streq(argv[0], s) && (!eaccess(s, X_OK) || !eaccess(s+=4, X_OK)))
328 			{
329 				argv[0] = s;
330 				return procrun(s, argv);
331 			}
332 			error(2, "%s", opt_info.arg);
333 			break;
334 		case '?':
335 			error(ERROR_usage(2), "%s", opt_info.arg);
336 			break;
337 		}
338 		break;
339 	}
340 	argv += opt_info.index;
341 	if (error_info.errors || *argv && (flags || sethost) || sethost && flags)
342 		error(ERROR_usage(2), "%s", optusage(NiL));
343 	if (sethost)
344 	{
345 #if _lib_sethostname
346 		if (sethostname(sethost, strlen(sethost) + 1))
347 #else
348 #ifdef	ENOSYS
349 		errno = ENOSYS;
350 #else
351 		errno = EPERM;
352 #endif
353 #endif
354 		error(ERROR_system(1), "%s: cannot set host name", sethost);
355 	}
356 	else if (list)
357 		astconflist(sfstdout, NiL, ASTCONF_base|ASTCONF_defined|ASTCONF_lower|ASTCONF_quote|ASTCONF_matchcall, "CS|SI");
358 	else if (*argv)
359 	{
360 		e = &buf[sizeof(buf)-1];
361 		while (s = *argv++)
362 		{
363 			t = buf;
364 			*t++ = 'C';
365 			*t++ = 'S';
366 			*t++ = '_';
367 			while (t < e && (n = *s++))
368 				*t++ = islower(n) ? toupper(n) : n;
369 			*t = 0;
370 			sfprintf(sfstdout, "%s%c", *(t = astconf(buf, NiL, NiL)) ? t : "unknown", *argv ? ' ' : '\n');
371 		}
372 	}
373 	else
374 	{
375 		s = buf;
376 		if (!flags)
377 			flags = OPT_system;
378 		memzero(&ut, sizeof(ut));
379 		if (uname(&ut) < 0)
380 			error(ERROR_usage(2), "information unavailable");
381 		output(OPT_system, ut.sysname, "sysname");
382 		if (flags & OPT_nodename)
383 		{
384 #if !_mem_nodeext_utsname && _lib_gethostname
385 			if (sizeof(ut.nodename) > 9 || gethostname(s, sizeof(buf)))
386 #endif
387 			s = ut.nodename;
388 			output(OPT_nodename, s, "nodename");
389 		}
390 		output(OPT_release, ut.release, "release");
391 		output(OPT_version, ut.version, "version");
392 		output(OPT_machine, ut.machine, "machine");
393 		if (flags & OPT_processor)
394 		{
395 			if (!*(s = astconf("ARCHITECTURE", NiL, NiL)))
396 				s = ut.machine;
397 			output(OPT_processor, s, "processor");
398 		}
399 		if (flags & OPT_implementation)
400 		{
401 			if (!*(s = astconf("PLATFORM", NiL, NiL)) && !*(s = astconf("HW_NAME", NiL, NiL)))
402 			{
403 				if (t = strchr(hosttype, '.'))
404 					t++;
405 				else
406 					t = (char*)hosttype;
407 				strncpy(s = buf, t, sizeof(buf) - 1);
408 			}
409 			output(OPT_implementation, s, "implementation");
410 		}
411 		if (flags & OPT_operating_system)
412 		{
413 			s = astconf("OPERATING_SYSTEM", NiL, NiL);
414 			if (!*s)
415 #ifdef _UNAME_os_DEFAULT
416 				s = _UNAME_os_DEFAULT;
417 #else
418 				s = ut.sysname;
419 #endif
420 			output(OPT_operating_system, s, "operating-system");
421 		}
422 		if (flags & OPT_extended_release)
423 		{
424 			s = astconf("RELEASE", NiL, NiL);
425 			output(OPT_extended_release, s, "extended-release");
426 		}
427 #if _mem_idnumber_utsname
428 		output(OPT_hostid, ut.idnumber, "hostid");
429 #else
430 		if (flags & OPT_hostid)
431 		{
432 			if (!*(s = astconf("HW_SERIAL", NiL, NiL)))
433 #if _lib_gethostid
434 				sfsprintf(s = buf, sizeof(buf), "%08x", gethostid());
435 #else
436 				/*NOP*/;
437 #endif
438 			output(OPT_hostid, s, "hostid");
439 		}
440 #endif
441 		if (flags & OPT_vendor)
442 		{
443 			s = astconf("HW_PROVIDER", NiL, NiL);
444 			output(OPT_vendor, s, "vendor");
445 		}
446 		if (flags & OPT_domain)
447 		{
448 			if (!*(s = astconf("SRPC_DOMAIN", NiL, NiL)))
449 #if _lib_getdomainname
450 				getdomainname(s, sizeof(buf));
451 #else
452 				/*NOP*/;
453 #endif
454 			output(OPT_domain, s, "domain");
455 		}
456 #if _mem_m_type_utsname
457 		s = ut.m_type;
458 #else
459 		s = astconf("MACHINE", NiL, NiL);
460 #endif
461 		output(OPT_machine_type, s, "m_type");
462 #if _mem_base_rel_utsname
463 		s = ut.base_rel;
464 #else
465 		s = astconf("BASE", NiL, NiL);
466 #endif
467 		output(OPT_base, s, "base_rel");
468 		if (flags & OPT_extra)
469 		{
470 			char*	last = (char*)&ut;
471 
472 			extra(sysname);
473 			extra(nodename);
474 			extra(release);
475 			extra(version);
476 			extra(machine);
477 #if _mem_idnumber_utsname
478 			extra(idnumber);
479 #endif
480 #if _mem_m_type_utsname
481 			extra(m_type);
482 #endif
483 #if _mem_base_rel_utsname
484 			extra(base_rel);
485 #endif
486 			if (last < ((char*)(&ut + 1)))
487 			{
488 				s = t = last;
489 				while (s < (char*)(&ut + 1))
490 				{
491 					if (!(n = *s++))
492 					{
493 						if ((s - t) > 1)
494 						{
495 							if (sep)
496 								sfputc(sfstdout, ' ');
497 							else
498 								sep = 1;
499 							sfputr(sfstdout, t, -1);
500 						}
501 						t = s;
502 					}
503 					else if (!isprint(n))
504 						break;
505 				}
506 			}
507 		}
508 		if (sep)
509 			sfputc(sfstdout, '\n');
510 	}
511 	return error_info.errors;
512 }
513