mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-28 07:59:50 +02:00
commit bash-20070802 snapshot
This commit is contained in:
+19
-1
@@ -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
@@ -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/{
|
||||
|
||||
@@ -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
@@ -39,7 +39,7 @@ libdir = @libdir@
|
||||
infodir = @infodir@
|
||||
includedir = @includedir@
|
||||
datadir = @datadir@
|
||||
localedir = $(datadir)/locale
|
||||
localedir = @localedir@
|
||||
|
||||
mandir = @mandir@
|
||||
manpfx = man
|
||||
|
||||
@@ -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@
|
||||
|
||||
@@ -26,6 +26,8 @@ libdir = @libdir@
|
||||
infodir = @infodir@
|
||||
includedir = @includedir@
|
||||
|
||||
datarootdir = @datarootdir@
|
||||
|
||||
topdir = @top_srcdir@
|
||||
BUILD_DIR = @BUILD_DIR@
|
||||
srcdir = @srcdir@
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <stdio.h>
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
#include "common.h"
|
||||
|
||||
basename_builtin (list)
|
||||
WORD_LIST *list;
|
||||
|
||||
@@ -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 */
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
};
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <stdio.h>
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
#include "common.h"
|
||||
|
||||
dirname_builtin (list)
|
||||
WORD_LIST *list;
|
||||
|
||||
@@ -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 */
|
||||
};
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <errno.h>
|
||||
#include "posixtime.h"
|
||||
|
||||
#include "bashansi.h"
|
||||
#include "shell.h"
|
||||
|
||||
@@ -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
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
#include "bashgetopt.h"
|
||||
#include "common.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
|
||||
@@ -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 */
|
||||
};
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
#include "bashgetopt.h"
|
||||
#include "common.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
|
||||
@@ -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 */
|
||||
};
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
#include "common.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
#include "bashgetopt.h"
|
||||
#include "common.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
|
||||
@@ -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
|
||||
};
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "stdc.h"
|
||||
#include "bashgetopt.h"
|
||||
#include "maxpath.h"
|
||||
#include "common.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
#include "bashgetopt.h"
|
||||
#include "common.h"
|
||||
|
||||
extern char **export_env;
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "shell.h"
|
||||
#include "jobs.h"
|
||||
#include "bashgetopt.h"
|
||||
#include "common.h"
|
||||
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
|
||||
@@ -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
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
};
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <errno.h>
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
#include "common.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
|
||||
@@ -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 */
|
||||
};
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
#include "common.h"
|
||||
|
||||
#define RETURN(x) \
|
||||
do { \
|
||||
|
||||
@@ -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
|
||||
};
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
#include "bashgetopt.h"
|
||||
#include "common.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
|
||||
@@ -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 */
|
||||
};
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "bashtypes.h"
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
#include "common.h"
|
||||
|
||||
true_builtin (list)
|
||||
WORD_LIST *list;
|
||||
|
||||
@@ -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
|
||||
};
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
#include "bashgetopt.h"
|
||||
#include "common.h"
|
||||
|
||||
extern char *ttyname ();
|
||||
|
||||
|
||||
@@ -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 */
|
||||
};
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
};
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
#include "common.h"
|
||||
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
|
||||
@@ -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 */
|
||||
};
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
#include "bashgetopt.h"
|
||||
#include "common.h"
|
||||
|
||||
whoami_builtin (list)
|
||||
WORD_LIST *list;
|
||||
|
||||
@@ -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
|
||||
};
|
||||
@@ -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
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user