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