summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1995-07-09 02:49:30 +0000
committerpeter <peter@FreeBSD.org>1995-07-09 02:49:30 +0000
commit0e9d5904c5f4ac85436f5db08213874f2488f5c1 (patch)
treebb30fae451eb0a4e14c08570bff7ad2211e25b58
parent0fb5fcb5e49ebc6a268a5f78625115b2f9b37aa1 (diff)
downloadFreeBSD-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
-rw-r--r--sys/kern/kern_sysctl.c113
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);
}
OpenPOWER on IntegriCloud