- int error, name[6];
- size_t size;
-
- switch (uap->op & 0xff00) {
-
- case KINFO_RT:
- name[0] = CTL_NET;
- name[1] = PF_ROUTE;
- name[2] = 0;
- name[3] = (uap->op & 0xff0000) >> 16;
- name[4] = uap->op & 0xff;
- name[5] = uap->arg;
- error = userland_sysctl(p, name, 6, uap->where, uap->size,
- 0, 0, 0, &size);
- break;
-
- case KINFO_VNODE:
- name[0] = CTL_KERN;
- name[1] = KERN_VNODE;
- error = userland_sysctl(p, name, 2, uap->where, uap->size,
- 0, 0, 0, &size);
- break;
-
- case KINFO_PROC:
- name[0] = CTL_KERN;
- name[1] = KERN_PROC;
- name[2] = uap->op & 0xff;
- name[3] = uap->arg;
- error = userland_sysctl(p, name, 4, uap->where, uap->size,
- 0, 0, 0, &size);
- break;
-
- case KINFO_FILE:
- name[0] = CTL_KERN;
- name[1] = KERN_FILE;
- error = userland_sysctl(p, name, 2, uap->where, uap->size,
- 0, 0, 0, &size);
- break;
-
- case KINFO_METER:
- name[0] = CTL_VM;
- name[1] = VM_METER;
- error = userland_sysctl(p, name, 2, uap->where, uap->size,
- 0, 0, 0, &size);
- break;
-
- case KINFO_LOADAVG:
- name[0] = CTL_VM;
- name[1] = VM_LOADAVG;
- error = userland_sysctl(p, name, 2, uap->where, uap->size,
- 0, 0, 0, &size);
- break;
-
- case KINFO_CLOCKRATE:
- name[0] = CTL_KERN;
- name[1] = KERN_CLOCKRATE;
- error = userland_sysctl(p, name, 2, uap->where, uap->size,
- 0, 0, 0, &size);
- 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);
- }
- if (error)
- return (error);
- p->p_retval[0] = size;
- if (uap->size)
- error = copyout((caddr_t)&size, (caddr_t)uap->size,
- sizeof(size));
- return (error);