xref: /dragonfly/usr.bin/uname/uname.c (revision 3170ffd7)
1 /*-
2  * Copyright (c) 2002 Juli Mallett.
3  * Copyright (c) 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 4. Neither the name of the University nor the names of its contributors
15  *    may be used to endorse or promote products derived from this software
16  *    without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * @(#) Copyright (c) 1993 The Regents of the University of California.  All rights reserved.
31  * @(#)uname.c	8.2 (Berkeley) 5/4/95
32  * $FreeBSD: src/usr.bin/uname/uname.c,v 1.4.6.2 2002/10/17 07:47:29 jmallett Exp $
33  */
34 
35 #include <sys/param.h>
36 #include <sys/sysctl.h>
37 #include <sys/varsym.h>
38 
39 #include <err.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <unistd.h>
43 #include <string.h>
44 
45 #define	MFLAG	0x01
46 #define	NFLAG	0x02
47 #define	PFLAG	0x04
48 #define	RFLAG	0x08
49 #define	SFLAG	0x10
50 #define	VFLAG	0x20
51 #define	IFLAG   0x40
52 
53 typedef void (*get_t)(void);
54 get_t get_ident, get_machine, get_hostname, get_arch;
55 get_t get_release, get_sysname, get_version;
56 
57 void native_ident(void);
58 void native_machine(void);
59 void native_hostname(void);
60 void native_arch(void);
61 void native_release(void);
62 void native_sysname(void);
63 void native_version(void);
64 void print_uname(u_int);
65 void setup_get(void);
66 void usage(void);
67 
68 char *ident, *machine, *hostname, *arch;
69 char *release, *sysname, *version;
70 int space;
71 
72 int
73 main(int argc, char *argv[])
74 {
75 	u_int flags;
76 	int ch;
77 
78 	setup_get();
79 	flags = 0;
80 
81 	while ((ch = getopt(argc, argv, "aimnprsv")) != -1)
82 		switch(ch) {
83 		case 'a':
84 			flags |= (MFLAG | NFLAG | RFLAG | SFLAG | VFLAG);
85 			break;
86 		case 'i':
87 			flags |= IFLAG;
88 			break;
89 		case 'm':
90 			flags |= MFLAG;
91 			break;
92 		case 'n':
93 			flags |= NFLAG;
94 			break;
95 		case 'p':
96 			flags |= PFLAG;
97 			break;
98 		case 'r':
99 			flags |= RFLAG;
100 			break;
101 		case 's':
102 			flags |= SFLAG;
103 			break;
104 		case 'v':
105 			flags |= VFLAG;
106 			break;
107 		case '?':
108 		default:
109 			usage();
110 		}
111 
112 	argc -= optind;
113 	argv += optind;
114 
115 	if (argc)
116 		usage();
117 
118 	if (!flags)
119 		flags |= SFLAG;
120 
121 	print_uname(flags);
122 	exit(0);
123 }
124 
125 /*
126  * Overrides.
127  *
128  * UNAME_x env variables have the highest priority
129  * UNAME_x varsyms have the next highest priority
130  * values retrieved from sysctls have the lowest priority
131  */
132 static
133 void
134 CHECK_ENV(const char *envname, get_t *getp, get_t nativep, char **varp)
135 {
136 	char buf[1024];
137 
138 	if ((*varp = getenv(envname)) == NULL) {
139 		if (varsym_get(VARSYM_ALL_MASK, envname,
140 			       buf, sizeof(buf)) < 0) {
141 			*getp = nativep;
142 			return;
143 		}
144 		*varp = strdup(buf);
145 	}
146 	*getp = NULL;
147 }
148 
149 void
150 setup_get(void)
151 {
152 	CHECK_ENV("UNAME_s", &get_sysname, native_sysname, &sysname);
153 	CHECK_ENV("UNAME_n", &get_hostname, native_hostname, &hostname);
154 	CHECK_ENV("UNAME_r", &get_release, native_release, &release);
155 	CHECK_ENV("UNAME_v", &get_version, native_version, &version);
156 	CHECK_ENV("UNAME_m", &get_machine, native_machine, &machine);
157 	CHECK_ENV("UNAME_p", &get_arch, native_arch, &arch);
158 	CHECK_ENV("UNAME_i", &get_ident, native_ident, &ident);
159 }
160 
161 #define	PRINT_FLAG(flags,flag,var)		\
162 	if ((flags & flag) == flag) {		\
163 		if (space)			\
164 			printf(" ");		\
165 		else				\
166 			space++;		\
167 		if (get_##var != NULL)		\
168 			(*get_##var)();		\
169 		printf("%s", var);		\
170 	}
171 
172 void
173 print_uname(u_int flags)
174 {
175 	PRINT_FLAG(flags, SFLAG, sysname);
176 	PRINT_FLAG(flags, NFLAG, hostname);
177 	PRINT_FLAG(flags, RFLAG, release);
178 	PRINT_FLAG(flags, VFLAG, version);
179 	PRINT_FLAG(flags, MFLAG, machine);
180 	PRINT_FLAG(flags, PFLAG, arch);
181 	PRINT_FLAG(flags, IFLAG, ident);
182 	printf("\n");
183 }
184 
185 #define	NATIVE_SYSCTL2_GET(var,mib0,mib1)	\
186 void						\
187 native_##var(void)				\
188 {						\
189 	int mib[] = { (mib0), (mib1) };		\
190 	size_t len;				\
191 	static char buf[1024];			\
192 	char **varp = &(var);			\
193 						\
194 	len = sizeof buf;			\
195 	if (sysctl(mib, sizeof mib / sizeof mib[0],	\
196 	   &buf, &len, NULL, 0) == -1)		\
197 		err(1, "sysctl");
198 
199 #define	NATIVE_SYSCTLNAME_GET(var,name)		\
200 void						\
201 native_##var(void)				\
202 {						\
203 	size_t len;				\
204 	static char buf[1024];			\
205 	char **varp = &(var);			\
206 						\
207 	len = sizeof buf;			\
208 	if (sysctlbyname(name, &buf, &len, NULL,\
209 	    0) == -1)				\
210 		err(1, "sysctlbyname");
211 
212 #define	NATIVE_SET				\
213 	*varp = buf;				\
214 	return;					\
215 }	struct __hack
216 
217 #define	NATIVE_BUFFER	(buf)
218 #define	NATIVE_LENGTH	(len)
219 
220 NATIVE_SYSCTL2_GET(sysname, CTL_KERN, KERN_OSTYPE) {
221 } NATIVE_SET;
222 
223 NATIVE_SYSCTL2_GET(hostname, CTL_KERN, KERN_HOSTNAME) {
224 } NATIVE_SET;
225 
226 NATIVE_SYSCTL2_GET(release, CTL_KERN, KERN_OSRELEASE) {
227 } NATIVE_SET;
228 
229 NATIVE_SYSCTL2_GET(version, CTL_KERN, KERN_VERSION) {
230 	size_t n;
231 	char *p;
232 
233 	p = NATIVE_BUFFER;
234 	n = NATIVE_LENGTH;
235 	for (; n--; ++p)
236 		if (*p == '\n' || *p == '\t')
237 			*p = ' ';
238 } NATIVE_SET;
239 
240 NATIVE_SYSCTL2_GET(machine, CTL_HW, HW_MACHINE) {
241 } NATIVE_SET;
242 
243 NATIVE_SYSCTL2_GET(arch, CTL_HW, HW_MACHINE_ARCH) {
244 } NATIVE_SET;
245 
246 NATIVE_SYSCTLNAME_GET(ident, "kern.ident") {
247 } NATIVE_SET;
248 
249 void
250 usage(void)
251 {
252 	fprintf(stderr, "usage: uname [-aimnprsv]\n");
253 	exit(1);
254 }
255