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