301 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			301 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* oslib.c - functions present only in some unix versions. */
 | |
| 
 | |
| /* Copyright (C) 1995,2010 Free Software Foundation, Inc.
 | |
| 
 | |
|    This file is part of GNU Bash, the Bourne Again SHell.
 | |
| 
 | |
|    Bash 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 3 of the License, or
 | |
|    (at your option) any later version.
 | |
| 
 | |
|    Bash 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 Bash.  If not, see <http://www.gnu.org/licenses/>.
 | |
| */
 | |
| 
 | |
| #include <config.h>
 | |
| 
 | |
| #include <bashtypes.h>
 | |
| #if defined (HAVE_SYS_PARAM_H)
 | |
| #  include <sys/param.h>
 | |
| #endif
 | |
| 
 | |
| #if defined (HAVE_UNISTD_H)
 | |
| #  include <unistd.h>
 | |
| #endif
 | |
| 
 | |
| #if defined (HAVE_LIMITS_H)
 | |
| #  include <limits.h>
 | |
| #endif
 | |
| 
 | |
| #include <posixstat.h>
 | |
| #include <filecntl.h>
 | |
| #include <bashansi.h>
 | |
| 
 | |
| #if !defined (HAVE_KILLPG)
 | |
| #  include <signal.h>
 | |
| #endif
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <errno.h>
 | |
| #include <chartypes.h>
 | |
| 
 | |
| #include <shell.h>
 | |
| 
 | |
| #if !defined (errno)
 | |
| extern int errno;
 | |
| #endif /* !errno */
 | |
| 
 | |
| /* Make the functions strchr and strrchr if they do not exist. */
 | |
| #if !defined (HAVE_STRCHR)
 | |
| char *
 | |
| strchr (string, c)
 | |
|      char *string;
 | |
|      int c;
 | |
| {
 | |
|   register char *s;
 | |
| 
 | |
|   for (s = string; s && *s; s++)
 | |
|     if (*s == c)
 | |
|       return (s);
 | |
| 
 | |
|   return ((char *) NULL);
 | |
| }
 | |
| 
 | |
| char *
 | |
| strrchr (string, c)
 | |
|      char *string;
 | |
|      int c;
 | |
| {
 | |
|   register char *s, *t;
 | |
| 
 | |
|   for (s = string, t = (char *)NULL; s && *s; s++)
 | |
|     if (*s == c)
 | |
|       t = s;
 | |
|   return (t);
 | |
| }
 | |
| #endif /* !HAVE_STRCHR */
 | |
| 
 | |
| #if !defined (HAVE_DUP2) || defined (DUP2_BROKEN)
 | |
| /* Replacement for dup2 (), for those systems which either don't have it,
 | |
|    or supply one with broken behaviour. */
 | |
| int
 | |
| dup2 (fd1, fd2)
 | |
|      int fd1, fd2;
 | |
| {
 | |
|   int saved_errno, r;
 | |
| 
 | |
|   /* If FD1 is not a valid file descriptor, then return immediately with
 | |
|      an error. */
 | |
|   if (fcntl (fd1, F_GETFL, 0) == -1)
 | |
|     return (-1);
 | |
| 
 | |
|   if (fd2 < 0 || fd2 >= getdtablesize ())
 | |
|     {
 | |
|       errno = EBADF;
 | |
|       return (-1);
 | |
|     }
 | |
| 
 | |
|   if (fd1 == fd2)
 | |
|     return (0);
 | |
| 
 | |
|   saved_errno = errno;
 | |
| 
 | |
|   (void) close (fd2);
 | |
|   r = fcntl (fd1, F_DUPFD, fd2);
 | |
| 
 | |
|   if (r >= 0)
 | |
|     errno = saved_errno;
 | |
|   else
 | |
|     if (errno == EINVAL)
 | |
|       errno = EBADF;
 | |
| 
 | |
|   /* Force the new file descriptor to remain open across exec () calls. */
 | |
|   SET_OPEN_ON_EXEC (fd2);
 | |
|   return (r);
 | |
| }
 | |
| #endif /* !HAVE_DUP2 */
 | |
| 
 | |
| /*
 | |
|  * Return the total number of available file descriptors.
 | |
|  *
 | |
|  * On some systems, like 4.2BSD and its descendants, there is a system call
 | |
|  * that returns the size of the descriptor table: getdtablesize().  There are
 | |
|  * lots of ways to emulate this on non-BSD systems.
 | |
|  *
 | |
|  * On System V.3, this can be obtained via a call to ulimit:
 | |
|  *	return (ulimit(4, 0L));
 | |
|  *
 | |
|  * On other System V systems, NOFILE is defined in /usr/include/sys/param.h
 | |
|  * (this is what we assume below), so we can simply use it:
 | |
|  *	return (NOFILE);
 | |
|  *
 | |
|  * On POSIX systems, there are specific functions for retrieving various
 | |
|  * configuration parameters:
 | |
|  *	return (sysconf(_SC_OPEN_MAX));
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #if !defined (HAVE_GETDTABLESIZE)
 | |
| int
 | |
| getdtablesize ()
 | |
| {
 | |
| #  if defined (_POSIX_VERSION) && defined (HAVE_SYSCONF) && defined (_SC_OPEN_MAX)
 | |
|   return (sysconf(_SC_OPEN_MAX));	/* Posix systems use sysconf */
 | |
| #  else /* ! (_POSIX_VERSION && HAVE_SYSCONF && _SC_OPEN_MAX) */
 | |
| #    if defined (ULIMIT_MAXFDS)
 | |
|   return (ulimit (4, 0L));	/* System V.3 systems use ulimit(4, 0L) */
 | |
| #    else /* !ULIMIT_MAXFDS */
 | |
| #      if defined (NOFILE)	/* Other systems use NOFILE */
 | |
|   return (NOFILE);
 | |
| #      else /* !NOFILE */
 | |
|   return (20);			/* XXX - traditional value is 20 */
 | |
| #      endif /* !NOFILE */
 | |
| #    endif /* !ULIMIT_MAXFDS */
 | |
| #  endif /* ! (_POSIX_VERSION && _SC_OPEN_MAX) */
 | |
| }
 | |
| #endif /* !HAVE_GETDTABLESIZE */
 | |
| 
 | |
| #if !defined (HAVE_BCOPY)
 | |
| #  if defined (bcopy)
 | |
| #    undef bcopy
 | |
| #  endif
 | |
| void
 | |
| bcopy (s,d,n)
 | |
|      char *d, *s;
 | |
|      int n;
 | |
| {
 | |
|   FASTCOPY (s, d, n);
 | |
| }
 | |
| #endif /* !HAVE_BCOPY */
 | |
| 
 | |
| #if !defined (HAVE_BZERO)
 | |
| #  if defined (bzero)
 | |
| #    undef bzero
 | |
| #  endif
 | |
| void
 | |
| bzero (s, n)
 | |
|      char *s;
 | |
|      int n;
 | |
| {
 | |
|   register int i;
 | |
|   register char *r;
 | |
| 
 | |
|   for (i = 0, r = s; i < n; i++)
 | |
|     *r++ = '\0';
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #if !defined (HAVE_GETHOSTNAME)
 | |
| #  if defined (HAVE_UNAME)
 | |
| #    include <sys/utsname.h>
 | |
| int
 | |
| gethostname (name, namelen)
 | |
|      char *name;
 | |
|      int namelen;
 | |
| {
 | |
|   int i;
 | |
|   struct utsname ut;
 | |
| 
 | |
|   --namelen;
 | |
| 
 | |
|   uname (&ut);
 | |
|   i = strlen (ut.nodename) + 1;
 | |
|   strncpy (name, ut.nodename, i < namelen ? i : namelen);
 | |
|   name[namelen] = '\0';
 | |
|   return (0);
 | |
| }
 | |
| #  else /* !HAVE_UNAME */
 | |
| int
 | |
| gethostname (name, namelen)
 | |
|      char *name;
 | |
|      int namelen;
 | |
| {
 | |
|   strncpy (name, "unknown", namelen);
 | |
|   name[namelen] = '\0';
 | |
|   return 0;
 | |
| }
 | |
| #  endif /* !HAVE_UNAME */
 | |
| #endif /* !HAVE_GETHOSTNAME */
 | |
| 
 | |
| #if !defined (HAVE_KILLPG)
 | |
| int
 | |
| killpg (pgrp, sig)
 | |
|      pid_t pgrp;
 | |
|      int sig;
 | |
| {
 | |
|   return (kill (-pgrp, sig));
 | |
| }
 | |
| #endif /* !HAVE_KILLPG */
 | |
| 
 | |
| #if !defined (HAVE_MKFIFO) && defined (PROCESS_SUBSTITUTION)
 | |
| int
 | |
| mkfifo (path, mode)
 | |
|      char *path;
 | |
|      int mode;
 | |
| {
 | |
| #if defined (S_IFIFO)
 | |
|   return (mknod (path, (mode | S_IFIFO), 0));
 | |
| #else /* !S_IFIFO */
 | |
|   return (-1);
 | |
| #endif /* !S_IFIFO */
 | |
| }
 | |
| #endif /* !HAVE_MKFIFO && PROCESS_SUBSTITUTION */
 | |
| 
 | |
| #define DEFAULT_MAXGROUPS 64
 | |
| 
 | |
| int
 | |
| getmaxgroups ()
 | |
| {
 | |
|   static int maxgroups = -1;
 | |
| 
 | |
|   if (maxgroups > 0)
 | |
|     return maxgroups;
 | |
| 
 | |
| #if defined (HAVE_SYSCONF) && defined (_SC_NGROUPS_MAX)
 | |
|   maxgroups = sysconf (_SC_NGROUPS_MAX);
 | |
| #else
 | |
| #  if defined (NGROUPS_MAX)
 | |
|   maxgroups = NGROUPS_MAX;
 | |
| #  else /* !NGROUPS_MAX */
 | |
| #    if defined (NGROUPS)
 | |
|   maxgroups = NGROUPS;
 | |
| #    else /* !NGROUPS */
 | |
|   maxgroups = DEFAULT_MAXGROUPS;
 | |
| #    endif /* !NGROUPS */
 | |
| #  endif /* !NGROUPS_MAX */  
 | |
| #endif /* !HAVE_SYSCONF || !SC_NGROUPS_MAX */
 | |
| 
 | |
|   if (maxgroups <= 0)
 | |
|     maxgroups = DEFAULT_MAXGROUPS;
 | |
| 
 | |
|   return maxgroups;
 | |
| }
 | |
| 
 | |
| long
 | |
| getmaxchild ()
 | |
| {
 | |
|   static long maxchild = -1L;
 | |
| 
 | |
|   if (maxchild > 0)
 | |
|     return maxchild;
 | |
| 
 | |
| #if defined (HAVE_SYSCONF) && defined (_SC_CHILD_MAX)
 | |
|   maxchild = sysconf (_SC_CHILD_MAX);
 | |
| #else
 | |
| #  if defined (CHILD_MAX)
 | |
|   maxchild = CHILD_MAX;
 | |
| #  else
 | |
| #    if defined (MAXUPRC)
 | |
|   maxchild = MAXUPRC;
 | |
| #    endif /* MAXUPRC */
 | |
| #  endif /* CHILD_MAX */
 | |
| #endif /* !HAVE_SYSCONF || !_SC_CHILD_MAX */
 | |
| 
 | |
|   return (maxchild);
 | |
| }
 | 
