diff options
Diffstat (limited to 'lib')
28 files changed, 5648 insertions, 46 deletions
diff --git a/lib/csu/i386/Makefile b/lib/csu/i386/Makefile index bb1c66e..12558ea 100644 --- a/lib/csu/i386/Makefile +++ b/lib/csu/i386/Makefile @@ -1,16 +1,22 @@ -# @(#)Makefile 5.6 (Berkeley) 5/22/91 +# from: @(#)Makefile 5.6 (Berkeley) 5/22/91 +# $Id: Makefile,v 1.8 1993/12/24 02:11:37 jkh Exp $ -CFLAGS= -O -DLIBC_SCCS -OBJS= crt0.o gcrt0.o +CFLAGS+= -DLIBC_SCCS -DDYNAMIC +OBJS= crt0.o gcrt0.o c++rt0.o CLEANFILES+= gmon.o moncrt0.o core a.out all: ${OBJS} crt0.o: crt0.c - ${CC} ${CFLAGS} -c -DCRT0 ${.ALLSRC} + ${CC} ${CFLAGS} -c -DCRT0 ${.ALLSRC} -o ${.TARGET} ${LD} -x -r ${.TARGET} mv a.out ${.TARGET} +c++rt0.o: c++rt0.c + ${CC} ${CFLAGS} -fpic -c ${.ALLSRC} + @${LD} -x -r ${.TARGET} + @mv a.out ${.TARGET} + moncrt0.o: crt0.c ${CC} ${CFLAGS} -c -DMCRT0 ${.ALLSRC} -o ${.TARGET} ${LD} -x -r ${.TARGET} @@ -20,12 +26,12 @@ gcrt0.o: moncrt0.o gmon.o ${LD} -x -r -o ${.TARGET} moncrt0.o gmon.o gmon.o: gmon.c gmon.h - ${CC} -c ${DEFS} ${.IMPSRC} + ${CC} ${CFLAGS} -c ${.IMPSRC} -o ${.TARGET} ${LD} -x -r ${.TARGET} mv a.out ${.TARGET} install: - install -o ${BINOWN} -g ${BINGRP} -m 444 ${OBJS} \ + install ${COPY} -o ${BINOWN} -g ${BINGRP} -m 444 ${OBJS} \ ${DESTDIR}/usr/lib depend lint tags: diff --git a/lib/csu/i386/c++rt0.c b/lib/csu/i386/c++rt0.c new file mode 100644 index 0000000..44da438 --- /dev/null +++ b/lib/csu/i386/c++rt0.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1993 Paul Kranenburg + * 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 Paul Kranenburg. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * $Id: c++rt0.c,v 1.2 1994/01/29 01:58:31 jtc Exp $ + */ + +/* + * Run-time module for GNU C++ compiled shared libraries. + * + * The linker constructs the following arrays of pointers to global + * constructors and destructors. The first element contains the + * number of pointers in each. + * The tables are also null-terminated. + */ +void (*__CTOR_LIST__[0])(void); +void (*__DTOR_LIST__[0])(void); + +static void +__dtors(void) +{ + unsigned long i = (unsigned long) __DTOR_LIST__[0]; + void (**p)(void) = __DTOR_LIST__ + i; + + while (i--) + (**p--)(); +} + +static void +__ctors(void) +{ + void (**p)(void) = __CTOR_LIST__ + 1; + + while (*p) + (**p++)(); +} + +extern void __init() asm(".init"); + +void +__init(void) +{ + static int initialized = 0; + + /* + * Call global constructors. + * Arrange to call global destructors at exit. + */ + if (!initialized) { + initialized = 1; + __ctors(); + atexit(__dtors); + } + +} diff --git a/lib/csu/i386/crt0.c b/lib/csu/i386/crt0.c index 363098b..38fd64c 100644 --- a/lib/csu/i386/crt0.c +++ b/lib/csu/i386/crt0.c @@ -1,5 +1,5 @@ -/*- - * Copyright (c) 1990 The Regents of the University of California. +/* + * Copyright (c) 1993 Paul Kranenburg * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -12,50 +12,105 @@ * 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 product includes software developed by Paul Kranenburg. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. * - * 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. + * $Id: crt0.c,v 1.8 1994/02/13 20:53:11 jkh Exp $ */ + #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)crt0.c 5.7 (Berkeley) 7/3/91"; +static char sccsid[] = "%W% (Erasmus) %G%"; #endif /* LIBC_SCCS and not lint */ +extern void exit(); +int _callmain(); -/* - * C start up routine. - * Robert Henry, UCB, 20 Oct 81 - * - * We make the following (true) assumption: - * 1) The only register variable that we can trust is the frame pointer, - * ebp, which points to the base of the kernel calling frame. - */ +#include <sys/param.h> + +#ifdef DYNAMIC +#include <sys/types.h> +#include <sys/syscall.h> +#include <a.out.h> +#ifndef N_GETMAGIC +#define N_GETMAGIC(x) ((x).a_magic) +#endif +#ifndef N_BSSADDR +#define N_BSSADDR(x) (N_DATADDR(x)+(x).a_data) +#endif +#include <sys/mman.h> +#ifdef sun +#define MAP_COPY MAP_PRIVATE +#define MAP_FILE 0 +#define MAP_ANON 0 +#endif +#include <link.h> + +extern struct _dynamic _DYNAMIC; +static struct ld_entry *ld_entry; +static void __do_dynamic_link (); +static char *_getenv(); +static int _strncmp(); + +#ifdef sun +#define LDSO "/usr/lib/ld.so" +#endif +#ifdef BSD +#define LDSO "/usr/libexec/ld.so" +#endif -char **environ = (char **)0; -int errno = 0; +#endif /* DYNAMIC */ -asm(".text"); -asm(".long 0xc000c000"); +static char *_strrchr(); +char **environ; + +#ifdef BSD extern unsigned char etext; extern unsigned char eprol asm ("eprol"); extern start() asm("start"); extern mcount() asm ("mcount"); +int errno; +static char empty[1]; +char *__progname = empty; +#endif + +/* + * We need these system calls, but can't use library stubs + */ +#define _exit(v) __syscall(SYS_exit, (v)) +#define open(name, f, m) __syscall(SYS_open, (name), (f), (m)) +#define close(fd) __syscall(SYS_close, (fd)) +#define read(fd, s, n) __syscall(SYS_read, (fd), (s), (n)) +#define write(fd, s, n) __syscall(SYS_write, (fd), (s), (n)) +#define dup(fd) __syscall(SYS_dup, (fd)) +#define dup2(fd, fdnew) __syscall(SYS_dup2, (fd), (fdnew)) +#ifdef sun +#define mmap(addr, len, prot, flags, fd, off) \ + __syscall(SYS_mmap, (addr), (len), (prot), _MAP_NEW|(flags), (fd), (off)) +#else +#define mmap(addr, len, prot, flags, fd, off) \ + __syscall(SYS_mmap, (addr), (len), (prot), (flags), (fd), (off)) +#endif + +#define _FATAL(str) \ + write(2, str, sizeof(str)), \ + _exit(1); + + start() { struct kframe { @@ -71,38 +126,251 @@ start() register char **targv; register char **argv; extern void _mcleanup(); +#ifdef DYNAMIC + volatile caddr_t x; +#endif #ifdef lint kfp = 0; initcode = initcode = 0; -#else not lint +#else /* not lint */ /* just above the saved frame pointer */ asm ("lea 4(%%ebp), %0" : "=r" (kfp) ); -#endif not lint +#endif /* not lint */ for (argv = targv = &kfp->kargv[0]; *targv++; /* void */) /* void */ ; if (targv >= (char **)(*argv)) --targv; environ = targv; + + if (argv[0]) + if ((__progname = _strrchr(argv[0], '/')) == NULL) + __progname = argv[0]; + else + ++__progname; + +#ifdef DYNAMIC + /* ld(1) convention: if DYNAMIC = 0 then statically linked */ +#ifdef stupid_gcc + if (&_DYNAMIC) + __do_dynamic_link(); +#else + x = (caddr_t)&_DYNAMIC; + if (x) + __do_dynamic_link(); +#endif +#endif /* DYNAMIC */ + asm("eprol:"); #ifdef MCRT0 atexit(_mcleanup); monstartup(&eprol, &etext); #endif MCRT0 + +asm ("__callmain:"); /* Defined for the benefit of debuggers */ exit(main(kfp->kargc, argv, environ)); } -#ifdef CRT0 +#ifdef DYNAMIC +static void +__do_dynamic_link () +{ + struct crt_ldso crt; + struct exec hdr; + char *ldso; + int dupzfd; + int (*entry)(); + +#ifdef DEBUG + /* Provision for alternate ld.so - security risk! */ + if (!(ldso = _getenv("LDSO"))) +#endif + ldso = LDSO; + + crt.crt_ldfd = open(ldso, 0, 0); + if (crt.crt_ldfd == -1) { + _FATAL("No ld.so\n"); + } + + /* Read LDSO exec header */ + if (read(crt.crt_ldfd, &hdr, sizeof hdr) < sizeof hdr) { + _FATAL("Failure reading ld.so\n"); + } + if ((N_GETMAGIC_NET(hdr) != ZMAGIC) && (N_GETMAGIC(hdr) != QMAGIC)) { + _FATAL("Bad magic: ld.so\n"); + } + + /* We use MAP_ANON */ + crt.crt_dzfd = -1; + + /* Map in ld.so */ + crt.crt_ba = mmap(0, hdr.a_text, + PROT_READ|PROT_EXEC, + MAP_FILE|MAP_COPY, + crt.crt_ldfd, N_TXTOFF(hdr)); + if (crt.crt_ba == -1) { + _FATAL("Cannot map ld.so\n"); + } + +#ifdef BSD +/* !!! + * This is gross, ld.so is a ZMAGIC a.out, but has `sizeof(hdr)' for + * an entry point and not at PAGSIZ as the N_*ADDR macros assume. + */ +#undef N_DATADDR +#undef N_BSSADDR +#define N_DATADDR(x) ((x).a_text) +#define N_BSSADDR(x) ((x).a_text + (x).a_data) +#endif + + /* Map in data segment of ld.so writable */ + if (mmap(crt.crt_ba+N_DATADDR(hdr), hdr.a_data, + PROT_READ|PROT_WRITE, + MAP_FIXED|MAP_FILE|MAP_COPY, + crt.crt_ldfd, N_DATOFF(hdr)) == -1) { + _FATAL("Cannot map ld.so\n"); + } + + /* Map bss segment of ld.so zero */ + if (hdr.a_bss && mmap(crt.crt_ba+N_BSSADDR(hdr), hdr.a_bss, + PROT_READ|PROT_WRITE, + MAP_FIXED|MAP_ANON|MAP_COPY, + crt.crt_dzfd, 0) == -1) { + _FATAL("Cannot map ld.so\n"); + } + + crt.crt_dp = &_DYNAMIC; + crt.crt_ep = environ; + crt.crt_bp = (caddr_t)_callmain; + crt.crt_prog = __progname; + + entry = (int (*)())(crt.crt_ba + sizeof hdr); + if ((*entry)(CRT_VERSION_BSD_3, &crt) == -1) { + _FATAL("ld.so failed\n"); + } + + ld_entry = _DYNAMIC.d_entry; + return; +} + /* - * null mcount and moncontrol, - * just in case some routine is compiled for profiling + * DL stubs */ -moncontrol(val) - int val; + +void * +dlopen(name, mode) +char *name; +int mode; { + if (ld_entry == NULL) + return NULL; + return (ld_entry->dlopen)(name, mode); } -mcount() { } -#endif CRT0 +int +dlclose(fd) +void *fd; +{ + if (ld_entry == NULL) + return -1; + + return (ld_entry->dlclose)(fd); +} + +void * +dlsym(fd, name) +void *fd; +char *name; +{ + if (ld_entry == NULL) + return NULL; + + return (ld_entry->dlsym)(fd, name); +} + +int +dlctl(fd, cmd, arg) +void *fd, *arg; +int cmd; +{ + if (ld_entry == NULL) + return -1; + + return (ld_entry->dlctl)(fd, cmd, arg); +} + +/* + * Support routines + */ + +static int +_strncmp(s1, s2, n) + register char *s1, *s2; + register n; +{ + + if (n == 0) + return (0); + do { + if (*s1 != *s2++) + return (*(unsigned char *)s1 - *(unsigned char *)--s2); + if (*s1++ == 0) + break; + } while (--n != 0); + return (0); +} + +static char * +_getenv(name) + register char *name; +{ + extern char **environ; + register int len; + register char **P, *C; + + for (C = name, len = 0; *C && *C != '='; ++C, ++len); + for (P = environ; *P; ++P) + if (!_strncmp(*P, name, len)) + if (*(C = *P + len) == '=') { + return(++C); + } + return (char *)0; +} + + asm(" ___syscall:"); + asm(" popl %ecx"); + asm(" popl %eax"); + asm(" pushl %ecx"); + asm(" .byte 0x9a"); + asm(" .long 0"); + asm(" .word 7"); + asm(" pushl %ecx"); + asm(" jc 1f"); + asm(" ret"); + asm(" 1:"); + asm(" movl $-1,%eax"); + asm(" ret"); + +#endif /* DYNAMIC */ + +static char * +_strrchr(p, ch) +register char *p, ch; +{ + register char *save; + + for (save = NULL;; ++p) { + if (*p == ch) + save = (char *)p; + if (!*p) + return(save); + } +/* NOTREACHED */ +} + +#ifdef MCRT0 +asm (" .text"); +asm ("_eprol:"); +#endif diff --git a/lib/csu/i386/gmon.c b/lib/csu/i386/gmon.c new file mode 100644 index 0000000..4ca8333 --- /dev/null +++ b/lib/csu/i386/gmon.c @@ -0,0 +1,330 @@ +/*- + * Copyright (c) 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char sccsid[] = "from: @(#)gmon.c 5.3 (Berkeley) 5/22/91";*/ +static char rcsid[] = "$Id: gmon.c,v 1.2 1993/08/01 18:44:18 mycroft Exp $"; +#endif /* LIBC_SCCS and not lint */ + + +#include <unistd.h> + +#ifdef DEBUG +#include <stdio.h> +#endif + +#include "gmon.h" + +extern mcount() asm ("mcount"); +extern char *minbrk asm ("minbrk"); + + /* + * froms is actually a bunch of unsigned shorts indexing tos + */ +static int profiling = 3; +static unsigned short *froms; +static struct tostruct *tos = 0; +static long tolimit = 0; +static char *s_lowpc = 0; +static char *s_highpc = 0; +static unsigned long s_textsize = 0; + +static int ssiz; +static char *sbuf; +static int s_scale; + /* see profil(2) where this is describe (incorrectly) */ +#define SCALE_1_TO_1 0x10000L + +#define MSG "No space for profiling buffer(s)\n" + +monstartup(lowpc, highpc) + char *lowpc; + char *highpc; +{ + int monsize; + char *buffer; + register int o; + + /* + * round lowpc and highpc to multiples of the density we're using + * so the rest of the scaling (here and in gprof) stays in ints. + */ + lowpc = (char *) + ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER)); + s_lowpc = lowpc; + highpc = (char *) + ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER)); + s_highpc = highpc; + s_textsize = highpc - lowpc; + monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr); + buffer = sbrk( monsize ); + if ( buffer == (char *) -1 ) { + write( 2 , MSG , sizeof(MSG) ); + return; + } + froms = (unsigned short *) sbrk( s_textsize / HASHFRACTION ); + if ( froms == (unsigned short *) -1 ) { + write( 2 , MSG , sizeof(MSG) ); + froms = 0; + return; + } + tolimit = s_textsize * ARCDENSITY / 100; + if ( tolimit < MINARCS ) { + tolimit = MINARCS; + } else if ( tolimit > 65534 ) { + tolimit = 65534; + } + tos = (struct tostruct *) sbrk( tolimit * sizeof( struct tostruct ) ); + if ( tos == (struct tostruct *) -1 ) { + write( 2 , MSG , sizeof(MSG) ); + froms = 0; + tos = 0; + return; + } + minbrk = sbrk(0); + tos[0].link = 0; + sbuf = buffer; + ssiz = monsize; + ( (struct phdr *) buffer ) -> lpc = lowpc; + ( (struct phdr *) buffer ) -> hpc = highpc; + ( (struct phdr *) buffer ) -> ncnt = ssiz; + monsize -= sizeof(struct phdr); + if ( monsize <= 0 ) + return; + o = highpc - lowpc; + if( monsize < o ) +#ifndef hp300 + s_scale = ( (float) monsize / o ) * SCALE_1_TO_1; +#else /* avoid floating point */ + { + int quot = o / monsize; + + if (quot >= 0x10000) + s_scale = 1; + else if (quot >= 0x100) + s_scale = 0x10000 / quot; + else if (o >= 0x800000) + s_scale = 0x1000000 / (o / (monsize >> 8)); + else + s_scale = 0x1000000 / ((o << 8) / monsize); + } +#endif + else + s_scale = SCALE_1_TO_1; + moncontrol(1); +} + +_mcleanup() +{ + int fd; + int fromindex; + int endfrom; + char *frompc; + int toindex; + struct rawarc rawarc; + + moncontrol(0); + fd = creat( "gmon.out" , 0666 ); + if ( fd < 0 ) { + perror( "mcount: gmon.out" ); + return; + } +# ifdef DEBUG + fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz ); +# endif DEBUG + write( fd , sbuf , ssiz ); + endfrom = s_textsize / (HASHFRACTION * sizeof(*froms)); + for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) { + if ( froms[fromindex] == 0 ) { + continue; + } + frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms)); + for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) { +# ifdef DEBUG + fprintf( stderr , + "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" , + frompc , tos[toindex].selfpc , tos[toindex].count ); +# endif DEBUG + rawarc.raw_frompc = (unsigned long) frompc; + rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc; + rawarc.raw_count = tos[toindex].count; + write( fd , &rawarc , sizeof rawarc ); + } + } + close( fd ); +} + +mcount() +{ + register char *selfpc; + register unsigned short *frompcindex; + register struct tostruct *top; + register struct tostruct *prevtop; + register long toindex; + + /* + * find the return address for mcount, + * and the return address for mcount's caller. + */ + asm(".text"); /* make sure we're in text space */ + /* + * selfpc = pc pushed by mcount call + */ + asm("movl 4(%%ebp),%0" : "=r" (selfpc)); + /* + * frompcindex = pc pushed by jsr into self. + * In GCC the caller's stack frame has already been built so we + * have to chase a6 to find caller's raddr. + */ + asm("movl (%%ebp),%0" : "=r" (frompcindex)); + frompcindex = ((unsigned short **)frompcindex)[1]; + /* + * check that we are profiling + * and that we aren't recursively invoked. + */ + if (profiling) { + goto out; + } + profiling++; + /* + * check that frompcindex is a reasonable pc value. + * for example: signal catchers get called from the stack, + * not from text space. too bad. + */ + frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc); + if ((unsigned long)frompcindex > s_textsize) { + goto done; + } + frompcindex = + &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))]; + toindex = *frompcindex; + if (toindex == 0) { + /* + * first time traversing this arc + */ + toindex = ++tos[0].link; + if (toindex >= tolimit) { + goto overflow; + } + *frompcindex = toindex; + top = &tos[toindex]; + top->selfpc = selfpc; + top->count = 1; + top->link = 0; + goto done; + } + top = &tos[toindex]; + if (top->selfpc == selfpc) { + /* + * arc at front of chain; usual case. + */ + top->count++; + goto done; + } + /* + * have to go looking down chain for it. + * top points to what we are looking at, + * prevtop points to previous top. + * we know it is not at the head of the chain. + */ + for (; /* goto done */; ) { + if (top->link == 0) { + /* + * top is end of the chain and none of the chain + * had top->selfpc == selfpc. + * so we allocate a new tostruct + * and link it to the head of the chain. + */ + toindex = ++tos[0].link; + if (toindex >= tolimit) { + goto overflow; + } + top = &tos[toindex]; + top->selfpc = selfpc; + top->count = 1; + top->link = *frompcindex; + *frompcindex = toindex; + goto done; + } + /* + * otherwise, check the next arc on the chain. + */ + prevtop = top; + top = &tos[top->link]; + if (top->selfpc == selfpc) { + /* + * there it is. + * increment its count + * move it to the head of the chain. + */ + top->count++; + toindex = prevtop->link; + prevtop->link = top->link; + top->link = *frompcindex; + *frompcindex = toindex; + goto done; + } + + } +done: + profiling--; + /* and fall through */ +out: + return; /* normal return restores saved registers */ + +overflow: + profiling++; /* halt further profiling */ +# define TOLIMIT "mcount: tos overflow\n" + write(2, TOLIMIT, sizeof(TOLIMIT)); + goto out; +} + +/* + * Control profiling + * profiling is what mcount checks to see if + * all the data structures are ready. + */ +moncontrol(mode) + int mode; +{ + if (mode) { + /* start */ + profil(sbuf + sizeof(struct phdr), ssiz - sizeof(struct phdr), + (int)s_lowpc, s_scale); + profiling = 0; + } else { + /* stop */ + profil((char *)0, 0, 0, 0); + profiling = 3; + } +} diff --git a/lib/csu/i386/gmon.h b/lib/csu/i386/gmon.h new file mode 100644 index 0000000..e400602 --- /dev/null +++ b/lib/csu/i386/gmon.h @@ -0,0 +1,106 @@ +/*- + * Copyright (c) 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. + * + * from: @(#)gmon.h 5.2 (Berkeley) 5/6/91 + * $Id: gmon.h,v 1.2 1993/08/01 18:44:21 mycroft Exp $ + */ + +struct phdr { + char *lpc; + char *hpc; + int ncnt; +}; + + /* + * histogram counters are unsigned shorts (according to the kernel). + */ +#define HISTCOUNTER unsigned short + + /* + * fraction of text space to allocate for histogram counters + * here, 1/2 + */ +#define HISTFRACTION 2 + + /* + * Fraction of text space to allocate for from hash buckets. + * The value of HASHFRACTION is based on the minimum number of bytes + * of separation between two subroutine call points in the object code. + * Given MIN_SUBR_SEPARATION bytes of separation the value of + * HASHFRACTION is calculated as: + * + * HASHFRACTION = MIN_SUBR_SEPARATION / (2 * sizeof(short) - 1); + * + * For the VAX, the shortest two call sequence is: + * + * calls $0,(r0) + * calls $0,(r0) + * + * which is separated by only three bytes, thus HASHFRACTION is + * calculated as: + * + * HASHFRACTION = 3 / (2 * 2 - 1) = 1 + * + * Note that the division above rounds down, thus if MIN_SUBR_FRACTION + * is less than three, this algorithm will not work! + */ +#define HASHFRACTION 1 + + /* + * percent of text space to allocate for tostructs + * with a minimum. + */ +#define ARCDENSITY 2 +#define MINARCS 50 + +struct tostruct { + char *selfpc; + long count; + unsigned short link; +}; + + /* + * a raw arc, + * with pointers to the calling site and the called site + * and a count. + */ +struct rawarc { + unsigned long raw_frompc; + unsigned long raw_selfpc; + long raw_count; +}; + + /* + * general rounding functions. + */ +#define ROUNDDOWN(x,y) (((x)/(y))*(y)) +#define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y)) diff --git a/lib/csu/i386/gprof.ex b/lib/csu/i386/gprof.ex new file mode 100644 index 0000000..d86d517 --- /dev/null +++ b/lib/csu/i386/gprof.ex @@ -0,0 +1,3 @@ +g/_mcount/s/_mcount/mcount/g +w +q diff --git a/lib/libc/amd64/sys/Makefile.inc b/lib/libc/amd64/sys/Makefile.inc new file mode 100644 index 0000000..6774dd3 --- /dev/null +++ b/lib/libc/amd64/sys/Makefile.inc @@ -0,0 +1,10 @@ +# from: Makefile.inc,v 1.1 1993/09/03 19:04:23 jtc Exp +# $Id$ + +.PATH: ${.CURDIR}/${MACHINE}/sys + +SRCS+= i386_get_ldt.c i386_set_ldt.c + +MAN2+= i386/sys/i386_get_ldt.2 + +MLINKS+=i386_get_ldt.2 i386_set_ldt.2 diff --git a/lib/libc/gen/fts-compat.h b/lib/libc/gen/fts-compat.h new file mode 100644 index 0000000..84dbe14 --- /dev/null +++ b/lib/libc/gen/fts-compat.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 1989, 1993 + * 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. + * + * @(#)fts.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _FTS_H_ +#define _FTS_H_ + +typedef struct { + struct _ftsent *fts_cur; /* current node */ + struct _ftsent *fts_child; /* linked list of children */ + struct _ftsent **fts_array; /* sort array */ + dev_t fts_dev; /* starting device # */ + char *fts_path; /* path for this descent */ + int fts_rfd; /* fd for root */ + int fts_pathlen; /* sizeof(path) */ + int fts_nitems; /* elements in the sort array */ + int (*fts_compar)(); /* compare function */ + +#define FTS_COMFOLLOW 0x001 /* follow command line symlinks */ +#define FTS_LOGICAL 0x002 /* logical walk */ +#define FTS_NOCHDIR 0x004 /* don't change directories */ +#define FTS_NOSTAT 0x008 /* don't get stat info */ +#define FTS_PHYSICAL 0x010 /* physical walk */ +#define FTS_SEEDOT 0x020 /* return dot and dot-dot */ +#define FTS_XDEV 0x040 /* don't cross devices */ +#define FTS_OPTIONMASK 0x07f /* valid user option mask */ + +#define FTS_NAMEONLY 0x080 /* (private) child names only */ +#define FTS_STOP 0x100 /* (private) unrecoverable error */ + int fts_options; /* fts_open options, global flags */ +} FTS; + +typedef struct _ftsent { + struct _ftsent *fts_cycle; /* cycle node */ + struct _ftsent *fts_parent; /* parent directory */ + struct _ftsent *fts_link; /* next file in directory */ + long fts_number; /* local numeric value */ + void *fts_pointer; /* local address value */ + char *fts_accpath; /* access path */ + char *fts_path; /* root path */ + int fts_errno; /* errno for this node */ + int fts_symfd; /* fd for symlink */ + u_short fts_pathlen; /* strlen(fts_path) */ + u_short fts_namelen; /* strlen(fts_name) */ + + ino_t fts_ino; /* inode */ + dev_t fts_dev; /* device */ + nlink_t fts_nlink; /* link count */ + +#define FTS_ROOTPARENTLEVEL -1 +#define FTS_ROOTLEVEL 0 + short fts_level; /* depth (-1 to N) */ + +#define FTS_D 1 /* preorder directory */ +#define FTS_DC 2 /* directory that causes cycles */ +#define FTS_DEFAULT 3 /* none of the above */ +#define FTS_DNR 4 /* unreadable directory */ +#define FTS_DOT 5 /* dot or dot-dot */ +#define FTS_DP 6 /* postorder directory */ +#define FTS_ERR 7 /* error; errno is set */ +#define FTS_F 8 /* regular file */ +#define FTS_INIT 9 /* initialized only */ +#define FTS_NS 10 /* stat(2) failed */ +#define FTS_NSOK 11 /* no stat(2) requested */ +#define FTS_SL 12 /* symbolic link */ +#define FTS_SLNONE 13 /* symbolic link without target */ + u_short fts_info; /* user flags for FTSENT structure */ + +#define FTS_DONTCHDIR 0x01 /* don't chdir .. to the parent */ +#define FTS_SYMFOLLOW 0x02 /* followed a symlink to get here */ + u_short fts_flags; /* private flags for FTSENT structure */ + +#define FTS_AGAIN 1 /* read node again */ +#define FTS_FOLLOW 2 /* follow symbolic link */ +#define FTS_NOINSTR 3 /* no instructions */ +#define FTS_SKIP 4 /* discard node */ + u_short fts_instr; /* fts_set() instructions */ + + struct stat *fts_statp; /* stat(2) information */ + char fts_name[1]; /* file name */ +} FTSENT; + +#include <sys/cdefs.h> + +__BEGIN_DECLS +FTSENT *fts_children __P((FTS *, int)); +int fts_close __P((FTS *)); +FTS *fts_open __P((char * const *, int, + int (*)(const FTSENT **, const FTSENT **))); +FTSENT *fts_read __P((FTS *)); +int fts_set __P((FTS *, FTSENT *, int)); +__END_DECLS + +#endif /* !_FTS_H_ */ diff --git a/lib/libc/gen/pw_scan.c b/lib/libc/gen/pw_scan.c new file mode 100644 index 0000000..3093ac2 --- /dev/null +++ b/lib/libc/gen/pw_scan.c @@ -0,0 +1,122 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)pw_scan.c 8.3 (Berkeley) 4/2/94"; +#endif /* not lint */ + +/* + * This module is used to "verify" password entries by chpass(1) and + * pwd_mkdb(8). + */ + +#include <sys/param.h> + +#include <err.h> +#include <fcntl.h> +#include <pwd.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> + +#include "pw_scan.h" + +int +pw_scan(bp, pw) + char *bp; + struct passwd *pw; +{ + long id; + int root; + char *p, *sh; + + if (!(pw->pw_name = strsep(&bp, ":"))) /* login */ + goto fmt; + root = !strcmp(pw->pw_name, "root"); + + if (!(pw->pw_passwd = strsep(&bp, ":"))) /* passwd */ + goto fmt; + + if (!(p = strsep(&bp, ":"))) /* uid */ + goto fmt; + id = atol(p); + if (root && id) { + warnx("root uid should be 0"); + return (0); + } + if (id > USHRT_MAX) { + warnx("%s > max uid value (%d)", p, USHRT_MAX); + return (0); + } + pw->pw_uid = id; + + if (!(p = strsep(&bp, ":"))) /* gid */ + goto fmt; + id = atol(p); + if (id > USHRT_MAX) { + warnx("%s > max gid value (%d)", p, USHRT_MAX); + return (0); + } + pw->pw_gid = id; + + pw->pw_class = strsep(&bp, ":"); /* class */ + if (!(p = strsep(&bp, ":"))) /* change */ + goto fmt; + pw->pw_change = atol(p); + if (!(p = strsep(&bp, ":"))) /* expire */ + goto fmt; + pw->pw_expire = atol(p); + pw->pw_gecos = strsep(&bp, ":"); /* gecos */ + pw->pw_dir = strsep(&bp, ":"); /* directory */ + if (!(pw->pw_shell = strsep(&bp, ":"))) /* shell */ + goto fmt; + + p = pw->pw_shell; + if (root && *p) /* empty == /bin/sh */ + for (setusershell();;) { + if (!(sh = getusershell())) { + warnx("warning, unknown root shell"); + break; + } + if (!strcmp(p, sh)) + break; + } + + if (p = strsep(&bp, ":")) { /* too many */ +fmt: warnx("corrupted entry"); + return (0); + } + return (1); +} diff --git a/lib/libc/gen/pw_scan.h b/lib/libc/gen/pw_scan.h new file mode 100644 index 0000000..d1d4bc1 --- /dev/null +++ b/lib/libc/gen/pw_scan.h @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 1994 + * 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. + * + * @(#)pw_scan.h 8.1 (Berkeley) 4/1/94 + */ + +extern int pw_scan __P((char *, struct passwd *)); diff --git a/lib/libc/gen/setflags.c b/lib/libc/gen/setflags.c new file mode 100644 index 0000000..5bc4b85 --- /dev/null +++ b/lib/libc/gen/setflags.c @@ -0,0 +1,148 @@ +/*- + * Copyright (c) 1993 + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)stat_flags.c 8.1 (Berkeley) 5/31/93"; +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/stat.h> + +#include <stddef.h> +#include <string.h> + +#define SAPPEND(s) { \ + if (prefix != NULL) \ + (void)strcat(string, prefix); \ + (void)strcat(string, s); \ + prefix = ","; \ +} + +/* + * flags_to_string -- + * Convert stat flags to a comma-separated string. If no flags + * are set, return the default string. + */ +char * +flags_to_string(flags, def) + u_long flags; + char *def; +{ + static char string[128]; + char *prefix; + + string[0] = '\0'; + prefix = NULL; + if (flags & UF_APPEND) + SAPPEND("uappnd"); + if (flags & UF_IMMUTABLE) + SAPPEND("uchg"); + if (flags & UF_NODUMP) + SAPPEND("nodump"); + if (flags & SF_APPEND) + SAPPEND("sappnd"); + if (flags & SF_ARCHIVED) + SAPPEND("arch"); + if (flags & SF_IMMUTABLE) + SAPPEND("schg"); + return (prefix == NULL && def != NULL ? def : string); +} + +#define TEST(a, b, f) { \ + if (!memcmp(a, b, sizeof(b))) { \ + if (clear) { \ + if (clrp) \ + *clrp |= (f); \ + } else if (setp) \ + *setp |= (f); \ + break; \ + } \ +} + +/* + * string_to_flags -- + * Take string of arguments and return stat flags. Return 0 on + * success, 1 on failure. On failure, stringp is set to point + * to the offending token. + */ +int +string_to_flags(stringp, setp, clrp) + char **stringp; + u_long *setp, *clrp; +{ + int clear; + char *string, *p; + + clear = 0; + if (setp) + *setp = 0; + if (clrp) + *clrp = 0; + string = *stringp; + while ((p = strsep(&string, "\t ,")) != NULL) { + *stringp = p; + if (*p == '\0') + continue; + if (p[0] == 'n' && p[1] == 'o') { + clear = 1; + p += 2; + } + switch (p[0]) { + case 'a': + TEST(p, "arch", SF_ARCHIVED); + TEST(p, "archived", SF_ARCHIVED); + return (1); + case 'd': + clear = !clear; + TEST(p, "dump", UF_NODUMP); + return (1); + case 's': + TEST(p, "sappnd", SF_APPEND); + TEST(p, "sappend", SF_APPEND); + TEST(p, "schg", SF_IMMUTABLE); + TEST(p, "schange", SF_IMMUTABLE); + TEST(p, "simmutable", SF_IMMUTABLE); + return (1); + case 'u': + TEST(p, "uappnd", UF_APPEND); + TEST(p, "uappend", UF_APPEND); + TEST(p, "uchg", UF_IMMUTABLE); + TEST(p, "uchange", UF_IMMUTABLE); + TEST(p, "uimmutable", UF_IMMUTABLE); + /* FALLTHROUGH */ + default: + return (1); + } + } + return (0); +} diff --git a/lib/libc/gen/setflagsbyname.c b/lib/libc/gen/setflagsbyname.c new file mode 100644 index 0000000..5bc4b85 --- /dev/null +++ b/lib/libc/gen/setflagsbyname.c @@ -0,0 +1,148 @@ +/*- + * Copyright (c) 1993 + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)stat_flags.c 8.1 (Berkeley) 5/31/93"; +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/stat.h> + +#include <stddef.h> +#include <string.h> + +#define SAPPEND(s) { \ + if (prefix != NULL) \ + (void)strcat(string, prefix); \ + (void)strcat(string, s); \ + prefix = ","; \ +} + +/* + * flags_to_string -- + * Convert stat flags to a comma-separated string. If no flags + * are set, return the default string. + */ +char * +flags_to_string(flags, def) + u_long flags; + char *def; +{ + static char string[128]; + char *prefix; + + string[0] = '\0'; + prefix = NULL; + if (flags & UF_APPEND) + SAPPEND("uappnd"); + if (flags & UF_IMMUTABLE) + SAPPEND("uchg"); + if (flags & UF_NODUMP) + SAPPEND("nodump"); + if (flags & SF_APPEND) + SAPPEND("sappnd"); + if (flags & SF_ARCHIVED) + SAPPEND("arch"); + if (flags & SF_IMMUTABLE) + SAPPEND("schg"); + return (prefix == NULL && def != NULL ? def : string); +} + +#define TEST(a, b, f) { \ + if (!memcmp(a, b, sizeof(b))) { \ + if (clear) { \ + if (clrp) \ + *clrp |= (f); \ + } else if (setp) \ + *setp |= (f); \ + break; \ + } \ +} + +/* + * string_to_flags -- + * Take string of arguments and return stat flags. Return 0 on + * success, 1 on failure. On failure, stringp is set to point + * to the offending token. + */ +int +string_to_flags(stringp, setp, clrp) + char **stringp; + u_long *setp, *clrp; +{ + int clear; + char *string, *p; + + clear = 0; + if (setp) + *setp = 0; + if (clrp) + *clrp = 0; + string = *stringp; + while ((p = strsep(&string, "\t ,")) != NULL) { + *stringp = p; + if (*p == '\0') + continue; + if (p[0] == 'n' && p[1] == 'o') { + clear = 1; + p += 2; + } + switch (p[0]) { + case 'a': + TEST(p, "arch", SF_ARCHIVED); + TEST(p, "archived", SF_ARCHIVED); + return (1); + case 'd': + clear = !clear; + TEST(p, "dump", UF_NODUMP); + return (1); + case 's': + TEST(p, "sappnd", SF_APPEND); + TEST(p, "sappend", SF_APPEND); + TEST(p, "schg", SF_IMMUTABLE); + TEST(p, "schange", SF_IMMUTABLE); + TEST(p, "simmutable", SF_IMMUTABLE); + return (1); + case 'u': + TEST(p, "uappnd", UF_APPEND); + TEST(p, "uappend", UF_APPEND); + TEST(p, "uchg", UF_IMMUTABLE); + TEST(p, "uchange", UF_IMMUTABLE); + TEST(p, "uimmutable", UF_IMMUTABLE); + /* FALLTHROUGH */ + default: + return (1); + } + } + return (0); +} diff --git a/lib/libc/gen/strtofflags.c b/lib/libc/gen/strtofflags.c new file mode 100644 index 0000000..5bc4b85 --- /dev/null +++ b/lib/libc/gen/strtofflags.c @@ -0,0 +1,148 @@ +/*- + * Copyright (c) 1993 + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)stat_flags.c 8.1 (Berkeley) 5/31/93"; +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/stat.h> + +#include <stddef.h> +#include <string.h> + +#define SAPPEND(s) { \ + if (prefix != NULL) \ + (void)strcat(string, prefix); \ + (void)strcat(string, s); \ + prefix = ","; \ +} + +/* + * flags_to_string -- + * Convert stat flags to a comma-separated string. If no flags + * are set, return the default string. + */ +char * +flags_to_string(flags, def) + u_long flags; + char *def; +{ + static char string[128]; + char *prefix; + + string[0] = '\0'; + prefix = NULL; + if (flags & UF_APPEND) + SAPPEND("uappnd"); + if (flags & UF_IMMUTABLE) + SAPPEND("uchg"); + if (flags & UF_NODUMP) + SAPPEND("nodump"); + if (flags & SF_APPEND) + SAPPEND("sappnd"); + if (flags & SF_ARCHIVED) + SAPPEND("arch"); + if (flags & SF_IMMUTABLE) + SAPPEND("schg"); + return (prefix == NULL && def != NULL ? def : string); +} + +#define TEST(a, b, f) { \ + if (!memcmp(a, b, sizeof(b))) { \ + if (clear) { \ + if (clrp) \ + *clrp |= (f); \ + } else if (setp) \ + *setp |= (f); \ + break; \ + } \ +} + +/* + * string_to_flags -- + * Take string of arguments and return stat flags. Return 0 on + * success, 1 on failure. On failure, stringp is set to point + * to the offending token. + */ +int +string_to_flags(stringp, setp, clrp) + char **stringp; + u_long *setp, *clrp; +{ + int clear; + char *string, *p; + + clear = 0; + if (setp) + *setp = 0; + if (clrp) + *clrp = 0; + string = *stringp; + while ((p = strsep(&string, "\t ,")) != NULL) { + *stringp = p; + if (*p == '\0') + continue; + if (p[0] == 'n' && p[1] == 'o') { + clear = 1; + p += 2; + } + switch (p[0]) { + case 'a': + TEST(p, "arch", SF_ARCHIVED); + TEST(p, "archived", SF_ARCHIVED); + return (1); + case 'd': + clear = !clear; + TEST(p, "dump", UF_NODUMP); + return (1); + case 's': + TEST(p, "sappnd", SF_APPEND); + TEST(p, "sappend", SF_APPEND); + TEST(p, "schg", SF_IMMUTABLE); + TEST(p, "schange", SF_IMMUTABLE); + TEST(p, "simmutable", SF_IMMUTABLE); + return (1); + case 'u': + TEST(p, "uappnd", UF_APPEND); + TEST(p, "uappend", UF_APPEND); + TEST(p, "uchg", UF_IMMUTABLE); + TEST(p, "uchange", UF_IMMUTABLE); + TEST(p, "uimmutable", UF_IMMUTABLE); + /* FALLTHROUGH */ + default: + return (1); + } + } + return (0); +} diff --git a/lib/libc/i386/sys/Makefile.inc b/lib/libc/i386/sys/Makefile.inc new file mode 100644 index 0000000..6774dd3 --- /dev/null +++ b/lib/libc/i386/sys/Makefile.inc @@ -0,0 +1,10 @@ +# from: Makefile.inc,v 1.1 1993/09/03 19:04:23 jtc Exp +# $Id$ + +.PATH: ${.CURDIR}/${MACHINE}/sys + +SRCS+= i386_get_ldt.c i386_set_ldt.c + +MAN2+= i386/sys/i386_get_ldt.2 + +MLINKS+=i386_get_ldt.2 i386_set_ldt.2 diff --git a/lib/libc/i386/sys/i386_get_ldt.2 b/lib/libc/i386/sys/i386_get_ldt.2 new file mode 100644 index 0000000..ade7e10 --- /dev/null +++ b/lib/libc/i386/sys/i386_get_ldt.2 @@ -0,0 +1,98 @@ +.\" Copyright (c) 1980, 1991 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. +.\" +.\" from: @(#)fork.2 6.5 (Berkeley) 3/10/91 +.\" $Id: i386_get_ldt.2,v 1.2 1993/10/09 00:59:10 cgd Exp $ +.\" +.Dd September 20, 1993 +.Dt I386_GET_LDT 2 +.Os FreeBSD +.Sh NAME +.Nm i386_get_ldt , +.Nm i386_set_ldt +.Nd manage i386 per-process Local Descriptor Table entries +.Sh SYNOPSIS +.Fd #include <machine/segments.h> +.Fd #include <machine/sysarch.h> +.Ft int +.Fn i386_get_ldt "int start_sel" "union descriptor *descs" "int num_sels" +.Ft int +.Fn i386_set_ldt "int start_sel" "union descriptor *descs" "int num_sels" +.Sh DESCRIPTION +.Fn i386_get_ldt +will return the list of i386 descriptors that the process has in its +LDT. +.Fn i386_set_ldt +will set a list of i386 descriptors for the current process in its +LDT. +Both routines accept a starting selector number +.Fa start_sel +, an array of memory that +will contain the descriptors to be set or returned +.Fa descs +, and the number of entries to set or return +.Fa num_sels . +.Pp +The argument +.Fa descs +can be either segment_descriptor or gate_descriptor and are defined in +.Fd <i386/segments.h> . +These structures are defined by the architecure +as disjoint bit-fields, so care must be taken in constructing them. +.Sh RETURN VALUES +Upon successful completion, +.Fn i386_get_ldt +returns the number of descriptors currently in the LDT. +.Fn i386_set_ldt +returns the first selector set. +Otherwise, a value of -1 is returned and the global +variable +.Va errno +is set to indicate the error. +.Sh ERRORS +.Fn i386_get_ldt +and +.Fn i386_set_ldt +will fail if: +.Bl -tag -width [EINVAL] +.It Bq Er EINVAL +An inappropriate parameter was used for +.Fa start_sel +or +.Fa num_sels . +.It Bq Er EACESS +The caller attempted to use a descriptor that would +circumvent protection or cause a failure. +.El +.Sh REFERENCES +i386 Microprocessor Programmer's Reference Manual, Intel +.Sh WARNING +You can really hose your process using this. diff --git a/lib/libc/i386/sys/i386_get_ldt.c b/lib/libc/i386/sys/i386_get_ldt.c new file mode 100644 index 0000000..989c6b6 --- /dev/null +++ b/lib/libc/i386/sys/i386_get_ldt.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1993 John Brezak + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR 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. + * + */ + +#include <sys/cdefs.h> +#include <machine/segments.h> +#include <machine/sysarch.h> + +struct parms { + int start; + union descriptor *descs; + int num; +}; + +int +i386_get_ldt(int start, union descriptor *descs, int num) +{ + struct parms p; + + p.start = start; + p.descs = descs; + p.num = num; + + return sysarch(I386_GET_LDT, (char *)&p); +} diff --git a/lib/libc/i386/sys/i386_set_ldt.c b/lib/libc/i386/sys/i386_set_ldt.c new file mode 100644 index 0000000..377437e --- /dev/null +++ b/lib/libc/i386/sys/i386_set_ldt.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1993 John Brezak + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR 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. + * + */ + +#include <sys/cdefs.h> +#include <machine/segments.h> +#include <machine/sysarch.h> + +struct parms { + int start; + union descriptor *descs; + int num; +}; + +int +i386_set_ldt(int start, union descriptor *descs, int num) +{ + struct parms p; + + p.start = start; + p.descs = descs; + p.num = num; + + return sysarch(I386_SET_LDT, (char *)&p); +} diff --git a/lib/libkvm/kvm.h b/lib/libkvm/kvm.h new file mode 100644 index 0000000..3c675ab --- /dev/null +++ b/lib/libkvm/kvm.h @@ -0,0 +1,69 @@ +/*- + * Copyright (c) 1989, 1993 + * 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. + * + * @(#)kvm.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _KVM_H_ +#define _KVM_H_ + +/* Default version symbol. */ +#define VRS_SYM "_version" +#define VRS_KEY "VERSION" + +#include <nlist.h> +#include <sys/cdefs.h> + +__BEGIN_DECLS + +typedef struct __kvm kvm_t; + +struct kinfo_proc; +int kvm_close __P((kvm_t *)); +char **kvm_getargv __P((kvm_t *, const struct kinfo_proc *, int)); +char **kvm_getenvv __P((kvm_t *, const struct kinfo_proc *, int)); +char *kvm_geterr __P((kvm_t *)); +int kvm_getloadavg __P((kvm_t *, double [], int)); +char *kvm_getfiles __P((kvm_t *, int, int, int *)); +struct kinfo_proc * + kvm_getprocs __P((kvm_t *, int, int, int *)); +int kvm_nlist __P((kvm_t *, struct nlist *)); +kvm_t *kvm_open + __P((const char *, const char *, const char *, int, const char *)); +kvm_t *kvm_openfiles + __P((const char *, const char *, const char *, int, char *)); +int kvm_read __P((kvm_t *, unsigned long, void *, unsigned int)); +int kvm_write __P((kvm_t *, unsigned long, const void *, unsigned int)); + +__END_DECLS + +#endif /* !_KVM_H_ */ diff --git a/lib/libskey/Makefile b/lib/libskey/Makefile new file mode 100644 index 0000000..ecf4833 --- /dev/null +++ b/lib/libskey/Makefile @@ -0,0 +1,7 @@ +# @(#)Makefile 5.4 (Berkeley) 5/7/91 + +LIB= skey +SRCS= authfile.c md4.c put.c skey_crypt.c skeylogin.c skeysubr.c +CFLAGS+=-DMPU8086 +.include <bsd.lib.mk> + diff --git a/lib/libskey/authfile.c b/lib/libskey/authfile.c new file mode 100644 index 0000000..32b920a --- /dev/null +++ b/lib/libskey/authfile.c @@ -0,0 +1,170 @@ + /* Portions taken from the skey distribution on Oct 21 1993 */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <string.h> +#include <netdb.h> +#include <arpa/inet.h> +#include <stdio.h> +#include <pwd.h> +#include <syslog.h> +#include <unistd.h> +#include <stdlib.h> + +#if (MAXHOSTNAMELEN < 64) /* AIX weirdness */ +#undef MAXHOSTNAMELEN +#endif + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 255 +#endif + +#include "skey.h" + +static int isaddr(); +static int rdnets(); + +#define MAXADDR 16 /* how many addresses can a machine + * have? */ + + /* + * Turn host into an IP address and then look it up in the authorization + * database to determine if ordinary password logins are OK + */ +int authfile(host) +char *host; +{ + char *addr[MAXADDR]; + char **ap; + long n; + struct hostent *hp; + char **lp; + struct hostent *xp; + int addr_length; + + if (strlen(host) == 0) { + /* Local login, okay */ + return 1; + } + if (isaddr(host)) { + return rdnets(inet_addr(host)); + } else { + + /* + * Stash away a copy of the host address list because it will be + * clobbered by other gethostbyXXX() calls. + */ + + hp = gethostbyname(host); + if (hp == NULL) { + syslog(LOG_ERR, "unknown host: %s", host); + return 0; + } + if (hp->h_addrtype != AF_INET) { + syslog(LOG_ERR, "unknown network family: %d", hp->h_addrtype); + return 0; + } + for (lp = hp->h_addr_list, ap = addr; ap < addr + MAXADDR; lp++, ap++) { + if (*lp == NULL) { + *ap = 0; + break; + } else { + if ((*ap = malloc(hp->h_length)) == 0) { + syslog(LOG_ERR, "out of memory"); + return 0; + } + memcpy(*ap, *lp, hp->h_length); + } + } + addr_length = hp->h_length; + + /* + * See if any of the addresses matches a pattern in the control file. + * Report and skip the address if it does not belong to the remote + * host. Assume localhost == localhost.domain. + */ + +#define NEQ(x,y) (strcasecmp((x),(y)) != 0) + + while (ap-- > addr) { + memcpy((char *) &n, *ap, addr_length); + if (rdnets(n)) { + if ((hp = gethostbyaddr(*ap, addr_length, AF_INET)) == 0 + || (NEQ(host, hp->h_name) && NEQ(host, "localhost"))) { + syslog(LOG_ERR, "IP address %s not registered for host %s", + inet_ntoa(*(struct in_addr *) * ap), host); + continue; + } + return 1; + } + } + return 0; + } +} +static int rdnets(host) +unsigned long host; +{ + FILE *fp; + char buf[128], + *cp; + long pattern, + mask; + char *strtok(); + int permit_it = 0; + + fp = fopen("/etc/skey.access", "r"); + if (fp == NULL) + return 1; /* XXX */ + while (fgets(buf, sizeof(buf), fp), !feof(fp)) { + if (buf[0] == '#') + continue; /* Comment */ + cp = strtok(buf, " \t"); + if (cp == NULL) + continue; + /* two choices permit or deny */ + if (strncasecmp(cp, "permit", 4) == 0) { + permit_it = 1; + } else { + if (strncasecmp(cp, "deny", 4) == 0) { + permit_it = 0; + } else { + continue; /* ignore this it is not + * permit/deny */ + } + } + cp = strtok(NULL, " \t"); + if (cp == NULL) + continue; /* Invalid line */ + pattern = inet_addr(cp); + cp = strtok(NULL, " \t"); + if (cp == NULL) + continue; /* Invalid line */ + mask = inet_addr(cp); + if ((host & mask) == pattern) { + fclose(fp); + return permit_it; + } + } + fclose(fp); + return 0; +} + + /* + * Return TRUE if string appears to be an IP address in dotted decimal; + * return FALSE otherwise (i.e., if string is a domain name) + */ +static int isaddr(s) +register char *s; +{ + char c; + + if (s == NULL) + return 1; /* Can't happen */ + + while ((c = *s++) != '\0') { + if (c != '[' && c != ']' && !isdigit(c) && c != '.') + return 0; + } + return 1; +} diff --git a/lib/libskey/md4.c b/lib/libskey/md4.c new file mode 100644 index 0000000..84d7661 --- /dev/null +++ b/lib/libskey/md4.c @@ -0,0 +1,336 @@ +/* + * md4.c -- Implementation of MD4 Message Digest Algorithm + * Updated: 2/16/90 by Ronald L. Rivest + * + * Portability nits fixed and reformatted - 2/12/91 Phil Karn + * + * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All + * rights reserved. + * + * License to copy and use this software is granted provided that it + * is identified as the "RSA Data Security, Inc. MD5 Message-Digest + * Algorithm" in all material mentioning or referencing this software + * or this function. + * + * License is also granted to make and use derivative works provided + * that such works are identified as "derived from the RSA Data + * Security, Inc. MD5 Message-Digest Algorithm" in all material + * mentioning or referencing the derived work. + * + * RSA Data Security, Inc. makes no representations concerning either + * the merchantability of this software or the suitability of this + * software for any particular purpose. It is provided "as is" + * without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + */ + +/* + * To use MD4: + * -- Include md4.h in your program + * -- Declare an MDstruct MD to hold the state of the digest computation. + * -- Initialize MD using MDbegin(&MD) + * -- For each full block (64 bytes) X you wish to process, call + * MDupdate(&MD,X,512) + * (512 is the number of bits in a full block.) + * -- For the last block (less than 64 bytes) you wish to process, + * MDupdate(&MD,X,n) + * where n is the number of bits in the partial block. A partial + * block terminates the computation, so every MD computation should + * terminate by processing a partial block, even if it has n = 0. + * -- The message digest is available in MD.buffer[0] ... MD.buffer[3]. + * (Least-significant byte of each word should be output first.) + * -- You can print out the digest using MDprint(&MD) + */ + +/* Implementation notes: + * This implementation assumes that longs are 32-bit quantities. + * If the machine stores the least-significant byte of an long in the + * least-addressed byte (eg., VAX and 8086), then LOWBYTEFIRST should be + * set to TRUE. Otherwise (eg., SUNS), LOWBYTEFIRST should be set to + * FALSE. Note that on machines with LOWBYTEFIRST FALSE the routine + * MDupdate modifies has a side-effect on its input array (the order of bytes + * in each word are reversed). If this is undesired a call to MDreverse(X) can + * reverse the bytes of X back into order after each call to MDupdate. + */ +#define TRUE 1 +#define FALSE 0 + +#if (defined(__MSDOS__) || defined(MPU8086) || defined(MPU8080) \ + || defined(vax) || defined (MIPSEL)) +#define LOWBYTEFIRST TRUE /* Low order bytes are first in memory */ +#else /* Almost all other machines are big-endian */ +#define LOWBYTEFIRST FALSE +#endif + + +/* Compile-time includes */ +#include <stdio.h> +#include "md4.h" + +/* Compile-time declarations of MD4 ``magic constants'' */ +#define I0 0x67452301 /* Initial values for MD buffer */ +#define I1 0xefcdab89 +#define I2 0x98badcfe +#define I3 0x10325476 +#define C2 013240474631 /* round 2 constant = sqrt(2) in octal */ +#define C3 015666365641 /* round 3 constant = sqrt(3) in octal */ +/* C2 and C3 are from Knuth, The Art of Programming, Volume 2 + * (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley. + * Table 2, page 660. + */ +#define fs1 3 /* round 1 shift amounts */ +#define fs2 7 +#define fs3 11 +#define fs4 19 +#define gs1 3 /* round 2 shift amounts */ +#define gs2 5 +#define gs3 9 +#define gs4 13 +#define hs1 3 /* round 3 shift amounts */ +#define hs2 9 +#define hs3 11 +#define hs4 15 + + +/* Compile-time macro declarations for MD4. + * Note: The ``rot'' operator uses the variable ``tmp''. + * It assumes tmp is declared as unsigned long, so that the >> + * operator will shift in zeros rather than extending the sign bit. + */ +#define f(X,Y,Z) ((X&Y) | ((~X)&Z)) +#define g(X,Y,Z) ((X&Y) | (X&Z) | (Y&Z)) +#define h(X,Y,Z) (X^Y^Z) +#define rot(X,S) (tmp=X,(tmp<<S) | (tmp>>(32-S))) +#define ff(A,B,C,D,i,s) A = rot((A + f(B,C,D) + X[i]),s) +#define gg(A,B,C,D,i,s) A = rot((A + g(B,C,D) + X[i] + C2),s) +#define hh(A,B,C,D,i,s) A = rot((A + h(B,C,D) + X[i] + C3),s) + +void MDreverse __ARGS((unsigned long *X)); + +/* MDprint(MDp) + * Print message digest buffer MDp as 32 hexadecimal digits. + * Order is from low-order byte of buffer[0] to high-order byte of buffer[3]. + * Each byte is printed with high-order hexadecimal digit first. + * This is a user-callable routine. + */ +void +MDprint(MDp) +MDptr MDp; +{ + int i,j; + + for(i=0;i<4;i++) + for(j=0;j<32;j=j+8) + printf("%02lx",(MDp->buffer[i]>>j) & 0xFF); +} + +/* MDbegin(MDp) + * Initialize message digest buffer MDp. + * This is a user-callable routine. + */ +void +MDbegin(MDp) +MDptr MDp; +{ + int i; + + MDp->buffer[0] = I0; + MDp->buffer[1] = I1; + MDp->buffer[2] = I2; + MDp->buffer[3] = I3; + for(i=0;i<8;i++) + MDp->count[i] = 0; + MDp->done = 0; +} + +/* MDreverse(X) + * Reverse the byte-ordering of every long in X. + * Assumes X is an array of 16 longs. + * The macro revx reverses the byte-ordering of the next word of X. + */ +#define revx { t = (*X << 16) | (*X >> 16); \ + *X++ = ((t & 0xFF00FF00) >> 8) | ((t & 0x00FF00FF) << 8); } +void +MDreverse(X) +unsigned long *X; +{ + register unsigned long t; + + revx; + revx; + revx; + revx; + revx; + revx; + revx; + revx; + revx; + revx; + revx; + revx; + revx; + revx; + revx; + revx; +} + +/* MDblock(MDp,X) + * Update message digest buffer MDp->buffer using 16-word data block X. + * Assumes all 16 words of X are full of data. + * Does not update MDp->count. + * This routine is not user-callable. + */ +static void +MDblock(MDp,X) +MDptr MDp; +unsigned long *X; +{ + register unsigned long tmp, A, B, C, D; + +#if LOWBYTEFIRST == FALSE + MDreverse(X); +#endif + A = MDp->buffer[0]; + B = MDp->buffer[1]; + C = MDp->buffer[2]; + D = MDp->buffer[3]; + /* Update the message digest buffer */ + ff(A,B,C,D,0,fs1); /* Round 1 */ + ff(D,A,B,C,1,fs2); + ff(C,D,A,B,2,fs3); + ff(B,C,D,A,3,fs4); + ff(A,B,C,D,4,fs1); + ff(D,A,B,C,5,fs2); + ff(C,D,A,B,6,fs3); + ff(B,C,D,A,7,fs4); + ff(A,B,C,D,8,fs1); + ff(D,A,B,C,9,fs2); + ff(C,D,A,B,10,fs3); + ff(B,C,D,A,11,fs4); + ff(A,B,C,D,12,fs1); + ff(D,A,B,C,13,fs2); + ff(C,D,A,B,14,fs3); + ff(B,C,D,A,15,fs4); + gg(A,B,C,D,0,gs1); /* Round 2 */ + gg(D,A,B,C,4,gs2); + gg(C,D,A,B,8,gs3); + gg(B,C,D,A,12,gs4); + gg(A,B,C,D,1,gs1); + gg(D,A,B,C,5,gs2); + gg(C,D,A,B,9,gs3); + gg(B,C,D,A,13,gs4); + gg(A,B,C,D,2,gs1); + gg(D,A,B,C,6,gs2); + gg(C,D,A,B,10,gs3); + gg(B,C,D,A,14,gs4); + gg(A,B,C,D,3,gs1); + gg(D,A,B,C,7,gs2); + gg(C,D,A,B,11,gs3); + gg(B,C,D,A,15,gs4); + hh(A,B,C,D,0,hs1); /* Round 3 */ + hh(D,A,B,C,8,hs2); + hh(C,D,A,B,4,hs3); + hh(B,C,D,A,12,hs4); + hh(A,B,C,D,2,hs1); + hh(D,A,B,C,10,hs2); + hh(C,D,A,B,6,hs3); + hh(B,C,D,A,14,hs4); + hh(A,B,C,D,1,hs1); + hh(D,A,B,C,9,hs2); + hh(C,D,A,B,5,hs3); + hh(B,C,D,A,13,hs4); + hh(A,B,C,D,3,hs1); + hh(D,A,B,C,11,hs2); + hh(C,D,A,B,7,hs3); + hh(B,C,D,A,15,hs4); + MDp->buffer[0] += A; + MDp->buffer[1] += B; + MDp->buffer[2] += C; + MDp->buffer[3] += D; +} + +/* MDupdate(MDp,X,count) + * Input: MDp -- an MDptr + * X -- a pointer to an array of unsigned characters. + * count -- the number of bits of X to use. + * (if not a multiple of 8, uses high bits of last byte.) + * Update MDp using the number of bits of X given by count. + * This is the basic input routine for an MD4 user. + * The routine completes the MD computation when count < 512, so + * every MD computation should end with one call to MDupdate with a + * count less than 512. A call with count 0 will be ignored if the + * MD has already been terminated (done != 0), so an extra call with count + * 0 can be given as a ``courtesy close'' to force termination if desired. + */ +void +MDupdate(MDp,X,count) +MDptr MDp; +unsigned char *X; +unsigned int count; +{ + int i,bit,byte,mask; + unsigned long tmp; + unsigned char XX[64]; + unsigned char *p; + + /* return with no error if this is a courtesy close with count + * zero and MDp->done is true. + */ + if(count == 0 && MDp->done) + return; + /* check to see if MD is already done and report error */ + if(MDp->done){ + printf("\nError: MDupdate MD already done."); + return; + } + /* Add count to MDp->count */ + tmp = count; + p = MDp->count; + while(tmp){ + tmp += *p; + *p++ = tmp; + tmp = tmp >> 8; + } + /* Process data */ + if(count == 512){ + /* Full block of data to handle */ + MDblock(MDp,(unsigned long *)X); + } else if(count > 512){ + /* Check for count too large */ + printf("\nError: MDupdate called with illegal count value %ld.",count); + return; + } else { + /* partial block -- must be last block so finish up + * Find out how many bytes and residual bits there are + */ + byte = count >> 3; + bit = count & 7; + /* Copy X into XX since we need to modify it */ + for(i=0;i<=byte;i++) + XX[i] = X[i]; + for(i=byte+1;i<64;i++) + XX[i] = 0; + /* Add padding '1' bit and low-order zeros in last byte */ + mask = 1 << (7 - bit); + XX[byte] = (XX[byte] | mask) & ~( mask - 1); + /* If room for bit count, finish up with this block */ + if(byte <= 55){ + for(i=0;i<8;i++) + XX[56+i] = MDp->count[i]; + MDblock(MDp,(unsigned long *)XX); + } else { + /* need to do two blocks to finish up */ + MDblock(MDp,(unsigned long *)XX); + for(i=0;i<56;i++) + XX[i] = 0; + for(i=0;i<8;i++) + XX[56+i] = MDp->count[i]; + MDblock(MDp,(unsigned long *)XX); + } + /* Set flag saying we're done with MD computation */ + MDp->done = 1; + } +} +/* End of md4.c */ diff --git a/lib/libskey/md4.h b/lib/libskey/md4.h new file mode 100644 index 0000000..5f2e031 --- /dev/null +++ b/lib/libskey/md4.h @@ -0,0 +1,50 @@ +#ifdef __STDC__ +#define __ARGS(X) X /* For ANSI C */ +#else +#define __ARGS(X) () +#endif + +/* + * + * md4.h -- Header file for implementation of MD4 Message Digest Algorithm + * Updated: 2/13/90 by Ronald L. Rivest + * (C) 1990 RSA Data Security, Inc. + * Reformatted and de-linted - 2/12/91 Phil Karn + */ + +/* MDstruct is the data structure for a message digest computation. */ +typedef struct { + unsigned long buffer[4];/* Holds 4-word result of MD computation */ + unsigned char count[8]; /* Number of bits processed so far */ + unsigned int done; /* Nonzero means MD computation finished */ +} MDstruct, *MDptr; + +/* MDbegin(MD) + * Input: MD -- an MDptr + * Initialize the MDstruct prepatory to doing a message digest computation. + */ +extern void MDbegin __ARGS((MDptr MDp)); + +/* MDupdate(MD,X,count) + * Input: MD -- an MDptr + * X -- a pointer to an array of unsigned characters. + * count -- the number of bits of X to use (an unsigned int). + * Updates MD using the first ``count'' bits of X. + * The array pointed to by X is not modified. + * If count is not a multiple of 8, MDupdate uses high bits of last byte. + * This is the basic input routine for a user. + * The routine terminates the MD computation when count < 512, so + * every MD computation should end with one call to MDupdate with a + * count less than 512. Zero is OK for a count. + */ +extern void MDupdate __ARGS((MDptr MDp,unsigned char *X,unsigned int count)); + +/* MDprint(MD) + * Input: MD -- an MDptr + * Prints message digest buffer MD as 32 hexadecimal digits. + * Order is from low-order byte of buffer[0] to high-order byte of buffer[3]. + * Each byte is printed with high-order hexadecimal digit first. + */ +extern void MDprint __ARGS((MDptr MDp)); + +/* End of md4.h */ diff --git a/lib/libskey/put.c b/lib/libskey/put.c new file mode 100644 index 0000000..1ef1ec0 --- /dev/null +++ b/lib/libskey/put.c @@ -0,0 +1,2289 @@ +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include <ctype.h> +#include "skey.h" + +static unsigned long extract __ARGS((char *s,int start,int length)); +static void standard __ARGS((char *word)); +static void insert __ARGS((char *s, int x, int start, int length)); +static int wsrch __ARGS((char *w,int low,int high)); + +/* Dictionary for integer-word translations */ +char Wp[2048][4] = { +"A", +"ABE", +"ACE", +"ACT", +"AD", +"ADA", +"ADD", +"AGO", +"AID", +"AIM", +"AIR", +"ALL", +"ALP", +"AM", +"AMY", +"AN", +"ANA", +"AND", +"ANN", +"ANT", +"ANY", +"APE", +"APS", +"APT", +"ARC", +"ARE", +"ARK", +"ARM", +"ART", +"AS", +"ASH", +"ASK", +"AT", +"ATE", +"AUG", +"AUK", +"AVE", +"AWE", +"AWK", +"AWL", +"AWN", +"AX", +"AYE", +"BAD", +"BAG", +"BAH", +"BAM", +"BAN", +"BAR", +"BAT", +"BAY", +"BE", +"BED", +"BEE", +"BEG", +"BEN", +"BET", +"BEY", +"BIB", +"BID", +"BIG", +"BIN", +"BIT", +"BOB", +"BOG", +"BON", +"BOO", +"BOP", +"BOW", +"BOY", +"BUB", +"BUD", +"BUG", +"BUM", +"BUN", +"BUS", +"BUT", +"BUY", +"BY", +"BYE", +"CAB", +"CAL", +"CAM", +"CAN", +"CAP", +"CAR", +"CAT", +"CAW", +"COD", +"COG", +"COL", +"CON", +"COO", +"COP", +"COT", +"COW", +"COY", +"CRY", +"CUB", +"CUE", +"CUP", +"CUR", +"CUT", +"DAB", +"DAD", +"DAM", +"DAN", +"DAR", +"DAY", +"DEE", +"DEL", +"DEN", +"DES", +"DEW", +"DID", +"DIE", +"DIG", +"DIN", +"DIP", +"DO", +"DOE", +"DOG", +"DON", +"DOT", +"DOW", +"DRY", +"DUB", +"DUD", +"DUE", +"DUG", +"DUN", +"EAR", +"EAT", +"ED", +"EEL", +"EGG", +"EGO", +"ELI", +"ELK", +"ELM", +"ELY", +"EM", +"END", +"EST", +"ETC", +"EVA", +"EVE", +"EWE", +"EYE", +"FAD", +"FAN", +"FAR", +"FAT", +"FAY", +"FED", +"FEE", +"FEW", +"FIB", +"FIG", +"FIN", +"FIR", +"FIT", +"FLO", +"FLY", +"FOE", +"FOG", +"FOR", +"FRY", +"FUM", +"FUN", +"FUR", +"GAB", +"GAD", +"GAG", +"GAL", +"GAM", +"GAP", +"GAS", +"GAY", +"GEE", +"GEL", +"GEM", +"GET", +"GIG", +"GIL", +"GIN", +"GO", +"GOT", +"GUM", +"GUN", +"GUS", +"GUT", +"GUY", +"GYM", +"GYP", +"HA", +"HAD", +"HAL", +"HAM", +"HAN", +"HAP", +"HAS", +"HAT", +"HAW", +"HAY", +"HE", +"HEM", +"HEN", +"HER", +"HEW", +"HEY", +"HI", +"HID", +"HIM", +"HIP", +"HIS", +"HIT", +"HO", +"HOB", +"HOC", +"HOE", +"HOG", +"HOP", +"HOT", +"HOW", +"HUB", +"HUE", +"HUG", +"HUH", +"HUM", +"HUT", +"I", +"ICY", +"IDA", +"IF", +"IKE", +"ILL", +"INK", +"INN", +"IO", +"ION", +"IQ", +"IRA", +"IRE", +"IRK", +"IS", +"IT", +"ITS", +"IVY", +"JAB", +"JAG", +"JAM", +"JAN", +"JAR", +"JAW", +"JAY", +"JET", +"JIG", +"JIM", +"JO", +"JOB", +"JOE", +"JOG", +"JOT", +"JOY", +"JUG", +"JUT", +"KAY", +"KEG", +"KEN", +"KEY", +"KID", +"KIM", +"KIN", +"KIT", +"LA", +"LAB", +"LAC", +"LAD", +"LAG", +"LAM", +"LAP", +"LAW", +"LAY", +"LEA", +"LED", +"LEE", +"LEG", +"LEN", +"LEO", +"LET", +"LEW", +"LID", +"LIE", +"LIN", +"LIP", +"LIT", +"LO", +"LOB", +"LOG", +"LOP", +"LOS", +"LOT", +"LOU", +"LOW", +"LOY", +"LUG", +"LYE", +"MA", +"MAC", +"MAD", +"MAE", +"MAN", +"MAO", +"MAP", +"MAT", +"MAW", +"MAY", +"ME", +"MEG", +"MEL", +"MEN", +"MET", +"MEW", +"MID", +"MIN", +"MIT", +"MOB", +"MOD", +"MOE", +"MOO", +"MOP", +"MOS", +"MOT", +"MOW", +"MUD", +"MUG", +"MUM", +"MY", +"NAB", +"NAG", +"NAN", +"NAP", +"NAT", +"NAY", +"NE", +"NED", +"NEE", +"NET", +"NEW", +"NIB", +"NIL", +"NIP", +"NIT", +"NO", +"NOB", +"NOD", +"NON", +"NOR", +"NOT", +"NOV", +"NOW", +"NU", +"NUN", +"NUT", +"O", +"OAF", +"OAK", +"OAR", +"OAT", +"ODD", +"ODE", +"OF", +"OFF", +"OFT", +"OH", +"OIL", +"OK", +"OLD", +"ON", +"ONE", +"OR", +"ORB", +"ORE", +"ORR", +"OS", +"OTT", +"OUR", +"OUT", +"OVA", +"OW", +"OWE", +"OWL", +"OWN", +"OX", +"PA", +"PAD", +"PAL", +"PAM", +"PAN", +"PAP", +"PAR", +"PAT", +"PAW", +"PAY", +"PEA", +"PEG", +"PEN", +"PEP", +"PER", +"PET", +"PEW", +"PHI", +"PI", +"PIE", +"PIN", +"PIT", +"PLY", +"PO", +"POD", +"POE", +"POP", +"POT", +"POW", +"PRO", +"PRY", +"PUB", +"PUG", +"PUN", +"PUP", +"PUT", +"QUO", +"RAG", +"RAM", +"RAN", +"RAP", +"RAT", +"RAW", +"RAY", +"REB", +"RED", +"REP", +"RET", +"RIB", +"RID", +"RIG", +"RIM", +"RIO", +"RIP", +"ROB", +"ROD", +"ROE", +"RON", +"ROT", +"ROW", +"ROY", +"RUB", +"RUE", +"RUG", +"RUM", +"RUN", +"RYE", +"SAC", +"SAD", +"SAG", +"SAL", +"SAM", +"SAN", +"SAP", +"SAT", +"SAW", +"SAY", +"SEA", +"SEC", +"SEE", +"SEN", +"SET", +"SEW", +"SHE", +"SHY", +"SIN", +"SIP", +"SIR", +"SIS", +"SIT", +"SKI", +"SKY", +"SLY", +"SO", +"SOB", +"SOD", +"SON", +"SOP", +"SOW", +"SOY", +"SPA", +"SPY", +"SUB", +"SUD", +"SUE", +"SUM", +"SUN", +"SUP", +"TAB", +"TAD", +"TAG", +"TAN", +"TAP", +"TAR", +"TEA", +"TED", +"TEE", +"TEN", +"THE", +"THY", +"TIC", +"TIE", +"TIM", +"TIN", +"TIP", +"TO", +"TOE", +"TOG", +"TOM", +"TON", +"TOO", +"TOP", +"TOW", +"TOY", +"TRY", +"TUB", +"TUG", +"TUM", +"TUN", +"TWO", +"UN", +"UP", +"US", +"USE", +"VAN", +"VAT", +"VET", +"VIE", +"WAD", +"WAG", +"WAR", +"WAS", +"WAY", +"WE", +"WEB", +"WED", +"WEE", +"WET", +"WHO", +"WHY", +"WIN", +"WIT", +"WOK", +"WON", +"WOO", +"WOW", +"WRY", +"WU", +"YAM", +"YAP", +"YAW", +"YE", +"YEA", +"YES", +"YET", +"YOU", +"ABED", +"ABEL", +"ABET", +"ABLE", +"ABUT", +"ACHE", +"ACID", +"ACME", +"ACRE", +"ACTA", +"ACTS", +"ADAM", +"ADDS", +"ADEN", +"AFAR", +"AFRO", +"AGEE", +"AHEM", +"AHOY", +"AIDA", +"AIDE", +"AIDS", +"AIRY", +"AJAR", +"AKIN", +"ALAN", +"ALEC", +"ALGA", +"ALIA", +"ALLY", +"ALMA", +"ALOE", +"ALSO", +"ALTO", +"ALUM", +"ALVA", +"AMEN", +"AMES", +"AMID", +"AMMO", +"AMOK", +"AMOS", +"AMRA", +"ANDY", +"ANEW", +"ANNA", +"ANNE", +"ANTE", +"ANTI", +"AQUA", +"ARAB", +"ARCH", +"AREA", +"ARGO", +"ARID", +"ARMY", +"ARTS", +"ARTY", +"ASIA", +"ASKS", +"ATOM", +"AUNT", +"AURA", +"AUTO", +"AVER", +"AVID", +"AVIS", +"AVON", +"AVOW", +"AWAY", +"AWRY", +"BABE", +"BABY", +"BACH", +"BACK", +"BADE", +"BAIL", +"BAIT", +"BAKE", +"BALD", +"BALE", +"BALI", +"BALK", +"BALL", +"BALM", +"BAND", +"BANE", +"BANG", +"BANK", +"BARB", +"BARD", +"BARE", +"BARK", +"BARN", +"BARR", +"BASE", +"BASH", +"BASK", +"BASS", +"BATE", +"BATH", +"BAWD", +"BAWL", +"BEAD", +"BEAK", +"BEAM", +"BEAN", +"BEAR", +"BEAT", +"BEAU", +"BECK", +"BEEF", +"BEEN", +"BEER", +"BEET", +"BELA", +"BELL", +"BELT", +"BEND", +"BENT", +"BERG", +"BERN", +"BERT", +"BESS", +"BEST", +"BETA", +"BETH", +"BHOY", +"BIAS", +"BIDE", +"BIEN", +"BILE", +"BILK", +"BILL", +"BIND", +"BING", +"BIRD", +"BITE", +"BITS", +"BLAB", +"BLAT", +"BLED", +"BLEW", +"BLOB", +"BLOC", +"BLOT", +"BLOW", +"BLUE", +"BLUM", +"BLUR", +"BOAR", +"BOAT", +"BOCA", +"BOCK", +"BODE", +"BODY", +"BOGY", +"BOHR", +"BOIL", +"BOLD", +"BOLO", +"BOLT", +"BOMB", +"BONA", +"BOND", +"BONE", +"BONG", +"BONN", +"BONY", +"BOOK", +"BOOM", +"BOON", +"BOOT", +"BORE", +"BORG", +"BORN", +"BOSE", +"BOSS", +"BOTH", +"BOUT", +"BOWL", +"BOYD", +"BRAD", +"BRAE", +"BRAG", +"BRAN", +"BRAY", +"BRED", +"BREW", +"BRIG", +"BRIM", +"BROW", +"BUCK", +"BUDD", +"BUFF", +"BULB", +"BULK", +"BULL", +"BUNK", +"BUNT", +"BUOY", +"BURG", +"BURL", +"BURN", +"BURR", +"BURT", +"BURY", +"BUSH", +"BUSS", +"BUST", +"BUSY", +"BYTE", +"CADY", +"CAFE", +"CAGE", +"CAIN", +"CAKE", +"CALF", +"CALL", +"CALM", +"CAME", +"CANE", +"CANT", +"CARD", +"CARE", +"CARL", +"CARR", +"CART", +"CASE", +"CASH", +"CASK", +"CAST", +"CAVE", +"CEIL", +"CELL", +"CENT", +"CERN", +"CHAD", +"CHAR", +"CHAT", +"CHAW", +"CHEF", +"CHEN", +"CHEW", +"CHIC", +"CHIN", +"CHOU", +"CHOW", +"CHUB", +"CHUG", +"CHUM", +"CITE", +"CITY", +"CLAD", +"CLAM", +"CLAN", +"CLAW", +"CLAY", +"CLOD", +"CLOG", +"CLOT", +"CLUB", +"CLUE", +"COAL", +"COAT", +"COCA", +"COCK", +"COCO", +"CODA", +"CODE", +"CODY", +"COED", +"COIL", +"COIN", +"COKE", +"COLA", +"COLD", +"COLT", +"COMA", +"COMB", +"COME", +"COOK", +"COOL", +"COON", +"COOT", +"CORD", +"CORE", +"CORK", +"CORN", +"COST", +"COVE", +"COWL", +"CRAB", +"CRAG", +"CRAM", +"CRAY", +"CREW", +"CRIB", +"CROW", +"CRUD", +"CUBA", +"CUBE", +"CUFF", +"CULL", +"CULT", +"CUNY", +"CURB", +"CURD", +"CURE", +"CURL", +"CURT", +"CUTS", +"DADE", +"DALE", +"DAME", +"DANA", +"DANE", +"DANG", +"DANK", +"DARE", +"DARK", +"DARN", +"DART", +"DASH", +"DATA", +"DATE", +"DAVE", +"DAVY", +"DAWN", +"DAYS", +"DEAD", +"DEAF", +"DEAL", +"DEAN", +"DEAR", +"DEBT", +"DECK", +"DEED", +"DEEM", +"DEER", +"DEFT", +"DEFY", +"DELL", +"DENT", +"DENY", +"DESK", +"DIAL", +"DICE", +"DIED", +"DIET", +"DIME", +"DINE", +"DING", +"DINT", +"DIRE", +"DIRT", +"DISC", +"DISH", +"DISK", +"DIVE", +"DOCK", +"DOES", +"DOLE", +"DOLL", +"DOLT", +"DOME", +"DONE", +"DOOM", +"DOOR", +"DORA", +"DOSE", +"DOTE", +"DOUG", +"DOUR", +"DOVE", +"DOWN", +"DRAB", +"DRAG", +"DRAM", +"DRAW", +"DREW", +"DRUB", +"DRUG", +"DRUM", +"DUAL", +"DUCK", +"DUCT", +"DUEL", +"DUET", +"DUKE", +"DULL", +"DUMB", +"DUNE", +"DUNK", +"DUSK", +"DUST", +"DUTY", +"EACH", +"EARL", +"EARN", +"EASE", +"EAST", +"EASY", +"EBEN", +"ECHO", +"EDDY", +"EDEN", +"EDGE", +"EDGY", +"EDIT", +"EDNA", +"EGAN", +"ELAN", +"ELBA", +"ELLA", +"ELSE", +"EMIL", +"EMIT", +"EMMA", +"ENDS", +"ERIC", +"EROS", +"EVEN", +"EVER", +"EVIL", +"EYED", +"FACE", +"FACT", +"FADE", +"FAIL", +"FAIN", +"FAIR", +"FAKE", +"FALL", +"FAME", +"FANG", +"FARM", +"FAST", +"FATE", +"FAWN", +"FEAR", +"FEAT", +"FEED", +"FEEL", +"FEET", +"FELL", +"FELT", +"FEND", +"FERN", +"FEST", +"FEUD", +"FIEF", +"FIGS", +"FILE", +"FILL", +"FILM", +"FIND", +"FINE", +"FINK", +"FIRE", +"FIRM", +"FISH", +"FISK", +"FIST", +"FITS", +"FIVE", +"FLAG", +"FLAK", +"FLAM", +"FLAT", +"FLAW", +"FLEA", +"FLED", +"FLEW", +"FLIT", +"FLOC", +"FLOG", +"FLOW", +"FLUB", +"FLUE", +"FOAL", +"FOAM", +"FOGY", +"FOIL", +"FOLD", +"FOLK", +"FOND", +"FONT", +"FOOD", +"FOOL", +"FOOT", +"FORD", +"FORE", +"FORK", +"FORM", +"FORT", +"FOSS", +"FOUL", +"FOUR", +"FOWL", +"FRAU", +"FRAY", +"FRED", +"FREE", +"FRET", +"FREY", +"FROG", +"FROM", +"FUEL", +"FULL", +"FUME", +"FUND", +"FUNK", +"FURY", +"FUSE", +"FUSS", +"GAFF", +"GAGE", +"GAIL", +"GAIN", +"GAIT", +"GALA", +"GALE", +"GALL", +"GALT", +"GAME", +"GANG", +"GARB", +"GARY", +"GASH", +"GATE", +"GAUL", +"GAUR", +"GAVE", +"GAWK", +"GEAR", +"GELD", +"GENE", +"GENT", +"GERM", +"GETS", +"GIBE", +"GIFT", +"GILD", +"GILL", +"GILT", +"GINA", +"GIRD", +"GIRL", +"GIST", +"GIVE", +"GLAD", +"GLEE", +"GLEN", +"GLIB", +"GLOB", +"GLOM", +"GLOW", +"GLUE", +"GLUM", +"GLUT", +"GOAD", +"GOAL", +"GOAT", +"GOER", +"GOES", +"GOLD", +"GOLF", +"GONE", +"GONG", +"GOOD", +"GOOF", +"GORE", +"GORY", +"GOSH", +"GOUT", +"GOWN", +"GRAB", +"GRAD", +"GRAY", +"GREG", +"GREW", +"GREY", +"GRID", +"GRIM", +"GRIN", +"GRIT", +"GROW", +"GRUB", +"GULF", +"GULL", +"GUNK", +"GURU", +"GUSH", +"GUST", +"GWEN", +"GWYN", +"HAAG", +"HAAS", +"HACK", +"HAIL", +"HAIR", +"HALE", +"HALF", +"HALL", +"HALO", +"HALT", +"HAND", +"HANG", +"HANK", +"HANS", +"HARD", +"HARK", +"HARM", +"HART", +"HASH", +"HAST", +"HATE", +"HATH", +"HAUL", +"HAVE", +"HAWK", +"HAYS", +"HEAD", +"HEAL", +"HEAR", +"HEAT", +"HEBE", +"HECK", +"HEED", +"HEEL", +"HEFT", +"HELD", +"HELL", +"HELM", +"HERB", +"HERD", +"HERE", +"HERO", +"HERS", +"HESS", +"HEWN", +"HICK", +"HIDE", +"HIGH", +"HIKE", +"HILL", +"HILT", +"HIND", +"HINT", +"HIRE", +"HISS", +"HIVE", +"HOBO", +"HOCK", +"HOFF", +"HOLD", +"HOLE", +"HOLM", +"HOLT", +"HOME", +"HONE", +"HONK", +"HOOD", +"HOOF", +"HOOK", +"HOOT", +"HORN", +"HOSE", +"HOST", +"HOUR", +"HOVE", +"HOWE", +"HOWL", +"HOYT", +"HUCK", +"HUED", +"HUFF", +"HUGE", +"HUGH", +"HUGO", +"HULK", +"HULL", +"HUNK", +"HUNT", +"HURD", +"HURL", +"HURT", +"HUSH", +"HYDE", +"HYMN", +"IBIS", +"ICON", +"IDEA", +"IDLE", +"IFFY", +"INCA", +"INCH", +"INTO", +"IONS", +"IOTA", +"IOWA", +"IRIS", +"IRMA", +"IRON", +"ISLE", +"ITCH", +"ITEM", +"IVAN", +"JACK", +"JADE", +"JAIL", +"JAKE", +"JANE", +"JAVA", +"JEAN", +"JEFF", +"JERK", +"JESS", +"JEST", +"JIBE", +"JILL", +"JILT", +"JIVE", +"JOAN", +"JOBS", +"JOCK", +"JOEL", +"JOEY", +"JOHN", +"JOIN", +"JOKE", +"JOLT", +"JOVE", +"JUDD", +"JUDE", +"JUDO", +"JUDY", +"JUJU", +"JUKE", +"JULY", +"JUNE", +"JUNK", +"JUNO", +"JURY", +"JUST", +"JUTE", +"KAHN", +"KALE", +"KANE", +"KANT", +"KARL", +"KATE", +"KEEL", +"KEEN", +"KENO", +"KENT", +"KERN", +"KERR", +"KEYS", +"KICK", +"KILL", +"KIND", +"KING", +"KIRK", +"KISS", +"KITE", +"KLAN", +"KNEE", +"KNEW", +"KNIT", +"KNOB", +"KNOT", +"KNOW", +"KOCH", +"KONG", +"KUDO", +"KURD", +"KURT", +"KYLE", +"LACE", +"LACK", +"LACY", +"LADY", +"LAID", +"LAIN", +"LAIR", +"LAKE", +"LAMB", +"LAME", +"LAND", +"LANE", +"LANG", +"LARD", +"LARK", +"LASS", +"LAST", +"LATE", +"LAUD", +"LAVA", +"LAWN", +"LAWS", +"LAYS", +"LEAD", +"LEAF", +"LEAK", +"LEAN", +"LEAR", +"LEEK", +"LEER", +"LEFT", +"LEND", +"LENS", +"LENT", +"LEON", +"LESK", +"LESS", +"LEST", +"LETS", +"LIAR", +"LICE", +"LICK", +"LIED", +"LIEN", +"LIES", +"LIEU", +"LIFE", +"LIFT", +"LIKE", +"LILA", +"LILT", +"LILY", +"LIMA", +"LIMB", +"LIME", +"LIND", +"LINE", +"LINK", +"LINT", +"LION", +"LISA", +"LIST", +"LIVE", +"LOAD", +"LOAF", +"LOAM", +"LOAN", +"LOCK", +"LOFT", +"LOGE", +"LOIS", +"LOLA", +"LONE", +"LONG", +"LOOK", +"LOON", +"LOOT", +"LORD", +"LORE", +"LOSE", +"LOSS", +"LOST", +"LOUD", +"LOVE", +"LOWE", +"LUCK", +"LUCY", +"LUGE", +"LUKE", +"LULU", +"LUND", +"LUNG", +"LURA", +"LURE", +"LURK", +"LUSH", +"LUST", +"LYLE", +"LYNN", +"LYON", +"LYRA", +"MACE", +"MADE", +"MAGI", +"MAID", +"MAIL", +"MAIN", +"MAKE", +"MALE", +"MALI", +"MALL", +"MALT", +"MANA", +"MANN", +"MANY", +"MARC", +"MARE", +"MARK", +"MARS", +"MART", +"MARY", +"MASH", +"MASK", +"MASS", +"MAST", +"MATE", +"MATH", +"MAUL", +"MAYO", +"MEAD", +"MEAL", +"MEAN", +"MEAT", +"MEEK", +"MEET", +"MELD", +"MELT", +"MEMO", +"MEND", +"MENU", +"MERT", +"MESH", +"MESS", +"MICE", +"MIKE", +"MILD", +"MILE", +"MILK", +"MILL", +"MILT", +"MIMI", +"MIND", +"MINE", +"MINI", +"MINK", +"MINT", +"MIRE", +"MISS", +"MIST", +"MITE", +"MITT", +"MOAN", +"MOAT", +"MOCK", +"MODE", +"MOLD", +"MOLE", +"MOLL", +"MOLT", +"MONA", +"MONK", +"MONT", +"MOOD", +"MOON", +"MOOR", +"MOOT", +"MORE", +"MORN", +"MORT", +"MOSS", +"MOST", +"MOTH", +"MOVE", +"MUCH", +"MUCK", +"MUDD", +"MUFF", +"MULE", +"MULL", +"MURK", +"MUSH", +"MUST", +"MUTE", +"MUTT", +"MYRA", +"MYTH", +"NAGY", +"NAIL", +"NAIR", +"NAME", +"NARY", +"NASH", +"NAVE", +"NAVY", +"NEAL", +"NEAR", +"NEAT", +"NECK", +"NEED", +"NEIL", +"NELL", +"NEON", +"NERO", +"NESS", +"NEST", +"NEWS", +"NEWT", +"NIBS", +"NICE", +"NICK", +"NILE", +"NINA", +"NINE", +"NOAH", +"NODE", +"NOEL", +"NOLL", +"NONE", +"NOOK", +"NOON", +"NORM", +"NOSE", +"NOTE", +"NOUN", +"NOVA", +"NUDE", +"NULL", +"NUMB", +"OATH", +"OBEY", +"OBOE", +"ODIN", +"OHIO", +"OILY", +"OINT", +"OKAY", +"OLAF", +"OLDY", +"OLGA", +"OLIN", +"OMAN", +"OMEN", +"OMIT", +"ONCE", +"ONES", +"ONLY", +"ONTO", +"ONUS", +"ORAL", +"ORGY", +"OSLO", +"OTIS", +"OTTO", +"OUCH", +"OUST", +"OUTS", +"OVAL", +"OVEN", +"OVER", +"OWLY", +"OWNS", +"QUAD", +"QUIT", +"QUOD", +"RACE", +"RACK", +"RACY", +"RAFT", +"RAGE", +"RAID", +"RAIL", +"RAIN", +"RAKE", +"RANK", +"RANT", +"RARE", +"RASH", +"RATE", +"RAVE", +"RAYS", +"READ", +"REAL", +"REAM", +"REAR", +"RECK", +"REED", +"REEF", +"REEK", +"REEL", +"REID", +"REIN", +"RENA", +"REND", +"RENT", +"REST", +"RICE", +"RICH", +"RICK", +"RIDE", +"RIFT", +"RILL", +"RIME", +"RING", +"RINK", +"RISE", +"RISK", +"RITE", +"ROAD", +"ROAM", +"ROAR", +"ROBE", +"ROCK", +"RODE", +"ROIL", +"ROLL", +"ROME", +"ROOD", +"ROOF", +"ROOK", +"ROOM", +"ROOT", +"ROSA", +"ROSE", +"ROSS", +"ROSY", +"ROTH", +"ROUT", +"ROVE", +"ROWE", +"ROWS", +"RUBE", +"RUBY", +"RUDE", +"RUDY", +"RUIN", +"RULE", +"RUNG", +"RUNS", +"RUNT", +"RUSE", +"RUSH", +"RUSK", +"RUSS", +"RUST", +"RUTH", +"SACK", +"SAFE", +"SAGE", +"SAID", +"SAIL", +"SALE", +"SALK", +"SALT", +"SAME", +"SAND", +"SANE", +"SANG", +"SANK", +"SARA", +"SAUL", +"SAVE", +"SAYS", +"SCAN", +"SCAR", +"SCAT", +"SCOT", +"SEAL", +"SEAM", +"SEAR", +"SEAT", +"SEED", +"SEEK", +"SEEM", +"SEEN", +"SEES", +"SELF", +"SELL", +"SEND", +"SENT", +"SETS", +"SEWN", +"SHAG", +"SHAM", +"SHAW", +"SHAY", +"SHED", +"SHIM", +"SHIN", +"SHOD", +"SHOE", +"SHOT", +"SHOW", +"SHUN", +"SHUT", +"SICK", +"SIDE", +"SIFT", +"SIGH", +"SIGN", +"SILK", +"SILL", +"SILO", +"SILT", +"SINE", +"SING", +"SINK", +"SIRE", +"SITE", +"SITS", +"SITU", +"SKAT", +"SKEW", +"SKID", +"SKIM", +"SKIN", +"SKIT", +"SLAB", +"SLAM", +"SLAT", +"SLAY", +"SLED", +"SLEW", +"SLID", +"SLIM", +"SLIT", +"SLOB", +"SLOG", +"SLOT", +"SLOW", +"SLUG", +"SLUM", +"SLUR", +"SMOG", +"SMUG", +"SNAG", +"SNOB", +"SNOW", +"SNUB", +"SNUG", +"SOAK", +"SOAR", +"SOCK", +"SODA", +"SOFA", +"SOFT", +"SOIL", +"SOLD", +"SOME", +"SONG", +"SOON", +"SOOT", +"SORE", +"SORT", +"SOUL", +"SOUR", +"SOWN", +"STAB", +"STAG", +"STAN", +"STAR", +"STAY", +"STEM", +"STEW", +"STIR", +"STOW", +"STUB", +"STUN", +"SUCH", +"SUDS", +"SUIT", +"SULK", +"SUMS", +"SUNG", +"SUNK", +"SURE", +"SURF", +"SWAB", +"SWAG", +"SWAM", +"SWAN", +"SWAT", +"SWAY", +"SWIM", +"SWUM", +"TACK", +"TACT", +"TAIL", +"TAKE", +"TALE", +"TALK", +"TALL", +"TANK", +"TASK", +"TATE", +"TAUT", +"TEAL", +"TEAM", +"TEAR", +"TECH", +"TEEM", +"TEEN", +"TEET", +"TELL", +"TEND", +"TENT", +"TERM", +"TERN", +"TESS", +"TEST", +"THAN", +"THAT", +"THEE", +"THEM", +"THEN", +"THEY", +"THIN", +"THIS", +"THUD", +"THUG", +"TICK", +"TIDE", +"TIDY", +"TIED", +"TIER", +"TILE", +"TILL", +"TILT", +"TIME", +"TINA", +"TINE", +"TINT", +"TINY", +"TIRE", +"TOAD", +"TOGO", +"TOIL", +"TOLD", +"TOLL", +"TONE", +"TONG", +"TONY", +"TOOK", +"TOOL", +"TOOT", +"TORE", +"TORN", +"TOTE", +"TOUR", +"TOUT", +"TOWN", +"TRAG", +"TRAM", +"TRAY", +"TREE", +"TREK", +"TRIG", +"TRIM", +"TRIO", +"TROD", +"TROT", +"TROY", +"TRUE", +"TUBA", +"TUBE", +"TUCK", +"TUFT", +"TUNA", +"TUNE", +"TUNG", +"TURF", +"TURN", +"TUSK", +"TWIG", +"TWIN", +"TWIT", +"ULAN", +"UNIT", +"URGE", +"USED", +"USER", +"USES", +"UTAH", +"VAIL", +"VAIN", +"VALE", +"VARY", +"VASE", +"VAST", +"VEAL", +"VEDA", +"VEIL", +"VEIN", +"VEND", +"VENT", +"VERB", +"VERY", +"VETO", +"VICE", +"VIEW", +"VINE", +"VISE", +"VOID", +"VOLT", +"VOTE", +"WACK", +"WADE", +"WAGE", +"WAIL", +"WAIT", +"WAKE", +"WALE", +"WALK", +"WALL", +"WALT", +"WAND", +"WANE", +"WANG", +"WANT", +"WARD", +"WARM", +"WARN", +"WART", +"WASH", +"WAST", +"WATS", +"WATT", +"WAVE", +"WAVY", +"WAYS", +"WEAK", +"WEAL", +"WEAN", +"WEAR", +"WEED", +"WEEK", +"WEIR", +"WELD", +"WELL", +"WELT", +"WENT", +"WERE", +"WERT", +"WEST", +"WHAM", +"WHAT", +"WHEE", +"WHEN", +"WHET", +"WHOA", +"WHOM", +"WICK", +"WIFE", +"WILD", +"WILL", +"WIND", +"WINE", +"WING", +"WINK", +"WINO", +"WIRE", +"WISE", +"WISH", +"WITH", +"WOLF", +"WONT", +"WOOD", +"WOOL", +"WORD", +"WORE", +"WORK", +"WORM", +"WORN", +"WOVE", +"WRIT", +"WYNN", +"YALE", +"YANG", +"YANK", +"YARD", +"YARN", +"YAWL", +"YAWN", +"YEAH", +"YEAR", +"YELL", +"YOGA", +"YOKE" +}; + +/* Encode 8 bytes in 'c' as a string of English words. + * Returns a pointer to a static buffer + */ +char * +btoe(engout,c) +char *c, *engout; +{ + char cp[9]; /* add in room for the parity 2 bits*/ + int p,i ; + + engout[0] = '\0'; + memcpy(cp, c,8); + /* compute parity */ + for(p = 0,i = 0; i < 64;i += 2) + p += extract(cp,i,2); + + cp[8] = (char)p << 6; + strncat(engout,&Wp[extract(cp, 0,11)][0],4); + strcat(engout," "); + strncat(engout,&Wp[extract(cp,11,11)][0],4); + strcat(engout," "); + strncat(engout,&Wp[extract(cp,22,11)][0],4); + strcat(engout," "); + strncat(engout,&Wp[extract(cp,33,11)][0],4); + strcat(engout," "); + strncat(engout,&Wp[extract(cp,44,11)][0],4); + strcat(engout," "); + strncat(engout,&Wp[extract(cp,55,11)][0],4); +#ifdef notdef + printf("engout is %s\n\r",engout); +#endif + return(engout); +} + +/* convert English to binary + * returns 1 OK - all good words and parity is OK + * 0 word not in data base + * -1 badly formed in put ie > 4 char word + * -2 words OK but parity is wrong + */ +int +etob(out, e) +char *out; +char *e; +{ + char *word; + int i, p, v,l, low,high; + char b[9]; + char input[36]; + + if(e == NULL) + return -1; + + strncpy(input,e,sizeof(input)); + memset(b, 0, sizeof(b)); + memset(out, 0, 8); + for(i=0,p=0;i<6;i++,p+=11){ + if((word = strtok(i == 0 ? input : NULL," ")) == NULL) + return -1; + l = strlen(word); + if(l > 4 || l < 1){ + return -1; + } else if(l < 4){ + low = 0; + high = 570; + } else { + low = 571; + high = 2047; + } + standard(word); + if( (v = wsrch(word,low,high)) < 0 ) + return 0; + insert(b,v,p,11); + } + + /* now check the parity of what we got */ + for(p = 0, i = 0; i < 64; i +=2) + p += extract(b, i, 2); + + if( (p & 3) != extract(b, 64,2) ) + return -2; + + memcpy(out,b,8); + + return 1; +} +/* Display 8 bytes as a series of 16-bit hex digits */ +char * +put8(out,s) +char *out; +char *s; +{ + sprintf(out,"%02X%02X %02X%02X %02X%02X %02X%02X", + s[0] & 0xff,s[1] & 0xff,s[2] & 0xff, + s[3] & 0xff,s[4] & 0xff,s[5] & 0xff, + s[6] & 0xff,s[7] & 0xff); + return out; +} +#ifdef notdef +/* Encode 8 bytes in 'cp' as stream of ascii letters. + * Provided as a possible alternative to btoe() + */ +char * +btoc(cp) +char *cp; +{ + int i; + static char out[31]; + + /* code out put by characters 6 bits each added to 0x21 (!)*/ + for(i=0;i <= 10;i++){ + /* last one is only 4 bits not 6*/ + out[i] = '!'+ extract(cp,6*i,i >= 10 ? 4:6); + } + out[i] = '\0'; + return(out); +} +#endif + +/* Internal subroutines for word encoding/decoding */ + +/* Dictionary binary search */ +static int +wsrch(w,low,high) +char *w; +int low, high; +{ + int i,j; + + for(;;){ + i = (low + high)/2; + if((j = strncmp(w,Wp[i],4)) == 0) + return i; /* Found it */ + if(high == low+1){ + /* Avoid effects of integer truncation in /2 */ + if(strncmp(w,Wp[high],4) == 0) + return high; + else + return -1; + } + if(low >= high) + return -1; /* I don't *think* this can happen...*/ + if(j < 0) + high = i; /* Search lower half */ + else + low = i; /* Search upper half */ + } +} +static void +insert(s, x, start, length) +char *s; +int x; +int start, length; +{ + unsigned char cl; + unsigned char cc; + unsigned char cr; + unsigned long y; + int shift; + + assert(length <= 11); + assert(start >= 0); + assert(length >= 0); + assert(start +length <= 66); + + shift = ((8 -(( start + length) % 8))%8); + y = (long) x << shift; + cl = (y >> 16) & 0xff; + cc = (y >> 8) & 0xff; + cr = y & 0xff; + if(shift + length > 16){ + s[start /8] |= cl; + s[start/8 +1] |= cc; + s[start/8 +2] |= cr; + } else if(shift +length > 8){ + s[start/8] |= cc; + s[start/8 + 1] |= cr; + } else { + s[start/8] |= cr; + } +} + +static void +standard(word) +register char *word; +{ + while(*word){ + if(!isascii(*word)) + break; + if(islower(*word)) + *word = toupper(*word); + if(*word == '1') + *word = 'L'; + if(*word == '0') + *word = 'O'; + if(*word == '5') + *word = 'S'; + word++; + } +} + +/* Extract 'length' bits from the char array 's' starting with bit 'start' */ +static unsigned long +extract(s, start, length) +char *s; +int start, length; +{ + unsigned char cl; + unsigned char cc; + unsigned char cr; + unsigned long x; + + assert(length <= 11); + assert(start >= 0); + assert(length >= 0); + assert(start +length <= 66); + + cl = s[start/8]; + cc = s[start/8 +1]; + cr = s[start/8 +2]; + x = ((long)(cl<<8 | cc) <<8 | cr) ; + x = x >> (24 - (length + (start %8))); + x =( x & (0xffff >> (16-length) ) ); + return(x); +} + diff --git a/lib/libskey/skey_crypt.c b/lib/libskey/skey_crypt.c new file mode 100644 index 0000000..ca1024f --- /dev/null +++ b/lib/libskey/skey_crypt.c @@ -0,0 +1,38 @@ +/* Author: Wietse Venema, Eindhoven University of Technology. */ + +#include <string.h> +#include <stdio.h> +#include <pwd.h> + +#include "skey.h" + +/* skey_crypt - return encrypted UNIX passwd if s/key or regular password ok */ + +char *skey_crypt(pp, salt, pwd, pwok) +char *pp; +char *salt; +struct passwd *pwd; +int pwok; +{ + struct skey skey; + char *p; + char *crypt(); + + /* Try s/key authentication even when the UNIX password is permitted. */ + + if (pwd != 0 && skeylookup(&skey, pwd->pw_name) == 0 + && skeyverify(&skey, pp) == 0) { + /* s/key authentication succeeded */ + return (pwd->pw_passwd); + } + + /* When s/key authentication does not work, always invoke crypt(). */ + + p = crypt(pp, salt); + if (pwok && pwd != 0 && strcmp(p, pwd->pw_passwd) == 0) + return (pwd->pw_passwd); + + /* The user does not exist or entered bad input. */ + + return (":"); +} diff --git a/lib/libskey/skeylogin.c b/lib/libskey/skeylogin.c new file mode 100644 index 0000000..bc49cb7 --- /dev/null +++ b/lib/libskey/skeylogin.c @@ -0,0 +1,328 @@ +/* Login code for S/KEY Authentication. S/KEY is a trademark + * of Bellcore. + * + * Mink is the former name of the S/KEY authentication system. + * Many references for mink may still be found in this program. */ + +#include <sys/param.h> +#ifdef QUOTA +#include <sys/quota.h> +#endif +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/resource.h> + + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <time.h> +#include <errno.h> +#include "skey.h" + +#define KEYFILE "/etc/skeykeys" + +char *skipspace(); +int skeylookup __ARGS((struct skey *mp,char *name)); + +#define setpriority(x,y,z) /* nothing */ + +/* Issue a skey challenge for user 'name'. If successful, + * fill in the caller's skey structure and return 0. If unsuccessful + * (e.g., if name is unknown) return -1. + * + * The file read/write pointer is left at the start of the + * record. + */ +int +getskeyprompt(mp,name,prompt) +struct skey *mp; +char *name; +char *prompt; +{ + int rval; + + sevenbit(name); + rval = skeylookup(mp,name); + strcpy(prompt,"s/key 55 latour1\n"); + switch(rval){ + case -1: /* File error */ + return -1; + case 0: /* Lookup succeeded, return challenge */ + sprintf(prompt,"s/key %d %s\n",mp->n - 1,mp->seed); + return 0; + case 1: /* User not found */ + fclose(mp->keyfile); + return -1; + } + return -1; /* Can't happen */ +} +/* Return a skey challenge string for user 'name'. If successful, + * fill in the caller's skey structure and return 0. If unsuccessful + * (e.g., if name is unknown) return -1. + * + * The file read/write pointer is left at the start of the + * record. + */ +int +skeychallenge(mp,name, ss) +struct skey *mp; +char *name; +char *ss; +{ + int rval; + + rval = skeylookup(mp,name); + switch(rval){ + case -1: /* File error */ + return -1; + case 0: /* Lookup succeeded, issue challenge */ + sprintf(ss, "s/key %d %s",mp->n - 1,mp->seed); + return 0; + case 1: /* User not found */ + fclose(mp->keyfile); + return -1; + } + return -1; /* Can't happen */ +} + +/* Find an entry in the One-time Password database. + * Return codes: + * -1: error in opening database + * 0: entry found, file R/W pointer positioned at beginning of record + * 1: entry not found, file R/W pointer positioned at EOF + */ +int +skeylookup(mp,name) +struct skey *mp; +char *name; +{ + int found; + int len; + long recstart; + char *cp; + struct stat statbuf; + + /* See if the KEYFILE exists, and create it if not */ + if(stat(KEYFILE,&statbuf) == -1 && errno == ENOENT){ + mp->keyfile = fopen(KEYFILE,"w+"); + (void) chmod(KEYFILE, 0644); + } else { + /* Otherwise open normally for update */ + mp->keyfile = fopen(KEYFILE,"r+"); + } + if(mp->keyfile == NULL) + return -1; + + /* Look up user name in database */ + len = strlen(name); + if( len > 8 ) len = 8; /* Added 8/2/91 - nmh */ + found = 0; + while(!feof(mp->keyfile)){ + recstart = ftell(mp->keyfile); + mp->recstart = recstart; + if(fgets(mp->buf,sizeof(mp->buf),mp->keyfile) != mp->buf){ + break; + } + rip(mp->buf); + if(mp->buf[0] == '#') + continue; /* Comment */ + if((mp->logname = strtok(mp->buf," \t")) == NULL) + continue; + if((cp = strtok(NULL," \t")) == NULL) + continue; + mp->n = atoi(cp); + if((mp->seed = strtok(NULL," \t")) == NULL) + continue; + if((mp->val = strtok(NULL," \t")) == NULL) + continue; + if(strlen(mp->logname) == len + && strncmp(mp->logname,name,len) == 0){ + found = 1; + break; + } + } + if(found){ + fseek(mp->keyfile,recstart,0); + return 0; + } else + return 1; +} +/* Verify response to a s/key challenge. + * + * Return codes: + * -1: Error of some sort; database unchanged + * 0: Verify successful, database updated + * 1: Verify failed, database unchanged + * + * The database file is always closed by this call. + */ +int +skeyverify(mp,response) +struct skey *mp; +char *response; +{ + struct timeval startval; + struct timeval endval; +long microsec; + char key[8]; + char fkey[8]; + char filekey[8]; + time_t now; + struct tm *tm; + char tbuf[27],buf[60]; + char me[80]; + int rval; + char *cp; + + time(&now); + tm = localtime(&now); + strftime(tbuf, sizeof(tbuf), " %b %d,%Y %T", tm); + + if(response == NULL){ + fclose(mp->keyfile); + return -1; + } + rip(response); + + /* Convert response to binary */ + if(etob(key,response) != 1 && atob8(key,response) != 0){ + /* Neither english words or ascii hex */ + fclose(mp->keyfile); + return -1; + } + + /* Compute fkey = f(key) */ + memcpy(fkey,key,sizeof(key)); + f(fkey); + /* in order to make the window of update as short as possible + we must do the comparison here and if OK write it back + other wise the same password can be used twice to get in + to the system + */ + + setpriority(PRIO_PROCESS, 0, -4); +/* + gettimeofday(&startval, (char *)0 ); +*/ + + /* reread the file record NOW*/ + + fseek(mp->keyfile,mp->recstart,0); + if(fgets(mp->buf,sizeof(mp->buf),mp->keyfile) != mp->buf){ + setpriority(PRIO_PROCESS, 0, 0); + fclose(mp->keyfile); + return -1; + } + rip(mp->buf); + mp->logname = strtok(mp->buf," \t"); + cp = strtok(NULL," \t") ; + mp->seed = strtok(NULL," \t"); + mp->val = strtok(NULL," \t"); + /* And convert file value to hex for comparison */ + atob8(filekey,mp->val); + + /* Do actual comparison */ + if(memcmp(filekey,fkey,8) != 0){ + /* Wrong response */ + setpriority(PRIO_PROCESS, 0, 0); + fclose(mp->keyfile); + return 1; + } + + /* Update key in database by overwriting entire record. Note + * that we must write exactly the same number of bytes as in + * the original record (note fixed width field for N) + */ + btoa8(mp->val,key); + mp->n--; + fseek(mp->keyfile,mp->recstart,0); + fprintf(mp->keyfile,"%s %04d %-16s %s %-21s\n",mp->logname,mp->n,mp->seed, + mp->val, tbuf); +/* +gettimeofday(&endval, (char *)0 ); + microsec = (endval.tv_sec - startval.tv_sec) * 1000000 + (endval.tv_usec - startval.tv_usec); +fprintf(stderr, "window= %d micro seconds \n" , microsec); +*/ + + + fclose(mp->keyfile); + + setpriority(PRIO_PROCESS, 0, 0); + return 0; +} + + +/* Convert 8-byte hex-ascii string to binary array + * Returns 0 on success, -1 on error + */ +atob8(out,in) +register char *out,*in; +{ + register int i; + register int val; + + if(in == NULL || out == NULL) + return -1; + + for(i=0;i<8;i++){ + if((in = skipspace(in)) == NULL) + return -1; + if((val = htoi(*in++)) == -1) + return -1; + *out = val << 4; + + if((in = skipspace(in)) == NULL) + return -1; + if((val = htoi(*in++)) == -1) + return -1; + *out++ |= val; + } + return 0; +} + +char * +skipspace(cp) +register char *cp; +{ + while(*cp == ' ' || *cp == '\t') + cp++; + + if(*cp == '\0') + return NULL; + else + return cp; +} + +/* Convert 8-byte binary array to hex-ascii string */ +int +btoa8(out,in) +register char *out,*in; +{ + register int i; + + if(in == NULL || out == NULL) + return -1; + + for(i=0;i<8;i++){ + sprintf(out,"%02x",*in++ & 0xff); + out += 2; + } + return 0; +} + + +/* Convert hex digit to binary integer */ +int +htoi(c) +register char c; +{ + if('0' <= c && c <= '9') + return c - '0'; + if('a' <= c && c <= 'f') + return 10 + c - 'a'; + if('A' <= c && c <= 'F') + return 10 + c - 'A'; + return -1; +} diff --git a/lib/libskey/skeysubr.c b/lib/libskey/skeysubr.c new file mode 100644 index 0000000..9762f1a --- /dev/null +++ b/lib/libskey/skeysubr.c @@ -0,0 +1,225 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifdef __MSDOS__ +#include <dos.h> +#endif +#ifdef unix /* Assume POSIX */ +#include <fcntl.h> +#include <termios.h> +#endif +#include "md4.h" +#include "skey.h" + +#if (defined(__MSDOS__) || defined(MPU8086) || defined(MPU8080) \ + || defined(vax) || defined (MIPSEL)) +#define LITTLE_ENDIAN /* Low order bytes are first in memory */ +#endif /* Almost all other machines are big-endian */ + +/* Crunch a key: + * concatenate the seed and the password, run through MD4 and + * collapse to 64 bits. This is defined as the user's starting key. + */ +int +keycrunch(result,seed,passwd) +char *result; /* 8-byte result */ +char *seed; /* Seed, any length */ +char *passwd; /* Password, any length */ +{ + char *buf; + MDstruct md; + unsigned int buflen; +#ifndef LITTLE_ENDIAN + int i; + register long tmp; +#endif + + buflen = strlen(seed) + strlen(passwd); + if((buf = malloc(buflen+1)) == NULL) + return -1; + strcpy(buf,seed); + strcat(buf,passwd); + + /* Crunch the key through MD4 */ + sevenbit(buf); + MDbegin(&md); + MDupdate(&md,(unsigned char *)buf,8*buflen); + + free(buf); + + /* Fold result from 128 to 64 bits */ + md.buffer[0] ^= md.buffer[2]; + md.buffer[1] ^= md.buffer[3]; + +#ifdef LITTLE_ENDIAN + /* Only works on byte-addressed little-endian machines!! */ + memcpy(result,(char *)md.buffer,8); +#else + /* Default (but slow) code that will convert to + * little-endian byte ordering on any machine + */ + for(i=0;i<2;i++){ + tmp = md.buffer[i]; + *result++ = tmp; + tmp >>= 8; + *result++ = tmp; + tmp >>= 8; + *result++ = tmp; + tmp >>= 8; + *result++ = tmp; + } +#endif + + return 0; +} + +/* The one-way function f(). Takes 8 bytes and returns 8 bytes in place */ +void +f(x) +char *x; +{ + MDstruct md; +#ifndef LITTLE_ENDIAN + register long tmp; +#endif + + MDbegin(&md); + MDupdate(&md,(unsigned char *)x,64); + + /* Fold 128 to 64 bits */ + md.buffer[0] ^= md.buffer[2]; + md.buffer[1] ^= md.buffer[3]; + +#ifdef LITTLE_ENDIAN + /* Only works on byte-addressed little-endian machines!! */ + memcpy(x,(char *)md.buffer,8); + +#else + /* Default (but slow) code that will convert to + * little-endian byte ordering on any machine + */ + tmp = md.buffer[0]; + *x++ = tmp; + tmp >>= 8; + *x++ = tmp; + tmp >>= 8; + *x++ = tmp; + tmp >>= 8; + *x++ = tmp; + + tmp = md.buffer[1]; + *x++ = tmp; + tmp >>= 8; + *x++ = tmp; + tmp >>= 8; + *x++ = tmp; + tmp >>= 8; + *x = tmp; +#endif +} + +/* Strip trailing cr/lf from a line of text */ +void +rip(buf) +char *buf; +{ + char *cp; + + if((cp = strchr(buf,'\r')) != NULL) + *cp = '\0'; + + if((cp = strchr(buf,'\n')) != NULL) + *cp = '\0'; +} +/************************/ +#ifdef __MSDOS__ +char * +readpass(buf,n) +char *buf; +int n; +{ + int i; + char *cp; + + for(cp=buf,i = 0; i < n ; i++) + if ((*cp++ = bdos(7,0,0)) == '\r') + break; + *cp = '\0'; + printf("\n"); + rip(buf); + return buf; +} +#else +char * +readpass(buf,n) +char *buf; +int n; +{ + struct termios saved_ttymode; + struct termios noecho_ttymode; + + /* Save normal line editing modes */ + tcgetattr(0, &saved_ttymode); + + /* Turn off echoing */ + tcgetattr(0, &noecho_ttymode); + noecho_ttymode.c_lflag &= ~ECHO; + tcsetattr(0, TCSANOW, &noecho_ttymode); + fgets(buf,n,stdin); + rip(buf); + + /* Restore previous tty modes */ + tcsetattr(0, TCSANOW, &saved_ttymode); + + /* + after the secret key is taken from the keyboard, the line feed is + written to standard error instead of standard output. That means that + anyone using the program from a terminal won't notice, but capturing + standard output will get the key words without a newline in front of + them. + */ + fprintf(stderr, "\n"); + fflush(stderr); + sevenbit(buf); + + return buf; +} + +#endif + +/* removebackspaced over charaters from the string*/ +backspace(buf) +char *buf; +{ + char bs = 0x8; + char *cp = buf; + char *out = buf; + + while(*cp){ + if( *cp == bs ) { + if(out == buf){ + cp++; + continue; + } + else { + cp++; + out--; + } + } + else { + *out++ = *cp++; + } + + } + *out = '\0'; + +} +sevenbit(s) +char *s; +{ + /* make sure there are only 7 bit code in the line*/ + while(*s){ + *s = 0x7f & ( *s); + s++; + } +} diff --git a/lib/libutil/pw_util.c b/lib/libutil/pw_util.c new file mode 100644 index 0000000..9873f74 --- /dev/null +++ b/lib/libutil/pw_util.c @@ -0,0 +1,204 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)pw_util.c 8.3 (Berkeley) 4/2/94"; +#endif /* not lint */ + +/* + * This file is used by all the "password" programs; vipw(8), chpass(1), + * and passwd(1). + */ + +#include <sys/param.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <sys/stat.h> +#include <sys/wait.h> + +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <paths.h> +#include <pwd.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "pw_util.h" + +extern char *tempname; + +void +pw_init() +{ + struct rlimit rlim; + + /* Unlimited resource limits. */ + rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; + (void)setrlimit(RLIMIT_CPU, &rlim); + (void)setrlimit(RLIMIT_FSIZE, &rlim); + (void)setrlimit(RLIMIT_STACK, &rlim); + (void)setrlimit(RLIMIT_DATA, &rlim); + (void)setrlimit(RLIMIT_RSS, &rlim); + + /* Don't drop core (not really necessary, but GP's). */ + rlim.rlim_cur = rlim.rlim_max = 0; + (void)setrlimit(RLIMIT_CORE, &rlim); + + /* Turn off signals. */ + (void)signal(SIGALRM, SIG_IGN); + (void)signal(SIGHUP, SIG_IGN); + (void)signal(SIGINT, SIG_IGN); + (void)signal(SIGPIPE, SIG_IGN); + (void)signal(SIGQUIT, SIG_IGN); + (void)signal(SIGTERM, SIG_IGN); + (void)signal(SIGTSTP, SIG_IGN); + (void)signal(SIGTTOU, SIG_IGN); + + /* Create with exact permissions. */ + (void)umask(0); +} + +static int lockfd; + +int +pw_lock() +{ + /* + * If the master password file doesn't exist, the system is hosed. + * Might as well try to build one. Set the close-on-exec bit so + * that users can't get at the encrypted passwords while editing. + * Open should allow flock'ing the file; see 4.4BSD. XXX + */ + lockfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0); + if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1) + err(1, "%s", _PATH_MASTERPASSWD); + if (flock(lockfd, LOCK_EX|LOCK_NB)) + errx(1, "the password db file is busy"); + return (lockfd); +} + +int +pw_tmp() +{ + static char path[MAXPATHLEN] = _PATH_MASTERPASSWD; + int fd; + char *p; + + if (p = strrchr(path, '/')) + ++p; + else + p = path; + strcpy(p, "pw.XXXXXX"); + if ((fd = mkstemp(path)) == -1) + err(1, "%s", path); + tempname = path; + return (fd); +} + +int +pw_mkdb() +{ + int pstat; + pid_t pid; + + warnx("rebuilding the database..."); + (void)fflush(stderr); + if (!(pid = vfork())) { + execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", tempname, NULL); + pw_error(_PATH_PWD_MKDB, 1, 1); + } + pid = waitpid(pid, &pstat, 0); + if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0) + return (0); + warnx("done"); + return (1); +} + +void +pw_edit(notsetuid) + int notsetuid; +{ + int pstat; + pid_t pid; + char *p, *editor; + + if (!(editor = getenv("EDITOR"))) + editor = _PATH_VI; + if (p = strrchr(editor, '/')) + ++p; + else + p = editor; + + if (!(pid = vfork())) { + if (notsetuid) { + (void)setgid(getgid()); + (void)setuid(getuid()); + } + execlp(editor, p, tempname, NULL); + _exit(1); + } + pid = waitpid(pid, (int *)&pstat, 0); + if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0) + pw_error(editor, 1, 1); +} + +void +pw_prompt() +{ + int c; + + (void)printf("re-edit the password file? [y]: "); + (void)fflush(stdout); + c = getchar(); + if (c != EOF && c != '\n') + while (getchar() != '\n'); + if (c == 'n') + pw_error(NULL, 0, 0); +} + +void +pw_error(name, err, eval) + char *name; + int err, eval; +{ + if (err) + warn(name); + + warnx("%s: unchanged", _PATH_MASTERPASSWD); + (void)unlink(tempname); + exit(eval); +} diff --git a/lib/libutil/stat_flags.c b/lib/libutil/stat_flags.c new file mode 100644 index 0000000..5bc4b85 --- /dev/null +++ b/lib/libutil/stat_flags.c @@ -0,0 +1,148 @@ +/*- + * Copyright (c) 1993 + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)stat_flags.c 8.1 (Berkeley) 5/31/93"; +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/stat.h> + +#include <stddef.h> +#include <string.h> + +#define SAPPEND(s) { \ + if (prefix != NULL) \ + (void)strcat(string, prefix); \ + (void)strcat(string, s); \ + prefix = ","; \ +} + +/* + * flags_to_string -- + * Convert stat flags to a comma-separated string. If no flags + * are set, return the default string. + */ +char * +flags_to_string(flags, def) + u_long flags; + char *def; +{ + static char string[128]; + char *prefix; + + string[0] = '\0'; + prefix = NULL; + if (flags & UF_APPEND) + SAPPEND("uappnd"); + if (flags & UF_IMMUTABLE) + SAPPEND("uchg"); + if (flags & UF_NODUMP) + SAPPEND("nodump"); + if (flags & SF_APPEND) + SAPPEND("sappnd"); + if (flags & SF_ARCHIVED) + SAPPEND("arch"); + if (flags & SF_IMMUTABLE) + SAPPEND("schg"); + return (prefix == NULL && def != NULL ? def : string); +} + +#define TEST(a, b, f) { \ + if (!memcmp(a, b, sizeof(b))) { \ + if (clear) { \ + if (clrp) \ + *clrp |= (f); \ + } else if (setp) \ + *setp |= (f); \ + break; \ + } \ +} + +/* + * string_to_flags -- + * Take string of arguments and return stat flags. Return 0 on + * success, 1 on failure. On failure, stringp is set to point + * to the offending token. + */ +int +string_to_flags(stringp, setp, clrp) + char **stringp; + u_long *setp, *clrp; +{ + int clear; + char *string, *p; + + clear = 0; + if (setp) + *setp = 0; + if (clrp) + *clrp = 0; + string = *stringp; + while ((p = strsep(&string, "\t ,")) != NULL) { + *stringp = p; + if (*p == '\0') + continue; + if (p[0] == 'n' && p[1] == 'o') { + clear = 1; + p += 2; + } + switch (p[0]) { + case 'a': + TEST(p, "arch", SF_ARCHIVED); + TEST(p, "archived", SF_ARCHIVED); + return (1); + case 'd': + clear = !clear; + TEST(p, "dump", UF_NODUMP); + return (1); + case 's': + TEST(p, "sappnd", SF_APPEND); + TEST(p, "sappend", SF_APPEND); + TEST(p, "schg", SF_IMMUTABLE); + TEST(p, "schange", SF_IMMUTABLE); + TEST(p, "simmutable", SF_IMMUTABLE); + return (1); + case 'u': + TEST(p, "uappnd", UF_APPEND); + TEST(p, "uappend", UF_APPEND); + TEST(p, "uchg", UF_IMMUTABLE); + TEST(p, "uchange", UF_IMMUTABLE); + TEST(p, "uimmutable", UF_IMMUTABLE); + /* FALLTHROUGH */ + default: + return (1); + } + } + return (0); +} |