diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
commit | d6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch) | |
tree | ece253b876159b39c620e62b6c9b1174642e070e /lib/libpthread |
initial import of NetBSD tree
Diffstat (limited to 'lib/libpthread')
112 files changed, 12925 insertions, 0 deletions
diff --git a/lib/libpthread/COPYRIGHT b/lib/libpthread/COPYRIGHT new file mode 100644 index 00000000000..1fb4e43cf26 --- /dev/null +++ b/lib/libpthread/COPYRIGHT @@ -0,0 +1,31 @@ +Copyright (c) 1993 by Chris Provenzano and contributors, proven@mit.edu +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 Chris Provenzano, + the University of California, Berkeley, and contributors. +4. Neither the name of Chris Provenzano, the University, nor the names of + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO 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 CHRIS PROVENZANO, 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. + diff --git a/lib/libpthread/Makefile b/lib/libpthread/Makefile new file mode 100644 index 00000000000..85978519fe8 --- /dev/null +++ b/lib/libpthread/Makefile @@ -0,0 +1,22 @@ +# from: @(#)Makefile 5.2 (Berkeley) 3/5/91 + +LIB=pthread +NOPIC= no +CPPFLAGS+= -DPTHREAD_KERNEL -I. -I${.CURDIR}/include -I${.CURDIR}/arch/${MACHINE} +CFLAGS+= ${CPPFLAGS} + +.include "${.CURDIR}/arch/${MACHINE}/Makefile.inc" +.include "${.CURDIR}/pthreads/Makefile.inc" +.include "${.CURDIR}/stdio/Makefile.inc" + +all beforedepend: pthread + +CLEANFILES+=pthread + +pthread: + if [ ! -e pthread ]; then \ + ln -s ${.CURDIR}/include pthread; \ + fi + +.include <bsd.lib.mk> + diff --git a/lib/libpthread/README b/lib/libpthread/README new file mode 100644 index 00000000000..f546325d948 --- /dev/null +++ b/lib/libpthread/README @@ -0,0 +1,85 @@ +This pthread package is/will be based on the POSIX1003.4a Draft 7 pthread +standard, and Frank Mullers paper on signal handelling presented +at the Winter 93 USENIX conference. + +It is currently being designed and written by me, Chris Provenzano. +All bug, comments, and questions can be sent me at either +proven@athena.mit.edu or proven@sun-lamp.cs.berkeley.edu +PLEASE, don't send questions, bugs or patches to any of the *BSD* mailing lists. + +Thanks goes to John Carr jfc@mit.edu for porting this to the IBM/RT, +and for his bug reports and fixes, Greg Hudson and Mark Eichin for the +testing they've done, and all the others. + +PORTING +One of the goals of this user space implementation of pthreads is that it +be portable. I have minimized the ammount of assembler code necessary, +but some is. + +If you want to port it to another platform here are a few basic hints. + +There are currently three files you'll have to creat for your +architecture, machdep.h, machdep.c and syscall.S. +The first two are necessary to get the context switch section of +the pthread package running, the third is for all the syscalls. + +To do an initial port, create an appropriate machdep.h, and machdep.c +and define PTHREAD_INITIAL_PORT in the Makefile + +Comment out references to the stdio package. + +INCLUDE FILES AND PORTING +To continue to make this package portable, some basic rules on includes +files must be followed. + +pthread.h should be included first (if it is to be included). +machdep.h should define size_t if the system doesn't define it already + +posix.h should be included last. This file is used to correct non +POSIX features, after everything else has been defined. + +INTERNAL LOCKING +To prevent deadlocks the following rules were used for locks. + +1. Local locks for mutex queues and other like things are only locked + by running threads, at NO time will a local lock be held by + a thread in a non running state. +2. Only threads that are in a run state can attempt to lock another thread, + this way, we can assume that the lock will be released shortly, and don't + have to unlock the local lock. +3. The only time a thread will have a pthread->lock and is not in a run + state is when it is in the reschedule routine. +4. The reschedule routine assumes all local locks have been released, + there is a lock on the currently running thread (pthread_run), + and that this thread is being rescheduled to a non running state. + It is safe to unlock the currently running threads lock after it + has been rescheduled. +5. The reschedule routine locks the kernel, sets the state of the currently + running thread, unlocks the currently running thread, calls the + context switch routines. +6 the kernel lock is used only ... + + +7. The order of locking is ... + +1 local locks +2 pthread->lock /* Assumes it will get it soon */ +3 pthread_run->lock /* Assumes it will get it soon, but must release 2 */ +4 kernel lock /* Currently assumes it will ALWAYS get it. */ + +8. The kernel lock will be changed to a spin lock for systems that +already support kernel threads, this way we can mutiplex threads onto +kernel threads. +9. There are points where the kernel is locked and it needs to get +either a local lock or a pthread lock, if at these points the code +fails to get the lock the kernel gives up and sets a flag which will +be checked at a later point. +10. Interrupts are dissabled while the kernel is locked, the interrupt +mask must be checked afterwards or cleared in some way, after interrputs +have been reenabled, this allows back to back interrupts, but should always +avoid missing one. + +Copyright (c) 1993 Chris Provenzano. All rights reserved. + +This product includes software developed by the Univeristy of California, +Berkeley and its contributors. diff --git a/lib/libpthread/arch/i386/Makefile.inc b/lib/libpthread/arch/i386/Makefile.inc new file mode 100644 index 00000000000..85468b9aa69 --- /dev/null +++ b/lib/libpthread/arch/i386/Makefile.inc @@ -0,0 +1,4 @@ +# Machine dependent sources +.PATH: ${.CURDIR}/arch/${MACHINE} + +SRCS+= machdep.c syscall.S diff --git a/lib/libpthread/arch/i386/machdep.c b/lib/libpthread/arch/i386/machdep.c new file mode 100644 index 00000000000..2437cead1b1 --- /dev/null +++ b/lib/libpthread/arch/i386/machdep.c @@ -0,0 +1,136 @@ +/* ==== machdep.c ============================================================ + * Copyright (c) 1993, 1994 Chris Provenzano, proven@athena.mit.edu + * + * Copyright (c) 1993 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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. + * + * Description : Machine dependent functions for NetBSD on i386 + * + * 1.00 93/08/04 proven + * -Started coding this file. + */ + +#ifndef lint +static const char rcsid[] = "$Id: machdep.c,v 1.1 1995/10/18 08:43:03 deraadt Exp $"; +#endif + +#include "pthread.h" + +/* ========================================================================== + * machdep_save_state() + */ +int machdep_save_state(void) +{ + return(_setjmp(pthread_run->machdep_data.machdep_state)); +} + +/* ========================================================================== + * machdep_restore_state() + */ +void machdep_restore_state(void) +{ + _longjmp(pthread_run->machdep_data.machdep_state, 1); +} + +/* ========================================================================== + * machdep_set_thread_timer() + */ +void machdep_set_thread_timer(struct machdep_pthread *machdep_pthread) +{ + if (setitimer(ITIMER_VIRTUAL, &(machdep_pthread->machdep_timer), NULL)) { + PANIC(); + } +} + +/* ========================================================================== + * machdep_unset_thread_timer() + */ +void machdep_unset_thread_timer(struct machdep_pthread *machdep_pthread) +{ + struct itimerval zeroval = { { 0, 0 }, { 0, 0} }; + + if (setitimer(ITIMER_VIRTUAL, &zeroval, NULL)) { + PANIC(); + } +} + +/* ========================================================================== + * machdep_pthread_cleanup() + */ +void *machdep_pthread_cleanup(struct machdep_pthread *machdep_pthread) +{ + return(machdep_pthread->machdep_stack); +} + +/* ========================================================================== + * machdep_pthread_start() + */ +void machdep_pthread_start(void) +{ + context_switch_done(); + sig_check_and_resume(); + + /* Run current threads start routine with argument */ + pthread_exit(pthread_run->machdep_data.start_routine + (pthread_run->machdep_data.start_argument)); + + /* should never reach here */ + PANIC(); +} + +/* ========================================================================== + * machdep_pthread_create() + */ +void machdep_pthread_create(struct machdep_pthread *machdep_pthread, + void *(* start_routine)(), void *start_argument, long stack_size, + void *stack_start, long nsec) +{ + machdep_pthread->machdep_stack = stack_start; + + machdep_pthread->start_routine = start_routine; + machdep_pthread->start_argument = start_argument; + + machdep_pthread->machdep_timer.it_value.tv_sec = 0; + machdep_pthread->machdep_timer.it_interval.tv_sec = 0; + machdep_pthread->machdep_timer.it_interval.tv_usec = 0; + machdep_pthread->machdep_timer.it_value.tv_usec = nsec / 1000; + + _setjmp(machdep_pthread->machdep_state); + /* + * Set up new stact frame so that it looks like it + * returned from a longjmp() to the beginning of + * machdep_pthread_start(). + */ + machdep_pthread->machdep_state[0] = (int)machdep_pthread_start; + + /* Stack starts high and builds down. */ + machdep_pthread->machdep_state[2] = + (int)machdep_pthread->machdep_stack + stack_size; +} diff --git a/lib/libpthread/arch/i386/machdep.h b/lib/libpthread/arch/i386/machdep.h new file mode 100644 index 00000000000..10521b02235 --- /dev/null +++ b/lib/libpthread/arch/i386/machdep.h @@ -0,0 +1,58 @@ +/* ==== machdep.h ============================================================ + * Copyright (c) 1993 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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. + * + */ + + +/* + * The first machine dependent functions are the SEMAPHORES + * needing the test and set instruction. + */ +#define SEMAPHORE_CLEAR 0 +#define SEMAPHORE_SET 1 + +#define SEMAPHORE_TEST_AND_SET(lock) \ +({ \ +volatile long temp = SEMAPHORE_SET; \ + \ +__asm__("xchgl %0,(%2)" \ + :"=r" (temp) \ + :"0" (temp),"r" (lock)); \ +temp; \ +}) + +#define SEMAPHORE_RESET(lock) *lock = SEMAPHORE_CLEAR + +/* + * Minimum stack size + */ +#define PTHREAD_STACK_MIN 1024 + diff --git a/lib/libpthread/arch/i386/syscall.S b/lib/libpthread/arch/i386/syscall.S new file mode 100644 index 00000000000..1b91abed0c8 --- /dev/null +++ b/lib/libpthread/arch/i386/syscall.S @@ -0,0 +1,174 @@ +/* ==== syscall.S ============================================================ + * Copyright (c) 1990 The Regents of the University of California. + * Copyright (c) 1993 Chris Provenzano, proven@mit.edu + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * 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. + * + * Description : Machine dependent syscalls for i386/i486/i586 + * + * 1.00 93/08/26 proven + * -Started coding this file. + * + * 1.01 93/11/13 proven + * -The functions readv() and writev() added. + */ + +#ifndef lint + .text + .asciz "$Id: syscall.S,v 1.1 1995/10/18 08:43:03 deraadt Exp $"; +#endif + +#if defined(SYSLIBC_SCCS) && !defined(lint) + .asciz "@(#)syscall.s 5.1 (Berkeley) 4/23/90" +#endif /* SYSLIBC_SCCS and not lint */ + +#include <machine/asm.h> +#include <sys/syscall.h> + +#define SYSCALL(x) \ + .globl _machdep_sys_/**/x; \ + \ +_machdep_sys_/**/x:; \ + \ + movl $(SYS_/**/x), %eax; \ + .byte 0x9a; .long 0; .word 7; \ + jb 1b; \ + ret; + +/* + * Initial asm stuff for all functions. + */ + .text + .align 2 + + +/* ========================================================================== + * error code for all syscalls. The error value is returned as the negative + * of the errno value. + */ + +1: + neg %eax + ret + +/* ========================================================================== + * machdep_sys_write() + */ +SYSCALL(write) + +/* ========================================================================== + * machdep_sys_read() + */ +SYSCALL(read) + +/* ========================================================================== + * machdep_sys_open() + */ +SYSCALL(open) + +/* ========================================================================== + * machdep_sys_close() + */ +SYSCALL(close) + +/* ========================================================================== + * machdep_sys_fcntl() + */ +SYSCALL(fcntl) + +/* ========================================================================== + * machdep_sys_lseek() + */ +SYSCALL(lseek) + +/* ========================================================================== + * Nonstandard calls used to make the system work + * + * ========================================================================== + * machdep_sys_select() + */ +SYSCALL(select) + +/* ========================================================================== + * Berkeley socket stuff + * + * ========================================================================== + * machdep_sys_socket() + */ +SYSCALL(socket) + +/* ========================================================================== + * machdep_sys_bind() + */ +SYSCALL(bind) + +/* ========================================================================== + * machdep_sys_connect() + */ +SYSCALL(connect) + +/* ========================================================================== + * machdep_sys_accept() + */ +SYSCALL(accept) + +/* ========================================================================== + * machdep_sys_listen() + */ +SYSCALL(listen) + +/* ========================================================================== + * machdep_sys_getsockopt() + */ +SYSCALL(getsockopt) + +/* ========================================================================== + * machdep_sys_readv() + */ +SYSCALL(readv) + +/* ========================================================================== + * machdep_sys_writev() + */ +SYSCALL(writev) + +/* ========================================================================== + * machdep_sys_getpeername() + */ +SYSCALL(getpeername) + +/* ========================================================================== + * machdep_sys_getsockname() + */ +SYSCALL(getsockname) + diff --git a/lib/libpthread/include/cond.h b/lib/libpthread/include/cond.h new file mode 100644 index 00000000000..ed76126cc98 --- /dev/null +++ b/lib/libpthread/include/cond.h @@ -0,0 +1,91 @@ +/* ==== cond.h ============================================================ + * Copyright (c) 1993 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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: cond.h,v 1.1 1995/10/18 08:43:04 deraadt Exp $ $provenid: cond.h,v 1.17 1994/02/07 03:31:53 proven Exp $ + * + * Description : mutex header. + * + * 1.00 93/10/30 proven + * -Started coding this file. + */ + +/* + * New cond structures + */ +enum pthread_cond_type { + COND_TYPE_FAST, + COND_TYPE_STATIC_FAST, + COND_TYPE_METERED, + COND_TYPE_DEBUG, /* Debug conds will have lots of options */ + COND_TYPE_MAX +}; + +typedef struct pthread_cond { + enum pthread_cond_type c_type; + struct pthread_queue c_queue; + semaphore c_lock; + void * c_data; + long c_flags; +} pthread_cond_t; + +typedef struct pthread_cond_attr { + enum pthread_cond_type c_type; + long c_flags; +} pthread_condattr_t; + +/* + * Flags for conds. + */ +#define COND_FLAGS_PRIVATE 0x01 +#define COND_FLAGS_INITED 0x02 +#define COND_FLAGS_BUSY 0x04 + +/* + * Static cond initialization values. + */ +#define PTHREAD_COND_INITIALIZER \ +{ COND_TYPE_STATIC_FAST, PTHREAD_QUEUE_INITIALIZER, \ + NULL, SEMAPHORE_CLEAR, COND_FLAGS_INITED } + +/* + * New functions + */ + +__BEGIN_DECLS + +int pthread_cond_init __P((pthread_cond_t *, pthread_condattr_t *)); +int pthread_cond_wait __P((pthread_cond_t *, pthread_mutex_t *)); +int pthread_cond_signal __P((pthread_cond_t *)); +int pthread_cond_broadcast __P((pthread_cond_t *)); +int pthread_cond_destroy __P((pthread_cond_t *)); + +__END_DECLS + diff --git a/lib/libpthread/include/engine.h b/lib/libpthread/include/engine.h new file mode 100644 index 00000000000..3539686755c --- /dev/null +++ b/lib/libpthread/include/engine.h @@ -0,0 +1,86 @@ +/* ==== engine.h ============================================================ + * Copyright (c) 1993 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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 <unistd.h> +#include <setjmp.h> +#include <sys/time.h> + +#if defined(PTHREAD_KERNEL) +#include "machdep.h" +#endif + +/* + * New types + */ +typedef long semaphore; + +#define SIGMAX 31 + +/* + * New Strutures + */ +struct machdep_pthread { + void *(*start_routine)(void *); + void *start_argument; + void *machdep_stack; + struct itimerval machdep_timer; + jmp_buf machdep_state; +}; + +/* + * Static machdep_pthread initialization values. + * For initial thread only. + */ +#define MACHDEP_PTHREAD_INIT \ +{ NULL, NULL, NULL, { { 0, 0 }, { 0, 0 } }, 0 } + +/* + * Some fd flag defines that are necessary to distinguish between posix + * behavior and bsd4.3 behavior. + */ +#define __FD_NONBLOCK O_NONBLOCK + +/* + * New functions + */ + +__BEGIN_DECLS + +#if defined(PTHREAD_KERNEL) + +int semaphore_text_and_set __P((semaphore *)); +int machdep_save_state __P((void)); + +#endif + +__END_DECLS diff --git a/lib/libpthread/include/fd.h b/lib/libpthread/include/fd.h new file mode 100644 index 00000000000..654a497aa70 --- /dev/null +++ b/lib/libpthread/include/fd.h @@ -0,0 +1,106 @@ +/* ==== fd.h ============================================================ + * Copyright (c) 1993 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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: fd.h,v 1.1 1995/10/18 08:43:04 deraadt Exp $ $provenid: fd.h,v 1.17 1994/02/07 03:31:54 proven Exp $ + * + * Description : Basic fd header. + * + * 1.00 93/08/14 proven + * -Started coding this file. + * + * 1.01 93/11/13 proven + * -The functions readv() and writev() added + */ + +/* + * New pthread types. + */ +enum fd_type { + FD_NT, /* Not tested */ + FD_NIU, /* Known to be not in use */ + FD_HALF_DUPLEX, /* Files, and seeking devices */ + FD_FULL_DUPLEX /* pipes, sockets, drivers, ... */ +}; + + +#define FD_READ 0x1 +#define FD_WRITE 0x2 +#define FD_RDWR (FD_READ | FD_WRITE) + +struct fd_ops { + int (*write)(); + int (*read)(); + int (*close)(); + int (*fcntl)(); + int (*writev)(); + int (*readv)(); + int (*seek)(); +}; + +union fd_data { + void *ptr; + int i; +}; + +struct fd_table_entry { + struct pthread_queue r_queue; + struct pthread_queue w_queue; + struct pthread *r_owner; + struct pthread *w_owner; + semaphore lock; + struct fd_table_entry *next; + struct fd_ops *ops; + enum fd_type type; + int lockcount; /* Count for FILE locks */ + int count; + + /* data that needs to be passed to the type dependent fd */ + int flags; + union fd_data fd; +}; + +/* + * Important data structure + */ +extern struct fd_table_entry *fd_table[]; +extern int dtablesize; + +/* + * New functions + */ + +__BEGIN_DECLS + +#if defined(PTHREAD_KERNEL) + +#endif + +__END_DECLS diff --git a/lib/libpthread/include/fd_pipe.h b/lib/libpthread/include/fd_pipe.h new file mode 100644 index 00000000000..6ec808ff687 --- /dev/null +++ b/lib/libpthread/include/fd_pipe.h @@ -0,0 +1,54 @@ +/* ==== fd_pipe.h ============================================================ + * Copyright (c) 1993 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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: fd_pipe.h,v 1.1 1995/10/18 08:43:04 deraadt Exp $ $provenid: fd_pipe.h,v 1.17 1994/02/07 03:31:56 proven Exp $ + * + * Description : The new fast ITC pipe header. + * + * 1.00 93/08/14 proven + * -Started coding this file. + */ + +struct __pipe { + semaphore lock; + char * buf; + int size; + int flags; + int count; + int offset; + struct pthread * wait; + char * wait_buf; + size_t wait_size; +}; + +#define RD_CLOSED 0x01 +#define WR_CLOSED 0x02 + diff --git a/lib/libpthread/include/kernel.h b/lib/libpthread/include/kernel.h new file mode 100644 index 00000000000..29e066f7ae7 --- /dev/null +++ b/lib/libpthread/include/kernel.h @@ -0,0 +1,50 @@ +/* ==== kernel.h ============================================================ + * Copyright (c) 1993 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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: kernel.h,v 1.1 1995/10/18 08:43:04 deraadt Exp $ $provenid: kernel.h,v 1.17 1994/02/07 03:31:57 proven Exp $ + * + * Description : mutex header. + * + * 1.00 93/07/22 proven + * -Started coding this file. + */ + +/* + * Defines only for the pthread user kernel. + */ +#if defined(PTHREAD_KERNEL) + +#define PANIC() abort() + +/* Time each rr thread gets */ +#define PTHREAD_RR_TIMEOUT 100000000 + +#endif diff --git a/lib/libpthread/include/mutex.h b/lib/libpthread/include/mutex.h new file mode 100644 index 00000000000..d8e5d8939d2 --- /dev/null +++ b/lib/libpthread/include/mutex.h @@ -0,0 +1,93 @@ +/* ==== mutex.h ============================================================ + * Copyright (c) 1993 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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: mutex.h,v 1.1 1995/10/18 08:43:04 deraadt Exp $ $provenid: mutex.h,v 1.17 1994/02/07 03:31:59 proven Exp $ + * + * Description : mutex header. + * + * 1.00 93/07/20 proven + * -Started coding this file. + */ + +/* + * New mutex structures + */ +enum pthread_mutex_type { + MUTEX_TYPE_FAST, + MUTEX_TYPE_STATIC_FAST, + MUTEX_TYPE_RECURSIVE, + MUTEX_TYPE_METERED, + MUTEX_TYPE_DEBUG, /* Debug mutexes will have lots of options */ + MUTEX_TYPE_MAX +}; + +typedef struct pthread_mutex { + enum pthread_mutex_type m_type; + struct pthread_queue m_queue; + struct pthread *m_owner; + semaphore m_lock; + void *m_data; + long m_flags; +} pthread_mutex_t; + +typedef struct pthread_mutex_attr { + enum pthread_mutex_type m_type; + long m_flags; +} pthread_mutexattr_t; + +/* + * Flags for mutexes. + */ +#define MUTEX_FLAGS_PRIVATE 0x01 +#define MUTEX_FLAGS_INITED 0x02 +#define MUTEX_FLAGS_BUSY 0x04 + +/* + * Static mutex initialization values. + */ +#define PTHREAD_MUTEX_INITIALIZER \ +{ MUTEX_TYPE_STATIC_FAST, PTHREAD_QUEUE_INITIALIZER, \ + NULL, SEMAPHORE_CLEAR, NULL, MUTEX_FLAGS_INITED } + +/* + * New functions + */ + +__BEGIN_DECLS + +int pthread_mutex_init __P((pthread_mutex_t *, pthread_mutexattr_t *)); +int pthread_mutex_lock __P((pthread_mutex_t *)); +int pthread_mutex_unlock __P((pthread_mutex_t *)); +int pthread_mutex_trylock __P((pthread_mutex_t *)); +int pthread_mutex_destroy __P((pthread_mutex_t *)); + +__END_DECLS + diff --git a/lib/libpthread/include/posix.h b/lib/libpthread/include/posix.h new file mode 100644 index 00000000000..a3a8ef049c6 --- /dev/null +++ b/lib/libpthread/include/posix.h @@ -0,0 +1,21 @@ +/* ==== posix.h ============================================================ + * Copyright (c) 1993 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Convert an Ultrix-4.2 system to a more or less POSIX system. + * + * $Id: posix.h,v 1.1 1995/10/18 08:43:04 deraadt Exp $ $provenid: posix-netbsd-0.9.h,v 1.17 1994/02/07 03:32:24 proven Exp $ + * + * 1.00 93/07/20 proven + * -Started coding this file. + */ + +#ifndef _PTHREAD_POSIX_H_ +#define _PTHREAD_POSIX_H_ + +#include <sys/cdefs.h> + +/* Make sure we have size_t defined */ +#include <stdlib.h> +#include <stdarg.h> + +#endif diff --git a/lib/libpthread/include/pthread_attr.h b/lib/libpthread/include/pthread_attr.h new file mode 100644 index 00000000000..3cfe54c29c1 --- /dev/null +++ b/lib/libpthread/include/pthread_attr.h @@ -0,0 +1,73 @@ +/* ==== pthread_attr.h ======================================================== + * Copyright (c) 1993 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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: pthread_attr.h,v 1.1 1995/10/18 08:43:04 deraadt Exp $ $provenid: pthread_attr.h,v 1.17 1994/02/07 03:32:02 proven Exp $ + * + * Description : Basic pthread attributes header. + * + * 1.00 93/11/03 proven + * -Started coding this file. + */ + +#define _POSIX_THREAD_ATTR_STACKSIZE + +#define PTHREAD_STACK_DEFAULT 65536 + +/* + * New pthread attribute types. + */ +enum pthread_sched_attr { + SCHED_RR, + SCHED_IO, + SCHED_FIFO, + SCHED_OTHER, +}; + +typedef struct pthread_attr { + enum pthread_sched_attr sched_attr; + void * stackaddr_attr; + size_t stacksize_attr; +} pthread_attr_t; + +/* + * New functions + */ + +__BEGIN_DECLS + +int pthread_attr_init __P((pthread_attr_t *)); +int pthread_attr_destroy __P((pthread_attr_t *)); +int pthread_attr_setstacksize __P((pthread_attr_t *, size_t)); +int pthread_attr_getstacksize __P((pthread_attr_t *, size_t *)); +int pthread_attr_setstackaddr __P((pthread_attr_t *, void *)); +int pthread_attr_getstackaddr __P((pthread_attr_t *, void **)); + +__END_DECLS diff --git a/lib/libpthread/include/pthread_once.h b/lib/libpthread/include/pthread_once.h new file mode 100644 index 00000000000..971bc493d1b --- /dev/null +++ b/lib/libpthread/include/pthread_once.h @@ -0,0 +1,53 @@ +/* ==== pthread_once.h ======================================================== + * Copyright (c) 1993 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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: pthread_once.h,v 1.1 1995/10/18 08:43:04 deraadt Exp $ $provenid: pthread_once.h,v 1.17 1994/02/07 03:32:04 proven Exp $ + * + * Description : mutex header. + * + * 1.00 93/12/12 proven + * -Started coding this file. + */ + +/* New pthread_once structures */ +typedef int pthread_once_t; + +/* Static pthread_once_t initialization value. */ +#define PTHREAD_ONCE_INIT 0 + +/* New functions */ + +__BEGIN_DECLS + +int pthread_once __P((pthread_once_t *, void (*init_routine)(void))); + +__END_DECLS + diff --git a/lib/libpthread/include/queue.h b/lib/libpthread/include/queue.h new file mode 100644 index 00000000000..d4d34b53861 --- /dev/null +++ b/lib/libpthread/include/queue.h @@ -0,0 +1,67 @@ +/* ==== queue.h ============================================================ + * Copyright (c) 1993 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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: queue.h,v 1.1 1995/10/18 08:43:04 deraadt Exp $ $provenid: queue.h,v 1.17 1994/02/07 03:39:52 proven Exp $ + * + * Description : mutex header. + * + * 1.00 93/07/20 proven + * -Started coding this file. + */ + +/* + * New queue structures + */ +struct pthread_queue { + struct pthread *q_next; + struct pthread *q_last; + void *q_data; +}; + +/* + * Static queue initialization values. + */ +#define PTHREAD_QUEUE_INITIALIZER { NULL, NULL, NULL } + +/* + * New functions + * Should make pthread_queue_get a macro + */ + +__BEGIN_DECLS + +void pthread_queue_init __P((struct pthread_queue *)); +void pthread_queue_enq __P((struct pthread_queue *, struct pthread *)); +void pthread_queue_remove __P((struct pthread_queue *, struct pthread *)); +struct pthread *pthread_queue_get __P((struct pthread_queue *)); +struct pthread *pthread_queue_deq __P((struct pthread_queue *)); + +__END_DECLS diff --git a/lib/libpthread/include/stdio.h b/lib/libpthread/include/stdio.h new file mode 100644 index 00000000000..5819547d7b2 --- /dev/null +++ b/lib/libpthread/include/stdio.h @@ -0,0 +1,354 @@ +/* ==== stdio.h ============================================================ + * Copyright (c) 1990 The Regents of the University of California. + * Copyright (c) 1993 by Chris Provenzano, proven@mit.edu + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)stdio.h 5.17 (Berkeley) 6/3/91 + * $Id: stdio.h,v 1.1 1995/10/18 08:43:04 deraadt Exp $ $provenid: stdio.h,v 1.18 1994/02/07 03:32:06 proven Exp $ + */ + +#ifndef _STDIO_H_ +#define _STDIO_H_ + +#include <sys/cdefs.h> +#include <pthread/posix.h> + +#ifndef NULL +#define NULL 0 +#endif + +typedef long fpos_t; /* Must match off_t <sys/types.h> */ + +#define _FSTDIO /* Define for new stdio with functions. */ + +/* + * NB: to fit things in six character monocase externals, the stdio + * code uses the prefix `__s' for stdio objects, typically followed + * by a three-character attempt at a mnemonic. + */ + +/* stdio buffers */ +struct __sbuf { + unsigned char *_base; + int _size; +}; + +/* + * stdio state variables. + * + * The following always hold: + * + * if (_flags&(__SLBF|__SWR)) == (__SLBF|__SWR), + * _lbfsize is -_bf._size, else _lbfsize is 0 + * if _flags&__SRD, _w is 0 + * if _flags&__SWR, _r is 0 + * + * This ensures that the getc and putc macros (or inline functions) never + * try to write or read from a file that is in `read' or `write' mode. + * (Moreover, they can, and do, automatically switch from read mode to + * write mode, and back, on "r+" and "w+" files.) + * + * _lbfsize is used only to make the inline line-buffered output stream + * code as compact as possible. + * + * _ub, _up, and _ur are used when ungetc() pushes back more characters + * than fit in the current _bf, or when ungetc() pushes back a character + * that does not match the previous one in _bf. When this happens, + * _ub._base becomes non-nil (i.e., a stream has ungetc() data iff + * _ub._base!=NULL) and _up and _ur save the current values of _p and _r. + */ +typedef struct __sFILE { + unsigned char *_p; /* current position in (some) buffer */ + int _r; /* read space left for getc() */ + int _w; /* write space left for putc() */ + short _flags; /* flags, below; this FILE is free if 0 */ + short _file; /* fileno, if Unix descriptor, else -1 */ + struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */ + int _lbfsize; /* 0 or -_bf._size, for inline putc */ + + /* separate buffer for long sequences of ungetc() */ + struct __sbuf _ub; /* ungetc buffer */ + unsigned char *_up; /* saved _p when _p is doing ungetc data */ + int _ur; /* saved _r when _r is counting ungetc data */ + + /* tricks to meet minimum requirements even when malloc() fails */ + unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */ + unsigned char _nbuf[1]; /* guarantee a getc() buffer */ + + /* separate buffer for fgetline() when line crosses buffer boundary */ + struct __sbuf _lb; /* buffer for fgetline() */ + + /* Unix stdio files get aligned to block boundaries on fseek() */ + int _blksize; /* stat.st_blksize (may be != _bf._size) */ + int _offset; /* current lseek offset */ +} FILE; + +__BEGIN_DECLS +extern FILE __sF[]; +__END_DECLS + +#define __SLBF 0x0001 /* line buffered */ +#define __SNBF 0x0002 /* unbuffered */ +#define __SRD 0x0004 /* OK to read */ +#define __SWR 0x0008 /* OK to write */ + /* RD and WR are never simultaneously asserted */ +#define __SRW 0x0010 /* open for reading & writing */ +#define __SEOF 0x0020 /* found EOF */ +#define __SERR 0x0040 /* found error */ +#define __SMBF 0x0080 /* _buf is from malloc */ +#define __SAPP 0x0100 /* fdopen()ed in append mode */ +#define __SSTR 0x0200 /* this is an sprintf/snprintf string */ +#define __SOPT 0x0400 /* do fseek() optimisation */ +#define __SNPT 0x0800 /* do not do fseek() optimisation */ +#define __SOFF 0x1000 /* set iff _offset is in fact correct */ +#define __SMOD 0x2000 /* true => fgetline modified _p text */ + +/* + * The following three definitions are for ANSI C, which took them + * from System V, which brilliantly took internal interface macros and + * made them official arguments to setvbuf(), without renaming them. + * Hence, these ugly _IOxxx names are *supposed* to appear in user code. + * + * Although numbered as their counterparts above, the implementation + * does not rely on this. + */ +#define _IOFBF 0 /* setvbuf should set fully buffered */ +#define _IOLBF 1 /* setvbuf should set line buffered */ +#define _IONBF 2 /* setvbuf should set unbuffered */ + +#define BUFSIZ 1024 /* size of buffer used by setbuf */ +#define EOF (-1) + +/* + * FOPEN_MAX is a minimum maximum, and should be the number of descriptors + * that the kernel can provide without allocation of a resource that can + * fail without the process sleeping. Do not use this for anything. + */ +#define FOPEN_MAX 20 /* must be <= OPEN_MAX <sys/syslimits.h> */ +#define FILENAME_MAX 1024 /* must be <= PATH_MAX <sys/syslimits.h> */ + +/* System V/ANSI C; this is the wrong way to do this, do *not* use these. */ +#ifndef _ANSI_SOURCE +#define P_tmpdir "/var/tmp/" +#endif +#define L_tmpnam 1024 /* XXX must be == PATH_MAX */ +#ifndef TMP_MAX +#define TMP_MAX 308915776 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 /* set file offset to offset */ +#endif +#ifndef SEEK_CUR +#define SEEK_CUR 1 /* set file offset to current plus offset */ +#endif +#ifndef SEEK_END +#define SEEK_END 2 /* set file offset to EOF plus offset */ +#endif + +#define stdin (&__sF[0]) +#define stdout (&__sF[1]) +#define stderr (&__sF[2]) + +/* + * Functions defined in ANSI C standard. + */ +__BEGIN_DECLS +void clearerr __P((FILE *)); +int fclose __P((FILE *)); +int feof __P((FILE *)); +int ferror __P((FILE *)); +int fflush __P((FILE *)); +int fgetc __P((FILE *)); +int fgetpos __P((FILE *, fpos_t *)); +char * fgets __P((char *, size_t, FILE *)); +FILE * fopen __P((const char *, const char *)); +int fprintf __P((FILE *, const char *, ...)); +int fputc __P((int, FILE *)); +int fputs __P((const char *, FILE *)); +size_t fread __P((void *, size_t, size_t, FILE *)); +FILE * freopen __P((const char *, const char *, FILE *)); +int fscanf __P((FILE *, const char *, ...)); +int fseek __P((FILE *, long, int)); +int fsetpos __P((FILE *, const fpos_t *)); +long ftell __P((const FILE *)); +size_t fwrite __P((const void *, size_t, size_t, FILE *)); +int getc __P((FILE *)); +int getchar __P((void)); +char * gets __P((char *)); + +#if !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE) +extern int sys_nerr; /* perror(3) external variables */ +extern char *sys_errlist[]; +#endif + +void perror __P((const char *)); +int printf __P((const char *, ...)); +int putc __P((int, FILE *)); +int putchar __P((int)); +int puts __P((const char *)); +int remove __P((const char *)); +int rename __P((const char *, const char *)); +void rewind __P((FILE *)); +int scanf __P((const char *, ...)); +void setbuf __P((FILE *, char *)); +int setvbuf __P((FILE *, char *, int, size_t)); +int sprintf __P((char *, const char *, ...)); +int sscanf __P((const char *, const char *, ...)); +FILE *tmpfile __P((void)); +char *tmpnam __P((char *)); +int ungetc __P((int, FILE *)); +int vfprintf __P((FILE *, const char *, va_list)); +int vprintf __P((const char *, va_list)); +int vsprintf __P((char *, const char *, va_list)); +__END_DECLS + +/* + * Functions defined in POSIX 1003.1. + */ +#ifndef _ANSI_SOURCE +#define L_ctermid 1024 /* size for ctermid(); PATH_MAX */ +#define L_cuserid 9 /* size for cuserid(); UT_NAMESIZE + 1 */ + +__BEGIN_DECLS +char *ctermid __P((char *)); +char *cuserid __P((char *)); +FILE *fdopen __P((int, const char *)); +int fileno __P((FILE *)); +__END_DECLS +#endif /* not ANSI */ + +/* + * Routines that are purely local. + */ +#if !defined (_ANSI_SOURCE) && !defined(_POSIX_SOURCE) +__BEGIN_DECLS +char *fgetline __P((FILE *, size_t *)); +int fpurge __P((FILE *)); +int getw __P((FILE *)); +int pclose __P((FILE *)); +FILE *popen __P((const char *, const char *)); +int putw __P((int, FILE *)); +void setbuffer __P((FILE *, char *, int)); +int setlinebuf __P((FILE *)); +char *tempnam __P((const char *, const char *)); +int snprintf __P((char *, size_t, const char *, ...)); +int vsnprintf __P((char *, size_t, const char *, va_list)); +int vscanf __P((const char *, va_list)); +int vsscanf __P((const char *, const char *, va_list)); +__END_DECLS + +/* + * This is a #define because the function is used internally and + * (unlike vfscanf) the name __svfscanf is guaranteed not to collide + * with a user function when _ANSI_SOURCE or _POSIX_SOURCE is defined. + */ +#define vfscanf __svfscanf + +/* + * Stdio function-access interface. + */ +__BEGIN_DECLS +FILE *funopen __P((const void *, + int (*)(void *, char *, int), + int (*)(void *, const char *, int), + fpos_t (*)(void *, fpos_t, int), + int (*)(void *))); +__END_DECLS +#define fropen(cookie, fn) funopen(cookie, fn, 0, 0, 0) +#define fwopen(cookie, fn) funopen(cookie, 0, fn, 0, 0) +#endif /* !_ANSI_SOURCE && !_POSIX_SOURCE */ + +/* + * Functions internal to the implementation. + */ +__BEGIN_DECLS +int __srget __P((FILE *)); +int __svfscanf __P((FILE *, const char *, va_list)); +int __swbuf __P((int, FILE *)); +__END_DECLS + +/* + * The __sfoo macros are here so that we can + * define function versions in the C library. + */ +#define __sgetc(p) (--(p)->_r < 0 ? __srget(p) : (int)(*(p)->_p++)) +static __inline int __getc(FILE *_p) +{ + int ret; + flockfile(_p); + ret = __sgetc(_p); + funlockfile(_p); + return(ret); +} + +#define getc(fp) __gets(fp) +#define getchar() getc(stdin) +#define getc_unlocked(fp) __sgetc(fp) +#define getchar_unlocked() getc_unlocked(stdin) + +static __inline int __sputc(int _c, FILE *_p) +{ + if (--_p->_w >= 0 || (_p->_w >= _p->_lbfsize && (char)_c != '\n')) + return (*_p->_p++ = _c); + else + return (__swbuf(_c, _p)); +} + +static __inline int __putc(int _c, FILE *_p) +{ + int ret; + flockfile(_p); + ret = __sputc(_c, _p); + funlockfile(_p); + return(ret); +} + +#define putc(x, fp) __putc(x, fp); +#define putchar(x) putc(x, stdout) +#define putc_unlocked(x, fp) __sputc(x, fp) +#define putchar_unlocked(x) putc_unlocked(x, stdout) + +#define __sfeof(p) (((p)->_flags & __SEOF) != 0) +#define __sferror(p) (((p)->_flags & __SERR) != 0) +#define __sfileno(p) ((p)->_file) + +#define feof(p) __sfeof(p) +#define ferror(p) __sferror(p) + +#ifndef _ANSI_SOURCE +#define fileno(p) __sfileno(p) +#endif + +#endif diff --git a/lib/libpthread/include/util.h b/lib/libpthread/include/util.h new file mode 100644 index 00000000000..249975df57a --- /dev/null +++ b/lib/libpthread/include/util.h @@ -0,0 +1,89 @@ +/* ==== util.h ============================================================ + * Copyright (c) 1991, 1992, 1993 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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: util.h,v 1.1 1995/10/18 08:43:04 deraadt Exp $ $provenid: util.h,v 1.15 1994/02/07 03:32:07 proven Exp $ + * + * Description : Header file for generic utility functions. + * + * 91/08/31 proven - Added exchange. + * Exchange any two objects of any size in any table. + * + * 91/10/06 proven - Cleaned out all the old junk. + * + * 91/03/06 proven - Added getint. + */ + +#ifndef _PTHREAD_UTIL_H +#define _PTHREAD_UTIL_H + +#ifndef NULL +#define NULL 0 +#endif + +/* Stuff only pthread internals really uses */ +#if defined(PTHREAD_KERNEL) + +#undef FALSE +#undef TRUE + +typedef enum Boolean { + FALSE, + TRUE, +} Boolean; + +#define OK 0 +#define NUL '\0' +#define NOTOK -1 + +#if ! defined(min) +#define min(a,b) (((a)<(b))?(a):(b)) +#define max(a,b) (((a)>(b))?(a):(b)) +#endif + +/* Alingn the size to the next multiple of 4 bytes */ +#define ALIGN4(size) ((size + 3) & ~3) +#define ALIGN8(size) ((size + 7) & ~7) + +#ifdef DEBUG +#define DEBUG0(s) printf(s) +#define DEBUG1(s,a) printf(s,a) +#define DEBUG2(s,a,b) printf(s,a,b) +#define DEBUG3(s,a,b,c) printf(s,a,b,c) +#else +#define DEBUG0(s) +#define DEBUG1(s) +#define DEBUG2(s) +#define DEBUG3(s) +#endif + +#endif + +#endif diff --git a/lib/libpthread/pthreads/Makefile.inc b/lib/libpthread/pthreads/Makefile.inc new file mode 100644 index 00000000000..86c63233c1a --- /dev/null +++ b/lib/libpthread/pthreads/Makefile.inc @@ -0,0 +1,9 @@ +# from: @(#)Makefile.inc 5.6 (Berkeley) 6/4/91 + +# pthread sources +.PATH: ${.CURDIR}/pthreads + +SRCS+= cond.c fd.c fd_kern.c fd_pipe.c file.c globals.c malloc.c mutex.c \ + pthread.c pthread_attr.c queue.c signal.c pthread_join.c \ + pthread_detach.c sleep.c + diff --git a/lib/libpthread/pthreads/cond.c b/lib/libpthread/pthreads/cond.c new file mode 100644 index 00000000000..7251f550d16 --- /dev/null +++ b/lib/libpthread/pthreads/cond.c @@ -0,0 +1,208 @@ +/* ==== cond.c ============================================================ + * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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. + * + * Description : Condition cariable functions. + * + * 1.00 93/10/28 proven + * -Started coding this file. + */ + +#ifndef lint +static const char rcsid[] = "$Id: cond.c,v 1.1 1995/10/18 08:43:04 deraadt Exp $ $provenid: cond.c,v 1.16 1994/02/07 02:18:35 proven Exp $"; +#endif + +#include <pthread.h> +#include <errno.h> + +/* ========================================================================== + * pthread_cond_init() + * + * In this implementation I don't need to allocate memory. + * ENOMEM, EAGAIN should never be returned. Arch that have + * weird constraints may need special coding. + */ +int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr) +{ + /* Only check if attr specifies some mutex type other than fast */ + if ((cond_attr) && (cond_attr->c_type != COND_TYPE_FAST)) { + if (cond_attr->c_type >= COND_TYPE_MAX) { + return(EINVAL); + } + if (cond->c_flags & COND_FLAGS_INITED) { + return(EBUSY); + } + cond->c_type = cond_attr->c_type; + } else { + cond->c_type = COND_TYPE_FAST; + } + /* Set all other paramaters */ + pthread_queue_init(&cond->c_queue); + cond->c_flags |= COND_FLAGS_INITED; + cond->c_lock = SEMAPHORE_CLEAR; + return(OK); +} + +/* ========================================================================== + * pthread_cond_destroy() + */ +int pthread_cond_destroy(pthread_cond_t *cond) +{ + /* Only check if cond is of type other than fast */ + switch(cond->c_type) { + case COND_TYPE_FAST: + break; + case COND_TYPE_STATIC_FAST: + default: + return(EINVAL); + break; + } + + /* Cleanup cond, others might want to use it. */ + pthread_queue_init(&cond->c_queue); + cond->c_flags |= COND_FLAGS_INITED; + cond->c_lock = SEMAPHORE_CLEAR; + cond->c_flags = 0; + return(OK); +} + +/* ========================================================================== + * pthread_cond_wait() + */ +int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + semaphore *lock, *plock; + int rval; + + lock = &(cond->c_lock); + while (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + + switch (cond->c_type) { + /* + * Fast condition variables do not check for any error conditions. + */ + case COND_TYPE_FAST: + case COND_TYPE_STATIC_FAST: + plock = &(pthread_run->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + pthread_queue_enq(&cond->c_queue, pthread_run); + pthread_mutex_unlock(mutex); + SEMAPHORE_RESET(lock); + + /* Reschedule will unlock pthread_run */ + reschedule(PS_COND_WAIT); + + return(pthread_mutex_lock(mutex)); + break; + default: + rval = EINVAL; + break; + } + SEMAPHORE_RESET(lock); + return(rval); +} + +/* ========================================================================== + * pthread_cond_signal() + */ +int pthread_cond_signal(pthread_cond_t *cond) +{ + struct pthread *pthread; + semaphore *lock, *plock; + int rval; + + lock = &(cond->c_lock); + while (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + + switch (cond->c_type) { + case COND_TYPE_FAST: + case COND_TYPE_STATIC_FAST: + if (pthread = pthread_queue_get(&cond->c_queue)) { + plock = &(pthread->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + pthread_queue_deq(&cond->c_queue); + pthread->state = PS_RUNNING; + SEMAPHORE_RESET(plock); + } + rval = OK; + break; + default: + rval = EINVAL; + break; + } + SEMAPHORE_RESET(lock); + return(rval); +} + +/* ========================================================================== + * pthread_cond_broadcast() + * + * Not much different then the above routine. + */ +int pthread_cond_broadcast(pthread_cond_t *cond) +{ + struct pthread *pthread; + semaphore *lock, *plock; + int rval; + + lock = &(cond->c_lock); + while (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + + switch (cond->c_type) { + case COND_TYPE_FAST: + case COND_TYPE_STATIC_FAST: + while (pthread = pthread_queue_get(&cond->c_queue)) { + plock = &(pthread->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + pthread_queue_deq(&cond->c_queue); + pthread->state = PS_RUNNING; + SEMAPHORE_RESET(plock); + } + rval = OK; + break; + default: + rval = EINVAL; + break; + } + SEMAPHORE_RESET(lock); + return(rval); +} diff --git a/lib/libpthread/pthreads/fd.c b/lib/libpthread/pthreads/fd.c new file mode 100644 index 00000000000..2302f1d2068 --- /dev/null +++ b/lib/libpthread/pthreads/fd.c @@ -0,0 +1,562 @@ +/* ==== fd.c ============================================================ + * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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. + * + * Description : All the syscalls dealing with fds. + * + * 1.00 93/08/14 proven + * -Started coding this file. + * + * 1.01 93/11/13 proven + * -The functions readv() and writev() added. + */ + +#ifndef lint +static const char rcsid[] = "$Id: fd.c,v 1.1 1995/10/18 08:43:04 deraadt Exp $ $provenid: fd.c,v 1.16 1994/02/07 02:18:39 proven Exp $"; +#endif + +#include <pthread.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <stdarg.h> +#include <fcntl.h> +#include <errno.h> +#include <pthread/posix.h> + +/* + * These first functions really should not be called by the user. + * + * I really should dynamically figure out what the table size is. + */ +int dtablesize = 64; +static struct fd_table_entry fd_entry[64]; + +/* ========================================================================== + * fd_init() + */ +void fd_init(void) +{ + int i; + + for (i = 0; i < dtablesize; i++) { + fd_table[i] = &fd_entry[i]; + + fd_table[i]->ops = NULL; + fd_table[i]->type = FD_NT; + fd_table[i]->fd.i = NOTOK; + fd_table[i]->flags = 0; + fd_table[i]->count = 0; + + pthread_queue_init(&(fd_table[i]->r_queue)); + pthread_queue_init(&(fd_table[i]->w_queue)); + + fd_table[i]->r_owner = NULL; + fd_table[i]->w_owner = NULL; + fd_table[i]->lock = SEMAPHORE_CLEAR; + fd_table[i]->next = NULL; + fd_table[i]->lockcount = 0; + } + + /* Currently only initialize first 3 fds. */ + fd_kern_init(0); + fd_kern_init(1); + fd_kern_init(2); + printf ("Warning: threaded process may have changed open file descriptors\n"); +} + +/* ========================================================================== + * fd_allocate() + */ +int fd_allocate() +{ + semaphore *lock; + int i; + + for (i = 0; i < dtablesize; i++) { + lock = &(fd_table[i]->lock); + while (SEMAPHORE_TEST_AND_SET(lock)) { + continue; + } + if (fd_table[i]->count || fd_table[i]->r_owner + || fd_table[i]->w_owner) { + SEMAPHORE_RESET(lock); + continue; + } + if (fd_table[i]->type == FD_NT) { + /* Test to see if the kernel version is in use */ + /* If so continue; */ + } + fd_table[i]->count++; + SEMAPHORE_RESET(lock); + return(i); + } + pthread_run->error = ENFILE; + return(NOTOK); +} + +/* ========================================================================== + * fd_free() + * + * Assumes fd is locked and owner by pthread_run + * Don't clear the queues, fd_unlock will do that. + */ +int fd_free(int fd) +{ + struct fd_table_entry *fd_valid; + int ret; + + if (ret = --fd_table[fd]->count) { + /* Separate pthread queue into two distinct queues. */ + fd_valid = fd_table[fd]; + fd_table[fd] = fd_table[fd]->next; + fd_valid->next = fd_table[fd]->next; + } + + fd_table[fd]->type = FD_NIU; + fd_table[fd]->fd.i = NOTOK; + fd_table[fd]->next = NULL; + fd_table[fd]->flags = 0; + fd_table[fd]->count = 0; + return(ret); +} + +/* ========================================================================== + * fd_basic_unlock() + * + * The real work of unlock without the locking of fd_table[fd].lock. + */ +void fd_basic_unlock(int fd, int lock_type) +{ + struct pthread *pthread; + semaphore *plock; + + if (fd_table[fd]->r_owner == pthread_run) { + if (pthread = pthread_queue_get(&fd_table[fd]->r_queue)) { + + plock = &(pthread->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + pthread_queue_deq(&fd_table[fd]->r_queue); + fd_table[fd]->r_owner = pthread; + pthread->state = PS_RUNNING; + SEMAPHORE_RESET(plock); + } else { + fd_table[fd]->r_owner = NULL; + } + } + + if (fd_table[fd]->w_owner == pthread_run) { + if (pthread = pthread_queue_get(&fd_table[fd]->w_queue)) { + plock = &(pthread->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + pthread_queue_deq(&fd_table[fd]->r_queue); + fd_table[fd]->w_owner = pthread; + pthread->state = PS_RUNNING; + SEMAPHORE_RESET(plock); + } else { + fd_table[fd]->w_owner = NULL; + } + } +} + +/* ========================================================================== + * fd_unlock() + * If there is a lock count then the function fileunlock will do + * the unlocking, just return. + */ +void fd_unlock(int fd, int lock_type) +{ + semaphore *lock; + + if (!(fd_table[fd]->lockcount)) { + lock = &(fd_table[fd]->lock); + while (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + fd_basic_unlock(fd, lock_type); + SEMAPHORE_RESET(lock); + } +} + +/* ========================================================================== + * fd_basic_lock() + * + * The real work of lock without the locking of fd_table[fd].lock. + * Be sure to leave the lock the same way you found it. i.e. locked. + */ +int fd_basic_lock(unsigned int fd, int lock_type, semaphore * lock) +{ + semaphore *plock; + + /* If not in use return EBADF error */ + if (fd_table[fd]->type == FD_NIU) { + return(NOTOK); + } + + /* If not tested, test it and see if it is valid */ + if (fd_table[fd]->type == FD_NT) { + /* If not ok return EBADF error */ + if (fd_kern_init(fd) != OK) { + return(NOTOK); + } + } + if ((fd_table[fd]->type == FD_HALF_DUPLEX) || + (lock_type & FD_READ)) { + if (fd_table[fd]->r_owner) { + if (fd_table[fd]->r_owner != pthread_run) { + plock = &(pthread_run->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + pthread_queue_enq(&fd_table[fd]->r_queue, pthread_run); + SEMAPHORE_RESET(lock); + + /* Reschedule will unlock pthread_run */ + reschedule(PS_FDLR_WAIT); + + while(SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + } else { + if (!fd_table[fd]->lockcount) { + PANIC(); + } + } + } + fd_table[fd]->r_owner = pthread_run; + } + if ((fd_table[fd]->type != FD_HALF_DUPLEX) && + (lock_type & FD_WRITE)) { + if (fd_table[fd]->w_owner) { + if (fd_table[fd]->w_owner != pthread_run) { + plock = &(pthread_run->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + pthread_queue_enq(&fd_table[fd]->w_queue, pthread_run); + SEMAPHORE_RESET(lock); + + /* Reschedule will unlock pthread_run */ + reschedule(PS_FDLW_WAIT); + + while(SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + } + } + fd_table[fd]->w_owner = pthread_run; + } + if (!fd_table[fd]->count) { + fd_basic_unlock(fd, lock_type); + return(NOTOK); + } + return(OK); +} + +/* ========================================================================== + * fd_lock() + */ +int fd_lock(unsigned int fd, int lock_type) +{ + semaphore *lock; + int error; + + if (fd < dtablesize) { + lock = &(fd_table[fd]->lock); + while (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + error = fd_basic_lock(fd, lock_type, lock); + SEMAPHORE_RESET(lock); + return(error); + } + return(NOTOK); +} + + +/* ========================================================================== + * ======================================================================= */ + +/* ========================================================================== + * read() + */ +ssize_t read(int fd, void *buf, size_t nbytes) +{ + int ret; + + if ((ret = fd_lock(fd, FD_READ)) == OK) { + ret = fd_table[fd]->ops->read(fd_table[fd]->fd, + fd_table[fd]->flags, buf, nbytes); + fd_unlock(fd, FD_READ); + } + return(ret); +} + +/* ========================================================================== + * readv() + */ +int readv(int fd, const struct iovec *iov, int iovcnt) +{ + int ret; + + if ((ret = fd_lock(fd, FD_READ)) == OK) { + ret = fd_table[fd]->ops->readv(fd_table[fd]->fd, + fd_table[fd]->flags, iov, iovcnt); + fd_unlock(fd, FD_READ); + } + return(ret); +} + +/* ========================================================================== + * write() + */ +ssize_t write(int fd, const void *buf, size_t nbytes) +{ + int ret; + + if ((ret = fd_lock(fd, FD_WRITE)) == OK) { + ret = fd_table[fd]->ops->write(fd_table[fd]->fd, + fd_table[fd]->flags, buf, nbytes); + fd_unlock(fd, FD_WRITE); + } + return(ret); +} + +/* ========================================================================== + * writev() + */ +int writev(int fd, const struct iovec *iov, int iovcnt) +{ + int ret; + + if ((ret = fd_lock(fd, FD_WRITE)) == OK) { + ret = fd_table[fd]->ops->writev(fd_table[fd]->fd, + fd_table[fd]->flags, iov, iovcnt); + fd_unlock(fd, FD_WRITE); + } + return(ret); +} + +/* ========================================================================== + * lseek() + */ +off_t lseek(int fd, off_t offset, int whence) +{ + int ret; + + if ((ret = fd_lock(fd, FD_RDWR)) == OK) { + ret = fd_table[fd]->ops->seek(fd_table[fd]->fd, + fd_table[fd]->flags, offset, whence); + fd_unlock(fd, FD_RDWR); + } + return(ret); +} + +/* ========================================================================== + * close() + * + * The whole close procedure is a bit odd and needs a bit of a rethink. + * For now close() locks the fd, calls fd_free() which checks to see if + * there are any other fd values poinging to the same real fd. If so + * It breaks the wait queue into two sections those that are waiting on fd + * and those waiting on other fd's. Those that are waiting on fd are connected + * to the fd_table[fd] queue, and the count is set to zero, (BUT THE LOCK IS NOT + * RELEASED). close() then calls fd_unlock which give the fd to the next queued + * element which determins that the fd is closed and then calls fd_unlock etc... + */ +int close(int fd) +{ + union fd_data realfd; + int ret, flags; + + if ((ret = fd_lock(fd, FD_RDWR)) == OK) { + flags = fd_table[fd]->flags; + realfd = fd_table[fd]->fd; + if (fd_free(fd) == OK) { + ret = fd_table[fd]->ops->close(realfd, flags); + } + fd_unlock(fd, FD_RDWR); + } + return(ret); +} + +/* ========================================================================== + * fd_basic_dup() + * + * Might need to do more than just what's below. + */ +static inline void fd_basic_dup(int fd, int newfd) +{ + fd_table[newfd]->next = fd_table[fd]->next; + fd_table[fd]->next = fd_table[newfd]; + fd_table[fd]->count++; +} + +/* ========================================================================== + * dup2() + * + * Always lock the lower number fd first to avoid deadlocks. + * newfd must be locked by hand so it can be closed if it is open, + * or it won't be opened while dup is in progress. + */ +int dup2(fd, newfd) +{ + union fd_data realfd; + semaphore *lock; + int ret, flags; + + if (newfd < dtablesize) { + if (fd < newfd) { + if ((ret = fd_lock(fd, FD_RDWR)) == OK) { + /* Need to lock the newfd by hand */ + lock = &(fd_table[newfd]->lock); + while(SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + + /* Is it inuse */ + if (fd_basic_lock(newfd, FD_RDWR, lock) == OK) { + /* free it and check close status */ + flags = fd_table[fd]->flags; + realfd = fd_table[fd]->fd; + if (fd_free(fd) == OK) { + ret = fd_table[fd]->ops->close(realfd, flags); + } else { + /* Lots of work to do */ + } + } + fd_basic_dup(fd, newfd); + } + fd_unlock(fd, FD_RDWR); + } else { + /* Need to lock the newfd by hand */ + lock = &(fd_table[newfd]->lock); + while(SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + if ((ret = fd_lock(fd, FD_RDWR)) == OK) { + } + /* Is it inuse */ + if ((ret = fd_basic_lock(newfd, FD_RDWR, lock)) == OK) { + /* free it and check close status */ + flags = fd_table[fd]->flags; + realfd = fd_table[fd]->fd; + if (fd_free(fd) == OK) { + ret = fd_table[fd]->ops->close(realfd, flags); + } else { + /* Lots of work to do */ + } + + fd_basic_dup(fd, newfd); + fd_unlock(fd, FD_RDWR); + } + SEMAPHORE_RESET(lock); + } + } else { + ret = NOTOK; + } + return(ret); + +} + +/* ========================================================================== + * dup() + */ +int dup(int fd) +{ + int ret; + + if ((ret = fd_lock(fd, FD_RDWR)) == OK) { + ret = fd_allocate(); + fd_basic_dup(fd, ret); + fd_unlock(fd, FD_RDWR); + } + return(ret); +} + +/* ========================================================================== + * fcntl() + */ +int fcntl(int fd, int cmd, ...) +{ + int ret, realfd, flags; + struct flock *flock; + semaphore *plock; + va_list ap; + + flags = 0; + if ((ret = fd_lock(fd, FD_RDWR)) == OK) { + va_start(ap, cmd); + switch(cmd) { + case F_DUPFD: + ret = fd_allocate(); + fd_basic_dup(va_arg(ap, int), ret); + break; + case F_SETFD: + flags = va_arg(ap, int); + case F_GETFD: + ret = fd_table[fd]->ops->fcntl(fd_table[fd]->fd, + fd_table[fd]->flags, cmd, flags | __FD_NONBLOCK); + break; + case F_GETFL: + ret = fd_table[fd]->flags; + break; + case F_SETFL: + flags = va_arg(ap, int); + if ((ret = fd_table[fd]->ops->fcntl(fd_table[fd]->fd, + fd_table[fd]->flags, cmd, flags | __FD_NONBLOCK)) == OK) { + fd_table[fd]->flags = flags; + } + break; +/* case F_SETLKW: */ + /* + * Do the same as SETLK but if it fails with EACCES or EAGAIN + * block the thread and try again later, not implemented yet + */ +/* case F_SETLK: */ +/* case F_GETLK: + flock = va_arg(ap, struct flock*); + ret = fd_table[fd]->ops->fcntl(fd_table[fd]->fd, + fd_table[fd]->flags, cmd, flock); + break; */ + default: + /* Might want to make va_arg use a union */ + ret = fd_table[fd]->ops->fcntl(fd_table[fd]->fd, + fd_table[fd]->flags, cmd, va_arg(ap, void*)); + break; + } + va_end(ap); + fd_unlock(fd, FD_RDWR); + } + return(ret); +} diff --git a/lib/libpthread/pthreads/fd_kern.c b/lib/libpthread/pthreads/fd_kern.c new file mode 100644 index 00000000000..ed4f5d008fb --- /dev/null +++ b/lib/libpthread/pthreads/fd_kern.c @@ -0,0 +1,647 @@ +/* ==== fd_kern.c ============================================================ + * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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. + * + * Description : Deals with the valid kernel fds. + * + * 1.00 93/09/27 proven + * -Started coding this file. + * + * 1.01 93/11/13 proven + * -The functions readv() and writev() added. + */ + +#ifndef lint +static const char rcsid[] = "$Id: fd_kern.c,v 1.1 1995/10/18 08:43:04 deraadt Exp $ $provenid: fd_kern.c,v 1.7 1994/02/07 02:18:49 proven Exp $"; +#endif + +#include <pthread.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/uio.h> +#include <stdarg.h> +#include <signal.h> +#include <fcntl.h> +#include <errno.h> +#include <pthread/posix.h> + +/* ========================================================================== + * Variables used by both fd_kern_poll and fd_kern_wait + */ +static struct pthread *fd_wait_read, *fd_wait_write; +static fd_set fd_set_read, fd_set_write; + +/* ========================================================================== + * fd_kern_poll() + * + * Called only from context_switch(). The kernel must be locked. + * + * This function uses a linked list of waiting pthreads, NOT a queue. + */ +static semaphore fd_wait_lock = SEMAPHORE_CLEAR; + +void fd_kern_poll() +{ + struct timeval __fd_kern_poll_timeout = { 0, 0 }; + struct pthread **pthread; + semaphore *lock; + int count; + + /* If someone has the lock then they are in RUNNING state, just return */ + lock = &fd_wait_lock; + if (SEMAPHORE_TEST_AND_SET(lock)) { + return; + } + if (fd_wait_read || fd_wait_write) { + for (pthread = &fd_wait_read; *pthread; pthread = &((*pthread)->next)) { + FD_SET((*pthread)->fd, &fd_set_read); + } + for (pthread = &fd_wait_write; *pthread; pthread = &((*pthread)->next)) { + FD_SET((*pthread)->fd, &fd_set_write); + } + + if ((count = machdep_sys_select(dtablesize, &fd_set_read, + &fd_set_write, NULL, &__fd_kern_poll_timeout)) < OK) { + if (count == -EINTR) { + SEMAPHORE_RESET(lock); + return; + } + PANIC(); + } + + for (pthread = &fd_wait_read; count && *pthread; ) { + if (FD_ISSET((*pthread)->fd, &fd_set_read)) { + /* Get lock on thread */ + + (*pthread)->state = PS_RUNNING; + *pthread = (*pthread)->next; + count--; + continue; + } + pthread = &((*pthread)->next); + } + + for (pthread = &fd_wait_write; count && *pthread; ) { + if (FD_ISSET((*pthread)->fd, &fd_set_write)) { + semaphore *plock; + + /* Get lock on thread */ + plock = &(*pthread)->lock; + if (!(SEMAPHORE_TEST_AND_SET(plock))) { + /* Thread locked, skip it. */ + (*pthread)->state = PS_RUNNING; + *pthread = (*pthread)->next; + SEMAPHORE_RESET(plock); + } + count--; + continue; + } + pthread = &((*pthread)->next); + } + } + SEMAPHORE_RESET(lock); +} + +/* ========================================================================== + * fd_kern_wait() + * + * Called when there is no active thread to run. + */ +extern struct timeval __fd_kern_wait_timeout; + +void fd_kern_wait() +{ + struct pthread **pthread; + sigset_t sig_to_block; + int count; + + if (fd_wait_read || fd_wait_write) { + for (pthread = &fd_wait_read; *pthread; pthread = &((*pthread)->next)) { + FD_SET((*pthread)->fd, &fd_set_read); + } + for (pthread = &fd_wait_write; *pthread; pthread = &((*pthread)->next)) { + FD_SET((*pthread)->fd, &fd_set_write); + } + + /* Turn off interrupts for real while we set the timer. */ + + sigfillset(&sig_to_block); + sigprocmask(SIG_BLOCK, &sig_to_block, NULL); + + machdep_unset_thread_timer(); + __fd_kern_wait_timeout.tv_usec = 0; + __fd_kern_wait_timeout.tv_sec = 3600; + + sigprocmask(SIG_UNBLOCK, &sig_to_block, NULL); + + /* + * There is a small but finite chance that an interrupt will + * occure between the unblock and the select. Because of this + * sig_handler_real() sets the value of __fd_kern_wait_timeout + * to zero causing the select to do a poll instead of a wait. + */ + + while ((count = machdep_sys_select(dtablesize, &fd_set_read, + &fd_set_write, NULL, &__fd_kern_wait_timeout)) < OK) { + if (count == -EINTR) { + return; + } + PANIC(); + } + + for (pthread = &fd_wait_read; count && *pthread; ) { + if (FD_ISSET((*pthread)->fd, &fd_set_read)) { + /* Get lock on thread */ + + (*pthread)->state = PS_RUNNING; + *pthread = (*pthread)->next; + count--; + continue; + } + pthread = &((*pthread)->next); + } + + for (pthread = &fd_wait_write; count && *pthread; ) { + if (FD_ISSET((*pthread)->fd, &fd_set_write)) { + semaphore *plock; + + /* Get lock on thread */ + plock = &(*pthread)->lock; + if (!(SEMAPHORE_TEST_AND_SET(plock))) { + /* Thread locked, skip it. */ + (*pthread)->state = PS_RUNNING; + *pthread = (*pthread)->next; + SEMAPHORE_RESET(plock); + } + count--; + continue; + } + pthread = &((*pthread)->next); + } + } else { + /* No threads, waiting on I/O, do a sigsuspend */ + sig_handler_pause(); + } +} + +/* ========================================================================== + * Special Note: All operations return the errno as a negative of the errno + * listed in errno.h + * ======================================================================= */ + +/* ========================================================================== + * read() + */ +ssize_t __fd_kern_read(int fd, int flags, void *buf, size_t nbytes) +{ + semaphore *lock, *plock; + int ret; + + while ((ret = machdep_sys_read(fd, buf, nbytes)) < OK) { + if (ret == -EWOULDBLOCK) { + /* Lock queue */ + lock = &fd_wait_lock; + while (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + + /* Lock pthread */ + plock = &(pthread_run->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + + /* queue pthread for a FDR_WAIT */ + pthread_run->next = fd_wait_read; + fd_wait_read = pthread_run; + pthread_run->fd = fd; + SEMAPHORE_RESET(lock); + reschedule(PS_FDR_WAIT); + } else { + pthread_run->error = -ret; + ret = NOTOK; + break; + } + } + return(ret); +} + +/* ========================================================================== + * readv() + */ +int __fd_kern_readv(int fd, int flags, struct iovec *iov, int iovcnt) +{ + semaphore *lock, *plock; + int ret; + + while ((ret = machdep_sys_readv(fd, iov, iovcnt)) < OK) { + if (ret == -EWOULDBLOCK) { + /* Lock queue */ + lock = &fd_wait_lock; + while (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + + /* Lock pthread */ + plock = &(pthread_run->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + + /* queue pthread for a FDR_WAIT */ + pthread_run->next = fd_wait_read; + fd_wait_read = pthread_run; + pthread_run->fd = fd; + SEMAPHORE_RESET(lock); + reschedule(PS_FDR_WAIT); + } else { + pthread_run->error = -ret; + ret = NOTOK; + break; + } + } + return(ret); +} + +/* ========================================================================== + * write() + */ +ssize_t __fd_kern_write(int fd, int flags, const void *buf, size_t nbytes) +{ + semaphore *lock, *plock; + int ret; + + while ((ret = machdep_sys_write(fd, buf, nbytes)) < OK) { + if (pthread_run->error == -EWOULDBLOCK) { + /* Lock queue */ + lock = &fd_wait_lock; + while (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + + /* Lock pthread */ + plock = &(pthread_run->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + + /* queue pthread for a FDW_WAIT */ + pthread_run->next = fd_wait_write; + fd_wait_write = pthread_run; + pthread_run->fd = fd; + SEMAPHORE_RESET(lock); + reschedule(PS_FDW_WAIT); + } else { + pthread_run->error = ret; + break; + } + } + return(ret); +} + +/* ========================================================================== + * writev() + */ +int __fd_kern_writev(int fd, int flags, struct iovec *iov, int iovcnt) +{ + semaphore *lock, *plock; + int ret; + + while ((ret = machdep_sys_writev(fd, iov, iovcnt)) < OK) { + if (pthread_run->error == -EWOULDBLOCK) { + /* Lock queue */ + lock = &fd_wait_lock; + while (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + + /* Lock pthread */ + plock = &(pthread_run->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + + /* queue pthread for a FDW_WAIT */ + pthread_run->next = fd_wait_write; + fd_wait_write = pthread_run; + pthread_run->fd = fd; + SEMAPHORE_RESET(lock); + reschedule(PS_FDW_WAIT); + } else { + pthread_run->error = ret; + break; + } + } + return(ret); +} + +/* ========================================================================== + * For blocking version we really should set an interrupt + * fcntl() + */ +int __fd_kern_fcntl(int fd, int flags, int cmd, int arg) +{ + return(machdep_sys_fcntl(fd, cmd, arg)); +} + +/* ========================================================================== + * close() + */ +int __fd_kern_close(int fd, int flags) +{ + return(machdep_sys_close(fd)); +} + +/* ========================================================================== + * lseek() + */ +int __fd_kern_lseek(int fd, int flags, off_t offset, int whence) +{ + return(machdep_sys_lseek(fd, offset, whence)); +} + +/* + * File descriptor operations + */ +extern machdep_sys_close(); + +/* Normal file operations */ +static struct fd_ops __fd_kern_ops = { + __fd_kern_write, __fd_kern_read, __fd_kern_close, __fd_kern_fcntl, + __fd_kern_readv, __fd_kern_writev, __fd_kern_lseek +}; + +/* NFS file opperations */ + +/* FIFO file opperations */ + +/* Device operations */ + +/* ========================================================================== + * open() + * + * Because open could potentially block opening a file from a remote + * system, we want to make sure the call will timeout. We then try and open + * the file, and stat the file to determine what operations we should + * associate with the fd. + * + * This is not done yet + * + * A reqular file on the local system needs no special treatment. + */ +int open(const char *path, int flags, ...) +{ + int fd, mode, fd_kern; + struct stat stat_buf; + va_list ap; + + /* If pthread scheduling == FIFO set a virtual timer */ + if (flags & O_CREAT) { + va_start(ap, flags); + mode = va_arg(ap, int); + va_end(ap); + } else { + mode = 0; + } + + if (!((fd = fd_allocate()) < OK)) { + fd_table[fd]->flags = flags; + flags |= __FD_NONBLOCK; + + if (!((fd_kern = machdep_sys_open(path, flags, mode)) < OK)) { + + /* fstat the file to determine what type it is */ + if (fstat(fd_kern, &stat_buf)) { +printf("error %d stating new fd %d\n", errno, fd); + } + if (S_ISREG(stat_buf.st_mode)) { + fd_table[fd]->ops = &(__fd_kern_ops); + fd_table[fd]->type = FD_HALF_DUPLEX; + } else { + fd_table[fd]->ops = &(__fd_kern_ops); + fd_table[fd]->type = FD_FULL_DUPLEX; + } + fd_table[fd]->fd = fd_kern; + return(fd); + } + + pthread_run->error = - fd_kern; + fd_table[fd]->count = 0; + } + return(NOTOK); +} + +/* ========================================================================== + * fd_kern_init() + * + * Assume the entry is locked before routine is invoked + * + * This may change. The problem is setting the fd to nonblocking changes + * the parents fd too, which may not be the desired result. + */ +static fd_kern_init_called = 0; +void fd_kern_init(int fd) +{ + if ((fd_table[fd]->flags = machdep_sys_fcntl(fd, F_GETFL, NULL)) >= OK) { + machdep_sys_fcntl(fd, F_SETFL, fd_table[fd]->flags | __FD_NONBLOCK); + fd_table[fd]->ops = &(__fd_kern_ops); + fd_table[fd]->type = FD_HALF_DUPLEX; + fd_table[fd]->fd = fd; + fd_table[fd]->count = 1; + + } +} + +/* ========================================================================== + * Here are the berkeley socket functions. These are not POSIX. + * ======================================================================= */ + +/* ========================================================================== + * socket() + */ +int socket(int af, int type, int protocol) +{ + int fd, fd_kern; + + if (!((fd = fd_allocate()) < OK)) { + + if (!((fd_kern = machdep_sys_socket(af, type, protocol)) < OK)) { + machdep_sys_fcntl(fd_kern, F_SETFL, __FD_NONBLOCK); + + /* Should fstat the file to determine what type it is */ + fd_table[fd]->ops = & __fd_kern_ops; + fd_table[fd]->type = FD_FULL_DUPLEX; + fd_table[fd]->fd = fd_kern; + fd_table[fd]->flags = 0; + return(fd); + } + + pthread_run->error = - fd_kern; + fd_table[fd]->count = 0; + } + return(NOTOK); +} + +/* ========================================================================== + * bind() + */ +int bind(int fd, const struct sockaddr *name, int namelen) +{ + /* Not much to do in bind */ + semaphore *plock; + int ret; + + if ((ret = fd_lock(fd, FD_RDWR)) == OK) { + if ((ret = machdep_sys_bind(fd_table[fd]->fd, name, namelen)) < OK) { + pthread_run->error = - ret; + } + fd_unlock(fd, FD_RDWR); + } + return(ret); +} + +/* ========================================================================== + * connect() + */ +int connect(int fd, const struct sockaddr *name, int namelen) +{ + semaphore *lock, *plock; + struct sockaddr tmpname; + int ret, tmpnamelen; + + if ((ret = fd_lock(fd, FD_RDWR)) == OK) { + if ((ret = machdep_sys_connect(fd_table[fd]->fd, name, namelen)) < OK) { + if ((ret == -EWOULDBLOCK) || (ret == -EINPROGRESS) || + (ret == -EALREADY)) { + /* Lock queue */ + lock = &fd_wait_lock; + while (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + + /* Lock pthread */ + plock = &(pthread_run->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + + /* queue pthread for a FDW_WAIT */ + pthread_run->fd = fd_table[fd]->fd.i; + pthread_run->next = fd_wait_write; + fd_wait_write = pthread_run; + SEMAPHORE_RESET(lock); + reschedule(PS_FDW_WAIT); + + /* OK now lets see if it really worked */ + if (((ret = machdep_sys_getpeername(fd_table[fd]->fd, + &tmpname, &tmpnamelen)) < OK) && (ret == -ENOTCONN)) { + + /* Get the error, this function should not fail */ + machdep_sys_getsockopt(fd_table[fd]->fd, SOL_SOCKET, + SO_ERROR, &pthread_run->error, &tmpnamelen); + } + } else { + pthread_run->error = -ret; + } + } + fd_unlock(fd, FD_RDWR); + } + return(ret); +} + +/* ========================================================================== + * accept() + */ +int accept(int fd, struct sockaddr *name, int *namelen) +{ + semaphore *lock, *plock; + int ret, fd_kern; + + + + if ((ret = fd_lock(fd, FD_RDWR)) == OK) { + while ((fd_kern = machdep_sys_accept(fd_table[fd]->fd, name, namelen)) < OK) { + if (fd_kern == -EWOULDBLOCK) { + /* Lock queue */ + lock = &fd_wait_lock; + while (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + + /* Lock pthread */ + plock = &(pthread_run->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + + /* queue pthread for a FDR_WAIT */ + pthread_run->fd = fd_table[fd]->fd.i; + pthread_run->next = fd_wait_write; + pthread_run->next = fd_wait_read; + fd_wait_read = pthread_run; + SEMAPHORE_RESET(lock); + reschedule(PS_FDR_WAIT); + } else { + fd_unlock(fd, FD_RDWR); + return(fd_kern); + } + } + fd_unlock(fd, FD_RDWR); + + if (!((ret = fd_allocate()) < OK)) { + + /* This may be unnecessary */ + machdep_sys_fcntl(fd_kern, F_SETFL, __FD_NONBLOCK); + + /* Should fstat the file to determine what type it is */ + fd_table[ret]->ops = & __fd_kern_ops; + fd_table[ret]->type = FD_FULL_DUPLEX; + fd_table[ret]->fd = fd_kern; + fd_table[ret]->flags = 0; + } + } + return(ret); +} + +/* ========================================================================== + * listen() + */ +int listen(int fd, int backlog) +{ + int ret; + + if ((ret = fd_lock(fd, FD_RDWR)) == OK) { + ret = machdep_sys_listen(fd_table[fd]->fd, backlog); + fd_unlock(fd, FD_RDWR); + } + return(ret); +} diff --git a/lib/libpthread/pthreads/fd_pipe.c b/lib/libpthread/pthreads/fd_pipe.c new file mode 100644 index 00000000000..d4cf6f2cb9e --- /dev/null +++ b/lib/libpthread/pthreads/fd_pipe.c @@ -0,0 +1,268 @@ +/* ==== fd_pipe.c ============================================================ + * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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. + * + * Description : The new fast ITC pipe routines. + * + * 1.00 93/08/14 proven + * -Started coding this file. + * + * 1.01 93/11/13 proven + * -The functions readv() and writev() added. + */ + +#ifndef lint +static const char rcsid[] = "$Id: fd_pipe.c,v 1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: fd_pipe.c,v 1.16 1994/02/07 02:18:52 proven Exp $"; +#endif + +#include <pthread.h> +#include <pthread/fd_pipe.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <fcntl.h> +#include <errno.h> +#include <pthread/posix.h> + +/* ========================================================================== + * The pipe lock is never unlocked until all pthreads waiting are done with it + * read() + */ +ssize_t __pipe_read(struct __pipe *fd, int flags, void *buf, size_t nbytes) +{ + semaphore *lock, *plock; + int ret = 0; + + if (flags & O_ACCMODE) { return(NOTOK); } + + lock = &(fd->lock); + while (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + /* If there is nothing to read, go to sleep */ + if (fd->count == 0) { + if (flags == WR_CLOSED) { + SEMAPHORE_RESET(lock); + return(0); + } /* Lock pthread */ + plock = &(pthread_run->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + + /* queue pthread for a FDR_WAIT */ + pthread_run->next = NULL; + fd->wait = pthread_run; + SEMAPHORE_RESET(lock); + reschedule(PS_FDR_WAIT); + ret = fd->size; + } else { + ret = MIN(nbytes, fd->count); + memcpy(buf, fd->buf + fd->offset, ret); + if (!(fd->count -= ret)) { + fd->offset = 0; + } + + /* Should try to read more from the waiting writer */ + + if (fd->wait) { + plock = &(fd->wait->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + fd->wait->state = PS_RUNNING; + SEMAPHORE_RESET(plock); + } else { + SEMAPHORE_RESET(lock); + } + } + return(ret); +} + +/* ========================================================================== + * __pipe_write() + * + * First check to see if the read side is still open, then + * check to see if there is a thread in a read wait for this pipe, if so + * copy as much data as possible directly into the read waiting threads + * buffer. The write thread(whether or not there was a read thread) + * copies as much data as it can into the pipe buffer and it there + * is still data it goes to sleep. + */ +ssize_t __pipe_write(struct __pipe *fd, int flags, const void *buf, size_t nbytes) { + semaphore *lock, *plock; + int ret, count; + + if (!(flags & O_ACCMODE)) { return(NOTOK); } + + lock = &(fd->lock); + while (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + while (fd->flags != RD_CLOSED) { + if (fd->wait) { + /* Lock pthread */ + plock = &(fd->wait->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + + /* Copy data directly into waiting pthreads buf */ + fd->wait_size = MIN(nbytes, fd->wait_size); + memcpy(fd->wait_buf, buf, fd->wait_size); + buf = (const char *)buf + fd->wait_size; + nbytes -= fd->wait_size; + ret = fd->wait_size; + + /* Wake up waiting pthread */ + fd->wait->state = PS_RUNNING; + SEMAPHORE_RESET(plock); + fd->wait = NULL; + } + + if (count = MIN(nbytes, fd->size - (fd->offset + fd->count))) { + memcpy(fd->buf + (fd->offset + fd->count), buf, count); + buf = (const char *)buf + count; + nbytes -= count; + ret += count; + } + if (nbytes) { + /* Lock pthread */ + plock = &(fd->wait->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + + fd->wait = pthread_run; + SEMAPHORE_RESET(lock); + reschedule(PS_FDW_WAIT); + } else { + return(ret); + } + } + return(NOTOK); +} + +/* ========================================================================== + * __pipe_close() + * + * The whole close procedure is a bit odd and needs a bit of a rethink. + * For now close() locks the fd, calls fd_free() which checks to see if + * there are any other fd values poinging to the same real fd. If so + * It breaks the wait queue into two sections those that are waiting on fd + * and those waiting on other fd's. Those that are waiting on fd are connected + * to the fd_table[fd] queue, and the count is set to zero, (BUT THE LOCK IS NOT + * RELEASED). close() then calls fd_unlock which give the fd to the next queued + * element which determins that the fd is closed and then calls fd_unlock etc... + */ +int __pipe_close(struct __pipe *fd, int flags) +{ + semaphore *lock, *plock; + + lock = &(fd->lock); + while (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + if (!(fd->flags)) { + if (fd->wait) { + if (flags & O_ACCMODE) { + fd->flags |= WR_CLOSED; + /* Lock pthread */ + /* Write side closed, wake read side and return EOF */ + plock = &((fd->wait)->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + + fd->count = 0; + + /* Wake up waiting pthread */ + fd->wait->state = PS_RUNNING; + SEMAPHORE_RESET(plock); + fd->wait = NULL; + } else { + /* Should send a signal */ + fd->flags |= RD_CLOSED; + } + } + } else { + free(fd); + return(OK); + } + SEMAPHORE_RESET(lock); +} + +/* ========================================================================== + * For those function that aren't implemented yet + * __pipe_enosys() + */ +static int __pipe_enosys() +{ + pthread_run->error = ENOSYS; + return(NOTOK); +} + +/* + * File descriptor operations + */ +struct fd_ops fd_ops[] = { +{ NULL, NULL, }, /* Non operations */ +{ __pipe_write, __pipe_read, __pipe_close, __pipe_enosys, __pipe_enosys, + __pipe_enosys }, +}; + +/* ========================================================================== + * open() + */ +/* int __pipe_open(const char *path, int flags, ...) */ +int newpipe(int fd[2]) +{ + struct __pipe *fd_data; + + if ((!((fd[0] = fd_allocate()) < OK)) && (!((fd[1] = fd_allocate()) < OK))) { + fd_data = malloc(sizeof(struct __pipe)); + fd_data->buf = malloc(4096); + fd_data->size = 4096; + fd_data->count = 0; + fd_data->offset = 0; + + fd_data->wait = NULL; + fd_data->flags = 0; + + fd_table[fd[0]]->fd.ptr = fd_data; + fd_table[fd[0]]->flags = O_RDONLY; + fd_table[fd[1]]->fd.ptr = fd_data; + fd_table[fd[1]]->flags = O_WRONLY; + + return(OK); + } + return(NOTOK); +} + diff --git a/lib/libpthread/pthreads/file.c b/lib/libpthread/pthreads/file.c new file mode 100644 index 00000000000..f22b3761c5a --- /dev/null +++ b/lib/libpthread/pthreads/file.c @@ -0,0 +1,117 @@ +/* ==== file.c ============================================================ + * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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. + * + * Description : The locking functions for stdio. + * + * 1.00 93/09/04 proven + * -Started coding this file. + */ + +#ifndef lint +static const char rcsid[] = "$Id: file.c,v 1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: file.c,v 1.16 1994/02/07 02:18:55 proven Exp $"; +#endif + +#include <pthread.h> +#include <stdio.h> + +/* ========================================================================== + * flockfile() + */ +void flockfile(FILE *fp) +{ + semaphore *lock; + int fd; + + fd = fileno(fp); + lock = &(fd_table[fd]->lock); + while (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + + if (fd_table[fd]->r_owner != pthread_run) { + /* This might fail but POSIX doesn't give a damn. */ + fd_basic_lock(fd, FD_RDWR, lock); + } + fd_table[fd]->lockcount++; + SEMAPHORE_RESET(lock); +} + +/* ========================================================================== + * ftrylockfile() + */ +int ftrylockfile(FILE *fp) +{ + semaphore *lock; + int fd; + + fd = fileno(fp); + lock = &(fd_table[fd]->lock); + while (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + + if (fd_table[fd]->r_owner != pthread_run) { + if (!(fd_table[fd]->r_owner && fd_table[fd]->w_owner)) { + fd_basic_lock(fd, FD_RDWR, lock); + fd = OK; + } else { + fd = NOTOK; + } + } else { + fd_table[fd]->lockcount++; + fd = OK; + } + SEMAPHORE_RESET(lock); + return(fd); +} + +/* ========================================================================== + * funlockfile() + */ +void funlockfile(FILE *fp) +{ + semaphore *lock; + int fd; + + fd = fileno(fp); + lock = &(fd_table[fd]->lock); + while (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + + if (fd_table[fd]->r_owner == pthread_run) { + if (--fd_table[fd]->lockcount == 0) { + fd_basic_unlock(fd, FD_RDWR); + } + } + SEMAPHORE_RESET(lock); +} + diff --git a/lib/libpthread/pthreads/globals.c b/lib/libpthread/pthreads/globals.c new file mode 100644 index 00000000000..00774e0a2f8 --- /dev/null +++ b/lib/libpthread/pthreads/globals.c @@ -0,0 +1,67 @@ +/* ==== globals.c ============================================================ + * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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. + * + * Description : Global variables. + * + * 1.00 93/07/26 proven + * -Started coding this file. + */ + +#ifndef lint +static const char rcsid[] = "$Id: globals.c,v 1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: globals.c,v 1.16 1994/02/07 02:18:57 proven Exp $"; +#endif + +#include <pthread.h> + +/* + * Initial thread, running thread, and top of link list + * of all threads. + */ +struct pthread *pthread_run; +struct pthread *pthread_initial; +struct pthread *pthread_link_list; + +/* + * default thread attributes + */ +pthread_attr_t pthread_default_attr = { SCHED_RR, NULL, PTHREAD_STACK_DEFAULT }; + +/* + * Queue for all threads elidgeable to run this scheduling round. + */ +struct pthread_queue pthread_current_queue = PTHREAD_QUEUE_INITIALIZER; + +/* + * File table information + */ +struct fd_table_entry *fd_table[64]; + + diff --git a/lib/libpthread/pthreads/malloc.c b/lib/libpthread/pthreads/malloc.c new file mode 100644 index 00000000000..0c5937ddb12 --- /dev/null +++ b/lib/libpthread/pthreads/malloc.c @@ -0,0 +1,361 @@ +/* ==== malloc.c ============================================================ + * Copyright (c) 1983 Regents of the University of California. + * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu + * 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. + * + * Description : Malloc functions. + * This is a very fast storage allocator. It allocates blocks of a small + * number of different sizes, and keeps free lists of each size. Blocks that + * don't exactly fit are passed up to the next larger size. In this + * implementation, the available sizes are 2^n-4 (or 2^n-10) bytes long. + * This is designed for use in a virtual memory environment. + * + * 0.00 82/02/21 Chris Kingsley kingsley@cit-20 + * + * 1.00 93/11/06 proven + * -Modified BSD libc malloc to be threadsafe. + * + */ + +#ifndef lint +static const char rcsid[] = "$Id: malloc.c,v 1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: malloc.c,v 1.16 1994/02/07 02:19:00 proven Exp $"; +#endif + +#include <pthread.h> +#include <sys/types.h> +#include <string.h> +#include <pthread/posix.h> + +/* + * The overhead on a block is at least 4 bytes. When free, this space + * contains a pointer to the next free block, and the bottom two bits must + * be zero. When in use, the first byte is set to MAGIC, and the second + * byte is the size index. The remaining bytes are for alignment. + * If range checking is enabled then a second word holds the size of the + * requested block, less 1, rounded up to a multiple of sizeof(RMAGIC). + * The order of elements is critical: ov_magic must overlay the low order + * bits of ov_next, and ov_magic can not be a valid ov_next bit pattern. + */ +union overhead { + union overhead *ov_next; /* when free */ + struct { + u_char ovu_magic; /* magic number */ + u_char ovu_index; /* bucket # */ +#ifdef RCHECK + u_short ovu_rmagic; /* range magic number */ + u_int ovu_size; /* actual block size */ +#endif + } ovu; +#define ov_magic ovu.ovu_magic +#define ov_index ovu.ovu_index +#define ov_rmagic ovu.ovu_rmagic +#define ov_size ovu.ovu_size +}; + +#define MAGIC 0xef /* magic # on accounting info */ +#define RMAGIC 0x5555 /* magic # on range info */ + +#ifdef RCHECK +#define RSLOP sizeof (u_short) +#else +#define RSLOP 0 +#endif + +/* + * nextf[i] is the pointer to the next free block of size 2^(i+3). The + * smallest allocatable block is 8 bytes. The overhead information + * precedes the data area returned to the user. + */ +#define NBUCKETS 30 +static union overhead *nextf[NBUCKETS]; +extern char *sbrk(); + +static int pagesz; /* page size */ +static int pagebucket; /* page size bucket */ +static semaphore malloc_lock = SEMAPHORE_CLEAR; + +#if defined(DEBUG) || defined(RCHECK) +#define ASSERT(p) if (!(p)) botch("p") +#include <stdio.h> +static +botch(s) + char *s; +{ + fprintf(stderr, "\r\nassertion botched: %s\r\n", s); + (void) fflush(stderr); /* just in case user buffered it */ + abort(); +} +#else +#define ASSERT(p) +#endif + +/* ========================================================================== + * morecore() + * + * Allocate more memory to the indicated bucket + */ +static inline void morecore(int bucket) +{ + register union overhead *op; + register int sz; /* size of desired block */ + int amt; /* amount to allocate */ + int nblks; /* how many blocks we get */ + + /* + * sbrk_size <= 0 only for big, FLUFFY, requests (about + * 2^30 bytes on a VAX, I think) or for a negative arg. + */ + sz = 1 << (bucket + 3); +#ifdef DEBUG + ASSERT(sz > 0); +#else + if (sz <= 0) + return; +#endif + if (sz < pagesz) { + amt = pagesz; + nblks = amt / sz; + } else { + amt = sz + pagesz; + nblks = 1; + } + op = (union overhead *)sbrk(amt); + /* no more room! */ + if ((int)op == -1) + return; + /* + * Add new memory allocated to that on + * free list for this hash bucket. + */ + nextf[bucket] = op; + while (--nblks > 0) { + op->ov_next = (union overhead *)((caddr_t)op + sz); + op = (union overhead *)((caddr_t)op + sz); + } +} + +/* ========================================================================== + * malloc() + */ +void *malloc(size_t nbytes) +{ + union overhead *op; + unsigned int amt; + int bucket, n; + semaphore *lock; + + lock = &malloc_lock; + while(SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + /* + * First time malloc is called, setup page size and + * align break pointer so all data will be page aligned. + */ + if (pagesz == 0) { + pagesz = n = getpagesize(); + op = (union overhead *)sbrk(0); + n = n - sizeof (*op) - ((int)op & (n - 1)); + if (n < 0) + n += pagesz; + if (n) { + if (sbrk(n) == (char *)-1) + return (NULL); + } + bucket = 0; + amt = 8; + while (pagesz > amt) { + amt <<= 1; + bucket++; + } + pagebucket = bucket; + } + /* + * Convert amount of memory requested into closest block size + * stored in hash buckets which satisfies request. + * Account for space used per block for accounting. + */ + if (nbytes <= (n = pagesz - sizeof (*op) - RSLOP)) { +#ifndef RCHECK + amt = 8; /* size of first bucket */ + bucket = 0; +#else + amt = 16; /* size of first bucket */ + bucket = 1; +#endif + n = -(sizeof (*op) + RSLOP); + } else { + amt = pagesz; + bucket = pagebucket; + } + while (nbytes > amt + n) { + amt <<= 1; + if (amt == 0) { + SEMAPHORE_RESET(lock); + return (NULL); + } + bucket++; + } + /* + * If nothing in hash bucket right now, + * request more memory from the system. + */ + if ((op = nextf[bucket]) == NULL) { + morecore(bucket); + if ((op = nextf[bucket]) == NULL) { + SEMAPHORE_RESET(lock); + return (NULL); + } + } + /* remove from linked list */ + nextf[bucket] = op->ov_next; + op->ov_magic = MAGIC; + op->ov_index = bucket; +#ifdef RCHECK + /* + * Record allocated size of block and + * bound space with magic numbers. + */ + op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); + op->ov_rmagic = RMAGIC; + *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; +#endif + SEMAPHORE_RESET(lock); + return ((char *)(op + 1)); +} + +/* ========================================================================== + * free() + */ +void free(void *cp) +{ + union overhead *op; + semaphore *lock; + int size; + + lock = &malloc_lock; + while(SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + if (cp == NULL) { + SEMAPHORE_RESET(lock); + return; + } + op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); +#ifdef DEBUG + ASSERT(op->ov_magic == MAGIC); /* make sure it was in use */ +#else + if (op->ov_magic != MAGIC) { + SEMAPHORE_RESET(lock); + return; /* sanity */ + } +#endif +#ifdef RCHECK + ASSERT(op->ov_rmagic == RMAGIC); + ASSERT(*(u_short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC); +#endif + size = op->ov_index; + ASSERT(size < NBUCKETS); + op->ov_next = nextf[size]; /* also clobbers ov_magic */ + nextf[size] = op; + + SEMAPHORE_RESET(lock); +} + +/* ========================================================================== + * realloc() + * + * Storage compaction is no longer supported, fix program and try again. + */ +void *realloc(void *cp, size_t nbytes) +{ + u_int onb; + int i; + semaphore *lock; + union overhead *op; + char *res; + + if (cp == NULL) + return (malloc(nbytes)); + op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); + + if (op->ov_magic == MAGIC) { + i = op->ov_index; + } else { + /* + * This will cause old programs using storage compaction feature of + * realloc to break in a pseudo resonable way that is easy to debug. + * Returning a malloced buffer without the copy may cause + * indeterministic behavior. + */ + return(NULL); + } + + lock = &malloc_lock; + while(SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + onb = 1 << (i + 3); + if (onb < pagesz) + onb -= sizeof (*op) + RSLOP; + else + onb += pagesz - sizeof (*op) - RSLOP; + + /* avoid the copy if same size block */ + if (i) { + i = 1 << (i + 2); + if (i < pagesz) + i -= sizeof (*op) + RSLOP; + else + i += pagesz - sizeof (*op) - RSLOP; + } + + if (nbytes <= onb && nbytes > i) { +#ifdef RCHECK + op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); + *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; +#endif + SEMAPHORE_RESET(lock); + return(cp); + } + SEMAPHORE_RESET(lock); + + if ((res = malloc(nbytes)) == NULL) { + free(cp); + return (NULL); + } + + bcopy(cp, res, (nbytes < onb) ? nbytes : onb); + free(cp); + + return (res); +} + diff --git a/lib/libpthread/pthreads/mutex.c b/lib/libpthread/pthreads/mutex.c new file mode 100644 index 00000000000..a269284ae2f --- /dev/null +++ b/lib/libpthread/pthreads/mutex.c @@ -0,0 +1,227 @@ +/* ==== mutex.c ============================================================ + * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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. + * + * Description : Mutex functions. + * + * 1.00 93/07/19 proven + * -Started coding this file. + */ + +#ifndef lint +static const char rcsid[] = "$Id: mutex.c,v 1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: mutex.c,v 1.16 1994/02/07 02:19:03 proven Exp $"; +#endif + +#include <pthread.h> +#include <errno.h> + +/* + * Basic mutex functionality + + * This is the basic lock order + * queue + * pthread + * global + * + * semaphore functionality is defined in machdep.h + */ + +/* ========================================================================== + * pthread_mutex_init() + * + * In this implementation I don't need to allocate memory. + * ENOMEM, EAGAIN should never be returned. Arch that have + * weird constraints may need special coding. + */ +int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *mutex_attr) +{ + /* Only check if attr specifies some mutex type other than fast */ + if ((mutex_attr) && (mutex_attr->m_type != MUTEX_TYPE_FAST)) { + if (mutex_attr->m_type >= MUTEX_TYPE_MAX) { + return(EINVAL); + } + if (mutex->m_flags & MUTEX_FLAGS_INITED) { + return(EBUSY); + } + mutex->m_type = mutex_attr->m_type; + } else { + mutex->m_type = MUTEX_TYPE_FAST; + } + /* Set all other paramaters */ + pthread_queue_init(&mutex->m_queue); + mutex->m_flags |= MUTEX_FLAGS_INITED; + mutex->m_lock = SEMAPHORE_CLEAR; + mutex->m_owner = NULL; + return(OK); +} + +/* ========================================================================== + * pthread_mutex_destroy() + */ +int pthread_mutex_destroy(pthread_mutex_t *mutex) +{ + /* Only check if mutex is of type other than fast */ + switch(mutex->m_type) { + case MUTEX_TYPE_FAST: + break; + case MUTEX_TYPE_STATIC_FAST: + default: + return(EINVAL); + break; + } + + /* Cleanup mutex, others might want to use it. */ + pthread_queue_init(&mutex->m_queue); + mutex->m_flags |= MUTEX_FLAGS_INITED; + mutex->m_lock = SEMAPHORE_CLEAR; + mutex->m_owner = NULL; + mutex->m_flags = 0; + return(OK); +} + +/* ========================================================================== + * pthread_mutex_trylock() + */ +int pthread_mutex_trylock(pthread_mutex_t *mutex) +{ + semaphore *lock; + int rval; + + lock = &(mutex->m_lock); + while (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + + switch (mutex->m_type) { + /* + * Fast mutexes do not check for any error conditions. + */ + case MUTEX_TYPE_FAST: + case MUTEX_TYPE_STATIC_FAST: + if (!mutex->m_owner) { + mutex->m_owner = pthread_run; + rval = OK; + } else { + rval = EBUSY; + } + break; + default: + rval = EINVAL; + break; + } + SEMAPHORE_RESET(lock); + return(rval); +} + +/* ========================================================================== + * pthread_mutex_lock() + */ +int pthread_mutex_lock(pthread_mutex_t *mutex) +{ + semaphore *lock, *plock; + int rval; + + lock = &(mutex->m_lock); + while (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + + switch (mutex->m_type) { + /* + * Fast mutexes do not check for any error conditions. + */ + case MUTEX_TYPE_FAST: + case MUTEX_TYPE_STATIC_FAST: + if (mutex->m_owner) { + plock = &(pthread_run->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + pthread_queue_enq(&mutex->m_queue, pthread_run); + SEMAPHORE_RESET(lock); + + /* Reschedule will unlock pthread_run */ + reschedule(PS_MUTEX_WAIT); + return(OK); + } + mutex->m_owner = pthread_run; + rval = OK; + break; + default: + rval = EINVAL; + break; + } + SEMAPHORE_RESET(lock); + return(rval); +} + +/* ========================================================================== + * pthread_mutex_unlock() + */ +int pthread_mutex_unlock(pthread_mutex_t *mutex) +{ + struct pthread *pthread; + semaphore *lock, *plock; + int rval; + + lock = &(mutex->m_lock); + while (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + + switch (mutex->m_type) { + /* + * Fast mutexes do not check for any error conditions. + */ + case MUTEX_TYPE_FAST: + case MUTEX_TYPE_STATIC_FAST: + if (pthread = pthread_queue_get(&mutex->m_queue)) { + plock = &(pthread->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + mutex->m_owner = pthread; + + /* Reset pthread state */ + pthread_queue_deq(&mutex->m_queue); + pthread->state = PS_RUNNING; + SEMAPHORE_RESET(plock); + } else { + mutex->m_owner = NULL; + } + rval = OK; + break; + default: + rval = EINVAL; + break; + } + SEMAPHORE_RESET(lock); + return(rval); +} diff --git a/lib/libpthread/pthreads/pthread.c b/lib/libpthread/pthreads/pthread.c new file mode 100644 index 00000000000..b16a14d67cb --- /dev/null +++ b/lib/libpthread/pthreads/pthread.c @@ -0,0 +1,204 @@ +/* ==== pthread.c ============================================================ + * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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. + * + * Description : Pthread functions. + * + * 1.00 93/07/26 proven + * -Started coding this file. + */ + +#ifndef lint +static const char rcsid[] = "$Id: pthread.c,v 1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: pthread.c,v 1.16 1994/02/07 02:19:06 proven Exp $"; +#endif + +#include "pthread.h" +#include <signal.h> +#include <errno.h> + +/* + * These first functions really should not be called by the user. + */ + +/* ========================================================================== + * pthread_init() + * + * This function should be called in crt0.o before main() is called. + * But on some systems It may not be possible to change crt0.o so currently + * I'm requiring this function to be called first thing after main. + * Actually I'm assuming it is, because I do no locking here. + */ +void pthread_init(void) +{ + struct machdep_pthread machdep_data = MACHDEP_PTHREAD_INIT; + + /* Initialize the first thread */ + if (pthread_initial = (pthread_t)malloc(sizeof(struct pthread))) { + memcpy(&(pthread_initial->machdep_data), &machdep_data, sizeof(machdep_data)); + pthread_initial->state = PS_RUNNING; + pthread_initial->queue = NULL; + pthread_initial->next = NULL; + pthread_initial->pll = NULL; + + pthread_initial->lock = SEMAPHORE_CLEAR; + pthread_initial->error = 0; + + pthread_link_list = pthread_initial; + pthread_run = pthread_initial; + + /* Initialize the signal handler. */ + sig_init(); + + /* Initialize the fd table. */ + fd_init(); + + return; + } + PANIC(); +} + +/* ========================================================================== + * pthread_yield() + */ +void pthread_yield() +{ + sig_handler_fake(SIGVTALRM); +} + +/* ======================================================================= */ +/* ========================================================================== + * pthread_self() + */ +pthread_t pthread_self() +{ + return(pthread_run); +} + +/* ========================================================================== + * pthread_equal() + */ +int pthread_equal(pthread_t t1, pthread_t t2) +{ + return(t1 == t2); +} + +/* ========================================================================== + * pthread_exit() + */ +void pthread_exit(void *status) +{ + semaphore *lock, *plock; + pthread_t pthread; + + lock = &pthread_run->lock; + if (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + + /* Save return value */ + pthread_run->ret = status; + + /* First execute all cleanup handlers */ + + + /* + * Are there any threads joined to this one, + * if so wake them and let them detach this thread. + */ + if (pthread = pthread_queue_get(&(pthread_run->join_queue))) { + /* The current thread pthread_run can't be detached */ + plock = &(pthread->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + (void)pthread_queue_deq(&(pthread_run->join_queue)); + pthread->state = PS_RUNNING; + + /* Thread will unlock itself in pthread_join() */ + } + + /* This thread will never run again */ + reschedule(PS_DEAD); + PANIC(); +} + +/* ========================================================================== + * pthread_create() + * + * After the new thread structure is allocated and set up, it is added to + * pthread_run_next_queue, which requires a sig_prevent(), + * sig_check_and_resume() + */ +int pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void * (*start_routine)(void *), void *arg) +{ + long nsec = 100000000; + void *stack; + + if ((*thread) = (pthread_t)malloc(sizeof(struct pthread))) { + + if (! attr) { attr = &pthread_default_attr; } + + /* Get a stack, if necessary */ + if ((stack = attr->stackaddr_attr) || + (stack = (void *)malloc(attr->stacksize_attr))) { + + machdep_pthread_create(&((*thread)->machdep_data), + start_routine, arg, 65536, stack, nsec); + + memcpy(&(*thread)->attr, attr, sizeof(pthread_attr_t)); + + (*thread)->queue = NULL; + (*thread)->next = NULL; + + (*thread)->lock = SEMAPHORE_CLEAR; + (*thread)->error = 0; + + sig_prevent(); + + /* Add to the link list of all threads. */ + (*thread)->pll = pthread_link_list; + pthread_link_list = (*thread); + + (*thread)->state = PS_RUNNING; + sig_check_and_resume(); + + return(OK); + } + free((*thread)); + } + return(ENOMEM); +} + +/* ========================================================================== + * pthread_cancel() + * + * This routine will also require a sig_prevent/sig_check_and_resume() + */ diff --git a/lib/libpthread/pthreads/pthread_attr.c b/lib/libpthread/pthreads/pthread_attr.c new file mode 100644 index 00000000000..87ebfced7a0 --- /dev/null +++ b/lib/libpthread/pthreads/pthread_attr.c @@ -0,0 +1,100 @@ +/* ==== pthread_attr.c ======================================================= + * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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. + * + * Description : Pthread attribute functions. + * + * 1.00 93/11/04 proven + * -Started coding this file. + */ + +#ifndef lint +static const char rcsid[] = "$Id: pthread_attr.c,v 1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: pthread_attr.c,v 1.16 1994/02/07 02:19:14 proven Exp $"; +#endif + +#include <pthread.h> +#include <errno.h> + +/* Currently we do no locking, should we just to be safe? CAP */ +/* ========================================================================== + * pthread_attr_init() + */ +int pthread_attr_init(pthread_attr_t *attr) +{ + memcpy(attr, &pthread_default_attr, sizeof(pthread_attr_t)); + return(OK); +} + +/* ========================================================================== + * pthread_attr_destroy() + */ +int pthread_attr_destroy(pthread_attr_t *attr) +{ + return(OK); +} + +/* ========================================================================== + * pthread_attr_getstacksize() + */ +int pthread_attr_getstacksize(pthread_attr_t *attr, size_t * stacksize) +{ + *stacksize = attr->stacksize_attr; + return(OK); +} + +/* ========================================================================== + * pthread_attr_setstacksize() + */ +int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) +{ + if (stacksize >= PTHREAD_STACK_MIN) { + attr->stacksize_attr = stacksize; + return(OK); + } + return(EINVAL); +} + +/* ========================================================================== + * pthread_attr_getstackaddr() + */ +int pthread_attr_getstackaddr(pthread_attr_t *attr, void ** stackaddr) +{ + *stackaddr = attr->stackaddr_attr; + return(OK); +} + +/* ========================================================================== + * pthread_attr_setstackaddr() + */ +int pthread_attr_setstackaddr(pthread_attr_t *attr, void * stackaddr) +{ + attr->stackaddr_attr = stackaddr; + return(OK); +} diff --git a/lib/libpthread/pthreads/pthread_detach.c b/lib/libpthread/pthreads/pthread_detach.c new file mode 100644 index 00000000000..37ac35de292 --- /dev/null +++ b/lib/libpthread/pthreads/pthread_detach.c @@ -0,0 +1,90 @@ +/* ==== pthread_detach.c ======================================================= + * Copyright (c) 1994 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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. + * + * Description : pthread_join function. + * + * 1.00 94/01/15 proven + * -Started coding this file. + */ + +#ifndef lint +static const char rcsid[] = "$Id: pthread_detach.c,v 1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: pthread_detach.c,v 1.16 1994/02/07 02:19:16 proven Exp $"; +#endif + +#include <pthread.h> + +/* ========================================================================== + * pthread_detach() + */ +int pthread_detach(pthread_t pthread) +{ + semaphore *plock; + int ret; + + plock = &(pthread->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + + /* Check that thread isn't detached already */ + if (!(pthread->flags & PF_DETACHED)) { + + pthread->flags |= PF_DETACHED; + + /* Wakeup first threads waiting on a join */ + { + struct pthread * next_thread; + semaphore * next_lock; + + if (next_thread = pthread_queue_get(&(pthread->join_queue))) { + next_lock = &(next_thread->lock); + while (SEMAPHORE_TEST_AND_SET(next_lock)) { + pthread_yield(); + } + pthread_queue_deq(&(pthread->join_queue)); + next_thread->state = PS_RUNNING; + /* + * Thread will wake up in pthread_join(), see the thread + * it was joined to already detached and unlock itself + * and pthread + */ + } else { + SEMAPHORE_RESET(plock); + } + } + ret = OK; + + } else { + SEMAPHORE_RESET(plock); + ret = ESRCH; + } + return(ret); +} diff --git a/lib/libpthread/pthreads/pthread_join.c b/lib/libpthread/pthreads/pthread_join.c new file mode 100644 index 00000000000..b94ce3a70ea --- /dev/null +++ b/lib/libpthread/pthreads/pthread_join.c @@ -0,0 +1,113 @@ +/* ==== pthread_join.c ======================================================= + * Copyright (c) 1994 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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. + * + * Description : pthread_join function. + * + * 1.00 94/01/15 proven + * -Started coding this file. + */ + +#ifndef lint +static const char rcsid[] = "$Id: pthread_join.c,v 1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: pthread_join.c,v 1.16 1994/02/07 02:19:19 proven Exp $"; +#endif + +#include <pthread.h> + +/* ========================================================================== + * pthread_join() + */ +int pthread_join(pthread_t pthread, void **thread_return) +{ + semaphore *lock, *plock; + int ret; + + + plock = &(pthread->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + + /* Check that thread isn't detached already */ + if (pthread->flags & PF_DETACHED) { + SEMAPHORE_RESET(plock); + return(ESRCH); + } + + lock = &(pthread_run->lock); + while (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + + /* If OK then queue current thread. */ + pthread_queue(&(pthread->join_queue), pthread_run); + + SEMAPHORE_RESET(plock); + reschedule(PS_JOIN); + + /* + * At this point the thread is locked from the pthread_exit + * and so are we, so no extra locking is required, but be sure + * to unlock at least ourself. + */ + if (!(pthread->flags & PF_DETACHED)) { + if (thread_return) { + *thread_return = pthread->ret; + } + pthread->flags |= PF_DETACHED; + ret = OK; + } else { + ret = ESRCH; + } + + /* Cant do a cleanup until queue is cleared */ + { + struct pthread * next_thread; + semaphore * next_lock; + + if (next_thread = pthread_queue_get(&(pthread->join_queue))) { + next_lock = &(next_thread->lock); + while (SEMAPHORE_TEST_AND_SET(next_lock)) { + pthread_yield(); + } + pthread_queue_deq(&(pthread->join_queue)); + next_thread->state = PS_RUNNING; + /* + * Thread will wake up in pthread_join(), see the thread + * it was joined to already detached and unlock itself + */ + } else { + SEMAPHORE_RESET(lock); + } + } + + SEMAPHORE_RESET(plock); + return(ret); +} diff --git a/lib/libpthread/pthreads/pthread_once.c b/lib/libpthread/pthreads/pthread_once.c new file mode 100644 index 00000000000..26a530971b0 --- /dev/null +++ b/lib/libpthread/pthreads/pthread_once.c @@ -0,0 +1,61 @@ +/* ==== pthread_once.c ======================================================= + * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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. + * + * Description : pthread_once function. + * + * 1.00 93/12/12 proven + * -Started coding this file. + */ + +#ifndef lint +static const char rcsid[] = "$Id: pthread_once.c,v 1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: pthread_once.c,v 1.4 1994/02/07 02:19:22 proven Exp $"; +#endif + +#include <pthread.h> + +/* ========================================================================== + * pthread_once() + */ +static pthread_mutex_t __pthread_once_mutex = PTHREAD_MUTEX_INITIALIZER; + +int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) +{ + /* Check first for speed */ + if (*once_control == PTHREAD_ONCE_INIT) { + pthread_mutex_lock(&__pthread_once_mutex); + if (*once_control == PTHREAD_ONCE_INIT) { + init_routine(); + (*once_control)++; + } + pthread_mutex_unlock(&__pthread_once_mutex); + } + return(OK); +} diff --git a/lib/libpthread/pthreads/queue.c b/lib/libpthread/pthreads/queue.c new file mode 100644 index 00000000000..dd662136c51 --- /dev/null +++ b/lib/libpthread/pthreads/queue.c @@ -0,0 +1,123 @@ +/* ==== queue.c ============================================================ + * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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. + * + * Description : Queue functions. + * + * 1.00 93/07/15 proven + * -Started coding this file. + */ + +#ifndef lint +static const char rcsid[] = "$Id: queue.c,v 1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: queue.c,v 1.16 1994/02/07 02:19:24 proven Exp $"; +#endif + +#include <pthread.h> + +/* + * All routines in this file assume that the queue has been appropriatly + * locked. + */ + +/* ========================================================================== + * pthread_queue_init() + */ +void pthread_queue_init(struct pthread_queue *queue) +{ + queue->q_next = NULL; + queue->q_last = NULL; + queue->q_data = NULL; +} + +/* ========================================================================== + * pthread_queue_enq() + */ +void pthread_queue_enq(struct pthread_queue *queue, struct pthread *thread) +{ + if (queue->q_last) { + queue->q_last->next = thread; + } else { + queue->q_next = thread; + } + queue->q_last = thread; + thread->queue = queue; + thread->next = NULL; + +} + +/* ========================================================================== + * pthread_queue_get() + */ +struct pthread *pthread_queue_get(struct pthread_queue *queue) +{ + return(queue->q_next); +} + +/* ========================================================================== + * pthread_queue_deq() + */ +struct pthread *pthread_queue_deq(struct pthread_queue *queue) +{ + struct pthread *thread = NULL; + + if (queue->q_next) { + thread = queue->q_next; + if (!(queue->q_next = queue->q_next->next)) { + queue->q_last = NULL; + } + thread->queue = NULL; + thread->next = NULL; + } + return(thread); +} + +/* ========================================================================== + * pthread_queue_remove() + */ +void pthread_queue_remove(struct pthread_queue *queue, struct pthread *thread) +{ + struct pthread **current = &(queue->q_next); + struct pthread *prev = NULL; + + while (*current) { + if (*current == thread) { + if ((*current)->next) { + *current = (*current)->next; + } else { + queue->q_last = prev; + *current = NULL; + } + } + prev = *current; + current = &((*current)->next); + } + thread->queue = NULL; + thread->next = NULL; +} diff --git a/lib/libpthread/pthreads/signal.c b/lib/libpthread/pthreads/signal.c new file mode 100644 index 00000000000..5bdbe6892d7 --- /dev/null +++ b/lib/libpthread/pthreads/signal.c @@ -0,0 +1,445 @@ +/* ==== signal.c ============================================================ + * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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. + * + * Description : Queue functions. + * + * 1.00 93/07/21 proven + * -Started coding this file. + */ + +#ifndef lint +static const char rcsid[] = "$Id: signal.c,v 1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: signal.c,v 1.18 1994/02/07 02:19:28 proven Exp $"; +#endif + +#include <pthread.h> +#include <signal.h> + +/* + * Time which select in fd_kern_wait() will sleep. + * If there are no threads to run we sleep for an hour or until + * we get an interrupt or an fd thats awakens. To make sure we + * don't miss an interrupt this variable gets reset too zero in + * sig_handler_real(). + */ +struct timeval __fd_kern_wait_timeout = { 0, 0 }; + +/* + * Global for user-kernel lock, and blocked signals + */ +static volatile sigset_t sig_to_tryagain; +static volatile sigset_t sig_to_process; +static volatile int kernel_lock = 0; +static volatile int sig_count = 0; + +static void sig_handler(int signal); +static void set_thread_timer(); +void sig_prevent(void); +void sig_resume(void); + +/* ========================================================================== + * context_switch() + * + * This routine saves the current state of the running thread gets + * the next thread to run and restores it's state. To allow different + * processors to work with this routine, I allow the machdep_restore_state() + * to either return or have it return from machdep_save_state with a value + * other than 0, this is for implementations which use setjmp/longjmp. + */ +static void context_switch() +{ + struct pthread **current, *next, *last; + semaphore *lock; + int count; + + /* save state of current thread */ + if (machdep_save_state()) { + return; + } + + last = pthread_run; + if (pthread_run = pthread_queue_deq(&pthread_current_queue)) { + /* restore state of new current thread */ + machdep_restore_state(); + return; + } + + /* Poll all the kernel fds */ + fd_kern_poll(); + +context_switch_reschedule:; + /* + * Go through the reschedule list once, this is the only place + * that goes through the queue without using the queue routines. + * + * But first delete the current queue. + */ + pthread_queue_init(&pthread_current_queue); + current = &(pthread_link_list); + count = 0; + + while (*current) { + switch((*current)->state) { + case PS_RUNNING: + pthread_queue_enq(&pthread_current_queue, *current); + current = &((*current)->pll); + count++; + break; + case PS_DEAD: + /* Cleanup thread, unless we're using the stack */ + if (((*current)->flags & PF_DETACHED) && (*current != last)) { + next = (*current)->pll; + lock = &((*current)->lock); + if (SEMAPHORE_TEST_AND_SET(lock)) { + /* Couldn't cleanup this time, try again later */ + current = &((*current)->pll); + } else { + if (!((*current)->attr.stackaddr_attr)) { + free (machdep_pthread_cleanup(&((*current)->machdep_data))); + } + free (*current); + *current = next; + } + } else { + current = &((*current)->pll); + } + break; + default: + /* Should be on a different queue. Ignore. */ + current = &((*current)->pll); + count++; + break; + } + } + + /* Are there any threads to run */ + if (pthread_run = pthread_queue_deq(&pthread_current_queue)) { + /* restore state of new current thread */ + machdep_restore_state(); + return; + } + + /* Are there any threads at all */ + if (count) { + /* + * Do a wait, timeout is set to a hour unless we get an interrupt + * before the select in wich case it polls and returns. + */ + fd_kern_wait(); + + /* Check for interrupts, but ignore SIGVTALR */ + sigdelset(&sig_to_process, SIGVTALRM); + + if (sig_to_process) { + /* Process interrupts */ + sig_handler(0); + } + + goto context_switch_reschedule; + + } + exit(0); +} + +/* ========================================================================== + * sig_handler_pause() + * + * Wait until a signal is sent to the process. + */ +void sig_handler_pause() +{ + sigset_t sig_to_block, sig_to_pause; + + sigfillset(&sig_to_block); + sigemptyset(&sig_to_pause); + sigprocmask(SIG_BLOCK, &sig_to_block, NULL); + if (!sig_to_process) { + sigsuspend(&sig_to_pause); + } + sigprocmask(SIG_UNBLOCK, &sig_to_block, NULL); +} + +/* ========================================================================== + * context_switch_done() + * + * This routine does all the things that are necessary after a context_switch() + * calls the machdep_restore_state(). DO NOT put this in the context_switch() + * routine because sometimes the machdep_restore_state() doesn't return + * to context_switch() but instead ends up in machdep_thread_start() or + * some such routine, which will need to call this routine and + * sig_check_and_resume(). + */ +void context_switch_done() +{ + sigdelset(&sig_to_process, SIGVTALRM); + set_thread_timer(); +} + +/* ========================================================================== + * set_thread_timer() + * + * Assums kernel is locked. + */ +static void set_thread_timer() +{ + static int last_sched_attr = SCHED_RR; + + switch (pthread_run->attr.sched_attr) { + case SCHED_RR: + machdep_set_thread_timer(&(pthread_run->machdep_data)); + break; + case SCHED_FIFO: + if (last_sched_attr != SCHED_FIFO) { + machdep_unset_thread_timer(); + } + break; + case SCHED_IO: + if ((last_sched_attr != SCHED_IO) && (!sig_count)) { + machdep_set_thread_timer(&(pthread_run->machdep_data)); + } + break; + default: + machdep_set_thread_timer(&(pthread_run->machdep_data)); + break; + } + last_sched_attr = pthread_run->attr.sched_attr; +} + +/* ========================================================================== + * sig_handler() + * + * Assumes the kernel is locked. + */ +static void sig_handler(int sig) +{ + + /* + * First check for old signals, do one pass through and don't + * check any twice. + */ + if (sig_to_tryagain) { + if (sigismember(&sig_to_tryagain, SIGALRM)) { + switch (sleep_wakeup()) { + case 1: + /* Do the default action, no threads were sleeping */ + case OK: + /* Woke up a sleeping thread */ + sigdelset(&sig_to_tryagain, SIGALRM); + break; + case NOTOK: + /* Couldn't get appropriate locks, try again later */ + break; + } + } else { + PANIC(); + } + } + + /* + * NOW, process signal that just came in, plus any pending on the + * signal mask. All of these must be resolved. + */ + +sig_handler_top:; + + switch(sig) { + case 0: + break; + case SIGVTALRM: + if (sig_count) { + sigset_t sigall; + + sig_count = 0; + + /* Unblock all signals */ + sigemptyset(&sigall); + sigprocmask(SIG_SETMASK, &sigall, NULL); + } + context_switch(); + context_switch_done(); + break; + case SIGALRM: + sigdelset(&sig_to_process, SIGALRM); + switch (sleep_wakeup()) { + case 1: + /* Do the default action, no threads were sleeping */ + case OK: + /* Woke up a sleeping thread */ + break; + case NOTOK: + /* Couldn't get appropriate locks, try again later */ + sigaddset(&sig_to_tryagain, SIGALRM); + break; + } + break; + default: + PANIC(); + } + + /* Determine if there are any other signals */ + if (sig_to_process) { + for (sig = 1; sig <= SIGMAX; sig++) { + if (sigismember(&sig_to_process, sig)) { + + /* goto sig_handler_top */ + goto sig_handler_top; + } + } + } +} + +/* ========================================================================== + * sig_handler_real() + * + * On a multi-processor this would need to use the test and set instruction + * otherwise the following will work. + */ +void sig_handler_real(int sig) +{ + if (kernel_lock) { + __fd_kern_wait_timeout.tv_sec = 0; + sigaddset(&sig_to_process, sig); + return; + } + sig_prevent(); + sig_count++; + sig_handler(sig); + sig_resume(); +} + +/* ========================================================================== + * sig_handler_fake() + */ +void sig_handler_fake(int sig) +{ + if (kernel_lock) { + /* Currently this should be impossible */ + PANIC(); + } + sig_prevent(); + sig_handler(sig); + sig_resume(); +} + +/* ========================================================================== + * reschedule() + * + * This routine assumes that the caller is the current pthread, pthread_run + * and that it has a lock on itself and that it wants to reschedule itself. + */ +void reschedule(enum pthread_state state) +{ + semaphore *plock; + + if (kernel_lock) { + /* Currently this should be impossible */ + PANIC(); + } + sig_prevent(); + pthread_run->state = state; + SEMAPHORE_RESET((plock = &(pthread_run->lock))); + sig_handler(SIGVTALRM); + sig_resume(); +} + +/* ========================================================================== + * sig_prevent() + */ +void sig_prevent(void) +{ + kernel_lock++; +} + +/* ========================================================================== + * sig_resume() + */ +void sig_resume() +{ + kernel_lock--; +} + +/* ========================================================================== + * sig_check_and_resume() + */ +void sig_check_and_resume() +{ + /* Some routine name that is yet to be determined. */ + + /* Only bother if we are truely unlocking the kernel */ + while (!(--kernel_lock)) { + + /* Assume sigset_t is not a struct or union */ + if (sig_to_process) { + kernel_lock++; + sig_handler(0); + } else { + break; + } + } +} + +/* ========================================================================== + * sig_init() + * + * SIGVTALRM (NOT POSIX) needed for thread timeslice timeouts. + * Since it's not POSIX I will replace it with a + * virtual timer for threads. + * SIGALRM (IS POSIX) so some special handling will be + * necessary to fake SIGALRM signals + */ +void sig_init(void) +{ + int sig_to_init[] = { SIGVTALRM, SIGALRM, 0 }; + +#if defined(SA_RESTART) + struct sigaction act; +#endif + + int i; + +#if defined(SA_RESTART) + act.sa_handler = sig_handler_real; + sigemptyset(&(act.sa_mask)); + act.sa_flags = SA_RESTART; +#endif + + /* Initialize only the necessary signals */ + for (i = 0; sig_to_init[i]; i++) { + +#if defined(SA_RESTART) + if (sigaction(sig_to_init[i], &act, NULL)) { +#else + if (signal(sig_to_init[i], sig_handler_real)) { +#endif + PANIC(); + } + } +} + diff --git a/lib/libpthread/pthreads/sleep.c b/lib/libpthread/pthreads/sleep.c new file mode 100644 index 00000000000..1b76f26391f --- /dev/null +++ b/lib/libpthread/pthreads/sleep.c @@ -0,0 +1,256 @@ +/* ==== sleep.c ============================================================ + * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu + * 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 Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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. + * + * Description : Condition cariable functions. + * + * 1.00 93/12/28 proven + * -Started coding this file. + */ + +#ifndef lint +static const char rcsid[] = "$Id: sleep.c,v 1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: sleep.c,v 1.18 1994/02/07 02:19:31 proven Exp $"; +#endif + +#include <pthread.h> +#include <unistd.h> + +struct pthread * pthread_sleep = NULL; +semaphore sleep_semaphore = SEMAPHORE_CLEAR; + + +#include <sys/time.h> +#include <stdio.h> + +/* ========================================================================== + * machdep_start_timer() + */ +int machdep_start_timer(struct itimerval *start_time_val) +{ + setitimer(ITIMER_REAL, start_time_val, NULL); + return(OK); +} + +/* ========================================================================== + * machdep_stop_timer() + */ +struct itimerval stop_time_val = { { 0, 0 }, { 0, 0 } }; +int machdep_stop_timer(struct itimerval * current) +{ + setitimer(ITIMER_REAL, &stop_time_val, current); + return(OK); +} + +/* ========================================================================== + * machdep_sub_timer() + * + * formula is: new -= current; + */ +static inline void machdep_sub_timer(struct itimerval * new, + struct itimerval * current) +{ + new->it_value.tv_usec -= current->it_value.tv_usec; + if (new->it_value.tv_usec < 0) { + new->it_value.tv_usec += 1000000; + new->it_value.tv_sec--; + } + new->it_value.tv_sec -= current->it_value.tv_sec; +} + + +/* ========================================================================== + * sleep_basic_wakeup() + * + * The real work of sleep_wakeup is done here. + */ +static inline int sleep_basic_wakeup() +{ + struct pthread *pthread_sleep_next; + struct itimerval current_time; + semaphore *plock; + + machdep_stop_timer(¤t_time); + do { + plock = &(pthread_sleep->lock); + if (SEMAPHORE_TEST_AND_SET(plock)) { + return(NOTOK); + } + + /* return remaining time */ + pthread_sleep->time_sec = current_time.it_value.tv_sec; + pthread_sleep->time_usec = current_time.it_value.tv_usec; + + if (pthread_sleep_next = pthread_sleep->sll) { + pthread_sleep_next->time_usec += current_time.it_value.tv_usec; + current_time.it_value.tv_usec = pthread_sleep_next->time_usec; + pthread_sleep_next->time_sec += current_time.it_value.tv_sec; + current_time.it_value.tv_sec = pthread_sleep_next->time_sec; + } + + /* Clean up removed thread and start it runnng again. */ + pthread_sleep->state = PS_RUNNING; + pthread_sleep->sll = NULL; + SEMAPHORE_RESET(plock); + + /* Set top of queue to next queue item */ + pthread_sleep = pthread_sleep_next; + + if (current_time.it_value.tv_sec || current_time.it_value.tv_usec) { + machdep_start_timer(¤t_time); + break; + } + + } while(pthread_sleep); + return(OK); +} + +/* ========================================================================== + * sleep_wakeup() + * + * This routine is called by the interrupt handler. It cannot call + * pthread_yield() thenrfore it returns NOTOK to inform the handler + * that it will have to be called at a later time. + */ +int sleep_wakeup() +{ + semaphore *lock, *plock; + int ret; + + /* Lock sleep queue */ + lock = &(sleep_semaphore); + if (SEMAPHORE_TEST_AND_SET(lock)) { + return(NOTOK); + } + + if (pthread_sleep) { + ret = sleep_basic_wakeup(); + } else { + ret = NOTOK; + } + + SEMAPHORE_RESET(lock); + return(ret); +} + +/* ========================================================================== + * sleep() + */ +unsigned int sleep(unsigned int seconds) +{ + struct pthread *pthread_sleep_current, *pthread_sleep_prev; + struct itimerval current_time, new_time; + semaphore *lock, *plock; + + if (seconds) { + /* Lock current thread */ + plock = &(pthread_run->lock); + while (SEMAPHORE_TEST_AND_SET(plock)) { + pthread_yield(); + } + + /* Set new_time timer value */ + new_time.it_value.tv_usec = 0; + new_time.it_value.tv_sec = seconds; + new_time.it_interval.tv_usec = 0; + new_time.it_interval.tv_sec = 0; + + /* Lock sleep queue */ + lock = &(sleep_semaphore); + while (SEMAPHORE_TEST_AND_SET(lock)) { + pthread_yield(); + } + + /* any threads? */ + if (pthread_sleep_current = pthread_sleep) { + + machdep_stop_timer(¤t_time); + + /* Is remaining time left <= new thread time */ + if (current_time.it_value.tv_sec <= new_time.it_value.tv_sec) { + machdep_sub_timer(&new_time, ¤t_time); + machdep_start_timer(¤t_time); + + while (pthread_sleep_current->sll) { + pthread_sleep_prev = pthread_sleep_current; + pthread_sleep_current = pthread_sleep_current->sll; + current_time.it_value.tv_sec = pthread_sleep_current->time_sec; + + if ((current_time.it_value.tv_sec > new_time.it_value.tv_sec) || + ((current_time.it_value.tv_sec == new_time.it_value.tv_sec) && + (current_time.it_value.tv_usec > new_time.it_value.tv_usec))) { + pthread_run->time_usec = new_time.it_value.tv_usec; + pthread_run->time_sec = new_time.it_value.tv_sec; + machdep_sub_timer(¤t_time, &new_time); + pthread_run->sll = pthread_sleep_current; + pthread_sleep_prev->sll = pthread_run; + + /* Unlock sleep mutex */ + SEMAPHORE_RESET(lock); + + /* Reschedule thread */ + reschedule(PS_SLEEP_WAIT); + + return(pthread_run->time_sec); + } + machdep_sub_timer(&new_time, ¤t_time); + + } + + /* No more threads in queue, attach pthread_run to end of list */ + pthread_sleep_current->sll = pthread_run; + pthread_run->sll = NULL; + + } else { + /* Start timer and enqueue thread */ + machdep_start_timer(&new_time); + machdep_sub_timer(¤t_time, &new_time); + pthread_run->sll = pthread_sleep_current; + pthread_sleep = pthread_run; + } + } else { + /* Start timer and enqueue thread */ + machdep_start_timer(&new_time); + pthread_sleep = pthread_run; + pthread_run->sll = NULL; + } + + pthread_run->time_usec = new_time.it_value.tv_usec; + pthread_run->time_sec = new_time.it_value.tv_sec; + + /* Unlock sleep mutex */ + SEMAPHORE_RESET(lock); + + /* Reschedule thread */ + reschedule(PS_SLEEP_WAIT); + + } + return(pthread_run->time_sec); +} + diff --git a/lib/libpthread/stdio/Makefile.inc b/lib/libpthread/stdio/Makefile.inc new file mode 100644 index 00000000000..ff13440c8d0 --- /dev/null +++ b/lib/libpthread/stdio/Makefile.inc @@ -0,0 +1,18 @@ +# from: @(#)Makefile.inc 5.7 (Berkeley) 6/27/91 +# $Id: Makefile.inc,v 1.1 1995/10/18 08:43:05 deraadt Exp $ + +# Thread safe stdio sources +.PATH: ${.CURDIR}/stdio + +SRCS+= clrerr.c fclose.c fdopen.c feof.c ferror.c fflush.c fgetc.c \ + fgetline.c fgetpos.c fgets.c fileno.c findfp.c flags.c fopen.c \ + fprintf.c fpurge.c fputc.c fputs.c fread.c freopen.c fscanf.c \ + fseek.c fsetpos.c ftell.c funopen.c fvwrite.c fwalk.c fwrite.c \ + getc.c getchar.c gets.c getw.c makebuf.c perror.c printf.c putc.c \ + putchar.c puts.c putw.c refill.c remove.c rewind.c rget.c scanf.c \ + setbuf.c setbuffer.c setvbuf.c snprintf.c sprintf.c sscanf.c \ + stdio.c tempnam.c tmpfile.c tmpnam.c ungetc.c vfprintf.c \ + vfscanf.c vprintf.c vscanf.c vsnprintf.c vsprintf.c vsscanf.c \ + wsetup.c putc_unlocked.c putchar_unlocked.c getc_unlocked.c \ + getchar_unlocked.c strerror.c wbuf.c + diff --git a/lib/libpthread/stdio/README b/lib/libpthread/stdio/README new file mode 100644 index 00000000000..017f61f1b46 --- /dev/null +++ b/lib/libpthread/stdio/README @@ -0,0 +1,40 @@ +This is a threadsafe stdio based on the BSD stdio written by Chris Torek. + +INCLUDE FILES AND PORTING +To continue to make this package portable, some basic rules on includes +files must be followed. + +pthread.h should be included first (if it is to be included). +stdio.h should be included. + +INTERNAL LOCKING +1. All functions that can be called by the user must have __flockfile at the + begining and a __funlockfile at the end. __Flockfile is a counting mutex, + The thread that owns the lock can call __flockfile as many times as + it wants, but must call an equal number of __funlockfile before the + lock will be released. +2. All functions starting with __ shouldn't need addtional locking. +3. Anything that writes the variable __sglue should lock __sfp_mutex, + check __sfp_state, and do a condion wait if it is set. +4. Anything that checks fp->_flag for valididity should also lock + __sfp_mutex. +5. Anything that reads the variable __sglue should lock __sfp_mutex, increment + __sfp_state, and then unlock the mutex. At function return it should + lock the mutex again decrement __sfp_state and check if zero. If so + do a cond_signal, and unlock the mutex. +6. The functions fopen, fdopen, and freopen are the only functions that + will change a fp->_file +7. fdopen and fopen both allocate the next fp by locking __sfp_mutex + checking fp->_flags and then setting it if free. +8. freopen tries to preserve fp->_file. It sets __sfp_mutex, then it + tries to lock fp->_file and close it. +9. __sinit is done with a pthread_once routine. + +Copyright (c) 1993 Chris Provenzano. All rights reserved. + +This product includes software developed by the Univeristy of California, +Berkeley and its contributors. + + +Things to do. +Fix printf so it uses the ininf function. diff --git a/lib/libpthread/stdio/clrerr.c b/lib/libpthread/stdio/clrerr.c new file mode 100644 index 00000000000..5989b6484b9 --- /dev/null +++ b/lib/libpthread/stdio/clrerr.c @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)clrerr.c 5.3 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: clrerr.c,v 1.1 1995/10/18 08:43:06 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> + +void clearerr(FILE *fp) +{ + flockfile(fp); + fp->_flags &= ~(__SERR|__SEOF); + funlockfile(fp); +} diff --git a/lib/libpthread/stdio/fclose.c b/lib/libpthread/stdio/fclose.c new file mode 100644 index 00000000000..538e0db8a35 --- /dev/null +++ b/lib/libpthread/stdio/fclose.c @@ -0,0 +1,71 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)fclose.c 5.2 (Berkeley) 2/1/91";*/ +static char *rcsid = "$Id: fclose.c,v 1.1 1995/10/18 08:43:06 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include "local.h" + +/* Do not reset the fd */ +fclose(fp) + register FILE *fp; +{ + register int r; + + if (fp->_flags) { + flockfile(fp); + r = fp->_flags & __SWR ? __sflush(fp) : 0; + if (__sclose(fp) < 0) + r = EOF; + if (fp->_flags & __SMBF) + free((char *)fp->_bf._base); + if (HASUB(fp)) + FREEUB(fp); + if (HASLB(fp)) + FREELB(fp); + fp->_flags = 0; /* release this FILE for reuse, DO THIS LAST */ + funlockfile(fp); + return(r); + } + errno = EBADF; + return(EOF); +} diff --git a/lib/libpthread/stdio/fdopen.c b/lib/libpthread/stdio/fdopen.c new file mode 100644 index 00000000000..8d860bbeac2 --- /dev/null +++ b/lib/libpthread/stdio/fdopen.c @@ -0,0 +1,92 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)fdopen.c 5.6 (Berkeley) 2/24/91";*/ +static char *rcsid = "$Id: fdopen.c,v 1.1 1995/10/18 08:43:06 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <sys/types.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <errno.h> +#include "local.h" + +extern pthread_mutex_t __sfp_mutex; +extern pthread_cond_t __sfp_cond; +extern int __sfp_state; + +FILE *fdopen(int fd, const char *mode) +{ + register FILE *fp; + int flags, oflags, fdflags, tmp; + + if ((flags = __sflags(mode, &oflags)) == 0) + return (NULL); + + /* Make sure the mode the user wants is a subset of the actual mode. */ + if ((fdflags = fcntl(fd, F_GETFL, 0)) < 0) + return (NULL); + tmp = fdflags & O_ACCMODE; + if (tmp != O_RDWR && (tmp != (oflags & O_ACCMODE))) { + errno = EINVAL; + return (NULL); + } + + pthread_once(&__sdidinit, __sinit); + pthread_mutex_lock(&__sfp_mutex); + while (__sfp_state) { + pthread_cond_wait(&__sfp_cond, &__sfp_mutex); + } + + if (fp = __sfp()) { + fp->_flags = flags; + + /* + * If opened for appending, but underlying descriptor does not have + * O_APPEND bit set, assert __SAPP so that __swrite() will lseek to + * end before each write. + */ + if ((oflags & O_APPEND) && !(fdflags & O_APPEND)) + fp->_flags |= __SAPP; + fp->_file = fd; + + } + pthread_mutex_unlock(&__sfp_mutex); + return (fp); +} diff --git a/lib/libpthread/stdio/feof.c b/lib/libpthread/stdio/feof.c new file mode 100644 index 00000000000..53e09f5ea50 --- /dev/null +++ b/lib/libpthread/stdio/feof.c @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)feof.c 5.1 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: feof.c,v 1.1 1995/10/18 08:43:06 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> + +/* + * A subroutine version of the macro feof. + */ +#undef feof + +feof(fp) + FILE *fp; +{ + return (__sfeof(fp)); +} diff --git a/lib/libpthread/stdio/ferror.c b/lib/libpthread/stdio/ferror.c new file mode 100644 index 00000000000..7e12f1d6a87 --- /dev/null +++ b/lib/libpthread/stdio/ferror.c @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)ferror.c 5.1 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: ferror.c,v 1.1 1995/10/18 08:43:06 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> + +/* + * A subroutine version of the macro ferror. + */ +#undef ferror + +ferror(fp) + FILE *fp; +{ + return (__sferror(fp)); +} diff --git a/lib/libpthread/stdio/fflush.c b/lib/libpthread/stdio/fflush.c new file mode 100644 index 00000000000..5e9f72c05ed --- /dev/null +++ b/lib/libpthread/stdio/fflush.c @@ -0,0 +1,97 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)fflush.c 5.1 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: fflush.c,v 1.1 1995/10/18 08:43:06 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <sys/errno.h> +#include <stdio.h> +#include "local.h" + +/* Flush a single file, or (if fp is NULL) all files. */ +fflush(fp) + register FILE *fp; +{ + int retval; + + if (fp == NULL) + return (__swalk_sflush); + flockfile(fp); + + if ((fp->_flags & (__SWR | __SRW)) == 0) { + errno = EBADF; + retval = EOF; + } else { + retval = __sflush(fp); + } + funlockfile(fp); + return(retval); +} + +__sflush(fp) + register FILE *fp; +{ + register unsigned char *p; + register int n, t; + + t = fp->_flags; + if ((t & __SWR) == 0) + return (0); + + if ((p = fp->_bf._base) == NULL) + return (0); + + n = fp->_p - p; /* write this much */ + + /* + * Set these immediately to avoid problems with longjmp and to allow + * exchange buffering (via setvbuf) in user write function. + */ + fp->_p = p; + fp->_w = t & (__SLBF|__SNBF) ? 0 : fp->_bf._size; + + for (; n > 0; n -= t, p += t) { + t = __swrite(fp, (char *)p, n); + if (t <= 0) { + fp->_flags |= __SERR; + return (EOF); + } + } + return (0); +} diff --git a/lib/libpthread/stdio/fgetc.c b/lib/libpthread/stdio/fgetc.c new file mode 100644 index 00000000000..382aac0602f --- /dev/null +++ b/lib/libpthread/stdio/fgetc.c @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)fgetc.c 5.3 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: fgetc.c,v 1.1 1995/10/18 08:43:06 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> + +fgetc(fp) + FILE *fp; +{ + flockfile(fp); + return (__sgetc(fp)); + funlockfile(fp); +} diff --git a/lib/libpthread/stdio/fgetline.c b/lib/libpthread/stdio/fgetline.c new file mode 100644 index 00000000000..320b306e745 --- /dev/null +++ b/lib/libpthread/stdio/fgetline.c @@ -0,0 +1,169 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)fgetline.c 5.2 (Berkeley) 5/4/91";*/ +static char *rcsid = "$Id: fgetline.c,v 1.1 1995/10/18 08:43:06 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "local.h" + +/* + * Expand the line buffer. Return -1 on error. + * The `new size' does not account for a terminating '\0', + * so we add 1 here. + */ +__slbexpand(fp, newsize) + FILE *fp; + size_t newsize; +{ + void *p; + + if (fp->_lb._size >= ++newsize) + return (0); + if ((p = realloc(fp->_lb._base, newsize)) == NULL) + return (-1); + fp->_lb._base = p; + fp->_lb._size = newsize; + return (0); +} + +/* + * Get an input line. The returned pointer often (but not always) + * points into a stdio buffer. Fgetline smashes the newline (if any) + * in the stdio buffer; callers must not use it on streams that + * have `magic' setvbuf() games happening. + */ +char * +fgetline(fp, lenp) + register FILE *fp; + size_t *lenp; +{ + register unsigned char *p; + register size_t len; + size_t off; + + flockfile(fp); + + /* make sure there is input */ + if (fp->_r <= 0 && __srefill(fp)) { + if (lenp != NULL) + *lenp = 0; + funlockfile(fp); + return (NULL); + } + + /* look for a newline in the input */ + if ((p = memchr((void *)fp->_p, '\n', fp->_r)) != NULL) { + register char *ret; + + /* + * Found one. Flag buffer as modified to keep + * fseek from `optimising' a backward seek, since + * the newline is about to be trashed. (We should + * be able to get away with doing this only if + * p is not pointing into an ungetc buffer, since + * fseek discards ungetc data, but this is the + * usual case anyway.) + */ + ret = (char *)fp->_p; + len = p - fp->_p; + fp->_flags |= __SMOD; + *p = 0; + fp->_r -= len + 1; + fp->_p = p + 1; + if (lenp != NULL) + *lenp = len; + funlockfile(fp); + return (ret); + } + + /* + * We have to copy the current buffered data to the line buffer. + * + * OPTIMISTIC is length that we (optimistically) + * expect will accomodate the `rest' of the string, + * on each trip through the loop below. + */ +#define OPTIMISTIC 80 + + for (len = fp->_r, off = 0;; len += fp->_r) { + register size_t diff; + + /* + * Make sure there is room for more bytes. + * Copy data from file buffer to line buffer, + * refill file and look for newline. The + * loop stops only when we find a newline. + */ + if (__slbexpand(fp, len + OPTIMISTIC)) + goto error; + (void) bcopy((void *)fp->_p, (void *)(fp->_lb._base + off), + len - off); + off = len; + if (__srefill(fp)) + break; /* EOF or error: return partial line */ + if ((p = memchr((void *)fp->_p, '\n', fp->_r)) == NULL) + continue; + + /* got it: finish up the line (like code above) */ + fp->_flags |= __SMOD; /* soon */ + diff = p - fp->_p; + len += diff; + if (__slbexpand(fp, len)) + goto error; + (void) bcopy((void *)fp->_p, (void *)(fp->_lb._base + off), diff); + fp->_r -= diff + 1; + fp->_p = p + 1; + break; + } + if (lenp != NULL) + *lenp = len; + fp->_lb._base[len] = 0; + + funlockfile(fp); + return ((char *)fp->_lb._base); + +error: + if (lenp != NULL) + *lenp = 0; /* ??? */ + funlockfile(fp); + return (NULL); /* ??? */ +} diff --git a/lib/libpthread/stdio/fgetpos.c b/lib/libpthread/stdio/fgetpos.c new file mode 100644 index 00000000000..752db946cd8 --- /dev/null +++ b/lib/libpthread/stdio/fgetpos.c @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)fgetpos.c 5.1 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: fgetpos.c,v 1.1 1995/10/18 08:43:06 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> + +/* Don't bother locking, ftell does it */ +fgetpos(fp, pos) + FILE *fp; + fpos_t *pos; +{ + return ((*pos = ftell(fp)) == (fpos_t)-1); +} diff --git a/lib/libpthread/stdio/fgets.c b/lib/libpthread/stdio/fgets.c new file mode 100644 index 00000000000..7c00b6bdae8 --- /dev/null +++ b/lib/libpthread/stdio/fgets.c @@ -0,0 +1,108 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)fgets.c 5.4 (Berkeley) 5/4/91";*/ +static char *rcsid = "$Id: fgets.c,v 1.1 1995/10/18 08:43:06 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> +#include <string.h> + +/* + * Read at most n-1 characters from the given file. + * Stop when a newline has been read, or the count runs out. + * Return first argument, or NULL if no characters were read. + */ +char * +fgets(buf, n, fp) + char *buf; + register size_t n; + register FILE *fp; +{ + register size_t len; + register char *s; + register unsigned char *p, *t; + + if (n < 2) /* sanity check */ + return (NULL); + + flockfile(fp); + s = buf; + n--; /* leave space for NUL */ + do { + /* + * If the buffer is empty, refill it. + */ + if ((len = fp->_r) <= 0) { + if (__srefill(fp)) { + /* EOF/error: stop with partial or no line */ + if (s == buf) + buf = NULL; + break; + } + len = fp->_r; + } + p = fp->_p; + + /* + * Scan through at most n bytes of the current buffer, + * looking for '\n'. If found, copy up to and including + * newline, and stop. Otherwise, copy entire chunk + * and loop. + */ + if (len > n) + len = n; + t = memchr((void *)p, '\n', len); + if (t != NULL) { + len = ++t - p; + fp->_r -= len; + fp->_p = t; + (void) bcopy((void *)p, (void *)s, len); + s += len; + break; + } + fp->_r -= len; + fp->_p += len; + (void) bcopy((void *)p, (void *)s, len); + s += len; + } while ((n -= len) != 0); + + *s = 0; + funlockfile(fp); + return (buf); +} diff --git a/lib/libpthread/stdio/fileno.c b/lib/libpthread/stdio/fileno.c new file mode 100644 index 00000000000..e4f08c105d8 --- /dev/null +++ b/lib/libpthread/stdio/fileno.c @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)fileno.c 5.1 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: fileno.c,v 1.1 1995/10/18 08:43:06 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> + +/* + * A subroutine version of the macro fileno. + */ +#undef fileno + +fileno(fp) + FILE *fp; +{ + return (__sfileno(fp)); +} diff --git a/lib/libpthread/stdio/findfp.c b/lib/libpthread/stdio/findfp.c new file mode 100644 index 00000000000..dc1045bc3ff --- /dev/null +++ b/lib/libpthread/stdio/findfp.c @@ -0,0 +1,151 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)findfp.c 5.10 (Berkeley) 2/24/91";*/ +static char *rcsid = "$Id: findfp.c,v 1.1 1995/10/18 08:43:06 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <posix.h> +#include "local.h" +#include "glue.h" + + +#define NSTATIC 20 /* stdin + stdout + stderr + the usual */ +#define NDYNAMIC 10 /* add ten more whenever necessary */ + +#define std(flags, file) \ + {0,0,0,flags,file,{0},0 } +/* p r w flags file _bf z */ + +static FILE usual[NSTATIC - 3]; /* the usual */ +static struct glue uglue = { 0, NSTATIC - 3, usual }; + +FILE __sF[3] = { + std(__SRD, 0), /* stdin */ + std(__SWR, 1), /* stdout */ + std(__SWR|__SNBF, 2) /* stderr */ +}; +struct glue __sglue = { &uglue, 3, __sF }; + +pthread_mutex_t __sfp_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t __sfp_cond = PTHREAD_COND_INITIALIZER; +pthread_once_t __sdidinit = PTHREAD_ONCE_INIT; +/* + * __sfp_state = 0, when free, > 0 when in _fwalk + * This allows multiple readers in _fwalk, but only one writer __sfp, + * or freopen() at a time. + */ +int __sfp_state = 0; + +static struct glue *moreglue(register int n) +{ + register struct glue *g; + register FILE *p; + static FILE empty; + + g = (struct glue *)malloc(sizeof(*g) + n * sizeof(FILE)); + if (g == NULL) + return (NULL); + p = (FILE *)(g + 1); + g->next = NULL; + g->niobs = n; + g->iobs = p; + while (--n >= 0) + *p++ = empty; + return (g); +} + +/* + * Find a free FILE for fopen et al. + */ +FILE *__sfp() +{ + register FILE *fp; + register int n; + register struct glue *g; + + for (g = &__sglue;; g = g->next) { + for (fp = g->iobs, n = g->niobs; --n >= 0; fp++) + if (fp->_flags == 0) { + fp->_flags = 1; /* reserve this slot; caller sets real flags */ + fp->_p = NULL; /* no current pointer */ + fp->_w = 0; /* nothing to read or write */ + fp->_r = 0; + fp->_bf._base = NULL; /* no buffer */ + fp->_bf._size = 0; + fp->_lbfsize = 0; /* not line buffered */ + fp->_file = -1; /* no file */ + fp->_ub._base = NULL; /* no ungetc buffer */ + fp->_ub._size = 0; + fp->_lb._base = NULL; /* no line buffer */ + fp->_lb._size = 0; + goto __sfp_done; + } + if (g->next == NULL && (g->next = moreglue(NDYNAMIC)) == NULL) { + fp = NULL; + break; + } + } +__sfp_done:; + return (fp); +} + +/* + * exit() calls _cleanup() through *__cleanup, set whenever we + * open or buffer a file. This chicanery is done so that programs + * that do not use stdio need not link it all in. + * + * The name `_cleanup' is, alas, fairly well known outside stdio. + */ +void _cleanup() +{ + (void) __swalk_sflush; +} + +/* + * __sinit() is called whenever stdio's internal variables must be set up. + */ +void __sinit() +{ + /* make sure we clean up on exit */ + __cleanup = _cleanup; + __sdidinit = 1; +} diff --git a/lib/libpthread/stdio/flags.c b/lib/libpthread/stdio/flags.c new file mode 100644 index 00000000000..7a0bfa71ab9 --- /dev/null +++ b/lib/libpthread/stdio/flags.c @@ -0,0 +1,90 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)flags.c 5.1 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: flags.c,v 1.1 1995/10/18 08:43:06 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/types.h> +#include <sys/file.h> +#include <stdio.h> +#include <errno.h> + +/* + * Return the (stdio) flags for a given mode. Store the flags + * to be passed to an open() syscall through *optr. + * Return 0 on error. + */ +__sflags(mode, optr) + register char *mode; + int *optr; +{ + register int ret, m, o; + + switch (*mode++) { + + case 'r': /* open for reading */ + ret = __SRD; + m = O_RDONLY; + o = 0; + break; + + case 'w': /* open for writing */ + ret = __SWR; + m = O_WRONLY; + o = O_CREAT | O_TRUNC; + break; + + case 'a': /* open for appending */ + ret = __SWR; + m = O_WRONLY; + o = O_CREAT | O_APPEND; + break; + + default: /* illegal mode */ + errno = EINVAL; + return (0); + } + + /* [rwa]\+ or [rwa]b\+ means read and write */ + if (*mode == '+' || (*mode == 'b' && mode[1] == '+')) { + ret = __SRW; + m = O_RDWR; + } + *optr = m | o; + return (ret); +} diff --git a/lib/libpthread/stdio/floatio.h b/lib/libpthread/stdio/floatio.h new file mode 100644 index 00000000000..a5bfd1f59e4 --- /dev/null +++ b/lib/libpthread/stdio/floatio.h @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)floatio.h 5.1 (Berkeley) 1/20/91 + * $Id: floatio.h,v 1.1 1995/10/18 08:43:06 deraadt Exp $ + */ + +/* + * Floating point scanf/printf (input/output) definitions. + */ + +/* 11-bit exponent (VAX G floating point) is 308 decimal digits */ +#define MAXEXP 308 +/* 128 bit fraction takes up 39 decimal digits; max reasonable precision */ +#define MAXFRACT 39 diff --git a/lib/libpthread/stdio/fopen.c b/lib/libpthread/stdio/fopen.c new file mode 100644 index 00000000000..f12842e3bc5 --- /dev/null +++ b/lib/libpthread/stdio/fopen.c @@ -0,0 +1,89 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)fopen.c 5.5 (Berkeley) 2/5/91";*/ +static char *rcsid = "$Id: fopen.c,v 1.1 1995/10/18 08:43:06 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdio.h> +#include <errno.h> +#include "local.h" + +extern pthread_mutex_t __sfp_mutex; +extern pthread_cond_t __sfp_cond; +extern int __sfp_state; + +FILE *fopen(const char *file, const char *mode) +{ + register FILE *fp; + register int f; + int flags, oflags; + + if ((flags = __sflags(mode, &oflags)) == 0) + return (NULL); + if ((f = open(file, oflags, 0666)) < 0) { + return (NULL); + } + + pthread_once(&__sdidinit, __sinit); + pthread_mutex_lock(&__sfp_mutex); + while (__sfp_state) { + pthread_cond_wait(&__sfp_cond, &__sfp_mutex); + } + + if (fp = __sfp()) { + fp->_file = f; + fp->_flags = flags; + + /* + * When opening in append mode, even though we use O_APPEND, + * we need to seek to the end so that ftell() gets the right + * answer. If the user then alters the seek pointer, or + * the file extends, this will fail, but there is not much + * we can do about this. (We could set __SAPP and check in + * fseek and ftell.) + */ + if (oflags & O_APPEND) + (void) __sseek((void *)fp, (fpos_t)0, SEEK_END); + } + pthread_mutex_unlock(&__sfp_mutex); + return (fp); +} diff --git a/lib/libpthread/stdio/fprintf.c b/lib/libpthread/stdio/fprintf.c new file mode 100644 index 00000000000..18f202e4a65 --- /dev/null +++ b/lib/libpthread/stdio/fprintf.c @@ -0,0 +1,70 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)fprintf.c 5.6 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: fprintf.c,v 1.1 1995/10/18 08:43:06 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +#if __STDC__ +fprintf(FILE *fp, const char *fmt, ...) +#else +fprintf(fp, fmt, va_alist) + FILE *fp; + char *fmt; + va_dcl +#endif +{ + int ret; + va_list ap; + +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + ret = vfprintf(fp, fmt, ap); + va_end(ap); + return (ret); +} diff --git a/lib/libpthread/stdio/fpurge.c b/lib/libpthread/stdio/fpurge.c new file mode 100644 index 00000000000..65788204920 --- /dev/null +++ b/lib/libpthread/stdio/fpurge.c @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)fpurge.c 5.2 (Berkeley) 2/24/91";*/ +static char *rcsid = "$Id: fpurge.c,v 1.1 1995/10/18 08:43:06 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include "local.h" + +/* + * fpurge: like fflush, but without writing anything: leave the + * given FILE's buffer empty. + */ +int +fpurge(fp) + register FILE *fp; +{ + int ret; + + flockfile(fp); + if (fp->_flags) { + if (HASUB(fp)) + FREEUB(fp); + fp->_p = fp->_bf._base; + fp->_r = 0; + fp->_w = fp->_flags & (__SLBF|__SNBF) ? 0 : fp->_bf._size; + ret = 0; + } else { + errno = EBADF; + ret = EOF; + } + funlockfile(fp); + return (ret); +} diff --git a/lib/libpthread/stdio/fputc.c b/lib/libpthread/stdio/fputc.c new file mode 100644 index 00000000000..b1febc14515 --- /dev/null +++ b/lib/libpthread/stdio/fputc.c @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)fputc.c 5.3 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: fputc.c,v 1.1 1995/10/18 08:43:06 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> + +fputc(c, fp) + int c; + register FILE *fp; +{ + int ret; + flockfile(fp); + ret = __sputc(c, fp); + funlockfile(fp); + return(ret); +} diff --git a/lib/libpthread/stdio/fputs.c b/lib/libpthread/stdio/fputs.c new file mode 100644 index 00000000000..320477ca416 --- /dev/null +++ b/lib/libpthread/stdio/fputs.c @@ -0,0 +1,66 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)fputs.c 5.6 (Berkeley) 2/24/91";*/ +static char *rcsid = "$Id: fputs.c,v 1.1 1995/10/18 08:43:06 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> +#include <string.h> +#include "fvwrite.h" + +/* + * Write the given string to the given file. + */ +fputs(s, fp) + const char *s; + FILE *fp; +{ + struct __suio uio; + struct __siov iov; + int ret; + + iov.iov_base = (void *)s; + iov.iov_len = uio.uio_resid = strlen(s); + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + flockfile(fp); + ret = __sfvwrite(fp, &uio); + funlockfile(fp); + return(ret); +} diff --git a/lib/libpthread/stdio/fread.c b/lib/libpthread/stdio/fread.c new file mode 100644 index 00000000000..3df1689f2f0 --- /dev/null +++ b/lib/libpthread/stdio/fread.c @@ -0,0 +1,83 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)fread.c 5.4 (Berkeley) 5/4/91";*/ +static char *rcsid = "$Id: fread.c,v 1.1 1995/10/18 08:43:06 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> +#include <string.h> + +size_t +fread(buf, size, count, fp) + void *buf; + size_t size, count; + register FILE *fp; +{ + register size_t resid; + register char *p; + register int r; + size_t total; + + if ((resid = count * size) == 0) + return (count); + + flockfile(fp); + if (fp->_r < 0) + fp->_r = 0; + total = resid; + p = buf; + while (resid > (r = fp->_r)) { + (void) bcopy((void *)fp->_p, (void *)p, (size_t)r); + fp->_p += r; + /* fp->_r = 0 ... done in __srefill */ + p += r; + resid -= r; + if (__srefill(fp)) { + /* no more input: return partial result */ + count = (total - resid) / size; + goto done_fread; + } + } + (void) bcopy((void *)fp->_p, (void *)p, resid); + fp->_r -= resid; + fp->_p += resid; +done_fread:; + funlockfile(fp); + return (count); +} diff --git a/lib/libpthread/stdio/freopen.c b/lib/libpthread/stdio/freopen.c new file mode 100644 index 00000000000..c7ab61c061a --- /dev/null +++ b/lib/libpthread/stdio/freopen.c @@ -0,0 +1,146 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)freopen.c 5.6 (Berkeley) 2/24/91";*/ +static char *rcsid = "$Id: freopen.c,v 1.1 1995/10/18 08:43:07 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include "local.h" + +extern pthread_mutex_t __sfp_mutex; +extern pthread_cond_t __sfp_cond; +extern int __sfp_state; + +/* + * Re-direct an existing, open (probably) file to some other file. + * ANSI is written such that the original file gets closed if at + * all possible, no matter what. + */ +FILE * +freopen(file, mode, fp) + const char *file, *mode; + register FILE *fp; +{ + int f, flags, oflags; + FILE *ret; + + if ((flags = __sflags(mode, &oflags)) == 0) { + (void) fclose(fp); + return (NULL); + } + + pthread_once(&__sdidinit, __sinit); + + /* + * There are actually programs that depend on being able to "freopen" + * descriptors that weren't originally open. Keep this from breaking. + * Remember whether the stream was open to begin with, and which file + * descriptor (if any) was associated with it. If it was attached to + * a descriptor, defer closing it; freopen("/dev/stdin", "r", stdin) + * should work. This is unnecessary if it was not a Unix file. + */ + /* while lock __sfp_mutex, to block out fopen, and other freopen calls */ + while (pthread_mutex_lock(&__sfp_mutex) == OK) { + if (ftrylockfile(fp) == OK) { + if (fp->_flags) { + /* flush the stream; ANSI doesn't require this. */ + if (fp->_flags & __SWR) + (void) __sflush(fp); + __sclose(fp); + /* + * Finish closing fp. We cannot keep fp->_base: + * it may be the wrong size. This loses the effect + * of any setbuffer calls, but stdio has always done + * this before. + * NOTE: We do this even if __ftrylockfilr failed with + * an error to avoid memory leaks. + */ + if (fp->_flags & __SMBF) + free((char *)fp->_bf._base); + fp->_w = 0; + fp->_r = 0; + fp->_p = NULL; + fp->_bf._base = NULL; + fp->_bf._size = 0; + fp->_lbfsize = 0; + if (HASUB(fp)) + FREEUB(fp); + fp->_ub._size = 0; + if (HASLB(fp)) + FREELB(fp); + fp->_lb._size = 0; + } + /* Get a new descriptor to refer to the new file. */ + if ((f = open(file, oflags, 0666)) < OK) + ret = NULL; + /* + * If reopening something that was open before on a real file, try + * to maintain the descriptor. Various C library routines (perror) + * assume stderr is always fd STDERR_FILENO, even if being freopen'd. + */ + /* Testing f == fp->_file may no longer be necessary */ + if (fp->_file >= 0 && f != fp->_file) { + if (dup2(f, fp->_file) >= OK) { + (void)close(f); + f = fp->_file; + } + } + fp->_flags = flags; + fp->_file = f; + ret = fp; + break; + } else { + /* unlock __sfp_mutex, and try again later */ + pthread_mutex_unlock(&__sfp_mutex); + pthread_yield(); + continue; + } + pthread_mutex_unlock(&__sfp_mutex); + funlockfile(fp); + return(ret); + } + (void)fclose(fp); + return(NULL); +} diff --git a/lib/libpthread/stdio/fscanf.c b/lib/libpthread/stdio/fscanf.c new file mode 100644 index 00000000000..54960c9c727 --- /dev/null +++ b/lib/libpthread/stdio/fscanf.c @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)fscanf.c 5.1 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: fscanf.c,v 1.1 1995/10/18 08:43:07 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +#if __STDC__ +fscanf(FILE *fp, char const *fmt, ...) { + int r; + va_list ap; + + va_start(ap, fmt); +#else +fscanf(fp, fmt, va_alist) + FILE *fp; + char *fmt; + va_dcl +{ + int r; + va_list ap; + + va_start(ap); +#endif + flockfile(fp); + r = __svfscanf(fp, fmt, ap); + funlockfile(fp); + va_end(ap); + return(r); +} diff --git a/lib/libpthread/stdio/fseek.c b/lib/libpthread/stdio/fseek.c new file mode 100644 index 00000000000..173d427ff43 --- /dev/null +++ b/lib/libpthread/stdio/fseek.c @@ -0,0 +1,246 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)fseek.c 5.7 (Berkeley) 2/24/91";*/ +static char *rcsid = "$Id: fseek.c,v 1.1 1995/10/18 08:43:07 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include "local.h" + +#define POS_ERR (-(fpos_t)1) + +/* + * Seek the given file to the given offset. + * `Whence' must be one of the three SEEK_* macros. + */ +fseek(fp, offset, whence) + register FILE *fp; + long offset; + int whence; +{ +#if __STDC__ + register fpos_t (*seekfn)(void *, fpos_t, int); +#else + register fpos_t (*seekfn)(); +#endif + fpos_t target, curoff; + size_t n; + struct stat st; + int havepos; + + /* make sure stdio is set up */ + if (!__sdidinit) + __sinit(); + + flockfile(fp); + + /* + * Change any SEEK_CUR to SEEK_SET, and check `whence' argument. + * After this, whence is either SEEK_SET or SEEK_END. + */ + switch (whence) { + case SEEK_CUR: + /* + * In order to seek relative to the current stream offset, + * we have to first find the current stream offset a la + * ftell (see ftell for details). + */ + if (fp->_flags & __SOFF) + curoff = fp->_offset; + else { + curoff = __sseek(fp, (fpos_t)0, SEEK_CUR); + if (curoff == -1L) + funlockfile(fp); + return (EOF); + } + if (fp->_flags & __SRD) { + curoff -= fp->_r; + if (HASUB(fp)) + curoff -= fp->_ur; + } else if (fp->_flags & __SWR && fp->_p != NULL) + curoff += fp->_p - fp->_bf._base; + + offset += curoff; + whence = SEEK_SET; + havepos = 1; + break; + + case SEEK_SET: + case SEEK_END: + curoff = 0; /* XXX just to keep gcc quiet */ + havepos = 0; + break; + + default: + errno = EINVAL; + funlockfile(fp); + return (EOF); + } + + /* + * Can only optimise if: + * reading (and not reading-and-writing); + * not unbuffered; and + * this is a `regular' Unix file (and hence seekfn==__sseek). + * We must check __NBF first, because it is possible to have __NBF + * and __SOPT both set. + */ + if (fp->_bf._base == NULL) + __smakebuf(fp); + if (fp->_flags & (__SWR | __SRW | __SNBF | __SNPT)) + goto dumb; + if ((fp->_flags & __SOPT) == 0) { + if (fp->_file < 0 || fstat(fp->_file, &st) || + (st.st_mode & S_IFMT) != S_IFREG) { + fp->_flags |= __SNPT; + goto dumb; + } + fp->_blksize = st.st_blksize; + fp->_flags |= __SOPT; + } + + /* + * We are reading; we can try to optimise. + * Figure out where we are going and where we are now. + */ + if (whence == SEEK_SET) + target = offset; + else { + if (fstat(fp->_file, &st)) + goto dumb; + target = st.st_size + offset; + } + + if (!havepos) { + if (fp->_flags & __SOFF) + curoff = fp->_offset; + else { + curoff = __sseek(fp, 0L, SEEK_CUR); + if (curoff == POS_ERR) + goto dumb; + } + curoff -= fp->_r; + if (HASUB(fp)) + curoff -= fp->_ur; + } + + /* + * Compute the number of bytes in the input buffer (pretending + * that any ungetc() input has been discarded). Adjust current + * offset backwards by this count so that it represents the + * file offset for the first byte in the current input buffer. + */ + if (HASUB(fp)) { + n = fp->_up - fp->_bf._base; + curoff -= n; + n += fp->_ur; + } else { + n = fp->_p - fp->_bf._base; + curoff -= n; + n += fp->_r; + } + + /* + * If the target offset is within the current buffer, + * simply adjust the pointers, clear EOF, undo ungetc(), + * and return. (If the buffer was modified, we have to + * skip this; see fgetline.c.) + */ + if ((fp->_flags & __SMOD) == 0 && + target >= curoff && target < curoff + n) { + register int o = target - curoff; + + fp->_p = fp->_bf._base + o; + fp->_r = n - o; + if (HASUB(fp)) + FREEUB(fp); + fp->_flags &= ~__SEOF; + funlockfile(fp); + return (0); + } + + /* + * The place we want to get to is not within the current buffer, + * but we can still be kind to the kernel copyout mechanism. + * By aligning the file offset to a block boundary, we can let + * the kernel use the VM hardware to map pages instead of + * copying bytes laboriously. Using a block boundary also + * ensures that we only read one block, rather than two. + */ + curoff = target & ~(fp->_blksize - 1); + if (__sseek(fp, 0L, SEEK_CUR) != POS_ERR) { + fp->_r = 0; + fp->_p = fp->_bf._base; + if (HASUB(fp)) + FREEUB(fp); + fp->_flags &= ~__SEOF; + n = target - curoff; + if (n) { + if (__srefill(fp) || fp->_r < n) + goto dumb; + fp->_p += n; + fp->_r -= n; + } + funlockfile(fp); + return (0); + } + + /* + * We get here if we cannot optimise the seek ... just + * do it. Allow the seek function to change fp->_bf._base. + */ +dumb: + if (__sflush(fp) || __sseek(fp, offset, whence) == POS_ERR) { + funlockfile(fp); + return (EOF); + } + /* success: clear EOF indicator and discard ungetc() data */ + if (HASUB(fp)) + FREEUB(fp); + fp->_p = fp->_bf._base; + fp->_r = 0; + /* fp->_w = 0; */ /* unnecessary (I think...) */ + fp->_flags &= ~__SEOF; + funlockfile(fp); + return (0); +} diff --git a/lib/libpthread/stdio/fsetpos.c b/lib/libpthread/stdio/fsetpos.c new file mode 100644 index 00000000000..69c9ddd0fcb --- /dev/null +++ b/lib/libpthread/stdio/fsetpos.c @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)fsetpos.c 5.2 (Berkeley) 2/5/91";*/ +static char *rcsid = "$Id: fsetpos.c,v 1.1 1995/10/18 08:43:07 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> + +/* + * fsetpos: like fseek. + * Don't bother locking, fseek does it. + */ +fsetpos(iop, pos) + FILE *iop; + const fpos_t *pos; +{ + return (fseek(iop, (long)*pos, SEEK_SET)); +} diff --git a/lib/libpthread/stdio/ftell.c b/lib/libpthread/stdio/ftell.c new file mode 100644 index 00000000000..2d5e5fa6eb1 --- /dev/null +++ b/lib/libpthread/stdio/ftell.c @@ -0,0 +1,89 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)ftell.c 5.4 (Berkeley) 2/5/91";*/ +static char *rcsid = "$Id: ftell.c,v 1.1 1995/10/18 08:43:07 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> +#include <errno.h> +#include "local.h" + +/* + * ftell: return current offset. + */ +long +ftell(fp) + register const FILE *fp; +{ + register fpos_t pos; + + flockfile(fp); + + /* + * Find offset of underlying I/O object, then + * adjust for buffered bytes. + */ + if (fp->_flags & __SOFF) + pos = fp->_offset; + else { + pos = lseek(fp, (fpos_t)0, SEEK_CUR); + } + + if (pos != -1L) { + if (fp->_flags & __SRD) { + /* + * Reading. Any unread characters (including + * those from ungetc) cause the position to be + * smaller than that in the underlying object. + */ + pos -= fp->_r; + if (HASUB(fp)) + pos -= fp->_ur; + } else if (fp->_flags & __SWR && fp->_p != NULL) { + /* + * Writing. Any buffered characters cause the + * position to be greater than that in the + * underlying object. + */ + pos += fp->_p - fp->_bf._base; + } + } + funlockfile(fp); + return (pos); +} diff --git a/lib/libpthread/stdio/funopen.c b/lib/libpthread/stdio/funopen.c new file mode 100644 index 00000000000..fd1689ada9e --- /dev/null +++ b/lib/libpthread/stdio/funopen.c @@ -0,0 +1,100 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)funopen.c 5.2 (Berkeley) 2/5/91";*/ +static char *rcsid = "$Id: funopen.c,v 1.1 1995/10/18 08:43:07 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> +#include <errno.h> +#include "local.h" + +FILE * +funopen(cookie, readfn, writefn, seekfn, closefn) + const void *cookie; + int (*readfn)(), (*writefn)(); +#if __STDC__ + fpos_t (*seekfn)(void *cookie, fpos_t off, int whence); +#else + fpos_t (*seekfn)(); +#endif + int (*closefn)(); +{ + struct fd_ops *fd_ops; + char *flags; + FILE *fp; + int fd; + + if (readfn == NULL) { + if (writefn == NULL) { /* illegal */ + errno = EINVAL; + return (NULL); + } else + flags = "w"; /* write only */ + } else { + if (writefn == NULL) + flags = "r"; /* read only */ + else + flags = "r+"; /* read-write */ + } + + if (fd_ops = (struct fd_ops*)malloc(sizeof(struct fd_ops))) { + if ((!(fd = fd_allocate())) < OK) { + + /* Set functions */ + fd_ops->seek = seekfn; + fd_ops->read = readfn; + fd_ops->write = writefn; + fd_ops->close = closefn; + + /* Alloc space for funtion pointer table */ + fd_table[fd]->type = FD_HALF_DUPLEX; + fd_table[fd]->ops = fd_ops; + + /* Save the cookie, it's important */ + fd_table[fd]->fd.ptr = cookie; + + if (fp = fdopen(fd, flags)) + return(fp); + + fd_free(fd); + } + free(fd_ops); + } + return(NULL); +} diff --git a/lib/libpthread/stdio/fvwrite.c b/lib/libpthread/stdio/fvwrite.c new file mode 100644 index 00000000000..c4646099fde --- /dev/null +++ b/lib/libpthread/stdio/fvwrite.c @@ -0,0 +1,188 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)fvwrite.c 5.3 (Berkeley) 5/4/91";*/ +static char *rcsid = "$Id: fvwrite.c,v 1.1 1995/10/18 08:43:07 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <string.h> +#include <stdio.h> +#include "local.h" +#include "fvwrite.h" + +/* + * Write some memory regions. Return zero on success, EOF on error. + * + * This routine is large and unsightly, but most of the ugliness due + * to the three different kinds of output buffering is handled here. + */ +__sfvwrite(fp, uio) + register FILE *fp; + register struct __suio *uio; +{ + register size_t len; + register char *p; + register struct __siov *iov; + register int w, s; + char *nl; + int nlknown, nldist; + + if ((len = uio->uio_resid) == 0) + return (0); + /* make sure we can write */ + if (cantwrite(fp)) + return (EOF); + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define COPY(n) (void) bcopy((void *)p, (void *)fp->_p, (size_t)(n)); + + iov = uio->uio_iov; + p = iov->iov_base; + len = iov->iov_len; + iov++; +#define GETIOV(extra_work) \ + while (len == 0) { \ + extra_work; \ + p = iov->iov_base; \ + len = iov->iov_len; \ + iov++; \ + } + if (fp->_flags & __SNBF) { + /* + * Unbuffered: write up to BUFSIZ bytes at a time. + */ + do { + GETIOV(;); + w = __swrite(fp, p, MIN(len, BUFSIZ)); + if (w <= 0) + goto err; + p += w; + len -= w; + } while ((uio->uio_resid -= w) != 0); + } else if ((fp->_flags & __SLBF) == 0) { + /* + * Fully buffered: fill partially full buffer, if any, + * and then flush. If there is no partial buffer, write + * one _bf._size byte chunk directly (without copying). + * + * String output is a special case: write as many bytes + * as fit, but pretend we wrote everything. This makes + * snprintf() return the number of bytes needed, rather + * than the number used, and avoids its write function + * (so that the write function can be invalid). + */ + do { + GETIOV(;); + w = fp->_w; + if (fp->_flags & __SSTR) { + if (len < w) + w = len; + COPY(w); /* copy MIN(fp->_w,len), */ + fp->_w -= w; + fp->_p += w; + w = len; /* but pretend copied all */ + } else if (fp->_p > fp->_bf._base && len > w) { + /* fill and flush */ + COPY(w); + /* fp->_w -= w; */ /* unneeded */ + fp->_p += w; + if (fflush(fp)) + goto err; + } else if (len >= (w = fp->_bf._size)) { + if ((w = __swrite(fp, p, w)) <= 0) + goto err; + } else { + /* fill and done */ + w = len; + COPY(w); + fp->_w -= w; + fp->_p += w; + } + p += w; + len -= w; + } while ((uio->uio_resid -= w) != 0); + } else { + /* + * Line buffered: like fully buffered, but we + * must check for newlines. Compute the distance + * to the first newline (including the newline), + * or `infinity' if there is none, then pretend + * that the amount to write is MIN(len,nldist). + */ + nlknown = 0; + nldist = 0; /* XXX just to keep gcc happy */ + do { + GETIOV(nlknown = 0); + if (!nlknown) { + nl = memchr((void *)p, '\n', len); + nldist = nl ? nl + 1 - p : len + 1; + nlknown = 1; + } + s = MIN(len, nldist); + w = fp->_w + fp->_bf._size; + if (fp->_p > fp->_bf._base && s > w) { + COPY(w); + /* fp->_w -= w; */ + fp->_p += w; + if (fflush(fp)) + goto err; + } else if (s >= (w = fp->_bf._size)) { + if ((w = __swrite(fp, p, w)) <= 0) + goto err; + } else { + w = s; + COPY(w); + fp->_w -= w; + fp->_p += w; + } + if ((nldist -= w) == 0) { + /* copied the newline: flush and forget */ + if (fflush(fp)) + goto err; + nlknown = 0; + } + p += w; + len -= w; + } while ((uio->uio_resid -= w) != 0); + } + return (0); + +err: + fp->_flags |= __SERR; + return (EOF); +} diff --git a/lib/libpthread/stdio/fvwrite.h b/lib/libpthread/stdio/fvwrite.h new file mode 100644 index 00000000000..8977a2bf49e --- /dev/null +++ b/lib/libpthread/stdio/fvwrite.h @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)fvwrite.h 5.1 (Berkeley) 1/20/91 + * $Id: fvwrite.h,v 1.1 1995/10/18 08:43:07 deraadt Exp $ + */ + +/* + * I/O descriptors for __sfvwrite(). + */ +struct __siov { + void *iov_base; + size_t iov_len; +}; + +struct __suio { + struct __siov *uio_iov; + int uio_iovcnt; + int uio_resid; +}; + +extern int __sfvwrite __P(( FILE *, struct __suio *)); diff --git a/lib/libpthread/stdio/fwalk.c b/lib/libpthread/stdio/fwalk.c new file mode 100644 index 00000000000..b4a81f083ba --- /dev/null +++ b/lib/libpthread/stdio/fwalk.c @@ -0,0 +1,131 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)fwalk.c 5.2 (Berkeley) 2/24/91";*/ +static char *rcsid = "$Id: fwalk.c,v 1.1 1995/10/18 08:43:07 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <errno.h> +#include <stdio.h> +#include "local.h" +#include "glue.h" + +extern pthread_mutex_t __sfp_mutex; +extern pthread_cond_t __sfp_cond; +extern int __sfp_state; + +/* + * fwalk now can only be used for flushing the buffers. + * This is all it was originally used for. + * The function has also become much more complicated. + * The first time through we flush everything we can. + * If this fails to flush everything because we couldn't get a lock + * we wait on the locksfor the second pass. Why this works ... + * + * This function must allow for multiple threads to flush everything. + * This function cannot flush buffers locked by another thread. + * So we flush everything we can the first pass. This includes all + * buffers locked by this thread, and wait on buffers that are locked. + * Eventually other threads willl unlock there buffers or flush them themselves + * at which point this thread will notice that it's empty or be able to + * flush the buffer. This is fine so long as no other thread tries to flush + * all buffers. Here is the possible deadlock condition, but since this thread + * has flushed all buffers it can, there are NO buffers locked by this thread + * that need flushing so any other thread flushing won't block waiting on this + * thread thereby eliminating the deadlock condition. + */ + +int __swalk_sflush() +{ + register FILE *fp, *savefp; + register int n, ret, saven; + register struct glue *g, *saveg; + + /* Only allow other threads to read __sglue */ + pthread_mutex_lock(&__sfp_mutex); + __sfp_state++; + pthread_mutex_unlock(&__sfp_mutex); + + ret = 0; + saven = 0; + saveg = NULL; + savefp = NULL; + for (g = &__sglue; g != NULL; g = g->next) { + for (fp = g->iobs, n = g->niobs; --n >= 0; fp++) { + if (fp->_flags != 0) { + /* Is there anything to flush? */ + if (fp->_bf._base && (fp->_bf._base - fp->_p)) { + if (ftrylockfile(fp)) { /* Can we flush it */ + if (!saven) { /* No, save first fp we can't flush */ + saven; + saveg = g; + savefp = fp; + continue; + } + ret |= __sflush(fp); + } + } + } + } + } + if (savefp) { + for (g = saveg; g != NULL; g = g->next) { + for (fp = savefp, n = saven + 1; --n >= 0; fp++) { + if (fp->_flags != 0) { + /* Anything to flush */ + while (fp->_bf._base && (fp->_bf._base - fp->_p)) { + if (ftrylockfile(fp)) { /* Can we flush it */ + pthread_yield(); + continue; + } + ret |= __sflush(fp); + } + } + } + } + } + + /* If no other readers wakeup a thread waiting to do __sfp */ + pthread_mutex_lock(&__sfp_mutex); + if (! (--__sfp_state)) { + pthread_cond_signal(&__sfp_cond); + } + pthread_mutex_unlock(&__sfp_mutex); + return (ret); +} + diff --git a/lib/libpthread/stdio/fwrite.c b/lib/libpthread/stdio/fwrite.c new file mode 100644 index 00000000000..35576013f62 --- /dev/null +++ b/lib/libpthread/stdio/fwrite.c @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)fwrite.c 5.5 (Berkeley) 2/24/91";*/ +static char *rcsid = "$Id: fwrite.c,v 1.1 1995/10/18 08:43:07 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> +#include "local.h" +#include "fvwrite.h" + +/* + * Write `count' objects (each size `size') from memory to the given file. + * Return the number of whole objects written. + */ +size_t +fwrite(buf, size, count, fp) + const void *buf; + size_t size, count; + FILE *fp; +{ + struct __suio uio; + struct __siov iov; + size_t n; + + iov.iov_base = (void *)buf; + uio.uio_resid = iov.iov_len = n = count * size; + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + + flockfile(fp); + + /* + * The usual case is success (__sfvwrite returns 0); + * skip the divide if this happens, since divides are + * generally slow and since this occurs whenever size==0. + */ + if (__sfvwrite(fp, &uio) == 0) + count = (n - uio.uio_resid) / size; + funlockfile(fp); + return(count); +} diff --git a/lib/libpthread/stdio/getc.c b/lib/libpthread/stdio/getc.c new file mode 100644 index 00000000000..2b487ce63c7 --- /dev/null +++ b/lib/libpthread/stdio/getc.c @@ -0,0 +1,57 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)getc.c 5.1 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: getc.c,v 1.1 1995/10/18 08:43:07 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> + +/* + * A subroutine version of the macro getc. + */ +#undef getc + +getc(fp) + register FILE *fp; +{ + int ret; + flockfile(fp); + ret = __sgetc(fp); + funlockfile(fp); + return(ret); +} diff --git a/lib/libpthread/stdio/getc_unlocked.c b/lib/libpthread/stdio/getc_unlocked.c new file mode 100644 index 00000000000..c60046cf34c --- /dev/null +++ b/lib/libpthread/stdio/getc_unlocked.c @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)getc.c 5.1 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: getc_unlocked.c,v 1.1 1995/10/18 08:43:07 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> + +/* + * A subroutine version of the macro getc. + */ +#undef getc_unlocked + +getc_unlocked(fp) + register FILE *fp; +{ + return (__sgetc(fp)); +} diff --git a/lib/libpthread/stdio/getchar.c b/lib/libpthread/stdio/getchar.c new file mode 100644 index 00000000000..1e2d6ac92a9 --- /dev/null +++ b/lib/libpthread/stdio/getchar.c @@ -0,0 +1,57 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)getchar.c 5.3 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: getchar.c,v 1.1 1995/10/18 08:43:07 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * A subroutine version of the macro getchar. + */ +#include <pthread.h> +#include <stdio.h> + +#undef getchar + +getchar() +{ + int ret; + flockfile(stdin); + ret = getc(stdin); + funlockfile(stdin); + return(ret); +} diff --git a/lib/libpthread/stdio/getchar_unlocked.c b/lib/libpthread/stdio/getchar_unlocked.c new file mode 100644 index 00000000000..f2eefcb29e3 --- /dev/null +++ b/lib/libpthread/stdio/getchar_unlocked.c @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)getchar.c 5.3 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: getchar_unlocked.c,v 1.1 1995/10/18 08:43:07 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * A subroutine version of the macro getchar. + */ +#include <pthread.h> +#include <stdio.h> + +#undef getchar_unlocked + +getchar_unlocked() +{ + return (getc(stdin)); +} diff --git a/lib/libpthread/stdio/gets.c b/lib/libpthread/stdio/gets.c new file mode 100644 index 00000000000..9cc4916e7a1 --- /dev/null +++ b/lib/libpthread/stdio/gets.c @@ -0,0 +1,69 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)gets.c 5.3 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: gets.c,v 1.1 1995/10/18 08:43:07 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <unistd.h> +#include <stdio.h> + +char * +gets(buf) + char *buf; +{ + register int c; + register char *s; + static int warned; + static char w[] = + "warning: this program uses gets(), which is unsafe.\r\n"; + + if (!warned) { + (void) write(STDERR_FILENO, w, sizeof(w) - 1); + warned = 1; + } + for (s = buf; (c = getchar()) != '\n';) + if (c == EOF) + if (s == buf) + return (NULL); + else + break; + else + *s++ = c; + *s = 0; + return (buf); +} diff --git a/lib/libpthread/stdio/getw.c b/lib/libpthread/stdio/getw.c new file mode 100644 index 00000000000..ef6472a0940 --- /dev/null +++ b/lib/libpthread/stdio/getw.c @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)getw.c 5.3 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: getw.c,v 1.1 1995/10/18 08:43:07 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> + +getw(fp) + FILE *fp; +{ + int x; + + return (fread((void *)&x, sizeof(x), 1, fp) == 1 ? x : EOF); +} diff --git a/lib/libpthread/stdio/glue.h b/lib/libpthread/stdio/glue.h new file mode 100644 index 00000000000..3467dd66b2f --- /dev/null +++ b/lib/libpthread/stdio/glue.h @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)glue.h 5.1 (Berkeley) 1/20/91 + * $Id: glue.h,v 1.1 1995/10/18 08:43:07 deraadt Exp $ + */ + +/* + * The first few FILEs are statically allocated; others are dynamically + * allocated and linked in via this glue structure. + */ +struct glue { + struct glue *next; + int niobs; + FILE *iobs; +} __sglue; diff --git a/lib/libpthread/stdio/local.h b/lib/libpthread/stdio/local.h new file mode 100644 index 00000000000..248bb3d5e31 --- /dev/null +++ b/lib/libpthread/stdio/local.h @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)local.h 5.3 (Berkeley) 5/6/93 + * $Id: local.h,v 1.1 1995/10/18 08:43:07 deraadt Exp $ + */ + +/* + * Information local to this implementation of stdio, + * in particular, macros and private variables. + */ + +FILE *__sfp __P((void)); +int __sflush __P((FILE *)); +int __srefill __P((FILE *)); +int __swrite __P((FILE *, const char *, int)); +int __sread __P((FILE *, char *, int)); +fpos_t __sseek __P((FILE *, fpos_t, int)); +int __sclose __P((FILE *)); +void __sinit __P((void)); +void _cleanup __P((void)); +void (*__cleanup) __P((void)); +void __smakebuf __P((FILE *)); +int __swhatbuf __P((FILE *, size_t *, int *)); +int __swalk_sflush __P(()); +int __swsetup __P((FILE *)); +int __sflags __P((const char *, int *)); + +extern int __sdidinit; + +/* + * Return true iff the given FILE cannot be written now. + */ +#define cantwrite(fp) \ + ((((fp)->_flags & __SWR) == 0 || (fp)->_bf._base == NULL) && \ + __swsetup(fp)) + +/* + * Test whether the given stdio file has an active ungetc buffer; + * release such a buffer, without restoring ordinary unread data. + */ +#define HASUB(fp) ((fp)->_ub._base != NULL) +#define FREEUB(fp) { \ + if ((fp)->_ub._base != (fp)->_ubuf) \ + free((char *)(fp)->_ub._base); \ + (fp)->_ub._base = NULL; \ +} + +/* + * test for an fgetline() buffer. + */ +#define HASLB(fp) ((fp)->_lb._base != NULL) +#define FREELB(fp) { \ + free((char *)(fp)->_lb._base); \ + (fp)->_lb._base = NULL; \ +} diff --git a/lib/libpthread/stdio/makebuf.c b/lib/libpthread/stdio/makebuf.c new file mode 100644 index 00000000000..e7b615437d8 --- /dev/null +++ b/lib/libpthread/stdio/makebuf.c @@ -0,0 +1,119 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)makebuf.c 5.3 (Berkeley) 5/6/93";*/ +static char *rcsid = "$Id: makebuf.c,v 1.1 1995/10/18 08:43:08 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include "local.h" + +/* + * Allocate a file buffer, or switch to unbuffered I/O. + * Per the ANSI C standard, ALL tty devices default to line buffered. + * + * As a side effect, we set __SOPT or __SNPT (en/dis-able fseek + * optimisation) right after the fstat() that finds the buffer size. + */ +void +__smakebuf(fp) + register FILE *fp; +{ + register void *p; + register int flags; + size_t size; + int couldbetty; + + if (fp->_flags & __SNBF) { + fp->_bf._base = fp->_p = fp->_nbuf; + fp->_bf._size = 1; + return; + } + flags = __swhatbuf(fp, &size, &couldbetty); + if ((p = malloc(size)) == NULL) { + fp->_flags |= __SNBF; + fp->_bf._base = fp->_p = fp->_nbuf; + fp->_bf._size = 1; + return; + } + __cleanup = _cleanup; + flags |= __SMBF; + fp->_bf._base = fp->_p = p; + fp->_bf._size = size; + if (couldbetty && isatty(fp->_file)) + flags |= __SLBF; + fp->_flags |= flags; +} + +/* + * Internal routine to determine `proper' buffering for a file. + */ +int +__swhatbuf(fp, bufsize, couldbetty) + register FILE *fp; + size_t *bufsize; + int *couldbetty; +{ + struct stat st; + + if (fp->_file < 0 || fstat(fp->_file, &st) < 0) { + *couldbetty = 0; + *bufsize = BUFSIZ; + return (__SNPT); + } + + /* could be a tty iff it is a character device */ + *couldbetty = (st.st_mode & S_IFMT) == S_IFCHR; + if (st.st_blksize <= 0) { + *bufsize = BUFSIZ; + return (__SNPT); + } + + /* + * Optimise fseek() only if it is a regular file. (The test for + * __sseek is mainly paranoia.) It is safe to set _blksize + * unconditionally; it will only be used if __SOPT is also set. + */ + *bufsize = st.st_blksize; + fp->_blksize = st.st_blksize; + return ((st.st_mode & S_IFMT) == S_IFREG ? __SOPT : __SNPT); +} diff --git a/lib/libpthread/stdio/mktemp.c b/lib/libpthread/stdio/mktemp.c new file mode 100644 index 00000000000..4f41c63ff48 --- /dev/null +++ b/lib/libpthread/stdio/mktemp.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 1987 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: @(#)mktemp.c 5.10 (Berkeley) 2/24/91";*/ +static char *rcsid = "$Id: mktemp.c,v 1.1 1995/10/18 08:43:08 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> + +static int _gettemp(); + +mkstemp(path) + char *path; +{ + int fd; + + return (_gettemp(path, &fd) ? fd : -1); +} + +char * +mktemp(path) + char *path; +{ + return(_gettemp(path, (int *)NULL) ? path : (char *)NULL); +} + +static +_gettemp(path, doopen) + char *path; + register int *doopen; +{ + extern int errno; + register char *start, *trv; + struct stat sbuf; + u_int pid; + + pid = getpid(); + for (trv = path; *trv; ++trv); /* extra X's get set to 0's */ + while (*--trv == 'X') { + *trv = (pid % 10) + '0'; + pid /= 10; + } + + /* + * check the target directory; if you have six X's and it + * doesn't exist this runs for a *very* long time. + */ + for (start = trv + 1;; --trv) { + if (trv <= path) + break; + if (*trv == '/') { + *trv = '\0'; + if (stat(path, &sbuf)) + return(0); + if (!S_ISDIR(sbuf.st_mode)) { + errno = ENOTDIR; + return(0); + } + *trv = '/'; + break; + } + } + + for (;;) { + if (doopen) { + if ((*doopen = + open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) + return(1); + if (errno != EEXIST) + return(0); + } + else if (stat(path, &sbuf)) + return(errno == ENOENT ? 1 : 0); + + /* tricky little algorithm for backward compatibility */ + for (trv = start;;) { + if (!*trv) + return(0); + if (*trv == 'z') + *trv++ = 'a'; + else { + if (isdigit(*trv)) + *trv = 'a'; + else + ++*trv; + break; + } + } + } + /*NOTREACHED*/ +} diff --git a/lib/libpthread/stdio/perror.c b/lib/libpthread/stdio/perror.c new file mode 100644 index 00000000000..c4cb0154da2 --- /dev/null +++ b/lib/libpthread/stdio/perror.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1988 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[] = "@(#)perror.c 5.11 (Berkeley) 2/24/91"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/types.h> +#include <sys/uio.h> +#include <unistd.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> + +void +perror(s) + const char *s; +{ + register struct iovec *v; + struct iovec iov[4]; + + v = iov; + if (s && *s) { + v->iov_base = (char *)s; + v->iov_len = strlen(s); + v++; + v->iov_base = ": "; + v->iov_len = 2; + v++; + } + v->iov_base = strerror(errno); + v->iov_len = strlen(v->iov_base); + v++; + v->iov_base = "\n"; + v->iov_len = 1; + (void)writev(STDERR_FILENO, iov, (v - iov) + 1); +} diff --git a/lib/libpthread/stdio/printf.c b/lib/libpthread/stdio/printf.c new file mode 100644 index 00000000000..4b546565d08 --- /dev/null +++ b/lib/libpthread/stdio/printf.c @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)printf.c 5.6 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: printf.c,v 1.1 1995/10/18 08:43:08 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> + +printf(char const *fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vfprintf(stdout, fmt, ap); + va_end(ap); + return (ret); +} diff --git a/lib/libpthread/stdio/putc.c b/lib/libpthread/stdio/putc.c new file mode 100644 index 00000000000..f98ace370ad --- /dev/null +++ b/lib/libpthread/stdio/putc.c @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)putc.c 5.1 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: putc.c,v 1.1 1995/10/18 08:43:08 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> + +/* + * A subroutine version of the macro putc. + */ +#undef putc + +putc(c, fp) + int c; + register FILE *fp; +{ + int ret; + flockfile(fp); + ret = __sputc(c, fp); + funlockfile(fp); + return(ret); +} diff --git a/lib/libpthread/stdio/putc_unlocked.c b/lib/libpthread/stdio/putc_unlocked.c new file mode 100644 index 00000000000..3f3a6a9a14c --- /dev/null +++ b/lib/libpthread/stdio/putc_unlocked.c @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)putc.c 5.1 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: putc_unlocked.c,v 1.1 1995/10/18 08:43:08 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> + +/* + * A subroutine version of the macro putc. + */ +#undef putc_unlocked + +putc_unlocked(c, fp) + int c; + register FILE *fp; +{ + return (__sputc(c, fp)); +} diff --git a/lib/libpthread/stdio/putchar.c b/lib/libpthread/stdio/putchar.c new file mode 100644 index 00000000000..d02c06beb33 --- /dev/null +++ b/lib/libpthread/stdio/putchar.c @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)putchar.c 5.3 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: putchar.c,v 1.1 1995/10/18 08:43:08 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> + +#undef putchar + +/* + * A subroutine version of the macro putchar + */ +putchar(c) + int c; +{ + register FILE *so = stdout; + int ret; + + flockfile(so); + ret = __sputc(c, so); + funlockfile(so); + return(ret); +} diff --git a/lib/libpthread/stdio/putchar_unlocked.c b/lib/libpthread/stdio/putchar_unlocked.c new file mode 100644 index 00000000000..c79dc7ed489 --- /dev/null +++ b/lib/libpthread/stdio/putchar_unlocked.c @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)putchar.c 5.3 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: putchar_unlocked.c,v 1.1 1995/10/18 08:43:08 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> + +#undef putchar_unlocked +/* + * A subroutine version of the macro putchar + */ +putchar_unlocked(c) + int c; +{ + register FILE *so = stdout; + + return (__sputc(c, so)); +} diff --git a/lib/libpthread/stdio/puts.c b/lib/libpthread/stdio/puts.c new file mode 100644 index 00000000000..bb7357b1cb4 --- /dev/null +++ b/lib/libpthread/stdio/puts.c @@ -0,0 +1,70 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)puts.c 5.6 (Berkeley) 2/24/91";*/ +static char *rcsid = "$Id: puts.c,v 1.1 1995/10/18 08:43:08 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> +#include <string.h> +#include "fvwrite.h" + +/* + * Write the given string to stdout, appending a newline. + */ +puts(s) + char const *s; +{ + size_t c = strlen(s); + struct __suio uio; + struct __siov iov[2]; + int r; + + iov[0].iov_base = (void *)s; + iov[0].iov_len = c; + iov[1].iov_base = "\n"; + iov[1].iov_len = 1; + uio.uio_resid = c + 1; + uio.uio_iov = &iov[0]; + uio.uio_iovcnt = 2; + + flockfile(stdout); + r = (__sfvwrite(stdout, &uio) ? EOF : '\n'); + funlockfile(stdout); + return(r); +} diff --git a/lib/libpthread/stdio/putw.c b/lib/libpthread/stdio/putw.c new file mode 100644 index 00000000000..0bb28601d4d --- /dev/null +++ b/lib/libpthread/stdio/putw.c @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)putw.c 5.3 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: putw.c,v 1.1 1995/10/18 08:43:08 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> +#include "fvwrite.h" + +putw(w, fp) + int w; + FILE *fp; +{ + struct __suio uio; + struct __siov iov; + int r; + + iov.iov_base = &w; + iov.iov_len = uio.uio_resid = sizeof(w); + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + + flockfile(fp); + r = (__sfvwrite(fp, &uio)); + funlockfile(fp); + return(r); +} diff --git a/lib/libpthread/stdio/refill.c b/lib/libpthread/stdio/refill.c new file mode 100644 index 00000000000..8485159ad6c --- /dev/null +++ b/lib/libpthread/stdio/refill.c @@ -0,0 +1,183 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)refill.c 5.3 (Berkeley) 2/24/91";*/ +static char *rcsid = "$Id: refill.c,v 1.1 1995/10/18 08:43:08 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include "local.h" +#include "glue.h" + +extern pthread_mutex_t __sfp_mutex; +extern pthread_cond_t __sfp_cond; +extern struct glue __sglue; +extern int __sfp_state; + +/* This function is very similar to __swalk_sflush */ +static void __swalk_lflush() +{ + register FILE *fp, *savefp; + register int n, saven; + register struct glue *g, *saveg; + + /* Only allow other threads to read __sglue */ + pthread_mutex_lock(&__sfp_mutex); + __sfp_state++; + pthread_mutex_unlock(&__sfp_mutex); + + saven = 0; + saveg = NULL; + savefp = NULL; + for (g = &__sglue; g != NULL; g = g->next) { + for (fp = g->iobs, n = g->niobs; --n >= 0; fp++) { + if ((fp->_flags & (__SLBF|__SWR)) == __SLBF|__SWR) { + /* Is there anything to flush? */ + if (fp->_bf._base && (fp->_bf._base - fp->_p)) { + if (ftrylockfile(fp)) { /* Can we flush it */ + if (!saven) { /* No, save first fp we can't flush */ + saven; + saveg = g; + savefp = fp; + continue; + } + (void) __sflush(fp); + } + } + } + } + } + if (savefp) { + for (g = saveg; g != NULL; g = g->next) { + for (fp = savefp, n = saven + 1; --n >= 0; fp++) { + if ((fp->_flags & (__SLBF|__SWR)) == __SLBF|__SWR) { + /* Anything to flush */ + while (fp->_bf._base && (fp->_bf._base - fp->_p)) { + if (ftrylockfile(fp)) { /* Can we flush it */ + pthread_yield(); + continue; + } + (void) __sflush(fp); + } + } + } + } + } + + /* If no other readers wakeup a thread waiting to do __sfp */ + pthread_mutex_lock(&__sfp_mutex); + if (! (--__sfp_state)) { + pthread_cond_signal(&__sfp_cond); + } + pthread_mutex_unlock(&__sfp_mutex); +} + +/* + * Refill a stdio buffer. + * Return EOF on eof or error, 0 otherwise. + */ +__srefill(fp) + register FILE *fp; +{ + + /* make sure stdio is set up */ + pthread_once(&__sdidinit, __sinit); + + fp->_r = 0; /* largely a convenience for callers */ + + /* SysV does not make this test; take it out for compatibility */ + if (fp->_flags & __SEOF) + return (EOF); + + /* if not already reading, have to be reading and writing */ + if ((fp->_flags & __SRD) == 0) { + if ((fp->_flags & __SRW) == 0) { + errno = EBADF; + return (EOF); + } + /* switch to reading */ + if (fp->_flags & __SWR) { + if (__sflush(fp)) + return (EOF); + fp->_flags &= ~__SWR; + fp->_w = 0; + fp->_lbfsize = 0; + } + fp->_flags |= __SRD; + } else { + /* + * We were reading. If there is an ungetc buffer, + * we must have been reading from that. Drop it, + * restoring the previous buffer (if any). If there + * is anything in that buffer, return. + */ + if (HASUB(fp)) { + FREEUB(fp); + if ((fp->_r = fp->_ur) != 0) { + fp->_p = fp->_up; + return (0); + } + } + } + + if (fp->_bf._base == NULL) + __smakebuf(fp); + + /* + * Before reading from a line buffered or unbuffered file, + * flush all line buffered output files, per the ANSI C + * standard. + */ + if (fp->_flags & (__SLBF|__SNBF)) + __swalk_lflush(); + fp->_p = fp->_bf._base; + fp->_r = __sread(fp, (char *)fp->_p, fp->_bf._size); + fp->_flags &= ~__SMOD; /* buffer contents are again pristine */ + if (fp->_r <= 0) { + if (fp->_r == 0) + fp->_flags |= __SEOF; + else { + fp->_r = 0; + fp->_flags |= __SERR; + } + return (EOF); + } + return (0); +} diff --git a/lib/libpthread/stdio/remove.c b/lib/libpthread/stdio/remove.c new file mode 100644 index 00000000000..3a09735f298 --- /dev/null +++ b/lib/libpthread/stdio/remove.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)remove.c 5.3 (Berkeley) 2/24/91";*/ +static char *rcsid = "$Id: remove.c,v 1.1 1995/10/18 08:43:08 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <unistd.h> + +remove(file) + const char *file; +{ + return (unlink(file)); +} diff --git a/lib/libpthread/stdio/rewind.c b/lib/libpthread/stdio/rewind.c new file mode 100644 index 00000000000..b5d1a9d8e67 --- /dev/null +++ b/lib/libpthread/stdio/rewind.c @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)rewind.c 5.6 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: rewind.c,v 1.1 1995/10/18 08:43:08 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <errno.h> +#include <stdio.h> + +void +rewind(fp) + register FILE *fp; +{ + flockfile(fp); + (void) fseek(fp, 0L, SEEK_SET); + fp->_flags &= ~(__SERR|__SEOF); /* clearerr */ + funlockfile(fp); + errno = 0; /* not required, but seems reasonable */ +} diff --git a/lib/libpthread/stdio/rget.c b/lib/libpthread/stdio/rget.c new file mode 100644 index 00000000000..f43747cda99 --- /dev/null +++ b/lib/libpthread/stdio/rget.c @@ -0,0 +1,57 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)rget.c 5.1 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: rget.c,v 1.1 1995/10/18 08:43:08 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> + +/* + * Handle getc() when the buffer ran out: + * Refill, then return the first character + * in the newly-filled buffer. + */ +__srget(fp) + register FILE *fp; +{ + if (__srefill(fp) == 0) { + fp->_r--; + return (*fp->_p++); + } + return (EOF); +} diff --git a/lib/libpthread/stdio/scanf.c b/lib/libpthread/stdio/scanf.c new file mode 100644 index 00000000000..7feb1f529f0 --- /dev/null +++ b/lib/libpthread/stdio/scanf.c @@ -0,0 +1,71 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)scanf.c 5.3 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: scanf.c,v 1.1 1995/10/18 08:43:08 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +#if __STDC__ +scanf(char const *fmt, ...) +#else +scanf(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + int ret; + va_list ap; + +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + flockfile(stdin); + ret = __svfscanf(stdin, fmt, ap); + flockfile(stdin); + va_end(ap); + return (ret); +} diff --git a/lib/libpthread/stdio/setbuf.c b/lib/libpthread/stdio/setbuf.c new file mode 100644 index 00000000000..94ae5d66d75 --- /dev/null +++ b/lib/libpthread/stdio/setbuf.c @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)setbuf.c 5.3 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: setbuf.c,v 1.1 1995/10/18 08:43:08 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> +#include "local.h" + +void +setbuf(fp, buf) + FILE *fp; + char *buf; +{ + (void) setvbuf(fp, buf, buf ? _IOFBF : _IONBF, BUFSIZ); +} diff --git a/lib/libpthread/stdio/setbuffer.c b/lib/libpthread/stdio/setbuffer.c new file mode 100644 index 00000000000..e390674110b --- /dev/null +++ b/lib/libpthread/stdio/setbuffer.c @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)setbuffer.c 5.5 (Berkeley) 3/18/91";*/ +static char *rcsid = "$Id: setbuffer.c,v 1.1 1995/10/18 08:43:09 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> + +void +setbuffer(fp, buf, size) + register FILE *fp; + char *buf; + int size; +{ + + (void) setvbuf(fp, buf, buf ? _IOFBF : _IONBF, size); +} + +/* + * set line buffering + */ +setlinebuf(fp) + FILE *fp; +{ + + (void) setvbuf(fp, (char *)NULL, _IOLBF, (size_t)0); + return (0); /* ??? */ +} diff --git a/lib/libpthread/stdio/setvbuf.c b/lib/libpthread/stdio/setvbuf.c new file mode 100644 index 00000000000..f0a195a5dcf --- /dev/null +++ b/lib/libpthread/stdio/setvbuf.c @@ -0,0 +1,153 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)setvbuf.c 5.5 (Berkeley) 5/6/93";*/ +static char *rcsid = "$Id: setvbuf.c,v 1.1 1995/10/18 08:43:09 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include "local.h" + +/* + * Set one of the three kinds of buffering, optionally including + * a buffer. + */ +setvbuf(fp, buf, mode, size) + register FILE *fp; + char *buf; + register int mode; + register size_t size; +{ + register int ret, flags; + size_t iosize; + int ttyflag; + + /* + * Verify arguments. The `int' limit on `size' is due to this + * particular implementation. Note, buf and size are ignored + * when setting _IONBF. + */ + if (mode != _IONBF) + if ((mode != _IOFBF && mode != _IOLBF) || (int)size < 0) + return (EOF); + + flockfile(fp); + /* + * Write current buffer, if any. Discard unread input, cancel + * line buffering, and free old buffer if malloc()ed. + */ + ret = 0; + (void)__sflush(fp); + fp->_r = fp->_lbfsize = 0; + flags = fp->_flags; + if (flags & __SMBF) + free((void *)fp->_bf._base); + flags &= ~(__SLBF | __SNBF | __SMBF | __SOPT | __SNPT); + + /* If setting unbuffered mode, skip all the hard work. */ + if (mode == _IONBF) + goto nbf; + + /* + * Find optimal I/O size for seek optimization. This also returns + * a `tty flag' to suggest that we check isatty(fd), but we do not + * care since our caller told us how to buffer. + */ + flags |= __swhatbuf(fp, &iosize, &ttyflag); + if (size == 0) { + buf = NULL; /* force local allocation */ + size = iosize; + } + + /* Allocate buffer if needed. */ + if (buf == NULL) { + if ((buf = malloc(size)) == NULL) { + /* + * Unable to honor user's request. We will return + * failure, but try again with file system size. + */ + ret = EOF; + if (size != iosize) { + size = iosize; + buf = malloc(size); + } + } + if (buf == NULL) { + /* No luck; switch to unbuffered I/O. */ +nbf: + fp->_flags = flags | __SNBF; + fp->_w = 0; + fp->_bf._base = fp->_p = fp->_nbuf; + fp->_bf._size = 1; + funlockfile(fp); + return (ret); + } + flags |= __SMBF; + } + + /* + * Kill any seek optimization if the buffer is not the + * right size. + * + * SHOULD WE ALLOW MULTIPLES HERE (i.e., ok iff (size % iosize) == 0)? + */ + if (size != iosize) + flags |= __SNPT; + + /* + * Fix up the FILE fields, and set __cleanup for output flush on + * exit (since we are buffered in some way). If in r/w mode, go + * to the intermediate state, so that everyone has to call + * __srefill or __swsetup on the first operation -- it is more + * trouble than it is worth to set things up correctly here. + */ + if (mode == _IOLBF) + flags |= __SLBF; + if (flags & __SRW) + flags &= ~(__SRD | __SWR); + fp->_w = 0; + fp->_flags = flags; + fp->_bf._base = fp->_p = (unsigned char *)buf; + fp->_bf._size = size; + fp->_lbfsize = 0; + __cleanup = _cleanup; + + funlockfile(fp); + return (ret); +} diff --git a/lib/libpthread/stdio/snprintf.c b/lib/libpthread/stdio/snprintf.c new file mode 100644 index 00000000000..8aed707d401 --- /dev/null +++ b/lib/libpthread/stdio/snprintf.c @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)snprintf.c 5.1 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: snprintf.c,v 1.1 1995/10/18 08:43:09 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +#if __STDC__ +snprintf(char *str, size_t n, char const *fmt, ...) +#else +snprintf(str, n, fmt, va_alist) + char *str; + size_t n; + char *fmt; + va_dcl +#endif +{ + int ret; + va_list ap; + FILE f; + + if ((int)n < 1) + return (EOF); +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *)str; + f._bf._size = f._w = n - 1; + ret = vfprintf(&f, fmt, ap); + *f._p = 0; + va_end(ap); + return (ret); +} diff --git a/lib/libpthread/stdio/sprintf.c b/lib/libpthread/stdio/sprintf.c new file mode 100644 index 00000000000..cc57310cddc --- /dev/null +++ b/lib/libpthread/stdio/sprintf.c @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)sprintf.c 5.7 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: sprintf.c,v 1.1 1995/10/18 08:43:09 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif +#include <limits.h> +#include "local.h" + +#if __STDC__ +sprintf(char *str, char const *fmt, ...) +#else +sprintf(str, fmt, va_alist) + char *str; + char *fmt; + va_dcl +#endif +{ + int ret; + va_list ap; + FILE f; + + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *)str; + f._bf._size = f._w = INT_MAX; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + ret = vfprintf(&f, fmt, ap); + va_end(ap); + *f._p = 0; + return (ret); +} diff --git a/lib/libpthread/stdio/sscanf.c b/lib/libpthread/stdio/sscanf.c new file mode 100644 index 00000000000..959f8b67c37 --- /dev/null +++ b/lib/libpthread/stdio/sscanf.c @@ -0,0 +1,78 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)sscanf.c 5.1 (Berkeley) 1/20/91";*/ +static char *rcsid = "$Id: sscanf.c,v 1.1 1995/10/18 08:43:09 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> +#include <string.h> +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif +#include "local.h" + +#if __STDC__ +sscanf(const char *str, char const *fmt, ...) +#else +sscanf(str, fmt, va_alist) + const char *str; + char *fmt; + va_dcl +#endif +{ + int ret; + va_list ap; + FILE f; + + f._flags = __SRD; + f._file = -1; + f._bf._base = f._p = (unsigned char *)str; + f._bf._size = f._r = strlen(str); + f._ub._base = NULL; + f._lb._base = NULL; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + ret = __svfscanf(&f, fmt, ap); + va_end(ap); + return (ret); +} diff --git a/lib/libpthread/stdio/stdio.c b/lib/libpthread/stdio/stdio.c new file mode 100644 index 00000000000..d485da20fbb --- /dev/null +++ b/lib/libpthread/stdio/stdio.c @@ -0,0 +1,92 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)stdio.c 5.3 (Berkeley) 2/24/91";*/ +static char *rcsid = "$Id: stdio.c,v 1.1 1995/10/18 08:43:09 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include "local.h" + +/* + * Small standard I/O/seek/close functions. + * These maintain the `known seek offset' for seek optimisation. + */ +int __sread(FILE *fp, char *buf, int n) +{ + register int ret; + + /* if the read succeeded, update the current offset */ + if ((ret = fd_table[fp->_file]->ops->read(fd_table[fp->_file]->fd, + fd_table[fp->_file]->flags, buf, n)) >= 0) { + fp->_offset += ret; + } else { + fp->_flags &= ~__SOFF; /* paranoia */ + } + return (ret); +} + +int __swrite(FILE *fp, const char *buf, int n) +{ + if (fp->_flags & __SAPP) + (void) lseek(fp->_file, (off_t)0, SEEK_END); + fp->_flags &= ~__SOFF; /* in case FAPPEND mode is set */ + return(fd_table[fp->_file]->ops->write(fd_table[fp->_file]->fd, + fd_table[fp->_file]->flags, buf, n)); +} + +fpos_t __sseek(FILE *fp, fpos_t offset, int whence) +{ + register off_t ret; + + ret = lseek(fp->_file, (off_t)offset, whence); + if (ret == -1L) + fp->_flags &= ~__SOFF; + else { + fp->_flags |= __SOFF; + fp->_offset = ret; + } + return (ret); +} + +int __sclose(FILE *fp) +{ + return (close(fp->_file)); +} diff --git a/lib/libpthread/stdio/strerror.c b/lib/libpthread/stdio/strerror.c new file mode 100644 index 00000000000..5aea7e7a4fc --- /dev/null +++ b/lib/libpthread/stdio/strerror.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1988 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[] = "@(#)strerror.c 5.6 (Berkeley) 5/4/91"; +#endif /* LIBC_SCCS and not lint */ + +#include <string.h> + +char * +strerror(num) + int num; +{ + extern int sys_nerr; + extern char *sys_errlist[]; +#define UPREFIX "Unknown error: " + static char ebuf[40] = UPREFIX; /* 64-bit number + slop */ + register unsigned int errnum; + register char *p, *t; + char tmp[40]; + + errnum = num; /* convert to unsigned */ + if (errnum < sys_nerr) + return(sys_errlist[errnum]); + + /* Do this by hand, so we don't include stdio(3). */ + t = tmp; + do { + *t++ = "0123456789"[errnum % 10]; + } while (errnum /= 10); + for (p = ebuf + sizeof(UPREFIX) - 1;;) { + *p++ = *--t; + if (t <= tmp) + break; + } + return(ebuf); +} diff --git a/lib/libpthread/stdio/tempnam.c b/lib/libpthread/stdio/tempnam.c new file mode 100644 index 00000000000..95ecfeb3a5a --- /dev/null +++ b/lib/libpthread/stdio/tempnam.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1988 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: @(#)tempnam.c 5.1 (Berkeley) 2/22/91";*/ +static char *rcsid = "$Id: tempnam.c,v 1.1 1995/10/18 08:43:09 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/param.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <paths.h> + +char * +tempnam(dir, pfx) + const char *dir, *pfx; +{ + int sverrno; + char *f, *name; + + if (!(name = malloc(MAXPATHLEN))) + return(NULL); + + if (!pfx) + pfx = "tmp."; + + if (f = getenv("TMPDIR")) { + (void)snprintf(name, MAXPATHLEN, "%s%s%sXXXXXX", f, + *(f + strlen(f) - 1) == '/'? "": "/", pfx); + if (f = mktemp(name)) + return(f); + } + + if (f = (char *)dir) { + (void)snprintf(name, MAXPATHLEN, "%s%s%sXXXXXX", f, + *(f + strlen(f) - 1) == '/'? "": "/", pfx); + if (f = mktemp(name)) + return(f); + } + + f = P_tmpdir; + (void)snprintf(name, MAXPATHLEN, "%s%sXXXXXX", f, pfx); + if (f = mktemp(name)) + return(f); + + f = _PATH_TMP; + (void)snprintf(name, MAXPATHLEN, "%s%sXXXXXX", f, pfx); + if (f = mktemp(name)) + return(f); + + sverrno = errno; + free(name); + errno = sverrno; + return(NULL); +} diff --git a/lib/libpthread/stdio/tmpfile.c b/lib/libpthread/stdio/tmpfile.c new file mode 100644 index 00000000000..1e0fcfe60ce --- /dev/null +++ b/lib/libpthread/stdio/tmpfile.c @@ -0,0 +1,80 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)tmpfile.c 5.4 (Berkeley) 5/27/91";*/ +static char *rcsid = "$Id: tmpfile.c,v 1.1 1995/10/18 08:43:09 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/types.h> +#include <signal.h> +#include <unistd.h> +#include <errno.h> +#include <stdio.h> +#include <paths.h> + +FILE * +tmpfile() +{ + sigset_t set, oset; + FILE *fp; + int fd, sverrno; +#define TRAILER "tmp.XXXXXX" + char buf[sizeof(_PATH_TMP) + sizeof(TRAILER)]; + + bcopy(_PATH_TMP, buf, sizeof(_PATH_TMP) - 1); + bcopy(TRAILER, buf + sizeof(_PATH_TMP) - 1, sizeof(TRAILER)); + + sigfillset(&set); + (void)sigprocmask(SIG_BLOCK, &set, &oset); + + fd = mkstemp(buf); + if (fd != -1) + (void)unlink(buf); + + (void)sigprocmask(SIG_SETMASK, &oset, NULL); + + if (fd == -1) + return (NULL); + + if (!(fp = fdopen(fd, "w+"))) { + sverrno = errno; + (void)close(fd); + errno = sverrno; + return (NULL); + } + return (fp); +} diff --git a/lib/libpthread/stdio/tmpnam.c b/lib/libpthread/stdio/tmpnam.c new file mode 100644 index 00000000000..c5001e29c6f --- /dev/null +++ b/lib/libpthread/stdio/tmpnam.c @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)tmpnam.c 5.3 (Berkeley) 2/24/91";*/ +static char *rcsid = "$Id: tmpnam.c,v 1.1 1995/10/18 08:43:09 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <unistd.h> +#include <stdio.h> + +char * +tmpnam(s) + char *s; +{ + static char buf[L_tmpnam]; + + if (s == NULL) + s = buf; + (void)snprintf(s, L_tmpnam, "%stmp.XXXXXX", P_tmpdir); + return(mktemp(s)); +} diff --git a/lib/libpthread/stdio/ungetc.c b/lib/libpthread/stdio/ungetc.c new file mode 100644 index 00000000000..6366050da70 --- /dev/null +++ b/lib/libpthread/stdio/ungetc.c @@ -0,0 +1,154 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)ungetc.c 5.6 (Berkeley) 5/4/91";*/ +static char *rcsid = "$Id: ungetc.c,v 1.1 1995/10/18 08:43:09 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "local.h" + +/* + * Expand the ungetc buffer `in place'. That is, adjust fp->_p when + * the buffer moves, so that it points the same distance from the end, + * and move the bytes in the buffer around as necessary so that they + * are all at the end (stack-style). + */ +static +__submore(fp) + register FILE *fp; +{ + register int i; + register unsigned char *p; + + if (fp->_ub._base == fp->_ubuf) { + /* + * Get a new buffer (rather than expanding the old one). + */ + if ((p = malloc((size_t)BUFSIZ)) == NULL) + return (EOF); + fp->_ub._base = p; + fp->_ub._size = BUFSIZ; + p += BUFSIZ - sizeof(fp->_ubuf); + for (i = sizeof(fp->_ubuf); --i >= 0;) + p[i] = fp->_ubuf[i]; + fp->_p = p; + return (0); + } + i = fp->_ub._size; + p = realloc(fp->_ub._base, i << 1); + if (p == NULL) + return (EOF); + (void) bcopy((void *)p, (void *)(p + i), (size_t)i); + fp->_p = p + i; + fp->_ub._base = p; + fp->_ub._size = i << 1; + return (0); +} + +ungetc(c, fp) + int c; + register FILE *fp; +{ + if (c == EOF) + return (EOF); + pthread_once(&__sdidinit, __sinit); + + flockfile(fp); + if ((fp->_flags & __SRD) == 0) { + /* + * Not already reading: no good unless reading-and-writing. + * Otherwise, flush any current write stuff. + */ + if ((fp->_flags & __SRW) == 0) + c = EOF; + goto ungetc_end; + if (fp->_flags & __SWR) { + if (__sflush(fp)) + c = EOF; + goto ungetc_end; + fp->_flags &= ~__SWR; + fp->_w = 0; + fp->_lbfsize = 0; + } + fp->_flags |= __SRD; + } + c = (unsigned char)c; + + /* + * If we are in the middle of ungetc'ing, just continue. + * This may require expanding the current ungetc buffer. + */ + if (HASUB(fp)) { + if (fp->_r >= fp->_ub._size && __submore(fp)) + return (EOF); + *--fp->_p = c; + fp->_r++; + goto ungetc_end; + } + + /* + * If we can handle this by simply backing up, do so, + * but never replace the original character. + * (This makes sscanf() work when scanning `const' data.) + */ + if (fp->_bf._base != NULL && fp->_p > fp->_bf._base && + fp->_p[-1] == c) { + fp->_p--; + fp->_r++; + goto ungetc_end; + } + + /* + * Create an ungetc buffer. + * Initially, we will use the `reserve' buffer. + */ + fp->_ur = fp->_r; + fp->_up = fp->_p; + fp->_ub._base = fp->_ubuf; + fp->_ub._size = sizeof(fp->_ubuf); + fp->_ubuf[sizeof(fp->_ubuf) - 1] = c; + fp->_p = &fp->_ubuf[sizeof(fp->_ubuf) - 1]; + fp->_r = 1; + +ungetc_end:; + funlockfile(fp); + return (c); +} diff --git a/lib/libpthread/stdio/vfprintf.c b/lib/libpthread/stdio/vfprintf.c new file mode 100644 index 00000000000..c246e417980 --- /dev/null +++ b/lib/libpthread/stdio/vfprintf.c @@ -0,0 +1,774 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)vfprintf.c 5.50 (Berkeley) 12/16/92";*/ +static char *rcsid = "$Id: vfprintf.c,v 1.1 1995/10/18 08:43:09 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Actual printf innards. + * + * This code is large and complicated... + */ + +#include <pthread.h> +#include <sys/types.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "local.h" +#include "fvwrite.h" + +/* Define FLOATING_POINT to get floating point. */ +#define FLOATING_POINT + +/* + * Flush out all the vectors defined by the given uio, + * then reset it so that it can be reused. + */ +static int +__sprint(fp, uio) + register FILE* fp; + register struct __suio *uio; +{ + register int err; + + if (uio->uio_resid == 0) { + uio->uio_iovcnt = 0; + return (0); + } + err = __sfvwrite(fp, uio); + uio->uio_resid = 0; + uio->uio_iovcnt = 0; + return (err); +} + +/* + * Helper function for `fprintf to unbuffered unix file': creates a + * temporary buffer. We only work on write-only files; this avoids + * worries about ungetc buffers and so forth. + */ +static int +__sbprintf(fp, fmt, ap) + FILE *fp; + const char *fmt; + va_list ap; +{ + unsigned char buf[BUFSIZ]; + FILE fake; + int ret; + + /* copy the important variables */ + fake._flags = fp->_flags & ~__SNBF; + fake._file = fp->_file; + + /* set up the buffer */ + fake._bf._base = fake._p = buf; + fake._bf._size = fake._w = sizeof(buf); + fake._lbfsize = 0; /* not actually used, but Just In Case */ + + /* do the work, then copy any error status */ + ret = vfprintf(&fake, fmt, ap); + if (ret >= 0 && fflush(&fake)) + ret = EOF; + if (fake._flags & __SERR) + fp->_flags |= __SERR; + return (ret); +} + + +#ifdef FLOATING_POINT +#include <locale.h> +#include <math.h> +#include "floatio.h" + +#define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */ +#define DEFPREC 6 + +static char *cvt __P((double, int, int, char *, int *, int, int *)); +static int exponent __P((char *, int, int)); + +#else /* no FLOATING_POINT */ + +#define BUF 40 + +#endif /* FLOATING_POINT */ + + +/* + * Macros for converting digits to letters and vice versa + */ +#define to_digit(c) ((c) - '0') +#define is_digit(c) ((unsigned)to_digit(c) <= 9) +#define to_char(n) ((n) + '0') + +/* + * Flags used during conversion. + */ +#define ALT 0x001 /* alternate form */ +#define HEXPREFIX 0x002 /* add 0x or 0X prefix */ +#define LADJUST 0x004 /* left adjustment */ +#define LONGDBL 0x008 /* long double; unimplemented */ +#define LONGINT 0x010 /* long integer */ +#define QUADINT 0x020 /* quad integer */ +#define SHORTINT 0x040 /* short integer */ +#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */ +#define FPT 0x100 /* Floating point number */ +int +vfprintf(fp, fmt0, ap) + FILE *fp; + const char *fmt0; + va_list ap; +{ + register char *fmt; /* format string */ + register int ch; /* character from fmt */ + register int n; /* handy integer (short term usage) */ + register char *cp; /* handy char pointer (short term usage) */ + register struct __siov *iovp;/* for PRINT macro */ + register int flags; /* flags as above */ + int ret; /* return value accumulator */ + int width; /* width from format (%8d), or 0 */ + int prec; /* precision from format (%.3d), or -1 */ + char sign; /* sign prefix (' ', '+', '-', or \0) */ +#ifdef FLOATING_POINT + char softsign; /* temporary negative sign for floats */ + double _double; /* double precision arguments %[eEfgG] */ + int expt; /* integer value of exponent */ + int expsize; /* character count for expstr */ + int ndig; /* actual number of digits returned by cvt */ + char expstr[7]; /* buffer for exponent string */ +#endif + +#ifdef __GNUC__ /* gcc has builtin quad type (long long) SOS */ +#define quad_t long long +#define u_quad_t unsigned long long +#endif + + u_quad_t _uquad; /* integer arguments %[diouxX] */ + enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */ + int dprec; /* a copy of prec if [diouxX], 0 otherwise */ + int fieldsz; /* field size expanded by sign, etc */ + int realsz; /* field size expanded by dprec */ + int size; /* size of converted field or string */ + char *xdigs; /* digits for [xX] conversion */ +#define NIOV 8 + struct __suio uio; /* output information: summary */ + struct __siov iov[NIOV];/* ... and individual io vectors */ + char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */ + char ox[2]; /* space for 0x hex-prefix */ + + /* + * Choose PADSIZE to trade efficiency vs. size. If larger printf + * fields occur frequently, increase PADSIZE and make the initialisers + * below longer. + */ +#define PADSIZE 16 /* pad chunk size */ + static char blanks[PADSIZE] = + {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; + static char zeroes[PADSIZE] = + {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; + + /* + * BEWARE, these `goto error' on error, and PAD uses `n'. + */ +#define PRINT(ptr, len) { \ + iovp->iov_base = (ptr); \ + iovp->iov_len = (len); \ + uio.uio_resid += (len); \ + iovp++; \ + if (++uio.uio_iovcnt >= NIOV) { \ + if (__sprint(fp, &uio)) \ + goto error; \ + iovp = iov; \ + } \ +} +#define PAD(howmany, with) { \ + if ((n = (howmany)) > 0) { \ + while (n > PADSIZE) { \ + PRINT(with, PADSIZE); \ + n -= PADSIZE; \ + } \ + PRINT(with, n); \ + } \ +} +#define FLUSH() { \ + if (uio.uio_resid && __sprint(fp, &uio)) \ + goto error; \ + uio.uio_iovcnt = 0; \ + iovp = iov; \ +} + + /* + * To extend shorts properly, we need both signed and unsigned + * argument extraction methods. + */ +#define SARG() \ + (flags&QUADINT ? va_arg(ap, quad_t) : \ + flags&LONGINT ? va_arg(ap, long) : \ + flags&SHORTINT ? (long)(short)va_arg(ap, int) : \ + (long)va_arg(ap, int)) +#define UARG() \ + (flags&QUADINT ? va_arg(ap, u_quad_t) : \ + flags&LONGINT ? va_arg(ap, u_long) : \ + flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \ + (u_long)va_arg(ap, u_int)) + + flockfile(fp); + + /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */ + if (cantwrite(fp)) + return (EOF); + + /* optimise fprintf(stderr) (and other unbuffered Unix files) */ + if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && + fp->_file >= 0) { + ret = (__sbprintf(fp, fmt0, ap)); + funlockfile(fp); + return(ret); + } + + fmt = (char *)fmt0; + uio.uio_iov = iovp = iov; + uio.uio_resid = 0; + uio.uio_iovcnt = 0; + ret = 0; + + /* + * Scan the format for conversions (`%' character). + */ + for (;;) { + for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) + /* void */; + if ((n = fmt - cp) != 0) { + PRINT(cp, n); + ret += n; + } + if (ch == '\0') + goto done; + fmt++; /* skip over '%' */ + + flags = 0; + dprec = 0; + width = 0; + prec = -1; + sign = '\0'; + +rflag: ch = *fmt++; +reswitch: switch (ch) { + case ' ': + /* + * ``If the space and + flags both appear, the space + * flag will be ignored.'' + * -- ANSI X3J11 + */ + if (!sign) + sign = ' '; + goto rflag; + case '#': + flags |= ALT; + goto rflag; + case '*': + /* + * ``A negative field width argument is taken as a + * - flag followed by a positive field width.'' + * -- ANSI X3J11 + * They don't exclude field widths read from args. + */ + if ((width = va_arg(ap, int)) >= 0) + goto rflag; + width = -width; + /* FALLTHROUGH */ + case '-': + flags |= LADJUST; + goto rflag; + case '+': + sign = '+'; + goto rflag; + case '.': + if ((ch = *fmt++) == '*') { + n = va_arg(ap, int); + prec = n < 0 ? -1 : n; + goto rflag; + } + n = 0; + while (is_digit(ch)) { + n = 10 * n + to_digit(ch); + ch = *fmt++; + } + prec = n < 0 ? -1 : n; + goto reswitch; + case '0': + /* + * ``Note that 0 is taken as a flag, not as the + * beginning of a field width.'' + * -- ANSI X3J11 + */ + flags |= ZEROPAD; + goto rflag; + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + n = 0; + do { + n = 10 * n + to_digit(ch); + ch = *fmt++; + } while (is_digit(ch)); + width = n; + goto reswitch; +#ifdef FLOATING_POINT + case 'L': + flags |= LONGDBL; + goto rflag; +#endif + case 'h': + flags |= SHORTINT; + goto rflag; + case 'l': + flags |= LONGINT; + goto rflag; + case 'q': + flags |= QUADINT; + goto rflag; + case 'c': + *(cp = buf) = va_arg(ap, int); + size = 1; + sign = '\0'; + break; + case 'D': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'd': + case 'i': + _uquad = SARG(); + if ((quad_t)_uquad < 0) { + _uquad = -_uquad; + sign = '-'; + } + base = DEC; + goto number; +#ifdef FLOATING_POINT + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + if (prec == -1) { + prec = DEFPREC; + } else if ((ch == 'g' || ch == 'G') && prec == 0) { + prec = 1; + } + + if (flags & LONGDBL) { + _double = (double) va_arg(ap, long double); + } else { + _double = va_arg(ap, double); + } + + /* do this before tricky precision changes */ + /* if (isinf(_double)) { + if (_double < 0) + sign = '-'; + cp = "Inf"; + size = 3; + break; + } */ +/* if (isnan(_double)) { + cp = "NaN"; + size = 3; + break; + } */ + + flags |= FPT; + cp = cvt(_double, prec, flags, &softsign, + &expt, ch, &ndig); + if (ch == 'g' || ch == 'G') { + if (expt <= -4 || expt > prec) + ch = (ch == 'g') ? 'e' : 'E'; + else + ch = 'g'; + } + if (ch <= 'e') { /* 'e' or 'E' fmt */ + --expt; + expsize = exponent(expstr, expt, ch); + size = expsize + ndig; + if (ndig > 1 || flags & ALT) + ++size; + } else if (ch == 'f') { /* f fmt */ + if (expt > 0) { + size = expt; + if (prec || flags & ALT) + size += prec + 1; + } else /* "0.X" */ + size = prec + 2; + } else if (expt >= ndig) { /* fixed g fmt */ + size = expt; + if (flags & ALT) + ++size; + } else + size = ndig + (expt > 0 ? + 1 : 2 - expt); + + if (softsign) + sign = '-'; + break; +#endif /* FLOATING_POINT */ + case 'n': + if (flags & QUADINT) + *va_arg(ap, quad_t *) = ret; + else if (flags & LONGINT) + *va_arg(ap, long *) = ret; + else if (flags & SHORTINT) + *va_arg(ap, short *) = ret; + else + *va_arg(ap, int *) = ret; + continue; /* no output */ + case 'O': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'o': + _uquad = UARG(); + base = OCT; + goto nosign; + case 'p': + /* + * ``The argument shall be a pointer to void. The + * value of the pointer is converted to a sequence + * of printable characters, in an implementation- + * defined manner.'' + * -- ANSI X3J11 + */ + /* NOSTRICT */ + _uquad = (u_quad_t)va_arg(ap, void *); + base = HEX; + xdigs = "0123456789abcdef"; + flags |= HEXPREFIX; + ch = 'x'; + goto nosign; + case 's': + if ((cp = va_arg(ap, char *)) == NULL) + cp = "(null)"; + if (prec >= 0) { + /* + * can't use strlen; can only look for the + * NUL in the first `prec' characters, and + * strlen() will go further. + */ + char *p = memchr(cp, 0, prec); + + if (p != NULL) { + size = p - cp; + if (size > prec) + size = prec; + } else + size = prec; + } else + size = strlen(cp); + sign = '\0'; + break; + case 'U': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'u': + _uquad = UARG(); + base = DEC; + goto nosign; + case 'X': + xdigs = "0123456789ABCDEF"; + goto hex; + case 'x': + xdigs = "0123456789abcdef"; +hex: _uquad = UARG(); + base = HEX; + /* leading 0x/X only if non-zero */ + if (flags & ALT && _uquad != 0) + flags |= HEXPREFIX; + + /* unsigned conversions */ +nosign: sign = '\0'; + /* + * ``... diouXx conversions ... if a precision is + * specified, the 0 flag will be ignored.'' + * -- ANSI X3J11 + */ +number: if ((dprec = prec) >= 0) + flags &= ~ZEROPAD; + + /* + * ``The result of converting a zero value with an + * explicit precision of zero is no characters.'' + * -- ANSI X3J11 + */ + cp = buf + BUF; + if (_uquad != 0 || prec != 0) { + /* + * Unsigned mod is hard, and unsigned mod + * by a constant is easier than that by + * a variable; hence this switch. + */ + switch (base) { + case OCT: + do { + *--cp = to_char(_uquad & 7); + _uquad >>= 3; + } while (_uquad); + /* handle octal leading 0 */ + if (flags & ALT && *cp != '0') + *--cp = '0'; + break; + + case DEC: + /* many numbers are 1 digit */ + while (_uquad >= 10) { + *--cp = to_char(_uquad % 10); + _uquad /= 10; + } + *--cp = to_char(_uquad); + break; + + case HEX: + do { + *--cp = xdigs[_uquad & 15]; + _uquad >>= 4; + } while (_uquad); + break; + + default: + cp = "bug in vfprintf: bad base"; + size = strlen(cp); + goto skipsize; + } + } + size = buf + BUF - cp; + skipsize: + break; + default: /* "%?" prints ?, unless ? is NUL */ + if (ch == '\0') + goto done; + /* pretend it was %c with argument ch */ + cp = buf; + *cp = ch; + size = 1; + sign = '\0'; + break; + } + + /* + * All reasonable formats wind up here. At this point, `cp' + * points to a string which (if not flags&LADJUST) should be + * padded out to `width' places. If flags&ZEROPAD, it should + * first be prefixed by any sign or other prefix; otherwise, + * it should be blank padded before the prefix is emitted. + * After any left-hand padding and prefixing, emit zeroes + * required by a decimal [diouxX] precision, then print the + * string proper, then emit zeroes required by any leftover + * floating precision; finally, if LADJUST, pad with blanks. + * + * Compute actual size, so we know how much to pad. + * fieldsz excludes decimal prec; realsz includes it. + */ + fieldsz = size; + if (sign) + fieldsz++; + else if (flags & HEXPREFIX) + fieldsz += 2; + realsz = dprec > fieldsz ? dprec : fieldsz; + + /* right-adjusting blank padding */ + if ((flags & (LADJUST|ZEROPAD)) == 0) + PAD(width - realsz, blanks); + + /* prefix */ + if (sign) { + PRINT(&sign, 1); + } else if (flags & HEXPREFIX) { + ox[0] = '0'; + ox[1] = ch; + PRINT(ox, 2); + } + + /* right-adjusting zero padding */ + if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) + PAD(width - realsz, zeroes); + + /* leading zeroes from decimal precision */ + PAD(dprec - fieldsz, zeroes); + + /* the string or number proper */ +#ifdef FLOATING_POINT + if ((flags & FPT) == 0) { + PRINT(cp, size); + } else { /* glue together f_p fragments */ + if (ch >= 'f') { /* 'f' or 'g' */ + if (_double == 0) { + /* kludge for __dtoa irregularity */ + if (expt >= ndig && (flags & ALT) == 0) { + PRINT("0", 1); + } else { + PRINT("0.", 2); + PAD(ndig - 1, zeroes); + } + } else if (expt <= 0) { + PRINT("0.", 2); + PAD(-expt, zeroes); + PRINT(cp, ndig); + } else if (expt >= ndig) { + PRINT(cp, ndig); + PAD(expt - ndig, zeroes); + if (flags & ALT) + PRINT(".", 1); + } else { + PRINT(cp, expt); + cp += expt; + PRINT(".", 1); + PRINT(cp, ndig-expt); + } + } else { /* 'e' or 'E' */ + if (ndig > 1 || flags & ALT) { + ox[0] = *cp++; + ox[1] = '.'; + PRINT(ox, 2); + if (_double || flags & ALT == 0) { + PRINT(cp, ndig-1); + } else /* 0.[0..] */ + /* __dtoa irregularity */ + PAD(ndig - 1, zeroes); + } else /* XeYYY */ + PRINT(cp, 1); + PRINT(expstr, expsize); + } + } +#else + PRINT(cp, size); +#endif + /* left-adjusting padding (always blank) */ + if (flags & LADJUST) + PAD(width - realsz, blanks); + + /* finally, adjust ret */ + ret += width > realsz ? width : realsz; + + FLUSH(); /* copy out the I/O vectors */ + } +done: + FLUSH(); +error: + if (__sferror(fp)) + ret = EOF; + funlockfile(fp); + return (ret); +} + +#ifdef FLOATING_POINT + +extern char *__dtoa __P((double, int, int, int *, int *, char **)); + +static char * +cvt(value, ndigits, flags, sign, decpt, ch, length) + double value; + int ndigits, flags, *decpt, ch, *length; + char *sign; +{ + int mode, dsgn; + char *digits, *bp, *rve; + + if (ch == 'f') { + mode = 3; /* ndigits after the decimal point */ + } else { + /* To obtain ndigits after the decimal point for the 'e' + * and 'E' formats, round to ndigits + 1 significant + * figures. + */ + if (ch == 'e' || ch == 'E') { + ndigits++; + } + mode = 2; /* ndigits significant digits */ + } + + if (value < 0) { + value = -value; + *sign = '-'; + } else + *sign = '\000'; + digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve); + if ((ch != 'g' && ch != 'G') || flags & ALT) { /* Print trailing zeros */ + bp = digits + ndigits; + if (ch == 'f') { + if (*digits == '0' && value) + *decpt = -ndigits + 1; + bp += *decpt; + } + if (value == 0) /* kludge for __dtoa irregularity */ + rve = bp; + while (rve < bp) + *rve++ = '0'; + } + *length = rve - digits; + return (digits); +} + +static int +exponent(p0, exp, fmtch) + char *p0; + int exp, fmtch; +{ + register char *p, *t; + char expbuf[MAXEXP]; + + p = p0; + *p++ = fmtch; + if (exp < 0) { + exp = -exp; + *p++ = '-'; + } + else + *p++ = '+'; + t = expbuf + MAXEXP; + if (exp > 9) { + do { + *--t = to_char(exp % 10); + } while ((exp /= 10) > 9); + *--t = to_char(exp); + for (; t < expbuf + MAXEXP; *p++ = *t++); + } + else { + *p++ = '0'; + *p++ = to_char(exp); + } + return (p - p0); +} +#endif /* FLOATING_POINT */ diff --git a/lib/libpthread/stdio/vfscanf.c b/lib/libpthread/stdio/vfscanf.c new file mode 100644 index 00000000000..121c35404fa --- /dev/null +++ b/lib/libpthread/stdio/vfscanf.c @@ -0,0 +1,749 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)vfscanf.c 5.7 (Berkeley) 12/14/92";*/ +static char *rcsid = "$Id: vfscanf.c,v 1.1 1995/10/18 08:43:09 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif +#include "local.h" + +#define FLOATING_POINT + +#include "floatio.h" +#define BUF 513 /* Maximum length of numeric string. */ + +/* + * Flags used during conversion. + */ +#define LONG 0x01 /* l: long or double */ +#define LONGDBL 0x02 /* L: long double; unimplemented */ +#define SHORT 0x04 /* h: short */ +#define SUPPRESS 0x08 /* suppress assignment */ +#define POINTER 0x10 /* weird %p pointer (`fake hex') */ +#define NOSKIP 0x20 /* do not skip blanks */ + +/* + * The following are used in numeric conversions only: + * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point; + * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral. + */ +#define SIGNOK 0x40 /* +/- is (still) legal */ +#define NDIGITS 0x80 /* no digits detected */ + +#define DPTOK 0x100 /* (float) decimal point is still legal */ +#define EXPOK 0x200 /* (float) exponent (e+3, etc) still legal */ + +#define PFXOK 0x100 /* 0x prefix is (still) legal */ +#define NZDIGITS 0x200 /* no zero digits detected */ + +/* + * Conversion types. + */ +#define CT_CHAR 0 /* %c conversion */ +#define CT_CCL 1 /* %[...] conversion */ +#define CT_STRING 2 /* %s conversion */ +#define CT_INT 3 /* integer, i.e., strtol or strtoul */ +#define CT_FLOAT 4 /* floating, i.e., strtod */ + +#define u_char unsigned char +#define u_long unsigned long + +static u_char *__sccl(); + +/* + * vfscanf + */ +__svfscanf(fp, fmt0, ap) + register FILE *fp; + char const *fmt0; + va_list ap; +{ + register u_char *fmt = (u_char *)fmt0; + register int c; /* character from format, or conversion */ + register size_t width; /* field width, or 0 */ + register char *p; /* points into all kinds of strings */ + register int n; /* handy integer */ + register int flags; /* flags as defined above */ + register char *p0; /* saves original value of p when necessary */ + int nassigned; /* number of fields assigned */ + int nread; /* number of characters consumed from fp */ + int base; /* base argument to strtol/strtoul */ + u_long (*ccfn)(); /* conversion function (strtol/strtoul) */ + char ccltab[256]; /* character class table for %[...] */ + char buf[BUF]; /* buffer for numeric conversions */ + + /* `basefix' is used to avoid `if' tests in the integer scanner */ + static short basefix[17] = + { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; + + nassigned = 0; + nread = 0; + base = 0; /* XXX just to keep gcc happy */ + ccfn = NULL; /* XXX just to keep gcc happy */ + for (;;) { + c = *fmt++; + if (c == 0) + return (nassigned); + if (isspace(c)) { + for (;;) { + if (fp->_r <= 0 && __srefill(fp)) + return (nassigned); + if (!isspace(*fp->_p)) + break; + nread++, fp->_r--, fp->_p++; + } + continue; + } + if (c != '%') + goto literal; + width = 0; + flags = 0; + /* + * switch on the format. continue if done; + * break once format type is derived. + */ +again: c = *fmt++; + switch (c) { + case '%': +literal: + if (fp->_r <= 0 && __srefill(fp)) + goto input_failure; + if (*fp->_p != c) + goto match_failure; + fp->_r--, fp->_p++; + nread++; + continue; + + case '*': + flags |= SUPPRESS; + goto again; + case 'l': + flags |= LONG; + goto again; + case 'L': + flags |= LONGDBL; + goto again; + case 'h': + flags |= SHORT; + goto again; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + width = width * 10 + c - '0'; + goto again; + + /* + * Conversions. + * Those marked `compat' are for 4.[123]BSD compatibility. + * + * (According to ANSI, E and X formats are supposed + * to the same as e and x. Sorry about that.) + */ + case 'D': /* compat */ + flags |= LONG; + /* FALLTHROUGH */ + case 'd': + c = CT_INT; + ccfn = (u_long (*)())strtol; + base = 10; + break; + + case 'i': + c = CT_INT; + ccfn = (u_long (*)())strtol; + base = 0; + break; + + case 'O': /* compat */ + flags |= LONG; + /* FALLTHROUGH */ + case 'o': + c = CT_INT; + ccfn = strtoul; + base = 8; + break; + + case 'u': + c = CT_INT; + ccfn = strtoul; + base = 10; + break; + + case 'X': /* compat XXX */ + flags |= LONG; + /* FALLTHROUGH */ + case 'x': + flags |= PFXOK; /* enable 0x prefixing */ + c = CT_INT; + ccfn = strtoul; + base = 16; + break; + +#ifdef FLOATING_POINT + case 'E': /* compat XXX */ + case 'F': /* compat */ + flags |= LONG; + /* FALLTHROUGH */ + case 'e': case 'f': case 'g': + c = CT_FLOAT; + break; +#endif + + case 's': + c = CT_STRING; + break; + + case '[': + fmt = __sccl(ccltab, fmt); + flags |= NOSKIP; + c = CT_CCL; + break; + + case 'c': + flags |= NOSKIP; + c = CT_CHAR; + break; + + case 'p': /* pointer format is like hex */ + flags |= POINTER | PFXOK; + c = CT_INT; + ccfn = strtoul; + base = 16; + break; + + case 'n': + if (flags & SUPPRESS) /* ??? */ + continue; + if (flags & SHORT) + *va_arg(ap, short *) = nread; + else if (flags & LONG) + *va_arg(ap, long *) = nread; + else + *va_arg(ap, int *) = nread; + continue; + + /* + * Disgusting backwards compatibility hacks. XXX + */ + case '\0': /* compat */ + return (EOF); + + default: /* compat */ + if (isupper(c)) + flags |= LONG; + c = CT_INT; + ccfn = (u_long (*)())strtol; + base = 10; + break; + } + + /* + * We have a conversion that requires input. + */ + if (fp->_r <= 0 && __srefill(fp)) + goto input_failure; + + /* + * Consume leading white space, except for formats + * that suppress this. + */ + if ((flags & NOSKIP) == 0) { + while (isspace(*fp->_p)) { + nread++; + if (--fp->_r > 0) + fp->_p++; + else if (__srefill(fp)) + goto input_failure; + } + /* + * Note that there is at least one character in + * the buffer, so conversions that do not set NOSKIP + * ca no longer result in an input failure. + */ + } + + /* + * Do the conversion. + */ + switch (c) { + + case CT_CHAR: + /* scan arbitrary characters (sets NOSKIP) */ + if (width == 0) + width = 1; + if (flags & SUPPRESS) { + size_t sum = 0; + for (;;) { + if ((n = fp->_r) < width) { + sum += n; + width -= n; + fp->_p += n; + if (__srefill(fp)) { + if (sum == 0) + goto input_failure; + break; + } + } else { + sum += width; + fp->_r -= width; + fp->_p += width; + break; + } + } + nread += sum; + } else { + size_t r = fread((void *)va_arg(ap, char *), 1, + width, fp); + + if (r == 0) + goto input_failure; + nread += r; + nassigned++; + } + break; + + case CT_CCL: + /* scan a (nonempty) character class (sets NOSKIP) */ + if (width == 0) + width = ~0; /* `infinity' */ + /* take only those things in the class */ + if (flags & SUPPRESS) { + n = 0; + while (ccltab[*fp->_p]) { + n++, fp->_r--, fp->_p++; + if (--width == 0) + break; + if (fp->_r <= 0 && __srefill(fp)) { + if (n == 0) + goto input_failure; + break; + } + } + if (n == 0) + goto match_failure; + } else { + p0 = p = va_arg(ap, char *); + while (ccltab[*fp->_p]) { + fp->_r--; + *p++ = *fp->_p++; + if (--width == 0) + break; + if (fp->_r <= 0 && __srefill(fp)) { + if (p == p0) + goto input_failure; + break; + } + } + n = p - p0; + if (n == 0) + goto match_failure; + *p = 0; + nassigned++; + } + nread += n; + break; + + case CT_STRING: + /* like CCL, but zero-length string OK, & no NOSKIP */ + if (width == 0) + width = ~0; + if (flags & SUPPRESS) { + n = 0; + while (!isspace(*fp->_p)) { + n++, fp->_r--, fp->_p++; + if (--width == 0) + break; + if (fp->_r <= 0 && __srefill(fp)) + break; + } + nread += n; + } else { + p0 = p = va_arg(ap, char *); + while (!isspace(*fp->_p)) { + fp->_r--; + *p++ = *fp->_p++; + if (--width == 0) + break; + if (fp->_r <= 0 && __srefill(fp)) + break; + } + *p = 0; + nread += p - p0; + nassigned++; + } + continue; + + case CT_INT: + /* scan an integer as if by strtol/strtoul */ +#ifdef hardway + if (width == 0 || width > sizeof(buf) - 1) + width = sizeof(buf) - 1; +#else + /* size_t is unsigned, hence this optimisation */ + if (--width > sizeof(buf) - 2) + width = sizeof(buf) - 2; + width++; +#endif + flags |= SIGNOK | NDIGITS | NZDIGITS; + for (p = buf; width; width--) { + c = *fp->_p; + /* + * Switch on the character; `goto ok' + * if we accept it as a part of number. + */ + switch (c) { + + /* + * The digit 0 is always legal, but is + * special. For %i conversions, if no + * digits (zero or nonzero) have been + * scanned (only signs), we will have + * base==0. In that case, we should set + * it to 8 and enable 0x prefixing. + * Also, if we have not scanned zero digits + * before this, do not turn off prefixing + * (someone else will turn it off if we + * have scanned any nonzero digits). + */ + case '0': + if (base == 0) { + base = 8; + flags |= PFXOK; + } + if (flags & NZDIGITS) + flags &= ~(SIGNOK|NZDIGITS|NDIGITS); + else + flags &= ~(SIGNOK|PFXOK|NDIGITS); + goto ok; + + /* 1 through 7 always legal */ + case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + base = basefix[base]; + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* digits 8 and 9 ok iff decimal or hex */ + case '8': case '9': + base = basefix[base]; + if (base <= 8) + break; /* not legal here */ + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* letters ok iff hex */ + case 'A': case 'B': case 'C': + case 'D': case 'E': case 'F': + case 'a': case 'b': case 'c': + case 'd': case 'e': case 'f': + /* no need to fix base here */ + if (base <= 10) + break; /* not legal here */ + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* sign ok only as first character */ + case '+': case '-': + if (flags & SIGNOK) { + flags &= ~SIGNOK; + goto ok; + } + break; + + /* x ok iff flag still set & 2nd char */ + case 'x': case 'X': + if (flags & PFXOK && p == buf + 1) { + base = 16; /* if %i */ + flags &= ~PFXOK; + goto ok; + } + break; + } + + /* + * If we got here, c is not a legal character + * for a number. Stop accumulating digits. + */ + break; + ok: + /* + * c is legal: store it and look at the next. + */ + *p++ = c; + if (--fp->_r > 0) + fp->_p++; + else if (__srefill(fp)) + break; /* EOF */ + } + /* + * If we had only a sign, it is no good; push + * back the sign. If the number ends in `x', + * it was [sign] '0' 'x', so push back the x + * and treat it as [sign] '0'. + */ + if (flags & NDIGITS) { + if (p > buf) + (void) ungetc(*(u_char *)--p, fp); + goto match_failure; + } + c = ((u_char *)p)[-1]; + if (c == 'x' || c == 'X') { + --p; + (void) ungetc(c, fp); + } + if ((flags & SUPPRESS) == 0) { + u_long res; + + *p = 0; + res = (*ccfn)(buf, (char **)NULL, base); + if (flags & POINTER) + *va_arg(ap, void **) = (void *)res; + else if (flags & SHORT) + *va_arg(ap, short *) = res; + else if (flags & LONG) + *va_arg(ap, long *) = res; + else + *va_arg(ap, int *) = res; + nassigned++; + } + nread += p - buf; + break; + +#ifdef FLOATING_POINT + case CT_FLOAT: + /* scan a floating point number as if by strtod */ +#ifdef hardway + if (width == 0 || width > sizeof(buf) - 1) + width = sizeof(buf) - 1; +#else + /* size_t is unsigned, hence this optimisation */ + if (--width > sizeof(buf) - 2) + width = sizeof(buf) - 2; + width++; +#endif + flags |= SIGNOK | NDIGITS | DPTOK | EXPOK; + for (p = buf; width; width--) { + c = *fp->_p; + /* + * This code mimicks the integer conversion + * code, but is much simpler. + */ + switch (c) { + + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case '8': case '9': + flags &= ~(SIGNOK | NDIGITS); + goto fok; + + case '+': case '-': + if (flags & SIGNOK) { + flags &= ~SIGNOK; + goto fok; + } + break; + case '.': + if (flags & DPTOK) { + flags &= ~(SIGNOK | DPTOK); + goto fok; + } + break; + case 'e': case 'E': + /* no exponent without some digits */ + if ((flags&(NDIGITS|EXPOK)) == EXPOK) { + flags = + (flags & ~(EXPOK|DPTOK)) | + SIGNOK | NDIGITS; + goto fok; + } + break; + } + break; + fok: + *p++ = c; + if (--fp->_r > 0) + fp->_p++; + else if (__srefill(fp)) + break; /* EOF */ + } + /* + * If no digits, might be missing exponent digits + * (just give back the exponent) or might be missing + * regular digits, but had sign and/or decimal point. + */ + if (flags & NDIGITS) { + if (flags & EXPOK) { + /* no digits at all */ + while (p > buf) + ungetc(*(u_char *)--p, fp); + goto match_failure; + } + /* just a bad exponent (e and maybe sign) */ + c = *(u_char *)--p; + if (c != 'e' && c != 'E') { + (void) ungetc(c, fp);/* sign */ + c = *(u_char *)--p; + } + (void) ungetc(c, fp); + } + if ((flags & SUPPRESS) == 0) { + double res; + + *p = 0; + res = strtod(buf, (char **) NULL); + if (flags & LONG) + *va_arg(ap, double *) = res; + else + *va_arg(ap, float *) = res; + nassigned++; + } + nread += p - buf; + break; +#endif /* FLOATING_POINT */ + } + } +input_failure: + return (nassigned ? nassigned : -1); +match_failure: + return (nassigned); +} + +/* + * Fill in the given table from the scanset at the given format + * (just after `['). Return a pointer to the character past the + * closing `]'. The table has a 1 wherever characters should be + * considered part of the scanset. + */ +static u_char * +__sccl(tab, fmt) + register char *tab; + register u_char *fmt; +{ + register int c, n, v; + + /* first `clear' the whole table */ + c = *fmt++; /* first char hat => negated scanset */ + if (c == '^') { + v = 1; /* default => accept */ + c = *fmt++; /* get new first char */ + } else + v = 0; /* default => reject */ + /* should probably use memset here */ + for (n = 0; n < 256; n++) + tab[n] = v; + if (c == 0) + return (fmt - 1);/* format ended before closing ] */ + + /* + * Now set the entries corresponding to the actual scanset + * to the opposite of the above. + * + * The first character may be ']' (or '-') without being special; + * the last character may be '-'. + */ + v = 1 - v; + for (;;) { + tab[c] = v; /* take character c */ +doswitch: + n = *fmt++; /* and examine the next */ + switch (n) { + + case 0: /* format ended too soon */ + return (fmt - 1); + + case '-': + /* + * A scanset of the form + * [01+-] + * is defined as `the digit 0, the digit 1, + * the character +, the character -', but + * the effect of a scanset such as + * [a-zA-Z0-9] + * is implementation defined. The V7 Unix + * scanf treats `a-z' as `the letters a through + * z', but treats `a-a' as `the letter a, the + * character -, and the letter a'. + * + * For compatibility, the `-' is not considerd + * to define a range if the character following + * it is either a close bracket (required by ANSI) + * or is not numerically greater than the character + * we just stored in the table (c). + */ + n = *fmt; + if (n == ']' || n < c) { + c = '-'; + break; /* resume the for(;;) */ + } + fmt++; + do { /* fill in the range */ + tab[++c] = v; + } while (c < n); +#if 1 /* XXX another disgusting compatibility hack */ + /* + * Alas, the V7 Unix scanf also treats formats + * such as [a-c-e] as `the letters a through e'. + * This too is permitted by the standard.... + */ + goto doswitch; +#else + c = *fmt++; + if (c == 0) + return (fmt - 1); + if (c == ']') + return (fmt); +#endif + break; + + case ']': /* end of scanset */ + return (fmt); + + default: /* just another character */ + c = n; + break; + } + } + /* NOTREACHED */ +} diff --git a/lib/libpthread/stdio/vprintf.c b/lib/libpthread/stdio/vprintf.c new file mode 100644 index 00000000000..62655e0f438 --- /dev/null +++ b/lib/libpthread/stdio/vprintf.c @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)vprintf.c 5.6 (Berkeley) 2/24/91";*/ +static char *rcsid = "$Id: vprintf.c,v 1.1 1995/10/18 08:43:09 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> + +vprintf(fmt, ap) + char const *fmt; + va_list ap; +{ + return (vfprintf(stdout, fmt, ap)); +} diff --git a/lib/libpthread/stdio/vscanf.c b/lib/libpthread/stdio/vscanf.c new file mode 100644 index 00000000000..c4c95901b47 --- /dev/null +++ b/lib/libpthread/stdio/vscanf.c @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Donn Seeley at UUNET Technologies, Inc. + * + * 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: @(#)vscanf.c 5.1 (Berkeley) 4/15/91";*/ +static char *rcsid = "$Id: vscanf.c,v 1.1 1995/10/18 08:43:09 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> + +vscanf(fmt, ap) + const char *fmt; + va_list ap; +{ + int r; + flockfile(stdin); + r = __svfscanf(stdin, fmt, ap); + funlockfile(stdin); + return(r); +} diff --git a/lib/libpthread/stdio/vsnprintf.c b/lib/libpthread/stdio/vsnprintf.c new file mode 100644 index 00000000000..672c86b2331 --- /dev/null +++ b/lib/libpthread/stdio/vsnprintf.c @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)vsnprintf.c 5.2 (Berkeley) 2/5/91";*/ +static char *rcsid = "$Id: vsnprintf.c,v 1.1 1995/10/18 08:43:09 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> + +vsnprintf(str, n, fmt, ap) + char *str; + size_t n; + const char *fmt; + va_list ap; +{ + int ret; + FILE f; + + if ((int)n < 1) + return (EOF); + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *)str; + f._bf._size = f._w = n - 1; + ret = vfprintf(&f, fmt, ap); + *f._p = 0; + return (ret); +} diff --git a/lib/libpthread/stdio/vsprintf.c b/lib/libpthread/stdio/vsprintf.c new file mode 100644 index 00000000000..d97f8b4723a --- /dev/null +++ b/lib/libpthread/stdio/vsprintf.c @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)vsprintf.c 5.5 (Berkeley) 2/5/91";*/ +static char *rcsid = "$Id: vsprintf.c,v 1.1 1995/10/18 08:43:09 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> +#include <limits.h> + +vsprintf(str, fmt, ap) + char *str; + const char *fmt; + va_list ap; +{ + int ret; + FILE f; + + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *)str; + f._bf._size = f._w = INT_MAX; + ret = vfprintf(&f, fmt, ap); + *f._p = 0; + return (ret); +} diff --git a/lib/libpthread/stdio/vsscanf.c b/lib/libpthread/stdio/vsscanf.c new file mode 100644 index 00000000000..a639a787a7c --- /dev/null +++ b/lib/libpthread/stdio/vsscanf.c @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Donn Seeley at UUNET Technologies, Inc. + * + * 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: @(#)vsscanf.c 5.1 (Berkeley) 4/15/91";*/ +static char *rcsid = "$Id: vsscanf.c,v 1.1 1995/10/18 08:43:09 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> +#include <string.h> + +vsscanf(str, fmt, ap) + const char *str; + const char *fmt; + va_list ap; +{ + int ret; + FILE f; + + f._flags = __SRD; + f._file = -1; /* This will do the right thing */ + f._bf._base = f._p = (unsigned char *)str; + f._bf._size = f._r = strlen(str); + f._ub._base = NULL; + f._lb._base = NULL; + return (__svfscanf(&f, fmt, ap)); +} diff --git a/lib/libpthread/stdio/wbuf.c b/lib/libpthread/stdio/wbuf.c new file mode 100644 index 00000000000..63d8f9e3648 --- /dev/null +++ b/lib/libpthread/stdio/wbuf.c @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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[] = "@(#)wbuf.c 5.6 (Berkeley) 1/20/91"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> +#include "local.h" + +/* + * Write the given character into the (probably full) buffer for + * the given file. Flush the buffer out if it is or becomes full, + * or if c=='\n' and the file is line buffered. + */ +__swbuf(c, fp) + register int c; + register FILE *fp; +{ + register int n; + + /* + * In case we cannot write, or longjmp takes us out early, + * make sure _w is 0 (if fully- or un-buffered) or -_bf._size + * (if line buffered) so that we will get called again. + * If we did not do this, a sufficient number of putc() + * calls might wrap _w from negative to positive. + */ + fp->_w = fp->_lbfsize; + if (cantwrite(fp)) + return (EOF); + c = (unsigned char)c; + + /* + * If it is completely full, flush it out. Then, in any case, + * stuff c into the buffer. If this causes the buffer to fill + * completely, or if c is '\n' and the file is line buffered, + * flush it (perhaps a second time). The second flush will always + * happen on unbuffered streams, where _bf._size==1; fflush() + * guarantees that putc() will always call wbuf() by setting _w + * to 0, so we need not do anything else. + */ + n = fp->_p - fp->_bf._base; + if (n >= fp->_bf._size) { + if (fflush(fp)) + return (EOF); + n = 0; + } + fp->_w--; + *fp->_p++ = c; + if (++n == fp->_bf._size || (fp->_flags & __SLBF && c == '\n')) + if (fflush(fp)) + return (EOF); + return (c); +} diff --git a/lib/libpthread/stdio/wsetup.c b/lib/libpthread/stdio/wsetup.c new file mode 100644 index 00000000000..16941e113b2 --- /dev/null +++ b/lib/libpthread/stdio/wsetup.c @@ -0,0 +1,92 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: @(#)wsetup.c 5.2 (Berkeley) 2/24/91";*/ +static char *rcsid = "$Id: wsetup.c,v 1.1 1995/10/18 08:43:09 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include "local.h" + +/* + * Various output routines call wsetup to be sure it is safe to write, + * because either _flags does not include __SWR, or _buf is NULL. + * _wsetup returns 0 if OK to write, nonzero otherwise. + */ +__swsetup(fp) + register FILE *fp; +{ + /* make sure stdio is set up */ + if (!__sdidinit) + __sinit(); + + /* + * If we are not writing, we had better be reading and writing. + */ + if ((fp->_flags & __SWR) == 0) { + if ((fp->_flags & __SRW) == 0) + return (EOF); + if (fp->_flags & __SRD) { + /* clobber any ungetc data */ + if (HASUB(fp)) + FREEUB(fp); + fp->_flags &= ~(__SRD|__SEOF); + fp->_r = 0; + fp->_p = fp->_bf._base; + } + fp->_flags |= __SWR; + } + + /* + * Make a buffer if necessary, then set _w. + */ + if (fp->_bf._base == NULL) + __smakebuf(fp); + if (fp->_flags & __SLBF) { + /* + * It is line buffered, so make _lbfsize be -_bufsize + * for the putc() macro. We will change _lbfsize back + * to 0 whenever we turn off __SWR. + */ + fp->_w = 0; + fp->_lbfsize = -fp->_bf._size; + } else + fp->_w = fp->_flags & __SNBF ? 0 : fp->_bf._size; + return (0); +} |