summaryrefslogtreecommitdiff
path: root/pkgtools/libkver/files/lib/kver.c
blob: 1e6abd168c3e8af92b2bae993f40574c544fe3de (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*	$NetBSD: kver.c,v 1.2 2003/09/30 19:13:30 seb Exp $	*/

#include <sys/types.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/utsname.h>
#include <assert.h>
#include <errno.h>
#include <string.h>

#define KVER_VERSION_FMT "NetBSD %.6s (GENERIC) #0: %.40s  root@localhost:/sys/arch/%.20s/compile/GENERIC"

/* _KVER_DATE is not really the real release date but the
   date of src/sys/sys/param.h's revision tagged for the release */

#if   _KVER_OSREVISION == 105000000
#  define _KVER_OSRELEASE "1.5"
#  define _KVER_DATE "Wed Dec  6 00:00:00 UTC 2000"
#elif _KVER_OSREVISION == 105000100
#  define _KVER_OSRELEASE "1.5.1"
#  define _KVER_DATE "Wed Jul 11 00:00:00 UTC 2001"
#elif _KVER_OSREVISION == 105000200
#  define _KVER_OSRELEASE "1.5.2"
#  define _KVER_DATE "Thu Sep 13 00:00:00 UTC 2001"
#elif _KVER_OSREVISION == 105000300
#  define _KVER_OSRELEASE "1.5.3"
#  define _KVER_DATE "Mon Jul 22 00:00:00 UTC 2002"
#elif _KVER_OSREVISION == 106000000
#  define _KVER_OSRELEASE "1.6"
#  define _KVER_DATE "Sat Sep 14 00:00:00 UTC 2002"
#elif _KVER_OSREVISION == 106000100
#  define _KVER_OSRELEASE "1.6.1";
#  define _KVER_DATE "Mon Apr 21 00:00:00 UTC 2003"
#else
#error You must define _KVER_OSREVISION
#endif

static char *kver_osrelease = _KVER_OSRELEASE;
static char *kver_date = _KVER_DATE;
static int kver_osrevision = _KVER_OSREVISION;

#define SYSCTL_STRING(oldp, oldlenp, str)				\
	if (oldlenp) {							\
		len = strlen(str) + 1;					\
		if (!oldp)						\
			*oldlenp = len;					\
		else {							\
			if (*oldlenp < len) {				\
				r = ENOMEM;				\
				len = *oldlenp;				\
			} else						\
				*oldlenp = len;				\
			(void) strncpy(oldp, str, len);			\
		}							\
	}

/* 6  chars for osrelease */
/* 40 chars for the date string */
/* 20 chars for utsname.machine */
#define KVER_VERSION_LEN	(sizeof(KVER_VERSION_FMT) + 6 + 40 + 20 + 1)
static char kver_version[KVER_VERSION_LEN] = "";
static struct utsname real_utsname;

static void
kver_init(void)
{
	if (_uname(&real_utsname) != 0)
		return;
	snprintf(kver_version, KVER_VERSION_LEN, KVER_VERSION_FMT,
		kver_osrelease,
		kver_date,
		real_utsname.machine);
}

int
sysctl(int *name, u_int namelen, void *oldp, size_t * oldlenp, const void *newp,
    size_t newlen)
{
	_DIAGASSERT(name != NULL);

	if (newp != (void *) NULL)
		goto real;

	if (namelen != 2) {
		errno = EINVAL;
		return (-1);
	}

	if (*kver_version == '\0') {
		kver_init();
		if (*kver_version == '\0')
			return(-1);
	}

	if (name[0] == CTL_KERN) {
		size_t len;
		int r = 0;
		switch (name[1]) {
		case KERN_OSRELEASE:
			SYSCTL_STRING(oldp, oldlenp, kver_osrelease);
			return (r);
		case KERN_OSREV:
			if (oldlenp) {
				if (!oldp)
					*oldlenp = sizeof(int);
				else {
					if (*oldlenp < sizeof(int))
						return (ENOMEM);
					*oldlenp = sizeof(int);
					*((int *) oldp) = kver_osrevision;
				}
			}
			return (r);
		case KERN_VERSION:
			SYSCTL_STRING(oldp, oldlenp, kver_version);
			return (r);
		}
	}
real:	return (_sysctl(name, namelen, oldp, oldlenp, newp, newlen));
}


int
uname(struct utsname * n)
{
	if (*kver_version == '\0') {
		kver_init();
		if (*kver_version == '\0')
			return(-1);
	}
	(void) strncpy(n->sysname, real_utsname.sysname, _SYS_NMLN);
	(void) strncpy(n->nodename, real_utsname.nodename, _SYS_NMLN);
	(void) strncpy(n->release, kver_osrelease, _SYS_NMLN);
	(void) strncpy(n->version, kver_version, _SYS_NMLN);
	(void) strncpy(n->machine, real_utsname.machine, _SYS_NMLN);
	return 0;
}