1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1992-2012 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                 Eclipse Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *          http://www.eclipse.org/org/documents/epl-v10.html           *
11 *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
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-04-19 $\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 specified"
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 "\n"
65 "\n[ name ... ]\n"
66 "\n"
67 "[+SEE ALSO?\bhostname\b(1), \bgetconf\b(1), \buname\b(2),"
68 "	\bsysconf\b(2), \bsysinfo\b(2)]"
69 ;
70 
71 #if defined(__STDPP__directive) && defined(__STDPP__hide)
72 __STDPP__directive pragma pp:hide getdomainname gethostid gethostname sethostname
73 #else
74 #define getdomainname	______getdomainname
75 #define gethostid	______gethostid
76 #define gethostname	______gethostname
77 #define sethostname	______sethostname
78 #endif
79 
80 #include <cmd.h>
81 #include <ctype.h>
82 #include <proc.h>
83 
84 #include "FEATURE/utsname"
85 
86 #define MAXHOSTNAME	64
87 
88 #if _lib_uname && _sys_utsname
89 
90 #include <sys/utsname.h>
91 
92 #endif
93 
94 #if defined(__STDPP__directive) && defined(__STDPP__hide)
95 __STDPP__directive pragma pp:nohide getdomainname gethostid gethostname sethostname
96 #else
97 #undef	getdomainname
98 #undef	gethostid
99 #undef	gethostname
100 #undef	sethostname
101 #endif
102 
103 #if _lib_getdomainname
104 extern int	getdomainname(char*, size_t);
105 #endif
106 #if _lib_gethostid
107 extern long	gethostid(void);
108 #endif
109 #if _lib_gethostname
110 extern int	gethostname(char*, size_t);
111 #endif
112 #if _lib_sethostname
113 extern int	sethostname(const char*, size_t);
114 #endif
115 
116 #ifndef HOSTTYPE
117 #define HOSTTYPE	"unknown"
118 #endif
119 
120 static const char	hosttype[] = HOSTTYPE;
121 
122 #if !_lib_uname || !_sys_utsname
123 
124 #if defined(__STDPP__)
125 #define SYSNAME		#(getprd machine)
126 #define RELEASE		#(getprd release)
127 #define VERSION		#(getprd version)
128 #define MACHINE		#(getprd architecture)
129 #else
130 #define SYSNAME		""
131 #define RELEASE		""
132 #define VERSION		""
133 #define MACHINE		""
134 #endif
135 
136 struct utsname
137 {
138 	char*	sysname;
139 	char	nodename[MAXHOSTNAME];
140 	char*	release;
141 	char*	version;
142 	char*	machine;
143 };
144 
145 int
uname(register struct utsname * ut)146 uname(register struct utsname* ut)
147 {
148 #ifdef HOSTTYPE
149 	char*		sys = 0;
150 	char*		arch = 0;
151 
152 	if (*hosttype)
153 	{
154 		static char	buf[sizeof(hosttype)];
155 
156 		strcpy(buf, hosttype);
157 		sys = buf;
158 		if (arch = strchr(sys, '.'))
159 		{
160 			*arch++ = 0;
161 			if (!*arch)
162 				arch = 0;
163 		}
164 		if (!*sys)
165 			sys = 0;
166 	}
167 #endif
168 #ifdef _lib_gethostname
169 	if (gethostname(ut->nodename, sizeof(ut->nodename) - 1))
170 		return -1;
171 #else
172 	strncpy(ut->nodename, "local", sizeof(ut->nodename) - 1);
173 #endif
174 #ifdef HOSTTYPE
175 	if (!(ut->sysname = sys))
176 #endif
177 	if (!*(ut->sysname = SYSNAME))
178 		ut->sysname = ut->nodename;
179 #ifdef HOSTTYPE
180 	if (!(ut->machine = arch))
181 #endif
182 	ut->machine = MACHINE;
183 	ut->release = RELEASE;
184 	ut->version = VERSION;
185 	return 0;
186 }
187 
188 #endif
189 
190 #define OPT_system		(1<<0)
191 #define OPT_nodename		(1<<1)
192 #define OPT_release		(1<<2)
193 #define OPT_version		(1<<3)
194 #define OPT_machine		(1<<4)
195 #define OPT_processor		(1<<5)
196 
197 #define OPT_STANDARD		6
198 
199 #define OPT_implementation	(1<<6)
200 #define OPT_operating_system	(1<<7)
201 
202 #define OPT_ALL			8
203 
204 #define OPT_hostid		(1<<8)
205 #define OPT_vendor		(1<<9)
206 #define OPT_domain		(1<<10)
207 #define OPT_machine_type	(1<<11)
208 #define OPT_base		(1<<12)
209 #define OPT_extended_release	(1<<13)
210 #define OPT_extra		(1<<14)
211 
212 #define OPT_TOTAL		15
213 
214 #define OPT_all			(1L<<29)
215 #define OPT_total		(1L<<30)
216 #define OPT_standard		((1<<OPT_STANDARD)-1)
217 
218 #ifndef MACHINE
219 #if defined(__STDPP__)
220 #define MACHINE			#(getprd architecture)
221 #else
222 #define MACHINE			""
223 #endif
224 #endif
225 
226 #ifndef HOSTTYPE
227 #define HOSTTYPE		"unknown"
228 #endif
229 
230 #define extra(m)        do \
231 			{ \
232 				if ((char*)&ut.m[sizeof(ut.m)] > last) \
233 					last = (char*)&ut.m[sizeof(ut.m)]; \
234 			} while(0)
235 
236 #define output(f,v,u)	do \
237 			{ \
238 				if ((flags&(f))&&(*(v)||(flags&(OPT_all|OPT_total))==OPT_all&&((f)&OPT_standard)||!(flags&(OPT_all|OPT_total)))) \
239 				{ \
240 					if (sep) \
241 						sfputc(sfstdout, ' '); \
242 					else \
243 						sep = 1; \
244 					if (*(v)) \
245 						sfputr(sfstdout, v, -1); \
246 					else \
247 						sfprintf(sfstdout, "[%s]", u); \
248 				} \
249 			} while (0)
250 
251 int
b_uname(int argc,char ** argv,Shbltin_t * context)252 b_uname(int argc, char** argv, Shbltin_t* context)
253 {
254 	register long	flags = 0;
255 	register int	sep = 0;
256 	register int	n;
257 	register char*	s;
258 	char*		t;
259 	char*		e;
260 	char*		sethost = 0;
261 	int		list = 0;
262 	struct utsname	ut;
263 	char		buf[257];
264 
265 	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
266 	for (;;)
267 	{
268 		switch (optget(argv, usage))
269 		{
270 		case 'a':
271 			flags |= OPT_all|((1L<<OPT_ALL)-1);
272 			continue;
273 		case 'b':
274 			flags |= OPT_base;
275 			continue;
276 		case 'c':
277 			flags |= OPT_vendor;
278 			continue;
279 		case 'd':
280 			flags |= OPT_domain;
281 			continue;
282 		case 'f':
283 			list = 1;
284 			continue;
285 		case 'h':
286 			flags |= OPT_hostid;
287 			continue;
288 		case 'i':
289 			flags |= OPT_implementation;
290 			continue;
291 		case 'm':
292 			flags |= OPT_machine;
293 			continue;
294 		case 'n':
295 			flags |= OPT_nodename;
296 			continue;
297 		case 'o':
298 			flags |= OPT_operating_system;
299 			continue;
300 		case 'p':
301 			flags |= OPT_processor;
302 			continue;
303 		case 'r':
304 			flags |= OPT_release;
305 			continue;
306 		case 's':
307 			flags |= OPT_system;
308 			continue;
309 		case 't':
310 			flags |= OPT_machine_type;
311 			continue;
312 		case 'v':
313 			flags |= OPT_version;
314 			continue;
315 		case 'x':
316 			flags |= OPT_extra;
317 			continue;
318 		case 'A':
319 			flags |= OPT_total|((1L<<OPT_TOTAL)-1);
320 			continue;
321 		case 'R':
322 			flags |= OPT_extended_release;
323 			continue;
324 		case 'S':
325 			sethost = opt_info.arg;
326 			continue;
327 		case ':':
328 			s = "/usr/bin/uname";
329 			if (!streq(argv[0], s) && (!eaccess(s, X_OK) || !eaccess(s+=4, X_OK)))
330 			{
331 				argv[0] = s;
332 				return sh_run(context, argc, argv);
333 			}
334 			error(2, "%s", opt_info.arg);
335 			break;
336 		case '?':
337 			error(ERROR_usage(2), "%s", opt_info.arg);
338 			break;
339 		}
340 		break;
341 	}
342 	argv += opt_info.index;
343 	if (error_info.errors || *argv && (flags || sethost) || sethost && flags)
344 		error(ERROR_usage(2), "%s", optusage(NiL));
345 	if (sethost)
346 	{
347 #if _lib_sethostname
348 		if (sethostname(sethost, strlen(sethost) + 1))
349 #else
350 #ifdef	ENOSYS
351 		errno = ENOSYS;
352 #else
353 		errno = EPERM;
354 #endif
355 #endif
356 		error(ERROR_system(1), "%s: cannot set host name", sethost);
357 	}
358 	else if (list)
359 		astconflist(sfstdout, NiL, ASTCONF_base|ASTCONF_defined|ASTCONF_lower|ASTCONF_quote|ASTCONF_matchcall, "CS|SI");
360 	else if (*argv)
361 	{
362 		e = &buf[sizeof(buf)-1];
363 		while (s = *argv++)
364 		{
365 			t = buf;
366 			*t++ = 'C';
367 			*t++ = 'S';
368 			*t++ = '_';
369 			while (t < e && (n = *s++))
370 				*t++ = islower(n) ? toupper(n) : n;
371 			*t = 0;
372 			sfprintf(sfstdout, "%s%c", *(t = astconf(buf, NiL, NiL)) ? t : *(t = astconf(buf+3, NiL, NiL)) ? t :  "unknown", *argv ? ' ' : '\n');
373 		}
374 	}
375 	else
376 	{
377 		s = buf;
378 		if (!flags)
379 			flags = OPT_system;
380 		memzero(&ut, sizeof(ut));
381 		if (uname(&ut) < 0)
382 			error(ERROR_usage(2), "information unavailable");
383 		output(OPT_system, ut.sysname, "sysname");
384 		if (flags & OPT_nodename)
385 		{
386 #if !_mem_nodeext_utsname && _lib_gethostname
387 			if (sizeof(ut.nodename) > 9 || gethostname(s, sizeof(buf)))
388 #endif
389 			s = ut.nodename;
390 			output(OPT_nodename, s, "nodename");
391 		}
392 		output(OPT_release, ut.release, "release");
393 		output(OPT_version, ut.version, "version");
394 		output(OPT_machine, ut.machine, "machine");
395 		if (flags & OPT_processor)
396 		{
397 			if (!*(s = astconf("ARCHITECTURE", NiL, NiL)))
398 				s = ut.machine;
399 			output(OPT_processor, s, "processor");
400 		}
401 		if (flags & OPT_implementation)
402 		{
403 			if (!*(s = astconf("PLATFORM", NiL, NiL)) && !*(s = astconf("HW_NAME", NiL, NiL)))
404 			{
405 				if (t = strchr(hosttype, '.'))
406 					t++;
407 				else
408 					t = (char*)hosttype;
409 				strncpy(s = buf, t, sizeof(buf) - 1);
410 			}
411 			output(OPT_implementation, s, "implementation");
412 		}
413 		if (flags & OPT_operating_system)
414 		{
415 			s = astconf("OPERATING_SYSTEM", NiL, NiL);
416 			if (!*s)
417 #ifdef _UNAME_os_DEFAULT
418 				s = _UNAME_os_DEFAULT;
419 #else
420 				s = ut.sysname;
421 #endif
422 			output(OPT_operating_system, s, "operating-system");
423 		}
424 		if (flags & OPT_extended_release)
425 		{
426 			s = astconf("RELEASE", NiL, NiL);
427 			output(OPT_extended_release, s, "extended-release");
428 		}
429 #if _mem_idnumber_utsname
430 		output(OPT_hostid, ut.idnumber, "hostid");
431 #else
432 		if (flags & OPT_hostid)
433 		{
434 			if (!*(s = astconf("HW_SERIAL", NiL, NiL)))
435 #if _lib_gethostid
436 				sfsprintf(s = buf, sizeof(buf), "%08x", gethostid());
437 #else
438 				{/*NOP*/};
439 #endif
440 			output(OPT_hostid, s, "hostid");
441 		}
442 #endif
443 		if (flags & OPT_vendor)
444 		{
445 			s = astconf("HW_PROVIDER", NiL, NiL);
446 			output(OPT_vendor, s, "vendor");
447 		}
448 		if (flags & OPT_domain)
449 		{
450 			if (!*(s = astconf("SRPC_DOMAIN", NiL, NiL)))
451 #if _lib_getdomainname
452 				getdomainname(s, sizeof(buf));
453 #else
454 				{/*NOP*/};
455 #endif
456 			output(OPT_domain, s, "domain");
457 		}
458 #if _mem_m_type_utsname
459 		s = ut.m_type;
460 #else
461 		s = astconf("MACHINE", NiL, NiL);
462 #endif
463 		output(OPT_machine_type, s, "m_type");
464 #if _mem_base_rel_utsname
465 		s = ut.base_rel;
466 #else
467 		s = astconf("BASE", NiL, NiL);
468 #endif
469 		output(OPT_base, s, "base_rel");
470 		if (flags & OPT_extra)
471 		{
472 			char*	last = (char*)&ut;
473 
474 			extra(sysname);
475 			extra(nodename);
476 			extra(release);
477 			extra(version);
478 			extra(machine);
479 #if _mem_idnumber_utsname
480 			extra(idnumber);
481 #endif
482 #if _mem_m_type_utsname
483 			extra(m_type);
484 #endif
485 #if _mem_base_rel_utsname
486 			extra(base_rel);
487 #endif
488 			if (last < ((char*)(&ut + 1)))
489 			{
490 				s = t = last;
491 				while (s < (char*)(&ut + 1))
492 				{
493 					if (!(n = *s++))
494 					{
495 						if ((s - t) > 1)
496 						{
497 							if (sep)
498 								sfputc(sfstdout, ' ');
499 							else
500 								sep = 1;
501 							sfputr(sfstdout, t, -1);
502 						}
503 						t = s;
504 					}
505 					else if (!isprint(n))
506 						break;
507 				}
508 			}
509 		}
510 		if (sep)
511 			sfputc(sfstdout, '\n');
512 	}
513 	return error_info.errors;
514 }
515