mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-07-01 17:39:56 +02:00
commit bash-20130301 snapshot
This commit is contained in:
@@ -0,0 +1,238 @@
|
||||
#
|
||||
# Simple makefile for the sample loadable builtins
|
||||
#
|
||||
# Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
# Include some boilerplate Gnu makefile definitions.
|
||||
prefix = @prefix@
|
||||
|
||||
exec_prefix = @exec_prefix@
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
infodir = @infodir@
|
||||
includedir = @includedir@
|
||||
|
||||
topdir = @top_srcdir@
|
||||
BUILD_DIR = @BUILD_DIR@
|
||||
srcdir = @srcdir@
|
||||
VPATH = .:@srcdir@
|
||||
|
||||
@SET_MAKE@
|
||||
CC = @CC@
|
||||
RM = rm -f
|
||||
|
||||
SHELL = @MAKE_SHELL@
|
||||
|
||||
host_os = @host_os@
|
||||
host_cpu = @host_cpu@
|
||||
host_vendor = @host_vendor@
|
||||
|
||||
CFLAGS = @CFLAGS@
|
||||
LOCAL_CFLAGS = @LOCAL_CFLAGS@
|
||||
DEFS = @DEFS@
|
||||
LOCAL_DEFS = @LOCAL_DEFS@
|
||||
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
|
||||
BASHINCDIR = ${topdir}/include
|
||||
|
||||
LIBBUILD = ${BUILD_DIR}/lib
|
||||
|
||||
INTL_LIBSRC = ${topdir}/lib/intl
|
||||
INTL_BUILDDIR = ${LIBBUILD}/intl
|
||||
INTL_INC = @INTL_INC@
|
||||
LIBINTL_H = @LIBINTL_H@
|
||||
|
||||
CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) $(CFLAGS)
|
||||
|
||||
#
|
||||
# These values are generated for configure by ${topdir}/support/shobj-conf.
|
||||
# If your system is not supported by that script, but includes facilities for
|
||||
# dynamic loading of shared objects, please update the script and send the
|
||||
# changes to bash-maintainers@gnu.org.
|
||||
#
|
||||
SHOBJ_CC = @SHOBJ_CC@
|
||||
SHOBJ_CFLAGS = @SHOBJ_CFLAGS@
|
||||
SHOBJ_LD = @SHOBJ_LD@
|
||||
SHOBJ_LDFLAGS = @SHOBJ_LDFLAGS@
|
||||
SHOBJ_XLDFLAGS = @SHOBJ_XLDFLAGS@
|
||||
SHOBJ_LIBS = @SHOBJ_LIBS@
|
||||
SHOBJ_STATUS = @SHOBJ_STATUS@
|
||||
|
||||
INC = -I. -I.. -I$(topdir) -I$(topdir)/lib -I$(topdir)/builtins \
|
||||
-I$(BASHINCDIR) -I$(BUILD_DIR) -I$(LIBBUILD) \
|
||||
-I$(BUILD_DIR)/builtins $(INTL_INC)
|
||||
|
||||
.c.o:
|
||||
$(SHOBJ_CC) $(SHOBJ_CFLAGS) $(CCFLAGS) $(INC) -c -o $@ $<
|
||||
|
||||
|
||||
ALLPROG = print truefalse sleep pushd finfo logname basename dirname \
|
||||
tty pathchk tee head mkdir rmdir printenv id whoami \
|
||||
uname sync push ln unlink cut realpath getconf strftime
|
||||
OTHERPROG = necho hello cat
|
||||
|
||||
all: $(SHOBJ_STATUS)
|
||||
|
||||
supported: $(ALLPROG)
|
||||
others: $(OTHERPROG)
|
||||
|
||||
unsupported:
|
||||
@echo "Your system (${host_os}) is not supported by the"
|
||||
@echo "${topdir}/support/shobj-conf script."
|
||||
@echo "If your operating system provides facilities for dynamic"
|
||||
@echo "loading of shared objects using the dlopen(3) interface,"
|
||||
@echo "please update the script and re-run configure.
|
||||
@echo "Please send the changes you made to bash-maintainers@gnu.org"
|
||||
@echo "for inclusion in future bash releases."
|
||||
|
||||
everything: supported others
|
||||
|
||||
print: print.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ print.o $(SHOBJ_LIBS)
|
||||
|
||||
necho: necho.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ necho.o $(SHOBJ_LIBS)
|
||||
|
||||
getconf: getconf.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ getconf.o $(SHOBJ_LIBS)
|
||||
|
||||
hello: hello.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ hello.o $(SHOBJ_LIBS)
|
||||
|
||||
truefalse: truefalse.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ truefalse.o $(SHOBJ_LIBS)
|
||||
|
||||
sleep: sleep.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ sleep.o $(SHOBJ_LIBS)
|
||||
|
||||
finfo: finfo.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ finfo.o $(SHOBJ_LIBS)
|
||||
|
||||
cat: cat.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ cat.o $(SHOBJ_LIBS)
|
||||
|
||||
logname: logname.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ logname.o $(SHOBJ_LIBS)
|
||||
|
||||
basename: basename.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ basename.o $(SHOBJ_LIBS)
|
||||
|
||||
dirname: dirname.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ dirname.o $(SHOBJ_LIBS)
|
||||
|
||||
tty: tty.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ tty.o $(SHOBJ_LIBS)
|
||||
|
||||
pathchk: pathchk.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ pathchk.o $(SHOBJ_LIBS)
|
||||
|
||||
tee: tee.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ tee.o $(SHOBJ_LIBS)
|
||||
|
||||
mkdir: mkdir.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ mkdir.o $(SHOBJ_LIBS)
|
||||
|
||||
rmdir: rmdir.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ rmdir.o $(SHOBJ_LIBS)
|
||||
|
||||
head: head.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ head.o $(SHOBJ_LIBS)
|
||||
|
||||
printenv: printenv.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ printenv.o $(SHOBJ_LIBS)
|
||||
|
||||
id: id.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ id.o $(SHOBJ_LIBS)
|
||||
|
||||
whoami: whoami.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ whoami.o $(SHOBJ_LIBS)
|
||||
|
||||
uname: uname.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ uname.o $(SHOBJ_LIBS)
|
||||
|
||||
sync: sync.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ sync.o $(SHOBJ_LIBS)
|
||||
|
||||
push: push.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ push.o $(SHOBJ_LIBS)
|
||||
|
||||
ln: ln.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ ln.o $(SHOBJ_LIBS)
|
||||
|
||||
unlink: unlink.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ unlink.o $(SHOBJ_LIBS)
|
||||
|
||||
cut: cut.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ cut.o $(SHOBJ_LIBS)
|
||||
|
||||
realpath: realpath.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ realpath.o $(SHOBJ_LIBS)
|
||||
|
||||
strftime: strftime.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ strftime.o $(SHOBJ_LIBS)
|
||||
|
||||
# pushd is a special case. We use the same source that the builtin version
|
||||
# uses, with special compilation options.
|
||||
#
|
||||
pushd.c: ${topdir}/builtins/pushd.def
|
||||
$(RM) $@
|
||||
${BUILD_DIR}/builtins/mkbuiltins -D ${topdir}/builtins ${topdir}/builtins/pushd.def
|
||||
|
||||
pushd.o: pushd.c
|
||||
$(RM) $@
|
||||
$(SHOBJ_CC) -DHAVE_CONFIG_H -DPUSHD_AND_POPD -DLOADABLE_BUILTIN $(SHOBJ_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(INC) -c -o $@ $<
|
||||
|
||||
pushd: pushd.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ pushd.o $(SHOBJ_LIBS)
|
||||
|
||||
clean:
|
||||
$(RM) $(ALLPROG) $(OTHERPROG) *.o
|
||||
-( cd perl && ${MAKE} ${MFLAGS} $@ )
|
||||
|
||||
mostlyclean: clean
|
||||
-( cd perl && ${MAKE} ${MFLAGS} $@ )
|
||||
|
||||
distclean maintainer-clean: clean
|
||||
$(RM) Makefile pushd.c
|
||||
-( cd perl && ${MAKE} ${MFLAGS} $@ )
|
||||
|
||||
print.o: print.c
|
||||
truefalse.o: truefalse.c
|
||||
sleep.o: sleep.c
|
||||
finfo.o: finfo.c
|
||||
logname.o: logname.c
|
||||
basename.o: basename.c
|
||||
dirname.o: dirname.c
|
||||
tty.o: tty.c
|
||||
pathchk.o: pathchk.c
|
||||
tee.o: tee.c
|
||||
head.o: head.c
|
||||
rmdir.o: rmdir.c
|
||||
necho.o: necho.c
|
||||
getconf.o: getconf.c
|
||||
hello.o: hello.c
|
||||
cat.o: cat.c
|
||||
printenv.o: printenv.c
|
||||
id.o: id.c
|
||||
whoami.o: whoami.c
|
||||
uname.o: uname.c
|
||||
sync.o: sync.c
|
||||
push.o: push.c
|
||||
mkdir.o: mkdir.c
|
||||
realpath.o: realpath.c
|
||||
strftime.o: strftime.c
|
||||
@@ -2,6 +2,24 @@
|
||||
|
||||
/* See Makefile for compilation details. */
|
||||
|
||||
/*
|
||||
Copyright (C) 1999-2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash.
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/* 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"
|
||||
#include "common.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[] = {
|
||||
"Return non-directory portion of pathname.",
|
||||
"",
|
||||
"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 */
|
||||
};
|
||||
@@ -0,0 +1,379 @@
|
||||
/*
|
||||
* 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"
|
||||
#include "common.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 lines.",
|
||||
"",
|
||||
"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
|
||||
};
|
||||
@@ -5,6 +5,24 @@
|
||||
* chet@po.cwru.edu
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (C) 1999-2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash.
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,602 @@
|
||||
/*
|
||||
* finfo - print file info
|
||||
*
|
||||
* Chet Ramey
|
||||
* chet@po.cwru.edu
|
||||
*/
|
||||
|
||||
#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 "posixtime.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", (long) 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 file attributes.",
|
||||
"",
|
||||
"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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,214 @@
|
||||
/* getconf.h -- replacement definitions for ones the system doesn't provide. */
|
||||
|
||||
#ifndef _GETCONF_H
|
||||
#define _GETCONF_H
|
||||
|
||||
/* Some systems do not define these; use POSIX.2 minimum recommended values. */
|
||||
#ifndef _POSIX2_COLL_WEIGHTS_MAX
|
||||
# define _POSIX2_COLL_WEIGHTS_MAX 2
|
||||
#endif
|
||||
|
||||
/* If we're on a posix system, but the system doesn't define the necessary
|
||||
constants, use posix.1 minimum values. */
|
||||
#if defined (_POSIX_VERSION)
|
||||
|
||||
#ifndef _POSIX_ARG_MAX
|
||||
# define _POSIX_ARG_MAX 4096
|
||||
#endif
|
||||
#ifndef _POSIX_CHILD_MAX
|
||||
# define _POSIX_CHILD_MAX 6
|
||||
#endif
|
||||
#ifndef _POSIX_LINK_MAX
|
||||
# define _POSIX_LINK_MAX 8
|
||||
#endif
|
||||
#ifndef _POSIX_MAX_CANON
|
||||
# define _POSIX_MAX_CANON 255
|
||||
#endif
|
||||
#ifndef _POSIX_MAX_INPUT
|
||||
# define _POSIX_MAX_INPUT 255
|
||||
#endif
|
||||
#ifndef _POSIX_NAME_MAX
|
||||
# define _POSIX_NAME_MAX 14
|
||||
#endif
|
||||
#ifndef _POSIX_NGROUPS_MAX
|
||||
# define _POSIX_NGROUPS_MAX 0
|
||||
#endif
|
||||
#ifndef _POSIX_OPEN_MAX
|
||||
# define _POSIX_OPEN_MAX 16
|
||||
#endif
|
||||
#ifndef _POSIX_PATH_MAX
|
||||
# define _POSIX_PATH_MAX 255
|
||||
#endif
|
||||
#ifndef _POSIX_PIPE_BUF
|
||||
# define _POSIX_PIPE_BUF 512
|
||||
#endif
|
||||
#ifndef _POSIX_SSIZE_MAX
|
||||
# define _POSIX_SSIZE_MAX 32767
|
||||
#endif
|
||||
#ifndef _POSIX_STREAM_MAX
|
||||
# define _POSIX_STREAM_MAX 8
|
||||
#endif
|
||||
#ifndef _POSIX_TZNAME_MAX
|
||||
# define _POSIX_TZNAME_MAX 3
|
||||
#endif
|
||||
|
||||
#ifndef _POSIX2_BC_BASE_MAX
|
||||
# define _POSIX2_BC_BASE_MAX 99
|
||||
#endif
|
||||
#ifndef _POSIX2_BC_DIM_MAX
|
||||
# define _POSIX2_BC_DIM_MAX 2048
|
||||
#endif
|
||||
#ifndef _POSIX2_BC_SCALE_MAX
|
||||
# define _POSIX2_BC_SCALE_MAX 99
|
||||
#endif
|
||||
#ifndef _POSIX2_BC_STRING_MAX
|
||||
# define _POSIX2_BC_STRING_MAX 1000
|
||||
#endif
|
||||
#ifndef _POSIX2_EQUIV_CLASS_MAX
|
||||
# define _POSIX2_EQUIV_CLASS_MAX 2
|
||||
#endif
|
||||
#ifndef _POSIX2_EXPR_NEST_MAX
|
||||
# define _POSIX2_EXPR_NEST_MAX 32
|
||||
#endif
|
||||
#ifndef _POSIX2_LINE_MAX
|
||||
# define _POSIX2_LINE_MAX 2048
|
||||
#endif
|
||||
#ifndef _POSIX2_RE_DUP_MAX
|
||||
# define _POSIX2_RE_DUP_MAX 255
|
||||
#endif
|
||||
|
||||
/* configurable system variables */
|
||||
#if !defined (HAVE_SYSCONF)
|
||||
|
||||
#ifndef _SC_ARG_MAX
|
||||
# define _SC_ARG_MAX 1
|
||||
# define _SC_CHILD_MAX 2
|
||||
# define _SC_CLK_TCK 3
|
||||
# define _SC_NGROUPS_MAX 4
|
||||
# define _SC_OPEN_MAX 5
|
||||
# define _SC_JOB_CONTROL 6
|
||||
# define _SC_SAVED_IDS 7
|
||||
# define _SC_VERSION 8
|
||||
# define _SC_BC_BASE_MAX 9
|
||||
# define _SC_BC_DIM_MAX 10
|
||||
# define _SC_BC_SCALE_MAX 11
|
||||
# define _SC_BC_STRING_MAX 12
|
||||
# define _SC_COLL_WEIGHTS_MAX 13
|
||||
# define _SC_EXPR_NEST_MAX 14
|
||||
# define _SC_LINE_MAX 15
|
||||
# define _SC_RE_DUP_MAX 16
|
||||
#if 0
|
||||
# define _SC_2_VERSION 17
|
||||
# define _SC_2_C_BIND 18
|
||||
# define _SC_2_C_DEV 19
|
||||
# define _SC_2_CHAR_TERM 20
|
||||
# define _SC_2_FORT_DEV 21
|
||||
# define _SC_2_FORT_RUN 22
|
||||
# define _SC_2_LOCALEDEF 23
|
||||
# define _SC_2_SW_DEV 24
|
||||
# define _SC_2_UPE 25
|
||||
#endif /* 0 */
|
||||
|
||||
# define _SC_STREAM_MAX 26
|
||||
# define _SC_TZNAME_MAX 27
|
||||
#endif /* !_SC_ARG_MAX */
|
||||
|
||||
#endif /* !HAVE_SYSCONF */
|
||||
|
||||
/* configurable pathname variables */
|
||||
#if !defined (HAVE_PATHCONF)
|
||||
|
||||
#ifndef _PC_LINK_MAX
|
||||
#define _PC_LINK_MAX 1
|
||||
#define _PC_MAX_CANON 2
|
||||
#define _PC_MAX_INPUT 3
|
||||
#define _PC_NAME_MAX 4
|
||||
#define _PC_PATH_MAX 5
|
||||
#define _PC_PIPE_BUF 6
|
||||
#define _PC_CHOWN_RESTRICTED 7
|
||||
#define _PC_NO_TRUNC 8
|
||||
#define _PC_VDISABLE 9
|
||||
#endif /* !_PC_LINK_MAX */
|
||||
|
||||
#endif /* !HAVE_PATHCONF */
|
||||
|
||||
#endif /* _POSIX_VERSION */
|
||||
|
||||
#ifndef _CS_PATH
|
||||
# define _CS_PATH 1
|
||||
#endif
|
||||
|
||||
/* ANSI/ISO C, POSIX.1-200x, XPG 4.2 (and later) C language type limits.
|
||||
Defined only if the system include files don't. Assume a 32-bit
|
||||
environment with signed 8-bit characters. */
|
||||
|
||||
#ifndef CHAR_BIT
|
||||
# define CHAR_BIT 8
|
||||
#endif
|
||||
#ifndef CHAR_MAX
|
||||
# define CHAR_MAX 127
|
||||
#endif
|
||||
#ifndef CHAR_MIN
|
||||
# define CHAR_MIN -128
|
||||
#endif
|
||||
|
||||
#ifndef INT_BIT
|
||||
# define INT_BIT (sizeof (int) * CHAR_BIT)
|
||||
#endif
|
||||
#ifndef INT_MAX
|
||||
# define INT_MAX 2147483647
|
||||
#endif
|
||||
#ifndef INT_MIN
|
||||
# define INT_MIN (-2147483647-1)
|
||||
#endif
|
||||
|
||||
#ifndef LONG_BIT
|
||||
# define LONG_BIT (sizeof (long int) * CHAR_BIT)
|
||||
#endif
|
||||
#ifndef LONG_MAX
|
||||
# define LONG_MAX 2147483647L
|
||||
#endif
|
||||
#ifndef LONG_MIN
|
||||
# define LONG_MIN (-2147483647L-1L)
|
||||
#endif
|
||||
|
||||
#ifndef SCHAR_MAX
|
||||
# define SCHAR_MAX CHAR_MAX
|
||||
#endif
|
||||
#ifndef SCHAR_MIN
|
||||
# define SCHAR_MIN CHAR_MIN
|
||||
#endif
|
||||
|
||||
#ifndef SHRT_MAX
|
||||
# define SHRT_MAX 32767
|
||||
#endif
|
||||
#ifndef SHRT_MIN
|
||||
# define SHRT_MIN (-32768)
|
||||
#endif
|
||||
|
||||
#ifndef UCHAR_MAX
|
||||
# define UCHAR_MAX 255
|
||||
#endif
|
||||
#ifndef UINT_MAX
|
||||
# define UINT_MAX 4294967295U
|
||||
#endif
|
||||
#ifndef ULONG_MAX
|
||||
# define ULONG_MAX 4294967295UL
|
||||
#endif
|
||||
#ifndef USHRT_MAX
|
||||
# define UCHAR_MAX 65535
|
||||
#endif
|
||||
|
||||
/* assume size_t is `unsigned int'; ssize_t is `int' */
|
||||
#ifndef SIZE_MAX
|
||||
# define SIZE_MAX UINT_MAX
|
||||
#endif
|
||||
#ifndef SSIZE_MAX
|
||||
# define SSIZE_MAX INT_MAX
|
||||
#endif
|
||||
|
||||
#ifndef WORD_BIT
|
||||
# define WORD_BIT (sizeof (int) * CHAR_BIT)
|
||||
#endif
|
||||
|
||||
#endif /* _GETCONF_H */
|
||||
@@ -3,6 +3,24 @@
|
||||
|
||||
/* See Makefile for compilation details. */
|
||||
|
||||
/*
|
||||
Copyright (C) 1999-2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash.
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/* Sample builtin to be dynamically loaded with enable -f and create a new
|
||||
builtin. */
|
||||
|
||||
/* 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"
|
||||
#include "bashgetopt.h"
|
||||
|
||||
/* A builtin `xxx' is normally implemented with an `xxx_builtin' function.
|
||||
If you're converting a command that uses the normal Unix argc/argv
|
||||
calling convention, use argv = make_builtin_argv (list, &argc) and call
|
||||
the original `main' something like `xxx_main'. Look at cat.c for an
|
||||
example.
|
||||
|
||||
Builtins should use internal_getopt to parse options. It is the same as
|
||||
getopt(3), but it takes a WORD_LIST *. Look at print.c for an example
|
||||
of its use.
|
||||
|
||||
If the builtin takes no options, call no_options(list) before doing
|
||||
anything else. If it returns a non-zero value, your builtin should
|
||||
immediately return EX_USAGE. Look at logname.c for an example.
|
||||
|
||||
A builtin command returns EXECUTION_SUCCESS for success and
|
||||
EXECUTION_FAILURE to indicate failure. */
|
||||
int
|
||||
hello_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
printf("hello world\n");
|
||||
fflush (stdout);
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
/* An array of strings forming the `long' documentation for a builtin xxx,
|
||||
which is printed by `help xxx'. It must end with a NULL. By convention,
|
||||
the first line is a short description. */
|
||||
char *hello_doc[] = {
|
||||
"Sample builtin.",
|
||||
"",
|
||||
"this is the long doc for the sample hello builtin",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
/* The standard structure describing a builtin command. bash keeps an array
|
||||
of these structures. The flags must include BUILTIN_ENABLED so the
|
||||
builtin can be used. */
|
||||
struct builtin hello_struct = {
|
||||
"hello", /* builtin name */
|
||||
hello_builtin, /* function implementing the builtin */
|
||||
BUILTIN_ENABLED, /* initial flags for builtin */
|
||||
hello_doc, /* array of long documentation strings. */
|
||||
"hello", /* usage synopsis; becomes short_doc */
|
||||
0 /* reserved for internal use */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,516 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if !defined(BUILTIN) && !defined(SHELL)
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1989, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)printf.c 8.1 (Berkeley) 7/20/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "bashansi.h"
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
#include "stdc.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
static char sbuf[1024];
|
||||
static int sblen;
|
||||
|
||||
/* Gee, I wish sprintf could be reliably counted upon to return the
|
||||
number of characters written :-( */
|
||||
#define PF(f, func) \
|
||||
do { \
|
||||
if (fieldwidth) \
|
||||
if (precision) \
|
||||
sprintf(sbuf, f, fieldwidth, precision, func); \
|
||||
else \
|
||||
sprintf(sbuf, f, fieldwidth, func); \
|
||||
else if (precision) \
|
||||
sprintf(sbuf, f, precision, func); \
|
||||
else \
|
||||
sprintf(sbuf, f, func); \
|
||||
spaddstr (sbuf, strlen (sbuf)); \
|
||||
} while (0)
|
||||
|
||||
static int asciicode __P((void));
|
||||
static void escape __P((char *));
|
||||
static int getchr __P((void));
|
||||
static double getdouble __P((void));
|
||||
static int getint __P((int *));
|
||||
static int getlong __P((long *));
|
||||
static char *getstr __P((void));
|
||||
static char *mklong __P((char *, int));
|
||||
static void usage __P((void));
|
||||
|
||||
static char **gargv;
|
||||
|
||||
static char *outstr;
|
||||
static int outsize;
|
||||
static int outind;
|
||||
|
||||
int sprintf_builtin ();
|
||||
static int sprintf_main ();
|
||||
static void spaddstr ();
|
||||
|
||||
extern char *this_command_name;
|
||||
extern char *single_quote ();
|
||||
extern char **make_builtin_argv ();
|
||||
|
||||
static char *sprintf_doc[] = {
|
||||
"Format arguments and assign result to variable.",
|
||||
"",
|
||||
"sprintf formats and outputs its arguments, after the second, under control",
|
||||
"of the format and assigns the result to the variable named by its first",
|
||||
"argument. The format is a character string which contains three types",
|
||||
"of objects: plain characters, which are simply copied to the output string,",
|
||||
"character escape sequences which are converted and copied to the output",
|
||||
"string, and format specifications, each of which causes printing of the",
|
||||
"next successive argument. In addition to the standard sprintf(3) formats,",
|
||||
"%b means to expand escapes in the corresponding argument, and %q means",
|
||||
"to quote the argument in a way that can be reused as shell input. Each",
|
||||
"one of the format specifications must not expand to more than 1024",
|
||||
"characters, though there is no limit on the total size of the output",
|
||||
"string.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
struct builtin sprintf_struct = {
|
||||
"sprintf",
|
||||
sprintf_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
sprintf_doc,
|
||||
"sprintf var format [arguments]",
|
||||
(char *)0
|
||||
};
|
||||
|
||||
int
|
||||
sprintf_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int c, r;
|
||||
char **v, *varname;
|
||||
WORD_LIST *l;
|
||||
SHELL_VAR *var;
|
||||
|
||||
if (list == 0)
|
||||
{
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
varname = list->word->word;
|
||||
list = list->next;
|
||||
|
||||
if (legal_identifier (varname) == 0)
|
||||
{
|
||||
builtin_error ("%s: not a legal variable name", varname);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
outind = 0;
|
||||
if (outstr == 0)
|
||||
outstr = xmalloc (outsize = 64);
|
||||
outstr[0] = '\0';
|
||||
|
||||
v = make_builtin_argv (list, &c);
|
||||
r = sprintf_main (c, v);
|
||||
free (v);
|
||||
|
||||
var = bind_variable (varname, outstr, 0);
|
||||
if (readonly_p (var))
|
||||
{
|
||||
builtin_error ("%s: readonly variable", varname);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
spaddstr(str, len)
|
||||
char *str;
|
||||
int len;
|
||||
{
|
||||
RESIZE_MALLOCED_BUFFER (outstr, outind, len, outsize, 64);
|
||||
strcpy (outstr + outind, str);
|
||||
outind += len;
|
||||
}
|
||||
|
||||
static int
|
||||
sprintf_main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern int optind;
|
||||
static char *skip1, *skip2;
|
||||
int ch, end, fieldwidth, precision;
|
||||
char convch, nextch, *format, *fmt, *start;
|
||||
|
||||
while ((ch = getopt(argc, argv, "")) != EOF)
|
||||
switch (ch) {
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc < 1) {
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Basic algorithm is to scan the format string for conversion
|
||||
* specifications -- once one is found, find out if the field
|
||||
* width or precision is a '*'; if it is, gather up value. Note,
|
||||
* format strings are reused as necessary to use up the provided
|
||||
* arguments, arguments of zero/null string are provided to use
|
||||
* up the format string.
|
||||
*/
|
||||
skip1 = "#-+ 0";
|
||||
skip2 = "*0123456789";
|
||||
|
||||
escape(fmt = format = *argv); /* backslash interpretation */
|
||||
gargv = ++argv;
|
||||
for (;;) {
|
||||
end = 0;
|
||||
/* find next format specification */
|
||||
next: for (start = fmt;; ++fmt) {
|
||||
if (!*fmt) {
|
||||
/* avoid infinite loop */
|
||||
if (end == 1) {
|
||||
warnx("missing format character",
|
||||
NULL, NULL);
|
||||
return (1);
|
||||
}
|
||||
end = 1;
|
||||
if (fmt > start)
|
||||
(void)printf("%s", start);
|
||||
if (!*gargv)
|
||||
return (0);
|
||||
fmt = format;
|
||||
goto next;
|
||||
}
|
||||
/* %% prints a % */
|
||||
if (*fmt == '%') {
|
||||
if (*++fmt != '%')
|
||||
break;
|
||||
*fmt++ = '\0';
|
||||
(void)printf("%s", start);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
/* skip to field width */
|
||||
for (; strchr(skip1, *fmt); ++fmt);
|
||||
if (*fmt == '*') {
|
||||
if (getint(&fieldwidth))
|
||||
return (1);
|
||||
} else
|
||||
fieldwidth = 0;
|
||||
|
||||
/* skip to possible '.', get following precision */
|
||||
for (; strchr(skip2, *fmt); ++fmt);
|
||||
if (*fmt == '.')
|
||||
++fmt;
|
||||
if (*fmt == '*') {
|
||||
if (getint(&precision))
|
||||
return (1);
|
||||
} else
|
||||
precision = 0;
|
||||
|
||||
/* skip to conversion char */
|
||||
for (; strchr(skip2, *fmt); ++fmt);
|
||||
if (!*fmt) {
|
||||
warnx("missing format character", NULL, NULL);
|
||||
return (1);
|
||||
}
|
||||
|
||||
convch = *fmt;
|
||||
nextch = *++fmt;
|
||||
*fmt = '\0';
|
||||
switch(convch) {
|
||||
case 'c': {
|
||||
char p;
|
||||
|
||||
p = getchr();
|
||||
PF(start, p);
|
||||
break;
|
||||
}
|
||||
case 's': {
|
||||
char *p;
|
||||
|
||||
p = getstr();
|
||||
PF(start, p);
|
||||
break;
|
||||
}
|
||||
case 'b': { /* expand escapes in argument */
|
||||
char *p;
|
||||
|
||||
p = getstr();
|
||||
escape(p);
|
||||
PF("%s", p);
|
||||
break;
|
||||
}
|
||||
case 'q': { /* print with shell single quoting */
|
||||
char *p, *p2;
|
||||
|
||||
p = getstr();
|
||||
p2 = single_quote(p);
|
||||
PF("%s", p2);
|
||||
free(p2);
|
||||
break;
|
||||
}
|
||||
case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': {
|
||||
long p;
|
||||
char *f;
|
||||
|
||||
if ((f = mklong(start, convch)) == NULL)
|
||||
return (1);
|
||||
if (getlong(&p))
|
||||
return (1);
|
||||
PF(f, p);
|
||||
break;
|
||||
}
|
||||
case 'e': case 'E': case 'f': case 'g': case 'G': {
|
||||
double p;
|
||||
|
||||
p = getdouble();
|
||||
PF(start, p);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
warnx("illegal format character", NULL, NULL);
|
||||
return (1);
|
||||
}
|
||||
*fmt = nextch;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static char *
|
||||
mklong(str, ch)
|
||||
char *str;
|
||||
int ch;
|
||||
{
|
||||
static char copy[64];
|
||||
int len;
|
||||
|
||||
len = strlen(str) + 2;
|
||||
memmove(copy, str, len - 3);
|
||||
copy[len - 3] = 'l';
|
||||
copy[len - 2] = ch;
|
||||
copy[len - 1] = '\0';
|
||||
return (copy);
|
||||
}
|
||||
|
||||
static void
|
||||
escape(fmt)
|
||||
register char *fmt;
|
||||
{
|
||||
register char *store;
|
||||
register int value, c;
|
||||
|
||||
for (store = fmt; c = *fmt; ++fmt, ++store) {
|
||||
if (c != '\\') {
|
||||
*store = c;
|
||||
continue;
|
||||
}
|
||||
switch (*++fmt) {
|
||||
case '\0': /* EOS, user error */
|
||||
*store = '\\';
|
||||
*++store = '\0';
|
||||
return;
|
||||
case '\\': /* backslash */
|
||||
case '\'': /* single quote */
|
||||
*store = *fmt;
|
||||
break;
|
||||
case 'a': /* bell/alert */
|
||||
*store = '\7';
|
||||
break;
|
||||
case 'b': /* backspace */
|
||||
*store = '\b';
|
||||
break;
|
||||
case 'c':
|
||||
return;
|
||||
case 'e':
|
||||
case 'E':
|
||||
*store = '\033';
|
||||
break;
|
||||
case 'f': /* form-feed */
|
||||
*store = '\f';
|
||||
break;
|
||||
case 'n': /* newline */
|
||||
*store = '\n';
|
||||
break;
|
||||
case 'r': /* carriage-return */
|
||||
*store = '\r';
|
||||
break;
|
||||
case 't': /* horizontal tab */
|
||||
*store = '\t';
|
||||
break;
|
||||
case 'v': /* vertical tab */
|
||||
*store = '\13';
|
||||
break;
|
||||
/* octal constant */
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
for (c = 3, value = 0;
|
||||
c-- && *fmt >= '0' && *fmt <= '7'; ++fmt) {
|
||||
value <<= 3;
|
||||
value += *fmt - '0';
|
||||
}
|
||||
--fmt;
|
||||
*store = value;
|
||||
break;
|
||||
default:
|
||||
*store = *fmt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*store = '\0';
|
||||
}
|
||||
|
||||
static int
|
||||
getchr()
|
||||
{
|
||||
if (!*gargv)
|
||||
return ('\0');
|
||||
return ((int)**gargv++);
|
||||
}
|
||||
|
||||
static char *
|
||||
getstr()
|
||||
{
|
||||
if (!*gargv)
|
||||
return ("");
|
||||
return (*gargv++);
|
||||
}
|
||||
|
||||
static char *Number = "+-.0123456789";
|
||||
static int
|
||||
getint(ip)
|
||||
int *ip;
|
||||
{
|
||||
long val;
|
||||
|
||||
if (getlong(&val))
|
||||
return (1);
|
||||
if (val > INT_MAX) {
|
||||
warnx("%s: %s", *gargv, strerror(ERANGE));
|
||||
return (1);
|
||||
}
|
||||
*ip = val;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
getlong(lp)
|
||||
long *lp;
|
||||
{
|
||||
long val;
|
||||
char *ep;
|
||||
|
||||
if (!*gargv) {
|
||||
*lp = 0;
|
||||
return (0);
|
||||
}
|
||||
if (strchr(Number, **gargv)) {
|
||||
errno = 0;
|
||||
val = strtol(*gargv, &ep, 0);
|
||||
if (*ep != '\0') {
|
||||
warnx("%s: illegal number", *gargv, NULL);
|
||||
return (1);
|
||||
}
|
||||
if (errno == ERANGE)
|
||||
if (val == LONG_MAX) {
|
||||
warnx("%s: %s", *gargv, strerror(ERANGE));
|
||||
return (1);
|
||||
}
|
||||
if (val == LONG_MIN) {
|
||||
warnx("%s: %s", *gargv, strerror(ERANGE));
|
||||
return (1);
|
||||
}
|
||||
|
||||
*lp = val;
|
||||
++gargv;
|
||||
return (0);
|
||||
}
|
||||
*lp = (long)asciicode();
|
||||
return (0);
|
||||
}
|
||||
|
||||
static double
|
||||
getdouble()
|
||||
{
|
||||
if (!*gargv)
|
||||
return ((double)0);
|
||||
if (strchr(Number, **gargv))
|
||||
return (atof(*gargv++));
|
||||
return ((double)asciicode());
|
||||
}
|
||||
|
||||
static int
|
||||
asciicode()
|
||||
{
|
||||
register int ch;
|
||||
|
||||
ch = **gargv;
|
||||
if (ch == '\'' || ch == '"')
|
||||
ch = (*gargv)[1];
|
||||
++gargv;
|
||||
return (ch);
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "usage: printf format [arg ...]\n");
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Originally from
|
||||
* http://www.excessus.demon.co.uk/misc-hacks/index.html#xtitle
|
||||
*/
|
||||
|
||||
/*
|
||||
* Made into a loadable builtin by chet@po.cwru.edu.
|
||||
*/
|
||||
|
||||
#if defined (HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
#ifdef BASH_BUILTIN
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
#include "bashgetopt.h"
|
||||
#endif
|
||||
|
||||
#ifdef BASH_BUILTIN
|
||||
int xtitle_builtin(WORD_LIST *list)
|
||||
#else
|
||||
int main(int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
int query = 0;
|
||||
int fd;
|
||||
int openned = 0;
|
||||
|
||||
#ifdef BASH_BUILTIN
|
||||
reset_internal_getopt();
|
||||
#endif
|
||||
for (;;) {
|
||||
#ifdef BASH_BUILTIN
|
||||
int i;
|
||||
i = internal_getopt(list, "q");
|
||||
#else
|
||||
int i = getopt(argc, argv, "q");
|
||||
#endif
|
||||
if (i < 0)
|
||||
break;
|
||||
switch (i) {
|
||||
case 'q':
|
||||
query = 1;
|
||||
break;
|
||||
default:
|
||||
#ifdef BASH_BUILTIN
|
||||
builtin_usage();
|
||||
#else
|
||||
fprintf(stderr, "usage: xtitle [-q] [string]\n");
|
||||
#endif
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BASH_BUILTIN
|
||||
if (!query && loptend == 0) {
|
||||
#else
|
||||
if (!query && optind == argc) {
|
||||
#endif
|
||||
fprintf(stderr, "xtitle: no string to set\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
{
|
||||
char *t = getenv("TERM");
|
||||
if (!t || strncmp(t, "xterm", 5))
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (isatty(0))
|
||||
fd = 0;
|
||||
else {
|
||||
fd = open("/dev/tty", O_RDWR);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "xtitle: couldn't open terminal: %s", strerror(errno));
|
||||
return (1);
|
||||
}
|
||||
openned = 1;
|
||||
}
|
||||
|
||||
if (!query) {
|
||||
#ifdef BASH_BUILTIN
|
||||
WORD_LIST *l = loptend;
|
||||
char sp = ' ';
|
||||
write(fd, "\33]0;", 4);
|
||||
while (l) {
|
||||
write(fd, l->word->word, strlen(l->word->word));
|
||||
if (l->next)
|
||||
write(fd, &sp, 1);
|
||||
l = l->next;
|
||||
}
|
||||
write(fd, "\33\\", 2);
|
||||
#else
|
||||
int i;
|
||||
char sp = ' ';
|
||||
write(fd, "\33]0;", 4);
|
||||
for (i = optind; i < argc; i++) {
|
||||
write(fd, argv[i], strlen(argv[i]));
|
||||
if (i < argc - 1)
|
||||
write(fd, &sp, 1);
|
||||
}
|
||||
write(fd, "\33\\", 2);
|
||||
#endif
|
||||
} else {
|
||||
struct termios o, n;
|
||||
char hack;
|
||||
int state = 0;
|
||||
|
||||
tcgetattr(fd, &o);
|
||||
n = o;
|
||||
n.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
|
||||
|INLCR|IGNCR|ICRNL|IXON);
|
||||
n.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
|
||||
n.c_cflag &= ~(CSIZE|PARENB);
|
||||
n.c_cflag |= CS8;
|
||||
tcsetattr(fd, TCSAFLUSH, &n);
|
||||
write(fd, "\33[21t", 5);
|
||||
|
||||
while (state != -1) {
|
||||
if (read(fd, &hack, 1) < 1)
|
||||
break;
|
||||
switch (state) {
|
||||
case 0:
|
||||
if (hack == '\33') state = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (hack == ']') state = 2; else state = 0;
|
||||
break;
|
||||
case 2:
|
||||
if (hack == 'l') state = 3; else state = 0;
|
||||
break;
|
||||
case 3:
|
||||
if (hack == '\33') state = 4; else putchar(hack);
|
||||
break;
|
||||
case 4:
|
||||
if (hack == '\\') { state = -1; putchar('\n'); }
|
||||
else { putchar('\33'); putchar(hack); state = 3; }
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tcsetattr(fd, TCSAFLUSH, &o);
|
||||
}
|
||||
|
||||
if (openned)
|
||||
close(fd);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
#ifdef BASH_BUILTIN
|
||||
|
||||
static char *xtitle_doc[] = {
|
||||
"Set xterm window title.",
|
||||
"",
|
||||
"Either set or read the title of the current xterm window. With the",
|
||||
"-q option, writes the current xterm title to standard output. Without",
|
||||
"the -q option, sets the xterm title to be the arguments given,",
|
||||
"separated by space characters. [By Mark Wooding, mdw@nsict.org]",
|
||||
0
|
||||
};
|
||||
|
||||
struct builtin xtitle_struct = {
|
||||
"xtitle",
|
||||
xtitle_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
xtitle_doc,
|
||||
"xtitle [-q] [arguments]",
|
||||
0
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user