1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1992-2010 AT&T Intellectual Property          *
5*                      and is licensed under the                       *
6*                  Common Public License, Version 1.0                  *
7*                    by AT&T Intellectual Property                     *
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
30static const char usage[] =
31"[-?\n@(#)$Id: uname (AT&T Research) 2007-04-19 $\n]"
32USAGE_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
104extern int	getdomainname(char*, size_t);
105#endif
106#if _lib_gethostid
107extern long	gethostid(void);
108#endif
109#if _lib_gethostname
110extern int	gethostname(char*, size_t);
111#endif
112#if _lib_sethostname
113extern int	sethostname(const char*, size_t);
114#endif
115
116#ifndef HOSTTYPE
117#define HOSTTYPE	"unknown"
118#endif
119
120static 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
136struct utsname
137{
138	char*	sysname;
139	char	nodename[MAXHOSTNAME];
140	char*	release;
141	char*	version;
142	char*	machine;
143};
144
145int
146uname(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
251int
252b_uname(int argc, char** argv, void* 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