diff options
author | David Greenman <dg@FreeBSD.org> | 1995-08-20 03:12:38 +0000 |
---|---|---|
committer | David Greenman <dg@FreeBSD.org> | 1995-08-20 03:12:38 +0000 |
commit | b3bdc8938eb682f653f8d57a38d9dd749bda252c (patch) | |
tree | 0091bd15cc8967a0e2e2db5dfda8d9e6e95894e6 | |
parent | e8991fa32b1348823c70af7ce83a8006a7b4aa86 (diff) |
Notes
-rw-r--r-- | sys/kern/kern_sysctl.c | 149 |
1 files changed, 136 insertions, 13 deletions
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index 76f809fbeb99c..ad4f6cb6452e3 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.25 1995/05/30 08:05:46 rgrimes Exp $ + * $Id: kern_sysctl.c,v 1.25.4.1 1995/07/29 05:14:28 davidg Exp $ */ /* @@ -250,14 +250,16 @@ kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) case KERN_HOSTNAME: error = sysctl_string(oldp, oldlenp, newp, newlen, hostname, sizeof(hostname)); - if (newp && !error) - hostnamelen = newlen; + if (newp) + if (error == 0 || error == ENOMEM) + hostnamelen = newlen; return (error); case KERN_DOMAINNAME: error = sysctl_string(oldp, oldlenp, newp, newlen, domainname, sizeof(domainname)); - if (newp && !error) - domainnamelen = newlen; + if (newp) + if (error == 0 || error == ENOMEM) + domainnamelen = newlen; return (error); case KERN_HOSTID: inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */ @@ -458,22 +460,28 @@ sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) char *str; int maxlen; { - int len, error = 0; + int len, error = 0, rval = 0; len = strlen(str) + 1; - if (oldp && *oldlenp < len) + if (oldp && *oldlenp < len) { len = *oldlenp; + rval = ENOMEM; + } if (newp && newlen >= maxlen) return (EINVAL); if (oldp) { *oldlenp = len; error = copyout(str, oldp, len); + if (error) + rval = error; } - if (error == 0 && newp) { + if ((error == 0 || error == ENOMEM) && newp) { error = copyin(newp, str, newlen); + if (error) + rval = error; str[newlen] = 0; } - return (error); + return (rval); } /* @@ -486,17 +494,21 @@ sysctl_rdstring(oldp, oldlenp, newp, str) void *newp; char *str; { - int len, error = 0; + int len, error = 0, rval = 0; len = strlen(str) + 1; - if (oldp && *oldlenp < len) - return (ENOMEM); + if (oldp && *oldlenp < len) { + len = *oldlenp; + rval = ENOMEM; + } if (newp) return (EPERM); *oldlenp = len; if (oldp) error = copyout(str, oldp, len); - return (error); + if (error) + rval = error; + return (rval); } /* @@ -768,6 +780,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; @@ -831,6 +890,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); } |