b17a7311488999529ff55506b290bbd0c2c365c1
[platform/upstream/bash.git] / oslib.c
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21 #include "config.h"
22
23 #include "bashtypes.h"
24 #include <sys/param.h>
25
26 #if defined (HAVE_UNISTD_H)
27 #  include <unistd.h>
28 #endif
29
30 #include "posixstat.h"
31 #include "filecntl.h"
32 #include "bashansi.h"
33
34 #include <stdio.h>
35 #include <errno.h>
36 #include <ctype.h>
37
38 #include "shell.h"
39 #include "maxpath.h"
40
41 #if !defined (errno)
42 extern int errno;
43 #endif /* !errno */
44
45 /* A standard error message to use when getcwd() returns NULL. */
46 char *bash_getcwd_errstr = "getcwd: cannot access parent directories";
47
48 #if !defined (HAVE_SYSCONF) || !defined (_SC_CLK_TCK)
49 #  if !defined (CLK_TCK)
50 #    if defined (HZ)
51 #      define CLK_TCK HZ
52 #    else
53 #      define CLK_TCK 60
54 #    endif
55 #  endif /* !CLK_TCK */
56 #endif /* !HAVE_SYSCONF && !_SC_CLK_TCK */
57
58 long
59 get_clk_tck ()
60 {
61   static long retval = 0;
62
63   if (retval != 0)
64     return (retval);
65
66 #if defined (HAVE_SYSCONF) && defined (_SC_CLK_TCK)
67   retval = sysconf (_SC_CLK_TCK);
68 #else /* !SYSCONF || !_SC_CLK_TCK */
69   retval = CLK_TCK;
70 #endif /* !SYSCONF || !_SC_CLK_TCK */
71
72   return (retval);
73 }
74
75 /* Make the functions strchr and strrchr if they do not exist. */
76 #if !defined (HAVE_STRCHR)
77 char *
78 strchr (string, c)
79      char *string;
80      int c;
81 {
82   register char *s;
83
84   for (s = string; s && *s; s++)
85     if (*s == c)
86       return (s);
87
88   return ((char *) NULL);
89 }
90
91 char *
92 strrchr (string, c)
93      char *string;
94      int c;
95 {
96   register char *s, *t;
97
98   for (s = string, t = (char *)NULL; s && *s; s++)
99     if (*s == c)
100       t = s;
101   return (t);
102 }
103 #endif /* !HAVE_STRCHR */
104
105 #if !defined (HAVE_STRCASECMP)
106
107 #if !defined (to_lower)
108 #  define to_lower(c) (islower(c) ? (c) : tolower(c))
109 #endif /* to_lower */
110
111 /* Compare at most COUNT characters from string1 to string2.  Case
112    doesn't matter. */
113 int
114 strncasecmp (string1, string2, count)
115      char *string1, *string2;
116      int count;
117 {
118   register char *s1, *s2;
119   register int r;
120
121   if (count > 0)
122     {
123       s1 = string1;
124       s2 = string2;
125       do
126         {
127           if ((r = to_lower (*s1) - to_lower (*s2)) != 0)
128             return r;
129           if (*s1++ == '\0')
130             break;
131           s2++;
132         }
133       while (--count != 0);
134     }
135   return (0);
136 }
137
138 /* strcmp (), but caseless. */
139 int
140 strcasecmp (string1, string2)
141      char *string1, *string2;
142 {
143   register char *s1, *s2;
144   register int r;
145
146   s1 = string1;
147   s2 = string2;
148
149   while ((r = to_lower (*s1) - to_lower (*s2)) == 0)
150     {
151       if (*s1++ == '\0')
152         return 0;
153       s2++;
154     }
155   return (r);
156 }
157 #endif /* !HAVE_STRCASECMP */
158
159 /* Return a string corresponding to the error number E.  From
160    the ANSI C spec. */
161 #if defined (strerror)
162 #  undef strerror
163 #endif
164
165 #if !defined (HAVE_STRERROR)
166 char *
167 strerror (e)
168      int e;
169 {
170   static char emsg[40];
171 #if defined (HAVE_SYS_ERRLIST)
172   extern int sys_nerr;
173   extern char *sys_errlist[];
174
175   if (e > 0 && e < sys_nerr)
176     return (sys_errlist[e]);
177   else
178 #endif /* HAVE_SYS_ERRLIST */
179     {
180       sprintf (emsg, "Unknown error %d", e);
181       return (&emsg[0]);
182     }
183 }
184 #endif /* HAVE_STRERROR */
185
186 #if !defined (HAVE_DUP2) || defined (DUP2_BROKEN)
187 /* Replacement for dup2 (), for those systems which either don't have it,
188    or supply one with broken behaviour. */
189 int
190 dup2 (fd1, fd2)
191      int fd1, fd2;
192 {
193   int saved_errno, r;
194
195   /* If FD1 is not a valid file descriptor, then return immediately with
196      an error. */
197   if (fcntl (fd1, F_GETFL, 0) == -1)
198     return (-1);
199
200   if (fd2 < 0 || fd2 >= getdtablesize ())
201     {
202       errno = EBADF;
203       return (-1);
204     }
205
206   if (fd1 == fd2)
207     return (0);
208
209   saved_errno = errno;
210
211   (void) close (fd2);
212   r = fcntl (fd1, F_DUPFD, fd2);
213
214   if (r >= 0)
215     errno = saved_errno;
216   else
217     if (errno == EINVAL)
218       errno = EBADF;
219
220   /* Force the new file descriptor to remain open across exec () calls. */
221   SET_OPEN_ON_EXEC (fd2);
222   return (r);
223 }
224 #endif /* !HAVE_DUP2 */
225
226 /*
227  * Return the total number of available file descriptors.
228  *
229  * On some systems, like 4.2BSD and its descendents, there is a system call
230  * that returns the size of the descriptor table: getdtablesize().  There are
231  * lots of ways to emulate this on non-BSD systems.
232  *
233  * On System V.3, this can be obtained via a call to ulimit:
234  *      return (ulimit(4, 0L));
235  *
236  * On other System V systems, NOFILE is defined in /usr/include/sys/param.h
237  * (this is what we assume below), so we can simply use it:
238  *      return (NOFILE);
239  *
240  * On POSIX systems, there are specific functions for retrieving various
241  * configuration parameters:
242  *      return (sysconf(_SC_OPEN_MAX));
243  *
244  */
245
246 #if !defined (HAVE_GETDTABLESIZE)
247 int
248 getdtablesize ()
249 {
250 #  if defined (_POSIX_VERSION) && defined (HAVE_SYSCONF) && defined (_SC_OPEN_MAX)
251   return (sysconf(_SC_OPEN_MAX));       /* Posix systems use sysconf */
252 #  else /* ! (_POSIX_VERSION && HAVE_SYSCONF && _SC_OPEN_MAX) */
253 #    if defined (ULIMIT_MAXFDS)
254   return (ulimit (4, 0L));      /* System V.3 systems use ulimit(4, 0L) */
255 #    else /* !ULIMIT_MAXFDS */
256 #      if defined (NOFILE)      /* Other systems use NOFILE */
257   return (NOFILE);
258 #      else /* !NOFILE */
259   return (20);                  /* XXX - traditional value is 20 */
260 #      endif /* !NOFILE */
261 #    endif /* !ULIMIT_MAXFDS */
262 #  endif /* ! (_POSIX_VERSION && _SC_OPEN_MAX) */
263 }
264 #endif /* !HAVE_GETDTABLESIZE */
265
266 #if !defined (HAVE_BCOPY)
267 void
268 bcopy (s,d,n)
269      char *d, *s;
270      int n;
271 {
272   FASTCOPY (s, d, n);
273 }
274 #endif /* !HAVE_BCOPY */
275
276 #if !defined (HAVE_BZERO)
277 void
278 bzero (s, n)
279      char *s;
280      int n;
281 {
282   register int i;
283   register char *r;
284
285   for (i = 0, r = s; i < n; i++)
286     *r++ = '\0';
287 }
288 #endif
289
290 #if !defined (HAVE_GETHOSTNAME)
291 #  if defined (HAVE_UNAME)
292 #    include <sys/utsname.h>
293 int
294 gethostname (name, namelen)
295      char *name;
296      int namelen;
297 {
298   int i;
299   struct utsname ut;
300
301   --namelen;
302
303   uname (&ut);
304   i = strlen (ut.nodename) + 1;
305   strncpy (name, ut.nodename, i < namelen ? i : namelen);
306   name[namelen] = '\0';
307   return (0);
308 }
309 #  else /* !HAVE_UNAME */
310 int
311 gethostname (name, namelen)
312      int name, namelen;
313 {
314   strncpy (name, "unknown", namelen);
315   name[namelen] = '\0';
316   return 0;
317 }
318 #  endif /* !HAVE_UNAME */
319 #endif /* !HAVE_GETHOSTNAME */
320
321 #if !defined (HAVE_KILLPG)
322 int
323 killpg (pgrp, sig)
324      pid_t pgrp;
325      int sig;
326 {
327   return (kill (-pgrp, sig));
328 }
329 #endif /* !HAVE_KILLPG */
330
331
332 /* We supply our own version of getenv () because we want library
333    routines to get the changed values of exported variables. */
334
335 /* The NeXT C library has getenv () defined and used in the same file.
336    This screws our scheme.  However, Bash will run on the NeXT using
337    the C library getenv (), since right now the only environment variable
338    that we care about is HOME, and that is already defined.  */
339 #if defined (CAN_REDEFINE_GETENV)
340 static char *last_tempenv_value = (char *)NULL;
341 extern char **environ;
342
343 char *
344 getenv (name)
345 #if defined (__linux__) || defined (__bsdi__) || defined (convex)
346      const char *name;
347 #else
348      char const *name;
349 #endif /* !__linux__ && !__bsdi__ && !convex */
350 {
351   SHELL_VAR *var;
352
353   var = find_tempenv_variable ((char *)name);
354   if (var)
355     {
356       FREE (last_tempenv_value);
357
358       last_tempenv_value = savestring (value_cell (var));
359       dispose_variable (var);
360       return (last_tempenv_value);
361     }
362   else if (shell_variables)
363     {
364       var = find_variable ((char *)name);
365       if (var && exported_p (var))
366         return (value_cell (var));
367     }
368   else
369     {
370       register int i, len;
371
372       /* In some cases, s5r3 invokes getenv() before main(); BSD systems
373          using gprof also exhibit this behavior.  This means that
374          shell_variables will be 0 when this is invoked.  We look up the
375          variable in the real environment in that case. */
376
377       for (i = 0, len = strlen (name); environ[i]; i++)
378         {
379           if ((STREQN (environ[i], name, len)) && (environ[i][len] == '='))
380             return (environ[i] + len + 1);
381         }
382     }
383
384   return ((char *)NULL);
385 }
386
387 /* Some versions of Unix use _getenv instead. */
388 char *
389 _getenv (name)
390 #if defined (__linux__) || defined (__bsdi__) || defined (convex)
391      const char *name;
392 #else
393      char const *name;
394 #endif /* !__linux__ && !__bsdi__ && !convex */
395 {
396   return (getenv (name));
397 }
398
399 #endif /* CAN_REDEFINE_GETENV */
400
401 #if !defined (HAVE_MKFIFO) && defined (PROCESS_SUBSTITUTION)
402 int
403 mkfifo (path, mode)
404      char *path;
405      int mode;
406 {
407 #if defined (S_IFIFO)
408   return (mknod (path, (mode | S_IFIFO), 0));
409 #else /* !S_IFIFO */
410   return (-1);
411 #endif /* !S_IFIFO */
412 }
413 #endif
414
415 #if !defined (HAVE_SETLINEBUF)
416 /* Cause STREAM to buffer lines as opposed to characters or blocks. */
417 int
418 setlinebuf (stream)
419      FILE *stream;
420 {
421 #if defined (_IOLBF)
422 #  if defined (SETVBUF_REVERSED)
423   setvbuf (stream, _IOLBF, (char *)NULL, BUFSIZ);
424 #  else /* !SETVBUF_REVERSED */
425   setvbuf (stream, (char *)NULL, _IOLBF, BUFSIZ);
426 #  endif /* !SETVBUF_REVERSED */
427 #endif /* _IOLBF */
428   return (0);
429 }
430 #endif /* !HAVE_SETLINEBUF */