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
----
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>
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
----
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/{
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
infodir = @infodir@
includedir = @includedir@
datadir = @datadir@
-localedir = $(datadir)/locale
+localedir = @localedir@
mandir = @mandir@
manpfx = man
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@
infodir = @infodir@
includedir = @includedir@
+datarootdir = @datarootdir@
+
topdir = @top_srcdir@
BUILD_DIR = @BUILD_DIR@
srcdir = @srcdir@
#include <stdio.h>
#include "builtins.h"
#include "shell.h"
+#include "common.h"
basename_builtin (list)
WORD_LIST *list;
--- /dev/null
+/* 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 */
+};
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
+#include "common.h"
#if !defined (errno)
extern int errno;
--- /dev/null
+/*
+ * 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
+};
#include <stdio.h>
#include "builtins.h"
#include "shell.h"
+#include "common.h"
dirname_builtin (list)
WORD_LIST *list;
--- /dev/null
+/* 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 */
+};
#include <pwd.h>
#include <grp.h>
#include <errno.h>
+#include "posixtime.h"
#include "bashansi.h"
#include "shell.h"
--- /dev/null
+/*
+ * 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
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
+#include "common.h"
#if !defined (errno)
extern int errno;
--- /dev/null
+/* 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 */
+};
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
+#include "common.h"
#if !defined (errno)
extern int errno;
--- /dev/null
+/* 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 */
+};
#include "builtins.h"
#include "shell.h"
+#include "common.h"
#if !defined (errno)
extern int errno;
--- /dev/null
+/* 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
+};
+
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
+#include "common.h"
#if !defined (errno)
extern int errno;
--- /dev/null
+/* 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
+};
#include "stdc.h"
#include "bashgetopt.h"
#include "maxpath.h"
+#include "common.h"
#if !defined (errno)
extern int errno;
--- /dev/null
+/* 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;
+}
#include "builtins.h"
#include "stdc.h"
#include "bashgetopt.h"
+#include "builtext.h"
+#include "common.h"
#if !defined (errno)
extern int errno;
--- /dev/null
+/*
+ * 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);
+}
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
+#include "common.h"
extern char **export_env;
--- /dev/null
+/*
+ * 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
+};
#include "shell.h"
#include "jobs.h"
#include "bashgetopt.h"
+#include "common.h"
#ifndef errno
extern int errno;
--- /dev/null
+/*
+ * 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
+};
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
+#include "common.h"
#ifndef errno
extern int errno;
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;
--- /dev/null
+/*
+ * 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 */
+};
#include <errno.h>
#include "builtins.h"
#include "shell.h"
+#include "common.h"
#if !defined (errno)
extern int errno;
--- /dev/null
+/* 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 */
+};
#include "shell.h"
#include "builtins.h"
+#include "common.h"
#define RETURN(x) \
do { \
--- /dev/null
+/*
+ * 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
+};
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
+#include "common.h"
#if !defined (errno)
extern int errno;
--- /dev/null
+/* 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 */
+};
#include "bashtypes.h"
#include "shell.h"
#include "builtins.h"
+#include "common.h"
true_builtin (list)
WORD_LIST *list;
--- /dev/null
+/* 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
+};
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
+#include "common.h"
extern char *ttyname ();
--- /dev/null
+/* 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 */
+};
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
+#include "common.h"
#define FLAG_SYSNAME 0x01 /* -s */
#define FLAG_NODENAME 0x02 /* -n */
--- /dev/null
+/*
+ * 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
+};
#include "builtins.h"
#include "shell.h"
+#include "common.h"
#ifndef errno
extern int errno;
--- /dev/null
+/* 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 */
+};
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
+#include "common.h"
whoami_builtin (list)
WORD_LIST *list;
--- /dev/null
+/*
+ * 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
+};
/* 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.
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 *));
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]);
/* 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.
{
homedir = tilde_expand ("~");
_rl_replace_text (homedir, start, end);
+ xfree (homedir);
return (0);
}
else if (rl_line_buffer[start] != '~')
xfree (temp);
_rl_replace_text (homedir, start, end);
+ xfree (homedir);
}
return (0);