1/* oslib.c - functions present only in some unix versions. */
2
3/* Copyright (C) 1995 Free Software Foundation, Inc.
4
5   This file is part of GNU Bash, the Bourne Again SHell.
6
7   Bash is free software; you can redistribute it and/or modify it under
8   the terms of the GNU General Public License as published by the Free
9   Software Foundation; either version 2, or (at your option) any later
10   version.
11
12   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
13   WARRANTY; without even the implied warranty of MERCHANTABILITY or
14   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15   for more details.
16
17   You should have received a copy of the GNU General Public License along
18   with Bash; see the file COPYING.  If not, write to the Free Software
19   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA */
20
21#include <config.h>
22
23#include <bashtypes.h>
24#ifndef _MINIX
25#  include <sys/param.h>
26#endif
27
28#if defined (HAVE_UNISTD_H)
29#  include <unistd.h>
30#endif
31
32#if defined (HAVE_LIMITS_H)
33#  include <limits.h>
34#endif
35
36#include <posixstat.h>
37#include <filecntl.h>
38#include <bashansi.h>
39
40#include <stdio.h>
41#include <errno.h>
42#include <chartypes.h>
43
44#include <shell.h>
45
46#if !defined (errno)
47extern int errno;
48#endif /* !errno */
49
50/* Make the functions strchr and strrchr if they do not exist. */
51#if !defined (HAVE_STRCHR)
52char *
53strchr (string, c)
54     char *string;
55     int c;
56{
57  register char *s;
58
59  for (s = string; s && *s; s++)
60    if (*s == c)
61      return (s);
62
63  return ((char *) NULL);
64}
65
66char *
67strrchr (string, c)
68     char *string;
69     int c;
70{
71  register char *s, *t;
72
73  for (s = string, t = (char *)NULL; s && *s; s++)
74    if (*s == c)
75      t = s;
76  return (t);
77}
78#endif /* !HAVE_STRCHR */
79
80#if !defined (HAVE_DUP2) || defined (DUP2_BROKEN)
81/* Replacement for dup2 (), for those systems which either don't have it,
82   or supply one with broken behaviour. */
83int
84dup2 (fd1, fd2)
85     int fd1, fd2;
86{
87  int saved_errno, r;
88
89  /* If FD1 is not a valid file descriptor, then return immediately with
90     an error. */
91  if (fcntl (fd1, F_GETFL, 0) == -1)
92    return (-1);
93
94  if (fd2 < 0 || fd2 >= getdtablesize ())
95    {
96      errno = EBADF;
97      return (-1);
98    }
99
100  if (fd1 == fd2)
101    return (0);
102
103  saved_errno = errno;
104
105  (void) close (fd2);
106  r = fcntl (fd1, F_DUPFD, fd2);
107
108  if (r >= 0)
109    errno = saved_errno;
110  else
111    if (errno == EINVAL)
112      errno = EBADF;
113
114  /* Force the new file descriptor to remain open across exec () calls. */
115  SET_OPEN_ON_EXEC (fd2);
116  return (r);
117}
118#endif /* !HAVE_DUP2 */
119
120/*
121 * Return the total number of available file descriptors.
122 *
123 * On some systems, like 4.2BSD and its descendents, there is a system call
124 * that returns the size of the descriptor table: getdtablesize().  There are
125 * lots of ways to emulate this on non-BSD systems.
126 *
127 * On System V.3, this can be obtained via a call to ulimit:
128 *	return (ulimit(4, 0L));
129 *
130 * On other System V systems, NOFILE is defined in /usr/include/sys/param.h
131 * (this is what we assume below), so we can simply use it:
132 *	return (NOFILE);
133 *
134 * On POSIX systems, there are specific functions for retrieving various
135 * configuration parameters:
136 *	return (sysconf(_SC_OPEN_MAX));
137 *
138 */
139
140#if !defined (HAVE_GETDTABLESIZE)
141int
142getdtablesize ()
143{
144#  if defined (_POSIX_VERSION) && defined (HAVE_SYSCONF) && defined (_SC_OPEN_MAX)
145  return (sysconf(_SC_OPEN_MAX));	/* Posix systems use sysconf */
146#  else /* ! (_POSIX_VERSION && HAVE_SYSCONF && _SC_OPEN_MAX) */
147#    if defined (ULIMIT_MAXFDS)
148  return (ulimit (4, 0L));	/* System V.3 systems use ulimit(4, 0L) */
149#    else /* !ULIMIT_MAXFDS */
150#      if defined (NOFILE)	/* Other systems use NOFILE */
151  return (NOFILE);
152#      else /* !NOFILE */
153  return (20);			/* XXX - traditional value is 20 */
154#      endif /* !NOFILE */
155#    endif /* !ULIMIT_MAXFDS */
156#  endif /* ! (_POSIX_VERSION && _SC_OPEN_MAX) */
157}
158#endif /* !HAVE_GETDTABLESIZE */
159
160#if !defined (HAVE_BCOPY)
161#  if defined (bcopy)
162#    undef bcopy
163#  endif
164void
165bcopy (s,d,n)
166     char *d, *s;
167     int n;
168{
169  FASTCOPY (s, d, n);
170}
171#endif /* !HAVE_BCOPY */
172
173#if !defined (HAVE_BZERO)
174#  if defined (bzero)
175#    undef bzero
176#  endif
177void
178bzero (s, n)
179     char *s;
180     int n;
181{
182  register int i;
183  register char *r;
184
185  for (i = 0, r = s; i < n; i++)
186    *r++ = '\0';
187}
188#endif
189
190#if !defined (HAVE_GETHOSTNAME)
191#  if defined (HAVE_UNAME)
192#    include <sys/utsname.h>
193int
194gethostname (name, namelen)
195     char *name;
196     int namelen;
197{
198  int i;
199  struct utsname ut;
200
201  --namelen;
202
203  uname (&ut);
204  i = strlen (ut.nodename) + 1;
205  strncpy (name, ut.nodename, i < namelen ? i : namelen);
206  name[namelen] = '\0';
207  return (0);
208}
209#  else /* !HAVE_UNAME */
210int
211gethostname (name, namelen)
212     int name, namelen;
213{
214  strncpy (name, "unknown", namelen);
215  name[namelen] = '\0';
216  return 0;
217}
218#  endif /* !HAVE_UNAME */
219#endif /* !HAVE_GETHOSTNAME */
220
221#if !defined (HAVE_KILLPG)
222int
223killpg (pgrp, sig)
224     pid_t pgrp;
225     int sig;
226{
227  return (kill (-pgrp, sig));
228}
229#endif /* !HAVE_KILLPG */
230
231#if !defined (HAVE_MKFIFO) && defined (PROCESS_SUBSTITUTION)
232int
233mkfifo (path, mode)
234     char *path;
235     int mode;
236{
237#if defined (S_IFIFO)
238  return (mknod (path, (mode | S_IFIFO), 0));
239#else /* !S_IFIFO */
240  return (-1);
241#endif /* !S_IFIFO */
242}
243#endif /* !HAVE_MKFIFO && PROCESS_SUBSTITUTION */
244
245#define DEFAULT_MAXGROUPS 64
246
247int
248getmaxgroups ()
249{
250  static int maxgroups = -1;
251
252  if (maxgroups > 0)
253    return maxgroups;
254
255#if defined (HAVE_SYSCONF) && defined (_SC_NGROUPS_MAX)
256  maxgroups = sysconf (_SC_NGROUPS_MAX);
257#else
258#  if defined (NGROUPS_MAX)
259  maxgroups = NGROUPS_MAX;
260#  else /* !NGROUPS_MAX */
261#    if defined (NGROUPS)
262  maxgroups = NGROUPS;
263#    else /* !NGROUPS */
264  maxgroups = DEFAULT_MAXGROUPS;
265#    endif /* !NGROUPS */
266#  endif /* !NGROUPS_MAX */
267#endif /* !HAVE_SYSCONF || !SC_NGROUPS_MAX */
268
269  if (maxgroups <= 0)
270    maxgroups = DEFAULT_MAXGROUPS;
271
272  return maxgroups;
273}
274
275long
276getmaxchild ()
277{
278  static long maxchild = -1L;
279
280  if (maxchild > 0)
281    return maxchild;
282
283#if defined (HAVE_SYSCONF) && defined (_SC_CHILD_MAX)
284  maxchild = sysconf (_SC_CHILD_MAX);
285#else
286#  if defined (CHILD_MAX)
287  maxchild = CHILD_MAX;
288#  else
289#    if defined (MAXUPRC)
290  maxchild = MAXUPRC;
291#    endif /* MAXUPRC */
292#  endif /* CHILD_MAX */
293#endif /* !HAVE_SYSCONF || !_SC_CHILD_MAX */
294
295  return (maxchild);
296}
297