diff options
author | peter <peter@FreeBSD.org> | 1995-07-09 02:49:30 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1995-07-09 02:49:30 +0000 |
commit | 0e9d5904c5f4ac85436f5db08213874f2488f5c1 (patch) | |
tree | bb30fae451eb0a4e14c08570bff7ad2211e25b58 /sys | |
parent | 0fb5fcb5e49ebc6a268a5f78625115b2f9b37aa1 (diff) | |
download | FreeBSD-src-0e9d5904c5f4ac85436f5db08213874f2488f5c1.zip FreeBSD-src-0e9d5904c5f4ac85436f5db08213874f2488f5c1.tar.gz |
This implements enough of the BSDI extensions to the net-2 ogetkerninfo()
syscall to allow applications linked against their libc's uname() to
work. Netscape 1.1N being a prime example, which prints:
"uname() failed. cant tell what system we're running on".
This change is a little ugly, but that's mainly because of the "interesting"
semantics of the BSDI extension.
Since ogetkerninfo() is only enabled by COMPAT_43, Netscape will only
be affected on kernels with that option (eg: "GENERIC")
Reviewed by: davidg
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/kern_sysctl.c | 113 |
1 files changed, 112 insertions, 1 deletions
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index cec5d55..b987f07 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94 - * $Id: kern_sysctl.c,v 1.24 1995/05/12 19:17:31 wollman Exp $ + * $Id: kern_sysctl.c,v 1.25 1995/05/30 08:05:46 rgrimes Exp $ */ /* @@ -767,6 +767,53 @@ fill_eproc(p, ep) #define KINFO_LOADAVG (5<<8) #define KINFO_CLOCKRATE (6<<8) +/* Non-standard BSDI extension - only present on their 4.3 net-2 releases */ +#define KINFO_BSDI_SYSINFO (101<<8) + +/* + * XXX this is bloat, but I hope it's better here than on the potentially + * limited kernel stack... -Peter + */ + +struct { + int bsdi_machine; /* "i386" on BSD/386 */ +/* ^^^ this is an offset to the string, relative to the struct start */ + char *pad0; + long pad1; + long pad2; + long pad3; + u_long pad4; + u_long pad5; + u_long pad6; + + int bsdi_ostype; /* "BSD/386" on BSD/386 */ + int bsdi_osrelease; /* "1.1" on BSD/386 */ + long pad7; + long pad8; + char *pad9; + + long pad10; + long pad11; + int pad12; + long pad13; + quad_t pad14; + long pad15; + + struct timeval pad16; + /* we dont set this, because BSDI's uname used gethostname() instead */ + int bsdi_hostname; /* hostname on BSD/386 */ + + /* the actual string data is appended here */ + +} bsdi_si; +/* + * this data is appended to the end of the bsdi_si structure during copyout. + * The "char *" offsets are relative to the base of the bsdi_si struct. + * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings + * should not exceed the length of the buffer here... (or else!! :-) + */ +char bsdi_strings[80]; /* It had better be less than this! */ + struct getkerninfo_args { int op; char *where; @@ -830,6 +877,70 @@ ogetkerninfo(p, uap, retval) error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); break; + case KINFO_BSDI_SYSINFO: { + /* + * this is pretty crude, but it's just enough for uname() + * from BSDI's 1.x libc to work. + * + * In particular, it doesn't return the same results when + * the supplied buffer is too small. BSDI's version apparently + * will return the amount copied, and set the *size to how + * much was needed. The emulation framework here isn't capable + * of that, so we just set both to the amount copied. + * BSDI's 2.x product apparently fails with ENOMEM in this + * scenario. + */ + + u_int needed; + u_int left; + char *s; + + bzero((char *)&bsdi_si, sizeof(bsdi_si)); + bzero(bsdi_strings, sizeof(bsdi_strings)); + + s = bsdi_strings; + + bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si); + strcpy(s, ostype); + s += strlen(s) + 1; + + bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si); + strcpy(s, osrelease); + s += strlen(s) + 1; + + bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si); + strcpy(s, machine); + s += strlen(s) + 1; + + needed = sizeof(bsdi_si) + (s - bsdi_strings); + + if (uap->where == NULL) { + /* process is asking how much buffer to supply.. */ + size = needed; + error = 0; + break; + } + + + /* if too much buffer supplied, trim it down */ + if (size > needed) + size = needed; + + /* how much of the buffer is remaining */ + left = size; + + if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0) + break; + + /* is there any point in continuing? */ + if (left > sizeof(bsdi_si)) { + left -= sizeof(bsdi_si); + error = copyout(&bsdi_strings, + uap->where + sizeof(bsdi_si), left); + } + break; + } + default: return (EOPNOTSUPP); } |