diff options
Diffstat (limited to 'lib/libutil')
| -rw-r--r-- | lib/libutil/Makefile | 12 | ||||
| -rw-r--r-- | lib/libutil/daemon.c | 65 | ||||
| -rw-r--r-- | lib/libutil/getloadavg.3 | 68 | ||||
| -rw-r--r-- | lib/libutil/getloadavg.c | 93 | ||||
| -rw-r--r-- | lib/libutil/kvm.c | 1497 | ||||
| -rw-r--r-- | lib/libutil/login.c | 61 | ||||
| -rw-r--r-- | lib/libutil/login_tty.c | 53 | ||||
| -rw-r--r-- | lib/libutil/logout.c | 69 | ||||
| -rw-r--r-- | lib/libutil/logwtmp.c | 65 | ||||
| -rw-r--r-- | lib/libutil/pty.c | 127 | ||||
| -rw-r--r-- | lib/libutil/pwcache.3 | 100 | ||||
| -rw-r--r-- | lib/libutil/pwcache.c | 112 |
12 files changed, 2322 insertions, 0 deletions
diff --git a/lib/libutil/Makefile b/lib/libutil/Makefile new file mode 100644 index 000000000000..8f30077d9dd4 --- /dev/null +++ b/lib/libutil/Makefile @@ -0,0 +1,12 @@ +# @(#)Makefile 5.10 (Berkeley) 5/6/91 + +LIB= util +# kvm.c needs -I/sys +CFLAGS+=-DLIBC_SCCS -I/sys +SRCS= daemon.c getloadavg.c kvm.c login.c login_tty.c logout.c logwtmp.c \ + pty.c pwcache.c +MAN3= getloadavg.3 pwcache.3 + +MLINKS+=pwcache.3 user_from_uid.3 pwcache.3 group_from_gid.3 + +.include <bsd.lib.mk> diff --git a/lib/libutil/daemon.c b/lib/libutil/daemon.c new file mode 100644 index 000000000000..f4e663c8de26 --- /dev/null +++ b/lib/libutil/daemon.c @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)daemon.c 5.3 (Berkeley) 12/28/90"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/fcntl.h> +#include <unistd.h> +#include <paths.h> + +daemon(nochdir, noclose) + int nochdir, noclose; +{ + int cpid; + + if ((cpid = fork()) == -1) + return (-1); + if (cpid) + exit(0); + (void) setsid(); + if (!nochdir) + (void) chdir("/"); + if (!noclose) { + int devnull = open(_PATH_DEVNULL, O_RDWR, 0); + + if (devnull != -1) { + (void) dup2(devnull, STDIN_FILENO); + (void) dup2(devnull, STDOUT_FILENO); + (void) dup2(devnull, STDERR_FILENO); + if (devnull > 2) + (void) close(devnull); + } + } +} diff --git a/lib/libutil/getloadavg.3 b/lib/libutil/getloadavg.3 new file mode 100644 index 000000000000..6864ec773cec --- /dev/null +++ b/lib/libutil/getloadavg.3 @@ -0,0 +1,68 @@ +.\" Copyright (c) 1989, 1991 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)getloadavg.3 6.3 (Berkeley) 4/19/91 +.\" +.Dd April 19, 1991 +.Dt GETLOADAVG 3 +.Os +.Sh NAME +.Nm getloadavg +.Nd get system load averages +.Sh SYNOPSIS +.Fn getloadavg "double loadavg[]" "int nelem" +.Sh DESCRIPTION +The +.Fn getloadavg +function +returns the number of processes in the system run queue +averaged over various periods of time. Up to +.Fa nelem +samples are retrieved and assigned to successive elements of +.Fa loadavg Ns Bq . +The system imposes a maximum of 3 samples, representing averages +over the last 1, 5, and 15 minutes, respectively. +.Sh DIAGNOSTICS +If the load average was unobtainable, \-1 is returned; otherwise, +the number of samples actually retrieved is returned. +.Sh SEE ALSO +.Xr uptime 1 , +.Xr nlist 3 , +.Xr kmem 4 +.Sh HISTORY +The +.Fn getloadavg +function is +.Ud . +.Sh BUGS +Programs using this utility must have read permission on +.Pa /dev/kmem . +This restriction will eventually be lifted. diff --git a/lib/libutil/getloadavg.c b/lib/libutil/getloadavg.c new file mode 100644 index 000000000000..8f6fb0bcaa86 --- /dev/null +++ b/lib/libutil/getloadavg.c @@ -0,0 +1,93 @@ +/*- + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)getloadavg.c 6.2 (Berkeley) 6/29/90"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/file.h> +#include <nlist.h> + +static struct nlist nl[] = { + { "_averunnable" }, +#define X_AVERUNNABLE 0 + { "_fscale" }, +#define X_FSCALE 1 + { "" }, +}; + +/* + * getloadavg() -- Get system load averages. + * + * Put `nelem' samples into `loadavg' array. + * Return number of samples retrieved, or -1 on error. + */ +getloadavg(loadavg, nelem) + double loadavg[]; + int nelem; +{ + static int need_nlist = 1; + fixpt_t averunnable[3]; + int fscale, kmemfd, i; + int alreadyopen; + + if ((alreadyopen = kvm_openfiles(NULL, NULL, NULL)) == -1) + return (-1); + /* + * cache nlist + */ + if (need_nlist) { + if (kvm_nlist(nl) != 0) + goto bad; + need_nlist = 0; + } + if (kvm_read((off_t)nl[X_AVERUNNABLE].n_value, (char *)averunnable, + sizeof(averunnable)) != sizeof(averunnable)) + goto bad; + if (kvm_read( (off_t)nl[X_FSCALE].n_value, (char *)&fscale, + sizeof(fscale)) != sizeof(fscale)) + goto bad; + nelem = MIN(nelem, sizeof(averunnable) / sizeof(averunnable[0])); + for (i = 0; i < nelem; i++) + loadavg[i] = (double) averunnable[i] / fscale; + if (!alreadyopen) + kvm_close(); + return (nelem); + +bad: + if (!alreadyopen) + kvm_close(); + return (-1); +} diff --git a/lib/libutil/kvm.c b/lib/libutil/kvm.c new file mode 100644 index 000000000000..96121cbb454a --- /dev/null +++ b/lib/libutil/kvm.c @@ -0,0 +1,1497 @@ +/*- + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE + * -------------------- ----- ---------------------- + * CURRENT PATCH LEVEL: 3 00136 + * -------------------- ----- ---------------------- + * + * 08 Sep 92 Greenman & Kranenburg Change vaddr calc, move bogus #endif + * 05 Aug 92 David Greenman Fix kernel namelist db create/use + * 08 Aug 93 Paul Kranenburg Fix for command line args from ps and w + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)kvm.c 5.18 (Berkeley) 5/7/91"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Updated for 386BSD 0.1 by David Greenman (davidg%implode@percy.rain.com) + * and Paul Kranenburg (pk@cs.few.eur.nl) + * 20-Aug-1992 + * And again by same on 04-Aug-1993 + */ + + +#include <sys/param.h> +#include <sys/user.h> +#include <sys/proc.h> +#include <sys/ioctl.h> +#include <sys/kinfo.h> +#include <sys/tty.h> +#include <machine/vmparam.h> +#include <fcntl.h> +#include <nlist.h> +#include <kvm.h> +#include <ndbm.h> +#include <limits.h> +#include <paths.h> +#include <stdio.h> +#include <string.h> + +#ifdef SPPWAIT +#define NEWVM +#endif + +#ifdef NEWVM +#define btop(x) (((unsigned)(x)) >> PGSHIFT) /* XXX */ +#define ptob(x) ((caddr_t)((x) << PGSHIFT)) /* XXX */ +#include <vm/vm.h> /* ??? kinfo_proc currently includes this*/ +#include <vm/vm_page.h> +#include <vm/swap_pager.h> +#include <sys/kinfo_proc.h> +#ifdef hp300 +#include <hp300/hp300/pte.h> +#endif +#else /* NEWVM */ +#include <machine/pte.h> +#include <sys/vmmac.h> +#include <sys/text.h> +#endif /* NEWVM */ + +/* + * files + */ +static const char *unixf, *memf, *kmemf, *swapf; +static int unixx, mem, kmem, swap; +static DBM *db; +/* + * flags + */ +static int deadkernel; +static int kvminit = 0; +static int kvmfilesopen = 0; +/* + * state + */ +static struct kinfo_proc *kvmprocbase, *kvmprocptr; +static int kvmnprocs; +/* + * u. buffer + */ +static union { + struct user user; + char upages[UPAGES][NBPG]; +} user; + +#ifdef NEWVM +struct swapblk { + long offset; /* offset in swap device */ + long size; /* remaining size of block in swap device */ +}; +#endif +/* + * random other stuff + */ +#ifndef NEWVM +static struct pte *Usrptmap, *usrpt; +static struct pte *Sysmap; +static int Syssize; +#endif +static int dmmin, dmmax; +static int pcbpf; +static int argaddr0; /* XXX */ +static int argaddr1; +static int swaddr; +static int nswap; +static char *tmp; +#if defined(hp300) +static int lowram; +static struct ste *Sysseg; +#endif +#if defined(i386) +static struct pde *PTD; +#endif + +#define basename(cp) ((tmp=rindex((cp), '/')) ? tmp+1 : (cp)) +#define MAXSYMSIZE 256 + +#if defined(hp300) +#define pftoc(f) ((f) - lowram) +#define iskva(v) (1) +#endif + +#ifndef pftoc +#define pftoc(f) (f) +#endif +#ifndef iskva +#define iskva(v) ((u_long)(v) & KERNBASE) +#endif + +static struct nlist nl[] = { + { "_Usrptmap" }, +#define X_USRPTMAP 0 + { "_usrpt" }, +#define X_USRPT 1 + { "_nswap" }, +#define X_NSWAP 2 + { "_dmmin" }, +#define X_DMMIN 3 + { "_dmmax" }, +#define X_DMMAX 4 + { "_vm_page_buckets" }, +#define X_VM_PAGE_BUCKETS 5 + { "_vm_page_hash_mask" }, +#define X_VM_PAGE_HASH_MASK 6 + { "_page_shift" }, +#define X_PAGE_SHIFT 7 + /* + * everything here and down, only if a dead kernel + */ + { "_Sysmap" }, +#define X_SYSMAP 8 +#define X_DEADKERNEL X_SYSMAP + { "_Syssize" }, +#define X_SYSSIZE 9 + { "_allproc" }, +#define X_ALLPROC 10 + { "_zombproc" }, +#define X_ZOMBPROC 11 + { "_nproc" }, +#define X_NPROC 12 +#define X_LAST 12 +#if defined(hp300) + { "_Sysseg" }, +#define X_SYSSEG (X_LAST+1) + { "_lowram" }, +#define X_LOWRAM (X_LAST+2) +#endif +#if defined(i386) + { "_IdlePTD" }, +#define X_IdlePTD (X_LAST+1) +#endif + { "" }, +}; + +static off_t Vtophys(); +static void klseek(), seterr(), setsyserr(), vstodb(); +static int getkvars(), kvm_doprocs(), kvm_init(); +#ifdef NEWVM +static int vatosw(); +static int findpage(); +#endif + +/* + * returns 0 if files were opened now, + * 1 if files were already opened, + * -1 if files could not be opened. + */ +kvm_openfiles(uf, mf, sf) + const char *uf, *mf, *sf; +{ + if (kvmfilesopen) + return (1); + unixx = mem = kmem = swap = -1; + unixf = (uf == NULL) ? _PATH_UNIX : uf; + memf = (mf == NULL) ? _PATH_MEM : mf; + + if ((unixx = open(unixf, O_RDONLY, 0)) == -1) { + setsyserr("can't open %s", unixf); + goto failed; + } + if ((mem = open(memf, O_RDONLY, 0)) == -1) { + setsyserr("can't open %s", memf); + goto failed; + } + if (sf != NULL) + swapf = sf; + if (mf != NULL) { + deadkernel++; + kmemf = mf; + kmem = mem; + swap = -1; + } else { + kmemf = _PATH_KMEM; + if ((kmem = open(kmemf, O_RDONLY, 0)) == -1) { + setsyserr("can't open %s", kmemf); + goto failed; + } + swapf = (sf == NULL) ? _PATH_DRUM : sf; + /* + * live kernel - avoid looking up nlist entries + * past X_DEADKERNEL. + */ + nl[X_DEADKERNEL].n_name = ""; + } + if (swapf != NULL && ((swap = open(swapf, O_RDONLY, 0)) == -1)) { + seterr("can't open %s", swapf); + goto failed; + } + kvmfilesopen++; + if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1) /*XXX*/ + return (-1); + return (0); +failed: + kvm_close(); + return (-1); +} + +static +kvm_init(uf, mf, sf) + char *uf, *mf, *sf; +{ + if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1) + return (-1); + if (getkvars() == -1) + return (-1); + kvminit = 1; + + return (0); +} + +kvm_close() +{ + if (unixx != -1) { + close(unixx); + unixx = -1; + } + if (kmem != -1) { + if (kmem != mem) + close(kmem); + /* otherwise kmem is a copy of mem, and will be closed below */ + kmem = -1; + } + if (mem != -1) { + close(mem); + mem = -1; + } + if (swap != -1) { + close(swap); + swap = -1; + } + if (db != NULL) { + dbm_close(db); + db = NULL; + } + kvminit = 0; + kvmfilesopen = 0; + deadkernel = 0; +#ifndef NEWVM + if (Sysmap) { + free(Sysmap); + Sysmap = NULL; + } +#endif +} + +kvm_nlist(nl) + struct nlist *nl; +{ + datum key, data; + char dbname[MAXPATHLEN]; + char dbversion[_POSIX2_LINE_MAX]; + char kversion[_POSIX2_LINE_MAX]; + int dbversionlen; + char symbuf[MAXSYMSIZE]; + struct nlist nbuf, *n; + int num, did; + + if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1) + return (-1); + if (deadkernel) + goto hard2; + /* + * initialize key datum + */ + key.dptr = symbuf; + + if (db != NULL) + goto win; /* off to the races */ + /* + * open database + */ + sprintf(dbname, "%s/kvm_%s", _PATH_VARRUN, basename(unixf)); + if ((db = dbm_open(dbname, O_RDONLY, 0)) == NULL) + goto hard2; + /* + * read version out of database + */ + bcopy("VERSION", symbuf, sizeof ("VERSION")-1); + key.dsize = (sizeof ("VERSION") - 1); + data = dbm_fetch(db, key); + if (data.dptr == NULL) + goto hard1; + bcopy(data.dptr, dbversion, data.dsize); + dbversionlen = data.dsize; + /* + * read version string from kernel memory + */ + bcopy("_version", symbuf, sizeof ("_version")-1); + key.dsize = (sizeof ("_version")-1); + data = dbm_fetch(db, key); + if (data.dptr == NULL) + goto hard1; + if (data.dsize != sizeof (struct nlist)) + goto hard1; + bcopy(data.dptr, &nbuf, sizeof (struct nlist)); + lseek(kmem, nbuf.n_value, 0); + if (read(kmem, kversion, dbversionlen) != dbversionlen) + goto hard1; + /* + * if they match, we win - otherwise do it the hard way + */ + if (bcmp(dbversion, kversion, dbversionlen) != 0) + goto hard1; + /* + * getem from the database. + */ +win: + num = did = 0; + for (n = nl; n->n_name && n->n_name[0]; n++, num++) { + int len; + /* + * clear out fields from users buffer + */ + n->n_type = 0; + n->n_other = 0; + n->n_desc = 0; + n->n_value = 0; + /* + * query db + */ + if ((len = strlen(n->n_name)) > MAXSYMSIZE) { + seterr("symbol too large"); + return (-1); + } + (void)strcpy(symbuf, n->n_name); + key.dsize = len; + data = dbm_fetch(db, key); + if (data.dptr == NULL || data.dsize != sizeof (struct nlist)) + continue; + bcopy(data.dptr, &nbuf, sizeof (struct nlist)); + n->n_value = nbuf.n_value; + n->n_type = nbuf.n_type; + n->n_desc = nbuf.n_desc; + n->n_other = nbuf.n_other; + did++; + } + return (num - did); +hard1: + dbm_close(db); + db = NULL; +hard2: + num = nlist(unixf, nl); + if (num == -1) + seterr("nlist (hard way) failed"); + return (num); +} + +kvm_getprocs(what, arg) + int what, arg; +{ + static int ocopysize = -1; + + if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1) + return (NULL); + if (!deadkernel) { + int ret, copysize; + + if ((ret = getkerninfo(what, NULL, NULL, arg)) == -1) { + setsyserr("can't get estimate for kerninfo"); + return (-1); + } + copysize = ret; + if (copysize > ocopysize && + (kvmprocbase = (struct kinfo_proc *)malloc(copysize)) + == NULL) { + seterr("out of memory"); + return (-1); + } + ocopysize = copysize; + if ((ret = getkerninfo(what, kvmprocbase, ©size, + arg)) == -1) { + setsyserr("can't get proc list"); + return (-1); + } + if (copysize % sizeof (struct kinfo_proc)) { + seterr("proc size mismatch (got %d total, kinfo_proc: %d)", + copysize, sizeof (struct kinfo_proc)); + return (-1); + } + kvmnprocs = copysize / sizeof (struct kinfo_proc); + } else { + int nproc; + + if (kvm_read((void *) nl[X_NPROC].n_value, &nproc, + sizeof (int)) != sizeof (int)) { + seterr("can't read nproc"); + return (-1); + } + if ((kvmprocbase = (struct kinfo_proc *) + malloc(nproc * sizeof (struct kinfo_proc))) == NULL) { + seterr("out of memory (addr: %x nproc = %d)", + nl[X_NPROC].n_value, nproc); + return (-1); + } + kvmnprocs = kvm_doprocs(what, arg, kvmprocbase); + realloc(kvmprocbase, kvmnprocs * sizeof (struct kinfo_proc)); + } + kvmprocptr = kvmprocbase; + + return (kvmnprocs); +} + +/* + * XXX - should NOT give up so easily - especially since the kernel + * may be corrupt (it died). Should gather as much information as possible. + * Follows proc ptrs instead of reading table since table may go + * away soon. + */ +static +kvm_doprocs(what, arg, buff) + int what, arg; + char *buff; +{ + struct proc *p, proc; + register char *bp = buff; + int i = 0; + int doingzomb = 0; + struct eproc eproc; + struct pgrp pgrp; + struct session sess; + struct tty tty; +#ifndef NEWVM + struct text text; +#endif + + /* allproc */ + if (kvm_read((void *) nl[X_ALLPROC].n_value, &p, + sizeof (struct proc *)) != sizeof (struct proc *)) { + seterr("can't read allproc"); + return (-1); + } + +again: + for (; p; p = proc.p_nxt) { + if (kvm_read(p, &proc, sizeof (struct proc)) != + sizeof (struct proc)) { + seterr("can't read proc at %x", p); + return (-1); + } +#ifdef NEWVM + if (kvm_read(proc.p_cred, &eproc.e_pcred, + sizeof (struct pcred)) == sizeof (struct pcred)) + (void) kvm_read(eproc.e_pcred.pc_ucred, &eproc.e_ucred, + sizeof (struct ucred)); + switch(ki_op(what)) { + + case KINFO_PROC_PID: + if (proc.p_pid != (pid_t)arg) + continue; + break; + + + case KINFO_PROC_UID: + if (eproc.e_ucred.cr_uid != (uid_t)arg) + continue; + break; + + case KINFO_PROC_RUID: + if (eproc.e_pcred.p_ruid != (uid_t)arg) + continue; + break; + } +#else + switch(ki_op(what)) { + + case KINFO_PROC_PID: + if (proc.p_pid != (pid_t)arg) + continue; + break; + + + case KINFO_PROC_UID: + if (proc.p_uid != (uid_t)arg) + continue; + break; + + case KINFO_PROC_RUID: + if (proc.p_ruid != (uid_t)arg) + continue; + break; + } +#endif + /* + * gather eproc + */ + eproc.e_paddr = p; + if (kvm_read(proc.p_pgrp, &pgrp, sizeof (struct pgrp)) != + sizeof (struct pgrp)) { + seterr("can't read pgrp at %x", proc.p_pgrp); + return (-1); + } + eproc.e_sess = pgrp.pg_session; + eproc.e_pgid = pgrp.pg_id; + eproc.e_jobc = pgrp.pg_jobc; + if (kvm_read(pgrp.pg_session, &sess, sizeof (struct session)) + != sizeof (struct session)) { + seterr("can't read session at %x", pgrp.pg_session); + return (-1); + } + if ((proc.p_flag&SCTTY) && sess.s_ttyp != NULL) { + if (kvm_read(sess.s_ttyp, &tty, sizeof (struct tty)) + != sizeof (struct tty)) { + seterr("can't read tty at %x", sess.s_ttyp); + return (-1); + } + eproc.e_tdev = tty.t_dev; + eproc.e_tsess = tty.t_session; + if (tty.t_pgrp != NULL) { + if (kvm_read(tty.t_pgrp, &pgrp, sizeof (struct + pgrp)) != sizeof (struct pgrp)) { + seterr("can't read tpgrp at &x", + tty.t_pgrp); + return (-1); + } + eproc.e_tpgid = pgrp.pg_id; + } else + eproc.e_tpgid = -1; + } else + eproc.e_tdev = NODEV; + if (proc.p_wmesg) + kvm_read(proc.p_wmesg, eproc.e_wmesg, WMESGLEN); +#ifdef NEWVM + (void) kvm_read(proc.p_vmspace, &eproc.e_vm, + sizeof (struct vmspace)); + eproc.e_xsize = eproc.e_xrssize = + eproc.e_xccount = eproc.e_xswrss = 0; +#else + if (proc.p_textp) { + kvm_read(proc.p_textp, &text, sizeof (text)); + eproc.e_xsize = text.x_size; + eproc.e_xrssize = text.x_rssize; + eproc.e_xccount = text.x_ccount; + eproc.e_xswrss = text.x_swrss; + } else { + eproc.e_xsize = eproc.e_xrssize = + eproc.e_xccount = eproc.e_xswrss = 0; + } +#endif + + switch(ki_op(what)) { + + case KINFO_PROC_PGRP: + if (eproc.e_pgid != (pid_t)arg) + continue; + break; + + case KINFO_PROC_TTY: + if ((proc.p_flag&SCTTY) == 0 || + eproc.e_tdev != (dev_t)arg) + continue; + break; + } + + i++; + bcopy(&proc, bp, sizeof (struct proc)); + bp += sizeof (struct proc); + bcopy(&eproc, bp, sizeof (struct eproc)); + bp+= sizeof (struct eproc); + } + if (!doingzomb) { + /* zombproc */ + if (kvm_read((void *) nl[X_ZOMBPROC].n_value, &p, + sizeof (struct proc *)) != sizeof (struct proc *)) { + seterr("can't read zombproc"); + return (-1); + } + doingzomb = 1; + goto again; + } + + return (i); +} + +struct proc * +kvm_nextproc() +{ + + if (!kvmprocbase && kvm_getprocs(0, 0) == -1) + return (NULL); + if (kvmprocptr >= (kvmprocbase + kvmnprocs)) { + seterr("end of proc list"); + return (NULL); + } + return((struct proc *)(kvmprocptr++)); +} + +struct eproc * +kvm_geteproc(p) + const struct proc *p; +{ + return ((struct eproc *)(((char *)p) + sizeof (struct proc))); +} + +kvm_setproc() +{ + kvmprocptr = kvmprocbase; +} + +kvm_freeprocs() +{ + + if (kvmprocbase) { + free(kvmprocbase); + kvmprocbase = NULL; + } +} + +#ifdef i386 +/* See also ./sys/kern/kern_execve.c */ +#define ARGSIZE (roundup(ARG_MAX, NBPG)) +#endif + +#ifdef NEWVM +struct user * +kvm_getu(p) + const struct proc *p; +{ + register struct kinfo_proc *kp = (struct kinfo_proc *)p; + register int i; + register char *up; + u_int vaddr; + struct swapblk swb; + + if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1) + return (NULL); + if (p->p_stat == SZOMB) { + seterr("zombie process"); + return (NULL); + } + + argaddr0 = argaddr1 = swaddr = 0; + if ((p->p_flag & SLOAD) == 0) { + vm_offset_t maddr; + + if (swap < 0) { + seterr("no swap"); + return (NULL); + } + /* + * Costly operation, better set enable_swap to zero + * in vm/vm_glue.c, since paging of user pages isn't + * done yet anyway. + */ + if (vatosw(p, USRSTACK + i * NBPG, &maddr, &swb) == 0) + return NULL; + + if (maddr == 0 && swb.size < UPAGES * NBPG) + return NULL; + + for (i = 0; i < UPAGES; i++) { + if (maddr) { + (void) lseek(mem, maddr + i * NBPG, 0); + if (read(mem, + (char *)user.upages[i], NBPG) != NBPG) { + seterr( + "can't read u for pid %d from %s", + p->p_pid, swapf); + return NULL; + } + } else { + (void) lseek(swap, swb.offset + i * NBPG, 0); + if (read(swap, + (char *)user.upages[i], NBPG) != NBPG) { + seterr( + "can't read u for pid %d from %s", + p->p_pid, swapf); + return NULL; + } + } + } + return(&user.user); + } + /* + * Read u-area one page at a time for the benefit of post-mortems + */ + up = (char *) p->p_addr; + for (i = 0; i < UPAGES; i++) { + klseek(kmem, (long)up, 0); + if (read(kmem, user.upages[i], CLBYTES) != CLBYTES) { + seterr("cant read page %x of u of pid %d from %s", + up, p->p_pid, kmemf); + return(NULL); + } + up += CLBYTES; + } + pcbpf = (int) btop(p->p_addr); /* what should this be really? */ + /* + * Conjure up a physical address for the arguments. + */ +#ifdef hp300 + if (kp->kp_eproc.e_vm.vm_pmap.pm_ptab) { + struct pte pte[CLSIZE*2]; + + klseek(kmem, + (long)&kp->kp_eproc.e_vm.vm_pmap.pm_ptab + [btoc(USRSTACK-CLBYTES*2)], 0); + if (read(kmem, (char *)&pte, sizeof(pte)) == sizeof(pte)) { +#if CLBYTES < 2048 + argaddr0 = ctob(pftoc(pte[CLSIZE*0].pg_pfnum)); +#endif + argaddr1 = ctob(pftoc(pte[CLSIZE*1].pg_pfnum)); + } + } +#endif + kp->kp_eproc.e_vm.vm_rssize = + kp->kp_eproc.e_vm.vm_pmap.pm_stats.resident_count; /* XXX */ + + vaddr = (u_int)kp->kp_eproc.e_vm.vm_maxsaddr + MAXSSIZ - ARGSIZE; + +#ifdef i386 + if (kp->kp_eproc.e_vm.vm_pmap.pm_pdir) { + struct pde pde; + + klseek(kmem, + (long)(&kp->kp_eproc.e_vm.vm_pmap.pm_pdir[pdei(vaddr)]), 0); + + if (read(kmem, (char *)&pde, sizeof pde) == sizeof pde + && pde.pd_v) { + + struct pte pte; + + if (lseek(mem, (long)ctob(pde.pd_pfnum) + + (ptei(vaddr) * sizeof pte), 0) == -1) + seterr("kvm_getu: lseek"); + if (read(mem, (char *)&pte, sizeof pte) == sizeof pte) { + if (pte.pg_v) { + argaddr1 = (long)ctob(pte.pg_pfnum); + } else { + goto hard; + } + } else { + seterr("kvm_getu: read"); + } + } else { + goto hard; + } + } +#endif /* i386 */ + +hard: + if (vatosw(p, vaddr, &argaddr1, &swb)) { + if (argaddr1 == 0 && swb.size >= ARGSIZE) + swaddr = swb.offset; + } + + return(&user.user); +} +#else +struct user * +kvm_getu(p) + const struct proc *p; +{ + struct pte *pteaddr, apte; + struct pte arguutl[HIGHPAGES+(CLSIZE*2)]; + register int i; + int ncl; + + if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1) + return (NULL); + if (p->p_stat == SZOMB) { + seterr("zombie process"); + return (NULL); + } + if ((p->p_flag & SLOAD) == 0) { + if (swap < 0) { + seterr("no swap"); + return (NULL); + } + (void) lseek(swap, (long)dtob(p->p_swaddr), 0); + if (read(swap, (char *)&user.user, sizeof (struct user)) != + sizeof (struct user)) { + seterr("can't read u for pid %d from %s", + p->p_pid, swapf); + return (NULL); + } + pcbpf = 0; + argaddr0 = 0; + argaddr1 = 0; + return (&user.user); + } + pteaddr = &Usrptmap[btokmx(p->p_p0br) + p->p_szpt - 1]; + klseek(kmem, (long)pteaddr, 0); + if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) { + seterr("can't read indir pte to get u for pid %d from %s", + p->p_pid, kmemf); + return (NULL); + } + lseek(mem, (long)ctob(pftoc(apte.pg_pfnum+1)) - sizeof(arguutl), 0); + if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) { + seterr("can't read page table for u of pid %d from %s", + p->p_pid, memf); + return (NULL); + } + if (arguutl[0].pg_fod == 0 && arguutl[0].pg_pfnum) + argaddr0 = ctob(pftoc(arguutl[0].pg_pfnum)); + else + argaddr0 = 0; + if (arguutl[CLSIZE*1].pg_fod == 0 && arguutl[CLSIZE*1].pg_pfnum) + argaddr1 = ctob(pftoc(arguutl[CLSIZE*1].pg_pfnum)); + else + argaddr1 = 0; + pcbpf = arguutl[CLSIZE*2].pg_pfnum; + ncl = (sizeof (struct user) + CLBYTES - 1) / CLBYTES; + while (--ncl >= 0) { + i = ncl * CLSIZE; + lseek(mem, + (long)ctob(pftoc(arguutl[(CLSIZE*2)+i].pg_pfnum)), 0); + if (read(mem, user.upages[i], CLBYTES) != CLBYTES) { + seterr("can't read page %d of u of pid %d from %s", + arguutl[(CLSIZE*2)+i].pg_pfnum, p->p_pid, memf); + return(NULL); + } + } + return (&user.user); +} +#endif + +char * +kvm_getargs(p, up) + const struct proc *p; + const struct user *up; +{ +#ifdef i386 + /* See also ./sys/kern/kern_execve.c */ + static char cmdbuf[ARGSIZE]; + static union { + char argc[ARGSIZE]; + int argi[ARGSIZE/sizeof (int)]; + } argspac; +#else + static char cmdbuf[CLBYTES*2]; + static union { + char argc[CLBYTES*2]; + int argi[CLBYTES*2/sizeof (int)]; + } argspac; +#endif + register char *cp; + register int *ip; + char c; + int nbad; +#ifndef NEWVM + struct dblock db; +#endif + const char *file; + int stkoff = 0; + +#if defined(NEWVM) && defined(hp300) + stkoff = 20; /* XXX for sigcode */ +#endif + if (up == NULL || p->p_pid == 0 || p->p_pid == 2) + goto retucomm; + if ((p->p_flag & SLOAD) == 0 || argaddr1 == 0) { +#ifdef NEWVM + if (swaddr == 0) + goto retucomm; /* XXX for now */ +#ifdef i386 + (void) lseek(swap, swaddr, 0); + if (read(swap, &argspac.argc[0], ARGSIZE) != ARGSIZE) + goto bad; +#else + if (argaddr0) { + lseek(swap, (long)argaddr0, 0); + if (read(swap, (char *)&argspac, CLBYTES) != CLBYTES) + goto bad; + } else + bzero(&argspac, CLBYTES); + lseek(swap, (long)argaddr1, 0); + if (read(swap, &argspac.argc[CLBYTES], CLBYTES) != CLBYTES) + goto bad; +#endif +#else + if (swap < 0 || p->p_ssize == 0) + goto retucomm; + vstodb(0, CLSIZE, &up->u_smap, &db, 1); + (void) lseek(swap, (long)dtob(db.db_base), 0); + if (read(swap, (char *)&argspac.argc[CLBYTES], CLBYTES) + != CLBYTES) + goto bad; + vstodb(1, CLSIZE, &up->u_smap, &db, 1); + (void) lseek(swap, (long)dtob(db.db_base), 0); + if (read(swap, (char *)&argspac.argc[0], CLBYTES) != CLBYTES) + goto bad; + file = swapf; +#endif + } else { +#ifdef i386 + lseek(mem, (long)argaddr1, 0); + if (read(mem, &argspac.argc[0], ARGSIZE) != ARGSIZE) + goto bad; +#else + if (argaddr0) { + lseek(mem, (long)argaddr0, 0); + if (read(mem, (char *)&argspac, CLBYTES) != CLBYTES) + goto bad; + } else + bzero(&argspac, CLBYTES); + lseek(mem, (long)argaddr1, 0); + if (read(mem, &argspac.argc[CLBYTES], CLBYTES) != CLBYTES) + goto bad; +#endif + file = (char *) memf; + } + + nbad = 0; +#ifdef i386 + ip = &argspac.argi[(ARGSIZE-ARG_MAX)/sizeof (int)]; + + for (cp = (char *)ip; cp < &argspac.argc[ARGSIZE-stkoff]; cp++) { +#else + ip = &argspac.argi[CLBYTES*2/sizeof (int)]; + ip -= 2; /* last arg word and .long 0 */ + ip -= stkoff / sizeof (int); + while (*--ip) { + if (ip == argspac.argi) + goto retucomm; + } + *(char *)ip = ' '; + ip++; + + for (cp = (char *)ip; cp < &argspac.argc[CLBYTES*2-stkoff]; cp++) { +#endif + c = *cp; + if (c == 0) { /* convert null between arguments to space */ + *cp = ' '; + if (*(cp+1) == 0) break; /* if null argument follows then no more args */ + } + else if (c < ' ' || c > 0176) { + if (++nbad >= 5*(0+1)) { /* eflg -> 0 XXX */ /* limit number of bad chars to 5 */ + *cp++ = '?'; + break; + } + *cp = '?'; + } + else if (0 == 0 && c == '=') { /* eflg -> 0 XXX */ + while (*--cp != ' ') + if (cp <= (char *)ip) + break; + break; + } + } + *cp = 0; + while (*--cp == ' ') + *cp = 0; + cp = (char *)ip; + (void) strcpy(cmdbuf, cp); + if (cp[0] == '-' || cp[0] == '?' || cp[0] <= ' ') { + (void) strcat(cmdbuf, " ("); + (void) strncat(cmdbuf, p->p_comm, sizeof(p->p_comm)); + (void) strcat(cmdbuf, ")"); + } + return (cmdbuf); + +bad: + seterr("error locating command name for pid %d from %s", + p->p_pid, file); +retucomm: + (void) strcpy(cmdbuf, " ("); + (void) strncat(cmdbuf, p->p_comm, sizeof (p->p_comm)); + (void) strcat(cmdbuf, ")"); + return (cmdbuf); +} + + +static +getkvars() +{ + if (kvm_nlist(nl) == -1) + return (-1); + if (deadkernel) { + /* We must do the sys map first because klseek uses it */ + long addr; + +#ifndef NEWVM + Syssize = nl[X_SYSSIZE].n_value; + Sysmap = (struct pte *) + calloc((unsigned) Syssize, sizeof (struct pte)); + if (Sysmap == NULL) { + seterr("out of space for Sysmap"); + return (-1); + } + addr = (long) nl[X_SYSMAP].n_value; + addr &= ~KERNBASE; + (void) lseek(kmem, addr, 0); + if (read(kmem, (char *) Sysmap, Syssize * sizeof (struct pte)) + != Syssize * sizeof (struct pte)) { + seterr("can't read Sysmap"); + return (-1); + } +#endif +#if defined(hp300) + addr = (long) nl[X_LOWRAM].n_value; + (void) lseek(kmem, addr, 0); + if (read(kmem, (char *) &lowram, sizeof (lowram)) + != sizeof (lowram)) { + seterr("can't read lowram"); + return (-1); + } + lowram = btop(lowram); + Sysseg = (struct ste *) malloc(NBPG); + if (Sysseg == NULL) { + seterr("out of space for Sysseg"); + return (-1); + } + addr = (long) nl[X_SYSSEG].n_value; + (void) lseek(kmem, addr, 0); + read(kmem, (char *)&addr, sizeof(addr)); + (void) lseek(kmem, (long)addr, 0); + if (read(kmem, (char *) Sysseg, NBPG) != NBPG) { + seterr("can't read Sysseg"); + return (-1); + } +#endif +#if defined(i386) + PTD = (struct pde *) malloc(NBPG); + if (PTD == NULL) { + seterr("out of space for PTD"); + return (-1); + } + addr = (long) nl[X_IdlePTD].n_value; + (void) lseek(kmem, addr, 0); + read(kmem, (char *)&addr, sizeof(addr)); + (void) lseek(kmem, (long)addr, 0); + if (read(kmem, (char *) PTD, NBPG) != NBPG) { + seterr("can't read PTD"); + return (-1); + } +#endif + } +#ifndef NEWVM + usrpt = (struct pte *)nl[X_USRPT].n_value; + Usrptmap = (struct pte *)nl[X_USRPTMAP].n_value; +#endif + if (kvm_read((void *) nl[X_NSWAP].n_value, &nswap, sizeof (long)) != + sizeof (long)) { + seterr("can't read nswap"); + return (-1); + } + if (kvm_read((void *) nl[X_DMMIN].n_value, &dmmin, sizeof (long)) != + sizeof (long)) { + seterr("can't read dmmin"); + return (-1); + } + if (kvm_read((void *) nl[X_DMMAX].n_value, &dmmax, sizeof (long)) != + sizeof (long)) { + seterr("can't read dmmax"); + return (-1); + } + return (0); +} + +kvm_read(loc, buf, len) + void *loc; + void *buf; +{ + if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1) + return (-1); + if (iskva(loc)) { + klseek(kmem, (off_t) loc, 0); + if (read(kmem, buf, len) != len) { + seterr("error reading kmem at %x", loc); + return (-1); + } + } else { + lseek(mem, (off_t) loc, 0); + if (read(mem, buf, len) != len) { + seterr("error reading mem at %x", loc); + return (-1); + } + } + return (len); +} + +static void +klseek(fd, loc, off) + int fd; + off_t loc; + int off; +{ + + if (deadkernel) { + if ((loc = Vtophys(loc)) == -1) + return; + } + (void) lseek(fd, (off_t)loc, off); +} + +#ifndef NEWVM +/* + * Given a base/size pair in virtual swap area, + * return a physical base/size pair which is the + * (largest) initial, physically contiguous block. + */ +static void +vstodb(vsbase, vssize, dmp, dbp, rev) + register int vsbase; + int vssize; + struct dmap *dmp; + register struct dblock *dbp; +{ + register int blk = dmmin; + register swblk_t *ip = dmp->dm_map; + + vsbase = ctod(vsbase); + vssize = ctod(vssize); + if (vsbase < 0 || vsbase + vssize > dmp->dm_size) + /*panic("vstodb")*/; + while (vsbase >= blk) { + vsbase -= blk; + if (blk < dmmax) + blk *= 2; + ip++; + } + if (*ip <= 0 || *ip + blk > nswap) + /*panic("vstodb")*/; + dbp->db_size = MIN(vssize, blk - vsbase); + dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase); +} +#endif + +#ifdef NEWVM +static off_t +Vtophys(loc) + u_long loc; +{ + off_t newloc = (off_t) -1; +#ifdef hp300 + int p, ste, pte; + + ste = *(int *)&Sysseg[loc >> SG_ISHIFT]; + if ((ste & SG_V) == 0) { + seterr("vtophys: segment not valid"); + return((off_t) -1); + } + p = btop(loc & SG_PMASK); + newloc = (ste & SG_FRAME) + (p * sizeof(struct pte)); + (void) lseek(kmem, (long)(newloc-(off_t)ptob(lowram)), 0); + if (read(kmem, (char *)&pte, sizeof pte) != sizeof pte) { + seterr("vtophys: cannot locate pte"); + return((off_t) -1); + } + newloc = pte & PG_FRAME; + if (pte == PG_NV || newloc < (off_t)ptob(lowram)) { + seterr("vtophys: page not valid"); + return((off_t) -1); + } + newloc = (newloc - (off_t)ptob(lowram)) + (loc & PGOFSET); +#endif +#ifdef i386 + struct pde pde; + struct pte pte; + int p; + + pde = PTD[loc >> PD_SHIFT]; + if (pde.pd_v == 0) { + seterr("vtophys: page directory entry not valid"); + return((off_t) -1); + } + p = btop(loc & PT_MASK); + newloc = pde.pd_pfnum + (p * sizeof(struct pte)); + (void) lseek(kmem, (long)newloc, 0); + if (read(kmem, (char *)&pte, sizeof pte) != sizeof pte) { + seterr("vtophys: cannot obtain desired pte"); + return((off_t) -1); + } + newloc = pte.pg_pfnum; + if (pte.pg_v == 0) { + seterr("vtophys: page table entry not valid"); + return((off_t) -1); + } + newloc += (loc & PGOFSET); +#endif + return((off_t) newloc); +} +#else +static off_t +vtophys(loc) + long loc; +{ + int p; + off_t newloc; + register struct pte *pte; + + newloc = loc & ~KERNBASE; + p = btop(newloc); +#if defined(vax) || defined(tahoe) + if ((loc & KERNBASE) == 0) { + seterr("vtophys: translating non-kernel address"); + return((off_t) -1); + } +#endif + if (p >= Syssize) { + seterr("vtophys: page out of bound (%d>=%d)", p, Syssize); + return((off_t) -1); + } + pte = &Sysmap[p]; + if (pte->pg_v == 0 && (pte->pg_fod || pte->pg_pfnum == 0)) { + seterr("vtophys: page not valid"); + return((off_t) -1); + } +#if defined(hp300) + if (pte->pg_pfnum < lowram) { + seterr("vtophys: non-RAM page (%d<%d)", pte->pg_pfnum, lowram); + return((off_t) -1); + } +#endif + loc = (long) (ptob(pftoc(pte->pg_pfnum)) + (loc & PGOFSET)); + return(loc); +} +#endif + + +#ifdef NEWVM +/* + * locate address of unwired or swapped page + */ + +#define DEBUG 0 + +#define KREAD(off, addr, len) \ + (kvm_read((void *)(off), (char *)(addr), (len)) == (len)) + + +static int +vatosw(p, vaddr, maddr, swb) +struct proc *p ; +vm_offset_t vaddr; +vm_offset_t *maddr; +struct swapblk *swb; +{ + register struct kinfo_proc *kp = (struct kinfo_proc *)p; + vm_map_t mp = &kp->kp_eproc.e_vm.vm_map; + struct vm_object vm_object; + struct vm_map_entry vm_entry; + struct pager_struct pager; + struct swpager swpager; + struct swblock swblock; + long addr, off; + int i; + + if (p->p_pid == 0 || p->p_pid == 2) + return 0; + + addr = (long)mp->header.next; + for (i = 0; i < mp->nentries; i++) { + /* Weed through map entries until vaddr in range */ + if (!KREAD(addr, &vm_entry, sizeof(vm_entry))) { + setsyserr("vatosw: read vm_map_entry"); + return 0; + } + if ((vaddr >= vm_entry.start) && (vaddr <= vm_entry.end) && + (vm_entry.object.vm_object != 0)) + break; + + addr = (long)vm_entry.next; + } + if (i == mp->nentries) { + seterr("%u: map not found\n", p->p_pid); + return 0; + } + + if (vm_entry.is_a_map || vm_entry.is_sub_map) { + seterr("%u: Is a map\n", p->p_pid); + return 0; + } + + /* Locate memory object */ + off = (vaddr - vm_entry.start) + vm_entry.offset; + addr = (long)vm_entry.object.vm_object; + while (1) { + if (!KREAD(addr, &vm_object, sizeof vm_object)) { + setsyserr("vatosw: read vm_object"); + return 0; + } + +#if DEBUG + fprintf(stderr, "%u: find page: object %#x offset %x\n", + p->p_pid, addr, off); +#endif + + /* Lookup in page queue */ + if (findpage(addr, off, maddr)) + return 1; + + if (vm_object.shadow == 0) + break; + +#if DEBUG + fprintf(stderr, "%u: shadow obj at %x: offset %x+%x\n", + p->p_pid, addr, off, vm_object.shadow_offset); +#endif + + addr = (long)vm_object.shadow; + off += vm_object.shadow_offset; + } + + if (!vm_object.pager) { + seterr("%u: no pager\n", p->p_pid); + return 0; + } + + /* Find address in swap space */ + if (!KREAD(vm_object.pager, &pager, sizeof pager)) { + setsyserr("vatosw: read pager"); + return 0; + } + if (pager.pg_type != PG_SWAP) { + seterr("%u: weird pager\n", p->p_pid); + return 0; + } + + /* Get swap pager data */ + if (!KREAD(pager.pg_data, &swpager, sizeof swpager)) { + setsyserr("vatosw: read swpager"); + return 0; + } + + off += vm_object.paging_offset; + + /* Read swap block array */ + if (!KREAD((long)swpager.sw_blocks + + (off/dbtob(swpager.sw_bsize)) * sizeof swblock, + &swblock, sizeof swblock)) { + setsyserr("vatosw: read swblock"); + return 0; + } + swb->offset = dbtob(swblock.swb_block)+ (off % dbtob(swpager.sw_bsize)); + swb->size = dbtob(swpager.sw_bsize) - (off % dbtob(swpager.sw_bsize)); + return 1; +} + + +#define atop(x) (((unsigned)(x)) >> page_shift) +#define vm_page_hash(object, offset) \ + (((unsigned)object+(unsigned)atop(offset))&vm_page_hash_mask) + +static int +findpage(object, offset, maddr) +long object; +long offset; +vm_offset_t *maddr; +{ +static long vm_page_hash_mask; +static long vm_page_buckets; +static long page_shift; + queue_head_t bucket; + struct vm_page mem; + long addr, baddr; + + if (vm_page_hash_mask == 0 && !KREAD(nl[X_VM_PAGE_HASH_MASK].n_value, + &vm_page_hash_mask, sizeof (long))) { + seterr("can't read vm_page_hash_mask"); + return 0; + } + if (page_shift == 0 && !KREAD(nl[X_PAGE_SHIFT].n_value, + &page_shift, sizeof (long))) { + seterr("can't read page_shift"); + return 0; + } + if (vm_page_buckets == 0 && !KREAD(nl[X_VM_PAGE_BUCKETS].n_value, + &vm_page_buckets, sizeof (long))) { + seterr("can't read vm_page_buckets"); + return 0; + } + + baddr = vm_page_buckets + vm_page_hash(object,offset) * sizeof(queue_head_t); + if (!KREAD(baddr, &bucket, sizeof (bucket))) { + seterr("can't read vm_page_bucket"); + return 0; + } + + addr = (long)bucket.next; + while (addr != baddr) { + if (!KREAD(addr, &mem, sizeof (mem))) { + seterr("can't read vm_page"); + return 0; + } + if ((long)mem.object == object && mem.offset == offset) { + *maddr = (long)mem.phys_addr; + return 1; + } + addr = (long)mem.hashq.next; + } + return 0; +} +#endif /* NEWVM */ + +#include <varargs.h> +static char errbuf[_POSIX2_LINE_MAX]; + +static void +seterr(va_alist) + va_dcl +{ + char *fmt; + va_list ap; + + va_start(ap); + fmt = va_arg(ap, char *); + (void) vsnprintf(errbuf, _POSIX2_LINE_MAX, fmt, ap); +#if DEBUG + (void) vfprintf(stderr, fmt, ap); +#endif + va_end(ap); +} + +static void +setsyserr(va_alist) + va_dcl +{ + char *fmt, *cp; + va_list ap; + extern int errno; + + va_start(ap); + fmt = va_arg(ap, char *); + (void) vsnprintf(errbuf, _POSIX2_LINE_MAX, fmt, ap); + for (cp=errbuf; *cp; cp++) + ; + snprintf(cp, _POSIX2_LINE_MAX - (cp - errbuf), ": %s", strerror(errno)); + va_end(ap); +} + +char * +kvm_geterr() +{ + return (errbuf); +} diff --git a/lib/libutil/login.c b/lib/libutil/login.c new file mode 100644 index 000000000000..6d3ffaaaefdd --- /dev/null +++ b/lib/libutil/login.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)login.c 5.4 (Berkeley) 6/1/90"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/types.h> +#include <sys/file.h> +#include <utmp.h> +#include <stdio.h> + +void +login(ut) + struct utmp *ut; +{ + register int fd; + int tty; + off_t lseek(); + + tty = ttyslot(); + if (tty > 0 && (fd = open(_PATH_UTMP, O_WRONLY|O_CREAT, 0644)) >= 0) { + (void)lseek(fd, (long)(tty * sizeof(struct utmp)), L_SET); + (void)write(fd, (char *)ut, sizeof(struct utmp)); + (void)close(fd); + } + if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) >= 0) { + (void)write(fd, (char *)ut, sizeof(struct utmp)); + (void)close(fd); + } +} diff --git a/lib/libutil/login_tty.c b/lib/libutil/login_tty.c new file mode 100644 index 000000000000..a5c841681905 --- /dev/null +++ b/lib/libutil/login_tty.c @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)login_tty.c 1.2 (Berkeley) 6/21/90"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/param.h> +#include <sys/ioctl.h> + +login_tty(fd) + int fd; +{ + (void) setsid(); + if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) + return (-1); + (void) dup2(fd, 0); + (void) dup2(fd, 1); + (void) dup2(fd, 2); + if (fd > 2) + (void) close(fd); + return (0); +} diff --git a/lib/libutil/logout.c b/lib/libutil/logout.c new file mode 100644 index 000000000000..8fbed5aca884 --- /dev/null +++ b/lib/libutil/logout.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)logout.c 5.5 (Berkeley) 6/1/90"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/types.h> +#include <sys/file.h> +#include <sys/time.h> +#include <utmp.h> + +typedef struct utmp UTMP; + +logout(line) + register char *line; +{ + register int fd; + UTMP ut; + int rval; + off_t lseek(); + time_t time(); + + if ((fd = open(_PATH_UTMP, O_RDWR)) < 0) + return(0); + rval = 0; + while (read(fd, (char *)&ut, sizeof(UTMP)) == sizeof(UTMP)) { + if (!ut.ut_name[0] || strncmp(ut.ut_line, line, UT_LINESIZE)) + continue; + bzero(ut.ut_name, UT_NAMESIZE); + bzero(ut.ut_host, UT_HOSTSIZE); + (void)time(&ut.ut_time); + (void)lseek(fd, -(long)sizeof(UTMP), L_INCR); + (void)write(fd, (char *)&ut, sizeof(UTMP)); + rval = 1; + } + (void)close(fd); + return(rval); +} diff --git a/lib/libutil/logwtmp.c b/lib/libutil/logwtmp.c new file mode 100644 index 000000000000..2e43d2cb4823 --- /dev/null +++ b/lib/libutil/logwtmp.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)logwtmp.c 5.5 (Berkeley) 6/1/90"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/types.h> +#include <sys/file.h> +#include <sys/time.h> +#include <sys/stat.h> +#include <utmp.h> + +logwtmp(line, name, host) + char *line, *name, *host; +{ + struct utmp ut; + struct stat buf; + int fd; + time_t time(); + char *strncpy(); + + if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) < 0) + return; + if (fstat(fd, &buf) == 0) { + (void) strncpy(ut.ut_line, line, sizeof(ut.ut_line)); + (void) strncpy(ut.ut_name, name, sizeof(ut.ut_name)); + (void) strncpy(ut.ut_host, host, sizeof(ut.ut_host)); + (void) time(&ut.ut_time); + if (write(fd, (char *)&ut, sizeof(struct utmp)) != + sizeof(struct utmp)) + (void) ftruncate(fd, buf.st_size); + } + (void) close(fd); +} diff --git a/lib/libutil/pty.c b/lib/libutil/pty.c new file mode 100644 index 000000000000..e5661dc829be --- /dev/null +++ b/lib/libutil/pty.c @@ -0,0 +1,127 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)pty.c 5.6 (Berkeley) 5/10/91"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/cdefs.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <termios.h> +#include <errno.h> +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <grp.h> + +openpty(amaster, aslave, name, termp, winp) + int *amaster, *aslave; + char *name; + struct termios *termp; + struct winsize *winp; +{ + static char line[] = "/dev/ptyXX"; + register const char *cp1, *cp2; + register int master, slave, ttygid; + struct group *gr; + + if ((gr = getgrnam("tty")) != NULL) + ttygid = gr->gr_gid; + else + ttygid = -1; + + for (cp1 = "pqrs"; *cp1; cp1++) { + line[8] = *cp1; + for (cp2 = "0123456789abcdef"; *cp2; cp2++) { + line[9] = *cp2; + if ((master = open(line, O_RDWR, 0)) == -1) { + if (errno == ENOENT) + return (-1); /* out of ptys */ + } else { + line[5] = 't'; + (void) chown(line, getuid(), ttygid); + (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP); + (void) revoke(line); + if ((slave = open(line, O_RDWR, 0)) != -1) { + *amaster = master; + *aslave = slave; + if (name) + strcpy(name, line); + if (termp) + (void) tcsetattr(slave, + TCSAFLUSH, termp); + if (winp) + (void) ioctl(slave, TIOCSWINSZ, + (char *)winp); + return (0); + } + (void) close(master); + line[5] = 'p'; + } + } + } + errno = ENOENT; /* out of ptys */ + return (-1); +} + +forkpty(amaster, name, termp, winp) + int *amaster; + char *name; + struct termios *termp; + struct winsize *winp; +{ + int master, slave, pid; + + if (openpty(&master, &slave, name, termp, winp) == -1) + return (-1); + switch (pid = fork()) { + case -1: + return (-1); + case 0: + /* + * child + */ + (void) close(master); + login_tty(slave); + return (0); + } + /* + * parent + */ + *amaster = master; + (void) close(slave); + return (pid); +} diff --git a/lib/libutil/pwcache.3 b/lib/libutil/pwcache.3 new file mode 100644 index 000000000000..7805650641fc --- /dev/null +++ b/lib/libutil/pwcache.3 @@ -0,0 +1,100 @@ +.\" Copyright (c) 1989, 1991 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)pwcache.3 5.4 (Berkeley) 4/19/91 +.\" +.Dd April 19, 1991 +.Dt PWCACHE 3 +.Os +.Sh NAME +.Nm pwcache +.Nd cache password and group entries +.Sh SYNOPSIS +.Fn user_from_uid "uid_t uid" "int nouser" +.Fn group_from_gid "gid_t gid" "int nogroup" +.Sh DESCRIPTION +.Bf -symbolic +This interface is not part of the C library. +It has been placed in the Berkeley utility library, libutil, as it is +used by several standard utilities. +.Ef +.Pp +The +.Fn user_from_uid +function returns the user name associated with the argument +.Fa uid . +The user name is cached so that multiple calls with the same +.Fa uid +do not require additional calls to +.Xr getpwuid 3 . +If there is no user associated with the +.Fa uid , +a pointer is returned +to an +.Tn ASCII +representation of the +.Fa uid , +unless the argument +.Fa nouser +is non-zero, in which case a +.Dv NULL +pointer is returned. +.Pp +The +.Fn group_from_gid +function returns the group name associated with the argument +.Fa gid . +The group name is cached so that multiple calls with the same +.Fa gid +do not require additional calls to +.Xr getgrgid 3 . +If there is no group associated with the +.Fa gid , +a pointer is returned +to an +.Tn ASCII +representation of the +.Fa gid , +unless the argument +.Fa nogroup +is non-zero, in which case a +.Dv NULL +pointer is returned. +.Sh SEE ALSO +.Xr getgrgid 3 , +.Xr getpwuid 3 +.Sh HISTORY +The +.Fn user_from_id +and +.Fn group_from_id +functions are +.Ud . diff --git a/lib/libutil/pwcache.c b/lib/libutil/pwcache.c new file mode 100644 index 000000000000..ad6df2ed3cee --- /dev/null +++ b/lib/libutil/pwcache.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)pwcache.c 5.4 (Berkeley) 6/1/90"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/types.h> +#include <utmp.h> +#include <pwd.h> +#include <grp.h> +#include <stdio.h> + +#define NCACHE 64 /* power of 2 */ +#define MASK NCACHE - 1 /* bits to store with */ + +static int pwopen = 0; +static int gropen = 0; + +char * +user_from_uid(uid, nouser) + uid_t uid; + int nouser; +{ + static struct ncache { + uid_t uid; + char name[UT_NAMESIZE + 1]; + } c_uid[NCACHE]; + static char nbuf[15]; /* 32 bits == 10 digits */ + register struct passwd *pw; + register struct ncache *cp; + + cp = c_uid + (uid & MASK); + if (cp->uid != uid || !*cp->name) { + if (pwopen == 0) { + setpassent(1); + pwopen++; + } + if (!(pw = getpwuid(uid))) { + if (nouser) + return((char *)NULL); + (void)sprintf(nbuf, "%u", uid); + return(nbuf); + } + cp->uid = uid; + (void)strncpy(cp->name, pw->pw_name, UT_NAMESIZE); + cp->name[UT_NAMESIZE] = '\0'; + } + return(cp->name); +} + +char * +group_from_gid(gid, nogroup) + gid_t gid; + int nogroup; +{ + static struct ncache { + gid_t gid; + char name[UT_NAMESIZE]; + } c_gid[NCACHE]; + static char nbuf[15]; /* 32 bits == 10 digits */ + register struct group *gr; + register struct ncache *cp; + + cp = c_gid + (gid & MASK); + if (cp->gid != gid || !*cp->name) { + if (gropen == 0) { + setgroupent(1); + gropen++; + } + if (!(gr = getgrgid(gid))) { + if (nogroup) + return((char *)NULL); + (void)sprintf(nbuf, "%u", gid); + return(nbuf); + } + cp->gid = gid; + (void)strncpy(cp->name, gr->gr_name, UT_NAMESIZE); + cp->name[UT_NAMESIZE] = '\0'; + } + return(cp->name); +} |
