New version of ash. From FreeBSD 5.4 via Minix-vmd.
This commit is contained in:
parent
3ea083b8d4
commit
7aa4c9ec2f
|
@ -1,41 +1,61 @@
|
|||
# Makefile for ash.
|
||||
|
||||
SRCS= builtins.c cd.c dirent.c error.c eval.c exec.c expand.c input.c \
|
||||
SRCS= alias.c builtins.c cd.c error.c eval.c exec.c expand.c histedit.c \
|
||||
input.c \
|
||||
jobs.c mail.c main.c memalloc.c miscbltin.c mystring.c nodes.c \
|
||||
options.c parser.c redir.c show.c signames.c syntax.c trap.c \
|
||||
options.c parser.c redir.c setmode.c show.c signames.c syntax.c \
|
||||
trap.c \
|
||||
output.c var.c
|
||||
|
||||
OBJS= builtins.o cd.o dirent.o error.o eval.o exec.o expand.o input.o \
|
||||
OBJS= alias.o builtins.o cd.o error.o eval.o exec.o expand.o histedit.o \
|
||||
input.o \
|
||||
jobs.o mail.o main.o memalloc.o miscbltin.o mystring.o nodes.o \
|
||||
options.o parser.o redir.o show.o signames.o syntax.o trap.o \
|
||||
options.o parser.o redir.o setmode.o show.o signames.o syntax.o \
|
||||
trap.o \
|
||||
output.o var.o init.o \
|
||||
bltin/echo.o bltin/expr.o bltin/operators.o bltin/regexp.o
|
||||
bltin/echo.o bltin/expr.o bltin/operators.o bltin/regexp.o \
|
||||
arith.o arith_lex.o
|
||||
|
||||
#
|
||||
# Set READLINE in shell.h and add -ledit to LIBS if you want to use the
|
||||
# editline package by Simmule Turner and Rich Salz. (The big, bloated
|
||||
# and GPL contaminated FSF readline should work too.)
|
||||
#
|
||||
CPPFLAGS= -DSHELL -I. -D_MINIX -D_POSIX_SOURCE
|
||||
CFLAGS= -wo -i $(CPPFLAGS)
|
||||
LIBS= -ledit
|
||||
CC = exec cc
|
||||
LEX=flex
|
||||
YACC=yacc
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
# Enable this line to disable command line editing
|
||||
#EDIT=-DNO_HISTORY
|
||||
# Enable this line to use the editline library instead of libedit
|
||||
EDIT=-DEDITLINE
|
||||
EDITLIB=-ledit
|
||||
|
||||
FLEXLIB=-lfl
|
||||
|
||||
# Enable this line if your system does not have a <paths.h>
|
||||
NO_PATHS_H=-DNO_PATHS_H
|
||||
|
||||
# Enable this if you don't want job control
|
||||
NO_JOBS=-DJOBS=0
|
||||
MKB_NO_JOBS=-j
|
||||
|
||||
CPPFLAGS= -DSHELL -I. -D_MINIX $(EDIT) $(NO_PATHS_H) $(NO_JOBS)
|
||||
CFLAGS= $(OPT) $(CPPFLAGS)
|
||||
LIBS= $(EDITLIB) $(FLEXLIB)
|
||||
|
||||
CLEANFILES= $(OBJS) \
|
||||
builtins.c builtins.h init.c mkinit mknodes mksignames mksyntax \
|
||||
nodes.c nodes.h signames.c signames.h syntax.c syntax.h token.def \
|
||||
arith.c arith_y.h arith_lex.c builtins.c builtins.h init.c \
|
||||
mkinit mknodes mksignames mksyntax \
|
||||
nodes.c nodes.h signames.c signames.h syntax.c syntax.h token.h \
|
||||
bltin/operators.h bltin/operators.c
|
||||
|
||||
all: sh
|
||||
|
||||
sh: $(OBJS)
|
||||
$(CC) $(CFLAGS) -o sh $(OBJS) $(LIBS)
|
||||
install -S 100k sh
|
||||
$(CC) $(CFLAGS) -fnone -o sh $(OBJS) $(LIBS)
|
||||
|
||||
install: /usr/bin/ash /usr/bin/sh /bin/sh /bin/bigsh
|
||||
install: /usr/bin/ash /usr/bin/sh /bin/sh /usr/man/man1/ash.1 \
|
||||
/usr/man/man1/echo.1 /usr/man/man1/expr.1
|
||||
|
||||
/usr/bin/ash: sh
|
||||
install -cs -o bin $? $@
|
||||
install -c $? $@
|
||||
|
||||
/usr/bin/sh: /usr/bin/ash
|
||||
install -l $? $@
|
||||
|
@ -43,8 +63,14 @@ install: /usr/bin/ash /usr/bin/sh /bin/sh /bin/bigsh
|
|||
/bin/sh: /usr/bin/ash
|
||||
install -lcs $? $@
|
||||
|
||||
/bin/bigsh: /usr/bin/ash
|
||||
install -S 1500000 -lcs $? $@
|
||||
/usr/man/man1/ash.1: sh.1
|
||||
install -lc $? $@
|
||||
|
||||
/usr/man/man1/echo.1: bltin/echo.1
|
||||
install -lc $? $@
|
||||
|
||||
/usr/man/man1/expr.1: bltin/expr.1
|
||||
install -lc $? $@
|
||||
|
||||
clean:
|
||||
rm -f $(CLEANFILES) sh core
|
||||
|
@ -54,11 +80,18 @@ parser.o: token.def
|
|||
token.def: mktokens
|
||||
sh mktokens
|
||||
|
||||
builtins.c builtins.h: builtins.table shell.h
|
||||
sh mkbuiltins shell.h builtins.table
|
||||
arith.c: arith.y
|
||||
$(YACC) -d $?
|
||||
mv y.tab.c $@
|
||||
mv y.tab.h arith_y.h
|
||||
|
||||
init.o: mkinit $(SRCS)
|
||||
./mkinit '$(CC) -c $(CFLAGS) init.c' $(SRCS)
|
||||
arith_lex.c: arith_lex.l
|
||||
|
||||
builtins.c builtins.h: builtins.def shell.h
|
||||
sh mkbuiltins $(MKB_NO_JOBS) . shell.h builtins.def
|
||||
|
||||
init.c: mkinit $(SRCS)
|
||||
./mkinit $(SRCS)
|
||||
|
||||
mkinit: mkinit.c
|
||||
$(CC) $(CFLAGS) mkinit.c -o $@
|
||||
|
@ -81,20 +114,8 @@ syntax.c syntax.h: mksyntax
|
|||
mksyntax: mksyntax.c parser.h
|
||||
$(CC) $(CFLAGS) mksyntax.c -o $@
|
||||
|
||||
bltin/operators.h: bltin/mkexpr bltin/binary_op bltin/unary_op
|
||||
cd bltin && sh mkexpr
|
||||
|
||||
bltin/echo.o: bltin/echo.c
|
||||
cd bltin && $(CC) -I.. $(CFLAGS) -c echo.c
|
||||
|
||||
bltin/expr.o: bltin/expr.c
|
||||
cd bltin && $(CC) -I.. $(CFLAGS) -c expr.c
|
||||
|
||||
bltin/operators.o: bltin/operators.c
|
||||
cd bltin && $(CC) -I.. $(CFLAGS) -c operators.c
|
||||
|
||||
bltin/regexp.o: bltin/regexp.c
|
||||
cd bltin && $(CC) -I.. $(CFLAGS) -c regexp.c
|
||||
bltin/operators.h: bltin/mkexpr bltin/unary_op bltin/binary_op
|
||||
cd bltin && sh mkexpr unary_op binary_op
|
||||
|
||||
# Dependencies you say? This will have to do.
|
||||
$(OBJS): error.h eval.h exec.h expand.h init.h input.h \
|
||||
|
@ -103,3 +124,6 @@ $(OBJS): error.h eval.h exec.h expand.h init.h input.h \
|
|||
builtins.h nodes.h signames.h syntax.h
|
||||
|
||||
bltin/expr.o bltin/operators.o: bltin/operators.h
|
||||
|
||||
#
|
||||
# $PchId: Makefile,v 1.4 2006/05/22 12:40:46 philip Exp $
|
||||
|
|
|
@ -1,4 +1,13 @@
|
|||
# @(#)TOUR 5.1 (Berkeley) 3/7/91
|
||||
# @(#)TOUR 8.1 (Berkeley) 5/31/93
|
||||
# $FreeBSD: src/bin/sh/TOUR,v 1.6 1999/08/27 23:15:07 peter Exp $
|
||||
|
||||
NOTE -- This is the original TOUR paper distributed with ash and
|
||||
does not represent the current state of the shell. It is provided anyway
|
||||
since it provides helpful information for how the shell is structured,
|
||||
but be warned that things have changed -- the current shell is
|
||||
still under development.
|
||||
|
||||
================================================================
|
||||
|
||||
A Tour through Ash
|
||||
|
||||
|
@ -20,7 +29,7 @@ programs is:
|
|||
mknodes nodetypes nodes.h nodes.c
|
||||
mksignames - signames.h signames.c
|
||||
mksyntax - syntax.h syntax.c
|
||||
mktokens - token.def
|
||||
mktokens - token.h
|
||||
bltin/mkexpr unary_op binary_op operators.h operators.c
|
||||
|
||||
There are undoubtedly too many of these. Mkinit searches all the
|
||||
|
@ -346,3 +355,6 @@ cause the preprocessor can't handle functions with a variable
|
|||
number of arguments. Defining DEBUG also causes the shell to
|
||||
generate a core dump if it is sent a quit signal. The tracing
|
||||
code is in show.c.
|
||||
|
||||
#
|
||||
# $PchId: TOUR,v 1.3 2006/03/31 11:33:46 philip Exp $
|
||||
|
|
265
commands/ash/alias.c
Normal file
265
commands/ash/alias.c
Normal file
|
@ -0,0 +1,265 @@
|
|||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* 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.
|
||||
* 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
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)alias.c 8.3 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/alias.c,v 1.18 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "shell.h"
|
||||
#include "input.h"
|
||||
#include "output.h"
|
||||
#include "error.h"
|
||||
#include "memalloc.h"
|
||||
#include "mystring.h"
|
||||
#include "alias.h"
|
||||
#include "options.h" /* XXX for argptr (should remove?) */
|
||||
#include "builtins.h"
|
||||
|
||||
#define ATABSIZE 39
|
||||
|
||||
STATIC struct alias *atab[ATABSIZE];
|
||||
|
||||
STATIC void setalias(char *, char *);
|
||||
STATIC int unalias(char *);
|
||||
STATIC struct alias **hashalias(char *);
|
||||
|
||||
STATIC
|
||||
void
|
||||
setalias(char *name, char *val)
|
||||
{
|
||||
struct alias *ap, **app;
|
||||
|
||||
app = hashalias(name);
|
||||
for (ap = *app; ap; ap = ap->next) {
|
||||
if (equal(name, ap->name)) {
|
||||
INTOFF;
|
||||
ckfree(ap->val);
|
||||
ap->val = savestr(val);
|
||||
INTON;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* not found */
|
||||
INTOFF;
|
||||
ap = ckmalloc(sizeof (struct alias));
|
||||
ap->name = savestr(name);
|
||||
/*
|
||||
* XXX - HACK: in order that the parser will not finish reading the
|
||||
* alias value off the input before processing the next alias, we
|
||||
* dummy up an extra space at the end of the alias. This is a crock
|
||||
* and should be re-thought. The idea (if you feel inclined to help)
|
||||
* is to avoid alias recursions. The mechanism used is: when
|
||||
* expanding an alias, the value of the alias is pushed back on the
|
||||
* input as a string and a pointer to the alias is stored with the
|
||||
* string. The alias is marked as being in use. When the input
|
||||
* routine finishes reading the string, it marks the alias not
|
||||
* in use. The problem is synchronization with the parser. Since
|
||||
* it reads ahead, the alias is marked not in use before the
|
||||
* resulting token(s) is next checked for further alias sub. The
|
||||
* H A C K is that we add a little fluff after the alias value
|
||||
* so that the string will not be exhausted. This is a good
|
||||
* idea ------- ***NOT***
|
||||
*/
|
||||
#ifdef notyet
|
||||
ap->val = savestr(val);
|
||||
#else /* hack */
|
||||
{
|
||||
int len = strlen(val);
|
||||
ap->val = ckmalloc(len + 2);
|
||||
memcpy(ap->val, val, len);
|
||||
ap->val[len] = ' '; /* fluff */
|
||||
ap->val[len+1] = '\0';
|
||||
}
|
||||
#endif
|
||||
ap->flag = 0;
|
||||
ap->next = *app;
|
||||
*app = ap;
|
||||
INTON;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
unalias(char *name)
|
||||
{
|
||||
struct alias *ap, **app;
|
||||
|
||||
app = hashalias(name);
|
||||
|
||||
for (ap = *app; ap; app = &(ap->next), ap = ap->next) {
|
||||
if (equal(name, ap->name)) {
|
||||
/*
|
||||
* if the alias is currently in use (i.e. its
|
||||
* buffer is being used by the input routine) we
|
||||
* just null out the name instead of freeing it.
|
||||
* We could clear it out later, but this situation
|
||||
* is so rare that it hardly seems worth it.
|
||||
*/
|
||||
if (ap->flag & ALIASINUSE)
|
||||
*ap->name = '\0';
|
||||
else {
|
||||
INTOFF;
|
||||
*app = ap->next;
|
||||
ckfree(ap->name);
|
||||
ckfree(ap->val);
|
||||
ckfree(ap);
|
||||
INTON;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
#ifdef mkinit
|
||||
INCLUDE "alias.h"
|
||||
SHELLPROC {
|
||||
rmaliases();
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
rmaliases(void)
|
||||
{
|
||||
struct alias *ap, *tmp;
|
||||
int i;
|
||||
|
||||
INTOFF;
|
||||
for (i = 0; i < ATABSIZE; i++) {
|
||||
ap = atab[i];
|
||||
atab[i] = NULL;
|
||||
while (ap) {
|
||||
ckfree(ap->name);
|
||||
ckfree(ap->val);
|
||||
tmp = ap;
|
||||
ap = ap->next;
|
||||
ckfree(tmp);
|
||||
}
|
||||
}
|
||||
INTON;
|
||||
}
|
||||
|
||||
struct alias *
|
||||
lookupalias(char *name, int check)
|
||||
{
|
||||
struct alias *ap = *hashalias(name);
|
||||
|
||||
for (; ap; ap = ap->next) {
|
||||
if (equal(name, ap->name)) {
|
||||
if (check && (ap->flag & ALIASINUSE))
|
||||
return (NULL);
|
||||
return (ap);
|
||||
}
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO - sort output
|
||||
*/
|
||||
int
|
||||
aliascmd(int argc, char **argv)
|
||||
{
|
||||
char *n, *v;
|
||||
int ret = 0;
|
||||
struct alias *ap;
|
||||
|
||||
if (argc == 1) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ATABSIZE; i++)
|
||||
for (ap = atab[i]; ap; ap = ap->next) {
|
||||
if (*ap->name != '\0') {
|
||||
out1fmt("alias %s=", ap->name);
|
||||
out1qstr(ap->val);
|
||||
out1c('\n');
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
while ((n = *++argv) != NULL) {
|
||||
if ((v = strchr(n+1, '=')) == NULL) /* n+1: funny ksh stuff */
|
||||
if ((ap = lookupalias(n, 0)) == NULL) {
|
||||
outfmt(out2, "alias: %s not found\n", n);
|
||||
ret = 1;
|
||||
} else {
|
||||
out1fmt("alias %s=", n);
|
||||
out1qstr(ap->val);
|
||||
out1c('\n');
|
||||
}
|
||||
else {
|
||||
*v++ = '\0';
|
||||
setalias(n, v);
|
||||
}
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
unaliascmd(int argc __unused, char **argv __unused)
|
||||
{
|
||||
int i;
|
||||
|
||||
while ((i = nextopt("a")) != '\0') {
|
||||
if (i == 'a') {
|
||||
rmaliases();
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
for (i = 0; *argptr; argptr++)
|
||||
i = unalias(*argptr);
|
||||
|
||||
return (i);
|
||||
}
|
||||
|
||||
STATIC struct alias **
|
||||
hashalias(char *p)
|
||||
{
|
||||
unsigned int hashval;
|
||||
|
||||
hashval = *p << 4;
|
||||
while (*p)
|
||||
hashval+= *p++;
|
||||
return &atab[hashval % ATABSIZE];
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: alias.c,v 1.5 2006/05/22 12:41:12 philip Exp $
|
||||
*/
|
52
commands/ash/alias.h
Normal file
52
commands/ash/alias.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* @(#)alias.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/alias.h,v 1.8 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
#define ALIASINUSE 1
|
||||
|
||||
struct alias {
|
||||
struct alias *next;
|
||||
char *name;
|
||||
char *val;
|
||||
int flag;
|
||||
};
|
||||
|
||||
struct alias *lookupalias(char *, int);
|
||||
int aliascmd(int, char **);
|
||||
int unaliascmd(int, char **);
|
||||
void rmaliases(void);
|
||||
|
||||
/*
|
||||
* $PchId: alias.h,v 1.4 2006/03/31 11:30:54 philip Exp $
|
||||
*/
|
39
commands/ash/arith.h
Normal file
39
commands/ash/arith.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*-
|
||||
* Copyright (c) 1995
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* @(#)arith.h 1.1 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/arith.h,v 1.9 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
int arith(char *);
|
||||
int arith_assign(char *, arith_t);
|
||||
int expcmd(int, char **);
|
||||
|
||||
/*
|
||||
* $PchId: arith.h,v 1.3 2006/03/31 11:25:25 philip Exp $
|
||||
*/
|
366
commands/ash/arith.y
Normal file
366
commands/ash/arith.y
Normal file
|
@ -0,0 +1,366 @@
|
|||
%{
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* 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.
|
||||
* 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 0
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/arith.y,v 1.19 2004/05/24 10:11:31 stefanf Exp $");
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "arith.h"
|
||||
#include "arith_lex.h"
|
||||
#include "var.h"
|
||||
%}
|
||||
%union {
|
||||
arith_t l_value;
|
||||
char* s_value;
|
||||
}
|
||||
%token <l_value> ARITH_NUM ARITH_LPAREN ARITH_RPAREN
|
||||
%token <s_value> ARITH_VAR
|
||||
|
||||
%type <l_value> expr
|
||||
%right ARITH_ASSIGN
|
||||
%right ARITH_ADDASSIGN ARITH_SUBASSIGN
|
||||
%right ARITH_MULASSIGN ARITH_DIVASSIGN ARITH_REMASSIGN
|
||||
%right ARITH_RSHASSIGN ARITH_LSHASSIGN
|
||||
%right ARITH_BANDASSIGN ARITH_BXORASSIGN ARITH_BORASSIGN
|
||||
%left ARITH_OR
|
||||
%left ARITH_AND
|
||||
%left ARITH_BOR
|
||||
%left ARITH_BXOR
|
||||
%left ARITH_BAND
|
||||
%left ARITH_EQ ARITH_NE
|
||||
%left ARITH_LT ARITH_GT ARITH_GE ARITH_LE
|
||||
%left ARITH_LSHIFT ARITH_RSHIFT
|
||||
%left ARITH_ADD ARITH_SUB
|
||||
%left ARITH_MUL ARITH_DIV ARITH_REM
|
||||
%left ARITH_UNARYMINUS ARITH_UNARYPLUS ARITH_NOT ARITH_BNOT
|
||||
%%
|
||||
|
||||
exp:
|
||||
expr
|
||||
{ return ($1); }
|
||||
;
|
||||
|
||||
expr:
|
||||
ARITH_LPAREN expr ARITH_RPAREN
|
||||
{ $$ = $2; } |
|
||||
expr ARITH_OR expr
|
||||
{ $$ = $1 ? $1 : $3 ? $3 : 0; } |
|
||||
expr ARITH_AND expr
|
||||
{ $$ = $1 ? ( $3 ? $3 : 0 ) : 0; } |
|
||||
expr ARITH_BOR expr
|
||||
{ $$ = $1 | $3; } |
|
||||
expr ARITH_BXOR expr
|
||||
{ $$ = $1 ^ $3; } |
|
||||
expr ARITH_BAND expr
|
||||
{ $$ = $1 & $3; } |
|
||||
expr ARITH_EQ expr
|
||||
{ $$ = $1 == $3; } |
|
||||
expr ARITH_GT expr
|
||||
{ $$ = $1 > $3; } |
|
||||
expr ARITH_GE expr
|
||||
{ $$ = $1 >= $3; } |
|
||||
expr ARITH_LT expr
|
||||
{ $$ = $1 < $3; } |
|
||||
expr ARITH_LE expr
|
||||
{ $$ = $1 <= $3; } |
|
||||
expr ARITH_NE expr
|
||||
{ $$ = $1 != $3; } |
|
||||
expr ARITH_LSHIFT expr
|
||||
{ $$ = $1 << $3; } |
|
||||
expr ARITH_RSHIFT expr
|
||||
{ $$ = $1 >> $3; } |
|
||||
expr ARITH_ADD expr
|
||||
{ $$ = $1 + $3; } |
|
||||
expr ARITH_SUB expr
|
||||
{ $$ = $1 - $3; } |
|
||||
expr ARITH_MUL expr
|
||||
{ $$ = $1 * $3; } |
|
||||
expr ARITH_DIV expr
|
||||
{
|
||||
if ($3 == 0)
|
||||
yyerror("division by zero");
|
||||
$$ = $1 / $3;
|
||||
} |
|
||||
expr ARITH_REM expr
|
||||
{
|
||||
if ($3 == 0)
|
||||
yyerror("division by zero");
|
||||
$$ = $1 % $3;
|
||||
} |
|
||||
ARITH_NOT expr
|
||||
{ $$ = !($2); } |
|
||||
ARITH_BNOT expr
|
||||
{ $$ = ~($2); } |
|
||||
ARITH_SUB expr %prec ARITH_UNARYMINUS
|
||||
{ $$ = -($2); } |
|
||||
ARITH_ADD expr %prec ARITH_UNARYPLUS
|
||||
{ $$ = $2; } |
|
||||
ARITH_NUM |
|
||||
ARITH_VAR
|
||||
{
|
||||
char *p;
|
||||
arith_t arith_val;
|
||||
char *str_val;
|
||||
|
||||
if (lookupvar($1) == NULL)
|
||||
setvarsafe($1, "0", 0);
|
||||
str_val = lookupvar($1);
|
||||
arith_val = strtoarith_t(str_val, &p, 0);
|
||||
/*
|
||||
* Conversion is successful only in case
|
||||
* we've converted _all_ characters.
|
||||
*/
|
||||
if (*p != '\0')
|
||||
yyerror("variable conversion error");
|
||||
$$ = arith_val;
|
||||
} |
|
||||
ARITH_VAR ARITH_ASSIGN expr
|
||||
{
|
||||
if (arith_assign($1, $3) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = $3;
|
||||
} |
|
||||
ARITH_VAR ARITH_ADDASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) + $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_SUBASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) - $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_MULASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) * $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_DIVASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
if ($3 == 0)
|
||||
yyerror("division by zero");
|
||||
|
||||
value = atoarith_t(lookupvar($1)) / $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_REMASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
if ($3 == 0)
|
||||
yyerror("division by zero");
|
||||
|
||||
value = atoarith_t(lookupvar($1)) % $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_RSHASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) >> $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_LSHASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) << $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_BANDASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) & $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_BXORASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) ^ $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_BORASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) | $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} ;
|
||||
%%
|
||||
#include "error.h"
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "builtins.h"
|
||||
|
||||
#define lstrlen(var) (3 + (2 + CHAR_BIT * sizeof((var))) / 3)
|
||||
|
||||
char *arith_buf, *arith_startbuf;
|
||||
|
||||
int yylex(void);
|
||||
int yyparse(void);
|
||||
|
||||
int
|
||||
arith_assign(char *name, arith_t value)
|
||||
{
|
||||
char *str;
|
||||
int ret;
|
||||
|
||||
str = (char *)ckmalloc(lstrlen(value));
|
||||
sprintf(str, ARITH_FORMAT_STR, value);
|
||||
ret = setvarsafe(name, str, 0);
|
||||
free(str);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
arith(char *s)
|
||||
{
|
||||
long result;
|
||||
|
||||
arith_buf = arith_startbuf = s;
|
||||
|
||||
INTOFF;
|
||||
result = yyparse();
|
||||
arith_lex_reset(); /* Reprime lex. */
|
||||
INTON;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
yyerror(char *s)
|
||||
{
|
||||
|
||||
yyerrok;
|
||||
yyclearin;
|
||||
arith_lex_reset(); /* Reprime lex. */
|
||||
error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* The exp(1) builtin.
|
||||
*/
|
||||
int
|
||||
expcmd(int argc, char **argv)
|
||||
{
|
||||
char *p;
|
||||
char *concat;
|
||||
char **ap;
|
||||
long i;
|
||||
|
||||
if (argc > 1) {
|
||||
p = argv[1];
|
||||
if (argc > 2) {
|
||||
/*
|
||||
* Concatenate arguments.
|
||||
*/
|
||||
STARTSTACKSTR(concat);
|
||||
ap = argv + 2;
|
||||
for (;;) {
|
||||
while (*p)
|
||||
STPUTC(*p++, concat);
|
||||
if ((p = *ap++) == NULL)
|
||||
break;
|
||||
STPUTC(' ', concat);
|
||||
}
|
||||
STPUTC('\0', concat);
|
||||
p = grabstackstr(concat);
|
||||
}
|
||||
} else
|
||||
p = "";
|
||||
|
||||
i = arith(p);
|
||||
|
||||
out1fmt("%ld\n", i);
|
||||
return !i;
|
||||
}
|
||||
|
||||
/*************************/
|
||||
#ifdef TEST_ARITH
|
||||
#include <stdio.h>
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
printf("%d\n", exp(argv[1]));
|
||||
}
|
||||
|
||||
error(char *s)
|
||||
{
|
||||
fprintf(stderr, "exp: %s\n", s);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $PchId: arith.y,v 1.6 2006/05/22 12:41:47 philip Exp $
|
||||
*/
|
12
commands/ash/arith_lex.h
Normal file
12
commands/ash/arith_lex.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
arith_lex.h
|
||||
|
||||
Created: July 1995 by Philip Homburg <philip@cs.vu.nl>
|
||||
*/
|
||||
|
||||
int yylex(void);
|
||||
void arith_lex_reset(void);
|
||||
|
||||
/*
|
||||
* $PchId: arith_lex.h,v 1.1 2001/05/18 19:57:55 philip Exp $
|
||||
*/
|
138
commands/ash/arith_lex.l
Normal file
138
commands/ash/arith_lex.l
Normal file
|
@ -0,0 +1,138 @@
|
|||
%{
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* 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.
|
||||
* 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 0
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)arith_lex.l 8.3 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/arith_lex.l,v 1.22 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "arith_lex.h"
|
||||
#include "arith_y.h"
|
||||
#include "error.h"
|
||||
#include "memalloc.h"
|
||||
#include "var.h"
|
||||
|
||||
extern char *arith_buf, *arith_startbuf;
|
||||
#undef YY_INPUT
|
||||
#define YY_INPUT(buf,result,max) \
|
||||
result = (*buf = *arith_buf++) ? 1 : YY_NULL;
|
||||
#define YY_NO_UNPUT
|
||||
%}
|
||||
|
||||
%%
|
||||
[ \t\n] { ; }
|
||||
|
||||
0x[a-fA-F0-9]+ {
|
||||
yylval.l_value = strtoarith_t(yytext, NULL, 16);
|
||||
return ARITH_NUM;
|
||||
}
|
||||
|
||||
0[0-7]+ {
|
||||
yylval.l_value = strtoarith_t(yytext, NULL, 8);
|
||||
return ARITH_NUM;
|
||||
}
|
||||
|
||||
[0-9]+ {
|
||||
yylval.l_value = strtoarith_t(yytext, NULL, 10);
|
||||
return ARITH_NUM;
|
||||
}
|
||||
|
||||
[A-Za-z][A-Za-z0-9_]* {
|
||||
/*
|
||||
* If variable doesn't exist, we should initialize
|
||||
* it to zero.
|
||||
*/
|
||||
char *temp;
|
||||
if (lookupvar(yytext) == NULL)
|
||||
setvarsafe(yytext, "0", 0);
|
||||
temp = (char *)ckmalloc(strlen(yytext) + 1);
|
||||
yylval.s_value = strcpy(temp, yytext);
|
||||
|
||||
return ARITH_VAR;
|
||||
}
|
||||
|
||||
"(" { return ARITH_LPAREN; }
|
||||
")" { return ARITH_RPAREN; }
|
||||
"||" { return ARITH_OR; }
|
||||
"&&" { return ARITH_AND; }
|
||||
"|" { return ARITH_BOR; }
|
||||
"^" { return ARITH_BXOR; }
|
||||
"&" { return ARITH_BAND; }
|
||||
"==" { return ARITH_EQ; }
|
||||
"!=" { return ARITH_NE; }
|
||||
">" { return ARITH_GT; }
|
||||
">=" { return ARITH_GE; }
|
||||
"<" { return ARITH_LT; }
|
||||
"<=" { return ARITH_LE; }
|
||||
"<<" { return ARITH_LSHIFT; }
|
||||
">>" { return ARITH_RSHIFT; }
|
||||
"*" { return ARITH_MUL; }
|
||||
"/" { return ARITH_DIV; }
|
||||
"%" { return ARITH_REM; }
|
||||
"+" { return ARITH_ADD; }
|
||||
"-" { return ARITH_SUB; }
|
||||
"~" { return ARITH_BNOT; }
|
||||
"!" { return ARITH_NOT; }
|
||||
"=" { return ARITH_ASSIGN; }
|
||||
"+=" { return ARITH_ADDASSIGN; }
|
||||
"-=" { return ARITH_SUBASSIGN; }
|
||||
"*=" { return ARITH_MULASSIGN; }
|
||||
"/=" { return ARITH_DIVASSIGN; }
|
||||
"%=" { return ARITH_REMASSIGN; }
|
||||
">>=" { return ARITH_RSHASSIGN; }
|
||||
"<<=" { return ARITH_LSHASSIGN; }
|
||||
"&=" { return ARITH_BANDASSIGN; }
|
||||
"^=" { return ARITH_BXORASSIGN; }
|
||||
"|=" { return ARITH_BORASSIGN; }
|
||||
. {
|
||||
error("arith: syntax error: \"%s\"\n", arith_startbuf);
|
||||
}
|
||||
%%
|
||||
|
||||
void
|
||||
arith_lex_reset(void)
|
||||
{
|
||||
YY_NEW_FILE;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: arith_lex.l,v 1.5 2006/04/10 14:35:29 philip Exp $
|
||||
*/
|
|
@ -1,26 +1,78 @@
|
|||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* @(#)bltin.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/bltin/bltin.h,v 1.13 2004/04/06 20:06:53 markm Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is included by programs which are optionally built into the
|
||||
* shell. If SHELL is defined, we try to map the standard UNIX library
|
||||
* routines to ash routines using defines.
|
||||
*
|
||||
* Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
|
||||
* This file is part of ash, which is distributed under the terms specified
|
||||
* by the Ash General Public License. See the file named LICENSE.
|
||||
*/
|
||||
|
||||
#include "../shell.h"
|
||||
#include "../mystring.h"
|
||||
#ifdef SHELL
|
||||
#include "builtins.h"
|
||||
#include "../output.h"
|
||||
#undef stdout
|
||||
#define stdout out1
|
||||
#undef stderr
|
||||
#define stderr out2
|
||||
#define printf out1fmt
|
||||
#undef putc
|
||||
#define putc(c, file) outc(c, file)
|
||||
#undef putchar
|
||||
#define putchar(c) out1c(c)
|
||||
#define fprintf outfmt
|
||||
#define fputs outstr
|
||||
#define fflush flushout
|
||||
#define INITARGS(argv)
|
||||
#define warnx1(a, b, c) { \
|
||||
char buf[64]; \
|
||||
(void)snprintf(buf, sizeof(buf), a); \
|
||||
error("%s", buf); \
|
||||
}
|
||||
#define warnx2(a, b, c) { \
|
||||
char buf[64]; \
|
||||
(void)snprintf(buf, sizeof(buf), a, b); \
|
||||
error("%s", buf); \
|
||||
}
|
||||
#define warnx3(a, b, c) { \
|
||||
char buf[64]; \
|
||||
(void)snprintf(buf, sizeof(buf), a, b, c); \
|
||||
error("%s", buf); \
|
||||
}
|
||||
|
||||
#else
|
||||
#undef NULL
|
||||
#include <stdio.h>
|
||||
|
@ -28,13 +80,12 @@
|
|||
#define INITARGS(argv) if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
pointer stalloc(int);
|
||||
void error(char *, ...);
|
||||
#else
|
||||
pointer stalloc();
|
||||
void error();
|
||||
#endif
|
||||
void error(const char *, ...);
|
||||
|
||||
|
||||
extern char *commandname;
|
||||
|
||||
/*
|
||||
* $PchId: bltin.h,v 1.4 2006/03/29 11:39:00 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,74 +1,126 @@
|
|||
/*
|
||||
* Echo command.
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
|
||||
* This file is part of ash, which is distributed under the terms specified
|
||||
* by the Ash General Public License. See the file named LICENSE.
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* @(#)echo.c 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
#define main echocmd
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/bltin/echo.c,v 1.14 2004/04/06 20:06:53 markm Exp $");
|
||||
*/
|
||||
|
||||
/*
|
||||
* Echo command.
|
||||
*/
|
||||
|
||||
#ifdef __minix
|
||||
#define MINIX
|
||||
#endif
|
||||
|
||||
#include "bltin.h"
|
||||
|
||||
#ifndef MINIX
|
||||
/* #define eflag 1 */
|
||||
#else
|
||||
#undef eflag
|
||||
|
||||
|
||||
main(argc, argv) char **argv; {
|
||||
register char **ap;
|
||||
register char *p;
|
||||
register char c;
|
||||
int count;
|
||||
int nflag = 0;
|
||||
#ifndef eflag
|
||||
int eflag = 0;
|
||||
#endif
|
||||
|
||||
ap = argv;
|
||||
if (argc)
|
||||
ap++;
|
||||
if ((p = *ap) != NULL) {
|
||||
if (equal(p, "--")) {
|
||||
ap++;
|
||||
}
|
||||
if (equal(p, "-n")) {
|
||||
nflag++;
|
||||
ap++;
|
||||
} else if (equal(p, "-e")) {
|
||||
int
|
||||
echocmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char **ap;
|
||||
char *p;
|
||||
char c;
|
||||
int count;
|
||||
int nflag = 0;
|
||||
#ifndef eflag
|
||||
eflag++;
|
||||
int eflag = 0;
|
||||
#endif
|
||||
ap++;
|
||||
}
|
||||
}
|
||||
while ((p = *ap++) != NULL) {
|
||||
while ((c = *p++) != '\0') {
|
||||
if (c == '\\' && eflag) {
|
||||
switch (*p++) {
|
||||
case 'b': c = '\b'; break;
|
||||
case 'c': return 0; /* exit */
|
||||
case 'f': c = '\f'; break;
|
||||
case 'n': c = '\n'; break;
|
||||
case 'r': c = '\r'; break;
|
||||
case 't': c = '\t'; break;
|
||||
case 'v': c = '\v'; break;
|
||||
case '\\': break; /* c = '\\' */
|
||||
case '0':
|
||||
c = 0;
|
||||
count = 3;
|
||||
while (--count >= 0 && (unsigned)(*p - '0') < 8)
|
||||
c = (c << 3) + (*p++ - '0');
|
||||
break;
|
||||
default:
|
||||
p--;
|
||||
break;
|
||||
|
||||
ap = argv;
|
||||
if (argc)
|
||||
ap++;
|
||||
if ((p = *ap) != NULL) {
|
||||
#ifdef MINIX
|
||||
if (equal(p, "--")) {
|
||||
ap++;
|
||||
}
|
||||
#endif
|
||||
if (equal(p, "-n")) {
|
||||
nflag++;
|
||||
ap++;
|
||||
} else if (equal(p, "-e")) {
|
||||
#ifndef eflag
|
||||
eflag++;
|
||||
#endif
|
||||
ap++;
|
||||
}
|
||||
}
|
||||
while ((p = *ap++) != NULL) {
|
||||
while ((c = *p++) != '\0') {
|
||||
if (c == '\\' && eflag) {
|
||||
switch (*p++) {
|
||||
case 'a': c = '\a'; break;
|
||||
case 'b': c = '\b'; break;
|
||||
case 'c': return 0; /* exit */
|
||||
case 'e': c = '\033'; break;
|
||||
case 'f': c = '\f'; break;
|
||||
case 'n': c = '\n'; break;
|
||||
case 'r': c = '\r'; break;
|
||||
case 't': c = '\t'; break;
|
||||
case 'v': c = '\v'; break;
|
||||
case '\\': break; /* c = '\\' */
|
||||
case '0':
|
||||
c = 0;
|
||||
count = 3;
|
||||
while (--count >= 0 && (unsigned)(*p - '0') < 8)
|
||||
c = (c << 3) + (*p++ - '0');
|
||||
break;
|
||||
default:
|
||||
p--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
putchar(c);
|
||||
}
|
||||
if (*ap)
|
||||
putchar(' ');
|
||||
}
|
||||
if (! nflag)
|
||||
putchar('\n');
|
||||
return 0;
|
||||
putchar(c);
|
||||
}
|
||||
if (*ap)
|
||||
putchar(' ');
|
||||
}
|
||||
if (! nflag)
|
||||
putchar('\n');
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: echo.c,v 1.5 2006/05/23 12:05:56 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -7,17 +7,14 @@
|
|||
*/
|
||||
|
||||
|
||||
#define main exprcmd
|
||||
|
||||
#include "bltin.h"
|
||||
#include "operators.h"
|
||||
#include <regex.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef S_ISLNK
|
||||
#define lstat stat
|
||||
#define S_ISLNK(mode) (0)
|
||||
#endif
|
||||
|
||||
#define STACKSIZE 12
|
||||
#define NESTINCR 16
|
||||
|
@ -50,7 +47,6 @@ struct operator {
|
|||
|
||||
|
||||
struct filestat {
|
||||
int op; /* OP_FILE or OP_LFILE */
|
||||
char *name; /* name of file */
|
||||
int rcode; /* return code from stat */
|
||||
struct stat stat; /* status info on file */
|
||||
|
@ -63,24 +59,18 @@ extern short number_parens; /* number of \( \) pairs */
|
|||
|
||||
|
||||
#ifdef __STDC__
|
||||
int expr_is_false(struct value *);
|
||||
void expr_operator(int, struct value *, struct filestat *);
|
||||
int lookup_op(char *, char *const*);
|
||||
char *re_compile(char *); /* defined in regexp.c */
|
||||
int re_match(char *, char *); /* defined in regexp.c */
|
||||
long atol(const char *);
|
||||
static int expr_is_false(struct value *);
|
||||
static void expr_operator(int, struct value *, struct filestat *);
|
||||
static int lookup_op(char *, char *const*);
|
||||
#else
|
||||
int expr_is_false();
|
||||
void expr_operator();
|
||||
int lookup_op();
|
||||
char *re_compile(); /* defined in regexp.c */
|
||||
int re_match(); /* defined in regexp.c */
|
||||
long atol();
|
||||
static int expr_is_false();
|
||||
static void expr_operator();
|
||||
static int lookup_op();
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
main(argc, argv) char **argv; {
|
||||
exprcmd(argc, argv) char **argv; {
|
||||
char **ap;
|
||||
char *opname;
|
||||
char c;
|
||||
|
@ -146,6 +136,13 @@ overflow: error("Expression too complex");
|
|||
continue;
|
||||
|
||||
} else {
|
||||
if (opname[0] == '\'') {
|
||||
for (p = opname ; *++p != '\0' ; );
|
||||
if (--p > opname && *p == '\'') {
|
||||
*p = '\0';
|
||||
opname++;
|
||||
}
|
||||
}
|
||||
valsp->type = STRING;
|
||||
valsp->u.string = opname;
|
||||
valsp++;
|
||||
|
@ -193,19 +190,11 @@ overflow: error("Expression too complex");
|
|||
valsp->u.string = "";
|
||||
}
|
||||
valsp->type = STRING;
|
||||
if (c >= OP_FILE
|
||||
&& (fs.op != c
|
||||
|| fs.name == NULL
|
||||
if (c == OP_FILE
|
||||
&& (fs.name == NULL
|
||||
|| ! equal(fs.name, valsp->u.string))) {
|
||||
fs.op = c;
|
||||
fs.name = valsp->u.string;
|
||||
if (c == OP_FILE) {
|
||||
fs.rcode = stat(valsp->u.string,
|
||||
&fs.stat);
|
||||
} else {
|
||||
fs.rcode = lstat(valsp->u.string,
|
||||
&fs.stat);
|
||||
}
|
||||
fs.rcode = stat(valsp->u.string, &fs.stat);
|
||||
}
|
||||
}
|
||||
if (binary < FIRST_BINARY_OP)
|
||||
|
@ -250,7 +239,7 @@ done:
|
|||
}
|
||||
|
||||
|
||||
int
|
||||
static int
|
||||
expr_is_false(val)
|
||||
struct value *val;
|
||||
{
|
||||
|
@ -274,14 +263,16 @@ expr_is_false(val)
|
|||
* to stat, to avoid repeated stat calls on the same file.
|
||||
*/
|
||||
|
||||
void
|
||||
static void
|
||||
expr_operator(op, sp, fs)
|
||||
int op;
|
||||
struct value *sp;
|
||||
struct filestat *fs;
|
||||
{
|
||||
int i;
|
||||
int i, r;
|
||||
struct stat st1, st2;
|
||||
regex_t pat;
|
||||
regmatch_t rm[2];
|
||||
|
||||
switch (op) {
|
||||
case NOT:
|
||||
|
@ -343,16 +334,16 @@ filebit:
|
|||
if (fs->stat.st_mode & i && fs->rcode >= 0)
|
||||
goto true;
|
||||
goto false;
|
||||
case ISSLINK:
|
||||
if (lstat(fs->name, &st1) == -1)
|
||||
goto false;
|
||||
if (S_ISLNK(st1.st_mode))
|
||||
goto true;
|
||||
goto false;
|
||||
case ISSIZE:
|
||||
sp->u.num = fs->rcode >= 0? fs->stat.st_size : 0L;
|
||||
sp->type = INTEGER;
|
||||
break;
|
||||
case ISLINK1:
|
||||
case ISLINK2:
|
||||
if (S_ISLNK(fs->stat.st_mode) && fs->rcode >= 0)
|
||||
goto true;
|
||||
fs->op = OP_FILE; /* not a symlink, so expect a -d or so next */
|
||||
goto false;
|
||||
case NEWER:
|
||||
if (stat(sp->u.string, &st1) != 0) {
|
||||
sp->u.num = 0;
|
||||
|
@ -439,19 +430,21 @@ filebit:
|
|||
break;
|
||||
case MATCHPAT:
|
||||
{
|
||||
char *pat;
|
||||
|
||||
pat = re_compile((sp + 1)->u.string);
|
||||
if (re_match(pat, sp->u.string)) {
|
||||
if (number_parens > 0) {
|
||||
sp->u.string = match_begin[1];
|
||||
sp->u.string[match_length[1]] = '\0';
|
||||
r = regcomp(&pat, (sp + 1)->u.string, 0);
|
||||
if (r)
|
||||
error("Bad regular expression");
|
||||
if (regexec(&pat, sp->u.string, 2, rm, 0) == 0 &&
|
||||
rm[0].rm_so == 0)
|
||||
{
|
||||
if (pat.re_nsub > 0) {
|
||||
sp->u.string[rm[1].rm_eo] = '\0';
|
||||
sp->u.string = sp->u.string+rm[1].rm_so;
|
||||
} else {
|
||||
sp->u.num = match_length[0];
|
||||
sp->u.num = rm[0].rm_eo;
|
||||
sp->type = INTEGER;
|
||||
}
|
||||
} else {
|
||||
if (number_parens > 0) {
|
||||
if (pat.re_nsub > 0) {
|
||||
sp->u.string[0] = '\0';
|
||||
} else {
|
||||
sp->u.num = 0;
|
||||
|
@ -464,7 +457,7 @@ filebit:
|
|||
}
|
||||
|
||||
|
||||
int
|
||||
static int
|
||||
lookup_op(name, table)
|
||||
char *name;
|
||||
char *const*table;
|
||||
|
|
|
@ -5,21 +5,28 @@
|
|||
|
||||
# All calls to awk removed, because Minix bawk is deficient. (kjb)
|
||||
|
||||
if [ $# -ne 2 ]
|
||||
then
|
||||
echo "Usage: $0 <unary_op> <binary_op>" >&2
|
||||
exit 1
|
||||
fi
|
||||
unary_op="$1"
|
||||
binary_op="$2"
|
||||
|
||||
exec > operators.h
|
||||
i=0
|
||||
sed -e '/^[^#]/!d' unary_op binary_op | while read line
|
||||
sed -e '/^[^#]/!d' "$unary_op" "$binary_op" | while read line
|
||||
do
|
||||
set -$- $line
|
||||
echo "#define $1 $i"
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
echo
|
||||
echo "#define FIRST_BINARY_OP" `sed -e '/^[^#]/!d' unary_op | wc -l`
|
||||
echo "#define FIRST_BINARY_OP" `sed -e '/^[^#]/!d' "$unary_op" | wc -l`
|
||||
echo '
|
||||
#define OP_INT 1 /* arguments to operator are integer */
|
||||
#define OP_STRING 2 /* arguments to operator are string */
|
||||
#define OP_FILE 3 /* argument is a file name */
|
||||
#define OP_LFILE 4 /* argument is a file name of a symlink? */
|
||||
|
||||
extern char *const unary_op[];
|
||||
extern char *const binary_op[];
|
||||
|
@ -31,14 +38,15 @@ echo '/*
|
|||
* Operators used in the expr/test command.
|
||||
*/
|
||||
|
||||
#include "../shell.h"
|
||||
#include <stddef.h>
|
||||
#include "shell.h"
|
||||
#include "operators.h"
|
||||
|
||||
char *const unary_op[] = {'
|
||||
sed -e '/^[^#]/!d
|
||||
s/[ ][ ]*/ /g
|
||||
s/^[^ ][^ ]* \([^ ][^ ]*\).*/ "\1",/
|
||||
' unary_op
|
||||
' "$unary_op"
|
||||
echo ' NULL
|
||||
};
|
||||
|
||||
|
@ -46,7 +54,7 @@ char *const binary_op[] = {'
|
|||
sed -e '/^[^#]/!d
|
||||
s/[ ][ ]*/ /g
|
||||
s/^[^ ][^ ]* \([^ ][^ ]*\).*/ "\1",/
|
||||
' binary_op
|
||||
' "$binary_op"
|
||||
echo ' NULL
|
||||
};
|
||||
|
||||
|
@ -54,7 +62,7 @@ const char op_priority[] = {'
|
|||
sed -e '/^[^#]/!d
|
||||
s/[ ][ ]*/ /g
|
||||
s/^[^ ][^ ]* [^ ][^ ]* \([^ ][^ ]*\).*/ \1,/
|
||||
' unary_op binary_op
|
||||
' "$unary_op" "$binary_op"
|
||||
echo '};
|
||||
|
||||
const char op_argflag[] = {'
|
||||
|
@ -62,5 +70,5 @@ sed -e '/^[^#]/!d
|
|||
s/[ ][ ]*/ /g
|
||||
s/^[^ ][^ ]* [^ ][^ ]* [^ ][^ ]*$/& 0/
|
||||
s/^[^ ][^ ]* [^ ][^ ]* [^ ][^ ]* \([^ ][^ ]*\)/ \1,/
|
||||
' unary_op binary_op
|
||||
' "$unary_op" "$binary_op"
|
||||
echo '};'
|
||||
|
|
8
commands/ash/bltin/myregexp.h
Normal file
8
commands/ash/bltin/myregexp.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
myregexp.h
|
||||
|
||||
Created: July 1995 by Philip Homburg <philip@cs.vu.nl>
|
||||
*/
|
||||
|
||||
char *re_compile(char *pattern);
|
||||
int re_match(char *pattern, char *string);
|
|
@ -8,7 +8,9 @@
|
|||
*/
|
||||
|
||||
#include "bltin.h"
|
||||
#include "myregexp.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define RE_END 0 /* end of regular expression */
|
||||
#define RE_LITERAL 1 /* normal character follows */
|
||||
|
@ -27,7 +29,7 @@
|
|||
char *match_begin[10];
|
||||
short match_length[10];
|
||||
short number_parens;
|
||||
static int match();
|
||||
static int match(char *pattern, char *string);
|
||||
|
||||
|
||||
|
||||
|
@ -48,7 +50,6 @@ re_compile(pattern)
|
|||
char stack[10];
|
||||
int paren_num;
|
||||
int i;
|
||||
char *malloc();
|
||||
|
||||
p = pattern;
|
||||
if (*p == '^')
|
||||
|
@ -176,6 +177,7 @@ out:
|
|||
|
||||
|
||||
|
||||
int
|
||||
re_match(pattern, string)
|
||||
char *pattern;
|
||||
char *string;
|
||||
|
@ -246,7 +248,7 @@ ccl:
|
|||
p++;
|
||||
}
|
||||
p++;
|
||||
if (found == negate || c == 0)
|
||||
if (found == negate)
|
||||
goto bad;
|
||||
break;
|
||||
case RE_LP:
|
||||
|
|
|
@ -16,9 +16,8 @@ ISFIFO -p 12 OP_FILE
|
|||
ISSETUID -u 12 OP_FILE
|
||||
ISSETGID -g 12 OP_FILE
|
||||
ISSTICKY -k 12 OP_FILE
|
||||
ISSLINK -h 12 OP_FILE
|
||||
ISSIZE -s 12 OP_FILE
|
||||
ISLINK1 -h 12 OP_LFILE
|
||||
ISLINK2 -L 12 OP_LFILE
|
||||
ISTTY -t 12 OP_INT
|
||||
NULSTR -z 12 OP_STRING
|
||||
STRLEN -n 12 OP_STRING
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/sh
|
||||
make clean
|
||||
make && make install
|
21
commands/ash/builtins.table → commands/ash/builtins
Executable file → Normal file
21
commands/ash/builtins.table → commands/ash/builtins
Executable file → Normal file
|
@ -1,7 +1,7 @@
|
|||
#!/bin/sh -
|
||||
#
|
||||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
|
@ -34,19 +34,21 @@
|
|||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)builtins 5.1 (Berkeley) 3/7/91
|
||||
# @(#)builtins 8.1 (Berkeley) 5/31/93
|
||||
|
||||
#
|
||||
# This file lists all the builtin commands. The first column is the name
|
||||
# of a C routine. The -j flag, if present, specifies that this command
|
||||
# is to be excluded from systems without job control. The rest of the line
|
||||
# specifies the command name or names used to run the command. The entry
|
||||
# for nullcmd, which is run when the user does not specify a command, must
|
||||
# for bltincmd, which is run when the user does not specify a command, must
|
||||
# come first.
|
||||
#
|
||||
# Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
|
||||
# This file is part of ash, which is distributed under the terms specified
|
||||
# by the Ash General Public License. See the file named LICENSE.
|
||||
#
|
||||
# NOTE: bltincmd must come first!
|
||||
|
||||
bltincmd command
|
||||
#alloccmd alloc
|
||||
|
@ -59,17 +61,19 @@ echocmd echo
|
|||
evalcmd eval
|
||||
execcmd exec
|
||||
exitcmd exit
|
||||
expcmd exp let
|
||||
exportcmd export readonly
|
||||
exprcmd expr test [
|
||||
#exprcmd expr test [
|
||||
histcmd fc
|
||||
fgcmd -j fg
|
||||
getoptscmd getopts
|
||||
hashcmd hash
|
||||
jobidcmd jobid
|
||||
jobscmd jobs
|
||||
#lccmd lc
|
||||
#linecmd line
|
||||
localcmd local
|
||||
#nlechocmd nlecho
|
||||
printfcmd printf
|
||||
pwdcmd pwd
|
||||
readcmd read
|
||||
returncmd return
|
||||
|
@ -77,7 +81,10 @@ setcmd set
|
|||
setvarcmd setvar
|
||||
shiftcmd shift
|
||||
trapcmd trap
|
||||
truecmd : true false
|
||||
truecmd : true
|
||||
umaskcmd umask
|
||||
unaliascmd unalias
|
||||
unsetcmd unset
|
||||
waitcmd wait
|
||||
#foocmd foo
|
||||
aliascmd alias
|
94
commands/ash/builtins.def
Normal file
94
commands/ash/builtins.def
Normal file
|
@ -0,0 +1,94 @@
|
|||
#!/bin/sh -
|
||||
#
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# 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.
|
||||
# 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.
|
||||
#
|
||||
# @(#)builtins.def 8.4 (Berkeley) 5/4/95
|
||||
# $FreeBSD: src/bin/sh/builtins.def,v 1.14 2004/04/06 20:06:51 markm Exp $
|
||||
|
||||
#
|
||||
# This file lists all the builtin commands. The first column is the name
|
||||
# of a C routine. The -j flag, if present, specifies that this command
|
||||
# is to be excluded from systems without job control, and the -h flag,
|
||||
# if present specifies that this command is to be excluded from systems
|
||||
# based on the NO_HISTORY compile-time symbol. The rest of the line
|
||||
# specifies the command name or names used to run the command. The entry
|
||||
# for bltincmd, which is run when the user does not specify a command, must
|
||||
# come first.
|
||||
#
|
||||
# NOTE: bltincmd must come first!
|
||||
|
||||
bltincmd builtin
|
||||
commandcmd command
|
||||
#alloccmd alloc
|
||||
bgcmd -j bg
|
||||
breakcmd break continue
|
||||
#catfcmd catf
|
||||
cdcmd cd chdir
|
||||
dotcmd .
|
||||
echocmd echo
|
||||
evalcmd eval
|
||||
execcmd exec
|
||||
exitcmd exit
|
||||
expcmd exp let
|
||||
exportcmd export readonly
|
||||
exprcmd expr test [
|
||||
falsecmd false
|
||||
histcmd -h fc
|
||||
fgcmd -j fg
|
||||
getoptscmd getopts
|
||||
hashcmd hash
|
||||
jobidcmd jobid
|
||||
jobscmd jobs
|
||||
#linecmd line
|
||||
localcmd local
|
||||
#nlechocmd nlecho
|
||||
#printfcmd printf
|
||||
pwdcmd pwd
|
||||
readcmd read
|
||||
returncmd return
|
||||
setcmd set
|
||||
setvarcmd setvar
|
||||
shiftcmd shift
|
||||
trapcmd trap
|
||||
truecmd : true
|
||||
typecmd type
|
||||
umaskcmd umask
|
||||
unaliascmd unalias
|
||||
unsetcmd unset
|
||||
waitcmd wait
|
||||
#foocmd foo
|
||||
aliascmd alias
|
||||
ulimitcmd ulimit
|
||||
bindcmd bind
|
||||
wordexpcmd wordexp
|
||||
|
||||
#
|
||||
# $PchId: builtins.def,v 1.5 2006/03/31 10:50:57 philip Exp $
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -35,8 +31,22 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)cd.c 5.2 (Berkeley) 3/13/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)cd.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/cd.c,v 1.34 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
/*
|
||||
* The cd and pwd commands.
|
||||
|
@ -50,115 +60,124 @@ static char sccsid[] = "@(#)cd.c 5.2 (Berkeley) 3/13/91";
|
|||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "exec.h"
|
||||
#include "redir.h"
|
||||
#include "mystring.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include "builtins.h"
|
||||
#include "show.h"
|
||||
#include "cd.h"
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
STATIC int cdlogical(char *);
|
||||
STATIC int cdphysical(char *);
|
||||
STATIC int docd(char *, int, int);
|
||||
STATIC void updatepwd(char *);
|
||||
STATIC void getpwd(void);
|
||||
STATIC char *getcomponent(void);
|
||||
#else
|
||||
STATIC int docd();
|
||||
STATIC void updatepwd();
|
||||
STATIC void getpwd();
|
||||
STATIC char *getcomponent();
|
||||
#endif
|
||||
STATIC int updatepwd(char *);
|
||||
|
||||
|
||||
char *curdir; /* current working directory */
|
||||
STATIC char *curdir = NULL; /* current working directory */
|
||||
STATIC char *prevdir; /* previous working directory */
|
||||
STATIC char *cdcomppath;
|
||||
|
||||
#if UDIR || TILDE
|
||||
extern int didudir; /* set if /u/logname or ~logname expanded */
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
cdcmd(argc, argv) char **argv; {
|
||||
cdcmd(int argc, char **argv)
|
||||
{
|
||||
char *dest;
|
||||
char *path;
|
||||
char *p;
|
||||
struct stat statb;
|
||||
char *padvance();
|
||||
int tohome= 0;
|
||||
int ch, phys, print = 0;
|
||||
|
||||
nextopt(nullstr);
|
||||
if ((dest = *argptr) == NULL) {
|
||||
if ((dest = bltinlookup("HOME", 1)) == NULL)
|
||||
error("HOME not set");
|
||||
tohome = 1;
|
||||
optreset = 1; optind = 1; opterr = 0; /* initialize getopt */
|
||||
phys = Pflag;
|
||||
while ((ch = getopt(argc, argv, "LP")) != -1) {
|
||||
switch (ch) {
|
||||
case 'L':
|
||||
phys = 0;
|
||||
break;
|
||||
case 'P':
|
||||
phys = 1;
|
||||
break;
|
||||
default:
|
||||
error("unknown option: -%c", optopt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc > 1)
|
||||
error("too many arguments");
|
||||
|
||||
if ((dest = *argv) == NULL && (dest = bltinlookup("HOME", 1)) == NULL)
|
||||
error("HOME not set");
|
||||
if (*dest == '\0')
|
||||
dest = ".";
|
||||
if (dest[0] == '-' && dest[1] == '\0') {
|
||||
dest = prevdir ? prevdir : curdir;
|
||||
if (dest)
|
||||
print = 1;
|
||||
else
|
||||
dest = ".";
|
||||
}
|
||||
if (*dest == '/' || (path = bltinlookup("CDPATH", 1)) == NULL)
|
||||
path = nullstr;
|
||||
while ((p = padvance(&path, dest)) != NULL) {
|
||||
if (stat(p, &statb) >= 0
|
||||
&& (statb.st_mode & S_IFMT) == S_IFDIR
|
||||
&& docd(p, strcmp(p, dest), tohome) >= 0)
|
||||
return 0;
|
||||
if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
|
||||
if (!print) {
|
||||
/*
|
||||
* XXX - rethink
|
||||
*/
|
||||
if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
|
||||
p += 2;
|
||||
print = strcmp(p, dest);
|
||||
}
|
||||
if (docd(p, print, phys) >= 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
error("can't cd to %s", dest);
|
||||
/*NOTREACHED*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Actually do the chdir. If the name refers to symbolic links, we
|
||||
* compute the actual directory name before doing the cd. In an
|
||||
* interactive shell, print the directory name if "print" is nonzero
|
||||
* or if the name refers to a symbolic link. We also print the name
|
||||
* if "/u/logname" was expanded in it, since this is similar to a
|
||||
* symbolic link. (The check for this breaks if the user gives the
|
||||
* cd command some additional, unused arguments.)
|
||||
* Actually change the directory. In an interactive shell, print the
|
||||
* directory name if "print" is nonzero.
|
||||
*/
|
||||
|
||||
#if SYMLINKS == 0
|
||||
STATIC int
|
||||
docd(dest, print, tohome)
|
||||
char *dest;
|
||||
{
|
||||
#if UDIR || TILDE
|
||||
if (didudir)
|
||||
print = 1;
|
||||
#endif
|
||||
INTOFF;
|
||||
if (chdir(dest) < 0) {
|
||||
INTON;
|
||||
return -1;
|
||||
}
|
||||
updatepwd(dest);
|
||||
INTON;
|
||||
if (print && iflag)
|
||||
out1fmt("%s\n", stackblock());
|
||||
docd(char *dest, int print, int phys)
|
||||
{
|
||||
|
||||
TRACE(("docd(\"%s\", %d, %d) called\n", dest, print, phys));
|
||||
|
||||
/* If logical cd fails, fall back to physical. */
|
||||
if ((phys || cdlogical(dest) < 0) && cdphysical(dest) < 0)
|
||||
return (-1);
|
||||
|
||||
if (print && iflag && curdir)
|
||||
out1fmt("%s\n", curdir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
|
||||
|
||||
STATIC int
|
||||
docd(dest, print, tohome)
|
||||
char *dest;
|
||||
{
|
||||
register char *p;
|
||||
register char *q;
|
||||
char *symlink;
|
||||
cdlogical(char *dest)
|
||||
{
|
||||
char *p;
|
||||
char *q;
|
||||
char *component;
|
||||
struct stat statb;
|
||||
int first;
|
||||
int i;
|
||||
int badstat;
|
||||
|
||||
TRACE(("docd(\"%s\", %d, %d) called\n", dest, print, tohome));
|
||||
#if UDIR || TILDE
|
||||
if (didudir)
|
||||
print = 1;
|
||||
#endif
|
||||
|
||||
top:
|
||||
cdcomppath = dest;
|
||||
/*
|
||||
* Check each component of the path. If we find a symlink or
|
||||
* something we can't stat, clear curdir to force a getcwd()
|
||||
* next time we get the value of the current directory.
|
||||
*/
|
||||
badstat = 0;
|
||||
cdcomppath = stalloc(strlen(dest) + 1);
|
||||
scopy(dest, cdcomppath);
|
||||
STARTSTACKSTR(p);
|
||||
if (*dest == '/') {
|
||||
STPUTC('/', p);
|
||||
|
@ -166,7 +185,7 @@ top:
|
|||
}
|
||||
first = 1;
|
||||
while ((q = getcomponent()) != NULL) {
|
||||
if (q[0] == '\0' || q[0] == '.' && q[1] == '\0')
|
||||
if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0'))
|
||||
continue;
|
||||
if (! first)
|
||||
STPUTC('/', p);
|
||||
|
@ -177,71 +196,42 @@ top:
|
|||
if (equal(component, ".."))
|
||||
continue;
|
||||
STACKSTRNUL(p);
|
||||
if (lstat(stackblock(), &statb) < 0)
|
||||
error("lstat %s failed", stackblock());
|
||||
if ((statb.st_mode & S_IFMT) != S_IFLNK)
|
||||
continue;
|
||||
|
||||
/* Hit a symbolic link. We have to start all over again. */
|
||||
print = 1;
|
||||
STPUTC('\0', p);
|
||||
symlink = grabstackstr(p);
|
||||
i = (int)statb.st_size + 2; /* 2 for '/' and '\0' */
|
||||
if (cdcomppath != NULL)
|
||||
i += strlen(cdcomppath);
|
||||
p = stalloc(i);
|
||||
if (readlink(symlink, p, (int)statb.st_size) < 0) {
|
||||
error("readlink %s failed", stackblock());
|
||||
if (lstat(stackblock(), &statb) < 0) {
|
||||
badstat = 1;
|
||||
break;
|
||||
}
|
||||
if (cdcomppath != NULL) {
|
||||
p[(int)statb.st_size] = '/';
|
||||
scopy(cdcomppath, p + (int)statb.st_size + 1);
|
||||
} else {
|
||||
p[(int)statb.st_size] = '\0';
|
||||
}
|
||||
if (p[0] != '/') { /* relative path name */
|
||||
char *r;
|
||||
q = r = symlink;
|
||||
while (*q) {
|
||||
if (*q++ == '/')
|
||||
r = q;
|
||||
}
|
||||
*r = '\0';
|
||||
dest = stalloc(strlen(symlink) + strlen(p) + 1);
|
||||
scopy(symlink, dest);
|
||||
strcat(dest, p);
|
||||
} else {
|
||||
dest = p;
|
||||
}
|
||||
goto top;
|
||||
}
|
||||
STPUTC('\0', p);
|
||||
p = grabstackstr(p);
|
||||
|
||||
INTOFF;
|
||||
/* The empty string is not a legal argument to chdir on a POSIX 1003.1
|
||||
* system. */
|
||||
if (p[0] != '\0' && chdir(p) < 0) {
|
||||
if (updatepwd(badstat ? NULL : dest) < 0 || chdir(curdir) < 0) {
|
||||
INTON;
|
||||
return -1;
|
||||
return (-1);
|
||||
}
|
||||
updatepwd(p);
|
||||
INTON;
|
||||
if (print && !tohome && iflag)
|
||||
out1fmt("%s\n", p);
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
#endif /* SYMLINKS */
|
||||
|
||||
STATIC int
|
||||
cdphysical(char *dest)
|
||||
{
|
||||
|
||||
INTOFF;
|
||||
if (chdir(dest) < 0 || updatepwd(NULL) < 0) {
|
||||
INTON;
|
||||
return (-1);
|
||||
}
|
||||
INTON;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the next component of the path name pointed to by cdcomppath.
|
||||
* This routine overwrites the string pointed to by cdcomppath.
|
||||
*/
|
||||
|
||||
STATIC char *
|
||||
getcomponent() {
|
||||
register char *p;
|
||||
getcomponent(void)
|
||||
{
|
||||
char *p;
|
||||
char *start;
|
||||
|
||||
if ((p = cdcomppath) == NULL)
|
||||
|
@ -259,29 +249,43 @@ getcomponent() {
|
|||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Update curdir (the name of the current directory) in response to a
|
||||
* cd command. We also call hashcd to let the routines in exec.c know
|
||||
* that the current directory has changed.
|
||||
*/
|
||||
|
||||
void hashcd();
|
||||
|
||||
STATIC void
|
||||
updatepwd(dir)
|
||||
char *dir;
|
||||
{
|
||||
STATIC int
|
||||
updatepwd(char *dir)
|
||||
{
|
||||
char *new;
|
||||
char *p;
|
||||
|
||||
hashcd(); /* update command hash table */
|
||||
|
||||
/*
|
||||
* If our argument is NULL, we don't know the current directory
|
||||
* any more because we traversed a symbolic link or something
|
||||
* we couldn't stat().
|
||||
*/
|
||||
if (dir == NULL || curdir == NULL) {
|
||||
if (prevdir)
|
||||
ckfree(prevdir);
|
||||
INTOFF;
|
||||
prevdir = curdir;
|
||||
curdir = NULL;
|
||||
if (getpwd() == NULL) {
|
||||
INTON;
|
||||
return (-1);
|
||||
}
|
||||
setvar("PWD", curdir, VEXPORT);
|
||||
setvar("OLDPWD", prevdir, VEXPORT);
|
||||
INTON;
|
||||
return (0);
|
||||
}
|
||||
cdcomppath = stalloc(strlen(dir) + 1);
|
||||
scopy(dir, cdcomppath);
|
||||
STARTSTACKSTR(new);
|
||||
if (*dir != '/') {
|
||||
if (curdir == NULL)
|
||||
return;
|
||||
p = curdir;
|
||||
while (*p)
|
||||
STPUTC(*p++, new);
|
||||
|
@ -300,73 +304,87 @@ updatepwd(dir)
|
|||
if (new == stackblock())
|
||||
STPUTC('/', new);
|
||||
STACKSTRNUL(new);
|
||||
if (curdir)
|
||||
ckfree(curdir);
|
||||
INTOFF;
|
||||
if (prevdir)
|
||||
ckfree(prevdir);
|
||||
prevdir = curdir;
|
||||
curdir = savestr(stackblock());
|
||||
setvar("PWD", curdir, VEXPORT);
|
||||
setvar("OLDPWD", prevdir, VEXPORT);
|
||||
INTON;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
pwdcmd(argc, argv) char **argv; {
|
||||
getpwd();
|
||||
out1str(curdir);
|
||||
out1c('\n');
|
||||
pwdcmd(int argc, char **argv)
|
||||
{
|
||||
char buf[PATH_MAX];
|
||||
int ch, phys;
|
||||
|
||||
optreset = 1; optind = 1; opterr = 0; /* initialize getopt */
|
||||
phys = Pflag;
|
||||
while ((ch = getopt(argc, argv, "LP")) != -1) {
|
||||
switch (ch) {
|
||||
case 'L':
|
||||
phys = 0;
|
||||
break;
|
||||
case 'P':
|
||||
phys = 1;
|
||||
break;
|
||||
default:
|
||||
error("unknown option: -%c", optopt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 0)
|
||||
error("too many arguments");
|
||||
|
||||
if (!phys && getpwd()) {
|
||||
out1str(curdir);
|
||||
out1c('\n');
|
||||
} else {
|
||||
if (getcwd(buf, sizeof(buf)) == NULL)
|
||||
error(".: %s", strerror(errno));
|
||||
out1str(buf);
|
||||
out1c('\n');
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Run /bin/pwd to find out what the current directory is. We suppress
|
||||
* interrupts throughout most of this, but the user can still break out
|
||||
* of it by killing the pwd program. If we already know the current
|
||||
* Find out what the current directory is. If we already know the current
|
||||
* directory, this routine returns immediately.
|
||||
*/
|
||||
|
||||
#define MAXPWD 256
|
||||
|
||||
STATIC void
|
||||
getpwd() {
|
||||
char buf[MAXPWD];
|
||||
char *p;
|
||||
int i;
|
||||
int status;
|
||||
struct job *jp;
|
||||
int pip[2];
|
||||
char *
|
||||
getpwd(void)
|
||||
{
|
||||
char buf[PATH_MAX];
|
||||
|
||||
if (curdir)
|
||||
return;
|
||||
INTOFF;
|
||||
if (pipe(pip) < 0)
|
||||
error("Pipe call failed");
|
||||
jp = makejob((union node *)NULL, 1);
|
||||
if (forkshell(jp, (union node *)NULL, FORK_NOJOB) == 0) {
|
||||
close(pip[0]);
|
||||
if (pip[1] != 1) {
|
||||
close(1);
|
||||
copyfd(pip[1], 1);
|
||||
close(pip[1]);
|
||||
return curdir;
|
||||
if (getcwd(buf, sizeof(buf)) == NULL) {
|
||||
char *pwd = getenv("PWD");
|
||||
struct stat stdot, stpwd;
|
||||
|
||||
if (pwd && *pwd == '/' && stat(".", &stdot) != -1 &&
|
||||
stat(pwd, &stpwd) != -1 &&
|
||||
stdot.st_dev == stpwd.st_dev &&
|
||||
stdot.st_ino == stpwd.st_ino) {
|
||||
curdir = savestr(pwd);
|
||||
return curdir;
|
||||
}
|
||||
execl("/bin/pwd", "pwd", (char *)0);
|
||||
error("Cannot exec /bin/pwd");
|
||||
return NULL;
|
||||
}
|
||||
close(pip[1]);
|
||||
pip[1] = -1;
|
||||
p = buf;
|
||||
while ((i = read(pip[0], p, buf + MAXPWD - p)) > 0
|
||||
|| i == -1 && errno == EINTR) {
|
||||
if (i > 0)
|
||||
p += i;
|
||||
}
|
||||
close(pip[0]);
|
||||
pip[0] = -1;
|
||||
status = waitforjob(jp);
|
||||
if (status != 0)
|
||||
error((char *)0);
|
||||
if (i < 0 || p == buf || p[-1] != '\n')
|
||||
error("pwd command failed");
|
||||
p[-1] = '\0';
|
||||
curdir = savestr(buf);
|
||||
INTON;
|
||||
|
||||
return curdir;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: cd.c,v 1.6 2006/05/22 12:42:03 philip Exp $
|
||||
*/
|
||||
|
|
38
commands/ash/cd.h
Normal file
38
commands/ash/cd.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*-
|
||||
* Copyright (c) 1995
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD: src/bin/sh/cd.h,v 1.7 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
char *getpwd(void);
|
||||
int cdcmd (int, char **);
|
||||
int pwdcmd(int, char **);
|
||||
|
||||
/*
|
||||
* $PchId: cd.h,v 1.3 2006/03/31 09:59:04 philip Exp $
|
||||
*/
|
354
commands/ash/complete.c
Normal file
354
commands/ash/complete.c
Normal file
|
@ -0,0 +1,354 @@
|
|||
/*
|
||||
complete.c
|
||||
|
||||
Created: July 1995 by Philip Homburg <philip@cs.vu.nl>
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include "myhistedit.h"
|
||||
#include "shell.h"
|
||||
|
||||
#include "complete.h"
|
||||
#include "error.h"
|
||||
#include "expand.h"
|
||||
#include "nodes.h"
|
||||
#include "memalloc.h"
|
||||
|
||||
static char **getlist(EditLine *el, int *baselen, int *isdir);
|
||||
static char **getlist_tilde(char *prefix);
|
||||
static int vstrcmp(const void *v1, const void *v2);
|
||||
static void print_list(char **list);
|
||||
static int install_extra(EditLine *el, char **list, int baselen, int isdir);
|
||||
|
||||
unsigned char complete(EditLine *el, int ch)
|
||||
{
|
||||
struct stackmark mark;
|
||||
const LineInfo *lf;
|
||||
char **list;
|
||||
int baselen, prefix, isdir;
|
||||
|
||||
/* Direct the cursor the the end of the word. */
|
||||
for(;;)
|
||||
{
|
||||
lf = el_line(el);
|
||||
if (lf->cursor < lf->lastchar &&
|
||||
!isspace((unsigned char)*lf->cursor))
|
||||
{
|
||||
(*(char **)&lf->cursor)++; /* XXX */
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
setstackmark(&mark);
|
||||
list= getlist(el, &baselen, &isdir);
|
||||
if (list)
|
||||
{
|
||||
prefix= install_extra(el, list, baselen, isdir);
|
||||
el_push(el, "i");
|
||||
}
|
||||
popstackmark(&mark);
|
||||
if (list)
|
||||
return CC_REFRESH;
|
||||
else
|
||||
return CC_ERROR;
|
||||
}
|
||||
|
||||
unsigned char complete_list(EditLine *el, int ch)
|
||||
{
|
||||
struct stackmark mark;
|
||||
char **list;
|
||||
|
||||
setstackmark(&mark);
|
||||
list= getlist(el, NULL, NULL);
|
||||
if (list)
|
||||
{
|
||||
print_list(list);
|
||||
re_goto_bottom(el);
|
||||
}
|
||||
popstackmark(&mark);
|
||||
if (list)
|
||||
{
|
||||
return CC_REFRESH;
|
||||
}
|
||||
else
|
||||
return CC_ERROR;
|
||||
}
|
||||
|
||||
unsigned char complete_or_list(EditLine *el, int ch)
|
||||
{
|
||||
struct stackmark mark;
|
||||
const LineInfo *lf;
|
||||
char **list;
|
||||
int baselen, prefix, isdir;
|
||||
|
||||
setstackmark(&mark);
|
||||
list= getlist(el, &baselen, &isdir);
|
||||
if (list)
|
||||
{
|
||||
prefix= install_extra(el, list, baselen, isdir);
|
||||
if (prefix == baselen)
|
||||
{
|
||||
print_list(list);
|
||||
re_goto_bottom(el);
|
||||
}
|
||||
}
|
||||
popstackmark(&mark);
|
||||
if (list)
|
||||
return CC_REFRESH;
|
||||
else
|
||||
return CC_ERROR;
|
||||
}
|
||||
|
||||
unsigned char complete_expand(EditLine *el, int ch)
|
||||
{
|
||||
printf("complete_expand\n");
|
||||
return CC_ERROR;
|
||||
}
|
||||
|
||||
static char **getlist(EditLine *el, int *baselen, int *isdir)
|
||||
{
|
||||
const LineInfo *lf;
|
||||
const char *begin, *end;
|
||||
char *dirnam, *basenam;
|
||||
union node arg;
|
||||
struct arglist arglist;
|
||||
DIR *dir;
|
||||
struct dirent *dirent;
|
||||
int i, l, n;
|
||||
char *p, **list;
|
||||
struct strlist *slp, *nslp;
|
||||
struct stat sb;
|
||||
|
||||
lf = el_line(el);
|
||||
|
||||
/* Try to find to begin and end of the word that we have to comple. */
|
||||
begin= lf->cursor;
|
||||
while (begin > lf->buffer && !isspace((unsigned char)begin[-1]))
|
||||
begin--;
|
||||
end= lf->cursor;
|
||||
while (end < lf->lastchar && !isspace((unsigned char)end[0]))
|
||||
end++;
|
||||
|
||||
*(const char **)&lf->cursor= end; /* XXX */
|
||||
|
||||
/* Copy the word to a string */
|
||||
dirnam= stalloc(end-begin+1);
|
||||
strncpy(dirnam, begin, end-begin);
|
||||
dirnam[end-begin]= '\0';
|
||||
|
||||
/* Cut the word in two pieces: a path and a (partial) component. */
|
||||
basenam= strrchr(dirnam, '/');
|
||||
if (basenam)
|
||||
{
|
||||
basenam++;
|
||||
p= stalloc(strlen(basenam) + 1);
|
||||
strcpy(p, basenam);
|
||||
*basenam= '\0';
|
||||
basenam= p;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dirnam[0] == '~')
|
||||
return getlist_tilde(dirnam);
|
||||
basenam= dirnam;
|
||||
dirnam= "./";
|
||||
}
|
||||
if (baselen)
|
||||
*baselen= strlen(basenam);
|
||||
|
||||
arg.type= NARG;
|
||||
arg.narg.next= NULL;
|
||||
arg.narg.text= dirnam;
|
||||
arg.narg.backquote= NULL;
|
||||
arglist.list= NULL;
|
||||
arglist.lastp= &arglist.list;
|
||||
expandarg(&arg, &arglist, EXP_TILDE);
|
||||
|
||||
INTOFF;
|
||||
list= NULL;
|
||||
dir= opendir(arglist.list->text);
|
||||
if (dir)
|
||||
{
|
||||
slp= NULL;
|
||||
n= 0;
|
||||
l= strlen(basenam);
|
||||
while(dirent= readdir(dir))
|
||||
{
|
||||
if (strncmp(dirent->d_name, basenam, l) != 0)
|
||||
continue;
|
||||
if (l == 0 && dirent->d_name[0] == '.')
|
||||
continue;
|
||||
nslp= stalloc(sizeof(*nslp));
|
||||
nslp->next= slp;
|
||||
slp= nslp;
|
||||
slp->text= stalloc(strlen(dirent->d_name)+1);
|
||||
strcpy(slp->text, dirent->d_name);
|
||||
n++;
|
||||
if (n == 1 && isdir != NULL)
|
||||
{
|
||||
/* Try to findout whether this entry is a
|
||||
* file or a directory.
|
||||
*/
|
||||
p= stalloc(strlen(arglist.list->text) +
|
||||
strlen(dirent->d_name) + 1);
|
||||
strcpy(p, arglist.list->text);
|
||||
strcat(p, dirent->d_name);
|
||||
if (stat(p, &sb) == -1)
|
||||
printf("stat '%s' failed: %s\n",
|
||||
p, strerror(errno));
|
||||
if (stat(p, &sb) == 0 && S_ISDIR(sb.st_mode))
|
||||
*isdir= 1;
|
||||
else
|
||||
*isdir= 0;
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
if (n != 0)
|
||||
{
|
||||
list= stalloc((n+1)*sizeof(*list));
|
||||
for(i= 0; slp; i++, slp= slp->next)
|
||||
list[i]= slp->text;
|
||||
if (i != n)
|
||||
error("complete'make_list: i != n");
|
||||
list[i]= NULL;
|
||||
qsort(list, n, sizeof(*list), vstrcmp);
|
||||
}
|
||||
}
|
||||
INTON;
|
||||
return list;
|
||||
}
|
||||
|
||||
static char **getlist_tilde(char *prefix)
|
||||
{
|
||||
printf("should ~-complete '%s'\n", prefix);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int vstrcmp(const void *v1, const void *v2)
|
||||
{
|
||||
return strcmp(*(char **)v1, *(char **)v2);
|
||||
}
|
||||
|
||||
#define MAXCOLS 40
|
||||
#define SEPWIDTH 4
|
||||
|
||||
static void print_list(char **list)
|
||||
{
|
||||
struct
|
||||
{
|
||||
int cols;
|
||||
int start[MAXCOLS+1];
|
||||
int width[MAXCOLS];
|
||||
} best, next;
|
||||
int e, i, j, l, n, o, cols, maxw, width;
|
||||
int linewidth= 80;
|
||||
|
||||
/* Count the number of entries. */
|
||||
for (n= 0; list[n]; n++)
|
||||
; /* do nothing */
|
||||
if (n == 0)
|
||||
error("complete'print_list: n= 0");
|
||||
|
||||
/* Try to maximize the number of columns */
|
||||
for (cols= 1; cols<= MAXCOLS; cols++)
|
||||
{
|
||||
next.cols= cols;
|
||||
|
||||
o= 0;
|
||||
width= 0;
|
||||
for(j= 0; j<cols; j++)
|
||||
{
|
||||
next.start[j]= o;
|
||||
|
||||
/* Number of entries in this column. */
|
||||
e= (n-o)/(cols-j);
|
||||
if ((n-o)%(cols-j))
|
||||
e++;
|
||||
|
||||
maxw= 0;
|
||||
for (i= 0; i<e; i++)
|
||||
{
|
||||
l= strlen(list[o+i]);
|
||||
if (l < 6)
|
||||
l= 6;
|
||||
l += SEPWIDTH;
|
||||
if (l > maxw)
|
||||
maxw= l;
|
||||
}
|
||||
next.width[j]= maxw;
|
||||
width += maxw;
|
||||
o += e;
|
||||
}
|
||||
next.start[j]= o;
|
||||
if (cols > 1 && width-SEPWIDTH>linewidth)
|
||||
break;
|
||||
best= next;
|
||||
}
|
||||
cols= best.cols;
|
||||
e= best.start[1];
|
||||
printf("\n");
|
||||
for(i= 0; i<e; i++)
|
||||
{
|
||||
for (j= 0; j<cols; j++)
|
||||
{
|
||||
if (best.start[j]+i == best.start[j+1])
|
||||
continue;
|
||||
if (j < cols-1)
|
||||
{
|
||||
printf("%-*s", best.width[j],
|
||||
list[best.start[j]+i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%s", list[best.start[j]+i]);
|
||||
}
|
||||
}
|
||||
if (i < e-1)
|
||||
printf("\n");
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
static int install_extra(EditLine *el, char **list, int baselen, int isdir)
|
||||
{
|
||||
int l;
|
||||
char *p, **lp;
|
||||
|
||||
l= strlen(list[0]);
|
||||
for (lp= &list[1]; *lp; lp++)
|
||||
{
|
||||
while(l>0)
|
||||
{
|
||||
if (strncmp(list[0], *lp, l) != 0)
|
||||
l--;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (l > baselen || list[1] == NULL)
|
||||
{
|
||||
p= stalloc(l-baselen+2);
|
||||
strncpy(p, list[0]+baselen, l-baselen);
|
||||
if (list[1] == NULL)
|
||||
{
|
||||
p[l-baselen]= isdir ? '/' : ' ';
|
||||
p[l-baselen+1]= '\0';
|
||||
l++;
|
||||
}
|
||||
else
|
||||
p[l-baselen]= '\0';
|
||||
if (el_insertstr(el, p) == -1)
|
||||
return -1;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: complete.c,v 1.2 2006/04/10 14:35:53 philip Exp $
|
||||
*/
|
14
commands/ash/complete.h
Normal file
14
commands/ash/complete.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
complete.h
|
||||
|
||||
Created: July 1995 by Philip Homburg <philip@cs.vu.nl>
|
||||
*/
|
||||
|
||||
unsigned char complete(EditLine *el, int ch);
|
||||
unsigned char complete_list(EditLine *el, int ch);
|
||||
unsigned char complete_or_list(EditLine *el, int ch);
|
||||
unsigned char complete_expand(EditLine *el, int ch);
|
||||
|
||||
/*
|
||||
* $PchId: complete.h,v 1.1 2001/05/17 07:12:05 philip Exp $
|
||||
*/
|
|
@ -1,194 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* 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 char sccsid[] = "@(#)dirent.c 5.1 (Berkeley) 3/7/91";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "shell.h" /* definitions for pointer, NULL, DIRENT, and BSD */
|
||||
|
||||
#if ! DIRENT
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#ifndef S_ISDIR /* macro to test for directory file */
|
||||
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
|
||||
#ifdef BSD
|
||||
|
||||
#ifdef __STDC__
|
||||
int stat(char *, struct stat *);
|
||||
#else
|
||||
int stat();
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* The BSD opendir routine doesn't check that what is being opened is a
|
||||
* directory, so we have to include the check in a wrapper routine.
|
||||
*/
|
||||
|
||||
#undef opendir
|
||||
|
||||
DIR *
|
||||
myopendir(dirname)
|
||||
char *dirname; /* name of directory */
|
||||
{
|
||||
struct stat statb;
|
||||
|
||||
if (stat(dirname, &statb) != 0 || ! S_ISDIR(statb.st_mode)) {
|
||||
errno = ENOTDIR;
|
||||
return NULL; /* not a directory */
|
||||
}
|
||||
return opendir(dirname);
|
||||
}
|
||||
|
||||
#else /* not BSD */
|
||||
|
||||
/*
|
||||
* Dirent routines for old style file systems.
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
pointer malloc(unsigned);
|
||||
void free(pointer);
|
||||
int open(char *, int, ...);
|
||||
int close(int);
|
||||
int fstat(int, struct stat *);
|
||||
#else
|
||||
pointer malloc();
|
||||
void free();
|
||||
int open();
|
||||
int close();
|
||||
int fstat();
|
||||
#endif
|
||||
|
||||
|
||||
DIR *
|
||||
opendir(dirname)
|
||||
char *dirname; /* name of directory */
|
||||
{
|
||||
register DIR *dirp; /* -> malloc'ed storage */
|
||||
register int fd; /* file descriptor for read */
|
||||
struct stat statb; /* result of fstat() */
|
||||
|
||||
#ifdef O_NDELAY
|
||||
fd = open(dirname, O_RDONLY|O_NDELAY);
|
||||
#else
|
||||
fd = open(dirname, O_RDONLY);
|
||||
#endif
|
||||
if (fd < 0)
|
||||
return NULL; /* errno set by open() */
|
||||
|
||||
if (fstat(fd, &statb) != 0 || !S_ISDIR(statb.st_mode)) {
|
||||
(void)close(fd);
|
||||
errno = ENOTDIR;
|
||||
return NULL; /* not a directory */
|
||||
}
|
||||
|
||||
if ((dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
|
||||
(void)close(fd);
|
||||
errno = ENOMEM;
|
||||
return NULL; /* not enough memory */
|
||||
}
|
||||
|
||||
dirp->dd_fd = fd;
|
||||
dirp->dd_nleft = 0; /* refill needed */
|
||||
|
||||
return dirp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
closedir(dirp)
|
||||
register DIR *dirp; /* stream from opendir() */
|
||||
{
|
||||
register int fd;
|
||||
|
||||
if (dirp == NULL) {
|
||||
errno = EFAULT;
|
||||
return -1; /* invalid pointer */
|
||||
}
|
||||
|
||||
fd = dirp->dd_fd;
|
||||
free((pointer)dirp);
|
||||
return close(fd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct dirent *
|
||||
readdir(dirp)
|
||||
register DIR *dirp; /* stream from opendir() */
|
||||
{
|
||||
register struct direct *dp;
|
||||
register char *p, *q;
|
||||
register int i;
|
||||
|
||||
do {
|
||||
if ((dirp->dd_nleft -= sizeof (struct direct)) < 0) {
|
||||
if ((i = read(dirp->dd_fd,
|
||||
(char *)dirp->dd_buf,
|
||||
DIRBUFENT*sizeof(struct direct))) <= 0) {
|
||||
if (i == 0)
|
||||
errno = 0; /* unnecessary */
|
||||
return NULL; /* EOF or error */
|
||||
}
|
||||
dirp->dd_loc = dirp->dd_buf;
|
||||
dirp->dd_nleft = i - sizeof (struct direct);
|
||||
}
|
||||
dp = dirp->dd_loc++;
|
||||
} while (dp->d_ino == 0);
|
||||
dirp->dd_entry.d_ino = dp->d_ino;
|
||||
|
||||
/* now copy the name, nul terminating it */
|
||||
p = dp->d_name;
|
||||
q = dirp->dd_entry.d_name;
|
||||
i = DIRSIZ;
|
||||
while (--i >= 0 && *p != '\0')
|
||||
*q++ = *p++;
|
||||
*q = '\0';
|
||||
return &dirp->dd_entry;
|
||||
}
|
||||
|
||||
#endif /* BSD */
|
||||
#endif /* DIRENT */
|
127
commands/ash/errmsg.c
Normal file
127
commands/ash/errmsg.c
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* 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 char sccsid[] = "@(#)errmsg.c 8.1 (Berkeley) 5/31/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "shell.h"
|
||||
#include "output.h"
|
||||
#include "errmsg.h"
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#define ALL (E_OPEN|E_CREAT|E_EXEC)
|
||||
|
||||
|
||||
struct errname {
|
||||
short errcode; /* error number */
|
||||
short action; /* operation which encountered the error */
|
||||
char *msg; /* text describing the error */
|
||||
};
|
||||
|
||||
|
||||
STATIC const struct errname errormsg[] = {
|
||||
EINTR, ALL, "interrupted",
|
||||
EACCES, ALL, "permission denied",
|
||||
EIO, ALL, "I/O error",
|
||||
ENOENT, E_OPEN, "no such file",
|
||||
ENOENT, E_CREAT, "directory nonexistent",
|
||||
ENOENT, E_EXEC, "not found",
|
||||
ENOTDIR, E_OPEN, "no such file",
|
||||
ENOTDIR, E_CREAT, "directory nonexistent",
|
||||
ENOTDIR, E_EXEC, "not found",
|
||||
EISDIR, ALL, "is a directory",
|
||||
/* EMFILE, ALL, "too many open files", */
|
||||
ENFILE, ALL, "file table overflow",
|
||||
ENOSPC, ALL, "file system full",
|
||||
#ifdef EDQUOT
|
||||
EDQUOT, ALL, "disk quota exceeded",
|
||||
#endif
|
||||
#ifdef ENOSR
|
||||
ENOSR, ALL, "no streams resources",
|
||||
#endif
|
||||
ENXIO, ALL, "no such device or address",
|
||||
EROFS, ALL, "read-only file system",
|
||||
ETXTBSY, ALL, "text busy",
|
||||
#ifdef SYSV
|
||||
EAGAIN, E_EXEC, "not enough memory",
|
||||
#endif
|
||||
ENOMEM, ALL, "not enough memory",
|
||||
#ifdef ENOLINK
|
||||
ENOLINK, ALL, "remote access failed"
|
||||
#endif
|
||||
#ifdef EMULTIHOP
|
||||
EMULTIHOP, ALL, "remote access failed",
|
||||
#endif
|
||||
#ifdef ECOMM
|
||||
ECOMM, ALL, "remote access failed",
|
||||
#endif
|
||||
#ifdef ESTALE
|
||||
ESTALE, ALL, "remote access failed",
|
||||
#endif
|
||||
#ifdef ETIMEDOUT
|
||||
ETIMEDOUT, ALL, "remote access failed",
|
||||
#endif
|
||||
#ifdef ELOOP
|
||||
ELOOP, ALL, "symbolic link loop",
|
||||
#endif
|
||||
E2BIG, E_EXEC, "argument list too long",
|
||||
#ifdef ELIBACC
|
||||
ELIBACC, E_EXEC, "shared library missing",
|
||||
#endif
|
||||
0, 0, NULL
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Return a string describing an error. The returned string may be a
|
||||
* pointer to a static buffer that will be overwritten on the next call.
|
||||
* Action describes the operation that got the error.
|
||||
*/
|
||||
|
||||
char *
|
||||
errmsg(e, action) {
|
||||
struct errname const *ep;
|
||||
static char buf[12];
|
||||
|
||||
for (ep = errormsg ; ep->errcode ; ep++) {
|
||||
if (ep->errcode == e && (ep->action & action) != 0)
|
||||
return ep->msg;
|
||||
}
|
||||
fmtstr(buf, sizeof buf, "error %d", e);
|
||||
return buf;
|
||||
}
|
47
commands/ash/errmsg.h
Normal file
47
commands/ash/errmsg.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @(#)errmsg.h 8.1 (Berkeley) 5/31/93
|
||||
*/
|
||||
|
||||
#define E_OPEN 01
|
||||
#define E_CREAT 02
|
||||
#define E_EXEC 04
|
||||
|
||||
#ifdef __STDC__
|
||||
char *errmsg(int, int);
|
||||
#else
|
||||
char *errmsg();
|
||||
#endif
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -35,8 +31,14 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)error.c 5.1 (Berkeley) 3/7/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/error.c,v 1.25 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
/*
|
||||
* Errors and exceptions.
|
||||
|
@ -47,14 +49,14 @@ static char sccsid[] = "@(#)error.c 5.1 (Berkeley) 3/7/91";
|
|||
#include "options.h"
|
||||
#include "output.h"
|
||||
#include "error.h"
|
||||
#include <sys/types.h>
|
||||
#include "nodes.h" /* show.h needs nodes.h */
|
||||
#include "show.h"
|
||||
#include "trap.h"
|
||||
#include <signal.h>
|
||||
#ifdef __STDC__
|
||||
#include "stdarg.h"
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
/*
|
||||
|
@ -62,12 +64,14 @@ static char sccsid[] = "@(#)error.c 5.1 (Berkeley) 3/7/91";
|
|||
*/
|
||||
|
||||
struct jmploc *handler;
|
||||
int exception;
|
||||
volatile int suppressint;
|
||||
volatile int intpending;
|
||||
volatile sig_atomic_t exception;
|
||||
volatile sig_atomic_t suppressint;
|
||||
volatile sig_atomic_t intpending;
|
||||
char *commandname;
|
||||
|
||||
|
||||
static void exverror(int, const char *, va_list) __printf0like(2, 0);
|
||||
|
||||
/*
|
||||
* Called to raise an exception. Since C doesn't include exceptions, we
|
||||
* just do a longjmp to the exception handler. The type of exception is
|
||||
|
@ -75,7 +79,8 @@ char *commandname;
|
|||
*/
|
||||
|
||||
void
|
||||
exraise(e) {
|
||||
exraise(int e)
|
||||
{
|
||||
if (handler == NULL)
|
||||
abort();
|
||||
exception = e;
|
||||
|
@ -87,69 +92,63 @@ exraise(e) {
|
|||
* Called from trap.c when a SIGINT is received. (If the user specifies
|
||||
* that SIGINT is to be trapped or ignored using the trap builtin, then
|
||||
* this routine is not called.) Suppressint is nonzero when interrupts
|
||||
* are held using the INTOFF macro. The call to _exit is necessary because
|
||||
* there is a short period after a fork before the signal handlers are
|
||||
* set to the appropriate value for the child. (The test for iflag is
|
||||
* just defensive programming.)
|
||||
* are held using the INTOFF macro. If SIGINTs are not suppressed and
|
||||
* the shell is not a root shell, then we want to be terminated if we
|
||||
* get here, as if we were terminated directly by a SIGINT. Arrange for
|
||||
* this here.
|
||||
*/
|
||||
|
||||
void
|
||||
onint() {
|
||||
if (suppressint) {
|
||||
onint(void)
|
||||
{
|
||||
sigset_t sigset;
|
||||
|
||||
/*
|
||||
* The !in_dotrap here is safe. The only way we can arrive here
|
||||
* with in_dotrap set is that a trap handler set SIGINT to SIG_DFL
|
||||
* and killed itself.
|
||||
*/
|
||||
|
||||
if (suppressint && !in_dotrap) {
|
||||
intpending++;
|
||||
return;
|
||||
}
|
||||
intpending = 0;
|
||||
#ifdef BSD
|
||||
sigsetmask(0);
|
||||
sigemptyset(&sigset);
|
||||
sigprocmask(SIG_SETMASK, &sigset, NULL);
|
||||
|
||||
/*
|
||||
* This doesn't seem to be needed, since main() emits a newline.
|
||||
*/
|
||||
#if 0
|
||||
if (tcgetpgrp(0) == getpid())
|
||||
write(STDERR_FILENO, "\n", 1);
|
||||
#endif
|
||||
if (rootshell && iflag)
|
||||
exraise(EXINT);
|
||||
else
|
||||
_exit(128 + SIGINT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
error2(a, b)
|
||||
char *a, *b;
|
||||
{
|
||||
error("%s: %s", a, b);
|
||||
else {
|
||||
signal(SIGINT, SIG_DFL);
|
||||
kill(getpid(), SIGINT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Error is called to raise the error exception. If the first argument
|
||||
* Exverror is called to raise the error exception. If the first argument
|
||||
* is not NULL then error prints an error message using printf style
|
||||
* formatting. It then raises the error exception.
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
void
|
||||
error(char *msg, ...) {
|
||||
#else
|
||||
void
|
||||
error(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
char *msg;
|
||||
#endif
|
||||
va_list ap;
|
||||
|
||||
static void
|
||||
exverror(int cond, const char *msg, va_list ap)
|
||||
{
|
||||
CLEAR_PENDING_INT;
|
||||
INTOFF;
|
||||
#ifdef __STDC__
|
||||
va_start(ap, msg);
|
||||
#else
|
||||
va_start(ap);
|
||||
msg = va_arg(ap, char *);
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
if (msg)
|
||||
TRACE(("error(\"%s\") pid=%d\n", msg, getpid()));
|
||||
TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
|
||||
else
|
||||
TRACE(("error(NULL) pid=%d\n", getpid()));
|
||||
TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
|
||||
#endif
|
||||
if (msg) {
|
||||
if (commandname)
|
||||
|
@ -157,96 +156,30 @@ error(va_alist)
|
|||
doformat(&errout, msg, ap);
|
||||
out2c('\n');
|
||||
}
|
||||
va_end(ap);
|
||||
flushall();
|
||||
exraise(EXERROR);
|
||||
exraise(cond);
|
||||
}
|
||||
|
||||
|
||||
#ifdef notdef /* These strange error messages only confuse. -- kjb */
|
||||
/*
|
||||
* Table of error messages.
|
||||
*/
|
||||
|
||||
struct errname {
|
||||
short errcode; /* error number */
|
||||
short action; /* operation which encountered the error */
|
||||
char *msg; /* text describing the error */
|
||||
};
|
||||
|
||||
|
||||
#define ALL (E_OPEN|E_CREAT|E_EXEC)
|
||||
|
||||
STATIC const struct errname errormsg[] = {
|
||||
EINTR, ALL, "interrupted",
|
||||
EACCES, ALL, "permission denied",
|
||||
EIO, ALL, "I/O error",
|
||||
ENOENT, E_OPEN, "no such file",
|
||||
ENOENT, E_CREAT, "directory nonexistent",
|
||||
ENOENT, E_EXEC, "not found",
|
||||
ENOTDIR, E_OPEN, "no such file",
|
||||
ENOTDIR, E_CREAT, "directory nonexistent",
|
||||
ENOTDIR, E_EXEC, "not found",
|
||||
ENOEXEC, ALL, "not an executable",
|
||||
EISDIR, ALL, "is a directory",
|
||||
/* EMFILE, ALL, "too many open files", */
|
||||
ENFILE, ALL, "file table overflow",
|
||||
ENOSPC, ALL, "file system full",
|
||||
#ifdef EDQUOT
|
||||
EDQUOT, ALL, "disk quota exceeded",
|
||||
#endif
|
||||
#ifdef ENOSR
|
||||
ENOSR, ALL, "no streams resources",
|
||||
#endif
|
||||
ENXIO, ALL, "no such device or address",
|
||||
EROFS, ALL, "read-only file system",
|
||||
ETXTBSY, ALL, "text busy",
|
||||
#ifdef SYSV
|
||||
EAGAIN, E_EXEC, "not enough memory",
|
||||
#endif
|
||||
ENOMEM, ALL, "not enough memory",
|
||||
#ifdef ENOLINK
|
||||
ENOLINK, ALL, "remote access failed",
|
||||
#endif
|
||||
#ifdef EMULTIHOP
|
||||
EMULTIHOP, ALL, "remote access failed",
|
||||
#endif
|
||||
#ifdef ECOMM
|
||||
ECOMM, ALL, "remote access failed",
|
||||
#endif
|
||||
#ifdef ESTALE
|
||||
ESTALE, ALL, "remote access failed",
|
||||
#endif
|
||||
#ifdef ETIMEDOUT
|
||||
ETIMEDOUT, ALL, "remote access failed",
|
||||
#endif
|
||||
#ifdef ELOOP
|
||||
ELOOP, ALL, "symbolic link loop",
|
||||
#endif
|
||||
E2BIG, E_EXEC, "argument list too long",
|
||||
#ifdef ELIBACC
|
||||
ELIBACC, E_EXEC, "shared library missing",
|
||||
#endif
|
||||
0, 0, NULL
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Return a string describing an error. The returned string may be a
|
||||
* pointer to a static buffer that will be overwritten on the next call.
|
||||
* Action describes the operation that got the error.
|
||||
*/
|
||||
|
||||
char *
|
||||
errmsg(e, action) {
|
||||
const struct errname *ep;
|
||||
static char buf[12];
|
||||
|
||||
for (ep = errormsg ; ep->errcode ; ep++) {
|
||||
if (ep->errcode == e && (ep->action & action) != 0)
|
||||
return ep->msg;
|
||||
}
|
||||
fmtstr(buf, sizeof buf, "error %d", e);
|
||||
return buf;
|
||||
void
|
||||
error(const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
exverror(EXERROR, msg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
exerror(int cond, const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
exverror(cond, msg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: error.c,v 1.5 2006/04/10 14:36:23 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -33,41 +29,35 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)error.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)error.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/error.h,v 1.17 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* Types of operations (passed to the errmsg routine).
|
||||
*/
|
||||
|
||||
#define E_OPEN 01 /* opening a file */
|
||||
#define E_CREAT 02 /* creating a file */
|
||||
#define E_EXEC 04 /* executing a program */
|
||||
|
||||
|
||||
/*
|
||||
* We enclose jmp_buf in a structure so that we can declare pointers to
|
||||
* jump locations. The global variable handler contains the location to
|
||||
* jump to when an exception occurs, and the global variable exception
|
||||
* contains a code identifying the exeception. To implement nested
|
||||
* contains a code identifying the exception. To implement nested
|
||||
* exception handlers, the user should save the value of handler on entry
|
||||
* to an inner scope, set handler to point to a jmploc structure for the
|
||||
* inner scope, and restore handler on exit from the scope.
|
||||
*/
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
|
||||
struct jmploc {
|
||||
jmp_buf loc;
|
||||
};
|
||||
|
||||
extern struct jmploc *handler;
|
||||
extern int exception;
|
||||
extern volatile sig_atomic_t exception;
|
||||
|
||||
/* exceptions */
|
||||
#define EXINT 0 /* SIGINT received */
|
||||
#define EXERROR 1 /* a generic error */
|
||||
#define EXSHELLPROC 2 /* execute a shell procedure */
|
||||
#define EXEXEC 3 /* command execution failed */
|
||||
|
||||
|
||||
/*
|
||||
|
@ -77,32 +67,21 @@ extern int exception;
|
|||
* more fun than worrying about efficiency and portability. :-))
|
||||
*/
|
||||
|
||||
extern volatile int suppressint;
|
||||
extern volatile int intpending;
|
||||
extern char *commandname; /* name of command--printed on error */
|
||||
extern volatile sig_atomic_t suppressint;
|
||||
extern volatile sig_atomic_t intpending;
|
||||
|
||||
#define INTOFF suppressint++
|
||||
#define INTON if (--suppressint == 0 && intpending) onint(); else
|
||||
#define INTON { if (--suppressint == 0 && intpending) onint(); }
|
||||
#define FORCEINTON {suppressint = 0; if (intpending) onint();}
|
||||
#define CLEAR_PENDING_INT intpending = 0
|
||||
#define int_pending() intpending
|
||||
|
||||
#ifdef __STDC__
|
||||
#define __printf0like(a,b)
|
||||
|
||||
void exraise(int);
|
||||
void onint(void);
|
||||
void error2(char *, char *);
|
||||
void error(char *, ...);
|
||||
char *errmsg(int, int);
|
||||
#else
|
||||
void exraise();
|
||||
void onint();
|
||||
void error2();
|
||||
void error();
|
||||
char *errmsg();
|
||||
#endif
|
||||
|
||||
/* Errmsg uses confusingly different messages. Prefer strerror(). -- kjb */
|
||||
#define errmsg(errno, action) strerror(errno)
|
||||
void error(const char *, ...) __printf0like(1, 2);
|
||||
void exerror(int, const char *, ...) __printf0like(2, 3);
|
||||
|
||||
|
||||
/*
|
||||
|
@ -111,6 +90,12 @@ char *errmsg();
|
|||
*/
|
||||
|
||||
#ifdef BSD
|
||||
#ifndef __minix
|
||||
#define setjmp(jmploc) _setjmp(jmploc)
|
||||
#define longjmp(jmploc, val) _longjmp(jmploc, val)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $PchId: error.h,v 1.5 2006/04/10 14:36:43 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -35,8 +31,23 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)eval.c 5.3 (Berkeley) 4/12/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/eval.c,v 1.42 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#ifndef NO_PATHS_H
|
||||
#include <paths.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h> /* For WIFSIGNALED(status) */
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* Evaluate a command.
|
||||
|
@ -59,22 +70,21 @@ static char sccsid[] = "@(#)eval.c 5.3 (Berkeley) 4/12/91";
|
|||
#include "var.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "show.h"
|
||||
#include "mystring.h"
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||
#include "myhistedit.h"
|
||||
#endif
|
||||
|
||||
#ifndef _PATH_STDPATH
|
||||
#define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin:"
|
||||
#endif
|
||||
|
||||
/* flags in argument to evaltree */
|
||||
#define EV_EXIT 01 /* exit after evaluating tree */
|
||||
#define EV_TESTED 02 /* exit status is checked; ignore -e flag */
|
||||
#define EV_BACKCMD 04 /* command executing within back quotes */
|
||||
|
||||
|
||||
/* reasons for skipping commands (see comment on breakcmd routine) */
|
||||
#define SKIPBREAK 1
|
||||
#define SKIPCONT 2
|
||||
#define SKIPFUNC 3
|
||||
|
||||
MKINIT int evalskip; /* set if we are skipping commands */
|
||||
STATIC int skipcount; /* number of levels to skip */
|
||||
MKINIT int loopnest; /* current loop nesting level */
|
||||
|
@ -87,7 +97,6 @@ int exitstatus; /* exit status of last command */
|
|||
int oexitstatus; /* saved exit status */
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
STATIC void evalloop(union node *);
|
||||
STATIC void evalfor(union node *);
|
||||
STATIC void evalcase(union node *, int);
|
||||
|
@ -96,17 +105,6 @@ STATIC void expredir(union node *);
|
|||
STATIC void evalpipe(union node *);
|
||||
STATIC void evalcommand(union node *, int, struct backcmd *);
|
||||
STATIC void prehash(union node *);
|
||||
#else
|
||||
STATIC void evalloop();
|
||||
STATIC void evalfor();
|
||||
STATIC void evalcase();
|
||||
STATIC void evalsubshell();
|
||||
STATIC void expredir();
|
||||
STATIC void evalpipe();
|
||||
STATIC void evalcommand();
|
||||
STATIC void prehash();
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
@ -130,11 +128,11 @@ SHELLPROC {
|
|||
|
||||
|
||||
/*
|
||||
* The eval commmand.
|
||||
* The eval command.
|
||||
*/
|
||||
|
||||
evalcmd(argc, argv)
|
||||
char **argv;
|
||||
int
|
||||
evalcmd(int argc, char **argv)
|
||||
{
|
||||
char *p;
|
||||
char *concat;
|
||||
|
@ -166,9 +164,8 @@ evalcmd(argc, argv)
|
|||
*/
|
||||
|
||||
void
|
||||
evalstring(s)
|
||||
char *s;
|
||||
{
|
||||
evalstring(char *s)
|
||||
{
|
||||
union node *n;
|
||||
struct stackmark smark;
|
||||
|
||||
|
@ -190,14 +187,17 @@ evalstring(s)
|
|||
*/
|
||||
|
||||
void
|
||||
evaltree(n, flags)
|
||||
union node *n;
|
||||
{
|
||||
evaltree(union node *n, int flags)
|
||||
{
|
||||
if (n == NULL) {
|
||||
TRACE(("evaltree(NULL) called\n"));
|
||||
return;
|
||||
exitstatus = 0;
|
||||
goto out;
|
||||
}
|
||||
TRACE(("evaltree(0x%x: %d) called\n", (int)n, n->type));
|
||||
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||
displayhist = 1; /* show history substitutions done with fc */
|
||||
#endif
|
||||
TRACE(("evaltree(0x%lx: %d) called\n", (long)n, n->type));
|
||||
switch (n->type) {
|
||||
case NSEMI:
|
||||
evaltree(n->nbinary.ch1, 0);
|
||||
|
@ -207,8 +207,9 @@ evaltree(n, flags)
|
|||
break;
|
||||
case NAND:
|
||||
evaltree(n->nbinary.ch1, EV_TESTED);
|
||||
if (evalskip || exitstatus != 0)
|
||||
if (evalskip || exitstatus != 0) {
|
||||
goto out;
|
||||
}
|
||||
evaltree(n->nbinary.ch2, flags);
|
||||
break;
|
||||
case NOR:
|
||||
|
@ -230,19 +231,15 @@ evaltree(n, flags)
|
|||
evalsubshell(n, flags);
|
||||
break;
|
||||
case NIF: {
|
||||
int status = 0;
|
||||
|
||||
evaltree(n->nif.test, EV_TESTED);
|
||||
if (evalskip)
|
||||
goto out;
|
||||
if (exitstatus == 0) {
|
||||
if (exitstatus == 0)
|
||||
evaltree(n->nif.ifpart, flags);
|
||||
status = exitstatus;
|
||||
} else if (n->nif.elsepart) {
|
||||
else if (n->nif.elsepart)
|
||||
evaltree(n->nif.elsepart, flags);
|
||||
status = exitstatus;
|
||||
}
|
||||
exitstatus = status;
|
||||
else
|
||||
exitstatus = 0;
|
||||
break;
|
||||
}
|
||||
case NWHILE:
|
||||
|
@ -259,6 +256,11 @@ evaltree(n, flags)
|
|||
defun(n->narg.text, n->narg.next);
|
||||
exitstatus = 0;
|
||||
break;
|
||||
case NNOT:
|
||||
evaltree(n->nnot.com, EV_TESTED);
|
||||
exitstatus = !exitstatus;
|
||||
break;
|
||||
|
||||
case NPIPE:
|
||||
evalpipe(n);
|
||||
break;
|
||||
|
@ -274,17 +276,15 @@ out:
|
|||
if (pendingsigs)
|
||||
dotrap();
|
||||
if ((flags & EV_EXIT) || (eflag && exitstatus
|
||||
&& !(flags & EV_TESTED) && (n->type == NCMD ||
|
||||
n->type == NSUBSHELL))) {
|
||||
&& !(flags & EV_TESTED) && (n->type == NCMD ||
|
||||
n->type == NSUBSHELL)))
|
||||
exitshell(exitstatus);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
STATIC void
|
||||
evalloop(n)
|
||||
union node *n;
|
||||
{
|
||||
evalloop(union node *n)
|
||||
{
|
||||
int status;
|
||||
|
||||
loopnest++;
|
||||
|
@ -319,9 +319,8 @@ skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
|
|||
|
||||
|
||||
STATIC void
|
||||
evalfor(n)
|
||||
union node *n;
|
||||
{
|
||||
evalfor(union node *n)
|
||||
{
|
||||
struct arglist arglist;
|
||||
union node *argp;
|
||||
struct strlist *sp;
|
||||
|
@ -331,7 +330,7 @@ evalfor(n)
|
|||
arglist.lastp = &arglist.list;
|
||||
for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
|
||||
oexitstatus = exitstatus;
|
||||
expandarg(argp, &arglist, 1);
|
||||
expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
|
||||
if (evalskip)
|
||||
goto out;
|
||||
}
|
||||
|
@ -360,9 +359,8 @@ out:
|
|||
|
||||
|
||||
STATIC void
|
||||
evalcase(n, flags)
|
||||
union node *n;
|
||||
{
|
||||
evalcase(union node *n, int flags)
|
||||
{
|
||||
union node *cp;
|
||||
union node *patp;
|
||||
struct arglist arglist;
|
||||
|
@ -370,8 +368,8 @@ evalcase(n, flags)
|
|||
|
||||
setstackmark(&smark);
|
||||
arglist.lastp = &arglist.list;
|
||||
oexitstatus = exitstatus;
|
||||
expandarg(n->ncase.expr, &arglist, 0);
|
||||
oexitstatus = exitstatus;
|
||||
expandarg(n->ncase.expr, &arglist, EXP_TILDE);
|
||||
for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
|
||||
for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
|
||||
if (casematch(patp, arglist.list->text)) {
|
||||
|
@ -393,9 +391,8 @@ out:
|
|||
*/
|
||||
|
||||
STATIC void
|
||||
evalsubshell(n, flags)
|
||||
union node *n;
|
||||
{
|
||||
evalsubshell(union node *n, int flags)
|
||||
{
|
||||
struct job *jp;
|
||||
int backgnd = (n->type == NBACKGND);
|
||||
|
||||
|
@ -409,7 +406,7 @@ evalsubshell(n, flags)
|
|||
}
|
||||
if (! backgnd) {
|
||||
INTOFF;
|
||||
exitstatus = waitforjob(jp);
|
||||
exitstatus = waitforjob(jp, (int *)NULL);
|
||||
INTON;
|
||||
}
|
||||
}
|
||||
|
@ -421,20 +418,30 @@ evalsubshell(n, flags)
|
|||
*/
|
||||
|
||||
STATIC void
|
||||
expredir(n)
|
||||
union node *n;
|
||||
{
|
||||
register union node *redir;
|
||||
expredir(union node *n)
|
||||
{
|
||||
union node *redir;
|
||||
|
||||
for (redir = n ; redir ; redir = redir->nfile.next) {
|
||||
struct arglist fn;
|
||||
fn.lastp = &fn.list;
|
||||
oexitstatus = exitstatus;
|
||||
if (redir->type == NFROM
|
||||
|| redir->type == NTO
|
||||
|| redir->type == NAPPEND) {
|
||||
struct arglist fn;
|
||||
fn.lastp = &fn.list;
|
||||
expandarg(redir->nfile.fname, &fn, 0);
|
||||
switch (redir->type) {
|
||||
case NFROM:
|
||||
case NTO:
|
||||
case NFROMTO:
|
||||
case NAPPEND:
|
||||
case NCLOBBER:
|
||||
expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
|
||||
redir->nfile.expfname = fn.list->text;
|
||||
break;
|
||||
case NFROMFD:
|
||||
case NTOFD:
|
||||
if (redir->ndup.vname) {
|
||||
expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
|
||||
fixredir(redir, fn.list->text, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -449,16 +456,15 @@ expredir(n)
|
|||
*/
|
||||
|
||||
STATIC void
|
||||
evalpipe(n)
|
||||
union node *n;
|
||||
{
|
||||
evalpipe(union node *n)
|
||||
{
|
||||
struct job *jp;
|
||||
struct nodelist *lp;
|
||||
int pipelen;
|
||||
int prevfd;
|
||||
int pip[2];
|
||||
|
||||
TRACE(("evalpipe(0x%x) called\n", (int)n));
|
||||
TRACE(("evalpipe(0x%lx) called\n", (long)n));
|
||||
pipelen = 0;
|
||||
for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
|
||||
pipelen++;
|
||||
|
@ -471,21 +477,20 @@ evalpipe(n)
|
|||
if (lp->next) {
|
||||
if (pipe(pip) < 0) {
|
||||
close(prevfd);
|
||||
error("Pipe call failed");
|
||||
error("Pipe call failed: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
|
||||
INTON;
|
||||
if (prevfd > 0) {
|
||||
close(0);
|
||||
copyfd(prevfd, 0);
|
||||
dup2(prevfd, 0);
|
||||
close(prevfd);
|
||||
}
|
||||
if (pip[1] >= 0) {
|
||||
close(pip[0]);
|
||||
if (!(prevfd >= 0 && pip[0] == 0))
|
||||
close(pip[0]);
|
||||
if (pip[1] != 1) {
|
||||
close(1);
|
||||
copyfd(pip[1], 1);
|
||||
dup2(pip[1], 1);
|
||||
close(pip[1]);
|
||||
}
|
||||
}
|
||||
|
@ -499,7 +504,7 @@ evalpipe(n)
|
|||
INTON;
|
||||
if (n->npipe.backgnd == 0) {
|
||||
INTOFF;
|
||||
exitstatus = waitforjob(jp);
|
||||
exitstatus = waitforjob(jp, (int *)NULL);
|
||||
TRACE(("evalpipe: job done exit status %d\n", exitstatus));
|
||||
INTON;
|
||||
}
|
||||
|
@ -515,10 +520,8 @@ evalpipe(n)
|
|||
*/
|
||||
|
||||
void
|
||||
evalbackcmd(n, result)
|
||||
union node *n;
|
||||
struct backcmd *result;
|
||||
{
|
||||
evalbackcmd(union node *n, struct backcmd *result)
|
||||
{
|
||||
int pip[2];
|
||||
struct job *jp;
|
||||
struct stackmark smark; /* unnecessary */
|
||||
|
@ -529,21 +532,22 @@ evalbackcmd(n, result)
|
|||
result->nleft = 0;
|
||||
result->jp = NULL;
|
||||
if (n == NULL) {
|
||||
/* `` */
|
||||
} else
|
||||
exitstatus = 0;
|
||||
goto out;
|
||||
}
|
||||
if (n->type == NCMD) {
|
||||
exitstatus = oexitstatus;
|
||||
exitstatus = oexitstatus;
|
||||
evalcommand(n, EV_BACKCMD, result);
|
||||
} else {
|
||||
exitstatus = 0;
|
||||
if (pipe(pip) < 0)
|
||||
error("Pipe call failed");
|
||||
error("Pipe call failed: %s", strerror(errno));
|
||||
jp = makejob(n, 1);
|
||||
if (forkshell(jp, n, FORK_NOJOB) == 0) {
|
||||
FORCEINTON;
|
||||
close(pip[0]);
|
||||
if (pip[1] != 1) {
|
||||
close(1);
|
||||
copyfd(pip[1], 1);
|
||||
dup2(pip[1], 1);
|
||||
close(pip[1]);
|
||||
}
|
||||
evaltree(n, EV_EXIT);
|
||||
|
@ -552,8 +556,9 @@ evalbackcmd(n, result)
|
|||
result->fd = pip[0];
|
||||
result->jp = jp;
|
||||
}
|
||||
out:
|
||||
popstackmark(&smark);
|
||||
TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
|
||||
TRACE(("evalbackcmd done: fd=%d buf=%p nleft=%d jp=%p\n",
|
||||
result->fd, result->buf, result->nleft, result->jp));
|
||||
}
|
||||
|
||||
|
@ -564,10 +569,8 @@ evalbackcmd(n, result)
|
|||
*/
|
||||
|
||||
STATIC void
|
||||
evalcommand(cmd, flags, backcmd)
|
||||
union node *cmd;
|
||||
struct backcmd *backcmd;
|
||||
{
|
||||
evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
|
||||
{
|
||||
struct stackmark smark;
|
||||
union node *argp;
|
||||
struct arglist arglist;
|
||||
|
@ -577,7 +580,6 @@ evalcommand(cmd, flags, backcmd)
|
|||
char **envp;
|
||||
int varflag;
|
||||
struct strlist *sp;
|
||||
register char *p;
|
||||
int mode;
|
||||
int pip[2];
|
||||
struct cmdentry cmdentry;
|
||||
|
@ -589,27 +591,38 @@ evalcommand(cmd, flags, backcmd)
|
|||
struct localvar *volatile savelocalvars;
|
||||
volatile int e;
|
||||
char *lastarg;
|
||||
int realstatus;
|
||||
int do_clearcmdentry;
|
||||
#if __GNUC__
|
||||
/* Avoid longjmp clobbering */
|
||||
(void) &argv;
|
||||
(void) &argc;
|
||||
(void) &lastarg;
|
||||
(void) &flags;
|
||||
(void) &do_clearcmdentry;
|
||||
#endif
|
||||
|
||||
/* First expand the arguments. */
|
||||
TRACE(("evalcommand(0x%x, %d) called\n", (int)cmd, flags));
|
||||
TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
|
||||
setstackmark(&smark);
|
||||
arglist.lastp = &arglist.list;
|
||||
varlist.lastp = &varlist.list;
|
||||
varflag = 1;
|
||||
oexitstatus = exitstatus;
|
||||
do_clearcmdentry = 0;
|
||||
oexitstatus = exitstatus;
|
||||
exitstatus = 0;
|
||||
for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
|
||||
p = argp->narg.text;
|
||||
char *p = argp->narg.text;
|
||||
if (varflag && is_name(*p)) {
|
||||
do {
|
||||
p++;
|
||||
} while (is_in_name(*p));
|
||||
if (*p == '=') {
|
||||
expandarg(argp, &varlist, 0);
|
||||
expandarg(argp, &varlist, EXP_VARTILDE);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
expandarg(argp, &arglist, 1);
|
||||
expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
|
||||
varflag = 0;
|
||||
}
|
||||
*arglist.lastp = NULL;
|
||||
|
@ -619,8 +632,11 @@ evalcommand(cmd, flags, backcmd)
|
|||
for (sp = arglist.list ; sp ; sp = sp->next)
|
||||
argc++;
|
||||
argv = stalloc(sizeof (char *) * (argc + 1));
|
||||
for (sp = arglist.list ; sp ; sp = sp->next)
|
||||
|
||||
for (sp = arglist.list ; sp ; sp = sp->next) {
|
||||
TRACE(("evalcommand arg: %s\n", sp->text));
|
||||
*argv++ = sp->text;
|
||||
}
|
||||
*argv = NULL;
|
||||
lastarg = NULL;
|
||||
if (iflag && funcnest == 0 && argc > 0)
|
||||
|
@ -628,7 +644,7 @@ evalcommand(cmd, flags, backcmd)
|
|||
argv -= argc;
|
||||
|
||||
/* Print the command if xflag is set. */
|
||||
if (xflag == 1) {
|
||||
if (xflag) {
|
||||
outc('+', &errout);
|
||||
for (sp = varlist.list ; sp ; sp = sp->next) {
|
||||
outc(' ', &errout);
|
||||
|
@ -647,11 +663,42 @@ evalcommand(cmd, flags, backcmd)
|
|||
cmdentry.cmdtype = CMDBUILTIN;
|
||||
cmdentry.u.index = BLTINCMD;
|
||||
} else {
|
||||
find_command(argv[0], &cmdentry, 1);
|
||||
static const char PATH[] = "PATH=";
|
||||
char *path = pathval();
|
||||
|
||||
/*
|
||||
* Modify the command lookup path, if a PATH= assignment
|
||||
* is present
|
||||
*/
|
||||
for (sp = varlist.list ; sp ; sp = sp->next)
|
||||
if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) {
|
||||
path = sp->text + sizeof(PATH) - 1;
|
||||
/*
|
||||
* On `PATH=... command`, we need to make
|
||||
* sure that the command isn't using the
|
||||
* non-updated hash table of the outer PATH
|
||||
* setting and we need to make sure that
|
||||
* the hash table isn't filled with items
|
||||
* from the temporary setting.
|
||||
*
|
||||
* It would be better to forbit using and
|
||||
* updating the table while this command
|
||||
* runs, by the command finding mechanism
|
||||
* is heavily integrated with hash handling,
|
||||
* so we just delete the hash before and after
|
||||
* the command runs. Partly deleting like
|
||||
* changepatch() does doesn't seem worth the
|
||||
* bookinging effort, since most such runs add
|
||||
* directories in front of the new PATH.
|
||||
*/
|
||||
clearcmdentry(0);
|
||||
do_clearcmdentry = 1;
|
||||
}
|
||||
|
||||
find_command(argv[0], &cmdentry, 1, path);
|
||||
if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */
|
||||
exitstatus = 2;
|
||||
exitstatus = 127;
|
||||
flushout(&errout);
|
||||
popstackmark(&smark);
|
||||
return;
|
||||
}
|
||||
/* implement the bltin builtin here */
|
||||
|
@ -662,9 +709,8 @@ evalcommand(cmd, flags, backcmd)
|
|||
break;
|
||||
if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
|
||||
outfmt(&errout, "%s: not found\n", *argv);
|
||||
exitstatus = 2;
|
||||
exitstatus = 127;
|
||||
flushout(&errout);
|
||||
popstackmark(&smark);
|
||||
return;
|
||||
}
|
||||
if (cmdentry.u.index != BLTINCMD)
|
||||
|
@ -675,17 +721,21 @@ evalcommand(cmd, flags, backcmd)
|
|||
|
||||
/* Fork off a child process if necessary. */
|
||||
if (cmd->ncmd.backgnd
|
||||
|| cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0
|
||||
|| (flags & EV_BACKCMD) != 0
|
||||
|| (cmdentry.cmdtype == CMDNORMAL
|
||||
&& ((flags & EV_EXIT) == 0 || Tflag))
|
||||
|| ((flags & EV_BACKCMD) != 0
|
||||
&& (cmdentry.cmdtype != CMDBUILTIN
|
||||
|| cmdentry.u.index == CDCMD
|
||||
|| cmdentry.u.index == DOTCMD
|
||||
|| cmdentry.u.index == EVALCMD)) {
|
||||
|| cmdentry.u.index == EVALCMD))
|
||||
|| (cmdentry.cmdtype == CMDBUILTIN &&
|
||||
cmdentry.u.index == COMMANDCMD)) {
|
||||
jp = makejob(cmd, 1);
|
||||
mode = cmd->ncmd.backgnd;
|
||||
if (flags & EV_BACKCMD) {
|
||||
mode = FORK_NOJOB;
|
||||
if (pipe(pip) < 0)
|
||||
error("Pipe call failed");
|
||||
error("Pipe call failed: %s", strerror(errno));
|
||||
}
|
||||
if (forkshell(jp, cmd, mode) != 0)
|
||||
goto parent; /* at end of routine */
|
||||
|
@ -693,8 +743,7 @@ evalcommand(cmd, flags, backcmd)
|
|||
FORCEINTON;
|
||||
close(pip[0]);
|
||||
if (pip[1] != 1) {
|
||||
close(1);
|
||||
copyfd(pip[1], 1);
|
||||
dup2(pip[1], 1);
|
||||
close(pip[1]);
|
||||
}
|
||||
}
|
||||
|
@ -704,10 +753,13 @@ evalcommand(cmd, flags, backcmd)
|
|||
/* This is the child process if a fork occurred. */
|
||||
/* Execute the command. */
|
||||
if (cmdentry.cmdtype == CMDFUNCTION) {
|
||||
#if DEBUG
|
||||
trputs("Shell function: "); trargs(argv);
|
||||
#endif
|
||||
redirect(cmd->ncmd.redirect, REDIR_PUSH);
|
||||
saveparam = shellparam;
|
||||
shellparam.malloc = 0;
|
||||
shellparam.reset = 1;
|
||||
shellparam.nparam = argc - 1;
|
||||
shellparam.p = argv + 1;
|
||||
shellparam.optnext = NULL;
|
||||
|
@ -752,7 +804,9 @@ evalcommand(cmd, flags, backcmd)
|
|||
if (flags & EV_EXIT)
|
||||
exitshell(exitstatus);
|
||||
} else if (cmdentry.cmdtype == CMDBUILTIN) {
|
||||
#if DEBUG
|
||||
trputs("builtin command: "); trargs(argv);
|
||||
#endif
|
||||
mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH;
|
||||
if (flags == EV_BACKCMD) {
|
||||
memout.nleft = 0;
|
||||
|
@ -777,6 +831,7 @@ evalcommand(cmd, flags, backcmd)
|
|||
exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv);
|
||||
flushall();
|
||||
cmddone:
|
||||
cmdenviron = NULL;
|
||||
out1 = &output;
|
||||
out2 = &errout;
|
||||
freestdout();
|
||||
|
@ -788,10 +843,15 @@ cmddone:
|
|||
}
|
||||
handler = savehandler;
|
||||
if (e != -1) {
|
||||
if (e != EXERROR || cmdentry.u.index == BLTINCMD
|
||||
|| cmdentry.u.index == DOTCMD
|
||||
|| cmdentry.u.index == EVALCMD
|
||||
|| cmdentry.u.index == EXECCMD)
|
||||
if ((e != EXERROR && e != EXEXEC)
|
||||
|| cmdentry.u.index == BLTINCMD
|
||||
|| cmdentry.u.index == DOTCMD
|
||||
|| cmdentry.u.index == EVALCMD
|
||||
#ifndef NO_HISTORY
|
||||
|| cmdentry.u.index == HISTCMD
|
||||
#endif
|
||||
|| cmdentry.u.index == EXECCMD
|
||||
|| cmdentry.u.index == COMMANDCMD)
|
||||
exraise(e);
|
||||
FORCEINTON;
|
||||
}
|
||||
|
@ -803,19 +863,15 @@ cmddone:
|
|||
memout.buf = NULL;
|
||||
}
|
||||
} else {
|
||||
#if DEBUG
|
||||
trputs("normal command: "); trargs(argv);
|
||||
#endif
|
||||
clearredir();
|
||||
redirect(cmd->ncmd.redirect, 0);
|
||||
if (varlist.list) {
|
||||
p = stalloc(strlen(pathval()) + 1);
|
||||
scopy(pathval(), p);
|
||||
} else {
|
||||
p = pathval();
|
||||
}
|
||||
for (sp = varlist.list ; sp ; sp = sp->next)
|
||||
setvareq(sp->text, VEXPORT|VSTACK);
|
||||
envp = environment();
|
||||
shellexec(argv, envp, p, cmdentry.u.index);
|
||||
shellexec(argv, envp, pathval(), cmdentry.u.index);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
goto out;
|
||||
|
@ -823,8 +879,12 @@ cmddone:
|
|||
parent: /* parent process gets here (if we forked) */
|
||||
if (mode == 0) { /* argument to fork */
|
||||
INTOFF;
|
||||
exitstatus = waitforjob(jp);
|
||||
exitstatus = waitforjob(jp, &realstatus);
|
||||
INTON;
|
||||
if (iflag && loopnest > 0 && WIFSIGNALED(realstatus)) {
|
||||
evalskip = SKIPBREAK;
|
||||
skipcount = loopnest;
|
||||
}
|
||||
} else if (mode == 2) {
|
||||
backcmd->fd = pip[0];
|
||||
close(pip[1]);
|
||||
|
@ -834,6 +894,8 @@ parent: /* parent process gets here (if we forked) */
|
|||
out:
|
||||
if (lastarg)
|
||||
setvar("_", lastarg, 0);
|
||||
if (do_clearcmdentry)
|
||||
clearcmdentry(0);
|
||||
popstackmark(&smark);
|
||||
}
|
||||
|
||||
|
@ -847,13 +909,14 @@ out:
|
|||
*/
|
||||
|
||||
STATIC void
|
||||
prehash(n)
|
||||
union node *n;
|
||||
{
|
||||
prehash(union node *n)
|
||||
{
|
||||
struct cmdentry entry;
|
||||
|
||||
if (n->type == NCMD && goodname(n->ncmd.args->narg.text))
|
||||
find_command(n->ncmd.args->narg.text, &entry, 0);
|
||||
if (n->type == NCMD && n->ncmd.args)
|
||||
if (goodname(n->ncmd.args->narg.text))
|
||||
find_command(n->ncmd.args->narg.text, &entry, 0,
|
||||
pathval());
|
||||
}
|
||||
|
||||
|
||||
|
@ -868,8 +931,14 @@ prehash(n)
|
|||
* specified variables.
|
||||
*/
|
||||
|
||||
bltincmd(argc, argv) char **argv; {
|
||||
int
|
||||
bltincmd(int argc __unused, char **argv __unused)
|
||||
{
|
||||
listsetvar(cmdenviron);
|
||||
/*
|
||||
* Preserve exitstatus of a previous possible redirection
|
||||
* as POSIX mandates
|
||||
*/
|
||||
return exitstatus;
|
||||
}
|
||||
|
||||
|
@ -885,12 +954,11 @@ bltincmd(argc, argv) char **argv; {
|
|||
* in the standard shell so we don't make it one here.
|
||||
*/
|
||||
|
||||
breakcmd(argc, argv) char **argv; {
|
||||
int n;
|
||||
int
|
||||
breakcmd(int argc, char **argv)
|
||||
{
|
||||
int n = argc > 1 ? number(argv[1]) : 1;
|
||||
|
||||
n = 1;
|
||||
if (argc > 1)
|
||||
n = number(argv[1]);
|
||||
if (n > loopnest)
|
||||
n = loopnest;
|
||||
if (n > 0) {
|
||||
|
@ -900,40 +968,108 @@ breakcmd(argc, argv) char **argv; {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The `command' command.
|
||||
*/
|
||||
int
|
||||
commandcmd(int argc, char **argv)
|
||||
{
|
||||
static char stdpath[] = _PATH_STDPATH;
|
||||
struct jmploc loc, *old;
|
||||
struct strlist *sp;
|
||||
char *path;
|
||||
int ch;
|
||||
|
||||
for (sp = cmdenviron; sp ; sp = sp->next)
|
||||
setvareq(sp->text, VEXPORT|VSTACK);
|
||||
path = pathval();
|
||||
|
||||
optind = optreset = 1;
|
||||
opterr = 0;
|
||||
while ((ch = getopt(argc, argv, "p")) != -1) {
|
||||
switch (ch) {
|
||||
case 'p':
|
||||
path = stdpath;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
error("unknown option: -%c", optopt);
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 0) {
|
||||
old = handler;
|
||||
handler = &loc;
|
||||
if (setjmp(handler->loc) == 0)
|
||||
shellexec(argv, environment(), path, 0);
|
||||
handler = old;
|
||||
if (exception == EXEXEC)
|
||||
exit(exerrno);
|
||||
exraise(exception);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do nothing successfully if no command was specified;
|
||||
* ksh also does this.
|
||||
*/
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The return command.
|
||||
*/
|
||||
|
||||
returncmd(argc, argv) char **argv; {
|
||||
int ret;
|
||||
int
|
||||
returncmd(int argc, char **argv)
|
||||
{
|
||||
int ret = argc > 1 ? number(argv[1]) : oexitstatus;
|
||||
|
||||
ret = oexitstatus;
|
||||
if (argc > 1)
|
||||
ret = number(argv[1]);
|
||||
if (funcnest) {
|
||||
evalskip = SKIPFUNC;
|
||||
skipcount = 1;
|
||||
} else {
|
||||
/* skip the rest of the file */
|
||||
evalskip = SKIPFILE;
|
||||
skipcount = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
truecmd(argc, argv) char **argv; {
|
||||
return strcmp(argv[0], "false") == 0 ? 1 : 0;
|
||||
int
|
||||
falsecmd(int argc __unused, char **argv __unused)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
execcmd(argc, argv) char **argv; {
|
||||
int
|
||||
truecmd(int argc __unused, char **argv __unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
execcmd(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1) {
|
||||
struct strlist *sp;
|
||||
|
||||
iflag = 0; /* exit on error */
|
||||
setinteractive(0);
|
||||
#if JOBS
|
||||
jflag = 0;
|
||||
setjobctl(0);
|
||||
#endif
|
||||
mflag = 0;
|
||||
optschanged();
|
||||
for (sp = cmdenviron; sp ; sp = sp->next)
|
||||
setvareq(sp->text, VEXPORT|VSTACK);
|
||||
shellexec(argv + 1, environment(), pathval(), 0);
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: eval.c,v 1.7 2006/04/10 14:46:14 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -33,7 +29,8 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)eval.h 5.2 (Berkeley) 4/12/91
|
||||
* @(#)eval.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/eval.h,v 1.10 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
extern char *commandname; /* currently executing command */
|
||||
|
@ -48,18 +45,30 @@ struct backcmd { /* result of evalbackcmd */
|
|||
struct job *jp; /* job structure for command */
|
||||
};
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
int evalcmd(int, char **);
|
||||
void evalstring(char *);
|
||||
union node; /* BLETCH for ansi C */
|
||||
void evaltree(union node *, int);
|
||||
void evalbackcmd(union node *, struct backcmd *);
|
||||
#else
|
||||
void evalstring();
|
||||
void evaltree();
|
||||
void evalbackcmd();
|
||||
#endif
|
||||
int bltincmd(int, char **);
|
||||
int breakcmd(int, char **);
|
||||
int returncmd(int, char **);
|
||||
int falsecmd(int, char **);
|
||||
int truecmd(int, char **);
|
||||
int execcmd(int, char **);
|
||||
int commandcmd(int, char **);
|
||||
|
||||
/* in_function returns nonzero if we are currently evaluating a function */
|
||||
#define in_function() funcnest
|
||||
extern int funcnest;
|
||||
extern int evalskip;
|
||||
|
||||
/* reasons for skipping commands (see comment on breakcmd routine) */
|
||||
#define SKIPBREAK 1
|
||||
#define SKIPCONT 2
|
||||
#define SKIPFUNC 3
|
||||
#define SKIPFILE 4
|
||||
|
||||
/*
|
||||
* $PchId: eval.h,v 1.3 2006/03/30 15:39:25 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -35,8 +31,21 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)exec.c 5.2 (Berkeley) 3/13/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)exec.c 8.4 (Berkeley) 6/8/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/exec.c,v 1.24.2.1 2004/09/30 04:41:55 des Exp $");
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* When commands are first encountered, they are entered in a hash table.
|
||||
|
@ -64,11 +73,9 @@ static char sccsid[] = "@(#)exec.c 5.2 (Berkeley) 3/13/91";
|
|||
#include "error.h"
|
||||
#include "init.h"
|
||||
#include "mystring.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include "show.h"
|
||||
#include "jobs.h"
|
||||
#include "alias.h"
|
||||
|
||||
|
||||
#define CMDTABLESIZE 31 /* should be prime */
|
||||
|
@ -87,23 +94,14 @@ struct tblentry {
|
|||
|
||||
STATIC struct tblentry *cmdtable[CMDTABLESIZE];
|
||||
STATIC int builtinloc = -1; /* index in path of %builtin, or -1 */
|
||||
int exerrno = 0; /* Last exec error */
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
STATIC void tryexec(char *, char **, char **);
|
||||
STATIC void execinterp(char **, char **);
|
||||
STATIC void printentry(struct tblentry *);
|
||||
STATIC void clearcmdentry(int);
|
||||
STATIC void printentry(struct tblentry *, int);
|
||||
STATIC struct tblentry *cmdlookup(char *, int);
|
||||
STATIC void delete_cmd_entry(void);
|
||||
#else
|
||||
STATIC void tryexec();
|
||||
STATIC void execinterp();
|
||||
STATIC void printentry();
|
||||
STATIC void clearcmdentry();
|
||||
STATIC struct tblentry *cmdlookup();
|
||||
STATIC void delete_cmd_entry();
|
||||
#endif
|
||||
STATIC void addcmdentry(char *, struct cmdentry *);
|
||||
|
||||
|
||||
|
||||
|
@ -113,10 +111,8 @@ STATIC void delete_cmd_entry();
|
|||
*/
|
||||
|
||||
void
|
||||
shellexec(argv, envp, path, index)
|
||||
char **argv, **envp;
|
||||
char *path;
|
||||
{
|
||||
shellexec(char **argv, char **envp, char *path, int index)
|
||||
{
|
||||
char *cmdname;
|
||||
int e;
|
||||
|
||||
|
@ -134,40 +130,37 @@ shellexec(argv, envp, path, index)
|
|||
stunalloc(cmdname);
|
||||
}
|
||||
}
|
||||
error2(argv[0], errmsg(e, E_EXEC));
|
||||
|
||||
/* Map to POSIX errors */
|
||||
switch (e) {
|
||||
case EACCES:
|
||||
exerrno = 126;
|
||||
break;
|
||||
case ENOENT:
|
||||
exerrno = 127;
|
||||
break;
|
||||
default:
|
||||
exerrno = 2;
|
||||
break;
|
||||
}
|
||||
if (e == ENOENT || e == ENOTDIR)
|
||||
exerror(EXEXEC, "%s: not found", argv[0]);
|
||||
exerror(EXEXEC, "%s: %s", argv[0], strerror(e));
|
||||
}
|
||||
|
||||
|
||||
STATIC void
|
||||
tryexec(cmd, argv, envp)
|
||||
char *cmd;
|
||||
char **argv;
|
||||
char **envp;
|
||||
{
|
||||
tryexec(char *cmd, char **argv, char **envp)
|
||||
{
|
||||
int e;
|
||||
char *p;
|
||||
|
||||
#ifdef SYSV
|
||||
do {
|
||||
execve(cmd, argv, envp);
|
||||
} while (errno == EINTR);
|
||||
#else
|
||||
execve(cmd, argv, envp);
|
||||
#endif
|
||||
#if HASHBANG
|
||||
#if !__minix_vmd
|
||||
e = errno;
|
||||
if (e == ENOEXEC) {
|
||||
initshellproc();
|
||||
setinputfile(cmd, 0);
|
||||
commandname = arg0 = savestr(argv[0]);
|
||||
#ifndef BSD
|
||||
pgetc(); pungetc(); /* fill up input buffer */
|
||||
p = parsenextc;
|
||||
if (parsenleft > 2 && p[0] == '#' && p[1] == '!') {
|
||||
argv[0] = cmd;
|
||||
execinterp(argv, envp);
|
||||
}
|
||||
#endif
|
||||
setparam(argv + 1);
|
||||
exraise(EXSHELLPROC);
|
||||
/*NOTREACHED*/
|
||||
|
@ -176,88 +169,6 @@ tryexec(cmd, argv, envp)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if !defined(BSD) && HASHBANG
|
||||
/*
|
||||
* Execute an interpreter introduced by "#!", for systems where this
|
||||
* feature has not been built into the kernel. If the interpreter is
|
||||
* the shell, return (effectively ignoring the "#!"). If the execution
|
||||
* of the interpreter fails, exit.
|
||||
*
|
||||
* This code peeks inside the input buffer in order to avoid actually
|
||||
* reading any input. It would benefit from a rewrite.
|
||||
*/
|
||||
|
||||
#define NEWARGS 5
|
||||
|
||||
STATIC void
|
||||
execinterp(argv, envp)
|
||||
char **argv, **envp;
|
||||
{
|
||||
int n;
|
||||
char *inp;
|
||||
char *outp;
|
||||
char c;
|
||||
char *p;
|
||||
char **ap;
|
||||
char *newargs[NEWARGS];
|
||||
int i;
|
||||
char **ap2;
|
||||
char **new;
|
||||
|
||||
n = parsenleft - 2;
|
||||
inp = parsenextc + 2;
|
||||
ap = newargs;
|
||||
for (;;) {
|
||||
while (--n >= 0 && (*inp == ' ' || *inp == '\t'))
|
||||
inp++;
|
||||
if (n < 0)
|
||||
goto bad;
|
||||
if ((c = *inp++) == '\n')
|
||||
break;
|
||||
if (ap == &newargs[NEWARGS])
|
||||
bad: error("Bad #! line");
|
||||
STARTSTACKSTR(outp);
|
||||
do {
|
||||
STPUTC(c, outp);
|
||||
} while (--n >= 0 && (c = *inp++) != ' ' && c != '\t' && c != '\n');
|
||||
STPUTC('\0', outp);
|
||||
n++, inp--;
|
||||
*ap++ = grabstackstr(outp);
|
||||
}
|
||||
#if !__minix
|
||||
if (ap == newargs + 1) { /* if no args, maybe no exec is needed */
|
||||
p = newargs[0];
|
||||
for (;;) {
|
||||
if (equal(p, "sh") || equal(p, "ash")) {
|
||||
return;
|
||||
}
|
||||
while (*p != '/') {
|
||||
if (*p == '\0')
|
||||
goto break2;
|
||||
p++;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
break2:;
|
||||
}
|
||||
#endif
|
||||
i = (char *)ap - (char *)newargs; /* size in bytes */
|
||||
if (i == 0)
|
||||
error("Bad #! line");
|
||||
for (ap2 = argv ; *ap2++ != NULL ; );
|
||||
new = ckmalloc(i + ((char *)ap2 - (char *)argv));
|
||||
ap = newargs, ap2 = new;
|
||||
while ((i -= sizeof (char **)) >= 0)
|
||||
*ap2++ = *ap++;
|
||||
ap = argv;
|
||||
while (*ap2++ = *ap++);
|
||||
shellexec(new, envp, pathval(), 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Do a path search. The variable path (passed by reference) should be
|
||||
* set to the start of the path before the first call; padvance will update
|
||||
|
@ -271,11 +182,9 @@ break2:;
|
|||
char *pathopt;
|
||||
|
||||
char *
|
||||
padvance(path, name)
|
||||
char **path;
|
||||
char *name;
|
||||
{
|
||||
register char *p, *q;
|
||||
padvance(char **path, char *name)
|
||||
{
|
||||
char *p, *q;
|
||||
char *start;
|
||||
int len;
|
||||
|
||||
|
@ -288,7 +197,7 @@ padvance(path, name)
|
|||
growstackblock();
|
||||
q = stackblock();
|
||||
if (p != start) {
|
||||
bcopy(start, q, p - start);
|
||||
memcpy(q, start, p - start);
|
||||
q += p - start;
|
||||
*q++ = '/';
|
||||
}
|
||||
|
@ -310,7 +219,9 @@ padvance(path, name)
|
|||
/*** Command hashing code ***/
|
||||
|
||||
|
||||
hashcmd(argc, argv) char **argv; {
|
||||
int
|
||||
hashcmd(int argc __unused, char **argv __unused)
|
||||
{
|
||||
struct tblentry **pp;
|
||||
struct tblentry *cmdp;
|
||||
int c;
|
||||
|
@ -318,14 +229,6 @@ hashcmd(argc, argv) char **argv; {
|
|||
struct cmdentry entry;
|
||||
char *name;
|
||||
|
||||
if (argc <= 1) {
|
||||
for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
|
||||
for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
|
||||
printentry(cmdp);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
verbose = 0;
|
||||
while ((c = nextopt("rv")) != '\0') {
|
||||
if (c == 'r') {
|
||||
|
@ -334,16 +237,28 @@ hashcmd(argc, argv) char **argv; {
|
|||
verbose++;
|
||||
}
|
||||
}
|
||||
if (*argptr == NULL) {
|
||||
for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
|
||||
for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
|
||||
if (cmdp->cmdtype == CMDNORMAL)
|
||||
printentry(cmdp, verbose);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
while ((name = *argptr) != NULL) {
|
||||
if ((cmdp = cmdlookup(name, 0)) != NULL
|
||||
&& (cmdp->cmdtype == CMDNORMAL
|
||||
|| cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
|
||||
|| (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
|
||||
delete_cmd_entry();
|
||||
find_command(name, &entry, 1);
|
||||
find_command(name, &entry, 1, pathval());
|
||||
if (verbose) {
|
||||
if (entry.cmdtype != CMDUNKNOWN) { /* if no error msg */
|
||||
cmdp = cmdlookup(name, 0);
|
||||
printentry(cmdp);
|
||||
if (cmdp != NULL)
|
||||
printentry(cmdp, verbose);
|
||||
else
|
||||
outfmt(&errout, "%s: not found\n", name);
|
||||
}
|
||||
flushall();
|
||||
}
|
||||
|
@ -354,9 +269,8 @@ hashcmd(argc, argv) char **argv; {
|
|||
|
||||
|
||||
STATIC void
|
||||
printentry(cmdp)
|
||||
struct tblentry *cmdp;
|
||||
{
|
||||
printentry(struct tblentry *cmdp, int verbose)
|
||||
{
|
||||
int index;
|
||||
char *path;
|
||||
char *name;
|
||||
|
@ -373,6 +287,14 @@ printentry(cmdp)
|
|||
out1fmt("builtin %s", cmdp->cmdname);
|
||||
} else if (cmdp->cmdtype == CMDFUNCTION) {
|
||||
out1fmt("function %s", cmdp->cmdname);
|
||||
if (verbose) {
|
||||
INTOFF;
|
||||
name = commandtext(cmdp->param.func);
|
||||
out1c(' ');
|
||||
out1str(name);
|
||||
ckfree(name);
|
||||
INTON;
|
||||
}
|
||||
#if DEBUG
|
||||
} else {
|
||||
error("internal error: cmdtype %d", cmdp->cmdtype);
|
||||
|
@ -391,14 +313,11 @@ printentry(cmdp)
|
|||
*/
|
||||
|
||||
void
|
||||
find_command(name, entry, printerr)
|
||||
char *name;
|
||||
struct cmdentry *entry;
|
||||
{
|
||||
find_command(char *name, struct cmdentry *entry, int printerr, char *path)
|
||||
{
|
||||
struct tblentry *cmdp;
|
||||
int index;
|
||||
int prev;
|
||||
char *path;
|
||||
char *fullname;
|
||||
struct stat statb;
|
||||
int e;
|
||||
|
@ -434,7 +353,6 @@ find_command(name, entry, printerr)
|
|||
prev = cmdp->param.index;
|
||||
}
|
||||
|
||||
path = pathval();
|
||||
e = ENOENT;
|
||||
index = -1;
|
||||
loop:
|
||||
|
@ -464,17 +382,13 @@ loop:
|
|||
TRACE(("searchexec \"%s\": no change\n", name));
|
||||
goto success;
|
||||
}
|
||||
while (stat(fullname, &statb) < 0) {
|
||||
#ifdef SYSV
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
#endif
|
||||
if (stat(fullname, &statb) < 0) {
|
||||
if (errno != ENOENT && errno != ENOTDIR)
|
||||
e = errno;
|
||||
goto loop;
|
||||
}
|
||||
e = EACCES; /* if we fail, this will be the error */
|
||||
if ((statb.st_mode & S_IFMT) != S_IFREG)
|
||||
if (!S_ISREG(statb.st_mode))
|
||||
goto loop;
|
||||
if (pathopt) { /* this is a %func directory */
|
||||
stalloc(strlen(fullname) + 1);
|
||||
|
@ -484,6 +398,7 @@ loop:
|
|||
stunalloc(fullname);
|
||||
goto success;
|
||||
}
|
||||
#ifdef notdef
|
||||
if (statb.st_uid == geteuid()) {
|
||||
if ((statb.st_mode & 0100) == 0)
|
||||
goto loop;
|
||||
|
@ -491,23 +406,10 @@ loop:
|
|||
if ((statb.st_mode & 010) == 0)
|
||||
goto loop;
|
||||
} else {
|
||||
#if __minix_vmd || defined(BSD)
|
||||
gid_t group_list[NGROUPS_MAX];
|
||||
int ngroups, i;
|
||||
|
||||
ngroups = getgroups(NGROUPS_MAX, group_list);
|
||||
|
||||
for (i = 0; i < ngroups; i++) {
|
||||
if (statb.st_gid == group_list[i]) break;
|
||||
}
|
||||
if (i < ngroups) {
|
||||
if ((statb.st_mode & 010) == 0)
|
||||
goto loop;
|
||||
} else
|
||||
#endif
|
||||
if ((statb.st_mode & 01) == 0)
|
||||
goto loop;
|
||||
}
|
||||
#endif
|
||||
TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
|
||||
INTOFF;
|
||||
cmdp = cmdlookup(name, 1);
|
||||
|
@ -520,8 +422,12 @@ loop:
|
|||
/* We failed. If there was an entry for this command, delete it */
|
||||
if (cmdp)
|
||||
delete_cmd_entry();
|
||||
if (printerr)
|
||||
outfmt(out2, "%s: %s\n", name, errmsg(e, E_EXEC));
|
||||
if (printerr) {
|
||||
if (e == ENOENT || e == ENOTDIR)
|
||||
outfmt(out2, "%s: not found\n", name);
|
||||
else
|
||||
outfmt(out2, "%s: %s\n", name, strerror(e));
|
||||
}
|
||||
entry->cmdtype = CMDUNKNOWN;
|
||||
return;
|
||||
|
||||
|
@ -538,10 +444,9 @@ success:
|
|||
*/
|
||||
|
||||
int
|
||||
find_builtin(name)
|
||||
char *name;
|
||||
{
|
||||
const register struct builtincmd *bp;
|
||||
find_builtin(char *name)
|
||||
{
|
||||
const struct builtincmd *bp;
|
||||
|
||||
for (bp = builtincmd ; bp->name ; bp++) {
|
||||
if (*bp->name == *name && equal(bp->name, name))
|
||||
|
@ -558,14 +463,15 @@ find_builtin(name)
|
|||
*/
|
||||
|
||||
void
|
||||
hashcd() {
|
||||
hashcd(void)
|
||||
{
|
||||
struct tblentry **pp;
|
||||
struct tblentry *cmdp;
|
||||
|
||||
for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
|
||||
for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
|
||||
if (cmdp->cmdtype == CMDNORMAL
|
||||
|| cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)
|
||||
|| (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
|
||||
cmdp->rehash = 1;
|
||||
}
|
||||
}
|
||||
|
@ -580,10 +486,9 @@ hashcd() {
|
|||
*/
|
||||
|
||||
void
|
||||
changepath(newval)
|
||||
char *newval;
|
||||
{
|
||||
char *old, *new;
|
||||
changepath(const char *newval)
|
||||
{
|
||||
const char *old, *new;
|
||||
int index;
|
||||
int firstchange;
|
||||
int bltin;
|
||||
|
@ -596,8 +501,8 @@ changepath(newval)
|
|||
for (;;) {
|
||||
if (*old != *new) {
|
||||
firstchange = index;
|
||||
if (*old == '\0' && *new == ':'
|
||||
|| *old == ':' && *new == '\0')
|
||||
if ((*old == '\0' && *new == ':')
|
||||
|| (*old == ':' && *new == '\0'))
|
||||
firstchange++;
|
||||
old = new; /* ignore subsequent differences */
|
||||
}
|
||||
|
@ -624,8 +529,9 @@ changepath(newval)
|
|||
* PATH which has changed.
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
clearcmdentry(firstchange) {
|
||||
void
|
||||
clearcmdentry(int firstchange)
|
||||
{
|
||||
struct tblentry **tblp;
|
||||
struct tblentry **pp;
|
||||
struct tblentry *cmdp;
|
||||
|
@ -634,8 +540,10 @@ clearcmdentry(firstchange) {
|
|||
for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
|
||||
pp = tblp;
|
||||
while ((cmdp = *pp) != NULL) {
|
||||
if (cmdp->cmdtype == CMDNORMAL && cmdp->param.index >= firstchange
|
||||
|| cmdp->cmdtype == CMDBUILTIN && builtinloc >= firstchange) {
|
||||
if ((cmdp->cmdtype == CMDNORMAL &&
|
||||
cmdp->param.index >= firstchange)
|
||||
|| (cmdp->cmdtype == CMDBUILTIN &&
|
||||
builtinloc >= firstchange)) {
|
||||
*pp = cmdp->next;
|
||||
ckfree(cmdp);
|
||||
} else {
|
||||
|
@ -652,15 +560,15 @@ clearcmdentry(firstchange) {
|
|||
*/
|
||||
|
||||
#ifdef mkinit
|
||||
MKINIT void deletefuncs();
|
||||
|
||||
INCLUDE "exec.h"
|
||||
SHELLPROC {
|
||||
deletefuncs();
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
deletefuncs() {
|
||||
deletefuncs(void)
|
||||
{
|
||||
struct tblentry **tblp;
|
||||
struct tblentry **pp;
|
||||
struct tblentry *cmdp;
|
||||
|
@ -691,15 +599,14 @@ deletefuncs() {
|
|||
* entry.
|
||||
*/
|
||||
|
||||
struct tblentry **lastcmdentry;
|
||||
STATIC struct tblentry **lastcmdentry;
|
||||
|
||||
|
||||
STATIC struct tblentry *
|
||||
cmdlookup(name, add)
|
||||
char *name;
|
||||
{
|
||||
cmdlookup(char *name, int add)
|
||||
{
|
||||
int hashval;
|
||||
register char *p;
|
||||
char *p;
|
||||
struct tblentry *cmdp;
|
||||
struct tblentry **pp;
|
||||
|
||||
|
@ -728,13 +635,13 @@ cmdlookup(name, add)
|
|||
return cmdp;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Delete the command entry returned on the last lookup.
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
delete_cmd_entry() {
|
||||
delete_cmd_entry(void)
|
||||
{
|
||||
struct tblentry *cmdp;
|
||||
|
||||
INTOFF;
|
||||
|
@ -746,35 +653,14 @@ delete_cmd_entry() {
|
|||
|
||||
|
||||
|
||||
#ifdef notdef
|
||||
void
|
||||
getcmdentry(name, entry)
|
||||
char *name;
|
||||
struct cmdentry *entry;
|
||||
{
|
||||
struct tblentry *cmdp = cmdlookup(name, 0);
|
||||
|
||||
if (cmdp) {
|
||||
entry->u = cmdp->param;
|
||||
entry->cmdtype = cmdp->cmdtype;
|
||||
} else {
|
||||
entry->cmdtype = CMDUNKNOWN;
|
||||
entry->u.index = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Add a new command entry, replacing any existing command entry for
|
||||
* the same name.
|
||||
*/
|
||||
|
||||
void
|
||||
addcmdentry(name, entry)
|
||||
char *name;
|
||||
struct cmdentry *entry;
|
||||
{
|
||||
static void
|
||||
addcmdentry(char *name, struct cmdentry *entry)
|
||||
{
|
||||
struct tblentry *cmdp;
|
||||
|
||||
INTOFF;
|
||||
|
@ -793,10 +679,8 @@ addcmdentry(name, entry)
|
|||
*/
|
||||
|
||||
void
|
||||
defun(name, func)
|
||||
char *name;
|
||||
union node *func;
|
||||
{
|
||||
defun(char *name, union node *func)
|
||||
{
|
||||
struct cmdentry entry;
|
||||
|
||||
INTOFF;
|
||||
|
@ -811,14 +695,98 @@ defun(name, func)
|
|||
* Delete a function if it exists.
|
||||
*/
|
||||
|
||||
void
|
||||
unsetfunc(name)
|
||||
char *name;
|
||||
{
|
||||
int
|
||||
unsetfunc(char *name)
|
||||
{
|
||||
struct tblentry *cmdp;
|
||||
|
||||
if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
|
||||
freefunc(cmdp->param.func);
|
||||
delete_cmd_entry();
|
||||
return (0);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Locate and print what a word is...
|
||||
*/
|
||||
|
||||
int
|
||||
typecmd(int argc, char **argv)
|
||||
{
|
||||
struct cmdentry entry;
|
||||
struct tblentry *cmdp;
|
||||
char **pp;
|
||||
struct alias *ap;
|
||||
int i;
|
||||
int error = 0;
|
||||
extern char *const parsekwd[];
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
out1str(argv[i]);
|
||||
/* First look at the keywords */
|
||||
for (pp = (char **)parsekwd; *pp; pp++)
|
||||
if (**pp == *argv[i] && equal(*pp, argv[i]))
|
||||
break;
|
||||
|
||||
if (*pp) {
|
||||
out1str(" is a shell keyword\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Then look at the aliases */
|
||||
if ((ap = lookupalias(argv[i], 1)) != NULL) {
|
||||
out1fmt(" is an alias for %s\n", ap->val);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Then check if it is a tracked alias */
|
||||
if ((cmdp = cmdlookup(argv[i], 0)) != NULL) {
|
||||
entry.cmdtype = cmdp->cmdtype;
|
||||
entry.u = cmdp->param;
|
||||
}
|
||||
else {
|
||||
/* Finally use brute force */
|
||||
find_command(argv[i], &entry, 0, pathval());
|
||||
}
|
||||
|
||||
switch (entry.cmdtype) {
|
||||
case CMDNORMAL: {
|
||||
if (strchr(argv[i], '/') == NULL) {
|
||||
char *path = pathval(), *name;
|
||||
int j = entry.u.index;
|
||||
do {
|
||||
name = padvance(&path, argv[i]);
|
||||
stunalloc(name);
|
||||
} while (--j >= 0);
|
||||
out1fmt(" is%s %s\n",
|
||||
cmdp ? " a tracked alias for" : "", name);
|
||||
} else {
|
||||
if (access(argv[i], X_OK) == 0)
|
||||
out1fmt(" is %s\n", argv[i]);
|
||||
else
|
||||
out1fmt(": %s\n", strerror(errno));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CMDFUNCTION:
|
||||
out1str(" is a shell function\n");
|
||||
break;
|
||||
|
||||
case CMDBUILTIN:
|
||||
out1str(" is a shell builtin\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
out1str(": not found\n");
|
||||
error |= 127;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: exec.c,v 1.6 2006/04/10 14:47:03 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -33,7 +29,8 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)exec.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)exec.h 8.3 (Berkeley) 6/8/95
|
||||
* $FreeBSD: src/bin/sh/exec.h,v 1.12 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
/* values of cmdtype */
|
||||
|
@ -53,23 +50,21 @@ struct cmdentry {
|
|||
|
||||
|
||||
extern char *pathopt; /* set by padvance */
|
||||
extern int exerrno; /* last exec error */
|
||||
|
||||
#ifdef __STDC__
|
||||
void shellexec(char **, char **, char *, int);
|
||||
char *padvance(char **, char *);
|
||||
void find_command(char *, struct cmdentry *, int);
|
||||
int hashcmd(int, char **);
|
||||
void find_command(char *, struct cmdentry *, int, char *);
|
||||
int find_builtin(char *);
|
||||
void hashcd(void);
|
||||
void changepath(char *);
|
||||
void changepath(const char *);
|
||||
void deletefuncs(void);
|
||||
void defun(char *, union node *);
|
||||
void unsetfunc(char *);
|
||||
#else
|
||||
void shellexec();
|
||||
char *padvance();
|
||||
void find_command();
|
||||
int find_builtin();
|
||||
void hashcd();
|
||||
void changepath();
|
||||
void defun();
|
||||
void unsetfunc();
|
||||
#endif
|
||||
int unsetfunc(char *);
|
||||
int typecmd(int, char **);
|
||||
void clearcmdentry(int);
|
||||
|
||||
/*
|
||||
* $PchId: exec.h,v 1.5 2006/04/10 14:47:34 philip Exp $
|
||||
*/
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -33,7 +29,8 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)expand.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)expand.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/expand.h,v 1.12 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
struct strlist {
|
||||
|
@ -47,17 +44,24 @@ struct arglist {
|
|||
struct strlist **lastp;
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
/*
|
||||
* expandarg() flags
|
||||
*/
|
||||
#define EXP_FULL 0x1 /* perform word splitting & file globbing */
|
||||
#define EXP_TILDE 0x2 /* do normal tilde expansion */
|
||||
#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
|
||||
#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
|
||||
#define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
|
||||
|
||||
|
||||
union node;
|
||||
void expandarg(union node *, struct arglist *, int);
|
||||
void expandhere(union node *, int);
|
||||
int patmatch(char *, char *);
|
||||
void expandarg(union node *, struct arglist *, int);
|
||||
int patmatch(char *, char *, int);
|
||||
void rmescapes(char *);
|
||||
int casematch(union node *, char *);
|
||||
#else
|
||||
void expandarg();
|
||||
void expandhere();
|
||||
int patmatch();
|
||||
void rmescapes();
|
||||
int casematch();
|
||||
#endif
|
||||
int wordexpcmd(int, char **);
|
||||
|
||||
/*
|
||||
* $PchId: expand.h,v 1.4 2006/03/30 14:50:52 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
|
@ -12,10 +12,6 @@
|
|||
# 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.
|
||||
|
@ -32,7 +28,8 @@
|
|||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)cmv 5.1 (Berkeley) 3/7/91
|
||||
# @(#)cmv 8.2 (Berkeley) 5/4/95
|
||||
# $FreeBSD: src/bin/sh/funcs/cmv,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||
|
||||
# Conditional move--don't replace an existing file.
|
||||
|
||||
|
@ -47,3 +44,6 @@ cmv() {
|
|||
fi
|
||||
/bin/mv "$1" "$2"
|
||||
}
|
||||
|
||||
#
|
||||
# $PchId: cmv,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
|
@ -12,10 +12,6 @@
|
|||
# 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.
|
||||
|
@ -32,7 +28,8 @@
|
|||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)dirs 5.1 (Berkeley) 3/7/91
|
||||
# @(#)dirs 8.2 (Berkeley) 5/4/95
|
||||
# $FreeBSD: src/bin/sh/funcs/dirs,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||
|
||||
# pushd, popd, and dirs --- written by Chris Bertin
|
||||
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
||||
|
@ -71,3 +68,6 @@ dirs () {
|
|||
echo "`pwd` $DSTACK"
|
||||
return 0
|
||||
}
|
||||
|
||||
#
|
||||
# $PchId: dirs,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
|
@ -12,10 +12,6 @@
|
|||
# 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.
|
||||
|
@ -32,7 +28,8 @@
|
|||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)kill 5.1 (Berkeley) 3/7/91
|
||||
# @(#)kill 8.2 (Berkeley) 5/4/95
|
||||
# $FreeBSD: src/bin/sh/funcs/kill,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||
|
||||
# Convert job names to process ids and then run /bin/kill.
|
||||
|
||||
|
@ -47,3 +44,6 @@ kill() {
|
|||
done
|
||||
/bin/kill $args
|
||||
}
|
||||
|
||||
#
|
||||
# $PchId: kill,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
|
@ -12,10 +12,6 @@
|
|||
# 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.
|
||||
|
@ -32,7 +28,11 @@
|
|||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)login 5.1 (Berkeley) 3/7/91
|
||||
# @(#)login 8.2 (Berkeley) 5/4/95
|
||||
# $FreeBSD: src/bin/sh/funcs/login,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||
|
||||
# replaces the login builtin in the BSD shell
|
||||
login () exec login "$@"
|
||||
|
||||
#
|
||||
# $PchId: login,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
|
@ -12,10 +12,6 @@
|
|||
# 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.
|
||||
|
@ -32,6 +28,10 @@
|
|||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)newgrp 5.1 (Berkeley) 3/7/91
|
||||
# @(#)newgrp 8.2 (Berkeley) 5/4/95
|
||||
# $FreeBSD: src/bin/sh/funcs/newgrp,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||
|
||||
newgrp() exec newgrp "$@"
|
||||
|
||||
#
|
||||
# $PchId: newgrp,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
|
@ -12,10 +12,6 @@
|
|||
# 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.
|
||||
|
@ -32,7 +28,8 @@
|
|||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)popd 5.1 (Berkeley) 3/7/91
|
||||
# @(#)popd 8.2 (Berkeley) 5/4/95
|
||||
# $FreeBSD: src/bin/sh/funcs/popd,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||
|
||||
# pushd, popd, and dirs --- written by Chris Bertin
|
||||
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
||||
|
@ -71,3 +68,6 @@ dirs () {
|
|||
echo "`pwd` $DSTACK"
|
||||
return 0
|
||||
}
|
||||
|
||||
#
|
||||
# $PchId: popd,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
|
@ -12,10 +12,6 @@
|
|||
# 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.
|
||||
|
@ -32,7 +28,8 @@
|
|||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)pushd 5.1 (Berkeley) 3/7/91
|
||||
# @(#)pushd 8.2 (Berkeley) 5/4/95
|
||||
# $FreeBSD: src/bin/sh/funcs/pushd,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||
|
||||
# pushd, popd, and dirs --- written by Chris Bertin
|
||||
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
||||
|
@ -71,3 +68,6 @@ dirs () {
|
|||
echo "`pwd` $DSTACK"
|
||||
return 0
|
||||
}
|
||||
|
||||
#
|
||||
# $PchId: pushd,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
|
@ -12,10 +12,6 @@
|
|||
# 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.
|
||||
|
@ -32,10 +28,14 @@
|
|||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)suspend 5.1 (Berkeley) 3/7/91
|
||||
# @(#)suspend 8.2 (Berkeley) 5/4/95
|
||||
# $FreeBSD: src/bin/sh/funcs/suspend,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||
|
||||
suspend() {
|
||||
local -
|
||||
set +j
|
||||
kill -TSTP 0
|
||||
}
|
||||
|
||||
#
|
||||
# $PchId: suspend,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||
|
|
533
commands/ash/histedit.c
Normal file
533
commands/ash/histedit.c
Normal file
|
@ -0,0 +1,533 @@
|
|||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* 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.
|
||||
* 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
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)histedit.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/histedit.c,v 1.26 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#ifndef NO_PATHS_H
|
||||
#include <paths.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
/*
|
||||
* Editline and history functions (and glue).
|
||||
*/
|
||||
#include "shell.h"
|
||||
#include "parser.h"
|
||||
#include "var.h"
|
||||
#include "options.h"
|
||||
#include "main.h"
|
||||
#include "output.h"
|
||||
#include "mystring.h"
|
||||
#include "builtins.h"
|
||||
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||
#include "myhistedit.h"
|
||||
#include "complete.h"
|
||||
#include "error.h"
|
||||
#include "eval.h"
|
||||
#include "memalloc.h"
|
||||
|
||||
#define MAXHISTLOOPS 4 /* max recursions through fc */
|
||||
#define DEFEDITOR "ed" /* default editor *should* be $EDITOR */
|
||||
|
||||
History *hist; /* history cookie */
|
||||
EditLine *el; /* editline cookie */
|
||||
int displayhist;
|
||||
static FILE *el_in, *el_out, *el_err;
|
||||
|
||||
STATIC char *fc_replace(const char *, char *, char *);
|
||||
STATIC int not_fcnumber(char *);
|
||||
STATIC int str_to_event(char *, int);
|
||||
|
||||
/*
|
||||
* Set history and editing status. Called whenever the status may
|
||||
* have changed (figures out what to do).
|
||||
*/
|
||||
void
|
||||
histedit(void)
|
||||
{
|
||||
|
||||
#define editing (Eflag || Vflag)
|
||||
|
||||
if (iflag) {
|
||||
if (!hist) {
|
||||
/*
|
||||
* turn history on
|
||||
*/
|
||||
INTOFF;
|
||||
hist = history_init();
|
||||
INTON;
|
||||
|
||||
if (hist != NULL)
|
||||
sethistsize(histsizeval());
|
||||
else
|
||||
out2str("sh: can't initialize history\n");
|
||||
}
|
||||
if (editing && !el && isatty(0)) { /* && isatty(2) ??? */
|
||||
/*
|
||||
* turn editing on
|
||||
*/
|
||||
INTOFF;
|
||||
if (el_in == NULL)
|
||||
el_in = fdopen(0, "r");
|
||||
if (el_err == NULL)
|
||||
el_err = fdopen(1, "w");
|
||||
if (el_out == NULL)
|
||||
el_out = fdopen(2, "w");
|
||||
if (el_in == NULL || el_err == NULL || el_out == NULL)
|
||||
goto bad;
|
||||
el = el_init(arg0, el_in, el_out, el_err);
|
||||
if (el != NULL) {
|
||||
if (hist)
|
||||
el_set(el, EL_HIST, history, hist);
|
||||
el_set(el, EL_PROMPT, getprompt);
|
||||
} else {
|
||||
bad:
|
||||
out2str("sh: can't initialize editing\n");
|
||||
}
|
||||
INTON;
|
||||
} else if (!editing && el) {
|
||||
INTOFF;
|
||||
el_end(el);
|
||||
el = NULL;
|
||||
INTON;
|
||||
}
|
||||
if (el) {
|
||||
if (Vflag)
|
||||
el_set(el, EL_EDITOR, "vi");
|
||||
else if (Eflag)
|
||||
el_set(el, EL_EDITOR, "emacs");
|
||||
el_set(el, EL_ADDFN, "ed-do-complete",
|
||||
"Complete Argument", complete);
|
||||
el_set(el, EL_ADDFN, "ed-list-complete",
|
||||
"List Argument Completions", complete_list);
|
||||
el_set(el, EL_ADDFN, "ed-maybe-complete",
|
||||
"Complete Argument Or List Completions",
|
||||
complete_or_list);
|
||||
el_set(el, EL_ADDFN, "ed-expand",
|
||||
"Expand Completions", complete_expand);
|
||||
el_set(el, EL_BIND, "^I", "ed-maybe-complete", NULL);
|
||||
el_set(el, EL_BIND, "-a", "=", "ed-list-complete",
|
||||
NULL);
|
||||
el_set(el, EL_BIND, "-a", "\\\\", "ed-do-complete",
|
||||
NULL);
|
||||
el_set(el, EL_BIND, "-a", "*", "ed-expand",
|
||||
NULL);
|
||||
el_source(el, NULL);
|
||||
}
|
||||
} else {
|
||||
INTOFF;
|
||||
if (el) { /* no editing if not interactive */
|
||||
el_end(el);
|
||||
el = NULL;
|
||||
}
|
||||
if (hist) {
|
||||
history_end(hist);
|
||||
hist = NULL;
|
||||
}
|
||||
INTON;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sethistsize(hs)
|
||||
const char *hs;
|
||||
{
|
||||
int histsize;
|
||||
HistEvent he;
|
||||
|
||||
if (hist != NULL) {
|
||||
if (hs == NULL || *hs == '\0' ||
|
||||
(histsize = atoi(hs)) < 0)
|
||||
histsize = 100;
|
||||
history(hist, &he, H_EVENT, histsize);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
histcmd(int argc, char **argv)
|
||||
{
|
||||
int ch;
|
||||
char *editor = NULL;
|
||||
HistEvent he;
|
||||
int lflg = 0, nflg = 0, rflg = 0, sflg = 0;
|
||||
int i, retval;
|
||||
char *firststr, *laststr;
|
||||
int first, last, direction;
|
||||
char *pat = NULL, *repl;
|
||||
static int active = 0;
|
||||
struct jmploc jmploc;
|
||||
struct jmploc *volatile savehandler;
|
||||
char editfile[PATH_MAX];
|
||||
FILE *efp;
|
||||
int oldhistnum;
|
||||
#ifdef __GNUC__
|
||||
/* Avoid longjmp clobbering */
|
||||
(void) &editor;
|
||||
(void) &lflg;
|
||||
(void) &nflg;
|
||||
(void) &rflg;
|
||||
(void) &sflg;
|
||||
(void) &firststr;
|
||||
(void) &laststr;
|
||||
(void) &pat;
|
||||
(void) &repl;
|
||||
(void) &efp;
|
||||
(void) &argc;
|
||||
(void) &argv;
|
||||
#endif
|
||||
|
||||
if (hist == NULL)
|
||||
error("history not active");
|
||||
|
||||
if (argc == 1)
|
||||
error("missing history argument");
|
||||
|
||||
optreset = 1; optind = 1; /* initialize getopt */
|
||||
opterr = 0;
|
||||
while (not_fcnumber(argv[optind]) &&
|
||||
(ch = getopt(argc, argv, ":e:lnrs")) != -1)
|
||||
switch ((char)ch) {
|
||||
case 'e':
|
||||
editor = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
lflg = 1;
|
||||
break;
|
||||
case 'n':
|
||||
nflg = 1;
|
||||
break;
|
||||
case 'r':
|
||||
rflg = 1;
|
||||
break;
|
||||
case 's':
|
||||
sflg = 1;
|
||||
break;
|
||||
case ':':
|
||||
error("option -%c expects argument", optopt);
|
||||
case '?':
|
||||
default:
|
||||
error("unknown option: -%c", optopt);
|
||||
}
|
||||
argc -= optind, argv += optind;
|
||||
|
||||
/*
|
||||
* If executing...
|
||||
*/
|
||||
if (lflg == 0 || editor || sflg) {
|
||||
lflg = 0; /* ignore */
|
||||
editfile[0] = '\0';
|
||||
/*
|
||||
* Catch interrupts to reset active counter and
|
||||
* cleanup temp files.
|
||||
*/
|
||||
if (setjmp(jmploc.loc)) {
|
||||
active = 0;
|
||||
if (*editfile)
|
||||
unlink(editfile);
|
||||
handler = savehandler;
|
||||
longjmp(handler->loc, 1);
|
||||
}
|
||||
savehandler = handler;
|
||||
handler = &jmploc;
|
||||
if (++active > MAXHISTLOOPS) {
|
||||
active = 0;
|
||||
displayhist = 0;
|
||||
error("called recursively too many times");
|
||||
}
|
||||
/*
|
||||
* Set editor.
|
||||
*/
|
||||
if (sflg == 0) {
|
||||
if (editor == NULL &&
|
||||
(editor = bltinlookup("FCEDIT", 1)) == NULL &&
|
||||
(editor = bltinlookup("EDITOR", 1)) == NULL)
|
||||
editor = DEFEDITOR;
|
||||
if (editor[0] == '-' && editor[1] == '\0') {
|
||||
sflg = 1; /* no edit */
|
||||
editor = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If executing, parse [old=new] now
|
||||
*/
|
||||
if (lflg == 0 && argc > 0 &&
|
||||
((repl = strchr(argv[0], '=')) != NULL)) {
|
||||
pat = argv[0];
|
||||
*repl++ = '\0';
|
||||
argc--, argv++;
|
||||
}
|
||||
/*
|
||||
* determine [first] and [last]
|
||||
*/
|
||||
switch (argc) {
|
||||
case 0:
|
||||
firststr = lflg ? "-16" : "-1";
|
||||
laststr = "-1";
|
||||
break;
|
||||
case 1:
|
||||
firststr = argv[0];
|
||||
laststr = lflg ? "-1" : argv[0];
|
||||
break;
|
||||
case 2:
|
||||
firststr = argv[0];
|
||||
laststr = argv[1];
|
||||
break;
|
||||
default:
|
||||
error("too many args");
|
||||
}
|
||||
/*
|
||||
* Turn into event numbers.
|
||||
*/
|
||||
first = str_to_event(firststr, 0);
|
||||
last = str_to_event(laststr, 1);
|
||||
|
||||
if (rflg) {
|
||||
i = last;
|
||||
last = first;
|
||||
first = i;
|
||||
}
|
||||
/*
|
||||
* XXX - this should not depend on the event numbers
|
||||
* always increasing. Add sequence numbers or offset
|
||||
* to the history element in next (diskbased) release.
|
||||
*/
|
||||
direction = first < last ? H_PREV : H_NEXT;
|
||||
|
||||
/*
|
||||
* If editing, grab a temp file.
|
||||
*/
|
||||
if (editor) {
|
||||
int fd;
|
||||
INTOFF; /* easier */
|
||||
sprintf(editfile, "%s/_shXXXXXX", _PATH_TMP);
|
||||
if ((fd = mkstemp(editfile)) < 0)
|
||||
error("can't create temporary file %s", editfile);
|
||||
if ((efp = fdopen(fd, "w")) == NULL) {
|
||||
close(fd);
|
||||
error("can't allocate stdio buffer for temp");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop through selected history events. If listing or executing,
|
||||
* do it now. Otherwise, put into temp file and call the editor
|
||||
* after.
|
||||
*
|
||||
* The history interface needs rethinking, as the following
|
||||
* convolutions will demonstrate.
|
||||
*/
|
||||
history(hist, &he, H_FIRST);
|
||||
retval = history(hist, &he, H_NEXT_EVENT, first);
|
||||
for (;retval != -1; retval = history(hist, &he, direction)) {
|
||||
if (lflg) {
|
||||
if (!nflg)
|
||||
out1fmt("%5d ", he.num);
|
||||
out1str(he.str);
|
||||
} else {
|
||||
char *s = pat ?
|
||||
fc_replace(he.str, pat, repl) : (char *)he.str;
|
||||
|
||||
if (sflg) {
|
||||
if (displayhist) {
|
||||
out2str(s);
|
||||
}
|
||||
evalstring(s);
|
||||
if (displayhist && hist) {
|
||||
/*
|
||||
* XXX what about recursive and
|
||||
* relative histnums.
|
||||
*/
|
||||
oldhistnum = he.num;
|
||||
history(hist, &he, H_ENTER, s);
|
||||
/*
|
||||
* XXX H_ENTER moves the internal
|
||||
* cursor, set it back to the current
|
||||
* entry.
|
||||
*/
|
||||
retval = history(hist, &he,
|
||||
H_NEXT_EVENT, oldhistnum);
|
||||
}
|
||||
} else
|
||||
fputs(s, efp);
|
||||
}
|
||||
/*
|
||||
* At end? (if we were to loose last, we'd sure be
|
||||
* messed up).
|
||||
*/
|
||||
if (he.num == last)
|
||||
break;
|
||||
}
|
||||
if (editor) {
|
||||
char *editcmd;
|
||||
|
||||
fclose(efp);
|
||||
editcmd = stalloc(strlen(editor) + strlen(editfile) + 2);
|
||||
sprintf(editcmd, "%s %s", editor, editfile);
|
||||
evalstring(editcmd); /* XXX - should use no JC command */
|
||||
INTON;
|
||||
readcmdfile(editfile); /* XXX - should read back - quick tst */
|
||||
unlink(editfile);
|
||||
}
|
||||
|
||||
if (lflg == 0 && active > 0)
|
||||
--active;
|
||||
if (displayhist)
|
||||
displayhist = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC char *
|
||||
fc_replace(const char *s, char *p, char *r)
|
||||
{
|
||||
char *dest;
|
||||
int plen = strlen(p);
|
||||
|
||||
STARTSTACKSTR(dest);
|
||||
while (*s) {
|
||||
if (*s == *p && strncmp(s, p, plen) == 0) {
|
||||
while (*r)
|
||||
STPUTC(*r++, dest);
|
||||
s += plen;
|
||||
*p = '\0'; /* so no more matches */
|
||||
} else
|
||||
STPUTC(*s++, dest);
|
||||
}
|
||||
STACKSTRNUL(dest);
|
||||
dest = grabstackstr(dest);
|
||||
|
||||
return (dest);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
not_fcnumber(char *s)
|
||||
{
|
||||
if (s == NULL)
|
||||
return (0);
|
||||
if (*s == '-')
|
||||
s++;
|
||||
return (!is_number(s));
|
||||
}
|
||||
|
||||
STATIC int
|
||||
str_to_event(char *str, int last)
|
||||
{
|
||||
HistEvent he;
|
||||
char *s = str;
|
||||
int relative = 0;
|
||||
int i, retval;
|
||||
|
||||
retval = history(hist, &he, H_FIRST);
|
||||
switch (*s) {
|
||||
case '-':
|
||||
relative = 1;
|
||||
/*FALLTHROUGH*/
|
||||
case '+':
|
||||
s++;
|
||||
}
|
||||
if (is_number(s)) {
|
||||
i = atoi(s);
|
||||
if (relative) {
|
||||
while (retval != -1 && i--) {
|
||||
retval = history(hist, &he, H_NEXT);
|
||||
}
|
||||
if (retval == -1)
|
||||
retval = history(hist, &he, H_LAST);
|
||||
} else {
|
||||
retval = history(hist, &he, H_NEXT_EVENT, i);
|
||||
if (retval == -1) {
|
||||
/*
|
||||
* the notion of first and last is
|
||||
* backwards to that of the history package
|
||||
*/
|
||||
retval = history(hist, &he, last ? H_FIRST : H_LAST);
|
||||
}
|
||||
}
|
||||
if (retval == -1)
|
||||
error("history number %s not found (internal error)",
|
||||
str);
|
||||
} else {
|
||||
/*
|
||||
* pattern
|
||||
*/
|
||||
retval = history(hist, &he, H_PREV_STR, str);
|
||||
if (retval == -1)
|
||||
error("history pattern not found: %s", str);
|
||||
}
|
||||
return (he.num);
|
||||
}
|
||||
|
||||
int
|
||||
bindcmd(int argc, char **argv)
|
||||
{
|
||||
|
||||
if (el == NULL)
|
||||
error("line editing is disabled");
|
||||
return (el_parse(el, argc, argv));
|
||||
}
|
||||
|
||||
#else
|
||||
#include "error.h"
|
||||
|
||||
int
|
||||
histcmd(int argc, char **argv)
|
||||
{
|
||||
|
||||
error("not compiled with history support");
|
||||
/*NOTREACHED*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
bindcmd(int argc, char **argv)
|
||||
{
|
||||
|
||||
error("not compiled with line editing support");
|
||||
return (0);
|
||||
}
|
||||
#endif /* !NO_HISTORY && !EDITLINE */
|
||||
|
||||
/*
|
||||
* $PchId: histedit.c,v 1.6 2006/04/10 14:52:58 philip Exp $
|
||||
*/
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -33,15 +29,14 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)init.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)init.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/init.h,v 1.8 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
void init(void);
|
||||
void reset(void);
|
||||
void initshellproc(void);
|
||||
#else
|
||||
void init();
|
||||
void reset();
|
||||
void initshellproc();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $PchId: init.h,v 1.3 2006/03/30 14:31:06 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -35,26 +31,61 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)input.c 5.4 (Berkeley) 7/1/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/input.c,v 1.22 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h> /* defines BUFSIZ */
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* This file implements the input routines used by the parser.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h> /* defines BUFSIZ */
|
||||
#include "shell.h"
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include "redir.h"
|
||||
#include "syntax.h"
|
||||
#include "input.h"
|
||||
#include "output.h"
|
||||
#include "options.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "alias.h"
|
||||
#include "parser.h"
|
||||
#ifdef EDITLINE
|
||||
#ifdef __minix_vmd
|
||||
#include <readline/readline.h>
|
||||
#else
|
||||
/* What about other systems? */
|
||||
#endif
|
||||
#else
|
||||
#include "myhistedit.h"
|
||||
#endif
|
||||
#include "redir.h"
|
||||
#include "trap.h"
|
||||
|
||||
static void popstring(void);
|
||||
|
||||
#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
|
||||
|
||||
MKINIT
|
||||
struct strpush {
|
||||
struct strpush *prev; /* preceding string on stack */
|
||||
char *prevstring;
|
||||
int prevnleft;
|
||||
int prevlleft;
|
||||
struct alias *ap; /* if push was associated with an alias */
|
||||
};
|
||||
|
||||
/*
|
||||
* The parsefile structure pointed to by the global variable parsefile
|
||||
|
@ -63,36 +94,34 @@ static char sccsid[] = "@(#)input.c 5.4 (Berkeley) 7/1/91";
|
|||
|
||||
MKINIT
|
||||
struct parsefile {
|
||||
struct parsefile *prev; /* preceding file on stack */
|
||||
int linno; /* current line */
|
||||
int fd; /* file descriptor (or -1 if string) */
|
||||
int nleft; /* number of chars left in buffer */
|
||||
int nleft; /* number of chars left in this line */
|
||||
int lleft; /* number of lines left in this buffer */
|
||||
char *nextc; /* next char in buffer */
|
||||
struct parsefile *prev; /* preceding file on stack */
|
||||
char *buf; /* input buffer */
|
||||
struct strpush *strpush; /* for pushing strings at this level */
|
||||
struct strpush basestrpush; /* so pushing one is fast */
|
||||
};
|
||||
|
||||
|
||||
int plinno = 1; /* input line number */
|
||||
MKINIT int parsenleft; /* copy of parsefile->nleft */
|
||||
MKINIT int parselleft; /* copy of parsefile->lleft */
|
||||
char *parsenextc; /* copy of parsefile->nextc */
|
||||
MKINIT struct parsefile basepf; /* top level input file */
|
||||
char basebuf[BUFSIZ]; /* buffer for top level input file */
|
||||
struct parsefile *parsefile = &basepf; /* current input file */
|
||||
char *pushedstring; /* copy of parsenextc when text pushed back */
|
||||
int pushednleft; /* copy of parsenleft when text pushed back */
|
||||
STATIC struct parsefile *parsefile = &basepf; /* current input file */
|
||||
int init_editline = 0; /* editline library initialized? */
|
||||
int whichprompt; /* -1 == PSE, 1 == PS1, 2 == PS2 */
|
||||
|
||||
#if READLINE
|
||||
char *readline __P((const char *prompt));
|
||||
char *r_use_prompt = NULL; /* the prompt to use with readline */
|
||||
#ifndef EDITLINE
|
||||
EditLine *el; /* cookie for editline package */
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
STATIC void pushfile(void);
|
||||
#else
|
||||
STATIC void pushfile();
|
||||
#endif
|
||||
|
||||
|
||||
static int preadfd(void);
|
||||
|
||||
#ifdef mkinit
|
||||
INCLUDE "input.h"
|
||||
|
@ -106,7 +135,7 @@ INIT {
|
|||
|
||||
RESET {
|
||||
if (exception != EXSHELLPROC)
|
||||
parsenleft = 0; /* clear input buffer */
|
||||
parselleft = parsenleft = 0; /* clear input buffer */
|
||||
popallfiles();
|
||||
}
|
||||
|
||||
|
@ -121,10 +150,9 @@ SHELLPROC {
|
|||
*/
|
||||
|
||||
char *
|
||||
pfgets(line, len)
|
||||
char *line;
|
||||
{
|
||||
register char *p = line;
|
||||
pfgets(char *line, int len)
|
||||
{
|
||||
char *p = line;
|
||||
int nleft = len;
|
||||
int c;
|
||||
|
||||
|
@ -151,64 +179,74 @@ pfgets(line, len)
|
|||
*/
|
||||
|
||||
int
|
||||
pgetc() {
|
||||
pgetc(void)
|
||||
{
|
||||
return pgetc_macro();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Refill the input buffer and return the next input character:
|
||||
*
|
||||
* 1) If a string was pushed back on the input, switch back to the regular
|
||||
* buffer.
|
||||
* 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
|
||||
* from a string so we can't refill the buffer, return EOF.
|
||||
* 3) Call read to read in the characters.
|
||||
* 4) Delete all nul characters from the buffer.
|
||||
*/
|
||||
static int
|
||||
preadfd(void)
|
||||
{
|
||||
int nr;
|
||||
parsenextc = parsefile->buf;
|
||||
|
||||
int
|
||||
preadbuffer() {
|
||||
register char *p, *q;
|
||||
register int i;
|
||||
|
||||
if (pushedstring) {
|
||||
parsenextc = pushedstring;
|
||||
pushedstring = NULL;
|
||||
parsenleft = pushednleft;
|
||||
if (--parsenleft >= 0)
|
||||
return *parsenextc++;
|
||||
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||
if (el != NULL && gotwinch) {
|
||||
gotwinch = 0;
|
||||
el_resize(el);
|
||||
}
|
||||
if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
|
||||
return PEOF;
|
||||
flushout(&output);
|
||||
flushout(&errout);
|
||||
#if READLINE
|
||||
/* Use the readline() call if a prompt is to be printed (interactive). */
|
||||
if (r_use_prompt != NULL) {
|
||||
char *prompt;
|
||||
char *line;
|
||||
|
||||
p = parsenextc = parsefile->buf;
|
||||
|
||||
prompt = r_use_prompt;
|
||||
r_use_prompt = NULL;
|
||||
|
||||
if ((line = readline(prompt)) == NULL) {
|
||||
parsenleft = EOF_NLEFT;
|
||||
return PEOF;
|
||||
}
|
||||
strcpy(p, line);
|
||||
free(line);
|
||||
i = strlen(p);
|
||||
p[i++] = '\n';
|
||||
} else {
|
||||
#endif
|
||||
retry:
|
||||
p = parsenextc = parsefile->buf;
|
||||
i = read(parsefile->fd, p, BUFSIZ);
|
||||
if (i <= 0) {
|
||||
if (i < 0) {
|
||||
#ifndef NO_HISTORY
|
||||
#ifdef EDITLINE
|
||||
if (parsefile->fd == 0) {
|
||||
static const char *rl_cp= NULL;
|
||||
static size_t rl_off= 0;
|
||||
|
||||
if (!rl_cp)
|
||||
{
|
||||
rl_cp = readline(getprompt(NULL));
|
||||
if (rl_cp == NULL)
|
||||
nr = 0;
|
||||
}
|
||||
if (rl_cp)
|
||||
{
|
||||
nr= strlen(rl_cp+rl_off);
|
||||
if (nr >= BUFSIZ-1)
|
||||
{
|
||||
nr= BUFSIZ-1;
|
||||
(void) memcpy(parsenextc, rl_cp+rl_off, nr);
|
||||
rl_off += nr;
|
||||
}
|
||||
else
|
||||
{
|
||||
(void) memcpy(parsenextc, rl_cp+rl_off, nr);
|
||||
parsenextc[nr++]= '\n';
|
||||
free(rl_cp);
|
||||
rl_cp= NULL;
|
||||
rl_off= 0;
|
||||
}
|
||||
}
|
||||
} else
|
||||
#else /* !EDITLINE */
|
||||
if (parsefile->fd == 0 && el) {
|
||||
const char *rl_cp;
|
||||
|
||||
rl_cp = el_gets(el, &nr);
|
||||
if (rl_cp == NULL)
|
||||
nr = 0;
|
||||
else {
|
||||
/* XXX - BUFSIZE should redesign so not necessary */
|
||||
(void) strcpy(parsenextc, rl_cp);
|
||||
}
|
||||
} else
|
||||
#endif /* !EDITLINE */
|
||||
#endif
|
||||
nr = read(parsefile->fd, parsenextc, BUFSIZ - 1);
|
||||
|
||||
if (nr <= 0) {
|
||||
if (nr < 0) {
|
||||
if (errno == EINTR)
|
||||
goto retry;
|
||||
#ifdef EWOULDBLOCK
|
||||
|
@ -222,35 +260,106 @@ retry:
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* EWOULDBLOCK */
|
||||
}
|
||||
parsenleft = EOF_NLEFT;
|
||||
return PEOF;
|
||||
nr = -1;
|
||||
}
|
||||
#if READLINE
|
||||
}
|
||||
#endif
|
||||
parsenleft = i - 1;
|
||||
|
||||
/* delete nul characters */
|
||||
for (;;) {
|
||||
if (*p++ == '\0')
|
||||
break;
|
||||
if (--i <= 0)
|
||||
return *parsenextc++; /* no nul characters */
|
||||
}
|
||||
q = p - 1;
|
||||
while (--i > 0) {
|
||||
if (*p != '\0')
|
||||
*q++ = *p;
|
||||
p++;
|
||||
}
|
||||
if (q == parsefile->buf)
|
||||
goto retry; /* buffer contained nothing but nuls */
|
||||
parsenleft = q - parsefile->buf - 1;
|
||||
return *parsenextc++;
|
||||
return nr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Refill the input buffer and return the next input character:
|
||||
*
|
||||
* 1) If a string was pushed back on the input, pop it;
|
||||
* 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
|
||||
* from a string so we can't refill the buffer, return EOF.
|
||||
* 3) If there is more in this buffer, use it else call read to fill it.
|
||||
* 4) Process input up to the next newline, deleting nul characters.
|
||||
*/
|
||||
|
||||
int
|
||||
preadbuffer(void)
|
||||
{
|
||||
char *p, *q;
|
||||
int more;
|
||||
int something;
|
||||
char savec;
|
||||
|
||||
if (parsefile->strpush) {
|
||||
popstring();
|
||||
if (--parsenleft >= 0)
|
||||
return (*parsenextc++);
|
||||
}
|
||||
if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
|
||||
return PEOF;
|
||||
flushout(&output);
|
||||
flushout(&errout);
|
||||
|
||||
again:
|
||||
if (parselleft <= 0) {
|
||||
if ((parselleft = preadfd()) == -1) {
|
||||
parselleft = parsenleft = EOF_NLEFT;
|
||||
return PEOF;
|
||||
}
|
||||
}
|
||||
|
||||
q = p = parsenextc;
|
||||
|
||||
/* delete nul characters */
|
||||
something = 0;
|
||||
for (more = 1; more;) {
|
||||
switch (*p) {
|
||||
case '\0':
|
||||
p++; /* Skip nul */
|
||||
goto check;
|
||||
|
||||
case '\t':
|
||||
case ' ':
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
parsenleft = q - parsenextc;
|
||||
more = 0; /* Stop processing here */
|
||||
break;
|
||||
|
||||
default:
|
||||
something = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
*q++ = *p++;
|
||||
check:
|
||||
if (--parselleft <= 0) {
|
||||
parsenleft = q - parsenextc - 1;
|
||||
if (parsenleft < 0)
|
||||
goto again;
|
||||
*q = '\0';
|
||||
more = 0;
|
||||
}
|
||||
}
|
||||
|
||||
savec = *q;
|
||||
*q = '\0';
|
||||
|
||||
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||
if (parsefile->fd == 0 && hist && something) {
|
||||
HistEvent he;
|
||||
INTOFF;
|
||||
history(hist, &he, whichprompt == 1 ? H_ENTER : H_ADD,
|
||||
parsenextc);
|
||||
INTON;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (vflag) {
|
||||
out2str(parsenextc);
|
||||
flushout(out2);
|
||||
}
|
||||
|
||||
*q = savec;
|
||||
|
||||
return *parsenextc++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Undo the last call to pgetc. Only one character may be pushed back.
|
||||
|
@ -258,28 +367,57 @@ retry:
|
|||
*/
|
||||
|
||||
void
|
||||
pungetc() {
|
||||
pungetc(void)
|
||||
{
|
||||
parsenleft++;
|
||||
parsenextc--;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Push a string back onto the input. This code doesn't work if the user
|
||||
* tries to push back more than one string at once.
|
||||
* Push a string back onto the input at this current parsefile level.
|
||||
* We handle aliases this way.
|
||||
*/
|
||||
|
||||
void
|
||||
ppushback(string, length)
|
||||
char *string;
|
||||
{
|
||||
pushedstring = parsenextc;
|
||||
pushednleft = parsenleft;
|
||||
parsenextc = string;
|
||||
parsenleft = length;
|
||||
pushstring(char *s, int len, void *ap)
|
||||
{
|
||||
struct strpush *sp;
|
||||
|
||||
INTOFF;
|
||||
/*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
|
||||
if (parsefile->strpush) {
|
||||
sp = ckmalloc(sizeof (struct strpush));
|
||||
sp->prev = parsefile->strpush;
|
||||
parsefile->strpush = sp;
|
||||
} else
|
||||
sp = parsefile->strpush = &(parsefile->basestrpush);
|
||||
sp->prevstring = parsenextc;
|
||||
sp->prevnleft = parsenleft;
|
||||
sp->prevlleft = parselleft;
|
||||
sp->ap = (struct alias *)ap;
|
||||
if (ap)
|
||||
((struct alias *)ap)->flag |= ALIASINUSE;
|
||||
parsenextc = s;
|
||||
parsenleft = len;
|
||||
INTON;
|
||||
}
|
||||
|
||||
static void
|
||||
popstring(void)
|
||||
{
|
||||
struct strpush *sp = parsefile->strpush;
|
||||
|
||||
INTOFF;
|
||||
parsenextc = sp->prevstring;
|
||||
parsenleft = sp->prevnleft;
|
||||
parselleft = sp->prevlleft;
|
||||
/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
|
||||
if (sp->ap)
|
||||
sp->ap->flag &= ~ALIASINUSE;
|
||||
parsefile->strpush = sp->prev;
|
||||
if (sp != &(parsefile->basestrpush))
|
||||
ckfree(sp);
|
||||
INTON;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the input to take input from a file. If push is set, push the
|
||||
|
@ -287,17 +425,16 @@ ppushback(string, length)
|
|||
*/
|
||||
|
||||
void
|
||||
setinputfile(fname, push)
|
||||
char *fname;
|
||||
{
|
||||
setinputfile(char *fname, int push)
|
||||
{
|
||||
int fd;
|
||||
int fd2;
|
||||
|
||||
INTOFF;
|
||||
if ((fd = open(fname, O_RDONLY)) < 0)
|
||||
error("Can't open %s", fname);
|
||||
error("Can't open %s: %s", fname, strerror(errno));
|
||||
if (fd < 10) {
|
||||
fd2 = copyfd(fd, 10);
|
||||
fd2 = fcntl(fd, F_DUPFD, 10);
|
||||
close(fd);
|
||||
if (fd2 < 0)
|
||||
error("Out of file descriptors");
|
||||
|
@ -314,8 +451,9 @@ setinputfile(fname, push)
|
|||
*/
|
||||
|
||||
void
|
||||
setinputfd(fd, push) {
|
||||
(void) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
|
||||
setinputfd(int fd, int push)
|
||||
{
|
||||
(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
if (push) {
|
||||
pushfile();
|
||||
parsefile->buf = ckmalloc(BUFSIZ);
|
||||
|
@ -325,7 +463,7 @@ setinputfd(fd, push) {
|
|||
parsefile->fd = fd;
|
||||
if (parsefile->buf == NULL)
|
||||
parsefile->buf = ckmalloc(BUFSIZ);
|
||||
parsenleft = 0;
|
||||
parselleft = parsenleft = 0;
|
||||
plinno = 1;
|
||||
}
|
||||
|
||||
|
@ -335,14 +473,13 @@ setinputfd(fd, push) {
|
|||
*/
|
||||
|
||||
void
|
||||
setinputstring(string, push)
|
||||
char *string;
|
||||
{
|
||||
setinputstring(char *string, int push)
|
||||
{
|
||||
INTOFF;
|
||||
if (push)
|
||||
pushfile();
|
||||
parsenextc = string;
|
||||
parsenleft = strlen(string);
|
||||
parselleft = parsenleft = strlen(string);
|
||||
parsefile->buf = NULL;
|
||||
plinno = 1;
|
||||
INTON;
|
||||
|
@ -356,21 +493,26 @@ setinputstring(string, push)
|
|||
*/
|
||||
|
||||
STATIC void
|
||||
pushfile() {
|
||||
pushfile(void)
|
||||
{
|
||||
struct parsefile *pf;
|
||||
|
||||
parsefile->nleft = parsenleft;
|
||||
parsefile->lleft = parselleft;
|
||||
parsefile->nextc = parsenextc;
|
||||
parsefile->linno = plinno;
|
||||
pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
|
||||
pf->prev = parsefile;
|
||||
pf->fd = -1;
|
||||
pf->strpush = NULL;
|
||||
pf->basestrpush.prev = NULL;
|
||||
parsefile = pf;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
popfile() {
|
||||
popfile(void)
|
||||
{
|
||||
struct parsefile *pf = parsefile;
|
||||
|
||||
INTOFF;
|
||||
|
@ -378,9 +520,12 @@ popfile() {
|
|||
close(pf->fd);
|
||||
if (pf->buf)
|
||||
ckfree(pf->buf);
|
||||
while (pf->strpush)
|
||||
popstring();
|
||||
parsefile = pf->prev;
|
||||
ckfree(pf);
|
||||
parsenleft = parsefile->nleft;
|
||||
parselleft = parsefile->lleft;
|
||||
parsenextc = parsefile->nextc;
|
||||
plinno = parsefile->linno;
|
||||
INTON;
|
||||
|
@ -392,7 +537,8 @@ popfile() {
|
|||
*/
|
||||
|
||||
void
|
||||
popallfiles() {
|
||||
popallfiles(void)
|
||||
{
|
||||
while (parsefile != &basepf)
|
||||
popfile();
|
||||
}
|
||||
|
@ -405,10 +551,15 @@ popallfiles() {
|
|||
*/
|
||||
|
||||
void
|
||||
closescript() {
|
||||
closescript(void)
|
||||
{
|
||||
popallfiles();
|
||||
if (parsefile->fd > 0) {
|
||||
close(parsefile->fd);
|
||||
parsefile->fd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: input.c,v 1.6 2006/05/23 12:00:32 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -33,7 +29,8 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)input.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)input.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/input.h,v 1.9 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
/* PEOF (the end of file marker) is defined in syntax.h */
|
||||
|
@ -46,39 +43,22 @@
|
|||
extern int plinno;
|
||||
extern int parsenleft; /* number of characters left in input buffer */
|
||||
extern char *parsenextc; /* next character in input buffer */
|
||||
extern int init_editline; /* 0 == not setup, 1 == OK, -1 == failed */
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
char *pfgets(char *, int);
|
||||
int pgetc(void);
|
||||
int preadbuffer(void);
|
||||
void pungetc(void);
|
||||
void ppushback(char *, int);
|
||||
void pushstring(char *, int, void *);
|
||||
void setinputfile(char *, int);
|
||||
void setinputfd(int, int);
|
||||
void setinputstring(char *, int);
|
||||
void popfile(void);
|
||||
void popallfiles(void);
|
||||
void closescript(void);
|
||||
#else
|
||||
char *pfgets();
|
||||
int pgetc();
|
||||
int preadbuffer();
|
||||
void pungetc();
|
||||
void ppushback();
|
||||
void setinputfile();
|
||||
void setinputfd();
|
||||
void setinputstring();
|
||||
void popfile();
|
||||
void popallfiles();
|
||||
void closescript();
|
||||
#endif
|
||||
|
||||
#define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer())
|
||||
|
||||
#if READLINE
|
||||
/* The variable "r_use_prompt" indicates the prompt to use with readline,
|
||||
* *and* that readline may only be used if non-NULL.
|
||||
/*
|
||||
* $PchId: input.h,v 1.3 2006/03/30 13:49:37 philip Exp $
|
||||
*/
|
||||
extern char *r_use_prompt;
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -33,7 +29,8 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)jobs.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)jobs.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/jobs.h,v 1.18 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
|
||||
|
@ -41,6 +38,7 @@
|
|||
#define FORK_BG 1
|
||||
#define FORK_NOJOB 2
|
||||
|
||||
#include <signal.h> /* for sig_atomic_t */
|
||||
|
||||
/*
|
||||
* A job structure contains information about a job. A job is either a
|
||||
|
@ -51,7 +49,7 @@
|
|||
|
||||
struct procstat {
|
||||
pid_t pid; /* process id */
|
||||
short status; /* status flags (defined above) */
|
||||
int status; /* status flags (defined above) */
|
||||
char *cmd; /* text of command being run */
|
||||
};
|
||||
|
||||
|
@ -64,33 +62,41 @@ struct procstat {
|
|||
struct job {
|
||||
struct procstat ps0; /* status of process */
|
||||
struct procstat *ps; /* status or processes when more than one */
|
||||
pid_t nprocs; /* number of processes */
|
||||
short nprocs; /* number of processes */
|
||||
pid_t pgrp; /* process group of this job */
|
||||
char state; /* true if job is finished */
|
||||
char used; /* true if this entry is in used */
|
||||
char changed; /* true if status has changed */
|
||||
char foreground; /* true if running in the foreground */
|
||||
#if JOBS
|
||||
char jobctl; /* job running under job control */
|
||||
struct job *next; /* job used after this one */
|
||||
#endif
|
||||
};
|
||||
|
||||
extern pid_t backgndpid; /* pid of last background process */
|
||||
extern int job_warning; /* user was warned about stopped jobs */
|
||||
extern int in_waitcmd; /* are we in waitcmd()? */
|
||||
extern int in_dowait; /* are we in dowait()? */
|
||||
extern volatile sig_atomic_t breakwaitcmd; /* break wait to process traps? */
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
void setjobctl(int);
|
||||
void showjobs(int);
|
||||
int fgcmd(int, char **);
|
||||
int bgcmd(int, char **);
|
||||
int jobscmd(int, char **);
|
||||
void showjobs(int, int, int);
|
||||
int waitcmd(int, char **);
|
||||
int jobidcmd(int, char **);
|
||||
struct job *makejob(union node *, int);
|
||||
int forkshell(struct job *, union node *, int);
|
||||
int waitforjob(struct job *);
|
||||
#else
|
||||
void setjobctl();
|
||||
void showjobs();
|
||||
struct job *makejob();
|
||||
int forkshell();
|
||||
int waitforjob();
|
||||
#endif
|
||||
pid_t forkshell(struct job *, union node *, int);
|
||||
int waitforjob(struct job *, int *);
|
||||
int stoppedjobs(void);
|
||||
char *commandtext(union node *);
|
||||
|
||||
#if ! JOBS
|
||||
#define setjobctl(on) /* do nothing */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $PchId: jobs.h,v 1.4 2006/03/30 12:07:24 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -33,7 +33,7 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)machdep.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)machdep.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -47,5 +47,9 @@ union align {
|
|||
char *cp;
|
||||
};
|
||||
|
||||
#define ALIGN(nbytes) ((nbytes) + sizeof(union align) - 1 &~ (sizeof(union align) - 1))
|
||||
#define ALIGN(nbytes) (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $PchId: machdep.h,v 1.2 2001/05/15 16:36:26 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -35,8 +31,14 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)mail.c 5.1 (Berkeley) 3/7/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)mail.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/mail.c,v 1.13 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
/*
|
||||
* Routines to check for mail. (Perhaps make part of main.c?)
|
||||
|
@ -48,8 +50,10 @@ static char sccsid[] = "@(#)mail.c 5.1 (Berkeley) 3/7/91";
|
|||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "mail.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#define MAXMBOXES 10
|
||||
|
@ -67,11 +71,12 @@ STATIC time_t mailtime[MAXMBOXES]; /* times of mailboxes */
|
|||
*/
|
||||
|
||||
void
|
||||
chkmail(silent) {
|
||||
register int i;
|
||||
chkmail(int silent)
|
||||
{
|
||||
int i;
|
||||
char *mpath;
|
||||
char *p;
|
||||
register char *q;
|
||||
char *q;
|
||||
struct stackmark smark;
|
||||
struct stat statb;
|
||||
|
||||
|
@ -91,18 +96,28 @@ chkmail(silent) {
|
|||
if (q[-1] != '/')
|
||||
abort();
|
||||
q[-1] = '\0'; /* delete trailing '/' */
|
||||
#ifdef notdef /* this is what the System V shell claims to do (it lies) */
|
||||
if (stat(p, &statb) < 0)
|
||||
statb.st_mtime = 0;
|
||||
if (!silent
|
||||
&& statb.st_size > 0
|
||||
&& statb.st_mtime > mailtime[i]
|
||||
&& statb.st_mtime > statb.st_atime
|
||||
) {
|
||||
out2str(pathopt? pathopt : "You have mail");
|
||||
if (statb.st_mtime > mailtime[i] && ! silent) {
|
||||
out2str(pathopt? pathopt : "you have mail");
|
||||
out2c('\n');
|
||||
}
|
||||
mailtime[i] = statb.st_mtime;
|
||||
#else /* this is what it should do */
|
||||
if (stat(p, &statb) < 0)
|
||||
statb.st_size = 0;
|
||||
if (statb.st_size > mailtime[i] && ! silent) {
|
||||
out2str(pathopt? pathopt : "you have mail");
|
||||
out2c('\n');
|
||||
}
|
||||
mailtime[i] = statb.st_size;
|
||||
#endif
|
||||
}
|
||||
nmboxes = i;
|
||||
popstackmark(&smark);
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: mail.c,v 1.5 2006/05/22 12:02:37 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -33,11 +29,12 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)mail.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)mail.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/mail.h,v 1.8 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
void chkmail(int);
|
||||
#else
|
||||
void chkmail();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $PchId: mail.h,v 1.3 2006/03/30 11:53:44 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -35,18 +31,29 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
char copyright[] =
|
||||
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
|
||||
All rights reserved.\n";
|
||||
static char const copyright[] =
|
||||
"@(#) Copyright (c) 1991, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)main.c 5.2 (Berkeley) 3/13/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/28/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/main.c,v 1.26 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <locale.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "main.h"
|
||||
#include "mail.h"
|
||||
|
@ -54,38 +61,26 @@ static char sccsid[] = "@(#)main.c 5.2 (Berkeley) 3/13/91";
|
|||
#include "output.h"
|
||||
#include "parser.h"
|
||||
#include "nodes.h"
|
||||
#include "expand.h"
|
||||
#include "eval.h"
|
||||
#include "jobs.h"
|
||||
#include "input.h"
|
||||
#include "trap.h"
|
||||
#if ATTY
|
||||
#include "var.h"
|
||||
#endif
|
||||
#include "show.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "init.h"
|
||||
#include "mystring.h"
|
||||
|
||||
#define PROFILE 0
|
||||
#include "exec.h"
|
||||
#include "cd.h"
|
||||
#include "builtins.h"
|
||||
|
||||
int rootpid;
|
||||
int rootshell;
|
||||
STATIC union node *curcmd;
|
||||
STATIC union node *prevcmd;
|
||||
extern int errno;
|
||||
#if PROFILE
|
||||
short profile_buf[16384];
|
||||
extern int etext();
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
STATIC void read_profile(char *);
|
||||
char *getenv(char *);
|
||||
#else
|
||||
STATIC void read_profile();
|
||||
char *getenv();
|
||||
#endif
|
||||
|
||||
STATIC char *find_dot_file(char *);
|
||||
|
||||
/*
|
||||
* Main routine. We initialize things, parse the arguments, execute
|
||||
|
@ -95,16 +90,15 @@ char *getenv();
|
|||
* is used to figure out how far we had gotten.
|
||||
*/
|
||||
|
||||
main(argc, argv) char **argv; {
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct jmploc jmploc;
|
||||
struct stackmark smark;
|
||||
volatile int state;
|
||||
char *shinit, *home;
|
||||
char *profile = NULL, *ashrc = NULL;
|
||||
char *shinit;
|
||||
|
||||
#if PROFILE
|
||||
monitor(4, etext, profile_buf, sizeof profile_buf, 50);
|
||||
#endif
|
||||
(void) setlocale(LC_ALL, "");
|
||||
state = 0;
|
||||
if (setjmp(jmploc.loc)) {
|
||||
/*
|
||||
|
@ -112,21 +106,32 @@ main(argc, argv) char **argv; {
|
|||
* exception EXSHELLPROC to clean up before executing
|
||||
* the shell procedure.
|
||||
*/
|
||||
if (exception == EXSHELLPROC) {
|
||||
switch (exception) {
|
||||
case EXSHELLPROC:
|
||||
rootpid = getpid();
|
||||
rootshell = 1;
|
||||
minusc = NULL;
|
||||
state = 3;
|
||||
} else if (state == 0 || iflag == 0 || ! rootshell)
|
||||
exitshell(2);
|
||||
break;
|
||||
|
||||
case EXEXEC:
|
||||
exitstatus = exerrno;
|
||||
break;
|
||||
|
||||
case EXERROR:
|
||||
exitstatus = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (exception != EXSHELLPROC) {
|
||||
if (state == 0 || iflag == 0 || ! rootshell)
|
||||
exitshell(exitstatus);
|
||||
}
|
||||
reset();
|
||||
#if ATTY
|
||||
if (exception == EXINT
|
||||
&& (! attyset() || equal(termval(), "emacs")))
|
||||
#else
|
||||
if (exception == EXINT)
|
||||
#endif
|
||||
{
|
||||
if (exception == EXINT) {
|
||||
out2c('\n');
|
||||
flushout(&errout);
|
||||
}
|
||||
|
@ -151,57 +156,38 @@ main(argc, argv) char **argv; {
|
|||
init();
|
||||
setstackmark(&smark);
|
||||
procargs(argc, argv);
|
||||
if (eflag) eflag = 2; /* Truly enable [ex]flag after init. */
|
||||
if (xflag) xflag = 2;
|
||||
if (getpwd() == NULL && iflag)
|
||||
out2str("sh: cannot determine working directory\n");
|
||||
if (argv[0] && argv[0][0] == '-') {
|
||||
state = 1;
|
||||
read_profile("/etc/profile");
|
||||
state1:
|
||||
state = 2;
|
||||
if ((home = getenv("HOME")) != NULL
|
||||
&& (profile = (char *) malloc(strlen(home) + 10)) != NULL)
|
||||
{
|
||||
strcpy(profile, home);
|
||||
strcat(profile, "/.profile");
|
||||
read_profile(profile);
|
||||
} else {
|
||||
if (privileged == 0)
|
||||
read_profile(".profile");
|
||||
}
|
||||
} else if ((sflag || minusc) && (shinit = getenv("SHINIT")) != NULL) {
|
||||
state = 2;
|
||||
evalstring(shinit);
|
||||
else
|
||||
read_profile("/etc/suid_profile");
|
||||
}
|
||||
state2:
|
||||
if (profile != NULL) free(profile);
|
||||
|
||||
state = 3;
|
||||
if (!argv[0] || argv[0][0] != '-') {
|
||||
if ((home = getenv("HOME")) != NULL
|
||||
&& (ashrc = (char *) malloc(strlen(home) + 8)) != NULL)
|
||||
{
|
||||
strcpy(ashrc, home);
|
||||
strcat(ashrc, "/.ashrc");
|
||||
read_profile(ashrc);
|
||||
if (!privileged && iflag) {
|
||||
if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
|
||||
state = 3;
|
||||
read_profile(shinit);
|
||||
}
|
||||
}
|
||||
state3:
|
||||
if (ashrc != NULL) free(ashrc);
|
||||
if (eflag) eflag = 1; /* Init done, enable [ex]flag */
|
||||
if (xflag) xflag = 1;
|
||||
exitstatus = 0; /* Init shouldn't influence initial $? */
|
||||
|
||||
state = 4;
|
||||
if (minusc) {
|
||||
evalstring(minusc);
|
||||
}
|
||||
if (sflag || minusc == NULL) {
|
||||
state4:
|
||||
state4: /* XXX ??? - why isn't this before the "if" statement */
|
||||
cmdloop(1);
|
||||
}
|
||||
#if PROFILE
|
||||
monitor(0);
|
||||
#endif
|
||||
exitshell(exitstatus);
|
||||
/*NOTREACHED*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -211,52 +197,49 @@ state4:
|
|||
*/
|
||||
|
||||
void
|
||||
cmdloop(top) {
|
||||
cmdloop(int top)
|
||||
{
|
||||
union node *n;
|
||||
struct stackmark smark;
|
||||
int inter;
|
||||
int numeof;
|
||||
int numeof = 0;
|
||||
|
||||
TRACE(("cmdloop(%d) called\n", top));
|
||||
setstackmark(&smark);
|
||||
numeof = 0;
|
||||
for (;;) {
|
||||
if (pendingsigs)
|
||||
dotrap();
|
||||
inter = 0;
|
||||
if (iflag && top) {
|
||||
inter++;
|
||||
showjobs(1);
|
||||
showjobs(1, 0, 0);
|
||||
chkmail(0);
|
||||
flushout(&output);
|
||||
}
|
||||
n = parsecmd(inter);
|
||||
#if DEBUG
|
||||
/* showtree(n); */
|
||||
#endif
|
||||
/* showtree(n); DEBUG */
|
||||
if (n == NEOF) {
|
||||
if (Iflag == 0 || numeof >= 50)
|
||||
if (!top || numeof >= 50)
|
||||
break;
|
||||
out2str("\nUse \"exit\" to leave shell.\n");
|
||||
if (!stoppedjobs()) {
|
||||
if (!Iflag)
|
||||
break;
|
||||
out2str("\nUse \"exit\" to leave shell.\n");
|
||||
}
|
||||
numeof++;
|
||||
} else if (n != NULL && nflag == 0) {
|
||||
if (inter) {
|
||||
INTOFF;
|
||||
if (prevcmd)
|
||||
freefunc(prevcmd);
|
||||
prevcmd = curcmd;
|
||||
curcmd = copyfunc(n);
|
||||
INTON;
|
||||
}
|
||||
job_warning = (job_warning == 2) ? 1 : 0;
|
||||
numeof = 0;
|
||||
evaltree(n, 0);
|
||||
#ifdef notdef
|
||||
if (exitstatus) /*DEBUG*/
|
||||
outfmt(&errout, "Exit status 0x%X\n", exitstatus);
|
||||
#endif
|
||||
}
|
||||
popstackmark(&smark);
|
||||
setstackmark(&smark);
|
||||
if (evalskip == SKIPFILE) {
|
||||
evalskip = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
popstackmark(&smark); /* unnecessary */
|
||||
popstackmark(&smark);
|
||||
}
|
||||
|
||||
|
||||
|
@ -266,9 +249,8 @@ cmdloop(top) {
|
|||
*/
|
||||
|
||||
STATIC void
|
||||
read_profile(name)
|
||||
char *name;
|
||||
{
|
||||
read_profile(char *name)
|
||||
{
|
||||
int fd;
|
||||
|
||||
INTOFF;
|
||||
|
@ -288,32 +270,63 @@ read_profile(name)
|
|||
*/
|
||||
|
||||
void
|
||||
readcmdfile(name)
|
||||
char *name;
|
||||
{
|
||||
readcmdfile(char *name)
|
||||
{
|
||||
int fd;
|
||||
|
||||
INTOFF;
|
||||
if ((fd = open(name, O_RDONLY)) >= 0)
|
||||
setinputfd(fd, 1);
|
||||
else
|
||||
error("Can't open %s", name);
|
||||
error("Can't open %s: %s", name, strerror(errno));
|
||||
INTON;
|
||||
cmdloop(0);
|
||||
popfile();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Take commands from a file. To be compatable we should do a path
|
||||
* search for the file, but a path search doesn't make any sense.
|
||||
* Take commands from a file. To be compatible we should do a path
|
||||
* search for the file, which is necessary to find sub-commands.
|
||||
*/
|
||||
|
||||
dotcmd(argc, argv) char **argv; {
|
||||
|
||||
STATIC char *
|
||||
find_dot_file(char *basename)
|
||||
{
|
||||
static char localname[FILENAME_MAX+1];
|
||||
char *fullname;
|
||||
char *path = pathval();
|
||||
struct stat statb;
|
||||
|
||||
/* don't try this for absolute or relative paths */
|
||||
if( strchr(basename, '/'))
|
||||
return basename;
|
||||
|
||||
while ((fullname = padvance(&path, basename)) != NULL) {
|
||||
strcpy(localname, fullname);
|
||||
stunalloc(fullname);
|
||||
if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode))
|
||||
return localname;
|
||||
}
|
||||
return basename;
|
||||
}
|
||||
|
||||
int
|
||||
dotcmd(int argc, char **argv)
|
||||
{
|
||||
struct strlist *sp;
|
||||
exitstatus = 0;
|
||||
|
||||
for (sp = cmdenviron; sp ; sp = sp->next)
|
||||
setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED);
|
||||
|
||||
if (argc >= 2) { /* That's what SVR2 does */
|
||||
setinputfile(argv[1], 1);
|
||||
commandname = argv[1];
|
||||
char *fullname = find_dot_file(argv[1]);
|
||||
|
||||
setinputfile(fullname, 1);
|
||||
commandname = fullname;
|
||||
cmdloop(0);
|
||||
popfile();
|
||||
}
|
||||
|
@ -321,40 +334,22 @@ dotcmd(argc, argv) char **argv; {
|
|||
}
|
||||
|
||||
|
||||
exitcmd(argc, argv) char **argv; {
|
||||
int
|
||||
exitcmd(int argc, char **argv)
|
||||
{
|
||||
extern int oexitstatus;
|
||||
|
||||
if (stoppedjobs())
|
||||
return 0;
|
||||
if (argc > 1)
|
||||
exitstatus = number(argv[1]);
|
||||
else
|
||||
exitstatus = oexitstatus;
|
||||
exitshell(exitstatus);
|
||||
/*NOTREACHED*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
lccmd(argc, argv) char **argv; {
|
||||
if (argc > 1) {
|
||||
defun(argv[1], prevcmd);
|
||||
return 0;
|
||||
} else {
|
||||
INTOFF;
|
||||
freefunc(curcmd);
|
||||
curcmd = prevcmd;
|
||||
prevcmd = NULL;
|
||||
INTON;
|
||||
evaltree(curcmd, 0);
|
||||
return exitstatus;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef notdef
|
||||
/*
|
||||
* Should never be called.
|
||||
* $PchId: main.c,v 1.5 2006/05/22 12:03:02 philip Exp $
|
||||
*/
|
||||
|
||||
void
|
||||
exit(exitstatus) {
|
||||
_exit(exitstatus);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -33,16 +29,18 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)main.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)main.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/main.h,v 1.8 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
extern int rootpid; /* pid of main shell */
|
||||
extern int rootshell; /* true if we aren't a child of the main shell */
|
||||
|
||||
#ifdef __STDC__
|
||||
void readcmdfile(char *);
|
||||
void cmdloop(int);
|
||||
#else
|
||||
void readcmdfile();
|
||||
void cmdloop();
|
||||
#endif
|
||||
int dotcmd(int, char **);
|
||||
int exitcmd(int, char **);
|
||||
|
||||
/*
|
||||
* $PchId: main.h,v 1.3 2006/03/30 11:43:59 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -35,24 +31,33 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)memalloc.c 5.2 (Berkeley) 3/13/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)memalloc.c 8.3 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/memalloc.c,v 1.26 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#include "shell.h"
|
||||
#include "output.h"
|
||||
#include "machdep.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "machdep.h"
|
||||
#include "mystring.h"
|
||||
#include "expand.h"
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* Like malloc, but returns an error when out of space.
|
||||
*/
|
||||
|
||||
pointer
|
||||
ckmalloc(nbytes) {
|
||||
register pointer p;
|
||||
pointer malloc();
|
||||
ckmalloc(int nbytes)
|
||||
{
|
||||
pointer p;
|
||||
|
||||
if ((p = malloc(nbytes)) == NULL)
|
||||
error("Out of space");
|
||||
|
@ -65,11 +70,8 @@ ckmalloc(nbytes) {
|
|||
*/
|
||||
|
||||
pointer
|
||||
ckrealloc(p, nbytes)
|
||||
register pointer p;
|
||||
{
|
||||
pointer realloc();
|
||||
|
||||
ckrealloc(pointer p, int nbytes)
|
||||
{
|
||||
if ((p = realloc(p, nbytes)) == NULL)
|
||||
error("Out of space");
|
||||
return p;
|
||||
|
@ -81,10 +83,9 @@ ckrealloc(p, nbytes)
|
|||
*/
|
||||
|
||||
char *
|
||||
savestr(s)
|
||||
char *s;
|
||||
{
|
||||
register char *p;
|
||||
savestr(char *s)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = ckmalloc(strlen(s) + 1);
|
||||
scopy(s, p);
|
||||
|
@ -97,47 +98,56 @@ savestr(s)
|
|||
* to make this more efficient, and also to avoid all sorts of exception
|
||||
* handling code to handle interrupts in the middle of a parse.
|
||||
*
|
||||
* The size 504 was chosen because the Ultrix malloc handles that size
|
||||
* well.
|
||||
* The size 496 was chosen because with 16-byte alignment the total size
|
||||
* for the allocated block is 512.
|
||||
*/
|
||||
|
||||
#define MINSIZE 504 /* minimum size of a block */
|
||||
#define MINSIZE 496 /* minimum size of a block. */
|
||||
|
||||
|
||||
struct stack_block {
|
||||
struct stack_block *prev;
|
||||
char space[MINSIZE];
|
||||
/* Data follows */
|
||||
};
|
||||
#define SPACE(sp) ((char*)(sp) + ALIGN(sizeof(struct stack_block)))
|
||||
|
||||
struct stack_block stackbase;
|
||||
struct stack_block *stackp = &stackbase;
|
||||
char *stacknxt = stackbase.space;
|
||||
int stacknleft = MINSIZE;
|
||||
STATIC struct stack_block *stackp;
|
||||
STATIC struct stackmark *markp;
|
||||
char *stacknxt;
|
||||
int stacknleft;
|
||||
int sstrnleft;
|
||||
int herefd = -1;
|
||||
|
||||
|
||||
static void
|
||||
stnewblock(int nbytes)
|
||||
{
|
||||
struct stack_block *sp;
|
||||
int allocsize;
|
||||
|
||||
if (nbytes < MINSIZE)
|
||||
nbytes = MINSIZE;
|
||||
|
||||
allocsize = ALIGN(sizeof(struct stack_block)) + ALIGN(nbytes);
|
||||
|
||||
INTOFF;
|
||||
sp = ckmalloc(allocsize);
|
||||
sp->prev = stackp;
|
||||
stacknxt = SPACE(sp);
|
||||
stacknleft = allocsize - (stacknxt - (char*)sp);
|
||||
stackp = sp;
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
pointer
|
||||
stalloc(nbytes) {
|
||||
register char *p;
|
||||
stalloc(int nbytes)
|
||||
{
|
||||
char *p;
|
||||
|
||||
nbytes = ALIGN(nbytes);
|
||||
if (nbytes > stacknleft) {
|
||||
int blocksize;
|
||||
struct stack_block *sp;
|
||||
|
||||
blocksize = nbytes;
|
||||
if (blocksize < MINSIZE)
|
||||
blocksize = MINSIZE;
|
||||
INTOFF;
|
||||
sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
|
||||
sp->prev = stackp;
|
||||
stacknxt = sp->space;
|
||||
stacknleft = blocksize;
|
||||
stackp = sp;
|
||||
INTON;
|
||||
}
|
||||
if (nbytes > stacknleft)
|
||||
stnewblock(nbytes);
|
||||
p = stacknxt;
|
||||
stacknxt += nbytes;
|
||||
stacknleft -= nbytes;
|
||||
|
@ -146,11 +156,10 @@ stalloc(nbytes) {
|
|||
|
||||
|
||||
void
|
||||
stunalloc(p)
|
||||
pointer p;
|
||||
{
|
||||
stunalloc(pointer p)
|
||||
{
|
||||
if (p == NULL) { /*DEBUG */
|
||||
write(2, "stunalloc\n", 10);
|
||||
write(STDERR_FILENO, "stunalloc\n", 10);
|
||||
abort();
|
||||
}
|
||||
stacknleft += stacknxt - (char *)p;
|
||||
|
@ -160,22 +169,23 @@ stunalloc(p)
|
|||
|
||||
|
||||
void
|
||||
setstackmark(mark)
|
||||
struct stackmark *mark;
|
||||
{
|
||||
setstackmark(struct stackmark *mark)
|
||||
{
|
||||
mark->stackp = stackp;
|
||||
mark->stacknxt = stacknxt;
|
||||
mark->stacknleft = stacknleft;
|
||||
mark->marknext = markp;
|
||||
markp = mark;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
popstackmark(mark)
|
||||
struct stackmark *mark;
|
||||
{
|
||||
popstackmark(struct stackmark *mark)
|
||||
{
|
||||
struct stack_block *sp;
|
||||
|
||||
INTOFF;
|
||||
markp = mark->marknext;
|
||||
while (stackp != mark->stackp) {
|
||||
sp = stackp;
|
||||
stackp = sp->prev;
|
||||
|
@ -198,35 +208,56 @@ popstackmark(mark)
|
|||
*/
|
||||
|
||||
void
|
||||
growstackblock() {
|
||||
growstackblock(void)
|
||||
{
|
||||
char *p;
|
||||
int newlen = stacknleft * 2 + 100;
|
||||
char *oldspace = stacknxt;
|
||||
int oldlen = stacknleft;
|
||||
int newlen;
|
||||
char *oldspace;
|
||||
int oldlen;
|
||||
struct stack_block *sp;
|
||||
struct stack_block *oldstackp;
|
||||
struct stackmark *xmark;
|
||||
|
||||
if (stacknxt == stackp->space && stackp != &stackbase) {
|
||||
newlen = (stacknleft == 0) ? MINSIZE : stacknleft * 2 + 100;
|
||||
newlen = ALIGN(newlen);
|
||||
oldspace = stacknxt;
|
||||
oldlen = stacknleft;
|
||||
|
||||
if (stackp != NULL && stacknxt == SPACE(stackp)) {
|
||||
INTOFF;
|
||||
sp = stackp;
|
||||
stackp = sp->prev;
|
||||
sp = ckrealloc((pointer)sp, sizeof(struct stack_block) - MINSIZE + newlen);
|
||||
oldstackp = stackp;
|
||||
stackp = oldstackp->prev;
|
||||
sp = ckrealloc((pointer)oldstackp, newlen);
|
||||
sp->prev = stackp;
|
||||
stackp = sp;
|
||||
stacknxt = sp->space;
|
||||
stacknleft = newlen;
|
||||
stacknxt = SPACE(sp);
|
||||
stacknleft = newlen - (stacknxt - (char*)sp);
|
||||
|
||||
/*
|
||||
* Stack marks pointing to the start of the old block
|
||||
* must be relocated to point to the new block
|
||||
*/
|
||||
xmark = markp;
|
||||
while (xmark != NULL && xmark->stackp == oldstackp) {
|
||||
xmark->stackp = stackp;
|
||||
xmark->stacknxt = stacknxt;
|
||||
xmark->stacknleft = stacknleft;
|
||||
xmark = xmark->marknext;
|
||||
}
|
||||
INTON;
|
||||
} else {
|
||||
p = stalloc(newlen);
|
||||
bcopy(oldspace, p, oldlen);
|
||||
stacknxt = p; /* free the space */
|
||||
stacknleft += newlen; /* we just allocated */
|
||||
if (oldlen != 0)
|
||||
memcpy(p, oldspace, oldlen);
|
||||
stunalloc(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
grabstackblock(len) {
|
||||
grabstackblock(int len)
|
||||
{
|
||||
len = ALIGN(len);
|
||||
stacknxt += len;
|
||||
stacknleft -= len;
|
||||
|
@ -254,8 +285,11 @@ grabstackblock(len) {
|
|||
|
||||
|
||||
char *
|
||||
growstackstr() {
|
||||
int len = stackblocksize();
|
||||
growstackstr(void)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = stackblocksize();
|
||||
if (herefd >= 0 && len >= 1024) {
|
||||
xwrite(herefd, stackblock(), len);
|
||||
sstrnleft = len - 1;
|
||||
|
@ -272,8 +306,11 @@ growstackstr() {
|
|||
*/
|
||||
|
||||
char *
|
||||
makestrspace() {
|
||||
int len = stackblocksize() - sstrnleft;
|
||||
makestrspace(void)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = stackblocksize() - sstrnleft;
|
||||
growstackblock();
|
||||
sstrnleft = stackblocksize() - len;
|
||||
return stackblock() + len;
|
||||
|
@ -282,11 +319,13 @@ makestrspace() {
|
|||
|
||||
|
||||
void
|
||||
ungrabstackstr(s, p)
|
||||
char *s;
|
||||
char *p;
|
||||
{
|
||||
ungrabstackstr(char *s, char *p)
|
||||
{
|
||||
stacknleft += stacknxt - s;
|
||||
stacknxt = s;
|
||||
sstrnleft = stacknleft - (p - s);
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: memalloc.c,v 1.5 2006/05/22 12:03:26 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -33,13 +29,15 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)memalloc.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)memalloc.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/memalloc.h,v 1.9 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
struct stackmark {
|
||||
struct stack_block *stackp;
|
||||
char *stacknxt;
|
||||
int stacknleft;
|
||||
struct stackmark *marknext;
|
||||
};
|
||||
|
||||
|
||||
|
@ -48,10 +46,8 @@ extern int stacknleft;
|
|||
extern int sstrnleft;
|
||||
extern int herefd;
|
||||
|
||||
#ifdef __STDC__
|
||||
pointer ckmalloc(int);
|
||||
pointer ckrealloc(pointer, int);
|
||||
void free(pointer); /* defined in C library */
|
||||
char *savestr(char *);
|
||||
pointer stalloc(int);
|
||||
void stunalloc(pointer);
|
||||
|
@ -62,21 +58,6 @@ void grabstackblock(int);
|
|||
char *growstackstr(void);
|
||||
char *makestrspace(void);
|
||||
void ungrabstackstr(char *, char *);
|
||||
#else
|
||||
pointer ckmalloc();
|
||||
pointer ckrealloc();
|
||||
void free(); /* defined in C library */
|
||||
char *savestr();
|
||||
pointer stalloc();
|
||||
void stunalloc();
|
||||
void setstackmark();
|
||||
void popstackmark();
|
||||
void growstackblock();
|
||||
void grabstackblock();
|
||||
char *growstackstr();
|
||||
char *makestrspace();
|
||||
void ungrabstackstr();
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
@ -84,7 +65,7 @@ void ungrabstackstr();
|
|||
#define stackblocksize() stacknleft
|
||||
#define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize()
|
||||
#define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
|
||||
#define CHECKSTRSPACE(n, p) if (sstrnleft < n) p = makestrspace(); else
|
||||
#define CHECKSTRSPACE(n, p) { if (sstrnleft < n) p = makestrspace(); }
|
||||
#define USTPUTC(c, p) (--sstrnleft, *p++ = (c))
|
||||
#define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
|
||||
#define STUNPUTC(p) (++sstrnleft, --p)
|
||||
|
@ -93,3 +74,7 @@ void ungrabstackstr();
|
|||
#define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
|
||||
|
||||
#define ckfree(p) free((pointer)(p))
|
||||
|
||||
/*
|
||||
* $PchId: memalloc.h,v 1.3 2006/03/30 11:39:41 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -35,13 +31,32 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)miscbltin.c 5.2 (Berkeley) 3/13/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/miscbltin.c,v 1.30 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
/*
|
||||
* Miscelaneous builtins.
|
||||
* Miscellaneous builtins.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/select.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "options.h"
|
||||
#include "var.h"
|
||||
|
@ -49,38 +64,71 @@ static char sccsid[] = "@(#)miscbltin.c 5.2 (Berkeley) 3/13/91";
|
|||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "mystring.h"
|
||||
#include "builtins.h"
|
||||
|
||||
#undef eflag
|
||||
|
||||
extern char **argptr; /* argument list for builtin command */
|
||||
|
||||
|
||||
/*
|
||||
* The read builtin. The -e option causes backslashes to escape the
|
||||
* following character.
|
||||
* The read builtin. The -r option causes backslashes to be treated like
|
||||
* ordinary characters.
|
||||
*
|
||||
* This uses unbuffered input, which may be avoidable in some cases.
|
||||
*/
|
||||
|
||||
readcmd(argc, argv) char **argv; {
|
||||
int
|
||||
readcmd(int argc __unused, char **argv __unused)
|
||||
{
|
||||
char **ap;
|
||||
int backslash;
|
||||
char c;
|
||||
int eflag;
|
||||
int rflag;
|
||||
char *prompt;
|
||||
char *ifs;
|
||||
char *p;
|
||||
int startword;
|
||||
int status;
|
||||
int i;
|
||||
struct timeval tv;
|
||||
char *tvptr;
|
||||
#ifndef __minix_vmd
|
||||
fd_set ifds;
|
||||
#endif
|
||||
struct termios told, tnew;
|
||||
int tsaved;
|
||||
|
||||
eflag = 0;
|
||||
rflag = 0;
|
||||
prompt = NULL;
|
||||
while ((i = nextopt("ep:")) != '\0') {
|
||||
if (i == 'p')
|
||||
prompt = optarg;
|
||||
else
|
||||
eflag = 1;
|
||||
tv.tv_sec = -1;
|
||||
tv.tv_usec = 0;
|
||||
while ((i = nextopt("erp:t:")) != '\0') {
|
||||
switch(i) {
|
||||
case 'p':
|
||||
prompt = shoptarg;
|
||||
break;
|
||||
case 'e':
|
||||
break;
|
||||
case 'r':
|
||||
rflag = 1;
|
||||
break;
|
||||
case 't':
|
||||
tv.tv_sec = strtol(shoptarg, &tvptr, 0);
|
||||
if (tvptr == shoptarg)
|
||||
error("timeout value");
|
||||
switch(*tvptr) {
|
||||
case 0:
|
||||
case 's':
|
||||
break;
|
||||
case 'h':
|
||||
tv.tv_sec *= 60;
|
||||
/* FALLTHROUGH */
|
||||
case 'm':
|
||||
tv.tv_sec *= 60;
|
||||
break;
|
||||
default:
|
||||
error("timeout unit");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (prompt && isatty(0)) {
|
||||
out2str(prompt);
|
||||
|
@ -90,12 +138,45 @@ readcmd(argc, argv) char **argv; {
|
|||
error("arg count");
|
||||
if ((ifs = bltinlookup("IFS", 1)) == NULL)
|
||||
ifs = nullstr;
|
||||
|
||||
if (tv.tv_sec >= 0) {
|
||||
#ifdef __minix
|
||||
abort();
|
||||
#else
|
||||
/*
|
||||
* See if we can disable input processing; this will
|
||||
* not give the desired result if we are in a pipeline
|
||||
* and someone upstream is still in line-by-line mode.
|
||||
*/
|
||||
tsaved = 0;
|
||||
if (tcgetattr(0, &told) == 0) {
|
||||
memcpy(&tnew, &told, sizeof(told));
|
||||
cfmakeraw(&tnew);
|
||||
tcsetattr(0, TCSANOW, &tnew);
|
||||
tsaved = 1;
|
||||
}
|
||||
/*
|
||||
* Wait for something to become available.
|
||||
*/
|
||||
FD_ZERO(&ifds);
|
||||
FD_SET(0, &ifds);
|
||||
status = select(1, &ifds, NULL, NULL, &tv);
|
||||
if (tsaved)
|
||||
tcsetattr(0, TCSANOW, &told);
|
||||
/*
|
||||
* If there's nothing ready, return an error.
|
||||
*/
|
||||
if (status <= 0)
|
||||
return(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
status = 0;
|
||||
startword = 1;
|
||||
backslash = 0;
|
||||
STARTSTACKSTR(p);
|
||||
for (;;) {
|
||||
if (read(0, &c, 1) != 1) {
|
||||
if (read(STDIN_FILENO, &c, 1) != 1) {
|
||||
status = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -107,7 +188,7 @@ readcmd(argc, argv) char **argv; {
|
|||
STPUTC(c, p);
|
||||
continue;
|
||||
}
|
||||
if (eflag && c == '\\') {
|
||||
if (!rflag && c == '\\') {
|
||||
backslash++;
|
||||
continue;
|
||||
}
|
||||
|
@ -118,7 +199,7 @@ readcmd(argc, argv) char **argv; {
|
|||
}
|
||||
startword = 0;
|
||||
if (backslash && c == '\\') {
|
||||
if (read(0, &c, 1) != 1) {
|
||||
if (read(STDIN_FILENO, &c, 1) != 1) {
|
||||
status = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -142,25 +223,274 @@ readcmd(argc, argv) char **argv; {
|
|||
|
||||
|
||||
|
||||
umaskcmd(argc, argv) char **argv; {
|
||||
int
|
||||
umaskcmd(int argc __unused, char **argv)
|
||||
{
|
||||
char *ap;
|
||||
int mask;
|
||||
char *p;
|
||||
int i;
|
||||
int symbolic_mode = 0;
|
||||
|
||||
if ((p = argv[1]) == NULL) {
|
||||
INTOFF;
|
||||
mask = umask(0);
|
||||
umask(mask);
|
||||
INTON;
|
||||
out1fmt("%.4o\n", mask); /* %#o might be better */
|
||||
while ((i = nextopt("S")) != '\0') {
|
||||
symbolic_mode = 1;
|
||||
}
|
||||
|
||||
INTOFF;
|
||||
mask = umask(0);
|
||||
umask(mask);
|
||||
INTON;
|
||||
|
||||
if ((ap = *argptr) == NULL) {
|
||||
if (symbolic_mode) {
|
||||
char u[4], g[4], o[4];
|
||||
|
||||
i = 0;
|
||||
if ((mask & S_IRUSR) == 0)
|
||||
u[i++] = 'r';
|
||||
if ((mask & S_IWUSR) == 0)
|
||||
u[i++] = 'w';
|
||||
if ((mask & S_IXUSR) == 0)
|
||||
u[i++] = 'x';
|
||||
u[i] = '\0';
|
||||
|
||||
i = 0;
|
||||
if ((mask & S_IRGRP) == 0)
|
||||
g[i++] = 'r';
|
||||
if ((mask & S_IWGRP) == 0)
|
||||
g[i++] = 'w';
|
||||
if ((mask & S_IXGRP) == 0)
|
||||
g[i++] = 'x';
|
||||
g[i] = '\0';
|
||||
|
||||
i = 0;
|
||||
if ((mask & S_IROTH) == 0)
|
||||
o[i++] = 'r';
|
||||
if ((mask & S_IWOTH) == 0)
|
||||
o[i++] = 'w';
|
||||
if ((mask & S_IXOTH) == 0)
|
||||
o[i++] = 'x';
|
||||
o[i] = '\0';
|
||||
|
||||
out1fmt("u=%s,g=%s,o=%s\n", u, g, o);
|
||||
} else {
|
||||
out1fmt("%.4o\n", mask);
|
||||
}
|
||||
} else {
|
||||
mask = 0;
|
||||
do {
|
||||
if ((unsigned)(i = *p - '0') >= 8)
|
||||
error("Illegal number: %s", argv[1]);
|
||||
mask = (mask << 3) + i;
|
||||
} while (*++p != '\0');
|
||||
umask(mask);
|
||||
if (isdigit(*ap)) {
|
||||
mask = 0;
|
||||
do {
|
||||
if (*ap >= '8' || *ap < '0')
|
||||
error("Illegal number: %s", argv[1]);
|
||||
mask = (mask << 3) + (*ap - '0');
|
||||
} while (*++ap != '\0');
|
||||
umask(mask);
|
||||
} else {
|
||||
void *set;
|
||||
if ((set = setmode (ap)) == 0)
|
||||
error("Illegal number: %s", ap);
|
||||
|
||||
mask = getmode (set, ~mask & 0777);
|
||||
umask(~mask & 0777);
|
||||
free(set);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __minix
|
||||
struct rlimit
|
||||
{
|
||||
unsigned long rlim_cur; /* current (soft) limit */
|
||||
unsigned long rlim_max; /* maximum value for rlim_cur */
|
||||
};
|
||||
#define RLIM_INFINITY (((unsigned long)1 << 31) - 1)
|
||||
|
||||
int getrlimit (int, struct rlimit *);
|
||||
int setrlimit (int, const struct rlimit *);
|
||||
|
||||
int getrlimit(resource, rlp)
|
||||
int resource;
|
||||
struct rlimit *rlp;
|
||||
{
|
||||
errno= ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
int setrlimit(resource, rlp)
|
||||
int resource;
|
||||
const struct rlimit *rlp;
|
||||
{
|
||||
errno= ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ulimit builtin
|
||||
*
|
||||
* This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
|
||||
* Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
|
||||
* ash by J.T. Conklin.
|
||||
*
|
||||
* Public domain.
|
||||
*/
|
||||
|
||||
struct limits {
|
||||
const char *name;
|
||||
const char *units;
|
||||
int cmd;
|
||||
int factor; /* multiply by to get rlim_{cur,max} values */
|
||||
char option;
|
||||
};
|
||||
|
||||
static const struct limits limits[] = {
|
||||
#ifdef RLIMIT_CPU
|
||||
{ "cpu time", "seconds", RLIMIT_CPU, 1, 't' },
|
||||
#endif
|
||||
#ifdef RLIMIT_FSIZE
|
||||
{ "file size", "512-blocks", RLIMIT_FSIZE, 512, 'f' },
|
||||
#endif
|
||||
#ifdef RLIMIT_DATA
|
||||
{ "data seg size", "kbytes", RLIMIT_DATA, 1024, 'd' },
|
||||
#endif
|
||||
#ifdef RLIMIT_STACK
|
||||
{ "stack size", "kbytes", RLIMIT_STACK, 1024, 's' },
|
||||
#endif
|
||||
#ifdef RLIMIT_CORE
|
||||
{ "core file size", "512-blocks", RLIMIT_CORE, 512, 'c' },
|
||||
#endif
|
||||
#ifdef RLIMIT_RSS
|
||||
{ "max memory size", "kbytes", RLIMIT_RSS, 1024, 'm' },
|
||||
#endif
|
||||
#ifdef RLIMIT_MEMLOCK
|
||||
{ "locked memory", "kbytes", RLIMIT_MEMLOCK, 1024, 'l' },
|
||||
#endif
|
||||
#ifdef RLIMIT_NPROC
|
||||
{ "max user processes", (char *)0, RLIMIT_NPROC, 1, 'u' },
|
||||
#endif
|
||||
#ifdef RLIMIT_NOFILE
|
||||
{ "open files", (char *)0, RLIMIT_NOFILE, 1, 'n' },
|
||||
#endif
|
||||
#ifdef RLIMIT_VMEM
|
||||
{ "virtual mem size", "kbytes", RLIMIT_VMEM, 1024, 'v' },
|
||||
#endif
|
||||
#ifdef RLIMIT_SWAP
|
||||
{ "swap limit", "kbytes", RLIMIT_SWAP, 1024, 'w' },
|
||||
#endif
|
||||
#ifdef RLIMIT_SBSIZE
|
||||
{ "sbsize", "bytes", RLIMIT_SBSIZE, 1, 'b' },
|
||||
#endif
|
||||
{ (char *) 0, (char *)0, 0, 0, '\0' }
|
||||
};
|
||||
|
||||
int
|
||||
ulimitcmd(int argc __unused, char **argv __unused)
|
||||
{
|
||||
int c;
|
||||
intmax_t val = 0;
|
||||
enum { SOFT = 0x1, HARD = 0x2 }
|
||||
how = SOFT | HARD;
|
||||
const struct limits *l;
|
||||
int set, all = 0;
|
||||
int optc, what;
|
||||
struct rlimit limit;
|
||||
|
||||
what = 'f';
|
||||
while ((optc = nextopt("HSatfdsmcnuvlb")) != '\0')
|
||||
switch (optc) {
|
||||
case 'H':
|
||||
how = HARD;
|
||||
break;
|
||||
case 'S':
|
||||
how = SOFT;
|
||||
break;
|
||||
case 'a':
|
||||
all = 1;
|
||||
break;
|
||||
default:
|
||||
what = optc;
|
||||
}
|
||||
|
||||
for (l = limits; l->name && l->option != what; l++)
|
||||
;
|
||||
if (!l->name)
|
||||
error("internal error (%c)", what);
|
||||
|
||||
set = *argptr ? 1 : 0;
|
||||
if (set) {
|
||||
char *p = *argptr;
|
||||
|
||||
if (all || argptr[1])
|
||||
error("too many arguments");
|
||||
if (strcmp(p, "unlimited") == 0)
|
||||
val = RLIM_INFINITY;
|
||||
else {
|
||||
val = 0;
|
||||
|
||||
while ((c = *p++) >= '0' && c <= '9')
|
||||
{
|
||||
val = (val * 10) + (long)(c - '0');
|
||||
if (val < 0)
|
||||
break;
|
||||
}
|
||||
if (c)
|
||||
error("bad number");
|
||||
val *= l->factor;
|
||||
}
|
||||
}
|
||||
if (all) {
|
||||
for (l = limits; l->name; l++) {
|
||||
char optbuf[40];
|
||||
if (getrlimit(l->cmd, &limit) < 0)
|
||||
error("can't get limit: %s", strerror(errno));
|
||||
if (how & SOFT)
|
||||
val = limit.rlim_cur;
|
||||
else if (how & HARD)
|
||||
val = limit.rlim_max;
|
||||
|
||||
if (l->units)
|
||||
snprintf(optbuf, sizeof(optbuf),
|
||||
"(%s, -%c) ", l->units, l->option);
|
||||
else
|
||||
snprintf(optbuf, sizeof(optbuf),
|
||||
"(-%c) ", l->option);
|
||||
out1fmt("%-18s %18s ", l->name, optbuf);
|
||||
if (val == RLIM_INFINITY)
|
||||
out1fmt("unlimited\n");
|
||||
else
|
||||
{
|
||||
val /= l->factor;
|
||||
out1fmt("%jd\n", (intmax_t)val);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (getrlimit(l->cmd, &limit) < 0)
|
||||
error("can't get limit: %s", strerror(errno));
|
||||
if (set) {
|
||||
if (how & SOFT)
|
||||
limit.rlim_cur = val;
|
||||
if (how & HARD)
|
||||
limit.rlim_max = val;
|
||||
if (setrlimit(l->cmd, &limit) < 0)
|
||||
error("bad limit: %s", strerror(errno));
|
||||
} else {
|
||||
if (how & SOFT)
|
||||
val = limit.rlim_cur;
|
||||
else if (how & HARD)
|
||||
val = limit.rlim_max;
|
||||
|
||||
if (val == RLIM_INFINITY)
|
||||
out1fmt("unlimited\n");
|
||||
else
|
||||
{
|
||||
val /= l->factor;
|
||||
out1fmt("%jd\n", (intmax_t)val);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: miscbltin.c,v 1.7 2006/05/23 11:59:08 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/sh -
|
||||
#
|
||||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
|
@ -14,10 +14,6 @@
|
|||
# 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.
|
||||
|
@ -34,90 +30,69 @@
|
|||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)mkbuiltins 5.2 (Berkeley) 3/8/91
|
||||
# @(#)mkbuiltins 8.2 (Berkeley) 5/4/95
|
||||
# $FreeBSD: src/bin/sh/mkbuiltins,v 1.13 2004/04/06 20:06:51 markm Exp $
|
||||
|
||||
# All calls to awk removed, because Minix bawk is deficient. (kjb)
|
||||
|
||||
if [ $# != 2 ]
|
||||
then
|
||||
echo "USAGE: $0 shell.h builtins"
|
||||
exit 1
|
||||
#temp=`/usr/bin/mktemp -t ka`
|
||||
temp=/tmp/mkb$$
|
||||
havehist=1
|
||||
if [ "X$1" = "X-h" ]; then
|
||||
havehist=0
|
||||
shift
|
||||
fi
|
||||
SHL=$1
|
||||
BLTINS=$2
|
||||
|
||||
temp=/tmp/ka$$
|
||||
exec > builtins.c
|
||||
havejobs=0
|
||||
if [ "X$1" = "X-j" ]; then
|
||||
havejobs=0
|
||||
shift
|
||||
elif grep '^#define[ ]*JOBS[ ]*1' $2 > /dev/null
|
||||
then havejobs=1
|
||||
fi
|
||||
objdir=$1
|
||||
exec > ${objdir}/builtins.c
|
||||
cat <<\!
|
||||
/*
|
||||
* This file was generated by the mkbuiltins program.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
|
||||
!
|
||||
if grep '^#define JOBS[ ]*1' $SHL > /dev/null
|
||||
then
|
||||
# Job control.
|
||||
sed -e '/^#/d
|
||||
s/ / /g
|
||||
s/ #.*//
|
||||
/^ *$/d
|
||||
s/-j//' $BLTINS > $temp
|
||||
else
|
||||
# No job control.
|
||||
sed -e '/^#/d
|
||||
s/ / /g
|
||||
s/ #.*//
|
||||
/^ *$/d
|
||||
/-j/d' $BLTINS > $temp
|
||||
fi
|
||||
sed -e 's/ .*//
|
||||
s/\(.*\)/int \1();/' $temp
|
||||
awk '/^[^#]/ {if(('$havejobs' || $2 != "-j") && ('$havehist' || $2 != "-h")) \
|
||||
print $0}' $3 | sed 's/-[hj]//' > $temp
|
||||
#awk '{ printf "int %s();\n", $1}' $temp
|
||||
echo '
|
||||
int (*const builtinfunc[])() = {'
|
||||
sed -e 's/ .*//
|
||||
s/\(.*\)/ \1,/' $temp
|
||||
int (*const builtinfunc[]) (int, char **) = {'
|
||||
awk '/^[^#]/ { printf "\t%s,\n", $1}' $temp
|
||||
echo '};
|
||||
|
||||
const struct builtincmd builtincmd[] = {'
|
||||
i=0
|
||||
while read line
|
||||
do
|
||||
set -$- $line
|
||||
shift
|
||||
for fun
|
||||
do
|
||||
echo " \"$fun\", $i,"
|
||||
done
|
||||
i=`expr $i + 1`
|
||||
done < $temp
|
||||
echo ' NULL, 0
|
||||
awk '{ for (i = 2 ; i <= NF ; i++) {
|
||||
printf "\t{ \"%s\", %d },\n", $i, NR-1
|
||||
}}' $temp
|
||||
echo ' { NULL, 0 }
|
||||
};'
|
||||
|
||||
exec > builtins.h
|
||||
exec > ${objdir}/builtins.h
|
||||
cat <<\!
|
||||
/*
|
||||
* This file was generated by the mkbuiltins program.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
!
|
||||
i=0
|
||||
tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ < $temp |
|
||||
while read line
|
||||
do
|
||||
set -$- $line
|
||||
echo "#define $1 $i"
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
awk '{ printf "#define %s %d\n", $1, NR-1}'
|
||||
echo '
|
||||
struct builtincmd {
|
||||
char *name;
|
||||
int code;
|
||||
};
|
||||
|
||||
extern int (*const builtinfunc[])();
|
||||
extern int (*const builtinfunc[]) (int, char **);
|
||||
extern const struct builtincmd builtincmd[];'
|
||||
awk '{ printf "int %s (int, char **);\n", $1 }' < $temp
|
||||
rm -f $temp
|
||||
|
||||
#
|
||||
# $PchId: mkbuiltins,v 1.6 2006/05/22 12:42:58 philip Exp $
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -35,43 +31,51 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
char copyright[] =
|
||||
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
|
||||
All rights reserved.\n";
|
||||
static char const copyright[] =
|
||||
"@(#) Copyright (c) 1991, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)mkinit.c 5.3 (Berkeley) 3/13/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)mkinit.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/mkinit.c,v 1.17 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program scans all the source files for code to handle various
|
||||
* special events and combines this code into one file. This (allegedly)
|
||||
* improves the structure of the program since there is no need for
|
||||
* anyone outside of a module to know that that module performs special
|
||||
* operations on particular events. The command is executed iff init.c
|
||||
* is actually changed.
|
||||
* operations on particular events.
|
||||
*
|
||||
* Usage: mkinit command sourcefile...
|
||||
* Usage: mkinit sourcefile...
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef __minix
|
||||
#define __unused
|
||||
#endif
|
||||
|
||||
/*
|
||||
* OUTFILE is the name of the output file. Output is initially written
|
||||
* to the file OUTTEMP, which is then moved to OUTFILE if OUTTEMP and
|
||||
* OUTFILE are different.
|
||||
* to the file OUTTEMP, which is then moved to OUTFILE.
|
||||
*/
|
||||
|
||||
#define OUTFILE "init.c"
|
||||
#define OUTTEMP "init.c.new"
|
||||
#define OUTOBJ "init.o"
|
||||
|
||||
|
||||
/*
|
||||
|
@ -105,7 +109,7 @@ struct event {
|
|||
char *name; /* name of event (e.g. INIT) */
|
||||
char *routine; /* name of routine called on event */
|
||||
char *comment; /* comment describing routine */
|
||||
struct text code; /* code for handling event */
|
||||
struct text code; /* code for handling event */
|
||||
};
|
||||
|
||||
|
||||
|
@ -148,42 +152,35 @@ struct text decls; /* declarations */
|
|||
int amiddecls; /* for formatting */
|
||||
|
||||
|
||||
void readfile(), doevent(), doinclude(), dodecl(), output();
|
||||
void addstr(), addchar(), writetext();
|
||||
static void readfile(char *);
|
||||
static int match(char *, char *);
|
||||
static int gooddefine(char *);
|
||||
static void doevent(struct event *, FILE *, char *);
|
||||
static void doinclude(char *);
|
||||
static void dodecl(char *, FILE *);
|
||||
static void output(void);
|
||||
static void addstr(char *, struct text *);
|
||||
static void addchar(int, struct text *);
|
||||
static void writetext(struct text *, FILE *);
|
||||
static FILE *ckfopen(char *, char *);
|
||||
static void *ckmalloc(int);
|
||||
static char *savestr(char *);
|
||||
static void error(char *);
|
||||
|
||||
#define equal(s1, s2) (strcmp(s1, s2) == 0)
|
||||
|
||||
FILE *ckfopen();
|
||||
char *savestr();
|
||||
void *ckmalloc __P((int));
|
||||
void error();
|
||||
|
||||
main(argc, argv)
|
||||
char **argv;
|
||||
{
|
||||
int
|
||||
main(int argc __unused, char *argv[])
|
||||
{
|
||||
char **ap;
|
||||
int fd;
|
||||
char c;
|
||||
|
||||
if (argc < 2)
|
||||
error("Usage: mkinit command file...");
|
||||
header_files[0] = "\"shell.h\"";
|
||||
header_files[1] = "\"mystring.h\"";
|
||||
for (ap = argv + 2 ; *ap ; ap++)
|
||||
for (ap = argv + 1 ; *ap ; ap++)
|
||||
readfile(*ap);
|
||||
output();
|
||||
if (file_changed()) {
|
||||
unlink(OUTFILE);
|
||||
link(OUTTEMP, OUTFILE);
|
||||
unlink(OUTTEMP);
|
||||
} else {
|
||||
unlink(OUTTEMP);
|
||||
if (touch(OUTOBJ))
|
||||
exit(0); /* no compilation necessary */
|
||||
}
|
||||
printf("%s\n", argv[1]);
|
||||
execl("/bin/sh", "sh", "-c", argv[1], (char *)0);
|
||||
error("Can't exec shell");
|
||||
rename(OUTTEMP, OUTFILE);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -191,10 +188,9 @@ main(argc, argv)
|
|||
* Parse an input file.
|
||||
*/
|
||||
|
||||
void
|
||||
readfile(fname)
|
||||
char *fname;
|
||||
{
|
||||
static void
|
||||
readfile(char *fname)
|
||||
{
|
||||
FILE *fp;
|
||||
char line[1024];
|
||||
struct event *ep;
|
||||
|
@ -215,19 +211,31 @@ readfile(fname)
|
|||
doinclude(line);
|
||||
if (line[0] == 'M' && match("MKINIT", line))
|
||||
dodecl(line, fp);
|
||||
if (line[0] == '#' && gooddefine(line))
|
||||
if (line[0] == '#' && gooddefine(line)) {
|
||||
char *cp;
|
||||
char line2[1024];
|
||||
static const char undef[] = "#undef ";
|
||||
|
||||
strcpy(line2, line);
|
||||
memcpy(line2, undef, sizeof(undef) - 1);
|
||||
cp = line2 + sizeof(undef) - 1;
|
||||
while(*cp && (*cp == ' ' || *cp == '\t'))
|
||||
cp++;
|
||||
while(*cp && *cp != ' ' && *cp != '\t' && *cp != '\n')
|
||||
cp++;
|
||||
*cp++ = '\n'; *cp = '\0';
|
||||
addstr(line2, &defines);
|
||||
addstr(line, &defines);
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
match(name, line)
|
||||
char *name;
|
||||
char *line;
|
||||
{
|
||||
register char *p, *q;
|
||||
static int
|
||||
match(char *name, char *line)
|
||||
{
|
||||
char *p, *q;
|
||||
|
||||
p = name, q = line;
|
||||
while (*p) {
|
||||
|
@ -240,11 +248,10 @@ match(name, line)
|
|||
}
|
||||
|
||||
|
||||
int
|
||||
gooddefine(line)
|
||||
char *line;
|
||||
{
|
||||
register char *p;
|
||||
static int
|
||||
gooddefine(char *line)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (! match("#define", line))
|
||||
return 0; /* not a define */
|
||||
|
@ -264,12 +271,9 @@ gooddefine(line)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
doevent(ep, fp, fname)
|
||||
register struct event *ep;
|
||||
FILE *fp;
|
||||
char *fname;
|
||||
{
|
||||
static void
|
||||
doevent(struct event *ep, FILE *fp, char *fname)
|
||||
{
|
||||
char line[1024];
|
||||
int indent;
|
||||
char *p;
|
||||
|
@ -304,13 +308,12 @@ doevent(ep, fp, fname)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
doinclude(line)
|
||||
char *line;
|
||||
{
|
||||
register char *p;
|
||||
static void
|
||||
doinclude(char *line)
|
||||
{
|
||||
char *p;
|
||||
char *name;
|
||||
register char **pp;
|
||||
char **pp;
|
||||
|
||||
for (p = line ; *p != '"' && *p != '<' && *p != '\0' ; p++);
|
||||
if (*p == '\0')
|
||||
|
@ -329,13 +332,11 @@ doinclude(line)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
dodecl(line1, fp)
|
||||
char *line1;
|
||||
FILE *fp;
|
||||
{
|
||||
static void
|
||||
dodecl(char *line1, FILE *fp)
|
||||
{
|
||||
char line[1024];
|
||||
register char *p, *q;
|
||||
char *p, *q;
|
||||
|
||||
if (strcmp(line1, "MKINIT\n") == 0) { /* start of struct/union decl */
|
||||
addchar('\n', &decls);
|
||||
|
@ -350,7 +351,8 @@ dodecl(line1, fp)
|
|||
if (! amiddecls)
|
||||
addchar('\n', &decls);
|
||||
q = NULL;
|
||||
for (p = line1 + 6 ; *p != '=' && *p != '/' ; p++);
|
||||
for (p = line1 + 6 ; *p && strchr("=/\n", *p) == NULL; p++)
|
||||
continue;
|
||||
if (*p == '=') { /* eliminate initialization */
|
||||
for (q = p ; *q && *q != ';' ; q++);
|
||||
if (*q == '\0')
|
||||
|
@ -375,8 +377,9 @@ dodecl(line1, fp)
|
|||
* Write the output to the file OUTTEMP.
|
||||
*/
|
||||
|
||||
void
|
||||
output() {
|
||||
static void
|
||||
output(void)
|
||||
{
|
||||
FILE *fp;
|
||||
char **pp;
|
||||
struct event *ep;
|
||||
|
@ -392,7 +395,7 @@ output() {
|
|||
for (ep = event ; ep->name ; ep++) {
|
||||
fputs("\n\n\n", fp);
|
||||
fputs(ep->comment, fp);
|
||||
fprintf(fp, "\nvoid\n%s() {\n", ep->routine);
|
||||
fprintf(fp, "\nvoid\n%s(void) {\n", ep->routine);
|
||||
writetext(&ep->code, fp);
|
||||
fprintf(fp, "}\n");
|
||||
}
|
||||
|
@ -400,62 +403,15 @@ output() {
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return true if the new output file is different from the old one.
|
||||
*/
|
||||
|
||||
int
|
||||
file_changed() {
|
||||
register FILE *f1, *f2;
|
||||
register int c;
|
||||
|
||||
if ((f1 = fopen(OUTFILE, "r")) == NULL
|
||||
|| (f2 = fopen(OUTTEMP, "r")) == NULL)
|
||||
return 1;
|
||||
while ((c = getc(f1)) == getc(f2)) {
|
||||
if (c == EOF)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Touch a file. Returns 0 on failure, 1 on success.
|
||||
*/
|
||||
|
||||
int
|
||||
touch(file)
|
||||
char *file;
|
||||
{
|
||||
int fd;
|
||||
char c;
|
||||
|
||||
if ((fd = open(file, O_RDWR)) < 0)
|
||||
return 0;
|
||||
if (read(fd, &c, 1) != 1) {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
lseek(fd, 0L, 0);
|
||||
write(fd, &c, 1);
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* A text structure is simply a block of text that is kept in memory.
|
||||
* Addstr appends a string to the text struct, and addchar appends a single
|
||||
* character.
|
||||
*/
|
||||
|
||||
void
|
||||
addstr(s, text)
|
||||
register char *s;
|
||||
register struct text *text;
|
||||
{
|
||||
static void
|
||||
addstr(char *s, struct text *text)
|
||||
{
|
||||
while (*s) {
|
||||
if (--text->nleft < 0)
|
||||
addchar(*s++, text);
|
||||
|
@ -465,10 +421,9 @@ addstr(s, text)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
addchar(c, text)
|
||||
register struct text *text;
|
||||
{
|
||||
static void
|
||||
addchar(int c, struct text *text)
|
||||
{
|
||||
struct block *bp;
|
||||
|
||||
if (--text->nleft < 0) {
|
||||
|
@ -487,11 +442,9 @@ addchar(c, text)
|
|||
/*
|
||||
* Write the contents of a text structure to a file.
|
||||
*/
|
||||
void
|
||||
writetext(text, fp)
|
||||
struct text *text;
|
||||
FILE *fp;
|
||||
{
|
||||
static void
|
||||
writetext(struct text *text, FILE *fp)
|
||||
{
|
||||
struct block *bp;
|
||||
|
||||
if (text->start != NULL) {
|
||||
|
@ -501,47 +454,47 @@ writetext(text, fp)
|
|||
}
|
||||
}
|
||||
|
||||
FILE *
|
||||
ckfopen(file, mode)
|
||||
char *file;
|
||||
char *mode;
|
||||
{
|
||||
static FILE *
|
||||
ckfopen(char *file, char *mode)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if ((fp = fopen(file, mode)) == NULL) {
|
||||
fprintf(stderr, "Can't open %s\n", file);
|
||||
fprintf(stderr, "Can't open %s: %s\n", file, strerror(errno));
|
||||
exit(2);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
void *
|
||||
ckmalloc(nbytes) {
|
||||
register char *p;
|
||||
char *malloc();
|
||||
static void *
|
||||
ckmalloc(int nbytes)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if ((p = malloc(nbytes)) == NULL)
|
||||
error("Out of space");
|
||||
return p;
|
||||
}
|
||||
|
||||
char *
|
||||
savestr(s)
|
||||
char *s;
|
||||
{
|
||||
register char *p;
|
||||
static char *
|
||||
savestr(char *s)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = ckmalloc(strlen(s) + 1);
|
||||
strcpy(p, s);
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
error(msg)
|
||||
char *msg;
|
||||
{
|
||||
static void
|
||||
error(char *msg)
|
||||
{
|
||||
if (curfile != NULL)
|
||||
fprintf(stderr, "%s:%d: ", curfile, linno);
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: mkinit.c,v 1.6 2006/05/22 12:16:50 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -34,15 +30,20 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
char copyright[] =
|
||||
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
|
||||
All rights reserved.\n";
|
||||
static char const copyright[] =
|
||||
"@(#) Copyright (c) 1991, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)mknodes.c 5.1 (Berkeley) 3/7/91";
|
||||
static char sccsid[] = "@(#)mknodes.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/bin/sh/mknodes.c,v 1.17 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program reads the nodetypes file and nodes.c.pat file. It generates
|
||||
|
@ -50,7 +51,10 @@ static char sccsid[] = "@(#)mknodes.c 5.1 (Berkeley) 3/7/91";
|
|||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define MAXTYPES 50 /* max number of node types */
|
||||
#define MAXFIELDS 20 /* max fields in a structure */
|
||||
|
@ -80,31 +84,42 @@ struct str { /* struct representing a node structure */
|
|||
};
|
||||
|
||||
|
||||
int ntypes; /* number of node types */
|
||||
char *nodename[MAXTYPES]; /* names of the nodes */
|
||||
struct str *nodestr[MAXTYPES]; /* type of structure used by the node */
|
||||
int nstr; /* number of structures */
|
||||
struct str str[MAXTYPES]; /* the structures */
|
||||
struct str *curstr; /* current structure */
|
||||
static int ntypes; /* number of node types */
|
||||
static char *nodename[MAXTYPES]; /* names of the nodes */
|
||||
static struct str *nodestr[MAXTYPES]; /* type of structure used by the node */
|
||||
static int nstr; /* number of structures */
|
||||
static struct str str[MAXTYPES]; /* the structures */
|
||||
static struct str *curstr; /* current structure */
|
||||
static FILE *infp;
|
||||
static char line[1024];
|
||||
static int linno;
|
||||
static char *linep;
|
||||
|
||||
#ifndef __printf0like
|
||||
#define __printf0like(a,b)
|
||||
#endif
|
||||
|
||||
static void parsenode(void);
|
||||
static void parsefield(void);
|
||||
static void output(char *);
|
||||
static void outsizes(FILE *);
|
||||
static void outfunc(FILE *, int);
|
||||
static void indent(int, FILE *);
|
||||
static int nextfield(char *);
|
||||
static void skipbl(void);
|
||||
static int readline(void);
|
||||
static void error(const char *, ...) __printf0like(1, 2);
|
||||
static char *savestr(const char *);
|
||||
|
||||
|
||||
FILE *infp = stdin;
|
||||
char line[1024];
|
||||
int linno;
|
||||
char *linep;
|
||||
|
||||
|
||||
char *savestr();
|
||||
#define equal(s1, s2) (strcmp(s1, s2) == 0)
|
||||
|
||||
|
||||
main(argc, argv)
|
||||
char **argv;
|
||||
{
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 3)
|
||||
error("usage: mknodes file\n");
|
||||
error("usage: mknodes file");
|
||||
infp = stdin;
|
||||
if ((infp = fopen(argv[1], "r")) == NULL)
|
||||
error("Can't open %s", argv[1]);
|
||||
error("Can't open %s: %s", argv[1], strerror(errno));
|
||||
while (readline()) {
|
||||
if (line[0] == ' ' || line[0] == '\t')
|
||||
parsefield();
|
||||
|
@ -112,12 +127,14 @@ main(argc, argv)
|
|||
parsenode();
|
||||
}
|
||||
output(argv[2]);
|
||||
return 0;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
parsenode() {
|
||||
static void
|
||||
parsenode(void)
|
||||
{
|
||||
char name[BUFLEN];
|
||||
char tag[BUFLEN];
|
||||
struct str *sp;
|
||||
|
@ -131,7 +148,7 @@ parsenode() {
|
|||
error("Garbage at end of line");
|
||||
nodename[ntypes] = savestr(name);
|
||||
for (sp = str ; sp < str + nstr ; sp++) {
|
||||
if (equal(sp->tag, tag))
|
||||
if (strcmp(sp->tag, tag) == 0)
|
||||
break;
|
||||
}
|
||||
if (sp >= str + nstr) {
|
||||
|
@ -145,7 +162,9 @@ parsenode() {
|
|||
}
|
||||
|
||||
|
||||
parsefield() {
|
||||
static void
|
||||
parsefield(void)
|
||||
{
|
||||
char name[BUFLEN];
|
||||
char type[BUFLEN];
|
||||
char decl[2 * BUFLEN];
|
||||
|
@ -159,21 +178,21 @@ parsefield() {
|
|||
error("No field type");
|
||||
fp = &curstr->field[curstr->nfields];
|
||||
fp->name = savestr(name);
|
||||
if (equal(type, "nodeptr")) {
|
||||
if (strcmp(type, "nodeptr") == 0) {
|
||||
fp->type = T_NODE;
|
||||
sprintf(decl, "union node *%s", name);
|
||||
} else if (equal(type, "nodelist")) {
|
||||
} else if (strcmp(type, "nodelist") == 0) {
|
||||
fp->type = T_NODELIST;
|
||||
sprintf(decl, "struct nodelist *%s", name);
|
||||
} else if (equal(type, "string")) {
|
||||
} else if (strcmp(type, "string") == 0) {
|
||||
fp->type = T_STRING;
|
||||
sprintf(decl, "char *%s", name);
|
||||
} else if (equal(type, "int")) {
|
||||
} else if (strcmp(type, "int") == 0) {
|
||||
fp->type = T_INT;
|
||||
sprintf(decl, "int %s", name);
|
||||
} else if (equal(type, "other")) {
|
||||
} else if (strcmp(type, "other") == 0) {
|
||||
fp->type = T_OTHER;
|
||||
} else if (equal(type, "temp")) {
|
||||
} else if (strcmp(type, "temp") == 0) {
|
||||
fp->type = T_TEMP;
|
||||
} else {
|
||||
error("Unknown type %s", type);
|
||||
|
@ -196,9 +215,9 @@ char writer[] = "\
|
|||
*/\n\
|
||||
\n";
|
||||
|
||||
output(file)
|
||||
char *file;
|
||||
{
|
||||
static void
|
||||
output(char *file)
|
||||
{
|
||||
FILE *hfile;
|
||||
FILE *cfile;
|
||||
FILE *patfile;
|
||||
|
@ -208,9 +227,9 @@ output(file)
|
|||
char *p;
|
||||
|
||||
if ((patfile = fopen(file, "r")) == NULL)
|
||||
error("Can't open %s", file);
|
||||
error("Can't open %s: %s", file, strerror(errno));
|
||||
if ((hfile = fopen("nodes.h", "w")) == NULL)
|
||||
error("Can't create nodes.h");
|
||||
error("Can't create nodes.h: %s", strerror(errno));
|
||||
if ((cfile = fopen("nodes.c", "w")) == NULL)
|
||||
error("Can't create nodes.c");
|
||||
fputs(writer, hfile);
|
||||
|
@ -234,22 +253,17 @@ output(file)
|
|||
fputs("\tstruct nodelist *next;\n", hfile);
|
||||
fputs("\tunion node *n;\n", hfile);
|
||||
fputs("};\n\n\n", hfile);
|
||||
fputs("#ifdef __STDC__\n", hfile);
|
||||
fputs("union node *copyfunc(union node *);\n", hfile);
|
||||
fputs("void freefunc(union node *);\n", hfile);
|
||||
fputs("#else\n", hfile);
|
||||
fputs("union node *copyfunc();\n", hfile);
|
||||
fputs("void freefunc();\n", hfile);
|
||||
fputs("#endif\n", hfile);
|
||||
|
||||
fputs(writer, cfile);
|
||||
while (fgets(line, sizeof line, patfile) != NULL) {
|
||||
for (p = line ; *p == ' ' || *p == '\t' ; p++);
|
||||
if (equal(p, "%SIZES\n"))
|
||||
if (strcmp(p, "%SIZES\n") == 0)
|
||||
outsizes(cfile);
|
||||
else if (equal(p, "%CALCSIZE\n"))
|
||||
else if (strcmp(p, "%CALCSIZE\n") == 0)
|
||||
outfunc(cfile, 1);
|
||||
else if (equal(p, "%COPY\n"))
|
||||
else if (strcmp(p, "%COPY\n") == 0)
|
||||
outfunc(cfile, 0);
|
||||
else
|
||||
fputs(line, cfile);
|
||||
|
@ -258,9 +272,9 @@ output(file)
|
|||
|
||||
|
||||
|
||||
outsizes(cfile)
|
||||
FILE *cfile;
|
||||
{
|
||||
static void
|
||||
outsizes(FILE *cfile)
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf(cfile, "static const short nodesize[%d] = {\n", ntypes);
|
||||
|
@ -271,9 +285,9 @@ outsizes(cfile)
|
|||
}
|
||||
|
||||
|
||||
outfunc(cfile, calcsize)
|
||||
FILE *cfile;
|
||||
{
|
||||
static void
|
||||
outfunc(FILE *cfile, int calcsize)
|
||||
{
|
||||
struct str *sp;
|
||||
struct field *fp;
|
||||
int i;
|
||||
|
@ -287,8 +301,7 @@ outfunc(cfile, calcsize)
|
|||
fputs(" funcblocksize += nodesize[n->type];\n", cfile);
|
||||
else {
|
||||
fputs(" new = funcblock;\n", cfile);
|
||||
fputs(" *(char **)&funcblock += nodesize[n->type];\n",
|
||||
cfile);
|
||||
fputs(" funcblock = (char *)funcblock + nodesize[n->type];\n", cfile);
|
||||
}
|
||||
fputs(" switch (n->type) {\n", cfile);
|
||||
for (sp = str ; sp < &str[nstr] ; sp++) {
|
||||
|
@ -351,9 +364,9 @@ outfunc(cfile, calcsize)
|
|||
}
|
||||
|
||||
|
||||
indent(amount, fp)
|
||||
FILE *fp;
|
||||
{
|
||||
static void
|
||||
indent(int amount, FILE *fp)
|
||||
{
|
||||
while (amount >= 8) {
|
||||
putc('\t', fp);
|
||||
amount -= 8;
|
||||
|
@ -364,11 +377,10 @@ indent(amount, fp)
|
|||
}
|
||||
|
||||
|
||||
int
|
||||
nextfield(buf)
|
||||
char *buf;
|
||||
{
|
||||
register char *p, *q;
|
||||
static int
|
||||
nextfield(char *buf)
|
||||
{
|
||||
char *p, *q;
|
||||
|
||||
p = linep;
|
||||
while (*p == ' ' || *p == '\t')
|
||||
|
@ -382,15 +394,18 @@ nextfield(buf)
|
|||
}
|
||||
|
||||
|
||||
skipbl() {
|
||||
static void
|
||||
skipbl(void)
|
||||
{
|
||||
while (*linep == ' ' || *linep == '\t')
|
||||
linep++;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
readline() {
|
||||
register char *p;
|
||||
static int
|
||||
readline(void)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (fgets(line, 1024, infp) == NULL)
|
||||
return 0;
|
||||
|
@ -407,26 +422,34 @@ readline() {
|
|||
|
||||
|
||||
|
||||
error(msg, a1, a2, a3, a4, a5, a6)
|
||||
char *msg;
|
||||
{
|
||||
fprintf(stderr, "line %d: ", linno);
|
||||
fprintf(stderr, msg, a1, a2, a3, a4, a5, a6);
|
||||
putc('\n', stderr);
|
||||
static void
|
||||
error(const char *msg, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, msg);
|
||||
|
||||
(void) fprintf(stderr, "line %d: ", linno);
|
||||
(void) vfprintf(stderr, msg, va);
|
||||
(void) fputc('\n', stderr);
|
||||
|
||||
va_end(va);
|
||||
|
||||
exit(2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *
|
||||
savestr(s)
|
||||
char *s;
|
||||
{
|
||||
register char *p;
|
||||
char *malloc();
|
||||
static char *
|
||||
savestr(const char *s)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if ((p = malloc(strlen(s) + 1)) == NULL)
|
||||
error("Out of space");
|
||||
strcpy(p, s);
|
||||
(void) strcpy(p, s);
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: mknodes.c,v 1.6 2006/05/23 12:05:14 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -35,23 +35,23 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
char copyright[] =
|
||||
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
|
||||
All rights reserved.\n";
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1991, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)mksignames.c 5.1 (Berkeley) 3/7/91";
|
||||
static char sccsid[] = "@(#)mksignames.c 8.1 (Berkeley) 5/31/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* This program generates the signames.h and signames.c files.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
|
||||
|
||||
int main(int argc, char *argv[]);
|
||||
|
||||
struct sig {
|
||||
int signo; /* signal number */
|
||||
|
@ -198,3 +198,7 @@ main(argc, argv) char **argv; {
|
|||
fprintf(cfile, "};\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: mksignames.c,v 1.2 2001/05/14 19:22:26 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -34,23 +30,33 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
char copyright[] =
|
||||
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
|
||||
All rights reserved.\n";
|
||||
static char const copyright[] =
|
||||
"@(#) Copyright (c) 1991, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)mksyntax.c 5.2 (Berkeley) 3/8/91";
|
||||
static char sccsid[] = "@(#)mksyntax.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/bin/sh/mksyntax.c,v 1.23 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program creates syntax.h and syntax.c.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "parser.h"
|
||||
|
||||
#ifdef __minix
|
||||
#define __unused
|
||||
#endif
|
||||
|
||||
struct synclass {
|
||||
char *name;
|
||||
|
@ -59,19 +65,21 @@ struct synclass {
|
|||
|
||||
/* Syntax classes */
|
||||
struct synclass synclass[] = {
|
||||
"CWORD", "character is nothing special",
|
||||
"CNL", "newline character",
|
||||
"CBACK", "a backslash character",
|
||||
"CSQUOTE", "single quote",
|
||||
"CDQUOTE", "double quote",
|
||||
"CENDQUOTE", "a terminating quote",
|
||||
"CBQUOTE", "backwards single quote",
|
||||
"CVAR", "a dollar sign",
|
||||
"CENDVAR", "a '}' character",
|
||||
"CEOF", "end of file",
|
||||
"CCTL", "like CWORD, except it must be escaped",
|
||||
"CSPCL", "these terminate a word",
|
||||
NULL, NULL
|
||||
{ "CWORD", "character is nothing special" },
|
||||
{ "CNL", "newline character" },
|
||||
{ "CBACK", "a backslash character" },
|
||||
{ "CSQUOTE", "single quote" },
|
||||
{ "CDQUOTE", "double quote" },
|
||||
{ "CENDQUOTE", "a terminating quote" },
|
||||
{ "CBQUOTE", "backwards single quote" },
|
||||
{ "CVAR", "a dollar sign" },
|
||||
{ "CENDVAR", "a '}' character" },
|
||||
{ "CLP", "a left paren in arithmetic" },
|
||||
{ "CRP", "a right paren in arithmetic" },
|
||||
{ "CEOF", "end of file" },
|
||||
{ "CCTL", "like CWORD, except it must be escaped" },
|
||||
{ "CSPCL", "these terminate a word" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
|
@ -80,31 +88,39 @@ struct synclass synclass[] = {
|
|||
* you may have to change the definition of the is_in_name macro.
|
||||
*/
|
||||
struct synclass is_entry[] = {
|
||||
"ISDIGIT", "a digit",
|
||||
"ISUPPER", "an upper case letter",
|
||||
"ISLOWER", "a lower case letter",
|
||||
"ISUNDER", "an underscore",
|
||||
"ISSPECL", "the name of a special parameter",
|
||||
NULL, NULL,
|
||||
{ "ISDIGIT", "a digit" },
|
||||
{ "ISUPPER", "an upper case letter" },
|
||||
{ "ISLOWER", "a lower case letter" },
|
||||
{ "ISUNDER", "an underscore" },
|
||||
{ "ISSPECL", "the name of a special parameter" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
char writer[] = "\
|
||||
static char writer[] = "\
|
||||
/*\n\
|
||||
* This file was generated by the mksyntax program.\n\
|
||||
*/\n\
|
||||
\n";
|
||||
|
||||
|
||||
FILE *cfile;
|
||||
FILE *hfile;
|
||||
char *syntax[513];
|
||||
int base;
|
||||
int size; /* number of values which a char variable can have */
|
||||
int nbits; /* number of bits in a character */
|
||||
int digit_contig; /* true if digits are contiguous */
|
||||
static FILE *cfile;
|
||||
static FILE *hfile;
|
||||
static char *syntax[513];
|
||||
static int base;
|
||||
static int size; /* number of values which a char variable can have */
|
||||
static int nbits; /* number of bits in a character */
|
||||
static int digit_contig;/* true if digits are contiguous */
|
||||
|
||||
static void filltable(char *);
|
||||
static void init(void);
|
||||
static void add(char *, char *);
|
||||
static void print(char *);
|
||||
static void output_type_macros(void);
|
||||
static void digit_convert(void);
|
||||
|
||||
main() {
|
||||
int
|
||||
main(int argc __unused, char **argv __unused)
|
||||
{
|
||||
char c;
|
||||
char d;
|
||||
int sign;
|
||||
|
@ -136,7 +152,9 @@ main() {
|
|||
if (d == c)
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits);
|
||||
#endif
|
||||
if (nbits > 9) {
|
||||
fputs("Characters can't have more than 9 bits\n", stderr);
|
||||
exit(2);
|
||||
|
@ -151,14 +169,14 @@ main() {
|
|||
digit_contig = 0;
|
||||
}
|
||||
|
||||
fputs("#include <sys/cdefs.h>\n", hfile);
|
||||
fputs("#include <ctype.h>\n", hfile);
|
||||
|
||||
/* Generate the #define statements in the header file */
|
||||
fputs("/* Syntax classes */\n", hfile);
|
||||
for (i = 0 ; synclass[i].name ; i++) {
|
||||
sprintf(buf, "#define %s %d", synclass[i].name, i);
|
||||
fputs(buf, hfile);
|
||||
for (pos = strlen(buf) ; pos < 32 ; pos = pos + 8 &~ 07)
|
||||
for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07)
|
||||
putc('\t', hfile);
|
||||
fprintf(hfile, "/* %s */\n", synclass[i].comment);
|
||||
}
|
||||
|
@ -167,7 +185,7 @@ main() {
|
|||
for (i = 0 ; is_entry[i].name ; i++) {
|
||||
sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i);
|
||||
fputs(buf, hfile);
|
||||
for (pos = strlen(buf) ; pos < 32 ; pos = pos + 8 &~ 07)
|
||||
for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07)
|
||||
putc('\t', hfile);
|
||||
fprintf(hfile, "/* %s */\n", is_entry[i].comment);
|
||||
}
|
||||
|
@ -178,6 +196,7 @@ main() {
|
|||
fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
|
||||
fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
|
||||
fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile);
|
||||
fputs("#define ARISYNTAX (arisyntax + SYNBASE)\n", hfile);
|
||||
putc('\n', hfile);
|
||||
output_type_macros(); /* is_digit, etc. */
|
||||
putc('\n', hfile);
|
||||
|
@ -204,14 +223,28 @@ main() {
|
|||
add("`", "CBQUOTE");
|
||||
add("$", "CVAR");
|
||||
add("}", "CENDVAR");
|
||||
add("!*?[=", "CCTL");
|
||||
/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
|
||||
add("!*?[=~:/-", "CCTL");
|
||||
print("dqsyntax");
|
||||
init();
|
||||
fputs("\n/* syntax table used when in single quotes */\n", cfile);
|
||||
add("\n", "CNL");
|
||||
add("'", "CENDQUOTE");
|
||||
add("!*?[=", "CCTL");
|
||||
/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
|
||||
add("!*?[=~:/-", "CCTL");
|
||||
print("sqsyntax");
|
||||
init();
|
||||
fputs("\n/* syntax table used when in arithmetic */\n", cfile);
|
||||
add("\n", "CNL");
|
||||
add("\\", "CBACK");
|
||||
add("`", "CBQUOTE");
|
||||
add("'", "CSQUOTE");
|
||||
add("\"", "CDQUOTE");
|
||||
add("$", "CVAR");
|
||||
add("}", "CENDVAR");
|
||||
add("(", "CLP");
|
||||
add(")", "CRP");
|
||||
print("arisyntax");
|
||||
filltable("0");
|
||||
fputs("\n/* character classification table */\n", cfile);
|
||||
add("0123456789", "ISDIGIT");
|
||||
|
@ -231,9 +264,9 @@ main() {
|
|||
* Clear the syntax table.
|
||||
*/
|
||||
|
||||
filltable(dftval)
|
||||
char *dftval;
|
||||
{
|
||||
static void
|
||||
filltable(char *dftval)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < size ; i++)
|
||||
|
@ -245,7 +278,9 @@ filltable(dftval)
|
|||
* Initialize the syntax table with default values.
|
||||
*/
|
||||
|
||||
init() {
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
filltable("CWORD");
|
||||
syntax[0] = "CEOF";
|
||||
syntax[base + CTLESC] = "CCTL";
|
||||
|
@ -253,6 +288,9 @@ init() {
|
|||
syntax[base + CTLENDVAR] = "CCTL";
|
||||
syntax[base + CTLBACKQ] = "CCTL";
|
||||
syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL";
|
||||
syntax[base + CTLARI] = "CCTL";
|
||||
syntax[base + CTLENDARI] = "CCTL";
|
||||
syntax[base + CTLQUOTEMARK] = "CCTL";
|
||||
}
|
||||
|
||||
|
||||
|
@ -260,9 +298,9 @@ init() {
|
|||
* Add entries to the syntax table.
|
||||
*/
|
||||
|
||||
add(p, type)
|
||||
char *p, *type;
|
||||
{
|
||||
static void
|
||||
add(char *p, char *type)
|
||||
{
|
||||
while (*p)
|
||||
syntax[*p++ + base] = type;
|
||||
}
|
||||
|
@ -273,9 +311,9 @@ add(p, type)
|
|||
* Output the syntax table.
|
||||
*/
|
||||
|
||||
print(name)
|
||||
char *name;
|
||||
{
|
||||
static void
|
||||
print(char *name)
|
||||
{
|
||||
int i;
|
||||
int col;
|
||||
|
||||
|
@ -306,16 +344,18 @@ print(name)
|
|||
* contiguous, we can test for them quickly.
|
||||
*/
|
||||
|
||||
char *macro[] = {
|
||||
static char *macro[] = {
|
||||
"#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)",
|
||||
"#define is_alpha(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER))",
|
||||
"#define is_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER))",
|
||||
"#define is_in_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER|ISDIGIT))",
|
||||
"#define is_alpha(c)\t((c) != PEOF && ((c) < CTLESC || (c) > CTLQUOTEMARK) && isalpha((unsigned char) (c)))",
|
||||
"#define is_name(c)\t((c) != PEOF && ((c) < CTLESC || (c) > CTLQUOTEMARK) && ((c) == '_' || isalpha((unsigned char) (c))))",
|
||||
"#define is_in_name(c)\t((c) != PEOF && ((c) < CTLESC || (c) > CTLQUOTEMARK) && ((c) == '_' || isalnum((unsigned char) (c))))",
|
||||
"#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))",
|
||||
NULL
|
||||
};
|
||||
|
||||
output_type_macros() {
|
||||
static void
|
||||
output_type_macros(void)
|
||||
{
|
||||
char **pp;
|
||||
|
||||
if (digit_contig)
|
||||
|
@ -334,7 +374,9 @@ output_type_macros() {
|
|||
* Output digit conversion table (if digits are not contiguous).
|
||||
*/
|
||||
|
||||
digit_convert() {
|
||||
static void
|
||||
digit_convert(void)
|
||||
{
|
||||
int maxdigit;
|
||||
static char digit[] = "0123456789";
|
||||
char *p;
|
||||
|
@ -350,7 +392,11 @@ digit_convert() {
|
|||
for (p = digit ; *p && *p != i ; p++);
|
||||
if (*p == '\0')
|
||||
p = digit;
|
||||
fprintf(cfile, " %d,\n", p - digit);
|
||||
fprintf(cfile, " %d,\n", (int)(p - digit));
|
||||
}
|
||||
fputs("};\n", cfile);
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: mksyntax.c,v 1.7 2006/05/23 12:04:27 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/sh -
|
||||
#
|
||||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
|
@ -14,10 +14,6 @@
|
|||
# 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.
|
||||
|
@ -34,7 +30,8 @@
|
|||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)mktokens 5.1 (Berkeley) 3/7/91
|
||||
# @(#)mktokens 8.1 (Berkeley) 5/31/93
|
||||
# $FreeBSD: src/bin/sh/mktokens,v 1.9 2004/04/06 20:06:51 markm Exp $
|
||||
|
||||
# All calls to awk removed, because Minix bawk is deficient. (kjb)
|
||||
|
||||
|
@ -42,7 +39,9 @@
|
|||
# token marks the end of a list. The third column is the name to print in
|
||||
# error messages.
|
||||
|
||||
cat > /tmp/ka$$ <<\!
|
||||
#temp=`/usr/bin/mktemp -t ka`
|
||||
temp=/tmp/mkt$$
|
||||
cat > $temp <<\!
|
||||
TEOF 1 end of file
|
||||
TNL 0 newline
|
||||
TSEMI 0 ";"
|
||||
|
@ -70,16 +69,17 @@ TBEGIN 0 "{"
|
|||
TEND 1 "}"
|
||||
TCASE 0 "case"
|
||||
TESAC 1 "esac"
|
||||
TNOT 0 "!"
|
||||
!
|
||||
nl=`wc -l /tmp/ka$$`
|
||||
exec > token.def
|
||||
nl=`wc -l $temp`
|
||||
exec > token.h
|
||||
i=0
|
||||
while read line
|
||||
do
|
||||
set -$- $line
|
||||
echo "#define $1 $i"
|
||||
i=`expr $i + 1`
|
||||
done </tmp/ka$$
|
||||
done <$temp
|
||||
echo '
|
||||
/* Array indicating which tokens mark the end of a list */
|
||||
const char tokendlist[] = {'
|
||||
|
@ -87,18 +87,18 @@ while read line
|
|||
do
|
||||
set -$- $line
|
||||
echo " $2,"
|
||||
done </tmp/ka$$
|
||||
done <$temp
|
||||
echo '};
|
||||
|
||||
char *const tokname[] = {'
|
||||
const char *const tokname[] = {'
|
||||
sed -e 's/"/\\"/g' \
|
||||
-e 's/[^ ]*[ ][ ]*[^ ]*[ ][ ]*\(.*\)/ "\1",/' \
|
||||
/tmp/ka$$
|
||||
$temp
|
||||
echo '};
|
||||
'
|
||||
i=0
|
||||
go=
|
||||
sed 's/"//g' /tmp/ka$$ |
|
||||
sed 's/"//g' $temp |
|
||||
while read line
|
||||
do
|
||||
set -$- $line
|
||||
|
@ -106,7 +106,7 @@ sed 's/"//g' /tmp/ka$$ |
|
|||
then
|
||||
echo "#define KWDOFFSET $i"
|
||||
echo
|
||||
echo "char *const parsekwd[] = {"
|
||||
echo "const char *const parsekwd[] = {"
|
||||
go=true
|
||||
fi
|
||||
if [ "$go" ]
|
||||
|
@ -118,4 +118,7 @@ sed 's/"//g' /tmp/ka$$ |
|
|||
echo ' 0
|
||||
};'
|
||||
|
||||
rm /tmp/ka$$
|
||||
rm $temp
|
||||
|
||||
#
|
||||
# $PchId: mktokens,v 1.5 2006/05/22 12:43:35 philip Exp $
|
||||
|
|
50
commands/ash/myhistedit.h
Normal file
50
commands/ash/myhistedit.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*-
|
||||
* Copyright (c) 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.
|
||||
* 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.
|
||||
*
|
||||
* @(#)myhistedit.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/myhistedit.h,v 1.10 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
#include <histedit.h>
|
||||
|
||||
extern History *hist;
|
||||
extern EditLine *el;
|
||||
extern int displayhist;
|
||||
|
||||
void histedit(void);
|
||||
void sethistsize(const char *);
|
||||
int histcmd(int, char **);
|
||||
int bindcmd(int, char **);
|
||||
|
||||
/* From libedit */
|
||||
void re_goto_bottom(EditLine *);
|
||||
|
||||
/*
|
||||
* $PchId: myhistedit.h,v 1.5 2006/03/29 15:55:18 philip Exp $
|
||||
*/
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -35,8 +31,14 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)mystring.c 5.1 (Berkeley) 3/7/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)mystring.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/mystring.c,v 1.13 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
/*
|
||||
* String functions.
|
||||
|
@ -44,12 +46,11 @@ static char sccsid[] = "@(#)mystring.c 5.1 (Berkeley) 3/7/91";
|
|||
* equal(s1, s2) Return true if strings are equal.
|
||||
* scopy(from, to) Copy a string.
|
||||
* scopyn(from, to, n) Like scopy, but checks for overflow.
|
||||
* strchr(s, c) Find first occurance of c in s.
|
||||
* bcopy(from, to, n) Copy a block of memory.
|
||||
* number(s) Convert a string of digits to an integer.
|
||||
* is_number(s) Return true if s is a string of digits.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "shell.h"
|
||||
#include "syntax.h"
|
||||
#include "error.h"
|
||||
|
@ -58,6 +59,14 @@ static char sccsid[] = "@(#)mystring.c 5.1 (Berkeley) 3/7/91";
|
|||
|
||||
char nullstr[1]; /* zero length string */
|
||||
|
||||
/*
|
||||
* equal - #defined in mystring.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* scopy - #defined in mystring.h
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* scopyn - copy a string from "from" to "to", truncating the string
|
||||
|
@ -66,11 +75,8 @@ char nullstr[1]; /* zero length string */
|
|||
*/
|
||||
|
||||
void
|
||||
scopyn(from, to, size)
|
||||
register char const *from;
|
||||
register char *to;
|
||||
register int size;
|
||||
{
|
||||
scopyn(const char *from, char *to, int size)
|
||||
{
|
||||
|
||||
while (--size > 0) {
|
||||
if ((*to++ = *from++) == '\0')
|
||||
|
@ -80,59 +86,13 @@ scopyn(from, to, size)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* strchr - find first occurrence of a character in a string.
|
||||
*/
|
||||
|
||||
#ifndef SYS5
|
||||
char *
|
||||
mystrchr(s, charwanted)
|
||||
char const *s;
|
||||
register char charwanted;
|
||||
{
|
||||
register char const *scan;
|
||||
|
||||
/*
|
||||
* The odd placement of the two tests is so NUL is findable.
|
||||
*/
|
||||
for (scan = s ; *scan != charwanted ; ) /* ++ moved down for opt. */
|
||||
if (*scan++ == '\0')
|
||||
return NULL;
|
||||
return (char *)scan;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* bcopy - copy bytes
|
||||
*
|
||||
* This routine was derived from code by Henry Spencer.
|
||||
*/
|
||||
|
||||
void
|
||||
mybcopy(src, dst, length)
|
||||
pointer dst;
|
||||
const pointer src;
|
||||
register int length;
|
||||
{
|
||||
register char *d = dst;
|
||||
register char *s = src;
|
||||
|
||||
while (--length >= 0)
|
||||
*d++ = *s++;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* prefix -- see if pfx is a prefix of string.
|
||||
*/
|
||||
|
||||
int
|
||||
prefix(pfx, string)
|
||||
register char const *pfx;
|
||||
register char const *string;
|
||||
{
|
||||
prefix(const char *pfx, const char *string)
|
||||
{
|
||||
while (*pfx) {
|
||||
if (*pfx++ != *string++)
|
||||
return 0;
|
||||
|
@ -147,12 +107,10 @@ prefix(pfx, string)
|
|||
*/
|
||||
|
||||
int
|
||||
number(s)
|
||||
const char *s;
|
||||
{
|
||||
|
||||
number(const char *s)
|
||||
{
|
||||
if (! is_number(s))
|
||||
error2("Illegal number", (char *)s);
|
||||
error("Illegal number: %s", (char *)s);
|
||||
return atoi(s);
|
||||
}
|
||||
|
||||
|
@ -163,12 +121,15 @@ number(s)
|
|||
*/
|
||||
|
||||
int
|
||||
is_number(p)
|
||||
register const char *p;
|
||||
{
|
||||
is_number(const char *p)
|
||||
{
|
||||
do {
|
||||
if (! is_digit(*p))
|
||||
return 0;
|
||||
} while (*++p != '\0');
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: mystring.c,v 1.4 2006/05/22 12:21:53 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -33,39 +29,20 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)mystring.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)mystring.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/mystring.h,v 1.8 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
#ifndef SYSV
|
||||
#define strchr mystrchr
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __STDC__
|
||||
void scopyn(const char *, char *, int);
|
||||
char *strchr(const char *, int);
|
||||
void mybcopy(const pointer, pointer, int);
|
||||
int prefix(const char *, const char *);
|
||||
int number(const char *);
|
||||
int is_number(const char *);
|
||||
int strcmp(const char *, const char *); /* from C library */
|
||||
char *strcpy(char *, const char *); /* from C library */
|
||||
int strlen(const char *); /* from C library */
|
||||
char *strcat(char *, const char *); /* from C library */
|
||||
char *strerror(int); /* from C library */
|
||||
#else
|
||||
void scopyn();
|
||||
char *strchr();
|
||||
void mybcopy();
|
||||
int prefix();
|
||||
int number();
|
||||
int is_number();
|
||||
int strcmp();
|
||||
char *strcpy();
|
||||
int strlen();
|
||||
char *strcat();
|
||||
char *strerror();
|
||||
#endif
|
||||
|
||||
#define equal(s1, s2) (strcmp(s1, s2) == 0)
|
||||
#define scopy(s1, s2) ((void)strcpy(s2, s1))
|
||||
#define bcopy(src, dst, n) mybcopy((pointer)(src), (pointer)(dst), n)
|
||||
|
||||
/*
|
||||
* $PchId: mystring.h,v 1.3 2006/03/29 15:49:08 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -33,9 +29,11 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nodes.c.pat 5.2 (Berkeley) 3/8/91
|
||||
* @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/nodes.c.pat,v 1.15 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
/*
|
||||
* Routine for dealing with parsed shell commands.
|
||||
*/
|
||||
|
@ -43,35 +41,26 @@
|
|||
#include "shell.h"
|
||||
#include "nodes.h"
|
||||
#include "memalloc.h"
|
||||
#include "machdep.h"
|
||||
#include "mystring.h"
|
||||
|
||||
|
||||
int funcblocksize; /* size of structures in function */
|
||||
int funcstringsize; /* size of strings in node */
|
||||
#ifdef __STDC__
|
||||
pointer funcblock; /* block to allocate function from */
|
||||
#else
|
||||
char *funcblock; /* block to allocate function from */
|
||||
#ifndef __minix
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
char *funcstring; /* block to allocate strings from */
|
||||
#include "machdep.h"
|
||||
|
||||
STATIC int funcblocksize; /* size of structures in function */
|
||||
STATIC int funcstringsize; /* size of strings in node */
|
||||
STATIC pointer funcblock; /* block to allocate function from */
|
||||
STATIC char *funcstring; /* block to allocate strings from */
|
||||
|
||||
%SIZES
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
STATIC void calcsize(union node *);
|
||||
STATIC void sizenodelist(struct nodelist *);
|
||||
STATIC union node *copynode(union node *);
|
||||
STATIC struct nodelist *copynodelist(struct nodelist *);
|
||||
STATIC char *nodesavestr(char *);
|
||||
#else
|
||||
STATIC void calcsize();
|
||||
STATIC void sizenodelist();
|
||||
STATIC union node *copynode();
|
||||
STATIC struct nodelist *copynodelist();
|
||||
STATIC char *nodesavestr();
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
@ -80,86 +69,81 @@ STATIC char *nodesavestr();
|
|||
*/
|
||||
|
||||
union node *
|
||||
copyfunc(n)
|
||||
union node *n;
|
||||
{
|
||||
if (n == NULL)
|
||||
return NULL;
|
||||
funcblocksize = 0;
|
||||
funcstringsize = 0;
|
||||
calcsize(n);
|
||||
funcblock = ckmalloc(funcblocksize + funcstringsize);
|
||||
funcstring = (char *)funcblock + funcblocksize;
|
||||
return copynode(n);
|
||||
copyfunc(union node *n)
|
||||
{
|
||||
if (n == NULL)
|
||||
return NULL;
|
||||
funcblocksize = 0;
|
||||
funcstringsize = 0;
|
||||
calcsize(n);
|
||||
funcblock = ckmalloc(funcblocksize + funcstringsize);
|
||||
funcstring = (char *)funcblock + funcblocksize;
|
||||
return copynode(n);
|
||||
}
|
||||
|
||||
|
||||
|
||||
STATIC void
|
||||
calcsize(n)
|
||||
union node *n;
|
||||
{
|
||||
%CALCSIZE
|
||||
calcsize(union node *n)
|
||||
{
|
||||
%CALCSIZE
|
||||
}
|
||||
|
||||
|
||||
|
||||
STATIC void
|
||||
sizenodelist(lp)
|
||||
struct nodelist *lp;
|
||||
{
|
||||
while (lp) {
|
||||
funcblocksize += ALIGN(sizeof (struct nodelist));
|
||||
calcsize(lp->n);
|
||||
lp = lp->next;
|
||||
}
|
||||
sizenodelist(struct nodelist *lp)
|
||||
{
|
||||
while (lp) {
|
||||
funcblocksize += ALIGN(sizeof(struct nodelist));
|
||||
calcsize(lp->n);
|
||||
lp = lp->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
STATIC union node *
|
||||
copynode(n)
|
||||
union node *n;
|
||||
{
|
||||
union node *new;
|
||||
copynode(union node *n)
|
||||
{
|
||||
union node *new;
|
||||
|
||||
%COPY
|
||||
return new;
|
||||
%COPY
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
STATIC struct nodelist *
|
||||
copynodelist(lp)
|
||||
struct nodelist *lp;
|
||||
{
|
||||
struct nodelist *start;
|
||||
struct nodelist **lpp;
|
||||
copynodelist(struct nodelist *lp)
|
||||
{
|
||||
struct nodelist *start;
|
||||
struct nodelist **lpp;
|
||||
|
||||
lpp = &start;
|
||||
while (lp) {
|
||||
*lpp = funcblock;
|
||||
*(char **)&funcblock += ALIGN(sizeof (struct nodelist));
|
||||
(*lpp)->n = copynode(lp->n);
|
||||
lp = lp->next;
|
||||
lpp = &(*lpp)->next;
|
||||
}
|
||||
*lpp = NULL;
|
||||
return start;
|
||||
lpp = &start;
|
||||
while (lp) {
|
||||
*lpp = funcblock;
|
||||
funcblock = (char *)funcblock + ALIGN(sizeof(struct nodelist));
|
||||
(*lpp)->n = copynode(lp->n);
|
||||
lp = lp->next;
|
||||
lpp = &(*lpp)->next;
|
||||
}
|
||||
*lpp = NULL;
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
|
||||
STATIC char *
|
||||
nodesavestr(s)
|
||||
char *s;
|
||||
{
|
||||
register char *p = s;
|
||||
register char *q = funcstring;
|
||||
char *rtn = funcstring;
|
||||
nodesavestr(char *s)
|
||||
{
|
||||
char *p = s;
|
||||
char *q = funcstring;
|
||||
char *rtn = funcstring;
|
||||
|
||||
while (*q++ = *p++);
|
||||
funcstring = q;
|
||||
return rtn;
|
||||
while ((*q++ = *p++) != '\0')
|
||||
continue;
|
||||
funcstring = q;
|
||||
return rtn;
|
||||
}
|
||||
|
||||
|
||||
|
@ -169,9 +153,12 @@ nodesavestr(s)
|
|||
*/
|
||||
|
||||
void
|
||||
freefunc(n)
|
||||
union node *n;
|
||||
{
|
||||
if (n)
|
||||
ckfree(n);
|
||||
freefunc(union node *n)
|
||||
{
|
||||
if (n)
|
||||
ckfree(n);
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: nodes.c.pat,v 1.5 2006/05/22 12:43:57 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#!/bin/sh -
|
||||
#
|
||||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
|
@ -14,10 +13,6 @@
|
|||
# 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.
|
||||
|
@ -34,7 +29,8 @@
|
|||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)nodetypes 5.1 (Berkeley) 3/7/91
|
||||
# @(#)nodetypes 8.2 (Berkeley) 5/4/95
|
||||
# $FreeBSD: src/bin/sh/nodetypes,v 1.9 2004/04/06 20:06:51 markm Exp $
|
||||
|
||||
# This file describes the nodes used in parse trees. Unindented lines
|
||||
# contain a node type followed by a structure tag. Subsequent indented
|
||||
|
@ -118,7 +114,9 @@ NARG narg # represents a word
|
|||
|
||||
NTO nfile # fd> fname
|
||||
NFROM nfile # fd< fname
|
||||
NFROMTO nfile # fd<> fname
|
||||
NAPPEND nfile # fd>> fname
|
||||
NCLOBBER nfile # fd>| fname
|
||||
type int
|
||||
next nodeptr # next redirection in list
|
||||
fd int # file descriptor being redirected
|
||||
|
@ -131,6 +129,8 @@ NFROMFD ndup # fd>&dupfd
|
|||
next nodeptr # next redirection in list
|
||||
fd int # file descriptor being redirected
|
||||
dupfd int # file descriptor to duplicate
|
||||
vname nodeptr # file name if fd>&$var
|
||||
|
||||
|
||||
NHERE nhere # fd<<\!
|
||||
NXHERE nhere # fd<<!
|
||||
|
@ -138,3 +138,10 @@ NXHERE nhere # fd<<!
|
|||
next nodeptr # next redirection in list
|
||||
fd int # file descriptor being redirected
|
||||
doc nodeptr # input to command (NARG node)
|
||||
|
||||
NNOT nnot # ! command (actually pipeline)
|
||||
type int
|
||||
com nodeptr
|
||||
|
||||
#
|
||||
# $PchId: nodetypes,v 1.3 2006/03/29 15:43:35 philip Exp $
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -35,8 +31,18 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)options.c 5.2 (Berkeley) 3/13/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/options.c,v 1.21 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "shell.h"
|
||||
#define DEFINE_OPTIONS
|
||||
|
@ -52,25 +58,24 @@ static char sccsid[] = "@(#)options.c 5.2 (Berkeley) 3/13/91";
|
|||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "mystring.h"
|
||||
#include "builtins.h"
|
||||
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||
#include "myhistedit.h"
|
||||
#endif
|
||||
|
||||
char *arg0; /* value of $0 */
|
||||
struct shparam shellparam; /* current positional parameters */
|
||||
char **argptr; /* argument list for builtin commands */
|
||||
char *optarg; /* set by nextopt (like getopt) */
|
||||
char *shoptarg; /* set by nextopt (like getopt) */
|
||||
char *optptr; /* used by nextopt */
|
||||
int editable; /* isatty(0) && isatty(1) */
|
||||
|
||||
char *minusc; /* argument to -c option */
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
STATIC void options(int);
|
||||
STATIC void minus_o(char *, int);
|
||||
STATIC void setoption(int, int);
|
||||
#else
|
||||
STATIC void options();
|
||||
STATIC void setoption();
|
||||
#endif
|
||||
|
||||
STATIC int getopts(char *, char *, char **, char ***, char **);
|
||||
|
||||
|
||||
/*
|
||||
|
@ -78,46 +83,55 @@ STATIC void setoption();
|
|||
*/
|
||||
|
||||
void
|
||||
procargs(argc, argv)
|
||||
char **argv;
|
||||
{
|
||||
char *p;
|
||||
procargs(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
argptr = argv;
|
||||
if (argc > 0)
|
||||
argptr++;
|
||||
for (p = optval ; p < optval + sizeof optval - 1 ; p++)
|
||||
*p = 2;
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
optlist[i].val = 2;
|
||||
privileged = (getuid() != geteuid() || getgid() != getegid());
|
||||
options(1);
|
||||
if (*argptr == NULL && minusc == NULL)
|
||||
sflag = 1;
|
||||
editable = (isatty(0) && isatty(1));
|
||||
if (iflag == 2 && sflag == 1 && editable)
|
||||
if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
|
||||
iflag = 1;
|
||||
if (jflag == 2)
|
||||
jflag = iflag;
|
||||
for (p = optval ; p < optval + sizeof optval - 1 ; p++)
|
||||
if (*p == 2)
|
||||
*p = 0;
|
||||
if (mflag == 2)
|
||||
mflag = iflag;
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
if (optlist[i].val == 2)
|
||||
optlist[i].val = 0;
|
||||
arg0 = argv[0];
|
||||
if (sflag == 0) {
|
||||
arg0 = *argptr++;
|
||||
if (minusc == NULL) {
|
||||
commandname = arg0;
|
||||
setinputfile(commandname, 0);
|
||||
}
|
||||
if (sflag == 0 && minusc == NULL) {
|
||||
commandname = arg0 = *argptr++;
|
||||
setinputfile(commandname, 0);
|
||||
}
|
||||
/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
|
||||
if (argptr && minusc && *argptr)
|
||||
arg0 = *argptr++;
|
||||
|
||||
shellparam.p = argptr;
|
||||
shellparam.reset = 1;
|
||||
/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
|
||||
while (*argptr) {
|
||||
shellparam.nparam++;
|
||||
argptr++;
|
||||
}
|
||||
setinteractive(iflag);
|
||||
setjobctl(jflag);
|
||||
optschanged();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
optschanged(void)
|
||||
{
|
||||
setinteractive(iflag);
|
||||
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||
histedit();
|
||||
#endif
|
||||
setjobctl(mflag);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process shell options. The global variable argptr contains a pointer
|
||||
|
@ -125,8 +139,9 @@ procargs(argc, argv)
|
|||
*/
|
||||
|
||||
STATIC void
|
||||
options(cmdline) {
|
||||
register char *p;
|
||||
options(int cmdline)
|
||||
{
|
||||
char *p;
|
||||
int val;
|
||||
int c;
|
||||
|
||||
|
@ -136,14 +151,14 @@ options(cmdline) {
|
|||
argptr++;
|
||||
if ((c = *p++) == '-') {
|
||||
val = 1;
|
||||
if (p[0] == '\0' || p[0] == '-' && p[1] == '\0') {
|
||||
if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
|
||||
if (!cmdline) {
|
||||
/* "-" means turn off -x and -v */
|
||||
if (p[0] == '\0')
|
||||
xflag = vflag = 0;
|
||||
/* "--" means reset params */
|
||||
else if (*argptr == NULL)
|
||||
setparam(argptr);
|
||||
setparam(argptr);
|
||||
}
|
||||
break; /* "-" or "--" terminates options */
|
||||
}
|
||||
|
@ -166,26 +181,79 @@ options(cmdline) {
|
|||
#ifdef NOHACK
|
||||
break;
|
||||
#endif
|
||||
} else if (c == 'o') {
|
||||
minus_o(*argptr, val);
|
||||
if (*argptr)
|
||||
argptr++;
|
||||
} else {
|
||||
if (c == 'p' && !val && privileged) {
|
||||
(void) setuid(getuid());
|
||||
(void) setgid(getgid());
|
||||
}
|
||||
setoption(c, val);
|
||||
}
|
||||
}
|
||||
if (! cmdline)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void
|
||||
minus_o(char *name, int val)
|
||||
{
|
||||
int doneset, i;
|
||||
|
||||
if (name == NULL) {
|
||||
if (val) {
|
||||
/* "Pretty" output. */
|
||||
out1str("Current option settings\n");
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
out1fmt("%-16s%s\n", optlist[i].name,
|
||||
optlist[i].val ? "on" : "off");
|
||||
} else {
|
||||
/* Output suitable for re-input to shell. */
|
||||
for (doneset = i = 0; i < NOPTS; i++)
|
||||
if (optlist[i].val) {
|
||||
if (!doneset) {
|
||||
out1str("set");
|
||||
doneset = 1;
|
||||
}
|
||||
out1fmt(" -o %s", optlist[i].name);
|
||||
}
|
||||
if (doneset)
|
||||
out1c('\n');
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
if (equal(name, optlist[i].name)) {
|
||||
if (!val && privileged && equal(name, "privileged")) {
|
||||
(void) setuid(getuid());
|
||||
(void) setgid(getgid());
|
||||
}
|
||||
setoption(optlist[i].letter, val);
|
||||
return;
|
||||
}
|
||||
error("Illegal option -o %s", name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
STATIC void
|
||||
setoption(flag, val)
|
||||
char flag;
|
||||
int val;
|
||||
{
|
||||
register char *p;
|
||||
setoption(int flag, int val)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ((p = strchr(optchar, flag)) == NULL)
|
||||
error("Illegal option -%c", flag);
|
||||
optval[p - optchar] = val;
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
if (optlist[i].letter == flag) {
|
||||
optlist[i].val = val;
|
||||
if (val) {
|
||||
/* #%$ hack for ksh semantics */
|
||||
if (flag == 'V')
|
||||
Eflag = 0;
|
||||
else if (flag == 'E')
|
||||
Vflag = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
error("Illegal option -%c", flag);
|
||||
}
|
||||
|
||||
|
||||
|
@ -194,10 +262,12 @@ setoption(flag, val)
|
|||
INCLUDE "options.h"
|
||||
|
||||
SHELLPROC {
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
optlist[i].val = 0;
|
||||
optschanged();
|
||||
|
||||
for (p = optval ; p < optval + sizeof optval ; p++)
|
||||
*p = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -207,9 +277,8 @@ SHELLPROC {
|
|||
*/
|
||||
|
||||
void
|
||||
setparam(argv)
|
||||
char **argv;
|
||||
{
|
||||
setparam(char **argv)
|
||||
{
|
||||
char **newparam;
|
||||
char **ap;
|
||||
int nparam;
|
||||
|
@ -233,9 +302,8 @@ setparam(argv)
|
|||
*/
|
||||
|
||||
void
|
||||
freeparam(param)
|
||||
struct shparam *param;
|
||||
{
|
||||
freeparam(struct shparam *param)
|
||||
{
|
||||
char **ap;
|
||||
|
||||
if (param->malloc) {
|
||||
|
@ -251,7 +319,9 @@ freeparam(param)
|
|||
* The shift builtin command.
|
||||
*/
|
||||
|
||||
shiftcmd(argc, argv) char **argv; {
|
||||
int
|
||||
shiftcmd(int argc, char **argv)
|
||||
{
|
||||
int n;
|
||||
char **ap1, **ap2;
|
||||
|
||||
|
@ -259,7 +329,7 @@ shiftcmd(argc, argv) char **argv; {
|
|||
if (argc > 1)
|
||||
n = number(argv[1]);
|
||||
if (n > shellparam.nparam)
|
||||
n = shellparam.nparam;
|
||||
error("can't shift that many");
|
||||
INTOFF;
|
||||
shellparam.nparam -= n;
|
||||
for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
|
||||
|
@ -279,13 +349,14 @@ shiftcmd(argc, argv) char **argv; {
|
|||
* The set command builtin.
|
||||
*/
|
||||
|
||||
setcmd(argc, argv) char **argv; {
|
||||
int
|
||||
setcmd(int argc, char **argv)
|
||||
{
|
||||
if (argc == 1)
|
||||
return showvarscmd(argc, argv);
|
||||
INTOFF;
|
||||
options(0);
|
||||
setinteractive(iflag);
|
||||
setjobctl(jflag);
|
||||
optschanged();
|
||||
if (*argptr != NULL) {
|
||||
setparam(argptr);
|
||||
}
|
||||
|
@ -294,6 +365,15 @@ setcmd(argc, argv) char **argv; {
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
getoptsreset(const char *value)
|
||||
{
|
||||
if (number(value) == 1) {
|
||||
shellparam.optnext = NULL;
|
||||
shellparam.reset = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The getopts builtin. Shellparam.optnext points to the next argument
|
||||
* to be processed. Shellparam.optptr points to the next character to
|
||||
|
@ -301,63 +381,127 @@ setcmd(argc, argv) char **argv; {
|
|||
* then it's the first time getopts has been called.
|
||||
*/
|
||||
|
||||
getoptscmd(argc, argv) char **argv; {
|
||||
register char *p, *q;
|
||||
char c;
|
||||
int
|
||||
getoptscmd(int argc, char **argv)
|
||||
{
|
||||
char **optbase = NULL;
|
||||
|
||||
if (argc < 3)
|
||||
error("usage: getopts optstring var [arg]");
|
||||
else if (argc == 3)
|
||||
optbase = shellparam.p;
|
||||
else
|
||||
optbase = &argv[3];
|
||||
|
||||
if (shellparam.reset == 1) {
|
||||
shellparam.optnext = optbase;
|
||||
shellparam.optptr = NULL;
|
||||
shellparam.reset = 0;
|
||||
}
|
||||
|
||||
return getopts(argv[1], argv[2], optbase, &shellparam.optnext,
|
||||
&shellparam.optptr);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
getopts(char *optstr, char *optvar, char **optfirst, char ***optnext,
|
||||
char **optptr)
|
||||
{
|
||||
char *p, *q;
|
||||
char c = '?';
|
||||
int done = 0;
|
||||
int ind = 0;
|
||||
int err = 0;
|
||||
char s[10];
|
||||
|
||||
if (argc != 3)
|
||||
error("Usage: getopts optstring var");
|
||||
if (shellparam.optnext == NULL) {
|
||||
shellparam.optnext = shellparam.p;
|
||||
shellparam.optptr = NULL;
|
||||
}
|
||||
if ((p = shellparam.optptr) == NULL || *p == '\0') {
|
||||
p = *shellparam.optnext;
|
||||
if ((p = *optptr) == NULL || *p == '\0') {
|
||||
/* Current word is done, advance */
|
||||
if (*optnext == NULL)
|
||||
return 1;
|
||||
p = **optnext;
|
||||
if (p == NULL || *p != '-' || *++p == '\0') {
|
||||
atend:
|
||||
fmtstr(s, 10, "%d", shellparam.optnext - shellparam.p + 1);
|
||||
setvar("OPTIND", s, 0);
|
||||
shellparam.optnext = NULL;
|
||||
return 1;
|
||||
ind = *optnext - optfirst + 1;
|
||||
*optnext = NULL;
|
||||
p = NULL;
|
||||
done = 1;
|
||||
goto out;
|
||||
}
|
||||
shellparam.optnext++;
|
||||
(*optnext)++;
|
||||
if (p[0] == '-' && p[1] == '\0') /* check for "--" */
|
||||
goto atend;
|
||||
}
|
||||
|
||||
c = *p++;
|
||||
for (q = argv[1] ; *q != c ; ) {
|
||||
for (q = optstr; *q != c; ) {
|
||||
if (*q == '\0') {
|
||||
out1fmt("Illegal option -%c\n", c);
|
||||
if (optstr[0] == ':') {
|
||||
s[0] = c;
|
||||
s[1] = '\0';
|
||||
err |= setvarsafe("OPTARG", s, 0);
|
||||
}
|
||||
else {
|
||||
out1fmt("Illegal option -%c\n", c);
|
||||
(void) unsetvar("OPTARG");
|
||||
}
|
||||
c = '?';
|
||||
goto out;
|
||||
goto bad;
|
||||
}
|
||||
if (*++q == ':')
|
||||
q++;
|
||||
}
|
||||
|
||||
if (*++q == ':') {
|
||||
if (*p == '\0') {
|
||||
if ((p = *shellparam.optnext) == NULL) {
|
||||
out1fmt("No arg for -%c option\n", c);
|
||||
c = '?';
|
||||
goto out;
|
||||
if (*p == '\0' && (p = **optnext) == NULL) {
|
||||
if (optstr[0] == ':') {
|
||||
s[0] = c;
|
||||
s[1] = '\0';
|
||||
err |= setvarsafe("OPTARG", s, 0);
|
||||
c = ':';
|
||||
}
|
||||
shellparam.optnext++;
|
||||
else {
|
||||
out1fmt("No arg for -%c option\n", c);
|
||||
(void) unsetvar("OPTARG");
|
||||
c = '?';
|
||||
}
|
||||
goto bad;
|
||||
}
|
||||
setvar("OPTARG", p, 0);
|
||||
p = "";
|
||||
|
||||
if (p == **optnext)
|
||||
(*optnext)++;
|
||||
setvarsafe("OPTARG", p, 0);
|
||||
p = NULL;
|
||||
}
|
||||
else
|
||||
setvarsafe("OPTARG", "", 0);
|
||||
ind = *optnext - optfirst + 1;
|
||||
goto out;
|
||||
|
||||
bad:
|
||||
ind = 1;
|
||||
*optnext = NULL;
|
||||
p = NULL;
|
||||
out:
|
||||
shellparam.optptr = p;
|
||||
*optptr = p;
|
||||
fmtstr(s, sizeof(s), "%d", ind);
|
||||
err |= setvarsafe("OPTIND", s, VNOFUNC);
|
||||
s[0] = c;
|
||||
s[1] = '\0';
|
||||
setvar(argv[2], s, 0);
|
||||
fmtstr(s, 10, "%d", shellparam.optnext - shellparam.p + 1);
|
||||
setvar("OPTIND", s, 0);
|
||||
return 0;
|
||||
err |= setvarsafe(optvar, s, 0);
|
||||
if (err) {
|
||||
*optnext = NULL;
|
||||
*optptr = NULL;
|
||||
flushall();
|
||||
exraise(EXERROR);
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX - should get rid of. have all builtins use getopt(3). the
|
||||
* library getopt must have the BSD extension static variable "optreset"
|
||||
* otherwise it can't be used within the shell safely.
|
||||
*
|
||||
* Standard option processing (a la getopt) for builtin routines. The
|
||||
* only argument that is passed to nextopt is the option string; the
|
||||
* other arguments are unnecessary. It return the character, or '\0' on
|
||||
|
@ -365,10 +509,9 @@ out:
|
|||
*/
|
||||
|
||||
int
|
||||
nextopt(optstring)
|
||||
char *optstring;
|
||||
{
|
||||
register char *p, *q;
|
||||
nextopt(char *optstring)
|
||||
{
|
||||
char *p, *q;
|
||||
char c;
|
||||
|
||||
if ((p = optptr) == NULL || *p == '\0') {
|
||||
|
@ -389,9 +532,13 @@ nextopt(optstring)
|
|||
if (*++q == ':') {
|
||||
if (*p == '\0' && (p = *argptr++) == NULL)
|
||||
error("No arg for -%c option", c);
|
||||
optarg = p;
|
||||
shoptarg = p;
|
||||
p = NULL;
|
||||
}
|
||||
optptr = p;
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: options.c,v 1.5 2006/05/22 12:23:10 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -33,38 +29,71 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)options.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)options.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/options.h,v 1.13 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
struct shparam {
|
||||
int nparam; /* number of positional parameters (without $0) */
|
||||
char malloc; /* true if parameter list dynamicly allocated */
|
||||
int nparam; /* # of positional parameters (without $0) */
|
||||
unsigned char malloc; /* if parameter list dynamically allocated */
|
||||
unsigned char reset; /* if getopts has been reset */
|
||||
char **p; /* parameter list */
|
||||
char **optnext; /* next parameter to be processed by getopts */
|
||||
char *optptr; /* used by getopts */
|
||||
char **optnext; /* next parameter to be processed by getopts */
|
||||
char *optptr; /* used by getopts */
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define eflag optval[0]
|
||||
#define fflag optval[1]
|
||||
#define Iflag optval[2]
|
||||
#define iflag optval[3]
|
||||
#define jflag optval[4]
|
||||
#define nflag optval[5]
|
||||
#define sflag optval[6]
|
||||
#define xflag optval[7]
|
||||
#define zflag optval[8]
|
||||
#define vflag optval[9]
|
||||
#define eflag optlist[0].val
|
||||
#define fflag optlist[1].val
|
||||
#define Iflag optlist[2].val
|
||||
#define iflag optlist[3].val
|
||||
#define mflag optlist[4].val
|
||||
#define nflag optlist[5].val
|
||||
#define sflag optlist[6].val
|
||||
#define xflag optlist[7].val
|
||||
#define vflag optlist[8].val
|
||||
#define Vflag optlist[9].val
|
||||
#define Eflag optlist[10].val
|
||||
#define Cflag optlist[11].val
|
||||
#define aflag optlist[12].val
|
||||
#define bflag optlist[13].val
|
||||
#define uflag optlist[14].val
|
||||
#define privileged optlist[15].val
|
||||
#define Tflag optlist[16].val
|
||||
#define Pflag optlist[17].val
|
||||
|
||||
#define NOPTS 10
|
||||
#define NOPTS 18
|
||||
|
||||
struct optent {
|
||||
const char *name;
|
||||
const char letter;
|
||||
char val;
|
||||
};
|
||||
|
||||
#ifdef DEFINE_OPTIONS
|
||||
const char optchar[NOPTS+1] = "efIijnsxzv"; /* shell flags */
|
||||
char optval[NOPTS+1]; /* values of option flags */
|
||||
struct optent optlist[NOPTS] = {
|
||||
{ "errexit", 'e', 0 },
|
||||
{ "noglob", 'f', 0 },
|
||||
{ "ignoreeof", 'I', 0 },
|
||||
{ "interactive",'i', 0 },
|
||||
{ "monitor", 'm', 0 },
|
||||
{ "noexec", 'n', 0 },
|
||||
{ "stdin", 's', 0 },
|
||||
{ "xtrace", 'x', 0 },
|
||||
{ "verbose", 'v', 0 },
|
||||
{ "vi", 'V', 0 },
|
||||
{ "emacs", 'E', 0 },
|
||||
{ "noclobber", 'C', 0 },
|
||||
{ "allexport", 'a', 0 },
|
||||
{ "notify", 'b', 0 },
|
||||
{ "nounset", 'u', 0 },
|
||||
{ "privileged", 'p', 0 },
|
||||
{ "trapsasync", 'T', 0 },
|
||||
{ "physical", 'P', 0 },
|
||||
};
|
||||
#else
|
||||
extern const char optchar[NOPTS+1];
|
||||
extern char optval[NOPTS+1];
|
||||
extern struct optent optlist[NOPTS];
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -72,19 +101,19 @@ extern char *minusc; /* argument to -c option */
|
|||
extern char *arg0; /* $0 */
|
||||
extern struct shparam shellparam; /* $@ */
|
||||
extern char **argptr; /* argument list for builtin commands */
|
||||
extern char *optarg; /* set by nextopt */
|
||||
extern char *shoptarg; /* set by nextopt */
|
||||
extern char *optptr; /* used by nextopt */
|
||||
extern int editable; /* isatty(0) && isatty(1) */
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
void procargs(int, char **);
|
||||
void optschanged(void);
|
||||
void setparam(char **);
|
||||
void freeparam(struct shparam *);
|
||||
int shiftcmd(int, char **);
|
||||
int setcmd(int, char **);
|
||||
int getoptscmd(int, char **);
|
||||
int nextopt(char *);
|
||||
#else
|
||||
void procargs();
|
||||
void setparam();
|
||||
void freeparam();
|
||||
int nextopt();
|
||||
#endif
|
||||
void getoptsreset(const char *);
|
||||
|
||||
/*
|
||||
* $PchId: options.h,v 1.4 2006/03/29 15:37:43 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -35,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)output.c 5.1 (Berkeley) 3/7/91";
|
||||
static char sccsid[] = "@(#)output.c 8.1 (Berkeley) 5/31/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
|
@ -55,12 +51,16 @@ static char sccsid[] = "@(#)output.c 5.1 (Berkeley) 3/7/91";
|
|||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "var.h"
|
||||
#ifdef __STDC__
|
||||
#include "stdarg.h"
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#define OUTBUFSIZ BUFSIZ
|
||||
|
@ -115,27 +115,63 @@ open_mem(block, length, file)
|
|||
|
||||
void
|
||||
out1str(p)
|
||||
char *p;
|
||||
const char *p;
|
||||
{
|
||||
outstr(p, out1);
|
||||
}
|
||||
|
||||
void
|
||||
out1qstr(const char *p)
|
||||
{
|
||||
outqstr(p, out1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
out2str(p)
|
||||
char *p;
|
||||
{
|
||||
out2str(const char *p)
|
||||
{
|
||||
outstr(p, out2);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
outstr(p, file)
|
||||
register char *p;
|
||||
register const char *p;
|
||||
register struct output *file;
|
||||
{
|
||||
while (*p)
|
||||
outc(*p++, file);
|
||||
if (file == out2)
|
||||
flushout(file);
|
||||
}
|
||||
|
||||
/* Like outstr(), but quote for re-input into the shell. */
|
||||
void
|
||||
outqstr(const char *p, struct output *file)
|
||||
{
|
||||
char ch;
|
||||
|
||||
if (p[strcspn(p, "|&;<>()$`\\\"'")] == '\0' && (!ifsset() ||
|
||||
p[strcspn(p, ifsval())] == '\0')) {
|
||||
outstr(p, file);
|
||||
return;
|
||||
}
|
||||
|
||||
out1c('\'');
|
||||
while ((ch = *p++) != '\0') {
|
||||
switch (ch) {
|
||||
case '\'':
|
||||
/*
|
||||
* Can't quote single quotes inside single quotes;
|
||||
* close them, write escaped single quote, open again.
|
||||
*/
|
||||
outstr("'\\''", file);
|
||||
break;
|
||||
default:
|
||||
outc(ch, file);
|
||||
}
|
||||
}
|
||||
out1c('\'');
|
||||
}
|
||||
|
||||
|
||||
|
@ -208,7 +244,8 @@ freestdout() {
|
|||
|
||||
#ifdef __STDC__
|
||||
void
|
||||
outfmt(struct output *file, char *fmt, ...) {
|
||||
outfmt(struct output *file, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
@ -218,7 +255,8 @@ outfmt(struct output *file, char *fmt, ...) {
|
|||
|
||||
|
||||
void
|
||||
out1fmt(char *fmt, ...) {
|
||||
out1fmt(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
@ -226,9 +264,20 @@ out1fmt(char *fmt, ...) {
|
|||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
dprintf(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
doformat(out2, fmt, ap);
|
||||
va_end(ap);
|
||||
flushout(out2);
|
||||
}
|
||||
|
||||
void
|
||||
fmtstr(char *outbuf, int length, char *fmt, ...) {
|
||||
fmtstr(char *outbuf, int length, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
struct output strout;
|
||||
|
||||
|
@ -275,6 +324,19 @@ out1fmt(va_alist)
|
|||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
dprintf(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
va_list ap;
|
||||
char *fmt;
|
||||
|
||||
va_start(ap);
|
||||
fmt = va_arg(ap, char *);
|
||||
doformat(out2, fmt, ap);
|
||||
va_end(ap);
|
||||
flushout(out2);
|
||||
}
|
||||
|
||||
void
|
||||
fmtstr(va_alist)
|
||||
|
@ -325,11 +387,8 @@ static const char digit[17] = "0123456789ABCDEF";
|
|||
|
||||
|
||||
void
|
||||
doformat(dest, f, ap)
|
||||
register struct output *dest;
|
||||
register char *f; /* format string */
|
||||
va_list ap;
|
||||
{
|
||||
doformat(struct output *dest, const char *f, va_list ap)
|
||||
{
|
||||
register char c;
|
||||
char temp[TEMPSIZE];
|
||||
int flushleft;
|
||||
|
@ -517,15 +576,6 @@ xwrite(fd, buf, nbytes)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Version of ioctl that retries after a signal is caught.
|
||||
* $PchId: output.c,v 1.6 2006/05/22 12:46:03 philip Exp $
|
||||
*/
|
||||
|
||||
int
|
||||
xioctl(fd, request, arg) {
|
||||
int i;
|
||||
|
||||
while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
|
||||
return i;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -33,11 +29,14 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)output.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)output.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/output.h,v 1.13 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
#ifndef OUTPUT_INCL
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
struct output {
|
||||
char *nextc;
|
||||
int nleft;
|
||||
|
@ -53,38 +52,27 @@ extern struct output memout;
|
|||
extern struct output *out1;
|
||||
extern struct output *out2;
|
||||
|
||||
#ifndef __printflike
|
||||
#define __printflike(a,b)
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
void outstr(char *, struct output *);
|
||||
void out1str(char *);
|
||||
void out2str(char *);
|
||||
void outfmt(struct output *, char *, ...);
|
||||
void out1fmt(char *, ...);
|
||||
void fmtstr(char *, int, char *, ...);
|
||||
/* void doformat(struct output *, char *, va_list); */
|
||||
void doformat();
|
||||
void open_mem(char *, int, struct output *);
|
||||
void out1str(const char *);
|
||||
void out1qstr(const char *);
|
||||
void out2str(const char *);
|
||||
void out2qstr(const char *);
|
||||
void outstr(const char *, struct output *);
|
||||
void outqstr(const char *, struct output *);
|
||||
void emptyoutbuf(struct output *);
|
||||
void flushall(void);
|
||||
void flushout(struct output *);
|
||||
void freestdout(void);
|
||||
void outfmt(struct output *, const char *, ...) __printflike(2, 3);
|
||||
void out1fmt(const char *, ...) __printflike(1, 2);
|
||||
void dprintf(const char *, ...) __printflike(1, 2);
|
||||
void fmtstr(char *, int, const char *, ...) __printflike(3, 4);
|
||||
void doformat(struct output *, const char *, va_list) __printflike(2, 0);
|
||||
int xwrite(int, char *, int);
|
||||
int xioctl(int, int, int);
|
||||
#else
|
||||
void outstr();
|
||||
void out1str();
|
||||
void out2str();
|
||||
void outfmt();
|
||||
void out1fmt();
|
||||
void fmtstr();
|
||||
/* void doformat(); */
|
||||
void doformat();
|
||||
void emptyoutbuf();
|
||||
void flushall();
|
||||
void flushout();
|
||||
void freestdout();
|
||||
int xwrite();
|
||||
int xioctl();
|
||||
#endif
|
||||
|
||||
#define outc(c, file) (--(file)->nleft < 0? (emptyoutbuf(file), *(file)->nextc++ = (c)) : (*(file)->nextc++ = (c)))
|
||||
#define out1c(c) outc(c, out1);
|
||||
|
@ -92,3 +80,7 @@ int xioctl();
|
|||
|
||||
#define OUTPUT_INCL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $PchId: output.h,v 1.5 2006/05/23 12:04:54 philip Exp $
|
||||
*/
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -33,7 +29,8 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)parser.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)parser.h 8.3 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/parser.h,v 1.10 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
/* control characters in argument strings */
|
||||
|
@ -42,18 +39,27 @@
|
|||
#define CTLENDVAR '\203'
|
||||
#define CTLBACKQ '\204'
|
||||
#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
|
||||
/* CTLBACKQ | CTLQUOTE == '\205' */
|
||||
#define CTLARI '\206'
|
||||
#define CTLENDARI '\207'
|
||||
#define CTLQUOTEMARK '\210'
|
||||
|
||||
/* variable substitution byte (follows CTLVAR) */
|
||||
#define VSTYPE 07 /* type of variable substitution */
|
||||
#define VSNUL 040 /* colon--treat the empty string as unset */
|
||||
#define VSQUOTE 0100 /* inside double quotes--suppress splitting */
|
||||
#define VSTYPE 0x0f /* type of variable substitution */
|
||||
#define VSNUL 0x10 /* colon--treat the empty string as unset */
|
||||
#define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
|
||||
|
||||
/* values of VSTYPE field */
|
||||
#define VSNORMAL 1 /* normal variable: $var or ${var} */
|
||||
#define VSMINUS 2 /* ${var-text} */
|
||||
#define VSPLUS 3 /* ${var+text} */
|
||||
#define VSQUESTION 4 /* ${var?message} */
|
||||
#define VSASSIGN 5 /* ${var=text} */
|
||||
#define VSNORMAL 0x1 /* normal variable: $var or ${var} */
|
||||
#define VSMINUS 0x2 /* ${var-text} */
|
||||
#define VSPLUS 0x3 /* ${var+text} */
|
||||
#define VSQUESTION 0x4 /* ${var?message} */
|
||||
#define VSASSIGN 0x5 /* ${var=text} */
|
||||
#define VSTRIMLEFT 0x6 /* ${var#pattern} */
|
||||
#define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */
|
||||
#define VSTRIMRIGHT 0x8 /* ${var%pattern} */
|
||||
#define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */
|
||||
#define VSLENGTH 0xa /* ${#var} */
|
||||
|
||||
|
||||
/*
|
||||
|
@ -63,12 +69,14 @@
|
|||
*/
|
||||
extern int tokpushback;
|
||||
#define NEOF ((union node *)&tokpushback)
|
||||
extern int whichprompt; /* 1 == PS1, 2 == PS2 */
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
union node *parsecmd(int);
|
||||
void fixredir(union node *, const char *, int);
|
||||
int goodname(char *);
|
||||
#else
|
||||
union node *parsecmd();
|
||||
int goodname();
|
||||
#endif
|
||||
char *getprompt(void *);
|
||||
|
||||
/*
|
||||
* $PchId: parser.h,v 1.3 2006/03/29 14:33:35 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -35,8 +31,23 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)redir.c 5.1 (Berkeley) 3/7/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/redir.c,v 1.26 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* Code for dealing with input/output redirection.
|
||||
|
@ -47,15 +58,10 @@ static char sccsid[] = "@(#)redir.c 5.1 (Berkeley) 3/7/91";
|
|||
#include "jobs.h"
|
||||
#include "expand.h"
|
||||
#include "redir.h"
|
||||
#include "eval.h"
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include "options.h"
|
||||
|
||||
|
||||
#define EMPTY -2 /* marks an unused slot in redirtab */
|
||||
|
@ -65,25 +71,21 @@ static char sccsid[] = "@(#)redir.c 5.1 (Berkeley) 3/7/91";
|
|||
MKINIT
|
||||
struct redirtab {
|
||||
struct redirtab *next;
|
||||
short renamed[10];
|
||||
int renamed[10];
|
||||
};
|
||||
|
||||
|
||||
MKINIT struct redirtab *redirlist;
|
||||
|
||||
/* We keep track of whether or not fd0 has been redirected. This is for
|
||||
background commands, where we want to redirect fd0 to /dev/null only
|
||||
if it hasn't already been redirected. */
|
||||
int fd0_redirected = 0;
|
||||
/*
|
||||
* We keep track of whether or not fd0 has been redirected. This is for
|
||||
* background commands, where we want to redirect fd0 to /dev/null only
|
||||
* if it hasn't already been redirected.
|
||||
*/
|
||||
STATIC int fd0_redirected = 0;
|
||||
|
||||
#ifdef __STDC__
|
||||
STATIC void openredirect(union node *, char *);
|
||||
STATIC void openredirect(union node *, char[10 ]);
|
||||
STATIC int openhere(union node *);
|
||||
#else
|
||||
STATIC void openredirect();
|
||||
STATIC int openhere();
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
@ -95,15 +97,14 @@ STATIC int openhere();
|
|||
*/
|
||||
|
||||
void
|
||||
redirect(redir, flags)
|
||||
union node *redir;
|
||||
int flags;
|
||||
{
|
||||
redirect(union node *redir, int flags)
|
||||
{
|
||||
union node *n;
|
||||
struct redirtab *sv;
|
||||
struct redirtab *sv = NULL;
|
||||
int i;
|
||||
int fd;
|
||||
char memory[10]; /* file descriptors to write to memory */
|
||||
int try;
|
||||
char memory[10]; /* file descriptors to write to memory */
|
||||
|
||||
for (i = 10 ; --i >= 0 ; )
|
||||
memory[i] = 0;
|
||||
|
@ -117,21 +118,38 @@ redirect(redir, flags)
|
|||
}
|
||||
for (n = redir ; n ; n = n->nfile.next) {
|
||||
fd = n->nfile.fd;
|
||||
try = 0;
|
||||
if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
|
||||
n->ndup.dupfd == fd)
|
||||
continue; /* redirect from/to same file descriptor */
|
||||
|
||||
if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
|
||||
INTOFF;
|
||||
if ((i = copyfd(fd, 10)) != EMPTY) {
|
||||
again:
|
||||
if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
|
||||
switch (errno) {
|
||||
case EBADF:
|
||||
if (!try) {
|
||||
openredirect(n, memory);
|
||||
try++;
|
||||
goto again;
|
||||
}
|
||||
/* FALLTHROUGH*/
|
||||
default:
|
||||
INTON;
|
||||
error("%d: %s", fd, strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!try) {
|
||||
sv->renamed[fd] = i;
|
||||
close(fd);
|
||||
}
|
||||
INTON;
|
||||
if (i == EMPTY)
|
||||
error("Out of file descriptors");
|
||||
} else {
|
||||
close(fd);
|
||||
}
|
||||
if (fd == 0)
|
||||
fd0_redirected++;
|
||||
openredirect(n, memory);
|
||||
if (!try)
|
||||
openredirect(n, memory);
|
||||
}
|
||||
if (memory[1])
|
||||
out1 = &memout;
|
||||
|
@ -141,16 +159,15 @@ redirect(redir, flags)
|
|||
|
||||
|
||||
STATIC void
|
||||
openredirect(redir, memory)
|
||||
union node *redir;
|
||||
char memory[10];
|
||||
{
|
||||
openredirect(union node *redir, char memory[10])
|
||||
{
|
||||
struct stat sb;
|
||||
int fd = redir->nfile.fd;
|
||||
char *fname;
|
||||
int f;
|
||||
|
||||
/* Assume redirection succeeds. */
|
||||
exitstatus = 0;
|
||||
{ extern int exitstatus; exitstatus = 0; }
|
||||
|
||||
/*
|
||||
* We suppress interrupts so that we won't leave open file
|
||||
|
@ -163,34 +180,35 @@ openredirect(redir, memory)
|
|||
case NFROM:
|
||||
fname = redir->nfile.expfname;
|
||||
if ((f = open(fname, O_RDONLY)) < 0)
|
||||
error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
|
||||
error("cannot open %s: %s", fname, strerror(errno));
|
||||
movefd:
|
||||
if (f != fd) {
|
||||
copyfd(f, fd);
|
||||
dup2(f, fd);
|
||||
close(f);
|
||||
}
|
||||
break;
|
||||
case NFROMTO:
|
||||
fname = redir->nfile.expfname;
|
||||
if ((f = open(fname, O_RDWR|O_CREAT, 0666)) < 0)
|
||||
error("cannot create %s: %s", fname, strerror(errno));
|
||||
goto movefd;
|
||||
case NTO:
|
||||
fname = redir->nfile.expfname;
|
||||
#ifdef O_CREAT
|
||||
if (Cflag && stat(fname, &sb) != -1 && S_ISREG(sb.st_mode))
|
||||
error("cannot create %s: %s", fname,
|
||||
strerror(EEXIST));
|
||||
if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
|
||||
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
|
||||
#else
|
||||
if ((f = creat(fname, 0666)) < 0)
|
||||
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
|
||||
#endif
|
||||
error("cannot create %s: %s", fname, strerror(errno));
|
||||
goto movefd;
|
||||
case NCLOBBER:
|
||||
fname = redir->nfile.expfname;
|
||||
if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
|
||||
error("cannot create %s: %s", fname, strerror(errno));
|
||||
goto movefd;
|
||||
case NAPPEND:
|
||||
fname = redir->nfile.expfname;
|
||||
#ifdef O_APPEND
|
||||
if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
|
||||
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
|
||||
#else
|
||||
if ((f = open(fname, O_WRONLY)) < 0
|
||||
&& (f = creat(fname, 0666)) < 0)
|
||||
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
|
||||
lseek(f, 0L, 2);
|
||||
#endif
|
||||
error("cannot create %s: %s", fname, strerror(errno));
|
||||
goto movefd;
|
||||
case NTOFD:
|
||||
case NFROMFD:
|
||||
|
@ -198,7 +216,9 @@ movefd:
|
|||
if (memory[redir->ndup.dupfd])
|
||||
memory[fd] = 1;
|
||||
else
|
||||
copyfd(redir->ndup.dupfd, fd);
|
||||
dup2(redir->ndup.dupfd, fd);
|
||||
} else {
|
||||
close(fd);
|
||||
}
|
||||
break;
|
||||
case NHERE:
|
||||
|
@ -219,14 +239,13 @@ movefd:
|
|||
*/
|
||||
|
||||
STATIC int
|
||||
openhere(redir)
|
||||
union node *redir;
|
||||
{
|
||||
openhere(union node *redir)
|
||||
{
|
||||
int pip[2];
|
||||
int len;
|
||||
int len = 0;
|
||||
|
||||
if (pipe(pip) < 0)
|
||||
error("Pipe call failed");
|
||||
error("Pipe call failed: %s", strerror(errno));
|
||||
if (redir->type == NHERE) {
|
||||
len = strlen(redir->nhere.doc->narg.text);
|
||||
if (len <= PIPESIZE) {
|
||||
|
@ -239,9 +258,7 @@ openhere(redir)
|
|||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGQUIT, SIG_IGN);
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
#ifdef SIGTSTP
|
||||
signal(SIGTSTP, SIG_IGN);
|
||||
#endif
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
if (redir->type == NHERE)
|
||||
xwrite(pip[1], redir->nhere.doc->narg.text, len);
|
||||
|
@ -261,18 +278,20 @@ out:
|
|||
*/
|
||||
|
||||
void
|
||||
popredir() {
|
||||
register struct redirtab *rp = redirlist;
|
||||
popredir(void)
|
||||
{
|
||||
struct redirtab *rp = redirlist;
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < 10 ; i++) {
|
||||
if (rp->renamed[i] != EMPTY) {
|
||||
if (i == 0)
|
||||
fd0_redirected--;
|
||||
close(i);
|
||||
if (i == 0)
|
||||
fd0_redirected--;
|
||||
if (rp->renamed[i] >= 0) {
|
||||
copyfd(rp->renamed[i], i);
|
||||
dup2(rp->renamed[i], i);
|
||||
close(rp->renamed[i]);
|
||||
} else {
|
||||
close(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -282,8 +301,6 @@ popredir() {
|
|||
INTON;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Undo all redirections. Called on error or interrupt.
|
||||
*/
|
||||
|
@ -303,14 +320,21 @@ SHELLPROC {
|
|||
|
||||
#endif
|
||||
|
||||
/* Return true if fd 0 has already been redirected at least once. */
|
||||
int
|
||||
fd0_redirected_p(void)
|
||||
{
|
||||
return fd0_redirected != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Discard all saved file descriptors.
|
||||
*/
|
||||
|
||||
void
|
||||
clearredir() {
|
||||
register struct redirtab *rp;
|
||||
clearredir(void)
|
||||
{
|
||||
struct redirtab *rp;
|
||||
int i;
|
||||
|
||||
for (rp = redirlist ; rp ; rp = rp->next) {
|
||||
|
@ -323,48 +347,6 @@ clearredir() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Copy a file descriptor, like the F_DUPFD option of fcntl. Returns -1
|
||||
* if the source file descriptor is closed, EMPTY if there are no unused
|
||||
* file descriptors left.
|
||||
* $PchId: redir.c,v 1.5 2006/05/22 12:27:37 philip Exp $
|
||||
*/
|
||||
|
||||
int
|
||||
copyfd(from, to) {
|
||||
#ifdef F_DUPFD
|
||||
int newfd;
|
||||
|
||||
newfd = fcntl(from, F_DUPFD, to);
|
||||
if (newfd < 0 && errno == EMFILE)
|
||||
return EMPTY;
|
||||
return newfd;
|
||||
#else
|
||||
char toclose[32];
|
||||
int i;
|
||||
int newfd;
|
||||
int e;
|
||||
|
||||
for (i = 0 ; i < to ; i++)
|
||||
toclose[i] = 0;
|
||||
INTOFF;
|
||||
while ((newfd = dup(from)) >= 0 && newfd < to)
|
||||
toclose[newfd] = 1;
|
||||
e = errno;
|
||||
for (i = 0 ; i < to ; i++) {
|
||||
if (toclose[i])
|
||||
close(i);
|
||||
}
|
||||
INTON;
|
||||
if (newfd < 0 && e == EMFILE)
|
||||
return EMPTY;
|
||||
return newfd;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return true if fd 0 has already been redirected at least once. */
|
||||
int
|
||||
fd0_redirected_p () {
|
||||
return fd0_redirected != 0;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -33,24 +29,21 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)redir.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)redir.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/redir.h,v 1.10 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
/* flags passed to redirect */
|
||||
#define REDIR_PUSH 01 /* save previous values of file descriptors */
|
||||
#define REDIR_BACKQ 02 /* save the command output in memory */
|
||||
|
||||
#ifdef __STDC__
|
||||
union node;
|
||||
void redirect(union node *, int);
|
||||
void popredir(void);
|
||||
void clearredir(void);
|
||||
int copyfd(int, int);
|
||||
int fd0_redirected_p(void);
|
||||
#else
|
||||
void redirect();
|
||||
void popredir();
|
||||
void clearredir();
|
||||
int copyfd();
|
||||
int fd0_redirected_p();
|
||||
#endif
|
||||
void clearredir(void);
|
||||
|
||||
|
||||
/*
|
||||
* $PchId: redir.h,v 1.3 2006/03/29 14:13:34 philip Exp $
|
||||
*/
|
||||
|
|
463
commands/ash/setmode.c
Normal file
463
commands/ash/setmode.c
Normal file
|
@ -0,0 +1,463 @@
|
|||
/*
|
||||
* Copyright (c) 1989, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Dave Borman at Cray Research, Inc.
|
||||
*
|
||||
* 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(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)setmode.c 8.2 (Berkeley) 3/25/94";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef SETMODE_DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "shell.h"
|
||||
|
||||
#ifndef S_ISTXT
|
||||
#define S_ISTXT S_ISVTX
|
||||
#endif
|
||||
|
||||
#define SET_LEN 6 /* initial # of bitcmd struct to malloc */
|
||||
#define SET_LEN_INCR 4 /* # of bitcmd structs to add as needed */
|
||||
|
||||
typedef struct bitcmd {
|
||||
char cmd;
|
||||
char cmd2;
|
||||
mode_t bits;
|
||||
} BITCMD;
|
||||
|
||||
#define CMD2_CLR 0x01
|
||||
#define CMD2_SET 0x02
|
||||
#define CMD2_GBITS 0x04
|
||||
#define CMD2_OBITS 0x08
|
||||
#define CMD2_UBITS 0x10
|
||||
|
||||
static BITCMD *addcmd (BITCMD *, int, int, int, unsigned int);
|
||||
static int compress_mode (BITCMD *);
|
||||
#ifdef SETMODE_DEBUG
|
||||
static void dumpmode __P((BITCMD *));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Given the old mode and an array of bitcmd structures, apply the operations
|
||||
* described in the bitcmd structures to the old mode, and return the new mode.
|
||||
* Note that there is no '=' command; a strict assignment is just a '-' (clear
|
||||
* bits) followed by a '+' (set bits).
|
||||
*/
|
||||
mode_t
|
||||
getmode(bbox, omode)
|
||||
void *bbox;
|
||||
mode_t omode;
|
||||
{
|
||||
register BITCMD *set;
|
||||
register mode_t clrval, newmode, value;
|
||||
|
||||
set = (BITCMD *)bbox;
|
||||
newmode = omode;
|
||||
for (value = 0;; set++)
|
||||
switch(set->cmd) {
|
||||
/*
|
||||
* When copying the user, group or other bits around, we "know"
|
||||
* where the bits are in the mode so that we can do shifts to
|
||||
* copy them around. If we don't use shifts, it gets real
|
||||
* grundgy with lots of single bit checks and bit sets.
|
||||
*/
|
||||
case 'u':
|
||||
value = (newmode & S_IRWXU) >> 6;
|
||||
goto common;
|
||||
|
||||
case 'g':
|
||||
value = (newmode & S_IRWXG) >> 3;
|
||||
goto common;
|
||||
|
||||
case 'o':
|
||||
value = newmode & S_IRWXO;
|
||||
common: if (set->cmd2 & CMD2_CLR) {
|
||||
clrval =
|
||||
(set->cmd2 & CMD2_SET) ? S_IRWXO : value;
|
||||
if (set->cmd2 & CMD2_UBITS)
|
||||
newmode &= ~((clrval<<6) & set->bits);
|
||||
if (set->cmd2 & CMD2_GBITS)
|
||||
newmode &= ~((clrval<<3) & set->bits);
|
||||
if (set->cmd2 & CMD2_OBITS)
|
||||
newmode &= ~(clrval & set->bits);
|
||||
}
|
||||
if (set->cmd2 & CMD2_SET) {
|
||||
if (set->cmd2 & CMD2_UBITS)
|
||||
newmode |= (value<<6) & set->bits;
|
||||
if (set->cmd2 & CMD2_GBITS)
|
||||
newmode |= (value<<3) & set->bits;
|
||||
if (set->cmd2 & CMD2_OBITS)
|
||||
newmode |= value & set->bits;
|
||||
}
|
||||
break;
|
||||
|
||||
case '+':
|
||||
newmode |= set->bits;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
newmode &= ~set->bits;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
|
||||
newmode |= set->bits;
|
||||
break;
|
||||
|
||||
case '\0':
|
||||
default:
|
||||
#ifdef SETMODE_DEBUG
|
||||
(void)printf("getmode:%04o -> %04o\n", omode, newmode);
|
||||
#endif
|
||||
return (newmode);
|
||||
}
|
||||
}
|
||||
|
||||
#define ADDCMD(a, b, c, d) \
|
||||
if (set >= endset) { \
|
||||
register BITCMD *newset; \
|
||||
setlen += SET_LEN_INCR; \
|
||||
newset = realloc(saveset, sizeof(BITCMD) * setlen); \
|
||||
if (!saveset) \
|
||||
return (NULL); \
|
||||
set = newset + (set - saveset); \
|
||||
saveset = newset; \
|
||||
endset = newset + (setlen - 2); \
|
||||
} \
|
||||
set = addcmd(set, (a), (b), (c), (d))
|
||||
|
||||
#define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
|
||||
|
||||
void *
|
||||
setmode(p)
|
||||
register char *p;
|
||||
{
|
||||
register int perm, who;
|
||||
register char op;
|
||||
BITCMD *set, *saveset, *endset;
|
||||
sigset_t sigset, sigoset;
|
||||
mode_t mask;
|
||||
int equalopdone, permXbits, setlen;
|
||||
|
||||
if (!*p)
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* Get a copy of the mask for the permissions that are mask relative.
|
||||
* Flip the bits, we want what's not set. Since it's possible that
|
||||
* the caller is opening files inside a signal handler, protect them
|
||||
* as best we can.
|
||||
*/
|
||||
sigfillset(&sigset);
|
||||
(void)sigprocmask(SIG_BLOCK, &sigset, &sigoset);
|
||||
(void)umask(mask = umask(0));
|
||||
mask = ~mask;
|
||||
(void)sigprocmask(SIG_SETMASK, &sigoset, NULL);
|
||||
|
||||
setlen = SET_LEN + 2;
|
||||
|
||||
if ((set = malloc((unsigned int)(sizeof(BITCMD) * setlen))) == NULL)
|
||||
return (NULL);
|
||||
saveset = set;
|
||||
endset = set + (setlen - 2);
|
||||
|
||||
/*
|
||||
* If an absolute number, get it and return; disallow non-octal digits
|
||||
* or illegal bits.
|
||||
*/
|
||||
if (isdigit(*p)) {
|
||||
perm = (mode_t)strtol(p, NULL, 8);
|
||||
if (perm & ~(STANDARD_BITS|S_ISTXT)) {
|
||||
free(saveset);
|
||||
return (NULL);
|
||||
}
|
||||
while (*++p)
|
||||
if (*p < '0' || *p > '7') {
|
||||
free(saveset);
|
||||
return (NULL);
|
||||
}
|
||||
ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
|
||||
return (saveset);
|
||||
}
|
||||
|
||||
/*
|
||||
* Build list of structures to set/clear/copy bits as described by
|
||||
* each clause of the symbolic mode.
|
||||
*/
|
||||
for (;;) {
|
||||
/* First, find out which bits might be modified. */
|
||||
for (who = 0;; ++p) {
|
||||
switch (*p) {
|
||||
case 'a':
|
||||
who |= STANDARD_BITS;
|
||||
break;
|
||||
case 'u':
|
||||
who |= S_ISUID|S_IRWXU;
|
||||
break;
|
||||
case 'g':
|
||||
who |= S_ISGID|S_IRWXG;
|
||||
break;
|
||||
case 'o':
|
||||
who |= S_IRWXO;
|
||||
break;
|
||||
default:
|
||||
goto getop;
|
||||
}
|
||||
}
|
||||
|
||||
getop: if ((op = *p++) != '+' && op != '-' && op != '=') {
|
||||
free(saveset);
|
||||
return (NULL);
|
||||
}
|
||||
if (op == '=')
|
||||
equalopdone = 0;
|
||||
|
||||
who &= ~S_ISTXT;
|
||||
for (perm = 0, permXbits = 0;; ++p) {
|
||||
switch (*p) {
|
||||
case 'r':
|
||||
perm |= S_IRUSR|S_IRGRP|S_IROTH;
|
||||
break;
|
||||
case 's':
|
||||
/* If only "other" bits ignore set-id. */
|
||||
if (who & ~S_IRWXO)
|
||||
perm |= S_ISUID|S_ISGID;
|
||||
break;
|
||||
case 't':
|
||||
/* If only "other" bits ignore sticky. */
|
||||
if (who & ~S_IRWXO) {
|
||||
who |= S_ISTXT;
|
||||
perm |= S_ISTXT;
|
||||
}
|
||||
break;
|
||||
case 'w':
|
||||
perm |= S_IWUSR|S_IWGRP|S_IWOTH;
|
||||
break;
|
||||
case 'X':
|
||||
permXbits = S_IXUSR|S_IXGRP|S_IXOTH;
|
||||
break;
|
||||
case 'x':
|
||||
perm |= S_IXUSR|S_IXGRP|S_IXOTH;
|
||||
break;
|
||||
case 'u':
|
||||
case 'g':
|
||||
case 'o':
|
||||
/*
|
||||
* When ever we hit 'u', 'g', or 'o', we have
|
||||
* to flush out any partial mode that we have,
|
||||
* and then do the copying of the mode bits.
|
||||
*/
|
||||
if (perm) {
|
||||
ADDCMD(op, who, perm, mask);
|
||||
perm = 0;
|
||||
}
|
||||
if (op == '=')
|
||||
equalopdone = 1;
|
||||
if (op == '+' && permXbits) {
|
||||
ADDCMD('X', who, permXbits, mask);
|
||||
permXbits = 0;
|
||||
}
|
||||
ADDCMD(*p, who, op, mask);
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* Add any permissions that we haven't already
|
||||
* done.
|
||||
*/
|
||||
if (perm || (op == '=' && !equalopdone)) {
|
||||
if (op == '=')
|
||||
equalopdone = 1;
|
||||
ADDCMD(op, who, perm, mask);
|
||||
perm = 0;
|
||||
}
|
||||
if (permXbits) {
|
||||
ADDCMD('X', who, permXbits, mask);
|
||||
permXbits = 0;
|
||||
}
|
||||
goto apply;
|
||||
}
|
||||
}
|
||||
|
||||
apply: if (!*p)
|
||||
break;
|
||||
if (*p != ',')
|
||||
goto getop;
|
||||
++p;
|
||||
}
|
||||
set->cmd = 0;
|
||||
#ifdef SETMODE_DEBUG
|
||||
(void)printf("Before compress_mode()\n");
|
||||
dumpmode(saveset);
|
||||
#endif
|
||||
compress_mode(saveset);
|
||||
#ifdef SETMODE_DEBUG
|
||||
(void)printf("After compress_mode()\n");
|
||||
dumpmode(saveset);
|
||||
#endif
|
||||
return (saveset);
|
||||
}
|
||||
|
||||
static BITCMD *
|
||||
addcmd(set, op, who, oparg, mask)
|
||||
BITCMD *set;
|
||||
register int oparg, who;
|
||||
register int op;
|
||||
unsigned int mask;
|
||||
{
|
||||
switch (op) {
|
||||
case '=':
|
||||
set->cmd = '-';
|
||||
set->bits = who ? who : STANDARD_BITS;
|
||||
set++;
|
||||
|
||||
op = '+';
|
||||
/* FALLTHROUGH */
|
||||
case '+':
|
||||
case '-':
|
||||
case 'X':
|
||||
set->cmd = op;
|
||||
set->bits = (who ? who : mask) & oparg;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
case 'g':
|
||||
case 'o':
|
||||
set->cmd = op;
|
||||
if (who) {
|
||||
set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) |
|
||||
((who & S_IRGRP) ? CMD2_GBITS : 0) |
|
||||
((who & S_IROTH) ? CMD2_OBITS : 0);
|
||||
set->bits = ~0;
|
||||
} else {
|
||||
set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
|
||||
set->bits = mask;
|
||||
}
|
||||
|
||||
if (oparg == '+')
|
||||
set->cmd2 |= CMD2_SET;
|
||||
else if (oparg == '-')
|
||||
set->cmd2 |= CMD2_CLR;
|
||||
else if (oparg == '=')
|
||||
set->cmd2 |= CMD2_SET|CMD2_CLR;
|
||||
break;
|
||||
}
|
||||
return (set + 1);
|
||||
}
|
||||
|
||||
#ifdef SETMODE_DEBUG
|
||||
static void
|
||||
dumpmode(set)
|
||||
register BITCMD *set;
|
||||
{
|
||||
for (; set->cmd; ++set)
|
||||
(void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n",
|
||||
set->cmd, set->bits, set->cmd2 ? " cmd2:" : "",
|
||||
set->cmd2 & CMD2_CLR ? " CLR" : "",
|
||||
set->cmd2 & CMD2_SET ? " SET" : "",
|
||||
set->cmd2 & CMD2_UBITS ? " UBITS" : "",
|
||||
set->cmd2 & CMD2_GBITS ? " GBITS" : "",
|
||||
set->cmd2 & CMD2_OBITS ? " OBITS" : "");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Given an array of bitcmd structures, compress by compacting consecutive
|
||||
* '+', '-' and 'X' commands into at most 3 commands, one of each. The 'u',
|
||||
* 'g' and 'o' commands continue to be separate. They could probably be
|
||||
* compacted, but it's not worth the effort.
|
||||
*/
|
||||
static int
|
||||
compress_mode(set)
|
||||
register BITCMD *set;
|
||||
{
|
||||
register BITCMD *nset;
|
||||
register int setbits, clrbits, Xbits, op;
|
||||
|
||||
for (nset = set;;) {
|
||||
/* Copy over any 'u', 'g' and 'o' commands. */
|
||||
while ((op = nset->cmd) != '+' && op != '-' && op != 'X') {
|
||||
*set++ = *nset++;
|
||||
if (!op)
|
||||
return;
|
||||
}
|
||||
|
||||
for (setbits = clrbits = Xbits = 0;; nset++) {
|
||||
if ((op = nset->cmd) == '-') {
|
||||
clrbits |= nset->bits;
|
||||
setbits &= ~nset->bits;
|
||||
Xbits &= ~nset->bits;
|
||||
} else if (op == '+') {
|
||||
setbits |= nset->bits;
|
||||
clrbits &= ~nset->bits;
|
||||
Xbits &= ~nset->bits;
|
||||
} else if (op == 'X')
|
||||
Xbits |= nset->bits & ~setbits;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (clrbits) {
|
||||
set->cmd = '-';
|
||||
set->cmd2 = 0;
|
||||
set->bits = clrbits;
|
||||
set++;
|
||||
}
|
||||
if (setbits) {
|
||||
set->cmd = '+';
|
||||
set->cmd2 = 0;
|
||||
set->bits = setbits;
|
||||
set++;
|
||||
}
|
||||
if (Xbits) {
|
||||
set->cmd = 'X';
|
||||
set->cmd2 = 0;
|
||||
set->bits = Xbits;
|
||||
set++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: setmode.c,v 1.3 2006/05/23 11:57:34 philip Exp $
|
||||
*/
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -33,19 +29,17 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)shell.h 5.4 (Berkeley) 4/12/91
|
||||
* @(#)shell.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/shell.h,v 1.17 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
#include <sys/types.h> /* for mode_t */
|
||||
|
||||
/*
|
||||
* The follow should be set to reflect the type of system you have:
|
||||
* JOBS -> 1 if you have Berkeley job control, 0 otherwise.
|
||||
* SYMLINKS -> 1 if your system includes symbolic links, 0 otherwise.
|
||||
* DIRENT -> 1 if your system has the SVR3 directory(3X) routines.
|
||||
* UDIR -> 1 if you want the shell to simulate the /u directory.
|
||||
* TILDE -> 1 if you want the shell to expand ~logname.
|
||||
* USEGETPW -> 1 if getpwnam() must be used to look up a name.
|
||||
* ATTY -> 1 to include code for atty(1).
|
||||
* SHORTNAMES -> 1 if your linker cannot handle long names.
|
||||
* READLINE -> 1 if line editing by readline() should be enabled.
|
||||
* define BSD if you are running 4.2 BSD or later.
|
||||
* define SYSV if you are running under System V.
|
||||
|
@ -56,52 +50,47 @@
|
|||
* a quit signal will generate a core dump.
|
||||
*/
|
||||
|
||||
#ifndef JOBS
|
||||
#define JOBS 1
|
||||
#endif
|
||||
#ifndef BSD
|
||||
#define BSD 1
|
||||
#endif
|
||||
#ifndef DEBUG
|
||||
#define DEBUG 0
|
||||
#endif
|
||||
#define POSIX 1
|
||||
|
||||
#define JOBS 0
|
||||
|
||||
/* Set SYMLINKS to 0 by request of Giovanni Falzoni, who wrote the
|
||||
* symlink patches for Minix; email to minix-devel-l of thu 3 nov.
|
||||
/*
|
||||
* Type of used arithmetics. SUSv3 requires us to have at least signed long.
|
||||
*/
|
||||
typedef long arith_t;
|
||||
#define ARITH_FORMAT_STR "%ld"
|
||||
#define atoarith_t(arg) strtol(arg, NULL, 0)
|
||||
#define strtoarith_t(nptr, endptr, base) strtol(nptr, endptr, base)
|
||||
|
||||
#if 0
|
||||
#define SYMLINKS defined(S_ISLNK)
|
||||
#else
|
||||
#define SYMLINKS 0
|
||||
#endif
|
||||
|
||||
#define DIRENT 1
|
||||
#define UDIR 0
|
||||
#define TILDE 1
|
||||
#define USEGETPW 0
|
||||
#define ATTY 0
|
||||
#define READLINE 1
|
||||
#define HASHBANG 0
|
||||
/* #define BSD */
|
||||
#define POSIX 1
|
||||
#define DEBUG 0
|
||||
|
||||
#ifdef __STDC__
|
||||
typedef void *pointer;
|
||||
#ifndef NULL
|
||||
#define NULL (void *)0
|
||||
#endif
|
||||
#else /* not __STDC__ */
|
||||
typedef char *pointer;
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
#endif /* not __STDC__ */
|
||||
#define STATIC /* empty */
|
||||
#define MKINIT /* empty */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
#define STATIC static
|
||||
#define MKINIT /* empty */
|
||||
|
||||
extern char nullstr[1]; /* null string */
|
||||
|
||||
|
||||
#if DEBUG
|
||||
#define TRACE(param) trace param
|
||||
#define TRACE(param) sh_trace param
|
||||
#else
|
||||
#define TRACE(param)
|
||||
#endif
|
||||
|
||||
#ifdef __minix
|
||||
#define __unused
|
||||
|
||||
typedef long quad_t; /* XXX */
|
||||
typedef unsigned long u_quad_t; /* XXX */
|
||||
#endif
|
||||
|
||||
mode_t getmode(void *, int /* mode_t */);
|
||||
void *setmode(char *);
|
||||
|
||||
/*
|
||||
* $PchId: shell.h,v 1.7 2006/05/22 12:47:00 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -35,38 +31,54 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)show.c 5.2 (Berkeley) 4/12/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/show.c,v 1.21 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "parser.h"
|
||||
#include "nodes.h"
|
||||
#include "mystring.h"
|
||||
|
||||
#include "show.h"
|
||||
|
||||
#if DEBUG
|
||||
static shtree(), shcmd(), sharg(), indent();
|
||||
static void trputc(int c);
|
||||
static void shtree(union node *, int, char *, FILE*);
|
||||
static void shcmd(union node *, FILE *);
|
||||
static void sharg(union node *, FILE *);
|
||||
static void indent(int, char *, FILE *);
|
||||
static void trstring(char *);
|
||||
static void showtree(union node *n);
|
||||
|
||||
|
||||
showtree(n)
|
||||
union node *n;
|
||||
{
|
||||
static void
|
||||
showtree(union node *n)
|
||||
{
|
||||
trputs("showtree called\n");
|
||||
shtree(n, 1, NULL, stdout);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
shtree(n, ind, pfx, fp)
|
||||
union node *n;
|
||||
char *pfx;
|
||||
FILE *fp;
|
||||
{
|
||||
static void
|
||||
shtree(union node *n, int ind, char *pfx, FILE *fp)
|
||||
{
|
||||
struct nodelist *lp;
|
||||
char *s;
|
||||
|
||||
if (n == NULL)
|
||||
return;
|
||||
|
||||
indent(ind, pfx, fp);
|
||||
switch(n->type) {
|
||||
case NSEMI:
|
||||
|
@ -109,11 +121,9 @@ binop:
|
|||
|
||||
|
||||
|
||||
static
|
||||
shcmd(cmd, fp)
|
||||
union node *cmd;
|
||||
FILE *fp;
|
||||
{
|
||||
static void
|
||||
shcmd(union node *cmd, FILE *fp)
|
||||
{
|
||||
union node *np;
|
||||
int first;
|
||||
char *s;
|
||||
|
@ -133,14 +143,20 @@ shcmd(cmd, fp)
|
|||
case NTO: s = ">"; dftfd = 1; break;
|
||||
case NAPPEND: s = ">>"; dftfd = 1; break;
|
||||
case NTOFD: s = ">&"; dftfd = 1; break;
|
||||
case NCLOBBER: s = ">|"; dftfd = 1; break;
|
||||
case NFROM: s = "<"; dftfd = 0; break;
|
||||
case NFROMTO: s = "<>"; dftfd = 0; break;
|
||||
case NFROMFD: s = "<&"; dftfd = 0; break;
|
||||
default: s = "*error*"; dftfd = 0; break;
|
||||
}
|
||||
if (np->nfile.fd != dftfd)
|
||||
fprintf(fp, "%d", np->nfile.fd);
|
||||
fputs(s, fp);
|
||||
if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
|
||||
fprintf(fp, "%d", np->ndup.dupfd);
|
||||
if (np->ndup.dupfd >= 0)
|
||||
fprintf(fp, "%d", np->ndup.dupfd);
|
||||
else
|
||||
fprintf(fp, "-");
|
||||
} else {
|
||||
sharg(np->nfile.fname, fp);
|
||||
}
|
||||
|
@ -150,11 +166,9 @@ shcmd(cmd, fp)
|
|||
|
||||
|
||||
|
||||
static
|
||||
sharg(arg, fp)
|
||||
union node *arg;
|
||||
FILE *fp;
|
||||
{
|
||||
static void
|
||||
sharg(union node *arg, FILE *fp)
|
||||
{
|
||||
char *p;
|
||||
struct nodelist *bqlist;
|
||||
int subtype;
|
||||
|
@ -174,10 +188,15 @@ sharg(arg, fp)
|
|||
putc('$', fp);
|
||||
putc('{', fp);
|
||||
subtype = *++p;
|
||||
if (subtype == VSLENGTH)
|
||||
putc('#', fp);
|
||||
|
||||
while (*p != '=')
|
||||
putc(*p++, fp);
|
||||
|
||||
if (subtype & VSNUL)
|
||||
putc(':', fp);
|
||||
|
||||
switch (subtype & VSTYPE) {
|
||||
case VSNORMAL:
|
||||
putc('}', fp);
|
||||
|
@ -194,6 +213,22 @@ sharg(arg, fp)
|
|||
case VSASSIGN:
|
||||
putc('=', fp);
|
||||
break;
|
||||
case VSTRIMLEFT:
|
||||
putc('#', fp);
|
||||
break;
|
||||
case VSTRIMLEFTMAX:
|
||||
putc('#', fp);
|
||||
putc('#', fp);
|
||||
break;
|
||||
case VSTRIMRIGHT:
|
||||
putc('%', fp);
|
||||
break;
|
||||
case VSTRIMRIGHTMAX:
|
||||
putc('%', fp);
|
||||
putc('%', fp);
|
||||
break;
|
||||
case VSLENGTH:
|
||||
break;
|
||||
default:
|
||||
printf("<subtype %d>", subtype);
|
||||
}
|
||||
|
@ -216,11 +251,9 @@ sharg(arg, fp)
|
|||
}
|
||||
|
||||
|
||||
static
|
||||
indent(amount, pfx, fp)
|
||||
char *pfx;
|
||||
FILE *fp;
|
||||
{
|
||||
static void
|
||||
indent(int amount, char *pfx, FILE *fp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < amount ; i++) {
|
||||
|
@ -229,8 +262,6 @@ indent(amount, pfx, fp)
|
|||
putc('\t', fp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
@ -247,52 +278,48 @@ int debug = 0;
|
|||
#endif
|
||||
|
||||
|
||||
trputc(c) {
|
||||
#if DEBUG
|
||||
static void
|
||||
trputc(int c)
|
||||
{
|
||||
if (tracefile == NULL)
|
||||
return;
|
||||
putc(c, tracefile);
|
||||
if (c == '\n')
|
||||
fflush(tracefile);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
trace(fmt, a1, a2, a3, a4, a5, a6, a7, a8)
|
||||
char *fmt;
|
||||
{
|
||||
#if DEBUG
|
||||
int e = errno;
|
||||
if (tracefile == NULL)
|
||||
return;
|
||||
fprintf(tracefile, fmt, a1, a2, a3, a4, a5, a6, a7, a8);
|
||||
if (strchr(fmt, '\n'))
|
||||
fflush(tracefile);
|
||||
errno = e;
|
||||
#endif
|
||||
void
|
||||
sh_trace(const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
if (tracefile != NULL) {
|
||||
(void) vfprintf(tracefile, fmt, va);
|
||||
if (strchr(fmt, '\n'))
|
||||
(void) fflush(tracefile);
|
||||
}
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
|
||||
trputs(s)
|
||||
char *s;
|
||||
{
|
||||
#if DEBUG
|
||||
void
|
||||
trputs(char *s)
|
||||
{
|
||||
if (tracefile == NULL)
|
||||
return;
|
||||
fputs(s, tracefile);
|
||||
if (strchr(s, '\n'))
|
||||
fflush(tracefile);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
trstring(s)
|
||||
char *s;
|
||||
{
|
||||
register char *p;
|
||||
static void
|
||||
trstring(char *s)
|
||||
{
|
||||
char *p;
|
||||
char c;
|
||||
|
||||
#if DEBUG
|
||||
if (tracefile == NULL)
|
||||
return;
|
||||
putc('"', tracefile);
|
||||
|
@ -324,14 +351,12 @@ backslash: putc('\\', tracefile);
|
|||
}
|
||||
}
|
||||
putc('"', tracefile);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
trargs(ap)
|
||||
char **ap;
|
||||
{
|
||||
#if DEBUG
|
||||
void
|
||||
trargs(char **ap)
|
||||
{
|
||||
if (tracefile == NULL)
|
||||
return;
|
||||
while (*ap) {
|
||||
|
@ -342,36 +367,43 @@ trargs(ap)
|
|||
putc('\n', tracefile);
|
||||
}
|
||||
fflush(tracefile);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
opentrace() {
|
||||
void
|
||||
opentrace(void)
|
||||
{
|
||||
char s[100];
|
||||
char *p;
|
||||
char *getenv();
|
||||
int flags;
|
||||
|
||||
#if DEBUG
|
||||
if (!debug)
|
||||
return;
|
||||
if ((p = getenv("HOME")) == NULL) {
|
||||
if (getuid() == 0)
|
||||
p = "/";
|
||||
else
|
||||
p = "/tmp";
|
||||
#ifdef not_this_way
|
||||
{
|
||||
char *p;
|
||||
if ((p = getenv("HOME")) == NULL) {
|
||||
if (geteuid() == 0)
|
||||
p = "/";
|
||||
else
|
||||
p = "/tmp";
|
||||
}
|
||||
scopy(p, s);
|
||||
strcat(s, "/trace");
|
||||
}
|
||||
scopy(p, s);
|
||||
strcat(s, "/trace");
|
||||
#else
|
||||
scopy("./trace", s);
|
||||
#endif /* not_this_way */
|
||||
if ((tracefile = fopen(s, "a")) == NULL) {
|
||||
fprintf(stderr, "Can't open %s\n", s);
|
||||
fprintf(stderr, "Can't open %s: %s\n", s, strerror(errno));
|
||||
return;
|
||||
}
|
||||
#ifdef O_APPEND
|
||||
if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
|
||||
fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
|
||||
#endif
|
||||
fputs("\nTracing started.\n", tracefile);
|
||||
fflush(tracefile);
|
||||
#endif
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
* $PchId: show.c,v 1.6 2006/05/22 12:27:51 philip Exp $
|
||||
*/
|
||||
|
|
42
commands/ash/show.h
Normal file
42
commands/ash/show.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*-
|
||||
* Copyright (c) 1995
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* @(#)show.h 1.1 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/show.h,v 1.11 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
void sh_trace(const char *, ...);
|
||||
void trargs(char **);
|
||||
void trputs(char *);
|
||||
void opentrace(void);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $PchId: show.h,v 1.4 2006/03/29 13:28:45 philip Exp $
|
||||
*/
|
|
@ -1,15 +0,0 @@
|
|||
/* Replacement for something BSD has in sys/cdefs.h. */
|
||||
|
||||
#ifndef _ASH_SYS_CDEFS
|
||||
#define _ASH_SYS_CDEFS
|
||||
|
||||
#if __STDC__
|
||||
#define __P(params) params
|
||||
#else
|
||||
#define __P(params) ()
|
||||
#endif
|
||||
|
||||
/* Probably in sys/types.h. */
|
||||
typedef void (*sig_t) __P(( int ));
|
||||
|
||||
#endif /* _ASH_SYS_CDEFS */
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -35,25 +31,45 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)trap.c 5.2 (Berkeley) 4/12/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/trap.c,v 1.29 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "main.h"
|
||||
#include "nodes.h" /* for other headers */
|
||||
#include "eval.h"
|
||||
#include "jobs.h"
|
||||
#include "show.h"
|
||||
#include "options.h"
|
||||
#include "syntax.h"
|
||||
#include "signames.h"
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "trap.h"
|
||||
#include "mystring.h"
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||
#include "myhistedit.h"
|
||||
#endif
|
||||
#include "builtins.h"
|
||||
|
||||
#ifdef __minix
|
||||
#define NO_SIGINTERRUPT
|
||||
#define NO_SYS_SIGNAME
|
||||
#define NO_SYS_SIGLIST
|
||||
|
||||
#endif
|
||||
|
||||
typedef void (*sig_T)(int);
|
||||
|
||||
/*
|
||||
* Sigmode records the current value of the signal handlers for the various
|
||||
|
@ -64,40 +80,130 @@ static char sccsid[] = "@(#)trap.c 5.2 (Berkeley) 4/12/91";
|
|||
#define S_DFL 1 /* default signal handling (SIG_DFL) */
|
||||
#define S_CATCH 2 /* signal is caught */
|
||||
#define S_IGN 3 /* signal is ignored (SIG_IGN) */
|
||||
#define S_HARD_IGN 4 /* signal is ignored permenantly */
|
||||
#define S_HARD_IGN 4 /* signal is ignored permanently */
|
||||
#define S_RESET 5 /* temporary - to reset a hard ignored sig */
|
||||
|
||||
|
||||
extern char nullstr[1]; /* null string */
|
||||
MKINIT char sigmode[_NSIG]; /* current value of signal */
|
||||
int pendingsigs; /* indicates some signal received */
|
||||
int is_interactive= -1; /* Shell is interactive */
|
||||
int in_dotrap; /* do we execute in a trap handler? */
|
||||
static char *volatile trap[_NSIG]; /* trap handler commands */
|
||||
static volatile sig_atomic_t gotsig[_NSIG];
|
||||
/* indicates specified signal received */
|
||||
static int ignore_sigchld; /* Used while handling SIGCHLD traps. */
|
||||
volatile sig_atomic_t gotwinch;
|
||||
|
||||
static int sigstring_to_signum (char *);
|
||||
static void printsignals (void);
|
||||
static int getsigaction(int, sig_T *);
|
||||
static void onsig (int);
|
||||
#ifdef NO_SIGINTERRUPT
|
||||
static int siginterrupt (int,int);
|
||||
#endif
|
||||
static char *strsigname (int);
|
||||
|
||||
|
||||
/*
|
||||
* Map a string to a signal number.
|
||||
*/
|
||||
static int
|
||||
sigstring_to_signum(char *sig)
|
||||
{
|
||||
|
||||
if (is_number(sig)) {
|
||||
int signo;
|
||||
|
||||
signo = atoi(sig);
|
||||
return ((signo >= 0 && signo < _NSIG) ? signo : (-1));
|
||||
} else if (strcasecmp(sig, "exit") == 0) {
|
||||
return (0);
|
||||
} else {
|
||||
int n;
|
||||
|
||||
if (strncasecmp(sig, "sig", 3) == 0)
|
||||
sig += 3;
|
||||
for (n = 1; n < _NSIG; n++)
|
||||
if (strcasecmp(strsigname(n), sig) == 0)
|
||||
return (n);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Print a list of valid signal names.
|
||||
*/
|
||||
static void
|
||||
printsignals(void)
|
||||
{
|
||||
int n, outlen;
|
||||
|
||||
outlen = 0;
|
||||
for (n = 1; n < _NSIG; n++) {
|
||||
if (strsigname(n)) {
|
||||
out1fmt("%s", strsigname(n));
|
||||
outlen += strlen(strsigname(n));
|
||||
} else {
|
||||
out1fmt("%d", n);
|
||||
outlen += 3; /* good enough */
|
||||
}
|
||||
++outlen;
|
||||
if (outlen > 70 || n == _NSIG - 1) {
|
||||
out1str("\n");
|
||||
outlen = 0;
|
||||
} else {
|
||||
out1c(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *trap[MAXSIG+1]; /* trap handler commands */
|
||||
MKINIT char sigmode[MAXSIG]; /* current value of signal */
|
||||
char gotsig[MAXSIG]; /* indicates specified signal received */
|
||||
int pendingsigs; /* indicates some signal received */
|
||||
|
||||
/*
|
||||
* The trap builtin.
|
||||
*/
|
||||
|
||||
trapcmd(argc, argv) char **argv; {
|
||||
int
|
||||
trapcmd(int argc, char **argv)
|
||||
{
|
||||
char *action;
|
||||
char **ap;
|
||||
int signo;
|
||||
|
||||
if (argc <= 1) {
|
||||
for (signo = 0 ; signo <= MAXSIG ; signo++) {
|
||||
if (trap[signo] != NULL)
|
||||
out1fmt("%d: %s\n", signo, trap[signo]);
|
||||
for (signo = 0 ; signo < _NSIG ; signo++) {
|
||||
if (trap[signo] != NULL) {
|
||||
if (signo == 0) {
|
||||
out1fmt("trap -- '%s' %s\n",
|
||||
trap[signo], "exit");
|
||||
} else if (strsigname(signo)) {
|
||||
out1fmt("trap -- '%s' %s\n",
|
||||
trap[signo], strsigname(signo));
|
||||
} else {
|
||||
out1fmt("trap -- '%s' %d\n",
|
||||
trap[signo], signo);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
ap = argv + 1;
|
||||
if (is_number(*ap))
|
||||
action = NULL;
|
||||
else
|
||||
action = *ap++;
|
||||
while (*ap) {
|
||||
if ((signo = number(*ap)) < 0 || signo > MAXSIG)
|
||||
error("%s: bad trap", *ap);
|
||||
action = NULL;
|
||||
if (*++argv && strcmp(*argv, "--") == 0)
|
||||
argv++;
|
||||
if (*argv && sigstring_to_signum(*argv) == -1) {
|
||||
if ((*argv)[0] != '-') {
|
||||
action = *argv;
|
||||
argv++;
|
||||
} else if ((*argv)[1] == '\0') {
|
||||
argv++;
|
||||
} else if ((*argv)[1] == 'l' && (*argv)[2] == '\0') {
|
||||
printsignals();
|
||||
return 0;
|
||||
} else {
|
||||
error("bad option %s", *argv);
|
||||
}
|
||||
}
|
||||
while (*argv) {
|
||||
if ((signo = sigstring_to_signum(*argv)) == -1)
|
||||
error("bad signal %s", *argv);
|
||||
INTOFF;
|
||||
if (action)
|
||||
action = savestr(action);
|
||||
|
@ -107,22 +213,21 @@ trapcmd(argc, argv) char **argv; {
|
|||
if (signo != 0)
|
||||
setsignal(signo);
|
||||
INTON;
|
||||
ap++;
|
||||
argv++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Clear traps on a fork.
|
||||
*/
|
||||
|
||||
void
|
||||
clear_traps() {
|
||||
char **tp;
|
||||
clear_traps(void)
|
||||
{
|
||||
char *volatile *tp;
|
||||
|
||||
for (tp = trap ; tp <= &trap[MAXSIG] ; tp++) {
|
||||
for (tp = trap ; tp <= &trap[_NSIG - 1] ; tp++) {
|
||||
if (*tp && **tp) { /* trap not NULL or SIG_IGN */
|
||||
INTOFF;
|
||||
ckfree(*tp);
|
||||
|
@ -135,18 +240,16 @@ clear_traps() {
|
|||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Set the signal handler for the specified signal. The routine figures
|
||||
* out what it should be set to.
|
||||
*/
|
||||
|
||||
int
|
||||
setsignal(signo) {
|
||||
void
|
||||
setsignal(int signo)
|
||||
{
|
||||
int action;
|
||||
sig_t sigact;
|
||||
sig_T sig, sigact = SIG_DFL;
|
||||
char *t;
|
||||
extern void onsig();
|
||||
|
||||
if ((t = trap[signo]) == NULL)
|
||||
action = S_DFL;
|
||||
|
@ -154,11 +257,10 @@ setsignal(signo) {
|
|||
action = S_CATCH;
|
||||
else
|
||||
action = S_IGN;
|
||||
if (rootshell && action == S_DFL) {
|
||||
if (action == S_DFL) {
|
||||
switch (signo) {
|
||||
case SIGINT:
|
||||
if (iflag)
|
||||
action = S_CATCH;
|
||||
action = S_CATCH;
|
||||
break;
|
||||
case SIGQUIT:
|
||||
#if DEBUG
|
||||
|
@ -169,68 +271,103 @@ setsignal(signo) {
|
|||
break;
|
||||
}
|
||||
#endif
|
||||
/* FALLTHROUGH */
|
||||
action = S_CATCH;
|
||||
break;
|
||||
case SIGTERM:
|
||||
if (iflag)
|
||||
if (rootshell && iflag)
|
||||
action = S_IGN;
|
||||
break;
|
||||
#if JOBS
|
||||
case SIGTSTP:
|
||||
case SIGTTOU:
|
||||
if (jflag)
|
||||
if (rootshell && mflag)
|
||||
action = S_IGN;
|
||||
break;
|
||||
#endif
|
||||
#ifndef NO_HISTORY
|
||||
case SIGWINCH:
|
||||
if (rootshell && iflag)
|
||||
action = S_CATCH;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
t = &sigmode[signo - 1];
|
||||
if (*t == 0) { /* current setting unknown */
|
||||
|
||||
t = &sigmode[signo];
|
||||
if (*t == 0) {
|
||||
/*
|
||||
* There is a race condition here if action is not S_IGN.
|
||||
* A signal can be ignored that shouldn't be.
|
||||
* current setting unknown
|
||||
*/
|
||||
if ((int)(sigact = signal(signo, SIG_IGN)) == -1)
|
||||
error("Signal system call failed");
|
||||
if (!getsigaction(signo, &sigact)) {
|
||||
/*
|
||||
* Pretend it worked; maybe we should give a warning
|
||||
* here, but other shells don't. We don't alter
|
||||
* sigmode, so that we retry every time.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
if (sigact == SIG_IGN) {
|
||||
*t = S_HARD_IGN;
|
||||
if (mflag && (signo == SIGTSTP ||
|
||||
signo == SIGTTIN || signo == SIGTTOU)) {
|
||||
*t = S_IGN; /* don't hard ignore these */
|
||||
} else
|
||||
*t = S_HARD_IGN;
|
||||
} else {
|
||||
*t = S_IGN;
|
||||
*t = S_RESET; /* force to be set */
|
||||
}
|
||||
}
|
||||
if (*t == S_HARD_IGN || *t == action)
|
||||
return 0;
|
||||
return;
|
||||
switch (action) {
|
||||
case S_DFL: sigact = SIG_DFL; break;
|
||||
case S_CATCH: sigact = onsig; break;
|
||||
case S_IGN: sigact = SIG_IGN; break;
|
||||
}
|
||||
*t = action;
|
||||
return (int)signal(signo, sigact);
|
||||
sig = signal(signo, sigact);
|
||||
if (sig != SIG_ERR && action == S_CATCH)
|
||||
siginterrupt(signo, 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the current setting for sig w/o changing it.
|
||||
*/
|
||||
static int
|
||||
getsigaction(int signo, sig_T *sigact)
|
||||
{
|
||||
struct sigaction sa;
|
||||
|
||||
if (sigaction(signo, (struct sigaction *)0, &sa) == -1)
|
||||
return 0;
|
||||
*sigact = (sig_T) sa.sa_handler;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Ignore a signal.
|
||||
*/
|
||||
|
||||
void
|
||||
ignoresig(signo) {
|
||||
if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
|
||||
ignoresig(int signo)
|
||||
{
|
||||
|
||||
if (sigmode[signo] != S_IGN && sigmode[signo] != S_HARD_IGN) {
|
||||
signal(signo, SIG_IGN);
|
||||
}
|
||||
sigmode[signo - 1] = S_HARD_IGN;
|
||||
sigmode[signo] = S_HARD_IGN;
|
||||
}
|
||||
|
||||
|
||||
#ifdef mkinit
|
||||
INCLUDE "signames.h"
|
||||
INCLUDE <signal.h>
|
||||
INCLUDE "trap.h"
|
||||
|
||||
SHELLPROC {
|
||||
char *sm;
|
||||
|
||||
clear_traps();
|
||||
for (sm = sigmode ; sm < sigmode + MAXSIG ; sm++) {
|
||||
for (sm = sigmode ; sm < sigmode + _NSIG ; sm++) {
|
||||
if (*sm == S_IGN)
|
||||
*sm = S_HARD_IGN;
|
||||
}
|
||||
|
@ -238,82 +375,119 @@ SHELLPROC {
|
|||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Signal handler.
|
||||
*/
|
||||
static void
|
||||
onsig(int signo)
|
||||
{
|
||||
|
||||
void
|
||||
onsig(signo) {
|
||||
#ifndef BSD
|
||||
signal(signo, onsig);
|
||||
#endif
|
||||
if (signo == SIGINT && trap[SIGINT] == NULL) {
|
||||
onint();
|
||||
return;
|
||||
}
|
||||
gotsig[signo - 1] = 1;
|
||||
pendingsigs++;
|
||||
}
|
||||
|
||||
if (signo != SIGCHLD || !ignore_sigchld)
|
||||
gotsig[signo] = 1;
|
||||
pendingsigs++;
|
||||
|
||||
/* If we are currently in a wait builtin, prepare to break it */
|
||||
if ((signo == SIGINT || signo == SIGQUIT) && in_waitcmd != 0)
|
||||
breakwaitcmd = 1;
|
||||
/*
|
||||
* If a trap is set, not ignored and not the null command, we need
|
||||
* to make sure traps are executed even when a child blocks signals.
|
||||
*/
|
||||
if (Tflag &&
|
||||
trap[signo] != NULL &&
|
||||
! trap[signo][0] == '\0' &&
|
||||
! (trap[signo][0] == ':' && trap[signo][1] == '\0'))
|
||||
breakwaitcmd = 1;
|
||||
|
||||
#ifndef NO_HISTORY
|
||||
if (signo == SIGWINCH)
|
||||
gotwinch = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called to execute a trap. Perhaps we should avoid entering new trap
|
||||
* handlers while we are executing a trap handler.
|
||||
*/
|
||||
|
||||
void
|
||||
dotrap() {
|
||||
dotrap(void)
|
||||
{
|
||||
int i;
|
||||
int savestatus;
|
||||
|
||||
in_dotrap++;
|
||||
for (;;) {
|
||||
for (i = 1 ; ; i++) {
|
||||
if (gotsig[i - 1])
|
||||
for (i = 1; i < _NSIG; i++) {
|
||||
if (gotsig[i]) {
|
||||
gotsig[i] = 0;
|
||||
if (trap[i]) {
|
||||
/*
|
||||
* Ignore SIGCHLD to avoid infinite
|
||||
* recursion if the trap action does
|
||||
* a fork.
|
||||
*/
|
||||
if (i == SIGCHLD)
|
||||
ignore_sigchld++;
|
||||
savestatus = exitstatus;
|
||||
evalstring(trap[i]);
|
||||
exitstatus = savestatus;
|
||||
if (i == SIGCHLD)
|
||||
ignore_sigchld--;
|
||||
}
|
||||
break;
|
||||
if (i >= MAXSIG)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
gotsig[i - 1] = 0;
|
||||
savestatus=exitstatus;
|
||||
evalstring(trap[i]);
|
||||
exitstatus=savestatus;
|
||||
if (i >= _NSIG)
|
||||
break;
|
||||
}
|
||||
done:
|
||||
in_dotrap--;
|
||||
pendingsigs = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Controls whether the shell is interactive or not.
|
||||
*/
|
||||
|
||||
int is_interactive;
|
||||
|
||||
void
|
||||
setinteractive(on) {
|
||||
setinteractive(int on)
|
||||
{
|
||||
if (on == is_interactive)
|
||||
return;
|
||||
setsignal(SIGINT);
|
||||
setsignal(SIGQUIT);
|
||||
setsignal(SIGTERM);
|
||||
#ifndef NO_HISTORY
|
||||
setsignal(SIGWINCH);
|
||||
#endif
|
||||
is_interactive = on;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Called to exit the shell.
|
||||
*/
|
||||
|
||||
void
|
||||
exitshell(status) {
|
||||
exitshell(int status)
|
||||
{
|
||||
struct jmploc loc1, loc2;
|
||||
char *p;
|
||||
|
||||
TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
|
||||
if (setjmp(loc1.loc)) goto l1;
|
||||
if (setjmp(loc2.loc)) goto l2;
|
||||
if (setjmp(loc1.loc)) {
|
||||
goto l1;
|
||||
}
|
||||
if (setjmp(loc2.loc)) {
|
||||
goto l2;
|
||||
}
|
||||
handler = &loc1;
|
||||
if ((p = trap[0]) != NULL && *p != '\0') {
|
||||
trap[0] = NULL;
|
||||
|
@ -326,3 +500,85 @@ l1: handler = &loc2; /* probably unnecessary */
|
|||
#endif
|
||||
l2: _exit(status);
|
||||
}
|
||||
|
||||
#ifdef NO_SIGINTERRUPT
|
||||
static int siginterrupt(sig, flag)
|
||||
int sig;
|
||||
int flag;
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NO_SYS_SIGNAME
|
||||
static char *strsigname(sig)
|
||||
int sig;
|
||||
{
|
||||
switch(sig)
|
||||
{
|
||||
case 0: return "Signal 0"; /* 0 */
|
||||
case SIGHUP: return "hup"; /* 1 */
|
||||
case SIGINT: return "int"; /* 2 */
|
||||
case SIGQUIT: return "quit"; /* 3 */
|
||||
case SIGILL: return "ill"; /* 4 */
|
||||
case SIGTRAP: return "trap"; /* 5 */
|
||||
case SIGABRT: return "abrt"; /* 6 */
|
||||
#ifdef __minix_vmd
|
||||
case SIGEMT: return "emt"; /* 7 */
|
||||
#else
|
||||
case SIGBUS: return "bus"; /* 7 */
|
||||
#endif
|
||||
case SIGFPE: return "fpe"; /* 8 */
|
||||
case SIGKILL: return "kill"; /* 9 */
|
||||
case SIGUSR1: return "usr1"; /* 10 */
|
||||
case SIGSEGV: return "segv"; /* 11 */
|
||||
case SIGUSR2: return "usr2"; /* 12 */
|
||||
case SIGPIPE: return "pipe"; /* 13 */
|
||||
case SIGALRM: return "alrm"; /* 14 */
|
||||
case SIGTERM: return "term"; /* 15 */
|
||||
#ifdef __minix_vmd
|
||||
case 16: return "Signal 16"; /* 16 */
|
||||
#else
|
||||
case SIGEMT: return "emt"; /* 16 */
|
||||
#endif
|
||||
case SIGCHLD: return "chld"; /* 17 */
|
||||
case SIGCONT: return "cont"; /* 18 */
|
||||
case SIGSTOP: return "stop"; /* 19 */
|
||||
case SIGTSTP: return "tstp"; /* 20 */
|
||||
case SIGTTIN: return "ttin"; /* 21 */
|
||||
case SIGTTOU: return "ttou"; /* 22 */
|
||||
case SIGWINCH: return "winch"; /* 23 */
|
||||
#ifdef __minix_vmd
|
||||
case SIGFPEMU: return "fpemu"; /* 30 */
|
||||
#endif
|
||||
default: return "Signal n";
|
||||
}
|
||||
}
|
||||
#else
|
||||
static char *strsigname(sig)
|
||||
int sig;
|
||||
{
|
||||
return sys_signame[sig];
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NO_SYS_SIGLIST
|
||||
#include "signames.h"
|
||||
char *strsiglist(sig)
|
||||
int sig;
|
||||
{
|
||||
if (sig > MAXSIG)
|
||||
return NULL;
|
||||
return sigmesg[sig];
|
||||
}
|
||||
#else
|
||||
char *strsiglist(sig)
|
||||
int sig;
|
||||
{
|
||||
return sys_siglist[sig];
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $PchId: trap.c,v 1.7 2006/05/23 11:56:21 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -33,23 +29,24 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)trap.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)trap.h 8.3 (Berkeley) 6/5/95
|
||||
* $FreeBSD: src/bin/sh/trap.h,v 1.12 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
extern int pendingsigs;
|
||||
extern int in_dotrap;
|
||||
extern int is_interactive;
|
||||
extern volatile sig_atomic_t gotwinch;
|
||||
|
||||
#ifdef __STDC__
|
||||
int trapcmd(int, char **);
|
||||
void clear_traps(void);
|
||||
int setsignal(int);
|
||||
void setsignal(int);
|
||||
void ignoresig(int);
|
||||
void dotrap(void);
|
||||
void setinteractive(int);
|
||||
void exitshell(int);
|
||||
#else
|
||||
void clear_traps();
|
||||
int setsignal();
|
||||
void ignoresig();
|
||||
void dotrap();
|
||||
void setinteractive();
|
||||
void exitshell();
|
||||
#endif
|
||||
char *strsiglist(int);
|
||||
|
||||
/*
|
||||
* $PchId: trap.h,v 1.6 2006/05/22 12:48:30 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -35,13 +31,27 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)var.c 5.3 (Berkeley) 4/12/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/var.c,v 1.26.2.1 2004/09/30 04:41:55 des Exp $");
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef NO_PATHS_H
|
||||
#include <paths.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Shell variables.
|
||||
*/
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "output.h"
|
||||
#include "expand.h"
|
||||
|
@ -55,7 +65,16 @@ static char sccsid[] = "@(#)var.c 5.3 (Berkeley) 4/12/91";
|
|||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "mystring.h"
|
||||
#include "parser.h"
|
||||
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||
#include "myhistedit.h"
|
||||
#endif
|
||||
|
||||
#include "builtins.h"
|
||||
|
||||
#ifndef _PATH_DEFPATH
|
||||
#define _PATH_DEFPATH "/usr/bin:/bin"
|
||||
#endif
|
||||
|
||||
#define VTABSIZE 39
|
||||
|
||||
|
@ -64,48 +83,57 @@ struct varinit {
|
|||
struct var *var;
|
||||
int flags;
|
||||
char *text;
|
||||
void (*func)(const char *);
|
||||
};
|
||||
|
||||
|
||||
#if ATTY
|
||||
struct var vatty;
|
||||
#ifndef NO_HISTORY
|
||||
struct var vhistsize;
|
||||
#endif
|
||||
struct var vifs;
|
||||
struct var vmail;
|
||||
struct var vmpath;
|
||||
struct var vpath;
|
||||
struct var vppid;
|
||||
struct var vps1;
|
||||
struct var vps2;
|
||||
struct var vpse;
|
||||
struct var vvers;
|
||||
#if ATTY
|
||||
struct var vterm;
|
||||
#endif
|
||||
STATIC struct var voptind;
|
||||
|
||||
const struct varinit varinit[] = {
|
||||
#if ATTY
|
||||
{&vatty, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY="},
|
||||
STATIC const struct varinit varinit[] = {
|
||||
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||
{ &vhistsize, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE=",
|
||||
sethistsize },
|
||||
#endif
|
||||
{&vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n"},
|
||||
{&vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL="},
|
||||
{&vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH="},
|
||||
{&vpath, VSTRFIXED|VTEXTFIXED, "PATH=:/bin:/usr/bin"},
|
||||
{ &vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n",
|
||||
NULL },
|
||||
{ &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=",
|
||||
NULL },
|
||||
{ &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=",
|
||||
NULL },
|
||||
{ &vpath, VSTRFIXED|VTEXTFIXED, "PATH=" _PATH_DEFPATH,
|
||||
changepath },
|
||||
{ &vppid, VSTRFIXED|VTEXTFIXED|VUNSET, "PPID=",
|
||||
NULL },
|
||||
/*
|
||||
* vps1 depends on uid
|
||||
*/
|
||||
{&vps2, VSTRFIXED|VTEXTFIXED, "PS2=> "},
|
||||
{&vpse, VSTRFIXED|VTEXTFIXED, "PSE=* "},
|
||||
#if ATTY
|
||||
{&vterm, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM="},
|
||||
#endif
|
||||
{NULL, 0, NULL}
|
||||
{ &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ",
|
||||
NULL },
|
||||
{ &vpse, VSTRFIXED|VTEXTFIXED|VUNSET, "PSE=",
|
||||
NULL },
|
||||
{ &voptind, VSTRFIXED|VTEXTFIXED, "OPTIND=1",
|
||||
getoptsreset },
|
||||
{ NULL, 0, NULL,
|
||||
NULL }
|
||||
};
|
||||
|
||||
struct var *vartab[VTABSIZE];
|
||||
STATIC struct var *vartab[VTABSIZE];
|
||||
|
||||
STATIC void unsetvar __P((char *));
|
||||
STATIC struct var **hashvar __P((char *));
|
||||
STATIC int varequal __P((char *, char *));
|
||||
STATIC struct var **hashvar(char *);
|
||||
STATIC int varequal(char *, char *);
|
||||
STATIC int localevar(char *);
|
||||
|
||||
/*
|
||||
* Initialize the varable symbol tables and import the environment
|
||||
|
@ -133,7 +161,9 @@ INIT {
|
|||
*/
|
||||
|
||||
void
|
||||
initvar() {
|
||||
initvar(void)
|
||||
{
|
||||
char ppid[20];
|
||||
const struct varinit *ip;
|
||||
struct var *vp;
|
||||
struct var **vpp;
|
||||
|
@ -145,6 +175,7 @@ initvar() {
|
|||
*vpp = vp;
|
||||
vp->text = ip->text;
|
||||
vp->flags = ip->flags;
|
||||
vp->func = ip->func;
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
@ -154,20 +185,48 @@ initvar() {
|
|||
vpp = hashvar("PS1=");
|
||||
vps1.next = *vpp;
|
||||
*vpp = &vps1;
|
||||
vps1.text = getuid() ? "PS1=$ " : "PS1=# ";
|
||||
vps1.text = geteuid() ? "PS1=$ " : "PS1=# ";
|
||||
vps1.flags = VSTRFIXED|VTEXTFIXED;
|
||||
}
|
||||
if ((vppid.flags & VEXPORT) == 0) {
|
||||
fmtstr(ppid, sizeof(ppid), "%d", (int)getppid());
|
||||
setvarsafe("PPID", ppid, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the value of a variable. The flags argument is ored with the
|
||||
* Safe version of setvar, returns 1 on success 0 on failure.
|
||||
*/
|
||||
|
||||
int
|
||||
setvarsafe(char *name, char *val, int flags)
|
||||
{
|
||||
struct jmploc jmploc;
|
||||
struct jmploc *volatile savehandler = handler;
|
||||
int err = 0;
|
||||
#if __GNUC__
|
||||
/* Avoid longjmp clobbering */
|
||||
(void) &err;
|
||||
#endif
|
||||
|
||||
if (setjmp(jmploc.loc))
|
||||
err = 1;
|
||||
else {
|
||||
handler = &jmploc;
|
||||
setvar(name, val, flags);
|
||||
}
|
||||
handler = savehandler;
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the value of a variable. The flags argument is tored with the
|
||||
* flags of the variable. If val is NULL, the variable is unset.
|
||||
*/
|
||||
|
||||
void
|
||||
setvar(name, val, flags)
|
||||
char *name, *val;
|
||||
{
|
||||
setvar(char *name, char *val, int flags)
|
||||
{
|
||||
char *p, *q;
|
||||
int len;
|
||||
int namelen;
|
||||
|
@ -176,8 +235,9 @@ setvar(name, val, flags)
|
|||
|
||||
isbad = 0;
|
||||
p = name;
|
||||
if (! is_name(*p++))
|
||||
if (! is_name(*p))
|
||||
isbad = 1;
|
||||
p++;
|
||||
for (;;) {
|
||||
if (! is_in_name(*p)) {
|
||||
if (*p == '\0' || *p == '=')
|
||||
|
@ -188,7 +248,7 @@ setvar(name, val, flags)
|
|||
}
|
||||
namelen = p - name;
|
||||
if (isbad)
|
||||
error("%.*s: is read only", namelen, name);
|
||||
error("%.*s: bad variable name", namelen, name);
|
||||
len = namelen + 2; /* 2 is space for '=' and '\0' */
|
||||
if (val == NULL) {
|
||||
flags |= VUNSET;
|
||||
|
@ -206,7 +266,26 @@ setvar(name, val, flags)
|
|||
setvareq(nameeq, flags);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
localevar(char *s)
|
||||
{
|
||||
static char *lnames[7] = {
|
||||
"ALL", "COLLATE", "CTYPE", "MONETARY",
|
||||
"NUMERIC", "TIME", NULL
|
||||
};
|
||||
char **ss;
|
||||
|
||||
if (*s != 'L')
|
||||
return 0;
|
||||
if (varequal(s + 1, "ANG"))
|
||||
return 1;
|
||||
if (strncmp(s + 1, "C_", 2) != 0)
|
||||
return 0;
|
||||
for (ss = lnames; *ss ; ss++)
|
||||
if (varequal(s + 3, *ss))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Same as setvar except that the variable and value are passed in
|
||||
|
@ -216,28 +295,42 @@ setvar(name, val, flags)
|
|||
*/
|
||||
|
||||
void
|
||||
setvareq(s, flags)
|
||||
char *s;
|
||||
{
|
||||
setvareq(char *s, int flags)
|
||||
{
|
||||
struct var *vp, **vpp;
|
||||
int len;
|
||||
|
||||
if (aflag)
|
||||
flags |= VEXPORT;
|
||||
vpp = hashvar(s);
|
||||
for (vp = *vpp ; vp ; vp = vp->next) {
|
||||
if (varequal(s, vp->text)) {
|
||||
if (vp->flags & VREADONLY) {
|
||||
int len = strchr(s, '=') - s;
|
||||
len = strchr(s, '=') - s;
|
||||
error("%.*s: is read only", len, s);
|
||||
}
|
||||
INTOFF;
|
||||
if (vp == &vpath)
|
||||
changepath(s + 5); /* 5 = strlen("PATH=") */
|
||||
|
||||
if (vp->func && (flags & VNOFUNC) == 0)
|
||||
(*vp->func)(strchr(s, '=') + 1);
|
||||
|
||||
if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
|
||||
ckfree(vp->text);
|
||||
vp->flags &=~ (VTEXTFIXED|VSTACK|VUNSET);
|
||||
|
||||
vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
|
||||
vp->flags |= flags;
|
||||
vp->text = s;
|
||||
|
||||
/*
|
||||
* We could roll this to a function, to handle it as
|
||||
* a regular variable function callback, but why bother?
|
||||
*/
|
||||
if (vp == &vmpath || (vp == &vmail && ! mpathset()))
|
||||
chkmail(1);
|
||||
if ((vp->flags & VEXPORT) && localevar(s)) {
|
||||
putenv(s);
|
||||
(void) setlocale(LC_ALL, "");
|
||||
}
|
||||
INTON;
|
||||
return;
|
||||
}
|
||||
|
@ -247,7 +340,14 @@ setvareq(s, flags)
|
|||
vp->flags = flags;
|
||||
vp->text = s;
|
||||
vp->next = *vpp;
|
||||
vp->func = NULL;
|
||||
INTOFF;
|
||||
*vpp = vp;
|
||||
if ((vp->flags & VEXPORT) && localevar(s)) {
|
||||
putenv(s);
|
||||
(void) setlocale(LC_ALL, "");
|
||||
}
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
|
@ -257,9 +357,8 @@ setvareq(s, flags)
|
|||
*/
|
||||
|
||||
void
|
||||
listsetvar(list)
|
||||
struct strlist *list;
|
||||
{
|
||||
listsetvar(struct strlist *list)
|
||||
{
|
||||
struct strlist *lp;
|
||||
|
||||
INTOFF;
|
||||
|
@ -276,9 +375,8 @@ listsetvar(list)
|
|||
*/
|
||||
|
||||
char *
|
||||
lookupvar(name)
|
||||
char *name;
|
||||
{
|
||||
lookupvar(char *name)
|
||||
{
|
||||
struct var *v;
|
||||
|
||||
for (v = *hashvar(name) ; v ; v = v->next) {
|
||||
|
@ -300,9 +398,8 @@ lookupvar(name)
|
|||
*/
|
||||
|
||||
char *
|
||||
bltinlookup(name, doall)
|
||||
char *name;
|
||||
{
|
||||
bltinlookup(char *name, int doall)
|
||||
{
|
||||
struct strlist *sp;
|
||||
struct var *v;
|
||||
|
||||
|
@ -312,8 +409,8 @@ bltinlookup(name, doall)
|
|||
}
|
||||
for (v = *hashvar(name) ; v ; v = v->next) {
|
||||
if (varequal(v->text, name)) {
|
||||
if (v->flags & VUNSET
|
||||
|| ! doall && (v->flags & VEXPORT) == 0)
|
||||
if ((v->flags & VUNSET)
|
||||
|| (!doall && (v->flags & VEXPORT) == 0))
|
||||
return NULL;
|
||||
return strchr(v->text, '=') + 1;
|
||||
}
|
||||
|
@ -329,7 +426,8 @@ bltinlookup(name, doall)
|
|||
*/
|
||||
|
||||
char **
|
||||
environment() {
|
||||
environment(void)
|
||||
{
|
||||
int nenv;
|
||||
struct var **vpp;
|
||||
struct var *vp;
|
||||
|
@ -359,15 +457,14 @@ environment() {
|
|||
*/
|
||||
|
||||
#ifdef mkinit
|
||||
MKINIT void shprocvar();
|
||||
|
||||
SHELLPROC {
|
||||
shprocvar();
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
shprocvar() {
|
||||
shprocvar(void)
|
||||
{
|
||||
struct var **vpp;
|
||||
struct var *vp, **prev;
|
||||
|
||||
|
@ -400,14 +497,21 @@ shprocvar() {
|
|||
*/
|
||||
|
||||
int
|
||||
showvarscmd(argc, argv) char **argv; {
|
||||
showvarscmd(int argc __unused, char **argv __unused)
|
||||
{
|
||||
struct var **vpp;
|
||||
struct var *vp;
|
||||
const char *s;
|
||||
|
||||
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
||||
for (vp = *vpp ; vp ; vp = vp->next) {
|
||||
if ((vp->flags & VUNSET) == 0)
|
||||
out1fmt("%s\n", vp->text);
|
||||
if (vp->flags & VUNSET)
|
||||
continue;
|
||||
for (s = vp->text; *s != '='; s++)
|
||||
out1c(*s);
|
||||
out1c('=');
|
||||
out1qstr(s + 1);
|
||||
out1c('\n');
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -420,15 +524,35 @@ showvarscmd(argc, argv) char **argv; {
|
|||
*/
|
||||
|
||||
int
|
||||
exportcmd(argc, argv) char **argv; {
|
||||
exportcmd(int argc, char **argv)
|
||||
{
|
||||
struct var **vpp;
|
||||
struct var *vp;
|
||||
char *name;
|
||||
char *p;
|
||||
char *cmdname;
|
||||
int ch, values;
|
||||
int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
|
||||
|
||||
cmdname = argv[0];
|
||||
optreset = optind = 1;
|
||||
opterr = 0;
|
||||
values = 0;
|
||||
while ((ch = getopt(argc, argv, "p")) != -1) {
|
||||
switch (ch) {
|
||||
case 'p':
|
||||
values = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
error("unknown option: -%c", optopt);
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
listsetvar(cmdenviron);
|
||||
if (argc > 1) {
|
||||
if (argc != 0) {
|
||||
while ((name = *argptr++) != NULL) {
|
||||
if ((p = strchr(name, '=')) != NULL) {
|
||||
p++;
|
||||
|
@ -436,7 +560,12 @@ exportcmd(argc, argv) char **argv; {
|
|||
vpp = hashvar(name);
|
||||
for (vp = *vpp ; vp ; vp = vp->next) {
|
||||
if (varequal(vp->text, name)) {
|
||||
|
||||
vp->flags |= flag;
|
||||
if ((vp->flags & VEXPORT) && localevar(vp->text)) {
|
||||
putenv(vp->text);
|
||||
(void) setlocale(LC_ALL, "");
|
||||
}
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
@ -448,8 +577,16 @@ found:;
|
|||
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
||||
for (vp = *vpp ; vp ; vp = vp->next) {
|
||||
if (vp->flags & flag) {
|
||||
if (values) {
|
||||
out1str(cmdname);
|
||||
out1c(' ');
|
||||
}
|
||||
for (p = vp->text ; *p != '=' ; p++)
|
||||
out1c(*p);
|
||||
if (values && !(vp->flags & VUNSET)) {
|
||||
out1c('=');
|
||||
out1qstr(p + 1);
|
||||
}
|
||||
out1c('\n');
|
||||
}
|
||||
}
|
||||
|
@ -463,7 +600,9 @@ found:;
|
|||
* The "local" command.
|
||||
*/
|
||||
|
||||
localcmd(argc, argv) char **argv; {
|
||||
int
|
||||
localcmd(int argc __unused, char **argv __unused)
|
||||
{
|
||||
char *name;
|
||||
|
||||
if (! in_function())
|
||||
|
@ -483,9 +622,8 @@ localcmd(argc, argv) char **argv; {
|
|||
*/
|
||||
|
||||
void
|
||||
mklocal(name)
|
||||
char *name;
|
||||
{
|
||||
mklocal(char *name)
|
||||
{
|
||||
struct localvar *lvp;
|
||||
struct var **vpp;
|
||||
struct var *vp;
|
||||
|
@ -493,8 +631,8 @@ mklocal(name)
|
|||
INTOFF;
|
||||
lvp = ckmalloc(sizeof (struct localvar));
|
||||
if (name[0] == '-' && name[1] == '\0') {
|
||||
lvp->text = ckmalloc(sizeof optval);
|
||||
bcopy(optval, lvp->text, sizeof optval);
|
||||
lvp->text = ckmalloc(sizeof optlist);
|
||||
memcpy(lvp->text, optlist, sizeof optlist);
|
||||
vp = NULL;
|
||||
} else {
|
||||
vpp = hashvar(name);
|
||||
|
@ -527,7 +665,8 @@ mklocal(name)
|
|||
*/
|
||||
|
||||
void
|
||||
poplocalvars() {
|
||||
poplocalvars(void)
|
||||
{
|
||||
struct localvar *lvp;
|
||||
struct var *vp;
|
||||
|
||||
|
@ -535,10 +674,10 @@ poplocalvars() {
|
|||
localvars = lvp->next;
|
||||
vp = lvp->vp;
|
||||
if (vp == NULL) { /* $- saved */
|
||||
bcopy(lvp->text, optval, sizeof optval);
|
||||
memcpy(optlist, lvp->text, sizeof optlist);
|
||||
ckfree(lvp->text);
|
||||
} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
|
||||
unsetvar(vp->text);
|
||||
(void)unsetvar(vp->text);
|
||||
} else {
|
||||
if ((vp->flags & VTEXTFIXED) == 0)
|
||||
ckfree(vp->text);
|
||||
|
@ -550,7 +689,9 @@ poplocalvars() {
|
|||
}
|
||||
|
||||
|
||||
setvarcmd(argc, argv) char **argv; {
|
||||
int
|
||||
setvarcmd(int argc, char **argv)
|
||||
{
|
||||
if (argc <= 2)
|
||||
return unsetcmd(argc, argv);
|
||||
else if (argc == 3)
|
||||
|
@ -567,14 +708,31 @@ setvarcmd(argc, argv) char **argv; {
|
|||
* with the same name.
|
||||
*/
|
||||
|
||||
unsetcmd(argc, argv) char **argv; {
|
||||
int
|
||||
unsetcmd(int argc __unused, char **argv __unused)
|
||||
{
|
||||
char **ap;
|
||||
int i;
|
||||
int flg_func = 0;
|
||||
int flg_var = 0;
|
||||
int ret = 0;
|
||||
|
||||
for (ap = argv + 1 ; *ap ; ap++) {
|
||||
unsetfunc(*ap);
|
||||
unsetvar(*ap);
|
||||
while ((i = nextopt("vf")) != '\0') {
|
||||
if (i == 'f')
|
||||
flg_func = 1;
|
||||
else
|
||||
flg_var = 1;
|
||||
}
|
||||
return 0;
|
||||
if (flg_func == 0 && flg_var == 0)
|
||||
flg_var = 1;
|
||||
|
||||
for (ap = argptr; *ap ; ap++) {
|
||||
if (flg_func)
|
||||
ret |= unsetfunc(*ap);
|
||||
if (flg_var)
|
||||
ret |= unsetvar(*ap);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -582,22 +740,25 @@ unsetcmd(argc, argv) char **argv; {
|
|||
* Unset the specified variable.
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
unsetvar(s)
|
||||
char *s;
|
||||
{
|
||||
int
|
||||
unsetvar(char *s)
|
||||
{
|
||||
struct var **vpp;
|
||||
struct var *vp;
|
||||
|
||||
vpp = hashvar(s);
|
||||
for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) {
|
||||
if (varequal(vp->text, s)) {
|
||||
if (vp->flags & VREADONLY)
|
||||
return (1);
|
||||
INTOFF;
|
||||
if (*(strchr(vp->text, '=') + 1) != '\0'
|
||||
|| vp->flags & VREADONLY) {
|
||||
if (*(strchr(vp->text, '=') + 1) != '\0')
|
||||
setvar(s, nullstr, 0);
|
||||
if ((vp->flags & VEXPORT) && localevar(vp->text)) {
|
||||
unsetenv(s);
|
||||
setlocale(LC_ALL, "");
|
||||
}
|
||||
vp->flags &=~ VEXPORT;
|
||||
vp->flags &= ~VEXPORT;
|
||||
vp->flags |= VUNSET;
|
||||
if ((vp->flags & VSTRFIXED) == 0) {
|
||||
if ((vp->flags & VTEXTFIXED) == 0)
|
||||
|
@ -606,9 +767,11 @@ unsetvar(s)
|
|||
ckfree(vp);
|
||||
}
|
||||
INTON;
|
||||
return;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -618,14 +781,13 @@ unsetvar(s)
|
|||
*/
|
||||
|
||||
STATIC struct var **
|
||||
hashvar(p)
|
||||
register char *p;
|
||||
{
|
||||
hashvar(char *p)
|
||||
{
|
||||
unsigned int hashval;
|
||||
|
||||
hashval = *p << 4;
|
||||
hashval = ((unsigned char) *p) << 4;
|
||||
while (*p && *p != '=')
|
||||
hashval += *p++;
|
||||
hashval += (unsigned char) *p++;
|
||||
return &vartab[hashval % VTABSIZE];
|
||||
}
|
||||
|
||||
|
@ -638,9 +800,8 @@ hashvar(p)
|
|||
*/
|
||||
|
||||
STATIC int
|
||||
varequal(p, q)
|
||||
register char *p, *q;
|
||||
{
|
||||
varequal(char *p, char *q)
|
||||
{
|
||||
while (*p == *q++) {
|
||||
if (*p++ == '=')
|
||||
return 1;
|
||||
|
@ -649,3 +810,7 @@ varequal(p, q)
|
|||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: var.c,v 1.5 2006/05/22 12:28:49 philip Exp $
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
|
@ -13,10 +13,6 @@
|
|||
* 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.
|
||||
|
@ -33,7 +29,8 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)var.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)var.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/var.h,v 1.12 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -41,43 +38,45 @@
|
|||
*/
|
||||
|
||||
/* flags */
|
||||
#define VEXPORT 01 /* variable is exported */
|
||||
#define VREADONLY 02 /* variable cannot be modified */
|
||||
#define VSTRFIXED 04 /* variable struct is staticly allocated */
|
||||
#define VTEXTFIXED 010 /* text is staticly allocated */
|
||||
#define VSTACK 020 /* text is allocated on the stack */
|
||||
#define VUNSET 040 /* the variable is not set */
|
||||
#define VEXPORT 0x01 /* variable is exported */
|
||||
#define VREADONLY 0x02 /* variable cannot be modified */
|
||||
#define VSTRFIXED 0x04 /* variable struct is staticly allocated */
|
||||
#define VTEXTFIXED 0x08 /* text is staticly allocated */
|
||||
#define VSTACK 0x10 /* text is allocated on the stack */
|
||||
#define VUNSET 0x20 /* the variable is not set */
|
||||
#define VNOFUNC 0x40 /* don't call the callback function */
|
||||
|
||||
|
||||
struct var {
|
||||
struct var *next; /* next entry in hash list */
|
||||
int flags; /* flags are defined above */
|
||||
char *text; /* name=value */
|
||||
int flags; /* flags are defined above */
|
||||
char *text; /* name=value */
|
||||
void (*func)(const char *);
|
||||
/* function to be called when */
|
||||
/* the variable gets set/unset */
|
||||
};
|
||||
|
||||
|
||||
struct localvar {
|
||||
struct localvar *next; /* next local variable in list */
|
||||
struct var *vp; /* the variable that was made local */
|
||||
int flags; /* saved flags */
|
||||
char *text; /* saved text */
|
||||
struct localvar *next; /* next local variable in list */
|
||||
struct var *vp; /* the variable that was made local */
|
||||
int flags; /* saved flags */
|
||||
char *text; /* saved text */
|
||||
};
|
||||
|
||||
|
||||
struct localvar *localvars;
|
||||
|
||||
#if ATTY
|
||||
extern struct var vatty;
|
||||
#endif
|
||||
extern struct var vifs;
|
||||
extern struct var vmail;
|
||||
extern struct var vmpath;
|
||||
extern struct var vpath;
|
||||
extern struct var vppid;
|
||||
extern struct var vps1;
|
||||
extern struct var vps2;
|
||||
extern struct var vpse;
|
||||
#if ATTY
|
||||
extern struct var vterm;
|
||||
#ifndef NO_HISTORY
|
||||
extern struct var vhistsize;
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -87,43 +86,39 @@ extern struct var vterm;
|
|||
*/
|
||||
|
||||
#define ifsval() (vifs.text + 4)
|
||||
#define ifsset() ((vifs.flags & VUNSET) == 0)
|
||||
#define mailval() (vmail.text + 5)
|
||||
#define mpathval() (vmpath.text + 9)
|
||||
#define pathval() (vpath.text + 5)
|
||||
#define ps1val() (vps1.text + 4)
|
||||
#define ps2val() (vps2.text + 4)
|
||||
#define pseval() (vpse.text + 4)
|
||||
#if ATTY
|
||||
#define termval() (vterm.text + 5)
|
||||
#define optindval() (voptind.text + 7)
|
||||
#ifndef NO_HISTORY
|
||||
#define histsizeval() (vhistsize.text + 9)
|
||||
#endif
|
||||
|
||||
#if ATTY
|
||||
#define attyset() ((vatty.flags & VUNSET) == 0)
|
||||
#endif
|
||||
#define mpathset() ((vmpath.flags & VUNSET) == 0)
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
void initvar();
|
||||
void initvar(void);
|
||||
void setvar(char *, char *, int);
|
||||
void setvareq(char *, int);
|
||||
struct strlist;
|
||||
void listsetvar(struct strlist *);
|
||||
char *lookupvar(char *);
|
||||
char *bltinlookup(char *, int);
|
||||
char **environment();
|
||||
char **environment(void);
|
||||
void shprocvar(void);
|
||||
int showvarscmd(int, char **);
|
||||
int exportcmd(int, char **);
|
||||
int localcmd(int, char **);
|
||||
void mklocal(char *);
|
||||
void poplocalvars(void);
|
||||
#else
|
||||
void initvar();
|
||||
void setvar();
|
||||
void setvareq();
|
||||
void listsetvar();
|
||||
char *lookupvar();
|
||||
char *bltinlookup();
|
||||
char **environment();
|
||||
int showvarscmd();
|
||||
void mklocal();
|
||||
void poplocalvars();
|
||||
#endif
|
||||
int setvarcmd(int, char **);
|
||||
int unsetcmd(int, char **);
|
||||
int unsetvar(char *);
|
||||
int setvarsafe(char *, char *, int);
|
||||
|
||||
/*
|
||||
* $PchId: var.h,v 1.4 2006/03/29 12:04:45 philip Exp $
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue