commit bash-20070802 snapshot

This commit is contained in:
Chet Ramey
2011-12-07 09:11:08 -05:00
parent 7a131ef23d
commit 29f3080f70
50 changed files with 3390 additions and 9 deletions
+19 -1
View File
@@ -14790,7 +14790,7 @@ lib/sh/getcwd.c
builtins/common.c
- change sh_invalidnum to be a little smarter about octal and hex
numbers and change the message appropriately. Bug originally
reported on coreutils list by Jürgen Niinre<Jyrgen.Niinre@emt.ee>
reported on coreutils list by Jürgen Niinre <Jyrgen.Niinre@emt.ee>
7/26
----
@@ -14813,3 +14813,21 @@ trap.c
trapped and issue a warning if the shell was compiled with
debugging enabled. Fixes bug reported by Fergus Henderson
<fergus@google.com>
8/1
---
lib/readline/{util,histexpand}.c
- fixes for small memory leaks from Michael Snyder <msnyder@sonic.net>
8/18
----
Makefile.in
- add dependency on builtins/builtext.h to nojobs.o list. Fixes
`make -j 5' issue reported by Chris MacGregor <chris@bouncingdog.com>
examples/loadables/Makefile.in
- add @LDFLAGS@ to SHOBJ_LDFLAGS assignment -- experimental. Suggested
by Mike Frysinger <vapier@gentoo.org>
examples/loadables/{basename,cut,dirname,finfo,head,ln,logname,mkdir,pathchk,print,printenv,push,realpath,rmdir,sleep,tee,truefalse,tty,uname,unlink,whoami}.c
- fix up some includes. Fix from Mike Frysinger <vapier@gentoo.org>
+29 -1
View File
@@ -14790,7 +14790,7 @@ lib/sh/getcwd.c
builtins/common.c
- change sh_invalidnum to be a little smarter about octal and hex
numbers and change the message appropriately. Bug originally
reported on coreutils list by Jürgen Niinre<Jyrgen.Niinre@emt.ee>
reported on coreutils list by Jürgen Niinre <Jyrgen.Niinre@emt.ee>
7/26
----
@@ -14802,3 +14802,31 @@ test.c
parse.y
- better input validation: make sure a word looks like a conditional
unary operator (-X) before calling test_unop
7/28
----
trap.c
- in trap_handler, if it's called directly from the signal handler
(e.g., SIGINT sighandler, set by set_sigint_handler), but the
trap disposition has been reset to the default between the
assignment and receipt of the signal, check that the signal is
trapped and issue a warning if the shell was compiled with
debugging enabled. Fixes bug reported by Fergus Henderson
<fergus@google.com>
8/1
---
lib/readline/{util,histexpand}.c
- fixes for small memory leaks from Michael Snyder <msnyder@sonic.net>
8/18
----
Makefile.in
- add dependency on builtins/builtext.h to nojobs.o list. Fixes
`make -j 5' issue reported by Chris MacGregor <chris@bouncingdog.com>
examples/loadables/Makefile.in
- add @LDFLAGS@ to SHOBJ_LDFLAGS assignment -- experimental. Suggested
by Mike Frysinger <vapier@gentoo.org>
examples/loadables/{
+1
View File
@@ -1055,6 +1055,7 @@ jobs.o: ${BASHINCDIR}/posixtime.h
nojobs.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h bashjmp.h ${BASHINCDIR}/posixjmp.h
nojobs.o: command.h ${BASHINCDIR}/stdc.h general.h xmalloc.h jobs.h quit.h siglist.h externs.h
nojobs.o: sig.h error.h ${BASHINCDIR}/shtty.h input.h
nojobs.o: $(DEFDIR)/builtext.h
# shell features that may be compiled in
+1 -1
View File
@@ -39,7 +39,7 @@ libdir = @libdir@
infodir = @infodir@
includedir = @includedir@
datadir = @datadir@
localedir = $(datadir)/locale
localedir = @localedir@
mandir = @mandir@
manpfx = man
+1 -1
View File
@@ -70,7 +70,7 @@ CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) $(CFLAGS)
SHOBJ_CC = @SHOBJ_CC@
SHOBJ_CFLAGS = @SHOBJ_CFLAGS@
SHOBJ_LD = @SHOBJ_LD@
SHOBJ_LDFLAGS = @SHOBJ_LDFLAGS@
SHOBJ_LDFLAGS = @SHOBJ_LDFLAGS@ @LDFLAGS@
SHOBJ_XLDFLAGS = @SHOBJ_XLDFLAGS@
SHOBJ_LIBS = @SHOBJ_LIBS@
SHOBJ_STATUS = @SHOBJ_STATUS@
+2
View File
@@ -26,6 +26,8 @@ libdir = @libdir@
infodir = @infodir@
includedir = @includedir@
datarootdir = @datarootdir@
topdir = @top_srcdir@
BUILD_DIR = @BUILD_DIR@
srcdir = @srcdir@
+1
View File
@@ -11,6 +11,7 @@
#include <stdio.h>
#include "builtins.h"
#include "shell.h"
#include "common.h"
basename_builtin (list)
WORD_LIST *list;
+108
View File
@@ -0,0 +1,108 @@
/* basename - return nondirectory portion of pathname */
/* See Makefile for compilation details. */
#include "config.h"
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
#include "builtins.h"
#include "shell.h"
basename_builtin (list)
WORD_LIST *list;
{
int slen, sufflen, off;
char *string, *suffix, *fn;
if (list == 0)
{
builtin_usage ();
return (EX_USAGE);
}
if (no_options (list))
return (EX_USAGE);
string = list->word->word;
suffix = (char *)NULL;
if (list->next)
{
list = list->next;
suffix = list->word->word;
}
if (list->next)
{
builtin_usage ();
return (EX_USAGE);
}
slen = strlen (string);
/* Strip trailing slashes */
while (slen > 0 && string[slen - 1] == '/')
slen--;
/* (2) If string consists entirely of slash characters, string shall be
set to a single slash character. In this case, skip steps (3)
through (5). */
if (slen == 0)
{
fputs ("/\n", stdout);
return (EXECUTION_SUCCESS);
}
/* (3) If there are any trailing slash characters in string, they
shall be removed. */
string[slen] = '\0';
/* (4) If there are any slash characters remaining in string, the prefix
of string up to an including the last slash character in string
shall be removed. */
while (--slen >= 0)
if (string[slen] == '/')
break;
fn = string + slen + 1;
/* (5) If the suffix operand is present, is not identical to the
characters remaining in string, and is identical to a suffix
of the characters remaining in string, the suffix suffix
shall be removed from string. Otherwise, string shall not be
modified by this step. */
if (suffix)
{
sufflen = strlen (suffix);
slen = strlen (fn);
if (sufflen < slen)
{
off = slen - sufflen;
if (strcmp (fn + off, suffix) == 0)
fn[off] = '\0';
}
}
printf ("%s\n", fn);
return (EXECUTION_SUCCESS);
}
char *basename_doc[] = {
"The STRING is converted to a filename corresponding to the last",
"pathname component in STRING. If the suffix string SUFFIX is",
"supplied, it is removed.",
(char *)NULL
};
/* The standard structure describing a builtin command. bash keeps an array
of these structures. */
struct builtin basename_struct = {
"basename", /* builtin name */
basename_builtin, /* function implementing the builtin */
BUILTIN_ENABLED, /* initial flags for builtin */
basename_doc, /* array of long documentation strings. */
"basename string [suffix]", /* usage synopsis */
0 /* reserved for internal use */
};
+1
View File
@@ -63,6 +63,7 @@ static const char sccsid[] = "@(#)cut.c 8.3 (Berkeley) 5/4/95";
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
#include "common.h"
#if !defined (errno)
extern int errno;
+376
View File
@@ -0,0 +1,376 @@
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam S. Moskowitz of Menlo Consulting and Marciano Pitargue.
*
* 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.
*/
#ifndef lint
static const char copyright[] =
"@(#) Copyright (c) 1989, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
static const char sccsid[] = "@(#)cut.c 8.3 (Berkeley) 5/4/95";
#endif /* not lint */
#include <config.h>
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
#include "bashansi.h"
#ifdef HAVE_LIMITS_H
# include <limits.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
#if !defined (errno)
extern int errno;
#endif
#if !defined (_POSIX2_LINE_MAX)
# define _POSIX2_LINE_MAX 2048
#endif
static int cflag;
static char dchar;
static int dflag;
static int fflag;
static int sflag;
static int autostart, autostop, maxval;
static char positions[_POSIX2_LINE_MAX + 1];
static int c_cut __P((FILE *, char *));
static int f_cut __P((FILE *, char *));
static int get_list __P((char *));
static char *_cut_strsep __P((char **, const char *));
int
cut_builtin(list)
WORD_LIST *list;
{
FILE *fp;
int (*fcn) __P((FILE *, char *)) = NULL;
int ch;
fcn = NULL;
dchar = '\t'; /* default delimiter is \t */
/* Since we don't support multi-byte characters, the -c and -b
options are equivalent, and the -n option is meaningless. */
reset_internal_getopt ();
while ((ch = internal_getopt (list, "b:c:d:f:sn")) != -1)
switch(ch) {
case 'b':
case 'c':
fcn = c_cut;
if (get_list(list_optarg) < 0)
return (EXECUTION_FAILURE);
cflag = 1;
break;
case 'd':
dchar = *list_optarg;
dflag = 1;
break;
case 'f':
fcn = f_cut;
if (get_list(list_optarg) < 0)
return (EXECUTION_FAILURE);
fflag = 1;
break;
case 's':
sflag = 1;
break;
case 'n':
break;
case '?':
default:
builtin_usage();
return (EX_USAGE);
}
list = loptend;
if (fflag) {
if (cflag) {
builtin_usage();
return (EX_USAGE);
}
} else if (!cflag || dflag || sflag) {
builtin_usage();
return (EX_USAGE);
}
if (list) {
while (list) {
fp = fopen(list->word->word, "r");
if (fp == 0) {
builtin_error("%s", list->word->word);
return (EXECUTION_FAILURE);
}
ch = (*fcn)(fp, list->word->word);
(void)fclose(fp);
if (ch < 0)
return (EXECUTION_FAILURE);
list = list->next;
}
} else {
ch = (*fcn)(stdin, "stdin");
if (ch < 0)
return (EXECUTION_FAILURE);
}
return (EXECUTION_SUCCESS);
}
static int
get_list(list)
char *list;
{
int setautostart, start, stop;
char *pos;
char *p;
/*
* set a byte in the positions array to indicate if a field or
* column is to be selected; use +1, it's 1-based, not 0-based.
* This parser is less restrictive than the Draft 9 POSIX spec.
* POSIX doesn't allow lists that aren't in increasing order or
* overlapping lists. We also handle "-3-5" although there's no
* real reason too.
*/
for (; (p = _cut_strsep(&list, ", \t")) != NULL;) {
setautostart = start = stop = 0;
if (*p == '-') {
++p;
setautostart = 1;
}
if (isdigit((unsigned char)*p)) {
start = stop = strtol(p, &p, 10);
if (setautostart && start > autostart)
autostart = start;
}
if (*p == '-') {
if (isdigit((unsigned char)p[1]))
stop = strtol(p + 1, &p, 10);
if (*p == '-') {
++p;
if (!autostop || autostop > stop)
autostop = stop;
}
}
if (*p) {
builtin_error("[-cf] list: illegal list value");
return -1;
}
if (!stop || !start) {
builtin_error("[-cf] list: values may not include zero");
return -1;
}
if (stop > _POSIX2_LINE_MAX) {
builtin_error("[-cf] list: %d too large (max %d)",
stop, _POSIX2_LINE_MAX);
return -1;
}
if (maxval < stop)
maxval = stop;
for (pos = positions + start; start++ <= stop; *pos++ = 1);
}
/* overlapping ranges */
if (autostop && maxval > autostop)
maxval = autostop;
/* set autostart */
if (autostart)
memset(positions + 1, '1', autostart);
return 0;
}
/* ARGSUSED */
static int
c_cut(fp, fname)
FILE *fp;
char *fname;
{
int ch, col;
char *pos;
ch = 0;
for (;;) {
pos = positions + 1;
for (col = maxval; col; --col) {
if ((ch = getc(fp)) == EOF)
return;
if (ch == '\n')
break;
if (*pos++)
(void)putchar(ch);
}
if (ch != '\n') {
if (autostop)
while ((ch = getc(fp)) != EOF && ch != '\n')
(void)putchar(ch);
else
while ((ch = getc(fp)) != EOF && ch != '\n');
}
(void)putchar('\n');
}
return (0);
}
static int
f_cut(fp, fname)
FILE *fp;
char *fname;
{
int ch, field, isdelim;
char *pos, *p, sep;
int output;
char lbuf[_POSIX2_LINE_MAX + 1];
for (sep = dchar; fgets(lbuf, sizeof(lbuf), fp);) {
output = 0;
for (isdelim = 0, p = lbuf;; ++p) {
if (!(ch = *p)) {
builtin_error("%s: line too long.", fname);
return -1;
}
/* this should work if newline is delimiter */
if (ch == sep)
isdelim = 1;
if (ch == '\n') {
if (!isdelim && !sflag)
(void)printf("%s", lbuf);
break;
}
}
if (!isdelim)
continue;
pos = positions + 1;
for (field = maxval, p = lbuf; field; --field, ++pos) {
if (*pos) {
if (output++)
(void)putchar(sep);
while ((ch = *p++) != '\n' && ch != sep)
(void)putchar(ch);
} else {
while ((ch = *p++) != '\n' && ch != sep)
continue;
}
if (ch == '\n')
break;
}
if (ch != '\n') {
if (autostop) {
if (output)
(void)putchar(sep);
for (; (ch = *p) != '\n'; ++p)
(void)putchar(ch);
} else
for (; (ch = *p) != '\n'; ++p);
}
(void)putchar('\n');
}
return (0);
}
/*
* Get next token from string *stringp, where tokens are possibly-empty
* strings separated by characters from delim.
*
* Writes NULs into the string at *stringp to end tokens.
* delim need not remain constant from call to call.
* On return, *stringp points past the last NUL written (if there might
* be further tokens), or is NULL (if there are definitely no more tokens).
*
* If *stringp is NULL, strsep returns NULL.
*/
static char *
_cut_strsep(stringp, delim)
register char **stringp;
register const char *delim;
{
register char *s;
register const char *spanp;
register int c, sc;
char *tok;
if ((s = *stringp) == NULL)
return (NULL);
for (tok = s;;) {
c = *s++;
spanp = delim;
do {
if ((sc = *spanp++) == c) {
if (c == 0)
s = NULL;
else
s[-1] = 0;
*stringp = s;
return (tok);
}
} while (sc != 0);
}
/* NOTREACHED */
}
static char *cut_doc[] = {
"Select portions of each line (as specified by LIST) from each FILE",
"(by default, the standard input), and write them to the standard output.",
"Items specified by LIST are either column positions or fields delimited",
"by a special character. Column numbering starts at 1.",
(char *)0
};
struct builtin cut_struct = {
"cut",
cut_builtin,
BUILTIN_ENABLED,
cut_doc,
"cut -b list [-n] [file ...] OR cut -c list [file ...] OR cut -f list [-s] [-d delim] [file ...]",
0
};
+1
View File
@@ -11,6 +11,7 @@
#include <stdio.h>
#include "builtins.h"
#include "shell.h"
#include "common.h"
dirname_builtin (list)
WORD_LIST *list;
+95
View File
@@ -0,0 +1,95 @@
/* dirname - return directory portion of pathname */
/* See Makefile for compilation details. */
#include "config.h"
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
#include "builtins.h"
#include "shell.h"
dirname_builtin (list)
WORD_LIST *list;
{
int slen;
char *string;
if (list == 0 || list->next)
{
builtin_usage ();
return (EX_USAGE);
}
if (no_options (list))
return (EX_USAGE);
string = list->word->word;
slen = strlen (string);
/* Strip trailing slashes */
while (slen > 0 && string[slen - 1] == '/')
slen--;
/* (2) If string consists entirely of slash characters, string shall be
set to a single slash character. In this case, skip steps (3)
through (8). */
if (slen == 0)
{
fputs ("/\n", stdout);
return (EXECUTION_SUCCESS);
}
/* (3) If there are any trailing slash characters in string, they
shall be removed. */
string[slen] = '\0';
/* (4) If there are no slash characters remaining in string, string
shall be set to a single period character. In this case, skip
steps (5) through (8).
(5) If there are any trailing nonslash characters in string,
they shall be removed. */
while (--slen >= 0)
if (string[slen] == '/')
break;
if (slen < 0)
{
fputs (".\n", stdout);
return (EXECUTION_SUCCESS);
}
/* (7) If there are any trailing slash characters in string, they
shall be removed. */
while (--slen >= 0)
if (string[slen] != '/')
break;
string[++slen] = '\0';
/* (8) If the remaining string is empty, string shall be set to a single
slash character. */
printf ("%s\n", (slen == 0) ? "/" : string);
return (EXECUTION_SUCCESS);
}
char *dirname_doc[] = {
"The STRING is converted to the name of the directory containing",
"the filename corresponding to the last pathname component in STRING.",
(char *)NULL
};
/* The standard structure describing a builtin command. bash keeps an array
of these structures. */
struct builtin dirname_struct = {
"dirname", /* builtin name */
dirname_builtin, /* function implementing the builtin */
BUILTIN_ENABLED, /* initial flags for builtin */
dirname_doc, /* array of long documentation strings. */
"dirname string", /* usage synopsis */
0 /* reserved for internal use */
};
+1
View File
@@ -12,6 +12,7 @@
#include <pwd.h>
#include <grp.h>
#include <errno.h>
#include "posixtime.h"
#include "bashansi.h"
#include "shell.h"
+596
View File
@@ -0,0 +1,596 @@
/*
* finfo - print file info
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/types.h>
#include "posixstat.h"
#include <stdio.h>
#include <pwd.h>
#include <grp.h>
#include <errno.h>
#include "bashansi.h"
#include "shell.h"
#include "builtins.h"
#include "common.h"
#ifndef errno
extern int errno;
#endif
extern char **make_builtin_argv ();
static int printst();
static int printsome();
static int printfinfo();
static int finfo_main();
extern int sh_optind;
extern char *sh_optarg;
extern char *this_command_name;
static char *prog;
static int pmask;
#define OPT_UID 0x00001
#define OPT_GID 0x00002
#define OPT_DEV 0x00004
#define OPT_INO 0x00008
#define OPT_PERM 0x00010
#define OPT_LNKNAM 0x00020
#define OPT_FID 0x00040
#define OPT_NLINK 0x00080
#define OPT_RDEV 0x00100
#define OPT_SIZE 0x00200
#define OPT_ATIME 0x00400
#define OPT_MTIME 0x00800
#define OPT_CTIME 0x01000
#define OPT_BLKSIZE 0x02000
#define OPT_BLKS 0x04000
#define OPT_FTYPE 0x08000
#define OPT_PMASK 0x10000
#define OPT_OPERM 0x20000
#define OPT_ASCII 0x1000000
#define OPTIONS "acdgiflmnopsuACGMP:U"
static int
octal(s)
char *s;
{
int r;
r = *s - '0';
while (*++s >= '0' && *s <= '7')
r = (r * 8) + (*s - '0');
return r;
}
static int
finfo_main(argc, argv)
int argc;
char **argv;
{
register int i;
int mode, flags, opt;
sh_optind = 0; /* XXX */
prog = base_pathname(argv[0]);
if (argc == 1) {
builtin_usage();
return(1);
}
flags = 0;
while ((opt = sh_getopt(argc, argv, OPTIONS)) != EOF) {
switch(opt) {
case 'a': flags |= OPT_ATIME; break;
case 'A': flags |= OPT_ATIME|OPT_ASCII; break;
case 'c': flags |= OPT_CTIME; break;
case 'C': flags |= OPT_CTIME|OPT_ASCII; break;
case 'd': flags |= OPT_DEV; break;
case 'i': flags |= OPT_INO; break;
case 'f': flags |= OPT_FID; break;
case 'g': flags |= OPT_GID; break;
case 'G': flags |= OPT_GID|OPT_ASCII; break;
case 'l': flags |= OPT_LNKNAM; break;
case 'm': flags |= OPT_MTIME; break;
case 'M': flags |= OPT_MTIME|OPT_ASCII; break;
case 'n': flags |= OPT_NLINK; break;
case 'o': flags |= OPT_OPERM; break;
case 'p': flags |= OPT_PERM; break;
case 'P': flags |= OPT_PMASK; pmask = octal(sh_optarg); break;
case 's': flags |= OPT_SIZE; break;
case 'u': flags |= OPT_UID; break;
case 'U': flags |= OPT_UID|OPT_ASCII; break;
default: builtin_usage (); return(1);
}
}
argc -= sh_optind;
argv += sh_optind;
if (argc == 0) {
builtin_usage();
return(1);
}
for (i = 0; i < argc; i++)
opt = flags ? printsome (argv[i], flags) : printfinfo(argv[i]);
return(opt);
}
static struct stat *
getstat(f)
char *f;
{
static struct stat st;
int fd, r;
intmax_t lfd;
if (strncmp(f, "/dev/fd/", 8) == 0) {
if ((legal_number(f + 8, &lfd) == 0) || (int)lfd != lfd) {
builtin_error("%s: invalid fd", f + 8);
return ((struct stat *)0);
}
fd = lfd;
r = fstat(fd, &st);
} else
#ifdef HAVE_LSTAT
r = lstat(f, &st);
#else
r = stat(f, &st);
#endif
if (r < 0) {
builtin_error("%s: cannot stat: %s", f, strerror(errno));
return ((struct stat *)0);
}
return (&st);
}
static int
printfinfo(f)
char *f;
{
struct stat *st;
st = getstat(f);
return (st ? printst(st) : 1);
}
static int
getperm(m)
int m;
{
return (m & (S_IRWXU|S_IRWXG|S_IRWXO|S_ISUID|S_ISGID));
}
static int
perms(m)
int m;
{
char ubits[4], gbits[4], obits[4]; /* u=rwx,g=rwx,o=rwx */
int i;
i = 0;
if (m & S_IRUSR)
ubits[i++] = 'r';
if (m & S_IWUSR)
ubits[i++] = 'w';
if (m & S_IXUSR)
ubits[i++] = 'x';
ubits[i] = '\0';
i = 0;
if (m & S_IRGRP)
gbits[i++] = 'r';
if (m & S_IWGRP)
gbits[i++] = 'w';
if (m & S_IXGRP)
gbits[i++] = 'x';
gbits[i] = '\0';
i = 0;
if (m & S_IROTH)
obits[i++] = 'r';
if (m & S_IWOTH)
obits[i++] = 'w';
if (m & S_IXOTH)
obits[i++] = 'x';
obits[i] = '\0';
if (m & S_ISUID)
ubits[2] = (m & S_IXUSR) ? 's' : 'S';
if (m & S_ISGID)
gbits[2] = (m & S_IXGRP) ? 's' : 'S';
if (m & S_ISVTX)
obits[2] = (m & S_IXOTH) ? 't' : 'T';
printf ("u=%s,g=%s,o=%s", ubits, gbits, obits);
}
static int
printmode(mode)
int mode;
{
if (S_ISBLK(mode))
printf("S_IFBLK ");
if (S_ISCHR(mode))
printf("S_IFCHR ");
if (S_ISDIR(mode))
printf("S_IFDIR ");
if (S_ISREG(mode))
printf("S_IFREG ");
if (S_ISFIFO(mode))
printf("S_IFIFO ");
if (S_ISLNK(mode))
printf("S_IFLNK ");
if (S_ISSOCK(mode))
printf("S_IFSOCK ");
#ifdef S_ISWHT
if (S_ISWHT(mode))
printf("S_ISWHT ");
#endif
perms(getperm(mode));
printf("\n");
}
static int
printst(st)
struct stat *st;
{
struct passwd *pw;
struct group *gr;
char *owner;
int ma, mi, d;
ma = major (st->st_rdev);
mi = minor (st->st_rdev);
#if defined (makedev)
d = makedev (ma, mi);
#else
d = st->st_rdev & 0xFF;
#endif
printf("Device (major/minor): %d (%d/%d)\n", d, ma, mi);
printf("Inode: %d\n", (int) st->st_ino);
printf("Mode: (%o) ", (int) st->st_mode);
printmode((int) st->st_mode);
printf("Link count: %d\n", (int) st->st_nlink);
pw = getpwuid(st->st_uid);
owner = pw ? pw->pw_name : "unknown";
printf("Uid of owner: %d (%s)\n", (int) st->st_uid, owner);
gr = getgrgid(st->st_gid);
owner = gr ? gr->gr_name : "unknown";
printf("Gid of owner: %d (%s)\n", (int) st->st_gid, owner);
printf("Device type: %d\n", (int) st->st_rdev);
printf("File size: %ld\n", (long) st->st_size);
printf("File last access time: %s", ctime (&st->st_atime));
printf("File last modify time: %s", ctime (&st->st_mtime));
printf("File last status change time: %s", ctime (&st->st_ctime));
fflush(stdout);
return(0);
}
static int
printsome(f, flags)
char *f;
int flags;
{
struct stat *st;
struct passwd *pw;
struct group *gr;
int p;
char *b;
st = getstat(f);
if (st == NULL)
return (1);
/* Print requested info */
if (flags & OPT_ATIME) {
if (flags & OPT_ASCII)
printf("%s", ctime(&st->st_atime));
else
printf("%ld\n", st->st_atime);
} else if (flags & OPT_MTIME) {
if (flags & OPT_ASCII)
printf("%s", ctime(&st->st_mtime));
else
printf("%ld\n", st->st_mtime);
} else if (flags & OPT_CTIME) {
if (flags & OPT_ASCII)
printf("%s", ctime(&st->st_ctime));
else
printf("%ld\n", st->st_ctime);
} else if (flags & OPT_DEV)
printf("%d\n", st->st_dev);
else if (flags & OPT_INO)
printf("%d\n", st->st_ino);
else if (flags & OPT_FID)
printf("%d:%ld\n", st->st_dev, st->st_ino);
else if (flags & OPT_NLINK)
printf("%d\n", st->st_nlink);
else if (flags & OPT_LNKNAM) {
#ifdef S_ISLNK
b = xmalloc(4096);
p = readlink(f, b, 4096);
if (p >= 0 && p < 4096)
b[p] = '\0';
else {
p = errno;
strcpy(b, prog);
strcat(b, ": ");
strcat(b, strerror(p));
}
printf("%s\n", b);
free(b);
#else
printf("%s\n", f);
#endif
} else if (flags & OPT_PERM) {
perms(st->st_mode);
printf("\n");
} else if (flags & OPT_OPERM)
printf("%o\n", getperm(st->st_mode));
else if (flags & OPT_PMASK)
printf("%o\n", getperm(st->st_mode) & pmask);
else if (flags & OPT_UID) {
pw = getpwuid(st->st_uid);
if (flags & OPT_ASCII)
printf("%s\n", pw ? pw->pw_name : "unknown");
else
printf("%d\n", st->st_uid);
} else if (flags & OPT_GID) {
gr = getgrgid(st->st_gid);
if (flags & OPT_ASCII)
printf("%s\n", gr ? gr->gr_name : "unknown");
else
printf("%d\n", st->st_gid);
} else if (flags & OPT_SIZE)
printf("%ld\n", st->st_size);
return (0);
}
#ifndef NOBUILTIN
int
finfo_builtin(list)
WORD_LIST *list;
{
int c, r;
char **v;
WORD_LIST *l;
v = make_builtin_argv (list, &c);
r = finfo_main (c, v);
free (v);
return r;
}
static char *finfo_doc[] = {
"Display information about each FILE. Only single operators should",
"be supplied. If no options are supplied, a summary of the info",
"available about each FILE is printed. If FILE is of the form",
"/dev/fd/XX, file descriptor XX is described. Operators, if supplied,",
"have the following meanings:",
"",
" -a last file access time",
" -A last file access time in ctime format",
" -c last file status change time",
" -C last file status change time in ctime format",
" -m last file modification time",
" -M last file modification time in ctime format",
" -d device",
" -i inode",
" -f composite file identifier (device:inode)",
" -g gid of owner",
" -G group name of owner",
" -l name of file pointed to by symlink",
" -n link count",
" -o permissions in octal",
" -p permissions in ascii",
" -P mask permissions ANDed with MASK (like with umask)",
" -s file size in bytes",
" -u uid of owner",
" -U user name of owner",
(char *)0
};
struct builtin finfo_struct = {
"finfo",
finfo_builtin,
BUILTIN_ENABLED,
finfo_doc,
"finfo [-acdgiflmnopsuACGMPU] file [file...]",
0
};
#endif
#ifdef NOBUILTIN
#if defined (PREFER_STDARG)
# include <stdarg.h>
#else
# if defined (PREFER_VARARGS)
# include <varargs.h>
# endif
#endif
char *this_command_name;
main(argc, argv)
int argc;
char **argv;
{
this_command_name = argv[0];
exit(finfo_main(argc, argv));
}
void
builtin_usage()
{
fprintf(stderr, "%s: usage: %s [-%s] [file ...]\n", prog, OPTIONS);
}
#ifndef HAVE_STRERROR
char *
strerror(e)
int e;
{
static char ebuf[40];
extern int sys_nerr;
extern char *sys_errlist[];
if (e < 0 || e > sys_nerr) {
sprintf(ebuf,"Unknown error code %d", e);
return (&ebuf[0]);
}
return (sys_errlist[e]);
}
#endif
char *
xmalloc(s)
size_t s;
{
char *ret;
extern char *malloc();
ret = malloc(s);
if (ret)
return (ret);
fprintf(stderr, "%s: cannot malloc %d bytes\n", prog, s);
exit(1);
}
char *
base_pathname(p)
char *p;
{
char *t;
if (t = strrchr(p, '/'))
return(++t);
return(p);
}
int
legal_number (string, result)
char *string;
long *result;
{
int sign;
long value;
sign = 1;
value = 0;
if (result)
*result = 0;
/* Skip leading whitespace characters. */
while (whitespace (*string))
string++;
if (!*string)
return (0);
/* We allow leading `-' or `+'. */
if (*string == '-' || *string == '+')
{
if (!digit (string[1]))
return (0);
if (*string == '-')
sign = -1;
string++;
}
while (digit (*string))
{
if (result)
value = (value * 10) + digit_value (*string);
string++;
}
/* Skip trailing whitespace, if any. */
while (whitespace (*string))
string++;
/* Error if not at end of string. */
if (*string)
return (0);
if (result)
*result = value * sign;
return (1);
}
int sh_optind;
char *sh_optarg;
int sh_opterr;
extern int optind;
extern char *optarg;
int
sh_getopt(c, v, o)
int c;
char **v, *o;
{
int r;
r = getopt(c, v, o);
sh_optind = optind;
sh_optarg = optarg;
return r;
}
#if defined (USE_VARARGS)
void
#if defined (PREFER_STDARG)
builtin_error (const char *format, ...)
#else
builtin_error (format, va_alist)
const char *format;
va_dcl
#endif
{
va_list args;
if (this_command_name && *this_command_name)
fprintf (stderr, "%s: ", this_command_name);
#if defined (PREFER_STDARG)
va_start (args, format);
#else
va_start (args);
#endif
vfprintf (stderr, format, args);
va_end (args);
fprintf (stderr, "\n");
}
#else
void
builtin_error (format, arg1, arg2, arg3, arg4, arg5)
char *format, *arg1, *arg2, *arg3, *arg4, *arg5;
{
if (this_command_name && *this_command_name)
fprintf (stderr, "%s: ", this_command_name);
fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
fprintf (stderr, "\n");
fflush (stderr);
}
#endif /* !USE_VARARGS */
#endif
+1
View File
@@ -21,6 +21,7 @@
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
#include "common.h"
#if !defined (errno)
extern int errno;
+143
View File
@@ -0,0 +1,143 @@
/* head - copy first part of files. */
/* See Makefile for compilation details. */
#include "config.h"
#include "bashtypes.h"
#include "posixstat.h"
#include "filecntl.h"
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "bashansi.h"
#include <stdio.h>
#include <errno.h>
#include "chartypes.h"
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
#if !defined (errno)
extern int errno;
#endif
static void
munge_list (list)
WORD_LIST *list;
{
WORD_LIST *l, *nl;
WORD_DESC *wd;
char *arg;
for (l = list; l; l = l->next)
{
arg = l->word->word;
if (arg[0] != '-' || arg[1] == '-' || (DIGIT(arg[1]) == 0))
return;
/* We have -[0-9]* */
wd = make_bare_word (arg+1);
nl = make_word_list (wd, l->next);
l->word->word[1] = 'n';
l->word->word[2] = '\0';
l->next = nl;
l = nl; /* skip over new argument */
}
}
static int
file_head (fp, cnt)
FILE *fp;
int cnt;
{
int ch;
while (cnt--)
{
while ((ch = getc (fp)) != EOF)
{
if (putchar (ch) == EOF)
{
builtin_error ("write error: %s", strerror (errno));
return EXECUTION_FAILURE;
}
if (ch == '\n')
break;
}
}
}
head_builtin (list)
WORD_LIST *list;
{
int nline, opt, rval;
WORD_LIST *l;
FILE *fp;
char *t;
munge_list (list); /* change -num into -n num */
reset_internal_getopt ();
nline = 10;
while ((opt = internal_getopt (list, "n:")) != -1)
{
switch (opt)
{
case 'n':
nline = atoi (list_optarg);
if (nline <= 0)
{
builtin_error ("bad line count: %s", list_optarg);
return (EX_USAGE);
}
break;
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
if (list == 0)
return (file_head (stdin, nline));
for (rval = EXECUTION_SUCCESS, opt = 1, l = list; l; l = l->next)
{
fp = fopen (l->word->word, "r");
if (fp == NULL)
{
builtin_error ("%s: %s", l->word->word, strerror (errno));
continue;
}
if (list->next) /* more than one file */
{
printf ("%s==> %s <==\n", opt ? "" : "\n", l->word->word);
opt = 0;
}
rval = file_head (fp, nline);
fclose (fp);
}
return (rval);
}
char *head_doc[] = {
"Copy the first N lines from the input files to the standard output.",
"N is supplied as an argument to the `-n' option. If N is not given,",
"the first ten lines are copied.",
(char *)NULL
};
struct builtin head_struct = {
"head", /* builtin name */
head_builtin, /* function implementing the builtin */
BUILTIN_ENABLED, /* initial flags for builtin */
head_doc, /* array of long documentation strings. */
"head [-n num] [file ...]", /* usage synopsis; becomes short_doc */
0 /* reserved for internal use */
};
+1
View File
@@ -18,6 +18,7 @@
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
#include "common.h"
#if !defined (errno)
extern int errno;
+205
View File
@@ -0,0 +1,205 @@
/* ln - make links */
/* See Makefile for compilation details. */
#include "config.h"
#include "bashtypes.h"
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "posixstat.h"
#include <stdio.h>
#include <errno.h>
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
#if !defined (errno)
extern int errno;
#endif
typedef int unix_link_syscall_t __P((const char *, const char *));
#define LN_SYMLINK 0x01
#define LN_UNLINK 0x02
static unix_link_syscall_t *linkfn;
static int dolink ();
ln_builtin (list)
WORD_LIST *list;
{
int rval, opt, flags;
WORD_LIST *l;
char *sdir;
struct stat sb;
flags = 0;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "fs")) != -1)
{
switch (opt)
{
case 'f':
flags |= LN_UNLINK;
break;
case 's':
flags |= LN_SYMLINK;
break;
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
if (list == 0)
{
builtin_usage ();
return (EX_USAGE);
}
linkfn = (flags & LN_SYMLINK) ? symlink : link;
if (list->next == 0) /* ln target, equivalent to ln target . */
return (dolink (list->word->word, ".", flags));
if (list->next->next == 0) /* ln target source */
return (dolink (list->word->word, list->next->word->word, flags));
/* ln target1 target2 ... directory */
/* find last argument: target directory, and make sure it's an existing
directory. */
for (l = list; l->next; l = l->next)
;
sdir = l->word->word;
if (stat(sdir, &sb) < 0)
{
builtin_error ("%s", sdir);
return (EXECUTION_FAILURE);
}
if (S_ISDIR (sb.st_mode) == 0)
{
builtin_usage ();
return (EX_USAGE);
}
for (rval = EXECUTION_SUCCESS; list != l; list = list->next)
rval += dolink (list->word->word, sdir, flags);
return rval;
}
static char *
mkdirpath (dir, file)
char *dir, *file;
{
int dlen, flen;
char *ret;
dlen = strlen (dir);
flen = strlen (file);
ret = xmalloc (2 + dlen + flen);
strcpy (ret, dir);
if (ret[dlen - 1] != '/')
ret[dlen++] = '/';
strcpy (ret + dlen, file);
return ret;
}
#if defined (HAVE_LSTAT)
# define LSTAT lstat
#else
# define LSTAT stat
#endif
static int
dolink (src, dst, flags)
char *src, *dst;
int flags;
{
struct stat ssb, dsb;
int exists;
char *dst_path, *p;
/* If we're not doing symlinks, the source must exist and not be a
directory. */
if ((flags & LN_SYMLINK) == 0)
{
if (stat (src, &ssb) != 0)
{
builtin_error ("%s: %s", src, strerror (errno));
return (EXECUTION_FAILURE);
}
if (S_ISDIR (ssb.st_mode))
{
errno = EISDIR;
builtin_error ("%s: %s", src, strerror (errno));
return (EXECUTION_FAILURE);
}
}
/* If the destination is a directory, create the final filename by appending
the basename of the source to the destination. */
dst_path = 0;
if ((stat (dst, &dsb) == 0) && S_ISDIR (dsb.st_mode))
{
if ((p = strrchr (src, '/')) == 0)
p = src;
else
p++;
dst_path = mkdirpath (dst, p);
dst = dst_path;
}
exists = LSTAT (dst, &dsb) == 0;
/* If -f was specified, and the destination exists, unlink it. */
if ((flags & LN_UNLINK) && exists && unlink (dst) != 0)
{
builtin_error ("%s: cannot unlink: %s", dst, strerror (errno));
FREE (dst_path);
return (EXECUTION_FAILURE);
}
/* Perform the link. */
if ((*linkfn) (src, dst) != 0)
{
builtin_error ("cannot link %s to %s: %s", dst, src, strerror (errno));
FREE (dst_path);
return (EXECUTION_FAILURE);
}
FREE (dst_path);
return (EXECUTION_SUCCESS);
}
char *ln_doc[] = {
"Create a new directory entry with the same modes as the original",
"file. The -f option means to unlink any existing file, permitting",
"the link to occur. The -s option means to create a symbolic link.",
"By default, ln makes hard links.",
(char *)NULL
};
/* The standard structure describing a builtin command. bash keeps an array
of these structures. */
struct builtin ln_struct = {
"ln", /* builtin name */
ln_builtin, /* function implementing the builtin */
BUILTIN_ENABLED, /* initial flags for builtin */
ln_doc, /* array of long documentation strings. */
"ln [-fs] file1 [file2] OR ln [-fs] file ... directory", /* usage synopsis; becomes short_doc */
0 /* reserved for internal use */
};
+1
View File
@@ -11,6 +11,7 @@
#include "builtins.h"
#include "shell.h"
#include "common.h"
#if !defined (errno)
extern int errno;
+52
View File
@@ -0,0 +1,52 @@
/* logname - print login name of current user */
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
#include <errno.h>
#include "builtins.h"
#include "shell.h"
#if !defined (errno)
extern int errno;
#endif
logname_builtin (list)
WORD_LIST *list;
{
char *np;
if (no_options (list))
return (EX_USAGE);
np = getlogin ();
if (np == 0)
{
builtin_error ("cannot find username: %s", strerror (errno));
return (EXECUTION_FAILURE);
}
printf ("%s\n", np);
return (EXECUTION_SUCCESS);
}
char *logname_doc[] = {
"write the current user's login name to the standard output",
"and exit. logname ignores the LOGNAME and USER variables.",
"logname ignores any non-option arguments.",
(char *)NULL
};
struct builtin logname_struct = {
"logname",
logname_builtin,
BUILTIN_ENABLED,
logname_doc,
"logname",
0
};
+1
View File
@@ -16,6 +16,7 @@
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
#include "common.h"
#if !defined (errno)
extern int errno;
+216
View File
@@ -0,0 +1,216 @@
/* mkdir - make directories */
/* See Makefile for compilation details. */
#include <config.h>
#include "bashtypes.h"
#include "posixstat.h"
#include <errno.h>
#include <stdio.h>
#include "bashansi.h"
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
#if !defined (errno)
extern int errno;
#endif
#define ISOCTAL(c) ((c) >= '0' && (c) <= '7')
extern int parse_symbolic_mode ();
static int make_path ();
static int original_umask;
int
mkdir_builtin (list)
WORD_LIST *list;
{
int opt, pflag, omode, rval, octal, nmode, parent_mode, um;
char *mode;
WORD_LIST *l;
reset_internal_getopt ();
pflag = 0;
mode = (char *)NULL;
while ((opt = internal_getopt(list, "m:p")) != -1)
switch (opt)
{
case 'p':
pflag = 1;
break;
case 'm':
mode = list_optarg;
break;
default:
builtin_usage();
return (EX_USAGE);
}
list = loptend;
if (list == 0)
{
builtin_usage ();
return (EX_USAGE);
}
if (mode == NULL)
omode = S_IRWXU | S_IRWXG | S_IRWXO; /* a=rwx */
else if (ISOCTAL (*mode)) /* octal number */
{
omode = read_octal (mode);
if (omode < 0)
{
builtin_error ("invalid file mode: %s", mode);
return (EXECUTION_FAILURE);
}
octal = 1;
}
else if (mode)
{
/* initial bits are a=rwx; the mode argument modifies them */
omode = parse_symbolic_mode (mode, S_IRWXU | S_IRWXG | S_IRWXO);
if (omode < 0)
{
builtin_error ("invalid file mode: %s", mode);
return (EXECUTION_FAILURE);
}
octal = 0;
}
/* Make the new mode */
original_umask = umask (0);
umask (original_umask);
nmode = (S_IRWXU | S_IRWXG | S_IRWXO) & ~original_umask;
parent_mode = nmode | (S_IWRITE|S_IEXEC); /* u+wx */
/* Adjust new mode based on mode argument */
nmode &= omode;
for (rval = EXECUTION_SUCCESS, l = list; l; l = l->next)
{
if (pflag && make_path (l->word->word, nmode, parent_mode))
{
rval = EXECUTION_FAILURE;
continue;
}
else if (pflag == 0 && mkdir (l->word->word, nmode) < 0)
{
builtin_error ("cannot create directory `%s': %s", l->word->word, strerror (errno));
rval = EXECUTION_FAILURE;
}
}
return rval;
}
/* Make all the directories leading up to PATH, then create PATH. Note that
this changes the process's umask; make sure that all paths leading to a
return reset it to ORIGINAL_UMASK */
static int
make_path (path, nmode, parent_mode)
char *path;
int nmode, parent_mode;
{
int oumask;
struct stat sb;
char *p, *npath;
if (stat (path, &sb) == 0)
{
if (S_ISDIR (sb.st_mode) == 0)
{
builtin_error ("`%s': file exists but is not a directory", path);
return 1;
}
if (chmod (path, nmode))
{
builtin_error ("%s: %s", path, strerror (errno));
return 1;
}
return 0;
}
oumask = umask (0);
npath = savestring (path); /* So we can write to it. */
/* Check whether or not we need to do anything with intermediate dirs. */
/* Skip leading slashes. */
p = npath;
while (*p == '/')
p++;
while (p = strchr (p, '/'))
{
*p = '\0';
if (stat (npath, &sb) != 0)
{
if (mkdir (npath, parent_mode))
{
builtin_error ("cannot create directory `%s': %s", npath, strerror (errno));
umask (original_umask);
free (npath);
return 1;
}
}
else if (S_ISDIR (sb.st_mode) == 0)
{
builtin_error ("`%s': file exists but is not a directory", npath);
umask (original_umask);
free (npath);
return 1;
}
*p++ = '/'; /* restore slash */
while (*p == '/')
p++;
}
/* Create the final directory component. */
if (stat (npath, &sb) && mkdir (npath, nmode))
{
builtin_error ("cannot create directory `%s': %s", npath, strerror (errno));
umask (original_umask);
free (npath);
return 1;
}
umask (original_umask);
free (npath);
return 0;
}
char *mkdir_doc[] = {
"Make directories. Create the directories named as arguments, in",
"the order specified, using mode rwxrwxrwx as modified by the current",
"umask (see `help umask'). The -m option causes the file permission",
"bits of the final directory to be MODE. The MODE argument may be",
"an octal number or a symbolic mode like that used by chmod(1). If",
"a symbolic mode is used, the operations are interpreted relative to",
"an initial mode of \"a=rwx\". The -p option causes any required",
"intermediate directories in PATH to be created. The directories",
"are created with permssion bits of rwxrwxrwx as modified by the current",
"umask, plus write and search permissions for the owner. mkdir",
"returns 0 if the directories are created successfully, and non-zero",
"if an error occurs.",
(char *)NULL
};
struct builtin mkdir_struct = {
"mkdir",
mkdir_builtin,
BUILTIN_ENABLED,
mkdir_doc,
"mkdir [-p] [-m mode] directory [directory ...]",
0
};
+1
View File
@@ -45,6 +45,7 @@
#include "stdc.h"
#include "bashgetopt.h"
#include "maxpath.h"
#include "common.h"
#if !defined (errno)
extern int errno;
+358
View File
@@ -0,0 +1,358 @@
/* pathchk - check pathnames for validity and portability */
/* Usage: pathchk [-p] path ...
For each PATH, print a message if any of these conditions are false:
* all existing leading directories in PATH have search (execute) permission
* strlen (PATH) <= PATH_MAX
* strlen (each_directory_in_PATH) <= NAME_MAX
Exit status:
0 All PATH names passed all of the tests.
1 An error occurred.
Options:
-p Instead of performing length checks on the
underlying filesystem, test the length of the
pathname and its components against the POSIX.1
minimum limits for portability, _POSIX_NAME_MAX
and _POSIX_PATH_MAX in 2.9.2. Also check that
the pathname contains no character not in the
portable filename character set. */
/* See Makefile for compilation details. */
#include <config.h>
#include <sys/types.h>
#include "posixstat.h"
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#if defined (HAVE_LIMITS_H)
# include <limits.h>
#endif
#include "bashansi.h"
#include <stdio.h>
#include <errno.h>
#include "builtins.h"
#include "shell.h"
#include "stdc.h"
#include "bashgetopt.h"
#include "maxpath.h"
#if !defined (errno)
extern int errno;
#endif
#if !defined (_POSIX_PATH_MAX)
# define _POSIX_PATH_MAX 255
#endif
#if !defined (_POSIX_NAME_MAX)
# define _POSIX_NAME_MAX 14
#endif
/* How do we get PATH_MAX? */
#if defined (_POSIX_VERSION) && !defined (PATH_MAX)
# define PATH_MAX_FOR(p) pathconf ((p), _PC_PATH_MAX)
#endif
/* How do we get NAME_MAX? */
#if defined (_POSIX_VERSION) && !defined (NAME_MAX)
# define NAME_MAX_FOR(p) pathconf ((p), _PC_NAME_MAX)
#endif
#if !defined (PATH_MAX_FOR)
# define PATH_MAX_FOR(p) PATH_MAX
#endif
#if !defined (NAME_MAX_FOR)
# define NAME_MAX_FOR(p) NAME_MAX
#endif
extern char *strerror ();
static int validate_path ();
pathchk_builtin (list)
WORD_LIST *list;
{
int retval, pflag, opt;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "p")) != -1)
{
switch (opt)
{
case 'p':
pflag = 1;
break;
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
if (list == 0)
{
builtin_usage ();
return (EX_USAGE);
}
for (retval = 0; list; list = list->next)
retval |= validate_path (list->word->word, pflag);
return (retval ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
}
char *pathchk_doc[] = {
"Check each pathname argument for validity (i.e., it may be used to",
"create or access a file without casuing syntax errors) and portability",
"(i.e., no filename truncation will result). If the `-p' option is",
"supplied, more extensive portability checks are performed.",
(char *)NULL
};
/* The standard structure describing a builtin command. bash keeps an array
of these structures. */
struct builtin pathchk_struct = {
"pathchk", /* builtin name */
pathchk_builtin, /* function implementing the builtin */
BUILTIN_ENABLED, /* initial flags for builtin */
pathchk_doc, /* array of long documentation strings. */
"pathchk [-p] pathname ...", /* usage synopsis */
0 /* reserved for internal use */
};
/* The remainder of this file is stolen shamelessly from `pathchk.c' in
the sh-utils-1.12 distribution, by
David MacKenzie <djm@gnu.ai.mit.edu>
and Jim Meyering <meyering@cs.utexas.edu> */
/* Each element is nonzero if the corresponding ASCII character is
in the POSIX portable character set, and zero if it is not.
In addition, the entry for `/' is nonzero to simplify checking. */
static char const portable_chars[256] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0-15 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16-31 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, /* 32-47 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 48-63 */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 64-79 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 80-95 */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 96-111 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 112-127 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* If PATH contains only portable characters, return 1, else 0. */
static int
portable_chars_only (path)
const char *path;
{
const char *p;
for (p = path; *p; ++p)
if (portable_chars[(const unsigned char) *p] == 0)
{
builtin_error ("path `%s' contains nonportable character `%c'", path, *p);
return 0;
}
return 1;
}
/* On some systems, stat can return EINTR. */
#ifndef EINTR
# define SAFE_STAT(name, buf) stat (name, buf)
#else
# define SAFE_STAT(name, buf) safe_stat (name, buf)
static inline int
safe_stat (name, buf)
const char *name;
struct stat *buf;
{
int ret;
do
ret = stat (name, buf);
while (ret < 0 && errno == EINTR);
return ret;
}
#endif
/* Return 1 if PATH is a usable leading directory, 0 if not,
2 if it doesn't exist. */
static int
dir_ok (path)
const char *path;
{
struct stat stats;
if (SAFE_STAT (path, &stats))
return 2;
if (!S_ISDIR (stats.st_mode))
{
builtin_error ("`%s' is not a directory", path);
return 0;
}
/* Use access to test for search permission because
testing permission bits of st_mode can lose with new
access control mechanisms. Of course, access loses if you're
running setuid. */
if (access (path, X_OK) != 0)
{
if (errno == EACCES)
builtin_error ("directory `%s' is not searchable", path);
else
builtin_error ("%s: %s", path, strerror (errno));
return 0;
}
return 1;
}
static char *
xstrdup (s)
char *s;
{
return (savestring (s));
}
/* Make sure that
strlen (PATH) <= PATH_MAX
&& strlen (each-existing-directory-in-PATH) <= NAME_MAX
If PORTABILITY is nonzero, compare against _POSIX_PATH_MAX and
_POSIX_NAME_MAX instead, and make sure that PATH contains no
characters not in the POSIX portable filename character set, which
consists of A-Z, a-z, 0-9, ., _, -.
Make sure that all leading directories along PATH that exist have
`x' permission.
Return 0 if all of these tests are successful, 1 if any fail. */
static int
validate_path (path, portability)
char *path;
int portability;
{
int path_max;
int last_elem; /* Nonzero if checking last element of path. */
int exists; /* 2 if the path element exists. */
char *slash;
char *parent; /* Last existing leading directory so far. */
if (portability && !portable_chars_only (path))
return 1;
if (*path == '\0')
return 0;
#ifdef lint
/* Suppress `used before initialized' warning. */
exists = 0;
#endif
/* Figure out the parent of the first element in PATH. */
parent = xstrdup (*path == '/' ? "/" : ".");
slash = path;
last_elem = 0;
while (1)
{
int name_max;
int length; /* Length of partial path being checked. */
char *start; /* Start of path element being checked. */
/* Find the end of this element of the path.
Then chop off the rest of the path after this element. */
while (*slash == '/')
slash++;
start = slash;
slash = strchr (slash, '/');
if (slash != NULL)
*slash = '\0';
else
{
last_elem = 1;
slash = strchr (start, '\0');
}
if (!last_elem)
{
exists = dir_ok (path);
if (dir_ok == 0)
{
free (parent);
return 1;
}
}
length = slash - start;
/* Since we know that `parent' is a directory, it's ok to call
pathconf with it as the argument. (If `parent' isn't a directory
or doesn't exist, the behavior of pathconf is undefined.)
But if `parent' is a directory and is on a remote file system,
it's likely that pathconf can't give us a reasonable value
and will return -1. (NFS and tempfs are not POSIX . . .)
In that case, we have no choice but to assume the pessimal
POSIX minimums. */
name_max = portability ? _POSIX_NAME_MAX : NAME_MAX_FOR (parent);
if (name_max < 0)
name_max = _POSIX_NAME_MAX;
if (length > name_max)
{
builtin_error ("name `%s' has length %d; exceeds limit of %d",
start, length, name_max);
free (parent);
return 1;
}
if (last_elem)
break;
if (exists == 1)
{
free (parent);
parent = xstrdup (path);
}
*slash++ = '/';
}
/* `parent' is now the last existing leading directory in the whole path,
so it's ok to call pathconf with it as the argument. */
path_max = portability ? _POSIX_PATH_MAX : PATH_MAX_FOR (parent);
if (path_max < 0)
path_max = _POSIX_PATH_MAX;
free (parent);
if (strlen (path) > path_max)
{
builtin_error ("path `%s' has length %d; exceeds limit of %d",
path, strlen (path), path_max);
return 1;
}
return 0;
}
+2
View File
@@ -17,6 +17,8 @@
#include "builtins.h"
#include "stdc.h"
#include "bashgetopt.h"
#include "builtext.h"
#include "common.h"
#if !defined (errno)
extern int errno;
+169
View File
@@ -0,0 +1,169 @@
/*
* print -- loadable ksh-93 style print builtin
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "bashtypes.h"
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include "bashansi.h"
#include "shell.h"
#include "builtins.h"
#include "stdc.h"
#include "bashgetopt.h"
#if !defined (errno)
extern int errno;
#endif
int print_builtin ();
static int printargs ();
static FILE *ofp;
extern char *this_command_name;
static char *print_doc[] = {
"Output the arguments. The -f option means to use the argument as a",
"format string as would be supplied to printf(1). The rest of the",
"options are as in ksh.",
(char *)NULL
};
struct builtin print_struct = {
"print",
print_builtin,
BUILTIN_ENABLED,
print_doc,
"print [-Rnprs] [-u unit] [-f format] [arguments]",
(char *)0
};
#ifndef ISOPTION
#define ISOPTION(s, c) (s[0] == '-' && s[2] == '\0' && s[1] == c)
#endif
int
print_builtin (list)
WORD_LIST *list;
{
int c, r, nflag, raw, ofd, sflag;
intmax_t lfd;
char **v, *pfmt, *arg;
WORD_LIST *l;
nflag = raw = sflag = 0;
ofd = 1;
pfmt = 0;
reset_internal_getopt ();
while ((c = internal_getopt (list, "Rnprsu:f:")) != -1)
{
switch (c)
{
case 'R':
raw = 2;
loptend = lcurrent;
if (loptend && ISOPTION (loptend->word->word, 'n'))
{
loptend = loptend->next;
nflag = 1;
}
goto opt_end;
case 'r':
raw = 1;
break;
case 'n':
nflag = 1;
break;
case 's':
sflag = 1;
break;
case 'p':
break; /* NOP */
case 'u':
if (all_digits (list_optarg) && legal_number (list_optarg, &lfd) && lfd == (int)lfd)
ofd = lfd;
else
{
for (l = list; l->next && l->next != lcurrent; l = l->next);
lcurrent = loptend = l;
goto opt_end;
}
break;
case 'f':
pfmt = list_optarg;
break;
default:
builtin_usage ();
return (EX_USAGE);
}
}
opt_end:
list = loptend;
ofp = (ofd == 1) ? stdout : fdopen (dup (ofd), "w");
if (pfmt)
{
WORD_DESC *w;
WORD_LIST *nlist;
w = make_word (pfmt);
nlist = make_word_list (w, list);
r = printf_builtin (nlist);
nlist->next = (WORD_LIST *)NULL;
dispose_words (nlist);
return (r);
}
if (raw)
{
for (l = list; l; l = l->next)
{
fprintf (ofp, "%s", l->word->word);
if (l->next)
fprintf (ofp, " ");
}
if (nflag == 0)
fprintf (ofp, "\n");
fflush (ofp);
return (0);
}
r = printargs (list, ofp);
if (r && nflag == 0)
fprintf (ofp, "\n");
if (ofd != 1)
fclose (ofp);
return 0;
}
static int
printargs (list, ofp)
WORD_LIST *list;
FILE *ofp;
{
WORD_LIST *l;
char *ostr;
int sawc;
for (sawc = 0, l = list; l; l = l->next)
{
ostr = ansicstr (l->word->word, strlen (l->word->word), 0, &sawc, (int *)0);
fprintf (ofp, "%s", ostr);
free (ostr);
if (sawc)
return (0);
if (l->next)
fprintf (ofp, " ");
}
return (1);
}
+1
View File
@@ -11,6 +11,7 @@
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
#include "common.h"
extern char **export_env;
+71
View File
@@ -0,0 +1,71 @@
/*
* printenv -- minimal builtin clone of BSD printenv(1).
*
* usage: printenv [varname]
*
*/
#include <config.h>
#include <stdio.h>
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
extern char **export_env;
int
printenv_builtin (list)
WORD_LIST *list;
{
register char **envp;
int opt;
SHELL_VAR *var;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "")) != -1)
{
switch (opt)
{
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
/* printenv */
if (list == 0)
{
maybe_make_export_env (); /* this allows minimal code */
for (envp = export_env; *envp; envp++)
printf ("%s\n", *envp);
return (EXECUTION_SUCCESS);
}
/* printenv varname */
var = find_variable (list->word->word);
if (var == 0 || (exported_p (var) == 0))
return (EXECUTION_FAILURE);
if (function_p (var))
print_var_function (var);
else
print_var_value (var, 0);
return (EXECUTION_SUCCESS);
}
char *printenv_doc[] = {
"print values of environment variables",
(char *)NULL
};
struct builtin printenv_struct = {
"printenv",
printenv_builtin,
BUILTIN_ENABLED,
printenv_doc,
"printenv [varname]",
0
};
+1
View File
@@ -11,6 +11,7 @@
#include "shell.h"
#include "jobs.h"
#include "bashgetopt.h"
#include "common.h"
#ifndef errno
extern int errno;
+95
View File
@@ -0,0 +1,95 @@
/*
* push - anyone remember TOPS-20?
*
*/
#include <config.h>
#include <stdio.h>
#include <errno.h>
#include "builtins.h"
#include "shell.h"
#include "jobs.h"
#include "bashgetopt.h"
#ifndef errno
extern int errno;
#endif
extern int dollar_dollar_pid;
extern int last_command_exit_value;
int
push_builtin (list)
WORD_LIST *list;
{
pid_t pid;
int xstatus, opt;
xstatus = EXECUTION_SUCCESS;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "")) != -1)
{
switch (opt)
{
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
pid = make_child (savestring ("push"), 0);
if (pid == -1)
{
builtin_error ("cannot fork: %s", strerror (errno));
return (EXECUTION_FAILURE);
}
else if (pid == 0)
{
/* Shell variable adjustments: $SHLVL, $$, $PPID, $! */
adjust_shell_level (1);
dollar_dollar_pid = getpid ();
set_ppid ();
/* Clean up job control stuff. */
stop_making_children ();
cleanup_the_pipeline ();
delete_all_jobs (0);
last_asynchronous_pid = NO_PID;
/* Make sure the job control code has the right values for
the shell's process group and tty process group, and that
the signals are set correctly for job control. */
initialize_job_control (0);
initialize_job_signals ();
/* And read commands until exit. */
reader_loop ();
exit_shell (last_command_exit_value);
}
else
{
stop_pipeline (0, (COMMAND *)NULL);
xstatus = wait_for (pid);
return (xstatus);
}
}
char *push_doc[] = {
"Create a child that is an exact duplicate of the running shell",
"and wait for it to exit. The $SHLVL, $!, $$, and $PPID variables",
"are adjusted in the child. The return value is the exit status",
"of the child.",
(char *)NULL
};
struct builtin push_struct = {
"push",
push_builtin,
BUILTIN_ENABLED,
push_doc,
"push",
0
};
+3 -2
View File
@@ -34,6 +34,7 @@
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
#include "common.h"
#ifndef errno
extern int errno;
@@ -67,14 +68,14 @@ WORD_LIST *list;
vflag = 1;
break;
default:
usage();
builtin_usage();
}
}
list = loptend;
if (list == 0)
usage();
builtin_usage();
for (es = EXECUTION_SUCCESS; list; list = list->next) {
p = list->word->word;
+119
View File
@@ -0,0 +1,119 @@
/*
* realpath -- canonicalize pathnames, resolving symlinks
*
* usage: realpath [-csv] pathname [pathname...]
*
* options: -c check whether or not each resolved path exists
* -s no output, exit status determines whether path is valid
* -v produce verbose output
*
*
* exit status: 0 if all pathnames resolved
* 1 if any of the pathname arguments could not be resolved
*
*
* Bash loadable builtin version
*
* Chet Ramey
* chet@po.cwru.edu
*/
#include "config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include "bashansi.h"
#include <maxpath.h>
#include <errno.h>
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
#ifndef errno
extern int errno;
#endif
extern char *sh_realpath();
realpath_builtin(list)
WORD_LIST *list;
{
int opt, cflag, vflag, sflag, es;
char *r, realbuf[PATH_MAX], *p;
struct stat sb;
if (list == 0) {
builtin_usage();
return (EX_USAGE);
}
vflag = cflag = sflag = 0;
reset_internal_getopt();
while ((opt = internal_getopt (list, "csv")) != -1) {
switch (opt) {
case 'c':
cflag = 1;
break;
case 's':
sflag = 1;
break;
case 'v':
vflag = 1;
break;
default:
usage();
}
}
list = loptend;
if (list == 0)
usage();
for (es = EXECUTION_SUCCESS; list; list = list->next) {
p = list->word->word;
r = sh_realpath(p, realbuf);
if (r == 0) {
es = EXECUTION_FAILURE;
if (sflag == 0)
builtin_error("%s: cannot resolve: %s", p, strerror(errno));
continue;
}
if (cflag && (stat(realbuf, &sb) < 0)) {
es = EXECUTION_FAILURE;
if (sflag == 0)
builtin_error("%s: %s", p, strerror(errno));
continue;
}
if (sflag == 0) {
if (vflag)
printf ("%s -> ", p);
printf("%s\n", realbuf);
}
}
return es;
}
char *realpath_doc[] = {
"Display the canonicalized version of each PATHNAME argument, resolving",
"symbolic links. The -c option checks whether or not each resolved name",
"exists. The -s option produces no output; the exit status determines the",
"valididty of each PATHNAME. The -v option produces verbose output. The",
"exit status is 0 if each PATHNAME was resolved; non-zero otherwise.",
(char *)NULL
};
struct builtin realpath_struct = {
"realpath", /* builtin name */
realpath_builtin, /* function implementing the builtin */
BUILTIN_ENABLED, /* initial flags for builtin */
realpath_doc, /* array of long documentation strings */
"realpath [-csv] pathname [pathname...]", /* usage synopsis */
0 /* reserved for internal use */
};
+1
View File
@@ -8,6 +8,7 @@
#include <errno.h>
#include "builtins.h"
#include "shell.h"
#include "common.h"
#if !defined (errno)
extern int errno;
+50
View File
@@ -0,0 +1,50 @@
/* rmdir - remove directory */
/* See Makefile for compilation details. */
#include "config.h"
#include <stdio.h>
#include <errno.h>
#include "builtins.h"
#include "shell.h"
#if !defined (errno)
extern int errno;
#endif
rmdir_builtin (list)
WORD_LIST *list;
{
int rval;
WORD_LIST *l;
if (no_options (list))
return (EX_USAGE);
for (rval = EXECUTION_SUCCESS, l = list; l; l = l->next)
if (rmdir (l->word->word) < 0)
{
builtin_error ("%s: %s", l->word->word, strerror (errno));
rval = EXECUTION_FAILURE;
}
return rval;
}
char *rmdir_doc[] = {
"rmdir removes the directory entry specified by each argument,",
"provided the directory is empty.",
(char *)NULL
};
/* The standard structure describing a builtin command. bash keeps an array
of these structures. */
struct builtin rmdir_struct = {
"rmdir", /* builtin name */
rmdir_builtin, /* function implementing the builtin */
BUILTIN_ENABLED, /* initial flags for builtin */
rmdir_doc, /* array of long documentation strings. */
"rmdir directory ...", /* usage synopsis; becomes short_doc */
0 /* reserved for internal use */
};
+1
View File
@@ -27,6 +27,7 @@
#include "shell.h"
#include "builtins.h"
#include "common.h"
#define RETURN(x) \
do { \
+146
View File
@@ -0,0 +1,146 @@
/*
* sleep -- sleep for fractions of a second
*
* usage: sleep seconds[.fraction]
*/
#include "config.h"
#include "bashtypes.h"
#if defined (TIME_WITH_SYS_TIME)
# include <sys/time.h>
# include <time.h>
#else
# if defined (HAVE_SYS_TIME_H)
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#if defined (HAVE_UNISTD_H)
#include <unistd.h>
#endif
#include <stdio.h>
#include "chartypes.h"
#include "shell.h"
#include "builtins.h"
#define RETURN(x) \
do { \
if (sp) *sp = sec; \
if (usp) *usp = usec; \
return (x); \
} while (0)
#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
static int
fsleep(sec, usec)
long sec, usec;
{
struct timeval tv;
tv.tv_sec = sec;
tv.tv_usec = usec;
return select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv);
}
#else /* !HAVE_TIMEVAL || !HAVE_SELECT */
static int
fsleep(sec, usec)
long sec, usec;
{
if (usec >= 500000) /* round */
sec++;
return (sleep(sec));
}
#endif /* !HAVE_TIMEVAL || !HAVE_SELECT */
/*
* An incredibly simplistic floating point converter.
*/
static int multiplier[7] = { 1, 100000, 10000, 1000, 100, 10, 1 };
static int
convert(s, sp, usp)
char *s;
long *sp, *usp;
{
int n;
long sec, usec;
char *p;
sec = usec = 0;
#define DECIMAL '.'
for (p = s; p && *p; p++) {
if (*p == DECIMAL) /* decimal point */
break;
if (DIGIT(*p) == 0)
RETURN(0);
sec = (sec * 10) + (*p - '0');
}
if (*p == 0)
RETURN(1);
if (*p == DECIMAL)
p++;
/* Look for up to six digits past a decimal point. */
for (n = 0; n < 6 && p[n]; n++) {
if (DIGIT(p[n]) == 0)
RETURN(0);
usec = (usec * 10) + (p[n] - '0');
}
/* Now convert to millionths */
usec *= multiplier[n];
if (n == 6 && p[6] >= '5' && p[6] <= '9')
usec++; /* round up 1 */
RETURN(1);
}
int
sleep_builtin (list)
WORD_LIST *list;
{
long sec, usec;
if (list == 0) {
builtin_usage();
return(EX_USAGE);
}
if (*list->word->word == '-' || list->next) {
builtin_usage ();
return (EX_USAGE);
}
if (convert(list->word->word, &sec, &usec)) {
fsleep(sec, usec);
return(EXECUTION_SUCCESS);
}
builtin_error("%s: bad sleep interval", list->word->word);
return (EXECUTION_FAILURE);
}
static char *sleep_doc[] = {
"sleep suspends execution for a minimum of SECONDS[.FRACTION] seconds.",
(char *)NULL
};
struct builtin sleep_struct = {
"sleep",
sleep_builtin,
BUILTIN_ENABLED,
sleep_doc,
"sleep seconds[.fraction]",
0
};
+1
View File
@@ -22,6 +22,7 @@
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
#include "common.h"
#if !defined (errno)
extern int errno;
+157
View File
@@ -0,0 +1,157 @@
/* tee - duplicate standard input */
/* See Makefile for compilation details. */
#include "config.h"
#include "bashtypes.h"
#include "posixstat.h"
#include "filecntl.h"
#include <signal.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "bashansi.h"
#include <stdio.h>
#include <errno.h>
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
#if !defined (errno)
extern int errno;
#endif
typedef struct flist {
struct flist *next;
int fd;
char *fname;
} FLIST;
static FLIST *tee_flist;
#define TEE_BUFSIZE 8192
extern int interrupt_immediately;
extern char *strerror ();
tee_builtin (list)
WORD_LIST *list;
{
int opt, append, nointr, rval, fd, fflags;
int n, nr, nw;
FLIST *fl;
char *buf, *bp;
char *t;
reset_internal_getopt ();
append = nointr = 0;
tee_flist = (FLIST *)NULL;
while ((opt = internal_getopt (list, "ai")) != -1)
{
switch (opt)
{
case 'a':
append = 1;
break;
case 'i':
nointr = 1;
break;
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
if (nointr == 0)
interrupt_immediately++;
buf = xmalloc (TEE_BUFSIZE);
/* Initialize output file list. */
fl = tee_flist = (FLIST *)xmalloc (sizeof(FLIST));
tee_flist->fd = 1;
tee_flist->fname = "stdout";
tee_flist->next = (FLIST *)NULL;
/* Add file arguments to list of output files. */
fflags = append ? O_WRONLY|O_CREAT|O_APPEND : O_WRONLY|O_CREAT|O_TRUNC;
for (rval = EXECUTION_SUCCESS; list; list = list->next)
{
fd = open (list->word->word, fflags, 0666);
if (fd < 0)
{
builtin_error ("%s: cannot open: %s", list->word->word, strerror (errno));
rval = EXECUTION_FAILURE;
}
else
{
fl->next = (FLIST *)xmalloc (sizeof(FLIST));
fl->next->fd = fd;
fl->next->fname = list->word->word;
fl = fl->next;
fl->next = (FLIST *)NULL;
}
}
while ((nr = read(0, buf, TEE_BUFSIZE)) > 0)
for (fl = tee_flist; fl; fl = fl->next)
{
n = nr;
bp = buf;
do
{
if ((nw = write (fl->fd, bp, n)) == -1)
{
builtin_error ("%s: write error: %s", fl->fname, strerror (errno));
rval = EXECUTION_FAILURE;
break;
}
bp += nw;
}
while (n -= nw);
}
if (nr < 0)
builtin_error ("read error: %s", strerror (errno));
/* Deallocate resources -- this is a builtin command. */
tee_flist = tee_flist->next; /* skip bogus close of stdout */
while (tee_flist)
{
fl = tee_flist;
if (close (fl->fd) < 0)
{
builtin_error ("%s: close_error: %s", fl->fname, strerror (errno));
rval = EXECUTION_FAILURE;
}
tee_flist = tee_flist->next;
free (fl);
}
return (rval);
}
char *tee_doc[] = {
"Copy standard input to standard output, making a copy in each",
"filename argument. If the `-a' option is gived, the specified",
"files are appended to, otherwise they are overwritten. If the",
"`-i' option is supplied, tee ignores interrupts.",
(char *)NULL
};
struct builtin tee_struct = {
"tee", /* builtin name */
tee_builtin, /* function implementing the builtin */
BUILTIN_ENABLED, /* initial flags for builtin */
tee_doc, /* array of long documentation strings. */
"tee [-ai] [file ...]", /* usage synopsis; becomes short_doc */
0 /* reserved for internal use */
};
+1
View File
@@ -4,6 +4,7 @@
#include "bashtypes.h"
#include "shell.h"
#include "builtins.h"
#include "common.h"
true_builtin (list)
WORD_LIST *list;
+46
View File
@@ -0,0 +1,46 @@
/* true and false builtins */
#include <config.h>
#include "bashtypes.h"
#include "shell.h"
#include "builtins.h"
true_builtin (list)
WORD_LIST *list;
{
return EXECUTION_SUCCESS;
}
false_builtin (list)
WORD_LIST *list;
{
return EXECUTION_FAILURE;
}
static char *true_doc[] = {
"Return a successful result.",
(char *)NULL
};
static char *false_doc[] = {
"Return an unsuccessful result.",
(char *)NULL
};
struct builtin true_struct = {
"true",
true_builtin,
BUILTIN_ENABLED,
true_doc,
"true",
0
};
struct builtin false_struct = {
"false",
false_builtin,
BUILTIN_ENABLED,
false_doc,
"false",
0
};
+1
View File
@@ -8,6 +8,7 @@
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
#include "common.h"
extern char *ttyname ();
+59
View File
@@ -0,0 +1,59 @@
/* tty - return terminal name */
/* See Makefile for compilation details. */
#include "config.h"
#include <stdio.h>
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
extern char *ttyname ();
tty_builtin (list)
WORD_LIST *list;
{
int opt, sflag;
char *t;
reset_internal_getopt ();
sflag = 0;
while ((opt = internal_getopt (list, "s")) != -1)
{
switch (opt)
{
case 's':
sflag = 1;
break;
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
t = ttyname (0);
if (sflag == 0)
puts (t ? t : "not a tty");
return (t ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
}
char *tty_doc[] = {
"tty writes the name of the terminal that is opened for standard",
"input to standard output. If the `-s' option is supplied, nothing",
"is written; the exit status determines whether or not the standard",
"input is connected to a tty.",
(char *)NULL
};
/* The standard structure describing a builtin command. bash keeps an array
of these structures. */
struct builtin tty_struct = {
"tty", /* builtin name */
tty_builtin, /* function implementing the builtin */
BUILTIN_ENABLED, /* initial flags for builtin */
tty_doc, /* array of long documentation strings. */
"tty [-s]", /* usage synopsis; becomes short_doc */
0 /* reserved for internal use */
};
+1
View File
@@ -27,6 +27,7 @@ struct utsname {
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
#include "common.h"
#define FLAG_SYSNAME 0x01 /* -s */
#define FLAG_NODENAME 0x02 /* -n */
+139
View File
@@ -0,0 +1,139 @@
/*
* uname - print system information
*
* usage: uname [-amnrsv]
*
*/
#include <config.h>
#include <stdio.h>
#include "bashtypes.h"
#if defined (HAVE_UNAME)
# include <sys/utsname.h>
#else
struct utsname {
char sysname[32];
char nodename[32];
char release[32];
char version[32];
char machine[32];
};
#endif
#include <errno.h>
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
#define FLAG_SYSNAME 0x01 /* -s */
#define FLAG_NODENAME 0x02 /* -n */
#define FLAG_RELEASE 0x04 /* -r */
#define FLAG_VERSION 0x08 /* -v */
#define FLAG_MACHINE 0x10 /* -m, -p */
#define FLAG_ALL 0x1f
#ifndef errno
extern int errno;
#endif
static void uprint();
static int uname_flags;
uname_builtin (list)
WORD_LIST *list;
{
int opt, r;
struct utsname uninfo;
uname_flags = 0;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "amnprsv")) != -1)
{
switch (opt)
{
case 'a':
uname_flags |= FLAG_ALL;
break;
case 'm':
case 'p':
uname_flags |= FLAG_MACHINE;
break;
case 'n':
uname_flags |= FLAG_NODENAME;
break;
case 'r':
uname_flags |= FLAG_RELEASE;
break;
case 's':
uname_flags |= FLAG_SYSNAME;
break;
case 'v':
uname_flags |= FLAG_VERSION;
break;
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
if (list)
{
builtin_usage ();
return (EX_USAGE);
}
if (uname_flags == 0)
uname_flags = FLAG_SYSNAME;
/* Only ancient systems will not have uname(2). */
#ifdef HAVE_UNAME
if (uname (&uninfo) < 0)
{
builtin_error ("cannot get system name: %s", strerror (errno));
return (EXECUTION_FAILURE);
}
#else
builtin_error ("cannot get system information: uname(2) not available");
return (EXECUTION_FAILURE);
#endif
uprint (FLAG_SYSNAME, uninfo.sysname);
uprint (FLAG_NODENAME, uninfo.nodename);
uprint (FLAG_RELEASE, uninfo.release);
uprint (FLAG_VERSION, uninfo.version);
uprint (FLAG_MACHINE, uninfo.machine);
return (EXECUTION_SUCCESS);
}
static void
uprint (flag, info)
int flag;
char *info;
{
if (uname_flags & flag)
{
uname_flags &= ~flag;
printf ("%s%c", info, uname_flags ? ' ' : '\n');
}
}
char *uname_doc[] = {
"display information about the system",
(char *)NULL
};
struct builtin uname_struct = {
"uname",
uname_builtin,
BUILTIN_ENABLED,
uname_doc,
"uname [-amnrsv]",
0
};
+1
View File
@@ -14,6 +14,7 @@
#include "builtins.h"
#include "shell.h"
#include "common.h"
#ifndef errno
extern int errno;
+52
View File
@@ -0,0 +1,52 @@
/* unlink - remove a directory entry */
/* Should only be used to remove directories by a superuser prepared to let
fsck clean up the file system. */
#include <config.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <stdio.h>
#include <errno.h>
#include "builtins.h"
#include "shell.h"
#ifndef errno
extern int errno;
#endif
unlink_builtin (list)
WORD_LIST *list;
{
if (list == 0)
{
builtin_usage ();
return (EX_USAGE);
}
if (unlink (list->word->word) != 0)
{
builtin_error ("%s: cannot unlink: %s", list->word->word, strerror (errno));
return (EXECUTION_FAILURE);
}
return (EXECUTION_SUCCESS);
}
char *unlink_doc[] = {
"Remove a directory entry.",
(char *)NULL
};
struct builtin unlink_struct = {
"unlink", /* builtin name */
unlink_builtin, /* function implementing the builtin */
BUILTIN_ENABLED, /* initial flags for builtin */
unlink_doc, /* array of long documentation strings. */
"unlink name", /* usage synopsis; becomes short_doc */
0 /* reserved for internal use */
};
+1
View File
@@ -8,6 +8,7 @@
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
#include "common.h"
whoami_builtin (list)
WORD_LIST *list;
+52
View File
@@ -0,0 +1,52 @@
/*
* whoami - print out username of current user
*/
#include <config.h>
#include <stdio.h>
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
whoami_builtin (list)
WORD_LIST *list;
{
int opt;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "")) != -1)
{
switch (opt)
{
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
if (list)
{
builtin_usage ();
return (EX_USAGE);
}
if (current_user.user_name == 0)
get_current_user_info ();
printf ("%s\n", current_user.user_name);
return (EXECUTION_SUCCESS);
}
char *whoami_doc[] = {
"display name of current user",
(char *)NULL
};
struct builtin whoami_struct = {
"whoami",
whoami_builtin,
BUILTIN_ENABLED,
whoami_doc,
"whoami",
0
};
+6 -2
View File
@@ -1,6 +1,6 @@
/* histexpand.c -- history expansion. */
/* Copyright (C) 1989-2004 Free Software Foundation, Inc.
/* Copyright (C) 1989-2007 Free Software Foundation, Inc.
This file contains the GNU History Library (the Library), a set of
routines for managing the text of previously typed lines.
@@ -66,6 +66,7 @@ static int subst_rhs_len;
static char *get_history_word_specifier PARAMS((char *, char *, int *));
static char *history_find_word PARAMS((char *, int));
static int history_tokenize_word PARAMS((const char *, int));
static char **history_tokenize_internal PARAMS((const char *, int, int *));
static char *history_substring PARAMS((const char *, int, int));
static char *quote_breaks PARAMS((char *));
@@ -1582,7 +1583,10 @@ history_find_word (line, ind)
words = history_tokenize_internal (line, ind, &wind);
if (wind == -1 || words == 0)
return ((char *)NULL);
{
FREE (words);
return ((char *)NULL);
}
s = words[wind];
for (i = 0; i < wind; i++)
free (words[i]);
+3 -1
View File
@@ -1,6 +1,6 @@
/* util.c -- readline utility functions */
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
This file is part of the GNU Readline Library, a library for
reading lines of text with interactive input and history editing.
@@ -185,6 +185,7 @@ rl_tilde_expand (ignore, key)
{
homedir = tilde_expand ("~");
_rl_replace_text (homedir, start, end);
xfree (homedir);
return (0);
}
else if (rl_line_buffer[start] != '~')
@@ -215,6 +216,7 @@ rl_tilde_expand (ignore, key)
xfree (temp);
_rl_replace_text (homedir, start, end);
xfree (homedir);
}
return (0);