mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-07-17 00:46:38 +02:00
commit bash-20120727 snapshot
This commit is contained in:
@@ -32,7 +32,7 @@
|
||||
#endif
|
||||
|
||||
#if !defined (getpagesize)
|
||||
# ifndef _MINIX
|
||||
# if defined (HAVE_SYS_PARAM_H)
|
||||
# include <sys/param.h>
|
||||
# endif
|
||||
# if defined (PAGESIZE)
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/* Emulation of getpagesize() for systems that need it.
|
||||
Copyright (C) 1991-2003 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/>.
|
||||
*/
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
# if defined (_SC_PAGESIZE)
|
||||
# define getpagesize() sysconf(_SC_PAGESIZE)
|
||||
# else
|
||||
# if defined (_SC_PAGE_SIZE)
|
||||
# define getpagesize() sysconf(_SC_PAGE_SIZE)
|
||||
# endif /* _SC_PAGE_SIZE */
|
||||
# endif /* _SC_PAGESIZE */
|
||||
#endif
|
||||
|
||||
#if !defined (getpagesize)
|
||||
# ifndef _MINIX
|
||||
# include <sys/param.h>
|
||||
# endif
|
||||
# if defined (PAGESIZE)
|
||||
# define getpagesize() PAGESIZE
|
||||
# else /* !PAGESIZE */
|
||||
# if defined (EXEC_PAGESIZE)
|
||||
# define getpagesize() EXEC_PAGESIZE
|
||||
# else /* !EXEC_PAGESIZE */
|
||||
# if defined (NBPG)
|
||||
# if !defined (CLSIZE)
|
||||
# define CLSIZE 1
|
||||
# endif /* !CLSIZE */
|
||||
# define getpagesize() (NBPG * CLSIZE)
|
||||
# else /* !NBPG */
|
||||
# if defined (NBPC)
|
||||
# define getpagesize() NBPC
|
||||
# endif /* NBPC */
|
||||
# endif /* !NBPG */
|
||||
# endif /* !EXEC_PAGESIZE */
|
||||
# endif /* !PAGESIZE */
|
||||
#endif /* !getpagesize */
|
||||
|
||||
#if !defined (getpagesize)
|
||||
# define getpagesize() 4096 /* Just punt and use reasonable value */
|
||||
#endif
|
||||
+3
-1
@@ -21,7 +21,9 @@
|
||||
#include <config.h>
|
||||
|
||||
#include <bashtypes.h>
|
||||
#include <sys/param.h>
|
||||
#if defined (HAVE_SYS_PARAM_H)
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/* clktck.c - get the value of CLK_TCK. */
|
||||
|
||||
/* Copyright (C) 1997 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>
|
||||
#include <sys/param.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_LIMITS_H)
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#if !defined (HAVE_SYSCONF) || !defined (_SC_CLK_TCK)
|
||||
# if !defined (CLK_TCK)
|
||||
# if defined (HZ)
|
||||
# define CLK_TCK HZ
|
||||
# else
|
||||
# define CLK_TCK 60
|
||||
# endif
|
||||
# endif /* !CLK_TCK */
|
||||
#endif /* !HAVE_SYSCONF && !_SC_CLK_TCK */
|
||||
|
||||
long
|
||||
get_clk_tck ()
|
||||
{
|
||||
static long retval = 0;
|
||||
|
||||
if (retval != 0)
|
||||
return (retval);
|
||||
|
||||
#if defined (HAVE_SYSCONF) && defined (_SC_CLK_TCK)
|
||||
retval = sysconf (_SC_CLK_TCK);
|
||||
#else /* !SYSCONF || !_SC_CLK_TCK */
|
||||
retval = CLK_TCK;
|
||||
#endif /* !SYSCONF || !_SC_CLK_TCK */
|
||||
|
||||
return (retval);
|
||||
}
|
||||
@@ -67,7 +67,9 @@ static char rcsid[] = "$Id: inet_addr.c,v 1.5 1996/08/14 03:48:37 drepper Exp $"
|
||||
#if !defined (HAVE_INET_ATON) && defined (HAVE_NETWORK) && defined (HAVE_NETINET_IN_H) && defined (HAVE_ARPA_INET_H)
|
||||
|
||||
#include <sys/types.h>
|
||||
#if defined (HAVE_SYS_PARAM_H)
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
/* inet_aton - convert string to numeric IP address */
|
||||
|
||||
/* Snagged from GNU C library, version 2.0.3. */
|
||||
|
||||
/*
|
||||
* ++Copyright++ 1983, 1990, 1993
|
||||
* -
|
||||
* Copyright (c) 1983, 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* -
|
||||
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies, and that
|
||||
* the name of Digital Equipment Corporation not be used in advertising or
|
||||
* publicity pertaining to distribution of the document or software without
|
||||
* specific, written prior permission.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
|
||||
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
* -
|
||||
* --Copyright--
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
|
||||
static char rcsid[] = "$Id: inet_addr.c,v 1.5 1996/08/14 03:48:37 drepper Exp $";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if !defined (HAVE_INET_ATON) && defined (HAVE_NETWORK) && defined (HAVE_NETINET_IN_H) && defined (HAVE_ARPA_INET_H)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <bashansi.h>
|
||||
#include <ctype.h>
|
||||
#include <stdc.h>
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
# define INADDR_NONE 0xffffffff
|
||||
#endif
|
||||
|
||||
/* these are compatibility routines, not needed on recent BSD releases */
|
||||
|
||||
#if 0
|
||||
/* Not used, not needed. */
|
||||
/*
|
||||
* Ascii internet address interpretation routine.
|
||||
* The value returned is in network order.
|
||||
*/
|
||||
u_long
|
||||
inet_addr(cp)
|
||||
register const char *cp;
|
||||
{
|
||||
struct in_addr val;
|
||||
|
||||
if (inet_aton(cp, &val))
|
||||
return (val.s_addr);
|
||||
return (INADDR_NONE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check whether "cp" is a valid ascii representation
|
||||
* of an Internet address and convert to a binary address.
|
||||
* Returns 1 if the address is valid, 0 if not.
|
||||
* This replaces inet_addr, the return value from which
|
||||
* cannot distinguish between failure and a local broadcast address.
|
||||
*/
|
||||
int
|
||||
inet_aton(cp, addr)
|
||||
register const char *cp;
|
||||
struct in_addr *addr;
|
||||
{
|
||||
register u_bits32_t val;
|
||||
register int base, n;
|
||||
register unsigned char c;
|
||||
u_int parts[4];
|
||||
register u_int *pp = parts;
|
||||
|
||||
c = *cp;
|
||||
for (;;) {
|
||||
/*
|
||||
* Collect number up to ``.''.
|
||||
* Values are specified as for C:
|
||||
* 0x=hex, 0=octal, isdigit=decimal.
|
||||
*/
|
||||
#if 0
|
||||
if (!isdigit(c))
|
||||
#else
|
||||
if (c != '0' && c != '1' && c != '2' && c != '3' && c != '4' &&
|
||||
c != '5' && c != '6' && c != '7' && c != '8' && c != '9')
|
||||
#endif
|
||||
return (0);
|
||||
val = 0; base = 10;
|
||||
if (c == '0') {
|
||||
c = *++cp;
|
||||
if (c == 'x' || c == 'X')
|
||||
base = 16, c = *++cp;
|
||||
else
|
||||
base = 8;
|
||||
}
|
||||
for (;;) {
|
||||
if (isascii(c) && isdigit(c)) {
|
||||
val = (val * base) + (c - '0');
|
||||
c = *++cp;
|
||||
} else if (base == 16 && isascii(c) && isxdigit(c)) {
|
||||
val = (val << 4) |
|
||||
(c + 10 - (islower(c) ? 'a' : 'A'));
|
||||
c = *++cp;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
if (c == '.') {
|
||||
/*
|
||||
* Internet format:
|
||||
* a.b.c.d
|
||||
* a.b.c (with c treated as 16 bits)
|
||||
* a.b (with b treated as 24 bits)
|
||||
*/
|
||||
if (pp >= parts + 3)
|
||||
return (0);
|
||||
*pp++ = val;
|
||||
c = *++cp;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Check for trailing characters.
|
||||
*/
|
||||
if (c != '\0' && (!isascii(c) || !isspace(c)))
|
||||
return (0);
|
||||
/*
|
||||
* Concoct the address according to
|
||||
* the number of parts specified.
|
||||
*/
|
||||
n = pp - parts + 1;
|
||||
switch (n) {
|
||||
|
||||
case 0:
|
||||
return (0); /* initial nondigit */
|
||||
|
||||
case 1: /* a -- 32 bits */
|
||||
break;
|
||||
|
||||
case 2: /* a.b -- 8.24 bits */
|
||||
if (val > 0xffffff)
|
||||
return (0);
|
||||
val |= parts[0] << 24;
|
||||
break;
|
||||
|
||||
case 3: /* a.b.c -- 8.8.16 bits */
|
||||
if (val > 0xffff)
|
||||
return (0);
|
||||
val |= (parts[0] << 24) | (parts[1] << 16);
|
||||
break;
|
||||
|
||||
case 4: /* a.b.c.d -- 8.8.8.8 bits */
|
||||
if (val > 0xff)
|
||||
return (0);
|
||||
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
|
||||
break;
|
||||
}
|
||||
if (addr)
|
||||
addr->s_addr = htonl(val);
|
||||
return (1);
|
||||
}
|
||||
|
||||
#endif /* !HAVE_INET_ATON */
|
||||
+1
-1
@@ -28,7 +28,7 @@
|
||||
#include <posixdir.h>
|
||||
#include <bashansi.h>
|
||||
|
||||
#ifndef _MINIX
|
||||
#if defined (HAVE_SYS_PARAM_H)
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
/* mailstat.c -- stat a mailbox file, handling maildir-type mail directories */
|
||||
|
||||
/* Copyright (C) 2001 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 <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <bashtypes.h>
|
||||
#include <posixstat.h>
|
||||
#include <posixdir.h>
|
||||
#include <bashansi.h>
|
||||
|
||||
#ifndef _MINIX
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#include <maxpath.h>
|
||||
|
||||
/*
|
||||
* Stat a file. If it's a maildir, check all messages
|
||||
* in the maildir and present the grand total as a file.
|
||||
* The fields in the 'struct stat' are from the mail directory.
|
||||
* The following fields are emulated:
|
||||
*
|
||||
* st_nlink always 1, unless st_blocks is not present, in which case it's
|
||||
* the total number of messages
|
||||
* st_size total number of bytes in all files
|
||||
* st_blocks total number of messages, if present in struct stat
|
||||
* st_atime access time of newest file in maildir
|
||||
* st_mtime modify time of newest file in maildir
|
||||
* st_mode S_IFDIR changed to S_IFREG
|
||||
*
|
||||
* This is good enough for most mail-checking applications.
|
||||
*/
|
||||
|
||||
int
|
||||
mailstat(path, st)
|
||||
const char *path;
|
||||
struct stat *st;
|
||||
{
|
||||
static struct stat st_new_last, st_ret_last;
|
||||
struct stat st_ret, st_tmp;
|
||||
DIR *dd;
|
||||
struct dirent *fn;
|
||||
char dir[PATH_MAX * 2], file[PATH_MAX * 2];
|
||||
int i, l;
|
||||
time_t atime, mtime;
|
||||
|
||||
atime = mtime = 0;
|
||||
|
||||
/* First see if it's a directory. */
|
||||
if ((i = stat(path, st)) != 0 || S_ISDIR(st->st_mode) == 0)
|
||||
return i;
|
||||
|
||||
if (strlen(path) > sizeof(dir) - 5)
|
||||
{
|
||||
#ifdef ENAMETOOLONG
|
||||
errno = ENAMETOOLONG;
|
||||
#else
|
||||
errno = EINVAL;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
st_ret = *st;
|
||||
st_ret.st_nlink = 1;
|
||||
st_ret.st_size = 0;
|
||||
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
|
||||
st_ret.st_blocks = 0;
|
||||
#else
|
||||
st_ret.st_nlink = 0;
|
||||
#endif
|
||||
st_ret.st_mode &= ~S_IFDIR;
|
||||
st_ret.st_mode |= S_IFREG;
|
||||
|
||||
/* See if cur/ is present */
|
||||
sprintf(dir, "%s/cur", path);
|
||||
if (stat(dir, &st_tmp) || S_ISDIR(st_tmp.st_mode) == 0)
|
||||
return 0;
|
||||
st_ret.st_atime = st_tmp.st_atime;
|
||||
|
||||
/* See if tmp/ is present */
|
||||
sprintf(dir, "%s/tmp", path);
|
||||
if (stat(dir, &st_tmp) || S_ISDIR(st_tmp.st_mode) == 0)
|
||||
return 0;
|
||||
st_ret.st_mtime = st_tmp.st_mtime;
|
||||
|
||||
/* And new/ */
|
||||
sprintf(dir, "%s/new", path);
|
||||
if (stat(dir, &st_tmp) || S_ISDIR(st_tmp.st_mode) == 0)
|
||||
return 0;
|
||||
st_ret.st_mtime = st_tmp.st_mtime;
|
||||
|
||||
/* Optimization - if new/ didn't change, nothing else did. */
|
||||
if (st_tmp.st_dev == st_new_last.st_dev &&
|
||||
st_tmp.st_ino == st_new_last.st_ino &&
|
||||
st_tmp.st_atime == st_new_last.st_atime &&
|
||||
st_tmp.st_mtime == st_new_last.st_mtime)
|
||||
{
|
||||
*st = st_ret_last;
|
||||
return 0;
|
||||
}
|
||||
st_new_last = st_tmp;
|
||||
|
||||
/* Loop over new/ and cur/ */
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
sprintf(dir, "%s/%s", path, i ? "cur" : "new");
|
||||
sprintf(file, "%s/", dir);
|
||||
l = strlen(file);
|
||||
if ((dd = opendir(dir)) == NULL)
|
||||
return 0;
|
||||
while ((fn = readdir(dd)) != NULL)
|
||||
{
|
||||
if (fn->d_name[0] == '.' || strlen(fn->d_name) + l >= sizeof(file))
|
||||
continue;
|
||||
strcpy(file + l, fn->d_name);
|
||||
if (stat(file, &st_tmp) != 0)
|
||||
continue;
|
||||
st_ret.st_size += st_tmp.st_size;
|
||||
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
|
||||
st_ret.st_blocks++;
|
||||
#else
|
||||
st_ret.st_nlink++;
|
||||
#endif
|
||||
if (st_tmp.st_atime != st_tmp.st_mtime && st_tmp.st_atime > atime)
|
||||
atime = st_tmp.st_atime;
|
||||
if (st_tmp.st_mtime > mtime)
|
||||
mtime = st_tmp.st_mtime;
|
||||
}
|
||||
closedir(dd);
|
||||
}
|
||||
|
||||
/* if (atime) */ /* Set atime even if cur/ is empty */
|
||||
st_ret.st_atime = atime;
|
||||
if (mtime)
|
||||
st_ret.st_mtime = mtime;
|
||||
|
||||
*st = st_ret_last = st_ret;
|
||||
return 0;
|
||||
}
|
||||
+1
-1
@@ -21,7 +21,7 @@
|
||||
#include <config.h>
|
||||
|
||||
#include <bashtypes.h>
|
||||
#ifndef _MINIX
|
||||
#if defined (HAVE_SYS_PARAM_H)
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
|
||||
+301
@@ -0,0 +1,301 @@
|
||||
/* 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>
|
||||
#ifndef _MINIX
|
||||
# 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 descendents, 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);
|
||||
}
|
||||
+1
-1
@@ -21,7 +21,7 @@
|
||||
#include <config.h>
|
||||
|
||||
#include <bashtypes.h>
|
||||
#ifndef _MINIX
|
||||
#if defined (HAVE_SYS_PARAM_H)
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
#include <posixstat.h>
|
||||
|
||||
@@ -0,0 +1,234 @@
|
||||
/* pathcanon.c -- canonicalize and manipulate pathnames. */
|
||||
|
||||
/* Copyright (C) 2000 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>
|
||||
#ifndef _MINIX
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
#include <posixstat.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <filecntl.h>
|
||||
#include <bashansi.h>
|
||||
#include <stdio.h>
|
||||
#include <chartypes.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "shell.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#if defined (__CYGWIN__)
|
||||
#include <sys/cygwin.h>
|
||||
|
||||
static int
|
||||
_is_cygdrive (path)
|
||||
char *path;
|
||||
{
|
||||
static char user[MAXPATHLEN];
|
||||
static char system[MAXPATHLEN];
|
||||
static int first_time = 1;
|
||||
|
||||
/* If the path is the first part of a network path, treat it as
|
||||
existing. */
|
||||
if (path[0] == '/' && path[1] == '/' && !strchr (path + 2, '/'))
|
||||
return 1;
|
||||
/* Otherwise check for /cygdrive prefix. */
|
||||
if (first_time)
|
||||
{
|
||||
char user_flags[MAXPATHLEN];
|
||||
char system_flags[MAXPATHLEN];
|
||||
/* Get the cygdrive info */
|
||||
cygwin_internal (CW_GET_CYGDRIVE_INFO, user, system, user_flags, system_flags);
|
||||
first_time = 0;
|
||||
}
|
||||
return !strcasecmp (path, user) || !strcasecmp (path, system);
|
||||
}
|
||||
#endif /* __CYGWIN__ */
|
||||
|
||||
/* Return 1 if PATH corresponds to a directory. A function for debugging. */
|
||||
static int
|
||||
_path_isdir (path)
|
||||
char *path;
|
||||
{
|
||||
int l;
|
||||
struct stat sb;
|
||||
|
||||
/* This should leave errno set to the correct value. */
|
||||
errno = 0;
|
||||
l = stat (path, &sb) == 0 && S_ISDIR (sb.st_mode);
|
||||
#if defined (__CYGWIN__)
|
||||
if (l == 0)
|
||||
l = _is_cygdrive (path);
|
||||
#endif
|
||||
return l;
|
||||
}
|
||||
|
||||
/* Canonicalize PATH, and return a new path. The new path differs from PATH
|
||||
in that:
|
||||
Multple `/'s are collapsed to a single `/'.
|
||||
Leading `./'s and trailing `/.'s are removed.
|
||||
Trailing `/'s are removed.
|
||||
Non-leading `../'s and trailing `..'s are handled by removing
|
||||
portions of the path. */
|
||||
|
||||
/* Look for ROOTEDPATH, PATHSEP, DIRSEP, and ISDIRSEP in ../../general.h */
|
||||
|
||||
#define DOUBLE_SLASH(p) ((p[0] == '/') && (p[1] == '/') && p[2] != '/')
|
||||
|
||||
char *
|
||||
sh_canonpath (path, flags)
|
||||
char *path;
|
||||
int flags;
|
||||
{
|
||||
char stub_char;
|
||||
char *result, *p, *q, *base, *dotdot;
|
||||
int rooted, double_slash_path;
|
||||
|
||||
/* The result cannot be larger than the input PATH. */
|
||||
result = (flags & PATH_NOALLOC) ? path : savestring (path);
|
||||
|
||||
/* POSIX.2 says to leave a leading `//' alone. On cygwin, we skip over any
|
||||
leading `x:' (dos drive name). */
|
||||
if (rooted = ROOTEDPATH(path))
|
||||
{
|
||||
stub_char = DIRSEP;
|
||||
#if defined (__CYGWIN__)
|
||||
base = (ISALPHA((unsigned char)result[0]) && result[1] == ':') ? result + 3 : result + 1;
|
||||
#else
|
||||
base = result + 1;
|
||||
#endif
|
||||
double_slash_path = DOUBLE_SLASH (path);
|
||||
base += double_slash_path;
|
||||
}
|
||||
else
|
||||
{
|
||||
stub_char = '.';
|
||||
#if defined (__CYGWIN__)
|
||||
base = (ISALPHA((unsigned char)result[0]) && result[1] == ':') ? result + 2 : result;
|
||||
#else
|
||||
base = result;
|
||||
#endif
|
||||
double_slash_path = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* invariants:
|
||||
* base points to the portion of the path we want to modify
|
||||
* p points at beginning of path element we're considering.
|
||||
* q points just past the last path element we wrote (no slash).
|
||||
* dotdot points just past the point where .. cannot backtrack
|
||||
* any further (no slash).
|
||||
*/
|
||||
p = q = dotdot = base;
|
||||
|
||||
while (*p)
|
||||
{
|
||||
if (ISDIRSEP(p[0])) /* null element */
|
||||
p++;
|
||||
else if(p[0] == '.' && PATHSEP(p[1])) /* . and ./ */
|
||||
p += 1; /* don't count the separator in case it is nul */
|
||||
else if (p[0] == '.' && p[1] == '.' && PATHSEP(p[2])) /* .. and ../ */
|
||||
{
|
||||
p += 2; /* skip `..' */
|
||||
if (q > dotdot) /* can backtrack */
|
||||
{
|
||||
if (flags & PATH_CHECKDOTDOT)
|
||||
{
|
||||
char c;
|
||||
|
||||
/* Make sure what we have so far corresponds to a valid
|
||||
path before we chop some of it off. */
|
||||
c = *q;
|
||||
*q = '\0';
|
||||
if (_path_isdir (result) == 0)
|
||||
{
|
||||
if ((flags & PATH_NOALLOC) == 0)
|
||||
free (result);
|
||||
return ((char *)NULL);
|
||||
}
|
||||
*q = c;
|
||||
}
|
||||
|
||||
while (--q > dotdot && ISDIRSEP(*q) == 0)
|
||||
;
|
||||
}
|
||||
else if (rooted == 0)
|
||||
{
|
||||
/* /.. is / but ./../ is .. */
|
||||
if (q != base)
|
||||
*q++ = DIRSEP;
|
||||
*q++ = '.';
|
||||
*q++ = '.';
|
||||
dotdot = q;
|
||||
}
|
||||
}
|
||||
else /* real path element */
|
||||
{
|
||||
/* add separator if not at start of work portion of result */
|
||||
if (q != base)
|
||||
*q++ = DIRSEP;
|
||||
while (*p && (ISDIRSEP(*p) == 0))
|
||||
*q++ = *p++;
|
||||
/* Check here for a valid directory with _path_isdir. */
|
||||
if (flags & PATH_CHECKEXISTS)
|
||||
{
|
||||
char c;
|
||||
|
||||
/* Make sure what we have so far corresponds to a valid
|
||||
path before we chop some of it off. */
|
||||
c = *q;
|
||||
*q = '\0';
|
||||
if (_path_isdir (result) == 0)
|
||||
{
|
||||
if ((flags & PATH_NOALLOC) == 0)
|
||||
free (result);
|
||||
return ((char *)NULL);
|
||||
}
|
||||
*q = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Empty string is really ``.'' or `/', depending on what we started with. */
|
||||
if (q == result)
|
||||
*q++ = stub_char;
|
||||
*q = '\0';
|
||||
|
||||
/* If the result starts with `//', but the original path does not, we
|
||||
can turn the // into /. Because of how we set `base', this should never
|
||||
be true, but it's a sanity check. */
|
||||
if (DOUBLE_SLASH(result) && double_slash_path == 0)
|
||||
{
|
||||
if (result[2] == '\0') /* short-circuit for bare `//' */
|
||||
result[1] = '\0';
|
||||
else
|
||||
strcpy (result, result + 1);
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
+1
-1
@@ -21,7 +21,7 @@
|
||||
#include <config.h>
|
||||
|
||||
#include <bashtypes.h>
|
||||
#ifndef _MINIX
|
||||
#if defined (HAVE_SYS_PARAM_H)
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
#include <posixstat.h>
|
||||
|
||||
@@ -0,0 +1,296 @@
|
||||
/* pathphys.c -- return pathname with all symlinks expanded. */
|
||||
|
||||
/* Copyright (C) 2000 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>
|
||||
#ifndef _MINIX
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
#include <posixstat.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <filecntl.h>
|
||||
#include <bashansi.h>
|
||||
#include <stdio.h>
|
||||
#include <chartypes.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "shell.h"
|
||||
|
||||
#if !defined (MAXSYMLINKS)
|
||||
# define MAXSYMLINKS 32
|
||||
#endif
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif /* !errno */
|
||||
|
||||
extern char *get_working_directory __P((char *));
|
||||
|
||||
static int
|
||||
_path_readlink (path, buf, bufsiz)
|
||||
char *path;
|
||||
char *buf;
|
||||
int bufsiz;
|
||||
{
|
||||
#ifdef HAVE_READLINK
|
||||
return readlink (path, buf, bufsiz);
|
||||
#else
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Look for ROOTEDPATH, PATHSEP, DIRSEP, and ISDIRSEP in ../../general.h */
|
||||
|
||||
#define DOUBLE_SLASH(p) ((p[0] == '/') && (p[1] == '/') && p[2] != '/')
|
||||
|
||||
/*
|
||||
* Return PATH with all symlinks expanded in newly-allocated memory.
|
||||
* This always gets an absolute pathname.
|
||||
*/
|
||||
|
||||
char *
|
||||
sh_physpath (path, flags)
|
||||
char *path;
|
||||
int flags;
|
||||
{
|
||||
char tbuf[PATH_MAX+1], linkbuf[PATH_MAX+1];
|
||||
char *result, *p, *q, *qsave, *qbase, *workpath;
|
||||
int double_slash_path, linklen, nlink;
|
||||
|
||||
linklen = strlen (path);
|
||||
|
||||
#if 0
|
||||
/* First sanity check -- punt immediately if the name is too long. */
|
||||
if (linklen >= PATH_MAX)
|
||||
return (savestring (path));
|
||||
#endif
|
||||
|
||||
nlink = 0;
|
||||
q = result = (char *)xmalloc (PATH_MAX + 1);
|
||||
|
||||
/* Even if we get something longer than PATH_MAX, we might be able to
|
||||
shorten it, so we try. */
|
||||
if (linklen >= PATH_MAX)
|
||||
workpath = savestring (path);
|
||||
else
|
||||
{
|
||||
workpath = (char *)xmalloc (PATH_MAX + 1);
|
||||
strcpy (workpath, path);
|
||||
}
|
||||
|
||||
/* This always gets an absolute pathname. */
|
||||
|
||||
/* POSIX.2 says to leave a leading `//' alone. On cygwin, we skip over any
|
||||
leading `x:' (dos drive name). */
|
||||
#if defined (__CYGWIN__)
|
||||
qbase = (ISALPHA((unsigned char)workpath[0]) && workpath[1] == ':') ? workpath + 3 : workpath + 1;
|
||||
#else
|
||||
qbase = workpath + 1;
|
||||
#endif
|
||||
double_slash_path = DOUBLE_SLASH (workpath);
|
||||
qbase += double_slash_path;
|
||||
|
||||
for (p = workpath; p < qbase; )
|
||||
*q++ = *p++;
|
||||
qbase = q;
|
||||
|
||||
/*
|
||||
* invariants:
|
||||
* qbase points to the portion of the result path we want to modify
|
||||
* p points at beginning of path element we're considering.
|
||||
* q points just past the last path element we wrote (no slash).
|
||||
*
|
||||
* XXX -- need to fix error checking for too-long pathnames
|
||||
*/
|
||||
|
||||
while (*p)
|
||||
{
|
||||
if (ISDIRSEP(p[0])) /* null element */
|
||||
p++;
|
||||
else if(p[0] == '.' && PATHSEP(p[1])) /* . and ./ */
|
||||
p += 1; /* don't count the separator in case it is nul */
|
||||
else if (p[0] == '.' && p[1] == '.' && PATHSEP(p[2])) /* .. and ../ */
|
||||
{
|
||||
p += 2; /* skip `..' */
|
||||
if (q > qbase)
|
||||
{
|
||||
while (--q > qbase && ISDIRSEP(*q) == 0)
|
||||
;
|
||||
}
|
||||
}
|
||||
else /* real path element */
|
||||
{
|
||||
/* add separator if not at start of work portion of result */
|
||||
qsave = q;
|
||||
if (q != qbase)
|
||||
*q++ = DIRSEP;
|
||||
while (*p && (ISDIRSEP(*p) == 0))
|
||||
{
|
||||
if (q - result >= PATH_MAX)
|
||||
{
|
||||
#ifdef ENAMETOOLONG
|
||||
errno = ENAMETOOLONG;
|
||||
#else
|
||||
errno = EINVAL;
|
||||
#endif
|
||||
goto error;
|
||||
}
|
||||
|
||||
*q++ = *p++;
|
||||
}
|
||||
|
||||
*q = '\0';
|
||||
|
||||
linklen = _path_readlink (result, linkbuf, PATH_MAX);
|
||||
if (linklen < 0) /* if errno == EINVAL, it's not a symlink */
|
||||
{
|
||||
if (errno != EINVAL)
|
||||
goto error;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* It's a symlink, and the value is in LINKBUF. */
|
||||
nlink++;
|
||||
if (nlink > MAXSYMLINKS)
|
||||
{
|
||||
#ifdef ELOOP
|
||||
errno = ELOOP;
|
||||
#else
|
||||
errno = EINVAL;
|
||||
#endif
|
||||
error:
|
||||
free (result);
|
||||
free (workpath);
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
linkbuf[linklen] = '\0';
|
||||
|
||||
/* If the new path length would overrun PATH_MAX, punt now. */
|
||||
if ((strlen (p) + linklen + 2) >= PATH_MAX)
|
||||
{
|
||||
#ifdef ENAMETOOLONG
|
||||
errno = ENAMETOOLONG;
|
||||
#else
|
||||
errno = EINVAL;
|
||||
#endif
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Form the new pathname by copying the link value to a temporary
|
||||
buffer and appending the rest of `workpath'. Reset p to point
|
||||
to the start of the rest of the path. If the link value is an
|
||||
absolute pathname, reset p, q, and qbase. If not, reset p
|
||||
and q. */
|
||||
strcpy (tbuf, linkbuf);
|
||||
tbuf[linklen] = '/';
|
||||
strcpy (tbuf + linklen, p);
|
||||
strcpy (workpath, tbuf);
|
||||
|
||||
if (ABSPATH(linkbuf))
|
||||
{
|
||||
q = result;
|
||||
/* Duplicating some code here... */
|
||||
#if defined (__CYGWIN__)
|
||||
qbase = (ISALPHA((unsigned char)workpath[0]) && workpath[1] == ':') ? workpath + 3 : workpath + 1;
|
||||
#else
|
||||
qbase = workpath + 1;
|
||||
#endif
|
||||
double_slash_path = DOUBLE_SLASH (workpath);
|
||||
qbase += double_slash_path;
|
||||
|
||||
for (p = workpath; p < qbase; )
|
||||
*q++ = *p++;
|
||||
qbase = q;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = workpath;
|
||||
q = qsave;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*q = '\0';
|
||||
free (workpath);
|
||||
|
||||
/* If the result starts with `//', but the original path does not, we
|
||||
can turn the // into /. Because of how we set `qbase', this should never
|
||||
be true, but it's a sanity check. */
|
||||
if (DOUBLE_SLASH(result) && double_slash_path == 0)
|
||||
{
|
||||
if (result[2] == '\0') /* short-circuit for bare `//' */
|
||||
result[1] = '\0';
|
||||
else
|
||||
strcpy (result, result + 1);
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
char *
|
||||
sh_realpath (pathname, resolved)
|
||||
const char *pathname;
|
||||
char *resolved;
|
||||
{
|
||||
char *tdir, *wd;
|
||||
|
||||
if (pathname == 0 || *pathname == '\0')
|
||||
{
|
||||
errno = (pathname == 0) ? EINVAL : ENOENT;
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
if (ABSPATH (pathname) == 0)
|
||||
{
|
||||
wd = get_working_directory ("sh_realpath");
|
||||
if (wd == 0)
|
||||
return ((char *)NULL);
|
||||
tdir = sh_makepath ((char *)pathname, wd, 0);
|
||||
free (wd);
|
||||
}
|
||||
else
|
||||
tdir = savestring (pathname);
|
||||
|
||||
wd = sh_physpath (tdir, 0);
|
||||
free (tdir);
|
||||
|
||||
if (resolved == 0)
|
||||
return (wd);
|
||||
|
||||
if (wd)
|
||||
{
|
||||
strncpy (resolved, wd, PATH_MAX - 1);
|
||||
resolved[PATH_MAX - 1] = '\0';
|
||||
free (wd);
|
||||
return resolved;
|
||||
}
|
||||
else
|
||||
{
|
||||
resolved[0] = '\0';
|
||||
return wd;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -30,7 +30,7 @@
|
||||
#include <bashtypes.h>
|
||||
#include <posixdir.h>
|
||||
#include <posixstat.h>
|
||||
#ifndef _MINIX
|
||||
#if defined (HAVE_SYS_PARAM_H)
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
|
||||
+212
@@ -0,0 +1,212 @@
|
||||
/* spell.c -- spelling correction for pathnames. */
|
||||
|
||||
/* Copyright (C) 2000 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>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <bashtypes.h>
|
||||
#include <posixdir.h>
|
||||
#include <posixstat.h>
|
||||
#ifndef _MINIX
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <bashansi.h>
|
||||
#include <maxpath.h>
|
||||
#include <stdc.h>
|
||||
|
||||
static int mindist __P((char *, char *, char *));
|
||||
static int spdist __P((char *, char *));
|
||||
|
||||
/*
|
||||
* `spname' and its helpers are inspired by the code in "The UNIX
|
||||
* Programming Environment", Kernighan & Pike, Prentice-Hall 1984,
|
||||
* pages 209 - 213.
|
||||
*/
|
||||
|
||||
/*
|
||||
* `spname' -- return a correctly spelled filename
|
||||
*
|
||||
* int spname(char * oldname, char * newname)
|
||||
* Returns: -1 if no reasonable match found
|
||||
* 0 if exact match found
|
||||
* 1 if corrected
|
||||
* Stores corrected name in `newname'.
|
||||
*/
|
||||
int
|
||||
spname(oldname, newname)
|
||||
char *oldname;
|
||||
char *newname;
|
||||
{
|
||||
char *op, *np, *p;
|
||||
char guess[PATH_MAX + 1], best[PATH_MAX + 1];
|
||||
|
||||
op = oldname;
|
||||
np = newname;
|
||||
for (;;)
|
||||
{
|
||||
while (*op == '/') /* Skip slashes */
|
||||
*np++ = *op++;
|
||||
*np = '\0';
|
||||
|
||||
if (*op == '\0') /* Exact or corrected */
|
||||
{
|
||||
/* `.' is rarely the right thing. */
|
||||
if (oldname[1] == '\0' && newname[1] == '\0' &&
|
||||
oldname[0] != '.' && newname[0] == '.')
|
||||
return -1;
|
||||
return strcmp(oldname, newname) != 0;
|
||||
}
|
||||
|
||||
/* Copy next component into guess */
|
||||
for (p = guess; *op != '/' && *op != '\0'; op++)
|
||||
if (p < guess + PATH_MAX)
|
||||
*p++ = *op;
|
||||
*p = '\0';
|
||||
|
||||
if (mindist(newname, guess, best) >= 3)
|
||||
return -1; /* Hopeless */
|
||||
|
||||
/*
|
||||
* Add to end of newname
|
||||
*/
|
||||
for (p = best; *np = *p++; np++)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Search directory for a guess
|
||||
*/
|
||||
static int
|
||||
mindist(dir, guess, best)
|
||||
char *dir;
|
||||
char *guess;
|
||||
char *best;
|
||||
{
|
||||
DIR *fd;
|
||||
struct dirent *dp;
|
||||
int dist, x;
|
||||
|
||||
dist = 3; /* Worst distance */
|
||||
if (*dir == '\0')
|
||||
dir = ".";
|
||||
|
||||
if ((fd = opendir(dir)) == NULL)
|
||||
return dist;
|
||||
|
||||
while ((dp = readdir(fd)) != NULL)
|
||||
{
|
||||
/*
|
||||
* Look for a better guess. If the new guess is as
|
||||
* good as the current one, we take it. This way,
|
||||
* any single character match will be a better match
|
||||
* than ".".
|
||||
*/
|
||||
x = spdist(dp->d_name, guess);
|
||||
if (x <= dist && x != 3)
|
||||
{
|
||||
strcpy(best, dp->d_name);
|
||||
dist = x;
|
||||
if (dist == 0) /* Exact match */
|
||||
break;
|
||||
}
|
||||
}
|
||||
(void)closedir(fd);
|
||||
|
||||
/* Don't return `.' */
|
||||
if (best[0] == '.' && best[1] == '\0')
|
||||
dist = 3;
|
||||
return dist;
|
||||
}
|
||||
|
||||
/*
|
||||
* `spdist' -- return the "distance" between two names.
|
||||
*
|
||||
* int spname(char * oldname, char * newname)
|
||||
* Returns: 0 if strings are identical
|
||||
* 1 if two characters are transposed
|
||||
* 2 if one character is wrong, added or deleted
|
||||
* 3 otherwise
|
||||
*/
|
||||
static int
|
||||
spdist(cur, new)
|
||||
char *cur, *new;
|
||||
{
|
||||
while (*cur == *new)
|
||||
{
|
||||
if (*cur == '\0')
|
||||
return 0; /* Exact match */
|
||||
cur++;
|
||||
new++;
|
||||
}
|
||||
|
||||
if (*cur)
|
||||
{
|
||||
if (*new)
|
||||
{
|
||||
if (cur[1] && new[1] && cur[0] == new[1] && cur[1] == new[0] && strcmp (cur + 2, new + 2) == 0)
|
||||
return 1; /* Transposition */
|
||||
|
||||
if (strcmp (cur + 1, new + 1) == 0)
|
||||
return 2; /* One character mismatch */
|
||||
}
|
||||
|
||||
if (strcmp(&cur[1], &new[0]) == 0)
|
||||
return 2; /* Extra character */
|
||||
}
|
||||
|
||||
if (*new && strcmp(cur, new + 1) == 0)
|
||||
return 2; /* Missing character */
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
char *
|
||||
dirspell (dirname)
|
||||
char *dirname;
|
||||
{
|
||||
int n;
|
||||
char *guess;
|
||||
|
||||
n = (strlen (dirname) * 3 + 1) / 2 + 1;
|
||||
guess = (char *)malloc (n);
|
||||
if (guess == 0)
|
||||
return 0;
|
||||
|
||||
switch (spname (dirname, guess))
|
||||
{
|
||||
case -1:
|
||||
default:
|
||||
free (guess);
|
||||
return (char *)NULL;
|
||||
case 0:
|
||||
case 1:
|
||||
return guess;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -23,7 +23,7 @@
|
||||
#if !defined (HAVE_STRERROR)
|
||||
|
||||
#include <bashtypes.h>
|
||||
#ifndef _MINIX
|
||||
#if defined (HAVE_SYS_PARAM_H)
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/* strerror.c - string corresponding to a particular value of errno. */
|
||||
|
||||
/* Copyright (C) 1995 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>
|
||||
|
||||
#if !defined (HAVE_STRERROR)
|
||||
|
||||
#include <bashtypes.h>
|
||||
#ifndef _MINIX
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <shell.h>
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif /* !errno */
|
||||
|
||||
/* Return a string corresponding to the error number E. From
|
||||
the ANSI C spec. */
|
||||
#if defined (strerror)
|
||||
# undef strerror
|
||||
#endif
|
||||
|
||||
static char *errbase = "Unknown system error ";
|
||||
|
||||
char *
|
||||
strerror (e)
|
||||
int e;
|
||||
{
|
||||
static char emsg[40];
|
||||
#if defined (HAVE_SYS_ERRLIST)
|
||||
extern int sys_nerr;
|
||||
extern char *sys_errlist[];
|
||||
|
||||
if (e > 0 && e < sys_nerr)
|
||||
return (sys_errlist[e]);
|
||||
else
|
||||
#endif /* HAVE_SYS_ERRLIST */
|
||||
{
|
||||
char *z;
|
||||
|
||||
z = itos (e);
|
||||
strcpy (emsg, errbase);
|
||||
strcat (emsg, z);
|
||||
free (z);
|
||||
return (&emsg[0]);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_STRERROR */
|
||||
Reference in New Issue
Block a user