diff options
author | Roland McGrath <roland@gnu.org> | 1995-02-18 01:27:10 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 1995-02-18 01:27:10 +0000 |
commit | 28f540f45bbacd939bfd07f213bcad2bf730b1bf (patch) | |
tree | 15f07c4c43d635959c6afee96bde71fb1b3614ee /sysdeps/posix | |
download | glibc-28f540f45bbacd939bfd07f213bcad2bf730b1bf.tar.gz glibc-28f540f45bbacd939bfd07f213bcad2bf730b1bf.tar.xz glibc-28f540f45bbacd939bfd07f213bcad2bf730b1bf.zip |
initial import
Diffstat (limited to 'sysdeps/posix')
43 files changed, 3260 insertions, 0 deletions
diff --git a/sysdeps/posix/Dist b/sysdeps/posix/Dist new file mode 100644 index 0000000000..d003c6e781 --- /dev/null +++ b/sysdeps/posix/Dist @@ -0,0 +1 @@ +mk-stdiolim.c diff --git a/sysdeps/posix/Makefile b/sysdeps/posix/Makefile new file mode 100644 index 0000000000..fd1b3f257a --- /dev/null +++ b/sysdeps/posix/Makefile @@ -0,0 +1,40 @@ +# Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc. +# This file is part of the GNU C Library. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. + +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. + +# You should have received a copy of the GNU Library General Public +# License along with the GNU C Library; see the file COPYING.LIB. If +# not, write to the Free Software Foundation, Inc., 675 Mass Ave, +# Cambridge, MA 02139, USA. + +$(common-objpfx)stdio_lim.h: $(common-objpfx)mk-stdiolim + $(dir $<)$(notdir $<) > $@-t + mv $@-t $@ + +ifdef subdir +objdir-CPPFLAGS = $(CPPFLAGS) # Already has appropriate `..'s. +else +objdir-CPPFLAGS = $(patsubst -I/..//%,-I/%,$(CPPFLAGS:-I%=-I../%)) +endif +# Turn into a version that works when cd'd into $(objdir). +cded-objdir-CPPFLAGS = $(patsubst -I$$cwd//%,-I/%,\ + $(patsubst -I%,-I$$cwd/%,$(CPPFLAGS))) +# $(BUILD_CFLAGS) needs to come last because it contains unwanted -Is. +$(common-objpfx)mk-stdiolim: $(sysdep_dir)/posix/mk-stdiolim.c \ + posix1_lim.h local_lim.h + cwd=`pwd`; cd $(common-objdir); \ + $(BUILD_CC) $(cded-objdir-CPPFLAGS) $(BUILD_CFLAGS) \ + $$cwd/$< -o $(patsubst $(common-objpfx)%,%,$@) + + +common-generated := $(common-generated) stdio_lim.h mk-stdiolim +before-compile := $(before-compile) $(common-objpfx)stdio_lim.h diff --git a/sysdeps/posix/clock.c b/sysdeps/posix/clock.c new file mode 100644 index 0000000000..c34593b9eb --- /dev/null +++ b/sysdeps/posix/clock.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <sys/times.h> +#include <time.h> + +/* Return the time used by the program so far (user time + system time). */ +clock_t +DEFUN_VOID(clock) +{ + struct tms buf; + + if (__times(&buf) < 0) + return (clock_t) -1; + + return ((buf.tms_utime + buf.tms_stime) * CLK_TCK * CLOCKS_PER_SEC); +} diff --git a/sysdeps/posix/ctermid.c b/sysdeps/posix/ctermid.c new file mode 100644 index 0000000000..8e96694841 --- /dev/null +++ b/sysdeps/posix/ctermid.c @@ -0,0 +1,39 @@ +/* Copyright (C) 1991 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <stdio.h> +#include <string.h> + + +/* Return the name of the controlling terminal. + If S is not NULL, the name is copied into it (it should be at + least L_ctermid bytes long), otherwise a static buffer is used. */ +char * +DEFUN(ctermid, (s), char *s) +{ + static char name[L_ctermid]; + + if (name[0] == '\0') + (void) strcpy(name, "/dev/tty"); + + if (s == NULL) + return(name); + + return(strcpy(s, name)); +} diff --git a/sysdeps/posix/cuserid.c b/sysdeps/posix/cuserid.c new file mode 100644 index 0000000000..b874e909ce --- /dev/null +++ b/sysdeps/posix/cuserid.c @@ -0,0 +1,46 @@ +/* Copyright (C) 1991 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <stdio.h> +#include <string.h> +#include <pwd.h> + +extern int EXFUN(geteuid, (NOARGS)); + + +/* Return the username of the caller. + If S is not NULL, it points to a buffer of at least L_cuserid bytes + into which the name is copied; otherwise, a static buffer is used. */ +char * +DEFUN(cuserid, (s), char *s) +{ + static char name[L_cuserid]; + struct passwd *pwent = getpwuid(geteuid()); + + if (pwent == NULL) + { + if (s != NULL) + s[0] = '\0'; + return NULL; + } + + if (s == NULL) + s = name; + return strcpy(s, pwent->pw_name); +} diff --git a/sysdeps/posix/defs.c b/sysdeps/posix/defs.c new file mode 100644 index 0000000000..fcbaf16f69 --- /dev/null +++ b/sysdeps/posix/defs.c @@ -0,0 +1,76 @@ +/* Definitions of global stdio data structures. + +Copyright (C) 1991, 1993 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <stddef.h> +#include <stdio.h> +#include <unistd.h> + +/* This file defines all the global internal variables for stdio. */ + +/* Standard streams. */ +#define READ 1, 0 +#define WRITE 0, 1 +#define BUFFERED 0 +#define UNBUFFERED 1 +#define stdstream(name, next, fd, readwrite, unbuffered) \ + { \ + _IOMAGIC, \ + NULL, NULL, NULL, NULL, 0, \ + (PTR) fd, \ + { readwrite, /* ... */ }, \ + { NULL, NULL, NULL, NULL, NULL }, \ + { NULL, NULL }, \ + -1, -1, \ + (next), \ + NULL, '\0', 0, \ + 0, 0, unbuffered, 0, 0, 0, 0 \ + } +static FILE stdstreams[3] = + { + stdstream (&stdstreams[0], &stdstreams[1], STDIN_FILENO, READ, BUFFERED), + stdstream (&stdstreams[1], &stdstreams[2], STDOUT_FILENO, WRITE, BUFFERED), + stdstream (&stdstreams[2], NULL, STDERR_FILENO, WRITE, UNBUFFERED), + }; +FILE *stdin = &stdstreams[0]; +FILE *stdout = &stdstreams[1]; +FILE *stderr = &stdstreams[2]; + +/* Pointer to the first stream in the list. */ +FILE *__stdio_head = &stdstreams[0]; + +/* This function MUST be in this file! + This is because we want _cleanup to go into the __libc_atexit set + when any stdio code is used (and to use any stdio code, one must reference + something defined in this file), and since only local symbols can be made + set elements, having the set element stab entry here and _cleanup elsewhere + loses; and having them both elsewhere loses because there is no reference + to cause _cleanup to be linked in. */ + +void +DEFUN_VOID(_cleanup) +{ + (void) fclose((FILE *) NULL); +} + + +#ifdef HAVE_GNU_LD +text_set_element(__libc_atexit, _cleanup); +#endif diff --git a/sysdeps/posix/dup.c b/sysdeps/posix/dup.c new file mode 100644 index 0000000000..73c5900f9c --- /dev/null +++ b/sysdeps/posix/dup.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1991, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> + + +/* Duplicate FD, returning a new file descriptor open on the same file. */ +int +DEFUN(__dup, (fd), int fd) +{ + return fcntl(fd, F_DUPFD, 0); +} + +weak_alias (__dup, dup) diff --git a/sysdeps/posix/dup2.c b/sysdeps/posix/dup2.c new file mode 100644 index 0000000000..c0c6b2a0f6 --- /dev/null +++ b/sysdeps/posix/dup2.c @@ -0,0 +1,59 @@ +/* Copyright (C) 1991, 1992, 1993, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <unistd.h> + + +/* Duplicate FD to FD2, closing the old FD2 and making FD2 be + open the same file as FD is. Return FD2 or -1. */ +int +DEFUN(__dup2, (fd, fd2), int fd AND int fd2) +{ + int save; + + if (fd2 < 0 +#ifdef OPEN_MAX + || fd2 >= OPEN_MAX +#endif +) + { + errno = EBADF; + return -1; + } + + /* Check if FD is kosher. */ + if (fcntl (fd, F_GETFL) < 0) + return -1; + + if (fd == fd2) + return fd2; + + /* This is not atomic. */ + + save = errno; + (void) close (fd2); + errno = save; + + return fcntl (fd, F_DUPFD, fd2); +} + +weak_alias (__dup2, dup2) diff --git a/sysdeps/posix/fdopen.c b/sysdeps/posix/fdopen.c new file mode 100644 index 0000000000..ad746ec371 --- /dev/null +++ b/sysdeps/posix/fdopen.c @@ -0,0 +1,72 @@ +/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <errno.h> +#include <stdio.h> +#include <fcntl.h> + +/* Defined in fopen.c. */ +extern int EXFUN(__getmode, (CONST char *mode, __io_mode *mptr)); + +/* Open a new stream on a given system file descriptor. */ +FILE * +DEFUN(fdopen, (fd, mode), int fd AND CONST char *mode) +{ + register FILE *stream; + __io_mode m; + int dflags; + + if (!__getmode (mode, &m)) + return NULL; + + /* Verify the FD is valid and allows the access MODE specifies. */ + + dflags = __fcntl (fd, F_GETFL); + if (dflags == -1) + /* FD was invalid; fcntl has already set errno. */ + return NULL; + + /* Check the access mode. */ + switch (dflags & O_ACCMODE) + { + case O_RDONLY: + if (!m.__read) + { + errno = EBADF; + return NULL; + } + break; + case O_WRONLY: + if (!m.__write) + { + errno = EBADF; + return NULL; + } + break; + } + + stream = __newstream (); + if (stream == NULL) + return NULL; + + stream->__cookie = (PTR) fd; + stream->__mode = m; + + return stream; +} diff --git a/sysdeps/posix/flock.c b/sysdeps/posix/flock.c new file mode 100644 index 0000000000..b4c9fc3b79 --- /dev/null +++ b/sysdeps/posix/flock.c @@ -0,0 +1,58 @@ +/* Copyright (C) 1992, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* This file implements the `flock' function in terms of the POSIX.1 `fcntl' + locking mechanism. In 4BSD, these are two incompatible locking mechanisms, + perhaps with different semantics? */ + +#include <ansidecl.h> +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/file.h> + +/* Apply or remove an advisory lock, according to OPERATION, + on the file FD refers to. */ +int +DEFUN(__flock, (fd, operation), int fd AND int operation) +{ + struct flock lbuf; + + switch (operation & ~LOCK_NB) + { + case LOCK_SH: + lbuf.l_type = F_RDLCK; + break; + case LOCK_EX: + lbuf.l_type = F_WRLCK; + break; + case LOCK_UN: + lbuf.l_type = F_UNLCK; + break; + default: + errno = EINVAL; + return -1; + } + + lbuf.l_whence = SEEK_SET; + lbuf.l_start = lbuf.l_len = 0L; /* Lock the whole file. */ + + return __fcntl (fd, (operation & LOCK_NB) ? F_SETLK : F_SETLKW, &lbuf); +} + +weak_alias (__flock, flock) diff --git a/sysdeps/posix/fpathconf.c b/sysdeps/posix/fpathconf.c new file mode 100644 index 0000000000..b339990b57 --- /dev/null +++ b/sysdeps/posix/fpathconf.c @@ -0,0 +1,116 @@ +/* Copyright (C) 1991, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <errno.h> +#include <stddef.h> +#include <unistd.h> +#include <limits.h> + + +/* Get file-specific information about descriptor FD. */ +long int +DEFUN(__fpathconf, (fd, name), int fd AND int name) +{ + if (fd < 0) + { + errno = EBADF; + return -1; + } + + switch (name) + { + default: + errno = EINVAL; + return -1; + + case _PC_LINK_MAX: +#ifdef LINK_MAX + return LINK_MAX; +#else + errno = ENOSYS; + return -1; +#endif + + case _PC_MAX_CANON: +#ifdef MAX_CANON + return MAX_CANON; +#else + errno = ENOSYS; + return -1; +#endif + + case _PC_MAX_INPUT: +#ifdef MAX_INPUT + return MAX_INPUT; +#else + errno = ENOSYS; + return -1; +#endif + + case _PC_NAME_MAX: +#ifdef NAME_MAX + return NAME_MAX; +#else + errno = ENOSYS; + return -1; +#endif + + case _PC_PATH_MAX: +#ifdef PATH_MAX + return PATH_MAX; +#else + errno = ENOSYS; + return -1; +#endif + + case _PC_PIPE_BUF: +#ifdef PIPE_BUF + return PIPE_BUF; +#else + errno = ENOSYS; + return -1; +#endif + + case _PC_CHOWN_RESTRICTED: +#ifdef _POSIX_CHOWN_RESTRICTED + return _POSIX_CHOWN_RESTRICTED; +#else + return -1; +#endif + + case _PC_NO_TRUNC: +#ifdef _POSIX_NO_TRUNC + return _POSIX_NO_TRUNC; +#else + return -1; +#endif + + case _PC_VDISABLE: +#ifdef _POSIX_VDISABLE + return _POSIX_VDISABLE; +#else + return -1; +#endif + } + + errno = ENOSYS; + return -1; +} + +weak_alias (__fpathconf, fpathconf) diff --git a/sysdeps/posix/getcwd.c b/sysdeps/posix/getcwd.c new file mode 100644 index 0000000000..7b992a9f43 --- /dev/null +++ b/sysdeps/posix/getcwd.c @@ -0,0 +1,366 @@ +/* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* Wants: + AC_STDC_HEADERS + AC_DIR_HEADER + AC_UNISTD_H + AC_MEMORY_H + AC_CONST + AC_ALLOCA + */ + +/* AIX requires this to be the first thing in the file. */ +#if defined (_AIX) && !defined (__GNUC__) + #pragma alloca +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> + +#ifdef STDC_HEADERS +#include <stddef.h> +#endif + +#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS) +extern int errno; +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#if defined (USGr3) && !defined (DIRENT) +#define DIRENT +#endif /* USGr3 */ +#if defined (Xenix) && !defined (SYSNDIR) +#define SYSNDIR +#endif /* Xenix */ + +#if defined (POSIX) || defined (DIRENT) || defined (__GNU_LIBRARY__) +#include <dirent.h> +#ifndef __GNU_LIBRARY__ +#define D_NAMLEN(d) strlen((d)->d_name) +#else +#define HAVE_D_NAMLEN +#define D_NAMLEN(d) ((d)->d_namlen) +#endif +#else /* not POSIX or DIRENT */ +#define dirent direct +#define D_NAMLEN(d) ((d)->d_namlen) +#define HAVE_D_NAMLEN +#if defined (USG) && !defined (sgi) +#if defined (SYSNDIR) +#include <sys/ndir.h> +#else /* Not SYSNDIR */ +#include "ndir.h" +#endif /* SYSNDIR */ +#else /* not USG */ +#include <sys/dir.h> +#endif /* USG */ +#endif /* POSIX or DIRENT or __GNU_LIBRARY__ */ + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#if (defined (STDC_HEADERS) || defined (__GNU_LIBRARY__) \ + || defined (POSIX)) +#include <stdlib.h> +#include <string.h> +#define ANSI_STRING +#else /* No standard headers. */ + +#ifdef USG + +#include <string.h> +#ifdef NEED_MEMORY_H +#include <memory.h> +#endif +#define ANSI_STRING + +#else /* Not USG. */ + +#ifdef NeXT + +#include <string.h> + +#else /* Not NeXT. */ + +#include <strings.h> + +#ifndef bcmp +extern int bcmp (); +#endif +#ifndef bzero +extern void bzero (); +#endif +#ifndef bcopy +extern void bcopy (); +#endif + +#endif /* NeXT. */ + +#endif /* USG. */ + +extern char *malloc (), *realloc (); +extern void free (); + +#endif /* Standard headers. */ + +#ifndef ANSI_STRING +#define memcpy(d, s, n) bcopy((s), (d), (n)) +#define memmove memcpy +#endif /* Not ANSI_STRING. */ + +#if !defined(__alloca) && !defined(__GNU_LIBRARY__) + +#ifdef __GNUC__ +#undef alloca +#define alloca(n) __builtin_alloca (n) +#else /* Not GCC. */ +#if defined (sparc) || defined (HAVE_ALLOCA_H) +#include <alloca.h> +#else /* Not sparc or HAVE_ALLOCA_H. */ +#ifndef _AIX +extern char *alloca (); +#endif /* Not _AIX. */ +#endif /* sparc or HAVE_ALLOCA_H. */ +#endif /* GCC. */ + +#define __alloca alloca + +#endif + +#if (defined (HAVE_LIMITS_H) || defined (STDC_HEADERS) || \ + defined (__GNU_LIBRARY__)) +#include <limits.h> +#else +#include <sys/param.h> +#endif + +#ifndef PATH_MAX +#ifdef MAXPATHLEN +#define PATH_MAX MAXPATHLEN +#else +#define PATH_MAX 1024 +#endif +#endif + +#ifndef STDC_HEADERS +#undef size_t +#define size_t unsigned int +#endif + +#if !__STDC__ && !defined (const) +#define const +#endif + +#ifndef __GNU_LIBRARY__ +#define __lstat stat +#endif + +/* Get the pathname of the current working directory, and put it in SIZE + bytes of BUF. Returns NULL if the directory couldn't be determined or + SIZE was too small. If successful, returns BUF. In GNU, if BUF is + NULL, an array is allocated with `malloc'; the array is SIZE bytes long, + unless SIZE <= 0, in which case it is as big as necessary. */ + +char * +getcwd (buf, size) + char *buf; + size_t size; +{ + static const char dots[] + = "../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../.."; + const char *dotp, *dotlist; + size_t dotsize; + dev_t rootdev, thisdev; + ino_t rootino, thisino; + char *path; + register char *pathp; + struct stat st; + + if (size == 0) + { + if (buf != NULL) + { + errno = EINVAL; + return NULL; + } + + size = PATH_MAX + 1; + } + + if (buf != NULL) + path = buf; + else + { + path = malloc (size); + if (path == NULL) + return NULL; + } + + pathp = path + size; + *--pathp = '\0'; + + if (__lstat (".", &st) < 0) + return NULL; + thisdev = st.st_dev; + thisino = st.st_ino; + + if (__lstat ("/", &st) < 0) + return NULL; + rootdev = st.st_dev; + rootino = st.st_ino; + + dotsize = sizeof (dots) - 1; + dotp = &dots[sizeof (dots)]; + dotlist = dots; + while (!(thisdev == rootdev && thisino == rootino)) + { + register DIR *dirstream; + register struct dirent *d; + dev_t dotdev; + ino_t dotino; + char mount_point; + + /* Look at the parent directory. */ + if (dotp == dotlist) + { + /* My, what a deep directory tree you have, Grandma. */ + char *new; + if (dotlist == dots) + { + new = malloc (dotsize * 2 + 1); + if (new == NULL) + return NULL; + memcpy (new, dots, dotsize); + } + else + { + new = realloc ((__ptr_t) dotlist, dotsize * 2 + 1); + if (new == NULL) + goto lose; + } + memcpy (&new[dotsize], new, dotsize); + dotp = &new[dotsize]; + dotsize *= 2; + new[dotsize] = '\0'; + dotlist = new; + } + + dotp -= 3; + + /* Figure out if this directory is a mount point. */ + if (__lstat (dotp, &st) < 0) + goto lose; + dotdev = st.st_dev; + dotino = st.st_ino; + mount_point = dotdev != thisdev; + + /* Search for the last directory. */ + dirstream = opendir (dotp); + if (dirstream == NULL) + goto lose; + while ((d = readdir (dirstream)) != NULL) + { + if (d->d_name[0] == '.' && + (d->d_namlen == 1 || (d->d_namlen == 2 && d->d_name[1] == '.'))) + continue; + if (mount_point || d->d_ino == thisino) + { + char *name = __alloca (dotlist + dotsize - dotp + + 1 + d->d_namlen + 1); + memcpy (name, dotp, dotlist + dotsize - dotp); + name[dotlist + dotsize - dotp] = '/'; + memcpy (&name[dotlist + dotsize - dotp + 1], + d->d_name, d->d_namlen + 1); + if (__lstat (name, &st) < 0) + { + int save = errno; + (void) closedir (dirstream); + errno = save; + goto lose; + } + if (st.st_dev == thisdev && st.st_ino == thisino) + break; + } + } + if (d == NULL) + { + int save = errno; + (void) closedir (dirstream); + errno = save; + goto lose; + } + else + { + if (pathp - path < d->d_namlen + 1) + { + if (buf != NULL) + { + errno = ERANGE; + return NULL; + } + else + { + size *= 2; + buf = realloc (path, size); + if (buf == NULL) + { + (void) closedir (dirstream); + free (path); + errno = ENOMEM; /* closedir might have changed it. */ + return NULL; + } + pathp = &buf[pathp - path]; + path = buf; + } + } + pathp -= d->d_namlen; + (void) memcpy (pathp, d->d_name, d->d_namlen); + *--pathp = '/'; + (void) closedir (dirstream); + } + + thisdev = dotdev; + thisino = dotino; + } + + if (pathp == &path[size - 1]) + *--pathp = '/'; + + if (dotlist != dots) + free ((__ptr_t) dotlist); + + memmove (path, pathp, path + size - pathp); + return path; + + lose: + if (dotlist != dots) + free ((__ptr_t) dotlist); + return NULL; +} diff --git a/sysdeps/posix/getdtsz.c b/sysdeps/posix/getdtsz.c new file mode 100644 index 0000000000..2080dc7c51 --- /dev/null +++ b/sysdeps/posix/getdtsz.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1991, 1993, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <unistd.h> + +extern long int EXFUN(__sysconf, (int)); + +/* Return the maximum number of file descriptors + the current process could possibly have. */ +int +DEFUN_VOID(__getdtablesize) +{ + return __sysconf (_SC_OPEN_MAX); +} + +weak_alias (__getdtablesize, getdtablesize) diff --git a/sysdeps/posix/getpagesize.c b/sysdeps/posix/getpagesize.c new file mode 100644 index 0000000000..4deb208633 --- /dev/null +++ b/sysdeps/posix/getpagesize.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1993, 1995 Free Software Foundation, Inc. + Contributed by Brendan Kehoe (brendan@cygnus.com). + +The GNU C Library is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with the GNU C Library; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <stddef.h> +#include <unistd.h> + +extern long int EXFUN(__sysconf, (int)); + +/* Return the system page size. */ +size_t +DEFUN_VOID(__getpagesize) +{ + return __sysconf (_SC_PAGESIZE); +} + +weak_alias (__getpagesize, getpagesize) diff --git a/sysdeps/posix/gettimeofday.c b/sysdeps/posix/gettimeofday.c new file mode 100644 index 0000000000..a4bb38a41c --- /dev/null +++ b/sysdeps/posix/gettimeofday.c @@ -0,0 +1,75 @@ +/* Copyright (C) 1991, 1992, 1994, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <errno.h> +#include <time.h> +#include <sys/time.h> + +#ifndef HAVE_GNU_LD +#define __daylight daylight +#define __timezone timezone +#define __tzname tzname +#endif + + +/* Get the current time of day and timezone information, + putting it into *TV and *TZ. If TZ is NULL, *TZ is not filled. + Returns 0 on success, -1 on errors. */ +int +DEFUN(__gettimeofday, (tv, tz), + struct timeval *tv AND struct timezone *tz) +{ + if (tv == NULL) + { + errno = EINVAL; + return -1; + } + + tv->tv_sec = (long int) time ((time_t *) NULL); + tv->tv_usec = 0L; + + if (tz != NULL) + { + CONST time_t timer = tv->tv_sec; + CONST struct tm *tm; + + CONST long int save_timezone = __timezone; + CONST long int save_daylight = __daylight; + char *save_tzname[2]; + save_tzname[0] = __tzname[0]; + save_tzname[1] = __tzname[1]; + + tm = localtime (&timer); + + tz->tz_minuteswest = __timezone / 60; + tz->tz_dsttime = __daylight; + + __timezone = save_timezone; + __daylight = save_daylight; + __tzname[0] = save_tzname[0]; + __tzname[1] = save_tzname[1]; + + if (tm == NULL) + return -1; + } + + return 0; +} + +weak_alias (__gettimeofday, gettimeofday) diff --git a/sysdeps/posix/isatty.c b/sysdeps/posix/isatty.c new file mode 100644 index 0000000000..7536b1eeed --- /dev/null +++ b/sysdeps/posix/isatty.c @@ -0,0 +1,39 @@ +/* Copyright (C) 1991, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <errno.h> +#include <unistd.h> +#include <termios.h> + +/* Return 1 if FD is a terminal, 0 if not. */ +int +DEFUN(__isatty, (fd), int fd) +{ + int save; + int is_tty; + struct termios term; + + save = errno; + is_tty = __tcgetattr(fd, &term) == 0; + errno = save; + + return is_tty; +} + +weak_alias (__isatty, isatty) diff --git a/sysdeps/posix/killpg.c b/sysdeps/posix/killpg.c new file mode 100644 index 0000000000..0c70dd2164 --- /dev/null +++ b/sysdeps/posix/killpg.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1991, 1993 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <errno.h> +#include <signal.h> + + +/* Send SIG to all processes in process group PGRP. + If PGRP is zero, send SIG to all processes in + the current process's process group. */ +int +DEFUN(killpg, (pgrp, sig), __pid_t pgrp AND int sig) +{ + if (pgrp < 0) + { + errno = EINVAL; + return -1; + } + + return __kill (- pgrp, sig); +} diff --git a/sysdeps/posix/libc_fatal.c b/sysdeps/posix/libc_fatal.c new file mode 100644 index 0000000000..5539516733 --- /dev/null +++ b/sysdeps/posix/libc_fatal.c @@ -0,0 +1,56 @@ +/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <stdio.h> +#include <unistd.h> +#include <errno.h> +#include <sysdep.h> + +#ifdef FATAL_PREPARE_INCLUDE +#include FATAL_PREPARE_INCLUDE +#endif + +/* Abort with an error message. */ +void +DEFUN(__libc_fatal, (message), CONST char *message) +{ + size_t len = strlen (message); + +#ifdef FATAL_PREPARE + FATAL_PREPARE; +#endif + + while (len > 0) + { + register int count = __write (STDERR_FILENO, message, len); + if (count > 0) + { + message += count; + len -= count; + } + else if (count < 0 +#ifdef EINTR + && errno != EINTR +#endif + ) + break; + } + + abort (); +} diff --git a/sysdeps/posix/mk-stdiolim.c b/sysdeps/posix/mk-stdiolim.c new file mode 100644 index 0000000000..da78a98394 --- /dev/null +++ b/sysdeps/posix/mk-stdiolim.c @@ -0,0 +1,71 @@ +/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <posix1_lim.h> + +int +main() +{ + /* These values correspond to the code in sysdeps/posix/tempname.c. + Change the values here if you change that code. */ + printf("#define L_tmpnam %u\n", sizeof("/usr/tmp/") + 8); + printf("#define TMP_MAX %u\n", 62 * 62 * 62); + + puts ("#ifdef __USE_POSIX"); + printf("#define L_ctermid %u\n", sizeof("/dev/tty")); + printf("#define L_cuserid 9\n"); + puts ("#endif"); + + /* POSIX does not require that OPEN_MAX and PATH_MAX be defined, so + <local_lim.h> will not define them if they are run-time variant (which + is the case in the Hurd). ANSI still requires that FOPEN_MAX and + FILENAME_MAX be defined, however. */ + + printf("#define FOPEN_MAX %u\n", +#ifdef OPEN_MAX + + OPEN_MAX +#else + /* This is the minimum number of files that the implementation + guarantees can be open simultaneously. OPEN_MAX not being + defined means the maximum is run-time variant; but POSIX.1 + requires that it never be less than _POSIX_OPEN_MAX, so that is + a good minimum to use. */ + _POSIX_OPEN_MAX +#endif + + ); + + printf("#define FILENAME_MAX %u\n", +#ifdef PATH_MAX + PATH_MAX +#else + /* This is supposed to be the size needed to hold the longest file + name string the implementation guarantees can be opened. + PATH_MAX not being defined means the actual limit on the length + of a file name is runtime-variant (or it is unlimited). ANSI + says in such a case FILENAME_MAX should be a good size to + allocate for a file name string. POSIX.1 guarantees that a + file name up to _POSIX_PATH_MAX chars long can be opened, so + this value must be at least that. */ + 1024 /* _POSIX_PATH_MAX is 255. */ +#endif + ); + + exit(0); +} diff --git a/sysdeps/posix/mkstemp.c b/sysdeps/posix/mkstemp.c new file mode 100644 index 0000000000..9f4f68d72d --- /dev/null +++ b/sysdeps/posix/mkstemp.c @@ -0,0 +1,64 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <string.h> +#include <errno.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> + +/* Generate a unique temporary file name from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the filename unique. + Returns a file descriptor open on the file for reading and writing. */ +int +DEFUN(mkstemp, (template), char *template) +{ + static CONST char letters[] + = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + size_t len; + size_t i; + + len = strlen (template); + if (len < 6 || strcmp (&template[len - 6], "XXXXXX")) + { + errno = EINVAL; + return -1; + } + + if (sprintf (&template[len - 5], "%.5u", + (unsigned int) getpid () % 100000) != 5) + /* Inconceivable lossage. */ + return -1; + + for (i = 0; i < sizeof (letters); ++i) + { + int fd; + + template[len - 6] = letters[i]; + + fd = open (template, O_RDWR|O_CREAT|O_EXCL, 0666); + if (fd >= 0) + return fd; + } + + /* We return the null string if we can't find a unique file name. */ + template[0] = '\0'; + return -1; +} diff --git a/sysdeps/posix/mktemp.c b/sysdeps/posix/mktemp.c new file mode 100644 index 0000000000..c3aae36a7b --- /dev/null +++ b/sysdeps/posix/mktemp.c @@ -0,0 +1,64 @@ +/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> + +/* Generate a unique temporary file name from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the filename unique. */ +char * +DEFUN(mktemp, (template), char *template) +{ + static CONST char letters[] + = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + size_t len; + size_t i; + + len = strlen (template); + if (len < 6 || strcmp (&template[len - 6], "XXXXXX")) + { + errno = EINVAL; + return NULL; + } + + if (sprintf (&template[len - 5], "%.5u", + (unsigned int) getpid () % 100000) != 5) + /* Inconceivable lossage. */ + return NULL; + + for (i = 0; i < sizeof (letters); ++i) + { + struct stat ignored; + + template[len - 6] = letters[i]; + + if (stat (template, &ignored) < 0 && errno == ENOENT) + /* The file does not exist. So return this name. */ + return template; + } + + /* We return the null string if we can't find a unique file name. */ + template[0] = '\0'; + return template; +} diff --git a/sysdeps/posix/pipestream.c b/sysdeps/posix/pipestream.c new file mode 100644 index 0000000000..53595f5b54 --- /dev/null +++ b/sysdeps/posix/pipestream.c @@ -0,0 +1,223 @@ +/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <errno.h> +#include <stddef.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> +#include <fcntl.h> + +#define SH_PATH "/bin/sh" /* Shell to run. */ +#define SH_NAME "sh" /* Name to give it. */ + +/* Structure describing a popen child. */ +struct child + { + pid_t pid; /* PID of the child. */ + __ptr_t cookie; /* Original cookie from fdopen. */ + __io_functions funcs; /* Original functions from fdopen. */ + }; + +/* io_functions for pipe streams. + These all simply call the corresponding + original function with the original cookie. */ + +#define FUNC(type, name, args) \ + static type DEFUN(__CONCAT(child_,name), args, __CONCAT(name,decl)) \ + { \ + struct child *c = (struct child *) cookie; \ + { \ + __ptr_t cookie = c->cookie; \ + return (*c->funcs.__CONCAT(__,name)) args; \ + } \ + } + +#define readdecl PTR cookie AND register char *buf AND register size_t n +FUNC (int, read, (cookie, buf, n)) +#define writedecl PTR cookie AND register CONST char *buf AND register size_t n +FUNC (int, write, (cookie, buf, n)) +#define seekdecl PTR cookie AND fpos_t *pos AND int whence +FUNC (int, seek, (cookie, pos, whence)) +#define closedecl PTR cookie +FUNC (int, close, (cookie)) +#define filenodecl PTR cookie +FUNC (int, fileno, (cookie)) + +static const __io_functions child_funcs + = { child_read, child_write, child_seek, child_close, child_fileno }; + +/* Open a new stream that is a one-way pipe to a + child process running the given shell command. */ +FILE * +DEFUN(popen, (command, mode), CONST char *command AND CONST char *mode) +{ + pid_t pid; + int pipedes[2]; + FILE *stream; + struct child *child; + + if (command == NULL || mode == NULL || (*mode != 'r' && *mode != 'w')) + { + errno = EINVAL; + return NULL; + } + + /* Create the pipe. */ + if (pipe(pipedes) < 0) + return NULL; + + /* Fork off the child. */ + pid = __vfork (); + if (pid == (pid_t) -1) + { + /* The fork failed. */ + (void) close (pipedes[0]); + (void) close (pipedes[1]); + return NULL; + } + else if (pid == (pid_t) 0) + { + /* We are the child side. Make the write side of + the pipe be stdin or the read side be stdout. */ + + CONST char *new_argv[4]; + + if ((*mode == 'w' ? dup2(pipedes[STDIN_FILENO], STDIN_FILENO) : + dup2(pipedes[STDOUT_FILENO], STDOUT_FILENO)) < 0) + _exit(127); + + /* Close the pipe descriptors. */ + (void) close(pipedes[STDIN_FILENO]); + (void) close(pipedes[STDOUT_FILENO]); + + /* Exec the shell. */ + new_argv[0] = SH_NAME; + new_argv[1] = "-c"; + new_argv[2] = command; + new_argv[3] = NULL; + (void) execve(SH_PATH, (char *CONST *) new_argv, environ); + /* Die if it failed. */ + _exit(127); + } + + /* We are the parent side. */ + + /* Close the irrelevant side of the pipe and open the relevant side as a + new stream. Mark our side of the pipe to close on exec, so new children + won't see it. */ + if (*mode == 'r') + { + (void) close (pipedes[STDOUT_FILENO]); + (void) fcntl (pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC); + stream = fdopen (pipedes[STDIN_FILENO], mode); + } + else + { + (void) close (pipedes[STDIN_FILENO]); + (void) fcntl (pipedes[STDOUT_FILENO], F_SETFD, FD_CLOEXEC); + stream = fdopen (pipedes[STDOUT_FILENO], mode); + } + + if (stream == NULL) + goto error; + + child = (struct child *) malloc (sizeof (struct child)); + if (child == NULL) + goto error; + + { + /* Make sure STREAM has its functions set before + we try to squirrel them away in CHILD. */ + extern void __stdio_check_funcs __P ((FILE *)); + __stdio_check_funcs (stream); + } + + child->pid = pid; + child->cookie = stream->__cookie; + child->funcs = stream->__io_funcs; + stream->__cookie = (PTR) child; + stream->__io_funcs = child_funcs; + stream->__ispipe = 1; + return stream; + + error: + { + /* The stream couldn't be opened or the child structure couldn't be + allocated. Kill the child and close the other side of the pipe. */ + int save = errno; + (void) kill (pid, SIGKILL); + if (stream == NULL) + (void) close (pipedes[*mode == 'r' ? STDOUT_FILENO : STDIN_FILENO]); + else + (void) fclose (stream); +#ifndef NO_WAITPID + (void) waitpid (pid, (int *) NULL, 0); +#else + { + pid_t dead; + do + dead = wait ((int *) NULL); + while (dead > 0 && dead != pid); + } +#endif + errno = save; + return NULL; + } +} + +/* Close a stream opened by popen and return its status. + Returns -1 if the stream was not opened by popen. */ +int +DEFUN(pclose, (stream), register FILE *stream) +{ + struct child *c; + pid_t pid, dead; + int status; + + if (!__validfp(stream) || !stream->__ispipe) + { + errno = EINVAL; + return -1; + } + + c = (struct child *) stream->__cookie; + pid = c->pid; + stream->__cookie = c->cookie; + stream->__io_funcs = c->funcs; + free ((PTR) c); + stream->__ispipe = 0; + if (fclose (stream)) + return -1; + +#ifndef NO_WAITPID + dead = waitpid (pid, &status, 0); +#else + do + dead = wait (&status); + while (dead > 0 && dead != pid); +#endif + if (dead != pid) + status = -1; + + return status; +} diff --git a/sysdeps/posix/raise.c b/sysdeps/posix/raise.c new file mode 100644 index 0000000000..159fdd5cb9 --- /dev/null +++ b/sysdeps/posix/raise.c @@ -0,0 +1,28 @@ +/* Copyright (C) 1991 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <signal.h> +#include <unistd.h> + +/* Raise the signal SIG. */ +int +DEFUN(raise, (sig), int sig) +{ + return __kill(__getpid(), sig); +} diff --git a/sysdeps/posix/readv.c b/sysdeps/posix/readv.c new file mode 100644 index 0000000000..5f61e61b9f --- /dev/null +++ b/sysdeps/posix/readv.c @@ -0,0 +1,68 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/uio.h> + +/* Read data from file descriptor FD, and put the result in the + buffers described by VECTOR, which is a vector of COUNT `struct iovec's. + The buffers are filled in the order specified. + Operates just like `read' (see <unistd.h>) except that data are + put in VECTOR instead of a contiguous buffer. */ +int +DEFUN(readv, (fd, vector, count), + int fd AND CONST struct iovec *vector AND size_t count) +{ + char *buffer; + size_t bytes; + int bytes_read; + register size_t i; + + /* Find the total number of bytes to be read. */ + bytes = 0; + for (i = 0; i < count; ++i) + bytes += vector[i].iov_len; + + /* Allocate a temporary buffer to hold the data. */ + buffer = (char *) __alloca(bytes); + + /* Read the data. */ + bytes_read = read(fd, buffer, bytes); + if (bytes_read <= 0) + return -1; + + /* Copy the data from BUFFER into the memory specified by VECTOR. */ + bytes = bytes_read; + for (i = 0; i < count; ++i) + { +#define min(a, b) ((a) > (b) ? (b) : (a)) + size_t copy = min(vector[i].iov_len, bytes); + + (void) memcpy((PTR) vector[i].iov_base, (PTR) buffer, copy); + + buffer += copy; + bytes -= copy; + if (bytes == 0) + break; + } + + return bytes_read; +} diff --git a/sysdeps/posix/remove.c b/sysdeps/posix/remove.c new file mode 100644 index 0000000000..66414c9039 --- /dev/null +++ b/sysdeps/posix/remove.c @@ -0,0 +1,40 @@ +/* ANSI C `remove' function to delete a file or directory. POSIX.1 version. +Copyright (C) 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <errno.h> +#include <stdio.h> +#include <unistd.h> + +int +remove (file) + const char *file; +{ + int save; + + save = errno; + if (__rmdir (file) == 0) + return 0; + else if (errno == ENOTDIR && __unlink (file) == 0) + { + errno = save; + return 0; + } + + return -1; +} diff --git a/sysdeps/posix/rename.c b/sysdeps/posix/rename.c new file mode 100644 index 0000000000..3245f9cf9c --- /dev/null +++ b/sysdeps/posix/rename.c @@ -0,0 +1,50 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <stdio.h> +#include <unistd.h> +#include <errno.h> + +/* Rename the file OLD to NEW. */ +int +DEFUN(rename, (old, new), CONST char *old AND CONST char *new) +{ + int save = errno; + if (__link(old, new) < 0) + { + if (errno == EEXIST) + { + errno = save; + /* Race condition, required for 1003.1 conformance. */ + if (__unlink(new) < 0 || + __link(old, new) < 0) + return -1; + } + else + return -1; + } + if (__unlink(old) < 0) + { + save = errno; + if (__unlink(new) == 0) + errno = save; + return -1; + } + return 0; +} diff --git a/sysdeps/posix/sigblock.c b/sysdeps/posix/sigblock.c new file mode 100644 index 0000000000..411a952bc3 --- /dev/null +++ b/sysdeps/posix/sigblock.c @@ -0,0 +1,55 @@ +/* Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <errno.h> +#include <signal.h> + +/* Block signals in MASK, returning the old mask. */ +int +DEFUN(__sigblock, (mask), int mask) +{ + register int sig; + sigset_t set, oset; + + if (__sigemptyset(&set) < 0) + return -1; + + if (sizeof (mask) == sizeof (set)) + *(int *) &set = mask; + else + for (sig = 1; sig < NSIG; ++sig) + if ((mask & sigmask(sig)) && + __sigaddset(&set, sig) < 0) + return -1; + + if (sigprocmask(SIG_BLOCK, &set, &oset) < 0) + return -1; + + mask = 0; + if (sizeof (mask) == sizeof (oset)) + mask = *(int *) &oset; + else + for (sig = 1; sig < NSIG; ++sig) + if (__sigismember(&oset, sig)) + mask |= sigmask(sig); + + return mask; +} + +weak_alias (__sigblock, sigblock) diff --git a/sysdeps/posix/sigintr.c b/sysdeps/posix/sigintr.c new file mode 100644 index 0000000000..441c643df8 --- /dev/null +++ b/sysdeps/posix/sigintr.c @@ -0,0 +1,57 @@ +/* Copyright (C) 1992, 1994 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <stddef.h> +#include <signal.h> +#include <errno.h> + +/* If INTERRUPT is nonzero, make signal SIG interrupt system calls + (causing them to fail with EINTR); if INTERRUPT is zero, make system + calls be restarted after signal SIG. */ +int +DEFUN(siginterrupt, (sig, interrupt), + int sig AND int interrupt) +{ +#ifdef SA_RESTART + extern sigset_t _sigintr; /* Defined in signal.c. */ + struct sigaction action; + + if (__sigaction (sig, (struct sigaction *) NULL, &action) < 0) + return -1; + + if (interrupt) + { + __sigaddset (&_sigintr, sig); + action.sa_flags &= ~SA_RESTART; + } + else + { + __sigdelset (&_sigintr, sig); + action.sa_flags |= SA_RESTART; + } + + if (__sigaction (sig, &action, (struct sigaction *) NULL) < 0) + return -1; + + return 0; +#else + errno = ENOSYS; + return -1; +#endif +} diff --git a/sysdeps/posix/signal.c b/sysdeps/posix/signal.c new file mode 100644 index 0000000000..f9ae47b6bb --- /dev/null +++ b/sysdeps/posix/signal.c @@ -0,0 +1,47 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <errno.h> +#include <signal.h> + + +sigset_t _sigintr; /* Set by siginterrupt. */ + +/* Set the handler for the signal SIG to HANDLER, + returning the old handler, or SIG_ERR on error. */ +__sighandler_t +DEFUN(signal, (sig, handler), int sig AND __sighandler_t handler) +{ + struct sigaction act, oact; + + if (handler == SIG_ERR) + { + errno = EINVAL; + return SIG_ERR; + } + + act.sa_handler = handler; + if (__sigemptyset (&act.sa_mask) < 0) + return SIG_ERR; + act.sa_flags = __sigismember (&_sigintr, sig) ? 0 : SA_RESTART; + if (__sigaction (sig, &act, &oact) < 0) + return SIG_ERR; + + return oact.sa_handler; +} diff --git a/sysdeps/posix/sigpause.c b/sysdeps/posix/sigpause.c new file mode 100644 index 0000000000..97716d352b --- /dev/null +++ b/sysdeps/posix/sigpause.c @@ -0,0 +1,45 @@ +/* Copyright (C) 1991, 1992, 1994, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <errno.h> +#include <signal.h> + +/* Set the mask of blocked signals to MASK, + wait for a signal to arrive, and then restore the mask. */ +int +DEFUN(__sigpause, (mask), int mask) +{ + sigset_t set; + int sig; + + if (__sigemptyset (&set) < 0) + return -1; + + if (sizeof (mask) == sizeof (set)) + *(int *) &set = mask; + else + for (sig = 1; sig < NSIG; ++sig) + if ((mask & sigmask(sig)) && + __sigaddset(&set, sig) < 0) + return -1; + + return sigsuspend (&set); +} + +weak_alias (__sigpause, sigpause) diff --git a/sysdeps/posix/sigsetmask.c b/sysdeps/posix/sigsetmask.c new file mode 100644 index 0000000000..12e77a619d --- /dev/null +++ b/sysdeps/posix/sigsetmask.c @@ -0,0 +1,55 @@ +/* Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <errno.h> +#include <signal.h> + +/* Set the mask of blocked signals to MASK, returning the old mask. */ +int +DEFUN(__sigsetmask, (mask), int mask) +{ + register int sig; + sigset_t set, oset; + + if (__sigemptyset(&set) < 0) + return -1; + + if (sizeof (mask) == sizeof (set)) + *(int *) &set = mask; + else + for (sig = 1; sig < NSIG; ++sig) + if ((mask & sigmask(sig)) && + __sigaddset(&set, sig) < 0) + return -1; + + if (sigprocmask(SIG_SETMASK, &set, &oset) < 0) + return -1; + + mask = 0; + if (sizeof (mask) == sizeof (oset)) + mask = *(int *) &oset; + else + for (sig = 1; sig < NSIG; ++sig) + if (__sigismember(&oset, sig)) + mask |= sigmask(sig); + + return mask; +} + +weak_alias (__sigsetmask, sigsetmask) diff --git a/sysdeps/posix/sigsuspend.c b/sysdeps/posix/sigsuspend.c new file mode 100644 index 0000000000..771315333a --- /dev/null +++ b/sysdeps/posix/sigsuspend.c @@ -0,0 +1,51 @@ +/* Copyright (C) 1991 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <errno.h> +#include <signal.h> +#include <stddef.h> +#include <unistd.h> + + +/* Change the set of blocked signals to SET, + wait until a signal arrives, and restore the set of blocked signals. */ +int +DEFUN(sigsuspend, (set), CONST sigset_t *set) +{ + sigset_t oset; + int save; + + if (set == NULL) + { + errno = EINVAL; + return -1; + } + + if (sigprocmask(SIG_SETMASK, set, &oset) < 0) + return -1; + + (void) pause(); + save = errno; + + if (sigprocmask(SIG_SETMASK, &oset, (sigset_t *) NULL) < 0) + return -1; + + errno = save; + return -1; +} diff --git a/sysdeps/posix/sigvec.c b/sysdeps/posix/sigvec.c new file mode 100644 index 0000000000..4aef22ae32 --- /dev/null +++ b/sysdeps/posix/sigvec.c @@ -0,0 +1,162 @@ +/* Copyright (C) 1991, 1992, 1994, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <signal.h> +#include <errno.h> +#include <stddef.h> + + +/* We use a wrapper handler to support SV_RESETHAND. */ + +static __sighandler_t wrapped_handlers[NSIG]; +static sigset_t wrapped_masks[NSIG]; + +static void +DEFUN(wrapper_handler, (sig), int sig) +{ + int save; + struct sigaction act; + + act.sa_handler = SIG_DFL; + act.sa_mask = wrapped_masks[sig]; + act.sa_flags = 0; + save = errno; + (void) __sigaction(sig, &act, (struct sigaction *) NULL); + errno = save; + + (*wrapped_handlers[sig])(sig); +} + +static +#ifdef __GNUC__ +inline +#endif +int +DEFUN(convert_mask, (set, mask), sigset_t *set AND CONST int mask) +{ + register int sig; + + if (sizeof(*set) == sizeof(mask)) + { + *(int *) set = mask; + return 0; + } + + if (__sigemptyset(set) < 0) + return -1; + + for (sig = 1; sig < NSIG; ++sig) + if (mask & sigmask(sig)) + if (__sigaddset(set, sig) < 0) + return -1; + + return 0; +} + +/* If VEC is non-NULL, set the handler for SIG to the `sv_handler' member + of VEC. The signals in `sv_mask' will be blocked while the handler runs. + If the SV_RESETHAND bit is set in `sv_flags', the handler for SIG will be + reset to SIG_DFL before `sv_handler' is entered. If OVEC is non-NULL, + it is filled in with the old information for SIG. */ +int +DEFUN(__sigvec, (sig, vec, ovec), + int sig AND CONST struct sigvec *vec AND struct sigvec *ovec) +{ + struct sigaction old; + + if (vec == NULL || !(vec->sv_flags & SV_RESETHAND)) + { + struct sigaction new, *n; + + if (vec == NULL) + n = NULL; + else + { + n = &new; + n->sa_handler = vec->sv_handler; + if (convert_mask (&n->sa_mask, vec->sv_mask) < 0) + return -1; + n->sa_flags = 0; + + if (vec->sv_flags & SV_ONSTACK) + { +#ifdef SA_ONSTACK + n->sa_flags |= SA_ONSTACK; +#else + errno = ENOSYS; + return -1; +#endif + } +#ifdef SA_RESTART + if (!(vec->sv_flags & SV_INTERRUPT)) + n->sa_flags |= SA_RESTART; +#endif + } + + if (__sigaction (sig, n, &old) < 0) + return -1; + } + else + { + struct sigaction wrapper; + + wrapper.sa_handler = wrapper_handler; + wrapped_handlers[sig] = vec->sv_handler; + if (convert_mask (&wrapped_masks[sig], vec->sv_mask) < 0) + return -1; + + if (__sigaction (sig, &wrapper, &old) < 0) + return -1; + } + + if (ovec != NULL) + { + register int i; + int mask = 0; + + if (sizeof (int) == sizeof (sigset_t)) + mask = *(int *) &old.sa_mask; + else + for (i = 1; i < NSIG; ++i) + if (__sigismember(&old.sa_mask, i)) + mask |= sigmask(i); + + ovec->sv_mask = mask; + ovec->sv_flags = 0; +#ifdef SA_ONSTACK + if (old.sa_flags & SA_ONSTACK) + ovec->sv_flags |= SV_ONSTACK; +#endif +#ifdef SA_RESTART + if (!(old.sa_flags & SA_RESTART)) +#endif + ovec->sv_flags |= SV_INTERRUPT; + if (old.sa_handler == wrapper_handler) + { + ovec->sv_flags |= SV_RESETHAND; + ovec->sv_handler = wrapped_handlers[sig]; + } + else + ovec->sv_handler = old.sa_handler; + } + + return 0; +} + +weak_alias (__sigvec, sigvec) diff --git a/sysdeps/posix/sleep.c b/sysdeps/posix/sleep.c new file mode 100644 index 0000000000..36864cbf6e --- /dev/null +++ b/sysdeps/posix/sleep.c @@ -0,0 +1,106 @@ +/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <signal.h> +#include <time.h> +#include <unistd.h> +#include <errno.h> + + +/* SIGALRM signal handler for `sleep'. This does nothing but return, + but SIG_IGN isn't supposed to break `pause'. */ +static void +DEFUN(sleep_handler, (sig), int sig) +{ + return; +} + +/* Make the process sleep for SECONDS seconds, or until a signal arrives + and is not ignored. The function returns the number of seconds less + than SECONDS which it actually slept (zero if it slept the full time). + If a signal handler does a `longjmp' or modifies the handling of the + SIGALRM signal while inside `sleep' call, the handling of the SIGALRM + signal afterwards is undefined. There is no return value to indicate + error, but if `sleep' returns SECONDS, it probably didn't work. */ +unsigned int +DEFUN(sleep, (seconds), unsigned int seconds) +{ + unsigned int remaining, slept; + time_t before, after; + sigset_t set, oset; + struct sigaction act, oact; + int save = errno; + + if (seconds == 0) + return 0; + + /* Block SIGALRM signals while frobbing the handler. */ + if (sigemptyset (&set) < 0 || + sigaddset (&set, SIGALRM) < 0 || + sigprocmask (SIG_BLOCK, &set, &oset)) + return seconds; + + act.sa_handler = sleep_handler; + act.sa_flags = 0; + if (sigemptyset (&act.sa_mask) < 0 || + sigaction (SIGALRM, &act, &oact) < 0) + return seconds; + + before = time ((time_t *) NULL); + remaining = alarm (seconds); + + if (remaining > 0 && remaining < seconds) + { + /* The user's alarm will expire before our own would. + Restore the user's signal action state and let his alarm happen. */ + (void) sigaction (SIGALRM, &oact, (struct sigaction *) NULL); + alarm (remaining); /* Restore sooner alarm. */ + sigsuspend (&oset); /* Wait for it to go off. */ + after = time ((time_t *) NULL); + } + else + { + /* Atomically restore the old signal mask + (which had better not block SIGALRM), + and wait for a signal to arrive. */ + sigsuspend (&oset); + + after = time ((time_t *) NULL); + + /* Restore the old signal action state. */ + (void) sigaction (SIGALRM, &oact, (struct sigaction *) NULL); + } + + /* Notice how long we actually slept. */ + slept = after - before; + + /* Restore the user's alarm if we have not already past it. + If we have, be sure to turn off the alarm in case a signal + other than SIGALRM was what woke us up. */ + (void) alarm (remaining > slept ? remaining - slept : 0); + + /* Restore the original signal mask. */ + (void) sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL); + + /* Restore the `errno' value we started with. + Some of the calls we made might have failed, but we didn't care. */ + errno = save; + + return slept > seconds ? 0 : seconds - slept; +} diff --git a/sysdeps/posix/stdio_init.c b/sysdeps/posix/stdio_init.c new file mode 100644 index 0000000000..422d9b69ef --- /dev/null +++ b/sysdeps/posix/stdio_init.c @@ -0,0 +1,70 @@ +/* Copyright (C) 1991, 1992, 1993, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +/* Initialize STREAM as necessary. + This may change I/O functions, give a buffer, etc. + If no buffer is allocated, but the bufsize is set, + the bufsize will be used to allocate the buffer. */ +void +DEFUN(__stdio_init_stream, (stream), FILE *stream) +{ + register CONST int fd = (int) stream->__cookie; + struct stat statb; + + if (stream->__buffer != NULL || stream->__userbuf) + /* If's unbuffered by request, we can't do anything useful. */ + return; + + /* Find out what sort of file this is. */ + if (__fstat (fd, &statb) < 0) + return; + + if (S_ISCHR (statb.st_mode)) + { + /* It's a character device. + Make it line-buffered if it's a terminal. */ + if (__isatty (fd)) + { + stream->__linebuf = 1; + + /* Unix terminal devices have the bad habit of claiming to be + seekable. On systems I have tried, seeking on a terminal + device seems to set its file position as specified, such that + a later tell says the same thing. This is in no way related + to actual seekability--the ability to seek back and read old + data. Unix terminal devices will let you "seek back", and + then read more new data from the terminal. I can think of + nothing to do about this lossage except to preemptively disable + seeking on terminal devices. */ + + stream->__io_funcs.__seek = NULL; /* Seeks get ESPIPE. */ + } + } + +#ifdef _STATBUF_ST_BLKSIZE + /* Use the block-size field to determine + the system's optimal buffering size. */ + stream->__bufsize = statb.st_blksize; +#endif +} diff --git a/sysdeps/posix/sysconf.c b/sysdeps/posix/sysconf.c new file mode 100644 index 0000000000..7f4fbb7261 --- /dev/null +++ b/sysdeps/posix/sysconf.c @@ -0,0 +1,183 @@ +/* Copyright (C) 1991, 1993, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <errno.h> +#include <limits.h> +#include <unistd.h> +#include <stddef.h> +#include <stdio.h> +#include <time.h> + +extern int EXFUN(__getdtablesize, (NOARGS)); +extern size_t EXFUN(__getpagesize, (NOARGS)); + +/* Get the value of the system variable NAME. */ +long int +DEFUN(__sysconf, (name), int name) +{ + switch (name) + { + default: + errno = EINVAL; + return -1; + + case _SC_ARG_MAX: +#ifdef ARG_MAX + return ARG_MAX; +#else + return -1; +#endif + + case _SC_CHILD_MAX: +#ifdef CHILD_MAX + return CHILD_MAX; +#else + return -1; +#endif + + case _SC_CLK_TCK: + return 60; + + case _SC_NGROUPS_MAX: +#ifdef NGROUPS_MAX + return NGROUPS_MAX; +#else + return -1; +#endif + + case _SC_OPEN_MAX: + return __getdtablesize (); + + case _SC_STREAM_MAX: + return FOPEN_MAX; + + case _SC_TZNAME_MAX: + return __tzname_max (); + + case _SC_JOB_CONTROL: +#ifdef _POSIX_JOB_CONTROL + return 1; +#else + return -1; +#endif + case _SC_SAVED_IDS: +#ifdef _POSIX_SAVED_IDS + return 1; +#else + return -1; +#endif + case _SC_VERSION: + return _POSIX_VERSION; + + case _SC_PAGESIZE: + return __getpagesize (); + + case _SC_BC_BASE_MAX: +#ifdef BC_BASE_MAX + return BC_BASE_MAX; +#else + return -1; +#endif + + case _SC_BC_DIM_MAX: +#ifdef BC_DIM_MAX + return BC_DIM_MAX; +#else + return -1; +#endif + + case _SC_BC_SCALE_MAX: +#ifdef BC_SCALE_MAX + return BC_SCALE_MAX; +#else + return -1; +#endif + + case _SC_BC_STRING_MAX: +#ifdef BC_STRING_MAX + return BC_STRING_MAX; +#else + return -1; +#endif + + case _SC_EQUIV_CLASS_MAX: +#ifdef EQUIV_CLASS_MAX + return EQUIV_CLASS_MAX; +#else + return -1; +#endif + + case _SC_EXPR_NEST_MAX: +#ifdef EXPR_NEST_MAX + return EXPR_NEST_MAX; +#else + return -1; +#endif + + case _SC_LINE_MAX: +#ifdef LINE_MAX + return LINE_MAX; +#else + return -1; +#endif + + case _SC_RE_DUP_MAX: +#ifdef RE_DUP_MAX + return RE_DUP_MAX; +#else + return -1; +#endif + + + case _SC_2_VERSION: + /* This is actually supposed to return the version + of the 1003.2 utilities on the system {POSIX2_VERSION}. */ + return _POSIX2_C_VERSION; + + case _SC_2_C_BIND: +#ifdef _POSIX2_C_BIND + return _POSIX2_C_BIND; +#else + return -1; +#endif + + case _SC_2_C_DEV: +#ifdef _POSIX2_C_DEV + return _POSIX2_C_DEV; +#else + return -1; +#endif + + case _SC_2_FORT_DEV: +#ifdef _POSIX2_FORT_DEV + return _POSIX2_FORT_DEV; +#else + return -1; +#endif + + case _SC_2_SW_DEV: +#ifdef _POSIX2_SW_DEV + return _POSIX2_SW_DEV; +#else + return -1; +#endif + } +} + +weak_alias (__sysconf, sysconf) diff --git a/sysdeps/posix/system.c b/sysdeps/posix/system.c new file mode 100644 index 0000000000..69b004bb41 --- /dev/null +++ b/sysdeps/posix/system.c @@ -0,0 +1,145 @@ +/* Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <stddef.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/wait.h> +#include <signal.h> +#include <sys/types.h> + + +#ifndef HAVE_GNU_LD +#define __environ environ +#endif + +#define SHELL_PATH "/bin/sh" /* Path of the shell. */ +#define SHELL_NAME "sh" /* Name to give it. */ + +/* Execute LINE as a shell command, returning its status. */ +int +DEFUN(system, (line), register CONST char *line) +{ + int status, save; + pid_t pid; + struct sigaction sa, intr, quit; +#ifndef WAITPID_CANNOT_BLOCK_SIGCHLD + sigset_t block, omask; +#endif + + if (line == NULL) + return 1; + + sa.sa_handler = SIG_IGN; + sa.sa_flags = 0; + __sigemptyset (&sa.sa_mask); + + if (__sigaction (SIGINT, &sa, &intr) < 0) + return -1; + if (__sigaction (SIGQUIT, &sa, &quit) < 0) + { + save = errno; + (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL); + errno = save; + return -1; + } + +#ifndef WAITPID_CANNOT_BLOCK_SIGCHLD + +/* SCO 3.2v4 has a bug where `waitpid' will never return if SIGCHLD is + blocked. This makes it impossible for `system' to be implemented in + compliance with POSIX.2-1992. They have acknowledged that this is a bug + but I have not seen nor heard of any forthcoming fix. */ + + __sigemptyset (&block); + __sigaddset (&block, SIGCHLD); + save = errno; + if (__sigprocmask (SIG_BLOCK, &block, &omask) < 0) + { + if (errno == ENOSYS) + errno = save; + else + { + save = errno; + (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL); + (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL); + errno = save; + return -1; + } + } +#define UNBLOCK __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL) +#else +#define UNBLOCK 0 +#endif + + pid = __vfork (); + if (pid == (pid_t) 0) + { + /* Child side. */ + CONST char *new_argv[4]; + new_argv[0] = SHELL_NAME; + new_argv[1] = "-c"; + new_argv[2] = line; + new_argv[3] = NULL; + + /* Restore the signals. */ + (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL); + (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL); + (void) UNBLOCK; + + /* Exec the shell. */ + (void) __execve (SHELL_PATH, (char *CONST *) new_argv, __environ); + _exit (127); + } + else if (pid < (pid_t) 0) + /* The fork failed. */ + status = -1; + else + /* Parent side. */ +#ifdef NO_WAITPID + { + pid_t child; + do + { + child = __wait (&status); + if (child <= -1) + { + status = -1; + break; + } + } while (child != pid); + } +#else + if (__waitpid (pid, &status, 0) != pid) + status = -1; +#endif + + save = errno; + if ((__sigaction (SIGINT, &intr, (struct sigaction *) NULL) | + __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL) | + UNBLOCK) != 0) + { + if (errno == ENOSYS) + errno = save; + else + return -1; + } + + return status; +} diff --git a/sysdeps/posix/tempname.c b/sysdeps/posix/tempname.c new file mode 100644 index 0000000000..f2da66a211 --- /dev/null +++ b/sysdeps/posix/tempname.c @@ -0,0 +1,208 @@ +/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <errno.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +/* Return nonzero if DIR is an existent directory. */ +static int +DEFUN(diraccess, (dir), CONST char *dir) +{ + struct stat buf; + return __stat (dir, &buf) == 0 && S_ISDIR (buf.st_mode); +} + +/* Return nonzero if FILE exists. */ +static int +DEFUN(exists, (file), CONST char *file) +{ + /* We can stat the file even if we can't read its data. */ + struct stat st; + int save = errno; + if (__stat (file, &st) == 0) + return 1; + else + { + /* We report that the file exists if stat failed for a reason other + than nonexistence. In this case, it may or may not exist, and we + don't know; but reporting that it does exist will never cause any + trouble, while reporting that it doesn't exist when it does would + violate the interface of __stdio_gen_tempname. */ + int exists = errno != ENOENT; + errno = save; + return exists; + } +} + + +/* These are the characters used in temporary filenames. */ +static CONST char letters[] = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + +/* Generate a temporary filename and return it (in a static buffer). If + STREAMPTR is not NULL, open a stream "w+b" on the file and set + *STREAMPTR to it. If DIR_SEARCH is nonzero, DIR and PFX are used as + described for tempnam. If not, a temporary filename in P_tmpdir with no + special prefix is generated. If LENPTR is not NULL, *LENPTR is set the + to length (including the terminating '\0') of the resultant filename, + which is returned. This goes through a cyclic pattern of all possible + filenames consisting of five decimal digits of the current pid and three + of the characters in `letters'. Data for tempnam and tmpnam is kept + separate, but when tempnam is using P_tmpdir and no prefix (i.e, it is + identical to tmpnam), the same data is used. Each potential filename is + tested for an already-existing file of the same name, and no name of an + existing file will be returned. When the cycle reaches its end + (12345ZZZ), NULL is returned. */ +char * +DEFUN(__stdio_gen_tempname, (dir, pfx, dir_search, lenptr, streamptr), + CONST char *dir AND CONST char *pfx AND + int dir_search AND size_t *lenptr AND + FILE **streamptr) +{ + int saverrno = errno; + static CONST char tmpdir[] = P_tmpdir; + static size_t indices[2]; + size_t *idx; + static char buf[FILENAME_MAX]; + static pid_t oldpid = (pid_t) 0; + pid_t pid = __getpid(); + register size_t len, plen, dlen; + + if (dir_search) + { + register CONST char *d = getenv ("TMPDIR"); + if (d != NULL && !diraccess (d)) + d = NULL; + if (d == NULL && dir != NULL && diraccess (dir)) + d = dir; + if (d == NULL && diraccess (tmpdir)) + d = tmpdir; + if (d == NULL && diraccess ("/tmp")) + d = "/tmp"; + if (d == NULL) + { + errno = ENOENT; + return NULL; + } + dir = d; + } + else + dir = tmpdir; + + dlen = strlen (dir); + + /* Remove trailing slashes from the directory name. */ + while (dlen > 1 && dir[dlen - 1] == '/') + --dlen; + + if (pfx != NULL && *pfx != '\0') + { + plen = strlen (pfx); + if (plen > 5) + plen = 5; + } + else + plen = 0; + + if (dir != tmpdir && !strcmp (dir, tmpdir)) + dir = tmpdir; + idx = &indices[(plen == 0 && dir == tmpdir) ? 1 : 0]; + + if (pid != oldpid) + { + oldpid = pid; + indices[0] = indices[1] = 0; + } + + len = dlen + 1 + plen + 5 + 3; + while (*idx < ((sizeof (letters) - 1) * (sizeof (letters) - 1) * + (sizeof (letters) - 1))) + { + const size_t i = (*idx)++; + + /* Construct a file name and see if it already exists. + + We use a single counter in *IDX to cycle each of three + character positions through each of 62 possible letters. */ + + if (sizeof (buf) < len || + sprintf (buf, "%.*s/%.*s%.5d%c%c%c", + (int) dlen, dir, (int) plen, + pfx, pid % 100000, + letters[i % (sizeof (letters) - 1)], + letters[(i / (sizeof (letters) - 1)) + % (sizeof (letters) - 1)], + letters[(i / ((sizeof (letters) - 1) * + (sizeof (letters) - 1))) + % (sizeof (letters) - 1)] + ) != (int) len) + return NULL; + + if (streamptr != NULL) + { + /* Try to create the file atomically. */ + int fd = __open (buf, O_RDWR|O_CREAT|O_EXCL, 0666); + if (fd >= 0) + { + /* We got a new file that did not previously exist. + Create a stream for it. */ + *streamptr = __newstream (); + if (*streamptr == NULL) + { + /* We lost trying to create a stream (out of memory?). + Nothing to do but remove the file, close the descriptor, + and return failure. */ + const int save = errno; + (void) remove (buf); + (void) __close (fd); + errno = save; + return NULL; + } + (*streamptr)->__cookie = (PTR) (long int) fd; + (*streamptr)->__mode.__write = 1; + (*streamptr)->__mode.__read = 1; + (*streamptr)->__mode.__binary = 1; + } + else + continue; + } + else if (exists (buf)) + continue; + + /* If the file already existed we have continued the loop above, + so we only get here when we have a winning name to return. */ + + errno = saverrno; + + if (lenptr != NULL) + *lenptr = len + 1; + return buf; + } + + /* We got out of the loop because we ran out of combinations to try. */ + errno = EEXIST; /* ? */ + return NULL; +} diff --git a/sysdeps/posix/truncate.c b/sysdeps/posix/truncate.c new file mode 100644 index 0000000000..9fe0d86a0a --- /dev/null +++ b/sysdeps/posix/truncate.c @@ -0,0 +1,41 @@ +/* Copyright (C) 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <sys/types.h> +#include <errno.h> +#include <unistd.h> + +/* Truncate PATH to LENGTH bytes. */ +int +DEFUN(truncate, (path, length), + CONST char *path AND off_t length) +{ + int fd, ret, save; + + fd = open (path, O_WRONLY); + if (fd < 0) + return -1; + + ret = ftruncate (fd, length); + save = errno; + (void) close (fd); + if (ret < 0) + errno = save; + return ret; +} diff --git a/sysdeps/posix/ttyname.c b/sysdeps/posix/ttyname.c new file mode 100644 index 0000000000..50e3c79341 --- /dev/null +++ b/sysdeps/posix/ttyname.c @@ -0,0 +1,82 @@ +/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <errno.h> +#include <limits.h> +#include <stddef.h> +#include <dirent.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> + +char *__ttyname = NULL; + +/* Return the pathname of the terminal FD is open on, or NULL on errors. + The returned storage is good only until the next call to this function. */ +char * +DEFUN(ttyname, (fd), int fd) +{ + static CONST char dev[] = "/dev"; + static char *name; + static size_t namelen = 0; + struct stat st; + dev_t mydev; + ino_t myino; + DIR *dirstream; + struct dirent *d; + int save = errno; + + if (fstat (fd, &st) < 0) + return NULL; + mydev = st.st_dev; + myino = st.st_ino; + + dirstream = opendir (dev); + if (dirstream == NULL) + return NULL; + + while ((d = readdir (dirstream)) != NULL) + if (d->d_fileno == myino) + { + if (sizeof (dev) + d->d_namlen + 1 > namelen) + { + free (name); + namelen = 2 * (sizeof (dev) + d->d_namlen + 1); /* Big enough. */ + name = malloc (namelen); + if (! name) + return NULL; + (void) memcpy (name, dev, sizeof (dev) - 1); + name[sizeof (dev) - 1] = '/'; + } + (void) memcpy (&name[sizeof (dev)], d->d_name, d->d_namlen + 1); + if (stat (name, &st) == 0 && st.st_dev == mydev) + { + (void) closedir (dirstream); + __ttyname = name; + errno = save; + return name; + } + } + + (void) closedir (dirstream); + errno = save; + return NULL; +} diff --git a/sysdeps/posix/wait.c b/sysdeps/posix/wait.c new file mode 100644 index 0000000000..38891c7e01 --- /dev/null +++ b/sysdeps/posix/wait.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1991, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <sys/wait.h> + + +/* Wait for a child to die. When one does, put its status in *STAT_LOC + and return its process ID. For errors, return (pid_t) -1. */ +__pid_t +DEFUN(__wait, (stat_loc), __WAIT_STATUS_DEFN stat_loc) +{ + return __waitpid(WAIT_ANY, (int *) stat_loc, 0); +} + +weak_alias (__wait, wait) diff --git a/sysdeps/posix/wait3.c b/sysdeps/posix/wait3.c new file mode 100644 index 0000000000..5eb084a7c9 --- /dev/null +++ b/sysdeps/posix/wait3.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1992, 1993, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <errno.h> +#include <sys/wait.h> +#include <sys/types.h> +#include <stddef.h> + +/* Wait for a child to exit. When one does, put its status in *STAT_LOC and + return its process ID. For errors return (pid_t) -1. If USAGE is not nil, + store information about the child's resource usage (as a `struct rusage') + there. If the WUNTRACED bit is set in OPTIONS, return status for stopped + children; otherwise don't. */ +pid_t +DEFUN(__wait3, (stat_loc, options, usage), + __WAIT_STATUS_DEFN stat_loc AND int options AND struct rusage *usage) +{ + if (usage != NULL) + { + errno = ENOSYS; + return (pid_t) -1; + } + return __waitpid (WAIT_ANY, stat_loc, options); +} + +weak_alias (__wait3, wait3) diff --git a/sysdeps/posix/writev.c b/sysdeps/posix/writev.c new file mode 100644 index 0000000000..56e29a64b9 --- /dev/null +++ b/sysdeps/posix/writev.c @@ -0,0 +1,64 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/uio.h> + +/* Write data pointed by the buffers described by VECTOR, which + is a vector of COUNT `struct iovec's, to file descriptor FD. + The data is written in the order specified. + Operates just like `write' (see <unistd.h>) except that the data + are taken from VECTOR instead of a contiguous buffer. */ +int +DEFUN(writev, (fd, vector, count), + int fd AND CONST struct iovec *vector AND size_t count) +{ + char *buffer; + register char *bp; + size_t bytes, to_copy; + register size_t i; + + /* Find the total number of bytes to be written. */ + bytes = 0; + for (i = 0; i < count; ++i) + bytes += vector[i].iov_len; + + /* Allocate a temporary buffer to hold the data. */ + buffer = (char *) __alloca(bytes); + + /* Copy the data into BUFFER. */ + to_copy = bytes; + bp = buffer; + for (i = 0; i < count; ++i) + { +#define min(a, b) ((a) > (b) ? (b) : (a)) + size_t copy = min(vector[i].iov_len, to_copy); + + (void) memcpy((PTR) bp, (PTR) vector[i].iov_base, copy); + + bp += copy; + to_copy -= copy; + if (bytes == 0) + break; + } + + return write(fd, buffer, bytes); +} |